diff options
Diffstat (limited to 'sound/core/compress_offload.c')
| -rw-r--r-- | sound/core/compress_offload.c | 96 | 
1 files changed, 96 insertions, 0 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 2d620688cfb..c84abc886e9 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -486,6 +486,8 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)  		if (retval)  			goto out;  		stream->runtime->state = SNDRV_PCM_STATE_SETUP; +		stream->metadata_set = false; +		stream->next_track = false;  	} else {  		return -EPERM;  	} @@ -517,6 +519,49 @@ out:  	return retval;  } +static int +snd_compr_get_metadata(struct snd_compr_stream *stream, unsigned long arg) +{ +	struct snd_compr_metadata metadata; +	int retval; + +	if (!stream->ops->get_metadata) +		return -ENXIO; + +	if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata))) +		return -EFAULT; + +	retval = stream->ops->get_metadata(stream, &metadata); +	if (retval != 0) +		return retval; + +	if (copy_to_user((void __user *)arg, &metadata, sizeof(metadata))) +		return -EFAULT; + +	return 0; +} + +static int +snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg) +{ +	struct snd_compr_metadata metadata; +	int retval; + +	if (!stream->ops->set_metadata) +		return -ENXIO; +	/* +	* we should allow parameter change only when stream has been +	* opened not in other cases +	*/ +	if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata))) +		return -EFAULT; + +	retval = stream->ops->set_metadata(stream, &metadata); +	stream->metadata_set = true; + +	return retval; +} +  static inline int  snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)  { @@ -600,6 +645,44 @@ static int snd_compr_drain(struct snd_compr_stream *stream)  	return retval;  } +static int snd_compr_next_track(struct snd_compr_stream *stream) +{ +	int retval; + +	/* only a running stream can transition to next track */ +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) +		return -EPERM; + +	/* you can signal next track isf this is intended to be a gapless stream +	 * and current track metadata is set +	 */ +	if (stream->metadata_set == false) +		return -EPERM; + +	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_NEXT_TRACK); +	if (retval != 0) +		return retval; +	stream->metadata_set = false; +	stream->next_track = true; +	return 0; +} + +static int snd_compr_partial_drain(struct snd_compr_stream *stream) +{ +	int retval; +	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || +			stream->runtime->state == SNDRV_PCM_STATE_SETUP) +		return -EPERM; +	/* stream can be drained only when next track has been signalled */ +	if (stream->next_track == false) +		return -EPERM; + +	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); + +	stream->next_track = false; +	return retval; +} +  static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)  {  	struct snd_compr_file *data = f->private_data; @@ -629,6 +712,12 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)  	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):  		retval = snd_compr_get_params(stream, arg);  		break; +	case _IOC_NR(SNDRV_COMPRESS_SET_METADATA): +		retval = snd_compr_set_metadata(stream, arg); +		break; +	case _IOC_NR(SNDRV_COMPRESS_GET_METADATA): +		retval = snd_compr_get_metadata(stream, arg); +		break;  	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):  		retval = snd_compr_tstamp(stream, arg);  		break; @@ -650,6 +739,13 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)  	case _IOC_NR(SNDRV_COMPRESS_DRAIN):  		retval = snd_compr_drain(stream);  		break; +	case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN): +		retval = snd_compr_partial_drain(stream); +		break; +	case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK): +		retval = snd_compr_next_track(stream); +		break; +  	}  	mutex_unlock(&stream->device->lock);  	return retval;  |