mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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 <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230918095129.440-2-rf@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6e743781d6
commit
6f03b446cb
@ -4912,6 +4912,7 @@ F: drivers/spi/spi-cs42l43*
|
||||
F: include/dt-bindings/sound/cs*
|
||||
F: include/linux/mfd/cs42l43*
|
||||
F: include/sound/cs*
|
||||
F: sound/pci/hda/cirrus*
|
||||
F: sound/pci/hda/cs*
|
||||
F: sound/pci/hda/hda_cs_dsp_ctl.*
|
||||
F: sound/soc/codecs/cs*
|
||||
|
@ -91,6 +91,9 @@ config SND_HDA_PATCH_LOADER
|
||||
start up. The "patch" file can be specified via patch module
|
||||
option, such as patch=hda-init.
|
||||
|
||||
config SND_HDA_CIRRUS_SCODEC
|
||||
tristate
|
||||
|
||||
config SND_HDA_SCODEC_CS35L41
|
||||
tristate
|
||||
select SND_HDA_GENERIC
|
||||
@ -144,6 +147,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CIRRUS_SCODEC
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
@ -158,6 +162,7 @@ config SND_HDA_SCODEC_CS35L56_SPI
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CIRRUS_SCODEC
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
|
@ -28,6 +28,7 @@ snd-hda-codec-via-objs := patch_via.o
|
||||
snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
|
||||
|
||||
# side codecs
|
||||
snd-hda-cirrus-scodec-objs := cirrus_scodec.o
|
||||
snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o
|
||||
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
|
||||
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
|
||||
obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
|
||||
|
||||
# side codecs
|
||||
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
|
||||
|
73
sound/pci/hda/cirrus_scodec.c
Normal file
73
sound/pci/hda/cirrus_scodec.c
Normal file
@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Common code for Cirrus side-codecs.
|
||||
//
|
||||
// Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "cirrus_scodec.h"
|
||||
|
||||
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
|
||||
int num_amps, int fixed_gpio_id)
|
||||
{
|
||||
struct gpio_desc *speaker_id_desc;
|
||||
int speaker_id = -ENOENT;
|
||||
|
||||
if (fixed_gpio_id >= 0) {
|
||||
dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
|
||||
speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
|
||||
if (IS_ERR(speaker_id_desc)) {
|
||||
speaker_id = PTR_ERR(speaker_id_desc);
|
||||
return speaker_id;
|
||||
}
|
||||
speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
|
||||
gpiod_put(speaker_id_desc);
|
||||
} else {
|
||||
int base_index;
|
||||
int gpios_per_amp;
|
||||
int count;
|
||||
int tmp;
|
||||
int i;
|
||||
|
||||
count = gpiod_count(dev, "spk-id");
|
||||
if (count > 0) {
|
||||
speaker_id = 0;
|
||||
gpios_per_amp = count / num_amps;
|
||||
base_index = gpios_per_amp * amp_index;
|
||||
|
||||
if (count % num_amps)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
|
||||
|
||||
for (i = 0; i < gpios_per_amp; i++) {
|
||||
speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
|
||||
GPIOD_IN);
|
||||
if (IS_ERR(speaker_id_desc)) {
|
||||
speaker_id = PTR_ERR(speaker_id_desc);
|
||||
break;
|
||||
}
|
||||
tmp = gpiod_get_value_cansleep(speaker_id_desc);
|
||||
gpiod_put(speaker_id_desc);
|
||||
if (tmp < 0) {
|
||||
speaker_id = tmp;
|
||||
break;
|
||||
}
|
||||
speaker_id |= tmp << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
|
||||
|
||||
return speaker_id;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, SND_HDA_CIRRUS_SCODEC);
|
||||
|
||||
MODULE_DESCRIPTION("HDA Cirrus side-codec library");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
13
sound/pci/hda/cirrus_scodec.h
Normal file
13
sound/pci/hda/cirrus_scodec.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#ifndef CIRRUS_SCODEC_H
|
||||
#define CIRRUS_SCODEC_H
|
||||
|
||||
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
|
||||
int num_amps, int fixed_gpio_id);
|
||||
|
||||
#endif /* CIRRUS_SCODEC_H */
|
@ -16,6 +16,7 @@
|
||||
#include <sound/core.h>
|
||||
#include <sound/hda_codec.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "cirrus_scodec.h"
|
||||
#include "cs35l56_hda.h"
|
||||
#include "hda_component.h"
|
||||
#include "hda_cs_dsp_ctl.h"
|
||||
@ -869,7 +870,17 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
|
||||
"Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
|
||||
PTR_ERR(sub));
|
||||
} else {
|
||||
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
|
||||
if (ret == -ENOENT) {
|
||||
cs35l56->system_name = sub;
|
||||
} else if (ret >= 0) {
|
||||
cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
|
||||
kfree(sub);
|
||||
if (!cs35l56->system_name)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
|
||||
|
||||
MODULE_DESCRIPTION("CS35L56 HDA Driver");
|
||||
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
|
||||
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
|
||||
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
|
Loading…
Reference in New Issue
Block a user