From b0c39f2104257f1ce643b77b8bc2be1d9035cc59 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Tue, 7 Oct 2025 11:57:54 +0530 Subject: [PATCH 1/7] ASoC: tas2783A: sdw_utils: support ch 3 & 4 Currently the machine driver for tas2783A can only support 2 channels. This patch adds support for 2 channel playback with 4 device setup. Signed-off-by: Niranjan H Y --- v2: - commit message updated --- sound/soc/sdw_utils/soc_sdw_ti_amp.c | 4 ++++ sound/soc/sdw_utils/soc_sdw_utils.c | 22 ++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/sound/soc/sdw_utils/soc_sdw_ti_amp.c b/sound/soc/sdw_utils/soc_sdw_ti_amp.c index f0011360ae9b6c..e1cfb388cb31f0 100644 --- a/sound/soc/sdw_utils/soc_sdw_ti_amp.c +++ b/sound/soc/sdw_utils/soc_sdw_ti_amp.c @@ -57,6 +57,10 @@ int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, strscpy(speaker, "Left Spk", sizeof(speaker)); } else if (!strncmp(prefix, "tas2783-2", strlen("tas2783-2"))) { strscpy(speaker, "Right Spk", sizeof(speaker)); + } else if (!strncmp(prefix, "tas2783-3", strlen("tas2783-3"))) { + strscpy(speaker, "Left Spk2", sizeof(speaker)); + } else if (!strncmp(prefix, "tas2783-4", strlen("tas2783-4"))) { + strscpy(speaker, "Right Spk2", sizeof(speaker)); } else { ret = -EINVAL; dev_err(card->dev, "unhandled prefix %s", prefix); diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 5ef9c4e88078cc..c5723974c5d2bc 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -40,11 +40,25 @@ static const struct snd_soc_dapm_widget lr_spk_widgets[] = { SND_SOC_DAPM_SPK("Right Spk", NULL), }; +static const struct snd_soc_dapm_widget lr_4spk_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), + SND_SOC_DAPM_SPK("Left Spk2", NULL), + SND_SOC_DAPM_SPK("Right Spk2", NULL), +}; + static const struct snd_kcontrol_new lr_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Left Spk"), SOC_DAPM_PIN_SWITCH("Right Spk"), }; +static const struct snd_kcontrol_new lr_4spk_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), + SOC_DAPM_PIN_SWITCH("Left Spk2"), + SOC_DAPM_PIN_SWITCH("Right Spk2"), +}; + static const struct snd_soc_dapm_widget rt700_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_MIC("AMIC", NULL), @@ -69,10 +83,10 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, .init = asoc_sdw_ti_amp_init, .rtd_init = asoc_sdw_ti_spk_rtd_init, - .controls = lr_spk_controls, - .num_controls = ARRAY_SIZE(lr_spk_controls), - .widgets = lr_spk_widgets, - .num_widgets = ARRAY_SIZE(lr_spk_widgets), + .controls = lr_4spk_controls, + .num_controls = ARRAY_SIZE(lr_4spk_controls), + .widgets = lr_4spk_widgets, + .num_widgets = ARRAY_SIZE(lr_4spk_widgets), }, }, .dai_num = 1, From 6f0b47b9c954317d04f785ed23727f7dd39ed314 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Thu, 9 Oct 2025 19:10:24 +0530 Subject: [PATCH 2/7] ASoc: tas2783A: Use acpi init data if present The ACPI table has initialization data for each device which needs to be updated to device to configure the device correctly. This commit adds the change to read the entry "mipi-sdca-function-initialization-table" and update the device with the data. Signed-off-by: Niranjan H Y --- v2: - update commit message description --- sound/soc/codecs/Kconfig | 1 + sound/soc/codecs/tas2783-sdw.c | 95 ++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 160c07699a8b72..3b9c57342cba69 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2103,6 +2103,7 @@ config SND_SOC_TAS2783_SDW tristate "Texas Instruments TAS2783 speaker amplifier (sdw)" depends on SOUNDWIRE depends on EFI + depends on SND_SOC_SDCA select REGMAP_SOUNDWIRE select REGMAP_SOUNDWIRE_MBQ select CRC32 diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index d62667957939b1..56642371b7155b 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #define TAS2783_PROBE_TIMEOUT 5000 #define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \ 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92) +#define MIPI_INIT_TABLE "mipi-sdca-function-initialization-table" static const u32 tas2783_cali_reg[] = { TAS2783_CAL_R0, @@ -56,6 +58,11 @@ struct bin_header_t { u32 length; }; +struct raw_init_data { + __le32 addr; + u8 val; +} __packed; + struct calibration_data { u32 is_valid; unsigned long read_sz; @@ -83,6 +90,8 @@ struct tas2783_prv { wait_queue_head_t fw_wait; bool fw_dl_task_done; bool fw_dl_success; + struct reg_sequence *init_data; + int num_init_data; }; static const struct reg_default tas2783_reg_default[] = { @@ -1214,9 +1223,19 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) dev_err(tas_dev->dev, "fw request, wait_event timeout\n"); ret = -EAGAIN; } else { - ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq, - ARRAY_SIZE(tas2783_init_seq)); - tas_dev->hw_init = true; + if (tas_dev->num_init_data > 0) + ret = regmap_multi_reg_write(tas_dev->regmap, + tas_dev->init_data, + tas_dev->num_init_data); + else + ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq, + ARRAY_SIZE(tas2783_init_seq)); + + if (ret) + dev_err(tas_dev->dev, + "init writes failed, err=%d", ret); + else + tas_dev->hw_init = true; } return ret; @@ -1260,6 +1279,73 @@ static void tas_remove(struct tas2783_prv *tas_dev) snd_soc_unregister_component(tas_dev->dev); } +static s32 tas_get_smartamp_init_data(struct sdw_slave *peripheral, + struct tas2783_prv *tas_dev) +{ + int num_init_data, i; + struct device *dev; + struct reg_sequence *init_data; + struct sdca_device_data *sdca_data; + struct sdca_function_desc *function; + struct raw_init_data *raw __free(kfree) = NULL; + + dev = &peripheral->dev; + sdca_data = &peripheral->sdca_data; + + dev_dbg(dev, "number of functions found %d", + sdca_data->num_functions); + + if (sdca_data->num_functions <= 0) + return -EINVAL; + + /* look for smartamp function */ + for (i = 0; i < sdca_data->num_functions; i++) { + if (sdca_data->function[i].type == + SDCA_FUNCTION_TYPE_SMART_AMP) + break; + } + if (i == sdca_data->num_functions) + return -EINVAL; + + function = &sdca_data->function[i]; + num_init_data = fwnode_property_count_u8(function->node, + MIPI_INIT_TABLE); + if (num_init_data <= 0) { + dev_dbg(dev, "error reading init table for tas2783 err=%d", + num_init_data); + return num_init_data; + } + + if (num_init_data % sizeof(*raw) != 0) { + dev_dbg(dev, "%s should be integer multiple of %lu", + MIPI_INIT_TABLE, sizeof(*raw)); + return -EINVAL; + } + + raw = kzalloc(num_init_data, GFP_KERNEL); + if (!raw) + return -ENOMEM; + + fwnode_property_read_u8_array(function->node, MIPI_INIT_TABLE, + (u8 *)raw, num_init_data); + + num_init_data /= sizeof(*raw); + init_data = devm_kcalloc(dev, num_init_data, sizeof(*init_data), + GFP_KERNEL); + if (!init_data) + return -ENOMEM; + + for (i = 0; i < num_init_data; i++) { + init_data[i].reg = le32_to_cpu(raw[i].addr); + init_data[i].def = raw[i].val; + } + + tas_dev->num_init_data = num_init_data; + tas_dev->init_data = init_data; + + return 0; +} + static s32 tas_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) { @@ -1272,6 +1358,8 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral, return dev_err_probe(dev, -ENOMEM, "Failed devm_kzalloc"); + tas_get_smartamp_init_data(peripheral, tas_dev); + tas_dev->dev = dev; tas_dev->sdw_peripheral = peripheral; tas_dev->hw_init = false; @@ -1325,6 +1413,7 @@ static struct sdw_driver tas_sdw_driver = { }; module_sdw_driver(tas_sdw_driver); +MODULE_IMPORT_NS("SND_SOC_SDCA"); MODULE_AUTHOR("Texas Instruments Inc."); MODULE_DESCRIPTION("ASoC TAS2783 SoundWire Driver"); MODULE_LICENSE("GPL"); From ed73984a9e3c73761125e97a34f20a11efcf9712 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Wed, 15 Oct 2025 09:32:27 +0530 Subject: [PATCH 3/7] ASoC: tas2783A: use custom fw binary parsing logic Use fw binary parsing logic same as windows as same the same will be used in Linux Signed-off-by: Niranjan H Y --- v2: - convert dbg to err log for firmware size mimatch issue - checkpatch error fix for logs - remove unwanted empty line - add software reset before fw download ASoC: tas2783A: add sw reset for firmware download --- sound/soc/codecs/tas2783-sdw.c | 147 +++++++++++++++++++++------------ sound/soc/codecs/tas2783.h | 1 + 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 56642371b7155b..54e04826960b13 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -36,8 +36,8 @@ #include "tas2783.h" #define TIMEOUT_FW_DL_MS (3000) -#define FW_DL_OFFSET 36 -#define FW_FL_HDR 12 +#define FW_DL_OFFSET 84 /* binary file information */ +#define FW_FL_HDR 20 /* minimum number of bytes in one chunk */ #define TAS2783_PROBE_TIMEOUT 5000 #define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \ 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92) @@ -51,11 +51,22 @@ static const u32 tas2783_cali_reg[] = { TAS2783_CAL_TLIM, }; -struct bin_header_t { - u16 vendor_id; - u16 version; +struct tas_fw_hdr { + u32 size; + u32 version_offset; + u32 plt_id; + u32 ppc3_ver; + u32 timestamp; + u8 ddc_name[64]; +}; + +struct tas_fw_file { + u32 vendor_id; u32 file_id; + u32 version; u32 length; + u32 dest_addr; + u8 *fw_data; }; struct raw_init_data { @@ -90,7 +101,7 @@ struct tas2783_prv { wait_queue_head_t fw_wait; bool fw_dl_task_done; bool fw_dl_success; - struct reg_sequence *init_data; + const struct reg_sequence *init_data; int num_init_data; }; @@ -744,13 +755,28 @@ static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev) return ret; } -static s32 read_header(const u8 *data, struct bin_header_t *hdr) +static s32 tas_fw_read_hdr(const u8 *data, struct tas_fw_hdr *hdr) +{ + hdr->size = get_unaligned_le32(data); + hdr->version_offset = get_unaligned_le32(&data[4]); + hdr->plt_id = get_unaligned_le32(&data[8]); + hdr->ppc3_ver = get_unaligned_le32(&data[12]); + memcpy(hdr->ddc_name, &data[16], 64); + hdr->timestamp = get_unaligned_le32(&data[80]); + + return 84; +} + +static s32 tas_fw_get_next_file(const u8 *data, struct tas_fw_file *file) { - hdr->vendor_id = get_unaligned_le16(&data[0]); - hdr->file_id = get_unaligned_le32(&data[2]); - hdr->version = get_unaligned_le16(&data[6]); - hdr->length = get_unaligned_le32(&data[8]); - return 12; + file->vendor_id = get_unaligned_le32(&data[0]); + file->file_id = get_unaligned_le32(&data[4]); + file->version = get_unaligned_le32(&data[8]); + file->length = get_unaligned_le32(&data[12]); + file->dest_addr = get_unaligned_le32(&data[16]); + file->fw_data = (u8 *)&data[20]; + + return file->length + sizeof(u32) * 5; } static void tas2783_fw_ready(const struct firmware *fmw, void *context) @@ -758,65 +784,68 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context) struct tas2783_prv *tas_dev = (struct tas2783_prv *)context; const u8 *buf = NULL; - s32 offset = 0, img_sz, file_blk_size, ret; - struct bin_header_t hdr; + s32 img_sz, ret, cur_file; + s32 offset = 0; + + struct tas_fw_hdr *hdr __free(kfree) = kzalloc(sizeof(*hdr), GFP_KERNEL); + struct tas_fw_file *file __free(kfree) = kzalloc(sizeof(*file), GFP_KERNEL); + if (!file || !hdr) { + ret = -ENOMEM; + goto out; + } if (!fmw || !fmw->data) { - /* No firmware binary, devices will work in ROM mode. */ + /* firmware binary not found*/ dev_err(tas_dev->dev, - "Failed to read %s, no side-effect on driver running\n", + "Failed to read fw binary %s\n", tas_dev->rca_binaryname); ret = -EINVAL; goto out; } - mutex_lock(&tas_dev->pde_lock); img_sz = fmw->size; buf = fmw->data; - offset += FW_DL_OFFSET; - while (offset < (img_sz - FW_FL_HDR)) { - memset(&hdr, 0, sizeof(hdr)); - offset += read_header(&buf[offset], &hdr); - dev_dbg(tas_dev->dev, - "vndr=%d, file=%d, version=%d, len=%d, off=%d\n", - hdr.vendor_id, hdr.file_id, hdr.version, - hdr.length, offset); - /* size also includes the header */ - file_blk_size = hdr.length - FW_FL_HDR; - - switch (hdr.file_id) { - case 0: - ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, - PRAM_ADDR_START, file_blk_size, - &buf[offset]); - if (ret < 0) - dev_err(tas_dev->dev, - "PRAM update failed: %d", ret); - break; - - case 1: - ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, - YRAM_ADDR_START, file_blk_size, - &buf[offset]); - if (ret < 0) - dev_err(tas_dev->dev, - "YRAM update failed: %d", ret); + offset += tas_fw_read_hdr(buf, hdr); + if (hdr->size != img_sz) { + ret = -EINVAL; + dev_err(tas_dev->dev, "firmware size mismatch with header"); + goto out; + } - break; + if (img_sz < FW_DL_OFFSET) { + ret = -EINVAL; + dev_err(tas_dev->dev, "unexpected size, size is too small"); + goto out; + } - default: - ret = -EINVAL; - dev_err(tas_dev->dev, "Unsupported file"); + mutex_lock(&tas_dev->pde_lock); + while (offset < (img_sz - FW_FL_HDR)) { + offset += tas_fw_get_next_file(&buf[offset], file); + dev_dbg(tas_dev->dev, + "v=%d, fid=%d, ver=%d, len=%d, daddr=0x%x, fw=%p", + file->vendor_id, file->file_id, + file->version, file->length, + file->dest_addr, file->fw_data); + + ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral, + file->dest_addr, + file->length, + file->fw_data); + if (ret < 0) { + dev_err(tas_dev->dev, + "FW download failed: %d", ret); break; } - - if (ret == 0) - offset += file_blk_size; - else - break; + cur_file++; } mutex_unlock(&tas_dev->pde_lock); - tas2783_update_calibdata(tas_dev); + + if (cur_file == 0) { + dev_err(tas_dev->dev, "fw with no files"); + ret = -EINVAL; + } else { + tas2783_update_calibdata(tas_dev); + } out: if (!ret) @@ -1204,6 +1233,14 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) tas_dev->fw_dl_task_done = false; tas_dev->fw_dl_success = false; + + ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1); + if (ret) { + dev_err(dev, "sw reset failed, err=%d", ret); + return ret; + } + usleep_range(2000, 2200); + scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname), "tas2783-%01x.bin", unique_id); diff --git a/sound/soc/codecs/tas2783.h b/sound/soc/codecs/tas2783.h index 794333e0a35029..bf34319c9a9fb7 100644 --- a/sound/soc/codecs/tas2783.h +++ b/sound/soc/codecs/tas2783.h @@ -28,6 +28,7 @@ #define TASDEV_REG_SDW(book, page, reg) (((book) * 256 * 128) + \ 0x800000 + ((page) * 128) + (reg)) +#define TAS2783_SW_RESET TASDEV_REG_SDW(0x0, 0x00, 0x01) /* Volume control */ #define TAS2783_DVC_LVL TASDEV_REG_SDW(0x0, 0x00, 0x1A) #define TAS2783_AMP_LEVEL TASDEV_REG_SDW(0x0, 0x00, 0x03) From 9b5ed96a951b8cd23199349f0623b759ff5273a4 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Thu, 23 Oct 2025 17:43:01 +0530 Subject: [PATCH 4/7] ASoC: tas2783A: update default init writes Remove unwanted initialistaion writes to the device which will now be part of the either firmware or acpi table. Signed-off-by: Niranjan H Y --- v2: - update commit message --- sound/soc/codecs/tas2783-sdw.c | 54 +--------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 54e04826960b13..89385efd8149b4 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -306,7 +306,7 @@ static const struct reg_default tas2783_reg_default[] = { }; static const struct reg_sequence tas2783_init_seq[] = { - REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0x00), 0x04), + REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PPU21, 0x10, 0x00), 0x01), REG_SEQ0(0x00800418, 0x00), REG_SEQ0(0x00800419, 0x00), REG_SEQ0(0x0080041a, 0x00), @@ -316,60 +316,19 @@ static const struct reg_sequence tas2783_init_seq[] = { REG_SEQ0(0x0080042a, 0x00), REG_SEQ0(0x0080042b, 0x00), REG_SEQ0(SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU23, 0x1, 0x00), 0x00), - REG_SEQ0(0x0080005c, 0xD9), - REG_SEQ0(0x00800082, 0x20), - REG_SEQ0(0x008000a1, 0x00), - REG_SEQ0(0x00800097, 0xc8), - REG_SEQ0(0x00800099, 0x20), - REG_SEQ0(0x008000c7, 0xaa), - REG_SEQ0(0x008000b5, 0x74), - REG_SEQ0(0x00800082, 0x20), - REG_SEQ0(0x00807e8d, 0x0d), - REG_SEQ0(0x00807eb9, 0x53), - REG_SEQ0(0x00807ebe, 0x42), - REG_SEQ0(0x00807ec5, 0x37), - REG_SEQ0(0x00800066, 0x92), - REG_SEQ0(0x00800003, 0x28), REG_SEQ0(0x00800004, 0x21), REG_SEQ0(0x00800005, 0x41), REG_SEQ0(0x00800006, 0x00), REG_SEQ0(0x00800007, 0x20), - REG_SEQ0(0x0080000c, 0x10), - REG_SEQ0(0x00800013, 0x08), REG_SEQ0(0x00800015, 0x00), - REG_SEQ0(0x00800017, 0x80), - REG_SEQ0(0x0080001a, 0x00), - REG_SEQ0(0x0080001b, 0x22), - REG_SEQ0(0x0080001c, 0x36), - REG_SEQ0(0x0080001d, 0x01), - REG_SEQ0(0x0080001f, 0x00), - REG_SEQ0(0x00800020, 0x2e), - REG_SEQ0(0x00800034, 0x06), - REG_SEQ0(0x00800035, 0xb9), REG_SEQ0(0x00800036, 0xad), REG_SEQ0(0x00800037, 0xa8), - REG_SEQ0(0x00800038, 0x00), - REG_SEQ0(0x0080003b, 0xfc), - REG_SEQ0(0x0080003d, 0xdd), - REG_SEQ0(0x00800040, 0xf6), - REG_SEQ0(0x00800041, 0x14), - REG_SEQ0(0x0080005c, 0x19), - REG_SEQ0(0x0080005d, 0x80), - REG_SEQ0(0x00800063, 0x48), - REG_SEQ0(0x00800065, 0x08), - REG_SEQ0(0x00800067, 0x00), - REG_SEQ0(0x0080006a, 0x12), REG_SEQ0(0x0080006b, 0x7b), REG_SEQ0(0x0080006c, 0x00), REG_SEQ0(0x0080006d, 0x00), REG_SEQ0(0x0080006e, 0x1a), REG_SEQ0(0x0080006f, 0x00), - REG_SEQ0(0x00800070, 0x96), REG_SEQ0(0x00800071, 0x02), - REG_SEQ0(0x00800073, 0x08), - REG_SEQ0(0x00800075, 0xe0), - REG_SEQ0(0x0080007a, 0x60), - REG_SEQ0(0x008000bd, 0x00), REG_SEQ0(0x008000be, 0x00), REG_SEQ0(0x008000bf, 0x00), REG_SEQ0(0x008000c0, 0x00), @@ -377,17 +336,6 @@ static const struct reg_sequence tas2783_init_seq[] = { REG_SEQ0(0x008000c2, 0x00), REG_SEQ0(0x008000c3, 0x00), REG_SEQ0(0x008000c4, 0x00), - REG_SEQ0(0x008000c5, 0x00), - REG_SEQ0(0x00800008, 0x49), - REG_SEQ0(0x00800009, 0x02), - REG_SEQ0(0x0080000a, 0x1a), - REG_SEQ0(0x0080000d, 0x93), - REG_SEQ0(0x0080000e, 0x82), - REG_SEQ0(0x0080000f, 0x42), - REG_SEQ0(0x00800010, 0x84), - REG_SEQ0(0x00800014, 0x0a), - REG_SEQ0(0x00800016, 0x00), - REG_SEQ0(0x00800060, 0x21), }; static int tas2783_sdca_mbq_size(struct device *dev, u32 reg) From e6fe84e6ee8a377833320dd1e2ebfeeea20b4f83 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Wed, 15 Oct 2025 16:21:04 +0530 Subject: [PATCH 5/7] ASoC: tas2783A: fix error log for calibration data The current error message is misleading for the calib data. Fix error message to indicate that calibration data is not valid. Signed-off-by: Niranjan H Y --- v2: - Update commit message --- sound/soc/codecs/tas2783-sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 89385efd8149b4..6ff8b2cd545bc4 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -644,7 +644,8 @@ static void tas2783_set_calib_params_to_device(struct tas2783_prv *tas_dev, u32 } if (device_num == dev_count) - dev_err(tas_dev->dev, "device not found\n"); + dev_err(tas_dev->dev, + "unique id not found in the calib data\n"); else dev_dbg(tas_dev->dev, "calib data update done\n"); } From c458b9230bc2a99cbbb0dd0466706caf0d5c4378 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Tue, 21 Oct 2025 11:42:14 +0530 Subject: [PATCH 6/7] ASoc: tas2783A: fw name based on system details The firmware file for tas2783A contains the device and algorithm settings. So the firmware files are unique for a system and driver should have the ability to distinctly identify and pick the right firmware. This commit adds the method to uniquely identify the firmware for a system based on the below format. --.bin * Subsystem is the PCI device subsystem-id * Link is the SoundWire link id on which the device recides. * Unique is the SoundWire slave unique id in the system. Signed-off-by: Niranjan H Y --- v2: - rename get_hwid to get_pci_dev - update commit message --- sound/soc/codecs/tas2783-sdw.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 6ff8b2cd545bc4..d1c0838e210d4e 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1171,8 +1172,21 @@ static const struct dev_pm_ops tas2783_sdca_pm = { RUNTIME_PM_OPS(tas2783_sdca_dev_suspend, tas2783_sdca_dev_resume, NULL) }; +static struct pci_dev *tas_get_pci_dev(struct sdw_slave *peripheral) +{ + struct device *dev = &peripheral->dev; + + for (; dev; dev = dev->parent) + if (dev->bus == &pci_bus_type) + return to_pci_dev(dev); + + return NULL; +} + static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) { + struct pci_dev *pci; + struct sdw_bus *bus; struct tas2783_prv *tas_dev = dev_get_drvdata(dev); s32 ret; u8 unique_id = tas_dev->sdw_peripheral->id.unique_id; @@ -1180,6 +1194,13 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) if (tas_dev->hw_init) return 0; + pci = tas_get_pci_dev(slave); + if (!pci) { + dev_err(dev, "pci device id can't be read"); + return -EINVAL; + } + + bus = slave->bus; tas_dev->fw_dl_task_done = false; tas_dev->fw_dl_success = false; @@ -1190,8 +1211,10 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) } usleep_range(2000, 2200); + /* subsystem_id-link_id-unique_id */ scnprintf(tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname), - "tas2783-%01x.bin", unique_id); + "%04X-%1X-%1X.bin", pci->subsystem_device, bus->link_id, + unique_id); ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, tas_dev->rca_binaryname, tas_dev->dev, From bc01d50e52391550cf25843ccd57b83a14a13d69 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Thu, 23 Oct 2025 21:47:11 +0530 Subject: [PATCH 7/7] ASoc: tas2783A: acpi match for 4 channel for mtl Add changes to support 4 tas2783A devices on mtl platform. The supported unique IDs are updated to 9, a, c, d, where c and d are configured to play left channels and 9 and a are configured to play right channel. Signed-off-by: Niranjan H Y --- v2: - update commit message --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index ec9fd8486c0534..f12d42986a758e 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -950,7 +950,7 @@ static const struct snd_soc_acpi_adr_device cs42l42_0_adr[] = { static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = { { - .adr = 0x0000380102000001ull, + .adr = 0x00003c0102000001ull, .num_endpoints = 1, .endpoints = &spk_l_endpoint, .name_prefix = "tas2783-1" @@ -960,6 +960,18 @@ static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = { .num_endpoints = 1, .endpoints = &spk_r_endpoint, .name_prefix = "tas2783-2" + }, + { + .adr = 0x00003d0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "tas2783-3" + }, + { + .adr = 0x00003a0102000001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "tas2783-4" } };