ASoC: Intel: bytcr_rt5640: Add support for non ACPI instantiated codec
authorHans de Goede <hdegoede@redhat.com>
Thu, 24 Oct 2024 21:16:14 +0000 (23:16 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 24 Oct 2024 23:50:14 +0000 (00:50 +0100)
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>
sound/soc/intel/boards/bytcr_rt5640.c

index 2ed49acb4e36e79467a082df6273839d6800f0b2..8dfd91cc36682de757f2b7fca250fc0955cd4358 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/device/bus.h>
 #include <linux/dmi.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/machine.h>
@@ -32,6 +33,8 @@
 #include "../atom/sst-atom-controls.h"
 #include "../common/soc-intel-quirks.h"
 
+#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME     "i2c-rt5640"
+
 enum {
        BYT_RT5640_DMIC1_MAP,
        BYT_RT5640_DMIC2_MAP,
@@ -1698,9 +1701,33 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 
        codec_dev = acpi_get_first_physical_node(adev);
        acpi_dev_put(adev);
-       if (!codec_dev)
-               return -EPROBE_DEFER;
-       priv->codec_dev = get_device(codec_dev);
+
+       if (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