sound fixes for 5.12-rc4
Majority of changes are various ASoC device/platform-specific small fixes (including a removal of stale file) while the only common change is a clk management fix in ASoC simple-card driver. The rest are usual HD-audio quirks. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmBUbqgOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+4yBAAkA6y2fNlWYsQzZeNeWNnZyRdeoi5M0Flqd0q PRK6VynM/M0kn2U/PgwhlDgrcNPqmW6AgXAPEEnv5zfwPs9MPXM3B9uJiiIOW6t1 c0EfS2msnTXx6RAn62ecYJkp6BUVnejAYIgzKiLOBj5/0mNXgnbTfC7PSnfghWca ajtq/+l3pr519C4ewJSKZ84ho3S7mEEZdBGkpvaYTVZY09mkoZj1eefuQBp8690d n/jTl+gCk8Z3834bhBKgdax2huZmTaMQ2wXsoEHZNPpHr2NfmR0RvPgnNutDA6uJ JVM4KBStTxIpgg84D0wXIOvUst4/FcPtaho5UCNqSJ1/xoom+BGV3hTXLSW1SVUT /TUZje6hCfl9WyN5lR2S2JIYorTp6yqLQscXPmolkq+vtkLbQa83MybhyTK1w78q xMLCezctc3cpFikydelWa39xMUyjd7/PkabhwWoFk50niBIVS119rhH/GqhGIusp UU6JyujhoM8JWvywoyHsgV6c+2gDLQVU9k6mrAgMf9hgjRTz2ztCgK4fWccqEGvt 5retVRVdv0xUxBxLkD9AhZ47ym8udcOLP7NyBl70MHJSm4GuEPUdefPNOGOWqIUr 0XJfCmvipxJkA4/QwC5j7du8uILMXmjqzvf/LGfhg8Yo4YtQbJSv6mPmCSrtE1JE 2yz8zTA= =kGbc -----END PGP SIGNATURE----- Merge tag 'sound-5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "The majority of changes are various ASoC device/platform-specific small fixes (including a removal of stale file) while the only common change is a clk management fix in ASoC simple-card driver. The rest are the usual HD-audio quirks" * tag 'sound-5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (44 commits) ALSA: usb-audio: Fix unintentional sign extension issue ALSA: hda/realtek: fix mute/micmute LEDs for HP 850 G8 ASoC: dt-bindings: fsl_spdif: Add compatible string for new platforms ASoC: rt711: add snd_soc_component remove callback ASoC: rt5659: Update MCLK rate in set_sysclk() ASoC: simple-card-utils: Do not handle device clock ALSA: hda/realtek: fix mute/micmute LEDs for HP 440 G8 ALSA: hda/realtek: fix mute/micmute LEDs for HP 840 G8 ALSA: hda/realtek: apply pin quirk for XiaomiNotebook Pro ALSA: hda/realtek: Apply headset-mic quirks for Xiaomi Redmibook Air ASoC: mediatek: mt8192: fix tdm out data is valid on rising edge ALSA: dice: fix null pointer dereference when node is disconnected ALSA: hda: generic: Fix the micmute led init state ASoC: qcom: lpass-cpu: Fix lpass dai ids parse spi: cadence: set cqspi to the driver_data field of struct device ASoC: SOF: intel: fix wrong poll bits in dsp power down ASoC: codecs: wcd934x: add a sanity check in set channel map ASoC: qcom: sdm845: Fix array out of range on rx slim channels ASoC: qcom: sdm845: Fix array out of bounds access ASoC: remove remnants of sirf prima/atlas audio codec ...
This commit is contained in:
commit
769e155c53
|
@ -21,6 +21,10 @@ properties:
|
|||
- fsl,vf610-spdif
|
||||
- fsl,imx6sx-spdif
|
||||
- fsl,imx8qm-spdif
|
||||
- fsl,imx8qxp-spdif
|
||||
- fsl,imx8mq-spdif
|
||||
- fsl,imx8mm-spdif
|
||||
- fsl,imx8mn-spdif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -1433,6 +1433,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
cqspi = spi_master_get_devdata(master);
|
||||
|
||||
cqspi->pdev = pdev;
|
||||
platform_set_drvdata(pdev, cqspi);
|
||||
|
||||
/* Obtain configuration from OF. */
|
||||
ret = cqspi_of_get_pdata(cqspi);
|
||||
|
|
|
@ -493,11 +493,10 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice)
|
|||
struct reg_params tx_params, rx_params;
|
||||
|
||||
if (dice->substreams_counter == 0) {
|
||||
if (get_register_params(dice, &tx_params, &rx_params) >= 0) {
|
||||
amdtp_domain_stop(&dice->domain);
|
||||
if (get_register_params(dice, &tx_params, &rx_params) >= 0)
|
||||
finish_session(dice, &tx_params, &rx_params);
|
||||
}
|
||||
|
||||
amdtp_domain_stop(&dice->domain);
|
||||
release_resources(dice);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4065,7 +4065,7 @@ static int add_micmute_led_hook(struct hda_codec *codec)
|
|||
|
||||
spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
|
||||
spec->micmute_led.capture = 0;
|
||||
spec->micmute_led.led_value = 0;
|
||||
spec->micmute_led.led_value = -1;
|
||||
spec->micmute_led.old_hook = spec->cap_sync_hook;
|
||||
spec->cap_sync_hook = update_micmute_led;
|
||||
if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
|
||||
|
|
|
@ -4225,6 +4225,12 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
static void alc236_fixup_hp_gpio_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
alc_fixup_hp_gpio_led(codec, action, 0x02, 0x01);
|
||||
}
|
||||
|
||||
static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
|
@ -6381,6 +6387,7 @@ enum {
|
|||
ALC294_FIXUP_ASUS_GX502_VERBS,
|
||||
ALC285_FIXUP_HP_GPIO_LED,
|
||||
ALC285_FIXUP_HP_MUTE_LED,
|
||||
ALC236_FIXUP_HP_GPIO_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED,
|
||||
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
||||
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
|
||||
|
@ -7616,6 +7623,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_mute_led,
|
||||
},
|
||||
[ALC236_FIXUP_HP_GPIO_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_gpio_led,
|
||||
},
|
||||
[ALC236_FIXUP_HP_MUTE_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_mute_led,
|
||||
|
@ -8045,9 +8056,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation",
|
||||
ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
|
||||
SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
|
@ -8242,7 +8256,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
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, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_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),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
|
||||
|
|
|
@ -186,7 +186,6 @@ config SND_SOC_ALL_CODECS
|
|||
imply SND_SOC_SI476X
|
||||
imply SND_SOC_SIMPLE_AMPLIFIER
|
||||
imply SND_SOC_SIMPLE_MUX
|
||||
imply SND_SOC_SIRF_AUDIO_CODEC
|
||||
imply SND_SOC_SPDIF
|
||||
imply SND_SOC_SSM2305
|
||||
imply SND_SOC_SSM2518
|
||||
|
@ -1279,10 +1278,6 @@ config SND_SOC_SIMPLE_MUX
|
|||
tristate "Simple Audio Mux"
|
||||
select GPIOLIB
|
||||
|
||||
config SND_SOC_SIRF_AUDIO_CODEC
|
||||
tristate "SiRF SoC internal audio codec"
|
||||
select REGMAP_MMIO
|
||||
|
||||
config SND_SOC_SPDIF
|
||||
tristate "S/PDIF CODEC"
|
||||
|
||||
|
|
|
@ -812,6 +812,7 @@ static const struct of_device_id ak4458_of_match[] = {
|
|||
{ .compatible = "asahi-kasei,ak4497", .data = &ak4497_drvdata},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ak4458_of_match);
|
||||
|
||||
static struct i2c_driver ak4458_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -419,6 +419,7 @@ static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = {
|
|||
{ .compatible = "asahi-kasei,ak5558"},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids);
|
||||
|
||||
static struct i2c_driver ak5558_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -401,7 +401,7 @@ static const struct regmap_config cs42l42_regmap = {
|
|||
};
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false);
|
||||
static DECLARE_TLV_DB_SCALE(mixer_tlv, -6200, 100, false);
|
||||
static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
|
||||
|
||||
static const char * const cs42l42_hpf_freq_text[] = {
|
||||
"1.86Hz", "120Hz", "235Hz", "466Hz"
|
||||
|
@ -458,7 +458,7 @@ static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
|
|||
CS42L42_DAC_HPF_EN_SHIFT, true, false),
|
||||
SOC_DOUBLE_R_TLV("Mixer Volume", CS42L42_MIXER_CHA_VOL,
|
||||
CS42L42_MIXER_CHB_VOL, CS42L42_MIXER_CH_VOL_SHIFT,
|
||||
0x3e, 1, mixer_tlv)
|
||||
0x3f, 1, mixer_tlv)
|
||||
};
|
||||
|
||||
static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w,
|
||||
|
@ -511,43 +511,6 @@ static const struct snd_soc_dapm_route cs42l42_audio_map[] = {
|
|||
{"HP", NULL, "HPDRV"}
|
||||
};
|
||||
|
||||
static int cs42l42_set_bias_level(struct snd_soc_component *component,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
|
||||
regcache_cache_only(cs42l42->regmap, false);
|
||||
regcache_sync(cs42l42->regmap);
|
||||
ret = regulator_bulk_enable(
|
||||
ARRAY_SIZE(cs42l42->supplies),
|
||||
cs42l42->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(component->dev,
|
||||
"Failed to enable regulators: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
|
||||
regcache_cache_only(cs42l42->regmap, true);
|
||||
regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
|
||||
cs42l42->supplies);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l42_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct cs42l42_private *cs42l42 =
|
||||
|
@ -560,7 +523,6 @@ static int cs42l42_component_probe(struct snd_soc_component *component)
|
|||
|
||||
static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
|
||||
.probe = cs42l42_component_probe,
|
||||
.set_bias_level = cs42l42_set_bias_level,
|
||||
.dapm_widgets = cs42l42_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets),
|
||||
.dapm_routes = cs42l42_audio_map,
|
||||
|
@ -691,24 +653,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
|
|||
CS42L42_CLK_OASRC_SEL_MASK,
|
||||
CS42L42_CLK_OASRC_SEL_12 <<
|
||||
CS42L42_CLK_OASRC_SEL_SHIFT);
|
||||
/* channel 1 on low LRCLK, 32 bit */
|
||||
snd_soc_component_update_bits(component,
|
||||
CS42L42_ASP_RX_DAI0_CH1_AP_RES,
|
||||
CS42L42_ASP_RX_CH_AP_MASK |
|
||||
CS42L42_ASP_RX_CH_RES_MASK,
|
||||
(CS42L42_ASP_RX_CH_AP_LOW <<
|
||||
CS42L42_ASP_RX_CH_AP_SHIFT) |
|
||||
(CS42L42_ASP_RX_CH_RES_32 <<
|
||||
CS42L42_ASP_RX_CH_RES_SHIFT));
|
||||
/* Channel 2 on high LRCLK, 32 bit */
|
||||
snd_soc_component_update_bits(component,
|
||||
CS42L42_ASP_RX_DAI0_CH2_AP_RES,
|
||||
CS42L42_ASP_RX_CH_AP_MASK |
|
||||
CS42L42_ASP_RX_CH_RES_MASK,
|
||||
(CS42L42_ASP_RX_CH_AP_HI <<
|
||||
CS42L42_ASP_RX_CH_AP_SHIFT) |
|
||||
(CS42L42_ASP_RX_CH_RES_32 <<
|
||||
CS42L42_ASP_RX_CH_RES_SHIFT));
|
||||
if (pll_ratio_table[i].mclk_src_sel == 0) {
|
||||
/* Pass the clock straight through */
|
||||
snd_soc_component_update_bits(component,
|
||||
|
@ -797,27 +741,23 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
|||
/* Bitclock/frame inversion */
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
asp_cfg_val |= CS42L42_ASP_POL_INV <<
|
||||
CS42L42_ASP_LCPOL_IN_SHIFT;
|
||||
asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
|
||||
asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
asp_cfg_val |= CS42L42_ASP_POL_INV <<
|
||||
CS42L42_ASP_SCPOL_IN_DAC_SHIFT;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
asp_cfg_val |= CS42L42_ASP_POL_INV <<
|
||||
CS42L42_ASP_LCPOL_IN_SHIFT;
|
||||
asp_cfg_val |= CS42L42_ASP_POL_INV <<
|
||||
CS42L42_ASP_SCPOL_IN_DAC_SHIFT;
|
||||
asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG,
|
||||
CS42L42_ASP_MODE_MASK |
|
||||
CS42L42_ASP_SCPOL_IN_DAC_MASK |
|
||||
CS42L42_ASP_LCPOL_IN_MASK, asp_cfg_val);
|
||||
snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, CS42L42_ASP_MODE_MASK |
|
||||
CS42L42_ASP_SCPOL_MASK |
|
||||
CS42L42_ASP_LCPOL_MASK,
|
||||
asp_cfg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -828,14 +768,29 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
|
||||
int retval;
|
||||
unsigned int width = (params_width(params) / 8) - 1;
|
||||
unsigned int val = 0;
|
||||
|
||||
cs42l42->srate = params_rate(params);
|
||||
cs42l42->swidth = params_width(params);
|
||||
|
||||
retval = cs42l42_pll_config(component);
|
||||
switch(substream->stream) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
val |= width << CS42L42_ASP_RX_CH_RES_SHIFT;
|
||||
/* channel 1 on low LRCLK */
|
||||
snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH1_AP_RES,
|
||||
CS42L42_ASP_RX_CH_AP_MASK |
|
||||
CS42L42_ASP_RX_CH_RES_MASK, val);
|
||||
/* Channel 2 on high LRCLK */
|
||||
val |= CS42L42_ASP_RX_CH_AP_HI << CS42L42_ASP_RX_CH_AP_SHIFT;
|
||||
snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES,
|
||||
CS42L42_ASP_RX_CH_AP_MASK |
|
||||
CS42L42_ASP_RX_CH_RES_MASK, val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return cs42l42_pll_config(component);
|
||||
}
|
||||
|
||||
static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
|
||||
|
@ -900,9 +855,9 @@ static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_LE )
|
||||
|
||||
|
||||
static const struct snd_soc_dai_ops cs42l42_ops = {
|
||||
|
@ -1801,7 +1756,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
|
|||
dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
|
||||
}
|
||||
mdelay(3);
|
||||
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
|
||||
|
||||
/* Request IRQ */
|
||||
ret = devm_request_threaded_irq(&i2c_client->dev,
|
||||
|
@ -1926,6 +1881,7 @@ static int cs42l42_runtime_resume(struct device *dev)
|
|||
}
|
||||
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
|
||||
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
|
||||
|
||||
regcache_cache_only(cs42l42->regmap, false);
|
||||
regcache_sync(cs42l42->regmap);
|
||||
|
|
|
@ -258,11 +258,12 @@
|
|||
#define CS42L42_ASP_SLAVE_MODE 0x00
|
||||
#define CS42L42_ASP_MODE_SHIFT 4
|
||||
#define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT)
|
||||
#define CS42L42_ASP_SCPOL_IN_DAC_SHIFT 2
|
||||
#define CS42L42_ASP_SCPOL_IN_DAC_MASK (1 << CS42L42_ASP_SCPOL_IN_DAC_SHIFT)
|
||||
#define CS42L42_ASP_LCPOL_IN_SHIFT 0
|
||||
#define CS42L42_ASP_LCPOL_IN_MASK (1 << CS42L42_ASP_LCPOL_IN_SHIFT)
|
||||
#define CS42L42_ASP_POL_INV 1
|
||||
#define CS42L42_ASP_SCPOL_SHIFT 2
|
||||
#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT)
|
||||
#define CS42L42_ASP_SCPOL_NOR 3
|
||||
#define CS42L42_ASP_LCPOL_SHIFT 0
|
||||
#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT)
|
||||
#define CS42L42_ASP_LCPOL_INV 3
|
||||
|
||||
#define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08)
|
||||
#define CS42L42_ASP_STP_SHIFT 4
|
||||
|
@ -739,6 +740,7 @@
|
|||
#define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16)
|
||||
|
||||
#define CS42L42_NUM_SUPPLIES 5
|
||||
#define CS42L42_BOOT_TIME_US 3000
|
||||
|
||||
static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = {
|
||||
"VA",
|
||||
|
@ -756,7 +758,6 @@ struct cs42l42_private {
|
|||
struct completion pdn_done;
|
||||
u32 sclk;
|
||||
u32 srate;
|
||||
u32 swidth;
|
||||
u8 plug_state;
|
||||
u8 hs_type;
|
||||
u8 ts_inv;
|
||||
|
|
|
@ -63,13 +63,8 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
|
|||
1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
|
||||
2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
|
||||
3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
|
||||
4, 4, TLV_DB_SCALE_ITEM(700, 0, 0),
|
||||
5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0),
|
||||
6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0),
|
||||
7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0),
|
||||
8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0),
|
||||
9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0),
|
||||
10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0),
|
||||
4, 7, TLV_DB_SCALE_ITEM(700, 300, 0),
|
||||
8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0),
|
||||
);
|
||||
|
||||
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
|
||||
|
|
|
@ -2895,7 +2895,7 @@ static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w,
|
|||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
u16 val, ec_hq_reg;
|
||||
int ec_tx;
|
||||
int ec_tx = -1;
|
||||
|
||||
val = snd_soc_component_read(component,
|
||||
CDC_RX_INP_MUX_RX_MIX_CFG4);
|
||||
|
|
|
@ -189,7 +189,6 @@ struct va_macro {
|
|||
struct device *dev;
|
||||
unsigned long active_ch_mask[VA_MACRO_MAX_DAIS];
|
||||
unsigned long active_ch_cnt[VA_MACRO_MAX_DAIS];
|
||||
unsigned long active_decimator[VA_MACRO_MAX_DAIS];
|
||||
u16 dmic_clk_div;
|
||||
|
||||
int dec_mode[VA_MACRO_NUM_DECIMATORS];
|
||||
|
@ -549,11 +548,9 @@ static int va_macro_tx_mixer_put(struct snd_kcontrol *kcontrol,
|
|||
if (enable) {
|
||||
set_bit(dec_id, &va->active_ch_mask[dai_id]);
|
||||
va->active_ch_cnt[dai_id]++;
|
||||
va->active_decimator[dai_id] = dec_id;
|
||||
} else {
|
||||
clear_bit(dec_id, &va->active_ch_mask[dai_id]);
|
||||
va->active_ch_cnt[dai_id]--;
|
||||
va->active_decimator[dai_id] = -1;
|
||||
}
|
||||
|
||||
snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
|
||||
|
@ -880,18 +877,19 @@ static int va_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
|
|||
struct va_macro *va = snd_soc_component_get_drvdata(component);
|
||||
u16 tx_vol_ctl_reg, decimator;
|
||||
|
||||
decimator = va->active_decimator[dai->id];
|
||||
|
||||
tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL +
|
||||
VA_MACRO_TX_PATH_OFFSET * decimator;
|
||||
if (mute)
|
||||
snd_soc_component_update_bits(component, tx_vol_ctl_reg,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN_MASK,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN);
|
||||
else
|
||||
snd_soc_component_update_bits(component, tx_vol_ctl_reg,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN_MASK,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_DISABLE);
|
||||
for_each_set_bit(decimator, &va->active_ch_mask[dai->id],
|
||||
VA_MACRO_DEC_MAX) {
|
||||
tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL +
|
||||
VA_MACRO_TX_PATH_OFFSET * decimator;
|
||||
if (mute)
|
||||
snd_soc_component_update_bits(component, tx_vol_ctl_reg,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN_MASK,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN);
|
||||
else
|
||||
snd_soc_component_update_bits(component, tx_vol_ctl_reg,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_EN_MASK,
|
||||
CDC_VA_TX_PATH_PGA_MUTE_DISABLE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1211,14 +1211,16 @@ static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
|
|||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
u16 gain_reg;
|
||||
u16 path_reg, gain_reg;
|
||||
int val;
|
||||
|
||||
switch (w->reg) {
|
||||
case CDC_WSA_RX0_RX_PATH_MIX_CTL:
|
||||
switch (w->shift) {
|
||||
case WSA_MACRO_RX_MIX0:
|
||||
path_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL;
|
||||
gain_reg = CDC_WSA_RX0_RX_VOL_MIX_CTL;
|
||||
break;
|
||||
case CDC_WSA_RX1_RX_PATH_MIX_CTL:
|
||||
case WSA_MACRO_RX_MIX1:
|
||||
path_reg = CDC_WSA_RX1_RX_PATH_MIX_CTL;
|
||||
gain_reg = CDC_WSA_RX1_RX_VOL_MIX_CTL;
|
||||
break;
|
||||
default:
|
||||
|
@ -1231,7 +1233,7 @@ static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
|
|||
snd_soc_component_write(component, gain_reg, val);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_component_update_bits(component, w->reg,
|
||||
snd_soc_component_update_bits(component, path_reg,
|
||||
CDC_WSA_RX_PATH_MIX_CLK_EN_MASK,
|
||||
CDC_WSA_RX_PATH_MIX_CLK_DISABLE);
|
||||
break;
|
||||
|
@ -2068,14 +2070,14 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux),
|
||||
SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux),
|
||||
SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux),
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", CDC_WSA_RX0_RX_PATH_MIX_CTL,
|
||||
0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0,
|
||||
0, &rx0_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux),
|
||||
SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux),
|
||||
SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux),
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", CDC_WSA_RX1_RX_PATH_MIX_CTL,
|
||||
0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1,
|
||||
0, &rx1_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0,
|
||||
|
|
|
@ -209,6 +209,7 @@ static bool rt1015_volatile_register(struct device *dev, unsigned int reg)
|
|||
case RT1015_VENDOR_ID:
|
||||
case RT1015_DEVICE_ID:
|
||||
case RT1015_PRO_ALT:
|
||||
case RT1015_MAN_I2C:
|
||||
case RT1015_DAC3:
|
||||
case RT1015_VBAT_TEST_OUT1:
|
||||
case RT1015_VBAT_TEST_OUT2:
|
||||
|
@ -513,6 +514,7 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015)
|
|||
msleep(300);
|
||||
regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008);
|
||||
regmap_write(regmap, RT1015_SYS_RST1, 0x05F5);
|
||||
regmap_write(regmap, RT1015_CLK_DET, 0x8000);
|
||||
|
||||
regcache_cache_bypass(regmap, false);
|
||||
regcache_mark_dirty(regmap);
|
||||
|
|
|
@ -339,9 +339,9 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg)
|
|||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
|
||||
static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
|
||||
static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
|
||||
|
||||
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
|
||||
|
|
|
@ -285,9 +285,9 @@ static bool rt5651_readable_register(struct device *dev, unsigned int reg)
|
|||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
|
||||
static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
|
||||
static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
|
||||
|
||||
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
|
||||
|
|
|
@ -3426,12 +3426,17 @@ static int rt5659_set_component_sysclk(struct snd_soc_component *component, int
|
|||
{
|
||||
struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int reg_val = 0;
|
||||
int ret;
|
||||
|
||||
if (freq == rt5659->sysclk && clk_id == rt5659->sysclk_src)
|
||||
return 0;
|
||||
|
||||
switch (clk_id) {
|
||||
case RT5659_SCLK_S_MCLK:
|
||||
ret = clk_set_rate(rt5659->mclk, freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg_val |= RT5659_SCLK_SRC_MCLK;
|
||||
break;
|
||||
case RT5659_SCLK_S_PLL1:
|
||||
|
|
|
@ -629,21 +629,69 @@ static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA,
|
|||
static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA,
|
||||
RT5670_IF2_ADC_SEL_SFT, rt5670_data_select);
|
||||
|
||||
/*
|
||||
* For reliable output-mute LED control we need a "DAC1 Playback Switch" control.
|
||||
* We emulate this by only clearing the RT5670_M_DAC1_L/_R AD_DA_MIXER register
|
||||
* bits when both our emulated DAC1 Playback Switch control and the DAC1 MIXL/R
|
||||
* DAPM-mixer DAC1 input are enabled.
|
||||
*/
|
||||
static void rt5670_update_ad_da_mixer_dac1_m_bits(struct rt5670_priv *rt5670)
|
||||
{
|
||||
int val = RT5670_M_DAC1_L | RT5670_M_DAC1_R;
|
||||
|
||||
if (rt5670->dac1_mixl_dac1_switch && rt5670->dac1_playback_switch_l)
|
||||
val &= ~RT5670_M_DAC1_L;
|
||||
|
||||
if (rt5670->dac1_mixr_dac1_switch && rt5670->dac1_playback_switch_r)
|
||||
val &= ~RT5670_M_DAC1_R;
|
||||
|
||||
regmap_update_bits(rt5670->regmap, RT5670_AD_DA_MIXER,
|
||||
RT5670_M_DAC1_L | RT5670_M_DAC1_R, val);
|
||||
}
|
||||
|
||||
static int rt5670_dac1_playback_switch_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
ucontrol->value.integer.value[0] = rt5670->dac1_playback_switch_l;
|
||||
ucontrol->value.integer.value[1] = rt5670->dac1_playback_switch_r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5670_dac1_playback_switch_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (rt5670->dac1_playback_switch_l == ucontrol->value.integer.value[0] &&
|
||||
rt5670->dac1_playback_switch_r == ucontrol->value.integer.value[1])
|
||||
return 0;
|
||||
|
||||
rt5670->dac1_playback_switch_l = ucontrol->value.integer.value[0];
|
||||
rt5670->dac1_playback_switch_r = ucontrol->value.integer.value[1];
|
||||
|
||||
rt5670_update_ad_da_mixer_dac1_m_bits(rt5670);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new rt5670_snd_controls[] = {
|
||||
/* Headphone Output Volume */
|
||||
SOC_DOUBLE("HP Playback Switch", RT5670_HP_VOL,
|
||||
RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1),
|
||||
SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL,
|
||||
RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
|
||||
39, 1, out_vol_tlv),
|
||||
/* OUTPUT Control */
|
||||
SOC_DOUBLE("OUT Channel Switch", RT5670_LOUT1,
|
||||
RT5670_VOL_L_SFT, RT5670_VOL_R_SFT, 1, 1),
|
||||
SOC_DOUBLE_TLV("OUT Playback Volume", RT5670_LOUT1,
|
||||
RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv),
|
||||
/* DAC Digital Volume */
|
||||
SOC_DOUBLE("DAC2 Playback Switch", RT5670_DAC_CTRL,
|
||||
RT5670_M_DAC_L2_VOL_SFT, RT5670_M_DAC_R2_VOL_SFT, 1, 1),
|
||||
SOC_DOUBLE_EXT("DAC1 Playback Switch", SND_SOC_NOPM, 0, 1, 1, 0,
|
||||
rt5670_dac1_playback_switch_get, rt5670_dac1_playback_switch_put),
|
||||
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5670_DAC1_DIG_VOL,
|
||||
RT5670_L_VOL_SFT, RT5670_R_VOL_SFT,
|
||||
175, 0, dac_vol_tlv),
|
||||
|
@ -913,18 +961,44 @@ static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] = {
|
|||
RT5670_M_MONO_ADC_R2_SFT, 1, 1),
|
||||
};
|
||||
|
||||
/* See comment above rt5670_update_ad_da_mixer_dac1_m_bits() */
|
||||
static int rt5670_put_dac1_mix_dac1_switch(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
|
||||
struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
if (mc->shift == 0)
|
||||
rt5670->dac1_mixl_dac1_switch = ucontrol->value.integer.value[0];
|
||||
else
|
||||
rt5670->dac1_mixr_dac1_switch = ucontrol->value.integer.value[0];
|
||||
|
||||
/* Apply the update (if any) */
|
||||
ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
rt5670_update_ad_da_mixer_dac1_m_bits(rt5670);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SOC_DAPM_SINGLE_RT5670_DAC1_SW(name, shift) \
|
||||
SOC_SINGLE_EXT(name, SND_SOC_NOPM, shift, 1, 0, \
|
||||
snd_soc_dapm_get_volsw, rt5670_put_dac1_mix_dac1_switch)
|
||||
|
||||
static const struct snd_kcontrol_new rt5670_dac_l_mix[] = {
|
||||
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER,
|
||||
RT5670_M_ADCMIX_L_SFT, 1, 1),
|
||||
SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER,
|
||||
RT5670_M_DAC1_L_SFT, 1, 1),
|
||||
SOC_DAPM_SINGLE_RT5670_DAC1_SW("DAC1 Switch", 0),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new rt5670_dac_r_mix[] = {
|
||||
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER,
|
||||
RT5670_M_ADCMIX_R_SFT, 1, 1),
|
||||
SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER,
|
||||
RT5670_M_DAC1_R_SFT, 1, 1),
|
||||
SOC_DAPM_SINGLE_RT5670_DAC1_SW("DAC1 Switch", 1),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] = {
|
||||
|
@ -1656,12 +1730,10 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = {
|
|||
RT5670_PWR_ADC_S1F_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5670_PWR_DIG2,
|
||||
RT5670_PWR_ADC_S2F_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", RT5670_STO1_ADC_DIG_VOL,
|
||||
RT5670_L_MUTE_SFT, 1, rt5670_sto1_adc_l_mix,
|
||||
ARRAY_SIZE(rt5670_sto1_adc_l_mix)),
|
||||
SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", RT5670_STO1_ADC_DIG_VOL,
|
||||
RT5670_R_MUTE_SFT, 1, rt5670_sto1_adc_r_mix,
|
||||
ARRAY_SIZE(rt5670_sto1_adc_r_mix)),
|
||||
SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0,
|
||||
rt5670_sto1_adc_l_mix, ARRAY_SIZE(rt5670_sto1_adc_l_mix)),
|
||||
SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0,
|
||||
rt5670_sto1_adc_r_mix, ARRAY_SIZE(rt5670_sto1_adc_r_mix)),
|
||||
SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0,
|
||||
rt5670_sto2_adc_l_mix,
|
||||
ARRAY_SIZE(rt5670_sto2_adc_l_mix)),
|
||||
|
@ -2999,6 +3071,16 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
|
|||
dev_info(&i2c->dev, "quirk JD mode 3\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the emulated "DAC1 Playback Switch" by default to avoid
|
||||
* muting the output with older UCM profiles.
|
||||
*/
|
||||
rt5670->dac1_playback_switch_l = true;
|
||||
rt5670->dac1_playback_switch_r = true;
|
||||
/* The Power-On-Reset values for the DAC1 mixer have the DAC1 input enabled. */
|
||||
rt5670->dac1_mixl_dac1_switch = true;
|
||||
rt5670->dac1_mixr_dac1_switch = true;
|
||||
|
||||
rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
|
||||
if (IS_ERR(rt5670->regmap)) {
|
||||
ret = PTR_ERR(rt5670->regmap);
|
||||
|
|
|
@ -212,12 +212,8 @@
|
|||
/* global definition */
|
||||
#define RT5670_L_MUTE (0x1 << 15)
|
||||
#define RT5670_L_MUTE_SFT 15
|
||||
#define RT5670_VOL_L_MUTE (0x1 << 14)
|
||||
#define RT5670_VOL_L_SFT 14
|
||||
#define RT5670_R_MUTE (0x1 << 7)
|
||||
#define RT5670_R_MUTE_SFT 7
|
||||
#define RT5670_VOL_R_MUTE (0x1 << 6)
|
||||
#define RT5670_VOL_R_SFT 6
|
||||
#define RT5670_L_VOL_MASK (0x3f << 8)
|
||||
#define RT5670_L_VOL_SFT 8
|
||||
#define RT5670_R_VOL_MASK (0x3f)
|
||||
|
@ -2017,6 +2013,11 @@ struct rt5670_priv {
|
|||
int dsp_rate;
|
||||
int jack_type;
|
||||
int jack_type_saved;
|
||||
|
||||
bool dac1_mixl_dac1_switch;
|
||||
bool dac1_mixr_dac1_switch;
|
||||
bool dac1_playback_switch_l;
|
||||
bool dac1_playback_switch_r;
|
||||
};
|
||||
|
||||
void rt5670_jack_suspend(struct snd_soc_component *component);
|
||||
|
|
|
@ -895,6 +895,13 @@ static int rt711_probe(struct snd_soc_component *component)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rt711_remove(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
regcache_cache_only(rt711->regmap, true);
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
|
||||
.probe = rt711_probe,
|
||||
.set_bias_level = rt711_set_bias_level,
|
||||
|
@ -905,6 +912,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
|
|||
.dapm_routes = rt711_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
|
||||
.set_jack = rt711_set_jack_detect,
|
||||
.remove = rt711_remove,
|
||||
};
|
||||
|
||||
static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
|
||||
|
|
|
@ -71,7 +71,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = {
|
|||
{ SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
|
||||
{ SGTL5000_DAP_MAIN_CHAN, 0x8000 },
|
||||
{ SGTL5000_DAP_MIX_CHAN, 0x0000 },
|
||||
{ SGTL5000_DAP_AVC_CTRL, 0x0510 },
|
||||
{ SGTL5000_DAP_AVC_CTRL, 0x5100 },
|
||||
{ SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
|
||||
{ SGTL5000_DAP_AVC_ATTACK, 0x0028 },
|
||||
{ SGTL5000_DAP_AVC_DECAY, 0x0050 },
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SiRF inner codec controllers define
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*/
|
||||
|
||||
#ifndef _SIRF_AUDIO_CODEC_H
|
||||
#define _SIRF_AUDIO_CODEC_H
|
||||
|
||||
|
||||
#define AUDIO_IC_CODEC_PWR (0x00E0)
|
||||
#define AUDIO_IC_CODEC_CTRL0 (0x00E4)
|
||||
#define AUDIO_IC_CODEC_CTRL1 (0x00E8)
|
||||
#define AUDIO_IC_CODEC_CTRL2 (0x00EC)
|
||||
#define AUDIO_IC_CODEC_CTRL3 (0x00F0)
|
||||
|
||||
#define MICBIASEN (1 << 3)
|
||||
|
||||
#define IC_RDACEN (1 << 0)
|
||||
#define IC_LDACEN (1 << 1)
|
||||
#define IC_HSREN (1 << 2)
|
||||
#define IC_HSLEN (1 << 3)
|
||||
#define IC_SPEN (1 << 4)
|
||||
#define IC_CPEN (1 << 5)
|
||||
|
||||
#define IC_HPRSELR (1 << 6)
|
||||
#define IC_HPLSELR (1 << 7)
|
||||
#define IC_HPRSELL (1 << 8)
|
||||
#define IC_HPLSELL (1 << 9)
|
||||
#define IC_SPSELR (1 << 10)
|
||||
#define IC_SPSELL (1 << 11)
|
||||
|
||||
#define IC_MONOR (1 << 12)
|
||||
#define IC_MONOL (1 << 13)
|
||||
|
||||
#define IC_RXOSRSEL (1 << 28)
|
||||
#define IC_CPFREQ (1 << 29)
|
||||
#define IC_HSINVEN (1 << 30)
|
||||
|
||||
#define IC_MICINREN (1 << 0)
|
||||
#define IC_MICINLEN (1 << 1)
|
||||
#define IC_MICIN1SEL (1 << 2)
|
||||
#define IC_MICIN2SEL (1 << 3)
|
||||
#define IC_MICDIFSEL (1 << 4)
|
||||
#define IC_LINEIN1SEL (1 << 5)
|
||||
#define IC_LINEIN2SEL (1 << 6)
|
||||
#define IC_RADCEN (1 << 7)
|
||||
#define IC_LADCEN (1 << 8)
|
||||
#define IC_ALM (1 << 9)
|
||||
|
||||
#define IC_DIGMICEN (1 << 22)
|
||||
#define IC_DIGMICFREQ (1 << 23)
|
||||
#define IC_ADC14B_12 (1 << 24)
|
||||
#define IC_FIRDAC_HSL_EN (1 << 25)
|
||||
#define IC_FIRDAC_HSR_EN (1 << 26)
|
||||
#define IC_FIRDAC_LOUT_EN (1 << 27)
|
||||
#define IC_POR (1 << 28)
|
||||
#define IC_CODEC_CLK_EN (1 << 29)
|
||||
#define IC_HP_3DB_BOOST (1 << 30)
|
||||
|
||||
#define IC_ADC_LEFT_GAIN_SHIFT 16
|
||||
#define IC_ADC_RIGHT_GAIN_SHIFT 10
|
||||
#define IC_ADC_GAIN_MASK 0x3F
|
||||
#define IC_MIC_MAX_GAIN 0x39
|
||||
|
||||
#define IC_RXPGAR_MASK 0x3F
|
||||
#define IC_RXPGAR_SHIFT 14
|
||||
#define IC_RXPGAL_MASK 0x3F
|
||||
#define IC_RXPGAL_SHIFT 21
|
||||
#define IC_RXPGAR 0x7B
|
||||
#define IC_RXPGAL 0x7B
|
||||
|
||||
#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F
|
||||
#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0
|
||||
#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10
|
||||
#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20
|
||||
|
||||
#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_TX_FIFO_SC_OFFSET)
|
||||
#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_TX_FIFO_LC_OFFSET)
|
||||
#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_TX_FIFO_HC_OFFSET)
|
||||
|
||||
#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F
|
||||
#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0
|
||||
#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10
|
||||
#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20
|
||||
|
||||
#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_RX_FIFO_SC_OFFSET)
|
||||
#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_RX_FIFO_LC_OFFSET)
|
||||
#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
|
||||
<< AUDIO_PORT_RX_FIFO_HC_OFFSET)
|
||||
#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4)
|
||||
#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8)
|
||||
|
||||
#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC)
|
||||
#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100)
|
||||
#define AUDIO_PORT_IC_TXFIFO_STS (0x0104)
|
||||
#define AUDIO_PORT_IC_TXFIFO_INT (0x0108)
|
||||
#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C)
|
||||
|
||||
#define AUDIO_PORT_IC_RXFIFO_OP (0x0110)
|
||||
#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114)
|
||||
#define AUDIO_PORT_IC_RXFIFO_STS (0x0118)
|
||||
#define AUDIO_PORT_IC_RXFIFO_INT (0x011C)
|
||||
#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120)
|
||||
|
||||
#define AUDIO_FIFO_START (1 << 0)
|
||||
#define AUDIO_FIFO_RESET (1 << 1)
|
||||
|
||||
#define AUDIO_FIFO_FULL (1 << 0)
|
||||
#define AUDIO_FIFO_EMPTY (1 << 1)
|
||||
#define AUDIO_FIFO_OFLOW (1 << 2)
|
||||
#define AUDIO_FIFO_UFLOW (1 << 3)
|
||||
|
||||
#define IC_TX_ENABLE (0x03)
|
||||
#define IC_RX_ENABLE_MONO (0x01)
|
||||
#define IC_RX_ENABLE_STEREO (0x03)
|
||||
|
||||
#endif /*__SIRF_AUDIO_CODEC_H*/
|
|
@ -1873,6 +1873,12 @@ static int wcd934x_set_channel_map(struct snd_soc_dai *dai,
|
|||
|
||||
wcd = snd_soc_component_get_drvdata(dai->component);
|
||||
|
||||
if (tx_num > WCD934X_TX_MAX || rx_num > WCD934X_RX_MAX) {
|
||||
dev_err(wcd->dev, "Invalid tx %d or rx %d channel count\n",
|
||||
tx_num, rx_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!tx_slot || !rx_slot) {
|
||||
dev_err(wcd->dev, "Invalid tx_slot=%p, rx_slot=%p\n",
|
||||
tx_slot, rx_slot);
|
||||
|
|
|
@ -878,6 +878,7 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
|
|||
static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
|
||||
{
|
||||
u32 strcr = 0, scr = 0, stcr, srcr, mask;
|
||||
unsigned int slots;
|
||||
|
||||
ssi->dai_fmt = fmt;
|
||||
|
||||
|
@ -909,10 +910,11 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
slots = ssi->slots ? : 2;
|
||||
regmap_update_bits(ssi->regs, REG_SSI_STCCR,
|
||||
SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
|
||||
SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
|
||||
regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
|
||||
SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
|
||||
SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
|
||||
|
||||
/* Data on rising edge of bclk, frame low, 1clk before data */
|
||||
strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
|
||||
|
|
|
@ -172,15 +172,16 @@ int asoc_simple_parse_clk(struct device *dev,
|
|||
* or device's module clock.
|
||||
*/
|
||||
clk = devm_get_clk_from_child(dev, node, NULL);
|
||||
if (IS_ERR(clk))
|
||||
clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
|
||||
|
||||
if (!IS_ERR(clk)) {
|
||||
simple_dai->clk = clk;
|
||||
simple_dai->sysclk = clk_get_rate(clk);
|
||||
} else if (!of_property_read_u32(node, "system-clock-frequency",
|
||||
&val)) {
|
||||
|
||||
simple_dai->clk = clk;
|
||||
} else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
|
||||
simple_dai->sysclk = val;
|
||||
} else {
|
||||
clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
|
||||
if (!IS_ERR(clk))
|
||||
simple_dai->sysclk = clk_get_rate(clk);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(node, "system-clock-direction-out"))
|
||||
|
|
|
@ -581,7 +581,7 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|||
},
|
||||
.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
|
||||
BYT_RT5640_JD_SRC_JD1_IN4P |
|
||||
BYT_RT5640_OVCD_TH_1500UA |
|
||||
BYT_RT5640_OVCD_TH_2000UA |
|
||||
BYT_RT5640_OVCD_SF_0P75 |
|
||||
BYT_RT5640_MCLK_EN),
|
||||
},
|
||||
|
|
|
@ -555,7 +555,9 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
/* set tdm */
|
||||
if (tdm_priv->bck_invert)
|
||||
tdm_con |= 1 << BCK_INVERSE_SFT;
|
||||
regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
|
||||
BCK_INVERSE_MASK_SFT,
|
||||
0x1 << BCK_INVERSE_SFT);
|
||||
|
||||
if (tdm_priv->lck_invert)
|
||||
tdm_con |= 1 << LRCK_INVERSE_SFT;
|
||||
|
|
|
@ -21,6 +21,11 @@ enum {
|
|||
/*****************************************************************************
|
||||
* R E G I S T E R D E F I N I T I O N
|
||||
*****************************************************************************/
|
||||
/* AUDIO_TOP_CON3 */
|
||||
#define BCK_INVERSE_SFT 3
|
||||
#define BCK_INVERSE_MASK 0x1
|
||||
#define BCK_INVERSE_MASK_SFT (0x1 << 3)
|
||||
|
||||
/* AFE_DAC_CON0 */
|
||||
#define VUL12_ON_SFT 31
|
||||
#define VUL12_ON_MASK 0x1
|
||||
|
@ -2079,9 +2084,6 @@ enum {
|
|||
#define TDM_EN_SFT 0
|
||||
#define TDM_EN_MASK 0x1
|
||||
#define TDM_EN_MASK_SFT (0x1 << 0)
|
||||
#define BCK_INVERSE_SFT 1
|
||||
#define BCK_INVERSE_MASK 0x1
|
||||
#define BCK_INVERSE_MASK_SFT (0x1 << 1)
|
||||
#define LRCK_INVERSE_SFT 2
|
||||
#define LRCK_INVERSE_MASK 0x1
|
||||
#define LRCK_INVERSE_MASK_SFT (0x1 << 2)
|
||||
|
|
|
@ -739,7 +739,7 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
|
|||
|
||||
for_each_child_of_node(dev->of_node, node) {
|
||||
ret = of_property_read_u32(node, "reg", &id);
|
||||
if (ret || id < 0 || id >= data->variant->num_dai) {
|
||||
if (ret || id < 0) {
|
||||
dev_err(dev, "valid dai id not found: %d\n", ret);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -27,18 +27,18 @@
|
|||
#define SPK_TDM_RX_MASK 0x03
|
||||
#define NUM_TDM_SLOTS 8
|
||||
#define SLIM_MAX_TX_PORTS 16
|
||||
#define SLIM_MAX_RX_PORTS 16
|
||||
#define SLIM_MAX_RX_PORTS 13
|
||||
#define WCD934X_DEFAULT_MCLK_RATE 9600000
|
||||
|
||||
struct sdm845_snd_data {
|
||||
struct snd_soc_jack jack;
|
||||
bool jack_setup;
|
||||
bool stream_prepared[SLIM_MAX_RX_PORTS];
|
||||
bool stream_prepared[AFE_PORT_MAX];
|
||||
struct snd_soc_card *card;
|
||||
uint32_t pri_mi2s_clk_count;
|
||||
uint32_t sec_mi2s_clk_count;
|
||||
uint32_t quat_tdm_clk_count;
|
||||
struct sdw_stream_runtime *sruntime[SLIM_MAX_RX_PORTS];
|
||||
struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
|
||||
};
|
||||
|
||||
static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
@ -1573,6 +1574,9 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
|
|||
if (card->long_name)
|
||||
return 0; /* long name already set by driver or from DMI */
|
||||
|
||||
if (!is_acpi_device_node(card->dev->fwnode))
|
||||
return 0;
|
||||
|
||||
/* make up dmi long name as: vendor-product-version-board */
|
||||
vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
|
||||
if (!vendor || !is_dmi_valid(vendor)) {
|
||||
|
|
|
@ -207,7 +207,7 @@ int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
|
|||
|
||||
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
|
||||
HDA_DSP_REG_ADSPCS, adspcs,
|
||||
!(adspcs & HDA_DSP_ADSPCS_SPA_MASK(core_mask)),
|
||||
!(adspcs & HDA_DSP_ADSPCS_CPA_MASK(core_mask)),
|
||||
HDA_DSP_REG_POLL_INTERVAL_US,
|
||||
HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -897,6 +897,7 @@ free_streams:
|
|||
/* dsp_unmap: not currently used */
|
||||
iounmap(sdev->bar[HDA_DSP_BAR]);
|
||||
hdac_bus_unmap:
|
||||
platform_device_unregister(hdev->dmic_dev);
|
||||
iounmap(bus->remap_addr);
|
||||
hda_codec_i915_exit(sdev);
|
||||
err:
|
||||
|
|
|
@ -2883,7 +2883,7 @@ static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_v
|
|||
u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
|
||||
u16 value = elem->value.enumerated.item[0];
|
||||
|
||||
kctl->private_value = ((device << SND_DJM_DEVICE_SHIFT) |
|
||||
kctl->private_value = (((unsigned long)device << SND_DJM_DEVICE_SHIFT) |
|
||||
(group << SND_DJM_GROUP_SHIFT) |
|
||||
value);
|
||||
|
||||
|
@ -2921,7 +2921,7 @@ static int snd_djm_controls_create(struct usb_mixer_interface *mixer,
|
|||
value = device->controls[i].default_value;
|
||||
knew.name = device->controls[i].name;
|
||||
knew.private_value = (
|
||||
(device_idx << SND_DJM_DEVICE_SHIFT) |
|
||||
((unsigned long)device_idx << SND_DJM_DEVICE_SHIFT) |
|
||||
(i << SND_DJM_GROUP_SHIFT) |
|
||||
value);
|
||||
err = snd_djm_controls_update(mixer, device_idx, i, value);
|
||||
|
|
Loading…
Reference in New Issue