Commit 5b46fb03 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull sound fixes from Takashi Iwai:
 "Another collection of small fixes. It's still not quite calm yet, but
  nothing looks scary.

  ALSA core got a few fixes for covering the issues detected by fuzzer
  and the 32bit compat problem of control API, while the rest are all
  device-specific small fixes, including the continued fixes for Tegra"

* tag 'sound-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (23 commits)
  ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 platform
  ALSA: usb-audio: Reorder snd_djm_devices[] entries
  ALSA: hda/realtek: Fix quirk for TongFang PHxTxX1
  ALSA: ctl: Fix copy of updated id with element read/write
  ALSA: pcm: oss: Handle missing errors in snd_pcm_oss_change_params*()
  ALSA: pcm: oss: Limit the period size to 16MB
  ALSA: pcm: oss: Fix negative period/buffer sizes
  ASoC: codecs: wsa881x: fix return values from kcontrol put
  ASoC: codecs: wcd934x: return correct value from mixer put
  ASoC: codecs: wcd934x: handle channel mappping list correctly
  ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer
  ASoC: SOF: Intel: Retry codec probing if it fails
  ASoC: amd: fix uninitialized variable in snd_acp6x_probe()
  ASoC: rockchip: i2s_tdm: Dup static DAI template
  ASoC: rt5682s: Fix crash due to out of scope stack vars
  ASoC: rt5682: Fix crash due to out of scope stack vars
  ASoC: tegra: Use normal system sleep for ADX
  ASoC: tegra: Use normal system sleep for AMX
  ASoC: tegra: Use normal system sleep for Mixer
  ASoC: tegra: Use normal system sleep for MVC
  ...
parents 9b302ffe d7f32791
......@@ -19,6 +19,9 @@ properties:
clocks:
maxItems: 1
interrupts:
maxItems: 1
"#sound-dai-cells":
const: 0
......
......@@ -264,6 +264,7 @@ static int copy_ctl_value_to_user(void __user *userdata,
struct snd_ctl_elem_value *data,
int type, int count)
{
struct snd_ctl_elem_value32 __user *data32 = userdata;
int i, size;
if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
......@@ -280,6 +281,8 @@ static int copy_ctl_value_to_user(void __user *userdata,
if (copy_to_user(valuep, data->value.bytes.data, size))
return -EFAULT;
}
if (copy_to_user(&data32->id, &data->id, sizeof(data32->id)))
return -EFAULT;
return 0;
}
......
......@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
*
* Return the maximum value for field PAR.
*/
static unsigned int
static int
snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
......@@ -682,18 +682,24 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *oss_params,
struct snd_pcm_hw_params *slave_params)
{
size_t s;
size_t oss_buffer_size, oss_period_size, oss_periods;
size_t min_period_size, max_period_size;
ssize_t s;
ssize_t oss_buffer_size;
ssize_t oss_period_size, oss_periods;
ssize_t min_period_size, max_period_size;
struct snd_pcm_runtime *runtime = substream->runtime;
size_t oss_frame_size;
oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
params_channels(oss_params) / 8;
oss_buffer_size = snd_pcm_hw_param_value_max(slave_params,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
NULL);
if (oss_buffer_size <= 0)
return -EINVAL;
oss_buffer_size = snd_pcm_plug_client_size(substream,
snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
if (!oss_buffer_size)
oss_buffer_size * oss_frame_size);
if (oss_buffer_size <= 0)
return -EINVAL;
oss_buffer_size = rounddown_pow_of_two(oss_buffer_size);
if (atomic_read(&substream->mmap_count)) {
......@@ -730,7 +736,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
min_period_size = snd_pcm_plug_client_size(substream,
snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
if (min_period_size) {
if (min_period_size > 0) {
min_period_size *= oss_frame_size;
min_period_size = roundup_pow_of_two(min_period_size);
if (oss_period_size < min_period_size)
......@@ -739,7 +745,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
max_period_size = snd_pcm_plug_client_size(substream,
snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
if (max_period_size) {
if (max_period_size > 0) {
max_period_size *= oss_frame_size;
max_period_size = rounddown_pow_of_two(max_period_size);
if (oss_period_size > max_period_size)
......@@ -752,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_periods = substream->oss.setup.periods;
s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags)
s = runtime->oss.maxfrags;
if (oss_periods > s)
oss_periods = s;
......@@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
err = -EINVAL;
goto failure;
}
choose_rate(substream, sparams, runtime->oss.rate);
snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL);
err = choose_rate(substream, sparams, runtime->oss.rate);
if (err < 0)
goto failure;
err = snd_pcm_hw_param_near(substream, sparams,
SNDRV_PCM_HW_PARAM_CHANNELS,
runtime->oss.channels, NULL);
if (err < 0)
goto failure;
format = snd_pcm_oss_format_from(runtime->oss.format);
......@@ -1956,7 +1969,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign
if (runtime->oss.subdivision || runtime->oss.fragshift)
return -EINVAL;
fragshift = val & 0xffff;
if (fragshift >= 31)
if (fragshift >= 25) /* should be large enough */
return -EINVAL;
runtime->oss.fragshift = fragshift;
runtime->oss.maxfrags = (val >> 16) & 0xffff;
......
......@@ -6503,22 +6503,26 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
/* for alc285_fixup_ideapad_s740_coef() */
#include "ideapad_s740_helper.c"
static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = {
WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000),
WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000),
WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089),
{}
};
static void alc256_fixup_set_coef_defaults(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
/*
* A certain other OS sets these coeffs to different values. On at least one TongFang
* barebone these settings might survive even a cold reboot. So to restore a clean slate the
* values are explicitly reset to default here. Without this, the external microphone is
* always in a plugged-in state, while the internal microphone is always in an unplugged
* state, breaking the ability to use the internal microphone.
*/
alc_write_coef_idx(codec, 0x24, 0x0000);
alc_write_coef_idx(codec, 0x26, 0x0000);
alc_write_coef_idx(codec, 0x29, 0x3000);
alc_write_coef_idx(codec, 0x37, 0xfe05);
alc_write_coef_idx(codec, 0x45, 0x5089);
* A certain other OS sets these coeffs to different values. On at least
* one TongFang barebone these settings might survive even a cold
* reboot. So to restore a clean slate the values are explicitly reset
* to default here. Without this, the external microphone is always in a
* plugged-in state, while the internal microphone is always in an
* unplugged state, breaking the ability to use the internal microphone.
*/
alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs);
}
static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = {
......@@ -6759,7 +6763,7 @@ enum {
ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC287_FIXUP_13S_GEN2_SPEAKERS,
ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS,
ALC256_FIXUP_SET_COEF_DEFAULTS,
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
ALC233_FIXUP_NO_AUDIO_JACK,
};
......@@ -8465,9 +8469,9 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE,
},
[ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = {
[ALC256_FIXUP_SET_COEF_DEFAULTS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc256_fixup_tongfang_reset_persistent_settings,
.v.func = alc256_fixup_set_coef_defaults,
},
[ALC245_FIXUP_HP_GPIO_LED] = {
.type = HDA_FIXUP_FUNC,
......@@ -8929,7 +8933,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS),
SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
......@@ -10231,6 +10235,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
}
}
static void alc897_hp_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
struct alc_spec *spec = codec->spec;
int vref;
snd_hda_gen_hp_automute(codec, jack);
vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP;
snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
vref);
}
static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.hp_automute_hook = alc897_hp_automute_hook;
}
}
static const struct coef_fw alc668_coefs[] = {
WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
......@@ -10311,6 +10336,8 @@ enum {
ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
ALC668_FIXUP_HEADSET_MIC,
ALC668_FIXUP_MIC_DET_COEF,
ALC897_FIXUP_LENOVO_HEADSET_MIC,
ALC897_FIXUP_HEADSET_MIC_PIN,
};
static const struct hda_fixup alc662_fixups[] = {
......@@ -10717,6 +10744,19 @@ static const struct hda_fixup alc662_fixups[] = {
{}
},
},
[ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc897_fixup_lenovo_headset_mic,
},
[ALC897_FIXUP_HEADSET_MIC_PIN] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1a, 0x03a11050 },
{ }
},
.chained = true,
.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
},
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
......@@ -10761,6 +10801,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
......
......@@ -146,10 +146,11 @@ static int snd_acp6x_probe(struct pci_dev *pci,
{
struct acp6x_dev_data *adata;
struct platform_device_info pdevinfo[ACP6x_DEVS];
int ret, index;
int index = 0;
int val = 0x00;
u32 addr;
unsigned int irqflags;
int ret;
irqflags = IRQF_SHARED;
/* Yellow Carp device check */
......
......@@ -2858,6 +2858,8 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) {
struct clk_init_data init = { };
struct clk_parent_data parent_data;
const struct clk_hw *parent;
dai_clk_hw = &rt5682->dai_clks_hw[i];
......@@ -2865,17 +2867,17 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
case RT5682_DAI_WCLK_IDX:
/* Make MCLK the parent of WCLK */
if (rt5682->mclk) {
init.parent_data = &(struct clk_parent_data){
parent_data = (struct clk_parent_data){
.fw_name = "mclk",
};
init.parent_data = &parent_data;
init.num_parents = 1;
}
break;
case RT5682_DAI_BCLK_IDX:
/* Make WCLK the parent of BCLK */
init.parent_hws = &(const struct clk_hw *){
&rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]
};
parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX];
init.parent_hws = &parent;
init.num_parents = 1;
break;
default:
......
......@@ -2693,6 +2693,8 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
for (i = 0; i < RT5682S_DAI_NUM_CLKS; ++i) {
struct clk_init_data init = { };
struct clk_parent_data parent_data;
const struct clk_hw *parent;
dai_clk_hw = &rt5682s->dai_clks_hw[i];
......@@ -2700,17 +2702,17 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
case RT5682S_DAI_WCLK_IDX:
/* Make MCLK the parent of WCLK */
if (rt5682s->mclk) {
init.parent_data = &(struct clk_parent_data){
parent_data = (struct clk_parent_data){
.fw_name = "mclk",
};
init.parent_data = &parent_data;
init.num_parents = 1;
}
break;
case RT5682S_DAI_BCLK_IDX:
/* Make WCLK the parent of BCLK */
init.parent_hws = &(const struct clk_hw *){
&rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX]
};
parent = &rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX];
init.parent_hws = &parent;
init.num_parents = 1;
break;
default:
......
......@@ -3256,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
int value = ucontrol->value.integer.value[0];
int sel;
if (wcd->comp_enabled[comp] == value)
return 0;
wcd->comp_enabled[comp] = value;
sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER :
WCD934X_HPH_GAIN_SRC_SEL_REGISTER;
......@@ -3279,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
case COMPANDER_8:
break;
default:
break;
return 0;
}
return 0;
return 1;
}
static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc,
......@@ -3326,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc,
return 0;
}
static int slim_rx_mux_to_dai_id(int mux)
{
int aif_id;
switch (mux) {
case 1:
aif_id = AIF1_PB;
break;
case 2:
aif_id = AIF2_PB;
break;
case 3:
aif_id = AIF3_PB;
break;
case 4:
aif_id = AIF4_PB;
break;
default:
aif_id = -1;
break;
}
return aif_id;
}
static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct snd_ctl_elem_value *ucontrol)
{
......@@ -3333,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);
struct soc_enum *e = (struct soc_enum *)kc->private_value;
struct snd_soc_dapm_update *update = NULL;
struct wcd934x_slim_ch *ch, *c;
u32 port_id = w->shift;
bool found = false;
int mux_idx;
int prev_mux_idx = wcd->rx_port_value[port_id];
int aif_id;
if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
return 0;
mux_idx = ucontrol->value.enumerated.item[0];
wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
if (mux_idx == prev_mux_idx)
return 0;
switch (wcd->rx_port_value[port_id]) {
switch(mux_idx) {
case 0:
list_del_init(&wcd->rx_chs[port_id].list);
break;
case 1:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF1_PB].slim_ch_list);
break;
case 2:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF2_PB].slim_ch_list);
break;
case 3:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF3_PB].slim_ch_list);
aif_id = slim_rx_mux_to_dai_id(prev_mux_idx);
if (aif_id < 0)
return 0;
list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) {
if (ch->port == port_id + WCD934X_RX_START) {
found = true;
list_del_init(&ch->list);
break;
}
}
if (!found)
return 0;
break;
case 4:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF4_PB].slim_ch_list);
case 1 ... 4:
aif_id = slim_rx_mux_to_dai_id(mux_idx);
if (aif_id < 0)
return 0;
if (list_empty(&wcd->rx_chs[port_id].list)) {
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[aif_id].slim_ch_list);
} else {
dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id);
return 0;
}
break;
default:
dev_err(wcd->dev, "Unknown AIF %d\n",
wcd->rx_port_value[port_id]);
dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx);
goto err;
}
wcd->rx_port_value[port_id] = mux_idx;
snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],
e, update);
return 0;
return 1;
err:
return -EINVAL;
}
......@@ -3815,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
struct soc_mixer_control *mixer =
(struct soc_mixer_control *)kc->private_value;
int enable = ucontrol->value.integer.value[0];
struct wcd934x_slim_ch *ch, *c;
int dai_id = widget->shift;
int port_id = mixer->shift;
......@@ -3822,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
if (enable == wcd->tx_port_value[port_id])
return 0;
wcd->tx_port_value[port_id] = enable;
if (enable)
list_add_tail(&wcd->tx_chs[port_id].list,
&wcd->dai[dai_id].slim_ch_list);
else
list_del_init(&wcd->tx_chs[port_id].list);
if (enable) {
if (list_empty(&wcd->tx_chs[port_id].list)) {
list_add_tail(&wcd->tx_chs[port_id].list,
&wcd->dai[dai_id].slim_ch_list);
} else {
dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id);
return 0;
}
} else {
bool found = false;
list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) {
if (ch->port == port_id) {
found = true;
list_del_init(&wcd->tx_chs[port_id].list);
break;
}
}
if (!found)
return 0;
}
wcd->tx_port_value[port_id] = enable;
snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update);
return 0;
return 1;
}
static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = {
......
......@@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc,
usleep_range(1000, 1010);
}
return 0;
return 1;
}
static int wsa881x_get_port(struct snd_kcontrol *kcontrol,
......@@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
int portidx = mixer->reg;
if (ucontrol->value.integer.value[0])
if (ucontrol->value.integer.value[0]) {
if (data->port_enable[portidx])
return 0;
data->port_enable[portidx] = true;
else
} else {
if (!data->port_enable[portidx])
return 0;
data->port_enable[portidx] = false;
}
if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */
wsa881x_boost_ctrl(comp, data->port_enable[portidx]);
return 0;
return 1;
}
static const char * const smart_boost_lvl_text[] = {
......
......@@ -498,14 +498,16 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
struct session_data *session = &data->sessions[session_id];
if (ucontrol->value.integer.value[0]) {
if (session->port_id == be_id)
return 0;
session->port_id = be_id;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update);
} else {
if (session->port_id == be_id) {
session->port_id = -1;
if (session->port_id == -1 || session->port_id != be_id)
return 0;
}
session->port_id = -1;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
}
......
......@@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev {
spinlock_t lock; /* xfer lock */
bool has_playback;
bool has_capture;
struct snd_soc_dai_driver *dai;
};
static int to_ch_num(unsigned int val)
......@@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
{},
};
static struct snd_soc_dai_driver i2s_tdm_dai = {
static const struct snd_soc_dai_driver i2s_tdm_dai = {
.probe = rockchip_i2s_tdm_dai_probe,
.playback = {
.stream_name = "Playback",
},
.capture = {
.stream_name = "Capture",
},
.ops = &rockchip_i2s_tdm_dai_ops,
};
static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
{
struct snd_soc_dai_driver *dai;
struct property *dma_names;
const char *dma_name;
u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
......@@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
i2s_tdm->has_capture = true;
}
dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai,
sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
if (i2s_tdm->has_playback) {
i2s_tdm_dai.playback.channels_min = 2;
i2s_tdm_dai.playback.channels_max = 8;
i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000;
i2s_tdm_dai.playback.formats = formats;
dai->playback.stream_name = "Playback";
dai->playback.channels_min = 2;
dai->playback.channels_max = 8;
dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
dai->playback.formats = formats;
}
if (i2s_tdm->has_capture) {
i2s_tdm_dai.capture.channels_min = 2;
i2s_tdm_dai.capture.channels_max = 8;
i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000;
i2s_tdm_dai.capture.formats = formats;
dai->capture.stream_name = "Capture";
dai->capture.channels_min = 2;
dai->capture.channels_max = 8;
dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
dai->capture.formats = formats;
}
if (i2s_tdm->clk_trcm != TRCM_TXRX)
dai->symmetric_rate = 1;
i2s_tdm->dai = dai;
return 0;
}
static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm,
......@@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
spin_lock_init(&i2s_tdm->lock);
i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data;
rockchip_i2s_tdm_init_dai(i2s_tdm);
i2s_tdm->frame_width = 64;
i2s_tdm->clk_trcm = TRCM_TXRX;
......@@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
}
i2s_tdm->clk_trcm = TRCM_RX;
}
if (i2s_tdm->clk_trcm != TRCM_TXRX)
i2s_tdm_dai.symmetric_rate = 1;
ret = rockchip_i2s_tdm_init_dai(i2s_tdm);
if (ret)
return ret;
i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
if (IS_ERR(i2s_tdm->grf))
......@@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_tdm_component,
&i2s_tdm_dai, 1);
i2s_tdm->dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n");
......
......@@ -22,6 +22,7 @@
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
#define IDISP_VID_INTEL 0x80860000
#define CODEC_PROBE_RETRIES 3
/* load the legacy HDA codec driver */
static int request_codec_module(struct hda_codec *codec)
......@@ -121,12 +122,15 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
u32 resp = -1;
int ret;
int ret, retry = 0;
do {
mutex_lock(&hbus->core.cmd_mutex);
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
snd_hdac_bus_get_response(&hbus->core, address, &resp);
mutex_unlock(&hbus->core.cmd_mutex);
} while (resp == -1 && retry++ < CODEC_PROBE_RETRIES);
mutex_lock(&hbus->core.cmd_mutex);
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
snd_hdac_bus_get_response(&hbus->core, address, &resp);
mutex_unlock(&hbus->core.cmd_mutex);
if (resp == -1)
return -EIO;
dev_dbg(sdev->dev, "HDA codec #%d probed OK: response: %x\n",
......
......@@ -514,8 +514,8 @@ static int tegra210_adx_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_adx_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
tegra210_adx_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_adx_driver = {
......
......@@ -583,8 +583,8 @@ static int tegra210_amx_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_amx_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
tegra210_amx_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_amx_driver = {
......
......@@ -666,8 +666,8 @@ static int tegra210_mixer_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_mixer_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
tegra210_mixer_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_mixer_driver = {
......
......@@ -164,7 +164,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
if (err < 0)
goto end;
return 1;
err = 1;
end:
pm_runtime_put(cmpnt->dev);
......@@ -236,7 +236,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
TEGRA210_MVC_VOLUME_SWITCH_MASK,
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
return 1;
err = 1;
end:
pm_runtime_put(cmpnt->dev);
......@@ -639,8 +639,8 @@ static int tegra210_mvc_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_mvc_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
tegra210_mvc_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_mvc_driver = {
......
......@@ -3594,8 +3594,8 @@ static int tegra210_sfc_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_sfc_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
tegra210_sfc_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_sfc_driver = {
......
......@@ -3016,11 +3016,11 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = {
static const struct snd_djm_device snd_djm_devices[] = {
SND_DJM_DEVICE(250mk2),
SND_DJM_DEVICE(750),
SND_DJM_DEVICE(750mk2),
SND_DJM_DEVICE(850),
SND_DJM_DEVICE(900nxs2)
[SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2),
[SND_DJM_750_IDX] = SND_DJM_DEVICE(750),
[SND_DJM_850_IDX] = SND_DJM_DEVICE(850),
[SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2),
[SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2),
};
......
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