diff options
Diffstat (limited to 'sound')
26 files changed, 991 insertions, 141 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 521da22cc80c..18eee84a6729 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -916,14 +916,13 @@ static const struct file_operations snd_compr_file_ops = { static int snd_compress_dev_register(struct snd_device *device) { int ret = -EINVAL; - char str[16]; struct snd_compr *compr; if (snd_BUG_ON(!device || !device->device_data)) return -EBADFD; compr = device->device_data; - pr_debug("reg %s for device %s, direction %d\n", str, compr->name, + pr_debug("reg device %s, direction %d\n", compr->name, compr->direction); /* register compressed device */ ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index e326c1d80416..e847b9923c19 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, struct snd_seq_client_port *port; struct snd_seq_port_info info; struct snd_seq_port_callback *callback; + int port_idx; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; @@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, return -ENOMEM; if (client->type == USER_CLIENT && info.kernel) { - snd_seq_delete_port(client, port->addr.port); + port_idx = port->addr.port; + snd_seq_port_unlock(port); + snd_seq_delete_port(client, port_idx); return -EINVAL; } if (client->type == KERNEL_CLIENT) { @@ -1294,6 +1297,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, snd_seq_set_port_info(port, &info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); + snd_seq_port_unlock(port); if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index fe686ee41c6d..f04714d70bf7 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) } -/* create a port, port number is returned (-1 on failure) */ +/* create a port, port number is returned (-1 on failure); + * the caller needs to unref the port via snd_seq_port_unlock() appropriately + */ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port) { @@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, snd_use_lock_init(&new_port->use_lock); port_subs_info_init(&new_port->c_src); port_subs_info_init(&new_port->c_dest); + snd_use_lock_use(&new_port->use_lock); num = port >= 0 ? port : 0; mutex_lock(&client->ports_mutex); @@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, list_add_tail(&new_port->list, &p->list); client->num_ports++; new_port->addr.port = num; /* store the port number in the port */ + sprintf(new_port->name, "port-%d", num); write_unlock_irqrestore(&client->ports_lock, flags); mutex_unlock(&client->ports_mutex); - sprintf(new_port->name, "port-%d", num); return new_port; } diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 81134e067184..3b126af4a026 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi, * decode input event and put to read buffer of each opened file */ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, - struct snd_seq_event *ev) + struct snd_seq_event *ev, + bool atomic) { struct snd_virmidi *vmidi; unsigned char msg[4]; int len; - read_lock(&rdev->filelist_lock); + if (atomic) + read_lock(&rdev->filelist_lock); + else + down_read(&rdev->filelist_sem); list_for_each_entry(vmidi, &rdev->filelist, list) { if (!vmidi->trigger) continue; @@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, snd_rawmidi_receive(vmidi->substream, msg, len); } } - read_unlock(&rdev->filelist_lock); + if (atomic) + read_unlock(&rdev->filelist_lock); + else + up_read(&rdev->filelist_sem); return 0; } @@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) struct snd_virmidi_dev *rdev; rdev = rmidi->private_data; - return snd_virmidi_dev_receive_event(rdev, ev); + return snd_virmidi_dev_receive_event(rdev, ev, true); } #endif /* 0 */ @@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct, rdev = private_data; if (!(rdev->flags & SNDRV_VIRMIDI_USE)) return 0; /* ignored */ - return snd_virmidi_dev_receive_event(rdev, ev); + return snd_virmidi_dev_receive_event(rdev, ev, atomic); } /* @@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) struct snd_virmidi_dev *rdev = substream->rmidi->private_data; struct snd_rawmidi_runtime *runtime = substream->runtime; struct snd_virmidi *vmidi; - unsigned long flags; vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); if (vmidi == NULL) @@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) vmidi->client = rdev->client; vmidi->port = rdev->port; runtime->private_data = vmidi; - write_lock_irqsave(&rdev->filelist_lock, flags); + down_write(&rdev->filelist_sem); + write_lock_irq(&rdev->filelist_lock); list_add_tail(&vmidi->list, &rdev->filelist); - write_unlock_irqrestore(&rdev->filelist_lock, flags); + write_unlock_irq(&rdev->filelist_lock); + up_write(&rdev->filelist_sem); vmidi->rdev = rdev; return 0; } @@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) struct snd_virmidi_dev *rdev = substream->rmidi->private_data; struct snd_virmidi *vmidi = substream->runtime->private_data; + down_write(&rdev->filelist_sem); write_lock_irq(&rdev->filelist_lock); list_del(&vmidi->list); write_unlock_irq(&rdev->filelist_lock); + up_write(&rdev->filelist_sem); snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; kfree(vmidi); @@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi rdev->rmidi = rmidi; rdev->device = device; rdev->client = -1; + init_rwsem(&rdev->filelist_sem); rwlock_init(&rdev->filelist_lock); INIT_LIST_HEAD(&rdev->filelist); rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index ffc67fd80c23..58e59cd3c95c 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv) unsigned long flags; struct snd_msndmidi *mpu = mpuv; void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; + u16 head, tail, size; spin_lock_irqsave(&mpu->input_lock, flags); - while (readw(mpu->dev->MIDQ + JQS_wTail) != - readw(mpu->dev->MIDQ + JQS_wHead)) { - u16 wTmp, val; - val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); - - if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, - (unsigned char *)&val, 1); - - wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; - if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) - writew(0, mpu->dev->MIDQ + JQS_wHead); - else - writew(wTmp, mpu->dev->MIDQ + JQS_wHead); + head = readw(mpu->dev->MIDQ + JQS_wHead); + tail = readw(mpu->dev->MIDQ + JQS_wTail); + size = readw(mpu->dev->MIDQ + JQS_wSize); + if (head > size || tail > size) + goto out; + while (head != tail) { + unsigned char val = readw(pwMIDQData + 2 * head); + + if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) + snd_rawmidi_receive(mpu->substream_input, &val, 1); + if (++head > size) + head = 0; + writew(head, mpu->dev->MIDQ + JQS_wHead); } + out: spin_unlock_irqrestore(&mpu->input_lock, flags); } EXPORT_SYMBOL(snd_msndmidi_input_read); diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 4c072666115d..a31ea6c22d19 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) { struct snd_msnd *chip = dev_id; void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; + u16 head, tail, size; /* Send ack to DSP */ /* inb(chip->io + HP_RXL); */ /* Evaluate queued DSP messages */ - while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { - u16 wTmp; - - snd_msnd_eval_dsp_msg(chip, - readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); - - wTmp = readw(chip->DSPQ + JQS_wHead) + 1; - if (wTmp > readw(chip->DSPQ + JQS_wSize)) - writew(0, chip->DSPQ + JQS_wHead); - else - writew(wTmp, chip->DSPQ + JQS_wHead); + head = readw(chip->DSPQ + JQS_wHead); + tail = readw(chip->DSPQ + JQS_wTail); + size = readw(chip->DSPQ + JQS_wSize); + if (head > size || tail > size) + goto out; + while (head != tail) { + snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head)); + if (++head > size) + head = 0; + writew(head, chip->DSPQ + JQS_wHead); } + out: /* Send ack to DSP */ inb(chip->io + HP_RXL); return IRQ_HANDLED; diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 74177189063c..065a69cf6118 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -2150,8 +2150,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, stream->resources, en, VORTEX_RESOURCE_SRC)) < 0) { memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); + sizeof(stream->resources)); return -EBUSY; } if (stream->type != VORTEX_PCM_A3D) { @@ -2161,7 +2160,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, VORTEX_RESOURCE_MIXIN)) < 0) { memset(stream->resources, 0, - sizeof(unsigned char) * VORTEX_RESOURCE_LAST); + sizeof(stream->resources)); return -EBUSY; } } @@ -2174,8 +2173,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, stream->resources, en, VORTEX_RESOURCE_A3D)) < 0) { memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); + sizeof(stream->resources)); dev_err(vortex->card->dev, "out of A3D sources. Sorry\n"); return -EBUSY; @@ -2281,6 +2279,9 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, } else { int src[2], mix[2]; + if (nr_ch < 1) + return -EINVAL; + /* Get SRC and MIXER hardware resources. */ for (i = 0; i < nr_ch; i++) { if ((mix[i] = @@ -2289,8 +2290,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, VORTEX_RESOURCE_MIXOUT)) < 0) { memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); + sizeof(stream->resources)); return -EBUSY; } if ((src[i] = @@ -2298,8 +2298,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, stream->resources, en, VORTEX_RESOURCE_SRC)) < 0) { memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); + sizeof(stream->resources)); return -EBUSY; } } diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c index 5f9dc9c0c392..6098a49b5c7c 100644 --- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c +++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c @@ -56,6 +56,12 @@ static unsigned long tx_digital_gain_reg[] = { MSM89XX_CDC_CORE_TX5_VOL_CTL_GAIN, }; +#define SDM660_TX_UNMUTE_DELAY_MS 40 +static int tx_unmute_delay = SDM660_TX_UNMUTE_DELAY_MS; +module_param(tx_unmute_delay, int, + S_IRUGO | S_IWUSR | S_IWGRP); +MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path"); + static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); struct snd_soc_codec *registered_digcodec; @@ -959,6 +965,9 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w, /* enable HPF */ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x00); + schedule_delayed_work( + &msm_dig_cdc->tx_mute_dwork[decimator - 1].dwork, + msecs_to_jiffies(tx_unmute_delay)); if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq != CF_MIN_3DB_150HZ) { @@ -972,20 +981,14 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_read(codec, tx_digital_gain_reg[w->shift + offset]) ); - if (pdata->lb_mode) { - pr_debug("%s: loopback mode unmute the DEC\n", - __func__); - snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00); - } - snd_soc_update_bits(codec, tx_vol_ctl_reg, - 0x01, 0x00); - break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01); msleep(20); snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08); cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork); + cancel_delayed_work_sync( + &msm_dig_cdc->tx_mute_dwork[decimator - 1].dwork); break; case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, @@ -1226,6 +1229,35 @@ int msm_dig_codec_info_create_codec_entry(struct snd_info_entry *codec_root, } EXPORT_SYMBOL(msm_dig_codec_info_create_codec_entry); +static void sdm660_tx_mute_update_callback(struct work_struct *work) +{ + struct tx_mute_work *tx_mute_dwork; + struct snd_soc_codec *codec = NULL; + struct msm_dig_priv *dig_cdc; + struct delayed_work *delayed_work; + u16 tx_vol_ctl_reg = 0; + u8 decimator = 0, i; + + delayed_work = to_delayed_work(work); + tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork); + dig_cdc = tx_mute_dwork->dig_cdc; + codec = dig_cdc->codec; + + for (i = 0; i < (NUM_DECIMATORS - 1); i++) { + if (dig_cdc->dec_active[i]) + decimator = i + 1; + if (decimator && decimator < NUM_DECIMATORS) { + /* unmute decimators corresponding to Tx DAI's*/ + tx_vol_ctl_reg = + MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG + + 32 * (decimator - 1); + snd_soc_update_bits(codec, tx_vol_ctl_reg, + 0x01, 0x00); + } + decimator = 0; + } +} + static int msm_dig_cdc_soc_probe(struct snd_soc_codec *codec) { struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(codec->dev); @@ -1242,6 +1274,10 @@ static int msm_dig_cdc_soc_probe(struct snd_soc_codec *codec) tx_hpf_work[i].decimator = i + 1; INIT_DELAYED_WORK(&tx_hpf_work[i].dwork, tx_hpf_corner_freq_callback); + msm_dig_cdc->tx_mute_dwork[i].dig_cdc = msm_dig_cdc; + msm_dig_cdc->tx_mute_dwork[i].decimator = i + 1; + INIT_DELAYED_WORK(&msm_dig_cdc->tx_mute_dwork[i].dwork, + sdm660_tx_mute_update_callback); } for (i = 0; i < MSM89XX_RX_MAX; i++) @@ -1932,63 +1968,8 @@ static const struct snd_kcontrol_new msm_dig_snd_controls[] = { MSM89XX_CDC_CORE_TX5_MUX_CTL, 3, 1, 0), }; -static int msm_dig_cdc_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = NULL; - u16 tx_vol_ctl_reg = 0; - u8 decimator = 0, i; - struct msm_dig_priv *dig_cdc; - - pr_debug("%s: Digital Mute val = %d\n", __func__, mute); - - if (!dai || !dai->codec) { - pr_err("%s: Invalid params\n", __func__); - return -EINVAL; - } - codec = dai->codec; - dig_cdc = snd_soc_codec_get_drvdata(codec); - - if (dai->id == AIF1_PB) { - dev_dbg(codec->dev, "%s: Not capture use case skip\n", - __func__); - return 0; - } - - mute = (mute) ? 1 : 0; - if (!mute) { - /* - * 15 ms is an emperical value for the mute time - * that was arrived by checking the pop level - * to be inaudible - */ - usleep_range(15000, 15010); - } - - if (dai->id == AIF3_SVA) { - snd_soc_update_bits(codec, - MSM89XX_CDC_CORE_TX5_VOL_CTL_CFG, 0x01, mute); - goto ret; - } - for (i = 0; i < (NUM_DECIMATORS - 1); i++) { - if (dig_cdc->dec_active[i]) - decimator = i + 1; - if (decimator && decimator < NUM_DECIMATORS) { - /* mute/unmute decimators corresponding to Tx DAI's */ - tx_vol_ctl_reg = - MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG + - 32 * (decimator - 1); - snd_soc_update_bits(codec, tx_vol_ctl_reg, - 0x01, mute); - } - decimator = 0; - } -ret: - return 0; -} - static struct snd_soc_dai_ops msm_dig_dai_ops = { .hw_params = msm_dig_cdc_hw_params, - .digital_mute = msm_dig_cdc_digital_mute, }; diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h index 11f36f99f1bd..cbb8a8138db8 100644 --- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h +++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h @@ -32,6 +32,12 @@ enum { MSM89XX_RX_MAX, }; +struct tx_mute_work { + struct msm_dig_priv *dig_cdc; + u32 decimator; + struct delayed_work dwork; +}; + struct msm_dig_priv { struct snd_soc_codec *codec; u32 comp_enabled[MSM89XX_RX_MAX]; @@ -55,6 +61,7 @@ struct msm_dig_priv { int (*register_notifier)(void *handle, struct notifier_block *nblock, bool enable); + struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS]; }; struct dig_ctrl_platform_data { diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig index 629a9c3d91db..18a5d924e282 100644 --- a/sound/soc/msm/Kconfig +++ b/sound/soc/msm/Kconfig @@ -22,6 +22,17 @@ config SND_SOC_QDSP6V2 audio drivers. This includes q6asm, q6adm, q6afe interfaces to DSP using apr. +config SND_SOC_QDSP6V2_VM + tristate "SoC ALSA audio driver for QDSP6V2 virtualization" + depends on MSM_QDSP6_APRV2_VM + select SND_SOC_COMPRESS + help + To add support for MSM QDSP6V2 virtualization + Soc Audio. + This will enable sound soc platform specific + audio drivers. This includes q6asm, q6adm, + q6afe interfaces to DSP using virtualized apr. + config SND_SOC_QDSP_DEBUG bool "QDSP Audio Driver Debug Feature" help @@ -70,7 +81,7 @@ config DTS_SRS_TM config QTI_PP bool "Enable QTI PP" - depends on SND_SOC_MSM_QDSP6V2_INTF + depends on SND_SOC_MSM_QDSP6V2_INTF || SND_SOC_QDSP6V2_VM help To add support for default QTI post processing. This support is to configure the post processing @@ -192,6 +203,22 @@ config SND_SOC_MSM8996 the machine driver and the corresponding DAI-links +config SND_SOC_MSM8996_VM + tristate "SoC Machine driver for MSM8996 virtualization" + select SND_SOC_QDSP6V2_VM + select SND_SOC_MSM_STUB + select SND_SOC_MSM_HOSTLESS_PCM + select SND_DYNAMIC_MINORS + select MSM_QDSP6_APRV2_VM + select QTI_PP + help + To add support for SoC audio on MSM8996 + virtualization platform. + This will enable sound soc drivers which + interfaces with DSP using virtualized apr, + also it will enable the machine driver and + the corresponding DAI-links + config SND_SOC_MSM8998 tristate "SoC Machine driver for MSM8998 boards" depends on ARCH_QCOM diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile index 63c4e61430c4..4d2a360ad1aa 100644 --- a/sound/soc/msm/Makefile +++ b/sound/soc/msm/Makefile @@ -4,9 +4,11 @@ snd-soc-hostless-pcm-objs := msm-pcm-hostless.o obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += qdsp6v2/ +obj-$(CONFIG_SND_SOC_QDSP6V2_VM) += qdsp6v2/ snd-soc-qdsp6v2-objs := msm-dai-fe.o obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o +obj-$(CONFIG_SND_SOC_QDSP6V2_VM) += snd-soc-qdsp6v2.o #for CPE drivers snd-soc-cpe-objs := msm-cpe-lsm.o @@ -16,6 +18,10 @@ obj-$(CONFIG_SND_SOC_CPE) += snd-soc-cpe.o snd-soc-msm8996-objs := msm8996.o apq8096-auto.o obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o +# for MSM8996 virtualization sound card driver +snd-soc-msm8996-vm-objs := apq8096-auto.o +obj-$(CONFIG_SND_SOC_MSM8996_VM) += snd-soc-msm8996-vm.o + # for MSM8998 sound card driver snd-soc-msm8998-objs := msm8998.o obj-$(CONFIG_SND_SOC_MSM8998) += snd-soc-msm8998.o diff --git a/sound/soc/msm/apq8096-auto.c b/sound/soc/msm/apq8096-auto.c index 749f386852c6..1fbdc7049d13 100644 --- a/sound/soc/msm/apq8096-auto.c +++ b/sound/soc/msm/apq8096-auto.c @@ -53,9 +53,11 @@ static int msm_hdmi_rx_ch = 2; static int msm_proxy_rx_ch = 2; static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ; static int msm_sec_mi2s_tx_ch = 2; +static int msm_sec_mi2s_rx_ch = 2; static int msm_tert_mi2s_tx_ch = 2; static int msm_quat_mi2s_rx_ch = 2; static int msm_sec_mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_sec_mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_tert_mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_quat_mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_sec_mi2s_rate = SAMPLING_RATE_48KHZ; @@ -76,6 +78,11 @@ static int msm_sec_tdm_tx_1_ch = 2; static int msm_sec_tdm_tx_2_ch = 2; static int msm_sec_tdm_tx_3_ch = 2; +static int msm_sec_tdm_rx_0_ch = 6; +static int msm_sec_tdm_rx_1_ch = 1; +static int msm_sec_tdm_rx_2_ch = 1; +static int msm_sec_tdm_rx_3_ch; + static int msm_tert_tdm_rx_0_ch = 2; /* ICC STREAM */ static int msm_tert_tdm_rx_1_ch = 2; static int msm_tert_tdm_rx_2_ch = 2; @@ -113,6 +120,11 @@ static int msm_sec_tdm_tx_1_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_sec_tdm_tx_2_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_sec_tdm_tx_3_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_sec_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_sec_tdm_rx_1_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_sec_tdm_rx_2_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_sec_tdm_rx_3_bit_format = SNDRV_PCM_FORMAT_S16_LE; + static int msm_tert_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_tert_tdm_rx_1_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_tert_tdm_rx_2_bit_format = SNDRV_PCM_FORMAT_S16_LE; @@ -257,9 +269,9 @@ static unsigned int tdm_slot_offset[TDM_MAX][TDM_SLOT_OFFSET_MAX] = { {0xFFFF}, /* not used */ {0xFFFF}, /* not used */ /* SEC_TDM_RX */ - {0xFFFF}, /* not used */ - {0xFFFF}, /* not used */ - {0xFFFF}, /* not used */ + {0, 4, 8, 12, 16, 20, 0xFFFF}, + {24, 0xFFFF}, + {28, 0xFFFF}, {0xFFFF}, /* not used */ {0xFFFF}, /* not used */ {0xFFFF}, /* not used */ @@ -765,6 +777,41 @@ static int msm_tert_mi2s_tx_bit_format_put(struct snd_kcontrol *kcontrol, return 0; } +static int msm_sec_mi2s_rx_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_sec_mi2s_rx_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_sec_mi2s_rx_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_sec_mi2s_rx_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 1: + msm_sec_mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_sec_mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: msm_sec_mi2s_rx_bit_format = %d\n", + __func__, msm_sec_mi2s_rx_bit_format); + return 0; +} + + static int msm_sec_mi2s_tx_bit_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1142,6 +1189,78 @@ static int msm_tdm_slot_mapping_put(struct snd_kcontrol *kcontrol, return 0; } +static int msm_sec_tdm_rx_0_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: msm_sec_tdm_rx_0_ch = %d\n", __func__, + msm_sec_tdm_rx_0_ch); + ucontrol->value.integer.value[0] = msm_sec_tdm_rx_0_ch - 1; + return 0; +} + +static int msm_sec_tdm_rx_0_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_sec_tdm_rx_0_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("%s: msm_sec_tdm_rx_0_ch = %d\n", __func__, + msm_sec_tdm_rx_0_ch); + return 0; +} + +static int msm_sec_tdm_rx_1_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: msm_sec_tdm_rx_1_ch = %d\n", __func__, + msm_sec_tdm_rx_1_ch); + ucontrol->value.integer.value[0] = msm_sec_tdm_rx_1_ch - 1; + return 0; +} + +static int msm_sec_tdm_rx_1_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_sec_tdm_rx_1_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("%s: msm_sec_tdm_rx_1_ch = %d\n", __func__, + msm_sec_tdm_rx_1_ch); + return 0; +} + +static int msm_sec_tdm_rx_2_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: msm_sec_tdm_rx_2_ch = %d\n", __func__, + msm_sec_tdm_rx_2_ch); + ucontrol->value.integer.value[0] = msm_sec_tdm_rx_2_ch - 1; + return 0; +} + +static int msm_sec_tdm_rx_2_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_sec_tdm_rx_2_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("%s: msm_sec_tdm_rx_2_ch = %d\n", __func__, + msm_sec_tdm_rx_2_ch); + return 0; +} + +static int msm_sec_tdm_rx_3_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: msm_sec_tdm_rx_3_ch = %d\n", __func__, + msm_sec_tdm_rx_3_ch); + ucontrol->value.integer.value[0] = msm_sec_tdm_rx_3_ch - 1; + return 0; +} + +static int msm_sec_tdm_rx_3_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_sec_tdm_rx_3_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("%s: msm_sec_tdm_rx_3_ch = %d\n", __func__, + msm_sec_tdm_rx_3_ch); + return 0; +} + static int msm_sec_tdm_tx_0_ch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1792,6 +1911,142 @@ static int msm_pri_tdm_rx_3_bit_format_put(struct snd_kcontrol *kcontrol, return 0; } +static int msm_sec_tdm_rx_0_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_sec_tdm_rx_0_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_sec_tdm_rx_0_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_sec_tdm_rx_0_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 1: + msm_sec_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_sec_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: msm_sec_tdm_rx_0_bit_format = %d\n", + __func__, msm_sec_tdm_rx_0_bit_format); + return 0; +} + +static int msm_sec_tdm_rx_1_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_sec_tdm_rx_1_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_sec_tdm_rx_1_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_sec_tdm_rx_1_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 1: + msm_sec_tdm_rx_1_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_sec_tdm_rx_1_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: msm_sec_tdm_rx_1_bit_format = %d\n", + __func__, msm_sec_tdm_rx_1_bit_format); + return 0; +} + +static int msm_sec_tdm_rx_2_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_sec_tdm_rx_2_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_sec_tdm_rx_2_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_sec_tdm_rx_2_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 1: + msm_sec_tdm_rx_2_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_sec_tdm_rx_2_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: msm_sec_tdm_rx_2_bit_format = %d\n", + __func__, msm_sec_tdm_rx_2_bit_format); + return 0; +} + +static int msm_sec_tdm_rx_3_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_sec_tdm_rx_3_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_sec_tdm_rx_3_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_sec_tdm_rx_3_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 1: + msm_sec_tdm_rx_3_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_sec_tdm_rx_3_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: msm_sec_tdm_rx_3_bit_format = %d\n", + __func__, msm_sec_tdm_rx_3_bit_format); + return 0; +} + static int msm_sec_tdm_tx_0_bit_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2679,16 +2934,38 @@ static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int msm_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - pr_debug("%s: channel:%d\n", __func__, msm_quat_mi2s_rx_ch); rate->min = rate->max = SAMPLING_RATE_48KHZ; - channels->min = channels->max = msm_quat_mi2s_rx_ch; - param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - msm_quat_mi2s_rx_bit_format); + + switch (cpu_dai->id) { + case 1: /*MSM_SEC_MI2S*/ + pr_debug("%s: channel:%d\n", __func__, msm_sec_mi2s_rx_ch); + rate->min = rate->max = msm_sec_mi2s_rate; + channels->min = channels->max = msm_sec_mi2s_rx_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_mi2s_rx_bit_format); + break; + case 3: /*MSM_QUAT_MI2S*/ + pr_debug("%s: channel:%d\n", __func__, msm_quat_mi2s_rx_ch); + rate->min = rate->max = SAMPLING_RATE_48KHZ; + channels->min = channels->max = msm_quat_mi2s_rx_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_mi2s_rx_bit_format); + break; + default: + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + pr_debug("%s: dai id = 0x%x channels = %d rate = %d format = 0x%x\n", + __func__, cpu_dai->id, channels->max, rate->max, + params_format(params)); return 0; } @@ -2806,6 +3083,26 @@ static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, msm_pri_tdm_rx_3_bit_format); rate->min = rate->max = msm_pri_tdm_rate; break; + case AFE_PORT_ID_SECONDARY_TDM_RX: + channels->min = channels->max = msm_sec_tdm_rx_0_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_tdm_rx_0_bit_format); + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_1: + channels->min = channels->max = msm_sec_tdm_rx_1_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_tdm_rx_1_bit_format); + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_2: + channels->min = channels->max = msm_sec_tdm_rx_2_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_tdm_rx_2_bit_format); + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_3: + channels->min = channels->max = msm_sec_tdm_rx_3_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_tdm_rx_3_bit_format); + break; case AFE_PORT_ID_SECONDARY_TDM_TX: channels->min = channels->max = msm_sec_tdm_tx_0_ch; param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, @@ -3442,6 +3739,14 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { msm_pri_tdm_rx_2_ch_get, msm_pri_tdm_rx_2_ch_put), SOC_ENUM_EXT("PRI_TDM_RX_3 Channels", msm_snd_enum[5], msm_pri_tdm_rx_3_ch_get, msm_pri_tdm_rx_3_ch_put), + SOC_ENUM_EXT("SEC_TDM_RX_0 Channels", msm_snd_enum[5], + msm_sec_tdm_rx_0_ch_get, msm_sec_tdm_rx_0_ch_put), + SOC_ENUM_EXT("SEC_TDM_RX_1 Channels", msm_snd_enum[5], + msm_sec_tdm_rx_1_ch_get, msm_sec_tdm_rx_1_ch_put), + SOC_ENUM_EXT("SEC_TDM_RX_2 Channels", msm_snd_enum[5], + msm_sec_tdm_rx_2_ch_get, msm_sec_tdm_rx_2_ch_put), + SOC_ENUM_EXT("SEC_TDM_RX_3 Channels", msm_snd_enum[5], + msm_sec_tdm_rx_3_ch_get, msm_sec_tdm_rx_3_ch_put), SOC_ENUM_EXT("SEC_TDM_TX_0 Channels", msm_snd_enum[5], msm_sec_tdm_tx_0_ch_get, msm_sec_tdm_tx_0_ch_put), SOC_ENUM_EXT("SEC_TDM_TX_1 Channels", msm_snd_enum[5], @@ -3508,6 +3813,18 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("PRI_TDM_RX_3 Bit Format", msm_snd_enum[6], msm_pri_tdm_rx_3_bit_format_get, msm_pri_tdm_rx_3_bit_format_put), + SOC_ENUM_EXT("SEC_TDM_RX_0 Bit Format", msm_snd_enum[6], + msm_sec_tdm_rx_0_bit_format_get, + msm_sec_tdm_rx_0_bit_format_put), + SOC_ENUM_EXT("SEC_TDM_RX_1 Bit Format", msm_snd_enum[6], + msm_sec_tdm_rx_1_bit_format_get, + msm_sec_tdm_rx_1_bit_format_put), + SOC_ENUM_EXT("SEC_TDM_RX_2 Bit Format", msm_snd_enum[6], + msm_sec_tdm_rx_2_bit_format_get, + msm_sec_tdm_rx_2_bit_format_put), + SOC_ENUM_EXT("SEC_TDM_RX_3 Bit Format", msm_snd_enum[6], + msm_sec_tdm_rx_3_bit_format_get, + msm_sec_tdm_rx_3_bit_format_put), SOC_ENUM_EXT("SEC_TDM_TX_0 Bit Format", msm_snd_enum[6], msm_sec_tdm_tx_0_bit_format_get, msm_sec_tdm_tx_0_bit_format_put), @@ -3577,6 +3894,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("TERT_MI2S_TX Bit Format", msm_snd_enum[7], msm_tert_mi2s_tx_bit_format_get, msm_tert_mi2s_tx_bit_format_put), + SOC_ENUM_EXT("SEC_MI2S_RX Bit Format", msm_snd_enum[7], + msm_sec_mi2s_rx_bit_format_get, + msm_sec_mi2s_rx_bit_format_put), SOC_ENUM_EXT("SEC_MI2S_TX Bit Format", msm_snd_enum[7], msm_sec_mi2s_tx_bit_format_get, msm_sec_mi2s_tx_bit_format_put), @@ -5283,6 +5603,21 @@ static struct snd_soc_dai_link apq8096_common_be_dai_links[] = { static struct snd_soc_dai_link apq8096_auto_be_dai_links[] = { /* Backend DAI Links */ + { + .name = LPASS_BE_SEC_MI2S_RX, + .stream_name = "Secondary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup, + .ops = &apq8096_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, { .name = LPASS_BE_SEC_MI2S_TX, .stream_name = "Secondary MI2S Capture", @@ -5326,6 +5661,62 @@ static struct snd_soc_dai_link apq8096_auto_be_dai_links[] = { .ignore_suspend = 1, }, { + .name = LPASS_BE_SEC_TDM_RX_0, + .stream_name = "Secondary TDM0 Playback", + .cpu_dai_name = "msm-dai-q6-tdm.36880", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &apq8096_tdm_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_TDM_RX_1, + .stream_name = "Secondary TDM1 Playback", + .cpu_dai_name = "msm-dai-q6-tdm.36882", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_1, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &apq8096_tdm_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_TDM_RX_2, + .stream_name = "Secondary TDM2 Playback", + .cpu_dai_name = "msm-dai-q6-tdm.36884", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_2, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &apq8096_tdm_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_TDM_RX_3, + .stream_name = "Secondary TDM3 Playback", + .cpu_dai_name = "msm-dai-q6-tdm.36886", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_3, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &apq8096_tdm_be_ops, + .ignore_suspend = 1, + }, + { .name = LPASS_BE_SEC_TDM_TX_0, .stream_name = "Secondary TDM0 Capture", .cpu_dai_name = "msm-dai-q6-tdm.36881", diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 5facafdc7729..3326c993e129 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -2568,7 +2568,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "MultiMedia17 Capture", .aif_name = "MM_UL17", - .rates = (SNDRV_PCM_RATE_8000_48000| + .rates = (SNDRV_PCM_RATE_8000_192000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2576,7 +2576,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2587,7 +2587,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "MultiMedia18 Capture", .aif_name = "MM_UL18", - .rates = (SNDRV_PCM_RATE_8000_48000| + .rates = (SNDRV_PCM_RATE_8000_192000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2606,7 +2606,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "MultiMedia19 Capture", .aif_name = "MM_UL19", - .rates = (SNDRV_PCM_RATE_8000_48000| + .rates = (SNDRV_PCM_RATE_8000_192000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2614,7 +2614,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2802,6 +2802,44 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia27", .probe = fe_dai_probe, }, + { + .capture = { + .stream_name = "MultiMedia28 Capture", + .aif_name = "MM_UL28", + .rates = (SNDRV_PCM_RATE_8000_192000| + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .compress_new = snd_soc_new_compress, + .name = "MultiMedia28", + .probe = fe_dai_probe, + }, + { + .capture = { + .stream_name = "MultiMedia29 Capture", + .aif_name = "MM_UL29", + .rates = (SNDRV_PCM_RATE_8000_192000| + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .compress_new = snd_soc_new_compress, + .name = "MultiMedia29", + .probe = fe_dai_probe, + }, }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile index 98c52a4db51f..4116f79890a3 100644 --- a/sound/soc/msm/qdsp6v2/Makefile +++ b/sound/soc/msm/qdsp6v2/Makefile @@ -4,10 +4,13 @@ snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \ msm-lsm-client.o msm-pcm-host-voice-v2.o \ msm-audio-effects-q6-v2.o msm-pcm-loopback-v2.o \ - msm-dai-slim.o msm-transcode-loopback-q6-v2.o \ + msm-transcode-loopback-q6-v2.o \ adsp_err.o +obj-$(CONFIG_SLIMBUS) += msm-dai-slim.o audio_slimslave.o obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \ msm-dai-stub-v2.o +obj-$(CONFIG_SND_SOC_QDSP6V2_VM) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \ + msm-dai-stub-v2.o obj-$(CONFIG_SND_HWDEP) += msm-pcm-routing-devdep.o obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o obj-$(CONFIG_DOLBY_DS2) += msm-ds2-dap-config.o @@ -15,7 +18,7 @@ obj-$(CONFIG_DOLBY_LICENSE) += msm-ds2-dap-config.o obj-$(CONFIG_DTS_SRS_TM) += msm-dts-srs-tm-config.o obj-$(CONFIG_QTI_PP) += msm-qti-pp-config.o obj-y += audio_calibration.o audio_cal_utils.o q6adm.o q6afe.o q6asm.o \ - q6audio-v2.o q6voice.o q6core.o rtac.o q6lsm.o audio_slimslave.o \ + q6audio-v2.o q6voice.o q6core.o rtac.o q6lsm.o \ msm-pcm-q6-noirq.o ocmem-audio-objs += audio_ocmem.o obj-$(CONFIG_AUDIO_OCMEM) += ocmem-audio.o diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 276270258771..ce9091b1ca16 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -424,7 +424,7 @@ static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } - +#ifdef CONFIG_SND_HWDEP static int msm_pcm_mmap_fd(struct snd_pcm_substream *substream, struct snd_pcm_mmap_fd *mmap_fd) { @@ -459,6 +459,7 @@ static int msm_pcm_mmap_fd(struct snd_pcm_substream *substream, } return mmap_fd->fd < 0 ? -EFAULT : 0; } +#endif static int msm_pcm_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) @@ -1042,6 +1043,7 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) return 0; } +#ifdef CONFIG_SND_HWDEP static int msm_pcm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { @@ -1137,6 +1139,7 @@ static int msm_pcm_add_hwdep_dev(struct snd_soc_pcm_runtime *runtime) hwdep->ops.ioctl_compat = msm_pcm_hwdep_compat_ioctl; return 0; } +#endif static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) { @@ -1170,9 +1173,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add app type controls failed %d\n", __func__, ret); } +#ifdef CONFIG_SND_HWDEP ret = msm_pcm_add_hwdep_dev(rtd); if (ret) pr_err("%s: Could not add hw dep node\n", __func__); +#endif pcm->nonatomic = true; exit: return ret; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index a45d89f80106..70531872076b 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -626,6 +626,12 @@ static struct msm_pcm_routing_fdai_data /* MULTIMEDIA27 */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* MULTIMEDIA28 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* MULTIMEDIA29 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, /* CS_VOICE */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, @@ -3695,6 +3701,16 @@ static const struct snd_kcontrol_new ext_ec_ref_mux_ul19 = msm_route_ec_ref_rx_enum[0], msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put); +static const struct snd_kcontrol_new ext_ec_ref_mux_ul28 = + SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL28 MUX Mux", + msm_route_ec_ref_rx_enum[0], + msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put); + +static const struct snd_kcontrol_new ext_ec_ref_mux_ul29 = + SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL29 MUX Mux", + msm_route_ec_ref_rx_enum[0], + msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put); + static int msm_routing_ext_ec_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3841,6 +3857,12 @@ static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_I2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_PRI_I2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_PRI_I2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = { @@ -3904,6 +3926,12 @@ static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_I2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SEC_I2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SEC_I2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = { @@ -3967,6 +3995,12 @@ static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SPDIF_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SPDIF_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_2_rx_mixer_controls[] = { @@ -4084,6 +4118,12 @@ static const struct snd_kcontrol_new slimbus_5_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SLIMBUS_5_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SLIMBUS_5_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SLIMBUS_5_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { @@ -4162,6 +4202,12 @@ static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = { @@ -4225,6 +4271,12 @@ static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = { @@ -4288,6 +4340,12 @@ static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = { @@ -4351,6 +4409,12 @@ static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUINARY_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = { @@ -4408,6 +4472,12 @@ static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERTIARY_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new secondary_mi2s_rx2_mixer_controls[] = { @@ -4477,6 +4547,12 @@ static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = { @@ -4540,6 +4616,12 @@ static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_MI2S_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_PRI_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_PRI_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = { @@ -4726,6 +4808,12 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_HDMI_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new display_port_mixer_controls[] = { @@ -5081,6 +5169,12 @@ static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_INT_BT_SCO_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_INT_BT_SCO_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_INT_BT_SCO_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = { @@ -5198,6 +5292,12 @@ static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_INT_FM_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_INT_FM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_INT_FM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = { @@ -5261,6 +5361,12 @@ static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_AFE_PCM_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_AFE_PCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_AFE_PCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = { @@ -5327,6 +5433,12 @@ static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_AUXPCM_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_AUXPCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_AUXPCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = { @@ -5393,6 +5505,12 @@ static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_AUXPCM_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SEC_AUXPCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SEC_AUXPCM_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new tert_auxpcm_rx_mixer_controls[] = { @@ -7541,6 +7659,12 @@ static const struct snd_kcontrol_new mmul17_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -7565,6 +7689,9 @@ static const struct snd_kcontrol_new mmul18_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -7592,6 +7719,12 @@ static const struct snd_kcontrol_new mmul19_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -7741,6 +7874,66 @@ static const struct snd_kcontrol_new mmul27_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new mmul28_mixer_controls[] = { + SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul29_mixer_controls[] = { + SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = { SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer, @@ -12621,6 +12814,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { mmul21_mixer_controls, ARRAY_SIZE(mmul21_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia27 Mixer", SND_SOC_NOPM, 0, 0, mmul27_mixer_controls, ARRAY_SIZE(mmul27_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia28 Mixer", SND_SOC_NOPM, 0, 0, + mmul28_mixer_controls, ARRAY_SIZE(mmul28_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia29 Mixer", SND_SOC_NOPM, 0, 0, + mmul29_mixer_controls, ARRAY_SIZE(mmul29_mixer_controls)), SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, @@ -13216,14 +13413,27 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia17 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia18 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia19 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, + {"MultiMedia28 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, + {"MultiMedia29 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia8 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia2 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia17 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia18 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia19 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia28 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia29 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia8 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia17 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia18 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia19 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia28 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia29 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia17 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"MultiMedia18 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia19 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia28 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia29 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"MultiMedia8 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, {"MultiMedia3 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, @@ -14168,6 +14378,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia17 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, {"MultiMedia18 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, {"MultiMedia19 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"MultiMedia28 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"MultiMedia29 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, {"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, {"MultiMedia8 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, {"MultiMedia16 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, @@ -14177,6 +14389,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia17 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"MultiMedia18 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"MultiMedia19 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"MultiMedia28 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"MultiMedia29 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"MultiMedia6 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"MultiMedia8 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, @@ -14187,6 +14401,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia17 Mixer", "AFE_PCM_TX", "PCM_TX"}, {"MultiMedia18 Mixer", "AFE_PCM_TX", "PCM_TX"}, {"MultiMedia19 Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"MultiMedia28 Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"MultiMedia29 Mixer", "AFE_PCM_TX", "PCM_TX"}, {"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"}, {"MultiMedia8 Mixer", "AFE_PCM_TX", "PCM_TX"}, {"MultiMedia16 Mixer", "AFE_PCM_TX", "PCM_TX"}, @@ -14206,6 +14422,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL20", NULL, "MultiMedia20 Mixer"}, {"MM_UL21", NULL, "MultiMedia21 Mixer"}, {"MM_UL27", NULL, "MultiMedia27 Mixer"}, + {"MM_UL28", NULL, "MultiMedia28 Mixer"}, + {"MM_UL29", NULL, "MultiMedia29 Mixer"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, @@ -14610,6 +14828,16 @@ static const struct snd_soc_dapm_route intercon[] = { {"AUDIO_REF_EC_UL19 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL19 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + + {"AUDIO_REF_EC_UL29 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"AUDIO_REF_EC_UL29 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"AUDIO_REF_EC_UL29 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"AUDIO_REF_EC_UL29 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MM_UL1", NULL, "AUDIO_REF_EC_UL1 MUX"}, {"MM_UL2", NULL, "AUDIO_REF_EC_UL2 MUX"}, {"MM_UL3", NULL, "AUDIO_REF_EC_UL3 MUX"}, @@ -14622,6 +14850,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL17", NULL, "AUDIO_REF_EC_UL17 MUX"}, {"MM_UL18", NULL, "AUDIO_REF_EC_UL18 MUX"}, {"MM_UL19", NULL, "AUDIO_REF_EC_UL19 MUX"}, + {"MM_UL28", NULL, "AUDIO_REF_EC_UL28 MUX"}, + {"MM_UL29", NULL, "AUDIO_REF_EC_UL29 MUX"}, {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"}, {"Voice_Tx Mixer", "PRI_MI2S_TX_Voice", "PRI_MI2S_TX"}, @@ -16215,7 +16445,8 @@ int msm_routing_set_downmix_control_data(int be_id, int session_id, uint16_t ii; uint16_t *dst_gain_ptr = NULL; - if (be_id >= MSM_BACKEND_DAI_MAX) { + if (be_id < MSM_BACKEND_DAI_PRI_I2S_RX || + be_id >= MSM_BACKEND_DAI_MAX) { rc = -EINVAL; return rc; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 21dfa48308c3..99541b824864 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -200,6 +200,8 @@ enum { MSM_FRONTEND_DAI_MULTIMEDIA25, MSM_FRONTEND_DAI_MULTIMEDIA26, MSM_FRONTEND_DAI_MULTIMEDIA27, + MSM_FRONTEND_DAI_MULTIMEDIA28, + MSM_FRONTEND_DAI_MULTIMEDIA29, MSM_FRONTEND_DAI_CS_VOICE, MSM_FRONTEND_DAI_VOIP, MSM_FRONTEND_DAI_AFE_RX, @@ -225,8 +227,8 @@ enum { MSM_FRONTEND_DAI_MAX, }; -#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA27 + 1) -#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA27 +#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA29 + 1) +#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA29 enum { MSM_BACKEND_DAI_PRI_I2S_RX = 0, diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c index 83628b8d62d9..77c6dfbbe8c1 100644 --- a/sound/soc/msm/qdsp6v2/rtac.c +++ b/sound/soc/msm/qdsp6v2/rtac.c @@ -901,6 +901,14 @@ int send_adm_apr(void *buf, u32 opcode) bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); + if (bytes_returned > rtac_cal[ADM_RTAC_CAL]. + map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", + __func__, bytes_returned); + result = -EINVAL; + goto err; + } + if (bytes_returned > user_buf_size) { pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", __func__, user_buf_size, bytes_returned); @@ -1123,6 +1131,14 @@ int send_rtac_asm_apr(void *buf, u32 opcode) bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); + if (bytes_returned > rtac_cal[ASM_RTAC_CAL]. + map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", + __func__, bytes_returned); + result = -EINVAL; + goto err; + } + if (bytes_returned > user_buf_size) { pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", __func__, user_buf_size, bytes_returned); @@ -1382,6 +1398,14 @@ static int send_rtac_afe_apr(void *buf, uint32_t opcode) bytes_returned = get_resp->param_size + sizeof(struct afe_port_param_data_v2); + if (bytes_returned > rtac_cal[AFE_RTAC_CAL]. + map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", + __func__, bytes_returned); + result = -EINVAL; + goto err; + } + if (bytes_returned > user_afe_buf.buf_size) { pr_err("%s: user size = 0x%x, returned size = 0x%x\n", __func__, user_afe_buf.buf_size, @@ -1606,6 +1630,14 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); + if (bytes_returned > rtac_cal[VOICE_RTAC_CAL]. + map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", + __func__, bytes_returned); + result = -EINVAL; + goto err; + } + if (bytes_returned > user_buf_size) { pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", __func__, user_buf_size, bytes_returned); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8f76f551e229..f97a10fff5df 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -360,6 +360,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, snd_soc_dapm_new_control_unlocked(widget->dapm, &template); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -394,6 +398,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, data->widget = snd_soc_dapm_new_control_unlocked( widget->dapm, &template); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -3293,11 +3301,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); w = snd_soc_dapm_new_control_unlocked(dapm, widget); + /* Do not nag about probe deferrals */ + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + goto out_unlock; + } if (!w) dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", widget->name); +out_unlock: mutex_unlock(&dapm->card->dapm_mutex); return w; } @@ -3319,6 +3338,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->regulator = devm_regulator_get(dapm->dev, w->name); if (IS_ERR(w->regulator)) { ret = PTR_ERR(w->regulator); + if (ret == -EPROBE_DEFER) + return ERR_PTR(ret); dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", w->name, ret); return NULL; @@ -3337,6 +3358,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->clk = devm_clk_get(dapm->dev, w->name); if (IS_ERR(w->clk)) { ret = PTR_ERR(w->clk); + if (ret == -EPROBE_DEFER) + return ERR_PTR(ret); dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", w->name, ret); return NULL; @@ -3450,6 +3473,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { w = snd_soc_dapm_new_control_unlocked(dapm, widget); + if (IS_ERR(w)) { + ret = PTR_ERR(w); + /* Do not nag about probe deferrals */ + if (ret == -EPROBE_DEFER) + break; + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + break; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", @@ -3716,6 +3749,15 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); + if (IS_ERR(w)) { + ret = PTR_ERR(w); + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(card->dev, + "ASoC: Failed to create %s widget (%d)\n", + link_name, ret); + goto outfree_kcontrol_news; + } if (!w) { dev_err(card->dev, "ASoC: Failed to create %s widget\n", link_name); @@ -3767,6 +3809,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->playback.stream_name); @@ -3786,6 +3838,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->capture.stream_name); diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 70396d3f6472..e3f34a86413c 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1481,6 +1481,15 @@ widget: widget = snd_soc_dapm_new_control(dapm, &template); else widget = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(widget)) { + ret = PTR_ERR(widget); + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(tplg->dev, + "ASoC: failed to create widget %s controls (%d)\n", + w->name, ret); + goto hdr_err; + } if (widget == NULL) { dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", w->name); diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index b871ba407e4e..4458190149d1 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev) err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); if (err) - return err; + goto err_kill_urb; - if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) - return -ENODEV; + if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) { + err = -ENODEV; + goto err_kill_urb; + } usb_string(usb_dev, usb_dev->descriptor.iManufacturer, cdev->vendor_name, CAIAQ_USB_STR_LEN); @@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev) setup_card(cdev); return 0; + + err_kill_urb: + usb_kill_urb(&cdev->ep1_in_urb); + return err; } static int snd_probe(struct usb_interface *intf, diff --git a/sound/usb/card.c b/sound/usb/card.c index 23ea575f3bcf..86096532dfba 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -316,6 +316,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) case UAC_VERSION_1: { void *control_header; struct uac1_ac_header_descriptor *h1; + int rest_bytes; control_header = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen, NULL, UAC_HEADER); @@ -324,12 +325,32 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) return -EINVAL; } + rest_bytes = (void *)(host_iface->extra + host_iface->extralen) - + control_header; + + /* just to be sure -- this shouldn't hit at all */ + if (rest_bytes <= 0) { + dev_err(&dev->dev, "invalid control header\n"); + return -EINVAL; + } + h1 = control_header; + + if (rest_bytes < sizeof(*h1)) { + dev_err(&dev->dev, "too short v1 buffer descriptor\n"); + return -EINVAL; + } + if (!h1->bInCollection) { dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); return -EINVAL; } + if (rest_bytes < h1->bLength) { + dev_err(&dev->dev, "invalid buffer length (v1)\n"); + return -EINVAL; + } + if (h1->bLength < sizeof(*h1) + h1->bInCollection) { dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); return -EINVAL; diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 183311cb849e..be78078a10ba 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -586,9 +586,10 @@ int line6_probe(struct usb_interface *interface, return 0; error: - if (line6->disconnect) - line6->disconnect(line6); - snd_card_free(card); + /* we can call disconnect callback here because no close-sync is + * needed yet at this point + */ + line6_disconnect(interface); return ret; } EXPORT_SYMBOL_GPL(line6_probe); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ad139d45f5b2..413824566102 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -215,7 +215,6 @@ static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) { int len = usb_string(state->chip->dev, index, buf, maxlen - 1); - buf[len] = 0; return len; } @@ -2437,6 +2436,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) { + /* kill pending URBs */ + snd_usb_mixer_disconnect(mixer); + kfree(mixer->id_elems); if (mixer->urb) { kfree(mixer->urb->transfer_buffer); @@ -2863,8 +2865,13 @@ _error: void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) { - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); + if (mixer->disconnected) + return; + if (mixer->urb) + usb_kill_urb(mixer->urb); + if (mixer->rc_urb) + usb_kill_urb(mixer->rc_urb); + mixer->disconnected = true; } #ifdef CONFIG_PM diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 2b4b067646ab..545d99b09706 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -22,6 +22,8 @@ struct usb_mixer_interface { struct urb *rc_urb; struct usb_ctrlrequest *rc_setup_packet; u8 rc_buffer[6]; + + bool disconnected; }; #define MAX_CHANNELS 16 /* max logical channels */ diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index bf618e1500ac..e7b934f4d837 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, } pg = get_order(read_size); - sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| + __GFP_NOWARN, pg); if (!sk->s) { snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); goto out; @@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, pg = get_order(write_size); sk->write_page = - (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| + __GFP_NOWARN, pg); if (!sk->write_page) { snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); usb_stream_free(sk); |
