Merge branch 'asoc-5.4' into asoc-next
This commit is contained in:
@@ -529,10 +529,6 @@ static const struct snd_kcontrol_new pm860x_snd_controls[] = {
|
||||
* DAPM Controls
|
||||
*/
|
||||
|
||||
/* PCM Switch / PCM Interface */
|
||||
static const struct snd_kcontrol_new pcm_switch_controls =
|
||||
SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
|
||||
|
||||
/* AUX1 Switch */
|
||||
static const struct snd_kcontrol_new aux1_switch_controls =
|
||||
SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
|
||||
@@ -549,17 +545,6 @@ static const struct snd_kcontrol_new lepa_switch_controls =
|
||||
static const struct snd_kcontrol_new repa_switch_controls =
|
||||
SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
|
||||
|
||||
/* PCM Mux / Mux7 */
|
||||
static const char *aif1_text[] = {
|
||||
"PCM L", "PCM R",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(aif1_enum,
|
||||
PM860X_PCM_IFACE_3, 6, aif1_text);
|
||||
|
||||
static const struct snd_kcontrol_new aif1_mux =
|
||||
SOC_DAPM_ENUM("PCM Mux", aif1_enum);
|
||||
|
||||
/* I2S Mux / Mux9 */
|
||||
static const char *i2s_din_text[] = {
|
||||
"DIN", "DIN1",
|
||||
|
@@ -70,10 +70,12 @@ config SND_SOC_ALL_CODECS
|
||||
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_CS47L15 if MFD_CS47L15
|
||||
select SND_SOC_CS47L24 if MFD_CS47L24
|
||||
select SND_SOC_CS47L35 if MFD_CS47L35
|
||||
select SND_SOC_CS47L85 if MFD_CS47L85
|
||||
select SND_SOC_CS47L90 if MFD_CS47L90
|
||||
select SND_SOC_CS47L92 if MFD_CS47L92
|
||||
select SND_SOC_CS53L30 if I2C
|
||||
select SND_SOC_CX20442 if TTY
|
||||
select SND_SOC_CX2072X if I2C
|
||||
@@ -197,6 +199,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_TS3A227E if I2C
|
||||
select SND_SOC_TWL4030 if TWL4030_CORE
|
||||
select SND_SOC_TWL6040 if TWL6040_CORE
|
||||
select SND_SOC_UDA1334 if GPIOLIB
|
||||
select SND_SOC_UDA134X
|
||||
select SND_SOC_UDA1380 if I2C
|
||||
select SND_SOC_WCD9335 if SLIMBUS
|
||||
@@ -581,6 +584,9 @@ config SND_SOC_CS4349
|
||||
tristate "Cirrus Logic CS4349 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_CS47L15
|
||||
tristate
|
||||
|
||||
config SND_SOC_CS47L24
|
||||
tristate
|
||||
|
||||
@@ -593,6 +599,9 @@ config SND_SOC_CS47L85
|
||||
config SND_SOC_CS47L90
|
||||
tristate
|
||||
|
||||
config SND_SOC_CS47L92
|
||||
tristate
|
||||
|
||||
# Cirrus Logic Quad-Channel ADC
|
||||
config SND_SOC_CS53L30
|
||||
tristate "Cirrus Logic CS53L30 CODEC"
|
||||
@@ -722,12 +731,16 @@ config SND_SOC_LOCHNAGAR_SC
|
||||
|
||||
config SND_SOC_MADERA
|
||||
tristate
|
||||
default y if SND_SOC_CS47L15=y
|
||||
default y if SND_SOC_CS47L35=y
|
||||
default y if SND_SOC_CS47L85=y
|
||||
default y if SND_SOC_CS47L90=y
|
||||
default y if SND_SOC_CS47L92=y
|
||||
default m if SND_SOC_CS47L15=m
|
||||
default m if SND_SOC_CS47L35=m
|
||||
default m if SND_SOC_CS47L85=m
|
||||
default m if SND_SOC_CS47L90=m
|
||||
default m if SND_SOC_CS47L92=m
|
||||
|
||||
config SND_SOC_MAX98088
|
||||
tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec"
|
||||
@@ -1195,6 +1208,14 @@ config SND_SOC_TWL4030
|
||||
config SND_SOC_TWL6040
|
||||
tristate
|
||||
|
||||
config SND_SOC_UDA1334
|
||||
tristate "NXP UDA1334 DAC"
|
||||
depends on GPIOLIB
|
||||
help
|
||||
The UDA1334 is an NXP audio codec, supports the I2S-bus data format
|
||||
and has basic features such as de-emphasis (at 44.1 kHz sampling
|
||||
rate) and mute.
|
||||
|
||||
config SND_SOC_UDA134X
|
||||
tristate
|
||||
|
||||
|
@@ -64,10 +64,12 @@ 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-cs47l15-objs := cs47l15.o
|
||||
snd-soc-cs47l24-objs := cs47l24.o
|
||||
snd-soc-cs47l35-objs := cs47l35.o
|
||||
snd-soc-cs47l85-objs := cs47l85.o
|
||||
snd-soc-cs47l90-objs := cs47l90.o
|
||||
snd-soc-cs47l92-objs := cs47l92.o
|
||||
snd-soc-cs53l30-objs := cs53l30.o
|
||||
snd-soc-cx20442-objs := cx20442.o
|
||||
snd-soc-cx2072x-objs := cx2072x.o
|
||||
@@ -210,6 +212,7 @@ snd-soc-tscs454-objs := tscs454.o
|
||||
snd-soc-ts3a227e-objs := ts3a227e.o
|
||||
snd-soc-twl4030-objs := twl4030.o
|
||||
snd-soc-twl6040-objs := twl6040.o
|
||||
snd-soc-uda1334-objs := uda1334.o
|
||||
snd-soc-uda134x-objs := uda134x.o
|
||||
snd-soc-uda1380-objs := uda1380.o
|
||||
snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o
|
||||
@@ -346,9 +349,11 @@ 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_CS47L15) += snd-soc-cs47l15.o
|
||||
obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o
|
||||
obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o
|
||||
obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o
|
||||
obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o
|
||||
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
|
||||
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
|
||||
obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o
|
||||
@@ -490,6 +495,7 @@ obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o
|
||||
obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
|
||||
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
|
||||
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
|
||||
obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
|
||||
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
|
||||
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
|
||||
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
|
||||
|
@@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
|
||||
.ops = &ad193x_dai_ops,
|
||||
};
|
||||
|
||||
struct ad193x_reg_default {
|
||||
unsigned int reg;
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
/* codec register values to set after reset */
|
||||
static void ad193x_reg_default_init(struct ad193x_priv *ad193x)
|
||||
{
|
||||
const struct ad193x_reg_default reg_init[] = {
|
||||
static const struct reg_sequence reg_init[] = {
|
||||
{ 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */
|
||||
{ 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */
|
||||
{ 2, 0x40 }, /* DAC_CTRL0: TDM mode */
|
||||
@@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x)
|
||||
{ 12, 0x00 }, /* DAC_L4_VOL: no attenuation */
|
||||
{ 13, 0x00 }, /* DAC_R4_VOL: no attenuation */
|
||||
};
|
||||
const struct ad193x_reg_default reg_adc_init[] = {
|
||||
static const struct reg_sequence reg_adc_init[] = {
|
||||
{ 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */
|
||||
{ 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */
|
||||
{ 16, 0x00 }, /* ADC_CTRL2: reset */
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reg_init); i++)
|
||||
regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val);
|
||||
regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init));
|
||||
|
||||
if (ad193x_has_adc(ad193x)) {
|
||||
for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) {
|
||||
regmap_write(ad193x->regmap, reg_adc_init[i].reg,
|
||||
reg_adc_init[i].val);
|
||||
}
|
||||
regmap_multi_reg_write(ad193x->regmap, reg_adc_init,
|
||||
ARRAY_SIZE(reg_adc_init));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -334,7 +334,7 @@ static struct cs4271_clk_cfg cs4271_clk_tab[] = {
|
||||
{0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2},
|
||||
};
|
||||
|
||||
#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
|
||||
#define CS4271_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
|
||||
|
||||
static int cs4271_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
@@ -383,13 +383,13 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
|
||||
val = CS4271_MODE1_MODE_4X;
|
||||
|
||||
ratio = cs4271->mclk / cs4271->rate;
|
||||
for (i = 0; i < CS4171_NR_RATIOS; i++)
|
||||
for (i = 0; i < CS4271_NR_RATIOS; i++)
|
||||
if ((cs4271_clk_tab[i].master == cs4271->master) &&
|
||||
(cs4271_clk_tab[i].speed_mode == val) &&
|
||||
(cs4271_clk_tab[i].ratio == ratio))
|
||||
break;
|
||||
|
||||
if (i == CS4171_NR_RATIOS) {
|
||||
if (i == CS4271_NR_RATIOS) {
|
||||
dev_err(component->dev, "Invalid sample rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@@ -199,14 +199,6 @@ static const struct soc_enum beep_bass_enum =
|
||||
SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1,
|
||||
ARRAY_SIZE(beep_bass_text), beep_bass_text);
|
||||
|
||||
static const char * const adc_swap_text[] = {
|
||||
"None", "A+B/2", "A-B/2", "Swap"
|
||||
};
|
||||
|
||||
static const struct soc_enum adc_swap_enum =
|
||||
SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3,
|
||||
ARRAY_SIZE(adc_swap_text), adc_swap_text);
|
||||
|
||||
static const char * const pgaa_mux_text[] = {
|
||||
"AIN1A", "AIN2A", "AIN3A"};
|
||||
|
||||
|
@@ -273,12 +273,6 @@ static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum,
|
||||
CS42L73_MIXERCTL, 4,
|
||||
cs42l73_spo_mixer_text);
|
||||
|
||||
static const struct snd_kcontrol_new vsp_output_mux =
|
||||
SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
|
||||
|
||||
static const struct snd_kcontrol_new xsp_output_mux =
|
||||
SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
|
||||
|
||||
static const struct snd_kcontrol_new hp_amp_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
|
||||
|
||||
|
@@ -684,6 +684,8 @@ static int cs42xx8_runtime_suspend(struct device *dev)
|
||||
#endif
|
||||
|
||||
const struct dev_pm_ops cs42xx8_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL)
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cs42xx8_pm);
|
||||
|
1490
sound/soc/codecs/cs47l15.c
Normal file
1490
sound/soc/codecs/cs47l15.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||
SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK,
|
||||
MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6,
|
||||
SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT,
|
||||
0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
|
||||
|
@@ -2402,13 +2402,6 @@ static irqreturn_t cs47l90_adsp2_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t cs47l90_dsp_bus_error(int irq, void *data)
|
||||
{
|
||||
struct wm_adsp *dsp = (struct wm_adsp *)data;
|
||||
|
||||
return wm_adsp2_bus_error(dsp);
|
||||
}
|
||||
|
||||
static int cs47l90_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component);
|
||||
@@ -2558,7 +2551,7 @@ static int cs47l90_probe(struct platform_device *pdev)
|
||||
|
||||
if (ret == 0) {
|
||||
ret = madera_init_bus_error_irq(&cs47l90->core, i,
|
||||
cs47l90_dsp_bus_error);
|
||||
wm_adsp2_bus_error);
|
||||
if (ret != 0)
|
||||
wm_adsp2_remove(&cs47l90->core.adsp[i]);
|
||||
}
|
||||
|
2039
sound/soc/codecs/cs47l92.c
Normal file
2039
sound/soc/codecs/cs47l92.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
@@ -33,6 +34,7 @@ static const unsigned int supported_mclk_lrck_ratios[] = {
|
||||
|
||||
struct es8316_priv {
|
||||
struct mutex lock;
|
||||
struct clk *mclk;
|
||||
struct regmap *regmap;
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
@@ -363,13 +365,21 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
{
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
|
||||
int i;
|
||||
int i, ret;
|
||||
int count = 0;
|
||||
|
||||
es8316->sysclk = freq;
|
||||
|
||||
if (freq == 0)
|
||||
if (freq == 0) {
|
||||
es8316->sysclk_constraints.list = NULL;
|
||||
es8316->sysclk_constraints.count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(es8316->mclk, freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Limit supported sample rates to ones that can be autodetected
|
||||
* by the codec running in slave mode.
|
||||
@@ -444,17 +454,10 @@ static int es8316_pcm_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (es8316->sysclk == 0) {
|
||||
dev_err(component->dev, "No sysclk provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The set of sample rates that can be supported depends on the
|
||||
* MCLK supplied to the CODEC.
|
||||
*/
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&es8316->sysclk_constraints);
|
||||
if (es8316->sysclk_constraints.list)
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&es8316->sysclk_constraints);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -466,11 +469,19 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
|
||||
u8 wordlen = 0;
|
||||
int i;
|
||||
|
||||
if (!es8316->sysclk) {
|
||||
dev_err(component->dev, "No MCLK configured\n");
|
||||
return -EINVAL;
|
||||
/* Validate supported sample rates that are autodetected from MCLK */
|
||||
for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
|
||||
const unsigned int ratio = supported_mclk_lrck_ratios[i];
|
||||
|
||||
if (es8316->sysclk % ratio != 0)
|
||||
continue;
|
||||
if (es8316->sysclk / ratio == params_rate(params))
|
||||
break;
|
||||
}
|
||||
if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
|
||||
return -EINVAL;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
@@ -700,9 +711,24 @@ static int es8316_set_jack(struct snd_soc_component *component,
|
||||
static int es8316_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
es8316->component = component;
|
||||
|
||||
es8316->mclk = devm_clk_get_optional(component->dev, "mclk");
|
||||
if (IS_ERR(es8316->mclk)) {
|
||||
dev_err(component->dev, "unable to get mclk\n");
|
||||
return PTR_ERR(es8316->mclk);
|
||||
}
|
||||
if (!es8316->mclk)
|
||||
dev_warn(component->dev, "assuming static mclk\n");
|
||||
|
||||
ret = clk_prepare_enable(es8316->mclk);
|
||||
if (ret) {
|
||||
dev_err(component->dev, "unable to enable mclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset codec and enable current state machine */
|
||||
snd_soc_component_write(component, ES8316_RESET, 0x3f);
|
||||
usleep_range(5000, 5500);
|
||||
@@ -725,8 +751,16 @@ static int es8316_probe(struct snd_soc_component *component)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void es8316_remove(struct snd_soc_component *component)
|
||||
{
|
||||
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
clk_disable_unprepare(es8316->mclk);
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_component_dev_es8316 = {
|
||||
.probe = es8316_probe,
|
||||
.remove = es8316_remove,
|
||||
.set_jack = es8316_set_jack,
|
||||
.controls = es8316_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(es8316_snd_controls),
|
||||
|
@@ -99,7 +99,6 @@ static SOC_ENUM_SINGLE_DECL(adcpol,
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);
|
||||
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
|
||||
struct snd_pcm_chmap *chmap_info;
|
||||
unsigned int chmap_idx;
|
||||
struct mutex lock;
|
||||
struct snd_soc_jack *jack;
|
||||
unsigned int jack_status;
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
||||
@@ -663,6 +666,49 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
|
||||
unsigned int jack_status)
|
||||
{
|
||||
if (hcp->jack && jack_status != hcp->jack_status) {
|
||||
snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
|
||||
hcp->jack_status = jack_status;
|
||||
}
|
||||
}
|
||||
|
||||
static void plugged_cb(struct device *dev, bool plugged)
|
||||
{
|
||||
struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
|
||||
|
||||
if (plugged)
|
||||
hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
|
||||
else
|
||||
hdmi_codec_jack_report(hcp, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdmi_codec_set_jack_detect - register HDMI plugged callback
|
||||
* @component: the hdmi-codec instance
|
||||
* @jack: ASoC jack to report (dis)connection events on
|
||||
*/
|
||||
int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *jack)
|
||||
{
|
||||
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (hcp->hcd.ops->hook_plugged_cb) {
|
||||
hcp->jack = jack;
|
||||
ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
|
||||
hcp->hcd.data,
|
||||
plugged_cb,
|
||||
component->dev);
|
||||
if (ret)
|
||||
hcp->jack = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
|
||||
|
||||
static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
|
||||
|
@@ -405,7 +405,6 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk3036_codec_priv *priv;
|
||||
struct device_node *of_node = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
struct regmap *grf;
|
||||
int ret;
|
||||
@@ -414,8 +413,7 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev)
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@@ -545,15 +545,13 @@ static int jz4725b_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct jz_icdc *icdc;
|
||||
struct resource *mem;
|
||||
int ret;
|
||||
|
||||
icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
|
||||
if (!icdc)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
icdc->base = devm_ioremap_resource(dev, mem);
|
||||
icdc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(icdc->base))
|
||||
return PTR_ERR(icdc->base);
|
||||
|
||||
|
@@ -318,7 +318,6 @@ static int jz4740_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct jz4740_codec *jz4740_codec;
|
||||
struct resource *mem;
|
||||
void __iomem *base;
|
||||
|
||||
jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
|
||||
@@ -326,8 +325,7 @@ static int jz4740_codec_probe(struct platform_device *pdev)
|
||||
if (!jz4740_codec)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@@ -87,6 +87,16 @@
|
||||
#define MADERA_FLLAO_MIN_N 4
|
||||
#define MADERA_FLLAO_MAX_N 1023
|
||||
#define MADERA_FLLAO_MAX_FBDIV 254
|
||||
#define MADERA_FLLHJ_INT_MAX_N 1023
|
||||
#define MADERA_FLLHJ_INT_MIN_N 1
|
||||
#define MADERA_FLLHJ_FRAC_MAX_N 255
|
||||
#define MADERA_FLLHJ_FRAC_MIN_N 4
|
||||
#define MADERA_FLLHJ_LOW_THRESH 192000
|
||||
#define MADERA_FLLHJ_MID_THRESH 1152000
|
||||
#define MADERA_FLLHJ_MAX_THRESH 13000000
|
||||
#define MADERA_FLLHJ_LOW_GAINS 0x23f0
|
||||
#define MADERA_FLLHJ_MID_GAINS 0x22f2
|
||||
#define MADERA_FLLHJ_HIGH_GAINS 0x21f0
|
||||
|
||||
#define MADERA_FLL_SYNCHRONISER_OFFS 0x10
|
||||
#define CS47L35_FLL_SYNCHRONISER_OFFS 0xE
|
||||
@@ -96,6 +106,7 @@
|
||||
#define MADERA_FLL_CONTROL_4_OFFS 0x4
|
||||
#define MADERA_FLL_CONTROL_5_OFFS 0x5
|
||||
#define MADERA_FLL_CONTROL_6_OFFS 0x6
|
||||
#define MADERA_FLL_GAIN_OFFS 0x8
|
||||
#define MADERA_FLL_CONTROL_7_OFFS 0x9
|
||||
#define MADERA_FLL_EFS_2_OFFS 0xA
|
||||
#define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1
|
||||
@@ -107,6 +118,9 @@
|
||||
#define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7
|
||||
#define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9
|
||||
#define MADERA_FLL_GPIO_CLOCK_OFFS 0xA
|
||||
#define MADERA_FLL_CONTROL_10_OFFS 0xA
|
||||
#define MADERA_FLL_CONTROL_11_OFFS 0xB
|
||||
#define MADERA_FLL1_DIGITAL_TEST_1_OFFS 0xD
|
||||
|
||||
#define MADERA_FLLAO_CONTROL_1_OFFS 0x1
|
||||
#define MADERA_FLLAO_CONTROL_2_OFFS 0x2
|
||||
@@ -300,6 +314,100 @@ int madera_free_overheat(struct madera_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_free_overheat);
|
||||
|
||||
static int madera_get_variable_u32_array(struct device *dev,
|
||||
const char *propname,
|
||||
u32 *dest, int n_max,
|
||||
int multiple)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = device_property_count_u32(dev, propname);
|
||||
if (n < 0) {
|
||||
if (n == -EINVAL)
|
||||
return 0; /* missing, ignore */
|
||||
|
||||
dev_warn(dev, "%s malformed (%d)\n", propname, n);
|
||||
|
||||
return n;
|
||||
} else if ((n % multiple) != 0) {
|
||||
dev_warn(dev, "%s not a multiple of %d entries\n",
|
||||
propname, multiple);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (n > n_max)
|
||||
n = n_max;
|
||||
|
||||
ret = device_property_read_u32_array(dev, propname, dest, n);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void madera_prop_get_inmode(struct madera_priv *priv)
|
||||
{
|
||||
struct madera *madera = priv->madera;
|
||||
struct madera_codec_pdata *pdata = &madera->pdata.codec;
|
||||
u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
|
||||
int n, i, in_idx, ch_idx;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
|
||||
|
||||
n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
|
||||
tmp, ARRAY_SIZE(tmp),
|
||||
MADERA_MAX_MUXED_CHANNELS);
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
in_idx = 0;
|
||||
ch_idx = 0;
|
||||
for (i = 0; i < n; ++i) {
|
||||
pdata->inmode[in_idx][ch_idx] = tmp[i];
|
||||
|
||||
if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
|
||||
ch_idx = 0;
|
||||
++in_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void madera_prop_get_pdata(struct madera_priv *priv)
|
||||
{
|
||||
struct madera *madera = priv->madera;
|
||||
struct madera_codec_pdata *pdata = &madera->pdata.codec;
|
||||
u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
|
||||
int i, n;
|
||||
|
||||
madera_prop_get_inmode(priv);
|
||||
|
||||
n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
|
||||
out_mono, ARRAY_SIZE(out_mono), 1);
|
||||
if (n > 0)
|
||||
for (i = 0; i < n; ++i)
|
||||
pdata->out_mono[i] = !!out_mono[i];
|
||||
|
||||
madera_get_variable_u32_array(madera->dev,
|
||||
"cirrus,max-channels-clocked",
|
||||
pdata->max_channels_clocked,
|
||||
ARRAY_SIZE(pdata->max_channels_clocked),
|
||||
1);
|
||||
|
||||
madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
|
||||
pdata->pdm_fmt,
|
||||
ARRAY_SIZE(pdata->pdm_fmt), 1);
|
||||
|
||||
madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
|
||||
pdata->pdm_mute,
|
||||
ARRAY_SIZE(pdata->pdm_mute), 1);
|
||||
|
||||
madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
|
||||
pdata->dmic_ref,
|
||||
ARRAY_SIZE(pdata->dmic_ref), 1);
|
||||
}
|
||||
|
||||
int madera_core_init(struct madera_priv *priv)
|
||||
{
|
||||
int i;
|
||||
@@ -308,6 +416,9 @@ int madera_core_init(struct madera_priv *priv)
|
||||
BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
|
||||
BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
|
||||
|
||||
if (!dev_get_platdata(priv->madera->dev))
|
||||
madera_prop_get_pdata(priv);
|
||||
|
||||
mutex_init(&priv->rate_lock);
|
||||
|
||||
for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
|
||||
@@ -944,6 +1055,10 @@ static void madera_configure_input_mode(struct madera *madera)
|
||||
int max_analogue_inputs, max_dmic_sup, i;
|
||||
|
||||
switch (madera->type) {
|
||||
case CS47L15:
|
||||
max_analogue_inputs = 1;
|
||||
max_dmic_sup = 2;
|
||||
break;
|
||||
case CS47L35:
|
||||
max_analogue_inputs = 2;
|
||||
max_dmic_sup = 2;
|
||||
@@ -1770,6 +1885,18 @@ const struct soc_enum madera_asrc1_rate[] = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_asrc1_rate);
|
||||
|
||||
const struct soc_enum madera_asrc1_bidir_rate[] = {
|
||||
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
|
||||
MADERA_ASRC1_RATE1_SHIFT, 0xf,
|
||||
MADERA_RATE_ENUM_SIZE,
|
||||
madera_rate_text, madera_rate_val),
|
||||
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
|
||||
MADERA_ASRC1_RATE2_SHIFT, 0xf,
|
||||
MADERA_RATE_ENUM_SIZE,
|
||||
madera_rate_text, madera_rate_val),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
|
||||
|
||||
const struct soc_enum madera_asrc2_rate[] = {
|
||||
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1,
|
||||
MADERA_ASRC2_RATE1_SHIFT, 0xf,
|
||||
@@ -2149,6 +2276,9 @@ int madera_out_ev(struct snd_soc_dapm_widget *w,
|
||||
switch (madera->type) {
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
out_up_delay = 6;
|
||||
break;
|
||||
default:
|
||||
@@ -2264,9 +2394,17 @@ int madera_hp_ev(struct snd_soc_dapm_widget *w,
|
||||
madera->hp_ena &= ~mask;
|
||||
madera->hp_ena |= val;
|
||||
|
||||
/* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
|
||||
regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
|
||||
ep_sel &= MADERA_EP_SEL_MASK;
|
||||
switch (madera->type) {
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
break;
|
||||
default:
|
||||
/* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
|
||||
regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
|
||||
ep_sel &= MADERA_EP_SEL_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Force off if HPDET has disabled the clamp for this output */
|
||||
if (!ep_sel &&
|
||||
@@ -2442,6 +2580,58 @@ static int madera_get_dspclk_setting(struct madera *madera,
|
||||
}
|
||||
}
|
||||
|
||||
static int madera_set_outclk(struct snd_soc_component *component,
|
||||
unsigned int source, unsigned int freq)
|
||||
{
|
||||
int div, div_inc, rate;
|
||||
|
||||
switch (source) {
|
||||
case MADERA_OUTCLK_SYSCLK:
|
||||
dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n");
|
||||
snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
|
||||
MADERA_OUT_CLK_SRC_MASK, source);
|
||||
return 0;
|
||||
case MADERA_OUTCLK_ASYNCCLK:
|
||||
dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n");
|
||||
snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
|
||||
MADERA_OUT_CLK_SRC_MASK, source);
|
||||
return 0;
|
||||
case MADERA_OUTCLK_MCLK1:
|
||||
case MADERA_OUTCLK_MCLK2:
|
||||
case MADERA_OUTCLK_MCLK3:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (freq % 4000)
|
||||
rate = 5644800;
|
||||
else
|
||||
rate = 6144000;
|
||||
|
||||
div = 1;
|
||||
div_inc = 0;
|
||||
while (div <= 8) {
|
||||
if (freq / div == rate && !(freq % div)) {
|
||||
dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate);
|
||||
snd_soc_component_update_bits(component,
|
||||
MADERA_OUTPUT_RATE_1,
|
||||
MADERA_OUT_EXT_CLK_DIV_MASK |
|
||||
MADERA_OUT_CLK_SRC_MASK,
|
||||
(div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) |
|
||||
source);
|
||||
return 0;
|
||||
}
|
||||
div_inc++;
|
||||
div *= 2;
|
||||
}
|
||||
|
||||
dev_err(component->dev,
|
||||
"Unable to generate %dHz OUTCLK from %dHz MCLK\n",
|
||||
rate, freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
|
||||
int source, unsigned int freq, int dir)
|
||||
{
|
||||
@@ -2478,6 +2668,8 @@ int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
|
||||
case MADERA_CLK_OPCLK:
|
||||
case MADERA_CLK_ASYNC_OPCLK:
|
||||
return madera_set_opclk(component, clk_id, freq);
|
||||
case MADERA_CLK_OUTCLK:
|
||||
return madera_set_outclk(component, source, freq);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2691,6 +2883,10 @@ static const unsigned int madera_sr_vals[] = {
|
||||
#define MADERA_192K_44K1_RATE_MASK 0x003E00
|
||||
#define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \
|
||||
MADERA_192K_44K1_RATE_MASK)
|
||||
#define MADERA_384K_48K_RATE_MASK 0x0F007E
|
||||
#define MADERA_384K_44K1_RATE_MASK 0x007E00
|
||||
#define MADERA_384K_RATE_MASK (MADERA_384K_48K_RATE_MASK | \
|
||||
MADERA_384K_44K1_RATE_MASK)
|
||||
|
||||
static const struct snd_pcm_hw_constraint_list madera_constraint = {
|
||||
.count = ARRAY_SIZE(madera_sr_vals),
|
||||
@@ -2703,6 +2899,7 @@ static int madera_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct madera_priv *priv = snd_soc_component_get_drvdata(component);
|
||||
struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
|
||||
struct madera *madera = priv->madera;
|
||||
unsigned int base_rate;
|
||||
|
||||
if (!substream->runtime)
|
||||
@@ -2722,12 +2919,26 @@ static int madera_startup(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base_rate == 0)
|
||||
dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
|
||||
else if (base_rate % 4000)
|
||||
dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
|
||||
else
|
||||
dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
|
||||
switch (madera->type) {
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
if (base_rate == 0)
|
||||
dai_priv->constraint.mask = MADERA_384K_RATE_MASK;
|
||||
else if (base_rate % 4000)
|
||||
dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK;
|
||||
else
|
||||
dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK;
|
||||
break;
|
||||
default:
|
||||
if (base_rate == 0)
|
||||
dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
|
||||
else if (base_rate % 4000)
|
||||
dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
|
||||
else
|
||||
dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
return snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
@@ -4048,6 +4259,308 @@ int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
|
||||
|
||||
static int madera_fllhj_disable(struct madera_fll *fll)
|
||||
{
|
||||
struct madera *madera = fll->madera;
|
||||
bool change;
|
||||
|
||||
madera_fll_dbg(fll, "Disabling FLL\n");
|
||||
|
||||
/* Disable lockdet, but don't set ctrl_upd update but. This allows the
|
||||
* lock status bit to clear as normal, but should the FLL be enabled
|
||||
* again due to a control clock being required, the lock won't re-assert
|
||||
* as the FLL config registers are automatically applied when the FLL
|
||||
* enables.
|
||||
*/
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_11_OFFS,
|
||||
MADERA_FLL1_LOCKDET_MASK, 0);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK);
|
||||
regmap_update_bits_check(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
MADERA_FLL1_ENA_MASK, 0, &change);
|
||||
|
||||
madera_wait_for_fll(fll, false);
|
||||
|
||||
/* ctrl_up gates the writes to all the fll's registers, setting it to 0
|
||||
* here ensures that after a runtime suspend/resume cycle when one
|
||||
* enables the fll then ctrl_up is the last bit that is configured
|
||||
* by the fll enable code rather than the cache sync operation which
|
||||
* would have updated it much earlier before writing out all fll
|
||||
* registers
|
||||
*/
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_2_OFFS,
|
||||
MADERA_FLL1_CTRL_UPD_MASK, 0);
|
||||
|
||||
if (change)
|
||||
pm_runtime_put_autosuspend(madera->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int madera_fllhj_apply(struct madera_fll *fll, int fin)
|
||||
{
|
||||
struct madera *madera = fll->madera;
|
||||
int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd;
|
||||
bool frac = false;
|
||||
unsigned int fll_n, min_n, max_n, ratio, theta, lambda;
|
||||
unsigned int gains, val, num;
|
||||
|
||||
madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
|
||||
|
||||
for (refdiv = 0; refdiv < 4; refdiv++)
|
||||
if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH)
|
||||
break;
|
||||
|
||||
fref = fin / (1 << refdiv);
|
||||
|
||||
/* Use simple heuristic approach to find a configuration that
|
||||
* should work for most input clocks.
|
||||
*/
|
||||
fast_clk = 0;
|
||||
fout = fll->fout;
|
||||
frac = fout % fref;
|
||||
|
||||
if (fref < MADERA_FLLHJ_LOW_THRESH) {
|
||||
lockdet_thr = 2;
|
||||
gains = MADERA_FLLHJ_LOW_GAINS;
|
||||
if (frac)
|
||||
fbdiv = 256;
|
||||
else
|
||||
fbdiv = 4;
|
||||
} else if (fref < MADERA_FLLHJ_MID_THRESH) {
|
||||
lockdet_thr = 8;
|
||||
gains = MADERA_FLLHJ_MID_GAINS;
|
||||
fbdiv = 1;
|
||||
} else {
|
||||
lockdet_thr = 8;
|
||||
gains = MADERA_FLLHJ_HIGH_GAINS;
|
||||
fbdiv = 1;
|
||||
/* For high speed input clocks, enable 300MHz fast oscillator
|
||||
* when we're in fractional divider mode.
|
||||
*/
|
||||
if (frac) {
|
||||
fast_clk = 0x3;
|
||||
fout = fll->fout * 6;
|
||||
}
|
||||
}
|
||||
/* Use high performance mode for fractional configurations. */
|
||||
if (frac) {
|
||||
hp = 0x3;
|
||||
min_n = MADERA_FLLHJ_FRAC_MIN_N;
|
||||
max_n = MADERA_FLLHJ_FRAC_MAX_N;
|
||||
} else {
|
||||
hp = 0x0;
|
||||
min_n = MADERA_FLLHJ_INT_MIN_N;
|
||||
max_n = MADERA_FLLHJ_INT_MAX_N;
|
||||
}
|
||||
|
||||
ratio = fout / fref;
|
||||
|
||||
madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n",
|
||||
refdiv, fref, frac);
|
||||
|
||||
while (ratio / fbdiv < min_n) {
|
||||
fbdiv /= 2;
|
||||
if (fbdiv < 1) {
|
||||
madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
while (frac && (ratio / fbdiv > max_n)) {
|
||||
fbdiv *= 2;
|
||||
if (fbdiv >= 1024) {
|
||||
madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n",
|
||||
lockdet_thr, hp, fbdiv);
|
||||
|
||||
/* Calculate N.K values */
|
||||
fllgcd = gcd(fout, fbdiv * fref);
|
||||
num = fout / fllgcd;
|
||||
lambda = (fref * fbdiv) / fllgcd;
|
||||
fll_n = num / lambda;
|
||||
theta = num % lambda;
|
||||
|
||||
madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
|
||||
fll_n, fllgcd, theta, lambda);
|
||||
|
||||
/* Some sanity checks before any registers are written. */
|
||||
if (fll_n < min_n || fll_n > max_n) {
|
||||
madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
|
||||
frac ? "fractional" : "integer", min_n, max_n,
|
||||
fll_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
|
||||
madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
|
||||
frac ? "fractional" : "integer", fbdiv);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* clear the ctrl_upd bit to guarantee we write to it later. */
|
||||
regmap_write(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_2_OFFS,
|
||||
fll_n << MADERA_FLL1_N_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_3_OFFS,
|
||||
MADERA_FLL1_THETA_MASK,
|
||||
theta << MADERA_FLL1_THETA_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_4_OFFS,
|
||||
MADERA_FLL1_LAMBDA_MASK,
|
||||
lambda << MADERA_FLL1_LAMBDA_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_5_OFFS,
|
||||
MADERA_FLL1_FB_DIV_MASK,
|
||||
fbdiv << MADERA_FLL1_FB_DIV_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_6_OFFS,
|
||||
MADERA_FLL1_REFCLK_DIV_MASK,
|
||||
refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_GAIN_OFFS,
|
||||
0xffff,
|
||||
gains);
|
||||
val = hp << MADERA_FLL1_HP_SHIFT;
|
||||
val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT;
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_10_OFFS,
|
||||
MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK,
|
||||
val);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_11_OFFS,
|
||||
MADERA_FLL1_LOCKDET_THR_MASK,
|
||||
lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT);
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS,
|
||||
MADERA_FLL1_SYNC_EFS_ENA_MASK |
|
||||
MADERA_FLL1_CLK_VCO_FAST_SRC_MASK,
|
||||
fast_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int madera_fllhj_enable(struct madera_fll *fll)
|
||||
{
|
||||
struct madera *madera = fll->madera;
|
||||
int already_enabled = madera_is_enabled_fll(fll, fll->base);
|
||||
int ret;
|
||||
|
||||
if (already_enabled < 0)
|
||||
return already_enabled;
|
||||
|
||||
if (!already_enabled)
|
||||
pm_runtime_get_sync(madera->dev);
|
||||
|
||||
madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
|
||||
already_enabled ? "enabled" : "disabled");
|
||||
|
||||
/* FLLn_HOLD must be set before configuring any registers */
|
||||
regmap_update_bits(fll->madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
MADERA_FLL1_HOLD_MASK,
|
||||
MADERA_FLL1_HOLD_MASK);
|
||||
|
||||
/* Apply refclk */
|
||||
ret = madera_fllhj_apply(fll, fll->ref_freq);
|
||||
if (ret) {
|
||||
madera_fll_err(fll, "Failed to set FLL: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
CS47L92_FLL1_REFCLK_SRC_MASK,
|
||||
fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
|
||||
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
MADERA_FLL1_ENA_MASK,
|
||||
MADERA_FLL1_ENA_MASK);
|
||||
|
||||
out:
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_11_OFFS,
|
||||
MADERA_FLL1_LOCKDET_MASK,
|
||||
MADERA_FLL1_LOCKDET_MASK);
|
||||
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_2_OFFS,
|
||||
MADERA_FLL1_CTRL_UPD_MASK,
|
||||
MADERA_FLL1_CTRL_UPD_MASK);
|
||||
|
||||
/* Release the hold so that flln locks to external frequency */
|
||||
regmap_update_bits(madera->regmap,
|
||||
fll->base + MADERA_FLL_CONTROL_1_OFFS,
|
||||
MADERA_FLL1_HOLD_MASK,
|
||||
0);
|
||||
|
||||
if (!already_enabled)
|
||||
madera_wait_for_fll(fll, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int madera_fllhj_validate(struct madera_fll *fll,
|
||||
unsigned int ref_in,
|
||||
unsigned int fout)
|
||||
{
|
||||
if (fout && !ref_in) {
|
||||
madera_fll_err(fll, "fllout set without valid input clk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fll->fout && fout != fll->fout) {
|
||||
madera_fll_err(fll, "Can't change output on active FLL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) {
|
||||
madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
|
||||
unsigned int fin, unsigned int fout)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* To remain consistent with previous FLLs, we expect fout to be
|
||||
* provided in the form of the required sysclk rate, which is
|
||||
* 2x the calculated fll out.
|
||||
*/
|
||||
if (fout)
|
||||
fout /= 2;
|
||||
|
||||
if (fll->ref_src == source && fll->ref_freq == fin &&
|
||||
fll->fout == fout)
|
||||
return 0;
|
||||
|
||||
if (fin && fout && madera_fllhj_validate(fll, fin, fout))
|
||||
return -EINVAL;
|
||||
|
||||
fll->ref_src = source;
|
||||
fll->ref_freq = fin;
|
||||
fll->fout = fout;
|
||||
|
||||
if (fout)
|
||||
ret = madera_fllhj_enable(fll);
|
||||
else
|
||||
madera_fllhj_disable(fll);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk);
|
||||
|
||||
/**
|
||||
* madera_set_output_mode - Set the mode of the specified output
|
||||
*
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#define MADERA_CLK_SYSCLK_3 6
|
||||
#define MADERA_CLK_ASYNCCLK_2 7
|
||||
#define MADERA_CLK_DSPCLK 8
|
||||
#define MADERA_CLK_OUTCLK 9
|
||||
|
||||
#define MADERA_CLK_SRC_MCLK1 0x0
|
||||
#define MADERA_CLK_SRC_MCLK2 0x1
|
||||
@@ -61,6 +62,12 @@
|
||||
#define MADERA_CLK_SRC_AIF4BCLK 0xB
|
||||
#define MADERA_CLK_SRC_FLLAO 0xF
|
||||
|
||||
#define MADERA_OUTCLK_SYSCLK 0
|
||||
#define MADERA_OUTCLK_ASYNCCLK 1
|
||||
#define MADERA_OUTCLK_MCLK1 4
|
||||
#define MADERA_OUTCLK_MCLK2 5
|
||||
#define MADERA_OUTCLK_MCLK3 6
|
||||
|
||||
#define MADERA_MIXER_VOL_MASK 0x00FE
|
||||
#define MADERA_MIXER_VOL_SHIFT 1
|
||||
#define MADERA_MIXER_VOL_WIDTH 7
|
||||
@@ -326,6 +333,7 @@ extern const struct soc_enum madera_sample_rate[];
|
||||
extern const struct soc_enum madera_isrc_fsl[];
|
||||
extern const struct soc_enum madera_isrc_fsh[];
|
||||
extern const struct soc_enum madera_asrc1_rate[];
|
||||
extern const struct soc_enum madera_asrc1_bidir_rate[];
|
||||
extern const struct soc_enum madera_asrc2_rate[];
|
||||
extern const struct soc_enum madera_dfc_width[];
|
||||
extern const struct soc_enum madera_dfc_type[];
|
||||
@@ -403,6 +411,8 @@ int madera_set_fll_syncclk(struct madera_fll *fll, int source,
|
||||
unsigned int fref, unsigned int fout);
|
||||
int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
|
||||
unsigned int fin, unsigned int fout);
|
||||
int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
|
||||
unsigned int fin, unsigned int fout);
|
||||
|
||||
int madera_core_init(struct madera_priv *priv);
|
||||
int madera_core_free(struct madera_priv *priv);
|
||||
|
@@ -154,10 +154,6 @@ static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv,
|
||||
8, 10, TLV_DB_SCALE_ITEM(400, 100, 0)
|
||||
);
|
||||
|
||||
static const DECLARE_TLV_DB_RANGE(max98371_noload_gain_tlv,
|
||||
0, 11, TLV_DB_SCALE_ITEM(950, 100, 0),
|
||||
);
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new max98371_snd_controls[] = {
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "max98373.h"
|
||||
@@ -901,6 +902,17 @@ static void max98373_slot_config(struct i2c_client *i2c,
|
||||
else
|
||||
max98373->i_slot = 1;
|
||||
|
||||
max98373->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
"maxim,reset-gpio", 0);
|
||||
if (!gpio_is_valid(max98373->reset_gpio)) {
|
||||
dev_err(dev, "Looking up %s property in node %s failed %d\n",
|
||||
"maxim,reset-gpio", dev->of_node->full_name,
|
||||
max98373->reset_gpio);
|
||||
} else {
|
||||
dev_dbg(dev, "maxim,reset-gpio=%d",
|
||||
max98373->reset_gpio);
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
|
||||
max98373->spkfb_slot = value & 0xF;
|
||||
else
|
||||
@@ -929,7 +941,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
|
||||
else
|
||||
max98373->interleave_mode = false;
|
||||
|
||||
|
||||
/* regmap initialization */
|
||||
max98373->regmap
|
||||
= devm_regmap_init_i2c(i2c, &max98373_regmap);
|
||||
@@ -940,6 +951,24 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* voltage/current slot & gpio configuration */
|
||||
max98373_slot_config(i2c, max98373);
|
||||
|
||||
/* Power on device */
|
||||
if (gpio_is_valid(max98373->reset_gpio)) {
|
||||
ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET");
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "%s: Failed to request gpio %d\n",
|
||||
__func__, max98373->reset_gpio);
|
||||
gpio_free(max98373->reset_gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
gpio_direction_output(max98373->reset_gpio, 0);
|
||||
msleep(50);
|
||||
gpio_direction_output(max98373->reset_gpio, 1);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
/* Check Revision ID */
|
||||
ret = regmap_read(max98373->regmap,
|
||||
MAX98373_R21FF_REV_ID, ®);
|
||||
@@ -950,9 +979,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
|
||||
}
|
||||
dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg);
|
||||
|
||||
/* voltage/current slot configuration */
|
||||
max98373_slot_config(i2c, max98373);
|
||||
|
||||
/* codec registeration */
|
||||
ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373,
|
||||
max98373_dai, ARRAY_SIZE(max98373_dai));
|
||||
|
@@ -205,6 +205,7 @@
|
||||
|
||||
struct max98373_priv {
|
||||
struct regmap *regmap;
|
||||
int reset_gpio;
|
||||
unsigned int v_slot;
|
||||
unsigned int i_slot;
|
||||
unsigned int spkfb_slot;
|
||||
|
@@ -27,19 +27,6 @@ struct max9850_priv {
|
||||
unsigned int sysclk;
|
||||
};
|
||||
|
||||
/* max9850 register cache */
|
||||
static const struct reg_default max9850_reg[] = {
|
||||
{ 2, 0x0c },
|
||||
{ 3, 0x00 },
|
||||
{ 4, 0x00 },
|
||||
{ 5, 0x00 },
|
||||
{ 6, 0x00 },
|
||||
{ 7, 0x00 },
|
||||
{ 8, 0x00 },
|
||||
{ 9, 0x00 },
|
||||
{ 10, 0x00 },
|
||||
};
|
||||
|
||||
/* these registers are not used at the moment but provided for the sake of
|
||||
* completeness */
|
||||
static bool max9850_volatile_register(struct device *dev, unsigned int reg)
|
||||
|
@@ -20,15 +20,6 @@ static const char * const max98926_boost_voltage_txt[] = {
|
||||
"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V"
|
||||
};
|
||||
|
||||
static const char * const max98926_boost_current_txt[] = {
|
||||
"0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0",
|
||||
"2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4"
|
||||
};
|
||||
|
||||
static const char *const max98926_dai_txt[] = {
|
||||
"Left", "Right", "LeftRight", "LeftRightDiv2",
|
||||
};
|
||||
|
||||
static const char *const max98926_pdm_ch_text[] = {
|
||||
"Current", "Voltage",
|
||||
};
|
||||
|
@@ -56,7 +56,6 @@ static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
|
||||
|
||||
static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
|
||||
"A-law"};
|
||||
|
@@ -1185,10 +1185,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get mbhc switch irq\n");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL,
|
||||
pm8916_mbhc_switch_irq_handler,
|
||||
@@ -1200,10 +1198,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
|
||||
|
||||
if (priv->mbhc_btn_enabled) {
|
||||
irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get button press irq\n");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL,
|
||||
mbhc_btn_press_irq_handler,
|
||||
@@ -1214,10 +1210,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "cannot request mbhc button press irq\n");
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get button release irq\n");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL,
|
||||
mbhc_btn_release_irq_handler,
|
||||
|
@@ -1143,7 +1143,6 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
|
||||
struct msm8916_wcd_digital_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *base;
|
||||
struct resource *mem_res;
|
||||
struct regmap *digital_map;
|
||||
int ret;
|
||||
|
||||
@@ -1151,8 +1150,7 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem_res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@@ -1066,11 +1066,6 @@ static int mt_mic_bias_2_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DAPM Kcontrols */
|
||||
static const struct snd_kcontrol_new mt_lineout_control =
|
||||
SOC_DAPM_SINGLE("Switch", MT6351_AUDDEC_ANA_CON3,
|
||||
RG_AUDLOLPWRUP_VAUDP32_BIT, 1, 0);
|
||||
|
||||
/* DAPM Widgets */
|
||||
static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = {
|
||||
/* Digital Clock */
|
||||
|
@@ -1730,6 +1730,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv)
|
||||
|
||||
/* UL turn on */
|
||||
regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003);
|
||||
|
||||
/* Prevent pop noise form dmic hw */
|
||||
msleep(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2255,10 +2259,8 @@ static struct snd_soc_dai_driver mt6358_dai_driver[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int mt6358_codec_init_reg(struct mt6358_priv *priv)
|
||||
static void mt6358_codec_init_reg(struct mt6358_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Disable HeadphoneL/HeadphoneR short circuit protection */
|
||||
regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0,
|
||||
RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT,
|
||||
@@ -2285,8 +2287,6 @@ static int mt6358_codec_init_reg(struct mt6358_priv *priv)
|
||||
/* set gpio */
|
||||
playback_gpio_reset(priv);
|
||||
capture_gpio_reset(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt6358_codec_probe(struct snd_soc_component *cmpnt)
|
||||
|
@@ -44,18 +44,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = {
|
||||
"VCCDA2"
|
||||
};
|
||||
|
||||
#define PCM3168A_DAI_DAC 0
|
||||
#define PCM3168A_DAI_ADC 1
|
||||
|
||||
/* ADC/DAC side parameters */
|
||||
struct pcm3168a_io_params {
|
||||
bool master_mode;
|
||||
unsigned int fmt;
|
||||
int tdm_slots;
|
||||
u32 tdm_mask;
|
||||
int slot_width;
|
||||
};
|
||||
|
||||
struct pcm3168a_priv {
|
||||
struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES];
|
||||
struct regmap *regmap;
|
||||
struct clk *scki;
|
||||
bool adc_master_mode;
|
||||
bool dac_master_mode;
|
||||
unsigned long sysclk;
|
||||
unsigned int adc_fmt;
|
||||
unsigned int dac_fmt;
|
||||
int tdm_slots;
|
||||
u32 tdm_mask[2];
|
||||
int slot_width;
|
||||
|
||||
struct pcm3168a_io_params io_params[2];
|
||||
};
|
||||
|
||||
static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
|
||||
@@ -263,7 +270,7 @@ static unsigned int pcm3168a_scki_ratios[] = {
|
||||
#define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios)
|
||||
#define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2)
|
||||
|
||||
#define PCM1368A_MAX_SYSCLK 36864000
|
||||
#define PCM3168A_MAX_SYSCLK 36864000
|
||||
|
||||
static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a)
|
||||
{
|
||||
@@ -296,7 +303,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
|
||||
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
|
||||
int ret;
|
||||
|
||||
if (freq > PCM1368A_MAX_SYSCLK)
|
||||
if (freq > PCM3168A_MAX_SYSCLK)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_set_rate(pcm3168a->scki, freq);
|
||||
@@ -308,8 +315,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
|
||||
unsigned int format, bool dac)
|
||||
static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
|
||||
@@ -356,43 +362,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dac) {
|
||||
if (dai->id == PCM3168A_DAI_DAC) {
|
||||
reg = PCM3168A_DAC_PWR_MST_FMT;
|
||||
mask = PCM3168A_DAC_FMT_MASK;
|
||||
shift = PCM3168A_DAC_FMT_SHIFT;
|
||||
pcm3168a->dac_master_mode = master_mode;
|
||||
pcm3168a->dac_fmt = fmt;
|
||||
} else {
|
||||
reg = PCM3168A_ADC_MST_FMT;
|
||||
mask = PCM3168A_ADC_FMTAD_MASK;
|
||||
shift = PCM3168A_ADC_FMTAD_SHIFT;
|
||||
pcm3168a->adc_master_mode = master_mode;
|
||||
pcm3168a->adc_fmt = fmt;
|
||||
}
|
||||
|
||||
pcm3168a->io_params[dai->id].master_mode = master_mode;
|
||||
pcm3168a->io_params[dai->id].fmt = fmt;
|
||||
|
||||
regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai,
|
||||
unsigned int format)
|
||||
{
|
||||
return pcm3168a_set_dai_fmt(dai, format, true);
|
||||
}
|
||||
|
||||
static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai,
|
||||
unsigned int format)
|
||||
{
|
||||
return pcm3168a_set_dai_fmt(dai, format, false);
|
||||
}
|
||||
|
||||
static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots,
|
||||
int slot_width)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
|
||||
struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
|
||||
|
||||
if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
|
||||
dev_err(component->dev,
|
||||
@@ -408,22 +402,13 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) {
|
||||
dev_err(component->dev, "Not matching slots %d vs %d\n",
|
||||
pcm3168a->tdm_slots, slots);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) {
|
||||
dev_err(component->dev, "Not matching slot_width %d vs %d\n",
|
||||
pcm3168a->slot_width, slot_width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pcm3168a->tdm_slots = slots;
|
||||
pcm3168a->slot_width = slot_width;
|
||||
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
|
||||
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
|
||||
io_params->tdm_slots = slots;
|
||||
io_params->slot_width = slot_width;
|
||||
/* Ignore the not relevant mask for the DAI/direction */
|
||||
if (dai->id == PCM3168A_DAI_DAC)
|
||||
io_params->tdm_mask = tx_mask;
|
||||
else
|
||||
io_params->tdm_mask = rx_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -434,7 +419,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
|
||||
bool tx, master_mode;
|
||||
struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
|
||||
bool master_mode;
|
||||
u32 val, mask, shift, reg;
|
||||
unsigned int rate, fmt, ratio, max_ratio;
|
||||
unsigned int tdm_slots;
|
||||
@@ -444,23 +430,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
ratio = pcm3168a->sysclk / rate;
|
||||
|
||||
tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
if (tx) {
|
||||
if (dai->id == PCM3168A_DAI_DAC) {
|
||||
max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC;
|
||||
reg = PCM3168A_DAC_PWR_MST_FMT;
|
||||
mask = PCM3168A_DAC_MSDA_MASK;
|
||||
shift = PCM3168A_DAC_MSDA_SHIFT;
|
||||
master_mode = pcm3168a->dac_master_mode;
|
||||
fmt = pcm3168a->dac_fmt;
|
||||
} else {
|
||||
max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC;
|
||||
reg = PCM3168A_ADC_MST_FMT;
|
||||
mask = PCM3168A_ADC_MSAD_MASK;
|
||||
shift = PCM3168A_ADC_MSAD_SHIFT;
|
||||
master_mode = pcm3168a->adc_master_mode;
|
||||
fmt = pcm3168a->adc_fmt;
|
||||
}
|
||||
|
||||
master_mode = io_params->master_mode;
|
||||
fmt = io_params->fmt;
|
||||
|
||||
for (i = 0; i < max_ratio; i++) {
|
||||
if (pcm3168a_scki_ratios[i] == ratio)
|
||||
break;
|
||||
@@ -471,8 +455,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pcm3168a->slot_width)
|
||||
slot_width = pcm3168a->slot_width;
|
||||
if (io_params->slot_width)
|
||||
slot_width = io_params->slot_width;
|
||||
else
|
||||
slot_width = params_width(params);
|
||||
|
||||
@@ -497,8 +481,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pcm3168a->tdm_slots)
|
||||
tdm_slots = pcm3168a->tdm_slots;
|
||||
if (io_params->tdm_slots)
|
||||
tdm_slots = io_params->tdm_slots;
|
||||
else
|
||||
tdm_slots = params_channels(params);
|
||||
|
||||
@@ -534,7 +518,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
regmap_update_bits(pcm3168a->regmap, reg, mask, val);
|
||||
|
||||
if (tx) {
|
||||
if (dai->id == PCM3168A_DAI_DAC) {
|
||||
mask = PCM3168A_DAC_FMT_MASK;
|
||||
shift = PCM3168A_DAC_FMT_SHIFT;
|
||||
} else {
|
||||
@@ -552,20 +536,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
|
||||
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
unsigned int fmt;
|
||||
unsigned int sample_min;
|
||||
unsigned int channel_max;
|
||||
unsigned int channel_maxs[] = {
|
||||
6, /* rx */
|
||||
8 /* tx */
|
||||
8, /* DAC */
|
||||
6 /* ADC */
|
||||
};
|
||||
|
||||
if (tx)
|
||||
fmt = pcm3168a->dac_fmt;
|
||||
else
|
||||
fmt = pcm3168a->adc_fmt;
|
||||
|
||||
/*
|
||||
* Available Data Bits
|
||||
*
|
||||
@@ -578,7 +555,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
|
||||
* I2S
|
||||
* LEFT_J
|
||||
*/
|
||||
switch (fmt) {
|
||||
switch (pcm3168a->io_params[dai->id].fmt) {
|
||||
case PCM3168A_FMT_RIGHT_J:
|
||||
sample_min = 16;
|
||||
channel_max = 2;
|
||||
@@ -588,7 +565,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
|
||||
case PCM3168A_FMT_DSP_A:
|
||||
case PCM3168A_FMT_DSP_B:
|
||||
sample_min = 24;
|
||||
channel_max = channel_maxs[tx];
|
||||
channel_max = channel_maxs[dai->id];
|
||||
break;
|
||||
default:
|
||||
sample_min = 24;
|
||||
@@ -599,32 +576,29 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
||||
sample_min, 32);
|
||||
|
||||
/* Allow all channels in multi DIN/DOUT mode */
|
||||
if (pcm3168a->io_params[dai->id].tdm_slots == 2)
|
||||
channel_max = channel_maxs[dai->id];
|
||||
|
||||
snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
2, channel_max);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = {
|
||||
static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
|
||||
.startup = pcm3168a_startup,
|
||||
.set_fmt = pcm3168a_set_dai_fmt_dac,
|
||||
.set_fmt = pcm3168a_set_dai_fmt,
|
||||
.set_sysclk = pcm3168a_set_dai_sysclk,
|
||||
.hw_params = pcm3168a_hw_params,
|
||||
.digital_mute = pcm3168a_digital_mute,
|
||||
.set_tdm_slot = pcm3168a_set_tdm_slot,
|
||||
};
|
||||
|
||||
static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = {
|
||||
.startup = pcm3168a_startup,
|
||||
.set_fmt = pcm3168a_set_dai_fmt_adc,
|
||||
.set_sysclk = pcm3168a_set_dai_sysclk,
|
||||
.hw_params = pcm3168a_hw_params,
|
||||
.set_tdm_slot = pcm3168a_set_tdm_slot,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver pcm3168a_dais[] = {
|
||||
{
|
||||
.name = "pcm3168a-dac",
|
||||
.id = PCM3168A_DAI_DAC,
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
@@ -632,10 +606,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = PCM3168A_FORMATS
|
||||
},
|
||||
.ops = &pcm3168a_dac_dai_ops
|
||||
.ops = &pcm3168a_dai_ops
|
||||
},
|
||||
{
|
||||
.name = "pcm3168a-adc",
|
||||
.id = PCM3168A_DAI_ADC,
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
@@ -643,7 +618,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = PCM3168A_FORMATS
|
||||
},
|
||||
.ops = &pcm3168a_adc_dai_ops
|
||||
.ops = &pcm3168a_dai_ops
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -432,7 +432,6 @@ static int rk3328_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *rk3328_np = pdev->dev.of_node;
|
||||
struct rk3328_codec_priv *rk3328;
|
||||
struct resource *res;
|
||||
struct regmap *grf;
|
||||
void __iomem *base;
|
||||
int ret = 0;
|
||||
@@ -482,8 +481,7 @@ static int rk3328_platform_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@@ -978,9 +978,6 @@ static bool rt1011_readable_register(struct device *dev, unsigned int reg)
|
||||
}
|
||||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9435, 37, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1739, 37, 0);
|
||||
|
||||
static const char * const rt1011_din_source_select[] = {
|
||||
"Left",
|
||||
"Right",
|
||||
@@ -1029,6 +1026,8 @@ static const char * const rt1011_tdm_adc_swap_select[] = {
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6,
|
||||
rt1011_tdm_adc_swap_select);
|
||||
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum, RT1011_TDM1_SET_3, 4,
|
||||
rt1011_tdm_adc_swap_select);
|
||||
|
||||
static void rt1011_reset(struct regmap *regmap)
|
||||
{
|
||||
@@ -1223,7 +1222,10 @@ static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol,
|
||||
static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = 0;
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
ucontrol->value.integer.value[0] = rt1011->cali_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1237,6 +1239,7 @@ static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol,
|
||||
if (!component->card->instantiated)
|
||||
return 0;
|
||||
|
||||
rt1011->cali_done = 0;
|
||||
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF &&
|
||||
ucontrol->value.integer.value[0])
|
||||
rt1011_calibrate(rt1011, 1);
|
||||
@@ -1333,7 +1336,8 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = {
|
||||
/* TDM1 Data Out Selection */
|
||||
SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum),
|
||||
SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum),
|
||||
SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum),
|
||||
SOC_ENUM("TDM1 ADC1DAT Swap Select", rt1011_tdm_adc1_1_enum),
|
||||
SOC_ENUM("TDM1 ADC2DAT Swap Select", rt1011_tdm_adc2_1_enum),
|
||||
|
||||
/* Data Out Mode */
|
||||
SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum),
|
||||
@@ -1355,6 +1359,10 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = {
|
||||
SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0,
|
||||
rt1011_r0_cali_get, rt1011_r0_cali_put),
|
||||
RT1011_R0_LOAD("R0 Load Mode"),
|
||||
|
||||
/* R0 temperature */
|
||||
SOC_SINGLE("R0 Temperature", RT1011_STP_INITIAL_RESISTANCE_TEMP,
|
||||
2, 255, 0),
|
||||
};
|
||||
|
||||
static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
|
||||
@@ -1511,7 +1519,8 @@ static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
|
||||
|
||||
static int rt1011_get_clk_info(int sclk, int rate)
|
||||
{
|
||||
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
int i;
|
||||
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
|
||||
if (sclk <= 0 || rate <= 0)
|
||||
return -EINVAL;
|
||||
@@ -2139,6 +2148,7 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag)
|
||||
r0_factor = ((format / r0[0] * 100) / 128)
|
||||
- (r0_integer * 100);
|
||||
rt1011->r0_reg = r0[0];
|
||||
rt1011->cali_done = 1;
|
||||
dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n",
|
||||
r0_integer, r0_factor, r0[0]);
|
||||
}
|
||||
@@ -2189,6 +2199,13 @@ static void rt1011_calibration_work(struct work_struct *work)
|
||||
|
||||
rt1011_calibrate(rt1011, 1);
|
||||
|
||||
/*
|
||||
* This flag should reset after booting.
|
||||
* The factory test will do calibration again and use this flag to check
|
||||
* whether the calibration completed
|
||||
*/
|
||||
rt1011->cali_done = 0;
|
||||
|
||||
/* initial */
|
||||
rt1011_reg_init(component);
|
||||
}
|
||||
|
@@ -227,6 +227,7 @@
|
||||
#define RT1011_STP_CALIB_RS_TEMP 0x152a
|
||||
#define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538
|
||||
#define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539
|
||||
#define RT1011_STP_INITIAL_RESISTANCE_TEMP 0x153c
|
||||
#define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e
|
||||
#define RT1011_SPK_RESISTANCE_1 0x1544
|
||||
#define RT1011_SPK_RESISTANCE_2 0x1546
|
||||
@@ -665,7 +666,7 @@ struct rt1011_priv {
|
||||
int pll_out;
|
||||
|
||||
int bq_drc_set;
|
||||
unsigned int r0_reg;
|
||||
unsigned int r0_reg, cali_done;
|
||||
int recv_spk_mode;
|
||||
};
|
||||
|
||||
|
@@ -608,7 +608,8 @@ static const struct snd_soc_dapm_route rt1305_dapm_routes[] = {
|
||||
|
||||
static int rt1305_get_clk_info(int sclk, int rate)
|
||||
{
|
||||
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
int i;
|
||||
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
|
||||
if (sclk <= 0 || rate <= 0)
|
||||
return -EINVAL;
|
||||
|
@@ -1,13 +1,10 @@
|
||||
/*
|
||||
* rt1308.c -- RT1308 ALSA SoC amplifier component driver
|
||||
*
|
||||
* Copyright 2019 Realtek Semiconductor Corp.
|
||||
* Author: Derek Fang <derek.fang@realtek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// rt1308.c -- RT1308 ALSA SoC amplifier component driver
|
||||
//
|
||||
// Copyright 2019 Realtek Semiconductor Corp.
|
||||
// Author: Derek Fang <derek.fang@realtek.com>
|
||||
//
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@@ -40,10 +37,10 @@ static const struct reg_sequence init_list[] = {
|
||||
{ RT1308_VREF, 0x18100000 },
|
||||
{ RT1308_IV_SENSE, 0x87010000 },
|
||||
{ RT1308_DUMMY_REG, 0x00000200 },
|
||||
{ RT1308_SIL_DET, 0x61c30000 },
|
||||
{ RT1308_SIL_DET, 0xe1c30000 },
|
||||
{ RT1308_DC_CAL_2, 0x00ffff00 },
|
||||
{ RT1308_CLK_DET, 0x01000000 },
|
||||
{ RT1308_POWER_STATUS, 0x00800000 },
|
||||
{ RT1308_POWER_STATUS, 0x08800000 },
|
||||
{ RT1308_DAC_SET, 0xafaf0700 },
|
||||
|
||||
};
|
||||
@@ -308,12 +305,13 @@ static int rt1308_classd_event(struct snd_soc_dapm_widget *w,
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
msleep(30);
|
||||
snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
|
||||
RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT);
|
||||
RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT,
|
||||
RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT);
|
||||
msleep(40);
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
|
||||
RT1308_POW_PDB_REG_BIT, 0);
|
||||
RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0);
|
||||
usleep_range(150000, 200000);
|
||||
break;
|
||||
|
||||
@@ -438,7 +436,8 @@ static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
|
||||
|
||||
static int rt1308_get_clk_info(int sclk, int rate)
|
||||
{
|
||||
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
int i;
|
||||
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
|
||||
|
||||
if (sclk <= 0 || rate <= 0)
|
||||
return -EINVAL;
|
||||
@@ -808,33 +807,11 @@ static void rt1308_efuse(struct rt1308_priv *rt1308)
|
||||
{
|
||||
regmap_write(rt1308->regmap, RT1308_RESET, 0);
|
||||
|
||||
regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600);
|
||||
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000);
|
||||
regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005);
|
||||
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
|
||||
regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505);
|
||||
regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000);
|
||||
regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000);
|
||||
regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200);
|
||||
regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000);
|
||||
regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000);
|
||||
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00);
|
||||
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000);
|
||||
regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00);
|
||||
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501);
|
||||
|
||||
regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000);
|
||||
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00);
|
||||
msleep(100);
|
||||
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00);
|
||||
msleep(20);
|
||||
regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000);
|
||||
|
||||
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000);
|
||||
regmap_write(rt1308->regmap, RT1308_POWER, 0x0);
|
||||
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000);
|
||||
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
|
||||
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00);
|
||||
}
|
||||
|
||||
static int rt1308_i2c_probe(struct i2c_client *i2c,
|
||||
|
@@ -1,12 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* RT1308.h -- RT1308 ALSA SoC amplifier component driver
|
||||
* rt1308.h -- RT1308 ALSA SoC amplifier component driver
|
||||
*
|
||||
* Copyright 2019 Realtek Semiconductor Corp.
|
||||
* Author: Derek Fang <derek.fang@realtek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _RT1308_H_
|
||||
|
@@ -2566,7 +2566,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5655_set_verf(struct snd_soc_dapm_widget *w,
|
||||
static int rt5665_set_verf(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
@@ -2686,11 +2686,11 @@ static const struct snd_soc_dapm_widget rt5665_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL,
|
||||
RT5665_PWR_MIC_DET_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0,
|
||||
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0,
|
||||
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0,
|
||||
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
|
||||
|
||||
/* ASRC */
|
||||
SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1,
|
||||
|
@@ -691,10 +691,12 @@ static void rt5677_set_dsp_mode(struct snd_soc_component *component, bool on)
|
||||
struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (on) {
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x2);
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1,
|
||||
RT5677_PWR_DSP, RT5677_PWR_DSP);
|
||||
rt5677->is_dsp_mode = true;
|
||||
} else {
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x0);
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1,
|
||||
RT5677_PWR_DSP, 0x0);
|
||||
rt5677->is_dsp_mode = false;
|
||||
}
|
||||
}
|
||||
@@ -4466,7 +4468,8 @@ static int rt5677_set_bias_level(struct snd_soc_component *component,
|
||||
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
|
||||
RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK,
|
||||
0x0055);
|
||||
5 << RT5677_LDO1_SEL_SFT |
|
||||
5 << RT5677_LDO2_SEL_SFT);
|
||||
regmap_update_bits(rt5677->regmap,
|
||||
RT5677_PR_BASE + RT5677_BIAS_CUR4,
|
||||
0x0f00, 0x0f00);
|
||||
@@ -4490,9 +4493,11 @@ static int rt5677_set_bias_level(struct snd_soc_component *component,
|
||||
case SND_SOC_BIAS_OFF:
|
||||
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_ANLG1,
|
||||
2 << RT5677_LDO1_SEL_SFT |
|
||||
2 << RT5677_LDO2_SEL_SFT);
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
|
||||
RT5677_PWR_CORE, 0);
|
||||
regmap_update_bits(rt5677->regmap,
|
||||
RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000);
|
||||
|
||||
@@ -4719,7 +4724,8 @@ static int rt5677_probe(struct snd_soc_component *component)
|
||||
|
||||
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC,
|
||||
~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DSP2,
|
||||
RT5677_PWR_SLIM_ISO | RT5677_PWR_CORE_ISO);
|
||||
|
||||
for (i = 0; i < RT5677_GPIO_NUM; i++)
|
||||
rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]);
|
||||
|
@@ -31,6 +31,13 @@
|
||||
#define SGTL5000_DAP_REG_OFFSET 0x0100
|
||||
#define SGTL5000_MAX_REG_OFFSET 0x013A
|
||||
|
||||
/* Delay for the VAG ramp up */
|
||||
#define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */
|
||||
/* Delay for the VAG ramp down */
|
||||
#define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */
|
||||
|
||||
#define SGTL5000_OUTPUTS_MUTE (SGTL5000_HP_MUTE | SGTL5000_LINE_OUT_MUTE)
|
||||
|
||||
/* default value of sgtl5000 registers */
|
||||
static const struct reg_default sgtl5000_reg_defaults[] = {
|
||||
{ SGTL5000_CHIP_DIG_POWER, 0x0000 },
|
||||
@@ -123,6 +130,13 @@ enum {
|
||||
I2S_SCLK_STRENGTH_HIGH,
|
||||
};
|
||||
|
||||
enum {
|
||||
HP_POWER_EVENT,
|
||||
DAC_POWER_EVENT,
|
||||
ADC_POWER_EVENT,
|
||||
LAST_POWER_EVENT = ADC_POWER_EVENT
|
||||
};
|
||||
|
||||
/* sgtl5000 private structure in codec */
|
||||
struct sgtl5000_priv {
|
||||
int sysclk; /* sysclk rate */
|
||||
@@ -137,8 +151,109 @@ struct sgtl5000_priv {
|
||||
u8 micbias_voltage;
|
||||
u8 lrclk_strength;
|
||||
u8 sclk_strength;
|
||||
u16 mute_state[LAST_POWER_EVENT + 1];
|
||||
};
|
||||
|
||||
static inline int hp_sel_input(struct snd_soc_component *component)
|
||||
{
|
||||
return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) &
|
||||
SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT;
|
||||
}
|
||||
|
||||
static inline u16 mute_output(struct snd_soc_component *component,
|
||||
u16 mute_mask)
|
||||
{
|
||||
u16 mute_reg = snd_soc_component_read32(component,
|
||||
SGTL5000_CHIP_ANA_CTRL);
|
||||
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
|
||||
mute_mask, mute_mask);
|
||||
return mute_reg;
|
||||
}
|
||||
|
||||
static inline void restore_output(struct snd_soc_component *component,
|
||||
u16 mute_mask, u16 mute_reg)
|
||||
{
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
|
||||
mute_mask, mute_reg);
|
||||
}
|
||||
|
||||
static void vag_power_on(struct snd_soc_component *component, u32 source)
|
||||
{
|
||||
if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) &
|
||||
SGTL5000_VAG_POWERUP)
|
||||
return;
|
||||
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
|
||||
|
||||
/* When VAG powering on to get local loop from Line-In, the sleep
|
||||
* is required to avoid loud pop.
|
||||
*/
|
||||
if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN &&
|
||||
source == HP_POWER_EVENT)
|
||||
msleep(SGTL5000_VAG_POWERUP_DELAY);
|
||||
}
|
||||
|
||||
static int vag_power_consumers(struct snd_soc_component *component,
|
||||
u16 ana_pwr_reg, u32 source)
|
||||
{
|
||||
int consumers = 0;
|
||||
|
||||
/* count dac/adc consumers unconditional */
|
||||
if (ana_pwr_reg & SGTL5000_DAC_POWERUP)
|
||||
consumers++;
|
||||
if (ana_pwr_reg & SGTL5000_ADC_POWERUP)
|
||||
consumers++;
|
||||
|
||||
/*
|
||||
* If the event comes from HP and Line-In is selected,
|
||||
* current action is 'DAC to be powered down'.
|
||||
* As HP_POWERUP is not set when HP muxed to line-in,
|
||||
* we need to keep VAG power ON.
|
||||
*/
|
||||
if (source == HP_POWER_EVENT) {
|
||||
if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN)
|
||||
consumers++;
|
||||
} else {
|
||||
if (ana_pwr_reg & SGTL5000_HP_POWERUP)
|
||||
consumers++;
|
||||
}
|
||||
|
||||
return consumers;
|
||||
}
|
||||
|
||||
static void vag_power_off(struct snd_soc_component *component, u32 source)
|
||||
{
|
||||
u16 ana_pwr = snd_soc_component_read32(component,
|
||||
SGTL5000_CHIP_ANA_POWER);
|
||||
|
||||
if (!(ana_pwr & SGTL5000_VAG_POWERUP))
|
||||
return;
|
||||
|
||||
/*
|
||||
* This function calls when any of VAG power consumers is disappearing.
|
||||
* Thus, if there is more than one consumer at the moment, as minimum
|
||||
* one consumer will definitely stay after the end of the current
|
||||
* event.
|
||||
* Don't clear VAG_POWERUP if 2 or more consumers of VAG present:
|
||||
* - LINE_IN (for HP events) / HP (for DAC/ADC events)
|
||||
* - DAC
|
||||
* - ADC
|
||||
* (the current consumer is disappearing right now)
|
||||
*/
|
||||
if (vag_power_consumers(component, ana_pwr, source) >= 2)
|
||||
return;
|
||||
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_VAG_POWERUP, 0);
|
||||
/* In power down case, we need wait 400-1000 ms
|
||||
* when VAG fully ramped down.
|
||||
* As longer we wait, as smaller pop we've got.
|
||||
*/
|
||||
msleep(SGTL5000_VAG_POWERDOWN_DELAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* mic_bias power on/off share the same register bits with
|
||||
* output impedance of mic bias, when power on mic bias, we
|
||||
@@ -170,36 +285,46 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* As manual described, ADC/DAC only works when VAG powerup,
|
||||
* So enabled VAG before ADC/DAC up.
|
||||
* In power down case, we need wait 400ms when vag fully ramped down.
|
||||
*/
|
||||
static int power_vag_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
static int vag_and_mute_control(struct snd_soc_component *component,
|
||||
int event, int event_source)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP;
|
||||
static const u16 mute_mask[] = {
|
||||
/*
|
||||
* Mask for HP_POWER_EVENT.
|
||||
* Muxing Headphones have to be wrapped with mute/unmute
|
||||
* headphones only.
|
||||
*/
|
||||
SGTL5000_HP_MUTE,
|
||||
/*
|
||||
* Masks for DAC_POWER_EVENT/ADC_POWER_EVENT.
|
||||
* Muxing DAC or ADC block have to wrapped with mute/unmute
|
||||
* both headphones and line-out.
|
||||
*/
|
||||
SGTL5000_OUTPUTS_MUTE,
|
||||
SGTL5000_OUTPUTS_MUTE
|
||||
};
|
||||
|
||||
struct sgtl5000_priv *sgtl5000 =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
|
||||
msleep(400);
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
sgtl5000->mute_state[event_source] =
|
||||
mute_output(component, mute_mask[event_source]);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
vag_power_on(component, event_source);
|
||||
restore_output(component, mute_mask[event_source],
|
||||
sgtl5000->mute_state[event_source]);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
/*
|
||||
* Don't clear VAG_POWERUP, when both DAC and ADC are
|
||||
* operational to prevent inadvertently starving the
|
||||
* other one of them.
|
||||
*/
|
||||
if ((snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) &
|
||||
mask) != mask) {
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_VAG_POWERUP, 0);
|
||||
msleep(400);
|
||||
}
|
||||
sgtl5000->mute_state[event_source] =
|
||||
mute_output(component, mute_mask[event_source]);
|
||||
vag_power_off(component, event_source);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
restore_output(component, mute_mask[event_source],
|
||||
sgtl5000->mute_state[event_source]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -208,6 +333,41 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mute Headphone when power it up/down.
|
||||
* Control VAG power on HP power path.
|
||||
*/
|
||||
static int headphone_pga_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
return vag_and_mute_control(component, event, HP_POWER_EVENT);
|
||||
}
|
||||
|
||||
/* As manual describes, ADC/DAC powering up/down requires
|
||||
* to mute outputs to avoid pops.
|
||||
* Control VAG power on ADC/DAC power path.
|
||||
*/
|
||||
static int adc_updown_depop(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
return vag_and_mute_control(component, event, ADC_POWER_EVENT);
|
||||
}
|
||||
|
||||
static int dac_updown_depop(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
return vag_and_mute_control(component, event, DAC_POWER_EVENT);
|
||||
}
|
||||
|
||||
/* input sources for ADC */
|
||||
static const char *adc_mux_text[] = {
|
||||
"MIC_IN", "LINE_IN"
|
||||
@@ -280,7 +440,10 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
|
||||
mic_bias_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||
|
||||
SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0,
|
||||
headphone_pga_event,
|
||||
SND_SOC_DAPM_PRE_POST_PMU |
|
||||
SND_SOC_DAPM_PRE_POST_PMD),
|
||||
SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
|
||||
@@ -301,11 +464,12 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
|
||||
0, SGTL5000_CHIP_DIG_POWER,
|
||||
1, 0),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
|
||||
SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
|
||||
|
||||
SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event),
|
||||
SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event),
|
||||
SND_SOC_DAPM_ADC_E("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0,
|
||||
adc_updown_depop, SND_SOC_DAPM_PRE_POST_PMU |
|
||||
SND_SOC_DAPM_PRE_POST_PMD),
|
||||
SND_SOC_DAPM_DAC_E("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0,
|
||||
dac_updown_depop, SND_SOC_DAPM_PRE_POST_PMU |
|
||||
SND_SOC_DAPM_PRE_POST_PMD),
|
||||
};
|
||||
|
||||
/* routes for sgtl5000 */
|
||||
@@ -556,6 +720,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
|
||||
SGTL5000_CHIP_ANA_ADC_CTRL,
|
||||
8, 1, 0, capture_6db_attenuate),
|
||||
SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0),
|
||||
SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, 0, 1, 1),
|
||||
|
||||
SOC_DOUBLE_TLV("Headphone Playback Volume",
|
||||
SGTL5000_CHIP_ANA_HP_CTRL,
|
||||
@@ -1173,12 +1338,17 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component)
|
||||
SGTL5000_INT_OSC_EN);
|
||||
/* Enable VDDC charge pump */
|
||||
ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
|
||||
} else if (vddio >= 3100 && vdda >= 3100) {
|
||||
} else {
|
||||
ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP;
|
||||
/* VDDC use VDDIO rail */
|
||||
lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
|
||||
lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
|
||||
SGTL5000_VDDC_MAN_ASSN_SHIFT;
|
||||
/*
|
||||
* if vddio == vdda the source of charge pump should be
|
||||
* assigned manually to VDDIO
|
||||
*/
|
||||
if (vddio == vdda) {
|
||||
lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
|
||||
lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
|
||||
SGTL5000_VDDC_MAN_ASSN_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl);
|
||||
@@ -1288,6 +1458,7 @@ static int sgtl5000_probe(struct snd_soc_component *component)
|
||||
int ret;
|
||||
u16 reg;
|
||||
struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN;
|
||||
|
||||
/* power up sgtl5000 */
|
||||
ret = sgtl5000_set_power_regs(component);
|
||||
@@ -1296,7 +1467,7 @@ static int sgtl5000_probe(struct snd_soc_component *component)
|
||||
|
||||
/* enable small pop, introduce 400ms delay in turning off */
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL,
|
||||
SGTL5000_SMALL_POP, 1);
|
||||
SGTL5000_SMALL_POP, SGTL5000_SMALL_POP);
|
||||
|
||||
/* disable short cut detector */
|
||||
snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0);
|
||||
@@ -1315,9 +1486,8 @@ static int sgtl5000_probe(struct snd_soc_component *component)
|
||||
0x1f);
|
||||
snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg);
|
||||
|
||||
snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL,
|
||||
SGTL5000_HP_ZCD_EN |
|
||||
SGTL5000_ADC_ZCD_EN);
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
|
||||
zcd_mask, zcd_mask);
|
||||
|
||||
snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL,
|
||||
SGTL5000_BIAS_R_MASK,
|
||||
|
@@ -273,7 +273,7 @@
|
||||
#define SGTL5000_BIAS_CTRL_MASK 0x000e
|
||||
#define SGTL5000_BIAS_CTRL_SHIFT 1
|
||||
#define SGTL5000_BIAS_CTRL_WIDTH 3
|
||||
#define SGTL5000_SMALL_POP 1
|
||||
#define SGTL5000_SMALL_POP 0x0001
|
||||
|
||||
/*
|
||||
* SGTL5000_CHIP_MIC_CTRL
|
||||
|
@@ -459,7 +459,6 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
struct sirf_audio_codec *sirf_audio_codec;
|
||||
void __iomem *base;
|
||||
struct resource *mem_res;
|
||||
|
||||
sirf_audio_codec = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct sirf_audio_codec), GFP_KERNEL);
|
||||
@@ -468,8 +467,7 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, sirf_audio_codec);
|
||||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem_res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@@ -67,8 +67,6 @@ static SOC_ENUM_SINGLE_DECL(rec_src_enum,
|
||||
static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
|
||||
SOC_DAPM_ENUM("Input Select", rec_src_enum);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src,
|
||||
TLV320AIC23_ANLG, 2, rec_src_text);
|
||||
static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph,
|
||||
TLV320AIC23_DIGT, 1, deemph_text);
|
||||
|
||||
|
@@ -258,7 +258,6 @@ static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4,
|
||||
static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2,
|
||||
mic_select_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
|
||||
mic_select_text);
|
||||
|
||||
@@ -1553,7 +1552,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
||||
aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(aic31xx->gpio_reset)) {
|
||||
dev_err(aic31xx->dev, "not able to acquire gpio\n");
|
||||
if (PTR_ERR(aic31xx->gpio_reset) != -EPROBE_DEFER)
|
||||
dev_err(aic31xx->dev, "not able to acquire gpio\n");
|
||||
return PTR_ERR(aic31xx->gpio_reset);
|
||||
}
|
||||
|
||||
@@ -1564,7 +1564,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
||||
ARRAY_SIZE(aic31xx->supplies),
|
||||
aic31xx->supplies);
|
||||
if (ret) {
|
||||
dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(aic31xx->dev,
|
||||
"Failed to request supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "tscs454.h"
|
||||
|
||||
static const unsigned int PLL_48K_RATE = (48000 * 256);
|
||||
static const unsigned int PLL_44_1K_RATE = (44100 * 256);
|
||||
|
||||
#define COEFF_SIZE 3
|
||||
|
@@ -1108,10 +1108,8 @@ static int twl6040_probe(struct snd_soc_component *component)
|
||||
priv->component = component;
|
||||
|
||||
priv->plug_irq = platform_get_irq(pdev, 0);
|
||||
if (priv->plug_irq < 0) {
|
||||
dev_err(component->dev, "invalid irq: %d\n", priv->plug_irq);
|
||||
if (priv->plug_irq < 0)
|
||||
return priv->plug_irq;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
|
||||
|
||||
|
295
sound/soc/codecs/uda1334.c
Normal file
295
sound/soc/codecs/uda1334.c
Normal file
@@ -0,0 +1,295 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// uda1334.c -- UDA1334 ALSA SoC Audio driver
|
||||
//
|
||||
// Based on WM8523 ALSA SoC Audio driver written by Mark Brown
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#define UDA1334_NUM_RATES 6
|
||||
|
||||
/* codec private data */
|
||||
struct uda1334_priv {
|
||||
struct gpio_desc *mute;
|
||||
struct gpio_desc *deemph;
|
||||
unsigned int sysclk;
|
||||
unsigned int rate_constraint_list[UDA1334_NUM_RATES];
|
||||
struct snd_pcm_hw_constraint_list rate_constraint;
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget uda1334_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route uda1334_dapm_routes[] = {
|
||||
{ "LINEVOUTL", NULL, "DAC" },
|
||||
{ "LINEVOUTR", NULL, "DAC" },
|
||||
};
|
||||
|
||||
static int uda1334_put_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
int deemph = ucontrol->value.integer.value[0];
|
||||
|
||||
if (deemph > 1)
|
||||
return -EINVAL;
|
||||
|
||||
gpiod_set_value_cansleep(uda1334->deemph, deemph);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int uda1334_get_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
ret = gpiod_get_value_cansleep(uda1334->deemph);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ucontrol->value.integer.value[0] = ret;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new uda1334_snd_controls[] = {
|
||||
SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0,
|
||||
uda1334_get_deemph, uda1334_put_deemph),
|
||||
};
|
||||
|
||||
static const struct {
|
||||
int value;
|
||||
int ratio;
|
||||
} lrclk_ratios[UDA1334_NUM_RATES] = {
|
||||
{ 1, 128 },
|
||||
{ 2, 192 },
|
||||
{ 3, 256 },
|
||||
{ 4, 384 },
|
||||
{ 5, 512 },
|
||||
{ 6, 768 },
|
||||
};
|
||||
|
||||
static int uda1334_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
/*
|
||||
* The set of sample rates that can be supported depends on the
|
||||
* MCLK supplied to the CODEC - enforce this.
|
||||
*/
|
||||
if (!uda1334->sysclk) {
|
||||
dev_err(component->dev,
|
||||
"No MCLK configured, call set_sysclk() on init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&uda1334->rate_constraint);
|
||||
|
||||
gpiod_set_value_cansleep(uda1334->mute, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uda1334_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
gpiod_set_value_cansleep(uda1334->mute, 0);
|
||||
}
|
||||
|
||||
static int uda1334_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val;
|
||||
int i, j = 0;
|
||||
|
||||
uda1334->sysclk = freq;
|
||||
|
||||
uda1334->rate_constraint.count = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
|
||||
val = freq / lrclk_ratios[i].ratio;
|
||||
/*
|
||||
* Check that it's a standard rate since core can't
|
||||
* cope with others and having the odd rates confuses
|
||||
* constraint matching.
|
||||
*/
|
||||
|
||||
switch (val) {
|
||||
case 8000:
|
||||
case 32000:
|
||||
case 44100:
|
||||
case 48000:
|
||||
case 64000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
dev_dbg(component->dev, "Supported sample rate: %dHz\n",
|
||||
val);
|
||||
uda1334->rate_constraint_list[j++] = val;
|
||||
uda1334->rate_constraint.count++;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(component->dev, "Skipping sample rate: %dHz\n",
|
||||
val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Need at least one supported rate... */
|
||||
if (uda1334->rate_constraint.count == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uda1334_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
{
|
||||
fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK |
|
||||
SND_SOC_DAIFMT_MASTER_MASK);
|
||||
|
||||
if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS)) {
|
||||
dev_err(codec_dai->dev, "Invalid DAI format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uda1334_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
{
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(dai->component);
|
||||
|
||||
if (uda1334->mute)
|
||||
gpiod_set_value_cansleep(uda1334->mute, mute);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define UDA1334_RATES SNDRV_PCM_RATE_8000_96000
|
||||
|
||||
#define UDA1334_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
||||
static const struct snd_soc_dai_ops uda1334_dai_ops = {
|
||||
.startup = uda1334_startup,
|
||||
.shutdown = uda1334_shutdown,
|
||||
.set_sysclk = uda1334_set_dai_sysclk,
|
||||
.set_fmt = uda1334_set_fmt,
|
||||
.mute_stream = uda1334_mute_stream,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver uda1334_dai = {
|
||||
.name = "uda1334-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = UDA1334_RATES,
|
||||
.formats = UDA1334_FORMATS,
|
||||
},
|
||||
.ops = &uda1334_dai_ops,
|
||||
};
|
||||
|
||||
static int uda1334_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
uda1334->rate_constraint.list = &uda1334->rate_constraint_list[0];
|
||||
uda1334->rate_constraint.count =
|
||||
ARRAY_SIZE(uda1334->rate_constraint_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_component_dev_uda1334 = {
|
||||
.probe = uda1334_probe,
|
||||
.controls = uda1334_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(uda1334_snd_controls),
|
||||
.dapm_widgets = uda1334_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(uda1334_dapm_widgets),
|
||||
.dapm_routes = uda1334_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(uda1334_dapm_routes),
|
||||
.idle_bias_on = 1,
|
||||
.use_pmdown_time = 1,
|
||||
.endianness = 1,
|
||||
.non_legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id uda1334_of_match[] = {
|
||||
{ .compatible = "nxp,uda1334" },
|
||||
{ /* sentinel*/ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, uda1334_of_match);
|
||||
|
||||
static int uda1334_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uda1334_priv *uda1334;
|
||||
int ret;
|
||||
|
||||
uda1334 = devm_kzalloc(&pdev->dev, sizeof(struct uda1334_priv),
|
||||
GFP_KERNEL);
|
||||
if (!uda1334)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, uda1334);
|
||||
|
||||
uda1334->mute = devm_gpiod_get(&pdev->dev, "nxp,mute", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(uda1334->mute)) {
|
||||
ret = PTR_ERR(uda1334->mute);
|
||||
dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uda1334->deemph = devm_gpiod_get(&pdev->dev, "nxp,deemph", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(uda1334->deemph)) {
|
||||
ret = PTR_ERR(uda1334->deemph);
|
||||
dev_err(&pdev->dev, "Failed to get deemph line: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&soc_component_dev_uda1334,
|
||||
&uda1334_dai, 1);
|
||||
if (ret < 0)
|
||||
dev_err(&pdev->dev, "Failed to register component: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver uda1334_codec_driver = {
|
||||
.probe = uda1334_codec_probe,
|
||||
.driver = {
|
||||
.name = "uda1334-codec",
|
||||
.of_match_table = uda1334_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(uda1334_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC UDA1334 driver");
|
||||
MODULE_AUTHOR("Andra Danciu <andradanciu1997@gmail.com>");
|
||||
MODULE_ALIAS("platform:uda1334-codec");
|
||||
MODULE_LICENSE("GPL v2");
|
@@ -65,7 +65,7 @@ struct wcd_clsh_ctrl {
|
||||
#define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0
|
||||
#define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7)
|
||||
#define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4)
|
||||
#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3)
|
||||
#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(3, 0)
|
||||
#define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3)
|
||||
#define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3)
|
||||
#define WCD9XXX_HPH_CONST_SEL_BYPASS 0
|
||||
|
@@ -2071,9 +2071,10 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
|
||||
.id = AIF1_PB,
|
||||
.playback = {
|
||||
.stream_name = "AIF1 Playback",
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK,
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
|
||||
SNDRV_PCM_RATE_384000,
|
||||
.formats = WCD9335_FORMATS_S16_S24_LE,
|
||||
.rate_max = 192000,
|
||||
.rate_max = 384000,
|
||||
.rate_min = 8000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
@@ -2099,10 +2100,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
|
||||
.id = AIF2_PB,
|
||||
.playback = {
|
||||
.stream_name = "AIF2 Playback",
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK,
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
|
||||
SNDRV_PCM_RATE_384000,
|
||||
.formats = WCD9335_FORMATS_S16_S24_LE,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 192000,
|
||||
.rate_max = 384000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
@@ -2127,10 +2129,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
|
||||
.id = AIF3_PB,
|
||||
.playback = {
|
||||
.stream_name = "AIF3 Playback",
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK,
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
|
||||
SNDRV_PCM_RATE_384000,
|
||||
.formats = WCD9335_FORMATS_S16_S24_LE,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 192000,
|
||||
.rate_max = 384000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
@@ -2155,10 +2158,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
|
||||
.id = AIF4_PB,
|
||||
.playback = {
|
||||
.stream_name = "AIF4 Playback",
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK,
|
||||
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
|
||||
SNDRV_PCM_RATE_384000,
|
||||
.formats = WCD9335_FORMATS_S16_S24_LE,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 192000,
|
||||
.rate_max = 384000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
@@ -3018,7 +3022,6 @@ static int wcd9335_codec_enable_slim(struct snd_soc_dapm_widget *w,
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
struct wcd9335_codec *wcd = snd_soc_component_get_drvdata(comp);
|
||||
struct wcd_slim_codec_dai_data *dai = &wcd->dai[w->shift];
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
@@ -3030,7 +3033,7 @@ static int wcd9335_codec_enable_slim(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
|
||||
@@ -3535,7 +3538,6 @@ static int wcd9335_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
int hph_mode = wcd->hph_mode;
|
||||
u8 dem_inp;
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@@ -3575,7 +3577,7 @@ static int wcd9335_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
|
||||
@@ -3603,7 +3605,6 @@ static int wcd9335_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@@ -3617,7 +3618,7 @@ static int wcd9335_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wcd9335_codec_hph_post_pa_config(struct wcd9335_codec *wcd,
|
||||
@@ -3688,7 +3689,6 @@ static int wcd9335_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
int hph_mode = wcd->hph_mode;
|
||||
u8 dem_inp;
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@@ -3727,7 +3727,7 @@ static int wcd9335_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
||||
@@ -3737,7 +3737,6 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
int hph_mode = wcd->hph_mode;
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@@ -3776,7 +3775,7 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
|
||||
@@ -3785,7 +3784,6 @@ static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
int vol_reg = 0, mix_vol_reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (w->reg == WCD9335_ANA_LO_1_2) {
|
||||
if (w->shift == 7) {
|
||||
@@ -3833,7 +3831,7 @@ static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wcd9335_codec_init_flyback(struct snd_soc_component *component)
|
||||
@@ -3888,7 +3886,6 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
int hph_mode = wcd->hph_mode;
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@@ -3926,14 +3923,13 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kc, int event)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
@@ -3963,7 +3959,7 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
|
||||
@@ -4062,7 +4058,8 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd)
|
||||
|
||||
ret = devm_request_threaded_irq(wcd->dev, irq, NULL,
|
||||
wcd9335_irqs[i].handler,
|
||||
IRQF_TRIGGER_RISING,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT,
|
||||
wcd9335_irqs[i].name, wcd);
|
||||
if (ret) {
|
||||
dev_err(wcd->dev, "Failed to request %s\n",
|
||||
|
@@ -140,7 +140,7 @@ struct pll_factors {
|
||||
* to allow rounding later */
|
||||
#define FIXED_FLL_SIZE ((1 << 22) * 10)
|
||||
|
||||
static int wm8995_pll_factors(struct device *dev,
|
||||
static int wm8955_pll_factors(struct device *dev,
|
||||
int Fref, int Fout, struct pll_factors *pll)
|
||||
{
|
||||
u64 Kpart;
|
||||
@@ -279,7 +279,7 @@ static int wm8955_configure_clocking(struct snd_soc_component *component)
|
||||
|
||||
/* Use the last divider configuration we saw for the
|
||||
* sample rate. */
|
||||
ret = wm8995_pll_factors(component->dev, wm8955->mclk_rate,
|
||||
ret = wm8955_pll_factors(component->dev, wm8955->mclk_rate,
|
||||
clock_cfgs[sr].mclk, &pll);
|
||||
if (ret != 0) {
|
||||
dev_err(component->dev,
|
||||
|
@@ -273,7 +273,7 @@ static const struct soc_enum wm8988_rline_enum =
|
||||
wm8988_line_texts,
|
||||
wm8988_line_values);
|
||||
static const struct snd_kcontrol_new wm8988_right_line_controls =
|
||||
SOC_DAPM_ENUM("Route", wm8988_lline_enum);
|
||||
SOC_DAPM_ENUM("Route", wm8988_rline_enum);
|
||||
|
||||
/* Left Mixer */
|
||||
static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
|
||||
|
@@ -4242,8 +4242,9 @@ static void wm_adsp_fatal_error(struct wm_adsp *dsp)
|
||||
}
|
||||
}
|
||||
|
||||
irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
|
||||
irqreturn_t wm_adsp2_bus_error(int irq, void *data)
|
||||
{
|
||||
struct wm_adsp *dsp = (struct wm_adsp *)data;
|
||||
unsigned int val;
|
||||
struct regmap *regmap = dsp->regmap;
|
||||
int ret = 0;
|
||||
@@ -4307,8 +4308,9 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
|
||||
|
||||
irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp)
|
||||
irqreturn_t wm_halo_bus_error(int irq, void *data)
|
||||
{
|
||||
struct wm_adsp *dsp = (struct wm_adsp *)data;
|
||||
struct regmap *regmap = dsp->regmap;
|
||||
unsigned int fault[6];
|
||||
struct reg_sequence clear[] = {
|
||||
|
@@ -171,8 +171,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
||||
int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
|
||||
irqreturn_t wm_adsp2_bus_error(struct wm_adsp *adsp);
|
||||
irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp);
|
||||
irqreturn_t wm_adsp2_bus_error(int irq, void *data);
|
||||
irqreturn_t wm_halo_bus_error(int irq, void *data);
|
||||
irqreturn_t wm_halo_wdt_expire(int irq, void *data);
|
||||
|
||||
int wm_adsp_event(struct snd_soc_dapm_widget *w,
|
||||
|
Reference in New Issue
Block a user