Commit aa07e38b authored by Mark Brown's avatar Mark Brown

Merge branch 'asoc-4.22' into asoc-5.0

parents bfeffd15 540f1ba7
Audio-Graph-SCU-Card:
Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM".
It is based on common bindings for device graphs.
see ${LINUX}/Documentation/devicetree/bindings/graph.txt
Basically, Audio-Graph-SCU-Card property is same as
Simple-Card / Simple-SCU-Card / Audio-Graph-Card.
see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
${LINUX}/Documentation/devicetree/bindings/sound/simple-scu-card.txt
${LINUX}/Documentation/devicetree/bindings/sound/audio-graph-card.txt
Below are same as Simple-Card / Audio-Graph-Card.
- label
- dai-format
- frame-master
- bitclock-master
- bitclock-inversion
- frame-inversion
- dai-tdm-slot-num
- dai-tdm-slot-width
- clocks / system-clock-frequency
Below are same as Simple-SCU-Card.
- convert-rate
- convert-channels
- prefix
- routing
Required properties:
- compatible : "audio-graph-scu-card";
- dais : list of CPU DAI port{s}
Example 1. Sampling Rate Conversion
sound_card {
compatible = "audio-graph-scu-card";
label = "sound-card";
prefix = "codec";
routing = "codec Playback", "DAI0 Playback",
"DAI0 Capture", "codec Capture";
convert-rate = <48000>;
dais = <&cpu_port>;
};
audio-codec {
...
port {
codec_endpoint: endpoint {
remote-endpoint = <&cpu_endpoint>;
};
};
};
dai-controller {
...
cpu_port: port {
cpu_endpoint: endpoint {
remote-endpoint = <&codec_endpoint>;
dai-format = "left_j";
...
};
};
};
Example 2. 2 CPU 1 Codec (Mixing)
sound_card {
compatible = "audio-graph-scu-card";
label = "sound-card";
routing = "codec Playback", "DAI0 Playback",
"codec Playback", "DAI1 Playback",
"DAI0 Capture", "codec Capture";
dais = <&cpu_port0
&cpu_port1>;
};
audio-codec {
...
audio-graph-card,prefix = "codec";
audio-graph-card,convert-rate = <48000>;
port {
codec_endpoint0: endpoint {
remote-endpoint = <&cpu_endpoint0>;
};
codec_endpoint1: endpoint {
remote-endpoint = <&cpu_endpoint1>;
};
};
};
dai-controller {
...
ports {
cpu_port0: port {
cpu_endpoint0: endpoint {
remote-endpoint = <&codec_endpoint0>;
dai-format = "left_j";
...
};
};
cpu_port1: port {
cpu_endpoint1: endpoint {
remote-endpoint = <&codec_endpoint1>;
dai-format = "left_j";
...
};
};
};
};
Cirrus Logic CS4341 audio DAC
This device supports both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible: "cirrus,cs4341a"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
For required properties on I2C-bus, please consult
Documentation/devicetree/bindings/i2c/i2c.txt
For required properties on SPI-bus, please consult
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
codec: cs4341@0 {
#sound-dai-cells = <0>;
compatible = "cirrus,cs4341a";
reg = <0>;
spi-max-frequency = <6000000>;
};
......@@ -45,6 +45,23 @@ Optional properties:
- fck_parent : Should contain a valid clock name which will be used as parent
for the McASP fck
Optional GPIO support:
If any McASP pin need to be used as GPIO then the McASP node must have:
...
gpio-controller
#gpio-cells = <2>;
...
When requesting a GPIO, the first parameter is the PIN index in McASP_P*
registers.
For example to request the AXR2 pin of mcasp8:
function-gpios = <&mcasp8 2 0>;
Or to request the ACLKR pin of mcasp8:
function-gpios = <&mcasp8 29 0>;
For generic gpio information, please refer to bindings/gpio/gpio.txt
Example:
mcasp0: mcasp0@1d00000 {
......
* Rockchip Rk3328 internal codec
Required properties:
- compatible: "rockchip,rk3328-codec"
- reg: physical base address of the controller and length of memory mapped
region.
- rockchip,grf: the phandle of the syscon node for GRF register.
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
- clock-names: should be "pclk".
- spk-depop-time-ms: speak depop time msec.
Example for rk3328 internal codec:
codec: codec@ff410000 {
compatible = "rockchip,rk3328-codec";
reg = <0x0 0xff410000 0x0 0x1000>;
rockchip,grf = <&grf>;
clocks = <&cru PCLK_ACODEC>;
clock-names = "pclk";
spk-depop-time-ms = 100;
status = "disabled";
};
ASoC Simple SCU Sound Card
Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM".
For example, you can use this driver if you want to exchange sampling rate convert,
Mixing, etc...
Required properties:
- compatible : "simple-scu-audio-card"
"renesas,rsrc-card"
Optional properties:
- simple-audio-card,name : see simple-audio-card.txt
- simple-audio-card,cpu : see simple-audio-card.txt
- simple-audio-card,codec : see simple-audio-card.txt
Optional subnode properties:
- simple-audio-card,format : see simple-audio-card.txt
- simple-audio-card,frame-master : see simple-audio-card.txt
- simple-audio-card,bitclock-master : see simple-audio-card.txt
- simple-audio-card,bitclock-inversion : see simple-audio-card.txt
- simple-audio-card,frame-inversion : see simple-audio-card.txt
- simple-audio-card,convert-rate : platform specified sampling rate convert
- simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch)
- simple-audio-card,prefix : see routing
- simple-audio-card,widgets : Please refer to widgets.txt.
- simple-audio-card,routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources.
use audio-prefix if some components is using same sink/sources naming.
it can be used if compatible was "renesas,rsrc-card";
Required CPU/CODEC subnodes properties:
- sound-dai : see simple-audio-card.txt
Optional CPU/CODEC subnodes properties:
- clocks / system-clock-frequency : see simple-audio-card.txt
Example 1. Sampling Rate Conversion
sound {
compatible = "simple-scu-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
simple-audio-card,convert-rate = <48000>;
simple-audio-card,prefix = "ak4642";
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"DAI0 Capture", "ak4642 Capture";
sndcpu: simple-audio-card,cpu {
sound-dai = <&rcar_sound>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&ak4643>;
system-clock-frequency = <11289600>;
};
};
Example 2. 2 CPU 1 Codec (Mixing)
sound {
compatible = "simple-scu-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&dpcmcpu>;
simple-audio-card,frame-master = <&dpcmcpu>;
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"ak4642 Playback", "DAI1 Playback";
dpcmcpu: cpu@0 {
sound-dai = <&rcar_sound 0>;
};
cpu@1 {
sound-dai = <&rcar_sound 1>;
};
codec {
prefix = "ak4642";
sound-dai = <&ak4643>;
clocks = <&audio_clock>;
};
};
Device-Tree bindings for Xilinx PL audio formatter
The IP core supports DMA, data formatting(AES<->PCM conversion)
of audio samples.
Required properties:
- compatible: "xlnx,audio-formatter-1.0"
- interrupt-names: Names specified to list of interrupts in same
order mentioned under "interrupts".
List of supported interrupt names are:
"irq_mm2s" : interrupt from MM2S block
"irq_s2mm" : interrupt from S2MM block
- interrupts-parent: Phandle for interrupt controller.
- interrupts: List of Interrupt numbers.
- reg: Base address and size of the IP core instance.
- clock-names: List of input clocks.
Required elements: "s_axi_lite_aclk", "aud_mclk"
- clocks: Input clock specifier. Refer to common clock bindings.
Example:
audio_ss_0_audio_formatter_0: audio_formatter@80010000 {
compatible = "xlnx,audio-formatter-1.0";
interrupt-names = "irq_mm2s", "irq_s2mm";
interrupt-parent = <&gic>;
interrupts = <0 104 4>, <0 105 4>;
reg = <0x0 0x80010000 0x0 0x1000>;
clock-names = "s_axi_lite_aclk", "aud_mclk";
clocks = <&clk 71>, <&clk_wiz_1 0>;
};
......@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
{
/* first let's check the buffer parameter's */
if (params->buffer.fragment_size == 0 ||
params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
params->buffer.fragments == 0)
return -EINVAL;
/* now codec parameters */
......
......@@ -65,6 +65,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS4271_SPI if SPI_MASTER
select SND_SOC_CS42XX8_I2C if I2C
select SND_SOC_CS43130 if I2C
select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI
select SND_SOC_CS4349 if I2C
select SND_SOC_CS47L24 if MFD_CS47L24
select SND_SOC_CS53L30 if I2C
......@@ -129,6 +130,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM5102A
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RK3328
select SND_SOC_RT274 if I2C
select SND_SOC_RT286 if I2C
select SND_SOC_RT298 if I2C
......@@ -542,6 +544,12 @@ config SND_SOC_CS43130
tristate "Cirrus Logic CS43130 CODEC"
depends on I2C
config SND_SOC_CS4341
tristate "Cirrus Logic CS4341 CODEC"
depends on I2C || SPI_MASTER
select REGMAP_I2C if I2C
select REGMAP_SPI if SPI_MASTER
# Cirrus Logic CS4349 HiFi DAC
config SND_SOC_CS4349
tristate "Cirrus Logic CS4349 CODEC"
......@@ -799,6 +807,10 @@ config SND_SOC_PCM512x_SPI
select SND_SOC_PCM512x
select REGMAP_SPI
config SND_SOC_RK3328
tristate "Rockchip RK3328 audio CODEC"
select REGMAP_MMIO
config SND_SOC_RL6231
tristate
default y if SND_SOC_RT5514=y
......@@ -1211,7 +1223,8 @@ config SND_SOC_WM8903
depends on I2C
config SND_SOC_WM8904
tristate
tristate "Wolfson Microelectronics WM8904 CODEC"
depends on I2C
config SND_SOC_WM8940
tristate
......
......@@ -60,6 +60,7 @@ snd-soc-cs4271-spi-objs := cs4271-spi.o
snd-soc-cs42xx8-objs := cs42xx8.o
snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cs43130-objs := cs43130.o
snd-soc-cs4341-objs := cs4341.o
snd-soc-cs4349-objs := cs4349.o
snd-soc-cs47l24-objs := cs47l24.o
snd-soc-cs53l30-objs := cs53l30.o
......@@ -132,6 +133,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o
snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt1305-objs := rt1305.o
......@@ -326,6 +328,7 @@ obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o
obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
......@@ -398,6 +401,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o
......
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Cirrus Logic CS4341A ALSA SoC Codec Driver
* Author: Alexander Shiyan <shc_work@mail.ru>
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#define CS4341_REG_MODE1 0x00
#define CS4341_REG_MODE2 0x01
#define CS4341_REG_MIX 0x02
#define CS4341_REG_VOLA 0x03
#define CS4341_REG_VOLB 0x04
#define CS4341_MODE2_DIF (7 << 4)
#define CS4341_MODE2_DIF_I2S_24 (0 << 4)
#define CS4341_MODE2_DIF_I2S_16 (1 << 4)
#define CS4341_MODE2_DIF_LJ_24 (2 << 4)
#define CS4341_MODE2_DIF_RJ_24 (3 << 4)
#define CS4341_MODE2_DIF_RJ_16 (5 << 4)
#define CS4341_VOLX_MUTE (1 << 7)
struct cs4341_priv {
unsigned int fmt;
struct regmap *regmap;
struct regmap_config regcfg;
};
static const struct reg_default cs4341_reg_defaults[] = {
{ CS4341_REG_MODE1, 0x00 },
{ CS4341_REG_MODE2, 0x82 },
{ CS4341_REG_MIX, 0x49 },
{ CS4341_REG_VOLA, 0x80 },
{ CS4341_REG_VOLB, 0x80 },
};
static int cs4341_set_fmt(struct snd_soc_dai *dai, unsigned int format)
{
struct snd_soc_component *component = dai->component;
struct cs4341_priv *cs4341 = snd_soc_component_get_drvdata(component);
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
default:
return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_LEFT_J:
case SND_SOC_DAIFMT_RIGHT_J:
cs4341->fmt = format & SND_SOC_DAIFMT_FORMAT_MASK;
break;
default:
return -EINVAL;
}
return 0;
}
static int cs4341_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct cs4341_priv *cs4341 = snd_soc_component_get_drvdata(component);
unsigned int mode = 0;
int b24 = 0;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S24_LE:
b24 = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
break;
default:
dev_err(component->dev, "Unsupported PCM format 0x%08x.\n",
params_format(params));
return -EINVAL;
}
switch (cs4341->fmt) {
case SND_SOC_DAIFMT_I2S:
mode = b24 ? CS4341_MODE2_DIF_I2S_24 : CS4341_MODE2_DIF_I2S_16;
break;
case SND_SOC_DAIFMT_LEFT_J:
mode = CS4341_MODE2_DIF_LJ_24;
break;
case SND_SOC_DAIFMT_RIGHT_J:
mode = b24 ? CS4341_MODE2_DIF_RJ_24 : CS4341_MODE2_DIF_RJ_16;
break;
default:
dev_err(component->dev, "Unsupported DAI format 0x%08x.\n",
cs4341->fmt);
return -EINVAL;
}
return snd_soc_component_update_bits(component, CS4341_REG_MODE2,
CS4341_MODE2_DIF, mode);
}
static int cs4341_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
int ret;
ret = snd_soc_component_update_bits(component, CS4341_REG_VOLA,
CS4341_VOLX_MUTE,
mute ? CS4341_VOLX_MUTE : 0);
if (ret < 0)
return ret;
return snd_soc_component_update_bits(component, CS4341_REG_VOLB,
CS4341_VOLX_MUTE,
mute ? CS4341_VOLX_MUTE : 0);
}
static DECLARE_TLV_DB_SCALE(out_tlv, -9000, 100, 0);
static const char * const deemph[] = {
"None", "44.1k", "48k", "32k",
};
static const struct soc_enum deemph_enum =
SOC_ENUM_SINGLE(CS4341_REG_MODE2, 2, 4, deemph);
static const char * const srzc[] = {
"Immediate", "Zero Cross", "Soft Ramp", "SR on ZC",
};
static const struct soc_enum srzc_enum =
SOC_ENUM_SINGLE(CS4341_REG_MIX, 5, 4, srzc);
static const struct snd_soc_dapm_widget cs4341_dapm_widgets[] = {
SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("OutA"),
SND_SOC_DAPM_OUTPUT("OutB"),
};
static const struct snd_soc_dapm_route cs4341_routes[] = {
{ "OutA", NULL, "HiFi DAC" },
{ "OutB", NULL, "HiFi DAC" },
{ "DAC Playback", NULL, "OutA" },
{ "DAC Playback", NULL, "OutB" },
};
static const struct snd_kcontrol_new cs4341_controls[] = {
SOC_DOUBLE_R_TLV("Master Playback Volume",
CS4341_REG_VOLA, CS4341_REG_VOLB, 0, 90, 1, out_tlv),
SOC_ENUM("De-Emphasis Control", deemph_enum),
SOC_ENUM("Soft Ramp Zero Cross Control", srzc_enum),
SOC_SINGLE("Auto-Mute Switch", CS4341_REG_MODE2, 7, 1, 0),
SOC_SINGLE("Popguard Transient Switch", CS4341_REG_MODE2, 1, 1, 0),
};
static const struct snd_soc_dai_ops cs4341_dai_ops = {
.set_fmt = cs4341_set_fmt,
.hw_params = cs4341_hw_params,
.digital_mute = cs4341_digital_mute,
};
static struct snd_soc_dai_driver cs4341_dai = {
.name = "cs4341a-hifi",
.playback = {
.stream_name = "DAC Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &cs4341_dai_ops,
.symmetric_rates = 1,
};
static const struct snd_soc_component_driver soc_component_cs4341 = {
.controls = cs4341_controls,
.num_controls = ARRAY_SIZE(cs4341_controls),
.dapm_widgets = cs4341_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs4341_dapm_widgets),
.dapm_routes = cs4341_routes,
.num_dapm_routes = ARRAY_SIZE(cs4341_routes),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct of_device_id __maybe_unused cs4341_dt_ids[] = {
{ .compatible = "cirrus,cs4341a", },
{ }
};
MODULE_DEVICE_TABLE(of, cs4341_dt_ids);
static int cs4341_probe(struct device *dev)
{
struct cs4341_priv *cs4341 = dev_get_drvdata(dev);
int i;
for (i = 0; i < ARRAY_SIZE(cs4341_reg_defaults); i++)
regmap_write(cs4341->regmap, cs4341_reg_defaults[i].reg,
cs4341_reg_defaults[i].def);
return devm_snd_soc_register_component(dev, &soc_component_cs4341,
&cs4341_dai, 1);
}
#if defined(CONFIG_I2C)
static int cs4341_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct cs4341_priv *cs4341;
cs4341 = devm_kzalloc(&i2c->dev, sizeof(*cs4341), GFP_KERNEL);
if (!cs4341)
return -ENOMEM;
i2c_set_clientdata(i2c, cs4341);
cs4341->regcfg.reg_bits = 8;
cs4341->regcfg.val_bits = 8;
cs4341->regcfg.max_register = CS4341_REG_VOLB;
cs4341->regcfg.cache_type = REGCACHE_FLAT;
cs4341->regcfg.reg_defaults = cs4341_reg_defaults;
cs4341->regcfg.num_reg_defaults = ARRAY_SIZE(cs4341_reg_defaults);
cs4341->regmap = devm_regmap_init_i2c(i2c, &cs4341->regcfg);
if (IS_ERR(cs4341->regmap))
return PTR_ERR(cs4341->regmap);
return cs4341_probe(&i2c->dev);
}
static const struct i2c_device_id cs4341_i2c_id[] = {
{ "cs4341", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs4341_i2c_id);
static struct i2c_driver cs4341_i2c_driver = {
.driver = {
.name = "cs4341-i2c",
.of_match_table = of_match_ptr(cs4341_dt_ids),
},
.probe = cs4341_i2c_probe,
.id_table = cs4341_i2c_id,
};
#endif
#if defined(CONFIG_SPI_MASTER)
static bool cs4341_reg_readable(struct device *dev, unsigned int reg)
{
return false;
}
static int cs4341_spi_probe(struct spi_device *spi)
{
struct cs4341_priv *cs4341;
int ret;
cs4341 = devm_kzalloc(&spi->dev, sizeof(*cs4341), GFP_KERNEL);
if (!cs4341)
return -ENOMEM;
if (!spi->bits_per_word)
spi->bits_per_word = 8;
if (!spi->max_speed_hz)
spi->max_speed_hz = 6000000;
ret = spi_setup(spi);
if (ret)
return ret;
spi_set_drvdata(spi, cs4341);
cs4341->regcfg.reg_bits = 16;
cs4341->regcfg.val_bits = 8;
cs4341->regcfg.write_flag_mask = 0x20;
cs4341->regcfg.max_register = CS4341_REG_VOLB;
cs4341->regcfg.cache_type = REGCACHE_FLAT;
cs4341->regcfg.readable_reg = cs4341_reg_readable;
cs4341->regcfg.reg_defaults = cs4341_reg_defaults;
cs4341->regcfg.num_reg_defaults = ARRAY_SIZE(cs4341_reg_defaults);
cs4341->regmap = devm_regmap_init_spi(spi, &cs4341->regcfg);
if (IS_ERR(cs4341->regmap))
return PTR_ERR(cs4341->regmap);
return cs4341_probe(&spi->dev);
}
static struct spi_driver cs4341_spi_driver = {
.driver = {
.name = "cs4341-spi",
.of_match_table = of_match_ptr(cs4341_dt_ids),
},
.probe = cs4341_spi_probe,
};
#endif
static int __init cs4341_init(void)
{
int ret = 0;
#if defined(CONFIG_I2C)
ret = i2c_add_driver(&cs4341_i2c_driver);
if (ret)
return ret;
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&cs4341_spi_driver);
#endif
return ret;
}
module_init(cs4341_init);
static void __exit cs4341_exit(void)
{
#if defined(CONFIG_I2C)
i2c_del_driver(&cs4341_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&cs4341_spi_driver);
#endif
}
module_exit(cs4341_exit);
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("Cirrus Logic CS4341 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
......@@ -15,12 +15,14 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/jack.h>
#include "es8316.h"
/* In slave mode at single speed, the codec is documented as accepting 5
......@@ -33,6 +35,11 @@ static const unsigned int supported_mclk_lrck_ratios[] = {
};
struct es8316_priv {
struct mutex lock;
struct regmap *regmap;
struct snd_soc_component *component;
struct snd_soc_jack *jack;
int irq;
unsigned int sysclk;
unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
struct snd_pcm_hw_constraint_list sysclk_constraints;
......@@ -94,6 +101,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = {
SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0),
SOC_ENUM("Capture Polarity", adcpol),
SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
......@@ -529,8 +537,162 @@ static struct snd_soc_dai_driver es8316_dai = {
.symmetric_rates = 1,
};
static void es8316_enable_micbias_for_mic_gnd_short_detect(
struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
msleep(20);
}
static void es8316_disable_micbias_for_mic_gnd_short_detect(
struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias");
snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power");
snd_soc_dapm_disable_pin_unlocked(dapm, "Bias");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
}
static irqreturn_t es8316_irq(int irq, void *data)
{
struct es8316_priv *es8316 = data;
struct snd_soc_component *comp = es8316->component;
unsigned int flags;
mutex_lock(&es8316->lock);
regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
if (flags == 0x00)
goto out; /* Powered-down / reset */
/* Catch spurious IRQ before set_jack is called */
if (!es8316->jack)
goto out;
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack removed, or spurious IRQ? */
if (es8316->jack->status & SND_JACK_MICROPHONE)
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
if (es8316->jack->status & SND_JACK_HEADPHONE) {
snd_soc_jack_report(es8316->jack, 0,
SND_JACK_HEADSET | SND_JACK_BTN_0);
dev_dbg(comp->dev, "jack unplugged\n");
}
} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
/* Jack inserted, determine type */
es8316_enable_micbias_for_mic_gnd_short_detect(comp);
regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack unplugged underneath us */
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
/* Open, headset */
snd_soc_jack_report(es8316->jack,
SND_JACK_HEADSET,
SND_JACK_HEADSET);
/* Keep mic-gnd-short detection on for button press */
} else {
/* Shorted, headphones */
snd_soc_jack_report(es8316->jack,
SND_JACK_HEADPHONE,
SND_JACK_HEADSET);
/* No longer need mic-gnd-short detection */
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
}
} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
/* Interrupt while jack inserted, report button state */
if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
/* Open, button release */
snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
} else {
/* Short, button press */
snd_soc_jack_report(es8316->jack,
SND_JACK_BTN_0,
SND_JACK_BTN_0);
}
}
out:
mutex_unlock(&es8316->lock);
return IRQ_HANDLED;
}
static void es8316_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
mutex_lock(&es8316->lock);
es8316->jack = jack;
if (es8316->jack->status & SND_JACK_MICROPHONE)
es8316_enable_micbias_for_mic_gnd_short_detect(component);
snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
ES8316_GPIO_ENABLE_INTERRUPT,
ES8316_GPIO_ENABLE_INTERRUPT);
mutex_unlock(&es8316->lock);
/* Enable irq and sync initial jack state */
enable_irq(es8316->irq);
es8316_irq(es8316->irq, es8316);
}
static void es8316_disable_jack_detect(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
disable_irq(es8316->irq);
mutex_lock(&es8316->lock);
snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
ES8316_GPIO_ENABLE_INTERRUPT, 0);
if (es8316->jack->status & SND_JACK_MICROPHONE) {
es8316_disable_micbias_for_mic_gnd_short_detect(component);
snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
}
es8316->jack = NULL;
mutex_unlock(&es8316->lock);
}
static int es8316_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{
if (jack)
es8316_enable_jack_detect(component, jack);
else
es8316_disable_jack_detect(component);
return 0;
}
static int es8316_probe(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
es8316->component = component;
/* Reset codec and enable current state machine */
snd_soc_component_write(component, ES8316_RESET, 0x3f);
usleep_range(5000, 5500);
......@@ -555,6 +717,7 @@ static int es8316_probe(struct snd_soc_component *component)
static const struct snd_soc_component_driver soc_component_dev_es8316 = {
.probe = es8316_probe,
.set_jack = es8316_set_jack,
.controls = es8316_snd_controls,
.num_controls = ARRAY_SIZE(es8316_snd_controls),
.dapm_widgets = es8316_dapm_widgets,
......@@ -566,18 +729,29 @@ static const struct snd_soc_component_driver soc_component_dev_es8316 = {
.non_legacy_dai_naming = 1,
};
static const struct regmap_range es8316_volatile_ranges[] = {
regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG),
};
static const struct regmap_access_table es8316_volatile_table = {
.yes_ranges = es8316_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges),
};
static const struct regmap_config es8316_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x53,
.volatile_table = &es8316_volatile_table,
.cache_type = REGCACHE_RBTREE,
};
static int es8316_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct device *dev = &i2c_client->dev;
struct es8316_priv *es8316;
struct regmap *regmap;
int ret;
es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
GFP_KERNEL);
......@@ -586,9 +760,23 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client,
i2c_set_clientdata(i2c_client, es8316);
regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
if (IS_ERR(es8316->regmap))
return PTR_ERR(es8316->regmap);
es8316->irq = i2c_client->irq;
mutex_init(&es8316->lock);
ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"es8316", es8316);
if (ret == 0) {
/* Gets re-enabled by es8316_set_jack() */
disable_irq(es8316->irq);
} else {
dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret);
es8316->irq = -ENXIO;
}
return devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_es8316,
......
......@@ -126,4 +126,11 @@
#define ES8316_SERDATA2_LEN_16 0x0c
#define ES8316_SERDATA2_LEN_32 0x10
/* ES8316_GPIO_DEBOUNCE */
#define ES8316_GPIO_ENABLE_INTERRUPT 0x02
/* ES8316_GPIO_FLAG */
#define ES8316_GPIO_FLAG_GM_NOT_SHORTED 0x02
#define ES8316_GPIO_FLAG_HP_NOT_INSERTED 0x04
#endif
......@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
if (ret != 0) {
dev_err(component->dev,
"Failed to set digital mute: %d\n", ret);
mutex_unlock(&pcm512x->mutex);
return ret;
goto unlock;
}
regmap_read_poll_timeout(pcm512x->regmap,
PCM512x_ANALOG_MUTE_DET,
mute_det, (mute_det & 0x3) == 0,
200, 10000);
mutex_unlock(&pcm512x->mutex);
} else {
pcm512x->mute &= ~0x1;
ret = pcm512x_update_mute(pcm512x);
if (ret != 0) {
dev_err(component->dev,
"Failed to update digital mute: %d\n", ret);
mutex_unlock(&pcm512x->mutex);
return ret;
goto unlock;
}
regmap_read_poll_timeout(pcm512x->regmap,
......@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
200, 10000);
}
unlock:
mutex_unlock(&pcm512x->mutex);
return 0;
return ret;
}
static const struct snd_soc_dai_ops pcm512x_dai_ops = {
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* rk3328 ALSA SoC Audio driver
*
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
*/
#ifndef _RK3328_CODEC_H
#define _RK3328_CODEC_H
#include <linux/bitfield.h>
/* codec register */
#define CODEC_RESET (0x00 << 2)
#define DAC_INIT_CTRL1 (0x03 << 2)
#define DAC_INIT_CTRL2 (0x04 << 2)
#define DAC_INIT_CTRL3 (0x05 << 2)
#define DAC_PRECHARGE_CTRL (0x22 << 2)
#define DAC_PWR_CTRL (0x23 << 2)
#define DAC_CLK_CTRL (0x24 << 2)
#define HPMIX_CTRL (0x25 << 2)
#define DAC_SELECT (0x26 << 2)
#define HPOUT_CTRL (0x27 << 2)
#define HPOUTL_GAIN_CTRL (0x28 << 2)
#define HPOUTR_GAIN_CTRL (0x29 << 2)
#define HPOUT_POP_CTRL (0x2a << 2)
/* REG00: CODEC_RESET */
#define PWR_RST_BYPASS_DIS (0x0 << 6)
#define PWR_RST_BYPASS_EN (0x1 << 6)
#define DIG_CORE_RST (0x0 << 1)
#define DIG_CORE_WORK (0x1 << 1)
#define SYS_RST (0x0 << 0)
#define SYS_WORK (0x1 << 0)
/* REG03: DAC_INIT_CTRL1 */
#define PIN_DIRECTION_MASK BIT(5)
#define PIN_DIRECTION_IN (0x0 << 5)
#define PIN_DIRECTION_OUT (0x1 << 5)
#define DAC_I2S_MODE_MASK BIT(4)
#define DAC_I2S_MODE_SLAVE (0x0 << 4)
#define DAC_I2S_MODE_MASTER (0x1 << 4)
/* REG04: DAC_INIT_CTRL2 */
#define DAC_I2S_LRP_MASK BIT(7)
#define DAC_I2S_LRP_NORMAL (0x0 << 7)
#define DAC_I2S_LRP_REVERSAL (0x1 << 7)
#define DAC_VDL_MASK GENMASK(6, 5)
#define DAC_VDL_16BITS (0x0 << 5)
#define DAC_VDL_20BITS (0x1 << 5)
#define DAC_VDL_24BITS (0x2 << 5)
#define DAC_VDL_32BITS (0x3 << 5)
#define DAC_MODE_MASK GENMASK(4, 3)
#define DAC_MODE_RJM (0x0 << 3)
#define DAC_MODE_LJM (0x1 << 3)
#define DAC_MODE_I2S (0x2 << 3)
#define DAC_MODE_PCM (0x3 << 3)
#define DAC_LR_SWAP_MASK BIT(2)
#define DAC_LR_SWAP_DIS (0x0 << 2)
#define DAC_LR_SWAP_EN (0x1 << 2)
/* REG05: DAC_INIT_CTRL3 */
#define DAC_WL_MASK GENMASK(3, 2)
#define DAC_WL_16BITS (0x0 << 2)
#define DAC_WL_20BITS (0x1 << 2)
#define DAC_WL_24BITS (0x2 << 2)
#define DAC_WL_32BITS (0x3 << 2)
#define DAC_RST_MASK BIT(1)
#define DAC_RST_EN (0x0 << 1)
#define DAC_RST_DIS (0x1 << 1)
#define DAC_BCP_MASK BIT(0)
#define DAC_BCP_NORMAL (0x0 << 0)
#define DAC_BCP_REVERSAL (0x1 << 0)
/* REG22: DAC_PRECHARGE_CTRL */
#define DAC_CHARGE_XCHARGE_MASK BIT(7)
#define DAC_CHARGE_DISCHARGE (0x0 << 7)
#define DAC_CHARGE_PRECHARGE (0x1 << 7)
#define DAC_CHARGE_CURRENT_64I_MASK BIT(6)
#define DAC_CHARGE_CURRENT_64I (0x1 << 6)
#define DAC_CHARGE_CURRENT_32I_MASK BIT(5)
#define DAC_CHARGE_CURRENT_32I (0x1 << 5)
#define DAC_CHARGE_CURRENT_16I_MASK BIT(4)
#define DAC_CHARGE_CURRENT_16I (0x1 << 4)
#define DAC_CHARGE_CURRENT_08I_MASK BIT(3)
#define DAC_CHARGE_CURRENT_08I (0x1 << 3)
#define DAC_CHARGE_CURRENT_04I_MASK BIT(2)
#define DAC_CHARGE_CURRENT_04I (0x1 << 2)
#define DAC_CHARGE_CURRENT_02I_MASK BIT(1)
#define DAC_CHARGE_CURRENT_02I (0x1 << 1)
#define DAC_CHARGE_CURRENT_I_MASK BIT(0)
#define DAC_CHARGE_CURRENT_I (0x1 << 0)
#define DAC_CHARGE_CURRENT_ALL_MASK GENMASK(6, 0)
#define DAC_CHARGE_CURRENT_ALL_OFF 0x00
#define DAC_CHARGE_CURRENT_ALL_ON 0x7f
/* REG23: DAC_PWR_CTRL */
#define DAC_PWR_MASK BIT(6)
#define DAC_PWR_OFF (0x0 << 6)
#define DAC_PWR_ON (0x1 << 6)
#define DACL_PATH_REFV_MASK BIT(5)
#define DACL_PATH_REFV_OFF (0x0 << 5)
#define DACL_PATH_REFV_ON (0x1 << 5)
#define HPOUTL_ZERO_CROSSING_MASK BIT(4)
#define HPOUTL_ZERO_CROSSING_OFF (0x0 << 4)
#define HPOUTL_ZERO_CROSSING_ON (0x1 << 4)
#define DACR_PATH_REFV_MASK BIT(1)
#define DACR_PATH_REFV_OFF (0x0 << 1)
#define DACR_PATH_REFV_ON (0x1 << 1)
#define HPOUTR_ZERO_CROSSING_MASK BIT(0)
#define HPOUTR_ZERO_CROSSING_OFF (0x0 << 0)
#define HPOUTR_ZERO_CROSSING_ON (0x1 << 0)
/* REG24: DAC_CLK_CTRL */
#define DACL_REFV_MASK BIT(7)
#define DACL_REFV_OFF (0x0 << 7)
#define DACL_REFV_ON (0x1 << 7)
#define DACL_CLK_MASK BIT(6)
#define DACL_CLK_OFF (0x0 << 6)
#define DACL_CLK_ON (0x1 << 6)
#define DACL_MASK BIT(5)
#define DACL_OFF (0x0 << 5)
#define DACL_ON (0x1 << 5)
#define DACL_INIT_MASK BIT(4)
#define DACL_INIT_OFF (0x0 << 4)
#define DACL_INIT_ON (0x1 << 4)
#define DACR_REFV_MASK BIT(3)
#define DACR_REFV_OFF (0x0 << 3)
#define DACR_REFV_ON (0x1 << 3)
#define DACR_CLK_MASK BIT(2)
#define DACR_CLK_OFF (0x0 << 2)
#define DACR_CLK_ON (0x1 << 2)
#define DACR_MASK BIT(1)
#define DACR_OFF (0x0 << 1)
#define DACR_ON (0x1 << 1)
#define DACR_INIT_MASK BIT(0)
#define DACR_INIT_OFF (0x0 << 0)
#define DACR_INIT_ON (0x1 << 0)
/* REG25: HPMIX_CTRL*/
#define HPMIXL_MASK BIT(6)
#define HPMIXL_DIS (0x0 << 6)
#define HPMIXL_EN (0x1 << 6)
#define HPMIXL_INIT_MASK BIT(5)
#define HPMIXL_INIT_DIS (0x0 << 5)
#define HPMIXL_INIT_EN (0x1 << 5)
#define HPMIXL_INIT2_MASK BIT(4)
#define HPMIXL_INIT2_DIS (0x0 << 4)
#define HPMIXL_INIT2_EN (0x1 << 4)
#define HPMIXR_MASK BIT(2)
#define HPMIXR_DIS (0x0 << 2)
#define HPMIXR_EN (0x1 << 2)
#define HPMIXR_INIT_MASK BIT(1)
#define HPMIXR_INIT_DIS (0x0 << 1)
#define HPMIXR_INIT_EN (0x1 << 1)
#define HPMIXR_INIT2_MASK BIT(0)
#define HPMIXR_INIT2_DIS (0x0 << 0)
#define HPMIXR_INIT2_EN (0x1 << 0)
/* REG26: DAC_SELECT */
#define DACL_SELECT_MASK BIT(4)
#define DACL_UNSELECT (0x0 << 4)
#define DACL_SELECT (0x1 << 4)
#define DACR_SELECT_MASK BIT(0)
#define DACR_UNSELECT (0x0 << 0)
#define DACR_SELECT (0x1 << 0)
/* REG27: HPOUT_CTRL */
#define HPOUTL_MASK BIT(7)
#define HPOUTL_DIS (0x0 << 7)
#define HPOUTL_EN (0x1 << 7)
#define HPOUTL_INIT_MASK BIT(6)
#define HPOUTL_INIT_DIS (0x0 << 6)
#define HPOUTL_INIT_EN (0x1 << 6)
#define HPOUTL_MUTE_MASK BIT(5)
#define HPOUTL_MUTE (0x0 << 5)
#define HPOUTL_UNMUTE (0x1 << 5)
#define HPOUTR_MASK BIT(4)
#define HPOUTR_DIS (0x0 << 4)
#define HPOUTR_EN (0x1 << 4)
#define HPOUTR_INIT_MASK BIT(3)
#define HPOUTR_INIT_DIS (0x0 << 3)
#define HPOUTR_INIT_EN (0x1 << 3)
#define HPOUTR_MUTE_MASK BIT(2)
#define HPOUTR_MUTE (0x0 << 2)
#define HPOUTR_UNMUTE (0x1 << 2)
/* REG28: HPOUTL_GAIN_CTRL */
#define HPOUTL_GAIN_MASK GENMASK(4, 0)
/* REG29: HPOUTR_GAIN_CTRL */
#define HPOUTR_GAIN_MASK GENMASK(4, 0)
/* REG2a: HPOUT_POP_CTRL */
#define HPOUTR_POP_MASK GENMASK(5, 4)
#define HPOUTR_POP_XCHARGE (0x1 << 4)
#define HPOUTR_POP_WORK (0x2 << 4)
#define HPOUTL_POP_MASK GENMASK(1, 0)
#define HPOUTL_POP_XCHARGE (0x1 << 0)
#define HPOUTL_POP_WORK (0x2 << 0)
#define RK3328_HIFI 0
struct rk3328_reg_msk_val {
unsigned int reg;
unsigned int msk;
unsigned int val;
};
#endif
......@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
return ret;
}
regmap_read(rt274->regmap,
ret = regmap_read(rt274->regmap,
RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
if (ret)
return ret;
if (val != RT274_VENDOR_ID) {
dev_err(&i2c->dev,
"Device with ID register %#x is not rt274\n", val);
......
......@@ -2512,6 +2512,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000);
regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000);
regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005);
regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4);
mutex_unlock(&rt5682->calibrate_mutex);
......
......@@ -1837,9 +1837,6 @@ static int wm8904_set_bias_level(struct snd_soc_component *component,
switch (level) {
case SND_SOC_BIAS_ON:
ret = clk_prepare_enable(wm8904->mclk);
if (ret)
return ret;
break;
case SND_SOC_BIAS_PREPARE:
......@@ -1864,6 +1861,15 @@ static int wm8904_set_bias_level(struct snd_soc_component *component,
return ret;
}
ret = clk_prepare_enable(wm8904->mclk);
if (ret) {
dev_err(component->dev,
"Failed to enable MCLK: %d\n", ret);
regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
wm8904->supplies);
return ret;
}
regcache_cache_only(wm8904->regmap, false);
regcache_sync(wm8904->regmap);
......@@ -2108,16 +2114,13 @@ static const struct regmap_config wm8904_regmap = {
};
#ifdef CONFIG_OF
static enum wm8904_type wm8904_data = WM8904;
static enum wm8904_type wm8912_data = WM8912;
static const struct of_device_id wm8904_of_match[] = {
{
.compatible = "wlf,wm8904",
.data = &wm8904_data,
.data = (void *)WM8904,
}, {
.compatible = "wlf,wm8912",
.data = &wm8912_data,
.data = (void *)WM8912,
}, {
/* sentinel */
}
......@@ -2158,7 +2161,7 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
match = of_match_node(wm8904_of_match, i2c->dev.of_node);
if (match == NULL)
return -EINVAL;
wm8904->devtype = *((enum wm8904_type *)match->data);
wm8904->devtype = (enum wm8904_type)match->data;
} else {
wm8904->devtype = id->driver_data;
}
......
......@@ -8,14 +8,6 @@ config SND_SIMPLE_CARD
This option enables generic simple sound card support
It also support DPCM of multi CPU single Codec ststem.
config SND_SIMPLE_SCU_CARD
tristate "ASoC Simple SCU sound card support"
depends on OF
select SND_SIMPLE_CARD_UTILS
help
This option enables generic simple SCU sound card support.
It supports DPCM of multi CPU single Codec system.
config SND_AUDIO_GRAPH_CARD
tristate "ASoC Audio Graph sound card support"
depends on OF
......@@ -24,12 +16,3 @@ config SND_AUDIO_GRAPH_CARD
This option enables generic simple sound card support
with OF-graph DT bindings.
It also support DPCM of multi CPU single Codec ststem.
config SND_AUDIO_GRAPH_SCU_CARD
tristate "ASoC Audio Graph SCU sound card support"
depends on OF
select SND_SIMPLE_CARD_UTILS
help
This option enables generic simple SCU sound card support
with OF-graph DT bindings.
It supports DPCM of multi CPU single Codec ststem.
# SPDX-License-Identifier: GPL-2.0
snd-soc-simple-card-utils-objs := simple-card-utils.o
snd-soc-simple-card-objs := simple-card.o
snd-soc-simple-scu-card-objs := simple-scu-card.o
snd-soc-audio-graph-card-objs := audio-graph-card.o
snd-soc-audio-graph-scu-card-objs := audio-graph-scu-card.o
obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o
obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o
obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o
obj-$(CONFIG_SND_AUDIO_GRAPH_SCU_CARD) += snd-soc-audio-graph-scu-card.o
This diff is collapsed.
This diff is collapsed.
......@@ -283,12 +283,20 @@ static int asoc_simple_card_get_dai_id(struct device_node *ep)
/* use endpoint/port reg if exist */
ret = of_graph_parse_endpoint(ep, &info);
if (ret == 0) {
if (info.id)
/*
* Because it will count port/endpoint if it doesn't have "reg".
* But, we can't judge whether it has "no reg", or "reg = <0>"
* only of_graph_parse_endpoint().
* We need to check "reg" property
*/
if (of_get_property(ep, "reg", NULL))
return info.id;
if (info.port)
node = of_get_parent(ep);
of_node_put(node);
if (of_get_property(node, "reg", NULL))
return info.port;
}
node = of_graph_get_port_parent(ep);
/*
......
This diff is collapsed.
This diff is collapsed.
......@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
default ACPI
depends on X86 && ACPI
depends on X86 && ACPI && PCI
select SND_SST_IPC_ACPI
select SND_SST_ATOM_HIFI2_PLATFORM
select SND_SOC_ACPI_INTEL_MATCH
......
......@@ -647,7 +647,7 @@ static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w,
set_mixer = false;
}
if (set_mixer == false)
if (!set_mixer)
return 0;
if (SND_SOC_DAPM_EVENT_ON(event) ||
......
......@@ -190,7 +190,7 @@ int sst_fill_stream_params(void *substream,
map = ctx->pdata->pdev_strm_map;
map_size = ctx->pdata->strm_map_size;
if (is_compress == true)
if (is_compress)
cstream = (struct snd_compr_stream *)substream;
else
pstream = (struct snd_pcm_substream *)substream;
......
......@@ -255,18 +255,16 @@ static int is_byt(void)
return status;
}
static int is_byt_cr(struct device *dev, bool *bytcr)
static bool is_byt_cr(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int status = 0;
if (IS_ENABLED(CONFIG_IOSF_MBI)) {
u32 bios_status;
if (!is_byt() || !iosf_mbi_available()) {
/* bail silently */
return status;
}
if (!is_byt())
return false;
if (iosf_mbi_available()) {
u32 bios_status;
status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */
MBI_REG_READ, /* 0x10 */
0x006, /* BIOS_CONFIG */
......@@ -278,15 +276,28 @@ static int is_byt_cr(struct device *dev, bool *bytcr)
/* bits 26:27 mirror PMIC options */
bios_status = (bios_status >> 26) & 3;
if ((bios_status == 1) || (bios_status == 3))
*bytcr = true;
else
if (bios_status == 1 || bios_status == 3) {
dev_info(dev, "Detected Baytrail-CR platform\n");
return true;
}
dev_info(dev, "BYT-CR not detected\n");
}
} else {
dev_info(dev, "IOSF_MBI not enabled, no BYT-CR detection\n");
dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n");
}
return status;
if (platform_get_resource(pdev, IORESOURCE_IRQ, 5) == NULL) {
/*
* Some devices detected as BYT-T have only a single IRQ listed,
* causing platform_get_irq with index 5 to return -ENXIO.
* The correct IRQ in this case is at index 0, as on BYT-CR.
*/
dev_info(dev, "Falling back to Baytrail-CR platform\n");
return true;
}
return false;
}
......@@ -301,7 +312,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
struct platform_device *plat_dev;
struct sst_platform_info *pdata;
unsigned int dev_id;
bool bytcr = false;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
......@@ -333,10 +343,7 @@ static int sst_acpi_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
ret = is_byt_cr(dev, &bytcr);
if (!((ret < 0) || (bytcr == false))) {
dev_info(dev, "Detected Baytrail-CR platform\n");
if (is_byt_cr(pdev)) {
/* override resource info */
byt_rvp_platform_data.res_info = &bytcr_res_info;
}
......
......@@ -146,7 +146,7 @@ static int sst_power_control(struct device *dev, bool state)
int ret = 0;
int usage_count = 0;
if (state == true) {
if (state) {
ret = pm_runtime_get_sync(dev);
usage_count = GET_USAGE_COUNT(dev);
dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
......
......@@ -269,7 +269,7 @@ static void sst_do_memcpy(struct list_head *memcpy_list)
struct sst_memcpy_list *listnode;
list_for_each_entry(listnode, memcpy_list, memcpylist) {
if (listnode->is_io == true)
if (listnode->is_io)
memcpy32_toio((void __iomem *)listnode->dstn,
listnode->src, listnode->size);
else
......
......@@ -278,7 +278,6 @@ static int sst_byt_process_notification(struct sst_byt *byt,
struct sst_byt_stream *stream;
u64 header;
u8 msg_id, stream_id;
int handled = 1;
header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
msg_id = sst_byt_header_msg_id(header);
......@@ -298,7 +297,7 @@ static int sst_byt_process_notification(struct sst_byt *byt,
break;
}
return handled;
return 1;
}
static irqreturn_t sst_byt_irq_thread(int irq, void *context)
......
......@@ -188,7 +188,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
sst_byt_stream_start(byt, pcm_data->stream, 0);
break;
case SNDRV_PCM_TRIGGER_RESUME:
if (pdata->restore_stream == true)
if (pdata->restore_stream)
schedule_work(&pcm_data->work);
else
sst_byt_stream_resume(byt, pcm_data->stream);
......
......@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
.stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio",
.dynamic = 0,
.dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
......
This diff is collapsed.
......@@ -428,6 +428,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
......
......@@ -164,7 +164,7 @@ static int geminilake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
/* set SSP to 24 bit */
snd_mask_none(fmt);
snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
......
......@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
.stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio",
.dynamic = 0,
.dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
......
......@@ -221,7 +221,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
snd_mask_none(fmt);
snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
}
/*
......@@ -229,7 +229,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
* thus changing the mask here
*/
if (!strcmp(be_dai_link->name, "SSP0-Codec"))
snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE);
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}
......
......@@ -154,6 +154,15 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = {
.sof_tplg_filename = "intel/sof-byt-da7213.tplg",
.asoc_plat_name = "sst-mfld-platform",
},
{
.id = "ESSX8316",
.drv_name = "bytcht_es8316",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcht_es8316",
.sof_fw_filename = "intel/sof-byt.ri",
.sof_tplg_filename = "intel/sof-byt-es8316.tplg",
.asoc_plat_name = "sst-mfld-platform",
},
/* some Baytrail platforms rely on RT5645, use CHT machine driver */
{
.id = "10EC5645",
......
......@@ -1216,7 +1216,7 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
return ret;
}
stream->commited = 1;
stream->commited = true;
trace_hsw_stream_alloc_reply(stream);
return 0;
......
......@@ -544,7 +544,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
dev_err(rtd->dev, "error: invalid DAI ID %d\n",
rtd->cpu_dai->id);
return -EINVAL;
};
}
ret = sst_hsw_stream_format(hsw, pcm_data->stream,
path_id, stream_type, SST_HSW_STREAM_FORMAT_PCM_FORMAT);
......@@ -861,7 +861,7 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream)
dev_dbg(rtd->dev, "error: free stream failed %d\n", ret);
goto out;
}
pcm_data->allocated = 0;
pcm_data->allocated = false;
pcm_data->stream = NULL;
out:
......
......@@ -416,7 +416,7 @@ int skl_resume_dsp(struct skl *skl)
snd_hdac_ext_bus_ppcap_int_enable(bus, true);
/* check if DSP 1st boot is done */
if (skl->skl_sst->is_first_boot == true)
if (skl->skl_sst->is_first_boot)
return 0;
/*
......
......@@ -1423,7 +1423,7 @@ static int skl_platform_soc_probe(struct snd_soc_component *component)
if (!ops)
return -EIO;
if (skl->skl_sst->is_first_boot == false) {
if (!skl->skl_sst->is_first_boot) {
dev_err(component->dev, "DSP reports first boot done!!!\n");
return -EIO;
}
......
......@@ -3103,7 +3103,7 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
ac->size = dfw_ac->max;
if (ac->max) {
ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
ac->params = devm_kzalloc(dev, ac->max, GFP_KERNEL);
if (!ac->params)
return -ENOMEM;
......
This diff is collapsed.
This diff is collapsed.
......@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
pr_debug("PCM data: addr 0x%08ulx len %d\n",
pr_debug("PCM data: addr 0x%08lx len %d\n",
(u32)runtime->dma_addr, runtime->dma_bytes);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
......
This diff is collapsed.
config SND_SOC_XILINX_I2S
tristate "Audio support for the the Xilinx I2S"
tristate "Audio support for the Xilinx I2S"
help
Select this option to enable Xilinx I2S Audio. This enables
I2S playback and capture using xilinx soft IP. In transmitter
mode, IP receives audio in AES format, extracts PCM and sends
PCM data. In receiver mode, IP receives PCM audio and
encapsulates PCM in AES format and sends AES data.
config SND_SOC_XILINX_AUDIO_FORMATTER
tristate "Audio support for the the Xilinx audio formatter"
help
Select this option to enable Xilinx audio formatter
support. This provides DMA platform device support for
audio functionality.
snd-soc-xlnx-i2s-objs := xlnx_i2s.o
obj-$(CONFIG_SND_SOC_XILINX_I2S) += snd-soc-xlnx-i2s.o
snd-soc-xlnx-formatter-pcm-objs := xlnx_formatter_pcm.o
obj-$(CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER) += snd-soc-xlnx-formatter-pcm.o
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment