From 06e8f5c842f2dbb232897ba967ea7b422745c271 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 6 Aug 2019 12:45:38 +0900 Subject: ASoC: rsnd: don't call clk_get_rate() under atomic context ADG is using clk_get_rate() under atomic context, thus, we might have scheduling issue. To avoid this issue, we need to get/keep clk rate under non atomic context. We need to handle ADG as special device at Renesas Sound driver. From SW point of view, we want to impletent it as rsnd_mod_ops :: prepare, but it makes code just complicate. To avoid complicated code/patch, this patch adds new clk_rate[] array, and keep clk IN rate when rsnd_adg_clk_enable() was called. Reported-by: Leon Kong Signed-off-by: Kuninori Morimoto Tested-by: Leon Kong Link: https://lore.kernel.org/r/87v9vb0xkp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index fce4e050a9b7..b9aacf3d3b29 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,7 @@ struct rsnd_adg { struct clk *clkout[CLKOUTMAX]; struct clk_onecell_data onecell; struct rsnd_mod mod; + int clk_rate[CLKMAX]; u32 flags; u32 ckr; u32 rbga; @@ -114,9 +115,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, unsigned int val, en; unsigned int min, diff; unsigned int sel_rate[] = { - clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ - clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ - clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->clk_rate[CLKA], /* 0000: CLKA */ + adg->clk_rate[CLKB], /* 0001: CLKB */ + adg->clk_rate[CLKC], /* 0010: CLKC */ adg->rbga_rate_for_441khz, /* 0011: RBGA */ adg->rbgb_rate_for_48khz, /* 0100: RBGB */ }; @@ -302,7 +303,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. */ for_each_rsnd_clk(clk, adg, i) { - if (rate == clk_get_rate(clk)) + if (rate == adg->clk_rate[i]) return sel_table[i]; } @@ -369,10 +370,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) for_each_rsnd_clk(clk, adg, i) { ret = 0; - if (enable) + if (enable) { ret = clk_prepare_enable(clk); - else + + /* + * We shouldn't use clk_get_rate() under + * atomic context. Let's keep it when + * rsnd_adg_clk_enable() was called + */ + adg->clk_rate[i] = clk_get_rate(adg->clk[i]); + } else { clk_disable_unprepare(clk); + } if (ret < 0) dev_warn(dev, "can't use clk %d\n", i); -- cgit v1.2.3 From cc352735d49c9c25fd711795bee35d3d001ddffa Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 6 Aug 2019 15:19:58 -0700 Subject: ASoC: SOF: Intel: hda: Initialize HDA controller after i915 init On some platforms, sound card registration fails when a HDMI monitor is not connected. This is caused by a recent commit that switched the order in which the HDA controller and the i915 are initialized. Initializing the i915 before initializing the HDA controller fixes the problem. Fixes: be1b577d01787c ("ASoC: SOF: Intel: hda: fix the hda init chip" Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190806221958.19180-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 136f98bf5d7e..82f61c4e74bd 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -321,10 +321,23 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->ppcap) dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* init i915 and HDMI codecs */ + ret = hda_codec_i915_init(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n"); + return ret; + } +#endif + + /* Init HDA controller after i915 init */ ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + hda_codec_i915_exit(sdev); +#endif return ret; } @@ -332,13 +345,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - /* init i915 and HDMI codecs */ - ret = hda_codec_i915_init(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: no HDMI audio devices found\n"); - return ret; - } - /* codec detection */ if (!bus->codec_mask) { dev_info(bus->dev, "no hda codecs found!\n"); -- cgit v1.2.3 From 804cbf4bb063204ca6c2471baa694548aab02ce3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 7 Aug 2019 09:50:30 -0500 Subject: ASoC: hdac_hda: fix page fault issue by removing race There is a race between hda codec device removing and the jack-detecting work, which will lead to a page fault issue as the latter work is accessing codec device which could be already removed. Here add the cancellation of jack-detecting work before codecs are actually removed to avoid the race and fix the issue. Bug: https://github.com/thesofproject/linux/issues/1067 Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807145030.26117-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hda.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 7d4940256914..91242b6f8ea7 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -495,6 +495,10 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) static int hdac_hda_dev_remove(struct hdac_device *hdev) { + struct hdac_hda_priv *hda_pvt; + + hda_pvt = dev_get_drvdata(&hdev->dev); + cancel_delayed_work_sync(&hda_pvt->codec.jackpoll_work); return 0; } -- cgit v1.2.3 From 332ccf00bf85adbf48015084be0e60f5cc57a055 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Aug 2019 17:15:31 +0200 Subject: ASoC: hdac_hdmi: Offload dapm update at jack detection hdac_hdmi_present_sense() calls the audio component to get ELD update, then it reports the jack status change and updates DAPM graph accordingly. This works when it's called from the normal code paths. However, it may lead to a dead lock when it's called from the audio component notifier. Namely, the DAPM update involves with the runtime PM, and it eventually calls again the audio component get_power() ops. Since i915 driver already takes a mutex around the audio component ops calls, we'll eventually get the mutex doubly. As a workaround, in this patch, only the jack state is updated in the code path from hdac_hdmi_eld_notify_cb(), and the DAPM update is deferred to a work so that it's processed in another context. Reported-by: Imre Deak Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20190809151531.24359-1-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 57 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 47eee18b66a3..11ec031ad749 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -88,8 +88,10 @@ struct hdac_hdmi_port { hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; struct hdac_hdmi_eld eld; const char *jack_pin; + bool is_connect; struct snd_soc_dapm_context *dapm; const char *output_pin; + struct work_struct dapm_work; }; struct hdac_hdmi_pcm { @@ -163,11 +165,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, { struct hdac_device *hdev = port->pin->hdev; - if (is_connect) - snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); - else - snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); - + port->is_connect = is_connect; if (is_connect) { /* * Report Jack connect event when a device is connected @@ -193,10 +191,32 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, if (pcm->jack_event > 0) pcm->jack_event--; } +} +static void hdac_hdmi_port_dapm_update(struct hdac_hdmi_port *port) +{ + if (port->is_connect) + snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); + else + snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); snd_soc_dapm_sync(port->dapm); } +static void hdac_hdmi_jack_dapm_work(struct work_struct *work) +{ + struct hdac_hdmi_port *port; + + port = container_of(work, struct hdac_hdmi_port, dapm_work); + hdac_hdmi_port_dapm_update(port); +} + +static void hdac_hdmi_jack_report_sync(struct hdac_hdmi_pcm *pcm, + struct hdac_hdmi_port *port, bool is_connect) +{ + hdac_hdmi_jack_report(pcm, port, is_connect); + hdac_hdmi_port_dapm_update(port); +} + /* MST supported verbs */ /* * Get the no devices that can be connected to a port on the Pin widget. @@ -873,7 +893,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, list_for_each_entry_safe(p, p_next, &pcm->port_list, head) { if (p == port && p->id == port->id && p->pin == port->pin) { - hdac_hdmi_jack_report(pcm, port, false); + hdac_hdmi_jack_report_sync(pcm, port, false); list_del(&p->head); } } @@ -887,7 +907,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, if (!strcmp(cvt_name, pcm->cvt->name)) { list_add_tail(&port->head, &pcm->port_list); if (port->eld.monitor_present && port->eld.eld_valid) { - hdac_hdmi_jack_report(pcm, port, true); + hdac_hdmi_jack_report_sync(pcm, port, true); mutex_unlock(&hdmi->pin_mutex); return ret; } @@ -1250,16 +1270,20 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, * report jack here. It will be done in usermode mux * control select. */ - if (pcm) + if (pcm) { hdac_hdmi_jack_report(pcm, port, false); + schedule_work(&port->dapm_work); + } mutex_unlock(&hdmi->pin_mutex); return; } if (port->eld.monitor_present && port->eld.eld_valid) { - if (pcm) + if (pcm) { hdac_hdmi_jack_report(pcm, port, true); + schedule_work(&port->dapm_work); + } print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, port->eld.eld_buffer, port->eld.eld_size, false); @@ -1288,6 +1312,7 @@ static int hdac_hdmi_add_ports(struct hdac_device *hdev, for (i = 0; i < max_ports; i++) { ports[i].id = i; ports[i].pin = pin; + INIT_WORK(&ports[i].dapm_work, hdac_hdmi_jack_dapm_work); } pin->ports = ports; pin->num_ports = max_ports; @@ -2052,8 +2077,20 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) return ret; } +static void clear_dapm_works(struct hdac_device *hdev) +{ + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); + struct hdac_hdmi_pin *pin; + int i; + + list_for_each_entry(pin, &hdmi->pin_list, head) + for (i = 0; i < pin->num_ports; i++) + cancel_work_sync(&pin->ports[i].dapm_work); +} + static int hdac_hdmi_dev_remove(struct hdac_device *hdev) { + clear_dapm_works(hdev); snd_hdac_display_power(hdev->bus, hdev->addr, false); return 0; @@ -2072,6 +2109,8 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) if (!bus) return 0; + clear_dapm_works(hdev); + /* * Power down afg. * codec_read is preferred over codec_write to set the power state. -- cgit v1.2.3 From 8afd1a99d713ccc7cf1bd509b205c3bb60cf0b90 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 9 Aug 2019 18:22:34 -0500 Subject: ASoC: Intel: sof-rt5682: add dmic dapm widget to support dmic PCM We need add DAPM MIC endpoint widget "SoC DMIC" and route, to enable DMIC PCM DAPM support. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809232236.21182-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 64db00353e18..7285474f7d65 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -309,6 +309,7 @@ static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SPK("Spk", NULL), + SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route sof_map[] = { @@ -319,6 +320,9 @@ static const struct snd_soc_dapm_route sof_map[] = { /* other jacks */ { "IN1P", NULL, "Headset Mic" }, + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, + }; static const struct snd_soc_dapm_route speaker_map[] = { -- cgit v1.2.3 From 7188f656cdf762d4ea8ce16b6aaf4c6b06e119ec Mon Sep 17 00:00:00 2001 From: Cheng-Yi Chiang Date: Tue, 13 Aug 2019 15:44:30 +0800 Subject: ASoC: rockchip: rockchip_max98090: Set period size to 240 From stress testing of arecord, we found that period size greater than ~900 will bring pl330 to DYING state and can not recover within 100 iterations. The result is that arecord will stuck and get I/O error, and issue can not be recovered until reboot. This issue does not happen when period size is small. Set constraint of period size to 240 to prevent such issue. With the constraint, there will be no issue after 2000 iterations. We can revert this patch once the root cause is found in rockchip's pl330 implementation. Signed-off-by: Cheng-Yi Chiang Link: https://lore.kernel.org/r/20190813074430.191791-1-cychiang@chromium.org Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 782e534d4c0d..d54f672d38d8 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -138,8 +138,19 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, return ret; } +static int rk_aif1_startup(struct snd_pcm_substream *substream) +{ + /* + * Set period size to 240 because pl330 has issue + * dealing with larger period in stress testing. + */ + return snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 240, 240); +} + static const struct snd_soc_ops rk_aif1_ops = { .hw_params = rk_aif1_hw_params, + .startup = rk_aif1_startup, }; SND_SOC_DAILINK_DEFS(hifi, -- cgit v1.2.3 From 630742c296341a8cfe00dfd941392025ba8dd4e8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 15 Aug 2019 17:23:00 +0800 Subject: ASoC: es8328: Fix copy-paste error in es8328_right_line_controls It seems 'es8328_rline_enum' should be used in es8328_right_line_controls Fixes: 567e4f98922c ("ASoC: add es8328 codec driver") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190815092300.68712-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8328.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 822a25a8f53c..69b81e704127 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -228,7 +228,7 @@ static const struct soc_enum es8328_rline_enum = ARRAY_SIZE(es8328_line_texts), es8328_line_texts); static const struct snd_kcontrol_new es8328_right_line_controls = - SOC_DAPM_ENUM("Route", es8328_lline_enum); + SOC_DAPM_ENUM("Route", es8328_rline_enum); /* Left Mixer */ static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { -- cgit v1.2.3 From 9b4275c415acca6264a3d7f1182589959c93d530 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 15 Aug 2019 17:01:57 +0800 Subject: ASoC: cs4349: Use PM ops 'cs4349_runtime_pm' sound/soc/codecs/cs4349.c:358:32: warning: cs4349_runtime_pm defined but not used [-Wunused-const-variable=] cs4349_runtime_pm ops already defined, it seems we should enable it. Reported-by: Hulk Robot Fixes: e40da86 ("ASoC: cs4349: Add support for Cirrus Logic CS4349") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190815090157.70036-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4349.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 09716fab1e26..3381209a882d 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -378,6 +378,7 @@ static struct i2c_driver cs4349_i2c_driver = { .driver = { .name = "cs4349", .of_match_table = cs4349_of_match, + .pm = &cs4349_runtime_pm, }, .id_table = cs4349_i2c_id, .probe = cs4349_i2c_probe, -- cgit v1.2.3 From 554b75bde64bcad9662530726d1483f7ef012069 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 15 Aug 2019 17:19:20 +0800 Subject: ASoC: wm8737: Fix copy-paste error in wm8737_snd_controls sound/soc/codecs/wm8737.c:112:29: warning: high_3d defined but not used [-Wunused-const-variable=] 'high_3d' should be used for 3D High Cut-off. Reported-by: Hulk Robot Fixes: 2a9ae13a2641 ("ASoC: Add initial WM8737 driver") Signed-off-by: YueHaibing Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20190815091920.64480-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 0c246fb5e5ac..7a3f9fbe8d53 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -167,7 +167,7 @@ SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0), SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0), SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0), SOC_ENUM("3D Low Cut-off", low_3d), -SOC_ENUM("3D High Cut-off", low_3d), +SOC_ENUM("3D High Cut-off", high_3d), SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv), SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0), -- cgit v1.2.3 From 8661ab5b23d6d30d8687fc05bc1dba8f9a64b444 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 16 Aug 2019 01:03:14 -0400 Subject: ASoC: imx-audmux: Add driver suspend and resume to support MEGA Fast For i.MX6 SoloX, there is a mode of the SoC to shutdown all power source of modules during system suspend and resume procedure. Thus, AUDMUX needs to save all the values of registers before the system suspend and restore them after the system resume. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1565931794-7218-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index b2351cd33b0f..16ede3b5cb32 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -23,6 +23,8 @@ static struct clk *audmux_clk; static void __iomem *audmux_base; +static u32 *regcache; +static u32 reg_max; #define IMX_AUDMUX_V2_PTCR(x) ((x) * 8) #define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) @@ -317,8 +319,23 @@ static int imx_audmux_probe(struct platform_device *pdev) if (of_id) pdev->id_entry = of_id->data; audmux_type = pdev->id_entry->driver_data; - if (audmux_type == IMX31_AUDMUX) + + switch (audmux_type) { + case IMX31_AUDMUX: audmux_debugfs_init(); + reg_max = 14; + break; + case IMX21_AUDMUX: + reg_max = 6; + break; + default: + dev_err(&pdev->dev, "unsupported version!\n"); + return -EINVAL; + } + + regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL); + if (!regcache) + return -ENOMEM; if (of_id) imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node); @@ -334,12 +351,47 @@ static int imx_audmux_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int imx_audmux_suspend(struct device *dev) +{ + int i; + + clk_prepare_enable(audmux_clk); + + for (i = 0; i < reg_max; i++) + regcache[i] = readl(audmux_base + i * 4); + + clk_disable_unprepare(audmux_clk); + + return 0; +} + +static int imx_audmux_resume(struct device *dev) +{ + int i; + + clk_prepare_enable(audmux_clk); + + for (i = 0; i < reg_max; i++) + writel(regcache[i], audmux_base + i * 4); + + clk_disable_unprepare(audmux_clk); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops imx_audmux_pm = { + SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume) +}; + static struct platform_driver imx_audmux_driver = { .probe = imx_audmux_probe, .remove = imx_audmux_remove, .id_table = imx_audmux_ids, .driver = { .name = DRIVER_NAME, + .pm = &imx_audmux_pm, .of_match_table = imx_audmux_dt_ids, } }; -- cgit v1.2.3 From c372a35550c8d60f673b20210eea58a06d6d38cb Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 20 Aug 2019 15:16:04 +0900 Subject: ASoC: uniphier: Fix double reset assersion when transitioning to suspend state When transitioning to supend state, uniphier_aio_dai_suspend() is called and asserts reset lines and disables clocks. However, if there are two or more DAIs, uniphier_aio_dai_suspend() are called multiple times, and double reset assersion will cause. This patch defines the counter that has the number of DAIs at first, and whenever uniphier_aio_dai_suspend() are called, it decrements the counter. And only if the counter is zero, it asserts reset lines and disables clocks. In the same way, uniphier_aio_dai_resume() are called, it increments the counter after deasserting reset lines and enabling clocks. Fixes: 139a34200233 ("ASoC: uniphier: add support for UniPhier AIO CPU DAI driver") Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1566281764-14059-1-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-cpu.c | 31 +++++++++++++++++++++---------- sound/soc/uniphier/aio.h | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c index ee90e6c3937c..2ae582a99b63 100644 --- a/sound/soc/uniphier/aio-cpu.c +++ b/sound/soc/uniphier/aio-cpu.c @@ -424,8 +424,11 @@ int uniphier_aio_dai_suspend(struct snd_soc_dai *dai) { struct uniphier_aio *aio = uniphier_priv(dai); - reset_control_assert(aio->chip->rst); - clk_disable_unprepare(aio->chip->clk); + aio->chip->num_wup_aios--; + if (!aio->chip->num_wup_aios) { + reset_control_assert(aio->chip->rst); + clk_disable_unprepare(aio->chip->clk); + } return 0; } @@ -439,13 +442,15 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai) if (!aio->chip->active) return 0; - ret = clk_prepare_enable(aio->chip->clk); - if (ret) - return ret; + if (!aio->chip->num_wup_aios) { + ret = clk_prepare_enable(aio->chip->clk); + if (ret) + return ret; - ret = reset_control_deassert(aio->chip->rst); - if (ret) - goto err_out_clock; + ret = reset_control_deassert(aio->chip->rst); + if (ret) + goto err_out_clock; + } aio_iecout_set_enable(aio->chip, true); aio_chip_init(aio->chip); @@ -458,7 +463,7 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai) ret = aio_init(sub); if (ret) - goto err_out_clock; + goto err_out_reset; if (!sub->setting) continue; @@ -466,11 +471,16 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai) aio_port_reset(sub); aio_src_reset(sub); } + aio->chip->num_wup_aios++; return 0; +err_out_reset: + if (!aio->chip->num_wup_aios) + reset_control_assert(aio->chip->rst); err_out_clock: - clk_disable_unprepare(aio->chip->clk); + if (!aio->chip->num_wup_aios) + clk_disable_unprepare(aio->chip->clk); return ret; } @@ -619,6 +629,7 @@ int uniphier_aio_probe(struct platform_device *pdev) return PTR_ERR(chip->rst); chip->num_aios = chip->chip_spec->num_dais; + chip->num_wup_aios = chip->num_aios; chip->aios = devm_kcalloc(dev, chip->num_aios, sizeof(struct uniphier_aio), GFP_KERNEL); diff --git a/sound/soc/uniphier/aio.h b/sound/soc/uniphier/aio.h index ca6ccbae0ee8..a7ff7e556429 100644 --- a/sound/soc/uniphier/aio.h +++ b/sound/soc/uniphier/aio.h @@ -285,6 +285,7 @@ struct uniphier_aio_chip { struct uniphier_aio *aios; int num_aios; + int num_wup_aios; struct uniphier_aio_pll *plls; int num_plls; -- cgit v1.2.3 From 18dd62ae3bc31baa0473e4a09e46c02e0bdc57a0 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 20 Aug 2019 14:34:13 +0200 Subject: ASoC: meson: axg-tdm-formatter: free reset on device removal Use the devm variant to get the formatter reset so it is properly freed on device removal Fixes: 751bd5db5260 ("ASoC: meson: axg-tdm-formatter: add reset") Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190820123413.22249-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-formatter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 2e498201139f..1a0bf9d3836d 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -327,7 +327,7 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) } /* Formatter dedicated reset line */ - formatter->reset = reset_control_get_optional_exclusive(dev, NULL); + formatter->reset = devm_reset_control_get_optional_exclusive(dev, NULL); if (IS_ERR(formatter->reset)) { ret = PTR_ERR(formatter->reset); if (ret != -EPROBE_DEFER) -- cgit v1.2.3 From 351b31002c1853af078ebfffd4b67bfc3d19e3dd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 20 Aug 2019 14:35:10 +0200 Subject: ASoC: meson: g12a-tohdmitx: require regmap mmio The tohdmitx glue uses regmap MMIO so it should require it. Fixes: c8609f3870f7 ("ASoC: meson: add g12a tohdmitx control") Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190820123510.22491-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 63b38c123103..2e3676147cea 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -87,6 +87,7 @@ config SND_MESON_AXG_PDM config SND_MESON_G12A_TOHDMITX tristate "Amlogic G12A To HDMI TX Control Support" + select REGMAP_MMIO imply SND_SOC_HDMI_CODEC help Select Y or M to add support for HDMI audio on the g12a SoC -- cgit v1.2.3 From 404be07f4ed27697f5fa69162f67a94555738595 Mon Sep 17 00:00:00 2001 From: Daniel Stuart Date: Thu, 15 Aug 2019 14:12:55 -0300 Subject: ASoC: intel: cht_bsw_max98090_ti: Add all Chromebooks that need pmc_plt_clk_0 quirk Every single baytrail chromebook sets PMC to 0, as can be seeing below by searching through coreboot source code: $ grep -rl "PMC_PLT_CLK\[0\]" . ./rambi/variants/glimmer/devicetree.cb ./rambi/variants/clapper/devicetree.cb ./rambi/variants/swanky/devicetree.cb ./rambi/variants/enguarde/devicetree.cb ./rambi/variants/winky/devicetree.cb ./rambi/variants/kip/devicetree.cb ./rambi/variants/squawks/devicetree.cb ./rambi/variants/orco/devicetree.cb ./rambi/variants/ninja/devicetree.cb ./rambi/variants/heli/devicetree.cb ./rambi/variants/sumo/devicetree.cb ./rambi/variants/banjo/devicetree.cb ./rambi/variants/candy/devicetree.cb ./rambi/variants/gnawty/devicetree.cb ./rambi/variants/rambi/devicetree.cb ./rambi/variants/quawks/devicetree.cb Plus, Cyan (only non-baytrail chromebook with max98090) also needs this patch for audio to work. Thus, this commit adds all the missing devices to bsw_max98090 quirk table, implemented by commit a182ecd3809c ("ASoC: intel: cht_bsw_max98090_ti: Add quirk for boards using pmc_plt_clk_0"). Signed-off-by: Daniel Stuart Link: https://lore.kernel.org/r/20190815171300.30126-1-daniel.stuart14@gmail.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 98 ++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 33eb72545be6..83b978e7b4c4 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -399,6 +399,20 @@ static struct snd_soc_card snd_soc_card_cht = { }; static const struct dmi_system_id cht_max98090_quirk_table[] = { + { + /* Banjo model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Banjo"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Candy model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Candy"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, { /* Clapper model Chromebook */ .matches = { @@ -406,6 +420,27 @@ static const struct dmi_system_id cht_max98090_quirk_table[] = { }, .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, }, + { + /* Cyan model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Enguarde model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Enguarde"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Glimmer model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, { /* Gnawty model Chromebook (Acer Chromebook CB3-111) */ .matches = { @@ -413,6 +448,62 @@ static const struct dmi_system_id cht_max98090_quirk_table[] = { }, .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, }, + { + /* Heli model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Heli"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Kip model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Kip"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Ninja model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Ninja"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Orco model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Orco"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Quawks model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Quawks"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Rambi model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Rambi"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Squawks model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Squawks"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, + { + /* Sumo model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Sumo"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, { /* Swanky model Chromebook (Toshiba Chromebook 2) */ .matches = { @@ -420,6 +511,13 @@ static const struct dmi_system_id cht_max98090_quirk_table[] = { }, .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, }, + { + /* Winky model Chromebook */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Winky"), + }, + .driver_data = (void *)QUIRK_PMC_PLT_CLK_0, + }, {} }; -- cgit v1.2.3 From 22afe6242387eca1ac3905fbde7bef38deb0357d Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 20 Aug 2019 13:02:35 +0200 Subject: ASoC: wm8904: fix typo in DAPM kcontrol name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trivial fix for typo in "Capture Inverting Mux"es' name. Signed-off-by: Michał Mirosław Acked-by: Charles Keepax Link: https://lore.kernel.org/r/f95ae1085f9f3c137a122c4d95728711613c15f7.1566298834.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 5ebdd1d9afde..525e4ef654a1 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -866,7 +866,7 @@ static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, lin_text); static const struct snd_kcontrol_new lin_inv_mux = - SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); + SOC_DAPM_ENUM("Left Capture Inverting Mux", lin_inv_enum); static const char *rin_text[] = { "IN1R", "IN2R", "IN3R" @@ -882,7 +882,7 @@ static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, rin_text); static const struct snd_kcontrol_new rin_inv_mux = - SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); + SOC_DAPM_ENUM("Right Capture Inverting Mux", rin_inv_enum); static const char *aif_text[] = { "Left", "Right" -- cgit v1.2.3 From 0a05f2e865ad6e461cada8f931b34551287dbba2 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 20 Aug 2019 13:02:37 +0200 Subject: ASoC: wm8904: implement input mode select as a mux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make '* Capture Mode' a mux. This makes DAPM know that in single-ended mode only inverting mux paths need to be enabled. Signed-off-by: Michał Mirosław Acked-by: Charles Keepax Link: https://lore.kernel.org/r/125cd3c9f298da9b08a4d6002d4c00d70a898950.1566298834.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 52 ++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 525e4ef654a1..bcb3c9d5abf0 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -545,18 +545,6 @@ static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const char *input_mode_text[] = { - "Single-Ended", "Differential Line", "Differential Mic" -}; - -static SOC_ENUM_SINGLE_DECL(lin_mode, - WM8904_ANALOGUE_LEFT_INPUT_1, 0, - input_mode_text); - -static SOC_ENUM_SINGLE_DECL(rin_mode, - WM8904_ANALOGUE_RIGHT_INPUT_1, 0, - input_mode_text); - static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; @@ -591,9 +579,6 @@ static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT, WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv), -SOC_ENUM("Left Capture Mode", lin_mode), -SOC_ENUM("Right Capture Mode", rin_mode), - /* No TLV since it depends on mode */ SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0, WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0), @@ -852,6 +837,10 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, return 0; } +static const char *input_mode_text[] = { + "Single-Ended", "Differential Line", "Differential Mic" +}; + static const char *lin_text[] = { "IN1L", "IN2L", "IN3L" }; @@ -868,6 +857,13 @@ static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, static const struct snd_kcontrol_new lin_inv_mux = SOC_DAPM_ENUM("Left Capture Inverting Mux", lin_inv_enum); +static SOC_ENUM_SINGLE_DECL(lin_mode_enum, + WM8904_ANALOGUE_LEFT_INPUT_1, 0, + input_mode_text); + +static const struct snd_kcontrol_new lin_mode = + SOC_DAPM_ENUM("Left Capture Mode", lin_mode_enum); + static const char *rin_text[] = { "IN1R", "IN2R", "IN3R" }; @@ -884,6 +880,13 @@ static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, static const struct snd_kcontrol_new rin_inv_mux = SOC_DAPM_ENUM("Right Capture Inverting Mux", rin_inv_enum); +static SOC_ENUM_SINGLE_DECL(rin_mode_enum, + WM8904_ANALOGUE_RIGHT_INPUT_1, 0, + input_mode_text); + +static const struct snd_kcontrol_new rin_mode = + SOC_DAPM_ENUM("Right Capture Mode", rin_mode_enum); + static const char *aif_text[] = { "Left", "Right" }; @@ -932,9 +935,11 @@ SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux), SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0, &lin_inv_mux), +SND_SOC_DAPM_MUX("Left Capture Mode", SND_SOC_NOPM, 0, 0, &lin_mode), SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rin_mux), SND_SOC_DAPM_MUX("Right Capture Inverting Mux", SND_SOC_NOPM, 0, 0, &rin_inv_mux), +SND_SOC_DAPM_MUX("Right Capture Mode", SND_SOC_NOPM, 0, 0, &rin_mode), SND_SOC_DAPM_PGA("Left Capture PGA", WM8904_POWER_MANAGEMENT_0, 1, 0, NULL, 0), @@ -1057,6 +1062,12 @@ static const struct snd_soc_dapm_route adc_intercon[] = { { "Left Capture Inverting Mux", "IN2L", "IN2L" }, { "Left Capture Inverting Mux", "IN3L", "IN3L" }, + { "Left Capture Mode", "Single-Ended", "Left Capture Inverting Mux" }, + { "Left Capture Mode", "Differential Line", "Left Capture Mux" }, + { "Left Capture Mode", "Differential Line", "Left Capture Inverting Mux" }, + { "Left Capture Mode", "Differential Mic", "Left Capture Mux" }, + { "Left Capture Mode", "Differential Mic", "Left Capture Inverting Mux" }, + { "Right Capture Mux", "IN1R", "IN1R" }, { "Right Capture Mux", "IN2R", "IN2R" }, { "Right Capture Mux", "IN3R", "IN3R" }, @@ -1065,11 +1076,14 @@ static const struct snd_soc_dapm_route adc_intercon[] = { { "Right Capture Inverting Mux", "IN2R", "IN2R" }, { "Right Capture Inverting Mux", "IN3R", "IN3R" }, - { "Left Capture PGA", NULL, "Left Capture Mux" }, - { "Left Capture PGA", NULL, "Left Capture Inverting Mux" }, + { "Right Capture Mode", "Single-Ended", "Right Capture Inverting Mux" }, + { "Right Capture Mode", "Differential Line", "Right Capture Mux" }, + { "Right Capture Mode", "Differential Line", "Right Capture Inverting Mux" }, + { "Right Capture Mode", "Differential Mic", "Right Capture Mux" }, + { "Right Capture Mode", "Differential Mic", "Right Capture Inverting Mux" }, - { "Right Capture PGA", NULL, "Right Capture Mux" }, - { "Right Capture PGA", NULL, "Right Capture Inverting Mux" }, + { "Left Capture PGA", NULL, "Left Capture Mode" }, + { "Right Capture PGA", NULL, "Right Capture Mode" }, { "AIFOUTL Mux", "Left", "ADCL" }, { "AIFOUTL Mux", "Right", "ADCR" }, -- cgit v1.2.3 From bf283a05c09b58db83afbb1a8a3c6a684c56c1bb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 19 Aug 2019 21:25:08 +0200 Subject: ASoC: sun4i-i2s: Register regmap and PCM before our component So far the regmap and the dmaengine PCM are registered after our component has been, which means that our driver isn't properly initialised by then. Let's fix that. Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/67e303f37f141ef73ce9ed47d7f831b63c694424.1566242458.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 7fa5c61169db..85c3b2c8cd77 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1148,11 +1148,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev) goto err_pm_disable; } - ret = devm_snd_soc_register_component(&pdev->dev, - &sun4i_i2s_component, - &sun4i_i2s_dai, 1); + ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s); if (ret) { - dev_err(&pdev->dev, "Could not register DAI\n"); + dev_err(&pdev->dev, "Could not initialise regmap fields\n"); goto err_suspend; } @@ -1162,9 +1160,11 @@ static int sun4i_i2s_probe(struct platform_device *pdev) goto err_suspend; } - ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s); + ret = devm_snd_soc_register_component(&pdev->dev, + &sun4i_i2s_component, + &sun4i_i2s_dai, 1); if (ret) { - dev_err(&pdev->dev, "Could not initialise regmap fields\n"); + dev_err(&pdev->dev, "Could not register DAI\n"); goto err_suspend; } -- cgit v1.2.3 From 988b59467b2b14523a266957affbe9eca3e99fc9 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Tue, 20 Aug 2019 19:24:09 +0300 Subject: ASoC: mchp-i2s-mcc: Fix unprepare of GCLK If hw_free() gets called after hw_params(), GCLK remains prepared, preventing further use of it. This patch fixes this by unpreparing the clock in hw_free() or if hw_params() gets an error. Fixes: 7e0cdf545a55 ("ASoC: mchp-i2s-mcc: add driver for I2SC Multi-Channel Controller") Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20190820162411.24836-2-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 86495883ca3f..319f975586f1 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -670,8 +670,13 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra); - if (ret < 0) + if (ret < 0) { + if (dev->gclk_use) { + clk_unprepare(dev->gclk); + dev->gclk_use = 0; + } return ret; + } return regmap_write(dev->regmap, MCHP_I2SMCC_MRB, mrb); } @@ -708,9 +713,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream, regmap_write(dev->regmap, MCHP_I2SMCC_CR, MCHP_I2SMCC_CR_CKDIS); if (dev->gclk_running) { - clk_disable_unprepare(dev->gclk); + clk_disable(dev->gclk); dev->gclk_running = 0; } + if (dev->gclk_use) { + clk_unprepare(dev->gclk); + dev->gclk_use = 0; + } } return 0; -- cgit v1.2.3 From 0f6fc97501b790c971b11b52a654009d21c45238 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Tue, 20 Aug 2019 19:24:10 +0300 Subject: ASoC: mchp-i2s-mcc: Wait for RX/TX RDY only if controller is running Since hw_free() can be called multiple times and not just after a stop trigger command, we should check whether the RX or TX ready interrupt was truly enabled previously. For this, we assure that the condition of the wait event is always true, except when RX/TX interrupts are enabled. Fixes: 7e0cdf545a55 ("ASoC: mchp-i2s-mcc: add driver for I2SC Multi-Channel Controller") Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20190820162411.24836-3-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 319f975586f1..ab7d5f98e759 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -691,22 +691,24 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream, err = wait_event_interruptible_timeout(dev->wq_txrdy, dev->tx_rdy, msecs_to_jiffies(500)); + if (err == 0) { + dev_warn_once(dev->dev, + "Timeout waiting for Tx ready\n"); + regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, + MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)); + dev->tx_rdy = 1; + } } else { err = wait_event_interruptible_timeout(dev->wq_rxrdy, dev->rx_rdy, msecs_to_jiffies(500)); - } - - if (err == 0) { - u32 idra; - - dev_warn_once(dev->dev, "Timeout waiting for %s\n", - is_playback ? "Tx ready" : "Rx ready"); - if (is_playback) - idra = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels); - else - idra = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels); - regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra); + if (err == 0) { + dev_warn_once(dev->dev, + "Timeout waiting for Rx ready\n"); + regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, + MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)); + dev->rx_rdy = 1; + } } if (!mchp_i2s_mcc_is_running(dev)) { @@ -818,6 +820,8 @@ static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai) init_waitqueue_head(&dev->wq_txrdy); init_waitqueue_head(&dev->wq_rxrdy); + dev->tx_rdy = 1; + dev->rx_rdy = 1; snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture); -- cgit v1.2.3 From 0ce6a624473e7e5752a84416f85f73d082308edd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:30:07 +0800 Subject: ASoC: AMD: Fix Kconfig warning without GPIOLIB While do rand build without GPIOLIB, we get Kconfig warning:\ WARNING: unmet direct dependencies detected for SND_SOC_MAX98357A Depends on [n]: SOUND [=y] && !UML && SND [=m] && SND_SOC [=m] && GPIOLIB [=n] Selected by [m]: - SND_SOC_AMD_CZ_DA7219MX98357_MACH [=m] && SOUND [=y] && !UML && SND [=m] && SND_SOC [=m] && SND_SOC_AMD_ACP [=m] && I2C [=y] Add GPIOLIB dependency to fix this. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822143007.73644-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 9ca9214cb7fb..5f40517717c4 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -10,7 +10,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH select SND_SOC_MAX98357A select SND_SOC_ADAU7002 select REGULATOR - depends on SND_SOC_AMD_ACP && I2C + depends on SND_SOC_AMD_ACP && I2C && GPIOLIB help This option enables machine driver for DA7219 and MAX9835. -- cgit v1.2.3 From 17d29ff98fd4b70e9ccdac5e95e18a087e2737ef Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 27 Aug 2019 16:17:07 +0200 Subject: ASoC: Intel: Skylake: Use correct function to access iomem space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For copying from __iomem, we should use __ioread32_copy. reported by sparse: sound/soc/intel/skylake/skl-debug.c:437:34: warning: incorrect type in argument 1 (different address spaces) sound/soc/intel/skylake/skl-debug.c:437:34: expected void [noderef] *to sound/soc/intel/skylake/skl-debug.c:437:34: got unsigned char * sound/soc/intel/skylake/skl-debug.c:437:51: warning: incorrect type in argument 2 (different address spaces) sound/soc/intel/skylake/skl-debug.c:437:51: expected void const *from sound/soc/intel/skylake/skl-debug.c:437:51: got void [noderef] *[assigned] fw_reg_addr Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20190827141712.21015-2-amadeuszx.slawinski@linux.intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/intel/skylake/skl-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index b9b4a72a4334..b28a9c2b0380 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -188,7 +188,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, memset(d->fw_read_buff, 0, FW_REG_BUF); if (w0_stat_sz > 0) - __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); + __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); for (offset = 0; offset < FW_REG_SIZE; offset += 16) { ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); -- cgit v1.2.3 From 810f3b860850148788fc1ed8a6f5f807199fed65 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 27 Aug 2019 16:17:08 +0200 Subject: ASoC: Intel: Fix use of potentially uninitialized variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If ipc->ops.reply_msg_match is NULL, we may end up using uninitialized mask value. reported by smatch: sound/soc/intel/common/sst-ipc.c:266 sst_ipc_reply_find_msg() error: uninitialized symbol 'mask'. Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20190827141712.21015-3-amadeuszx.slawinski@linux.intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/intel/common/sst-ipc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index ef5b66af1cd2..3a66121ee9bb 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -222,6 +222,8 @@ struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, if (ipc->ops.reply_msg_match != NULL) header = ipc->ops.reply_msg_match(header, &mask); + else + mask = (u64)-1; if (list_empty(&ipc->rx_list)) { dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n", -- cgit v1.2.3 From db33f00d15a63d269e283bad3f6f61eb00d2bc9d Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 27 Aug 2019 16:17:09 +0200 Subject: ASoC: dapm: Expose snd_soc_dapm_new_control_unlocked properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use snd_soc_dapm_new_control_unlocked for topology and have local declaration, instead declare it properly in header like already declared snd_soc_dapm_new_control. Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20190827141712.21015-4-amadeuszx.slawinski@linux.intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 +++ sound/soc/soc-topology.c | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c00a0b8ade08..8a90816a6eb5 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -402,6 +402,9 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *snd_soc_dapm_new_control( struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_widget *widget); +struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked( + struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget); int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index dc463f1a9e24..2eca85c04a3e 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -80,12 +80,6 @@ struct soc_tplg { static int soc_tplg_process_headers(struct soc_tplg *tplg); static void soc_tplg_complete(struct soc_tplg *tplg); -struct snd_soc_dapm_widget * -snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_widget *widget); -struct snd_soc_dapm_widget * -snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_widget *widget); static void soc_tplg_denum_remove_texts(struct soc_enum *se); static void soc_tplg_denum_remove_values(struct soc_enum *se); -- cgit v1.2.3 From 855a06da37a773fd073d51023ac9d07988c87da8 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 27 Aug 2019 16:17:12 +0200 Subject: ASoC: Intel: NHLT: Fix debug print format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit oem_table_id is 8 chars long, so we need to limit it, otherwise it may print some unprintable characters into dmesg. Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20190827141712.21015-7-amadeuszx.slawinski@linux.intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/intel/skylake/skl-nhlt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 1132109cb992..e01815cec6fd 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -225,7 +225,7 @@ int skl_nhlt_update_topology_bin(struct skl *skl) struct hdac_bus *bus = skl_to_bus(skl); struct device *dev = bus->dev; - dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n", + dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n", nhlt->header.oem_id, nhlt->header.oem_table_id, nhlt->header.oem_revision); -- cgit v1.2.3 From f972d02fee2496024cfd6f59021c9d89d54922a6 Mon Sep 17 00:00:00 2001 From: Katsuhiro Suzuki Date: Tue, 27 Aug 2019 00:38:59 +0900 Subject: ASoC: es8316: fix headphone mixer volume table This patch fix setting table of Headphone mixer volume. Current code uses 4 ... 7 values but these values are prohibited. Correct settings are the following: 0000 -12dB 0001 -10.5dB 0010 -9dB 0011 -7.5dB 0100 -6dB 1000 -4.5dB 1001 -3dB 1010 -1.5dB 1011 0dB Signed-off-by: Katsuhiro Suzuki Reviewed-by: Daniel Drake Link: https://lore.kernel.org/r/20190826153900.25969-1-katsuhiro@katsuster.net Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 6db002cc2058..96d04896193f 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -51,7 +51,10 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0); -static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv, + 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0), + 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0), +); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv, 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0), @@ -89,7 +92,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = { SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL, 4, 0, 3, 1, hpout_vol_tlv), SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL, - 0, 4, 7, 0, hpmixer_gain_tlv), + 0, 4, 11, 0, hpmixer_gain_tlv), SOC_ENUM("Playback Polarity", dacpol), SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL, -- cgit v1.2.3 From f6e77921969003eaf5dbae9c0b5feeb20c6caf50 Mon Sep 17 00:00:00 2001 From: Katsuhiro Suzuki Date: Tue, 27 Aug 2019 00:39:00 +0900 Subject: ASoC: es8316: fix inverted L/R of headphone mixer volume This patch fixes inverted Left-Right channel of headphone mixer volume by wrong shift_left, shift_right values. Signed-off-by: Katsuhiro Suzuki Reviewed-by: Daniel Drake Link: https://lore.kernel.org/r/20190826153900.25969-2-katsuhiro@katsuster.net Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 96d04896193f..ed2959dbe1fb 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -92,7 +92,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = { SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL, 4, 0, 3, 1, hpout_vol_tlv), SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL, - 0, 4, 11, 0, hpmixer_gain_tlv), + 4, 0, 11, 0, hpmixer_gain_tlv), SOC_ENUM("Playback Polarity", dacpol), SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL, -- cgit v1.2.3 From e9e897d5fdba9bda3a8c80ea39761413725f198c Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Mon, 26 Aug 2019 17:00:52 +0800 Subject: ASoC: rt1011: add mutex protection to set_fmt/set_tdm_slot The calibration process at booting will reset registers and bypass cache to make sure the calibration is done. We add mutex protection to avoid unexpected settings while the registration process and calibration are interleaved. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190826090052.1875-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 0a6ff13d76e1..ed28250d5e34 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1619,14 +1619,18 @@ static int rt1011_hw_params(struct snd_pcm_substream *substream, static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); unsigned int reg_val = 0, reg_bclk_inv = 0; + int ret = 0; + snd_soc_dapm_mutex_lock(dapm); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: reg_val |= RT1011_I2S_TDM_MS_S; break; default: - return -EINVAL; + ret = -EINVAL; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -1636,7 +1640,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) reg_bclk_inv |= RT1011_TDM_INV_BCLK; break; default: - return -EINVAL; + ret = -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1652,7 +1656,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) reg_val |= RT1011_I2S_TDM_DF_PCM_B; break; default: - return -EINVAL; + ret = -EINVAL; } switch (dai->id) { @@ -1667,9 +1671,11 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; default: dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); - return -EINVAL; + ret = -EINVAL; } - return 0; + + snd_soc_dapm_mutex_unlock(dapm); + return ret; } static int rt1011_set_component_sysclk(struct snd_soc_component *component, @@ -1788,8 +1794,12 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_component *component = dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); unsigned int val = 0, tdm_en = 0; + int ret = 0; + snd_soc_dapm_mutex_lock(dapm); if (rx_mask || tx_mask) tdm_en = RT1011_TDM_I2S_DOCK_EN_1; @@ -1809,7 +1819,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, case 2: break; default: - return -EINVAL; + ret = -EINVAL; } switch (slot_width) { @@ -1828,7 +1838,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, case 16: break; default: - return -EINVAL; + ret = -EINVAL; } snd_soc_component_update_bits(component, RT1011_TDM1_SET_1, @@ -1845,7 +1855,8 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG, RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT); - return 0; + snd_soc_dapm_mutex_unlock(dapm); + return ret; } static int rt1011_probe(struct snd_soc_component *component) -- cgit v1.2.3 From d2ac1fe0342ce2b44621f60d053800e2d94f1d21 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Sat, 24 Aug 2019 12:58:46 +0800 Subject: ASoC: mediatek: mt8183: fix tdm out data align issue Mt8183 tdm out support S16_LE/S24_LE/S32_LE formats. When output S32_LE, we need set hd_align so that memif can output MSB 24bits. When output S24_LE, we need reset hd_align so that memif can output LSB 24bits. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/1566622726-27113-1-git-send-email-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-afe-fe-dai.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index d16563408465..10ea4fdbeb1e 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -241,7 +241,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; int hd_audio = 0; - int hd_align = 1; + int hd_align = 0; /* set hd mode */ switch (substream->runtime->format) { @@ -254,7 +254,6 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, break; case SNDRV_PCM_FORMAT_S24_LE: hd_audio = 1; - hd_align = 0; break; default: dev_err(afe->dev, "%s() error: unsupported format %d\n", -- cgit v1.2.3 From 696d05225cebffd172008d212657be90e823eac0 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 28 Aug 2019 13:20:17 -0400 Subject: ASoC: fsl_ssi: Fix clock control issue in master mode The test case is arecord -Dhw:0 -d 10 -f S16_LE -r 48000 -c 2 temp.wav & aplay -Dhw:0 -d 30 -f S16_LE -r 48000 -c 2 test.wav There will be error after end of arecord: aplay: pcm_write:2051: write error: Input/output error Capture and Playback work in parallel in master mode, one substream stops, the other substream is impacted, the reason is that clock is disabled wrongly. The clock's reference count is not increased when second substream starts, the hw_param() function returns in the beginning because first substream is enabled, then in end of first substream, the hw_free() disables the clock. This patch is to move the clock enablement to the place before checking of the device enablement in hw_param(). Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1567012817-12625-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index fa862af25c1a..085855f9b08d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -799,15 +799,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, u32 wl = SSI_SxCCR_WL(sample_size); int ret; - /* - * SSI is properly configured if it is enabled and running in - * the synchronous mode; Note that AC97 mode is an exception - * that should set separate configurations for STCCR and SRCCR - * despite running in the synchronous mode. - */ - if (ssi->streams && ssi->synchronous) - return 0; - if (fsl_ssi_is_i2s_master(ssi)) { ret = fsl_ssi_set_bclk(substream, dai, hw_params); if (ret) @@ -823,6 +814,15 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, } } + /* + * SSI is properly configured if it is enabled and running in + * the synchronous mode; Note that AC97 mode is an exception + * that should set separate configurations for STCCR and SRCCR + * despite running in the synchronous mode. + */ + if (ssi->streams && ssi->synchronous) + return 0; + if (!fsl_ssi_is_ac97(ssi)) { /* * Keep the ssi->i2s_net intact while having a local variable -- cgit v1.2.3 From cc9bbb6cde6c321706f1eff79d077b4a91cd5d12 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 28 Aug 2019 11:51:02 +0200 Subject: ASoC: Intel: Baytrail: Fix implicit fallthrough warning Append fallthrough statement to fix warning reported during compilation. Fixes: b80d19c166c4 ("ASoC: Intel: Restore Baytrail ADSP streams only when ADSP was in reset") Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190828095102.15737-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/baytrail/sst-baytrail-pcm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 9cbc982d46a9..54f2ee3010ee 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -193,6 +193,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_SUSPEND: pdata->restore_stream = false; + /* fallthrough */ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: sst_byt_stream_pause(byt, pcm_data->stream); break; -- cgit v1.2.3 From a2dc6f82fd86fa165222f6062e2478fd122f9f1c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 30 Aug 2019 13:38:39 +0300 Subject: ASoC: ti: davinci-i2s: Move the XSYNCERR workaround to .prepare callback Currently the driver uses snd_soc_rtdcom_lookup() in it's mcbsp_start function to try to stop/restart the DMA as the initial XSYNCERR workaround need to be done before the DMA is armed. There are couple of things wrong with this: - the driver crashes with NULL pointer dereference as the component->driver->ops is actually NULL - the driver should not use snd_soc_rtdcom_lookup() in the first place - Fiddling with DMA is never a good thing Move the workaround handling to .prepare which is called before the DMA is armed, so it complies with the requirements. Reported-by (usage of snd_soc_rtdcom_lookup): Kuninori Morimoto Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190830103841.25128-3-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 82 +++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 48 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 92c1bdc69086..27afdbb9adf3 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -187,57 +187,9 @@ static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); u32 spcr; u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (spcr & mask) { - /* start off disabled */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, - spcr & ~mask); - toggle_clock(dev, playback); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - if (playback) { - /* Stop the DMA to avoid data loss */ - /* while the transmitter is out of reset to handle XSYNCERR */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_STOP); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA stop failed\n"); - } - - /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - - /* wait for any unexpected frame sync error to occur */ - udelay(100); - - /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); - - /* Restart the DMA */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA start failed\n"); - } - } /* Enable transmitter or receiver */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); @@ -575,7 +527,41 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, { struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + u32 spcr; + u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; + davinci_mcbsp_stop(dev, playback); + + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + if (spcr & mask) { + /* start off disabled */ + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, + spcr & ~mask); + toggle_clock(dev, playback); + } + if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | + DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { + /* Start the sample generator */ + spcr |= DAVINCI_MCBSP_SPCR_GRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + } + + if (playback) { + /* Enable the transmitter */ + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + spcr |= DAVINCI_MCBSP_SPCR_XRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + + /* wait for any unexpected frame sync error to occur */ + udelay(100); + + /* Disable the transmitter to clear any outstanding XSYNCERR */ + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + spcr &= ~DAVINCI_MCBSP_SPCR_XRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + toggle_clock(dev, playback); + } + return 0; } -- cgit v1.2.3 From 2ec42f3147e1610716f184b02e65d7f493eed925 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Sep 2019 08:55:24 +0300 Subject: ASoC: dmaengine: Make the pcm->name equal to pcm->id if the name is not set Some tools use the snd_pcm_info_get_name() to try to identify PCMs or for other purposes. Currently it is left empty with the dmaengine-pcm, in this case copy the pcm->id string as pcm->name. For example IGT is using this to find the HDMI PCM for testing audio on it. Signed-off-by: Peter Ujfalusi Reported-by: Arthur She Link: https://lore.kernel.org/r/20190906055524.7393-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/soc-generic-dmaengine-pcm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 748f5f641002..d93db2c2b527 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -306,6 +306,12 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i])) pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; + + if (rtd->pcm->streams[i].pcm->name[0] == '\0') { + strncpy(rtd->pcm->streams[i].pcm->name, + rtd->pcm->streams[i].pcm->id, + sizeof(rtd->pcm->streams[i].pcm->name)); + } } return 0; -- cgit v1.2.3 From 73681f4f1426847b421649c6aa6c2dc303acc7c8 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Sat, 7 Sep 2019 13:16:50 +0200 Subject: ASoC: ams-delta: Take control over audio mute GPIO pins Since commit 1137ceee76ba ("ARM: OMAP1: ams-delta: Don't request unused GPIOs"), on-board audio has appeared muted. It has been discovered that believed to be unused GPIO pins "hookflash1" and "hookflash2" need to be set low for audible sound in handsfree and handset mode respectively. According to Amstrad E3 wiki, the purpose of both pins hasn't been clearly identified. Original Amstrad software used to produce a high pulse on them when the phone was taken off hook or recall was pressed. With the current findings, we can assume the pins provide a kind of audio mute function, separately for handset and handsfree operation modes. Commit 2afdb4c41d78 ("ARM: OMAP1: ams-delta: Fix audio permanently muted") attempted to fix the issue temporarily by hogging the GPIO pin "hookflash1" renamed to "audio_mute", however the fix occurred incomplete as it restored audible sound only for handsfree mode. Stop hogging that pin, rename the pins to "handsfree_mute" and "handset_mute" respectively and implement appropriate DAPM event callbacks for "Speaker" and "Earpiece" DAPM widgets. Fixes: 1137ceee76ba ("ARM: OMAP1: ams-delta: Don't request unused GPIOs") Signed-off-by: Janusz Krzysztofik Reviewed-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190907111650.15440-1-jmkrzyszt@gmail.com Signed-off-by: Mark Brown --- arch/arm/mach-omap1/board-ams-delta.c | 10 ++++++---- sound/soc/ti/ams-delta.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 36498ea1b2f3..c2affc727967 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -245,8 +245,8 @@ static struct platform_device latch2_gpio_device = { #define LATCH2_PIN_SCARD_CMDVCC 11 #define LATCH2_PIN_MODEM_NRESET 12 #define LATCH2_PIN_MODEM_CODEC 13 -#define LATCH2_PIN_AUDIO_MUTE 14 -#define LATCH2_PIN_HOOKFLASH 15 +#define LATCH2_PIN_HANDSFREE_MUTE 14 +#define LATCH2_PIN_HANDSET_MUTE 15 static struct regulator_consumer_supply modem_nreset_consumers[] = { REGULATOR_SUPPLY("RESET#", "serial8250.1"), @@ -475,6 +475,10 @@ static struct gpiod_lookup_table ams_delta_audio_gpio_table = { "hook_switch", 0), GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC, "modem_codec", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSFREE_MUTE, + "handsfree_mute", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSET_MUTE, + "handset_mute", 0), { }, }, }; @@ -589,8 +593,6 @@ static int gpiochip_match_by_label(struct gpio_chip *chip, void *data) static struct gpiod_hog ams_delta_gpio_hogs[] = { GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout", GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW), - GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_AUDIO_MUTE, "audio_mute", - GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW), {}, }; diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index dee8fc70a64f..8e2fb81ad05c 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -23,14 +23,31 @@ #include "omap-mcbsp.h" #include "../codecs/cx20442.h" +static struct gpio_desc *handset_mute; +static struct gpio_desc *handsfree_mute; + +static int ams_delta_event_handset(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + gpiod_set_value_cansleep(handset_mute, !SND_SOC_DAPM_EVENT_ON(event)); + return 0; +} + +static int ams_delta_event_handsfree(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + gpiod_set_value_cansleep(handsfree_mute, !SND_SOC_DAPM_EVENT_ON(event)); + return 0; +} + /* Board specific DAPM widgets */ static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { /* Handset */ SND_SOC_DAPM_MIC("Mouthpiece", NULL), - SND_SOC_DAPM_HP("Earpiece", NULL), + SND_SOC_DAPM_HP("Earpiece", ams_delta_event_handset), /* Handsfree/Speakerphone */ SND_SOC_DAPM_MIC("Microphone", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_SPK("Speaker", ams_delta_event_handsfree), }; /* How they are connected to codec pins */ @@ -542,6 +559,16 @@ static int ams_delta_probe(struct platform_device *pdev) card->dev = &pdev->dev; + handset_mute = devm_gpiod_get(card->dev, "handset_mute", + GPIOD_OUT_HIGH); + if (IS_ERR(handset_mute)) + return PTR_ERR(handset_mute); + + handsfree_mute = devm_gpiod_get(card->dev, "handsfree_mute", + GPIOD_OUT_HIGH); + if (IS_ERR(handsfree_mute)) + return PTR_ERR(handsfree_mute); + ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); -- cgit v1.2.3