diff options
27 files changed, 579 insertions, 120 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 6f0d99d560cd..acf12239c813 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -2107,7 +2107,9 @@ Required properties: "qcom,apq8096-asoc-snd-adp-agave" for adp agave codec and node is "sound-adp-agave", "qcom,apq8096-asoc-snd-adp-mmxf" for adp mmxf codec and - node is "sound-adp-mmxf". + node is "sound-adp-mmxf", + "qcom,apq8096-asoc-snd-auto-custom" for auto custom codec and + node is "sound-auto-custom". - qcom,model : The user-visible name of this sound card. - asoc-platform: This is phandle list containing the references to platform device nodes that are used as part of the sound card dai-links. diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index a2e7311705e3..74aefe4e616d 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -166,6 +166,7 @@ dtb-$(CONFIG_ARCH_SDM660) += sdm660-sim.dtb \ sdm660-pm660a-headset-jacktype-no-cdp.dtb \ sdm660-pm660a-headset-jacktype-no-rcm.dtb \ sdm660-usbc-audio-mtp.dtb \ + sdm660-usbc-audio-rcm.dtb \ sdm658-mtp.dtb \ sdm658-cdp.dtb \ sdm658-rcm.dtb \ @@ -191,6 +192,7 @@ dtb-$(CONFIG_ARCH_SDM630) += sdm630-rumi.dtb \ sdm630-pm660a-rumi.dtb \ sdm630-mtp.dtb \ sdm630-usbc-audio-mtp.dtb \ + sdm630-usbc-audio-rcm.dtb \ sdm630-cdp.dtb \ sdm630-rcm.dtb \ sdm630-internal-codec-mtp.dtb \ diff --git a/arch/arm/boot/dts/qcom/sdm630-usbc-audio-rcm.dts b/arch/arm/boot/dts/qcom/sdm630-usbc-audio-rcm.dts new file mode 100644 index 000000000000..6c944305acff --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm630-usbc-audio-rcm.dts @@ -0,0 +1,30 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "sdm630.dtsi" +#include "sdm630-cdp.dtsi" +#include "sdm660-external-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660L, USBC Audio, RCM"; + compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp"; + qcom,board-id = <21 3>; + qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>, + <0x0001001b 0x0201011a 0x0 0x0>; +}; + +&tavil_snd { + qcom,msm-mbhc-usbc-audio-supported = <1>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660-usbc-audio-rcm.dts b/arch/arm/boot/dts/qcom/sdm660-usbc-audio-rcm.dts new file mode 100644 index 000000000000..6528558e92ec --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm660-usbc-audio-rcm.dts @@ -0,0 +1,30 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "sdm660.dtsi" +#include "sdm660-cdp.dtsi" +#include "sdm660-external-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM 660 PM660 + PM660L, USBC Audio, RCM"; + compatible = "qcom,sdm660-cdp", "qcom,sdm660", "qcom,cdp"; + qcom,board-id = <21 3>; + qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>, + <0x0001001b 0x0201011a 0x0 0x0>; +}; + +&tavil_snd { + qcom,msm-mbhc-usbc-audio-supported = <1>; +}; diff --git a/block/genhd.c b/block/genhd.c index dae7c9ed87e5..7f1e8f81ceb4 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -656,12 +656,16 @@ void del_gendisk(struct gendisk *disk) disk->flags &= ~GENHD_FL_UP; sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); - /* - * Unregister bdi before releasing device numbers (as they can get - * reused and we'd get clashes in sysfs). - */ - bdi_unregister(&disk->queue->backing_dev_info); - blk_unregister_queue(disk); + if (disk->queue) { + /* + * Unregister bdi before releasing device numbers (as they can + * get reused and we'd get clashes in sysfs). + */ + bdi_unregister(&disk->queue->backing_dev_info); + blk_unregister_queue(disk); + } else { + WARN_ON(1); + } blk_unregister_region(disk_devt(disk), disk->minors); part_stat_set_all(&disk->part0, 0); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 8882f0bc94a5..51a08995442d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -393,6 +393,7 @@ static struct cpu_attr cpu_attrs[] = { _CPU_ATTR(online, &cpu_online_mask), _CPU_ATTR(possible, &cpu_possible_mask), _CPU_ATTR(present, &cpu_present_mask), + _CPU_ATTR(core_ctl_isolated, &cpu_isolated_mask), }; /* @@ -627,6 +628,7 @@ static struct attribute *cpu_root_attrs[] = { &cpu_attrs[0].attr.attr, &cpu_attrs[1].attr.attr, &cpu_attrs[2].attr.attr, + &cpu_attrs[3].attr.attr, &dev_attr_kernel_max.attr, &dev_attr_offline.attr, &dev_attr_isolated.attr, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 3faa5aaf9d03..89c7590ad121 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2675,11 +2675,11 @@ static void adreno_pwrlevel_change_settings(struct kgsl_device *device, } static void adreno_clk_set_options(struct kgsl_device *device, const char *name, - struct clk *clk) + struct clk *clk, bool on) { if (ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options) ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options( - ADRENO_DEVICE(device), name, clk); + ADRENO_DEVICE(device), name, clk, on); } static void adreno_iommu_sync(struct kgsl_device *device, bool sync) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 33fdb9ae11fa..218d08e6dfc3 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -789,7 +789,7 @@ struct adreno_gpudev { void (*preemption_schedule)(struct adreno_device *); void (*enable_64bit)(struct adreno_device *); void (*clk_set_options)(struct adreno_device *, - const char *, struct clk *); + const char *, struct clk *, bool on); }; /** diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 87300096fbf1..0715022be6e3 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1640,11 +1640,15 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev, } static void a5xx_clk_set_options(struct adreno_device *adreno_dev, - const char *name, struct clk *clk) + const char *name, struct clk *clk, bool on) { + + if (!adreno_is_a540(adreno_dev) && !adreno_is_a512(adreno_dev) && + !adreno_is_a508(adreno_dev)) + return; + /* Handle clock settings for GFX PSCBCs */ - if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev) || - adreno_is_a508(adreno_dev)) { + if (on) { if (!strcmp(name, "mem_iface_clk")) { clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); @@ -1652,6 +1656,11 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_RETAIN_MEM); } + } else { + if (!strcmp(name, "core_clk")) { + clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); + } } } diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index aca484618268..177b283a2dda 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -166,7 +166,7 @@ struct kgsl_functable { unsigned int prelevel, unsigned int postlevel, bool post); void (*regulator_disable_poll)(struct kgsl_device *device); void (*clk_set_options)(struct kgsl_device *device, - const char *name, struct clk *clk); + const char *name, struct clk *clk, bool on); void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); void (*stop_fault_timer)(struct kgsl_device *device); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index e4c431546d2a..0150d50c925b 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -150,9 +150,6 @@ static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr, *ab = pwr->bus_ab_mbytes; else *ab = (pwr->bus_percent_ab * max_bw) / 100; - - if (*ab > ib) - *ab = ib; } /** @@ -2003,10 +2000,6 @@ static int _get_clocks(struct kgsl_device *device) if (!strcmp(name, "isense_clk")) pwr->isense_clk_indx = i; - - if (device->ftbl->clk_set_options) - device->ftbl->clk_set_options(device, name, - pwr->grp_clks[i]); break; } } @@ -2453,6 +2446,22 @@ static void kgsl_pwrctrl_disable(struct kgsl_device *device) kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF); } +static void +kgsl_pwrctrl_clk_set_options(struct kgsl_device *device, bool on) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + int i; + + for (i = 0; i < KGSL_MAX_CLKS; i++) { + if (pwr->grp_clks[i] == NULL) + continue; + + if (device->ftbl->clk_set_options) + device->ftbl->clk_set_options(device, clocks[i], + pwr->grp_clks[i], on); + } +} + /** * _init() - Get the GPU ready to start, but don't turn anything on * @device - Pointer to the kgsl_device struct @@ -2499,6 +2508,7 @@ static int _wake(struct kgsl_device *device) device->ftbl->resume(device); /* fall through */ case KGSL_STATE_SLUMBER: + kgsl_pwrctrl_clk_set_options(device, true); status = device->ftbl->start(device, device->pwrctrl.superfast); device->pwrctrl.superfast = false; @@ -2535,6 +2545,7 @@ static int _wake(struct kgsl_device *device) device->pwrctrl.interval_timeout); break; case KGSL_STATE_AWARE: + kgsl_pwrctrl_clk_set_options(device, true); /* Enable state before turning on irq */ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); @@ -2649,6 +2660,7 @@ _slumber(struct kgsl_device *device) status = kgsl_pwrctrl_enable(device); device->ftbl->suspend_context(device); device->ftbl->stop(device); + kgsl_pwrctrl_clk_set_options(device, false); kgsl_pwrctrl_disable(device); kgsl_pwrscale_sleep(device); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index ec6075ec5767..311f6d639d06 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -428,7 +428,6 @@ void mmc_remove_card(struct mmc_card *card) } kfree(card->wr_pack_stats.packing_events); - kfree(card->cached_ext_csd); put_device(&card->dev); } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5396e1d00178..c409f713d4f0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2126,6 +2126,7 @@ int mmc_try_claim_host(struct mmc_host *host, unsigned int delay_ms) int claimed_host = 0; unsigned long flags; int retry_cnt = delay_ms/10; + bool pm = false; do { spin_lock_irqsave(&host->lock, flags); @@ -2134,11 +2135,17 @@ int mmc_try_claim_host(struct mmc_host *host, unsigned int delay_ms) host->claimer = current; host->claim_cnt += 1; claimed_host = 1; + if (host->claim_cnt == 1) + pm = true; } spin_unlock_irqrestore(&host->lock, flags); if (!claimed_host) mmc_delay(10); } while (!claimed_host && retry_cnt--); + + if (pm) + pm_runtime_get_sync(mmc_dev(host)); + if (host->ops->enable && claimed_host && host->claim_cnt == 1) host->ops->enable(host); return claimed_host; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 542f1733d0dd..5ab09b4ae868 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -722,7 +722,6 @@ static int mmc_read_ext_csd(struct mmc_card *card) return err; } - card->cached_ext_csd = ext_csd; err = mmc_decode_ext_csd(card, ext_csd); kfree(ext_csd); return err; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index dc22a29349cb..4a299f238c54 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -524,9 +524,8 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - wil_memcpy_fromio_halp_vote(wil_blob->wil, buf, - (const volatile void __iomem *) - wil_blob->blob.data + pos, count); + wil_memcpy_fromio_32(buf, (const void __iomem *) + wil_blob->blob.data + pos, count); ret = copy_to_user(user_buf, buf, count); kfree(buf); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 01a27335ec34..54d978d884ff 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -141,14 +141,6 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, } } -void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, - const volatile void __iomem *src, size_t count) -{ - wil_halp_vote(wil); - wil_memcpy_fromio_32(dst, src, count); - wil_halp_unvote(wil); -} - void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count) { @@ -167,15 +159,6 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, } } -void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, - volatile void __iomem *dst, - const void *src, size_t count) -{ - wil_halp_vote(wil); - wil_memcpy_toio_32(dst, src, count); - wil_halp_unvote(wil); -} - static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, u16 reason_code, bool from_event) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f64323b03a3b..6111ef6408ea 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -795,12 +795,6 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, size_t count); void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count); -void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, - const volatile void __iomem *src, - size_t count); -void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, - volatile void __iomem *dst, - const void *src, size_t count); void *wil_if_alloc(struct device *dev); void wil_if_free(struct wil6210_priv *wil); diff --git a/drivers/pinctrl/qcom/pinctrl-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpi.c index 4ca5d5fa0531..3fe41ee4c3c1 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpi.c @@ -408,13 +408,19 @@ static void lpi_gpio_set(struct gpio_chip *chip, unsigned pin, int value) static int lpi_notifier_service_cb(struct notifier_block *this, unsigned long opcode, void *ptr) { + static bool initial_boot = true; + pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); switch (opcode) { case AUDIO_NOTIFIER_SERVICE_DOWN: + if (initial_boot) + break; lpi_dev_up = false; break; case AUDIO_NOTIFIER_SERVICE_UP: + if (initial_boot) + initial_boot = false; lpi_dev_up = true; break; default: diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index c2902beaa0b8..08bffc344429 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2824,10 +2824,8 @@ static int msm_gsi_probe(struct platform_device *pdev) gsi_ctx->ipc_logbuf = ipc_log_context_create(GSI_IPC_LOG_PAGES, "gsi", 0); - if (gsi_ctx->ipc_logbuf == NULL) { - GSIERR("failed to get ipc_logbuf\n"); - return -ENOMEM; - } + if (gsi_ctx->ipc_logbuf == NULL) + GSIERR("failed to create IPC log, continue...\n"); gsi_ctx->dev = dev; init_completion(&gsi_ctx->gen_ee_cmd_compl); diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index e8249163e948..b4fb80a2d4f3 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -1133,6 +1133,9 @@ static int smb2_init_vconn_regulator(struct smb2 *chip) struct regulator_config cfg = {}; int rc = 0; + if (chg->micro_usb_mode) + return 0; + chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg), GFP_KERNEL); if (!chg->vconn_vreg) @@ -1344,9 +1347,10 @@ static int smb2_disable_typec(struct smb_charger *chg) int rc; /* Move to typeC mode */ - /* configure FSM in idle state */ + /* configure FSM in idle state and disable UFP_ENABLE bit */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, - TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT); + TYPEC_DISABLE_CMD_BIT | UFP_EN_CMD_BIT, + TYPEC_DISABLE_CMD_BIT); if (rc < 0) { dev_err(chg->dev, "Couldn't put FSM in idle rc=%d\n", rc); return rc; @@ -2131,7 +2135,7 @@ static int smb2_probe(struct platform_device *pdev) rc = smb2_init_vconn_regulator(chip); if (rc < 0) { pr_err("Couldn't initialize vconn regulator rc=%d\n", - rc); + rc); goto cleanup; } diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 51c87f963307..c74b310bd470 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -4117,6 +4117,9 @@ static void smblib_vconn_oc_work(struct work_struct *work) int rc, i; u8 stat; + if (chg->micro_usb_mode) + return; + smblib_err(chg, "over-current detected on VCONN\n"); if (!chg->vconn_vreg || !chg->vconn_vreg->rdev) return; diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c index 176c3888aa34..7a501d6d7c84 100644 --- a/drivers/scsi/ufs/ufs_quirks.c +++ b/drivers/scsi/ufs/ufs_quirks.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -30,6 +30,20 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_HYNIX, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), + UFS_FIX(UFS_VENDOR_HYNIX, "hB8aL1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "hC8aL1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "hD8aL1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "hC8aM1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "h08aM1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "hC8GL1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), + UFS_FIX(UFS_VENDOR_HYNIX, "hC8HL1", + UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), END_FIX }; diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index b8ab5948f12d..3102517e841c 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -139,6 +139,14 @@ struct ufs_card_fix { */ #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 7) +/* + * Some UFS devices may stop responding after switching from HS-G1 to HS-G3. + * Also, it is found that these devices work fine if we do 2 steps switch: + * HS-G1 to HS-G2 followed by HS-G2 to HS-G3. Enabling this quirk for such + * device would apply this 2 steps gear switch workaround. + */ +#define UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH (1 << 8) + struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 16f130dd3c76..3e858015813f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -509,7 +509,7 @@ out: /* replace non-printable or non-ASCII characters with spaces */ static inline void ufshcd_remove_non_printable(char *val) { - if (!val) + if (!val || !*val) return; if (*val < 0x20 || *val > 0x7e) @@ -3651,7 +3651,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf, goto out; } - buff_ascii = kmalloc(ascii_len, GFP_KERNEL); + buff_ascii = kzalloc(ascii_len, GFP_KERNEL); if (!buff_ascii) { dev_err(hba->dev, "%s: Failed allocating %d bytes\n", __func__, ascii_len); @@ -9207,6 +9207,31 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) if (scale_up) { memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info.info, sizeof(struct ufs_pa_layer_attr)); + /* + * Some UFS devices may stop responding after switching from + * HS-G1 to HS-G3. Also, it is found that these devices work + * fine if we do 2 steps switch: HS-G1 to HS-G2 followed by + * HS-G2 to HS-G3. If UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH + * quirk is enabled for such devices, this 2 steps gear switch + * workaround will be applied. + */ + if ((hba->dev_quirks & UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH) + && (hba->pwr_info.gear_tx == UFS_HS_G1) + && (new_pwr_info.gear_tx == UFS_HS_G3)) { + /* scale up to G2 first */ + new_pwr_info.gear_tx = UFS_HS_G2; + new_pwr_info.gear_rx = UFS_HS_G2; + ret = ufshcd_change_power_mode(hba, &new_pwr_info); + if (ret) + goto out; + + /* scale up to G3 now */ + new_pwr_info.gear_tx = UFS_HS_G3; + new_pwr_info.gear_rx = UFS_HS_G3; + ret = ufshcd_change_power_mode(hba, &new_pwr_info); + if (ret) + goto out; + } } else { memcpy(&new_pwr_info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); @@ -9226,10 +9251,10 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) new_pwr_info.pwr_rx = FASTAUTO_MODE; } } + ret = ufshcd_change_power_mode(hba, &new_pwr_info); } - ret = ufshcd_change_power_mode(hba, &new_pwr_info); - +out: if (ret) dev_err(hba->dev, "%s: failed err %d, old gear: (tx %d rx %d), new gear: (tx %d rx %d), scale_up = %d", __func__, ret, @@ -9292,10 +9317,29 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) goto clk_scaling_unprepare; } + /* + * If auto hibern8 is supported then put the link in + * hibern8 manually, this is to avoid auto hibern8 + * racing during clock frequency scaling sequence. + */ + if (ufshcd_is_auto_hibern8_supported(hba)) { + ret = ufshcd_uic_hibern8_enter(hba); + if (ret) + /* link will be bad state so no need to scale_up_gear */ + return ret; + } + ret = ufshcd_scale_clks(hba, scale_up); if (ret) goto scale_up_gear; + if (ufshcd_is_auto_hibern8_supported(hba)) { + ret = ufshcd_uic_hibern8_exit(hba); + if (ret) + /* link will be bad state so no need to scale_up_gear */ + return ret; + } + /* scale up the gear after scaling up clocks */ if (scale_up) { ret = ufshcd_scale_gear(hba, true); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 1c87478b5fc0..3d426520bfa1 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -432,7 +432,6 @@ struct mmc_card { struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/ struct notifier_block reboot_notify; enum mmc_pon_type pon_type; - u8 *cached_ext_csd; bool cmdq_init; struct mmc_bkops_info bkops; }; diff --git a/sound/soc/msm/apq8096-auto.c b/sound/soc/msm/apq8096-auto.c index 138f4a02452c..7b363bdca291 100644 --- a/sound/soc/msm/apq8096-auto.c +++ b/sound/soc/msm/apq8096-auto.c @@ -115,6 +115,9 @@ static int msm_ec_ref_ch = 4; static int msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int msm_ec_ref_sampling_rate = SAMPLING_RATE_48KHZ; +static int msm_tdm_slot_width = 32; +static int msm_tdm_num_slots = 8; + static void *adsp_state_notifier; static bool dummy_device_registered; @@ -295,6 +298,62 @@ static unsigned int tdm_slot_offset_adp_mmxf[TDM_MAX][TDM_SLOT_OFFSET_MAX] = { {0xFFFF}, /* not used */ }; +static unsigned int tdm_slot_offset_custom[TDM_MAX][TDM_SLOT_OFFSET_MAX] = { + /* QUAT_TDM_RX */ + {0, 2, 0xFFFF}, + {4, 6, 8, 10, 12, 14, 16, 18}, + {20, 22, 24, 26, 28, 30, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + /* QUAT_TDM_TX */ + {0, 2, 0xFFFF}, + {4, 6, 8, 10, 12, 14, 16, 18}, + {20, 22, 24, 26, 28, 30, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + /* TERT_TDM_RX */ + {0, 2, 0xFFFF}, + {4, 0xFFFF}, + {6, 0xFFFF}, + {8, 0xFFFF}, + {10, 0xFFFF}, + {12, 14, 16, 18, 20, 22, 24, 26}, + {28, 30, 0xFFFF}, + {0xFFFF}, /* not used */ + /* TERT_TDM_TX */ + {0, 2, 4, 6, 8, 10, 12, 0xFFFF}, + {14, 16, 0xFFFF}, + {18, 20, 22, 24, 26, 28, 30, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + /* SEC_TDM_RX */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + /* SEC_TDM_TX */ + {0xFFFF}, + {0xFFFF}, + {0xFFFF}, + {0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ +}; static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five", "Six", "Seven", "Eight"}; @@ -2256,44 +2315,38 @@ static int apq8096_tdm_snd_hw_params(struct snd_pcm_substream *substream, pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); channels = params_channels(params); - switch (channels) { - case 1: - case 2: - case 3: - case 4: - case 6: - case 8: - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S32_LE: - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S16_LE: - /* - * up to 8 channel HW configuration should - * use 32 bit slot width for max support of - * stream bit width. (slot_width > bit_width) - */ - slot_width = 32; - break; - default: - pr_err("%s: invalid param format 0x%x\n", - __func__, params_format(params)); - return -EINVAL; - } - slots = 8; - slot_mask = tdm_param_set_slot_mask(cpu_dai->id, - slot_width, slots); - if (!slot_mask) { - pr_err("%s: invalid slot_mask 0x%x\n", - __func__, slot_mask); - return -EINVAL; - } - break; - default: + if (channels < 1 || channels > 8) { pr_err("%s: invalid param channels %d\n", __func__, channels); return -EINVAL; } + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S16_LE: + /* + * up to 8 channel HW configuration should + * use 32 bit slot width for max support of + * stream bit width. (slot_width > bit_width) + */ + slot_width = msm_tdm_slot_width; + break; + default: + pr_err("%s: invalid param format 0x%x\n", + __func__, params_format(params)); + return -EINVAL; + } + + slots = msm_tdm_num_slots; + slot_mask = tdm_param_set_slot_mask(cpu_dai->id, + slot_width, slots); + if (!slot_mask) { + pr_err("%s: invalid slot_mask 0x%x\n", + __func__, slot_mask); + return -EINVAL; + } + switch (cpu_dai->id) { case AFE_PORT_ID_SECONDARY_TDM_RX: slot_offset = tdm_slot_offset[SECONDARY_TDM_RX_0]; @@ -2660,7 +2713,7 @@ static int apq8096_get_ll_qos_val(struct snd_pcm_runtime *runtime) return usecs; } -static int apq8096_mm5_prepare(struct snd_pcm_substream *substream) +static int apq8096_ll_prepare(struct snd_pcm_substream *substream) { if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -2670,8 +2723,8 @@ static int apq8096_mm5_prepare(struct snd_pcm_substream *substream) return 0; } -static struct snd_soc_ops apq8096_mm5_ops = { - .prepare = apq8096_mm5_prepare, +static struct snd_soc_ops apq8096_ll_ops = { + .prepare = apq8096_ll_prepare, }; /* Digital audio interface glue - connects codec <---> CPU */ @@ -2938,7 +2991,7 @@ static struct snd_soc_dai_link apq8096_common_dai_links[] = { /* this dainlink has playback support */ .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, - .ops = &apq8096_mm5_ops, + .ops = &apq8096_ll_ops, }, { .name = "Listen 1 Audio Service", @@ -3647,6 +3700,143 @@ static struct snd_soc_dai_link apq8096_auto_fe_dai_links[] = { }, }; +static struct snd_soc_dai_link apq8096_custom_fe_dai_links[] = { + /* FrontEnd DAI Links */ + { + .name = "MSM8996 Media1", + .stream_name = "MultiMedia1", + .cpu_dai_name = "MultiMedia1", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media2", + .stream_name = "MultiMedia2", + .cpu_dai_name = "MultiMedia2", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media3", + .stream_name = "MultiMedia3", + .cpu_dai_name = "MultiMedia3", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media5", + .stream_name = "MultiMedia5", + .cpu_dai_name = "MultiMedia5", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media6", + .stream_name = "MultiMedia6", + .cpu_dai_name = "MultiMedia6", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media8", + .stream_name = "MultiMedia8", + .cpu_dai_name = "MultiMedia8", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8, + .ops = &apq8096_ll_ops, + }, + { + .name = "MSM8996 Media9", + .stream_name = "MultiMedia9", + .cpu_dai_name = "MultiMedia9", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9, + .ops = &apq8096_ll_ops, + }, +}; + static struct snd_soc_dai_link apq8096_common_be_dai_links[] = { /* Backend AFE DAI Links */ { @@ -4115,6 +4305,13 @@ static struct snd_soc_dai_link apq8096_auto_dai_links[ ARRAY_SIZE(apq8096_auto_be_dai_links) + ARRAY_SIZE(apq8096_hdmi_dai_link)]; +static struct snd_soc_dai_link apq8096_auto_custom_dai_links[ + ARRAY_SIZE(apq8096_custom_fe_dai_links) + + ARRAY_SIZE(apq8096_auto_fe_dai_links) + + ARRAY_SIZE(apq8096_common_be_dai_links) + + ARRAY_SIZE(apq8096_auto_be_dai_links) + + ARRAY_SIZE(apq8096_hdmi_dai_link)]; + struct snd_soc_card snd_soc_card_auto_apq8096 = { .name = "apq8096-auto-snd-card", }; @@ -4127,6 +4324,10 @@ struct snd_soc_card snd_soc_card_adp_mmxf_apq8096 = { .name = "apq8096-adp-mmxf-snd-card", }; +struct snd_soc_card snd_soc_card_auto_custom_apq8096 = { + .name = "apq8096-auto-custom-snd-card", +}; + static int apq8096_populate_dai_link_component_of_node( struct snd_soc_card *card) { @@ -4220,6 +4421,8 @@ static const struct of_device_id apq8096_asoc_machine_of_match[] = { .data = "adp_agave_codec"}, { .compatible = "qcom,apq8096-asoc-snd-adp-mmxf", .data = "adp_mmxf_codec"}, + { .compatible = "qcom,apq8096-asoc-snd-auto-custom", + .data = "auto_custom_codec"}, {}, }; @@ -4243,31 +4446,55 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) card = &snd_soc_card_adp_agave_apq8096; else if (!strcmp(match->data, "adp_mmxf_codec")) card = &snd_soc_card_adp_mmxf_apq8096; - else { + else if (!strcmp(match->data, "auto_custom_codec")) { + card = &snd_soc_card_auto_custom_apq8096; + } else { dev_err(dev, "%s: Codec not supported\n", __func__); return NULL; } - /* same FE and BE used for all codec */ - len_1 = ARRAY_SIZE(apq8096_common_dai_links); - len_2 = len_1 + ARRAY_SIZE(apq8096_auto_fe_dai_links); - len_3 = len_2 + ARRAY_SIZE(apq8096_common_be_dai_links); - - memcpy(apq8096_auto_dai_links, - apq8096_common_dai_links, - sizeof(apq8096_common_dai_links)); - memcpy(apq8096_auto_dai_links + len_1, - apq8096_auto_fe_dai_links, - sizeof(apq8096_auto_fe_dai_links)); - memcpy(apq8096_auto_dai_links + len_2, - apq8096_common_be_dai_links, - sizeof(apq8096_common_be_dai_links)); - memcpy(apq8096_auto_dai_links + len_3, - apq8096_auto_be_dai_links, - sizeof(apq8096_auto_be_dai_links)); - - dailink = apq8096_auto_dai_links; + if (!strcmp(match->data, "auto_custom_codec")) { + len_1 = ARRAY_SIZE(apq8096_custom_fe_dai_links); + len_2 = len_1 + ARRAY_SIZE(apq8096_auto_fe_dai_links); + len_3 = len_2 + ARRAY_SIZE(apq8096_common_be_dai_links); + + memcpy(apq8096_auto_custom_dai_links, + apq8096_custom_fe_dai_links, + sizeof(apq8096_custom_fe_dai_links)); + memcpy(apq8096_auto_custom_dai_links + len_1, + apq8096_auto_fe_dai_links, + sizeof(apq8096_auto_fe_dai_links)); + memcpy(apq8096_auto_custom_dai_links + len_2, + apq8096_common_be_dai_links, + sizeof(apq8096_common_be_dai_links)); + memcpy(apq8096_auto_custom_dai_links + len_3, + apq8096_auto_be_dai_links, + sizeof(apq8096_auto_be_dai_links)); + + dailink = apq8096_auto_custom_dai_links; + } else { + /* same FE and BE used for all non-custom codec */ + len_1 = ARRAY_SIZE(apq8096_common_dai_links); + len_2 = len_1 + ARRAY_SIZE(apq8096_auto_fe_dai_links); + len_3 = len_2 + ARRAY_SIZE(apq8096_common_be_dai_links); + + memcpy(apq8096_auto_dai_links, + apq8096_common_dai_links, + sizeof(apq8096_common_dai_links)); + memcpy(apq8096_auto_dai_links + len_1, + apq8096_auto_fe_dai_links, + sizeof(apq8096_auto_fe_dai_links)); + memcpy(apq8096_auto_dai_links + len_2, + apq8096_common_be_dai_links, + sizeof(apq8096_common_be_dai_links)); + memcpy(apq8096_auto_dai_links + len_3, + apq8096_auto_be_dai_links, + sizeof(apq8096_auto_be_dai_links)); + + dailink = apq8096_auto_dai_links; + } + len_4 = len_3 + ARRAY_SIZE(apq8096_auto_be_dai_links); if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) { @@ -4308,10 +4535,20 @@ static int apq8096_init_tdm_dev(struct device *dev) memcpy(tdm_slot_offset, tdm_slot_offset_adp_mmxf, sizeof(tdm_slot_offset_adp_mmxf)); + } else if (!strcmp(match->data, "auto_custom_codec")) { + dev_dbg(dev, "%s: custom tdm slot offset\n", __func__); + msm_tdm_slot_width = 16; + msm_tdm_num_slots = 16; + memcpy(tdm_slot_offset, + tdm_slot_offset_custom, + sizeof(tdm_slot_offset_custom)); } else { dev_dbg(dev, "%s: DEFAULT tdm slot offset\n", __func__); } + dev_dbg(dev, "%s: tdm slot_width %d, num_slots %d\n", + __func__, msm_tdm_slot_width, msm_tdm_num_slots); + return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 837a08488991..7ce73484a681 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -5362,6 +5362,57 @@ static const struct snd_kcontrol_new tert_tdm_rx_3_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new tert_tdm_rx_4_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new quat_tdm_rx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_QUAT_TDM_RX_0 , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -11158,6 +11209,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("TERT_TDM_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, tert_tdm_rx_3_mixer_controls, ARRAY_SIZE(tert_tdm_rx_3_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_TDM_RX_4 Audio Mixer", SND_SOC_NOPM, 0, 0, + tert_tdm_rx_4_mixer_controls, + ARRAY_SIZE(tert_tdm_rx_4_mixer_controls)), SND_SOC_DAPM_MIXER("QUAT_TDM_RX_0 Audio Mixer", SND_SOC_NOPM, 0, 0, quat_tdm_rx_0_mixer_controls, ARRAY_SIZE(quat_tdm_rx_0_mixer_controls)), @@ -12182,6 +12236,24 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_3", NULL, "TERT_TDM_RX_3 Audio Mixer"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"TERT_TDM_RX_4", NULL, "TERT_TDM_RX_4 Audio Mixer"}, + {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -12937,6 +13009,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VOIP_UL", NULL, "VOC_EXT_EC MUX"}, {"VoLTE_UL", NULL, "VOC_EXT_EC MUX"}, {"VOICE2_UL", NULL, "VOC_EXT_EC MUX"}, + {"VoWLAN_UL", NULL, "VOC_EXT_EC MUX"}, {"VOICEMMODE1_UL", NULL, "VOC_EXT_EC MUX"}, {"VOICEMMODE2_UL", NULL, "VOC_EXT_EC MUX"}, @@ -13890,6 +13963,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "TERT_TDM_RX_1"}, {"BE_OUT", NULL, "TERT_TDM_RX_2"}, {"BE_OUT", NULL, "TERT_TDM_RX_3"}, + {"BE_OUT", NULL, "TERT_TDM_RX_4"}, {"BE_OUT", NULL, "QUAT_TDM_RX_0"}, {"BE_OUT", NULL, "QUAT_TDM_RX_1"}, {"BE_OUT", NULL, "QUAT_TDM_RX_2"}, |
