mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
ALSA: hda/cs35l56: Add driver for Cirrus Logic CS35L56 amplifier
Add a driver for the Cirrus Logic CS35L56 amplifier. This uses the same component binding API as the CS35L41 driver. This is not a standalone HDA device; it provides control of the CS35L56 for systems that use a combination of an HDA codec and CS35L56 amplifiers with audio routed through the HDA codec. The CS35L56 combines a high-performance mono audio amplifier, Class-H tracking inductive boost converter, Halo Core(TM) DSP and a DC-DC boost converter supporting Class-H tracking. Control interfaces are I2C or SPI through the standard Linux I2C or SPI bus framework. Most chip functionality is controlled by on-board ROM firmware that is always running. Firmware patches can be applied by the driver in the form of a .wmfw file (firmware patch) and/or a .bin file (system tuning). Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/20230721132120.5523-12-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
64e0532150
commit
73cfbfa9ca
@@ -130,6 +130,37 @@ config SND_HDA_SCODEC_CS35L41_SPI
|
||||
comment "Set to Y if you want auto-loading the side codec driver"
|
||||
depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m
|
||||
|
||||
config SND_HDA_SCODEC_CS35L56
|
||||
tristate
|
||||
|
||||
config SND_HDA_SCODEC_CS35L56_I2C
|
||||
tristate "Build CS35L56 HD-audio side codec support for I2C Bus"
|
||||
depends on I2C
|
||||
depends on ACPI || COMPILE_TEST
|
||||
depends on SND_SOC
|
||||
select CS_DSP
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
I2C control.
|
||||
|
||||
config SND_HDA_SCODEC_CS35L56_SPI
|
||||
tristate "Build CS35L56 HD-audio side codec support for SPI Bus"
|
||||
depends on SPI_MASTER
|
||||
depends on ACPI || COMPILE_TEST
|
||||
depends on SND_SOC
|
||||
select CS_DSP
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
SPI control.
|
||||
|
||||
config SND_HDA_CODEC_REALTEK
|
||||
tristate "Build Realtek HD-audio codec support"
|
||||
select SND_HDA_GENERIC
|
||||
|
||||
@@ -31,6 +31,9 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
|
||||
snd-hda-scodec-cs35l41-objs := cs35l41_hda.o
|
||||
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
|
||||
snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o
|
||||
snd-hda-scodec-cs35l56-objs := cs35l56_hda.o
|
||||
snd-hda-scodec-cs35l56-i2c-objs := cs35l56_hda_i2c.o
|
||||
snd-hda-scodec-cs35l56-spi-objs := cs35l56_hda_spi.o
|
||||
snd-hda-cs-dsp-ctls-objs := hda_cs_dsp_ctl.o
|
||||
|
||||
# common driver
|
||||
@@ -55,6 +58,9 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.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
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56) += snd-hda-scodec-cs35l56.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_I2C) += snd-hda-scodec-cs35l56-i2c.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_SPI) += snd-hda-scodec-cs35l56-spi.o
|
||||
obj-$(CONFIG_SND_HDA_CS_DSP_CONTROLS) += snd-hda-cs-dsp-ctls.o
|
||||
|
||||
# this must be the last entry after codec drivers;
|
||||
|
||||
995
sound/pci/hda/cs35l56_hda.c
Normal file
995
sound/pci/hda/cs35l56_hda.c
Normal file
File diff suppressed because it is too large
Load Diff
48
sound/pci/hda/cs35l56_hda.h
Normal file
48
sound/pci/hda/cs35l56_hda.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
*
|
||||
* HDA audio driver for Cirrus Logic CS35L56 smart amp
|
||||
*
|
||||
* Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __CS35L56_HDA_H__
|
||||
#define __CS35L56_HDA_H__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/firmware/cirrus/cs_dsp.h>
|
||||
#include <linux/firmware/cirrus/wmfw.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <sound/cs35l56.h>
|
||||
|
||||
struct dentry;
|
||||
|
||||
struct cs35l56_hda {
|
||||
struct cs35l56_base base;
|
||||
struct hda_codec *codec;
|
||||
|
||||
int index;
|
||||
const char *system_name;
|
||||
const char *amp_name;
|
||||
|
||||
struct cs_dsp cs_dsp;
|
||||
bool playing;
|
||||
bool suspended;
|
||||
u8 asp_tx_mask;
|
||||
|
||||
struct snd_kcontrol *posture_ctl;
|
||||
struct snd_kcontrol *volume_ctl;
|
||||
struct snd_kcontrol *mixer_ctl[4];
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_DEBUG)
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern const struct dev_pm_ops cs35l56_hda_pm_ops;
|
||||
|
||||
int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id);
|
||||
void cs35l56_hda_remove(struct device *dev);
|
||||
|
||||
#endif /*__CS35L56_HDA_H__*/
|
||||
69
sound/pci/hda/cs35l56_hda_i2c.c
Normal file
69
sound/pci/hda/cs35l56_hda_i2c.c
Normal file
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// CS35L56 HDA audio driver I2C binding
|
||||
//
|
||||
// Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "cs35l56_hda.h"
|
||||
|
||||
static int cs35l56_hda_i2c_probe(struct i2c_client *clt)
|
||||
{
|
||||
struct cs35l56_hda *cs35l56;
|
||||
int ret;
|
||||
|
||||
cs35l56 = devm_kzalloc(&clt->dev, sizeof(*cs35l56), GFP_KERNEL);
|
||||
if (!cs35l56)
|
||||
return -ENOMEM;
|
||||
|
||||
cs35l56->base.dev = &clt->dev;
|
||||
cs35l56->base.can_hibernate = true;
|
||||
cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c);
|
||||
if (IS_ERR(cs35l56->base.regmap)) {
|
||||
ret = PTR_ERR(cs35l56->base.regmap);
|
||||
dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cs35l56_hda_common_probe(cs35l56, clt->addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = cs35l56_irq_request(&cs35l56->base, clt->irq);
|
||||
if (ret < 0)
|
||||
cs35l56_hda_remove(cs35l56->base.dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs35l56_hda_i2c_remove(struct i2c_client *clt)
|
||||
{
|
||||
cs35l56_hda_remove(&clt->dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cs35l56_hda_i2c_id[] = {
|
||||
{ "cs35l56-hda", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct i2c_driver cs35l56_hda_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs35l56-hda",
|
||||
.pm = &cs35l56_hda_pm_ops,
|
||||
},
|
||||
.id_table = cs35l56_hda_i2c_id,
|
||||
.probe = cs35l56_hda_i2c_probe,
|
||||
.remove = cs35l56_hda_i2c_remove,
|
||||
};
|
||||
module_i2c_driver(cs35l56_hda_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("HDA CS35L56 I2C driver");
|
||||
MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56);
|
||||
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
68
sound/pci/hda/cs35l56_hda_spi.c
Normal file
68
sound/pci/hda/cs35l56_hda_spi.c
Normal file
@@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// CS35L56 HDA audio driver SPI binding
|
||||
//
|
||||
// Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "cs35l56_hda.h"
|
||||
|
||||
static int cs35l56_hda_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct cs35l56_hda *cs35l56;
|
||||
int ret;
|
||||
|
||||
cs35l56 = devm_kzalloc(&spi->dev, sizeof(*cs35l56), GFP_KERNEL);
|
||||
if (!cs35l56)
|
||||
return -ENOMEM;
|
||||
|
||||
cs35l56->base.dev = &spi->dev;
|
||||
cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi);
|
||||
if (IS_ERR(cs35l56->base.regmap)) {
|
||||
ret = PTR_ERR(cs35l56->base.regmap);
|
||||
dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cs35l56_hda_common_probe(cs35l56, spi->chip_select);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
|
||||
if (ret < 0)
|
||||
cs35l56_hda_remove(cs35l56->base.dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs35l56_hda_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
cs35l56_hda_remove(&spi->dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id cs35l56_hda_spi_id[] = {
|
||||
{ "cs35l56-hda", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct spi_driver cs35l56_hda_spi_driver = {
|
||||
.driver = {
|
||||
.name = "cs35l56-hda",
|
||||
.pm = &cs35l56_hda_pm_ops,
|
||||
},
|
||||
.id_table = cs35l56_hda_spi_id,
|
||||
.probe = cs35l56_hda_spi_probe,
|
||||
.remove = cs35l56_hda_spi_remove,
|
||||
};
|
||||
module_spi_driver(cs35l56_hda_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("HDA CS35L56 SPI driver");
|
||||
MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56);
|
||||
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user