Skip to content

Commit 245eeff

Browse files
rfvirgilbroonie
authored andcommitted
ASoC: cs35l56: Load tunings for the correct speaker models
If the "spk-id-gpios" property is present it points to GPIOs whose value must be used to select the correct bin file to match the speakers. Some manufacturers use multiple sources of speakers, which need different tunings for best performance. On these models the type of speaker fitted is indicated by the values of one or more GPIOs. The number formed by the GPIOs identifies the tuning required. The speaker ID must be used in combination with the subsystem ID (either from PCI SSID or cirrus,firmware-uid property), because the GPIOs can only indicate variants of a specific model. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Fixes: 1a1c3d7 ("ASoC: cs35l56: Use PCI SSID as the firmware UID") Link: https://msgid.link/r/20240129162737.497-14-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent f4ef514 commit 245eeff

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

include/sound/cs35l56.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_ds
289289
int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,
290290
bool *fw_missing, unsigned int *fw_version);
291291
int cs35l56_hw_init(struct cs35l56_base *cs35l56_base);
292+
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base);
292293
int cs35l56_get_bclk_freq_id(unsigned int freq);
293294
void cs35l56_fill_supply_names(struct regulator_bulk_data *data);
294295

sound/soc/codecs/cs35l56-shared.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Copyright (C) 2023 Cirrus Logic, Inc. and
66
// Cirrus Logic International Semiconductor Ltd.
77

8+
#include <linux/gpio/consumer.h>
89
#include <linux/regmap.h>
910
#include <linux/regulator/consumer.h>
1011
#include <linux/types.h>
@@ -736,6 +737,41 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
736737
}
737738
EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
738739

740+
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
741+
{
742+
struct gpio_descs *descs;
743+
int speaker_id;
744+
int i, ret;
745+
746+
/* Read the speaker type qualifier from the motherboard GPIOs */
747+
descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN);
748+
if (!descs) {
749+
return -ENOENT;
750+
} else if (IS_ERR(descs)) {
751+
ret = PTR_ERR(descs);
752+
return dev_err_probe(cs35l56_base->dev, ret, "Failed to get spk-id-gpios\n");
753+
}
754+
755+
speaker_id = 0;
756+
for (i = 0; i < descs->ndescs; i++) {
757+
ret = gpiod_get_value_cansleep(descs->desc[i]);
758+
if (ret < 0) {
759+
dev_err_probe(cs35l56_base->dev, ret, "Failed to read spk-id[%d]\n", i);
760+
goto err;
761+
}
762+
763+
speaker_id |= (ret << i);
764+
}
765+
766+
dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);
767+
ret = speaker_id;
768+
err:
769+
gpiod_put_array(descs);
770+
771+
return ret;
772+
}
773+
EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED);
774+
739775
static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
740776
[0x0C] = 128000,
741777
[0x0F] = 256000,

sound/soc/codecs/cs35l56.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -959,10 +959,19 @@ static int cs35l56_component_probe(struct snd_soc_component *component)
959959

960960
if (!cs35l56->dsp.system_name &&
961961
(snd_soc_card_get_pci_ssid(component->card, &vendor, &device) == 0)) {
962-
cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev,
963-
GFP_KERNEL,
964-
"%04x%04x",
965-
vendor, device);
962+
/* Append a speaker qualifier if there is a speaker ID */
963+
if (cs35l56->speaker_id >= 0) {
964+
cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev,
965+
GFP_KERNEL,
966+
"%04x%04x-spkid%d",
967+
vendor, device,
968+
cs35l56->speaker_id);
969+
} else {
970+
cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev,
971+
GFP_KERNEL,
972+
"%04x%04x",
973+
vendor, device);
974+
}
966975
if (!cs35l56->dsp.system_name)
967976
return -ENOMEM;
968977
}
@@ -1245,7 +1254,13 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56)
12451254
if (ret < 0)
12461255
return 0;
12471256

1248-
cs35l56->dsp.system_name = devm_kstrdup(dev, prop, GFP_KERNEL);
1257+
/* Append a speaker qualifier if there is a speaker ID */
1258+
if (cs35l56->speaker_id >= 0)
1259+
cs35l56->dsp.system_name = devm_kasprintf(dev, GFP_KERNEL, "%s-spkid%d",
1260+
prop, cs35l56->speaker_id);
1261+
else
1262+
cs35l56->dsp.system_name = devm_kstrdup(dev, prop, GFP_KERNEL);
1263+
12491264
if (cs35l56->dsp.system_name == NULL)
12501265
return -ENOMEM;
12511266

@@ -1260,6 +1275,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
12601275

12611276
init_completion(&cs35l56->init_completion);
12621277
mutex_init(&cs35l56->base.irq_lock);
1278+
cs35l56->speaker_id = -ENOENT;
12631279

12641280
dev_set_drvdata(cs35l56->base.dev, cs35l56);
12651281

@@ -1296,6 +1312,12 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
12961312
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
12971313
}
12981314

1315+
ret = cs35l56_get_speaker_id(&cs35l56->base);
1316+
if ((ret < 0) && (ret != -ENOENT))
1317+
goto err;
1318+
1319+
cs35l56->speaker_id = ret;
1320+
12991321
ret = cs35l56_get_firmware_uid(cs35l56);
13001322
if (ret != 0)
13011323
goto err;

sound/soc/codecs/cs35l56.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct cs35l56_private {
4545
bool sdw_attached;
4646
struct completion init_completion;
4747

48+
int speaker_id;
4849
u32 rx_mask;
4950
u32 tx_mask;
5051
u8 asp_slot_width;

0 commit comments

Comments
 (0)