diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/amd/acp/acp-renoir.c | 7 | ||||
-rw-r--r-- | sound/soc/amd/raven/acp3x-pcm-dma.c | 7 | ||||
-rw-r--r-- | sound/soc/amd/renoir/acp3x-pdm-dma.c | 7 | ||||
-rw-r--r-- | sound/soc/amd/vangogh/acp5x-pcm-dma.c | 7 | ||||
-rw-r--r-- | sound/soc/atmel/sam9g20_wm8731.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 10 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/aw8738.c | 104 | ||||
-rw-r--r-- | sound/soc/codecs/cs35l41.c | 8 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l42.c | 13 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l42.h | 9 | ||||
-rw-r--r-- | sound/soc/codecs/rt5682s.c | 47 | ||||
-rw-r--r-- | sound/soc/codecs/wm8350.c | 28 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 99 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.h | 1 | ||||
-rw-r--r-- | sound/soc/qcom/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 19 |
17 files changed, 311 insertions, 60 deletions
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 738cf2e2b973..75c9229ece97 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -282,9 +282,10 @@ static int renoir_audio_probe(struct platform_device *pdev) if (!adata->acp_base) return -ENOMEM; - adata->i2s_irq = platform_get_irq_byname(pdev, "acp_dai_irq"); - if (adata->i2s_irq < 0) - return -ENODEV; + ret = platform_get_irq_byname(pdev, "acp_dai_irq"); + if (ret < 0) + return ret; + adata->i2s_irq = ret; adata->dev = dev; adata->dai_driver = acp_renoir_dai; diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index e4f8dbf0d11d..6aec11cf0a6a 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -394,9 +394,10 @@ static int acp3x_audio_probe(struct platform_device *pdev) if (!adata->acp3x_base) return -ENOMEM; - adata->i2s_irq = platform_get_irq(pdev, 0); - if (adata->i2s_irq < 0) - return -ENODEV; + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->i2s_irq = status; dev_set_drvdata(&pdev->dev, adata); status = devm_snd_soc_register_component(&pdev->dev, diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 88a242538461..8c42345ee41e 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -399,9 +399,10 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) if (!adata->acp_base) return -ENOMEM; - adata->pdm_irq = platform_get_irq(pdev, 0); - if (adata->pdm_irq < 0) - return -ENODEV; + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->pdm_irq = status; adata->capture_stream = NULL; diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c index e4e668593b3d..31fa166df98a 100644 --- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -388,9 +388,10 @@ static int acp5x_audio_probe(struct platform_device *pdev) if (!adata->acp5x_base) return -ENOMEM; - adata->i2s_irq = platform_get_irq(pdev, 0); - if (adata->i2s_irq < 0) - return -ENODEV; + status = platform_get_irq(pdev, 0); + if (status < 0) + return status; + adata->i2s_irq = status; dev_set_drvdata(&pdev->dev, adata); status = devm_snd_soc_register_component(&pdev->dev, diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 915da92e1ec8..33e43013ff77 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -214,6 +214,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "dai and pcm info missing\n"); + of_node_put(codec_np); return -EINVAL; } at91sam9g20ek_dai.cpus->of_node = cpu_np; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4de029ae377c..f46a22660103 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_AK5558 imply SND_SOC_ALC5623 imply SND_SOC_ALC5632 + imply SND_SOC_AW8738 imply SND_SOC_BT_SCO imply SND_SOC_BD28623 imply SND_SOC_CQ0093VC @@ -579,6 +580,15 @@ config SND_SOC_ALC5632 tristate depends on I2C +config SND_SOC_AW8738 + tristate "Awinic AW8738 Audio Amplifier" + select GPIOLIB + help + Enable support for the Awinic AW8738 audio amplifier (or similar). + The driver supports simple audio amplifiers similar to + SND_SOC_SIMPLE_AMPLIFIER, but additionally allows setting the + operation mode using the Awinic-specific one-wire pulse control. + config SND_SOC_BD28623 tristate "ROHM BD28623 CODEC" help diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c3c6059a5f8a..8637e9e869e3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -45,6 +45,7 @@ snd-soc-ak4671-objs := ak4671.o snd-soc-ak5386-objs := ak5386.o snd-soc-ak5558-objs := ak5558.o snd-soc-arizona-objs := arizona.o arizona-jack.o +snd-soc-aw8738-objs := aw8738.o snd-soc-bd28623-objs := bd28623.o snd-soc-bt-sco-objs := bt-sco.o snd-soc-cpcap-objs := cpcap.o @@ -388,6 +389,7 @@ obj-$(CONFIG_SND_SOC_AK5558) += snd-soc-ak5558.o obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o +obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o diff --git a/sound/soc/codecs/aw8738.c b/sound/soc/codecs/aw8738.c new file mode 100644 index 000000000000..0fe8af160319 --- /dev/null +++ b/sound/soc/codecs/aw8738.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <sound/soc.h> + +struct aw8738_priv { + struct gpio_desc *gpiod_mode; + unsigned int mode; +}; + +static int aw8738_drv_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct aw8738_priv *aw = snd_soc_component_get_drvdata(c); + int i; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + for (i = 0; i < aw->mode; i++) { + gpiod_set_value_cansleep(aw->gpiod_mode, 0); + udelay(2); + gpiod_set_value_cansleep(aw->gpiod_mode, 1); + udelay(2); + } + msleep(40); + break; + case SND_SOC_DAPM_PRE_PMD: + gpiod_set_value_cansleep(aw->gpiod_mode, 0); + usleep_range(1000, 2000); + break; + default: + WARN(1, "Unexpected event"); + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dapm_widget aw8738_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN"), + SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, aw8738_drv_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUTPUT("OUT"), +}; + +static const struct snd_soc_dapm_route aw8738_dapm_routes[] = { + { "DRV", NULL, "IN" }, + { "OUT", NULL, "DRV" }, +}; + +static const struct snd_soc_component_driver aw8738_component_driver = { + .dapm_widgets = aw8738_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aw8738_dapm_widgets), + .dapm_routes = aw8738_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(aw8738_dapm_routes), +}; + +static int aw8738_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct aw8738_priv *aw; + int ret; + + aw = devm_kzalloc(dev, sizeof(*aw), GFP_KERNEL); + if (!aw) + return -ENOMEM; + platform_set_drvdata(pdev, aw); + + aw->gpiod_mode = devm_gpiod_get(dev, "mode", GPIOD_OUT_LOW); + if (IS_ERR(aw->gpiod_mode)) + return dev_err_probe(dev, PTR_ERR(aw->gpiod_mode), + "Failed to get 'mode' gpio"); + + ret = device_property_read_u32(dev, "awinic,mode", &aw->mode); + if (ret) + return -EINVAL; + + return devm_snd_soc_register_component(&pdev->dev, + &aw8738_component_driver, + NULL, 0); +} + +#ifdef CONFIG_OF +static const struct of_device_id aw8738_of_match[] = { + { .compatible = "awinic,aw8738" }, + { } +}; +MODULE_DEVICE_TABLE(of, aw8738_of_match); +#endif + +static struct platform_driver aw8738_driver = { + .probe = aw8738_probe, + .driver = { + .name = "aw8738", + .of_match_table = of_match_ptr(aw8738_of_match), + }, +}; +module_platform_driver(aw8738_driver); + +MODULE_DESCRIPTION("Awinic AW8738 Amplifier Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 77a017694645..e10d1276a937 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1091,7 +1091,7 @@ static struct snd_soc_dai_driver cs35l41_dai[] = { .capture = { .stream_name = "AMP Capture", .channels_min = 1, - .channels_max = 8, + .channels_max = 4, .rates = SNDRV_PCM_RATE_KNOT, .formats = CS35L41_TX_FORMATS, }, @@ -1115,9 +1115,7 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l41 = { .set_sysclk = cs35l41_component_set_sysclk, }; -static int cs35l41_handle_pdata(struct device *dev, - struct cs35l41_platform_data *pdata, - struct cs35l41_private *cs35l41) +static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_platform_data *pdata) { struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1; struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2; @@ -1260,7 +1258,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, if (pdata) { cs35l41->pdata = *pdata; } else { - ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata, cs35l41); + ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata); if (ret != 0) return ret; } diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index db6ef6cdce15..c8409d50e934 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -1012,7 +1012,14 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) } } else { if (!cs42l42->stream_use) { - /* SCLK must be running before codec unmute */ + /* SCLK must be running before codec unmute. + * + * PLL must not be started with ADC and HP both off + * otherwise the FILT+ supply will not charge properly. + * DAPM widgets power-up before stream unmute so at least + * one of the "DAC" or "ADC" widgets will already have + * powered-up. + */ if (pll_ratio_table[cs42l42->pll_config].mclk_src_sel) { snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, CS42L42_PLL_START_MASK, 1); @@ -1830,6 +1837,10 @@ static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42) cs42l42->hs_type = CS42L42_PLUG_INVALID; + /* + * DETECT_MODE must always be 0 with ADC and HP both off otherwise the + * FILT+ supply will not charge properly. + */ regmap_update_bits(cs42l42->regmap, CS42L42_MISC_DET_CTL, CS42L42_DETECT_MODE_MASK, 0); diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 244b24d1f5e9..60d3bdf5d7c9 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -491,7 +491,10 @@ #define CS42L42_TS_UNPLUG 0 #define CS42L42_TS_TRANS 1 -/* Page 0x15 Fractional-N PLL Registers */ +/* + * NOTE: PLL_START must be 0 while both ADC_PDN=1 and HP_PDN=1. + * Otherwise it will prevent FILT+ from charging properly. + */ #define CS42L42_PLL_CTL1 (CS42L42_PAGE_15 + 0x01) #define CS42L42_PLL_START_SHIFT 0 #define CS42L42_PLL_START_MASK (1 << CS42L42_PLL_START_SHIFT) @@ -574,6 +577,10 @@ #define CS42L42_TIP_SENSE_CTRL_MASK (3 << \ CS42L42_TIP_SENSE_CTRL_SHIFT) +/* + * NOTE: DETECT_MODE must be 0 while both ADC_PDN=1 and HP_PDN=1. + * Otherwise it will prevent FILT+ from charging properly. + */ #define CS42L42_MISC_DET_CTL (CS42L42_PAGE_1B + 0x74) #define CS42L42_PDN_MIC_LVL_DET_SHIFT 0 #define CS42L42_PDN_MIC_LVL_DET_MASK (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT) diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index efa1016831dd..8f3d59c75aa0 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -644,8 +644,7 @@ enum { SAR_PWR_SAVING, }; -static void rt5682s_sar_power_mode(struct snd_soc_component *component, - int mode, int jd_step) +static void rt5682s_sar_power_mode(struct snd_soc_component *component, int mode) { struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); @@ -675,16 +674,17 @@ static void rt5682s_sar_power_mode(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, RT5682S_MB1_PATH_MASK | RT5682S_MB2_PATH_MASK, RT5682S_CTRL_MB1_FSM | RT5682S_CTRL_MB2_FSM); - if (!jd_step) { - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_SEL_MB1_2_AUTO); - usleep_range(5000, 5500); - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK, - RT5682S_SAR_BUTDET_EN | RT5682S_SAR_BUTDET_POW_NORM); - } + snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, + RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_SEL_MB1_2_AUTO); + usleep_range(5000, 5500); + snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, + RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK, + RT5682S_SAR_BUTDET_EN | RT5682S_SAR_BUTDET_POW_NORM); break; case SAR_PWR_OFF: + snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, + RT5682S_MB1_PATH_MASK | RT5682S_MB2_PATH_MASK, + RT5682S_CTRL_MB1_FSM | RT5682S_CTRL_MB2_FSM); snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_DIS | @@ -702,6 +702,10 @@ static void rt5682s_enable_push_button_irq(struct snd_soc_component *component) { snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_13, RT5682S_SAR_SOUR_MASK, RT5682S_SAR_SOUR_BTN); + snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, + RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | + RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_EN | + RT5682S_SAR_BUTDET_POW_NORM | RT5682S_SAR_SEL_MB1_2_AUTO); snd_soc_component_write(component, RT5682S_IL_CMD_1, 0x0040); snd_soc_component_update_bits(component, RT5682S_4BTN_IL_CMD_2, RT5682S_4BTN_IL_MASK | RT5682S_4BTN_IL_RST_MASK, @@ -718,6 +722,10 @@ static void rt5682s_disable_push_button_irq(struct snd_soc_component *component) RT5682S_4BTN_IL_MASK, RT5682S_4BTN_IL_DIS); snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_13, RT5682S_SAR_SOUR_MASK, RT5682S_SAR_SOUR_TYPE); + snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, + RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | + RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_DIS | + RT5682S_SAR_BUTDET_POW_SAV | RT5682S_SAR_SEL_MB1_2_MANU); } /** @@ -753,7 +761,8 @@ static int rt5682s_headset_detect(struct snd_soc_component *component, int jack_ RT5682S_OSW_L_DIS | RT5682S_OSW_R_DIS); snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_13, RT5682S_SAR_SOUR_MASK, RT5682S_SAR_SOUR_TYPE); - rt5682s_sar_power_mode(component, SAR_PWR_NORMAL, 1); + snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_3, + RT5682S_CBJ_IN_BUF_MASK, RT5682S_CBJ_IN_BUF_EN); snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, RT5682S_TRIG_JD_MASK, RT5682S_TRIG_JD_LOW); usleep_range(45000, 50000); @@ -779,9 +788,8 @@ static int rt5682s_headset_detect(struct snd_soc_component *component, int jack_ RT5682S_FAST_OFF_MASK, RT5682S_FAST_OFF_EN); snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, RT5682S_SAR_SEL_MB1_2_MASK, val << RT5682S_SAR_SEL_MB1_2_SFT); - if (!snd_soc_dapm_get_pin_status(&component->dapm, "SAR")) - rt5682s_sar_power_mode(component, SAR_PWR_SAVING, 1); rt5682s_enable_push_button_irq(component); + rt5682s_sar_power_mode(component, SAR_PWR_SAVING); break; default: jack_type = SND_JACK_HEADPHONE; @@ -792,7 +800,7 @@ static int rt5682s_headset_detect(struct snd_soc_component *component, int jack_ RT5682S_OSW_L_EN | RT5682S_OSW_R_EN); usleep_range(35000, 40000); } else { - rt5682s_sar_power_mode(component, SAR_PWR_OFF, 1); + rt5682s_sar_power_mode(component, SAR_PWR_OFF); rt5682s_disable_push_button_irq(component); snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, RT5682S_TRIG_JD_MASK, RT5682S_TRIG_JD_LOW); @@ -1403,10 +1411,10 @@ static int sar_power_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - rt5682s_sar_power_mode(component, SAR_PWR_NORMAL, 0); + rt5682s_sar_power_mode(component, SAR_PWR_NORMAL); break; case SND_SOC_DAPM_POST_PMD: - rt5682s_sar_power_mode(component, SAR_PWR_SAVING, 0); + rt5682s_sar_power_mode(component, SAR_PWR_SAVING); break; } @@ -2835,9 +2843,8 @@ static int rt5682s_suspend(struct snd_soc_component *component) cancel_delayed_work_sync(&rt5682s->jack_detect_work); cancel_delayed_work_sync(&rt5682s->jd_check_work); - if (rt5682s->hs_jack && rt5682s->jack_type == SND_JACK_HEADSET) - snd_soc_component_update_bits(component, RT5682S_4BTN_IL_CMD_2, - RT5682S_4BTN_IL_MASK, RT5682S_4BTN_IL_DIS); + if (rt5682s->hs_jack) + rt5682s->jack_type = rt5682s_headset_detect(component, 0); regcache_cache_only(rt5682s->regmap, true); regcache_mark_dirty(rt5682s->regmap); @@ -2853,8 +2860,6 @@ static int rt5682s_resume(struct snd_soc_component *component) regcache_sync(rt5682s->regmap); if (rt5682s->hs_jack) { - rt5682s->jack_type = 0; - rt5682s_sar_power_mode(component, SAR_PWR_NORMAL, 0); mod_delayed_work(system_power_efficient_wq, &rt5682s->jack_detect_work, msecs_to_jiffies(0)); } diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 15d42ce3b21d..41504ce2a682 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1537,18 +1537,38 @@ static int wm8350_component_probe(struct snd_soc_component *component) wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, WM8350_JDL_ENA | WM8350_JDR_ENA); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, wm8350_hpl_jack_handler, 0, "Left jack detect", priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, + if (ret != 0) + goto err; + + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, wm8350_hpr_jack_handler, 0, "Right jack detect", priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, + if (ret != 0) + goto free_jck_det_l; + + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, wm8350_mic_handler, 0, "Microphone short", priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, + if (ret != 0) + goto free_jck_det_r; + + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, wm8350_mic_handler, 0, "Microphone detect", priv); + if (ret != 0) + goto free_micscd; return 0; + +free_micscd: + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv); +free_jck_det_r: + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); +free_jck_det_l: + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); +err: + return ret; } static void wm8350_component_remove(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index c8c8338cb401..375cb14aaccd 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -749,21 +749,48 @@ static void wm_adsp_release_firmware_files(struct wm_adsp *dsp, } static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, - const struct firmware **firmware, - char **filename, - char *suffix) + const struct firmware **firmware, char **filename, + const char *dir, const char *system_name, + const char *asoc_component_prefix, + const char *filetype) { struct cs_dsp *cs_dsp = &dsp->cs_dsp; + char *s, c; int ret = 0; - *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", dsp->part, dsp->fwf_name, - wm_adsp_fw[dsp->fw].file, suffix); + if (system_name && asoc_component_prefix) + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part, + dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, + asoc_component_prefix, filetype); + else if (system_name) + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, + dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, + filetype); + else + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, dsp->fwf_name, + wm_adsp_fw[dsp->fw].file, filetype); + if (*filename == NULL) return -ENOMEM; - ret = request_firmware(firmware, *filename, cs_dsp->dev); + /* + * Make sure that filename is lower-case and any non alpha-numeric + * characters except full stop and forward slash are replaced with + * hyphens. + */ + s = *filename; + while (*s) { + c = *s; + if (isalnum(c)) + *s = tolower(c); + else if ((c != '.') && (c != '/')) + *s = '-'; + s++; + } + + ret = firmware_request_nowarn(firmware, *filename, cs_dsp->dev); if (ret != 0) { - adsp_err(dsp, "Failed to request '%s'\n", *filename); + adsp_dbg(dsp, "Failed to request '%s'\n", *filename); kfree(*filename); *filename = NULL; } @@ -771,21 +798,69 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, return ret; } +static const char *cirrus_dir = "cirrus/"; static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, const struct firmware **wmfw_firmware, char **wmfw_filename, const struct firmware **coeff_firmware, char **coeff_filename) { + const char *system_name = dsp->system_name; + const char *asoc_component_prefix = dsp->component->name_prefix; int ret = 0; - ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "wmfw"); - if (ret != 0) - return ret; + if (system_name && asoc_component_prefix) { + if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, + cirrus_dir, system_name, + asoc_component_prefix, "wmfw")) { + adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + asoc_component_prefix, "bin"); + return 0; + } + } - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "bin"); + if (system_name) { + if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, + cirrus_dir, system_name, + NULL, "wmfw")) { + adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); + if (asoc_component_prefix) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + asoc_component_prefix, "bin"); + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + NULL, "bin"); + return 0; + } + } - return 0; + if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, + "", NULL, NULL, "wmfw")) { + adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + "", NULL, NULL, "bin"); + return 0; + } + + ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, + cirrus_dir, NULL, NULL, "wmfw"); + if (!ret) { + adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, NULL, NULL, "bin"); + return 0; + } + + adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", + cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, + system_name, asoc_component_prefix); + + return -ENOENT; } static int wm_adsp_common_init(struct wm_adsp *dsp) diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 7f4fabbc6ad3..375009a65828 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -28,6 +28,7 @@ struct wm_adsp { struct cs_dsp cs_dsp; const char *part; const char *fwf_name; + const char *system_name; struct snd_soc_component *component; unsigned int sys_config_size; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 0cd0dae5c545..82f5eafb2f6c 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -193,7 +193,7 @@ config SND_SOC_SC7280 select SND_SOC_QCOM_COMMON select SND_SOC_LPASS_SC7280 select SND_SOC_MAX98357A - select SND_SOC_WCD938X + select SND_SOC_WCD938X_SDW select SND_SOC_LPASS_MACRO_COMMON select SND_SOC_LPASS_RX_MACRO select SND_SOC_LPASS_TX_MACRO diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index cdf3b7f69ba7..e9a1eb6bdf66 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -816,14 +816,27 @@ static int fsi_clk_enable(struct device *dev, return ret; } - clk_enable(clock->xck); - clk_enable(clock->ick); - clk_enable(clock->div); + ret = clk_enable(clock->xck); + if (ret) + goto err; + ret = clk_enable(clock->ick); + if (ret) + goto disable_xck; + ret = clk_enable(clock->div); + if (ret) + goto disable_ick; clock->count++; } return ret; + +disable_ick: + clk_disable(clock->ick); +disable_xck: + clk_disable(clock->xck); +err: + return ret; } static int fsi_clk_disable(struct device *dev, |