Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions drivers/soundwire/bus_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static int sdw_drv_probe(struct device *dev)
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
const struct sdw_device_id *id;
const char *name;
int ret;

/*
Expand All @@ -108,7 +109,10 @@ static int sdw_drv_probe(struct device *dev)

ret = drv->probe(slave, id);
if (ret) {
dev_err(dev, "Probe of %s failed: %d\n", drv->name, ret);
name = drv->name;
if (!name)
name = drv->driver.name;
dev_err(dev, "Probe of %s failed: %d\n", name, ret);
Comment thread
plbossart marked this conversation as resolved.
dev_pm_domain_detach(dev, false);
return ret;
}
Expand Down Expand Up @@ -174,11 +178,16 @@ static void sdw_drv_shutdown(struct device *dev)
*/
int __sdw_register_driver(struct sdw_driver *drv, struct module *owner)
{
const char *name;

drv->driver.bus = &sdw_bus_type;

if (!drv->probe) {
pr_err("driver %s didn't provide SDW probe routine\n",
drv->name);
name = drv->name;
if (!name)
name = drv->driver.name;

pr_err("driver %s didn't provide SDW probe routine\n", name);
return -EINVAL;
}

Expand Down
2 changes: 2 additions & 0 deletions include/sound/soc-acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ struct snd_soc_acpi_endpoint {
/**
* snd_soc_acpi_adr_device - descriptor for _ADR-enumerated device
* @adr: 64 bit ACPI _ADR value
* @adr_override: used when @adr is not correct in platform firmware
* @num_endpoints: number of endpoints for this device
* @endpoints: array of endpoints
* @name_prefix: string used for codec controls
*/
struct snd_soc_acpi_adr_device {
const u64 adr;
const u64 adr_override;
const u8 num_endpoints;
const struct snd_soc_acpi_endpoint *endpoints;
const char *name_prefix;
Expand Down
35 changes: 35 additions & 0 deletions sound/soc/codecs/rt1308-sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/pm_runtime.h>
#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
Expand Down Expand Up @@ -668,23 +669,57 @@ static int rt1308_sdw_init(struct device *dev, struct regmap *regmap,
return ret;
}

#define RT701_WORKAROUND_LINK1 1

/* DMI quirks */
static const struct dmi_system_id rt701_quirk_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"),
},
.driver_data = (void *)(RT701_WORKAROUND_LINK1),
},
{}
};

static int rt1308_sdw_probe(struct sdw_slave *slave,
const struct sdw_device_id *id)
{
struct regmap *regmap;
const struct dmi_system_id *dmi_id;
unsigned long link_id;

/* only allow BIOS work-around in specific configurations */
if (id->part_id == 0x701) {
dmi_id = dmi_first_match(rt701_quirk_table);
if (!dmi_id) {
dev_dbg(&slave->dev, "%s: probe workaround requires DMI quirk\n", __func__);
return -ENODEV;
}
link_id = (unsigned long)dmi_id->driver_data;
if (link_id != slave->bus->link_id) {
dev_dbg(&slave->dev, "%s: probe workaround on link %d not supported\n",
__func__, slave->bus->link_id);
return -ENODEV;
}
}

/* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);

slave->id.part_id = 0x1308;
rt1308_sdw_init(&slave->dev, regmap, slave);

return 0;
}

static const struct sdw_device_id rt1308_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0),
/* fake part_id to work-around incorrect _ADR in DSDT */
SDW_SLAVE_ENTRY_EXT(0x025d, 0x701, 0x1, 0, 0),
{},
};
MODULE_DEVICE_TABLE(sdw, rt1308_id);
Expand Down
36 changes: 36 additions & 0 deletions sound/soc/codecs/rt711-sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
Expand Down Expand Up @@ -438,10 +439,42 @@ static struct sdw_slave_ops rt711_slave_ops = {
.bus_config = rt711_bus_config,
};

#define RT701_WORKAROUND_LINK0 0

/* DMI quirks */
static const struct dmi_system_id rt701_quirk_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"),
},
.driver_data = (void *)(RT701_WORKAROUND_LINK0),

},
{}
};

static int rt711_sdw_probe(struct sdw_slave *slave,
const struct sdw_device_id *id)
{
struct regmap *sdw_regmap, *regmap;
const struct dmi_system_id *dmi_id;
unsigned long link_id;

/* only allow BIOS work-around in specific configurations */
if (id->part_id == 0x701) {
dmi_id = dmi_first_match(rt701_quirk_table);
if (!dmi_id) {
dev_dbg(&slave->dev, "%s: probe workaround requires DMI quirk\n", __func__);
return -ENODEV;
}
link_id = (unsigned long)dmi_id->driver_data;
if (link_id != slave->bus->link_id) {
dev_dbg(&slave->dev, "%s: probe workaround on link %d not supported\n",
__func__, slave->bus->link_id);
return -ENODEV;
}
}

/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap);
Expand All @@ -453,6 +486,7 @@ static int rt711_sdw_probe(struct sdw_slave *slave,
if (IS_ERR(regmap))
return PTR_ERR(regmap);

slave->id.part_id = 0x711;
rt711_init(&slave->dev, sdw_regmap, regmap, slave);

return 0;
Expand All @@ -473,6 +507,8 @@ static int rt711_sdw_remove(struct sdw_slave *slave)

static const struct sdw_device_id rt711_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x711, 0x2, 0, 0),
/* fake part_id to work-around incorrect _ADR in DSDT */
SDW_SLAVE_ENTRY_EXT(0x025d, 0x701, 0x1, 0, 0),
{},
};
MODULE_DEVICE_TABLE(sdw, rt711_id);
Expand Down
50 changes: 46 additions & 4 deletions sound/soc/intel/boards/sof_sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
SOF_SDW_FOUR_SPK),
},

{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"),
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
SOF_RT711_JD_SRC_JD2),
},
{}
};

Expand Down Expand Up @@ -424,7 +432,11 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
int stream;
u64 adr;

adr = link->adr_d->adr;
if (link->adr_d->adr_override)
adr = link->adr_d->adr_override;
else
adr = link->adr_d->adr;

codec_index = find_codec_info_part(adr);
if (codec_index < 0)
return codec_index;
Expand Down Expand Up @@ -562,6 +574,15 @@ static int create_codec_dai_name(struct device *dev,
if (!codec[comp_index].name)
return -ENOMEM;

/*
* special case: we override the _ADR only here since
* the codec component name above needs to use a name
* made after the firmware _ADR. All other case
* override the _ADR directly.
*/
if (link->adr_d[i].adr_override)
adr = link->adr_d[i].adr_override;

codec_index = find_codec_info_part(adr);
if (codec_index < 0)
return codec_index;
Expand Down Expand Up @@ -592,8 +613,14 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
*/
for (i = 0; i < link->num_adr; i++) {
int codec_index;
u64 adr;

codec_index = find_codec_info_part(link->adr_d[i].adr);
if (link->adr_d[i].adr_override)
adr = link->adr_d[i].adr_override;
else
adr = link->adr_d[i].adr;

codec_index = find_codec_info_part(adr);

if (codec_index < 0)
return codec_index;
Expand Down Expand Up @@ -707,6 +734,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
int codec_num;
int stream;
int ret;
u64 adr;
int k;

ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
Expand Down Expand Up @@ -743,7 +771,12 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
}

/* find codec info to create BE DAI */
codec_index = find_codec_info_part(link->adr_d[0].adr);
if (link->adr_d[0].adr_override)
adr = link->adr_d[0].adr_override;
else
adr = link->adr_d[0].adr;

codec_index = find_codec_info_part(adr);
if (codec_index < 0)
return codec_index;

Expand Down Expand Up @@ -1197,6 +1230,15 @@ static int mc_probe(struct platform_device *pdev)
if (!card->components)
return -ENOMEM;

if (mach->mach_params.dmic_num) {
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s mic:dmic cfg-mics:%d",
card->components,
mach->mach_params.dmic_num);
if (!card->components)
return -ENOMEM;
}

card->long_name = sdw_card_long_name;

/* Register the card */
Expand Down
66 changes: 66 additions & 0 deletions sound/soc/intel/common/soc-acpi-intel-tgl-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
*/

#include <linux/dmi.h>
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>

Expand Down Expand Up @@ -44,6 +45,16 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = {
}
};

static const struct snd_soc_acpi_adr_device workaround_rt711_0_adr[] = {
{
.adr = 0x000010025D070100,
.adr_override = 0x000020025D071100, /* same as rt711_0_adr */
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt711"
}
};

static const struct snd_soc_acpi_adr_device rt711_1_adr[] = {
{
.adr = 0x000120025D071100,
Expand Down Expand Up @@ -77,6 +88,16 @@ static const struct snd_soc_acpi_adr_device rt1308_1_single_adr[] = {
}
};

static const struct snd_soc_acpi_adr_device workaround_rt1308_1_single_adr[] = {
{
.adr = 0x000110025d070100,
.adr_override = 0x000120025D130800, /* same as rt1308_1_single_adr */
.num_endpoints = 1,
Comment thread
plbossart marked this conversation as resolved.
.endpoints = &single_endpoint,
.name_prefix = "rt1308-1"
}
};

static const struct snd_soc_acpi_adr_device rt1308_2_single_adr[] = {
{
.adr = 0x000220025D130800,
Expand Down Expand Up @@ -281,6 +302,20 @@ static const struct snd_soc_acpi_link_adr tgl_sdw_rt711_link1_rt1308_link2_rt715
{}
};

static const struct snd_soc_acpi_link_adr workaround_tgl_hp[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(workaround_rt711_0_adr),
.adr_d = workaround_rt711_0_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(workaround_rt1308_1_single_adr),
.adr_d = workaround_rt1308_1_single_adr,
},
{}
};

static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca[] = {
{
.mask = BIT(0),
Expand Down Expand Up @@ -352,6 +387,29 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);

/* DMI quirks */
static const struct dmi_system_id tgl_quirk_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"),
},
},
{}
};

static struct snd_soc_acpi_mach *tgl_quirk(void *arg)
{
struct snd_soc_acpi_mach *mach = arg;
const struct dmi_system_id *dmi_id;

dmi_id = dmi_first_match(tgl_quirk_table);
if (!dmi_id)
return NULL;

return mach;
}

/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
{
Expand Down Expand Up @@ -401,6 +459,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-rt5682.tplg",
},
/* workaround, this shall remain last to avoid matching on the wrong platforms */
{
.link_mask = 0x3, /* rt711 on link 0 and rt1308 on link 1 */
.links = workaround_tgl_hp,
.machine_quirk = tgl_quirk,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg",
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
Loading