Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a59c350 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "USB: f_audio_source: Enable audio endpoint for alternate setting one"

parents f08b04f2 7ca56f09
Loading
Loading
Loading
Loading
+67 −9
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
 *
 */

#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/usb/audio.h>
#include <linux/wait.h>
@@ -268,6 +270,7 @@ struct audio_dev {
	/* number of frames sent since start_time */
	s64				frames_sent;
	struct audio_source_config	*config;
	bool				audio_ep_enabled;
};

static inline struct audio_dev *func_to_audio(struct usb_function *f)
@@ -588,11 +591,27 @@ static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)

	pr_debug("audio_set_alt intf %d, alt %d\n", intf, alt);

	if (intf == as_interface_alt_1_desc.bInterfaceNumber) {
		if (alt && !audio->audio_ep_enabled) {
			ret = config_ep_by_speed(cdev->gadget, f, audio->in_ep);
	if (ret)
			if (ret) {
				audio->in_ep->desc = NULL;
				ERROR(cdev, "config_ep fail ep %s, result %d\n",
						audio->in_ep->name, ret);
				return ret;

	usb_ep_enable(audio->in_ep);
			}
			ret = usb_ep_enable(audio->in_ep);
			if (ret) {
				ERROR(cdev, "failedto enable ep%s, result %d\n",
					audio->in_ep->name, ret);
				return ret;
			}
			audio->audio_ep_enabled = true;
		} else if (!alt && audio->audio_ep_enabled) {
			usb_ep_disable(audio->in_ep);
			audio->audio_ep_enabled = false;
		}
	}
	return 0;
}

@@ -601,7 +620,10 @@ static void audio_disable(struct usb_function *f)
	struct audio_dev	*audio = func_to_audio(f);

	pr_debug("audio_disable\n");
	if (audio->audio_ep_enabled) {
		usb_ep_disable(audio->in_ep);
		audio->audio_ep_enabled = false;
	}
}

/*-------------------------------------------------------------------------*/
@@ -774,6 +796,7 @@ static int audio_pcm_close(struct snd_pcm_substream *substream)
static int audio_pcm_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params)
{
	struct snd_dma_buffer *buf = &substream->dma_buffer;
	unsigned int channels = params_channels(params);
	unsigned int rate = params_rate(params);

@@ -782,13 +805,31 @@ static int audio_pcm_hw_params(struct snd_pcm_substream *substream,
	if (channels != 2)
		return -EINVAL;

	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
		params_buffer_bytes(params));
	if (!substream->pcm->card->dev->coherent_dma_mask)
		substream->pcm->card->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	buf->dev.type = SNDRV_DMA_TYPE_DEV;
	buf->dev.dev = substream->pcm->card->dev;
	buf->private_data = NULL;
	buf->area = dma_alloc_coherent(substream->pcm->card->dev,
			params_buffer_bytes(params),
			&buf->addr, GFP_KERNEL);
	if (!buf->area)
		return -ENOMEM;
	buf->bytes = params_buffer_bytes(params);
	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	return 0;
}

static int audio_pcm_hw_free(struct snd_pcm_substream *substream)
{
	return snd_pcm_lib_free_vmalloc_buffer(substream);
	struct snd_dma_buffer *buf = &substream->dma_buffer;

	if (buf->area != NULL)
		dma_free_coherent(substream->pcm->card->dev, buf->bytes,
					buf->area, buf->addr);
	buf->area = NULL;
	return 0;
}

static int audio_pcm_prepare(struct snd_pcm_substream *substream)
@@ -840,6 +881,22 @@ static int audio_pcm_playback_trigger(struct snd_pcm_substream *substream,
	return ret;
}

static int audio_pcm_mmap(struct snd_pcm_substream *substream,
				struct vm_area_struct *vma)
{
	struct snd_pcm_runtime *runtime = substream->runtime;

	if (runtime->dma_addr && runtime->dma_bytes) {
		return dma_mmap_coherent(substream->pcm->card->dev, vma,
					runtime->dma_area,
					runtime->dma_addr,
					runtime->dma_bytes);
	} else {
		pr_err("Physical address or size of buf is NULL");
		return -EINVAL;
	}
}

static struct audio_dev _audio_dev = {
	.func = {
		.name = "audio_source",
@@ -862,6 +919,7 @@ static struct snd_pcm_ops audio_playback_ops = {
	.prepare	= audio_pcm_prepare,
	.trigger	= audio_pcm_playback_trigger,
	.pointer	= audio_pcm_pointer,
	.mmap		= audio_pcm_mmap,
};

int audio_source_bind_config(struct usb_configuration *c,