Skip to content

Commit 6f03b44

Browse files
rfvirgiltiwai
authored andcommitted
ALSA: hda: cs35l56: Add support for speaker id
Add handling of the "spk-id-gpios" _DSD property. If present, the value indicated by the GPIOs is appended to the subsystem-id part of the firmware name to load the appropriate tunings for that speaker. 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 is only used in combination with a _SUB identifier because the value is only meaningful if the exact model is known. The code to get the speaker ID value has been implemented as a new library so that the cs35l41_hda driver can be switched in future to share common code. This library can be extended for other common functionality shared by Cirrus Logic amp drivers. Signed-off-by: Richard Fitzgerald <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 6e74378 commit 6f03b44

File tree

6 files changed

+107
-1
lines changed

6 files changed

+107
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4912,6 +4912,7 @@ F: drivers/spi/spi-cs42l43*
49124912
F: include/dt-bindings/sound/cs*
49134913
F: include/linux/mfd/cs42l43*
49144914
F: include/sound/cs*
4915+
F: sound/pci/hda/cirrus*
49154916
F: sound/pci/hda/cs*
49164917
F: sound/pci/hda/hda_cs_dsp_ctl.*
49174918
F: sound/soc/codecs/cs*

sound/pci/hda/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ config SND_HDA_PATCH_LOADER
9191
start up. The "patch" file can be specified via patch module
9292
option, such as patch=hda-init.
9393

94+
config SND_HDA_CIRRUS_SCODEC
95+
tristate
96+
9497
config SND_HDA_SCODEC_CS35L41
9598
tristate
9699
select SND_HDA_GENERIC
@@ -144,6 +147,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
144147
select SND_HDA_GENERIC
145148
select SND_SOC_CS35L56_SHARED
146149
select SND_HDA_SCODEC_CS35L56
150+
select SND_HDA_CIRRUS_SCODEC
147151
select SND_HDA_CS_DSP_CONTROLS
148152
help
149153
Say Y or M here to include CS35L56 amplifier support with
@@ -158,6 +162,7 @@ config SND_HDA_SCODEC_CS35L56_SPI
158162
select SND_HDA_GENERIC
159163
select SND_SOC_CS35L56_SHARED
160164
select SND_HDA_SCODEC_CS35L56
165+
select SND_HDA_CIRRUS_SCODEC
161166
select SND_HDA_CS_DSP_CONTROLS
162167
help
163168
Say Y or M here to include CS35L56 amplifier support with

sound/pci/hda/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ snd-hda-codec-via-objs := patch_via.o
2828
snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
2929

3030
# side codecs
31+
snd-hda-cirrus-scodec-objs := cirrus_scodec.o
3132
snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o
3233
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
3334
snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
5657
obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
5758

5859
# side codecs
60+
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
5961
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
6062
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
6163
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o

sound/pci/hda/cirrus_scodec.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
//
3+
// Common code for Cirrus side-codecs.
4+
//
5+
// Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
6+
// Cirrus Logic International Semiconductor Ltd.
7+
8+
#include <linux/dev_printk.h>
9+
#include <linux/gpio/consumer.h>
10+
#include <linux/module.h>
11+
12+
#include "cirrus_scodec.h"
13+
14+
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
15+
int num_amps, int fixed_gpio_id)
16+
{
17+
struct gpio_desc *speaker_id_desc;
18+
int speaker_id = -ENOENT;
19+
20+
if (fixed_gpio_id >= 0) {
21+
dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
22+
speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
23+
if (IS_ERR(speaker_id_desc)) {
24+
speaker_id = PTR_ERR(speaker_id_desc);
25+
return speaker_id;
26+
}
27+
speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
28+
gpiod_put(speaker_id_desc);
29+
} else {
30+
int base_index;
31+
int gpios_per_amp;
32+
int count;
33+
int tmp;
34+
int i;
35+
36+
count = gpiod_count(dev, "spk-id");
37+
if (count > 0) {
38+
speaker_id = 0;
39+
gpios_per_amp = count / num_amps;
40+
base_index = gpios_per_amp * amp_index;
41+
42+
if (count % num_amps)
43+
return -EINVAL;
44+
45+
dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
46+
47+
for (i = 0; i < gpios_per_amp; i++) {
48+
speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
49+
GPIOD_IN);
50+
if (IS_ERR(speaker_id_desc)) {
51+
speaker_id = PTR_ERR(speaker_id_desc);
52+
break;
53+
}
54+
tmp = gpiod_get_value_cansleep(speaker_id_desc);
55+
gpiod_put(speaker_id_desc);
56+
if (tmp < 0) {
57+
speaker_id = tmp;
58+
break;
59+
}
60+
speaker_id |= tmp << i;
61+
}
62+
}
63+
}
64+
65+
dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
66+
67+
return speaker_id;
68+
}
69+
EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, SND_HDA_CIRRUS_SCODEC);
70+
71+
MODULE_DESCRIPTION("HDA Cirrus side-codec library");
72+
MODULE_AUTHOR("Richard Fitzgerald <[email protected]>");
73+
MODULE_LICENSE("GPL");

sound/pci/hda/cirrus_scodec.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* SPDX-License-Identifier: GPL-2.0
2+
*
3+
* Copyright (C) 2023 Cirrus Logic, Inc. and
4+
* Cirrus Logic International Semiconductor Ltd.
5+
*/
6+
7+
#ifndef CIRRUS_SCODEC_H
8+
#define CIRRUS_SCODEC_H
9+
10+
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
11+
int num_amps, int fixed_gpio_id);
12+
13+
#endif /* CIRRUS_SCODEC_H */

sound/pci/hda/cs35l56_hda.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <sound/core.h>
1717
#include <sound/hda_codec.h>
1818
#include <sound/tlv.h>
19+
#include "cirrus_scodec.h"
1920
#include "cs35l56_hda.h"
2021
#include "hda_component.h"
2122
#include "hda_cs_dsp_ctl.h"
@@ -869,7 +870,17 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
869870
"Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
870871
PTR_ERR(sub));
871872
} else {
872-
cs35l56->system_name = sub;
873+
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
874+
if (ret == -ENOENT) {
875+
cs35l56->system_name = sub;
876+
} else if (ret >= 0) {
877+
cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
878+
kfree(sub);
879+
if (!cs35l56->system_name)
880+
return -ENOMEM;
881+
} else {
882+
return ret;
883+
}
873884
}
874885

875886
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
@@ -1025,6 +1036,7 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = {
10251036
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
10261037

10271038
MODULE_DESCRIPTION("CS35L56 HDA Driver");
1039+
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
10281040
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
10291041
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
10301042
MODULE_AUTHOR("Richard Fitzgerald <[email protected]>");

0 commit comments

Comments
 (0)