Commit 343b529a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "Here is a collection of fixes for 5.9. All look small and are nothing
  scary.

  The majority of changes are about ASoC driver- specific fixes, while
  there are a couple of ASoC core fixes (DAI lookup and lockdep stuff)
  and usual HD-audio quirks"

* tag 'sound-5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (23 commits)
  ALSA: hda/realtek - The Mic on a RedmiBook doesn't work
  ASoC: tlv320adcx140: Wake up codec before accessing register
  ASoC: core: Do not cleanup uninitialized dais on soc_pcm_open failure
  ALSA: hda: fixup headset for ASUS GX502 laptop
  ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN Converter9 2-in-1
  ASoC: Intel: haswell: Fix power transition refactor
  ASoC: tlv320adcx140: Fix accessing uninitialized adcx140->dev
  ASoC: wm8994: Ensure the device is resumed in wm89xx_mic_detect functions
  ASoC: wm8994: Skip setting of the WM8994_MICBIAS register for WM1811
  ASoC: meson: axg-toddr: fix channel order on g12 platforms
  ASoC: soc-core: add snd_soc_find_dai_with_mutex()
  ASoC: qcom: common: Fix refcount imbalance on error
  ASoC: rt700: Fix return check for devm_regmap_init_sdw()
  ASoC: rt715: Fix return check for devm_regmap_init_sdw()
  ASoC: rt711: Fix return check for devm_regmap_init_sdw()
  ASoC: rt1308-sdw: Fix return check for devm_regmap_init_sdw()
  ASoC: max98373: Fix return check for devm_regmap_init_sdw()
  ASoC: ti: fixup ams_delta_mute() function name
  ASoC: pcm3168a: ignore 0 Hz settings
  ASoC: Intel: tgl_max98373: fix a runtime pm issue in multi-thread case
  ...
parents 1fd79656 8949b666
......@@ -1193,6 +1193,8 @@ struct snd_soc_pcm_runtime {
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
((dai) = (rtd)->dais[i]); \
(i)++)
#define for_each_rtd_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = (rtd)->dais[i]);)
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
......@@ -1361,6 +1363,8 @@ void snd_soc_unregister_dai(struct snd_soc_dai *dai);
struct snd_soc_dai *snd_soc_find_dai(
const struct snd_soc_dai_link_component *dlc);
struct snd_soc_dai *snd_soc_find_dai_with_mutex(
const struct snd_soc_dai_link_component *dlc);
#include <sound/soc-dai.h>
......
......@@ -5993,6 +5993,40 @@ static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
}
static void alc294_gx502_toggle_output(struct hda_codec *codec,
struct hda_jack_callback *cb)
{
/* The Windows driver sets the codec up in a very different way where
* it appears to leave 0x10 = 0x8a20 set. For Linux we need to toggle it
*/
if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
alc_write_coef_idx(codec, 0x10, 0x8a20);
else
alc_write_coef_idx(codec, 0x10, 0x0a20);
}
static void alc294_fixup_gx502_hp(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
/* Pin 0x21: headphones/headset mic */
if (!is_jack_detectable(codec, 0x21))
return;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_jack_detect_enable_callback(codec, 0x21,
alc294_gx502_toggle_output);
break;
case HDA_FIXUP_ACT_INIT:
/* Make sure to start in a correct state, i.e. if
* headphones have been plugged in before powering up the system
*/
alc294_gx502_toggle_output(codec, NULL);
break;
}
}
static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
......@@ -6173,6 +6207,9 @@ enum {
ALC285_FIXUP_THINKPAD_HEADSET_JACK,
ALC294_FIXUP_ASUS_HPE,
ALC294_FIXUP_ASUS_COEF_1B,
ALC294_FIXUP_ASUS_GX502_HP,
ALC294_FIXUP_ASUS_GX502_PINS,
ALC294_FIXUP_ASUS_GX502_VERBS,
ALC285_FIXUP_HP_GPIO_LED,
ALC285_FIXUP_HP_MUTE_LED,
ALC236_FIXUP_HP_MUTE_LED,
......@@ -6191,6 +6228,7 @@ enum {
ALC269_FIXUP_LEMOTE_A1802,
ALC269_FIXUP_LEMOTE_A190X,
ALC256_FIXUP_INTEL_NUC8_RUGGED,
ALC255_FIXUP_XIAOMI_HEADSET_MIC,
};
static const struct hda_fixup alc269_fixups[] = {
......@@ -7338,6 +7376,33 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
},
[ALC294_FIXUP_ASUS_GX502_PINS] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, 0x03a11050 }, /* front HP mic */
{ 0x1a, 0x01a11830 }, /* rear external mic */
{ 0x21, 0x03211020 }, /* front HP out */
{ }
},
.chained = true,
.chain_id = ALC294_FIXUP_ASUS_GX502_VERBS
},
[ALC294_FIXUP_ASUS_GX502_VERBS] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* set 0x15 to HP-OUT ctrl */
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* unmute the 0x15 amp */
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
{ }
},
.chained = true,
.chain_id = ALC294_FIXUP_ASUS_GX502_HP
},
[ALC294_FIXUP_ASUS_GX502_HP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc294_fixup_gx502_hp,
},
[ALC294_FIXUP_ASUS_COEF_1B] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
......@@ -7527,6 +7592,16 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE
},
[ALC255_FIXUP_XIAOMI_HEADSET_MIC] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
{ }
},
.chained = true,
.chain_id = ALC289_FIXUP_ASUS_GA401
},
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
......@@ -7711,6 +7786,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
......@@ -7823,6 +7899,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
......@@ -8000,6 +8077,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
{.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
{.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
{}
};
#define ALC225_STANDARD_PINS \
......
......@@ -838,8 +838,8 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap);
if (!regmap)
return -EINVAL;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return max98373_init(slave, regmap);
}
......
......@@ -306,6 +306,13 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
int ret;
/*
* Some sound card sets 0 Hz as reset,
* but it is impossible to set. Ignore it here
*/
if (freq == 0)
return 0;
if (freq > PCM3168A_MAX_SYSCLK)
return -EINVAL;
......
......@@ -684,8 +684,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap);
if (!regmap)
return -EINVAL;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
rt1308_sdw_init(&slave->dev, regmap, slave);
......
......@@ -452,8 +452,8 @@ static int rt700_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt700_regmap);
......
......@@ -452,8 +452,8 @@ static int rt711_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt711_regmap);
......
......@@ -527,8 +527,8 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL, &slave->dev,
&rt715_regmap);
......
......@@ -842,6 +842,18 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret)
goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
pdm_count = device_property_count_u32(adcx140->dev,
"ti,pdm-edge-select");
if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) {
......@@ -889,18 +901,6 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret)
goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
ADCX140_MIC_BIAS_VAL_MSK |
ADCX140_MIC_BIAS_VREF_MSK, bias_cfg);
......@@ -980,6 +980,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
if (!adcx140)
return -ENOMEM;
adcx140->dev = &i2c->dev;
adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
"reset", GPIOD_OUT_LOW);
if (IS_ERR(adcx140->gpio_reset))
......@@ -1007,7 +1009,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
ret);
return ret;
}
adcx140->dev = &i2c->dev;
i2c_set_clientdata(i2c, adcx140);
return devm_snd_soc_register_component(&i2c->dev,
......
......@@ -3514,6 +3514,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL;
}
pm_runtime_get_sync(component->dev);
switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
......@@ -3561,6 +3563,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm);
pm_runtime_put(component->dev);
return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
......@@ -3932,6 +3936,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL;
}
pm_runtime_get_sync(component->dev);
if (jack) {
snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS");
snd_soc_dapm_sync(dapm);
......@@ -4000,6 +4006,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm);
}
pm_runtime_put(component->dev);
return 0;
}
EXPORT_SYMBOL_GPL(wm8958_mic_detect);
......@@ -4193,11 +4201,13 @@ static int wm8994_component_probe(struct snd_soc_component *component)
wm8994->hubs.dcs_readback_mode = 2;
break;
}
wm8994->hubs.micd_scthr = true;
break;
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
wm8994->hubs.hp_startup_mode = 1;
wm8994->hubs.micd_scthr = true;
switch (control->revision) {
case 0:
......
......@@ -1223,6 +1223,9 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
if (!hubs->micd_scthr)
return 0;
snd_soc_component_update_bits(component, WM8993_MICBIAS,
WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
WM8993_MICB1_LVL | WM8993_MICB2_LVL,
......
......@@ -27,6 +27,7 @@ struct wm_hubs_data {
int hp_startup_mode;
int series_startup;
int no_series_update;
bool micd_scthr;
bool no_cache_dac_hp_direct;
struct list_head dcs_cache;
......
......@@ -333,6 +333,17 @@ static int sst_media_open(struct snd_pcm_substream *substream,
if (ret_val < 0)
goto out_power_up;
/*
* Make sure the period to be multiple of 1ms to align the
* design of firmware. Apply same rule to buffer size to make
* sure alsa could always find a value for period size
* regardless the buffer size given by user space.
*/
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48);
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48);
/* Make sure, that the period size is always even */
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIODS, 2);
......
......@@ -591,6 +591,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{
/* MPMAN MPWIN895CL */
.matches = {
......
......@@ -181,7 +181,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
struct snd_soc_dai *dai;
for_each_card_rtds(card, rtd) {
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio"))
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))
continue;
dai = asoc_rtd_to_codec(rtd, 0);
hda_pvt = snd_soc_component_get_drvdata(dai->component);
......
......@@ -66,6 +66,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
int j;
int ret = 0;
/* set spk pin by playback only */
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
return 0;
for_each_rtd_codec_dais(rtd, j, codec_dai) {
struct snd_soc_component *component = codec_dai->component;
struct snd_soc_dapm_context *dapm =
......@@ -86,9 +90,6 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* Make sure no streams are active before disable pin */
if (snd_soc_dai_active(codec_dai) != 1)
break;
ret = snd_soc_dapm_disable_pin(dapm, pin_name);
if (!ret)
snd_soc_dapm_sync(dapm);
......
......@@ -243,92 +243,45 @@ static irqreturn_t hsw_irq(int irq, void *context)
return ret;
}
#define CSR_DEFAULT_VALUE 0x8480040E
#define ISC_DEFAULT_VALUE 0x0
#define ISD_DEFAULT_VALUE 0x0
#define IMC_DEFAULT_VALUE 0x7FFF0003
#define IMD_DEFAULT_VALUE 0x7FFF0003
#define IPCC_DEFAULT_VALUE 0x0
#define IPCD_DEFAULT_VALUE 0x0
#define CLKCTL_DEFAULT_VALUE 0x7FF
#define CSR2_DEFAULT_VALUE 0x0
#define LTR_CTRL_DEFAULT_VALUE 0x0
#define HMD_CTRL_DEFAULT_VALUE 0x0
static void hsw_set_shim_defaults(struct sst_dsp *sst)
{
sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
}
/* all clock-gating minus DCLCGE and DTCGE */
#define SST_VDRTCL2_CG_OTHER 0xB7D
static void hsw_set_dsp_D3(struct sst_dsp *sst)
{
u32 val;
u32 reg;
/* disable clock core gating */
/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE);
reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* stall, reset and set 24MHz XOSC */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST,
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST);
/* DRAM power gating all */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_ISRAMPGE_MASK |
SST_VDRTCL0_DSRAMPGE_MASK;
reg &= ~(SST_VDRTCL0_D3SRAMPGD);
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
udelay(50);
/* enable power gating and switch off DRAM & IRAM blocks */
val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
val |= SST_VDRTCL0_DSRAMPGE_MASK |
SST_VDRTCL0_ISRAMPGE_MASK;
val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
/* PLL shutdown enable */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* switch off audio PLL */
val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
val |= SST_VDRTCL2_APLLSE_MASK;
writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
/* disable MCLK */
/* disable MCLK(clkctl.smos = 0) */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, 0);
/* switch clock gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_CG_OTHER;
reg &= ~(SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* enable DTCGE separatelly */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* set shim defaults */
hsw_set_shim_defaults(sst);
/* set D3 */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg |= SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* Set D3 state, delay 50 us */
val = readl(sst->addr.pci_cfg + SST_PMCS);
val |= SST_PMCS_PS_MASK;
writel(val, sst->addr.pci_cfg + SST_PMCS);
udelay(50);
/* enable clock core gating */
/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE;
reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
udelay(50);
}
static void hsw_reset(struct sst_dsp *sst)
......@@ -346,62 +299,75 @@ static void hsw_reset(struct sst_dsp *sst)
SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
}
/* recommended CSR state for power-up */
#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
static int hsw_set_dsp_D0(struct sst_dsp *sst)
{
u32 reg;
int tries = 10;
u32 reg, fw_dump_bit;
/* disable clock core gating */
/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE);
reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* switch clock gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_CG_OTHER;
reg &= ~(SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* Disable D3PG (VDRTCTL0.D3PGD = 1) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
/* set D0 */
/* Set D0 state */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg &= ~(SST_PMCS_PS_MASK);
reg &= ~SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* DRAM power gating none */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK |
SST_VDRTCL0_DSRAMPGE_MASK);
reg |= SST_VDRTCL0_D3SRAMPGD;
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
mdelay(10);
/* check that ADSP shim is enabled */
while (tries--) {
reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
if (reg == 0)
goto finish;
msleep(1);
}
/* set shim defaults */
hsw_set_shim_defaults(sst);
return -ENODEV;
/* restore MCLK */
finish:
/* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
/* stall DSP core, set clk to 192/96Mhz */
sst_dsp_shim_update_bits_unlocked(sst,
SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
SST_CSR_STALL | SST_CSR_DCS(4));
/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, SST_CLKCTL_MASK);
SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
/* Stall and reset core, set CSR */
hsw_reset(sst);
/* PLL shutdown disable */
/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_APLLSE_MASK);
reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
SST_CSR_STALL | SST_CSR_DCS(4));
udelay(50);
/* enable clock core gating */
/* switch on audio PLL */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE;
reg &= ~SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* clear reset */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0);
/* set default power gating control, enable power gating control for all blocks. that is,
can't be accessed, please enable each block before accessing. */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
/* for D0, always enable the block(DSRAM[0]) used for FW dump */
fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
/* disable DMA finish function for SSP0 & SSP1 */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
......@@ -418,6 +384,12 @@ static int hsw_set_dsp_D0(struct sst_dsp *sst)
sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
/* clear IPC registers */
sst_dsp_shim_write(sst, SST_IPCX, 0x0);
sst_dsp_shim_write(sst, SST_IPCD, 0x0);
sst_dsp_shim_write(sst, 0x80, 0x6);
sst_dsp_shim_write(sst, 0xe0, 0x300a);
return 0;
}
......@@ -443,6 +415,11 @@ static void hsw_sleep(struct sst_dsp *sst)
{
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
/* put DSP into reset and stall */
sst_dsp_shim_update_bits(sst, SST_CSR,
SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
hsw_set_dsp_D3(sst);
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
}
......
......@@ -18,6 +18,7 @@
#define CTRL0_TODDR_SEL_RESAMPLE BIT(30)
#define CTRL0_TODDR_EXT_SIGNED BIT(29)
#define CTRL0_TODDR_PP_MODE BIT(28)
#define CTRL0_TODDR_SYNC_CH BIT(27)
#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13)
#define CTRL0_TODDR_TYPE(x) ((x) << 13)
#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8)
......@@ -189,10 +190,31 @@ static const struct axg_fifo_match_data axg_toddr_match_data = {
.dai_drv = &axg_toddr_dai_drv
};
static int g12a_toddr_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
int ret;
ret = axg_toddr_dai_startup(substream, dai);
if (ret)
return ret;
/*
* Make sure the first channel ends up in the at beginning of the output
* As weird as it looks, without this the first channel may be misplaced
* in memory, with a random shift of 2 channels.
*/
regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SYNC_CH,
CTRL0_TODDR_SYNC_CH);
return 0;
}
static const struct snd_soc_dai_ops g12a_toddr_ops = {
.prepare = g12a_toddr_dai_prepare,
.hw_params = axg_toddr_dai_hw_params,
.startup = axg_toddr_dai_startup,
.startup = g12a_toddr_dai_startup,
.shutdown = axg_toddr_dai_shutdown,
};
......
......@@ -143,6 +143,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev)
card = &data->card;
card->dev = dev;
card->owner = THIS_MODULE;
card->dapm_widgets = apq8016_sbc_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets);
......
......@@ -114,6 +114,7 @@ static int apq8096_platform_probe(struct platform_device *pdev)
return -ENOMEM;
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card);
if (ret)
......
......@@ -52,8 +52,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
for_each_child_of_node(dev->of_node, np) {
dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
if (!dlc)
return -ENOMEM;
if (!dlc) {
ret = -ENOMEM;
goto err;
}
link->cpus = &dlc[0];
link->platforms = &dlc[1];
......
......@@ -555,6 +555,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
card->dapm_widgets = sdm845_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card);
if (ret)
......
......@@ -96,6 +96,7 @@ static int storm_platform_probe(struct platform_device *pdev)
return -ENOMEM;
card->dev = &pdev->dev;
card->owner = THIS_MODULE;
ret = snd_soc_of_parse_card_name(card, "qcom,model");
if (ret) {
......
......@@ -834,6 +834,19 @@ struct snd_soc_dai *snd_soc_find_dai(
}
EXPORT_SYMBOL_GPL(snd_soc_find_dai);
struct snd_soc_dai *snd_soc_find_dai_with_mutex(
const struct snd_soc_dai_link_component *dlc)
{
struct snd_soc_dai *dai;
mutex_lock(&client_mutex);
dai = snd_soc_find_dai(dlc);
mutex_unlock(&client_mutex);
return dai;
}
EXPORT_SYMBOL_GPL(snd_soc_find_dai_with_mutex);
static int soc_dai_link_sanity_check(struct snd_soc_card *card,
struct snd_soc_dai_link *link)
{
......
......@@ -412,14 +412,14 @@ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
supported_codec = false;
for_each_link_cpus(dai_link, i, cpu) {
dai = snd_soc_find_dai(cpu);
dai = snd_soc_find_dai_with_mutex(cpu);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_cpu = true;
break;
}
}
for_each_link_codecs(dai_link, i, codec) {
dai = snd_soc_find_dai(codec);
dai = snd_soc_find_dai_with_mutex(codec);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_codec = true;
break;
......
......@@ -812,7 +812,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
return 0;
config_err:
for_each_rtd_dais(rtd, i, dai)
for_each_rtd_dais_rollback(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream);
snd_soc_link_shutdown(substream);
......
......@@ -446,12 +446,12 @@ static const struct snd_soc_dai_ops ams_delta_dai_ops = {
/* Will be used if the codec ever has its own digital_mute function */
static int ams_delta_startup(struct snd_pcm_substream *substream)
{
return ams_delta_digital_mute(NULL, 0, substream->stream);
return ams_delta_mute(NULL, 0, substream->stream);
}
static void ams_delta_shutdown(struct snd_pcm_substream *substream)
{
ams_delta_digital_mute(NULL, 1, substream->stream);
ams_delta_mute(NULL, 1, substream->stream);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment