Commit 6b571e26 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-fix2-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull more sound fixes from Takashi Iwai:
 "The remaining fixes for 6.9-rc1 that have been gathered in this week.

  More about ASoC at this time (one long-standing fix for compress
  offload, SOF, AMD ACP, Rockchip, Cirrus and tlv320 stuff) while
  another regression fix in ALSA core and a couple of HD-audio quirks as
  usual are included"

* tag 'sound-fix2-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: control: Fix unannotated kfree() cleanup
  ALSA: hda/realtek: Add quirks for some Clevo laptops
  ALSA: hda/realtek: Add quirk for HP Spectre x360 14 eu0000
  ALSA: hda/realtek: fix the hp playback volume issue for LG machines
  ASoC: soc-compress: Fix and add DPCM locking
  ASoC: SOF: amd: Skip IRAM/DRAM size modification for Steam Deck OLED
  ASoC: SOF: amd: Move signed_fw_image to struct acp_quirk_entry
  ASoC: amd: yc: Revert "add new YC platform variant (0x63) support"
  ASoC: amd: yc: Revert "Fix non-functional mic on Lenovo 21J2"
  ASoC: soc-core.c: Skip dummy codec when adding platforms
  ASoC: rockchip: i2s-tdm: Fix inaccurate sampling rates
  ASoC: dt-bindings: cirrus,cs42l43: Fix 'gpio-ranges' schema
  ASoC: amd: yc: Fix non-functional mic on ASUS M7600RE
  ASoC: tlv320adc3xxx: Don't strip remove function when driver is builtin
parents 5ee2433f 9f234784
......@@ -185,6 +185,7 @@ properties:
gpio-ranges:
items:
- items:
- description: A phandle to the CODEC pinctrl node
minimum: 0
- const: 0
......
......@@ -1275,12 +1275,12 @@ static int snd_ctl_elem_read(struct snd_card *card,
static int snd_ctl_elem_read_user(struct snd_card *card,
struct snd_ctl_elem_value __user *_control)
{
struct snd_ctl_elem_value *control;
struct snd_ctl_elem_value *control __free(kfree) = NULL;
int result;
control = memdup_user(_control, sizeof(*control));
if (IS_ERR(control))
return PTR_ERR(control);
return PTR_ERR(no_free_ptr(control));
result = snd_ctl_elem_read(card, control);
if (result < 0)
......
......@@ -2645,6 +2645,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x66a6, "Clevo PE60SN[CDE]-[GS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
......@@ -6964,6 +6965,25 @@ static void alc256_fixup_mic_no_presence_and_resume(struct hda_codec *codec,
}
}
static void alc256_decrease_headphone_amp_val(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
u32 caps;
u8 nsteps, offs;
if (action != HDA_FIXUP_ACT_PRE_PROBE)
return;
caps = query_amp_caps(codec, 0x3, HDA_OUTPUT);
nsteps = ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) - 10;
offs = ((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT) - 10;
caps &= ~AC_AMPCAP_NUM_STEPS & ~AC_AMPCAP_OFFSET;
caps |= (nsteps << AC_AMPCAP_NUM_STEPS_SHIFT) | (offs << AC_AMPCAP_OFFSET_SHIFT);
if (snd_hda_override_amp_caps(codec, 0x3, HDA_OUTPUT, caps))
codec_warn(codec, "failed to override amp caps for NID 0x3\n");
}
static void alc_fixup_dell4_mic_no_presence_quiet(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
......@@ -7104,6 +7124,38 @@ static void alc_fixup_headset_mic(struct hda_codec *codec,
}
}
static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
/*
* The Pin Complex 0x14 for the treble speakers is wrongly reported as
* unconnected.
* The Pin Complex 0x17 for the bass speakers has the lowest association
* and sequence values so shift it up a bit to squeeze 0x14 in.
*/
static const struct hda_pintbl pincfgs[] = {
{ 0x14, 0x90170110 }, // top/treble
{ 0x17, 0x90170111 }, // bottom/bass
{ }
};
/*
* Force DAC 0x02 for the bass speakers 0x17.
*/
static const hda_nid_t conn[] = { 0x02 };
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_apply_pincfgs(codec, pincfgs);
snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
break;
}
cs35l41_fixup_i2c_two(codec, fix, action);
alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
alc245_fixup_hp_gpio_led(codec, fix, action);
}
enum {
ALC269_FIXUP_GPIO2,
......@@ -7382,6 +7434,8 @@ enum {
ALC294_FIXUP_CS35L41_I2C_2,
ALC245_FIXUP_CS35L56_SPI_4_HP_GPIO_LED,
ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
ALC256_FIXUP_HEADPHONE_AMP_VOL,
ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
......@@ -9581,6 +9635,14 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc256_fixup_acer_sfg16_micmute_led,
},
[ALC256_FIXUP_HEADPHONE_AMP_VOL] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc256_decrease_headphone_amp_val,
},
[ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_spectre_x360_eu0xxx,
},
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
......@@ -9944,7 +10006,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8be8, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre 14", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
......@@ -10115,12 +10177,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
......@@ -10319,6 +10383,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x9e56, "Lenovo ZhaoYang CF4620Z", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK),
SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL),
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
......
......@@ -199,13 +199,6 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21HY"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21J2"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
......@@ -318,6 +311,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "M7600RE"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
......
......@@ -162,7 +162,6 @@ static int snd_acp6x_probe(struct pci_dev *pci,
/* Yellow Carp device check */
switch (pci->revision) {
case 0x60:
case 0x63:
case 0x6f:
break;
default:
......
......@@ -1429,7 +1429,7 @@ static int adc3xxx_i2c_probe(struct i2c_client *i2c)
return ret;
}
static void __exit adc3xxx_i2c_remove(struct i2c_client *client)
static void adc3xxx_i2c_remove(struct i2c_client *client)
{
struct adc3xxx *adc3xxx = i2c_get_clientdata(client);
......@@ -1452,7 +1452,7 @@ static struct i2c_driver adc3xxx_i2c_driver = {
.of_match_table = tlv320adc3xxx_of_match,
},
.probe = adc3xxx_i2c_probe,
.remove = __exit_p(adc3xxx_i2c_remove),
.remove = adc3xxx_i2c_remove,
.id_table = adc3xxx_i2c_id,
};
......
......@@ -25,8 +25,6 @@
#define DEFAULT_MCLK_FS 256
#define CH_GRP_MAX 4 /* The max channel 8 / 2 */
#define MULTIPLEX_CH_MAX 10
#define CLK_PPM_MIN -1000
#define CLK_PPM_MAX 1000
#define TRCM_TXRX 0
#define TRCM_TX 1
......@@ -53,20 +51,6 @@ struct rk_i2s_tdm_dev {
struct clk *hclk;
struct clk *mclk_tx;
struct clk *mclk_rx;
/* The mclk_tx_src is parent of mclk_tx */
struct clk *mclk_tx_src;
/* The mclk_rx_src is parent of mclk_rx */
struct clk *mclk_rx_src;
/*
* The mclk_root0 and mclk_root1 are root parent and supplies for
* the different FS.
*
* e.g:
* mclk_root0 is VPLL0, used for FS=48000Hz
* mclk_root1 is VPLL1, used for FS=44100Hz
*/
struct clk *mclk_root0;
struct clk *mclk_root1;
struct regmap *regmap;
struct regmap *grf;
struct snd_dmaengine_dai_dma_data capture_dma_data;
......@@ -76,19 +60,11 @@ struct rk_i2s_tdm_dev {
const struct rk_i2s_soc_data *soc_data;
bool is_master_mode;
bool io_multiplex;
bool mclk_calibrate;
bool tdm_mode;
unsigned int mclk_rx_freq;
unsigned int mclk_tx_freq;
unsigned int mclk_root0_freq;
unsigned int mclk_root1_freq;
unsigned int mclk_root0_initial_freq;
unsigned int mclk_root1_initial_freq;
unsigned int frame_width;
unsigned int clk_trcm;
unsigned int i2s_sdis[CH_GRP_MAX];
unsigned int i2s_sdos[CH_GRP_MAX];
int clk_ppm;
int refcount;
spinlock_t lock; /* xfer lock */
bool has_playback;
......@@ -114,12 +90,6 @@ static void i2s_tdm_disable_unprepare_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
{
clk_disable_unprepare(i2s_tdm->mclk_tx);
clk_disable_unprepare(i2s_tdm->mclk_rx);
if (i2s_tdm->mclk_calibrate) {
clk_disable_unprepare(i2s_tdm->mclk_tx_src);
clk_disable_unprepare(i2s_tdm->mclk_rx_src);
clk_disable_unprepare(i2s_tdm->mclk_root0);
clk_disable_unprepare(i2s_tdm->mclk_root1);
}
}
/**
......@@ -142,29 +112,9 @@ static int i2s_tdm_prepare_enable_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
ret = clk_prepare_enable(i2s_tdm->mclk_rx);
if (ret)
goto err_mclk_rx;
if (i2s_tdm->mclk_calibrate) {
ret = clk_prepare_enable(i2s_tdm->mclk_tx_src);
if (ret)
goto err_mclk_rx;
ret = clk_prepare_enable(i2s_tdm->mclk_rx_src);
if (ret)
goto err_mclk_rx_src;
ret = clk_prepare_enable(i2s_tdm->mclk_root0);
if (ret)
goto err_mclk_root0;
ret = clk_prepare_enable(i2s_tdm->mclk_root1);
if (ret)
goto err_mclk_root1;
}
return 0;
err_mclk_root1:
clk_disable_unprepare(i2s_tdm->mclk_root0);
err_mclk_root0:
clk_disable_unprepare(i2s_tdm->mclk_rx_src);
err_mclk_rx_src:
clk_disable_unprepare(i2s_tdm->mclk_tx_src);
err_mclk_rx:
clk_disable_unprepare(i2s_tdm->mclk_tx);
err_mclk_tx:
......@@ -564,159 +514,6 @@ static void rockchip_i2s_tdm_xfer_resume(struct snd_pcm_substream *substream,
I2S_XFER_RXS_START);
}
static int rockchip_i2s_tdm_clk_set_rate(struct rk_i2s_tdm_dev *i2s_tdm,
struct clk *clk, unsigned long rate,
int ppm)
{
unsigned long rate_target;
int delta, ret;
if (ppm == i2s_tdm->clk_ppm)
return 0;
if (ppm < 0)
delta = -1;
else
delta = 1;
delta *= (int)div64_u64((u64)rate * (u64)abs(ppm) + 500000,
1000000);
rate_target = rate + delta;
if (!rate_target)
return -EINVAL;
ret = clk_set_rate(clk, rate_target);
if (ret)
return ret;
i2s_tdm->clk_ppm = ppm;
return 0;
}
static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
struct snd_pcm_substream *substream,
unsigned int lrck_freq)
{
struct clk *mclk_root;
struct clk *mclk_parent;
unsigned int mclk_root_freq;
unsigned int mclk_root_initial_freq;
unsigned int mclk_parent_freq;
unsigned int div, delta;
u64 ppm;
int ret;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
mclk_parent = i2s_tdm->mclk_tx_src;
else
mclk_parent = i2s_tdm->mclk_rx_src;
switch (lrck_freq) {
case 8000:
case 16000:
case 24000:
case 32000:
case 48000:
case 64000:
case 96000:
case 192000:
mclk_root = i2s_tdm->mclk_root0;
mclk_root_freq = i2s_tdm->mclk_root0_freq;
mclk_root_initial_freq = i2s_tdm->mclk_root0_initial_freq;
mclk_parent_freq = DEFAULT_MCLK_FS * 192000;
break;
case 11025:
case 22050:
case 44100:
case 88200:
case 176400:
mclk_root = i2s_tdm->mclk_root1;
mclk_root_freq = i2s_tdm->mclk_root1_freq;
mclk_root_initial_freq = i2s_tdm->mclk_root1_initial_freq;
mclk_parent_freq = DEFAULT_MCLK_FS * 176400;
break;
default:
dev_err(i2s_tdm->dev, "Invalid LRCK frequency: %u Hz\n",
lrck_freq);
return -EINVAL;
}
ret = clk_set_parent(mclk_parent, mclk_root);
if (ret)
return ret;
ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, mclk_root,
mclk_root_freq, 0);
if (ret)
return ret;
delta = abs(mclk_root_freq % mclk_parent_freq - mclk_parent_freq);
ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)mclk_root_freq);
if (ppm) {
div = DIV_ROUND_CLOSEST(mclk_root_initial_freq, mclk_parent_freq);
if (!div)
return -EINVAL;
mclk_root_freq = mclk_parent_freq * round_up(div, 2);
ret = clk_set_rate(mclk_root, mclk_root_freq);
if (ret)
return ret;
i2s_tdm->mclk_root0_freq = clk_get_rate(i2s_tdm->mclk_root0);
i2s_tdm->mclk_root1_freq = clk_get_rate(i2s_tdm->mclk_root1);
}
return clk_set_rate(mclk_parent, mclk_parent_freq);
}
static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
struct snd_pcm_substream *substream,
struct clk **mclk)
{
unsigned int mclk_freq;
int ret;
if (i2s_tdm->clk_trcm) {
if (i2s_tdm->mclk_tx_freq != i2s_tdm->mclk_rx_freq) {
dev_err(i2s_tdm->dev,
"clk_trcm, tx: %d and rx: %d should be the same\n",
i2s_tdm->mclk_tx_freq,
i2s_tdm->mclk_rx_freq);
return -EINVAL;
}
ret = clk_set_rate(i2s_tdm->mclk_tx, i2s_tdm->mclk_tx_freq);
if (ret)
return ret;
ret = clk_set_rate(i2s_tdm->mclk_rx, i2s_tdm->mclk_rx_freq);
if (ret)
return ret;
/* mclk_rx is also ok. */
*mclk = i2s_tdm->mclk_tx;
} else {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
*mclk = i2s_tdm->mclk_tx;
mclk_freq = i2s_tdm->mclk_tx_freq;
} else {
*mclk = i2s_tdm->mclk_rx;
mclk_freq = i2s_tdm->mclk_rx_freq;
}
ret = clk_set_rate(*mclk, mclk_freq);
if (ret)
return ret;
}
return 0;
}
static int rockchip_i2s_ch_to_io(unsigned int ch, bool substream_capture)
{
if (substream_capture) {
......@@ -853,19 +650,17 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
struct clk *mclk;
int ret = 0;
unsigned int val = 0;
unsigned int mclk_rate, bclk_rate, div_bclk = 4, div_lrck = 64;
int err;
if (i2s_tdm->is_master_mode) {
if (i2s_tdm->mclk_calibrate)
rockchip_i2s_tdm_calibrate_mclk(i2s_tdm, substream,
params_rate(params));
struct clk *mclk = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
i2s_tdm->mclk_tx : i2s_tdm->mclk_rx;
ret = rockchip_i2s_tdm_set_mclk(i2s_tdm, substream, &mclk);
if (ret)
return ret;
err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
if (err)
return err;
mclk_rate = clk_get_rate(mclk);
bclk_rate = i2s_tdm->frame_width * params_rate(params);
......@@ -973,96 +768,6 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream,
return 0;
}
static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
unsigned int freq, int dir)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
/* Put set mclk rate into rockchip_i2s_tdm_set_mclk() */
if (i2s_tdm->clk_trcm) {
i2s_tdm->mclk_tx_freq = freq;
i2s_tdm->mclk_rx_freq = freq;
} else {
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
i2s_tdm->mclk_tx_freq = freq;
else
i2s_tdm->mclk_rx_freq = freq;
}
dev_dbg(i2s_tdm->dev, "The target mclk_%s freq is: %d\n",
stream ? "rx" : "tx", freq);
return 0;
}
static int rockchip_i2s_tdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = CLK_PPM_MIN;
uinfo->value.integer.max = CLK_PPM_MAX;
uinfo->value.integer.step = 1;
return 0;
}
static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
ucontrol->value.integer.value[0] = i2s_tdm->clk_ppm;
return 0;
}
static int rockchip_i2s_tdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
int ret = 0, ppm = 0;
int changed = 0;
unsigned long old_rate;
if (ucontrol->value.integer.value[0] < CLK_PPM_MIN ||
ucontrol->value.integer.value[0] > CLK_PPM_MAX)
return -EINVAL;
ppm = ucontrol->value.integer.value[0];
old_rate = clk_get_rate(i2s_tdm->mclk_root0);
ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root0,
i2s_tdm->mclk_root0_freq, ppm);
if (ret)
return ret;
if (old_rate != clk_get_rate(i2s_tdm->mclk_root0))
changed = 1;
if (clk_is_match(i2s_tdm->mclk_root0, i2s_tdm->mclk_root1))
return changed;
old_rate = clk_get_rate(i2s_tdm->mclk_root1);
ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root1,
i2s_tdm->mclk_root1_freq, ppm);
if (ret)
return ret;
if (old_rate != clk_get_rate(i2s_tdm->mclk_root1))
changed = 1;
return changed;
}
static struct snd_kcontrol_new rockchip_i2s_tdm_compensation_control = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Clock Compensation in PPM",
.info = rockchip_i2s_tdm_clk_compensation_info,
.get = rockchip_i2s_tdm_clk_compensation_get,
.put = rockchip_i2s_tdm_clk_compensation_put,
};
static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
{
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
......@@ -1072,9 +777,6 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
if (i2s_tdm->has_playback)
snd_soc_dai_dma_data_set_playback(dai, &i2s_tdm->playback_dma_data);
if (i2s_tdm->mclk_calibrate)
snd_soc_add_dai_controls(dai, &rockchip_i2s_tdm_compensation_control, 1);
return 0;
}
......@@ -1115,7 +817,6 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
.probe = rockchip_i2s_tdm_dai_probe,
.hw_params = rockchip_i2s_tdm_hw_params,
.set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio,
.set_sysclk = rockchip_i2s_tdm_set_sysclk,
.set_fmt = rockchip_i2s_tdm_set_fmt,
.set_tdm_slot = rockchip_dai_tdm_slot,
.trigger = rockchip_i2s_tdm_trigger,
......@@ -1444,35 +1145,6 @@ static void rockchip_i2s_tdm_path_config(struct rk_i2s_tdm_dev *i2s_tdm,
rockchip_i2s_tdm_tx_path_config(i2s_tdm, num);
}
static int rockchip_i2s_tdm_get_calibrate_mclks(struct rk_i2s_tdm_dev *i2s_tdm)
{
int num_mclks = 0;
i2s_tdm->mclk_tx_src = devm_clk_get(i2s_tdm->dev, "mclk_tx_src");
if (!IS_ERR(i2s_tdm->mclk_tx_src))
num_mclks++;
i2s_tdm->mclk_rx_src = devm_clk_get(i2s_tdm->dev, "mclk_rx_src");
if (!IS_ERR(i2s_tdm->mclk_rx_src))
num_mclks++;
i2s_tdm->mclk_root0 = devm_clk_get(i2s_tdm->dev, "mclk_root0");
if (!IS_ERR(i2s_tdm->mclk_root0))
num_mclks++;
i2s_tdm->mclk_root1 = devm_clk_get(i2s_tdm->dev, "mclk_root1");
if (!IS_ERR(i2s_tdm->mclk_root1))
num_mclks++;
if (num_mclks < 4 && num_mclks != 0)
return -ENOENT;
if (num_mclks == 4)
i2s_tdm->mclk_calibrate = 1;
return 0;
}
static int rockchip_i2s_tdm_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,
struct device_node *np,
bool is_rx_path)
......@@ -1610,11 +1282,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
i2s_tdm->io_multiplex =
of_property_read_bool(node, "rockchip,io-multiplex");
ret = rockchip_i2s_tdm_get_calibrate_mclks(i2s_tdm);
if (ret)
return dev_err_probe(i2s_tdm->dev, ret,
"mclk-calibrate clocks missing");
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs)) {
return dev_err_probe(i2s_tdm->dev, PTR_ERR(regs),
......@@ -1667,13 +1334,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
goto err_disable_hclk;
}
if (i2s_tdm->mclk_calibrate) {
i2s_tdm->mclk_root0_initial_freq = clk_get_rate(i2s_tdm->mclk_root0);
i2s_tdm->mclk_root1_initial_freq = clk_get_rate(i2s_tdm->mclk_root1);
i2s_tdm->mclk_root0_freq = i2s_tdm->mclk_root0_initial_freq;
i2s_tdm->mclk_root1_freq = i2s_tdm->mclk_root1_initial_freq;
}
pm_runtime_enable(&pdev->dev);
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
......
......@@ -385,11 +385,15 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
snd_soc_dpcm_mutex_lock(fe);
ret = dpcm_be_dai_hw_params(fe, stream);
snd_soc_dpcm_mutex_unlock(fe);
if (ret < 0)
goto out;
snd_soc_dpcm_mutex_lock(fe);
ret = dpcm_be_dai_prepare(fe, stream);
snd_soc_dpcm_mutex_unlock(fe);
if (ret < 0)
goto out;
......
......@@ -1219,6 +1219,9 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
if (!snd_soc_is_matching_component(platform, component))
continue;
if (snd_soc_component_is_dummy(component) && component->num_dai)
continue;
snd_soc_rtd_add_component(rtd, component);
}
}
......
......@@ -173,7 +173,7 @@ int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
adata = sdev->pdata->hw_pdata;
if (adata->signed_fw_image)
if (adata->quirks && adata->quirks->signed_fw_image)
size_fw = adata->fw_bin_size - ACP_FIRMWARE_SIGNATURE;
else
size_fw = adata->fw_bin_size;
......
......@@ -20,12 +20,15 @@
#include "acp.h"
#include "acp-dsp-offset.h"
#define SECURED_FIRMWARE 1
static bool enable_fw_debug;
module_param(enable_fw_debug, bool, 0444);
MODULE_PARM_DESC(enable_fw_debug, "Enable Firmware debug");
static struct acp_quirk_entry quirk_valve_galileo = {
.signed_fw_image = true,
.skip_iram_dram_size_mod = true,
};
const struct dmi_system_id acp_sof_quirk_table[] = {
{
/* Steam Deck OLED device */
......@@ -33,7 +36,7 @@ const struct dmi_system_id acp_sof_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Valve"),
DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"),
},
.driver_data = (void *)SECURED_FIRMWARE,
.driver_data = &quirk_valve_galileo,
},
{}
};
......@@ -254,7 +257,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
}
}
if (adata->signed_fw_image)
if (adata->quirks && adata->quirks->signed_fw_image)
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_INCLUDE_HDR, ACP_SHA_HEADER);
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_STRT_ADDR, start_addr);
......@@ -278,7 +281,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
}
/* psp_send_cmd only required for vangogh platform (rev - 5) */
if (desc->rev == 5) {
if (desc->rev == 5 && !(adata->quirks && adata->quirks->skip_iram_dram_size_mod)) {
/* Modify IRAM and DRAM size */
ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | IRAM_DRAM_FENCE_2);
if (ret)
......@@ -738,9 +741,11 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
sdev->debug_box.offset = sdev->host_box.offset + sdev->host_box.size;
sdev->debug_box.size = BOX_SIZE_1024;
adata->signed_fw_image = false;
dmi_id = dmi_first_match(acp_sof_quirk_table);
if (dmi_id && dmi_id->driver_data) {
if (dmi_id) {
adata->quirks = dmi_id->driver_data;
if (adata->quirks->signed_fw_image) {
adata->fw_code_bin = devm_kasprintf(sdev->dev, GFP_KERNEL,
"sof-%s-code.bin",
chip->name);
......@@ -756,8 +761,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
ret = -ENOMEM;
goto free_ipc_irq;
}
adata->signed_fw_image = dmi_id->driver_data;
}
}
adata->enable_fw_debug = enable_fw_debug;
......
......@@ -207,6 +207,11 @@ struct sof_amd_acp_desc {
u64 sdw_acpi_dev_addr;
};
struct acp_quirk_entry {
bool signed_fw_image;
bool skip_iram_dram_size_mod;
};
/* Common device data struct for ACP devices */
struct acp_dev_data {
struct snd_sof_dev *dev;
......@@ -236,7 +241,7 @@ struct acp_dev_data {
u8 *data_buf;
dma_addr_t sram_dma_addr;
u8 *sram_data_buf;
bool signed_fw_image;
struct acp_quirk_entry *quirks;
struct dma_descriptor dscr_info[ACP_MAX_DESC];
struct acp_dsp_stream stream_buf[ACP_MAX_STREAM];
struct acp_dsp_stream *dtrace_stream;
......
......@@ -143,6 +143,7 @@ EXPORT_SYMBOL_NS(sof_vangogh_ops, SND_SOC_SOF_AMD_COMMON);
int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
{
const struct dmi_system_id *dmi_id;
struct acp_quirk_entry *quirks;
/* common defaults */
memcpy(&sof_vangogh_ops, &sof_acp_common_ops, sizeof(struct snd_sof_dsp_ops));
......@@ -151,8 +152,12 @@ int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
sof_vangogh_ops.num_drv = ARRAY_SIZE(vangogh_sof_dai);
dmi_id = dmi_first_match(acp_sof_quirk_table);
if (dmi_id && dmi_id->driver_data)
if (dmi_id) {
quirks = dmi_id->driver_data;
if (quirks->signed_fw_image)
sof_vangogh_ops.load_firmware = acp_sof_load_signed_firmware;
}
return 0;
}
......
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