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

[ Upstream commit d48696b915527b5bcdd207a299aec03fb037eb17 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Hans de Goede 2024-10-24 23:16:14 +02:00 committed by Greg Kroah-Hartman
parent e4d90d63d3
commit eade0698b8

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,
@ -1687,9 +1690,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