ASoC: Fixes for v6.12

The biggest set of changes here is Hans' fixes and quirks for various
 Baytrail based platforms with RT5640 CODECs, and there's one core fix
 for a missed length assignment for __counted_by() checking.  Otherwise
 it's small device specific fixes, several of them in the DT bindings.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmciNo8ACgkQJNaLcl1U
 h9CNfAf/bw39l2d16DVOdzq1gv4I0BUX7M/wTsLRujnDCv8F7qZn3BhhPEeEiLDP
 3wa8MzwcnXGI7rM5kzPKUERI352N7FzWUpSz6r7QtszPpttzx8HSxcHuuU68msSo
 oqrUmEqA+1sFuDwsMMm85uUpeHHFQtgEhtMxMafz9VxWhTqSQCfIoM62pAns2Xdq
 X3mSaovGIofWXszMjzf7tWrWfAAnzgvYjmOYNd7QwIpi/HZL9iAxw/orbLW6AZCm
 ZnrhiGxf5ZZeeaiZhEzdH7iktM1+WpvLihl1PUD8JcgCHW3CJud/OqtpXV+AeyHm
 p7dI0bb71g0RJ08pt+i64wxS6HA+Qg==
 =I/0i
 -----END PGP SIGNATURE-----

Merge tag 'asoc-fix-v6.12-rc5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v6.12

The biggest set of changes here is Hans' fixes and quirks for various
Baytrail based platforms with RT5640 CODECs, and there's one core fix
for a missed length assignment for __counted_by() checking.  Otherwise
it's small device specific fixes, several of them in the DT bindings.
This commit is contained in:
Takashi Iwai 2024-10-30 14:46:35 +01:00
commit 7027eee090
9 changed files with 144 additions and 28 deletions

View File

@ -48,6 +48,10 @@ properties:
- const: mclk_rx - const: mclk_rx
- const: hclk - const: hclk
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
resets: resets:
maxItems: 1 maxItems: 1

View File

@ -721,6 +721,10 @@ static const struct config_entry acpi_config_table[] = {
#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
/* BayTrail */ /* BayTrail */
{
.flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "LPE0F28",
},
{ {
.flags = FLAG_SST_OR_SOF_BYT, .flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "80860F28", .acpi_hid = "80860F28",

View File

@ -747,8 +747,10 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset", cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(cs42l51->reset_gpio)) if (IS_ERR(cs42l51->reset_gpio)) {
return PTR_ERR(cs42l51->reset_gpio); ret = PTR_ERR(cs42l51->reset_gpio);
goto error;
}
if (cs42l51->reset_gpio) { if (cs42l51->reset_gpio) {
dev_dbg(dev, "Release reset gpio\n"); dev_dbg(dev, "Release reset gpio\n");
@ -780,6 +782,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
return 0; return 0;
error: error:
gpiod_set_value_cansleep(cs42l51->reset_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies), regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies); cs42l51->supplies);
return ret; return ret;

View File

@ -2419,10 +2419,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void rt5640_cancel_work(void *data) static void rt5640_disable_irq_and_cancel_work(void *data)
{ {
struct rt5640_priv *rt5640 = data; struct rt5640_priv *rt5640 = data;
if (rt5640->jd_gpio_irq_requested) {
free_irq(rt5640->jd_gpio_irq, rt5640);
rt5640->jd_gpio_irq_requested = false;
}
if (rt5640->irq_requested) {
free_irq(rt5640->irq, rt5640);
rt5640->irq_requested = false;
}
cancel_delayed_work_sync(&rt5640->jack_work); cancel_delayed_work_sync(&rt5640->jack_work);
cancel_delayed_work_sync(&rt5640->bp_work); cancel_delayed_work_sync(&rt5640->bp_work);
} }
@ -2463,13 +2473,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
if (!rt5640->jack) if (!rt5640->jack)
return; return;
if (rt5640->jd_gpio_irq_requested) rt5640_disable_irq_and_cancel_work(rt5640);
free_irq(rt5640->jd_gpio_irq, rt5640);
if (rt5640->irq_requested)
free_irq(rt5640->irq, rt5640);
rt5640_cancel_work(rt5640);
if (rt5640->jack->status & SND_JACK_MICROPHONE) { if (rt5640->jack->status & SND_JACK_MICROPHONE) {
rt5640_disable_micbias1_ovcd_irq(component); rt5640_disable_micbias1_ovcd_irq(component);
@ -2477,8 +2481,6 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0); snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
} }
rt5640->jd_gpio_irq_requested = false;
rt5640->irq_requested = false;
rt5640->jd_gpio = NULL; rt5640->jd_gpio = NULL;
rt5640->jack = NULL; rt5640->jack = NULL;
} }
@ -2798,7 +2800,8 @@ static int rt5640_suspend(struct snd_soc_component *component)
if (rt5640->jack) { if (rt5640->jack) {
/* disable jack interrupts during system suspend */ /* disable jack interrupts during system suspend */
disable_irq(rt5640->irq); disable_irq(rt5640->irq);
rt5640_cancel_work(rt5640); cancel_delayed_work_sync(&rt5640->jack_work);
cancel_delayed_work_sync(&rt5640->bp_work);
} }
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
@ -3032,7 +3035,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c)
INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work); INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work);
/* Make sure work is stopped on probe-error / remove */ /* Make sure work is stopped on probe-error / remove */
ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640); ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640);
if (ret) if (ret)
return ret; return ret;

View File

@ -715,12 +715,17 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
int hph_mode = wcd937x->hph_mode; int hph_mode = wcd937x->hph_mode;
u8 val;
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
val = WCD937X_DIGITAL_PDM_WD_CTL2_EN |
WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL |
WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF;
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2, WCD937X_DIGITAL_PDM_WD_CTL2,
BIT(0), BIT(0)); WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
val);
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
usleep_range(1000, 1010); usleep_range(1000, 1010);
@ -741,7 +746,8 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
hph_mode); hph_mode);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2, WCD937X_DIGITAL_PDM_WD_CTL2,
BIT(0), 0x00); WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
0x00);
break; break;
} }
@ -2049,6 +2055,8 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
wcd937x_get_swr_port, wcd937x_set_swr_port), wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0, SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port), wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("LO Switch", WCD937X_LO, 0, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0, SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port), wcd937x_get_swr_port, wcd937x_set_swr_port),

View File

@ -391,6 +391,10 @@
#define WCD937X_DIGITAL_PDM_WD_CTL0 0x3465 #define WCD937X_DIGITAL_PDM_WD_CTL0 0x3465
#define WCD937X_DIGITAL_PDM_WD_CTL1 0x3466 #define WCD937X_DIGITAL_PDM_WD_CTL1 0x3466
#define WCD937X_DIGITAL_PDM_WD_CTL2 0x3467 #define WCD937X_DIGITAL_PDM_WD_CTL2 0x3467
#define WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF BIT(2)
#define WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL BIT(1)
#define WCD937X_DIGITAL_PDM_WD_CTL2_EN BIT(0)
#define WCD937X_DIGITAL_PDM_WD_CTL2_MASK GENMASK(2, 0)
#define WCD937X_DIGITAL_INTR_MODE 0x346A #define WCD937X_DIGITAL_INTR_MODE 0x346A
#define WCD937X_DIGITAL_INTR_MASK_0 0x346B #define WCD937X_DIGITAL_INTR_MASK_0 0x346B
#define WCD937X_DIGITAL_INTR_MASK_1 0x346C #define WCD937X_DIGITAL_INTR_MASK_1 0x346C

View File

@ -125,6 +125,28 @@ static const struct sst_res_info bytcr_res_info = {
.acpi_ipc_irq_index = 0 .acpi_ipc_irq_index = 0
}; };
/* For "LPE0F28" ACPI device found on some Android factory OS models */
static const struct sst_res_info lpe8086_res_info = {
.shim_offset = 0x140000,
.shim_size = 0x000100,
.shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
.ssp0_offset = 0xa0000,
.ssp0_size = 0x1000,
.dma0_offset = 0x98000,
.dma0_size = 0x4000,
.dma1_offset = 0x9c000,
.dma1_size = 0x4000,
.iram_offset = 0x0c0000,
.iram_size = 0x14000,
.dram_offset = 0x100000,
.dram_size = 0x28000,
.mbox_offset = 0x144000,
.mbox_size = 0x1000,
.acpi_lpe_res_index = 1,
.acpi_ddr_index = 0,
.acpi_ipc_irq_index = 0
};
static struct sst_platform_info byt_rvp_platform_data = { static struct sst_platform_info byt_rvp_platform_data = {
.probe_data = &byt_fwparse_info, .probe_data = &byt_fwparse_info,
.ipc_info = &byt_ipc_info, .ipc_info = &byt_ipc_info,
@ -268,10 +290,38 @@ static int sst_acpi_probe(struct platform_device *pdev)
mach->pdata = &chv_platform_data; mach->pdata = &chv_platform_data;
pdata = mach->pdata; pdata = mach->pdata;
ret = kstrtouint(id->id, 16, &dev_id); if (!strcmp(id->id, "LPE0F28")) {
if (ret < 0) { struct resource *rsrc;
dev_err(dev, "Unique device id conversion error: %d\n", ret);
return ret; /* Use regular BYT SST PCI VID:PID */
dev_id = 0x80860F28;
byt_rvp_platform_data.res_info = &lpe8086_res_info;
/*
* The "LPE0F28" ACPI device has separate IO-mem resources for:
* DDR, SHIM, MBOX, IRAM, DRAM, CFG
* None of which covers the entire LPE base address range.
* lpe8086_res_info.acpi_lpe_res_index points to the SHIM.
* Patch this to cover the entire base address range as expected
* by sst_platform_get_resources().
*/
rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
pdata->res_info->acpi_lpe_res_index);
if (!rsrc) {
dev_err(dev, "Invalid SHIM base\n");
return -EIO;
}
rsrc->start -= pdata->res_info->shim_offset;
rsrc->end = rsrc->start + 0x200000 - 1;
} else {
ret = kstrtouint(id->id, 16, &dev_id);
if (ret < 0) {
dev_err(dev, "Unique device id conversion error: %d\n", ret);
return ret;
}
if (soc_intel_is_byt_cr(pdev))
byt_rvp_platform_data.res_info = &bytcr_res_info;
} }
dev_dbg(dev, "ACPI device id: %x\n", dev_id); dev_dbg(dev, "ACPI device id: %x\n", dev_id);
@ -280,11 +330,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (soc_intel_is_byt_cr(pdev)) {
/* override resource info */
byt_rvp_platform_data.res_info = &bytcr_res_info;
}
/* update machine parameters */ /* update machine parameters */
mach->mach_params.acpi_ipc_irq_index = mach->mach_params.acpi_ipc_irq_index =
pdata->res_info->acpi_ipc_irq_index; pdata->res_info->acpi_ipc_irq_index;
@ -344,6 +389,7 @@ static void sst_acpi_remove(struct platform_device *pdev)
} }
static const struct acpi_device_id sst_acpi_ids[] = { static const struct acpi_device_id sst_acpi_ids[] = {
{ "LPE0F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines}, { "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines}, { "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
{ }, { },

View File

@ -17,6 +17,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/device/bus.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h> #include <linux/gpio/machine.h>
@ -32,6 +33,8 @@
#include "../atom/sst-atom-controls.h" #include "../atom/sst-atom-controls.h"
#include "../common/soc-intel-quirks.h" #include "../common/soc-intel-quirks.h"
#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"
enum { enum {
BYT_RT5640_DMIC1_MAP, BYT_RT5640_DMIC1_MAP,
BYT_RT5640_DMIC2_MAP, BYT_RT5640_DMIC2_MAP,
@ -1129,6 +1132,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 | BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ /* Vexia Edu Atla 10 tablet */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
/* Above strings are too generic, also match on BIOS date */
DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_DIFF_MIC |
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
{ /* Voyo Winpad A15 */ { /* Voyo Winpad A15 */
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
@ -1698,9 +1716,33 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
codec_dev = acpi_get_first_physical_node(adev); codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev); acpi_dev_put(adev);
if (!codec_dev)
return -EPROBE_DEFER; if (codec_dev) {
priv->codec_dev = get_device(codec_dev); priv->codec_dev = get_device(codec_dev);
} else {
/*
* Special case for Android tablets where the codec i2c_client
* has been manually instantiated by x86_android_tablets.ko due
* to a broken DSDT.
*/
codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
if (!codec_dev)
return -EPROBE_DEFER;
if (!i2c_verify_client(codec_dev)) {
dev_err(dev, "Error '%s' is not an i2c_client\n",
BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
put_device(codec_dev);
}
/* fixup codec name */
strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,
sizeof(byt_rt5640_codec_name));
/* bus_find_device() returns a reference no need to get() */
priv->codec_dev = codec_dev;
}
/* /*
* swap SSP0 if bytcr is detected * swap SSP0 if bytcr is detected

View File

@ -1147,6 +1147,8 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
if (*list == NULL) if (*list == NULL)
return -ENOMEM; return -ENOMEM;
(*list)->num_widgets = size;
list_for_each_entry(w, widgets, work_list) list_for_each_entry(w, widgets, work_list)
(*list)->widgets[i++] = w; (*list)->widgets[i++] = w;