diff options
Diffstat (limited to 'sound/soc')
30 files changed, 425 insertions, 260 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 18baea2f7d65..84f86745c30e 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -148,11 +148,11 @@ SND_SOC_DAPM_OUTPUT("AOUTR"), }; static const struct snd_soc_dapm_route cs4270_dapm_routes[] = { - { "Capture", NULL, "AINA" }, - { "Capture", NULL, "AINB" }, + { "Capture", NULL, "AINL" }, + { "Capture", NULL, "AINR" }, - { "AOUTA", NULL, "Playback" }, - { "AOUTB", NULL, "Playback" }, + { "AOUTL", NULL, "Playback" }, + { "AOUTR", NULL, "Playback" }, }; /** diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 2b8914dd5990..6274d79c1353 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -204,10 +204,19 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL, DA7219_MIXOUT_R_AMP_EN_MASK, DA7219_MIXOUT_R_AMP_EN_MASK); - snd_soc_write(codec, DA7219_HP_L_CTRL, - DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK); - snd_soc_write(codec, DA7219_HP_R_CTRL, - DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK, + DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK); + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK, + DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); + msleep(DA7219_SETTLING_DELAY); + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_MUTE_EN_MASK | + DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, 0); + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_MUTE_EN_MASK | + DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, 0); /* * If we're running from the internal oscillator then give audio paths @@ -244,6 +253,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) regcache_mark_dirty(da7219->regmap); regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL, DA7219_HP_R_CTRL); + msleep(DA7219_SETTLING_DELAY); regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL, DA7219_MIXOUT_R_CTRL); regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L, diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 1152aa5e7c39..99601627f83c 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -823,6 +823,85 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, } } +static int da7219_settling_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_POST_PMD: + msleep(DA7219_SETTLING_DELAY); + break; + default: + break; + } + + return 0; +} + +static int da7219_mixout_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + u8 hp_ctrl, min_gain_mask; + + switch (w->reg) { + case DA7219_MIXOUT_L_CTRL: + hp_ctrl = DA7219_HP_L_CTRL; + min_gain_mask = DA7219_HP_L_AMP_MIN_GAIN_EN_MASK; + break; + case DA7219_MIXOUT_R_CTRL: + hp_ctrl = DA7219_HP_R_CTRL; + min_gain_mask = DA7219_HP_R_AMP_MIN_GAIN_EN_MASK; + break; + default: + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMD: + /* Enable minimum gain on HP to avoid pops */ + snd_soc_update_bits(codec, hp_ctrl, min_gain_mask, + min_gain_mask); + + msleep(DA7219_MIN_GAIN_DELAY); + + break; + case SND_SOC_DAPM_POST_PMU: + /* Remove minimum gain on HP */ + snd_soc_update_bits(codec, hp_ctrl, min_gain_mask, 0); + + break; + } + + return 0; +} + +static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + case SND_SOC_DAPM_PRE_PMD: + /* Ensure nominal gain ramping for DAPM sequence */ + da7219->gain_ramp_ctrl = + snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, + DA7219_GAIN_RAMP_RATE_NOMINAL); + break; + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_POST_PMD: + /* Restore previous gain ramp settings */ + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, + da7219->gain_ramp_ctrl); + break; + } + + return 0; +} + /* * DAPM Widgets @@ -880,7 +959,8 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* DAI */ - SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, DA7219_DAI_TDM_CTRL, + DA7219_DAI_OE_SHIFT, DA7219_NO_INVERT), SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), /* Output Muxes */ @@ -906,30 +986,46 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { ARRAY_SIZE(da7219_st_out_filtr_mix_controls)), /* DACs */ - SND_SOC_DAPM_DAC("DACL", NULL, DA7219_DAC_L_CTRL, DA7219_DAC_L_EN_SHIFT, - DA7219_NO_INVERT), - SND_SOC_DAPM_DAC("DACR", NULL, DA7219_DAC_R_CTRL, DA7219_DAC_R_EN_SHIFT, - DA7219_NO_INVERT), + SND_SOC_DAPM_DAC_E("DACL", NULL, DA7219_DAC_L_CTRL, + DA7219_DAC_L_EN_SHIFT, DA7219_NO_INVERT, + da7219_settling_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC_E("DACR", NULL, DA7219_DAC_R_CTRL, + DA7219_DAC_R_EN_SHIFT, DA7219_NO_INVERT, + da7219_settling_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* Output PGAs */ - SND_SOC_DAPM_PGA("Mixout Left PGA", DA7219_MIXOUT_L_CTRL, - DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT, - NULL, 0), - SND_SOC_DAPM_PGA("Mixout Right PGA", DA7219_MIXOUT_R_CTRL, - DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT, - NULL, 0), - SND_SOC_DAPM_PGA("Headphone Left PGA", DA7219_HP_L_CTRL, - DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), - SND_SOC_DAPM_PGA("Headphone Right PGA", DA7219_HP_R_CTRL, - DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), + SND_SOC_DAPM_PGA_E("Mixout Left PGA", DA7219_MIXOUT_L_CTRL, + DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_mixout_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA_E("Mixout Right PGA", DA7219_MIXOUT_R_CTRL, + DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_mixout_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY_S("Headphone Left PGA", 1, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT, + da7219_settling_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("Headphone Right PGA", 1, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT, + da7219_settling_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* Output Supplies */ - SND_SOC_DAPM_SUPPLY("Charge Pump", DA7219_CP_CTRL, DA7219_CP_EN_SHIFT, - DA7219_NO_INVERT, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("Charge Pump", 0, DA7219_CP_CTRL, + DA7219_CP_EN_SHIFT, DA7219_NO_INVERT, + da7219_settling_event, + SND_SOC_DAPM_POST_PMU), /* Outputs */ SND_SOC_DAPM_OUTPUT("HPL"), SND_SOC_DAPM_OUTPUT("HPR"), + + /* Pre/Post Power */ + SND_SOC_DAPM_PRE("Pre Power Gain Ramp", da7219_gain_ramp_event), + SND_SOC_DAPM_POST("Post Power Gain Ramp", da7219_gain_ramp_event), }; @@ -1002,8 +1098,8 @@ static const struct snd_soc_dapm_route da7219_audio_map[] = { {"Mixout Left PGA", NULL, "DACL"}, {"Mixout Right PGA", NULL, "DACR"}, - {"Headphone Left PGA", NULL, "Mixout Left PGA"}, - {"Headphone Right PGA", NULL, "Mixout Right PGA"}, + {"HPL", NULL, "Mixout Left PGA"}, + {"HPR", NULL, "Mixout Right PGA"}, {"HPL", NULL, "Headphone Left PGA"}, {"HPR", NULL, "Headphone Right PGA"}, @@ -1711,6 +1807,14 @@ static int da7219_probe(struct snd_soc_codec *codec) DA7219_HP_R_AMP_RAMP_EN_MASK, DA7219_HP_R_AMP_RAMP_EN_MASK); + /* Default minimum gain on HP to avoid pops during DAPM sequencing */ + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, + DA7219_HP_L_AMP_MIN_GAIN_EN_MASK); + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, + DA7219_HP_R_AMP_MIN_GAIN_EN_MASK); + /* Default infinite tone gen, start/stop by Kcontrol */ snd_soc_write(codec, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK); diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 66d3bad86739..6baba7455fa1 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -777,6 +777,10 @@ #define DA7219_SYS_STAT_CHECK_RETRIES 6 #define DA7219_SYS_STAT_CHECK_DELAY 50 +/* Power up/down Delays */ +#define DA7219_SETTLING_DELAY 40 +#define DA7219_MIN_GAIN_DELAY 30 + enum da7219_clk_src { DA7219_CLKSRC_MCLK = 0, DA7219_CLKSRC_MCLK_SQR, @@ -814,6 +818,7 @@ struct da7219_priv { bool master; bool alc_en; + u8 gain_ramp_ctrl; }; #endif /* __DA7219_H */ diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index b904492d7744..90b5948e0ff3 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -364,7 +364,12 @@ static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, struct of_phandle_args *args, const char **dai_name) { - int id = args->args[0]; + int id; + + if (args->args_count) + id = args->args[0]; + else + id = 0; if (id < ARRAY_SIZE(hdmi_dai_name)) { *dai_name = hdmi_dai_name[id]; diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 55558643166f..2db8179047ae 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -249,6 +249,11 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) snd_soc_dapm_force_enable_pin(dapm, "LDO1"); snd_soc_dapm_sync(dapm); + regmap_update_bits(rt298->regmap, + RT298_POWER_CTRL1, 0x1001, 0); + regmap_update_bits(rt298->regmap, + RT298_POWER_CTRL2, 0x4, 0x4); + regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); msleep(50); diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 01a18d88f1eb..00ff2788879e 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1547,11 +1547,11 @@ static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert) msleep(sleep_time[i]); val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) & 0x0003; + dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", + __func__, val, sleep_time[i]); i++; if (val == 0x1 || val == 0x2 || val == 0x3) break; - dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", - __func__, val, sleep_time[i]); } dev_dbg(codec->dev, "%s val = %d\n", __func__, val); switch (val) { diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index 7b31ee9b82bc..d6e00c77edcd 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -424,7 +424,7 @@ static const struct snd_soc_dai_ops stih407_dac_ops = { static const struct regmap_config stih407_sas_regmap = { .reg_bits = 32, .val_bits = 32, - + .fast_io = true, .max_register = STIH407_AUDIO_DAC_CTRL, .reg_defaults = stih407_sas_reg_defaults, .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults), diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index df5e5cb33baa..810369f687d7 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -341,20 +341,9 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec, return ret; } } - - gpiod_set_value(priv->pdn_gpio, 0); - usleep_range(5000, 6000); - - regcache_cache_only(priv->regmap, false); - ret = regcache_sync(priv->regmap); - if (ret) - return ret; } break; case SND_SOC_BIAS_OFF: - regcache_cache_only(priv->regmap, true); - gpiod_set_value(priv->pdn_gpio, 1); - if (!IS_ERR(priv->mclk)) clk_disable_unprepare(priv->mclk); break; @@ -401,16 +390,6 @@ static const struct snd_kcontrol_new tas5711_controls[] = { TAS571X_SOFT_MUTE_REG, TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 1, 1), - - SOC_DOUBLE_R_RANGE("CH1 Mixer Volume", - TAS5717_CH1_LEFT_CH_MIX_REG, - TAS5717_CH1_RIGHT_CH_MIX_REG, - 16, 0, 0x80, 0), - - SOC_DOUBLE_R_RANGE("CH2 Mixer Volume", - TAS5717_CH2_LEFT_CH_MIX_REG, - TAS5717_CH2_RIGHT_CH_MIX_REG, - 16, 0, 0x80, 0), }; static const struct regmap_range tas571x_readonly_regs_range[] = { @@ -488,6 +467,16 @@ static const struct snd_kcontrol_new tas5717_controls[] = { TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 1, 1), + SOC_DOUBLE_R_RANGE("CH1 Mixer Volume", + TAS5717_CH1_LEFT_CH_MIX_REG, + TAS5717_CH1_RIGHT_CH_MIX_REG, + 16, 0, 0x80, 0), + + SOC_DOUBLE_R_RANGE("CH2 Mixer Volume", + TAS5717_CH2_LEFT_CH_MIX_REG, + TAS5717_CH2_RIGHT_CH_MIX_REG, + 16, 0, 0x80, 0), + /* * The biquads are named according to the register names. * Please note that TI's TAS57xx Graphical Development Environment @@ -747,13 +736,14 @@ static int tas571x_i2c_probe(struct i2c_client *client, /* pulse the active low reset line for ~100us */ usleep_range(100, 200); gpiod_set_value(priv->reset_gpio, 0); - usleep_range(12000, 20000); + usleep_range(13500, 20000); } ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0); if (ret) return ret; + usleep_range(50000, 60000); memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); priv->codec_driver.component_driver.controls = priv->chip->controls; @@ -770,9 +760,6 @@ static int tas571x_i2c_probe(struct i2c_client *client, return ret; } - regcache_cache_only(priv->regmap, true); - gpiod_set_value(priv->pdn_gpio, 1); - return snd_soc_register_codec(&client->dev, &priv->codec_driver, &tas571x_dai, 1); } diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 26eb5a0a5575..fd5d1e091038 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -47,6 +47,7 @@ config SND_SOC_INTEL_SST_MATCH config SND_SOC_INTEL_HASWELL tristate + select SND_SOC_INTEL_SST_FIRMWARE config SND_SOC_INTEL_BAYTRAIL tristate @@ -56,7 +57,6 @@ config SND_SOC_INTEL_HASWELL_MACH depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM depends on DW_DMAC_CORE select SND_SOC_INTEL_SST - select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_HASWELL select SND_SOC_RT5640 help @@ -138,7 +138,6 @@ config SND_SOC_INTEL_BROADWELL_MACH I2C_DESIGNWARE_PLATFORM depends on DW_DMAC_CORE select SND_SOC_INTEL_SST - select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_HASWELL select SND_SOC_RT286 help diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 25c6d87c818e..f5a8050351b5 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -771,6 +771,9 @@ static int sst_soc_prepare(struct device *dev) struct sst_data *drv = dev_get_drvdata(dev); struct snd_soc_pcm_runtime *rtd; + if (!drv->soc_card) + return 0; + /* suspend all pcms first */ snd_soc_suspend(drv->soc_card->dev); snd_soc_poweroff(drv->soc_card->dev); @@ -793,6 +796,9 @@ static void sst_soc_complete(struct device *dev) struct sst_data *drv = dev_get_drvdata(dev); struct snd_soc_pcm_runtime *rtd; + if (!drv->soc_card) + return; + /* restart SSPs */ list_for_each_entry(rtd, &drv->soc_card->rtd_list, list) { struct snd_soc_dai *dai = rtd->cpu_dai; diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index ba5c0d71720a..f4d92bbc5373 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -416,6 +416,7 @@ static const struct dmi_system_id cht_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"), }, }, + { } }; @@ -451,6 +452,8 @@ static struct sst_acpi_mach sst_acpi_bytcr[] = { static struct sst_acpi_mach sst_acpi_chv[] = { {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, &chv_platform_data }, + {"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, + &chv_platform_data }, {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, &chv_platform_data }, {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 7486a0022fde..80f3a2d95737 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -220,10 +220,12 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { }; static int broadwell_suspend(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt286_mic_detect(codec, NULL); break; @@ -233,10 +235,12 @@ static int broadwell_suspend(struct snd_soc_card *card){ } static int broadwell_resume(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt286_mic_detect(codec, &broadwell_headset); break; diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 6532b8f0ab2f..865a21e557cc 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -130,8 +130,8 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) */ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, &broxton_headset, - NULL, 0); + SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, + &broxton_headset, NULL, 0); if (ret) { dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 56056ed7fcfd..16c94c45ce50 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -44,6 +44,7 @@ struct cht_acpi_card { struct cht_mc_private { struct snd_soc_jack jack; struct cht_acpi_card *acpi_card; + char codec_name[16]; }; static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) @@ -354,7 +355,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) int i; struct cht_mc_private *drv; struct snd_soc_card *card = snd_soc_cards[0].soc_card; - char codec_name[16]; struct sst_acpi_mach *mach; const char *i2c_name = NULL; int dai_index = 0; @@ -374,12 +374,12 @@ static int snd_cht_mc_probe(struct platform_device *pdev) } card->dev = &pdev->dev; mach = card->dev->platform_data; - sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id); + sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id); /* set correct codec name */ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00")) { - card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL); + card->dai_link[i].codec_name = drv->codec_name; dai_index = i; } diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index df9d254baa18..dfae9cfa0ac6 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -292,10 +292,12 @@ static struct snd_soc_dai_link cht_dailink[] = { static int cht_suspend_pre(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt5670_jack_suspend(codec); break; @@ -306,10 +308,12 @@ static int cht_suspend_pre(struct snd_soc_card *card) static int cht_resume_post(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt5670_jack_resume(codec); break; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 2989c164dafe..06fa5e85dd0e 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -674,7 +674,7 @@ static int skl_probe(struct pci_dev *pci, if (skl->nhlt == NULL) { err = -ENODEV; - goto out_free; + goto out_display_power_off; } skl_nhlt_update_topology_bin(skl); @@ -746,6 +746,9 @@ out_mach_free: skl_machine_device_unregister(skl); out_nhlt_free: skl_nhlt_free(skl->nhlt); +out_display_power_off: + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + snd_hdac_display_power(bus, false); out_free: skl->init_failed = 1; skl_free(ebus); @@ -785,8 +788,7 @@ static void skl_remove(struct pci_dev *pci) release_firmware(skl->tplg); - if (pci_dev_run_wake(pci)) - pm_runtime_get_noresume(&pci->dev); + pm_runtime_get_noresume(&pci->dev); /* codec removal, invoke bus_device_remove */ snd_hdac_ext_bus_device_remove(ebus); diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f2bf8661dd21..823b5a236d8d 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -208,7 +208,7 @@ config SND_PXA2XX_SOC_IMOTE2 config SND_MMP_SOC_BROWNSTONE tristate "SoC Audio support for Marvell Brownstone" - depends on SND_MMP_SOC && MACH_BROWNSTONE + depends on SND_MMP_SOC && MACH_BROWNSTONE && I2C select SND_MMP_SOC_SSPA select MFD_WM8994 select SND_SOC_WM8994 diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 3cde9fb977fa..eff3f9a8b685 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -586,3 +586,6 @@ int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) return 0; } EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); + +MODULE_DESCRIPTION("QTi LPASS CPU Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index e2ff538a8aa5..420d200f9a05 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -61,7 +61,44 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - int ret; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; + struct lpass_data *drvdata = + snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; + int ret, dma_ch, dir = substream->stream; + struct lpass_pcm_data *data; + + data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->i2s_port = cpu_dai->driver->id; + runtime->private_data = data; + + dma_ch = 0; + if (v->alloc_dma_channel) + dma_ch = v->alloc_dma_channel(drvdata, dir); + else + dma_ch = 0; + + if (dma_ch < 0) + return dma_ch; + + drvdata->substream[dma_ch] = substream; + + ret = regmap_write(drvdata->lpaif_map, + LPAIF_DMACTL_REG(v, dma_ch, dir), 0); + if (ret) { + dev_err(soc_runtime->dev, + "%s() error writing to rdmactl reg: %d\n", + __func__, ret); + return ret; + } + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + data->rdma_ch = dma_ch; + else + data->wrdma_ch = dma_ch; snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); @@ -80,13 +117,40 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) return 0; } +static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_data *drvdata = + snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; + struct lpass_pcm_data *data; + int dma_ch, dir = substream->stream; + + data = runtime->private_data; + v = drvdata->variant; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + dma_ch = data->rdma_ch; + else + dma_ch = data->wrdma_ch; + + drvdata->substream[dma_ch] = NULL; + + if (v->free_dma_channel) + v->free_dma_channel(drvdata, dma_ch); + + return 0; +} + static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); @@ -179,7 +243,8 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; unsigned int reg; int ret; @@ -203,7 +268,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -257,7 +323,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -333,7 +400,8 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_pcm_data *pcm_data = drvdata->private_data; + struct snd_pcm_runtime *rt = substream->runtime; + struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; unsigned int base_addr, curr_addr; int ret, ch, dir = substream->stream; @@ -374,6 +442,7 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream, static const struct snd_pcm_ops lpass_platform_pcm_ops = { .open = lpass_platform_pcmops_open, + .close = lpass_platform_pcmops_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = lpass_platform_pcmops_hw_params, .hw_free = lpass_platform_pcmops_hw_free, @@ -470,117 +539,45 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) { struct snd_pcm *pcm = soc_runtime->pcm; struct snd_pcm_substream *psubstream, *csubstream; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct lpass_data *drvdata = - snd_soc_platform_get_drvdata(soc_runtime->platform); - struct lpass_variant *v = drvdata->variant; int ret = -EINVAL; - struct lpass_pcm_data *data; size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; - data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->i2s_port = cpu_dai->driver->id; - drvdata->private_data = data; - psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; if (psubstream) { - if (v->alloc_dma_channel) - data->rdma_ch = v->alloc_dma_channel(drvdata, - SNDRV_PCM_STREAM_PLAYBACK); - - if (data->rdma_ch < 0) - return data->rdma_ch; - - drvdata->substream[data->rdma_ch] = psubstream; - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, soc_runtime->platform->dev, size, &psubstream->dma_buffer); - if (ret) - goto playback_alloc_err; - - ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, data->rdma_ch), 0); if (ret) { - dev_err(soc_runtime->dev, - "%s() error writing to rdmactl reg: %d\n", - __func__, ret); - goto capture_alloc_err; + dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); + return ret; } } csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; if (csubstream) { - if (v->alloc_dma_channel) - data->wrdma_ch = v->alloc_dma_channel(drvdata, - SNDRV_PCM_STREAM_CAPTURE); - - if (data->wrdma_ch < 0) { - ret = data->wrdma_ch; - goto capture_alloc_err; - } - - drvdata->substream[data->wrdma_ch] = csubstream; - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, soc_runtime->platform->dev, size, &csubstream->dma_buffer); - if (ret) - goto capture_alloc_err; - - ret = regmap_write(drvdata->lpaif_map, - LPAIF_WRDMACTL_REG(v, data->wrdma_ch), 0); if (ret) { - dev_err(soc_runtime->dev, - "%s() error writing to wrdmactl reg: %d\n", - __func__, ret); - goto capture_reg_err; + dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); + if (psubstream) + snd_dma_free_pages(&psubstream->dma_buffer); + return ret; } + } return 0; - -capture_reg_err: - if (csubstream) - snd_dma_free_pages(&csubstream->dma_buffer); - -capture_alloc_err: - if (psubstream) - snd_dma_free_pages(&psubstream->dma_buffer); - - playback_alloc_err: - dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); - - return ret; } static void lpass_platform_pcm_free(struct snd_pcm *pcm) { - struct snd_soc_pcm_runtime *rt; - struct lpass_data *drvdata; - struct lpass_pcm_data *data; - struct lpass_variant *v; struct snd_pcm_substream *substream; - int ch, i; + int i; for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { substream = pcm->streams[i].substream; if (substream) { - rt = substream->private_data; - drvdata = snd_soc_platform_get_drvdata(rt->platform); - data = drvdata->private_data; - - ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ? data->rdma_ch - : data->wrdma_ch; - v = drvdata->variant; - drvdata->substream[ch] = NULL; - if (v->free_dma_channel) - v->free_dma_channel(drvdata, ch); - snd_dma_free_pages(&substream->dma_buffer); substream->dma_buffer.area = NULL; substream->dma_buffer.addr = 0; diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 35b3cea8207d..924971b6ded5 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -59,7 +59,6 @@ struct lpass_data { struct clk *pcnoc_mport_clk; struct clk *pcnoc_sway_clk; - void *private_data; }; /* Vairant data per each SOC */ diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 97d6700b1009..cbc0023c2bc8 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -383,11 +383,6 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err4; } - ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, - s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); - if (ret) - goto err5; - ret = samsung_asoc_dma_platform_register(&pdev->dev, ac97_pdata->dma_filter, NULL, NULL); @@ -396,6 +391,11 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err5; } + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, + s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); + if (ret) + goto err5; + return 0; err5: free_irq(irq_res->start, NULL); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 7e32cf4581f8..7825bff45ae3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1237,14 +1237,14 @@ static int samsung_i2s_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unable to get drvdata\n"); return -EFAULT; } - ret = devm_snd_soc_register_component(&sec_dai->pdev->dev, - &samsung_i2s_component, - &sec_dai->i2s_dai_drv, 1); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + sec_dai->filter, "tx-sec", NULL); if (ret != 0) return ret; - return samsung_asoc_dma_platform_register(&pdev->dev, - sec_dai->filter, "tx-sec", NULL); + return devm_snd_soc_register_component(&sec_dai->pdev->dev, + &samsung_i2s_component, + &sec_dai->i2s_dai_drv, 1); } pri_dai = i2s_alloc_dai(pdev, false); @@ -1314,6 +1314,11 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (quirks & QUIRK_PRI_6CHAN) pri_dai->i2s_dai_drv.playback.channels_max = 6; + ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, + NULL, NULL); + if (ret < 0) + goto err_disable_clk; + if (quirks & QUIRK_SEC_DAI) { sec_dai = i2s_alloc_dai(pdev, true); if (!sec_dai) { @@ -1353,10 +1358,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (ret < 0) goto err_free_dai; - ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, - NULL, NULL); - if (ret < 0) - goto err_free_dai; pm_runtime_enable(&pdev->dev); diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 43e367a9acc3..c484985812ed 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -565,24 +565,25 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id]; pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id]; + ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, + NULL, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); + goto err5; + } + pm_runtime_enable(&pdev->dev); ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component, &s3c_pcm_dai[pdev->id], 1); if (ret != 0) { dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); - goto err5; - } - - ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err5; + goto err6; } return 0; - +err6: + pm_runtime_disable(&pdev->dev); err5: clk_disable_unprepare(pcm->pclk); err4: diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 3e89fbc0c51d..0a4718207e6e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -168,19 +168,19 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) s3c2412_i2s_pcm_stereo_in.addr = res->start + S3C2412_IISRXD; s3c2412_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; - ret = s3c_i2sv2_register_component(&pdev->dev, -1, - &s3c2412_i2s_component, - &s3c2412_i2s_dai); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + pdata->dma_filter, + NULL, NULL); if (ret) { - pr_err("failed to register the dai\n"); + pr_err("failed to register the DMA: %d\n", ret); return ret; } - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, - NULL, NULL); + ret = s3c_i2sv2_register_component(&pdev->dev, -1, + &s3c2412_i2s_component, + &s3c2412_i2s_dai); if (ret) - pr_err("failed to register the DMA: %d\n", ret); + pr_err("failed to register the dai\n"); return ret; } diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index c78a936a3099..9052f6a7073e 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -474,18 +474,18 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; - ret = devm_snd_soc_register_component(&pdev->dev, - &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); + ret = samsung_asoc_dma_platform_register(&pdev->dev, + pdata->dma_filter, + NULL, NULL); if (ret) { - pr_err("failed to register the dai\n"); + pr_err("failed to register the dma: %d\n", ret); return ret; } - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, - NULL, NULL); + ret = devm_snd_soc_register_component(&pdev->dev, + &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); if (ret) - pr_err("failed to register the dma: %d\n", ret); + pr_err("failed to register the dai\n"); return ret; } diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 26c1fbed4d35..779504f54bc0 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -416,15 +416,6 @@ static int spdif_probe(struct platform_device *pdev) goto err3; } - dev_set_drvdata(&pdev->dev, spdif); - - ret = devm_snd_soc_register_component(&pdev->dev, - &samsung_spdif_component, &samsung_spdif_dai, 1); - if (ret != 0) { - dev_err(&pdev->dev, "fail to register dai\n"); - goto err4; - } - spdif_stereo_out.addr_width = 2; spdif_stereo_out.addr = mem_res->start + DATA_OUTBUF; filter = NULL; @@ -432,7 +423,6 @@ static int spdif_probe(struct platform_device *pdev) spdif_stereo_out.filter_data = spdif_pdata->dma_playback; filter = spdif_pdata->dma_filter; } - spdif->dma_playback = &spdif_stereo_out; ret = samsung_asoc_dma_platform_register(&pdev->dev, filter, @@ -442,6 +432,15 @@ static int spdif_probe(struct platform_device *pdev) goto err4; } + dev_set_drvdata(&pdev->dev, spdif); + + ret = devm_snd_soc_register_component(&pdev->dev, + &samsung_spdif_component, &samsung_spdif_dai, 1); + if (ret != 0) { + dev_err(&pdev->dev, "fail to register dai\n"); + goto err4; + } + return 0; err4: iounmap(spdif->regs); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c0bbcd903261..7c3bf160a1a1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -626,7 +626,7 @@ static void codec2codec_close_delayed_work(struct work_struct *work) int snd_soc_suspend(struct device *dev) { struct snd_soc_card *card = dev_get_drvdata(dev); - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_pcm_runtime *rtd; int i; @@ -702,39 +702,39 @@ int snd_soc_suspend(struct device *dev) dapm_mark_endpoints_dirty(card); snd_soc_dapm_sync(&card->dapm); - /* suspend all CODECs */ - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + /* suspend all COMPONENTs */ + list_for_each_entry(component, &card->component_dev_list, card_list) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - /* If there are paths active then the CODEC will be held with + /* If there are paths active then the COMPONENT will be held with * bias _ON and should not be suspended. */ - if (!codec->suspended) { + if (!component->suspended) { switch (snd_soc_dapm_get_bias_level(dapm)) { case SND_SOC_BIAS_STANDBY: /* - * If the CODEC is capable of idle + * If the COMPONENT is capable of idle * bias off then being in STANDBY * means it's doing something, * otherwise fall through. */ if (dapm->idle_bias_off) { - dev_dbg(codec->dev, + dev_dbg(component->dev, "ASoC: idle_bias_off CODEC on over suspend\n"); break; } case SND_SOC_BIAS_OFF: - if (codec->driver->suspend) - codec->driver->suspend(codec); - codec->suspended = 1; - if (codec->component.regmap) - regcache_mark_dirty(codec->component.regmap); + if (component->suspend) + component->suspend(component); + component->suspended = 1; + if (component->regmap) + regcache_mark_dirty(component->regmap); /* deactivate pins to sleep state */ - pinctrl_pm_select_sleep_state(codec->dev); + pinctrl_pm_select_sleep_state(component->dev); break; default: - dev_dbg(codec->dev, - "ASoC: CODEC is on over suspend\n"); + dev_dbg(component->dev, + "ASoC: COMPONENT is on over suspend\n"); break; } } @@ -768,7 +768,7 @@ static void soc_resume_deferred(struct work_struct *work) struct snd_soc_card *card = container_of(work, struct snd_soc_card, deferred_resume_work); struct snd_soc_pcm_runtime *rtd; - struct snd_soc_codec *codec; + struct snd_soc_component *component; int i; /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, @@ -794,11 +794,11 @@ static void soc_resume_deferred(struct work_struct *work) cpu_dai->driver->resume(cpu_dai); } - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (codec->suspended) { - if (codec->driver->resume) - codec->driver->resume(codec); - codec->suspended = 0; + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (component->suspended) { + if (component->resume) + component->resume(component); + component->suspended = 0; } } @@ -993,6 +993,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link_component cpu_dai_component; struct snd_soc_dai **codec_dais; struct snd_soc_platform *platform; + struct device_node *platform_of_node; const char *platform_name; int i; @@ -1042,9 +1043,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, /* find one from the set of registered platforms */ list_for_each_entry(platform, &platform_list, list) { + platform_of_node = platform->dev->of_node; + if (!platform_of_node && platform->dev->parent->of_node) + platform_of_node = platform->dev->parent->of_node; + if (dai_link->platform_of_node) { - if (platform->dev->of_node != - dai_link->platform_of_node) + if (platform_of_node != dai_link->platform_of_node) continue; } else { if (strcmp(platform->component.name, platform_name)) @@ -1072,9 +1076,7 @@ static void soc_remove_component(struct snd_soc_component *component) if (!component->card) return; - /* This is a HACK and will be removed soon */ - if (component->codec) - list_del(&component->codec->card_list); + list_del(&component->card_list); if (component->remove) component->remove(component); @@ -1443,10 +1445,7 @@ static int soc_probe_component(struct snd_soc_card *card, component->num_dapm_routes); list_add(&dapm->list, &card->dapm_list); - - /* This is a HACK and will be removed soon */ - if (component->codec) - list_add(&component->codec->card_list, &card->codec_dev_list); + list_add(&component->card_list, &card->component_dev_list); return 0; @@ -1706,7 +1705,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) } component->init = aux_dev->init; - list_add(&component->list_aux, &card->aux_comp_list); + component->auxiliary = 1; + return 0; err_defer: @@ -1722,7 +1722,10 @@ static int soc_probe_aux_devices(struct snd_soc_card *card) for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { - list_for_each_entry(comp, &card->aux_comp_list, list_aux) { + list_for_each_entry(comp, &card->component_dev_list, card_list) { + if (!comp->auxiliary) + continue; + if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { @@ -1746,11 +1749,14 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry_safe(comp, _comp, - &card->aux_comp_list, list_aux) { + &card->component_dev_list, card_list) { + + if (!comp->auxiliary) + continue; + if (comp->driver->remove_order == order) { soc_remove_component(comp); - /* remove it from the card's aux_comp_list */ - list_del(&comp->list_aux); + comp->auxiliary = 0; } } } @@ -2926,6 +2932,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->driver = driver; component->probe = component->driver->probe; component->remove = component->driver->remove; + component->suspend = component->driver->suspend; + component->resume = component->driver->resume; dapm = &component->dapm; dapm->dev = dev; @@ -3275,6 +3283,20 @@ static void snd_soc_codec_drv_remove(struct snd_soc_component *component) codec->driver->remove(codec); } +static int snd_soc_codec_drv_suspend(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->suspend(codec); +} + +static int snd_soc_codec_drv_resume(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->resume(codec); +} + static int snd_soc_codec_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val) { @@ -3336,6 +3358,10 @@ int snd_soc_register_codec(struct device *dev, codec->component.probe = snd_soc_codec_drv_probe; if (codec_drv->remove) codec->component.remove = snd_soc_codec_drv_remove; + if (codec_drv->suspend) + codec->component.suspend = snd_soc_codec_drv_suspend; + if (codec_drv->resume) + codec->component.resume = snd_soc_codec_drv_resume; if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read) diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 1bc8ebc2528e..ad54d4cf58ad 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -614,7 +614,11 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, iec958->status[3] = ucontrol->value.iec958.status[3]; mutex_unlock(&player->ctrl_lock); - uni_player_set_channel_status(player, NULL); + if (player->substream && player->substream->runtime) + uni_player_set_channel_status(player, + player->substream->runtime); + else + uni_player_set_channel_status(player, NULL); return 0; } diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index e047ec06d538..56ed9472e89f 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -765,11 +765,11 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev) card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) - return NULL; + return ERR_PTR(-ENOMEM); card->dai_link = sun4i_codec_create_link(dev, &card->num_links); if (!card->dai_link) - return NULL; + return ERR_PTR(-ENOMEM); card->dev = dev; card->name = "sun4i-codec"; @@ -829,12 +829,6 @@ static int sun4i_codec_probe(struct platform_device *pdev) return PTR_ERR(scodec->clk_module); } - /* Enable the bus clock */ - if (clk_prepare_enable(scodec->clk_apb)) { - dev_err(&pdev->dev, "Failed to enable the APB clock\n"); - return -EINVAL; - } - scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa", GPIOD_OUT_LOW); if (IS_ERR(scodec->gpio_pa)) { @@ -844,6 +838,12 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + /* Enable the bus clock */ + if (clk_prepare_enable(scodec->clk_apb)) { + dev_err(&pdev->dev, "Failed to enable the APB clock\n"); + return -EINVAL; + } + /* DMA configuration for TX FIFO */ scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA; scodec->playback_dma_data.maxburst = 4; @@ -876,7 +876,8 @@ static int sun4i_codec_probe(struct platform_device *pdev) } card = sun4i_codec_create_card(&pdev->dev); - if (!card) { + if (IS_ERR(card)) { + ret = PTR_ERR(card); dev_err(&pdev->dev, "Failed to create our card\n"); goto err_unregister_codec; } |