From 1b435e405d63155d2391c27054cf98237d11d0a4 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Wed, 9 Nov 2022 17:13:06 +0800 Subject: ASoC: Intel: sof_sdw_rt1308: add BQ params for the Dell models The Dell SKU 0A5D/0A5E/0990/098F model needs the BQ params for the tweeter/woofer. Signed-off-by: Shuming Fan Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20221109091306.17221-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index ee9857dc3135..a3bbdc261a4a 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -510,6 +510,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt1308-aif", .ops = &sof_sdw_rt1308_i2s_ops, .init = sof_sdw_rt1308_init, + .exit = sof_sdw_rt1308_exit, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { -- cgit v1.2.3 From cf6946d95005add8437f874e0952ec4f28fe5c02 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Wed, 9 Nov 2022 17:13:17 +0800 Subject: ASoC: Intel: sof_sdw_rt1316: add BQ params for the Dell models The Dell SKU 0B00/0B01/0AFE/0AFF model needs the BQ params for the tweeter/woofer. Signed-off-by: Shuming Fan Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20221109091317.17240-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 1 + sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h | 138 ++++++++++++++++++++++ sound/soc/intel/boards/sof_sdw_common.h | 1 + sound/soc/intel/boards/sof_sdw_rt1316.c | 119 +++++++++++++++++++ 4 files changed, 259 insertions(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index a3bbdc261a4a..949adfdd0e3c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -518,6 +518,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "rt1316-aif", .init = sof_sdw_rt1316_init, + .exit = sof_sdw_rt1316_exit, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { diff --git a/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h b/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h index bb90a5922fd2..82230fbb5b05 100644 --- a/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h +++ b/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h @@ -9,6 +9,7 @@ #define SND_SOC_SOF_SDW_AMP_COEFF_H #define RT1308_MAX_BQ_REG 480 +#define RT1316_MAX_BQ_REG 580 static const u8 dell_0a5d_bq_params[] = { 0xb0, 0xc5, 0x00, /* address: 0xc5b0; data: 0x00 */ @@ -159,4 +160,141 @@ static const u8 dell_0a5d_bq_params[] = { 0x50, 0xc5, 0x01, }; +static const u8 dell_0b00_bq_params[] = { + 0x03, 0xc2, 0x00, + 0x04, 0xc2, 0xb2, + 0x05, 0xc2, 0xe0, + 0x06, 0xc2, 0x3a, + 0x07, 0xc2, 0x01, + 0x08, 0xc2, 0x65, + 0x09, 0xc2, 0xc0, + 0x0a, 0xc2, 0x75, + 0x0b, 0xc2, 0x00, + 0x0c, 0xc2, 0xb2, + 0x0d, 0xc2, 0xe0, + 0x0e, 0xc2, 0x3a, + 0x0f, 0xc2, 0xf7, + 0x10, 0xc2, 0x4d, + 0x11, 0xc2, 0x5b, + 0x12, 0xc2, 0xe9, + 0x13, 0xc2, 0x03, + 0x14, 0xc2, 0x7e, + 0x15, 0xc2, 0x25, + 0x16, 0xc2, 0x01, + 0x17, 0xc2, 0x07, + 0x18, 0xc2, 0xfd, + 0x19, 0xc2, 0x15, + 0x1a, 0xc2, 0x04, + 0x1b, 0xc2, 0xf0, + 0x1c, 0xc2, 0x05, + 0x1d, 0xc2, 0xd5, + 0x1e, 0xc2, 0xf7, + 0x1f, 0xc2, 0x07, + 0x20, 0xc2, 0xfd, + 0x21, 0xc2, 0x15, + 0x22, 0xc2, 0x04, + 0x23, 0xc2, 0xf0, + 0x24, 0xc2, 0x05, + 0x25, 0xc2, 0xd8, + 0x26, 0xc2, 0x17, + 0x27, 0xc2, 0x07, + 0x28, 0xc2, 0xfa, + 0x29, 0xc2, 0x2c, + 0x2a, 0xc2, 0x29, + 0x2b, 0xc2, 0x07, + 0x2c, 0xc2, 0x74, + 0x2d, 0xc2, 0xe0, + 0x2e, 0xc2, 0x33, + 0x2f, 0xc2, 0xf1, + 0x30, 0xc2, 0x16, + 0x31, 0xc2, 0x3f, + 0x32, 0xc2, 0x9b, + 0x33, 0xc2, 0x07, + 0x34, 0xc2, 0x74, + 0x35, 0xc2, 0xe0, + 0x36, 0xc2, 0x33, + 0x37, 0xc2, 0xf1, + 0x38, 0xc2, 0x29, + 0x39, 0xc2, 0xb0, + 0x3a, 0xc2, 0x4d, + 0x3b, 0xc2, 0x06, + 0x3c, 0xc2, 0xfd, + 0x3d, 0xc2, 0x31, + 0x3e, 0xc2, 0x18, + 0x3f, 0xc2, 0x07, + 0x40, 0xc2, 0xfd, + 0x41, 0xc2, 0x15, + 0x42, 0xc2, 0x04, + 0x43, 0xc2, 0xf0, + 0x44, 0xc2, 0x05, + 0x45, 0xc2, 0xd5, + 0x46, 0xc2, 0xf7, + 0x47, 0xc2, 0x07, + 0x48, 0xc2, 0xfd, + 0x49, 0xc2, 0x15, + 0x4a, 0xc2, 0x04, + 0x4b, 0xc2, 0xf0, + 0x4c, 0xc2, 0x05, + 0x4d, 0xc2, 0xd8, + 0x4e, 0xc2, 0x17, + 0x4f, 0xc2, 0x07, + 0x50, 0xc2, 0xfa, + 0x51, 0xc2, 0x2c, + 0x52, 0xc2, 0x29, + 0x0b, 0xc0, 0x30, + 0x80, 0xc3, 0x13, + 0x81, 0xc3, 0x88, + 0x82, 0xc3, 0x17, + 0x83, 0xc3, 0x70, + 0x84, 0xc3, 0x00, + 0x85, 0xc3, 0x00, + 0x86, 0xc3, 0xff, + 0x87, 0xc3, 0xee, + 0x88, 0xc3, 0x02, + 0x92, 0xc3, 0x00, + 0x93, 0xc3, 0x14, + 0x94, 0xc3, 0x00, + 0x95, 0xc3, 0x14, + 0x96, 0xc3, 0x00, + 0x97, 0xc3, 0x00, + 0x98, 0xc3, 0x00, + 0x99, 0xc3, 0x00, + 0x9a, 0xc3, 0x01, + 0x89, 0xc3, 0x03, + 0x8a, 0xc3, 0xe8, + 0x8b, 0xc3, 0x03, + 0x8c, 0xc3, 0xb6, + 0x8d, 0xc3, 0x00, + 0x8e, 0xc3, 0x00, + 0x8f, 0xc3, 0xff, + 0x90, 0xc3, 0xee, + 0x91, 0xc3, 0x01, + 0x9b, 0xc3, 0x00, + 0x9c, 0xc3, 0x14, + 0x9d, 0xc3, 0x00, + 0x9e, 0xc3, 0x14, + 0x9f, 0xc3, 0x00, + 0xa0, 0xc3, 0x00, + 0xa1, 0xc3, 0x00, + 0xa2, 0xc3, 0x00, + 0xa3, 0xc3, 0x01, + 0x61, 0xc2, 0x08, + 0x62, 0xc2, 0x00, + 0x63, 0xc2, 0x00, + 0x64, 0xc2, 0x00, + 0x65, 0xc2, 0x08, + 0x66, 0xc2, 0x00, + 0x67, 0xc2, 0x00, + 0x68, 0xc2, 0x00, + 0x69, 0xc2, 0x08, + 0x6a, 0xc2, 0x00, + 0x6b, 0xc2, 0x00, + 0x6c, 0xc2, 0x00, + 0x6d, 0xc2, 0x08, + 0x6e, 0xc2, 0x00, + 0x6f, 0xc2, 0x00, + 0x70, 0xc2, 0x00, + 0x00, 0xc2, 0xc0, +}; + #endif diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 772af23e7497..bac93fdc8d82 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -141,6 +141,7 @@ int sof_sdw_rt1316_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); +int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); /* RT715 support */ int sof_sdw_rt715_init(struct snd_soc_card *card, diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c index 58194b380232..f6bbea0d3810 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1316.c +++ b/sound/soc/intel/boards/sof_sdw_rt1316.c @@ -11,7 +11,83 @@ #include #include #include +#include +#include +#include #include "sof_sdw_common.h" +#include "sof_sdw_amp_coeff_tables.h" + +struct rt1316_platform_data { + const unsigned char *bq_params; + const unsigned int bq_params_cnt; +}; + +static const struct rt1316_platform_data dell_0b00_platform_data = { + .bq_params = dell_0b00_bq_params, + .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params), +}; + +static const struct dmi_system_id dmi_platform_data[] = { + /* AlderLake devices */ + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, +}; + +static int rt1316_add_device_props(struct device *sdw_dev) +{ + struct property_entry props[3] = {}; + struct fwnode_handle *fwnode; + const struct dmi_system_id *dmi_data; + const struct rt1316_platform_data *pdata; + unsigned char params[RT1316_MAX_BQ_REG]; + int ret; + + dmi_data = dmi_first_match(dmi_platform_data); + if (!dmi_data) + return 0; + + pdata = dmi_data->driver_data; + memcpy(¶ms, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt); + + props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params); + props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt); + + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); + + return ret; +} static const struct snd_soc_dapm_widget rt1316_widgets[] = { SND_SOC_DAPM_SPK("Speaker", NULL), @@ -89,12 +165,33 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd) return second_spk_init(rtd); } +int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (ctx->amp_dev1) { + device_remove_software_node(ctx->amp_dev1); + put_device(ctx->amp_dev1); + } + + if (ctx->amp_dev2) { + device_remove_software_node(ctx->amp_dev2); + put_device(ctx->amp_dev2); + } + + return 0; +} + int sof_sdw_rt1316_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) { + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct device *sdw_dev1, *sdw_dev2; + int ret; + /* Count amp number and do init on playback link only. */ if (!playback) return 0; @@ -104,6 +201,28 @@ int sof_sdw_rt1316_init(struct snd_soc_card *card, dai_links->init = first_spk_init; if (info->amp_num == 2) { + sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); + if (!sdw_dev1) + return -EPROBE_DEFER; + + ret = rt1316_add_device_props(sdw_dev1); + if (ret < 0) { + put_device(sdw_dev1); + return ret; + } + ctx->amp_dev1 = sdw_dev1; + + sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name); + if (!sdw_dev2) + return -EPROBE_DEFER; + + ret = rt1316_add_device_props(sdw_dev2); + if (ret < 0) { + put_device(sdw_dev2); + return ret; + } + ctx->amp_dev2 = sdw_dev2; + /* * if two 1316s are in one dai link, the init function * in this dai link will be first set for the first speaker, -- cgit v1.2.3 From d608bc44181c1010eca165e895bbe630077b2e16 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Thu, 10 Nov 2022 16:54:28 -0600 Subject: ASoC: Intel: sof_sdw: Add support for SKU 0C10 product MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SKU 0C10 product supports SoundWire capture from local microphone and two SoundWire amplifiers(no headset codec). Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Gongjun Song Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20221110225432.144184-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index ee9857dc3135..ed4ca10b6710 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -355,6 +355,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | RT711_JD2), }, + /* RaptorLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"), + }, + /* No Jack */ + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_FOUR_SPK), + }, /* MeteorLake devices */ { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From 880bf4b47fc1810616e254738bb40fe108c01cb9 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Thu, 10 Nov 2022 16:54:30 -0600 Subject: ASoC: Intel: sof_sdw: Add support for SKU 0C40 product MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SKU 0C40 product supports a SoundWire headset codec, SoundWire capture from local microphones and two SoundWire amplifiers. Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Gongjun Song Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20221110225432.144184-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index ed4ca10b6710..47f743debc72 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -366,6 +366,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, /* MeteorLake devices */ { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From a9248c868c39440369c614598b2465d1a1b1cf62 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Tue, 22 Nov 2022 13:20:52 +0800 Subject: ASoC: Intel: sof_sdw: Add support for SKU 0C4F product SKU 0C4F product supports a SoundWire headset codec, SoundWire capture from local microphones and two SoundWire amplifiers. Signed-off-by: Gongjun Song Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20221122052052.687281-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 172f008adea0..ffef492e3f3d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -376,6 +376,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { RT711_JD2 | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, /* MeteorLake devices */ { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From 8c4b3a8ea2c04d7979f378165e5c3dfa270659b6 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Thu, 17 Nov 2022 08:27:56 +0800 Subject: ASoC: intel: sof_sdw: add rt1318 codec support. Add rt1318 sdca codec support in sof_sdw machine driver. Signed-off-by: Gongjun Song Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20221117002758.496211-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + sound/soc/intel/boards/Makefile | 4 +- sound/soc/intel/boards/sof_sdw.c | 7 ++ sound/soc/intel/boards/sof_sdw_common.h | 7 ++ sound/soc/intel/boards/sof_sdw_rt1318.c | 120 ++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 sound/soc/intel/boards/sof_sdw_rt1318.c (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index aa12d7e3dd2f..a472de1909f4 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -668,6 +668,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_RT1308_SDW select SND_SOC_RT1308 select SND_SOC_RT1316_SDW + select SND_SOC_RT1318_SDW select SND_SOC_RT715_SDW select SND_SOC_RT715_SDCA_SDW select SND_SOC_RT5682_SDW diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 53458e748191..7e1a4ff77ac3 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -37,8 +37,8 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o snd-soc-sof-sdw-objs += sof_sdw.o \ - sof_sdw_max98373.o \ - sof_sdw_rt1308.o sof_sdw_rt1316.o \ + sof_sdw_max98373.o sof_sdw_rt1308.o \ + sof_sdw_rt1316.o sof_sdw_rt1318.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ sof_sdw_rt711.o sof_sdw_rt711_sdca.o \ sof_sdw_rt715.o sof_sdw_rt715_sdca.o \ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 172f008adea0..b86b1c5579bb 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -542,6 +542,13 @@ static struct sof_sdw_codec_info codec_info_list[] = { .exit = sof_sdw_rt1316_exit, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, + { + .part_id = 0x1318, + .direction = {true, true}, + .dai_name = "rt1318-aif", + .init = sof_sdw_rt1318_init, + .codec_type = SOF_SDW_CODEC_TYPE_AMP, + }, { .part_id = 0x714, .version_id = 3, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index bac93fdc8d82..54a50f7da4da 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -143,6 +143,13 @@ int sof_sdw_rt1316_init(struct snd_soc_card *card, bool playback); int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +/* RT1318 support */ +int sof_sdw_rt1318_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* RT715 support */ int sof_sdw_rt715_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, diff --git a/sound/soc/intel/boards/sof_sdw_rt1318.c b/sound/soc/intel/boards/sof_sdw_rt1318.c new file mode 100644 index 000000000000..dbee4bf5c814 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt1318.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2022 Intel Corporation + +/* + * sof_sdw_rt1318 - Helpers to handle RT1318 from generic machine driver + */ + +#include +#include +#include +#include +#include +#include +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget rt1318_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +/* + * dapm routes for rt1318 will be registered dynamically according + * to the number of rt1318 used. The first two entries will be registered + * for one codec case, and the last two entries are also registered + * if two 1318s are used. + */ +static const struct snd_soc_dapm_route rt1318_map[] = { + { "Speaker", NULL, "rt1318-1 SPOL" }, + { "Speaker", NULL, "rt1318-1 SPOR" }, + { "Speaker", NULL, "rt1318-2 SPOL" }, + { "Speaker", NULL, "rt1318-2 SPOR" }, +}; + +static const struct snd_kcontrol_new rt1318_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int first_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:rt1318", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt1318_controls, + ARRAY_SIZE(rt1318_controls)); + if (ret) { + dev_err(card->dev, "rt1318 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt1318_widgets, + ARRAY_SIZE(rt1318_widgets)); + if (ret) { + dev_err(card->dev, "rt1318 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static int second_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map + 2, 2); + if (ret) + dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); + + return ret; +} + +static int all_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = first_spk_init(rtd); + if (ret) + return ret; + + return second_spk_init(rtd); +} + +int sof_sdw_rt1318_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* Count amp number and do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + if (info->amp_num == 1) + dai_links->init = first_spk_init; + + if (info->amp_num == 2) { + /* + * if two 1318s are in one dai link, the init function + * in this dai link will be first set for the first speaker, + * and it should be reset to initialize all speakers when + * the second speaker is found. + */ + if (dai_links->init) + dai_links->init = all_spk_init; + else + dai_links->init = second_spk_init; + } + + return 0; +} -- cgit v1.2.3 From d84e10da17e7fc07e758a8b8f1fd6150bcd8ba08 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Thu, 17 Nov 2022 08:27:57 +0800 Subject: ASoC: Intel: sof_sdw: Add support for SKU 0C11 product SKU 0C11 product supports a SoundWire headset codec, SoundWire capture from local microphones and two SoundWire amplifiers. Signed-off-by: Gongjun Song Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20221117002758.496211-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index b86b1c5579bb..33b404299430 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -366,6 +366,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, { .callback = sof_sdw_quirk_cb, .matches = { -- cgit v1.2.3 From 5c10da436ebd93f9bfa244ea933773d14b566499 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Tue, 6 Dec 2022 15:25:06 -0600 Subject: ASoC: Intel: sof_sdw: use common helpers for all Realtek amps sof_sdw_rt1308.c/sof_sdw_rt1316.c/sof_sdw_rt1318.c handle amp in basically the same way, optimized and merged into one file. Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Gongjun Song Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20221206212507.359993-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 3 +- sound/soc/intel/boards/sof_sdw.c | 10 +- sound/soc/intel/boards/sof_sdw_common.h | 20 +- sound/soc/intel/boards/sof_sdw_rt1308.c | 278 ------------------------- sound/soc/intel/boards/sof_sdw_rt1316.c | 239 --------------------- sound/soc/intel/boards/sof_sdw_rt1318.c | 120 ----------- sound/soc/intel/boards/sof_sdw_rt_amp.c | 359 ++++++++++++++++++++++++++++++++ 7 files changed, 369 insertions(+), 660 deletions(-) delete mode 100644 sound/soc/intel/boards/sof_sdw_rt1308.c delete mode 100644 sound/soc/intel/boards/sof_sdw_rt1316.c delete mode 100644 sound/soc/intel/boards/sof_sdw_rt1318.c create mode 100644 sound/soc/intel/boards/sof_sdw_rt_amp.c (limited to 'sound/soc/intel/boards/sof_sdw.c') diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 7e1a4ff77ac3..d1fd7a2b32db 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -37,8 +37,7 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o snd-soc-sof-sdw-objs += sof_sdw.o \ - sof_sdw_max98373.o sof_sdw_rt1308.o \ - sof_sdw_rt1316.o sof_sdw_rt1318.o \ + sof_sdw_max98373.o sof_sdw_rt_amp.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ sof_sdw_rt711.o sof_sdw_rt711_sdca.o \ sof_sdw_rt715.o sof_sdw_rt715_sdca.o \ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index b58c7b35599d..d2ed807abde9 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -550,23 +550,23 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, false}, .dai_name = "rt1308-aif", .ops = &sof_sdw_rt1308_i2s_ops, - .init = sof_sdw_rt1308_init, - .exit = sof_sdw_rt1308_exit, + .init = sof_sdw_rt_amp_init, + .exit = sof_sdw_rt_amp_exit, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { .part_id = 0x1316, .direction = {true, true}, .dai_name = "rt1316-aif", - .init = sof_sdw_rt1316_init, - .exit = sof_sdw_rt1316_exit, + .init = sof_sdw_rt_amp_init, + .exit = sof_sdw_rt_amp_exit, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { .part_id = 0x1318, .direction = {true, true}, .dai_name = "rt1318-aif", - .init = sof_sdw_rt1318_init, + .init = sof_sdw_rt_amp_init, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 54a50f7da4da..350010b0e5f4 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -125,30 +125,18 @@ int sof_sdw_rt700_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); -/* RT1308 support */ +/* RT1308 I2S support */ extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; -int sof_sdw_rt1308_init(struct snd_soc_card *card, +/* generic amp support */ +int sof_sdw_rt_amp_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); /* RT1316 support */ -int sof_sdw_rt1316_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - -/* RT1318 support */ -int sof_sdw_rt1318_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); /* RT715 support */ int sof_sdw_rt715_init(struct snd_soc_card *card, diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c deleted file mode 100644 index a19b055b9c6f..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt1308 - Helpers to handle RT1308 from generic machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sof_sdw_common.h" -#include "sof_sdw_amp_coeff_tables.h" -#include "../../codecs/rt1308.h" - -struct rt1308_platform_data { - const unsigned char *bq_params; - const unsigned int bq_params_cnt; -}; - -static const struct rt1308_platform_data dell_0a5d_platform_data = { - .bq_params = dell_0a5d_bq_params, - .bq_params_cnt = ARRAY_SIZE(dell_0a5d_bq_params), -}; - -static const struct dmi_system_id dmi_platform_data[] = { - /* CometLake devices */ - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990") - }, - .driver_data = (void *)&dell_0a5d_platform_data, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F") - }, - .driver_data = (void *)&dell_0a5d_platform_data, - }, - /* TigerLake devices */ - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") - }, - .driver_data = (void *)&dell_0a5d_platform_data, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") - }, - .driver_data = (void *)&dell_0a5d_platform_data, - }, -}; - -static int rt1308_add_device_props(struct device *sdw_dev) -{ - struct property_entry props[3] = {}; - struct fwnode_handle *fwnode; - const struct dmi_system_id *dmi_data; - const struct rt1308_platform_data *pdata; - unsigned char params[RT1308_MAX_BQ_REG]; - int ret; - - dmi_data = dmi_first_match(dmi_platform_data); - if (!dmi_data) - return 0; - - pdata = dmi_data->driver_data; - memcpy(¶ms, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt); - - props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params); - props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt); - - fwnode = fwnode_create_software_node(props, NULL); - if (IS_ERR(fwnode)) - return PTR_ERR(fwnode); - - ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); - - fwnode_handle_put(fwnode); - - return ret; -} - -static const struct snd_soc_dapm_widget rt1308_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* - * dapm routes for rt1308 will be registered dynamically according - * to the number of rt1308 used. The first two entries will be registered - * for one codec case, and the last two entries are also registered - * if two 1308s are used. - */ -static const struct snd_soc_dapm_route rt1308_map[] = { - { "Speaker", NULL, "rt1308-1 SPOL" }, - { "Speaker", NULL, "rt1308-1 SPOR" }, - { "Speaker", NULL, "rt1308-2 SPOL" }, - { "Speaker", NULL, "rt1308-2 SPOR" }, -}; - -static const struct snd_kcontrol_new rt1308_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -static int first_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:rt1308", - card->components); - if (!card->components) - return -ENOMEM; - - ret = snd_soc_add_card_controls(card, rt1308_controls, - ARRAY_SIZE(rt1308_controls)); - if (ret) { - dev_err(card->dev, "rt1308 controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_widgets, - ARRAY_SIZE(rt1308_widgets)); - if (ret) { - dev_err(card->dev, "rt1308 widgets addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map, 2); - if (ret) - dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); - - return ret; -} - -static int second_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map + 2, 2); - if (ret) - dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); - - return ret; -} - -static int all_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - - ret = first_spk_init(rtd); - if (ret) - return ret; - - return second_spk_init(rtd); -} - -static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - int clk_id, clk_freq, pll_out; - int err; - - clk_id = RT1308_PLL_S_MCLK; - clk_freq = 38400000; - - pll_out = params_rate(params) * 512; - - /* Set rt1308 pll */ - err = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); - if (err < 0) { - dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", err); - return err; - } - - /* Set rt1308 sysclk */ - err = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, - SND_SOC_CLOCK_IN); - if (err < 0) { - dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", err); - return err; - } - - return 0; -} - -/* machine stream operations */ -struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { - .hw_params = rt1308_i2s_hw_params, -}; - -int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) -{ - struct mc_private *ctx = snd_soc_card_get_drvdata(card); - - if (ctx->amp_dev1) { - device_remove_software_node(ctx->amp_dev1); - put_device(ctx->amp_dev1); - } - - if (ctx->amp_dev2) { - device_remove_software_node(ctx->amp_dev2); - put_device(ctx->amp_dev2); - } - - return 0; -} - -int sof_sdw_rt1308_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - struct mc_private *ctx = snd_soc_card_get_drvdata(card); - struct device *sdw_dev1, *sdw_dev2; - int ret; - - /* Count amp number and do init on playback link only. */ - if (!playback) - return 0; - - info->amp_num++; - if (info->amp_num == 1) - dai_links->init = first_spk_init; - - if (info->amp_num == 2) { - sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); - if (!sdw_dev1) - return -EPROBE_DEFER; - - ret = rt1308_add_device_props(sdw_dev1); - if (ret < 0) { - put_device(sdw_dev1); - return ret; - } - ctx->amp_dev1 = sdw_dev1; - - sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name); - if (!sdw_dev2) - return -EPROBE_DEFER; - - ret = rt1308_add_device_props(sdw_dev2); - if (ret < 0) { - put_device(sdw_dev2); - return ret; - } - ctx->amp_dev2 = sdw_dev2; - - /* - * if two 1308s are in one dai link, the init function - * in this dai link will be first set for the first speaker, - * and it should be reset to initialize all speakers when - * the second speaker is found. - */ - if (dai_links->init) - dai_links->init = all_spk_init; - else - dai_links->init = second_spk_init; - } - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c deleted file mode 100644 index f6bbea0d3810..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt1316.c +++ /dev/null @@ -1,239 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sof_sdw_common.h" -#include "sof_sdw_amp_coeff_tables.h" - -struct rt1316_platform_data { - const unsigned char *bq_params; - const unsigned int bq_params_cnt; -}; - -static const struct rt1316_platform_data dell_0b00_platform_data = { - .bq_params = dell_0b00_bq_params, - .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params), -}; - -static const struct dmi_system_id dmi_platform_data[] = { - /* AlderLake devices */ - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") - }, - .driver_data = (void *)&dell_0b00_platform_data, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") - }, - .driver_data = (void *)&dell_0b00_platform_data, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") - }, - .driver_data = (void *)&dell_0b00_platform_data, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") - }, - .driver_data = (void *)&dell_0b00_platform_data, - }, -}; - -static int rt1316_add_device_props(struct device *sdw_dev) -{ - struct property_entry props[3] = {}; - struct fwnode_handle *fwnode; - const struct dmi_system_id *dmi_data; - const struct rt1316_platform_data *pdata; - unsigned char params[RT1316_MAX_BQ_REG]; - int ret; - - dmi_data = dmi_first_match(dmi_platform_data); - if (!dmi_data) - return 0; - - pdata = dmi_data->driver_data; - memcpy(¶ms, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt); - - props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params); - props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt); - - fwnode = fwnode_create_software_node(props, NULL); - if (IS_ERR(fwnode)) - return PTR_ERR(fwnode); - - ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); - - fwnode_handle_put(fwnode); - - return ret; -} - -static const struct snd_soc_dapm_widget rt1316_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* - * dapm routes for rt1316 will be registered dynamically according - * to the number of rt1316 used. The first two entries will be registered - * for one codec case, and the last two entries are also registered - * if two 1316s are used. - */ -static const struct snd_soc_dapm_route rt1316_map[] = { - { "Speaker", NULL, "rt1316-1 SPOL" }, - { "Speaker", NULL, "rt1316-1 SPOR" }, - { "Speaker", NULL, "rt1316-2 SPOL" }, - { "Speaker", NULL, "rt1316-2 SPOR" }, -}; - -static const struct snd_kcontrol_new rt1316_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -static int first_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:rt1316", - card->components); - if (!card->components) - return -ENOMEM; - - ret = snd_soc_add_card_controls(card, rt1316_controls, - ARRAY_SIZE(rt1316_controls)); - if (ret) { - dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets, - ARRAY_SIZE(rt1316_widgets)); - if (ret) { - dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2); - if (ret) - dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); - - return ret; -} - -static int second_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2); - if (ret) - dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); - - return ret; -} - -static int all_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - - ret = first_spk_init(rtd); - if (ret) - return ret; - - return second_spk_init(rtd); -} - -int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) -{ - struct mc_private *ctx = snd_soc_card_get_drvdata(card); - - if (ctx->amp_dev1) { - device_remove_software_node(ctx->amp_dev1); - put_device(ctx->amp_dev1); - } - - if (ctx->amp_dev2) { - device_remove_software_node(ctx->amp_dev2); - put_device(ctx->amp_dev2); - } - - return 0; -} - -int sof_sdw_rt1316_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - struct mc_private *ctx = snd_soc_card_get_drvdata(card); - struct device *sdw_dev1, *sdw_dev2; - int ret; - - /* Count amp number and do init on playback link only. */ - if (!playback) - return 0; - - info->amp_num++; - if (info->amp_num == 1) - dai_links->init = first_spk_init; - - if (info->amp_num == 2) { - sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); - if (!sdw_dev1) - return -EPROBE_DEFER; - - ret = rt1316_add_device_props(sdw_dev1); - if (ret < 0) { - put_device(sdw_dev1); - return ret; - } - ctx->amp_dev1 = sdw_dev1; - - sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name); - if (!sdw_dev2) - return -EPROBE_DEFER; - - ret = rt1316_add_device_props(sdw_dev2); - if (ret < 0) { - put_device(sdw_dev2); - return ret; - } - ctx->amp_dev2 = sdw_dev2; - - /* - * if two 1316s are in one dai link, the init function - * in this dai link will be first set for the first speaker, - * and it should be reset to initialize all speakers when - * the second speaker is found. - */ - if (dai_links->init) - dai_links->init = all_spk_init; - else - dai_links->init = second_spk_init; - } - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt1318.c b/sound/soc/intel/boards/sof_sdw_rt1318.c deleted file mode 100644 index dbee4bf5c814..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt1318.c +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2022 Intel Corporation - -/* - * sof_sdw_rt1318 - Helpers to handle RT1318 from generic machine driver - */ - -#include -#include -#include -#include -#include -#include -#include "sof_sdw_common.h" - -static const struct snd_soc_dapm_widget rt1318_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* - * dapm routes for rt1318 will be registered dynamically according - * to the number of rt1318 used. The first two entries will be registered - * for one codec case, and the last two entries are also registered - * if two 1318s are used. - */ -static const struct snd_soc_dapm_route rt1318_map[] = { - { "Speaker", NULL, "rt1318-1 SPOL" }, - { "Speaker", NULL, "rt1318-1 SPOR" }, - { "Speaker", NULL, "rt1318-2 SPOL" }, - { "Speaker", NULL, "rt1318-2 SPOR" }, -}; - -static const struct snd_kcontrol_new rt1318_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -static int first_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:rt1318", - card->components); - if (!card->components) - return -ENOMEM; - - ret = snd_soc_add_card_controls(card, rt1318_controls, - ARRAY_SIZE(rt1318_controls)); - if (ret) { - dev_err(card->dev, "rt1318 controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, rt1318_widgets, - ARRAY_SIZE(rt1318_widgets)); - if (ret) { - dev_err(card->dev, "rt1318 widgets addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map, 2); - if (ret) - dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); - - return ret; -} - -static int second_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map + 2, 2); - if (ret) - dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); - - return ret; -} - -static int all_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - - ret = first_spk_init(rtd); - if (ret) - return ret; - - return second_spk_init(rtd); -} - -int sof_sdw_rt1318_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - /* Count amp number and do init on playback link only. */ - if (!playback) - return 0; - - info->amp_num++; - if (info->amp_num == 1) - dai_links->init = first_spk_init; - - if (info->amp_num == 2) { - /* - * if two 1318s are in one dai link, the init function - * in this dai link will be first set for the first speaker, - * and it should be reset to initialize all speakers when - * the second speaker is found. - */ - if (dai_links->init) - dai_links->init = all_spk_init; - else - dai_links->init = second_spk_init; - } - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c new file mode 100644 index 000000000000..26bf9e0dd3d2 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2022 Intel Corporation + +/* + * sof_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sof_sdw_common.h" +#include "sof_sdw_amp_coeff_tables.h" +#include "../../codecs/rt1308.h" + +#define CODEC_NAME_SIZE 7 + +/* choose a larger value to resolve compatibility issues */ +#define RT_AMP_MAX_BQ_REG RT1316_MAX_BQ_REG + +struct rt_amp_platform_data { + const unsigned char *bq_params; + const unsigned int bq_params_cnt; +}; + +static const struct rt_amp_platform_data dell_0a5d_platform_data = { + .bq_params = dell_0a5d_bq_params, + .bq_params_cnt = ARRAY_SIZE(dell_0a5d_bq_params), +}; + +static const struct rt_amp_platform_data dell_0b00_platform_data = { + .bq_params = dell_0b00_bq_params, + .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params), +}; + +static const struct dmi_system_id dmi_platform_data[] = { + /* CometLake devices */ + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990") + }, + .driver_data = (void *)&dell_0a5d_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F") + }, + .driver_data = (void *)&dell_0a5d_platform_data, + }, + /* TigerLake devices */ + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") + }, + .driver_data = (void *)&dell_0a5d_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") + }, + .driver_data = (void *)&dell_0a5d_platform_data, + }, + /* AlderLake devices */ + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") + }, + .driver_data = (void *)&dell_0b00_platform_data, + }, + {}, +}; + +static int rt_amp_add_device_props(struct device *sdw_dev) +{ + struct property_entry props[3] = {}; + struct fwnode_handle *fwnode; + const struct dmi_system_id *dmi_data; + const struct rt_amp_platform_data *pdata; + unsigned char params[RT_AMP_MAX_BQ_REG]; + int ret; + + dmi_data = dmi_first_match(dmi_platform_data); + if (!dmi_data) + return 0; + + pdata = dmi_data->driver_data; + memcpy(¶ms, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt); + + props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params); + props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt); + + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); + + return ret; +} + +static const struct snd_kcontrol_new rt_amp_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static const struct snd_soc_dapm_widget rt_amp_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +/* + * dapm routes for rt1308/rt1316/rt1318 will be registered dynamically + * according to the number of rt1308/rt1316/rt1318 used. The first two + * entries will be registered for one codec case, and the last two entries + * are also registered if two 1308s/1316s/1318s are used. + */ +static const struct snd_soc_dapm_route rt1308_map[] = { + { "Speaker", NULL, "rt1308-1 SPOL" }, + { "Speaker", NULL, "rt1308-1 SPOR" }, + { "Speaker", NULL, "rt1308-2 SPOL" }, + { "Speaker", NULL, "rt1308-2 SPOR" }, +}; + +static const struct snd_soc_dapm_route rt1316_map[] = { + { "Speaker", NULL, "rt1316-1 SPOL" }, + { "Speaker", NULL, "rt1316-1 SPOR" }, + { "Speaker", NULL, "rt1316-2 SPOL" }, + { "Speaker", NULL, "rt1316-2 SPOR" }, +}; + +static const struct snd_soc_dapm_route rt1318_map[] = { + { "Speaker", NULL, "rt1318-1 SPOL" }, + { "Speaker", NULL, "rt1318-1 SPOR" }, + { "Speaker", NULL, "rt1318-2 SPOL" }, + { "Speaker", NULL, "rt1318-2 SPOR" }, +}; + +static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_pcm_runtime *rtd, + char *codec_name) +{ + const char *dai_name; + + dai_name = rtd->dai_link->codecs->dai_name; + + /* get the codec name */ + snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai_name); + + /* choose the right codec's map */ + if (strcmp(codec_name, "rt1308") == 0) + return rt1308_map; + else if (strcmp(codec_name, "rt1316") == 0) + return rt1316_map; + else + return rt1318_map; +} + +static int first_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + const struct snd_soc_dapm_route *rt_amp_map; + char codec_name[CODEC_NAME_SIZE]; + int ret; + + rt_amp_map = get_codec_name_and_route(rtd, codec_name); + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:%s", + card->components, codec_name); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt_amp_controls, + ARRAY_SIZE(rt_amp_controls)); + if (ret) { + dev_err(card->dev, "%s controls addition failed: %d\n", codec_name, ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt_amp_widgets, + ARRAY_SIZE(rt_amp_widgets)); + if (ret) { + dev_err(card->dev, "%s widgets addition failed: %d\n", codec_name, ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static int second_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + const struct snd_soc_dapm_route *rt_amp_map; + char codec_name[CODEC_NAME_SIZE]; + int ret; + + rt_amp_map = get_codec_name_and_route(rtd, codec_name); + + ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2); + if (ret) + dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); + + return ret; +} + +static int all_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = first_spk_init(rtd); + if (ret) + return ret; + + return second_spk_init(rtd); +} + +static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int clk_id, clk_freq, pll_out; + int err; + + clk_id = RT1308_PLL_S_MCLK; + clk_freq = 38400000; + + pll_out = params_rate(params) * 512; + + /* Set rt1308 pll */ + err = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); + if (err < 0) { + dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", err); + return err; + } + + /* Set rt1308 sysclk */ + err = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, + SND_SOC_CLOCK_IN); + if (err < 0) { + dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", err); + return err; + } + + return 0; +} + +/* machine stream operations */ +struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { + .hw_params = rt1308_i2s_hw_params, +}; + +int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (ctx->amp_dev1) { + device_remove_software_node(ctx->amp_dev1); + put_device(ctx->amp_dev1); + } + + if (ctx->amp_dev2) { + device_remove_software_node(ctx->amp_dev2); + put_device(ctx->amp_dev2); + } + + return 0; +} + +int sof_sdw_rt_amp_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct device *sdw_dev1, *sdw_dev2; + int ret; + + /* Count amp number and do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + if (info->amp_num == 1) + dai_links->init = first_spk_init; + + if (info->amp_num == 2) { + sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); + if (!sdw_dev1) + return -EPROBE_DEFER; + + ret = rt_amp_add_device_props(sdw_dev1); + if (ret < 0) { + put_device(sdw_dev1); + return ret; + } + ctx->amp_dev1 = sdw_dev1; + + sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name); + if (!sdw_dev2) + return -EPROBE_DEFER; + + ret = rt_amp_add_device_props(sdw_dev2); + if (ret < 0) { + put_device(sdw_dev2); + return ret; + } + ctx->amp_dev2 = sdw_dev2; + + /* + * if two amps are in one dai link, the init function + * in this dai link will be first set for the first speaker, + * and it should be reset to initialize all speakers when + * the second speaker is found. + */ + if (dai_links->init) + dai_links->init = all_spk_init; + else + dai_links->init = second_spk_init; + } + + return 0; +} -- cgit v1.2.3