Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: Intel: bytcr_rt5640: Add support for non ACPI instantiated codec

On some x86 Bay Trail tablets which shipped with Android as factory OS,
the DSDT is so broken that the codec needs to be manually instantatiated
by the special x86-android-tablets.ko "fixup" driver for cases like this.

This means that the codec-dev cannot be retrieved through its ACPI fwnode,
add support to the bytcr_rt5640 machine driver for such manually
instantiated rt5640 i2c_clients.

An example of a tablet which needs this is the Vexia EDU ATLA 10 tablet,
which has been distributed to schools in the Spanish Andalucía region.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patch.msgid.link/20241024211615.79518-1-hdegoede@redhat.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Hans de Goede and committed by
Mark Brown
d48696b9 032532f9

+30 -3
+30 -3
sound/soc/intel/boards/bytcr_rt5640.c
··· 17 17 #include <linux/acpi.h> 18 18 #include <linux/clk.h> 19 19 #include <linux/device.h> 20 + #include <linux/device/bus.h> 20 21 #include <linux/dmi.h> 21 22 #include <linux/gpio/consumer.h> 22 23 #include <linux/gpio/machine.h> ··· 32 31 #include "../../codecs/rt5640.h" 33 32 #include "../atom/sst-atom-controls.h" 34 33 #include "../common/soc-intel-quirks.h" 34 + 35 + #define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640" 35 36 36 37 enum { 37 38 BYT_RT5640_DMIC1_MAP, ··· 1701 1698 1702 1699 codec_dev = acpi_get_first_physical_node(adev); 1703 1700 acpi_dev_put(adev); 1704 - if (!codec_dev) 1705 - return -EPROBE_DEFER; 1706 - priv->codec_dev = get_device(codec_dev); 1701 + 1702 + if (codec_dev) { 1703 + priv->codec_dev = get_device(codec_dev); 1704 + } else { 1705 + /* 1706 + * Special case for Android tablets where the codec i2c_client 1707 + * has been manually instantiated by x86_android_tablets.ko due 1708 + * to a broken DSDT. 1709 + */ 1710 + codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, 1711 + BYT_RT5640_FALLBACK_CODEC_DEV_NAME); 1712 + if (!codec_dev) 1713 + return -EPROBE_DEFER; 1714 + 1715 + if (!i2c_verify_client(codec_dev)) { 1716 + dev_err(dev, "Error '%s' is not an i2c_client\n", 1717 + BYT_RT5640_FALLBACK_CODEC_DEV_NAME); 1718 + put_device(codec_dev); 1719 + } 1720 + 1721 + /* fixup codec name */ 1722 + strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME, 1723 + sizeof(byt_rt5640_codec_name)); 1724 + 1725 + /* bus_find_device() returns a reference no need to get() */ 1726 + priv->codec_dev = codec_dev; 1727 + } 1707 1728 1708 1729 /* 1709 1730 * swap SSP0 if bytcr is detected