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>
This commit is contained in:
Hans de Goede 2024-10-24 23:16:14 +02:00 committed by Mark Brown
parent 032532f91a
commit d48696b915
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View 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