From ef9bec27485fefb6b93168fea73fda0dc9638046 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 26 Jun 2019 00:04:50 -0700 Subject: ASoC: SOF: Intel: hda: Make hdac_device device-managed snd_hdac_ext_bus_device_exit() has been recently modified to no longer free the hdac device. SOF allocates memory for hdac_device and hda_hda_priv with kzalloc. Make them device-managed instead so that they will be freed when the SOF driver is unloaded. Because of the above change, hda_codec is device-managed and it will be freed when the ASoC device is removed. Freeing the codec in snd_hda_codec_dev_release() leads to kernel panic while unloading and reloading the ASoC driver. So, avoid freeing the hda_codec for ASoC driver. This is done in the same patch to avoid bisect failure. Signed-off-by: Libin Yang Signed-off-by: Ranjani Sridharan Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190626070450.7229-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/pci/hda/hda_codec.c | 8 +++++++- sound/soc/sof/intel/hda-codec.c | 6 ++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e30e86ca6b72..133200d31170 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev) snd_hda_sysfs_clear(codec); kfree(codec->modelname); kfree(codec->wcaps); - kfree(codec); + + /* + * In the case of ASoC HD-audio, hda_codec is device managed. + * It will be freed when the ASoC device is removed. + */ + if (codec->core.type == HDA_DEV_LEGACY) + kfree(codec); } #define DEV_NAME_LEN 31 diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index b8b37f082309..0d8437b080bf 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -62,8 +62,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) address, resp); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ - hda_priv = kzalloc(sizeof(*hda_priv), GFP_KERNEL); + hda_priv = devm_kzalloc(sdev->dev, sizeof(*hda_priv), GFP_KERNEL); if (!hda_priv) return -ENOMEM; @@ -82,8 +81,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) return 0; #else - /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); + hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); if (!hdev) return -ENOMEM; -- cgit v1.2.3 From f7408a3d5b5fd10571a653d1a81ce9167c62727f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Jul 2019 22:04:25 -0700 Subject: ASoC: wcd9335: Fix misuse of GENMASK macro Arguments are supposed to be ordered high then low. Signed-off-by: Joe Perches Link: https://lore.kernel.org/r/92e31a9f321fe731d428ec3ec9d4654ea8a16d1b.1562734889.git.joe@perches.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd-clsh-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd-clsh-v2.c b/sound/soc/codecs/wcd-clsh-v2.c index c397d713f01a..cc5a9c9b918b 100644 --- a/sound/soc/codecs/wcd-clsh-v2.c +++ b/sound/soc/codecs/wcd-clsh-v2.c @@ -65,7 +65,7 @@ struct wcd_clsh_ctrl { #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 #define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) -#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3) +#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(3, 0) #define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) #define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) #define WCD9XXX_HPH_CONST_SEL_BYPASS 0 -- cgit v1.2.3 From eaba5585944e6d692828bca701c9362f60172b8a Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Wed, 10 Jul 2019 13:51:19 +0300 Subject: ASoC: codecs: ad193x: Use regmap_multi_reg_write() when initializing Using regmap_multi_reg_write() when we set the default values for our registers makes the code smaller and easier to read. Suggested-by: Tzung-Bi Shih Signed-off-by: Codrin Ciubotariu Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190710105119.22987-1-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 80dab5df9633..fb04c9379b71 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { .ops = &ad193x_dai_ops, }; -struct ad193x_reg_default { - unsigned int reg; - unsigned int val; -}; - /* codec register values to set after reset */ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { - const struct ad193x_reg_default reg_init[] = { + const struct reg_sequence reg_init[] = { { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ @@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ }; - const struct ad193x_reg_default reg_adc_init[] = { + const struct reg_sequence reg_adc_init[] = { { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ { 16, 0x00 }, /* ADC_CTRL2: reset */ }; - int i; - for (i = 0; i < ARRAY_SIZE(reg_init); i++) - regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val); + regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init)); if (ad193x_has_adc(ad193x)) { - for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { - regmap_write(ad193x->regmap, reg_adc_init[i].reg, - reg_adc_init[i].val); - } + regmap_multi_reg_write(ad193x->regmap, reg_adc_init, + ARRAY_SIZE(reg_adc_init)); } } -- cgit v1.2.3 From 4dc057a786dc23fd1ed70e6bcab691c0f26daa1e Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 10 Jul 2019 17:28:38 -0700 Subject: ASoC: rt5677: remove superfluous set We define this variable with the same value, no need to set it twice Signed-off-by: Curtis Malainey Link: https://lore.kernel.org/r/20190711002838.35363-1-cujomalainey@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index c779dc3474f9..deaed5132dc9 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5098,7 +5098,6 @@ static irqreturn_t rt5677_irq(int unused, void *data) goto exit; } - irq_fired = false; for (i = 0; i < RT5677_IRQ_NUM; i++) { if (reg_irq & rt5677_irq_descs[i].status_mask) { irq_fired = true; -- cgit v1.2.3 From 5be6155b50bbf7083b4bfa219e4ce6d1491f42f0 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 11 Jul 2019 18:49:45 +0800 Subject: ASoC: fsl_esai: Wrap some operations to be functions Extract the operation to be functions, to improve the readability. In this patch, fsl_esai_hw_init, fsl_esai_register_restore, fsl_esai_trigger_start and fsl_esai_trigger_stop are extracted. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/804d7e75ae7e06a913479912b578b3538ca7cd3f.1562842206.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 188 +++++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 71 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 10d2210c91ef..ab460d6d7432 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -35,6 +35,7 @@ * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @slots: number of slots + * @channels: channel num for tx or rx * @hck_rate: clock rate of desired HCKx clock * @sck_rate: clock rate of desired SCKx clock * @hck_dir: the direction of HCKx pads @@ -57,6 +58,7 @@ struct fsl_esai { u32 slots; u32 tx_mask; u32 rx_mask; + u32 channels[2]; u32 hck_rate[2]; u32 sck_rate[2]; bool hck_dir[2]; @@ -543,64 +545,132 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, return 0; } +static int fsl_esai_hw_init(struct fsl_esai *esai_priv) +{ + struct platform_device *pdev = esai_priv->pdev; + int ret; + + /* Reset ESAI unit */ + ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, + ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, + ESAI_ECR_ESAIEN | ESAI_ECR_ERST); + if (ret) { + dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); + return ret; + } + + /* + * We need to enable ESAI so as to access some of its registers. + * Otherwise, we would fail to dump regmap from user space. + */ + ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, + ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, + ESAI_ECR_ESAIEN); + if (ret) { + dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); + return ret; + } + + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, + ESAI_PRRC_PDC_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, + ESAI_PCRC_PC_MASK, 0); + + return 0; +} + +static int fsl_esai_register_restore(struct fsl_esai *esai_priv) +{ + int ret; + + /* FIFO reset for safety */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, + ESAI_xFCR_xFR, ESAI_xFCR_xFR); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, + ESAI_xFCR_xFR, ESAI_xFCR_xFR); + + regcache_mark_dirty(esai_priv->regmap); + ret = regcache_sync(esai_priv->regmap); + if (ret) + return ret; + + /* FIFO reset done */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); + + return 0; +} + +static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) +{ + u8 i, channels = esai_priv->channels[tx]; + u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); + u32 mask; + + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); + + /* Write initial words reqiured by ESAI as normal procedure */ + for (i = 0; tx && i < channels; i++) + regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); + + /* + * When set the TE/RE in the end of enablement flow, there + * will be channel swap issue for multi data line case. + * In order to workaround this issue, we switch the bit + * enablement sequence to below sequence + * 1) clear the xSMB & xSMA: which is done in probe and + * stop state. + * 2) set TE/RE + * 3) set xSMB + * 4) set xSMA: xSMA is the last one in this flow, which + * will trigger esai to start. + */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, + tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); + mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; + + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), + ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), + ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); +} + +static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) +{ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), + ESAI_xSMA_xS_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), + ESAI_xSMB_xS_MASK, 0); + + /* Disable and reset FIFO */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFR, 0); +} + static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - u8 i, channels = substream->runtime->channels; - u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); - u32 mask; + + esai_priv->channels[tx] = substream->runtime->channels; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); - - /* Write initial words reqiured by ESAI as normal procedure */ - for (i = 0; tx && i < channels; i++) - regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); - - /* - * When set the TE/RE in the end of enablement flow, there - * will be channel swap issue for multi data line case. - * In order to workaround this issue, we switch the bit - * enablement sequence to below sequence - * 1) clear the xSMB & xSMA: which is done in probe and - * stop state. - * 2) set TE/RE - * 3) set xSMB - * 4) set xSMA: xSMA is the last one in this flow, which - * will trigger esai to start. - */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), - tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, - tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); - mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; - - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), - ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), - ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); - + fsl_esai_trigger_start(esai_priv, tx); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), - tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), - ESAI_xSMA_xS_MASK, 0); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), - ESAI_xSMB_xS_MASK, 0); - - /* Disable and reset FIFO */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFR, 0); + fsl_esai_trigger_stop(esai_priv, tx); break; default: return -EINVAL; @@ -866,22 +936,9 @@ static int fsl_esai_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, esai_priv); - /* Reset ESAI unit */ - ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); - if (ret) { - dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); - return ret; - } - - /* - * We need to enable ESAI so as to access some of its registers. - * Otherwise, we would fail to dump regmap from user space. - */ - ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); - if (ret) { - dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); + ret = fsl_esai_hw_init(esai_priv); + if (ret) return ret; - } esai_priv->tx_mask = 0xFFFFFFFF; esai_priv->rx_mask = 0xFFFFFFFF; @@ -955,20 +1012,10 @@ static int fsl_esai_runtime_resume(struct device *dev) regcache_cache_only(esai->regmap, false); - /* FIFO reset for safety */ - regmap_update_bits(esai->regmap, REG_ESAI_TFCR, - ESAI_xFCR_xFR, ESAI_xFCR_xFR); - regmap_update_bits(esai->regmap, REG_ESAI_RFCR, - ESAI_xFCR_xFR, ESAI_xFCR_xFR); - - ret = regcache_sync(esai->regmap); + ret = fsl_esai_register_restore(esai); if (ret) goto err_regcache_sync; - /* FIFO reset done */ - regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); - regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); - return 0; err_regcache_sync: @@ -991,7 +1038,6 @@ static int fsl_esai_runtime_suspend(struct device *dev) struct fsl_esai *esai = dev_get_drvdata(dev); regcache_cache_only(esai->regmap, true); - regcache_mark_dirty(esai->regmap); if (!IS_ERR(esai->fsysclk)) clk_disable_unprepare(esai->fsysclk); -- cgit v1.2.3 From 1d3dd532883be6167da5df6117efd6d4e8790456 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Tue, 9 Jul 2019 23:55:43 +0530 Subject: sound: soc: codecs: mt6358: change return type of mt6358_codec_init_reg As mt6358_codec_init_reg function always returns 0 , change return type from int to void. fixes below issue reported by coccicheck sound/soc/codecs/mt6358.c:2260:5-8: Unneeded variable: "ret". Return "0" on line 2289 Signed-off-by: Hariprasad Kelam Acked-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190709182543.GA6611@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 50b3fc5457ea..c17250aab2d0 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -2255,10 +2255,8 @@ static struct snd_soc_dai_driver mt6358_dai_driver[] = { }, }; -static int mt6358_codec_init_reg(struct mt6358_priv *priv) +static void mt6358_codec_init_reg(struct mt6358_priv *priv) { - int ret = 0; - /* Disable HeadphoneL/HeadphoneR short circuit protection */ regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0, RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, @@ -2285,8 +2283,6 @@ static int mt6358_codec_init_reg(struct mt6358_priv *priv) /* set gpio */ playback_gpio_reset(priv); capture_gpio_reset(priv); - - return ret; } static int mt6358_codec_probe(struct snd_soc_component *cmpnt) -- cgit v1.2.3 From e1fb714bddf452ef0ecf67c420957438977f107d Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 10 Jul 2019 00:12:37 +0530 Subject: ASoC: bcm: cygnus-pcm: Unneeded variable: "ret". This patch fixes below issues reported by coccicheck sound/soc/bcm/cygnus-pcm.c:642:5-8: Unneeded variable: "ret". Return "0" on line 650 sound/soc/bcm/cygnus-pcm.c:671:5-8: Unneeded variable: "ret". Return "0" on line 696 We cannot change return type of these functions as they are callback functions of snd_pcm_ops Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190709184236.GA7873@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 123ecf5479d7..8966b02844dc 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; - int ret = 0; aio = cygnus_dai_get_dma_data(substream); dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); @@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); - return ret; + return 0; } static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) @@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; unsigned long bufsize, periodsize; - int ret = 0; bool is_play; u32 start; struct ringbuf_regs *p_rbuf = NULL; @@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, periodsize, bufsize); - return ret; + return 0; } static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) -- cgit v1.2.3 From af62a3c8a872631e63833e2a99a8f43f81532fae Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 10 Jul 2019 07:46:27 +0530 Subject: ASoC: wcd9335: add irqflag IRQF_ONESHOT flag Add IRQF_ONESHOT to ensure "Interrupt is not reenabled after the hardirq handler finished". fixes below issue reported by coccicheck sound/soc/codecs/wcd9335.c:4068:8-33: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190710021627.GA13396@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 1bbbe421b999..956602788d0e 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -4062,7 +4062,8 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd) ret = devm_request_threaded_irq(wcd->dev, irq, NULL, wcd9335_irqs[i].handler, - IRQF_TRIGGER_RISING, + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, wcd9335_irqs[i].name, wcd); if (ret) { dev_err(wcd->dev, "Failed to request %s\n", -- cgit v1.2.3 From a962a809e5e45715081fa247726a562b8dbd082a Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Tue, 16 Jul 2019 11:24:17 +0800 Subject: ASoC: mediatek: mt8183: make headset codec optional Make headset codec optional because some variant machines may not have an audio jack. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190716032417.19015-1-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 887c932229d0..4c816c86844b 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -352,8 +352,6 @@ static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { .owner = THIS_MODULE, .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), - .aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev, - .num_aux_devs = 1, }; static int @@ -404,10 +402,9 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,headset-codec", 0); - if (!mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { - dev_err(&pdev->dev, - "Property 'mediatek,headset-codec' missing/invalid\n"); - return -EINVAL; + if (mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { + card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; + card->num_aux_devs = 1; } default_pins = -- cgit v1.2.3 From 89c9679f699d88986ce552738dc7c5c500c8fc67 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:56:33 +0200 Subject: ASoC: fsl_sai: add of_match data New revisions of the SAI IP block have even more differences that need be taken into account by the driver. To avoid sprinking compatible checks all over the driver move the current differences into of_match_data. Signed-off-by: Lucas Stach Tested-by: Angus Ainslie Reviewed-by: Angus Ainslie Reviewed-by: Daniel Baluta Link: https://lore.kernel.org/r/20190717105635.18514-2-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 22 ++++++++++++++-------- sound/soc/fsl/fsl_sai.h | 6 +++++- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index d58cc3ae90d8..ed0432e7327a 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -788,10 +789,7 @@ static int fsl_sai_probe(struct platform_device *pdev) return -ENOMEM; sai->pdev = pdev; - - if (of_device_is_compatible(np, "fsl,imx6sx-sai") || - of_device_is_compatible(np, "fsl,imx6ul-sai")) - sai->sai_on_imx = true; + sai->soc_data = of_device_get_match_data(&pdev->dev); sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); @@ -900,7 +898,7 @@ static int fsl_sai_probe(struct platform_device *pdev) if (ret) return ret; - if (sai->sai_on_imx) + if (sai->soc_data->use_imx_pcm) return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); else return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); @@ -913,10 +911,18 @@ static int fsl_sai_remove(struct platform_device *pdev) return 0; } +static const struct fsl_sai_soc_data fsl_sai_vf610_data = { + .use_imx_pcm = false, +}; + +static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { + .use_imx_pcm = true, +}; + static const struct of_device_id fsl_sai_ids[] = { - { .compatible = "fsl,vf610-sai", }, - { .compatible = "fsl,imx6sx-sai", }, - { .compatible = "fsl,imx6ul-sai", }, + { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data }, + { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data }, + { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 24cb156bf995..83e2bfe05b1b 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -126,6 +126,10 @@ #define FSL_SAI_MAXBURST_TX 6 #define FSL_SAI_MAXBURST_RX 6 +struct fsl_sai_soc_data { + bool use_imx_pcm; +}; + struct fsl_sai { struct platform_device *pdev; struct regmap *regmap; @@ -135,7 +139,6 @@ struct fsl_sai { bool is_slave_mode; bool is_lsb_first; bool is_dsp_mode; - bool sai_on_imx; bool synchronous[2]; unsigned int mclk_id[2]; @@ -143,6 +146,7 @@ struct fsl_sai { unsigned int slots; unsigned int slot_width; + const struct fsl_sai_soc_data *soc_data; struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; }; -- cgit v1.2.3 From bd517707d85f19a7339ea8b882fcbf0fd9976bd6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:56:34 +0200 Subject: ASoC: fsl_sai: derive TX FIFO watermark from FIFO depth The DMA request schould be triggered as soon as the FIFO has space for another burst. As different versions of the SAI block have different FIFO sizes, the watrmark level needs to be derived from version specific data. Signed-off-by: Lucas Stach Tested-by: Angus Ainslie Reviewed-by: Angus Ainslie Link: https://lore.kernel.org/r/20190717105635.18514-3-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 4 +++- sound/soc/fsl/fsl_sai.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index ed0432e7327a..1d1a447163e3 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -640,7 +640,7 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) regmap_write(sai->regmap, FSL_SAI_RCSR, 0); regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, - FSL_SAI_MAXBURST_TX * 2); + sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); @@ -913,10 +913,12 @@ static int fsl_sai_remove(struct platform_device *pdev) static const struct fsl_sai_soc_data fsl_sai_vf610_data = { .use_imx_pcm = false, + .fifo_depth = 32, }; static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { .use_imx_pcm = true, + .fifo_depth = 32, }; static const struct of_device_id fsl_sai_ids[] = { diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 83e2bfe05b1b..7c1ef671da28 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -128,6 +128,7 @@ struct fsl_sai_soc_data { bool use_imx_pcm; + unsigned int fifo_depth; }; struct fsl_sai { -- cgit v1.2.3 From 6d19d8a3cec74a9680947ecb6abdeda38583110e Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:51:56 +0200 Subject: ASoC: fsl_sai: mark regmap as fast_io The regmap is only ever used to access MMIO registers, so it's fair to say that register access is fast. Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20190717105156.15721-1-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 1d1a447163e3..6d3c6c8d50ce 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -763,6 +763,7 @@ static const struct regmap_config fsl_sai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .fast_io = true, .max_register = FSL_SAI_RMR, .reg_defaults = fsl_sai_reg_defaults, -- cgit v1.2.3 From 96cd3b97bf32557ba722c2e96095cb6361b5dc42 Mon Sep 17 00:00:00 2001 From: fengchunguo Date: Mon, 15 Jul 2019 17:55:56 +0800 Subject: ASoC: max98383: fix i2c probe failure Added reset_gpio configuration for i2c probe successfully. If not,i2c address can't be found rightly. Error information: max98373 3-0031: Failed to read: 0x21FF Fixed: [3.761299@3] max98373 3-0031: MAX98373 revisionID: 0x43 [3.828911@3] asoc-aml-card auge_sound: max98373-aif1 <-> TDM-B mapping ok Signed-off-by: fengchunguo Link: https://lore.kernel.org/r/20190715095556.1614-1-chunguo.feng@amlogic.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 34 ++++++++++++++++++++++++++++++---- sound/soc/codecs/max98373.h | 1 + 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 528695cd6a1c..9a1eb7222357 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "max98373.h" @@ -895,6 +896,17 @@ static void max98373_slot_config(struct i2c_client *i2c, else max98373->i_slot = 1; + max98373->reset_gpio = of_get_named_gpio(dev->of_node, + "maxim,reset-gpio", 0); + if (!gpio_is_valid(max98373->reset_gpio)) { + dev_err(dev, "Looking up %s property in node %s failed %d\n", + "maxim,reset-gpio", dev->of_node->full_name, + max98373->reset_gpio); + } else { + dev_dbg(dev, "maxim,reset-gpio=%d", + max98373->reset_gpio); + } + if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) max98373->spkfb_slot = value & 0xF; else @@ -923,7 +935,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, else max98373->interleave_mode = false; - /* regmap initialization */ max98373->regmap = devm_regmap_init_i2c(i2c, &max98373_regmap); @@ -934,6 +945,24 @@ static int max98373_i2c_probe(struct i2c_client *i2c, return ret; } + /* voltage/current slot & gpio configuration */ + max98373_slot_config(i2c, max98373); + + /* Power on device */ + if (gpio_is_valid(max98373->reset_gpio)) { + ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET"); + if (ret) { + dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", + __func__, max98373->reset_gpio); + gpio_free(max98373->reset_gpio); + return -EINVAL; + } + gpio_direction_output(max98373->reset_gpio, 0); + msleep(50); + gpio_direction_output(max98373->reset_gpio, 1); + msleep(20); + } + /* Check Revision ID */ ret = regmap_read(max98373->regmap, MAX98373_R21FF_REV_ID, ®); @@ -944,9 +973,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, } dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); - /* voltage/current slot configuration */ - max98373_slot_config(i2c, max98373); - /* codec registeration */ ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, max98373_dai, ARRAY_SIZE(max98373_dai)); diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index f6a37aa02f26..533d2053f608 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -203,6 +203,7 @@ struct max98373_priv { struct regmap *regmap; + int reset_gpio; unsigned int v_slot; unsigned int i_slot; unsigned int spkfb_slot; -- cgit v1.2.3 From b7e814deae33eb30f8f8c6528e8e69b107978d88 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 19 Jul 2019 16:36:37 +0200 Subject: ASoC: tlv320aic31xx: suppress error message for EPROBE_DEFER Both the supplies and reset GPIO might need a probe deferral for the resource to be available. Don't print a error message in that case, as it is a normal operating condition. Signed-off-by: Lucas Stach Acked-by: Andrew F. Davis Link: https://lore.kernel.org/r/20190719143637.2018-1-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 9b37e98da0db..26a4f6cd3288 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1553,7 +1553,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(aic31xx->gpio_reset)) { - dev_err(aic31xx->dev, "not able to acquire gpio\n"); + if (PTR_ERR(aic31xx->gpio_reset) != -EPROBE_DEFER) + dev_err(aic31xx->dev, "not able to acquire gpio\n"); return PTR_ERR(aic31xx->gpio_reset); } @@ -1564,7 +1565,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, ARRAY_SIZE(aic31xx->supplies), aic31xx->supplies); if (ret) { - dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(aic31xx->dev, + "Failed to request supplies: %d\n", ret); return ret; } -- cgit v1.2.3 From 980c10cda954770640d9d7cd7b793efa12cae0d9 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Fri, 19 Jul 2019 14:32:35 +0800 Subject: ASoC: rt1308: simplify the EFUSE read function The rt1308_efuse function contains many redundant settings. We remove the redundant settings and the function still works. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190719063235.18757-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index d673506c7c39..19d255e01827 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -808,33 +808,11 @@ static void rt1308_efuse(struct rt1308_priv *rt1308) { regmap_write(rt1308->regmap, RT1308_RESET, 0); - regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600); - regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000); - regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); - regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505); - regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000); - regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000); - regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200); - regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000); - regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000); - regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00); regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); - regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501); - - regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000); - regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00); msleep(100); regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); msleep(20); regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); - - regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000); - regmap_write(rt1308->regmap, RT1308_POWER, 0x0); - regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); - regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00); } static int rt1308_i2c_probe(struct i2c_client *i2c, -- cgit v1.2.3 From 730e051c78b05f0ce87df06e0fc1ea002d722fe8 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Fri, 19 Jul 2019 14:32:49 +0800 Subject: ASoC: rt1308: add silence detection and manual PDB control We enable the silence detection function in initial settings. PDB control changes to manual mode, hence the driver could fully control the AMP output on/off. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190719063249.18806-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index 19d255e01827..cf3d72f99705 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -40,10 +40,10 @@ static const struct reg_sequence init_list[] = { { RT1308_VREF, 0x18100000 }, { RT1308_IV_SENSE, 0x87010000 }, { RT1308_DUMMY_REG, 0x00000200 }, - { RT1308_SIL_DET, 0x61c30000 }, + { RT1308_SIL_DET, 0xe1c30000 }, { RT1308_DC_CAL_2, 0x00ffff00 }, { RT1308_CLK_DET, 0x01000000 }, - { RT1308_POWER_STATUS, 0x00800000 }, + { RT1308_POWER_STATUS, 0x08800000 }, { RT1308_DAC_SET, 0xafaf0700 }, }; @@ -308,12 +308,13 @@ static int rt1308_classd_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: msleep(30); snd_soc_component_update_bits(component, RT1308_POWER_STATUS, - RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT); + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT); msleep(40); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_component_update_bits(component, RT1308_POWER_STATUS, - RT1308_POW_PDB_REG_BIT, 0); + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0); usleep_range(150000, 200000); break; -- cgit v1.2.3 From 03b0deb6ba5f47d346fbb0783018c0d415203142 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:35:16 +0100 Subject: ASoC: cs47l35: Use define for DSPCLK enable bit Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722093516.12906-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index e3585c1dab3d..d396a8545d51 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6, +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), -- cgit v1.2.3 From 4aefb7387198740318c5e7bf7211701f4e0d849e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 19 Jul 2019 20:05:58 +0200 Subject: ASoC: rockchip-max98090: Remove MICBIAS as supply of input pin IN34 Commit ec0d23b295b9 ("ASoC: rockchip-max98090: Fix the Headset Mic route.") moved the MICBIAS widget to supply Headset Mic but forget to remove the MICBIAS widget to supply IN34 which is not really needed, so remove that path so we have: IN34 <==== Headset MIC <==== MICBIAS Signed-off-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20190719180558.11459-1-enric.balletbo@collabora.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index c5fc24675a33..d1c907631c2d 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -45,7 +45,6 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { static const struct snd_soc_dapm_route rk_audio_map[] = { {"IN34", NULL, "Headset Mic"}, - {"IN34", NULL, "MICBIAS"}, {"Headset Mic", NULL, "MICBIAS"}, {"DMICL", NULL, "Int Mic"}, {"Headphone", NULL, "HPL"}, -- cgit v1.2.3 From b1f373a11d25fc9a5f7679c9b85799fe09b0dc4a Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:31 +0000 Subject: ASoC: sgtl5000: Improve VAG power and mute control VAG power control is improved to fit the manual [1]. This patch fixes as minimum one bug: if customer muxes Headphone to Line-In right after boot, the VAG power remains off that leads to poor sound quality from line-in. I.e. after boot: - Connect sound source to Line-In jack; - Connect headphone to HP jack; - Run following commands: $ amixer set 'Headphone' 80% $ amixer set 'Headphone Mux' LINE_IN Change VAG power on/off control according to the following algorithm: - turn VAG power ON on the 1st incoming event. - keep it ON if there is any active VAG consumer (ADC/DAC/HP/Line-In). - turn VAG power OFF when there is the latest consumer's pre-down event come. - always delay after VAG power OFF to avoid pop. - delay after VAG power ON if the initiative consumer is Line-In, this prevents pop during line-in muxing. According to the data sheet [1], to avoid any pops/clicks, the outputs should be muted during input/output routing changes. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Cc: stable@vger.kernel.org Fixes: 9b34e6cc3bc2 ("ASoC: Add Freescale SGTL5000 codec support") Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Fabio Estevam Reviewed-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190719100524.23300-3-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 224 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 194 insertions(+), 30 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index a6a4748c97f9..34cc85e49003 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -31,6 +31,13 @@ #define SGTL5000_DAP_REG_OFFSET 0x0100 #define SGTL5000_MAX_REG_OFFSET 0x013A +/* Delay for the VAG ramp up */ +#define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */ +/* Delay for the VAG ramp down */ +#define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */ + +#define SGTL5000_OUTPUTS_MUTE (SGTL5000_HP_MUTE | SGTL5000_LINE_OUT_MUTE) + /* default value of sgtl5000 registers */ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_CHIP_DIG_POWER, 0x0000 }, @@ -123,6 +130,13 @@ enum { I2S_SCLK_STRENGTH_HIGH, }; +enum { + HP_POWER_EVENT, + DAC_POWER_EVENT, + ADC_POWER_EVENT, + LAST_POWER_EVENT = ADC_POWER_EVENT +}; + /* sgtl5000 private structure in codec */ struct sgtl5000_priv { int sysclk; /* sysclk rate */ @@ -137,8 +151,109 @@ struct sgtl5000_priv { u8 micbias_voltage; u8 lrclk_strength; u8 sclk_strength; + u16 mute_state[LAST_POWER_EVENT + 1]; }; +static inline int hp_sel_input(struct snd_soc_component *component) +{ + return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) & + SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT; +} + +static inline u16 mute_output(struct snd_soc_component *component, + u16 mute_mask) +{ + u16 mute_reg = snd_soc_component_read32(component, + SGTL5000_CHIP_ANA_CTRL); + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + mute_mask, mute_mask); + return mute_reg; +} + +static inline void restore_output(struct snd_soc_component *component, + u16 mute_mask, u16 mute_reg) +{ + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + mute_mask, mute_reg); +} + +static void vag_power_on(struct snd_soc_component *component, u32 source) +{ + if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & + SGTL5000_VAG_POWERUP) + return; + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, + SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); + + /* When VAG powering on to get local loop from Line-In, the sleep + * is required to avoid loud pop. + */ + if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN && + source == HP_POWER_EVENT) + msleep(SGTL5000_VAG_POWERUP_DELAY); +} + +static int vag_power_consumers(struct snd_soc_component *component, + u16 ana_pwr_reg, u32 source) +{ + int consumers = 0; + + /* count dac/adc consumers unconditional */ + if (ana_pwr_reg & SGTL5000_DAC_POWERUP) + consumers++; + if (ana_pwr_reg & SGTL5000_ADC_POWERUP) + consumers++; + + /* + * If the event comes from HP and Line-In is selected, + * current action is 'DAC to be powered down'. + * As HP_POWERUP is not set when HP muxed to line-in, + * we need to keep VAG power ON. + */ + if (source == HP_POWER_EVENT) { + if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN) + consumers++; + } else { + if (ana_pwr_reg & SGTL5000_HP_POWERUP) + consumers++; + } + + return consumers; +} + +static void vag_power_off(struct snd_soc_component *component, u32 source) +{ + u16 ana_pwr = snd_soc_component_read32(component, + SGTL5000_CHIP_ANA_POWER); + + if (!(ana_pwr & SGTL5000_VAG_POWERUP)) + return; + + /* + * This function calls when any of VAG power consumers is disappearing. + * Thus, if there is more than one consumer at the moment, as minimum + * one consumer will definitely stay after the end of the current + * event. + * Don't clear VAG_POWERUP if 2 or more consumers of VAG present: + * - LINE_IN (for HP events) / HP (for DAC/ADC events) + * - DAC + * - ADC + * (the current consumer is disappearing right now) + */ + if (vag_power_consumers(component, ana_pwr, source) >= 2) + return; + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, + SGTL5000_VAG_POWERUP, 0); + /* In power down case, we need wait 400-1000 ms + * when VAG fully ramped down. + * As longer we wait, as smaller pop we've got. + */ + msleep(SGTL5000_VAG_POWERDOWN_DELAY); +} + /* * mic_bias power on/off share the same register bits with * output impedance of mic bias, when power on mic bias, we @@ -170,36 +285,46 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, return 0; } -/* - * As manual described, ADC/DAC only works when VAG powerup, - * So enabled VAG before ADC/DAC up. - * In power down case, we need wait 400ms when vag fully ramped down. - */ -static int power_vag_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int vag_and_mute_control(struct snd_soc_component *component, + int event, int event_source) { - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; + static const u16 mute_mask[] = { + /* + * Mask for HP_POWER_EVENT. + * Muxing Headphones have to be wrapped with mute/unmute + * headphones only. + */ + SGTL5000_HP_MUTE, + /* + * Masks for DAC_POWER_EVENT/ADC_POWER_EVENT. + * Muxing DAC or ADC block have to wrapped with mute/unmute + * both headphones and line-out. + */ + SGTL5000_OUTPUTS_MUTE, + SGTL5000_OUTPUTS_MUTE + }; + + struct sgtl5000_priv *sgtl5000 = + snd_soc_component_get_drvdata(component); switch (event) { + case SND_SOC_DAPM_PRE_PMU: + sgtl5000->mute_state[event_source] = + mute_output(component, mute_mask[event_source]); + break; case SND_SOC_DAPM_POST_PMU: - snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); - msleep(400); + vag_power_on(component, event_source); + restore_output(component, mute_mask[event_source], + sgtl5000->mute_state[event_source]); break; - case SND_SOC_DAPM_PRE_PMD: - /* - * Don't clear VAG_POWERUP, when both DAC and ADC are - * operational to prevent inadvertently starving the - * other one of them. - */ - if ((snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & - mask) != mask) { - snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, 0); - msleep(400); - } + sgtl5000->mute_state[event_source] = + mute_output(component, mute_mask[event_source]); + vag_power_off(component, event_source); + break; + case SND_SOC_DAPM_POST_PMD: + restore_output(component, mute_mask[event_source], + sgtl5000->mute_state[event_source]); break; default: break; @@ -208,6 +333,41 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, return 0; } +/* + * Mute Headphone when power it up/down. + * Control VAG power on HP power path. + */ +static int headphone_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, HP_POWER_EVENT); +} + +/* As manual describes, ADC/DAC powering up/down requires + * to mute outputs to avoid pops. + * Control VAG power on ADC/DAC power path. + */ +static int adc_updown_depop(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, ADC_POWER_EVENT); +} + +static int dac_updown_depop(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, DAC_POWER_EVENT); +} + /* input sources for ADC */ static const char *adc_mux_text[] = { "MIC_IN", "LINE_IN" @@ -280,7 +440,10 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { mic_bias_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0, + headphone_pga_event, + SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), @@ -301,11 +464,12 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { 0, SGTL5000_CHIP_DIG_POWER, 1, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), - SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), - - SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), - SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), + SND_SOC_DAPM_ADC_E("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0, + adc_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), + SND_SOC_DAPM_DAC_E("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0, + dac_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), }; /* routes for sgtl5000 */ -- cgit v1.2.3 From cadee10c983145c16d6c75af88f6a943b22ebeb2 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:33 +0000 Subject: ASoC: sgtl5000: Fix definition of VAG Ramp Control SGTL5000_SMALL_POP is a bit mask, not a value. Usage of correct definition makes device probing code more clear. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-4-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 2 +- sound/soc/codecs/sgtl5000.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 34cc85e49003..3f28e7862b5b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1460,7 +1460,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) /* enable small pop, introduce 400ms delay in turning off */ snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL, - SGTL5000_SMALL_POP, 1); + SGTL5000_SMALL_POP, SGTL5000_SMALL_POP); /* disable short cut detector */ snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0); diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 18cae08bbd3a..a4bf4bca95bf 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -273,7 +273,7 @@ #define SGTL5000_BIAS_CTRL_MASK 0x000e #define SGTL5000_BIAS_CTRL_SHIFT 1 #define SGTL5000_BIAS_CTRL_WIDTH 3 -#define SGTL5000_SMALL_POP 1 +#define SGTL5000_SMALL_POP 0x0001 /* * SGTL5000_CHIP_MIC_CTRL -- cgit v1.2.3 From 694b14554d75f2a1ae111202e71860d58b434a21 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:34 +0000 Subject: ASoC: sgtl5000: add ADC mute control This control mute/unmute the ADC input of SGTL5000 using its CHIP_ANA_CTRL register. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-5-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3f28e7862b5b..b65232521ea8 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -720,6 +720,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { SGTL5000_CHIP_ANA_ADC_CTRL, 8, 1, 0, capture_6db_attenuate), SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), + SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, 0, 1, 1), SOC_DOUBLE_TLV("Headphone Playback Volume", SGTL5000_CHIP_ANA_HP_CTRL, -- cgit v1.2.3 From 631bc8f0134ae9620d86a96b8c5f9445d91a2dca Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:35 +0000 Subject: ASoC: sgtl5000: Fix of unmute outputs on probe To enable "zero cross detect" for ADC/HP, change HP_ZCD_EN/ADC_ZCD_EN bits only instead of writing the whole CHIP_ANA_CTRL register. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-6-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index b65232521ea8..23f4ae2f0723 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1453,6 +1453,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) int ret; u16 reg; struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component); + unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN; /* power up sgtl5000 */ ret = sgtl5000_set_power_regs(component); @@ -1480,9 +1481,8 @@ static int sgtl5000_probe(struct snd_soc_component *component) 0x1f); snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg); - snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL, - SGTL5000_HP_ZCD_EN | - SGTL5000_ADC_ZCD_EN); + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + zcd_mask, zcd_mask); snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL, SGTL5000_BIAS_R_MASK, -- cgit v1.2.3 From b6319b061ba279577fd7030a9848fbd6a17151e3 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:37 +0000 Subject: ASoC: sgtl5000: Fix charge pump source assignment If VDDA != VDDIO and any of them is greater than 3.1V, charge pump source can be assigned automatically [1]. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-7-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 23f4ae2f0723..aa1f9637d895 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1338,12 +1338,17 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) SGTL5000_INT_OSC_EN); /* Enable VDDC charge pump */ ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; - } else if (vddio >= 3100 && vdda >= 3100) { + } else { ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; - /* VDDC use VDDIO rail */ - lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; - lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << - SGTL5000_VDDC_MAN_ASSN_SHIFT; + /* + * if vddio == vdda the source of charge pump should be + * assigned manually to VDDIO + */ + if (vddio == vdda) { + lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; + lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << + SGTL5000_VDDC_MAN_ASSN_SHIFT; + } } snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); -- cgit v1.2.3 From 748fd07e2b9ca4132e3d2aae25395aedc4d1aee8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 14:52:09 +0100 Subject: ASoC: madera: Read device tree configuration Read the configuration of the Madera ASoC driver from device tree. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722135209.30302-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/madera.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 1b1be19a2f99..5f1e32a5a855 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -300,6 +300,100 @@ int madera_free_overheat(struct madera_priv *priv) } EXPORT_SYMBOL_GPL(madera_free_overheat); +static int madera_get_variable_u32_array(struct device *dev, + const char *propname, + u32 *dest, int n_max, + int multiple) +{ + int n, ret; + + n = device_property_count_u32(dev, propname); + if (n < 0) { + if (n == -EINVAL) + return 0; /* missing, ignore */ + + dev_warn(dev, "%s malformed (%d)\n", propname, n); + + return n; + } else if ((n % multiple) != 0) { + dev_warn(dev, "%s not a multiple of %d entries\n", + propname, multiple); + + return -EINVAL; + } + + if (n > n_max) + n = n_max; + + ret = device_property_read_u32_array(dev, propname, dest, n); + if (ret < 0) + return ret; + + return n; +} + +static void madera_prop_get_inmode(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + struct madera_codec_pdata *pdata = &madera->pdata.codec; + u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS]; + int n, i, in_idx, ch_idx; + + BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT); + BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS); + + n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode", + tmp, ARRAY_SIZE(tmp), + MADERA_MAX_MUXED_CHANNELS); + if (n < 0) + return; + + in_idx = 0; + ch_idx = 0; + for (i = 0; i < n; ++i) { + pdata->inmode[in_idx][ch_idx] = tmp[i]; + + if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) { + ch_idx = 0; + ++in_idx; + } + } +} + +static void madera_prop_get_pdata(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + struct madera_codec_pdata *pdata = &madera->pdata.codec; + u32 out_mono[ARRAY_SIZE(pdata->out_mono)]; + int i, n; + + madera_prop_get_inmode(priv); + + n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono", + out_mono, ARRAY_SIZE(out_mono), 1); + if (n > 0) + for (i = 0; i < n; ++i) + pdata->out_mono[i] = !!out_mono[i]; + + madera_get_variable_u32_array(madera->dev, + "cirrus,max-channels-clocked", + pdata->max_channels_clocked, + ARRAY_SIZE(pdata->max_channels_clocked), + 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt", + pdata->pdm_fmt, + ARRAY_SIZE(pdata->pdm_fmt), 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute", + pdata->pdm_mute, + ARRAY_SIZE(pdata->pdm_mute), 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref", + pdata->dmic_ref, + ARRAY_SIZE(pdata->dmic_ref), 1); +} + int madera_core_init(struct madera_priv *priv) { int i; @@ -308,6 +402,9 @@ int madera_core_init(struct madera_priv *priv) BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); + if (!dev_get_platdata(priv->madera->dev)) + madera_prop_get_pdata(priv); + mutex_init(&priv->rate_lock); for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) -- cgit v1.2.3 From f8f85216f8d309daadb37aba8a4b0826783d8747 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 22 Jul 2019 23:15:28 +0200 Subject: ASoC: pcm3168a: Fix a typo in the name of a constant There is a typo in PCM1368A_MAX_SYSCLK, it should be PCM3168A_MAX_SYSCLK (1 and 3 switched in 3168) Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190722211528.26600-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index f1104d7d6426..5d59ce254821 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -263,7 +263,7 @@ static unsigned int pcm3168a_scki_ratios[] = { #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) -#define PCM1368A_MAX_SYSCLK 36864000 +#define PCM3168A_MAX_SYSCLK 36864000 static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) { @@ -296,7 +296,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, struct pcm3168a_priv *pcm3168a = sn