Skip to content

Commit dc8b609

Browse files
committed
ASoC: cs35l56: Change firmware filenames for SoundWire
Merge series from Richard Fitzgerald <[email protected]>: Change the firmware filename format on SoundWire systems to directly tie it to the physical amp it applies to. This is mainly to decouple it from the ALSA prefix strings to avoid complications when the SoundWire machine driver starts creating dailinks based on SDCA Disco info instead of hardcoded match tables. It also avoids errors from having to rename firmware files from a hardware-address to a ALSA-prefix naming for Linux publication. There are already published firmware files for the L56 B0 silicon so that has a fallback scheme for backward compatibility which has been separated into its own patch on top of the main change. We'd like to get this into 6.16 so that the L63 support starts "clean" with this new naming and we don't have to support one kernel version with L63 using the old naming. Unfortunately we didn't manage to get these patches through internal review and testing before the merge window opened.
2 parents f594279 + fa8fae5 commit dc8b609

File tree

6 files changed

+109
-26
lines changed

6 files changed

+109
-26
lines changed

Documentation/sound/codecs/cs35l56.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,32 @@ In this example the SSID is 10280c63.
104104

105105
The format of the firmware file names is:
106106

107+
SoundWire (except CS35L56 Rev B0):
108+
cs35lxx-b0-dsp1-misc-SSID[-spkidX]-l?u?
109+
110+
SoundWire CS35L56 Rev B0:
111+
cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN
112+
113+
Non-SoundWire (HDA and I2S):
107114
cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN
108115

109116
Where:
110117

111118
* cs35lxx-b0 is the amplifier model and silicon revision. This information
112119
is logged by the driver during initialization.
113120
* SSID is the 8-digit hexadecimal SSID value.
121+
* l?u? is the physical address on the SoundWire bus of the amp this
122+
file applies to.
114123
* ampN is the amplifier number (for example amp1). This is the same as
115124
the prefix on the ALSA control names except that it is always lower-case
116125
in the file name.
117126
* spkidX is an optional part, used for laptops that have firmware
118127
configurations for different makes and models of internal speakers.
119128

129+
The CS35L56 Rev B0 continues to use the old filename scheme because a
130+
large number of firmware files have already been published with these
131+
names.
132+
120133
Sound Open Firmware and ALSA topology files
121134
-------------------------------------------
122135

sound/soc/codecs/cs35l56-sdw.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,16 +238,15 @@ static const struct regmap_bus cs35l56_regmap_bus_sdw = {
238238
.val_format_endian_default = REGMAP_ENDIAN_BIG,
239239
};
240240

241-
static int cs35l56_sdw_set_cal_index(struct cs35l56_private *cs35l56)
241+
static int cs35l56_sdw_get_unique_id(struct cs35l56_private *cs35l56)
242242
{
243243
int ret;
244244

245-
/* SoundWire UniqueId is used to index the calibration array */
246245
ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0);
247246
if (ret < 0)
248247
return ret;
249248

250-
cs35l56->base.cal_index = ret & 0xf;
249+
cs35l56->sdw_unique_id = ret & 0xf;
251250

252251
return 0;
253252
}
@@ -259,11 +258,13 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
259258

260259
pm_runtime_get_noresume(cs35l56->base.dev);
261260

262-
if (cs35l56->base.cal_index < 0) {
263-
ret = cs35l56_sdw_set_cal_index(cs35l56);
264-
if (ret < 0)
265-
goto out;
266-
}
261+
ret = cs35l56_sdw_get_unique_id(cs35l56);
262+
if (ret)
263+
goto out;
264+
265+
/* SoundWire UniqueId is used to index the calibration array */
266+
if (cs35l56->base.cal_index < 0)
267+
cs35l56->base.cal_index = cs35l56->sdw_unique_id;
267268

268269
ret = cs35l56_init(cs35l56);
269270
if (ret < 0) {
@@ -587,6 +588,7 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi
587588

588589
cs35l56->base.dev = dev;
589590
cs35l56->sdw_peripheral = peripheral;
591+
cs35l56->sdw_link_num = peripheral->bus->link_id;
590592
INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work);
591593

592594
dev_set_drvdata(dev, cs35l56);

sound/soc/codecs/cs35l56.c

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -706,17 +706,41 @@ static int cs35l56_write_cal(struct cs35l56_private *cs35l56)
706706
return ret;
707707
}
708708

709-
static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56)
709+
static int cs35l56_dsp_download_and_power_up(struct cs35l56_private *cs35l56,
710+
bool load_firmware)
710711
{
711712
int ret;
712713

713-
/* Use wm_adsp to load and apply the firmware patch and coefficient files */
714-
ret = wm_adsp_power_up(&cs35l56->dsp, true);
714+
/*
715+
* Abort the first load if it didn't find the suffixed bins and
716+
* we have an alternate fallback suffix.
717+
*/
718+
cs35l56->dsp.bin_mandatory = (load_firmware && cs35l56->fallback_fw_suffix);
719+
720+
ret = wm_adsp_power_up(&cs35l56->dsp, load_firmware);
721+
if ((ret == -ENOENT) && cs35l56->dsp.bin_mandatory) {
722+
cs35l56->dsp.fwf_suffix = cs35l56->fallback_fw_suffix;
723+
cs35l56->fallback_fw_suffix = NULL;
724+
cs35l56->dsp.bin_mandatory = false;
725+
ret = wm_adsp_power_up(&cs35l56->dsp, load_firmware);
726+
}
727+
715728
if (ret) {
716-
dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
717-
return;
729+
dev_dbg(cs35l56->base.dev, "wm_adsp_power_up ret %d\n", ret);
730+
return ret;
718731
}
719732

733+
return 0;
734+
}
735+
736+
static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56)
737+
{
738+
int ret;
739+
740+
ret = cs35l56_dsp_download_and_power_up(cs35l56, true);
741+
if (ret)
742+
return;
743+
720744
cs35l56_write_cal(cs35l56);
721745

722746
/* Always REINIT after applying patch or coefficients */
@@ -750,11 +774,9 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing
750774
* but only if firmware is missing. If firmware is already patched just
751775
* power-up wm_adsp without downloading firmware.
752776
*/
753-
ret = wm_adsp_power_up(&cs35l56->dsp, !!firmware_missing);
754-
if (ret) {
755-
dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
777+
ret = cs35l56_dsp_download_and_power_up(cs35l56, firmware_missing);
778+
if (ret)
756779
goto err;
757-
}
758780

759781
mutex_lock(&cs35l56->base.irq_lock);
760782

@@ -853,6 +875,34 @@ static void cs35l56_dsp_work(struct work_struct *work)
853875
pm_runtime_put_autosuspend(cs35l56->base.dev);
854876
}
855877

878+
static int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56)
879+
{
880+
if (cs35l56->dsp.fwf_suffix)
881+
return 0;
882+
883+
if (!cs35l56->sdw_peripheral)
884+
return 0;
885+
886+
cs35l56->dsp.fwf_suffix = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL,
887+
"l%uu%u",
888+
cs35l56->sdw_link_num,
889+
cs35l56->sdw_unique_id);
890+
if (!cs35l56->dsp.fwf_suffix)
891+
return -ENOMEM;
892+
893+
/*
894+
* There are published firmware files for L56 B0 silicon using
895+
* the ALSA prefix as the filename suffix. Default to trying these
896+
* first, with the new name as an alternate.
897+
*/
898+
if ((cs35l56->base.type == 0x56) && (cs35l56->base.rev == 0xb0)) {
899+
cs35l56->fallback_fw_suffix = cs35l56->dsp.fwf_suffix;
900+
cs35l56->dsp.fwf_suffix = cs35l56->component->name_prefix;
901+
}
902+
903+
return 0;
904+
}
905+
856906
static int cs35l56_component_probe(struct snd_soc_component *component)
857907
{
858908
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
@@ -892,6 +942,10 @@ static int cs35l56_component_probe(struct snd_soc_component *component)
892942
return -ENOMEM;
893943

894944
cs35l56->component = component;
945+
ret = cs35l56_set_fw_suffix(cs35l56);
946+
if (ret)
947+
return ret;
948+
895949
wm_adsp2_component_probe(&cs35l56->dsp, component);
896950

897951
debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done);

sound/soc/codecs/cs35l56.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct cs35l56_private {
3838
struct snd_soc_component *component;
3939
struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES];
4040
struct sdw_slave *sdw_peripheral;
41+
const char *fallback_fw_suffix;
4142
struct work_struct sdw_irq_work;
4243
bool sdw_irq_no_unmask;
4344
bool soft_resetting;
@@ -52,6 +53,8 @@ struct cs35l56_private {
5253
bool tdm_mode;
5354
bool sysclk_set;
5455
u8 old_sdw_clock_scale;
56+
u8 sdw_link_num;
57+
u8 sdw_unique_id;
5558
};
5659

5760
extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi;

sound/soc/codecs/wm_adsp.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -783,16 +783,19 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
783783
char **coeff_filename)
784784
{
785785
const char *system_name = dsp->system_name;
786-
const char *asoc_component_prefix = dsp->component->name_prefix;
786+
const char *suffix = dsp->component->name_prefix;
787787
int ret = 0;
788788

789-
if (system_name && asoc_component_prefix) {
789+
if (dsp->fwf_suffix)
790+
suffix = dsp->fwf_suffix;
791+
792+
if (system_name && suffix) {
790793
if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
791794
cirrus_dir, system_name,
792-
asoc_component_prefix, "wmfw")) {
795+
suffix, "wmfw")) {
793796
wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
794797
cirrus_dir, system_name,
795-
asoc_component_prefix, "bin");
798+
suffix, "bin");
796799
return 0;
797800
}
798801
}
@@ -801,10 +804,10 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
801804
if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
802805
cirrus_dir, system_name,
803806
NULL, "wmfw")) {
804-
if (asoc_component_prefix)
807+
if (suffix)
805808
wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
806809
cirrus_dir, system_name,
807-
asoc_component_prefix, "bin");
810+
suffix, "bin");
808811

809812
if (!*coeff_firmware)
810813
wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
@@ -816,10 +819,10 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
816819

817820
/* Check system-specific bin without wmfw before falling back to generic */
818821
if (dsp->wmfw_optional && system_name) {
819-
if (asoc_component_prefix)
822+
if (suffix)
820823
wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
821824
cirrus_dir, system_name,
822-
asoc_component_prefix, "bin");
825+
suffix, "bin");
823826

824827
if (!*coeff_firmware)
825828
wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
@@ -850,7 +853,7 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
850853
adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n",
851854
cirrus_dir, dsp->part,
852855
dsp->fwf_name ? dsp->fwf_name : dsp->cs_dsp.name,
853-
wm_adsp_fw[dsp->fw].file, system_name, asoc_component_prefix);
856+
wm_adsp_fw[dsp->fw].file, system_name, suffix);
854857

855858
return -ENOENT;
856859
}
@@ -997,11 +1000,17 @@ int wm_adsp_power_up(struct wm_adsp *dsp, bool load_firmware)
9971000
return ret;
9981001
}
9991002

1003+
if (dsp->bin_mandatory && !coeff_firmware) {
1004+
ret = -ENOENT;
1005+
goto err;
1006+
}
1007+
10001008
ret = cs_dsp_power_up(&dsp->cs_dsp,
10011009
wmfw_firmware, wmfw_filename,
10021010
coeff_firmware, coeff_filename,
10031011
wm_adsp_fw_text[dsp->fw]);
10041012

1013+
err:
10051014
wm_adsp_release_firmware_files(dsp,
10061015
wmfw_firmware, wmfw_filename,
10071016
coeff_firmware, coeff_filename);

sound/soc/codecs/wm_adsp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ struct wm_adsp {
2929
const char *part;
3030
const char *fwf_name;
3131
const char *system_name;
32+
const char *fwf_suffix;
3233
struct snd_soc_component *component;
3334

3435
unsigned int sys_config_size;
3536

3637
int fw;
3738
bool wmfw_optional;
39+
bool bin_mandatory;
3840

3941
struct work_struct boot_work;
4042
int (*control_add)(struct wm_adsp *dsp, struct cs_dsp_coeff_ctl *cs_ctl);

0 commit comments

Comments
 (0)