sound: usb: Map audio format received from QMI client

Audio format received from QMI client are not one to one
mapped to pcm format defined by ALSA driver. This causes
format mismatch when QMI client request a format not
defined by ALSA driver. Fix this by creating a mapping
between two formats.

Change-Id: I0f08dd57fa39d385369ef4886d12e8ea77c6ebc0
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
This commit is contained in:
Hemant Kumar 2016-10-13 15:41:55 -07:00
parent bbd8499b43
commit 23b3d4b4de

View file

@ -147,6 +147,27 @@ enum mem_type {
MEM_XFER_BUF,
};
enum usb_qmi_audio_format {
USB_QMI_PCM_FORMAT_S8 = 0,
USB_QMI_PCM_FORMAT_U8,
USB_QMI_PCM_FORMAT_S16_LE,
USB_QMI_PCM_FORMAT_S16_BE,
USB_QMI_PCM_FORMAT_U16_LE,
USB_QMI_PCM_FORMAT_U16_BE,
USB_QMI_PCM_FORMAT_S24_LE,
USB_QMI_PCM_FORMAT_S24_BE,
USB_QMI_PCM_FORMAT_U24_LE,
USB_QMI_PCM_FORMAT_U24_BE,
USB_QMI_PCM_FORMAT_S24_3LE,
USB_QMI_PCM_FORMAT_S24_3BE,
USB_QMI_PCM_FORMAT_U24_3LE,
USB_QMI_PCM_FORMAT_U24_3BE,
USB_QMI_PCM_FORMAT_S32_LE,
USB_QMI_PCM_FORMAT_S32_BE,
USB_QMI_PCM_FORMAT_U32_LE,
USB_QMI_PCM_FORMAT_U32_BE,
};
static unsigned long uaudio_get_iova(unsigned long *curr_iova,
size_t *curr_iova_size, struct list_head *head, size_t size)
{
@ -767,6 +788,51 @@ static void uaudio_dev_release(struct kref *kref)
wake_up(&dev->disconnect_wq);
}
/* maps audio format received over QMI to asound.h based pcm format */
int map_pcm_format(unsigned int fmt_received)
{
switch (fmt_received) {
case USB_QMI_PCM_FORMAT_S8:
return SNDRV_PCM_FORMAT_S8;
case USB_QMI_PCM_FORMAT_U8:
return SNDRV_PCM_FORMAT_U8;
case USB_QMI_PCM_FORMAT_S16_LE:
return SNDRV_PCM_FORMAT_S16_LE;
case USB_QMI_PCM_FORMAT_S16_BE:
return SNDRV_PCM_FORMAT_S16_BE;
case USB_QMI_PCM_FORMAT_U16_LE:
return SNDRV_PCM_FORMAT_U16_LE;
case USB_QMI_PCM_FORMAT_U16_BE:
return SNDRV_PCM_FORMAT_U16_BE;
case USB_QMI_PCM_FORMAT_S24_LE:
return SNDRV_PCM_FORMAT_S24_LE;
case USB_QMI_PCM_FORMAT_S24_BE:
return SNDRV_PCM_FORMAT_S24_BE;
case USB_QMI_PCM_FORMAT_U24_LE:
return SNDRV_PCM_FORMAT_U24_LE;
case USB_QMI_PCM_FORMAT_U24_BE:
return SNDRV_PCM_FORMAT_U24_BE;
case USB_QMI_PCM_FORMAT_S24_3LE:
return SNDRV_PCM_FORMAT_S24_3LE;
case USB_QMI_PCM_FORMAT_S24_3BE:
return SNDRV_PCM_FORMAT_S24_3BE;
case USB_QMI_PCM_FORMAT_U24_3LE:
return SNDRV_PCM_FORMAT_U24_3LE;
case USB_QMI_PCM_FORMAT_U24_3BE:
return SNDRV_PCM_FORMAT_U24_3BE;
case USB_QMI_PCM_FORMAT_S32_LE:
return SNDRV_PCM_FORMAT_S32_LE;
case USB_QMI_PCM_FORMAT_S32_BE:
return SNDRV_PCM_FORMAT_S32_BE;
case USB_QMI_PCM_FORMAT_U32_LE:
return SNDRV_PCM_FORMAT_U32_LE;
case USB_QMI_PCM_FORMAT_U32_BE:
return SNDRV_PCM_FORMAT_U32_BE;
default:
return -EINVAL;
}
}
static int handle_uaudio_stream_req(void *req_h, void *req)
{
struct qmi_uaudio_stream_req_msg_v01 *req_msg;
@ -775,6 +841,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
struct snd_usb_audio *chip = NULL;
struct uaudio_qmi_svc *svc = uaudio_svc;
struct intf_info *info;
int pcm_format;
u8 pcm_card_num, pcm_dev_num, direction;
int intf_num = -1, ret = 0;
@ -802,6 +869,14 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
goto response;
}
pcm_format = map_pcm_format(req_msg->audio_format);
if (pcm_format == -EINVAL) {
pr_err("%s: unsupported pcm format received %d\n",
__func__, req_msg->audio_format);
ret = -EINVAL;
goto response;
}
subs = find_snd_usb_substream(pcm_card_num, pcm_dev_num, direction,
&chip, uaudio_disconnect_cb);
if (!subs || !chip || atomic_read(&chip->shutdown)) {
@ -820,7 +895,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
goto response;
}
subs->pcm_format = req_msg->audio_format;
subs->pcm_format = pcm_format;
subs->channels = req_msg->number_of_ch;
subs->cur_rate = req_msg->bit_rate;