Merge remote-tracking branch 'asoc/fix/ab8500' into asoc-linus
This commit is contained in:
@@ -117,8 +117,7 @@ static inline void pxa_ac97_warm_pxa25x(void)
|
||||
{
|
||||
gsr_bits = 0;
|
||||
|
||||
GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
|
||||
wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
|
||||
GCR |= GCR_WARM_RST;
|
||||
}
|
||||
|
||||
static inline void pxa_ac97_cold_pxa25x(void)
|
||||
@@ -129,8 +128,6 @@ static inline void pxa_ac97_cold_pxa25x(void)
|
||||
gsr_bits = 0;
|
||||
|
||||
GCR = GCR_COLD_RST;
|
||||
GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
|
||||
wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -149,8 +146,6 @@ static inline void pxa_ac97_warm_pxa27x(void)
|
||||
|
||||
static inline void pxa_ac97_cold_pxa27x(void)
|
||||
{
|
||||
unsigned int timeout;
|
||||
|
||||
GCR &= GCR_COLD_RST; /* clear everything but nCRST */
|
||||
GCR &= ~GCR_COLD_RST; /* then assert nCRST */
|
||||
|
||||
@@ -161,29 +156,20 @@ static inline void pxa_ac97_cold_pxa27x(void)
|
||||
udelay(5);
|
||||
clk_disable(ac97conf_clk);
|
||||
GCR = GCR_COLD_RST | GCR_WARM_RST;
|
||||
timeout = 100; /* wait for the codec-ready bit to be set */
|
||||
while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
|
||||
mdelay(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PXA3xx
|
||||
static inline void pxa_ac97_warm_pxa3xx(void)
|
||||
{
|
||||
int timeout = 100;
|
||||
|
||||
gsr_bits = 0;
|
||||
|
||||
/* Can't use interrupts */
|
||||
GCR |= GCR_WARM_RST;
|
||||
while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
static inline void pxa_ac97_cold_pxa3xx(void)
|
||||
{
|
||||
int timeout = 1000;
|
||||
|
||||
/* Hold CLKBPB for 100us */
|
||||
GCR = 0;
|
||||
GCR = GCR_CLKBPB;
|
||||
@@ -199,14 +185,13 @@ static inline void pxa_ac97_cold_pxa3xx(void)
|
||||
GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
|
||||
|
||||
GCR = GCR_WARM_RST | GCR_COLD_RST;
|
||||
while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
|
||||
mdelay(10);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
|
||||
{
|
||||
unsigned long gsr;
|
||||
unsigned int timeout = 100;
|
||||
|
||||
#ifdef CONFIG_PXA25x
|
||||
if (cpu_is_pxa25x())
|
||||
@@ -224,6 +209,10 @@ bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
|
||||
else
|
||||
#endif
|
||||
BUG();
|
||||
|
||||
while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
|
||||
mdelay(1);
|
||||
|
||||
gsr = GSR | gsr_bits;
|
||||
if (!(gsr & (GSR_PCR | GSR_SCR))) {
|
||||
printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
|
||||
@@ -239,6 +228,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
|
||||
bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
|
||||
{
|
||||
unsigned long gsr;
|
||||
unsigned int timeout = 1000;
|
||||
|
||||
#ifdef CONFIG_PXA25x
|
||||
if (cpu_is_pxa25x())
|
||||
@@ -257,6 +247,9 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
|
||||
#endif
|
||||
BUG();
|
||||
|
||||
while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
|
||||
mdelay(1);
|
||||
|
||||
gsr = GSR | gsr_bits;
|
||||
if (!(gsr & (GSR_PCR | GSR_SCR))) {
|
||||
printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
|
||||
snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
|
||||
snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
||||
|
@@ -50,7 +50,7 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
|
||||
buf->area = dma_alloc_coherent(pcm->card->dev, size,
|
||||
&buf->addr, GFP_KERNEL);
|
||||
pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
|
||||
(void *)buf->area, (void *)buf->addr, size);
|
||||
(void *)buf->area, (void *)(long)buf->addr, size);
|
||||
|
||||
if (!buf->area)
|
||||
return -ENOMEM;
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
@@ -155,15 +154,8 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
||||
struct snd_soc_card *card = &atmel_asoc_wm8904_card;
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
struct clk *clk_src;
|
||||
struct pinctrl *pinctrl;
|
||||
int id, ret;
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl)) {
|
||||
dev_err(&pdev->dev, "failed to request pinctrl\n");
|
||||
return PTR_ERR(pinctrl);
|
||||
}
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
ret = atmel_asoc_wm8904_dt_init(pdev);
|
||||
if (ret) {
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/atmel-ssc.h>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
config SND_EP93XX_SOC
|
||||
tristate "SoC Audio support for the Cirrus Logic EP93xx series"
|
||||
depends on ARCH_EP93XX && SND_SOC
|
||||
depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC
|
||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
help
|
||||
Say Y or M if you want to add support for codecs attached to
|
||||
|
@@ -57,9 +57,22 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct dma_chan *ep93xx_compat_request_channel(
|
||||
struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_dmaengine_dai_dma_data *dma_data;
|
||||
|
||||
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
return snd_dmaengine_pcm_request_channel(ep93xx_pcm_dma_filter,
|
||||
dma_data);
|
||||
}
|
||||
|
||||
static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
|
||||
.pcm_hardware = &ep93xx_pcm_hardware,
|
||||
.compat_filter_fn = ep93xx_pcm_dma_filter,
|
||||
.compat_request_channel = ep93xx_compat_request_channel,
|
||||
.prealloc_buffer_size = 131072,
|
||||
};
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <linux/mfd/88pm860x.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@@ -140,6 +141,7 @@ struct pm860x_priv {
|
||||
unsigned int filter;
|
||||
struct snd_soc_codec *codec;
|
||||
struct i2c_client *i2c;
|
||||
struct regmap *regmap;
|
||||
struct pm860x_chip *chip;
|
||||
struct pm860x_det det;
|
||||
|
||||
@@ -269,48 +271,6 @@ static struct st_gain st_table[] = {
|
||||
{ -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0},
|
||||
};
|
||||
|
||||
static int pm860x_volatile(unsigned int reg)
|
||||
{
|
||||
BUG_ON(reg >= REG_CACHE_SIZE);
|
||||
|
||||
switch (reg) {
|
||||
case PM860X_AUDIO_SUPPLIES_2:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned char *cache = codec->reg_cache;
|
||||
|
||||
BUG_ON(reg >= REG_CACHE_SIZE);
|
||||
|
||||
if (pm860x_volatile(reg))
|
||||
return cache[reg];
|
||||
|
||||
reg += REG_CACHE_BASE;
|
||||
|
||||
return pm860x_reg_read(codec->control_data, reg);
|
||||
}
|
||||
|
||||
static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
unsigned char *cache = codec->reg_cache;
|
||||
|
||||
BUG_ON(reg >= REG_CACHE_SIZE);
|
||||
|
||||
if (!pm860x_volatile(reg))
|
||||
cache[reg] = (unsigned char)value;
|
||||
|
||||
reg += REG_CACHE_BASE;
|
||||
|
||||
return pm860x_reg_write(codec->control_data, reg, value);
|
||||
}
|
||||
|
||||
static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
@@ -1169,6 +1129,7 @@ static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
|
||||
int data;
|
||||
|
||||
switch (level) {
|
||||
@@ -1182,17 +1143,17 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Enable Audio PLL & Audio section */
|
||||
data = AUDIO_PLL | AUDIO_SECTION_ON;
|
||||
pm860x_reg_write(codec->control_data, REG_MISC2, data);
|
||||
pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
|
||||
udelay(300);
|
||||
data = AUDIO_PLL | AUDIO_SECTION_RESET
|
||||
| AUDIO_SECTION_ON;
|
||||
pm860x_reg_write(codec->control_data, REG_MISC2, data);
|
||||
pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
|
||||
pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
|
||||
pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
@@ -1322,17 +1283,17 @@ int pm860x_hs_jack_detect(struct snd_soc_codec *codec,
|
||||
pm860x->det.lo_shrt = lo_shrt;
|
||||
|
||||
if (det & SND_JACK_HEADPHONE)
|
||||
pm860x_set_bits(codec->control_data, REG_HS_DET,
|
||||
pm860x_set_bits(pm860x->i2c, REG_HS_DET,
|
||||
EN_HS_DET, EN_HS_DET);
|
||||
/* headset short detect */
|
||||
if (hs_shrt) {
|
||||
data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
|
||||
pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
|
||||
pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
|
||||
}
|
||||
/* Lineout short detect */
|
||||
if (lo_shrt) {
|
||||
data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
|
||||
pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
|
||||
pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
|
||||
}
|
||||
|
||||
/* sync status */
|
||||
@@ -1350,7 +1311,7 @@ int pm860x_mic_jack_detect(struct snd_soc_codec *codec,
|
||||
pm860x->det.mic_det = det;
|
||||
|
||||
if (det & SND_JACK_MICROPHONE)
|
||||
pm860x_set_bits(codec->control_data, REG_MIC_DET,
|
||||
pm860x_set_bits(pm860x->i2c, REG_MIC_DET,
|
||||
MICDET_MASK, MICDET_MASK);
|
||||
|
||||
/* sync status */
|
||||
@@ -1366,7 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec)
|
||||
|
||||
pm860x->codec = codec;
|
||||
|
||||
codec->control_data = pm860x->i2c;
|
||||
codec->control_data = pm860x->regmap;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = request_threaded_irq(pm860x->irq[i], NULL,
|
||||
@@ -1380,14 +1341,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
|
||||
|
||||
pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
|
||||
REG_CACHE_SIZE, codec->reg_cache);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to fill register cache: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
@@ -1410,10 +1363,6 @@ static int pm860x_remove(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
|
||||
.probe = pm860x_probe,
|
||||
.remove = pm860x_remove,
|
||||
.read = pm860x_read_reg_cache,
|
||||
.write = pm860x_write_reg_cache,
|
||||
.reg_cache_size = REG_CACHE_SIZE,
|
||||
.reg_word_size = sizeof(u8),
|
||||
.set_bias_level = pm860x_set_bias_level,
|
||||
|
||||
.controls = pm860x_snd_controls,
|
||||
@@ -1439,6 +1388,8 @@ static int pm860x_codec_probe(struct platform_device *pdev)
|
||||
pm860x->chip = chip;
|
||||
pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
|
||||
: chip->companion;
|
||||
pm860x->regmap = (chip->id == CHIP_PM8607) ? chip->regmap
|
||||
: chip->regmap_companion;
|
||||
platform_set_drvdata(pdev, pm860x);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@@ -12,67 +12,66 @@
|
||||
#ifndef __88PM860X_H
|
||||
#define __88PM860X_H
|
||||
|
||||
/* The offset of these registers are 0xb0 */
|
||||
#define PM860X_PCM_IFACE_1 0x00
|
||||
#define PM860X_PCM_IFACE_2 0x01
|
||||
#define PM860X_PCM_IFACE_3 0x02
|
||||
#define PM860X_PCM_RATE 0x03
|
||||
#define PM860X_EC_PATH 0x04
|
||||
#define PM860X_SIDETONE_L_GAIN 0x05
|
||||
#define PM860X_SIDETONE_R_GAIN 0x06
|
||||
#define PM860X_SIDETONE_SHIFT 0x07
|
||||
#define PM860X_ADC_OFFSET_1 0x08
|
||||
#define PM860X_ADC_OFFSET_2 0x09
|
||||
#define PM860X_DMIC_DELAY 0x0a
|
||||
#define PM860X_PCM_IFACE_1 0xb0
|
||||
#define PM860X_PCM_IFACE_2 0xb1
|
||||
#define PM860X_PCM_IFACE_3 0xb2
|
||||
#define PM860X_PCM_RATE 0xb3
|
||||
#define PM860X_EC_PATH 0xb4
|
||||
#define PM860X_SIDETONE_L_GAIN 0xb5
|
||||
#define PM860X_SIDETONE_R_GAIN 0xb6
|
||||
#define PM860X_SIDETONE_SHIFT 0xb7
|
||||
#define PM860X_ADC_OFFSET_1 0xb8
|
||||
#define PM860X_ADC_OFFSET_2 0xb9
|
||||
#define PM860X_DMIC_DELAY 0xba
|
||||
|
||||
#define PM860X_I2S_IFACE_1 0x0b
|
||||
#define PM860X_I2S_IFACE_2 0x0c
|
||||
#define PM860X_I2S_IFACE_3 0x0d
|
||||
#define PM860X_I2S_IFACE_4 0x0e
|
||||
#define PM860X_EQUALIZER_N0_1 0x0f
|
||||
#define PM860X_EQUALIZER_N0_2 0x10
|
||||
#define PM860X_EQUALIZER_N1_1 0x11
|
||||
#define PM860X_EQUALIZER_N1_2 0x12
|
||||
#define PM860X_EQUALIZER_D1_1 0x13
|
||||
#define PM860X_EQUALIZER_D1_2 0x14
|
||||
#define PM860X_LOFI_GAIN_LEFT 0x15
|
||||
#define PM860X_LOFI_GAIN_RIGHT 0x16
|
||||
#define PM860X_HIFIL_GAIN_LEFT 0x17
|
||||
#define PM860X_HIFIL_GAIN_RIGHT 0x18
|
||||
#define PM860X_HIFIR_GAIN_LEFT 0x19
|
||||
#define PM860X_HIFIR_GAIN_RIGHT 0x1a
|
||||
#define PM860X_DAC_OFFSET 0x1b
|
||||
#define PM860X_OFFSET_LEFT_1 0x1c
|
||||
#define PM860X_OFFSET_LEFT_2 0x1d
|
||||
#define PM860X_OFFSET_RIGHT_1 0x1e
|
||||
#define PM860X_OFFSET_RIGHT_2 0x1f
|
||||
#define PM860X_ADC_ANA_1 0x20
|
||||
#define PM860X_ADC_ANA_2 0x21
|
||||
#define PM860X_ADC_ANA_3 0x22
|
||||
#define PM860X_ADC_ANA_4 0x23
|
||||
#define PM860X_ANA_TO_ANA 0x24
|
||||
#define PM860X_HS1_CTRL 0x25
|
||||
#define PM860X_HS2_CTRL 0x26
|
||||
#define PM860X_LO1_CTRL 0x27
|
||||
#define PM860X_LO2_CTRL 0x28
|
||||
#define PM860X_EAR_CTRL_1 0x29
|
||||
#define PM860X_EAR_CTRL_2 0x2a
|
||||
#define PM860X_AUDIO_SUPPLIES_1 0x2b
|
||||
#define PM860X_AUDIO_SUPPLIES_2 0x2c
|
||||
#define PM860X_ADC_EN_1 0x2d
|
||||
#define PM860X_ADC_EN_2 0x2e
|
||||
#define PM860X_DAC_EN_1 0x2f
|
||||
#define PM860X_DAC_EN_2 0x31
|
||||
#define PM860X_AUDIO_CAL_1 0x32
|
||||
#define PM860X_AUDIO_CAL_2 0x33
|
||||
#define PM860X_AUDIO_CAL_3 0x34
|
||||
#define PM860X_AUDIO_CAL_4 0x35
|
||||
#define PM860X_AUDIO_CAL_5 0x36
|
||||
#define PM860X_ANA_INPUT_SEL_1 0x37
|
||||
#define PM860X_ANA_INPUT_SEL_2 0x38
|
||||
#define PM860X_I2S_IFACE_1 0xbb
|
||||
#define PM860X_I2S_IFACE_2 0xbc
|
||||
#define PM860X_I2S_IFACE_3 0xbd
|
||||
#define PM860X_I2S_IFACE_4 0xbe
|
||||
#define PM860X_EQUALIZER_N0_1 0xbf
|
||||
#define PM860X_EQUALIZER_N0_2 0xc0
|
||||
#define PM860X_EQUALIZER_N1_1 0xc1
|
||||
#define PM860X_EQUALIZER_N1_2 0xc2
|
||||
#define PM860X_EQUALIZER_D1_1 0xc3
|
||||
#define PM860X_EQUALIZER_D1_2 0xc4
|
||||
#define PM860X_LOFI_GAIN_LEFT 0xc5
|
||||
#define PM860X_LOFI_GAIN_RIGHT 0xc6
|
||||
#define PM860X_HIFIL_GAIN_LEFT 0xc7
|
||||
#define PM860X_HIFIL_GAIN_RIGHT 0xc8
|
||||
#define PM860X_HIFIR_GAIN_LEFT 0xc9
|
||||
#define PM860X_HIFIR_GAIN_RIGHT 0xca
|
||||
#define PM860X_DAC_OFFSET 0xcb
|
||||
#define PM860X_OFFSET_LEFT_1 0xcc
|
||||
#define PM860X_OFFSET_LEFT_2 0xcd
|
||||
#define PM860X_OFFSET_RIGHT_1 0xce
|
||||
#define PM860X_OFFSET_RIGHT_2 0xcf
|
||||
#define PM860X_ADC_ANA_1 0xd0
|
||||
#define PM860X_ADC_ANA_2 0xd1
|
||||
#define PM860X_ADC_ANA_3 0xd2
|
||||
#define PM860X_ADC_ANA_4 0xd3
|
||||
#define PM860X_ANA_TO_ANA 0xd4
|
||||
#define PM860X_HS1_CTRL 0xd5
|
||||
#define PM860X_HS2_CTRL 0xd6
|
||||
#define PM860X_LO1_CTRL 0xd7
|
||||
#define PM860X_LO2_CTRL 0xd8
|
||||
#define PM860X_EAR_CTRL_1 0xd9
|
||||
#define PM860X_EAR_CTRL_2 0xda
|
||||
#define PM860X_AUDIO_SUPPLIES_1 0xdb
|
||||
#define PM860X_AUDIO_SUPPLIES_2 0xdc
|
||||
#define PM860X_ADC_EN_1 0xdd
|
||||
#define PM860X_ADC_EN_2 0xde
|
||||
#define PM860X_DAC_EN_1 0xdf
|
||||
#define PM860X_DAC_EN_2 0xe1
|
||||
#define PM860X_AUDIO_CAL_1 0xe2
|
||||
#define PM860X_AUDIO_CAL_2 0xe3
|
||||
#define PM860X_AUDIO_CAL_3 0xe4
|
||||
#define PM860X_AUDIO_CAL_4 0xe5
|
||||
#define PM860X_AUDIO_CAL_5 0xe6
|
||||
#define PM860X_ANA_INPUT_SEL_1 0xe7
|
||||
#define PM860X_ANA_INPUT_SEL_2 0xe8
|
||||
|
||||
#define PM860X_PCM_IFACE_4 0x39
|
||||
#define PM860X_I2S_IFACE_5 0x3a
|
||||
#define PM860X_PCM_IFACE_4 0xe9
|
||||
#define PM860X_I2S_IFACE_5 0xea
|
||||
|
||||
#define PM860X_SHORTS 0x3b
|
||||
#define PM860X_PLL_ADJ_1 0x3c
|
||||
|
@@ -2532,12 +2532,10 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* Override HW-defaults */
|
||||
ab8500_codec_write_reg(codec,
|
||||
AB8500_ANACONF5,
|
||||
BIT(AB8500_ANACONF5_HSAUTOEN));
|
||||
ab8500_codec_write_reg(codec,
|
||||
AB8500_SHORTCIRCONF,
|
||||
BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
|
||||
snd_soc_write(codec, AB8500_ANACONF5,
|
||||
BIT(AB8500_ANACONF5_HSAUTOEN));
|
||||
snd_soc_write(codec, AB8500_SHORTCIRCONF,
|
||||
BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
|
||||
|
||||
/* Add filter controls */
|
||||
status = snd_soc_add_codec_controls(codec, ab8500_filter_controls,
|
||||
@@ -2606,7 +2604,7 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
|
||||
|
||||
static int ab8500_codec_driver_remove(struct platform_device *pdev)
|
||||
{
|
||||
dev_info(&pdev->dev, "%s Enter.\n", __func__);
|
||||
dev_dbg(&pdev->dev, "%s Enter.\n", __func__);
|
||||
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
|
||||
|
@@ -32,6 +32,7 @@ struct adau1373_dai {
|
||||
};
|
||||
|
||||
struct adau1373 {
|
||||
struct regmap *regmap;
|
||||
struct adau1373_dai dais[3];
|
||||
};
|
||||
|
||||
@@ -73,7 +74,6 @@ struct adau1373 {
|
||||
#define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7)
|
||||
#define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7)
|
||||
#define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7)
|
||||
#define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7)
|
||||
#define ADAU1373_HEADDECT 0x36
|
||||
#define ADAU1373_ADC_DAC_STATUS 0x37
|
||||
#define ADAU1373_ADC_CTRL 0x3c
|
||||
@@ -152,37 +152,172 @@ struct adau1373 {
|
||||
#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
|
||||
#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2
|
||||
|
||||
static const uint8_t adau1373_default_regs[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */
|
||||
0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */
|
||||
0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
|
||||
0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */
|
||||
0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
|
||||
0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */
|
||||
0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */
|
||||
0x00, 0x1f, 0x0f, 0x00, 0x00,
|
||||
static const struct reg_default adau1373_reg_defaults[] = {
|
||||
{ ADAU1373_INPUT_MODE, 0x00 },
|
||||
{ ADAU1373_AINL_CTRL(0), 0x00 },
|
||||
{ ADAU1373_AINR_CTRL(0), 0x00 },
|
||||
{ ADAU1373_AINL_CTRL(1), 0x00 },
|
||||
{ ADAU1373_AINR_CTRL(1), 0x00 },
|
||||
{ ADAU1373_AINL_CTRL(2), 0x00 },
|
||||
{ ADAU1373_AINR_CTRL(2), 0x00 },
|
||||
{ ADAU1373_AINL_CTRL(3), 0x00 },
|
||||
{ ADAU1373_AINR_CTRL(3), 0x00 },
|
||||
{ ADAU1373_LLINE_OUT(0), 0x00 },
|
||||
{ ADAU1373_RLINE_OUT(0), 0x00 },
|
||||
{ ADAU1373_LLINE_OUT(1), 0x00 },
|
||||
{ ADAU1373_RLINE_OUT(1), 0x00 },
|
||||
{ ADAU1373_LSPK_OUT, 0x00 },
|
||||
{ ADAU1373_RSPK_OUT, 0x00 },
|
||||
{ ADAU1373_LHP_OUT, 0x00 },
|
||||
{ ADAU1373_RHP_OUT, 0x00 },
|
||||
{ ADAU1373_ADC_GAIN, 0x00 },
|
||||
{ ADAU1373_LADC_MIXER, 0x00 },
|
||||
{ ADAU1373_RADC_MIXER, 0x00 },
|
||||
{ ADAU1373_LLINE1_MIX, 0x00 },
|
||||
{ ADAU1373_RLINE1_MIX, 0x00 },
|
||||
{ ADAU1373_LLINE2_MIX, 0x00 },
|
||||
{ ADAU1373_RLINE2_MIX, 0x00 },
|
||||
{ ADAU1373_LSPK_MIX, 0x00 },
|
||||
{ ADAU1373_RSPK_MIX, 0x00 },
|
||||
{ ADAU1373_LHP_MIX, 0x00 },
|
||||
{ ADAU1373_RHP_MIX, 0x00 },
|
||||
{ ADAU1373_EP_MIX, 0x00 },
|
||||
{ ADAU1373_HP_CTRL, 0x00 },
|
||||
{ ADAU1373_HP_CTRL2, 0x00 },
|
||||
{ ADAU1373_LS_CTRL, 0x00 },
|
||||
{ ADAU1373_EP_CTRL, 0x00 },
|
||||
{ ADAU1373_MICBIAS_CTRL1, 0x00 },
|
||||
{ ADAU1373_MICBIAS_CTRL2, 0x00 },
|
||||
{ ADAU1373_OUTPUT_CTRL, 0x00 },
|
||||
{ ADAU1373_PWDN_CTRL1, 0x00 },
|
||||
{ ADAU1373_PWDN_CTRL2, 0x00 },
|
||||
{ ADAU1373_PWDN_CTRL3, 0x00 },
|
||||
{ ADAU1373_DPLL_CTRL(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL1(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL2(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL3(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL4(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL5(0), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL6(0), 0x02 },
|
||||
{ ADAU1373_DPLL_CTRL(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL1(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL2(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL3(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL4(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL5(1), 0x00 },
|
||||
{ ADAU1373_PLL_CTRL6(1), 0x02 },
|
||||
{ ADAU1373_HEADDECT, 0x00 },
|
||||
{ ADAU1373_ADC_CTRL, 0x00 },
|
||||
{ ADAU1373_CLK_SRC_DIV(0), 0x00 },
|
||||
{ ADAU1373_CLK_SRC_DIV(1), 0x00 },
|
||||
{ ADAU1373_DAI(0), 0x0a },
|
||||
{ ADAU1373_DAI(1), 0x0a },
|
||||
{ ADAU1373_DAI(2), 0x0a },
|
||||
{ ADAU1373_BCLKDIV(0), 0x00 },
|
||||
{ ADAU1373_BCLKDIV(1), 0x00 },
|
||||
{ ADAU1373_BCLKDIV(2), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOA(0), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOB(0), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOA(1), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOB(1), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOA(2), 0x00 },
|
||||
{ ADAU1373_SRC_RATIOB(2), 0x00 },
|
||||
{ ADAU1373_DEEMP_CTRL, 0x00 },
|
||||
{ ADAU1373_SRC_DAI_CTRL(0), 0x08 },
|
||||
{ ADAU1373_SRC_DAI_CTRL(1), 0x08 },
|
||||
{ ADAU1373_SRC_DAI_CTRL(2), 0x08 },
|
||||
{ ADAU1373_DIN_MIX_CTRL(0), 0x00 },
|
||||
{ ADAU1373_DIN_MIX_CTRL(1), 0x00 },
|
||||
{ ADAU1373_DIN_MIX_CTRL(2), 0x00 },
|
||||
{ ADAU1373_DIN_MIX_CTRL(3), 0x00 },
|
||||
{ ADAU1373_DIN_MIX_CTRL(4), 0x00 },
|
||||
{ ADAU1373_DOUT_MIX_CTRL(0), 0x00 },
|
||||
{ ADAU1373_DOUT_MIX_CTRL(1), 0x00 },
|
||||
{ ADAU1373_DOUT_MIX_CTRL(2), 0x00 },
|
||||
{ ADAU1373_DOUT_MIX_CTRL(3), 0x00 },
|
||||
{ ADAU1373_DOUT_MIX_CTRL(4), 0x00 },
|
||||
{ ADAU1373_DAI_PBL_VOL(0), 0x00 },
|
||||
{ ADAU1373_DAI_PBR_VOL(0), 0x00 },
|
||||
{ ADAU1373_DAI_PBL_VOL(1), 0x00 },
|
||||
{ ADAU1373_DAI_PBR_VOL(1), 0x00 },
|
||||
{ ADAU1373_DAI_PBL_VOL(2), 0x00 },
|
||||
{ ADAU1373_DAI_PBR_VOL(2), 0x00 },
|
||||
{ ADAU1373_DAI_RECL_VOL(0), 0x00 },
|
||||
{ ADAU1373_DAI_RECR_VOL(0), 0x00 },
|
||||
{ ADAU1373_DAI_RECL_VOL(1), 0x00 },
|
||||
{ ADAU1373_DAI_RECR_VOL(1), 0x00 },
|
||||
{ ADAU1373_DAI_RECL_VOL(2), 0x00 },
|
||||
{ ADAU1373_DAI_RECR_VOL(2), 0x00 },
|
||||
{ ADAU1373_DAC1_PBL_VOL, 0x00 },
|
||||
{ ADAU1373_DAC1_PBR_VOL, 0x00 },
|
||||
{ ADAU1373_DAC2_PBL_VOL, 0x00 },
|
||||
{ ADAU1373_DAC2_PBR_VOL, 0x00 },
|
||||
{ ADAU1373_ADC_RECL_VOL, 0x00 },
|
||||
{ ADAU1373_ADC_RECR_VOL, 0x00 },
|
||||
{ ADAU1373_DMIC_RECL_VOL, 0x00 },
|
||||
{ ADAU1373_DMIC_RECR_VOL, 0x00 },
|
||||
{ ADAU1373_VOL_GAIN1, 0x00 },
|
||||
{ ADAU1373_VOL_GAIN2, 0x00 },
|
||||
{ ADAU1373_VOL_GAIN3, 0x00 },
|
||||
{ ADAU1373_HPF_CTRL, 0x00 },
|
||||
{ ADAU1373_BASS1, 0x00 },
|
||||
{ ADAU1373_BASS2, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x0, 0x78 },
|
||||
{ ADAU1373_DRC(0) + 0x1, 0x18 },
|
||||
{ ADAU1373_DRC(0) + 0x2, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x3, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x4, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x5, 0xc0 },
|
||||
{ ADAU1373_DRC(0) + 0x6, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x7, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x8, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0x9, 0xc0 },
|
||||
{ ADAU1373_DRC(0) + 0xa, 0x88 },
|
||||
{ ADAU1373_DRC(0) + 0xb, 0x7a },
|
||||
{ ADAU1373_DRC(0) + 0xc, 0xdf },
|
||||
{ ADAU1373_DRC(0) + 0xd, 0x20 },
|
||||
{ ADAU1373_DRC(0) + 0xe, 0x00 },
|
||||
{ ADAU1373_DRC(0) + 0xf, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x0, 0x78 },
|
||||
{ ADAU1373_DRC(1) + 0x1, 0x18 },
|
||||
{ ADAU1373_DRC(1) + 0x2, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x3, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x4, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x5, 0xc0 },
|
||||
{ ADAU1373_DRC(1) + 0x6, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x7, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x8, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0x9, 0xc0 },
|
||||
{ ADAU1373_DRC(1) + 0xa, 0x88 },
|
||||
{ ADAU1373_DRC(1) + 0xb, 0x7a },
|
||||
{ ADAU1373_DRC(1) + 0xc, 0xdf },
|
||||
{ ADAU1373_DRC(1) + 0xd, 0x20 },
|
||||
{ ADAU1373_DRC(1) + 0xe, 0x00 },
|
||||
{ ADAU1373_DRC(1) + 0xf, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x0, 0x78 },
|
||||
{ ADAU1373_DRC(2) + 0x1, 0x18 },
|
||||
{ ADAU1373_DRC(2) + 0x2, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x3, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x4, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x5, 0xc0 },
|
||||
{ ADAU1373_DRC(2) + 0x6, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x7, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x8, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0x9, 0xc0 },
|
||||
{ ADAU1373_DRC(2) + 0xa, 0x88 },
|
||||
{ ADAU1373_DRC(2) + 0xb, 0x7a },
|
||||
{ ADAU1373_DRC(2) + 0xc, 0xdf },
|
||||
{ ADAU1373_DRC(2) + 0xd, 0x20 },
|
||||
{ ADAU1373_DRC(2) + 0xe, 0x00 },
|
||||
{ ADAU1373_DRC(2) + 0xf, 0x00 },
|
||||
{ ADAU1373_3D_CTRL1, 0x00 },
|
||||
{ ADAU1373_3D_CTRL2, 0x00 },
|
||||
{ ADAU1373_FDSP_SEL1, 0x00 },
|
||||
{ ADAU1373_FDSP_SEL2, 0x00 },
|
||||
{ ADAU1373_FDSP_SEL2, 0x00 },
|
||||
{ ADAU1373_FDSP_SEL4, 0x00 },
|
||||
{ ADAU1373_DIGMICCTRL, 0x00 },
|
||||
{ ADAU1373_DIGEN, 0x00 },
|
||||
};
|
||||
|
||||
static const unsigned int adau1373_out_tlv[] = {
|
||||
@@ -418,6 +553,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int pll_id = w->name[3] - '1';
|
||||
unsigned int val;
|
||||
|
||||
@@ -426,7 +562,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
|
||||
else
|
||||
val = 0;
|
||||
|
||||
snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
|
||||
ADAU1373_PLL_CTRL6_PLL_EN, val);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
@@ -938,7 +1074,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
adau1373_dai->enable_src = (div != 0);
|
||||
|
||||
snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
|
||||
ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
|
||||
(div << 2) | ADAU1373_BCLKDIV_64);
|
||||
|
||||
@@ -959,7 +1095,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
|
||||
return regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
|
||||
ADAU1373_DAI_WLEN_MASK, ctrl);
|
||||
}
|
||||
|
||||
@@ -1016,7 +1152,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
|
||||
~ADAU1373_DAI_WLEN_MASK, ctrl);
|
||||
|
||||
return 0;
|
||||
@@ -1039,7 +1175,7 @@ static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai,
|
||||
adau1373_dai->sysclk = freq;
|
||||
adau1373_dai->clk_src = clk_id;
|
||||
|
||||
snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
|
||||
ADAU1373_BCLKDIV_SOURCE, clk_id << 5);
|
||||
|
||||
return 0;
|
||||
@@ -1120,6 +1256,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
|
||||
static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
int source, unsigned int freq_in, unsigned int freq_out)
|
||||
{
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int dpll_div = 0;
|
||||
unsigned int x, r, n, m, i, j, mode;
|
||||
|
||||
@@ -1187,36 +1324,36 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
|
||||
if (dpll_div) {
|
||||
dpll_div = 11 - dpll_div;
|
||||
snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
|
||||
ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
|
||||
ADAU1373_PLL_CTRL6_DPLL_BYPASS,
|
||||
ADAU1373_PLL_CTRL6_DPLL_BYPASS);
|
||||
}
|
||||
|
||||
snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id),
|
||||
regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id),
|
||||
(source << 4) | dpll_div);
|
||||
snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
|
||||
snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
|
||||
snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
|
||||
snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
|
||||
snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id),
|
||||
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
|
||||
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
|
||||
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
|
||||
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
|
||||
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id),
|
||||
(r << 3) | (x << 1) | mode);
|
||||
|
||||
/* Set sysclk to pll_rate / 4 */
|
||||
snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adau1373_load_drc_settings(struct snd_soc_codec *codec,
|
||||
static void adau1373_load_drc_settings(struct adau1373 *adau1373,
|
||||
unsigned int nr, uint8_t *drc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ADAU1373_DRC_SIZE; ++i)
|
||||
snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]);
|
||||
regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]);
|
||||
}
|
||||
|
||||
static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
|
||||
@@ -1235,13 +1372,14 @@ static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
|
||||
|
||||
static int adau1373_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
struct adau1373_platform_data *pdata = codec->dev->platform_data;
|
||||
bool lineout_differential = false;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -1256,7 +1394,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < pdata->num_drc; ++i) {
|
||||
adau1373_load_drc_settings(codec, i,
|
||||
adau1373_load_drc_settings(adau1373, i,
|
||||
pdata->drc_setting[i]);
|
||||
}
|
||||
|
||||
@@ -1268,18 +1406,18 @@ static int adau1373_probe(struct snd_soc_codec *codec)
|
||||
if (pdata->input_differential[i])
|
||||
val |= BIT(i);
|
||||
}
|
||||
snd_soc_write(codec, ADAU1373_INPUT_MODE, val);
|
||||
regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val);
|
||||
|
||||
val = 0;
|
||||
if (pdata->lineout_differential)
|
||||
val |= ADAU1373_OUTPUT_CTRL_LDIFF;
|
||||
if (pdata->lineout_ground_sense)
|
||||
val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
|
||||
snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val);
|
||||
regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val);
|
||||
|
||||
lineout_differential = pdata->lineout_differential;
|
||||
|
||||
snd_soc_write(codec, ADAU1373_EP_CTRL,
|
||||
regmap_write(adau1373->regmap, ADAU1373_EP_CTRL,
|
||||
(pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
|
||||
(pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
|
||||
}
|
||||
@@ -1289,7 +1427,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
|
||||
ARRAY_SIZE(adau1373_lineout2_controls));
|
||||
}
|
||||
|
||||
snd_soc_write(codec, ADAU1373_ADC_CTRL,
|
||||
regmap_write(adau1373->regmap, ADAU1373_ADC_CTRL,
|
||||
ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT);
|
||||
|
||||
return 0;
|
||||
@@ -1298,17 +1436,19 @@ static int adau1373_probe(struct snd_soc_codec *codec)
|
||||
static int adau1373_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
|
||||
ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
|
||||
regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
|
||||
ADAU1373_PWDN_CTRL3_PWR_EN, 0);
|
||||
break;
|
||||
}
|
||||
@@ -1324,17 +1464,49 @@ static int adau1373_remove(struct snd_soc_codec *codec)
|
||||
|
||||
static int adau1373_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
regcache_cache_only(adau1373->regmap, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adau1373_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
regcache_cache_only(adau1373->regmap, false);
|
||||
adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
snd_soc_cache_sync(codec);
|
||||
regcache_sync(adau1373->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool adau1373_register_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case ADAU1373_SOFT_RESET:
|
||||
case ADAU1373_ADC_DAC_STATUS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config adau1373_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.reg_bits = 8,
|
||||
|
||||
.volatile_reg = adau1373_register_volatile,
|
||||
.max_register = ADAU1373_SOFT_RESET,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.reg_defaults = adau1373_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults),
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver adau1373_codec_driver = {
|
||||
.probe = adau1373_probe,
|
||||
.remove = adau1373_remove,
|
||||
@@ -1342,9 +1514,6 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
|
||||
.resume = adau1373_resume,
|
||||
.set_bias_level = adau1373_set_bias_level,
|
||||
.idle_bias_off = true,
|
||||
.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
|
||||
.reg_cache_default = adau1373_default_regs,
|
||||
.reg_word_size = sizeof(uint8_t),
|
||||
|
||||
.set_pll = adau1373_set_pll,
|
||||
|
||||
@@ -1366,6 +1535,13 @@ static int adau1373_i2c_probe(struct i2c_client *client,
|
||||
if (!adau1373)
|
||||
return -ENOMEM;
|
||||
|
||||
adau1373->regmap = devm_regmap_init_i2c(client,
|
||||
&adau1373_regmap_config);
|
||||
if (IS_ERR(adau1373->regmap))
|
||||
return PTR_ERR(adau1373->regmap);
|
||||
|
||||
regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00);
|
||||
|
||||
dev_set_drvdata(&client->dev, adau1373);
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver,
|
||||
|
@@ -115,22 +115,34 @@
|
||||
|
||||
#define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x))
|
||||
|
||||
static u8 adav80x_default_regs[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00,
|
||||
0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37,
|
||||
0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b,
|
||||
0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00,
|
||||
0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee,
|
||||
0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x52, 0x00,
|
||||
static struct reg_default adav80x_reg_defaults[] = {
|
||||
{ ADAV80X_PLAYBACK_CTRL, 0x01 },
|
||||
{ ADAV80X_AUX_IN_CTRL, 0x01 },
|
||||
{ ADAV80X_REC_CTRL, 0x02 },
|
||||
{ ADAV80X_AUX_OUT_CTRL, 0x01 },
|
||||
{ ADAV80X_DPATH_CTRL1, 0xc0 },
|
||||
{ ADAV80X_DPATH_CTRL2, 0x11 },
|
||||
{ ADAV80X_DAC_CTRL1, 0x00 },
|
||||
{ ADAV80X_DAC_CTRL2, 0x00 },
|
||||
{ ADAV80X_DAC_CTRL3, 0x00 },
|
||||
{ ADAV80X_DAC_L_VOL, 0xff },
|
||||
{ ADAV80X_DAC_R_VOL, 0xff },
|
||||
{ ADAV80X_PGA_L_VOL, 0x00 },
|
||||
{ ADAV80X_PGA_R_VOL, 0x00 },
|
||||
{ ADAV80X_ADC_CTRL1, 0x00 },
|
||||
{ ADAV80X_ADC_CTRL2, 0x00 },
|
||||
{ ADAV80X_ADC_L_VOL, 0xff },
|
||||
{ ADAV80X_ADC_R_VOL, 0xff },
|
||||
{ ADAV80X_PLL_CTRL1, 0x00 },
|
||||
{ ADAV80X_PLL_CTRL2, 0x00 },
|
||||
{ ADAV80X_ICLK_CTRL1, 0x00 },
|
||||
{ ADAV80X_ICLK_CTRL2, 0x00 },
|
||||
{ ADAV80X_PLL_CLK_SRC, 0x00 },
|
||||
{ ADAV80X_PLL_OUTE, 0x00 },
|
||||
};
|
||||
|
||||
struct adav80x {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regmap *regmap;
|
||||
|
||||
enum adav80x_clk_src clk_src;
|
||||
unsigned int sysclk;
|
||||
@@ -298,7 +310,7 @@ static int adav80x_set_deemph(struct snd_soc_codec *codec)
|
||||
val = ADAV80X_DAC_CTRL2_DEEMPH_NONE;
|
||||
}
|
||||
|
||||
return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
|
||||
return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
|
||||
ADAV80X_DAC_CTRL2_DEEMPH_MASK, val);
|
||||
}
|
||||
|
||||
@@ -394,10 +406,11 @@ static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
|
||||
regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
|
||||
ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER,
|
||||
capture);
|
||||
snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback);
|
||||
regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
|
||||
playback);
|
||||
|
||||
adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
|
||||
|
||||
@@ -407,6 +420,7 @@ static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
|
||||
unsigned int sample_rate)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int val;
|
||||
|
||||
if (sample_rate <= 48000)
|
||||
@@ -414,7 +428,7 @@ static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
|
||||
else
|
||||
val = ADAV80X_ADC_CTRL1_MODULATOR_64FS;
|
||||
|
||||
snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1,
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1,
|
||||
ADAV80X_ADC_CTRL1_MODULATOR_MASK, val);
|
||||
|
||||
return 0;
|
||||
@@ -423,6 +437,7 @@ static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
|
||||
static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
|
||||
unsigned int sample_rate)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int val;
|
||||
|
||||
if (sample_rate <= 48000)
|
||||
@@ -430,7 +445,7 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
|
||||
else
|
||||
val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS;
|
||||
|
||||
snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
|
||||
ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK,
|
||||
val);
|
||||
|
||||
@@ -440,6 +455,7 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
|
||||
static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
|
||||
struct snd_soc_dai *dai, snd_pcm_format_t format)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int val;
|
||||
|
||||
switch (format) {
|
||||
@@ -459,7 +475,7 @@ static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
|
||||
regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
|
||||
ADAV80X_CAPTURE_WORD_LEN_MASK, val);
|
||||
|
||||
return 0;
|
||||
@@ -491,7 +507,7 @@ static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1],
|
||||
regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
|
||||
ADAV80X_PLAYBACK_MODE_MASK, val);
|
||||
|
||||
return 0;
|
||||
@@ -554,8 +570,10 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||
ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id);
|
||||
iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id);
|
||||
|
||||
snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1);
|
||||
snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2);
|
||||
regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1,
|
||||
iclk_ctrl1);
|
||||
regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
|
||||
iclk_ctrl2);
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
}
|
||||
@@ -575,10 +593,12 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||
mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id);
|
||||
|
||||
if (freq == 0) {
|
||||
snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask);
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
|
||||
mask, mask);
|
||||
adav80x->sysclk_pd[clk_id] = true;
|
||||
} else {
|
||||
snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0);
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
|
||||
mask, 0);
|
||||
adav80x->sysclk_pd[clk_id] = false;
|
||||
}
|
||||
|
||||
@@ -650,9 +670,9 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV,
|
||||
pll_ctrl1);
|
||||
snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2,
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1,
|
||||
ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1);
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2,
|
||||
ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2);
|
||||
|
||||
if (source != adav80x->pll_src) {
|
||||
@@ -661,7 +681,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
else
|
||||
pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id);
|
||||
|
||||
snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC,
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC,
|
||||
ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src);
|
||||
|
||||
adav80x->pll_src = source;
|
||||
@@ -675,6 +695,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
static int adav80x_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int mask = ADAV80X_DAC_CTRL1_PD;
|
||||
|
||||
switch (level) {
|
||||
@@ -683,10 +704,12 @@ static int adav80x_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00);
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
|
||||
0x00);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask);
|
||||
regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
|
||||
mask);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -780,7 +803,7 @@ static int adav80x_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -791,23 +814,31 @@ static int adav80x_probe(struct snd_soc_codec *codec)
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
|
||||
|
||||
/* Power down S/PDIF receiver, since it is currently not supported */
|
||||
snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20);
|
||||
regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
|
||||
/* Disable DAC zero flag */
|
||||
snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6);
|
||||
regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6);
|
||||
|
||||
return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
}
|
||||
|
||||
static int adav80x_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
regcache_cache_only(adav80x->regmap, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adav80x_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
regcache_cache_only(adav80x->regmap, false);
|
||||
adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
codec->cache_sync = 1;
|
||||
snd_soc_cache_sync(codec);
|
||||
regcache_sync(adav80x->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -827,10 +858,6 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
|
||||
.set_pll = adav80x_set_pll,
|
||||
.set_sysclk = adav80x_set_sysclk,
|
||||
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_size = ARRAY_SIZE(adav80x_default_regs),
|
||||
.reg_cache_default = adav80x_default_regs,
|
||||
|
||||
.controls = adav80x_controls,
|
||||
.num_controls = ARRAY_SIZE(adav80x_controls),
|
||||
.dapm_widgets = adav80x_dapm_widgets,
|
||||
@@ -839,18 +866,21 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
|
||||
.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
|
||||
};
|
||||
|
||||
static int adav80x_bus_probe(struct device *dev,
|
||||
enum snd_soc_control_type control_type)
|
||||
static int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct adav80x *adav80x;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
|
||||
if (!adav80x)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
dev_set_drvdata(dev, adav80x);
|
||||
adav80x->control_type = control_type;
|
||||
adav80x->regmap = regmap;
|
||||
|
||||
ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
|
||||
adav80x_dais, ARRAY_SIZE(adav80x_dais));
|
||||
@@ -868,6 +898,19 @@ static int adav80x_bus_remove(struct device *dev)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static const struct regmap_config adav80x_spi_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.pad_bits = 1,
|
||||
.reg_bits = 7,
|
||||
.read_flag_mask = 0x01,
|
||||
|
||||
.max_register = ADAV80X_PLL_OUTE,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.reg_defaults = adav80x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
|
||||
};
|
||||
|
||||
static const struct spi_device_id adav80x_spi_id[] = {
|
||||
{ "adav801", 0 },
|
||||
{ }
|
||||
@@ -876,7 +919,8 @@ MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
|
||||
|
||||
static int adav80x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
|
||||
return adav80x_bus_probe(&spi->dev,
|
||||
devm_regmap_init_spi(spi, &adav80x_spi_regmap_config));
|
||||
}
|
||||
|
||||
static int adav80x_spi_remove(struct spi_device *spi)
|
||||
@@ -896,6 +940,18 @@ static struct spi_driver adav80x_spi_driver = {
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
static const struct regmap_config adav80x_i2c_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.pad_bits = 1,
|
||||
.reg_bits = 7,
|
||||
|
||||
.max_register = ADAV80X_PLL_OUTE,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.reg_defaults = adav80x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
|
||||
};
|
||||
|
||||
static const struct i2c_device_id adav80x_i2c_id[] = {
|
||||
{ "adav803", 0 },
|
||||
{ }
|
||||
@@ -905,7 +961,8 @@ MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
|
||||
static int adav80x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
|
||||
return adav80x_bus_probe(&client->dev,
|
||||
devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config));
|
||||
}
|
||||
|
||||
static int adav80x_i2c_remove(struct i2c_client *client)
|
||||
|
@@ -45,8 +45,6 @@
|
||||
#define AK4104_TX_TXE (1 << 0)
|
||||
#define AK4104_TX_V (1 << 1)
|
||||
|
||||
#define DRV_NAME "ak4104-codec"
|
||||
|
||||
struct ak4104_private {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
@@ -291,12 +289,19 @@ static const struct of_device_id ak4104_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ak4104_of_match);
|
||||
|
||||
static const struct spi_device_id ak4104_id_table[] = {
|
||||
{ "ak4104", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ak4104_id_table);
|
||||
|
||||
static struct spi_driver ak4104_spi_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.name = "ak4104",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ak4104_of_match,
|
||||
},
|
||||
.id_table = ak4104_id_table,
|
||||
.probe = ak4104_spi_probe,
|
||||
.remove = ak4104_spi_remove,
|
||||
};
|
||||
|
@@ -352,7 +352,6 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
*/
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
|
||||
|
||||
@@ -405,7 +404,6 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate);
|
||||
|
||||
|
@@ -1477,21 +1477,25 @@ static void arizona_enable_fll(struct arizona_fll *fll,
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
int ret;
|
||||
bool use_sync = false;
|
||||
|
||||
/*
|
||||
* If we have both REFCLK and SYNCCLK then enable both,
|
||||
* otherwise apply the SYNCCLK settings to REFCLK.
|
||||
*/
|
||||
if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
|
||||
if (fll->ref_src >= 0 && fll->ref_freq &&
|
||||
fll->ref_src != fll->sync_src) {
|
||||
regmap_update_bits(arizona->regmap, fll->base + 5,
|
||||
ARIZONA_FLL1_OUTDIV_MASK,
|
||||
ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
|
||||
|
||||
arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
|
||||
false);
|
||||
if (fll->sync_src >= 0)
|
||||
if (fll->sync_src >= 0) {
|
||||
arizona_apply_fll(arizona, fll->base + 0x10, sync,
|
||||
fll->sync_src, true);
|
||||
use_sync = true;
|
||||
}
|
||||
} else if (fll->sync_src >= 0) {
|
||||
regmap_update_bits(arizona->regmap, fll->base + 5,
|
||||
ARIZONA_FLL1_OUTDIV_MASK,
|
||||
@@ -1511,7 +1515,7 @@ static void arizona_enable_fll(struct arizona_fll *fll,
|
||||
* Increase the bandwidth if we're not using a low frequency
|
||||
* sync source.
|
||||
*/
|
||||
if (fll->sync_src >= 0 && fll->sync_freq > 100000)
|
||||
if (use_sync && fll->sync_freq > 100000)
|
||||
regmap_update_bits(arizona->regmap, fll->base + 0x17,
|
||||
ARIZONA_FLL1_SYNC_BW, 0);
|
||||
else
|
||||
@@ -1526,8 +1530,7 @@ static void arizona_enable_fll(struct arizona_fll *fll,
|
||||
|
||||
regmap_update_bits(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
|
||||
if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
|
||||
fll->ref_src != fll->sync_src)
|
||||
if (use_sync)
|
||||
regmap_update_bits(arizona->regmap, fll->base + 0x11,
|
||||
ARIZONA_FLL1_SYNC_ENA,
|
||||
ARIZONA_FLL1_SYNC_ENA);
|
||||
@@ -1561,10 +1564,12 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
if (fll->ref_src == source && fll->ref_freq == Fref)
|
||||
return 0;
|
||||
|
||||
if (fll->fout && Fref > 0) {
|
||||
ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (fll->fout) {
|
||||
if (Fref > 0) {
|
||||
ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fll->sync_src >= 0) {
|
||||
ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
|
||||
|
@@ -38,24 +38,6 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct davinci_vc *davinci_vc = codec->control_data;
|
||||
|
||||
return readl(davinci_vc->base + reg);
|
||||
}
|
||||
|
||||
static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct davinci_vc *davinci_vc = codec->control_data;
|
||||
|
||||
writel(value, davinci_vc->base + reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
|
||||
SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
|
||||
SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
|
||||
@@ -64,13 +46,15 @@ static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
|
||||
static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
|
||||
u8 reg;
|
||||
|
||||
if (mute)
|
||||
cq93vc_write(codec, DAVINCI_VC_REG09,
|
||||
reg | DAVINCI_VC_REG09_MUTE);
|
||||
reg = DAVINCI_VC_REG09_MUTE;
|
||||
else
|
||||
cq93vc_write(codec, DAVINCI_VC_REG09, reg);
|
||||
reg = 0;
|
||||
|
||||
snd_soc_update_bits(codec, DAVINCI_VC_REG09, DAVINCI_VC_REG09_MUTE,
|
||||
reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -79,7 +63,7 @@ static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct davinci_vc *davinci_vc = codec->control_data;
|
||||
struct davinci_vc *davinci_vc = codec->dev->platform_data;
|
||||
|
||||
switch (freq) {
|
||||
case 22579200:
|
||||
@@ -97,18 +81,18 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
cq93vc_write(codec, DAVINCI_VC_REG12,
|
||||
snd_soc_write(codec, DAVINCI_VC_REG12,
|
||||
DAVINCI_VC_REG12_POWER_ALL_ON);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
cq93vc_write(codec, DAVINCI_VC_REG12,
|
||||
snd_soc_write(codec, DAVINCI_VC_REG12,
|
||||
DAVINCI_VC_REG12_POWER_ALL_OFF);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* force all power off */
|
||||
cq93vc_write(codec, DAVINCI_VC_REG12,
|
||||
snd_soc_write(codec, DAVINCI_VC_REG12,
|
||||
DAVINCI_VC_REG12_POWER_ALL_OFF);
|
||||
break;
|
||||
}
|
||||
@@ -154,11 +138,9 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
|
||||
struct davinci_vc *davinci_vc = codec->dev->platform_data;
|
||||
|
||||
davinci_vc->cq93vc.codec = codec;
|
||||
codec->control_data = davinci_vc;
|
||||
codec->control_data = davinci_vc->regmap;
|
||||
|
||||
/* Set controls */
|
||||
snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
|
||||
ARRAY_SIZE(cq93vc_snd_controls));
|
||||
snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
|
||||
|
||||
/* Off, with power on */
|
||||
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
@@ -174,12 +156,12 @@ static int cq93vc_remove(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
|
||||
.read = cq93vc_read,
|
||||
.write = cq93vc_write,
|
||||
.set_bias_level = cq93vc_set_bias_level,
|
||||
.probe = cq93vc_probe,
|
||||
.remove = cq93vc_remove,
|
||||
.resume = cq93vc_resume,
|
||||
.controls = cq93vc_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cq93vc_snd_controls),
|
||||
};
|
||||
|
||||
static int cq93vc_platform_probe(struct platform_device *pdev)
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -28,6 +29,7 @@
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/cs42l73.h>
|
||||
#include "cs42l73.h"
|
||||
|
||||
struct sp_config {
|
||||
@@ -35,6 +37,7 @@ struct sp_config {
|
||||
u32 srate;
|
||||
};
|
||||
struct cs42l73_private {
|
||||
struct cs42l73_platform_data pdata;
|
||||
struct sp_config config[3];
|
||||
struct regmap *regmap;
|
||||
u32 sysclk;
|
||||
@@ -310,15 +313,6 @@ static const struct soc_enum ng_delay_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
|
||||
ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
|
||||
|
||||
static const char * const charge_pump_freq_text[] = {
|
||||
"0", "1", "2", "3", "4",
|
||||
"5", "6", "7", "8", "9",
|
||||
"10", "11", "12", "13", "14", "15" };
|
||||
|
||||
static const struct soc_enum charge_pump_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
|
||||
ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
|
||||
|
||||
static const char * const cs42l73_mono_mix_texts[] = {
|
||||
"Left", "Right", "Mono Mix"};
|
||||
|
||||
@@ -511,8 +505,6 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
|
||||
SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
|
||||
SOC_ENUM("NG Delay", ng_delay_enum),
|
||||
|
||||
SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
|
||||
|
||||
SOC_DOUBLE_R_TLV("XSP-IP Volume",
|
||||
CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
|
||||
attn_tlv),
|
||||
@@ -1055,11 +1047,11 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
mmcc |= MS_MASTER;
|
||||
mmcc |= CS42L73_MS_MASTER;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
mmcc &= ~MS_MASTER;
|
||||
mmcc &= ~CS42L73_MS_MASTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1071,11 +1063,11 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
|
||||
switch (format) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
spc &= ~SPDIF_PCM;
|
||||
spc &= ~CS42L73_SPDIF_PCM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
if (mmcc & MS_MASTER) {
|
||||
if (mmcc & CS42L73_MS_MASTER) {
|
||||
dev_err(codec->dev,
|
||||
"PCM format in slave mode only\n");
|
||||
return -EINVAL;
|
||||
@@ -1085,25 +1077,25 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
"PCM format is not supported on ASP port\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
spc |= SPDIF_PCM;
|
||||
spc |= CS42L73_SPDIF_PCM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (spc & SPDIF_PCM) {
|
||||
if (spc & CS42L73_SPDIF_PCM) {
|
||||
/* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
|
||||
spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
|
||||
spc &= ~(CS42L73_PCM_MODE_MASK | CS42L73_PCM_BIT_ORDER);
|
||||
switch (format) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
if (inv == SND_SOC_DAIFMT_IB_IF)
|
||||
spc |= PCM_MODE0;
|
||||
spc |= CS42L73_PCM_MODE0;
|
||||
if (inv == SND_SOC_DAIFMT_IB_NF)
|
||||
spc |= PCM_MODE1;
|
||||
spc |= CS42L73_PCM_MODE1;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
if (inv == SND_SOC_DAIFMT_IB_IF)
|
||||
spc |= PCM_MODE1;
|
||||
spc |= CS42L73_PCM_MODE1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -1163,7 +1155,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
int mclk_coeff;
|
||||
int srate = params_rate(params);
|
||||
|
||||
if (priv->config[id].mmcc & MS_MASTER) {
|
||||
if (priv->config[id].mmcc & CS42L73_MS_MASTER) {
|
||||
/* CS42L73 Master */
|
||||
/* MCLK -> srate */
|
||||
mclk_coeff =
|
||||
@@ -1182,13 +1174,13 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
priv->config[id].spc &= 0xFC;
|
||||
/* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */
|
||||
if (priv->mclk >= 6400000)
|
||||
priv->config[id].spc |= MCK_SCLK_64FS;
|
||||
priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
|
||||
else
|
||||
priv->config[id].spc |= MCK_SCLK_MCLK;
|
||||
priv->config[id].spc |= CS42L73_MCK_SCLK_MCLK;
|
||||
} else {
|
||||
/* CS42L73 Slave */
|
||||
priv->config[id].spc &= 0xFC;
|
||||
priv->config[id].spc |= MCK_SCLK_64FS;
|
||||
priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
|
||||
}
|
||||
/* Update ASRCs */
|
||||
priv->config[id].srate = srate;
|
||||
@@ -1208,8 +1200,8 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
|
||||
snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 0);
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 0);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
@@ -1220,11 +1212,11 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_cache_only(cs42l73->regmap, false);
|
||||
regcache_sync(cs42l73->regmap);
|
||||
}
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
|
||||
snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
|
||||
if (cs42l73->shutdwn_delay > 0) {
|
||||
mdelay(cs42l73->shutdwn_delay);
|
||||
cs42l73->shutdwn_delay = 0;
|
||||
@@ -1233,7 +1225,7 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
|
||||
* down.
|
||||
*/
|
||||
}
|
||||
snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
|
||||
snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
@@ -1367,11 +1359,16 @@ static int cs42l73_probe(struct snd_soc_codec *codec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
regcache_cache_only(cs42l73->regmap, true);
|
||||
|
||||
cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */
|
||||
/* Set Charge Pump Frequency */
|
||||
if (cs42l73->pdata.chgfreq)
|
||||
snd_soc_update_bits(codec, CS42L73_CPFCHC,
|
||||
CS42L73_CHARGEPUMP_MASK,
|
||||
cs42l73->pdata.chgfreq << 4);
|
||||
|
||||
/* MCLK1 as master clk */
|
||||
cs42l73->mclksel = CS42L73_CLKID_MCLK1;
|
||||
cs42l73->mclk = 0;
|
||||
|
||||
return ret;
|
||||
@@ -1415,9 +1412,11 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs42l73_private *cs42l73;
|
||||
struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
|
||||
int ret;
|
||||
unsigned int devid = 0;
|
||||
unsigned int reg;
|
||||
u32 val32;
|
||||
|
||||
cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
|
||||
GFP_KERNEL);
|
||||
@@ -1426,14 +1425,49 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs42l73);
|
||||
|
||||
cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
|
||||
if (IS_ERR(cs42l73->regmap)) {
|
||||
ret = PTR_ERR(cs42l73->regmap);
|
||||
dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
cs42l73->pdata = *pdata;
|
||||
} else {
|
||||
pdata = devm_kzalloc(&i2c_client->dev,
|
||||
sizeof(struct cs42l73_platform_data),
|
||||
GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(&i2c_client->dev, "could not allocate pdata\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (i2c_client->dev.of_node) {
|
||||
if (of_property_read_u32(i2c_client->dev.of_node,
|
||||
"chgfreq", &val32) >= 0)
|
||||
pdata->chgfreq = val32;
|
||||
}
|
||||
pdata->reset_gpio = of_get_named_gpio(i2c_client->dev.of_node,
|
||||
"reset-gpio", 0);
|
||||
cs42l73->pdata = *pdata;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs42l73);
|
||||
|
||||
if (cs42l73->pdata.reset_gpio) {
|
||||
ret = gpio_request_one(cs42l73->pdata.reset_gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "CS42L73 /RST");
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
|
||||
cs42l73->pdata.reset_gpio, ret);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
|
||||
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
|
||||
}
|
||||
|
||||
regcache_cache_bypass(cs42l73->regmap, true);
|
||||
|
||||
/* initialize codec */
|
||||
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®);
|
||||
devid = (reg & 0xFF) << 12;
|
||||
@@ -1444,7 +1478,6 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
|
||||
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, ®);
|
||||
devid |= (reg & 0xF0) >> 4;
|
||||
|
||||
|
||||
if (devid != CS42L73_DEVID) {
|
||||
ret = -ENODEV;
|
||||
dev_err(&i2c_client->dev,
|
||||
@@ -1462,7 +1495,7 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
|
||||
dev_info(&i2c_client->dev,
|
||||
"Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
|
||||
|
||||
regcache_cache_only(cs42l73->regmap, true);
|
||||
regcache_cache_bypass(cs42l73->regmap, false);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_dev_cs42l73, cs42l73_dai,
|
||||
@@ -1478,6 +1511,12 @@ static int cs42l73_i2c_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cs42l73_of_match[] = {
|
||||
{ .compatible = "cirrus,cs42l73", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs42l73_of_match);
|
||||
|
||||
static const struct i2c_device_id cs42l73_id[] = {
|
||||
{"cs42l73", 0},
|
||||
{}
|
||||
@@ -1489,6 +1528,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l73",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cs42l73_of_match,
|
||||
},
|
||||
.id_table = cs42l73_id,
|
||||
.probe = cs42l73_i2c_probe,
|
||||
|
@@ -128,59 +128,60 @@
|
||||
/* Bitfield Definitions */
|
||||
|
||||
/* CS42L73_PWRCTL1 */
|
||||
#define PDN_ADCB (1 << 7)
|
||||
#define PDN_DMICB (1 << 6)
|
||||
#define PDN_ADCA (1 << 5)
|
||||
#define PDN_DMICA (1 << 4)
|
||||
#define PDN_LDO (1 << 2)
|
||||
#define DISCHG_FILT (1 << 1)
|
||||
#define PDN (1 << 0)
|
||||
#define CS42L73_PDN_ADCB (1 << 7)
|
||||
#define CS42L73_PDN_DMICB (1 << 6)
|
||||
#define CS42L73_PDN_ADCA (1 << 5)
|
||||
#define CS42L73_PDN_DMICA (1 << 4)
|
||||
#define CS42L73_PDN_LDO (1 << 2)
|
||||
#define CS42L73_DISCHG_FILT (1 << 1)
|
||||
#define CS42L73_PDN (1 << 0)
|
||||
|
||||
/* CS42L73_PWRCTL2 */
|
||||
#define PDN_MIC2_BIAS (1 << 7)
|
||||
#define PDN_MIC1_BIAS (1 << 6)
|
||||
#define PDN_VSP (1 << 4)
|
||||
#define PDN_ASP_SDOUT (1 << 3)
|
||||
#define PDN_ASP_SDIN (1 << 2)
|
||||
#define PDN_XSP_SDOUT (1 << 1)
|
||||
#define PDN_XSP_SDIN (1 << 0)
|
||||
#define CS42L73_PDN_MIC2_BIAS (1 << 7)
|
||||
#define CS42L73_PDN_MIC1_BIAS (1 << 6)
|
||||
#define CS42L73_PDN_VSP (1 << 4)
|
||||
#define CS42L73_PDN_ASP_SDOUT (1 << 3)
|
||||
#define CS42L73_PDN_ASP_SDIN (1 << 2)
|
||||
#define CS42L73_PDN_XSP_SDOUT (1 << 1)
|
||||
#define CS42L73_PDN_XSP_SDIN (1 << 0)
|
||||
|
||||
/* CS42L73_PWRCTL3 */
|
||||
#define PDN_THMS (1 << 5)
|
||||
#define PDN_SPKLO (1 << 4)
|
||||
#define PDN_EAR (1 << 3)
|
||||
#define PDN_SPK (1 << 2)
|
||||
#define PDN_LO (1 << 1)
|
||||
#define PDN_HP (1 << 0)
|
||||
#define CS42L73_PDN_THMS (1 << 5)
|
||||
#define CS42L73_PDN_SPKLO (1 << 4)
|
||||
#define CS42L73_PDN_EAR (1 << 3)
|
||||
#define CS42L73_PDN_SPK (1 << 2)
|
||||
#define CS42L73_PDN_LO (1 << 1)
|
||||
#define CS42L73_PDN_HP (1 << 0)
|
||||
|
||||
/* Thermal Overload Detect. Requires interrupt ... */
|
||||
#define THMOVLD_150C 0
|
||||
#define THMOVLD_132C 1
|
||||
#define THMOVLD_115C 2
|
||||
#define THMOVLD_098C 3
|
||||
#define CS42L73_THMOVLD_150C 0
|
||||
#define CS42L73_THMOVLD_132C 1
|
||||
#define CS42L73_THMOVLD_115C 2
|
||||
#define CS42L73_THMOVLD_098C 3
|
||||
|
||||
#define CS42L73_CHARGEPUMP_MASK (0xF0)
|
||||
|
||||
/* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */
|
||||
#define SP_3ST (1 << 7)
|
||||
#define SPDIF_I2S (0 << 6)
|
||||
#define SPDIF_PCM (1 << 6)
|
||||
#define PCM_MODE0 (0 << 4)
|
||||
#define PCM_MODE1 (1 << 4)
|
||||
#define PCM_MODE2 (2 << 4)
|
||||
#define PCM_MODE_MASK (3 << 4)
|
||||
#define PCM_BIT_ORDER (1 << 3)
|
||||
#define MCK_SCLK_64FS (0 << 0)
|
||||
#define MCK_SCLK_MCLK (2 << 0)
|
||||
#define MCK_SCLK_PREMCLK (3 << 0)
|
||||
#define CS42L73_SP_3ST (1 << 7)
|
||||
#define CS42L73_SPDIF_I2S (0 << 6)
|
||||
#define CS42L73_SPDIF_PCM (1 << 6)
|
||||
#define CS42L73_PCM_MODE0 (0 << 4)
|
||||
#define CS42L73_PCM_MODE1 (1 << 4)
|
||||
#define CS42L73_PCM_MODE2 (2 << 4)
|
||||
#define CS42L73_PCM_MODE_MASK (3 << 4)
|
||||
#define CS42L73_PCM_BIT_ORDER (1 << 3)
|
||||
#define CS42L73_MCK_SCLK_64FS (0 << 0)
|
||||
#define CS42L73_MCK_SCLK_MCLK (2 << 0)
|
||||
#define CS42L73_MCK_SCLK_PREMCLK (3 << 0)
|
||||
|
||||
/* CS42L73_xSPMMCC */
|
||||
#define MS_MASTER (1 << 7)
|
||||
#define CS42L73_MS_MASTER (1 << 7)
|
||||
|
||||
|
||||
/* CS42L73_DMMCC */
|
||||
#define MCLKDIS (1 << 0)
|
||||
#define MCLKSEL_MCLK2 (1 << 4)
|
||||
#define MCLKSEL_MCLK1 (0 << 4)
|
||||
#define CS42L73_MCLKDIS (1 << 0)
|
||||
#define CS42L73_MCLKSEL_MCLK2 (1 << 4)
|
||||
#define CS42L73_MCLKSEL_MCLK1 (0 << 4)
|
||||
|
||||
/* CS42L73 MCLK derived from MCLK1 or MCLK2 */
|
||||
#define CS42L73_CLKID_MCLK1 0
|
||||
@@ -194,28 +195,26 @@
|
||||
#define CS42L73_VSP 2
|
||||
|
||||
/* IS1, IM1 */
|
||||
#define MIC2_SDET (1 << 6)
|
||||
#define THMOVLD (1 << 4)
|
||||
#define DIGMIXOVFL (1 << 3)
|
||||
#define IPBOVFL (1 << 1)
|
||||
#define IPAOVFL (1 << 0)
|
||||
#define CS42L73_MIC2_SDET (1 << 6)
|
||||
#define CS42L73_THMOVLD (1 << 4)
|
||||
#define CS42L73_DIGMIXOVFL (1 << 3)
|
||||
#define CS42L73_IPBOVFL (1 << 1)
|
||||
#define CS42L73_IPAOVFL (1 << 0)
|
||||
|
||||
/* Analog Softramp */
|
||||
#define ANLGOSFT (1 << 0)
|
||||
#define CS42L73_ANLGOSFT (1 << 0)
|
||||
|
||||
/* HP A/B Analog Mute */
|
||||
#define HPA_MUTE (1 << 7)
|
||||
#define CS42L73_HPA_MUTE (1 << 7)
|
||||
/* LO A/B Analog Mute */
|
||||
#define LOA_MUTE (1 << 7)
|
||||
#define CS42L73_LOA_MUTE (1 << 7)
|
||||
/* Digital Mute */
|
||||
#define HLAD_MUTE (1 << 0)
|
||||
#define HLBD_MUTE (1 << 1)
|
||||
#define SPKD_MUTE (1 << 2)
|
||||
#define ESLD_MUTE (1 << 3)
|
||||
#define CS42L73_HLAD_MUTE (1 << 0)
|
||||
#define CS42L73_HLBD_MUTE (1 << 1)
|
||||
#define CS42L73_SPKD_MUTE (1 << 2)
|
||||
#define CS42L73_ESLD_MUTE (1 << 3)
|
||||
|
||||
/* Misc defines for codec */
|
||||
#define CS42L73_RESET_GPIO 143
|
||||
|
||||
#define CS42L73_DEVID 0x00042A73
|
||||
#define CS42L73_MCLKX_MIN 5644800
|
||||
#define CS42L73_MCLKX_MAX 38400000
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@@ -38,294 +39,223 @@ struct max98088_cdata {
|
||||
};
|
||||
|
||||
struct max98088_priv {
|
||||
enum max98088_type devtype;
|
||||
struct max98088_pdata *pdata;
|
||||
unsigned int sysclk;
|
||||
struct max98088_cdata dai[2];
|
||||
int eq_textcnt;
|
||||
const char **eq_texts;
|
||||
struct soc_enum eq_enum;
|
||||
u8 ina_state;
|
||||
u8 inb_state;
|
||||
unsigned int ex_mode;
|
||||
unsigned int digmic;
|
||||
unsigned int mic1pre;
|
||||
unsigned int mic2pre;
|
||||
unsigned int extmic_mode;
|
||||
struct regmap *regmap;
|
||||
enum max98088_type devtype;
|
||||
struct max98088_pdata *pdata;
|
||||
unsigned int sysclk;
|
||||
struct max98088_cdata dai[2];
|
||||
int eq_textcnt;
|
||||
const char **eq_texts;
|
||||
struct soc_enum eq_enum;
|
||||
u8 ina_state;
|
||||
u8 inb_state;
|
||||
unsigned int ex_mode;
|
||||
unsigned int digmic;
|
||||
unsigned int mic1pre;
|
||||
unsigned int mic2pre;
|
||||
unsigned int extmic_mode;
|
||||
};
|
||||
|
||||
static const u8 max98088_reg[M98088_REG_CNT] = {
|
||||
0x00, /* 00 IRQ status */
|
||||
0x00, /* 01 MIC status */
|
||||
0x00, /* 02 jack status */
|
||||
0x00, /* 03 battery voltage */
|
||||
0x00, /* 04 */
|
||||
0x00, /* 05 */
|
||||
0x00, /* 06 */
|
||||
0x00, /* 07 */
|
||||
0x00, /* 08 */
|
||||
0x00, /* 09 */
|
||||
0x00, /* 0A */
|
||||
0x00, /* 0B */
|
||||
0x00, /* 0C */
|
||||
0x00, /* 0D */
|
||||
0x00, /* 0E */
|
||||
0x00, /* 0F interrupt enable */
|
||||
static const struct reg_default max98088_reg[] = {
|
||||
{ 0xf, 0x00 }, /* 0F interrupt enable */
|
||||
|
||||
0x00, /* 10 master clock */
|
||||
0x00, /* 11 DAI1 clock mode */
|
||||
0x00, /* 12 DAI1 clock control */
|
||||
0x00, /* 13 DAI1 clock control */
|
||||
0x00, /* 14 DAI1 format */
|
||||
0x00, /* 15 DAI1 clock */
|
||||
0x00, /* 16 DAI1 config */
|
||||
0x00, /* 17 DAI1 TDM */
|
||||
0x00, /* 18 DAI1 filters */
|
||||
0x00, /* 19 DAI2 clock mode */
|
||||
0x00, /* 1A DAI2 clock control */
|
||||
0x00, /* 1B DAI2 clock control */
|
||||
0x00, /* 1C DAI2 format */
|
||||
0x00, /* 1D DAI2 clock */
|
||||
0x00, /* 1E DAI2 config */
|
||||
0x00, /* 1F DAI2 TDM */
|
||||
{ 0x10, 0x00 }, /* 10 master clock */
|
||||
{ 0x11, 0x00 }, /* 11 DAI1 clock mode */
|
||||
{ 0x12, 0x00 }, /* 12 DAI1 clock control */
|
||||
{ 0x13, 0x00 }, /* 13 DAI1 clock control */
|
||||
{ 0x14, 0x00 }, /* 14 DAI1 format */
|
||||
{ 0x15, 0x00 }, /* 15 DAI1 clock */
|
||||
{ 0x16, 0x00 }, /* 16 DAI1 config */
|
||||
{ 0x17, 0x00 }, /* 17 DAI1 TDM */
|
||||
{ 0x18, 0x00 }, /* 18 DAI1 filters */
|
||||
{ 0x19, 0x00 }, /* 19 DAI2 clock mode */
|
||||
{ 0x1a, 0x00 }, /* 1A DAI2 clock control */
|
||||
{ 0x1b, 0x00 }, /* 1B DAI2 clock control */
|
||||
{ 0x1c, 0x00 }, /* 1C DAI2 format */
|
||||
{ 0x1d, 0x00 }, /* 1D DAI2 clock */
|
||||
{ 0x1e, 0x00 }, /* 1E DAI2 config */
|
||||
{ 0x1f, 0x00 }, /* 1F DAI2 TDM */
|
||||
|
||||
0x00, /* 20 DAI2 filters */
|
||||
0x00, /* 21 data config */
|
||||
0x00, /* 22 DAC mixer */
|
||||
0x00, /* 23 left ADC mixer */
|
||||
0x00, /* 24 right ADC mixer */
|
||||
0x00, /* 25 left HP mixer */
|
||||
0x00, /* 26 right HP mixer */
|
||||
0x00, /* 27 HP control */
|
||||
0x00, /* 28 left REC mixer */
|
||||
0x00, /* 29 right REC mixer */
|
||||
0x00, /* 2A REC control */
|
||||
0x00, /* 2B left SPK mixer */
|
||||
0x00, /* 2C right SPK mixer */
|
||||
0x00, /* 2D SPK control */
|
||||
0x00, /* 2E sidetone */
|
||||
0x00, /* 2F DAI1 playback level */
|
||||
{ 0x20, 0x00 }, /* 20 DAI2 filters */
|
||||
{ 0x21, 0x00 }, /* 21 data config */
|
||||
{ 0x22, 0x00 }, /* 22 DAC mixer */
|
||||
{ 0x23, 0x00 }, /* 23 left ADC mixer */
|
||||
{ 0x24, 0x00 }, /* 24 right ADC mixer */
|
||||
{ 0x25, 0x00 }, /* 25 left HP mixer */
|
||||
{ 0x26, 0x00 }, /* 26 right HP mixer */
|
||||
{ 0x27, 0x00 }, /* 27 HP control */
|
||||
{ 0x28, 0x00 }, /* 28 left REC mixer */
|
||||
{ 0x29, 0x00 }, /* 29 right REC mixer */
|
||||
{ 0x2a, 0x00 }, /* 2A REC control */
|
||||
{ 0x2b, 0x00 }, /* 2B left SPK mixer */
|
||||
{ 0x2c, 0x00 }, /* 2C right SPK mixer */
|
||||
{ 0x2d, 0x00 }, /* 2D SPK control */
|
||||
{ 0x2e, 0x00 }, /* 2E sidetone */
|
||||
{ 0x2f, 0x00 }, /* 2F DAI1 playback level */
|
||||
|
||||
0x00, /* 30 DAI1 playback level */
|
||||
0x00, /* 31 DAI2 playback level */
|
||||
0x00, /* 32 DAI2 playbakc level */
|
||||
0x00, /* 33 left ADC level */
|
||||
0x00, /* 34 right ADC level */
|
||||
0x00, /* 35 MIC1 level */
|
||||
0x00, /* 36 MIC2 level */
|
||||
0x00, /* 37 INA level */
|
||||
0x00, /* 38 INB level */
|
||||
0x00, /* 39 left HP volume */
|
||||
0x00, /* 3A right HP volume */
|
||||
0x00, /* 3B left REC volume */
|
||||
0x00, /* 3C right REC volume */
|
||||
0x00, /* 3D left SPK volume */
|
||||
0x00, /* 3E right SPK volume */
|
||||
0x00, /* 3F MIC config */
|
||||
{ 0x30, 0x00 }, /* 30 DAI1 playback level */
|
||||
{ 0x31, 0x00 }, /* 31 DAI2 playback level */
|
||||
{ 0x32, 0x00 }, /* 32 DAI2 playbakc level */
|
||||
{ 0x33, 0x00 }, /* 33 left ADC level */
|
||||
{ 0x34, 0x00 }, /* 34 right ADC level */
|
||||
{ 0x35, 0x00 }, /* 35 MIC1 level */
|
||||
{ 0x36, 0x00 }, /* 36 MIC2 level */
|
||||
{ 0x37, 0x00 }, /* 37 INA level */
|
||||
{ 0x38, 0x00 }, /* 38 INB level */
|
||||
{ 0x39, 0x00 }, /* 39 left HP volume */
|
||||
{ 0x3a, 0x00 }, /* 3A right HP volume */
|
||||
{ 0x3b, 0x00 }, /* 3B left REC volume */
|
||||
{ 0x3c, 0x00 }, /* 3C right REC volume */
|
||||
{ 0x3d, 0x00 }, /* 3D left SPK volume */
|
||||
{ 0x3e, 0x00 }, /* 3E right SPK volume */
|
||||
{ 0x3f, 0x00 }, /* 3F MIC config */
|
||||
|
||||
0x00, /* 40 MIC threshold */
|
||||
0x00, /* 41 excursion limiter filter */
|
||||
0x00, /* 42 excursion limiter threshold */
|
||||
0x00, /* 43 ALC */
|
||||
0x00, /* 44 power limiter threshold */
|
||||
0x00, /* 45 power limiter config */
|
||||
0x00, /* 46 distortion limiter config */
|
||||
0x00, /* 47 audio input */
|
||||
0x00, /* 48 microphone */
|
||||
0x00, /* 49 level control */
|
||||
0x00, /* 4A bypass switches */
|
||||
0x00, /* 4B jack detect */
|
||||
0x00, /* 4C input enable */
|
||||
0x00, /* 4D output enable */
|
||||
0xF0, /* 4E bias control */
|
||||
0x00, /* 4F DAC power */
|
||||
{ 0x40, 0x00 }, /* 40 MIC threshold */
|
||||
{ 0x41, 0x00 }, /* 41 excursion limiter filter */
|
||||
{ 0x42, 0x00 }, /* 42 excursion limiter threshold */
|
||||
{ 0x43, 0x00 }, /* 43 ALC */
|
||||
{ 0x44, 0x00 }, /* 44 power limiter threshold */
|
||||
{ 0x45, 0x00 }, /* 45 power limiter config */
|
||||
{ 0x46, 0x00 }, /* 46 distortion limiter config */
|
||||
{ 0x47, 0x00 }, /* 47 audio input */
|
||||
{ 0x48, 0x00 }, /* 48 microphone */
|
||||
{ 0x49, 0x00 }, /* 49 level control */
|
||||
{ 0x4a, 0x00 }, /* 4A bypass switches */
|
||||
{ 0x4b, 0x00 }, /* 4B jack detect */
|
||||
{ 0x4c, 0x00 }, /* 4C input enable */
|
||||
{ 0x4d, 0x00 }, /* 4D output enable */
|
||||
{ 0x4e, 0xF0 }, /* 4E bias control */
|
||||
{ 0x4f, 0x00 }, /* 4F DAC power */
|
||||
|
||||
0x0F, /* 50 DAC power */
|
||||
0x00, /* 51 system */
|
||||
0x00, /* 52 DAI1 EQ1 */
|
||||
0x00, /* 53 DAI1 EQ1 */
|
||||
0x00, /* 54 DAI1 EQ1 */
|
||||
0x00, /* 55 DAI1 EQ1 */
|
||||
0x00, /* 56 DAI1 EQ1 */
|
||||
0x00, /* 57 DAI1 EQ1 */
|
||||
0x00, /* 58 DAI1 EQ1 */
|
||||
0x00, /* 59 DAI1 EQ1 */
|
||||
0x00, /* 5A DAI1 EQ1 */
|
||||
0x00, /* 5B DAI1 EQ1 */
|
||||
0x00, /* 5C DAI1 EQ2 */
|
||||
0x00, /* 5D DAI1 EQ2 */
|
||||
0x00, /* 5E DAI1 EQ2 */
|
||||
0x00, /* 5F DAI1 EQ2 */
|
||||
{ 0x50, 0x0F }, /* 50 DAC power */
|
||||
{ 0x51, 0x00 }, /* 51 system */
|
||||
{ 0x52, 0x00 }, /* 52 DAI1 EQ1 */
|
||||
{ 0x53, 0x00 }, /* 53 DAI1 EQ1 */
|
||||
{ 0x54, 0x00 }, /* 54 DAI1 EQ1 */
|
||||
{ 0x55, 0x00 }, /* 55 DAI1 EQ1 */
|
||||
{ 0x56, 0x00 }, /* 56 DAI1 EQ1 */
|
||||
{ 0x57, 0x00 }, /* 57 DAI1 EQ1 */
|
||||
{ 0x58, 0x00 }, /* 58 DAI1 EQ1 */
|
||||
{ 0x59, 0x00 }, /* 59 DAI1 EQ1 */
|
||||
{ 0x5a, 0x00 }, /* 5A DAI1 EQ1 */
|
||||
{ 0x5b, 0x00 }, /* 5B DAI1 EQ1 */
|
||||
{ 0x5c, 0x00 }, /* 5C DAI1 EQ2 */
|
||||
{ 0x5d, 0x00 }, /* 5D DAI1 EQ2 */
|
||||
{ 0x5e, 0x00 }, /* 5E DAI1 EQ2 */
|
||||
{ 0x5f, 0x00 }, /* 5F DAI1 EQ2 */
|
||||
|
||||
0x00, /* 60 DAI1 EQ2 */
|
||||
0x00, /* 61 DAI1 EQ2 */
|
||||
0x00, /* 62 DAI1 EQ2 */
|
||||
0x00, /* 63 DAI1 EQ2 */
|
||||
0x00, /* 64 DAI1 EQ2 */
|
||||
0x00, /* 65 DAI1 EQ2 */
|
||||
0x00, /* 66 DAI1 EQ3 */
|
||||
0x00, /* 67 DAI1 EQ3 */
|
||||
0x00, /* 68 DAI1 EQ3 */
|
||||
0x00, /* 69 DAI1 EQ3 */
|
||||
0x00, /* 6A DAI1 EQ3 */
|
||||
0x00, /* 6B DAI1 EQ3 */
|
||||
0x00, /* 6C DAI1 EQ3 */
|
||||
0x00, /* 6D DAI1 EQ3 */
|
||||
0x00, /* 6E DAI1 EQ3 */
|
||||
0x00, /* 6F DAI1 EQ3 */
|
||||
{ 0x60, 0x00 }, /* 60 DAI1 EQ2 */
|
||||
{ 0x61, 0x00 }, /* 61 DAI1 EQ2 */
|
||||
{ 0x62, 0x00 }, /* 62 DAI1 EQ2 */
|
||||
{ 0x63, 0x00 }, /* 63 DAI1 EQ2 */
|
||||
{ 0x64, 0x00 }, /* 64 DAI1 EQ2 */
|
||||
{ 0x65, 0x00 }, /* 65 DAI1 EQ2 */
|
||||
{ 0x66, 0x00 }, /* 66 DAI1 EQ3 */
|
||||
{ 0x67, 0x00 }, /* 67 DAI1 EQ3 */
|
||||
{ 0x68, 0x00 }, /* 68 DAI1 EQ3 */
|
||||
{ 0x69, 0x00 }, /* 69 DAI1 EQ3 */
|
||||
{ 0x6a, 0x00 }, /* 6A DAI1 EQ3 */
|
||||
{ 0x6b, 0x00 }, /* 6B DAI1 EQ3 */
|
||||
{ 0x6c, 0x00 }, /* 6C DAI1 EQ3 */
|
||||
{ 0x6d, 0x00 }, /* 6D DAI1 EQ3 */
|
||||
{ 0x6e, 0x00 }, /* 6E DAI1 EQ3 */
|
||||
{ 0x6f, 0x00 }, /* 6F DAI1 EQ3 */
|
||||
|
||||
0x00, /* 70 DAI1 EQ4 */
|
||||
0x00, /* 71 DAI1 EQ4 */
|
||||
0x00, /* 72 DAI1 EQ4 */
|
||||
0x00, /* 73 DAI1 EQ4 */
|
||||
0x00, /* 74 DAI1 EQ4 */
|
||||
0x00, /* 75 DAI1 EQ4 */
|
||||
0x00, /* 76 DAI1 EQ4 */
|
||||
0x00, /* 77 DAI1 EQ4 */
|
||||
0x00, /* 78 DAI1 EQ4 */
|
||||
0x00, /* 79 DAI1 EQ4 */
|
||||
0x00, /* 7A DAI1 EQ5 */
|
||||
0x00, /* 7B DAI1 EQ5 */
|
||||
0x00, /* 7C DAI1 EQ5 */
|
||||
0x00, /* 7D DAI1 EQ5 */
|
||||
0x00, /* 7E DAI1 EQ5 */
|
||||
0x00, /* 7F DAI1 EQ5 */
|
||||
{ 0x70, 0x00 }, /* 70 DAI1 EQ4 */
|
||||
{ 0x71, 0x00 }, /* 71 DAI1 EQ4 */
|
||||
{ 0x72, 0x00 }, /* 72 DAI1 EQ4 */
|
||||
{ 0x73, 0x00 }, /* 73 DAI1 EQ4 */
|
||||
{ 0x74, 0x00 }, /* 74 DAI1 EQ4 */
|
||||
{ 0x75, 0x00 }, /* 75 DAI1 EQ4 */
|
||||
{ 0x76, 0x00 }, /* 76 DAI1 EQ4 */
|
||||
{ 0x77, 0x00 }, /* 77 DAI1 EQ4 */
|
||||
{ 0x78, 0x00 }, /* 78 DAI1 EQ4 */
|
||||
{ 0x79, 0x00 }, /* 79 DAI1 EQ4 */
|
||||
{ 0x7a, 0x00 }, /* 7A DAI1 EQ5 */
|
||||
{ 0x7b, 0x00 }, /* 7B DAI1 EQ5 */
|
||||
{ 0x7c, 0x00 }, /* 7C DAI1 EQ5 */
|
||||
{ 0x7d, 0x00 }, /* 7D DAI1 EQ5 */
|
||||
{ 0x7e, 0x00 }, /* 7E DAI1 EQ5 */
|
||||
{ 0x7f, 0x00 }, /* 7F DAI1 EQ5 */
|
||||
|
||||
0x00, /* 80 DAI1 EQ5 */
|
||||
0x00, /* 81 DAI1 EQ5 */
|
||||
0x00, /* 82 DAI1 EQ5 */
|
||||
0x00, /* 83 DAI1 EQ5 */
|
||||
0x00, /* 84 DAI2 EQ1 */
|
||||
0x00, /* 85 DAI2 EQ1 */
|
||||
0x00, /* 86 DAI2 EQ1 */
|
||||
0x00, /* 87 DAI2 EQ1 */
|
||||
0x00, /* 88 DAI2 EQ1 */
|
||||
0x00, /* 89 DAI2 EQ1 */
|
||||
0x00, /* 8A DAI2 EQ1 */
|
||||
0x00, /* 8B DAI2 EQ1 */
|
||||
0x00, /* 8C DAI2 EQ1 */
|
||||
0x00, /* 8D DAI2 EQ1 */
|
||||
0x00, /* 8E DAI2 EQ2 */
|
||||
0x00, /* 8F DAI2 EQ2 */
|
||||
{ 0x80, 0x00 }, /* 80 DAI1 EQ5 */
|
||||
{ 0x81, 0x00 }, /* 81 DAI1 EQ5 */
|
||||
{ 0x82, 0x00 }, /* 82 DAI1 EQ5 */
|
||||
{ 0x83, 0x00 }, /* 83 DAI1 EQ5 */
|
||||
{ 0x84, 0x00 }, /* 84 DAI2 EQ1 */
|
||||
{ 0x85, 0x00 }, /* 85 DAI2 EQ1 */
|
||||
{ 0x86, 0x00 }, /* 86 DAI2 EQ1 */
|
||||
{ 0x87, 0x00 }, /* 87 DAI2 EQ1 */
|
||||
{ 0x88, 0x00 }, /* 88 DAI2 EQ1 */
|
||||
{ 0x89, 0x00 }, /* 89 DAI2 EQ1 */
|
||||
{ 0x8a, 0x00 }, /* 8A DAI2 EQ1 */
|
||||
{ 0x8b, 0x00 }, /* 8B DAI2 EQ1 */
|
||||
{ 0x8c, 0x00 }, /* 8C DAI2 EQ1 */
|
||||
{ 0x8d, 0x00 }, /* 8D DAI2 EQ1 */
|
||||
{ 0x8e, 0x00 }, /* 8E DAI2 EQ2 */
|
||||
{ 0x8f, 0x00 }, /* 8F DAI2 EQ2 */
|
||||
|
||||
0x00, /* 90 DAI2 EQ2 */
|
||||
0x00, /* 91 DAI2 EQ2 */
|
||||
0x00, /* 92 DAI2 EQ2 */
|
||||
0x00, /* 93 DAI2 EQ2 */
|
||||
0x00, /* 94 DAI2 EQ2 */
|
||||
0x00, /* 95 DAI2 EQ2 */
|
||||
0x00, /* 96 DAI2 EQ2 */
|
||||
0x00, /* 97 DAI2 EQ2 */
|
||||
0x00, /* 98 DAI2 EQ3 */
|
||||
0x00, /* 99 DAI2 EQ3 */
|
||||
0x00, /* 9A DAI2 EQ3 */
|
||||
0x00, /* 9B DAI2 EQ3 */
|
||||
0x00, /* 9C DAI2 EQ3 */
|
||||
0x00, /* 9D DAI2 EQ3 */
|
||||
0x00, /* 9E DAI2 EQ3 */
|
||||
0x00, /* 9F DAI2 EQ3 */
|
||||
{ 0x90, 0x00 }, /* 90 DAI2 EQ2 */
|
||||
{ 0x91, 0x00 }, /* 91 DAI2 EQ2 */
|
||||
{ 0x92, 0x00 }, /* 92 DAI2 EQ2 */
|
||||
{ 0x93, 0x00 }, /* 93 DAI2 EQ2 */
|
||||
{ 0x94, 0x00 }, /* 94 DAI2 EQ2 */
|
||||
{ 0x95, 0x00 }, /* 95 DAI2 EQ2 */
|
||||
{ 0x96, 0x00 }, /* 96 DAI2 EQ2 */
|
||||
{ 0x97, 0x00 }, /* 97 DAI2 EQ2 */
|
||||
{ 0x98, 0x00 }, /* 98 DAI2 EQ3 */
|
||||
{ 0x99, 0x00 }, /* 99 DAI2 EQ3 */
|
||||
{ 0x9a, 0x00 }, /* 9A DAI2 EQ3 */
|
||||
{ 0x9b, 0x00 }, /* 9B DAI2 EQ3 */
|
||||
{ 0x9c, 0x00 }, /* 9C DAI2 EQ3 */
|
||||
{ 0x9d, 0x00 }, /* 9D DAI2 EQ3 */
|
||||
{ 0x9e, 0x00 }, /* 9E DAI2 EQ3 */
|
||||
{ 0x9f, 0x00 }, /* 9F DAI2 EQ3 */
|
||||
|
||||
0x00, /* A0 DAI2 EQ3 */
|
||||
0x00, /* A1 DAI2 EQ3 */
|
||||
0x00, /* A2 DAI2 EQ4 */
|
||||
0x00, /* A3 DAI2 EQ4 */
|
||||
0x00, /* A4 DAI2 EQ4 */
|
||||
0x00, /* A5 DAI2 EQ4 */
|
||||
0x00, /* A6 DAI2 EQ4 */
|
||||
0x00, /* A7 DAI2 EQ4 */
|
||||
0x00, /* A8 DAI2 EQ4 */
|
||||
0x00, /* A9 DAI2 EQ4 */
|
||||
0x00, /* AA DAI2 EQ4 */
|
||||
0x00, /* AB DAI2 EQ4 */
|
||||
0x00, /* AC DAI2 EQ5 */
|
||||
0x00, /* AD DAI2 EQ5 */
|
||||
0x00, /* AE DAI2 EQ5 */
|
||||
0x00, /* AF DAI2 EQ5 */
|
||||
{ 0xa0, 0x00 }, /* A0 DAI2 EQ3 */
|
||||
{ 0xa1, 0x00 }, /* A1 DAI2 EQ3 */
|
||||
{ 0xa2, 0x00 }, /* A2 DAI2 EQ4 */
|
||||
{ 0xa3, 0x00 }, /* A3 DAI2 EQ4 */
|
||||
{ 0xa4, 0x00 }, /* A4 DAI2 EQ4 */
|
||||
{ 0xa5, 0x00 }, /* A5 DAI2 EQ4 */
|
||||
{ 0xa6, 0x00 }, /* A6 DAI2 EQ4 */
|
||||
{ 0xa7, 0x00 }, /* A7 DAI2 EQ4 */
|
||||
{ 0xa8, 0x00 }, /* A8 DAI2 EQ4 */
|
||||
{ 0xa9, 0x00 }, /* A9 DAI2 EQ4 */
|
||||
{ 0xaa, 0x00 }, /* AA DAI2 EQ4 */
|
||||
{ 0xab, 0x00 }, /* AB DAI2 EQ4 */
|
||||
{ 0xac, 0x00 }, /* AC DAI2 EQ5 */
|
||||
{ 0xad, 0x00 }, /* AD DAI2 EQ5 */
|
||||
{ 0xae, 0x00 }, /* AE DAI2 EQ5 */
|
||||
{ 0xaf, 0x00 }, /* AF DAI2 EQ5 */
|
||||
|
||||
0x00, /* B0 DAI2 EQ5 */
|
||||
0x00, /* B1 DAI2 EQ5 */
|
||||
0x00, /* B2 DAI2 EQ5 */
|
||||
0x00, /* B3 DAI2 EQ5 */
|
||||
0x00, /* B4 DAI2 EQ5 */
|
||||
0x00, /* B5 DAI2 EQ5 */
|
||||
0x00, /* B6 DAI1 biquad */
|
||||
0x00, /* B7 DAI1 biquad */
|
||||
0x00, /* B8 DAI1 biquad */
|
||||
0x00, /* B9 DAI1 biquad */
|
||||
0x00, /* BA DAI1 biquad */
|
||||
0x00, /* BB DAI1 biquad */
|
||||
0x00, /* BC DAI1 biquad */
|
||||
0x00, /* BD DAI1 biquad */
|
||||
0x00, /* BE DAI1 biquad */
|
||||
0x00, /* BF DAI1 biquad */
|
||||
{ 0xb0, 0x00 }, /* B0 DAI2 EQ5 */
|
||||
{ 0xb1, 0x00 }, /* B1 DAI2 EQ5 */
|
||||
{ 0xb2, 0x00 }, /* B2 DAI2 EQ5 */
|
||||
{ 0xb3, 0x00 }, /* B3 DAI2 EQ5 */
|
||||
{ 0xb4, 0x00 }, /* B4 DAI2 EQ5 */
|
||||
{ 0xb5, 0x00 }, /* B5 DAI2 EQ5 */
|
||||
{ 0xb6, 0x00 }, /* B6 DAI1 biquad */
|
||||
{ 0xb7, 0x00 }, /* B7 DAI1 biquad */
|
||||
{ 0xb8 ,0x00 }, /* B8 DAI1 biquad */
|
||||
{ 0xb9, 0x00 }, /* B9 DAI1 biquad */
|
||||
{ 0xba, 0x00 }, /* BA DAI1 biquad */
|
||||
{ 0xbb, 0x00 }, /* BB DAI1 biquad */
|
||||
{ 0xbc, 0x00 }, /* BC DAI1 biquad */
|
||||
{ 0xbd, 0x00 }, /* BD DAI1 biquad */
|
||||
{ 0xbe, 0x00 }, /* BE DAI1 biquad */
|
||||
{ 0xbf, 0x00 }, /* BF DAI1 biquad */
|
||||
|
||||
0x00, /* C0 DAI2 biquad */
|
||||
0x00, /* C1 DAI2 biquad */
|
||||
0x00, /* C2 DAI2 biquad */
|
||||
0x00, /* C3 DAI2 biquad */
|
||||
0x00, /* C4 DAI2 biquad */
|
||||
0x00, /* C5 DAI2 biquad */
|
||||
0x00, /* C6 DAI2 biquad */
|
||||
0x00, /* C7 DAI2 biquad */
|
||||
0x00, /* C8 DAI2 biquad */
|
||||
0x00, /* C9 DAI2 biquad */
|
||||
0x00, /* CA */
|
||||
0x00, /* CB */
|
||||
0x00, /* CC */
|
||||
0x00, /* CD */
|
||||
0x00, /* CE */
|
||||
0x00, /* CF */
|
||||
|
||||
0x00, /* D0 */
|
||||
0x00, /* D1 */
|
||||
0x00, /* D2 */
|
||||
0x00, /* D3 */
|
||||
0x00, /* D4 */
|
||||
0x00, /* D5 */
|
||||
0x00, /* D6 */
|
||||
0x00, /* D7 */
|
||||
0x00, /* D8 */
|
||||
0x00, /* D9 */
|
||||
0x00, /* DA */
|
||||
0x70, /* DB */
|
||||
0x00, /* DC */
|
||||
0x00, /* DD */
|
||||
0x00, /* DE */
|
||||
0x00, /* DF */
|
||||
|
||||
0x00, /* E0 */
|
||||
0x00, /* E1 */
|
||||
0x00, /* E2 */
|
||||
0x00, /* E3 */
|
||||
0x00, /* E4 */
|
||||
0x00, /* E5 */
|
||||
0x00, /* E6 */
|
||||
0x00, /* E7 */
|
||||
0x00, /* E8 */
|
||||
0x00, /* E9 */
|
||||
0x00, /* EA */
|
||||
0x00, /* EB */
|
||||
0x00, /* EC */
|
||||
0x00, /* ED */
|
||||
0x00, /* EE */
|
||||
0x00, /* EF */
|
||||
|
||||
0x00, /* F0 */
|
||||
0x00, /* F1 */
|
||||
0x00, /* F2 */
|
||||
0x00, /* F3 */
|
||||
0x00, /* F4 */
|
||||
0x00, /* F5 */
|
||||
0x00, /* F6 */
|
||||
0x00, /* F7 */
|
||||
0x00, /* F8 */
|
||||
0x00, /* F9 */
|
||||
0x00, /* FA */
|
||||
0x00, /* FB */
|
||||
0x00, /* FC */
|
||||
0x00, /* FD */
|
||||
0x00, /* FE */
|
||||
0x00, /* FF */
|
||||
{ 0xc0, 0x00 }, /* C0 DAI2 biquad */
|
||||
{ 0xc1, 0x00 }, /* C1 DAI2 biquad */
|
||||
{ 0xc2, 0x00 }, /* C2 DAI2 biquad */
|
||||
{ 0xc3, 0x00 }, /* C3 DAI2 biquad */
|
||||
{ 0xc4, 0x00 }, /* C4 DAI2 biquad */
|
||||
{ 0xc5, 0x00 }, /* C5 DAI2 biquad */
|
||||
{ 0xc6, 0x00 }, /* C6 DAI2 biquad */
|
||||
{ 0xc7, 0x00 }, /* C7 DAI2 biquad */
|
||||
{ 0xc8, 0x00 }, /* C8 DAI2 biquad */
|
||||
{ 0xc9, 0x00 }, /* C9 DAI2 biquad */
|
||||
};
|
||||
|
||||
static struct {
|
||||
@@ -606,11 +536,28 @@ static struct {
|
||||
{ 0xFF, 0x00, 1 }, /* FF */
|
||||
};
|
||||
|
||||
static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
|
||||
static bool max98088_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return max98088_access[reg].readable;
|
||||
}
|
||||
|
||||
static bool max98088_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return max98088_access[reg].vol;
|
||||
}
|
||||
|
||||
static const struct regmap_config max98088_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.readable_reg = max98088_readable_register,
|
||||
.volatile_reg = max98088_volatile_register,
|
||||
.max_register = 0xff,
|
||||
|
||||
.reg_defaults = max98088_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(max98088_reg),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Load equalizer DSP coefficient configurations registers
|
||||
@@ -1610,58 +1557,34 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max98088_sync_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 *reg_cache = codec->reg_cache;
|
||||
int i;
|
||||
|
||||
if (!codec->cache_sync)
|
||||
return;
|
||||
|
||||
codec->cache_only = 0;
|
||||
|
||||
/* write back cached values if they're writeable and
|
||||
* different from the hardware default.
|
||||
*/
|
||||
for (i = 1; i < codec->driver->reg_cache_size; i++) {
|
||||
if (!max98088_access[i].writable)
|
||||
continue;
|
||||
|
||||
if (reg_cache[i] == max98088_reg[i])
|
||||
continue;
|
||||
|
||||
snd_soc_write(codec, i, reg_cache[i]);
|
||||
}
|
||||
|
||||
codec->cache_sync = 0;
|
||||
}
|
||||
|
||||
static int max98088_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
max98088_sync_cache(codec);
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
M98088_MBEN, M98088_MBEN);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
regcache_sync(max98088->regmap);
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
M98088_MBEN, 0);
|
||||
codec->cache_sync = 1;
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
M98088_MBEN, M98088_MBEN);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
M98088_MBEN, 0);
|
||||
regcache_mark_dirty(max98088->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
|
||||
@@ -1988,9 +1911,9 @@ static int max98088_probe(struct snd_soc_codec *codec)
|
||||
struct max98088_cdata *cdata;
|
||||
int ret = 0;
|
||||
|
||||
codec->cache_sync = 1;
|
||||
regcache_mark_dirty(max98088->regmap);
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -2048,9 +1971,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
|
||||
|
||||
max98088_handle_pdata(codec);
|
||||
|
||||
snd_soc_add_codec_controls(codec, max98088_snd_controls,
|
||||
ARRAY_SIZE(max98088_snd_controls));
|
||||
|
||||
err_access:
|
||||
return ret;
|
||||
}
|
||||
@@ -2066,15 +1986,13 @@ static int max98088_remove(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
|
||||
.probe = max98088_probe,
|
||||
.remove = max98088_remove,
|
||||
.suspend = max98088_suspend,
|
||||
.resume = max98088_resume,
|
||||
.set_bias_level = max98088_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(max98088_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = max98088_reg,
|
||||
.volatile_register = max98088_volatile_register,
|
||||
.probe = max98088_probe,
|
||||
.remove = max98088_remove,
|
||||
.suspend = max98088_suspend,
|
||||
.resume = max98088_resume,
|
||||
.set_bias_level = max98088_set_bias_level,
|
||||
.controls = max98088_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(max98088_snd_controls),
|
||||
.dapm_widgets = max98088_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets),
|
||||
.dapm_routes = max98088_audio_map,
|
||||
@@ -2082,7 +2000,7 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
|
||||
};
|
||||
|
||||
static int max98088_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max98088_priv *max98088;
|
||||
int ret;
|
||||
@@ -2092,6 +2010,10 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
|
||||
if (max98088 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap);
|
||||
if (IS_ERR(max98088->regmap))
|
||||
return PTR_ERR(max98088->regmap);
|
||||
|
||||
max98088->devtype = id->driver_data;
|
||||
|
||||
i2c_set_clientdata(i2c, max98088);
|
||||
|
@@ -39,6 +39,7 @@ struct max98095_cdata {
|
||||
};
|
||||
|
||||
struct max98095_priv {
|
||||
struct regmap *regmap;
|
||||
enum max98095_type devtype;
|
||||
struct max98095_pdata *pdata;
|
||||
unsigned int sysclk;
|
||||
@@ -56,263 +57,145 @@ struct max98095_priv {
|
||||
struct snd_soc_jack *mic_jack;
|
||||
};
|
||||
|
||||
static const u8 max98095_reg_def[M98095_REG_CNT] = {
|
||||
0x00, /* 00 */
|
||||
0x00, /* 01 */
|
||||
0x00, /* 02 */
|
||||
0x00, /* 03 */
|
||||
0x00, /* 04 */
|
||||
0x00, /* 05 */
|
||||
0x00, /* 06 */
|
||||
0x00, /* 07 */
|
||||
0x00, /* 08 */
|
||||
0x00, /* 09 */
|
||||
0x00, /* 0A */
|
||||
0x00, /* 0B */
|
||||
0x00, /* 0C */
|
||||
0x00, /* 0D */
|
||||
0x00, /* 0E */
|
||||
0x00, /* 0F */
|
||||
0x00, /* 10 */
|
||||
0x00, /* 11 */
|
||||
0x00, /* 12 */
|
||||
0x00, /* 13 */
|
||||
0x00, /* 14 */
|
||||
0x00, /* 15 */
|
||||
0x00, /* 16 */
|
||||
0x00, /* 17 */
|
||||
0x00, /* 18 */
|
||||
0x00, /* 19 */
|
||||
0x00, /* 1A */
|
||||
0x00, /* 1B */
|
||||
0x00, /* 1C */
|
||||
0x00, /* 1D */
|
||||
0x00, /* 1E */
|
||||
0x00, /* 1F */
|
||||
0x00, /* 20 */
|
||||
0x00, /* 21 */
|
||||
0x00, /* 22 */
|
||||
0x00, /* 23 */
|
||||
0x00, /* 24 */
|
||||
0x00, /* 25 */
|
||||
0x00, /* 26 */
|
||||
0x00, /* 27 */
|
||||
0x00, /* 28 */
|
||||
0x00, /* 29 */
|
||||
0x00, /* 2A */
|
||||
0x00, /* 2B */
|
||||
0x00, /* 2C */
|
||||
0x00, /* 2D */
|
||||
0x00, /* 2E */
|
||||
0x00, /* 2F */
|
||||
0x00, /* 30 */
|
||||
0x00, /* 31 */
|
||||
0x00, /* 32 */
|
||||
0x00, /* 33 */
|
||||
0x00, /* 34 */
|
||||
0x00, /* 35 */
|
||||
0x00, /* 36 */
|
||||
0x00, /* 37 */
|
||||
0x00, /* 38 */
|
||||
0x00, /* 39 */
|
||||
0x00, /* 3A */
|
||||
0x00, /* 3B */
|
||||
0x00, /* 3C */
|
||||
0x00, /* 3D */
|
||||
0x00, /* 3E */
|
||||
0x00, /* 3F */
|
||||
0x00, /* 40 */
|
||||
0x00, /* 41 */
|
||||
0x00, /* 42 */
|
||||
0x00, /* 43 */
|
||||
0x00, /* 44 */
|
||||
0x00, /* 45 */
|
||||
0x00, /* 46 */
|
||||
0x00, /* 47 */
|
||||
0x00, /* 48 */
|
||||
0x00, /* 49 */
|
||||
0x00, /* 4A */
|
||||
0x00, /* 4B */
|
||||
0x00, /* 4C */
|
||||
0x00, /* 4D */
|
||||
0x00, /* 4E */
|
||||
0x00, /* 4F */
|
||||
0x00, /* 50 */
|
||||
0x00, /* 51 */
|
||||
0x00, /* 52 */
|
||||
0x00, /* 53 */
|
||||
0x00, /* 54 */
|
||||
0x00, /* 55 */
|
||||
0x00, /* 56 */
|
||||
0x00, /* 57 */
|
||||
0x00, /* 58 */
|
||||
0x00, /* 59 */
|
||||
0x00, /* 5A */
|
||||
0x00, /* 5B */
|
||||
0x00, /* 5C */
|
||||
0x00, /* 5D */
|
||||
0x00, /* 5E */
|
||||
0x00, /* 5F */
|
||||
0x00, /* 60 */
|
||||
0x00, /* 61 */
|
||||
0x00, /* 62 */
|
||||
0x00, /* 63 */
|
||||
0x00, /* 64 */
|
||||
0x00, /* 65 */
|
||||
0x00, /* 66 */
|
||||
0x00, /* 67 */
|
||||
0x00, /* 68 */
|
||||
0x00, /* 69 */
|
||||
0x00, /* 6A */
|
||||
0x00, /* 6B */
|
||||
0x00, /* 6C */
|
||||
0x00, /* 6D */
|
||||
0x00, /* 6E */
|
||||
0x00, /* 6F */
|
||||
0x00, /* 70 */
|
||||
0x00, /* 71 */
|
||||
0x00, /* 72 */
|
||||
0x00, /* 73 */
|
||||
0x00, /* 74 */
|
||||
0x00, /* 75 */
|
||||
0x00, /* 76 */
|
||||
0x00, /* 77 */
|
||||
0x00, /* 78 */
|
||||
0x00, /* 79 */
|
||||
0x00, /* 7A */
|
||||
0x00, /* 7B */
|
||||
0x00, /* 7C */
|
||||
0x00, /* 7D */
|
||||
0x00, /* 7E */
|
||||
0x00, /* 7F */
|
||||
0x00, /* 80 */
|
||||
0x00, /* 81 */
|
||||
0x00, /* 82 */
|
||||
0x00, /* 83 */
|
||||
0x00, /* 84 */
|
||||
0x00, /* 85 */
|
||||
0x00, /* 86 */
|
||||
0x00, /* 87 */
|
||||
0x00, /* 88 */
|
||||
0x00, /* 89 */
|
||||
0x00, /* 8A */
|
||||
0x00, /* 8B */
|
||||
0x00, /* 8C */
|
||||
0x00, /* 8D */
|
||||
0x00, /* 8E */
|
||||
0x00, /* 8F */
|
||||
0x00, /* 90 */
|
||||
0x00, /* 91 */
|
||||
0x30, /* 92 */
|
||||
0xF0, /* 93 */
|
||||
0x00, /* 94 */
|
||||
0x00, /* 95 */
|
||||
0x3F, /* 96 */
|
||||
0x00, /* 97 */
|
||||
0x00, /* 98 */
|
||||
0x00, /* 99 */
|
||||
0x00, /* 9A */
|
||||
0x00, /* 9B */
|
||||
0x00, /* 9C */
|
||||
0x00, /* 9D */
|
||||
0x00, /* 9E */
|
||||
0x00, /* 9F */
|
||||
0x00, /* A0 */
|
||||
0x00, /* A1 */
|
||||
0x00, /* A2 */
|
||||
0x00, /* A3 */
|
||||
0x00, /* A4 */
|
||||
0x00, /* A5 */
|
||||
0x00, /* A6 */
|
||||
0x00, /* A7 */
|
||||
0x00, /* A8 */
|
||||
0x00, /* A9 */
|
||||
0x00, /* AA */
|
||||
0x00, /* AB */
|
||||
0x00, /* AC */
|
||||
0x00, /* AD */
|
||||
0x00, /* AE */
|
||||
0x00, /* AF */
|
||||
0x00, /* B0 */
|
||||
0x00, /* B1 */
|
||||
0x00, /* B2 */
|
||||
0x00, /* B3 */
|
||||
0x00, /* B4 */
|
||||
0x00, /* B5 */
|
||||
0x00, /* B6 */
|
||||
0x00, /* B7 */
|
||||
0x00, /* B8 */
|
||||
0x00, /* B9 */
|
||||
0x00, /* BA */
|
||||
0x00, /* BB */
|
||||
0x00, /* BC */
|
||||
0x00, /* BD */
|
||||
0x00, /* BE */
|
||||
0x00, /* BF */
|
||||
0x00, /* C0 */
|
||||
0x00, /* C1 */
|
||||
0x00, /* C2 */
|
||||
0x00, /* C3 */
|
||||
0x00, /* C4 */
|
||||
0x00, /* C5 */
|
||||
0x00, /* C6 */
|
||||
0x00, /* C7 */
|
||||
0x00, /* C8 */
|
||||
0x00, /* C9 */
|
||||
0x00, /* CA */
|
||||
0x00, /* CB */
|
||||
0x00, /* CC */
|
||||
0x00, /* CD */
|
||||
0x00, /* CE */
|
||||
0x00, /* CF */
|
||||
0x00, /* D0 */
|
||||
0x00, /* D1 */
|
||||
0x00, /* D2 */
|
||||
0x00, /* D3 */
|
||||
0x00, /* D4 */
|
||||
0x00, /* D5 */
|
||||
0x00, /* D6 */
|
||||
0x00, /* D7 */
|
||||
0x00, /* D8 */
|
||||
0x00, /* D9 */
|
||||
0x00, /* DA */
|
||||
0x00, /* DB */
|
||||
0x00, /* DC */
|
||||
0x00, /* DD */
|
||||
0x00, /* DE */
|
||||
0x00, /* DF */
|
||||
0x00, /* E0 */
|
||||
0x00, /* E1 */
|
||||
0x00, /* E2 */
|
||||
0x00, /* E3 */
|
||||
0x00, /* E4 */
|
||||
0x00, /* E5 */
|
||||
0x00, /* E6 */
|
||||
0x00, /* E7 */
|
||||
0x00, /* E8 */
|
||||
0x00, /* E9 */
|
||||
0x00, /* EA */
|
||||
0x00, /* EB */
|
||||
0x00, /* EC */
|
||||
0x00, /* ED */
|
||||
0x00, /* EE */
|
||||
0x00, /* EF */
|
||||
0x00, /* F0 */
|
||||
0x00, /* F1 */
|
||||
0x00, /* F2 */
|
||||
0x00, /* F3 */
|
||||
0x00, /* F4 */
|
||||
0x00, /* F5 */
|
||||
0x00, /* F6 */
|
||||
0x00, /* F7 */
|
||||
0x00, /* F8 */
|
||||
0x00, /* F9 */
|
||||
0x00, /* FA */
|
||||
0x00, /* FB */
|
||||
0x00, /* FC */
|
||||
0x00, /* FD */
|
||||
0x00, /* FE */
|
||||
0x00, /* FF */
|
||||
static const struct reg_default max98095_reg_def[] = {
|
||||
{ 0xf, 0x00 }, /* 0F */
|
||||
{ 0x10, 0x00 }, /* 10 */
|
||||
{ 0x11, 0x00 }, /* 11 */
|
||||
{ 0x12, 0x00 }, /* 12 */
|
||||
{ 0x13, 0x00 }, /* 13 */
|
||||
{ 0x14, 0x00 }, /* 14 */
|
||||
{ 0x15, 0x00 }, /* 15 */
|
||||
{ 0x16, 0x00 }, /* 16 */
|
||||
{ 0x17, 0x00 }, /* 17 */
|
||||
{ 0x18, 0x00 }, /* 18 */
|
||||
{ 0x19, 0x00 }, /* 19 */
|
||||
{ 0x1a, 0x00 }, /* 1A */
|
||||
{ 0x1b, 0x00 }, /* 1B */
|
||||
{ 0x1c, 0x00 }, /* 1C */
|
||||
{ 0x1d, 0x00 }, /* 1D */
|
||||
{ 0x1e, 0x00 }, /* 1E */
|
||||
{ 0x1f, 0x00 }, /* 1F */
|
||||
{ 0x20, 0x00 }, /* 20 */
|
||||
{ 0x21, 0x00 }, /* 21 */
|
||||
{ 0x22, 0x00 }, /* 22 */
|
||||
{ 0x23, 0x00 }, /* 23 */
|
||||
{ 0x24, 0x00 }, /* 24 */
|
||||
{ 0x25, 0x00 }, /* 25 */
|
||||
{ 0x26, 0x00 }, /* 26 */
|
||||
{ 0x27, 0x00 }, /* 27 */
|
||||
{ 0x28, 0x00 }, /* 28 */
|
||||
{ 0x29, 0x00 }, /* 29 */
|
||||
{ 0x2a, 0x00 }, /* 2A */
|
||||
{ 0x2b, 0x00 }, /* 2B */
|
||||
{ 0x2c, 0x00 }, /* 2C */
|
||||
{ 0x2d, 0x00 }, /* 2D */
|
||||
{ 0x2e, 0x00 }, /* 2E */
|
||||
{ 0x2f, 0x00 }, /* 2F */
|
||||
{ 0x30, 0x00 }, /* 30 */
|
||||
{ 0x31, 0x00 }, /* 31 */
|
||||
{ 0x32, 0x00 }, /* 32 */
|
||||
{ 0x33, 0x00 }, /* 33 */
|
||||
{ 0x34, 0x00 }, /* 34 */
|
||||
{ 0x35, 0x00 }, /* 35 */
|
||||
{ 0x36, 0x00 }, /* 36 */
|
||||
{ 0x37, 0x00 }, /* 37 */
|
||||
{ 0x38, 0x00 }, /* 38 */
|
||||
{ 0x39, 0x00 }, /* 39 */
|
||||
{ 0x3a, 0x00 }, /* 3A */
|
||||
{ 0x3b, 0x00 }, /* 3B */
|
||||
{ 0x3c, 0x00 }, /* 3C */
|
||||
{ 0x3d, 0x00 }, /* 3D */
|
||||
{ 0x3e, 0x00 }, /* 3E */
|
||||
{ 0x3f, 0x00 }, /* 3F */
|
||||
{ 0x40, 0x00 }, /* 40 */
|
||||
{ 0x41, 0x00 }, /* 41 */
|
||||
{ 0x42, 0x00 }, /* 42 */
|
||||
{ 0x43, 0x00 }, /* 43 */
|
||||
{ 0x44, 0x00 }, /* 44 */
|
||||
{ 0x45, 0x00 }, /* 45 */
|
||||
{ 0x46, 0x00 }, /* 46 */
|
||||
{ 0x47, 0x00 }, /* 47 */
|
||||
{ 0x48, 0x00 }, /* 48 */
|
||||
{ 0x49, 0x00 }, /* 49 */
|
||||
{ 0x4a, 0x00 }, /* 4A */
|
||||
{ 0x4b, 0x00 }, /* 4B */
|
||||
{ 0x4c, 0x00 }, /* 4C */
|
||||
{ 0x4d, 0x00 }, /* 4D */
|
||||
{ 0x4e, 0x00 }, /* 4E */
|
||||
{ 0x4f, 0x00 }, /* 4F */
|
||||
{ 0x50, 0x00 }, /* 50 */
|
||||
{ 0x51, 0x00 }, /* 51 */
|
||||
{ 0x52, 0x00 }, /* 52 */
|
||||
{ 0x53, 0x00 }, /* 53 */
|
||||
{ 0x54, 0x00 }, /* 54 */
|
||||
{ 0x55, 0x00 }, /* 55 */
|
||||
{ 0x56, 0x00 }, /* 56 */
|
||||
{ 0x57, 0x00 }, /* 57 */
|
||||
{ 0x58, 0x00 }, /* 58 */
|
||||
{ 0x59, 0x00 }, /* 59 */
|
||||
{ 0x5a, 0x00 }, /* 5A */
|
||||
{ 0x5b, 0x00 }, /* 5B */
|
||||
{ 0x5c, 0x00 }, /* 5C */
|
||||
{ 0x5d, 0x00 }, /* 5D */
|
||||
{ 0x5e, 0x00 }, /* 5E */
|
||||
{ 0x5f, 0x00 }, /* 5F */
|
||||
{ 0x60, 0x00 }, /* 60 */
|
||||
{ 0x61, 0x00 }, /* 61 */
|
||||
{ 0x62, 0x00 }, /* 62 */
|
||||
{ 0x63, 0x00 }, /* 63 */
|
||||
{ 0x64, 0x00 }, /* 64 */
|
||||
{ 0x65, 0x00 }, /* 65 */
|
||||
{ 0x66, 0x00 }, /* 66 */
|
||||
{ 0x67, 0x00 }, /* 67 */
|
||||
{ 0x68, 0x00 }, /* 68 */
|
||||
{ 0x69, 0x00 }, /* 69 */
|
||||
{ 0x6a, 0x00 }, /* 6A */
|
||||
{ 0x6b, 0x00 }, /* 6B */
|
||||
{ 0x6c, 0x00 }, /* 6C */
|
||||
{ 0x6d, 0x00 }, /* 6D */
|
||||
{ 0x6e, 0x00 }, /* 6E */
|
||||
{ 0x6f, 0x00 }, /* 6F */
|
||||
{ 0x70, 0x00 }, /* 70 */
|
||||
{ 0x71, 0x00 }, /* 71 */
|
||||
{ 0x72, 0x00 }, /* 72 */
|
||||
{ 0x73, 0x00 }, /* 73 */
|
||||
{ 0x74, 0x00 }, /* 74 */
|
||||
{ 0x75, 0x00 }, /* 75 */
|
||||
{ 0x76, 0x00 }, /* 76 */
|
||||
{ 0x77, 0x00 }, /* 77 */
|
||||
{ 0x78, 0x00 }, /* 78 */
|
||||
{ 0x79, 0x00 }, /* 79 */
|
||||
{ 0x7a, 0x00 }, /* 7A */
|
||||
{ 0x7b, 0x00 }, /* 7B */
|
||||
{ 0x7c, 0x00 }, /* 7C */
|
||||
{ 0x7d, 0x00 }, /* 7D */
|
||||
{ 0x7e, 0x00 }, /* 7E */
|
||||
{ 0x7f, 0x00 }, /* 7F */
|
||||
{ 0x80, 0x00 }, /* 80 */
|
||||
{ 0x81, 0x00 }, /* 81 */
|
||||
{ 0x82, 0x00 }, /* 82 */
|
||||
{ 0x83, 0x00 }, /* 83 */
|
||||
{ 0x84, 0x00 }, /* 84 */
|
||||
{ 0x85, 0x00 }, /* 85 */
|
||||
{ 0x86, 0x00 }, /* 86 */
|
||||
{ 0x87, 0x00 }, /* 87 */
|
||||
{ 0x88, 0x00 }, /* 88 */
|
||||
{ 0x89, 0x00 }, /* 89 */
|
||||
{ 0x8a, 0x00 }, /* 8A */
|
||||
{ 0x8b, 0x00 }, /* 8B */
|
||||
{ 0x8c, 0x00 }, /* 8C */
|
||||
{ 0x8d, 0x00 }, /* 8D */
|
||||
{ 0x8e, 0x00 }, /* 8E */
|
||||
{ 0x8f, 0x00 }, /* 8F */
|
||||
{ 0x90, 0x00 }, /* 90 */
|
||||
{ 0x91, 0x00 }, /* 91 */
|
||||
{ 0x92, 0x30 }, /* 92 */
|
||||
{ 0x93, 0xF0 }, /* 93 */
|
||||
{ 0x94, 0x00 }, /* 94 */
|
||||
{ 0x95, 0x00 }, /* 95 */
|
||||
{ 0x96, 0x3F }, /* 96 */
|
||||
{ 0x97, 0x00 }, /* 97 */
|
||||
{ 0xff, 0x00 }, /* FF */
|
||||
};
|
||||
|
||||
static struct {
|
||||
@@ -577,14 +460,14 @@ static struct {
|
||||
{ 0xFF, 0x00 }, /* FF */
|
||||
};
|
||||
|
||||
static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg)
|
||||
static bool max98095_readable(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (reg >= M98095_REG_CNT)
|
||||
return 0;
|
||||
return max98095_access[reg].readable != 0;
|
||||
}
|
||||
|
||||
static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
|
||||
static bool max98095_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (reg > M98095_REG_MAX_CACHED)
|
||||
return 1;
|
||||
@@ -611,22 +494,18 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Filter coefficients are in a separate register segment
|
||||
* and they share the address space of the normal registers.
|
||||
* The coefficient registers do not need or share the cache.
|
||||
*/
|
||||
static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
int ret;
|
||||
static const struct regmap_config max98095_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
codec->cache_bypass = 1;
|
||||
ret = snd_soc_write(codec, reg, value);
|
||||
codec->cache_bypass = 0;
|
||||
.reg_defaults = max98095_reg_def,
|
||||
.num_reg_defaults = ARRAY_SIZE(max98095_reg_def),
|
||||
.max_register = M98095_0FF_REV_ID,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
|
||||
return ret ? -EIO : 0;
|
||||
}
|
||||
.readable_reg = max98095_readable,
|
||||
.volatile_reg = max98095_volatile,
|
||||
};
|
||||
|
||||
/*
|
||||
* Load equalizer DSP coefficient configurations registers
|
||||
@@ -648,8 +527,8 @@ static void m98095_eq_band(struct snd_soc_codec *codec, unsigned int dai,
|
||||
|
||||
/* Step through the registers and coefs */
|
||||
for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
|
||||
max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
|
||||
max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
|
||||
snd_soc_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
|
||||
snd_soc_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,8 +552,8 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai,
|
||||
|
||||
/* Step through the registers and coefs */
|
||||
for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
|
||||
max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
|
||||
max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
|
||||
snd_soc_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
|
||||
snd_soc_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1285,14 +1164,6 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
|
||||
{"MIC2 Input", NULL, "MIC2"},
|
||||
};
|
||||
|
||||
static int max98095_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_add_codec_controls(codec, max98095_snd_controls,
|
||||
ARRAY_SIZE(max98095_snd_controls));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* codec mclk clock divider coefficients */
|
||||
static const struct {
|
||||
u32 rate;
|
||||
@@ -1748,6 +1619,7 @@ static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai,
|
||||
static int max98095_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
@@ -1759,7 +1631,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = snd_soc_cache_sync(codec);
|
||||
ret = regcache_sync(max98095->regmap);
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
|
||||
@@ -1774,7 +1646,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, M98095_090_PWR_EN_IN,
|
||||
M98095_MBEN, 0);
|
||||
codec->cache_sync = 1;
|
||||
regcache_mark_dirty(max98095->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
@@ -2341,7 +2213,7 @@ static int max98095_reset(struct snd_soc_codec *codec)
|
||||
/* Reset to hardware default for registers, as there is not
|
||||
* a soft reset hardware control register */
|
||||
for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
|
||||
ret = snd_soc_write(codec, i, max98095_reg_def[i]);
|
||||
ret = snd_soc_write(codec, i, snd_soc_read(codec, i));
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to reset: %d\n", ret);
|
||||
return ret;
|
||||
@@ -2358,7 +2230,7 @@ static int max98095_probe(struct snd_soc_codec *codec)
|
||||
struct i2c_client *client;
|
||||
int ret = 0;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -2447,8 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec)
|
||||
snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN,
|
||||
M98095_SHDNRUN);
|
||||
|
||||
max98095_add_widgets(codec);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
@@ -2480,11 +2350,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max98095 = {
|
||||
.suspend = max98095_suspend,
|
||||
.resume = max98095_resume,
|
||||
.set_bias_level = max98095_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(max98095_reg_def),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = max98095_reg_def,
|
||||
.readable_register = max98095_readable,
|
||||
.volatile_register = max98095_volatile,
|
||||
.controls = max98095_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(max98095_snd_controls),
|
||||
.dapm_widgets = max98095_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets),
|
||||
.dapm_routes = max98095_audio_map,
|
||||
@@ -2502,6 +2369,13 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
|
||||
if (max98095 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap);
|
||||
if (IS_ERR(max98095->regmap)) {
|
||||
ret = PTR_ERR(max98095->regmap);
|
||||
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
max98095->devtype = id->driver_data;
|
||||
i2c_set_clientdata(i2c, max98095);
|
||||
max98095->pdata = i2c->dev.platform_data;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@@ -27,18 +28,26 @@
|
||||
#include "max9850.h"
|
||||
|
||||
struct max9850_priv {
|
||||
struct regmap *regmap;
|
||||
unsigned int sysclk;
|
||||
};
|
||||
|
||||
/* max9850 register cache */
|
||||
static const u8 max9850_reg[MAX9850_CACHEREGNUM] = {
|
||||
0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
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 int max9850_volatile_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
static bool max9850_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case MAX9850_STATUSA:
|
||||
@@ -49,6 +58,15 @@ static int max9850_volatile_register(struct snd_soc_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config max9850_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = MAX9850_DIGITAL_AUDIO,
|
||||
.volatile_reg = max9850_volatile_register,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const unsigned int max9850_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(4),
|
||||
0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
|
||||
@@ -225,6 +243,7 @@ static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
static int max9850_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
@@ -234,7 +253,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = snd_soc_cache_sync(codec);
|
||||
ret = regcache_sync(max9850->regmap);
|
||||
if (ret) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to sync cache: %d\n", ret);
|
||||
@@ -295,7 +314,7 @@ static int max9850_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -316,10 +335,6 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
|
||||
.suspend = max9850_suspend,
|
||||
.resume = max9850_resume,
|
||||
.set_bias_level = max9850_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(max9850_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = max9850_reg,
|
||||
.volatile_register = max9850_volatile_register,
|
||||
|
||||
.controls = max9850_controls,
|
||||
.num_controls = ARRAY_SIZE(max9850_controls),
|
||||
@@ -340,6 +355,10 @@ static int max9850_i2c_probe(struct i2c_client *i2c,
|
||||
if (max9850 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
max9850->regmap = devm_regmap_init_i2c(i2c, &max9850_regmap);
|
||||
if (IS_ERR(max9850->regmap))
|
||||
return PTR_ERR(max9850->regmap);
|
||||
|
||||
i2c_set_clientdata(i2c, max9850);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@@ -30,16 +30,10 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "mc13783.h"
|
||||
|
||||
#define MC13783_AUDIO_RX0 36
|
||||
#define MC13783_AUDIO_RX1 37
|
||||
#define MC13783_AUDIO_TX 38
|
||||
#define MC13783_SSI_NETWORK 39
|
||||
#define MC13783_AUDIO_CODEC 40
|
||||
#define MC13783_AUDIO_DAC 41
|
||||
|
||||
#define AUDIO_RX0_ALSPEN (1 << 5)
|
||||
#define AUDIO_RX0_ALSPSEL (1 << 7)
|
||||
#define AUDIO_RX0_ADDCDC (1 << 21)
|
||||
@@ -95,45 +89,12 @@
|
||||
|
||||
struct mc13783_priv {
|
||||
struct mc13xxx *mc13xxx;
|
||||
struct regmap *regmap;
|
||||
|
||||
enum mc13783_ssi_port adc_ssi_port;
|
||||
enum mc13783_ssi_port dac_ssi_port;
|
||||
};
|
||||
|
||||
static unsigned int mc13783_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int value = 0;
|
||||
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
|
||||
mc13xxx_reg_read(priv->mc13xxx, reg, &value);
|
||||
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int mc13783_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
|
||||
ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
|
||||
|
||||
/* include errata fix for spi audio problems */
|
||||
if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC)
|
||||
ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
|
||||
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mapping between sample rates and register value */
|
||||
static unsigned int mc13783_rates[] = {
|
||||
8000, 11025, 12000, 16000,
|
||||
@@ -466,6 +427,29 @@ static const struct snd_kcontrol_new right_input_mux =
|
||||
static const struct snd_kcontrol_new samp_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0);
|
||||
|
||||
static const char * const speaker_amp_source_text[] = {
|
||||
"CODEC", "Right"
|
||||
};
|
||||
static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
|
||||
speaker_amp_source_text);
|
||||
static const struct snd_kcontrol_new speaker_amp_source_mux =
|
||||
SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source);
|
||||
|
||||
static const char * const headset_amp_source_text[] = {
|
||||
"CODEC", "Mixer"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
|
||||
headset_amp_source_text);
|
||||
static const struct snd_kcontrol_new headset_amp_source_mux =
|
||||
SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source);
|
||||
|
||||
static const struct snd_kcontrol_new cdcout_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 18, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new adc_bypass_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_CODEC, 16, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new lamp_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0);
|
||||
|
||||
@@ -503,12 +487,22 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
|
||||
&right_input_mux),
|
||||
|
||||
SND_SOC_DAPM_MUX("Speaker Amp Source MUX", SND_SOC_NOPM, 0, 0,
|
||||
&speaker_amp_source_mux),
|
||||
|
||||
SND_SOC_DAPM_MUX("Headset Amp Source MUX", SND_SOC_NOPM, 0, 0,
|
||||
&headset_amp_source_mux),
|
||||
|
||||
SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0),
|
||||
SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("Voice CODEC PGA", MC13783_AUDIO_RX1, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SWITCH("Voice CODEC Bypass", MC13783_AUDIO_CODEC, 16, 0,
|
||||
&adc_bypass_ctl),
|
||||
|
||||
/* Output */
|
||||
SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0),
|
||||
@@ -516,10 +510,15 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("RXOUTR"),
|
||||
SND_SOC_DAPM_OUTPUT("HSL"),
|
||||
SND_SOC_DAPM_OUTPUT("HSR"),
|
||||
SND_SOC_DAPM_OUTPUT("LSPL"),
|
||||
SND_SOC_DAPM_OUTPUT("LSP"),
|
||||
SND_SOC_DAPM_OUTPUT("SP"),
|
||||
SND_SOC_DAPM_OUTPUT("CDCOUT"),
|
||||
|
||||
SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl),
|
||||
SND_SOC_DAPM_SWITCH("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 0,
|
||||
&cdcout_ctl),
|
||||
SND_SOC_DAPM_SWITCH("Speaker Amp Switch", MC13783_AUDIO_RX0, 3, 0,
|
||||
&samp_ctl),
|
||||
SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl),
|
||||
SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0,
|
||||
&hlamp_ctl),
|
||||
@@ -554,20 +553,28 @@ static struct snd_soc_dapm_route mc13783_routes[] = {
|
||||
{ "ADC", NULL, "PGA Right Input"},
|
||||
{ "ADC", NULL, "ADC_Reset"},
|
||||
|
||||
{ "Voice CODEC PGA", "Voice CODEC Bypass", "ADC" },
|
||||
|
||||
{ "Speaker Amp Source MUX", "CODEC", "Voice CODEC PGA"},
|
||||
{ "Speaker Amp Source MUX", "Right", "DAC PGA"},
|
||||
|
||||
{ "Headset Amp Source MUX", "CODEC", "Voice CODEC PGA"},
|
||||
{ "Headset Amp Source MUX", "Mixer", "DAC PGA"},
|
||||
|
||||
/* Output */
|
||||
{ "HSL", NULL, "Headset Amp Left" },
|
||||
{ "HSR", NULL, "Headset Amp Right"},
|
||||
{ "RXOUTL", NULL, "Line out Amp Left"},
|
||||
{ "RXOUTR", NULL, "Line out Amp Right"},
|
||||
{ "SP", NULL, "Speaker Amp"},
|
||||
{ "Speaker Amp", NULL, "DAC PGA"},
|
||||
{ "LSP", NULL, "DAC PGA"},
|
||||
{ "Headset Amp Left", NULL, "DAC PGA"},
|
||||
{ "Headset Amp Right", NULL, "DAC PGA"},
|
||||
{ "SP", "Speaker Amp Switch", "Speaker Amp Source MUX"},
|
||||
{ "LSP", "Loudspeaker Amp", "Speaker Amp Source MUX"},
|
||||
{ "HSL", "Headset Amp Left", "Headset Amp Source MUX"},
|
||||
{ "HSR", "Headset Amp Right", "Headset Amp Source MUX"},
|
||||
{ "Line out Amp Left", NULL, "DAC PGA"},
|
||||
{ "Line out Amp Right", NULL, "DAC PGA"},
|
||||
{ "DAC PGA", NULL, "DAC"},
|
||||
{ "DAC", NULL, "DAC_E"},
|
||||
{ "CDCOUT", "CDCOUT Switch", "Voice CODEC PGA"},
|
||||
};
|
||||
|
||||
static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
|
||||
@@ -580,15 +587,39 @@ static const struct soc_enum mc13783_enum_3d_mixer =
|
||||
static struct snd_kcontrol_new mc13783_control_list[] = {
|
||||
SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
|
||||
SOC_SINGLE("PCM Playback Volume", MC13783_AUDIO_RX1, 6, 15, 0),
|
||||
SOC_SINGLE("PCM Playback Switch", MC13783_AUDIO_RX1, 5, 1, 0),
|
||||
SOC_DOUBLE("PCM Capture Volume", MC13783_AUDIO_TX, 19, 14, 31, 0),
|
||||
SOC_ENUM("3D Control", mc13783_enum_3d_mixer),
|
||||
|
||||
SOC_SINGLE("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 1, 0),
|
||||
SOC_SINGLE("Earpiece Amp Switch", MC13783_AUDIO_RX0, 3, 1, 0),
|
||||
SOC_DOUBLE("Headset Amp Switch", MC13783_AUDIO_RX0, 10, 9, 1, 0),
|
||||
SOC_DOUBLE("Line out Amp Switch", MC13783_AUDIO_RX0, 16, 15, 1, 0),
|
||||
|
||||
SOC_SINGLE("PCM Capture Mixin Switch", MC13783_AUDIO_RX0, 22, 1, 0),
|
||||
SOC_SINGLE("Line in Capture Mixin Switch", MC13783_AUDIO_RX0, 23, 1, 0),
|
||||
|
||||
SOC_SINGLE("CODEC Capture Volume", MC13783_AUDIO_RX1, 1, 15, 0),
|
||||
SOC_SINGLE("CODEC Capture Mixin Switch", MC13783_AUDIO_RX0, 21, 1, 0),
|
||||
|
||||
SOC_SINGLE("Line in Capture Volume", MC13783_AUDIO_RX1, 12, 15, 0),
|
||||
SOC_SINGLE("Line in Capture Switch", MC13783_AUDIO_RX1, 10, 1, 0),
|
||||
|
||||
SOC_SINGLE("MC1 Capture Bias Switch", MC13783_AUDIO_TX, 0, 1, 0),
|
||||
SOC_SINGLE("MC2 Capture Bias Switch", MC13783_AUDIO_TX, 1, 1, 0),
|
||||
};
|
||||
|
||||
static int mc13783_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* these are the reset values */
|
||||
mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
|
||||
@@ -612,8 +643,6 @@ static int mc13783_probe(struct snd_soc_codec *codec)
|
||||
mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
|
||||
0, AUDIO_SSI_SEL);
|
||||
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -621,13 +650,9 @@ static int mc13783_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
|
||||
/* Make sure VAUDIOON is off */
|
||||
mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
|
||||
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -717,8 +742,6 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
|
||||
.probe = mc13783_probe,
|
||||
.remove = mc13783_remove,
|
||||
.read = mc13783_read,
|
||||
.write = mc13783_write,
|
||||
.controls = mc13783_control_list,
|
||||
.num_controls = ARRAY_SIZE(mc13783_control_list),
|
||||
.dapm_widgets = mc13783_dapm_widgets,
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "pcm1792a.h"
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@@ -926,7 +927,7 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hp_amp_power_on(struct snd_soc_codec *codec)
|
||||
static void hp_amp_power_on(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
@@ -1609,7 +1610,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
|
||||
rt5640->lrck[dai->id] = params_rate(params);
|
||||
pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
|
||||
if (pre_div < 0) {
|
||||
dev_err(codec->dev, "Unsupported clock setting\n");
|
||||
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
|
||||
rt5640->lrck[dai->id], dai->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
frame_size = snd_soc_params_to_frame_size(params);
|
||||
@@ -1977,13 +1979,20 @@ static int rt5640_suspend(struct snd_soc_codec *codec)
|
||||
rt5640_reset(codec);
|
||||
regcache_cache_only(rt5640->regmap, true);
|
||||
regcache_mark_dirty(rt5640->regmap);
|
||||
if (gpio_is_valid(rt5640->pdata.ldo1_en))
|
||||
gpio_set_value_cansleep(rt5640->pdata.ldo1_en, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5640_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (gpio_is_valid(rt5640->pdata.ldo1_en)) {
|
||||
gpio_set_value_cansleep(rt5640->pdata.ldo1_en, 1);
|
||||
msleep(400);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2080,6 +2089,14 @@ static const struct i2c_device_id rt5640_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static struct acpi_device_id rt5640_acpi_match[] = {
|
||||
{ "INT33CA", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
|
||||
#endif
|
||||
|
||||
static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np)
|
||||
{
|
||||
rt5640->pdata.in1_diff = of_property_read_bool(np,
|
||||
@@ -2199,6 +2216,7 @@ static struct i2c_driver rt5640_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rt5640",
|
||||
.owner = THIS_MODULE,
|
||||
.acpi_match_table = ACPI_PTR(rt5640_acpi_match),
|
||||
},
|
||||
.probe = rt5640_i2c_probe,
|
||||
.remove = rt5640_i2c_remove,
|
||||
|
@@ -60,48 +60,6 @@ enum si476x_pcm_format {
|
||||
SI476X_PCM_FORMAT_S24_LE = 6,
|
||||
};
|
||||
|
||||
static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
int err;
|
||||
unsigned int val;
|
||||
struct si476x_core *core = codec->control_data;
|
||||
|
||||
si476x_core_lock(core);
|
||||
if (!si476x_core_is_powered_up(core))
|
||||
regcache_cache_only(core->regmap, true);
|
||||
|
||||
err = regmap_read(core->regmap, reg, &val);
|
||||
|
||||
if (!si476x_core_is_powered_up(core))
|
||||
regcache_cache_only(core->regmap, false);
|
||||
si476x_core_unlock(core);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int si476x_codec_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int val)
|
||||
{
|
||||
int err;
|
||||
struct si476x_core *core = codec->control_data;
|
||||
|
||||
si476x_core_lock(core);
|
||||
if (!si476x_core_is_powered_up(core))
|
||||
regcache_cache_only(core->regmap, true);
|
||||
|
||||
err = regmap_write(core->regmap, reg, val);
|
||||
|
||||
if (!si476x_core_is_powered_up(core))
|
||||
regcache_cache_only(core->regmap, false);
|
||||
si476x_core_unlock(core);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("LOUT"),
|
||||
SND_SOC_DAPM_OUTPUT("ROUT"),
|
||||
@@ -115,6 +73,7 @@ static const struct snd_soc_dapm_route si476x_dapm_routes[] = {
|
||||
static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev);
|
||||
int err;
|
||||
u16 format = 0;
|
||||
|
||||
@@ -178,9 +137,14 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
si476x_core_lock(core);
|
||||
|
||||
err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
|
||||
SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
|
||||
format);
|
||||
|
||||
si476x_core_unlock(core);
|
||||
|
||||
if (err < 0) {
|
||||
dev_err(codec_dai->codec->dev, "Failed to set output format\n");
|
||||
return err;
|
||||
@@ -193,6 +157,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev);
|
||||
int rate, width, err;
|
||||
|
||||
rate = params_rate(params);
|
||||
@@ -218,11 +183,13 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
si476x_core_lock(core);
|
||||
|
||||
err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
|
||||
rate);
|
||||
if (err < 0) {
|
||||
dev_err(dai->codec->dev, "Failed to set sample rate\n");
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
|
||||
@@ -231,15 +198,18 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
|
||||
(width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
|
||||
if (err < 0) {
|
||||
dev_err(dai->codec->dev, "Failed to set output width\n");
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
si476x_core_unlock(core);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int si476x_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
codec->control_data = i2c_mfd_cell_to_core(codec->dev);
|
||||
codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,8 +238,6 @@ static struct snd_soc_dai_driver si476x_dai = {
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_si476x = {
|
||||
.probe = si476x_codec_probe,
|
||||
.read = si476x_codec_read,
|
||||
.write = si476x_codec_write,
|
||||
.dapm_widgets = si476x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
|
||||
.dapm_routes = si476x_dapm_routes,
|
||||
|
@@ -164,30 +164,28 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
|
||||
}
|
||||
/*end - adc helper functions */
|
||||
|
||||
static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
static int sn95031_read(void *ctx, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
u8 value = 0;
|
||||
int ret;
|
||||
|
||||
ret = intel_scu_ipc_ioread8(reg, &value);
|
||||
if (ret)
|
||||
pr_err("read of %x failed, err %d\n", reg, ret);
|
||||
return value;
|
||||
if (ret == 0)
|
||||
*val = value;
|
||||
|
||||
}
|
||||
|
||||
static inline int sn95031_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_scu_ipc_iowrite8(reg, value);
|
||||
if (ret)
|
||||
pr_err("write of %x failed, err %d\n", reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sn95031_write(void *ctx, unsigned int reg, unsigned int value)
|
||||
{
|
||||
return intel_scu_ipc_iowrite8(reg, value);
|
||||
}
|
||||
|
||||
static const struct regmap_config sn95031_regmap = {
|
||||
.reg_read = sn95031_read,
|
||||
.reg_write = sn95031_write,
|
||||
};
|
||||
|
||||
static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
@@ -827,6 +825,8 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
pr_debug("codec_probe called\n");
|
||||
|
||||
snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
|
||||
|
||||
/* PCM interface config
|
||||
* This sets the pcm rx slot conguration to max 6 slots
|
||||
* for max 4 dais (2 stereo and 2 mono)
|
||||
@@ -886,8 +886,6 @@ static int sn95031_codec_remove(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_codec_driver sn95031_codec = {
|
||||
.probe = sn95031_codec_probe,
|
||||
.remove = sn95031_codec_remove,
|
||||
.read = sn95031_read,
|
||||
.write = sn95031_write,
|
||||
.set_bias_level = sn95031_set_vaud_bias,
|
||||
.idle_bias_off = true,
|
||||
.dapm_widgets = sn95031_dapm_widgets,
|
||||
@@ -898,7 +896,14 @@ static struct snd_soc_codec_driver sn95031_codec = {
|
||||
|
||||
static int sn95031_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
|
||||
pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
|
||||
|
||||
regmap = devm_regmap_init(&pdev->dev, NULL, NULL, &sn95031_regmap);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
|
||||
sn95031_dais, ARRAY_SIZE(sn95031_dais));
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/pcm.h>
|
||||
@@ -244,6 +245,8 @@ struct tas5086_private {
|
||||
unsigned int mclk, sclk;
|
||||
unsigned int format;
|
||||
bool deemph;
|
||||
unsigned int charge_period;
|
||||
unsigned int pwm_start_mid_z;
|
||||
/* Current sample rate for de-emphasis control */
|
||||
int rate;
|
||||
/* GPIO driving Reset pin, if any */
|
||||
@@ -456,6 +459,75 @@ static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
|
||||
}
|
||||
|
||||
static void tas5086_reset(struct tas5086_private *priv)
|
||||
{
|
||||
if (gpio_is_valid(priv->gpio_nreset)) {
|
||||
/* Reset codec - minimum assertion time is 400ns */
|
||||
gpio_direction_output(priv->gpio_nreset, 0);
|
||||
udelay(1);
|
||||
gpio_set_value(priv->gpio_nreset, 1);
|
||||
|
||||
/* Codec needs ~15ms to wake up */
|
||||
msleep(15);
|
||||
}
|
||||
}
|
||||
|
||||
/* charge period values in microseconds */
|
||||
static const int tas5086_charge_period[] = {
|
||||
13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
|
||||
130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
|
||||
1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
|
||||
};
|
||||
|
||||
static int tas5086_init(struct device *dev, struct tas5086_private *priv)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* If any of the channels is configured to start in Mid-Z mode,
|
||||
* configure 'part 1' of the PWM starts to use Mid-Z, and tell
|
||||
* all configured mid-z channels to start start under 'part 1'.
|
||||
*/
|
||||
if (priv->pwm_start_mid_z)
|
||||
regmap_write(priv->regmap, TAS5086_PWM_START,
|
||||
TAS5086_PWM_START_MIDZ_FOR_START_1 |
|
||||
priv->pwm_start_mid_z);
|
||||
|
||||
/* lookup and set split-capacitor charge period */
|
||||
if (priv->charge_period == 0) {
|
||||
regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
|
||||
} else {
|
||||
i = index_in_array(tas5086_charge_period,
|
||||
ARRAY_SIZE(tas5086_charge_period),
|
||||
priv->charge_period);
|
||||
if (i >= 0)
|
||||
regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
|
||||
i + 0x08);
|
||||
else
|
||||
dev_warn(dev,
|
||||
"Invalid split-cap charge period of %d ns.\n",
|
||||
priv->charge_period);
|
||||
}
|
||||
|
||||
/* enable factory trim */
|
||||
ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* start all channels */
|
||||
ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* mute all channels for now */
|
||||
ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
|
||||
TAS5086_SOFT_MUTE_ALL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TAS5086 controls */
|
||||
static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
|
||||
|
||||
@@ -691,14 +763,39 @@ static struct snd_soc_dai_driver tas5086_dai = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tas5086_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
/* Shut down all channels */
|
||||
ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas5086_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
/* Restore codec state */
|
||||
return regcache_sync(priv->regmap);
|
||||
tas5086_reset(priv);
|
||||
regcache_mark_dirty(priv->regmap);
|
||||
|
||||
ret = tas5086_init(codec->dev, priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regcache_sync(priv->regmap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define tas5086_soc_suspend NULL
|
||||
#define tas5086_soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
@@ -710,23 +807,19 @@ static const struct of_device_id tas5086_dt_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
|
||||
#endif
|
||||
|
||||
/* charge period values in microseconds */
|
||||
static const int tas5086_charge_period[] = {
|
||||
13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
|
||||
130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
|
||||
1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
|
||||
};
|
||||
|
||||
static int tas5086_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int charge_period = 1300000; /* hardware default is 1300 ms */
|
||||
u8 pwm_start_mid_z = 0;
|
||||
int i, ret;
|
||||
|
||||
priv->pwm_start_mid_z = 0;
|
||||
priv->charge_period = 1300000; /* hardware default is 1300 ms */
|
||||
|
||||
if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
|
||||
struct device_node *of_node = codec->dev->of_node;
|
||||
of_property_read_u32(of_node, "ti,charge-period", &charge_period);
|
||||
|
||||
of_property_read_u32(of_node, "ti,charge-period",
|
||||
&priv->charge_period);
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
char name[25];
|
||||
@@ -735,43 +828,11 @@ static int tas5086_probe(struct snd_soc_codec *codec)
|
||||
"ti,mid-z-channel-%d", i + 1);
|
||||
|
||||
if (of_get_property(of_node, name, NULL) != NULL)
|
||||
pwm_start_mid_z |= 1 << i;
|
||||
priv->pwm_start_mid_z |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If any of the channels is configured to start in Mid-Z mode,
|
||||
* configure 'part 1' of the PWM starts to use Mid-Z, and tell
|
||||
* all configured mid-z channels to start start under 'part 1'.
|
||||
*/
|
||||
if (pwm_start_mid_z)
|
||||
regmap_write(priv->regmap, TAS5086_PWM_START,
|
||||
TAS5086_PWM_START_MIDZ_FOR_START_1 |
|
||||
pwm_start_mid_z);
|
||||
|
||||
/* lookup and set split-capacitor charge period */
|
||||
if (charge_period == 0) {
|
||||
regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
|
||||
} else {
|
||||
i = index_in_array(tas5086_charge_period,
|
||||
ARRAY_SIZE(tas5086_charge_period),
|
||||
charge_period);
|
||||
if (i >= 0)
|
||||
regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
|
||||
i + 0x08);
|
||||
else
|
||||
dev_warn(codec->dev,
|
||||
"Invalid split-cap charge period of %d ns.\n",
|
||||
charge_period);
|
||||
}
|
||||
|
||||
/* enable factory trim */
|
||||
ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* start all channels */
|
||||
ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
|
||||
ret = tas5086_init(codec->dev, priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -780,12 +841,6 @@ static int tas5086_probe(struct snd_soc_codec *codec)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* mute all channels for now */
|
||||
ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
|
||||
TAS5086_SOFT_MUTE_ALL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -803,6 +858,7 @@ static int tas5086_remove(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
|
||||
.probe = tas5086_probe,
|
||||
.remove = tas5086_remove,
|
||||
.suspend = tas5086_soc_suspend,
|
||||
.resume = tas5086_soc_resume,
|
||||
.controls = tas5086_controls,
|
||||
.num_controls = ARRAY_SIZE(tas5086_controls),
|
||||
@@ -862,17 +918,8 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
|
||||
if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
|
||||
gpio_nreset = -EINVAL;
|
||||
|
||||
if (gpio_is_valid(gpio_nreset)) {
|
||||
/* Reset codec - minimum assertion time is 400ns */
|
||||
gpio_direction_output(gpio_nreset, 0);
|
||||
udelay(1);
|
||||
gpio_set_value(gpio_nreset, 1);
|
||||
|
||||
/* Codec needs ~15ms to wake up */
|
||||
msleep(15);
|
||||
}
|
||||
|
||||
priv->gpio_nreset = gpio_nreset;
|
||||
tas5086_reset(priv);
|
||||
|
||||
/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
|
||||
ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
@@ -37,11 +38,27 @@
|
||||
/*
|
||||
* AIC23 register cache
|
||||
*/
|
||||
static const u16 tlv320aic23_reg[] = {
|
||||
0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
|
||||
0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
|
||||
0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
|
||||
static const struct reg_default tlv320aic23_reg[] = {
|
||||
{ 0, 0x0097 },
|
||||
{ 1, 0x0097 },
|
||||
{ 2, 0x00F9 },
|
||||
{ 3, 0x00F9 },
|
||||
{ 4, 0x001A },
|
||||
{ 5, 0x0004 },
|
||||
{ 6, 0x0007 },
|
||||
{ 7, 0x0001 },
|
||||
{ 8, 0x0020 },
|
||||
{ 9, 0x0000 },
|
||||
};
|
||||
|
||||
static const struct regmap_config tlv320aic23_regmap = {
|
||||
.reg_bits = 7,
|
||||
.val_bits = 9,
|
||||
|
||||
.max_register = TLV320AIC23_RESET,
|
||||
.reg_defaults = tlv320aic23_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const char *rec_src_text[] = { "Line", "Mic" };
|
||||
@@ -171,7 +188,7 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
|
||||
|
||||
/* AIC23 driver data */
|
||||
struct aic23 {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regmap *regmap;
|
||||
int mclk;
|
||||
int requested_adc;
|
||||
int requested_dac;
|
||||
@@ -532,7 +549,9 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec)
|
||||
|
||||
static int tlv320aic23_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_cache_sync(codec);
|
||||
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
|
||||
regcache_mark_dirty(aic23->regmap);
|
||||
regcache_sync(aic23->regmap);
|
||||
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
@@ -540,10 +559,9 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
|
||||
|
||||
static int tlv320aic23_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
@@ -552,16 +570,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
|
||||
/* Reset codec */
|
||||
snd_soc_write(codec, TLV320AIC23_RESET, 0);
|
||||
|
||||
/* Write the register default value to cache for reserved registers,
|
||||
* so the write to the these registers are suppressed by the cache
|
||||
* restore code when it skips writes of default registers.
|
||||
*/
|
||||
snd_soc_cache_write(codec, 0x0A, 0);
|
||||
snd_soc_cache_write(codec, 0x0B, 0);
|
||||
snd_soc_cache_write(codec, 0x0C, 0);
|
||||
snd_soc_cache_write(codec, 0x0D, 0);
|
||||
snd_soc_cache_write(codec, 0x0E, 0);
|
||||
|
||||
/* power on device */
|
||||
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
@@ -586,9 +594,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
|
||||
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
|
||||
|
||||
snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
|
||||
ARRAY_SIZE(tlv320aic23_snd_controls));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -599,21 +604,19 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
|
||||
.reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = tlv320aic23_reg,
|
||||
.probe = tlv320aic23_probe,
|
||||
.remove = tlv320aic23_remove,
|
||||
.suspend = tlv320aic23_suspend,
|
||||
.resume = tlv320aic23_resume,
|
||||
.set_bias_level = tlv320aic23_set_bias_level,
|
||||
.controls = tlv320aic23_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(tlv320aic23_snd_controls),
|
||||
.dapm_widgets = tlv320aic23_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
|
||||
.dapm_routes = tlv320aic23_intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
/*
|
||||
* If the i2c layer weren't so broken, we could pass this kind of data
|
||||
* around
|
||||
@@ -631,8 +634,11 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
|
||||
if (aic23 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
|
||||
if (IS_ERR(aic23->regmap))
|
||||
return PTR_ERR(aic23->regmap);
|
||||
|
||||
i2c_set_clientdata(i2c, aic23);
|
||||
aic23->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
|
||||
@@ -660,29 +666,7 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
|
||||
.id_table = tlv320aic23_id,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int __init tlv320aic23_modinit(void)
|
||||
{
|
||||
int ret;
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
ret = i2c_add_driver(&tlv320aic23_i2c_driver);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
module_init(tlv320aic23_modinit);
|
||||
|
||||
static void __exit tlv320aic23_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
i2c_del_driver(&tlv320aic23_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(tlv320aic23_exit);
|
||||
module_i2c_driver(tlv320aic23_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
|
||||
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
|
||||
|
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL");
|
||||
/* AIC26 driver private data */
|
||||
struct aic26 {
|
||||
struct spi_device *spi;
|
||||
struct regmap *regmap;
|
||||
struct snd_soc_codec *codec;
|
||||
int master;
|
||||
int datfm;
|
||||
@@ -40,85 +41,6 @@ struct aic26 {
|
||||
int keyclick_len;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Register access routines
|
||||
*/
|
||||
static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 *cache = codec->reg_cache;
|
||||
u16 cmd, value;
|
||||
u8 buffer[2];
|
||||
int rc;
|
||||
|
||||
if (reg >= AIC26_NUM_REGS) {
|
||||
WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do SPI transfer; first 16bits are command; remaining is
|
||||
* register contents */
|
||||
cmd = AIC26_READ_COMMAND_WORD(reg);
|
||||
buffer[0] = (cmd >> 8) & 0xff;
|
||||
buffer[1] = cmd & 0xff;
|
||||
rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);
|
||||
if (rc) {
|
||||
dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
|
||||
return -EIO;
|
||||
}
|
||||
value = (buffer[0] << 8) | buffer[1];
|
||||
|
||||
/* Update the cache before returning with the value */
|
||||
cache[reg] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
if (reg >= AIC26_NUM_REGS) {
|
||||
WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 *cache = codec->reg_cache;
|
||||
u16 cmd;
|
||||
u8 buffer[4];
|
||||
int rc;
|
||||
|
||||
if (reg >= AIC26_NUM_REGS) {
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do SPI transfer; first 16bits are command; remaining is data
|
||||
* to write into register */
|
||||
cmd = AIC26_WRITE_COMMAND_WORD(reg);
|
||||
buffer[0] = (cmd >> 8) & 0xff;
|
||||
buffer[1] = cmd & 0xff;
|
||||
buffer[2] = value >> 8;
|
||||
buffer[3] = value;
|
||||
rc = spi_write(aic26->spi, buffer, 4);
|
||||
if (rc) {
|
||||
dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* update cache before returning */
|
||||
cache[reg] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("MICIN"),
|
||||
SND_SOC_DAPM_INPUT("AUX"),
|
||||
@@ -195,19 +117,15 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
|
||||
snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg);
|
||||
|
||||
/* Audio Control 3 (master mode, fsref rate) */
|
||||
reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
|
||||
reg &= ~0xf800;
|
||||
if (aic26->master)
|
||||
reg |= 0x0800;
|
||||
reg = 0x0800;
|
||||
if (fsref == 48000)
|
||||
reg |= 0x2000;
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
reg = 0x2000;
|
||||
snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL3, 0xf800, reg);
|
||||
|
||||
/* Audio Control 1 (FSref divisor) */
|
||||
reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
|
||||
reg &= ~0x0fff;
|
||||
reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
|
||||
reg = wlen | aic26->datfm | (divisor << 3) | divisor;
|
||||
snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL1, 0xfff, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -219,16 +137,16 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
|
||||
u16 reg;
|
||||
|
||||
dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
|
||||
dai, mute);
|
||||
|
||||
if (mute)
|
||||
reg |= 0x8080;
|
||||
reg = 0x8080;
|
||||
else
|
||||
reg &= ~0x8080;
|
||||
snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg);
|
||||
reg = 0;
|
||||
snd_soc_update_bits(codec, AIC26_REG_DAC_GAIN, 0x8000, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -346,7 +264,7 @@ static ssize_t aic26_keyclick_show(struct device *dev,
|
||||
struct aic26 *aic26 = dev_get_drvdata(dev);
|
||||
int val, amp, freq, len;
|
||||
|
||||
val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
val = snd_soc_read(aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
amp = (val >> 12) & 0x7;
|
||||
freq = (125 << ((val >> 8) & 0x7)) >> 1;
|
||||
len = 2 * (1 + ((val >> 4) & 0xf));
|
||||
@@ -360,11 +278,9 @@ static ssize_t aic26_keyclick_set(struct device *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct aic26 *aic26 = dev_get_drvdata(dev);
|
||||
int val;
|
||||
|
||||
val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
val |= 0x8000;
|
||||
snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
|
||||
snd_soc_update_bits(aic26->codec, AIC26_REG_AUDIO_CTRL2,
|
||||
0x8000, 0x800);
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -377,7 +293,9 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
|
||||
static int aic26_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic26 *aic26 = dev_get_drvdata(codec->dev);
|
||||
int ret, err, i, reg;
|
||||
int ret, reg;
|
||||
|
||||
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
|
||||
|
||||
aic26->codec = codec;
|
||||
|
||||
@@ -393,37 +311,30 @@ static int aic26_probe(struct snd_soc_codec *codec)
|
||||
reg |= 0x0800; /* set master mode */
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
|
||||
/* Fill register cache */
|
||||
for (i = 0; i < codec->driver->reg_cache_size; i++)
|
||||
snd_soc_read(codec, i);
|
||||
|
||||
/* Register the sysfs files for debugging */
|
||||
/* Create SysFS files */
|
||||
ret = device_create_file(codec->dev, &dev_attr_keyclick);
|
||||
if (ret)
|
||||
dev_info(codec->dev, "error creating sysfs files\n");
|
||||
|
||||
/* register controls */
|
||||
dev_dbg(codec->dev, "Registering controls\n");
|
||||
err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
|
||||
ARRAY_SIZE(aic26_snd_controls));
|
||||
WARN_ON(err < 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver aic26_soc_codec_dev = {
|
||||
.probe = aic26_probe,
|
||||
.read = aic26_reg_read,
|
||||
.write = aic26_reg_write,
|
||||
.reg_cache_size = AIC26_NUM_REGS,
|
||||
.reg_word_size = sizeof(u16),
|
||||
.controls = aic26_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(aic26_snd_controls),
|
||||
.dapm_widgets = tlv320aic26_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets),
|
||||
.dapm_routes = tlv320aic26_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config aic26_regmap = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 16,
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* SPI device portion of driver: probe and release routines and SPI
|
||||
* driver registration.
|
||||
@@ -440,6 +351,10 @@ static int aic26_spi_probe(struct spi_device *spi)
|
||||
if (!aic26)
|
||||
return -ENOMEM;
|
||||
|
||||
aic26->regmap = devm_regmap_init_spi(spi, &aic26_regmap);
|
||||
if (IS_ERR(aic26->regmap))
|
||||
return PTR_ERR(aic26->regmap);
|
||||
|
||||
/* Initialize the driver data */
|
||||
aic26->spi = spi;
|
||||
dev_set_drvdata(&spi->dev, aic26);
|
||||
|
@@ -9,10 +9,7 @@
|
||||
#define _TLV320AIC16_H_
|
||||
|
||||
/* AIC26 Registers */
|
||||
#define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5))
|
||||
#define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5))
|
||||
#define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset)
|
||||
#define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0)
|
||||
#define AIC26_PAGE_ADDR(page, offset) ((page << 11) | offset << 5)
|
||||
|
||||
/* Page 0: Auxiliary data registers */
|
||||
#define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05)
|
||||
|
@@ -60,9 +60,8 @@ struct aic32x4_rate_divs {
|
||||
};
|
||||
|
||||
struct aic32x4_priv {
|
||||
struct regmap *regmap;
|
||||
u32 sysclk;
|
||||
u8 page_no;
|
||||
void *control_data;
|
||||
u32 power_cfg;
|
||||
u32 micpga_routing;
|
||||
bool swapdacs;
|
||||
@@ -262,67 +261,25 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
|
||||
{"Right ADC", NULL, "Right Input Mixer"},
|
||||
};
|
||||
|
||||
static inline int aic32x4_change_page(struct snd_soc_codec *codec,
|
||||
unsigned int new_page)
|
||||
{
|
||||
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 data[2];
|
||||
int ret;
|
||||
static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
|
||||
{
|
||||
.selector_reg = 0,
|
||||
.selector_mask = 0xff,
|
||||
.window_start = 0,
|
||||
.window_len = 128,
|
||||
.range_min = AIC32X4_PAGE1,
|
||||
.range_max = AIC32X4_PAGE1 + 127,
|
||||
},
|
||||
};
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = new_page & 0xff;
|
||||
static const struct regmap_config aic32x4_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
ret = codec->hw_write(codec->control_data, data, 2);
|
||||
if (ret == 2) {
|
||||
aic32x4->page_no = new_page;
|
||||
return 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int page = reg / 128;
|
||||
unsigned int fixed_reg = reg % 128;
|
||||
u8 data[2];
|
||||
int ret;
|
||||
|
||||
/* A write to AIC32X4_PSEL is really a non-explicit page change */
|
||||
if (reg == AIC32X4_PSEL)
|
||||
return aic32x4_change_page(codec, val);
|
||||
|
||||
if (aic32x4->page_no != page) {
|
||||
ret = aic32x4_change_page(codec, page);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
data[0] = fixed_reg & 0xff;
|
||||
data[1] = val & 0xff;
|
||||
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg)
|
||||
{
|
||||
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int page = reg / 128;
|
||||
unsigned int fixed_reg = reg % 128;
|
||||
int ret;
|
||||
|
||||
if (aic32x4->page_no != page) {
|
||||
ret = aic32x4_change_page(codec, page);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
|
||||
}
|
||||
.max_register = AIC32X4_RMICPGAVOL,
|
||||
.ranges = aic32x4_regmap_pages,
|
||||
.num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
|
||||
};
|
||||
|
||||
static inline int aic32x4_get_divs(int mclk, int rate)
|
||||
{
|
||||
@@ -617,16 +574,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
|
||||
u32 tmp_reg;
|
||||
int ret;
|
||||
|
||||
codec->hw_write = (hw_write_t) i2c_master_send;
|
||||
codec->control_data = aic32x4->control_data;
|
||||
snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
|
||||
if (aic32x4->rstn_gpio >= 0) {
|
||||
ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ndelay(10);
|
||||
gpio_set_value(aic32x4->rstn_gpio, 1);
|
||||
}
|
||||
@@ -692,8 +643,6 @@ static int aic32x4_remove(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
|
||||
.read = aic32x4_read,
|
||||
.write = aic32x4_write,
|
||||
.probe = aic32x4_probe,
|
||||
.remove = aic32x4_remove,
|
||||
.suspend = aic32x4_suspend,
|
||||
@@ -720,7 +669,10 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
|
||||
if (aic32x4 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
aic32x4->control_data = i2c;
|
||||
aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap);
|
||||
if (IS_ERR(aic32x4->regmap))
|
||||
return PTR_ERR(aic32x4->regmap);
|
||||
|
||||
i2c_set_clientdata(i2c, aic32x4);
|
||||
|
||||
if (pdata) {
|
||||
@@ -735,6 +687,13 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
|
||||
aic32x4->rstn_gpio = -1;
|
||||
}
|
||||
|
||||
if (aic32x4->rstn_gpio >= 0) {
|
||||
ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
|
||||
return ret;
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
@@ -72,9 +73,9 @@ struct aic3x_disable_nb {
|
||||
/* codec private data */
|
||||
struct aic3x_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
struct regmap *regmap;
|
||||
struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
|
||||
struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
|
||||
enum snd_soc_control_type control_type;
|
||||
struct aic3x_setup_data *setup;
|
||||
unsigned int sysclk;
|
||||
struct list_head list;
|
||||
@@ -90,41 +91,45 @@ struct aic3x_priv {
|
||||
enum aic3x_micbias_voltage micbias_vg;
|
||||
};
|
||||
|
||||
/*
|
||||
* AIC3X register cache
|
||||
* We can't read the AIC3X register space when we are
|
||||
* using 2 wire for device control, so we cache them instead.
|
||||
* There is no point in caching the reset register
|
||||
*/
|
||||
static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
|
||||
0x00, 0x00, 0x00, 0x10, /* 0 */
|
||||
0x04, 0x00, 0x00, 0x00, /* 4 */
|
||||
0x00, 0x00, 0x00, 0x01, /* 8 */
|
||||
0x00, 0x00, 0x00, 0x80, /* 12 */
|
||||
0x80, 0xff, 0xff, 0x78, /* 16 */
|
||||
0x78, 0x78, 0x78, 0x78, /* 20 */
|
||||
0x78, 0x00, 0x00, 0xfe, /* 24 */
|
||||
0x00, 0x00, 0xfe, 0x00, /* 28 */
|
||||
0x18, 0x18, 0x00, 0x00, /* 32 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 36 */
|
||||
0x00, 0x00, 0x00, 0x80, /* 40 */
|
||||
0x80, 0x00, 0x00, 0x00, /* 44 */
|
||||
0x00, 0x00, 0x00, 0x04, /* 48 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 52 */
|
||||
0x00, 0x00, 0x04, 0x00, /* 56 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 60 */
|
||||
0x00, 0x04, 0x00, 0x00, /* 64 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 68 */
|
||||
0x04, 0x00, 0x00, 0x00, /* 72 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 76 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 80 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 84 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 88 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 92 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 96 */
|
||||
0x00, 0x00, 0x02, 0x00, /* 100 */
|
||||
0x00, 0x00, 0x00, 0x00, /* 104 */
|
||||
0x00, 0x00, /* 108 */
|
||||
static const struct reg_default aic3x_reg[] = {
|
||||
{ 0, 0x00 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x10 },
|
||||
{ 4, 0x04 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
|
||||
{ 8, 0x00 }, { 9, 0x00 }, { 10, 0x00 }, { 11, 0x01 },
|
||||
{ 12, 0x00 }, { 13, 0x00 }, { 14, 0x00 }, { 15, 0x80 },
|
||||
{ 16, 0x80 }, { 17, 0xff }, { 18, 0xff }, { 19, 0x78 },
|
||||
{ 20, 0x78 }, { 21, 0x78 }, { 22, 0x78 }, { 23, 0x78 },
|
||||
{ 24, 0x78 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0xfe },
|
||||
{ 28, 0x00 }, { 29, 0x00 }, { 30, 0xfe }, { 31, 0x00 },
|
||||
{ 32, 0x18 }, { 33, 0x18 }, { 34, 0x00 }, { 35, 0x00 },
|
||||
{ 36, 0x00 }, { 37, 0x00 }, { 38, 0x00 }, { 39, 0x00 },
|
||||
{ 40, 0x00 }, { 41, 0x00 }, { 42, 0x00 }, { 43, 0x80 },
|
||||
{ 44, 0x80 }, { 45, 0x00 }, { 46, 0x00 }, { 47, 0x00 },
|
||||
{ 48, 0x00 }, { 49, 0x00 }, { 50, 0x00 }, { 51, 0x04 },
|
||||
{ 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, { 55, 0x00 },
|
||||
{ 56, 0x00 }, { 57, 0x00 }, { 58, 0x04 }, { 59, 0x00 },
|
||||
{ 60, 0x00 }, { 61, 0x00 }, { 62, 0x00 }, { 63, 0x00 },
|
||||
{ 64, 0x00 }, { 65, 0x04 }, { 66, 0x00 }, { 67, 0x00 },
|
||||
{ 68, 0x00 }, { 69, 0x00 }, { 70, 0x00 }, { 71, 0x00 },
|
||||
{ 72, 0x04 }, { 73, 0x00 }, { 74, 0x00 }, { 75, 0x00 },
|
||||
{ 76, 0x00 }, { 77, 0x00 }, { 78, 0x00 }, { 79, 0x00 },
|
||||
{ 80, 0x00 }, { 81, 0x00 }, { 82, 0x00 }, { 83, 0x00 },
|
||||
{ 84, 0x00 }, { 85, 0x00 }, { 86, 0x00 }, { 87, 0x00 },
|
||||
{ 88, 0x00 }, { 89, 0x00 }, { 90, 0x00 }, { 91, 0x00 },
|
||||
{ 92, 0x00 }, { 93, 0x00 }, { 94, 0x00 }, { 95, 0x00 },
|
||||
{ 96, 0x00 }, { 97, 0x00 }, { 98, 0x00 }, { 99, 0x00 },
|
||||
{ 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 },
|
||||
{ 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 },
|
||||
{ 108, 0x00 }, { 109, 0x00 },
|
||||
};
|
||||
|
||||
static const struct regmap_config aic3x_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = DAC_ICC_ADJ,
|
||||
.reg_defaults = aic3x_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(aic3x_reg),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
|
||||
@@ -828,12 +833,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
|
||||
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
|
||||
ARRAY_SIZE(aic3x_dapm_widgets));
|
||||
|
||||
/* set up audio path interconnects */
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
if (aic3x->model == AIC3X_MODEL_3007) {
|
||||
snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
|
||||
ARRAY_SIZE(aic3007_dapm_widgets));
|
||||
@@ -1082,29 +1081,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aic3x_init_3007(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 tmp1, tmp2, *cache = codec->reg_cache;
|
||||
|
||||
/*
|
||||
* There is no need to cache writes to undocumented page 0xD but
|
||||
* respective page 0 register cache entries must be preserved
|
||||
*/
|
||||
tmp1 = cache[0xD];
|
||||
tmp2 = cache[0x8];
|
||||
/* Class-D speaker driver init; datasheet p. 46 */
|
||||
snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
|
||||
snd_soc_write(codec, 0xD, 0x0D);
|
||||
snd_soc_write(codec, 0x8, 0x5C);
|
||||
snd_soc_write(codec, 0x8, 0x5D);
|
||||
snd_soc_write(codec, 0x8, 0x5C);
|
||||
snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
|
||||
cache[0xD] = tmp1;
|
||||
cache[0x8] = tmp2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aic3x_regulator_event(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
@@ -1119,7 +1095,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
|
||||
*/
|
||||
if (gpio_is_valid(aic3x->gpio_reset))
|
||||
gpio_set_value(aic3x->gpio_reset, 0);
|
||||
aic3x->codec->cache_sync = 1;
|
||||
regcache_mark_dirty(aic3x->regmap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1128,8 +1104,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
|
||||
static int aic3x_set_power(struct snd_soc_codec *codec, int power)
|
||||
{
|
||||
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
u8 *cache = codec->reg_cache;
|
||||
int ret;
|
||||
|
||||
if (power) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
|
||||
@@ -1137,12 +1112,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
|
||||
if (ret)
|
||||
goto out;
|
||||
aic3x->power = 1;
|
||||
/*
|
||||
* Reset release and cache sync is necessary only if some
|
||||
* supply was off or if there were cached writes
|
||||
*/
|
||||
if (!codec->cache_sync)
|
||||
goto out;
|
||||
|
||||
if (gpio_is_valid(aic3x->gpio_reset)) {
|
||||
udelay(1);
|
||||
@@ -1150,12 +1119,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
|
||||
}
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
codec->cache_only = 0;
|
||||
for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++)
|
||||
snd_soc_write(codec, i, cache[i]);
|
||||
if (aic3x->model == AIC3X_MODEL_3007)
|
||||
aic3x_init_3007(codec);
|
||||
codec->cache_sync = 0;
|
||||
regcache_cache_only(aic3x->regmap, false);
|
||||
regcache_sync(aic3x->regmap);
|
||||
} else {
|
||||
/*
|
||||
* Do soft reset to this codec instance in order to clear
|
||||
@@ -1163,10 +1128,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
|
||||
* remain on
|
||||
*/
|
||||
snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
|
||||
codec->cache_sync = 1;
|
||||
regcache_mark_dirty(aic3x->regmap);
|
||||
aic3x->power = 0;
|
||||
/* HW writes are needless when bias is off */
|
||||
codec->cache_only = 1;
|
||||
regcache_cache_only(aic3x->regmap, true);
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
|
||||
aic3x->supplies);
|
||||
}
|
||||
@@ -1321,7 +1286,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
|
||||
snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
|
||||
|
||||
if (aic3x->model == AIC3X_MODEL_3007) {
|
||||
aic3x_init_3007(codec);
|
||||
snd_soc_write(codec, CLASSD_CTRL, 0);
|
||||
}
|
||||
|
||||
@@ -1349,29 +1313,12 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
||||
INIT_LIST_HEAD(&aic3x->list);
|
||||
aic3x->codec = codec;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
|
||||
if (ret != 0)
|
||||
goto err_gpio;
|
||||
gpio_direction_output(aic3x->gpio_reset, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
|
||||
aic3x->supplies[i].supply = aic3x_supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
|
||||
aic3x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
|
||||
goto err_get;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
|
||||
aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
|
||||
aic3x->disable_nb[i].aic3x = aic3x;
|
||||
@@ -1385,7 +1332,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
}
|
||||
|
||||
codec->cache_only = 1;
|
||||
regcache_mark_dirty(aic3x->regmap);
|
||||
aic3x_init(codec);
|
||||
|
||||
if (aic3x->setup) {
|
||||
@@ -1396,8 +1343,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
||||
(aic3x->setup->gpio_func[1] & 0xf) << 4);
|
||||
}
|
||||
|
||||
snd_soc_add_codec_controls(codec, aic3x_snd_controls,
|
||||
ARRAY_SIZE(aic3x_snd_controls));
|
||||
if (aic3x->model == AIC3X_MODEL_3007)
|
||||
snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
|
||||
|
||||
@@ -1428,12 +1373,6 @@ err_notif:
|
||||
while (i--)
|
||||
regulator_unregister_notifier(aic3x->supplies[i].consumer,
|
||||
&aic3x->disable_nb[i].nb);
|
||||
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
|
||||
err_get:
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x))
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
err_gpio:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1444,15 +1383,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
|
||||
|
||||
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
list_del(&aic3x->list);
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
gpio_set_value(aic3x->gpio_reset, 0);
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
|
||||
regulator_unregister_notifier(aic3x->supplies[i].consumer,
|
||||
&aic3x->disable_nb[i].nb);
|
||||
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1460,13 +1393,16 @@ static int aic3x_remove(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
|
||||
.set_bias_level = aic3x_set_bias_level,
|
||||
.idle_bias_off = true,
|
||||
.reg_cache_size = ARRAY_SIZE(aic3x_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = aic3x_reg,
|
||||
.probe = aic3x_probe,
|
||||
.remove = aic3x_remove,
|
||||
.suspend = aic3x_suspend,
|
||||
.resume = aic3x_resume,
|
||||
.controls = aic3x_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(aic3x_snd_controls),
|
||||
.dapm_widgets = aic3x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
|
||||
.dapm_routes = intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(intercon),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1483,6 +1419,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
|
||||
|
||||
static const struct reg_default aic3007_class_d[] = {
|
||||
/* Class-D speaker driver init; datasheet p. 46 */
|
||||
{ AIC3X_PAGE_SELECT, 0x0D },
|
||||
{ 0xD, 0x0D },
|
||||
{ 0x8, 0x5C },
|
||||
{ 0x8, 0x5D },
|
||||
{ 0x8, 0x5C },
|
||||
{ AIC3X_PAGE_SELECT, 0x00 },
|
||||
};
|
||||
|
||||
/*
|
||||
* If the i2c layer weren't so broken, we could pass this kind of data
|
||||
* around
|
||||
@@ -1494,7 +1440,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
struct aic3x_priv *aic3x;
|
||||
struct aic3x_setup_data *ai3x_setup;
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
int ret;
|
||||
int ret, i;
|
||||
u32 value;
|
||||
|
||||
aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
|
||||
@@ -1503,7 +1449,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
aic3x->control_type = SND_SOC_I2C;
|
||||
aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
|
||||
if (IS_ERR(aic3x->regmap)) {
|
||||
ret = PTR_ERR(aic3x->regmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regcache_cache_only(aic3x->regmap, true);
|
||||
|
||||
i2c_set_clientdata(i2c, aic3x);
|
||||
if (pdata) {
|
||||
@@ -1555,14 +1507,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
aic3x->model = id->driver_data;
|
||||
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
gpio_direction_output(aic3x->gpio_reset, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
|
||||
aic3x->supplies[i].supply = aic3x_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies),
|
||||
aic3x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
if (aic3x->model == AIC3X_MODEL_3007) {
|
||||
ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
|
||||
ARRAY_SIZE(aic3007_class_d));
|
||||
if (ret != 0)
|
||||
dev_err(&i2c->dev, "Failed to init class D: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_aic3x, &aic3x_dai, 1);
|
||||
return ret;
|
||||
|
||||
err_gpio:
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x))
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aic3x_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct aic3x_priv *aic3x = i2c_get_clientdata(client);
|
||||
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
gpio_set_value(aic3x->gpio_reset, 0);
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <sound/tpa6130a2-plat.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include "tpa6130a2.h"
|
||||
|
||||
@@ -364,30 +365,33 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
||||
{
|
||||
struct device *dev;
|
||||
struct tpa6130a2_data *data;
|
||||
struct tpa6130a2_platform_data *pdata;
|
||||
struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
const char *regulator;
|
||||
int ret;
|
||||
|
||||
dev = &client->dev;
|
||||
|
||||
if (client->dev.platform_data == NULL) {
|
||||
dev_err(dev, "Platform data not set\n");
|
||||
dump_stack();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
dev_err(dev, "Can not allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
data->power_gpio = pdata->power_gpio;
|
||||
} else if (np) {
|
||||
data->power_gpio = of_get_named_gpio(np, "power-gpio", 0);
|
||||
} else {
|
||||
dev_err(dev, "Platform data not set\n");
|
||||
dump_stack();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
tpa6130a2_client = client;
|
||||
|
||||
i2c_set_clientdata(tpa6130a2_client, data);
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
data->power_gpio = pdata->power_gpio;
|
||||
data->id = id->driver_data;
|
||||
|
||||
mutex_init(&data->mutex);
|
||||
@@ -466,10 +470,20 @@ static const struct i2c_device_id tpa6130a2_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id tpa6130a2_of_match[] = {
|
||||
{ .compatible = "ti,tpa6130a2", },
|
||||
{ .compatible = "ti,tpa6140a2" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tpa6130a2_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver tpa6130a2_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tpa6130a2",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(tpa6130a2_of_match),
|
||||
},
|
||||
.probe = tpa6130a2_probe,
|
||||
.remove = tpa6130a2_remove,
|
||||
|
@@ -46,13 +46,7 @@
|
||||
/* TWL4030 PMBR1 Register GPIO6 mux bits */
|
||||
#define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2)
|
||||
|
||||
/* Shadow register used by the audio driver */
|
||||
#define TWL4030_REG_SW_SHADOW 0x4A
|
||||
#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
|
||||
|
||||
/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
|
||||
#define TWL4030_HFL_EN 0x01
|
||||
#define TWL4030_HFR_EN 0x02
|
||||
#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
|
||||
|
||||
/*
|
||||
* twl4030 register cache & default register settings
|
||||
@@ -132,7 +126,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
|
||||
0x00, /* REG_VIBRA_PWM_SET (0x47) */
|
||||
0x00, /* REG_ANAMIC_GAIN (0x48) */
|
||||
0x00, /* REG_MISC_SET_2 (0x49) */
|
||||
0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */
|
||||
};
|
||||
|
||||
/* codec private data */
|
||||
@@ -198,42 +191,41 @@ static int twl4030_write(struct snd_soc_codec *codec,
|
||||
int write_to_reg = 0;
|
||||
|
||||
twl4030_write_reg_cache(codec, reg, value);
|
||||
if (likely(reg < TWL4030_REG_SW_SHADOW)) {
|
||||
/* Decide if the given register can be written */
|
||||
switch (reg) {
|
||||
case TWL4030_REG_EAR_CTL:
|
||||
if (twl4030->earpiece_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PREDL_CTL:
|
||||
if (twl4030->predrivel_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PREDR_CTL:
|
||||
if (twl4030->predriver_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PRECKL_CTL:
|
||||
if (twl4030->carkitl_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PRECKR_CTL:
|
||||
if (twl4030->carkitr_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_HS_GAIN_SET:
|
||||
if (twl4030->hsl_enabled || twl4030->hsr_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
default:
|
||||
/* All other register can be written */
|
||||
/* Decide if the given register can be written */
|
||||
switch (reg) {
|
||||
case TWL4030_REG_EAR_CTL:
|
||||
if (twl4030->earpiece_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
}
|
||||
if (write_to_reg)
|
||||
return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
|
||||
value, reg);
|
||||
break;
|
||||
case TWL4030_REG_PREDL_CTL:
|
||||
if (twl4030->predrivel_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PREDR_CTL:
|
||||
if (twl4030->predriver_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PRECKL_CTL:
|
||||
if (twl4030->carkitl_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_PRECKR_CTL:
|
||||
if (twl4030->carkitr_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
case TWL4030_REG_HS_GAIN_SET:
|
||||
if (twl4030->hsl_enabled || twl4030->hsr_enabled)
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
default:
|
||||
/* All other register can be written */
|
||||
write_to_reg = 1;
|
||||
break;
|
||||
}
|
||||
if (write_to_reg)
|
||||
return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
|
||||
value, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,7 +524,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
|
||||
|
||||
/* Handsfree Left virtual mute */
|
||||
static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
|
||||
SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
|
||||
SOC_DAPM_SINGLE_VIRT("Switch", 1);
|
||||
|
||||
/* Handsfree Right */
|
||||
static const char *twl4030_handsfreer_texts[] =
|
||||
@@ -548,7 +540,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
|
||||
|
||||
/* Handsfree Right virtual mute */
|
||||
static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
|
||||
SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
|
||||
SOC_DAPM_SINGLE_VIRT("Switch", 1);
|
||||
|
||||
/* Vibra */
|
||||
/* Vibra audio path selection */
|
||||
|
@@ -54,12 +54,7 @@ enum twl6040_dai_id {
|
||||
#define TWL6040_OUTHF_0dB 0x03
|
||||
#define TWL6040_OUTHF_M52dB 0x1D
|
||||
|
||||
/* Shadow register used by the driver */
|
||||
#define TWL6040_REG_SW_SHADOW 0x2F
|
||||
#define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1)
|
||||
|
||||
/* TWL6040_REG_SW_SHADOW (0x2F) fields */
|
||||
#define TWL6040_EAR_PATH_ENABLE 0x01
|
||||
#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
|
||||
|
||||
struct twl6040_jack_data {
|
||||
struct snd_soc_jack *jack;
|
||||
@@ -135,8 +130,6 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
|
||||
0x00, /* REG_HFOTRIM 0x2C */
|
||||
0x09, /* REG_ACCCTL 0x2D */
|
||||
0x00, /* REG_STATUS 0x2E (ro) */
|
||||
|
||||
0x00, /* REG_SW_SHADOW 0x2F - Shadow, non HW register */
|
||||
};
|
||||
|
||||
/* List of registers to be restored after power up */
|
||||
@@ -220,12 +213,8 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
|
||||
if (reg >= TWL6040_CACHEREGNUM)
|
||||
return -EIO;
|
||||
|
||||
if (likely(reg < TWL6040_REG_SW_SHADOW)) {
|
||||
value = twl6040_reg_read(twl6040, reg);
|
||||
twl6040_write_reg_cache(codec, reg, value);
|
||||
} else {
|
||||
value = twl6040_read_reg_cache(codec, reg);
|
||||
}
|
||||
value = twl6040_reg_read(twl6040, reg);
|
||||
twl6040_write_reg_cache(codec, reg, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -246,7 +235,7 @@ static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec,
|
||||
return priv->dl2_unmuted;
|
||||
default:
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -261,8 +250,7 @@ static int twl6040_write(struct snd_soc_codec *codec,
|
||||
return -EIO;
|
||||
|
||||
twl6040_write_reg_cache(codec, reg, value);
|
||||
if (likely(reg < TWL6040_REG_SW_SHADOW) &&
|
||||
twl6040_is_path_unmuted(codec, reg))
|
||||
if (twl6040_is_path_unmuted(codec, reg))
|
||||
return twl6040_reg_write(twl6040, reg, value);
|
||||
else
|
||||
return 0;
|
||||
@@ -555,7 +543,7 @@ static const struct snd_kcontrol_new hfr_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
|
||||
|
||||
static const struct snd_kcontrol_new ep_path_enable_control =
|
||||
SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
|
||||
SOC_DAPM_SINGLE_VIRT("Switch", 1);
|
||||
|
||||
static const struct snd_kcontrol_new auxl_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
|
||||
@@ -1100,7 +1088,7 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
|
@@ -32,13 +32,6 @@
|
||||
|
||||
#include "wm8400.h"
|
||||
|
||||
/* Fake register for internal state */
|
||||
#define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1)
|
||||
#define WM8400_INMIXL_PWR 0
|
||||
#define WM8400_AINLMUX_PWR 1
|
||||
#define WM8400_INMIXR_PWR 2
|
||||
#define WM8400_AINRMUX_PWR 3
|
||||
|
||||
static struct regulator_bulk_data power[] = {
|
||||
{
|
||||
.supply = "I2S1VDD",
|
||||
@@ -74,32 +67,6 @@ struct wm8400_priv {
|
||||
int fll_in, fll_out;
|
||||
};
|
||||
|
||||
static inline unsigned int wm8400_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (reg == WM8400_INTDRIVBITS)
|
||||
return wm8400->fake_register;
|
||||
else
|
||||
return wm8400_reg_read(wm8400->wm8400, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* write to the wm8400 register space
|
||||
*/
|
||||
static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (reg == WM8400_INTDRIVBITS) {
|
||||
wm8400->fake_register = value;
|
||||
return 0;
|
||||
} else
|
||||
return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value);
|
||||
}
|
||||
|
||||
static void wm8400_codec_reset(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
|
||||
@@ -352,32 +319,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
|
||||
* _DAPM_ Controls
|
||||
*/
|
||||
|
||||
static int inmixer_event (struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
u16 reg, fakepower;
|
||||
|
||||
reg = snd_soc_read(w->codec, WM8400_POWER_MANAGEMENT_2);
|
||||
fakepower = snd_soc_read(w->codec, WM8400_INTDRIVBITS);
|
||||
|
||||
if (fakepower & ((1 << WM8400_INMIXL_PWR) |
|
||||
(1 << WM8400_AINLMUX_PWR))) {
|
||||
reg |= WM8400_AINL_ENA;
|
||||
} else {
|
||||
reg &= ~WM8400_AINL_ENA;
|
||||
}
|
||||
|
||||
if (fakepower & ((1 << WM8400_INMIXR_PWR) |
|
||||
(1 << WM8400_AINRMUX_PWR))) {
|
||||
reg |= WM8400_AINR_ENA;
|
||||
} else {
|
||||
reg &= ~WM8400_AINR_ENA;
|
||||
}
|
||||
snd_soc_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int outmixer_event (struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol * kcontrol, int event)
|
||||
{
|
||||
@@ -658,27 +599,26 @@ SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2,
|
||||
0, &wm8400_dapm_rin34_pga_controls[0],
|
||||
ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("INL", WM8400_POWER_MANAGEMENT_2, WM8400_AINL_ENA_SHIFT,
|
||||
0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("INR", WM8400_POWER_MANAGEMENT_2, WM8400_AINR_ENA_SHIFT,
|
||||
0, NULL, 0),
|
||||
|
||||
/* INMIXL */
|
||||
SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0,
|
||||
SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
|
||||
&wm8400_dapm_inmixl_controls[0],
|
||||
ARRAY_SIZE(wm8400_dapm_inmixl_controls),
|
||||
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
ARRAY_SIZE(wm8400_dapm_inmixl_controls)),
|
||||
|
||||
/* AINLMUX */
|
||||
SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0,
|
||||
&wm8400_dapm_ainlmux_controls, inmixer_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX("AILNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainlmux_controls),
|
||||
|
||||
/* INMIXR */
|
||||
SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0,
|
||||
SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
|
||||
&wm8400_dapm_inmixr_controls[0],
|
||||
ARRAY_SIZE(wm8400_dapm_inmixr_controls),
|
||||
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
ARRAY_SIZE(wm8400_dapm_inmixr_controls)),
|
||||
|
||||
/* AINRMUX */
|
||||
SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0,
|
||||
&wm8400_dapm_ainrmux_controls, inmixer_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX("AIRNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainrmux_controls),
|
||||
|
||||
/* Output Side */
|
||||
/* DACs */
|
||||
@@ -789,11 +729,13 @@ static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
|
||||
{"LIN34 PGA", "LIN3 Switch", "LIN3"},
|
||||
{"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
|
||||
/* INMIXL */
|
||||
{"INMIXL", NULL, "INL"},
|
||||
{"INMIXL", "Record Left Volume", "LOMIX"},
|
||||
{"INMIXL", "LIN2 Volume", "LIN2"},
|
||||
{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
|
||||
{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
|
||||
/* AILNMUX */
|
||||
{"AILNMUX", NULL, "INL"},
|
||||
{"AILNMUX", "INMIXL Mix", "INMIXL"},
|
||||
{"AILNMUX", "DIFFINL Mix", "LIN12 PGA"},
|
||||
{"AILNMUX", "DIFFINL Mix", "LIN34 PGA"},
|
||||
@@ -808,12 +750,14 @@ static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
|
||||
/* RIN34 PGA */
|
||||
{"RIN34 PGA", "RIN3 Switch", "RIN3"},
|
||||
{"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
|
||||
/* INMIXL */
|
||||
/* INMIXR */
|
||||
{"INMIXR", NULL, "INR"},
|
||||
{"INMIXR", "Record Right Volume", "ROMIX"},
|
||||
{"INMIXR", "RIN2 Volume", "RIN2"},
|
||||
{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
|
||||
{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
|
||||
/* AIRNMUX */
|
||||
{"AIRNMUX", NULL, "INR"},
|
||||
{"AIRNMUX", "INMIXR Mix", "INMIXR"},
|
||||
{"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"},
|
||||
{"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"},
|
||||
@@ -1365,9 +1309,12 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
|
||||
return -ENOMEM;
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, priv);
|
||||
codec->control_data = priv->wm8400 = wm8400;
|
||||
priv->wm8400 = wm8400;
|
||||
codec->control_data = wm8400->regmap;
|
||||
priv->codec = codec;
|
||||
|
||||
snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
|
||||
|
||||
ret = devm_regulator_bulk_get(wm8400->dev,
|
||||
ARRAY_SIZE(power), &power[0]);
|
||||
if (ret != 0) {
|
||||
@@ -1414,8 +1361,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
|
||||
.remove = wm8400_codec_remove,
|
||||
.suspend = wm8400_suspend,
|
||||
.resume = wm8400_resume,
|
||||
.read = snd_soc_read,
|
||||
.write = wm8400_write,
|
||||
.set_bias_level = wm8400_set_bias_level,
|
||||
|
||||
.controls = wm8400_snd_controls,
|
||||
|
@@ -3242,7 +3242,7 @@ static void wm8962_free_beep(struct snd_soc_codec *codec)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
|
||||
static void wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio)
|
||||
{
|
||||
int mask = 0;
|
||||
int val = 0;
|
||||
@@ -3263,8 +3263,8 @@ static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
|
||||
}
|
||||
|
||||
if (mask)
|
||||
snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,
|
||||
mask, val);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_ANALOGUE_CLOCKING1,
|
||||
mask, val);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
@@ -3276,7 +3276,6 @@ static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip)
|
||||
static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
|
||||
struct snd_soc_codec *codec = wm8962->codec;
|
||||
|
||||
/* The WM8962 GPIOs aren't linearly numbered. For simplicity
|
||||
* we export linear numbers and error out if the unsupported
|
||||
@@ -3292,7 +3291,7 @@ static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wm8962_set_gpio_mode(codec, offset + 1);
|
||||
wm8962_set_gpio_mode(wm8962, offset + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3376,8 +3375,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm8962_pdata *pdata = &wm8962->pdata;
|
||||
int i, trigger, irq_pol;
|
||||
int i;
|
||||
bool dmicclk, dmicdat;
|
||||
|
||||
wm8962->codec = codec;
|
||||
@@ -3409,75 +3407,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
}
|
||||
|
||||
/* SYSCLK defaults to on; make sure it is off so we can safely
|
||||
* write to registers if the device is declocked.
|
||||
*/
|
||||
snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
|
||||
|
||||
/* Ensure we have soft control over all registers */
|
||||
snd_soc_update_bits(codec, WM8962_CLOCKING2,
|
||||
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
|
||||
|
||||
/* Ensure that the oscillator and PLLs are disabled */
|
||||
snd_soc_update_bits(codec, WM8962_PLL2,
|
||||
WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
|
||||
0);
|
||||
|
||||
/* Apply static configuration for GPIOs */
|
||||
for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
|
||||
if (pdata->gpio_init[i]) {
|
||||
wm8962_set_gpio_mode(codec, i + 1);
|
||||
snd_soc_write(codec, 0x200 + i,
|
||||
pdata->gpio_init[i] & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
/* Put the speakers into mono mode? */
|
||||
if (pdata->spk_mono)
|
||||
snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2,
|
||||
WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
|
||||
|
||||
/* Micbias setup, detection enable and detection
|
||||
* threasholds. */
|
||||
if (pdata->mic_cfg)
|
||||
snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
|
||||
WM8962_MICDET_ENA |
|
||||
WM8962_MICDET_THR_MASK |
|
||||
WM8962_MICSHORT_THR_MASK |
|
||||
WM8962_MICBIAS_LVL,
|
||||
pdata->mic_cfg);
|
||||
|
||||
/* Latch volume update bits */
|
||||
snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
|
||||
WM8962_IN_VU, WM8962_IN_VU);
|
||||
snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
|
||||
WM8962_IN_VU, WM8962_IN_VU);
|
||||
snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
|
||||
WM8962_ADC_VU, WM8962_ADC_VU);
|
||||
snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
|
||||
WM8962_ADC_VU, WM8962_ADC_VU);
|
||||
snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME,
|
||||
WM8962_DAC_VU, WM8962_DAC_VU);
|
||||
snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME,
|
||||
WM8962_DAC_VU, WM8962_DAC_VU);
|
||||
snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
|
||||
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
|
||||
snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
|
||||
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
|
||||
snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
|
||||
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
|
||||
snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
|
||||
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
|
||||
|
||||
/* Stereo control for EQ */
|
||||
snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
|
||||
|
||||
/* Don't debouce interrupts so we don't need SYSCLK */
|
||||
snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE,
|
||||
WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
|
||||
WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
|
||||
0);
|
||||
|
||||
wm8962_add_widgets(codec);
|
||||
|
||||
/* Save boards having to disable DMIC when not in use */
|
||||
@@ -3506,36 +3435,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
|
||||
wm8962_init_beep(codec);
|
||||
wm8962_init_gpio(codec);
|
||||
|
||||
if (wm8962->irq) {
|
||||
if (pdata->irq_active_low) {
|
||||
trigger = IRQF_TRIGGER_LOW;
|
||||
irq_pol = WM8962_IRQ_POL;
|
||||
} else {
|
||||
trigger = IRQF_TRIGGER_HIGH;
|
||||
irq_pol = 0;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
|
||||
WM8962_IRQ_POL, irq_pol);
|
||||
|
||||
ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
|
||||
trigger | IRQF_ONESHOT,
|
||||
"wm8962", codec->dev);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
|
||||
wm8962->irq, ret);
|
||||
wm8962->irq = 0;
|
||||
/* Non-fatal */
|
||||
} else {
|
||||
/* Enable some IRQs by default */
|
||||
snd_soc_update_bits(codec,
|
||||
WM8962_INTERRUPT_STATUS_2_MASK,
|
||||
WM8962_FLL_LOCK_EINT |
|
||||
WM8962_TEMP_SHUT_EINT |
|
||||
WM8962_FIFOS_ERR_EINT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3544,9 +3443,6 @@ static int wm8962_remove(struct snd_soc_codec *codec)
|
||||
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
|
||||
if (wm8962->irq)
|
||||
free_irq(wm8962->irq, codec);
|
||||
|
||||
cancel_delayed_work_sync(&wm8962->mic_work);
|
||||
|
||||
wm8962_free_gpio(codec);
|
||||
@@ -3619,7 +3515,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
|
||||
struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
|
||||
struct wm8962_priv *wm8962;
|
||||
unsigned int reg;
|
||||
int ret, i;
|
||||
int ret, i, irq_pol, trigger;
|
||||
|
||||
wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
|
||||
GFP_KERNEL);
|
||||
@@ -3704,6 +3600,77 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
/* SYSCLK defaults to on; make sure it is off so we can safely
|
||||
* write to registers if the device is declocked.
|
||||
*/
|
||||
regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
|
||||
WM8962_SYSCLK_ENA, 0);
|
||||
|
||||
/* Ensure we have soft control over all registers */
|
||||
regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
|
||||
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
|
||||
|
||||
/* Ensure that the oscillator and PLLs are disabled */
|
||||
regmap_update_bits(wm8962->regmap, WM8962_PLL2,
|
||||
WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
|
||||
0);
|
||||
|
||||
/* Apply static configuration for GPIOs */
|
||||
for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
|
||||
if (pdata->gpio_init[i]) {
|
||||
wm8962_set_gpio_mode(wm8962, i + 1);
|
||||
regmap_write(wm8962->regmap, 0x200 + i,
|
||||
pdata->gpio_init[i] & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
/* Put the speakers into mono mode? */
|
||||
if (pdata->spk_mono)
|
||||
regmap_update_bits(wm8962->regmap, WM8962_CLASS_D_CONTROL_2,
|
||||
WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
|
||||
|
||||
/* Micbias setup, detection enable and detection
|
||||
* threasholds. */
|
||||
if (pdata->mic_cfg)
|
||||
regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4,
|
||||
WM8962_MICDET_ENA |
|
||||
WM8962_MICDET_THR_MASK |
|
||||
WM8962_MICSHORT_THR_MASK |
|
||||
WM8962_MICBIAS_LVL,
|
||||
pdata->mic_cfg);
|
||||
|
||||
/* Latch volume update bits */
|
||||
regmap_update_bits(wm8962->regmap, WM8962_LEFT_INPUT_VOLUME,
|
||||
WM8962_IN_VU, WM8962_IN_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME,
|
||||
WM8962_IN_VU, WM8962_IN_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_LEFT_ADC_VOLUME,
|
||||
WM8962_ADC_VU, WM8962_ADC_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_RIGHT_ADC_VOLUME,
|
||||
WM8962_ADC_VU, WM8962_ADC_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_LEFT_DAC_VOLUME,
|
||||
WM8962_DAC_VU, WM8962_DAC_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_RIGHT_DAC_VOLUME,
|
||||
WM8962_DAC_VU, WM8962_DAC_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_SPKOUTL_VOLUME,
|
||||
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_SPKOUTR_VOLUME,
|
||||
WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_HPOUTL_VOLUME,
|
||||
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
|
||||
regmap_update_bits(wm8962->regmap, WM8962_HPOUTR_VOLUME,
|
||||
WM8962_HPOUT_VU, WM8962_HPOUT_VU);
|
||||
|
||||
/* Stereo control for EQ */
|
||||
regmap_update_bits(wm8962->regmap, WM8962_EQ1,
|
||||
WM8962_EQ_SHARED_COEFF, 0);
|
||||
|
||||
/* Don't debouce interrupts so we don't need SYSCLK */
|
||||
regmap_update_bits(wm8962->regmap, WM8962_IRQ_DEBOUNCE,
|
||||
WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
|
||||
WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
|
||||
0);
|
||||
|
||||
if (wm8962->pdata.in4_dc_measure) {
|
||||
ret = regmap_register_patch(wm8962->regmap,
|
||||
wm8962_dc_measure,
|
||||
@@ -3714,6 +3681,37 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
|
||||
ret);
|
||||
}
|
||||
|
||||
if (wm8962->irq) {
|
||||
if (pdata->irq_active_low) {
|
||||
trigger = IRQF_TRIGGER_LOW;
|
||||
irq_pol = WM8962_IRQ_POL;
|
||||
} else {
|
||||
trigger = IRQF_TRIGGER_HIGH;
|
||||
irq_pol = 0;
|
||||
}
|
||||
|
||||
regmap_update_bits(wm8962->regmap, WM8962_INTERRUPT_CONTROL,
|
||||
WM8962_IRQ_POL, irq_pol);
|
||||
|
||||
ret = devm_request_threaded_irq(&i2c->dev, wm8962->irq, NULL,
|
||||
wm8962_irq,
|
||||
trigger | IRQF_ONESHOT,
|
||||
"wm8962", &i2c->dev);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
|
||||
wm8962->irq, ret);
|
||||
wm8962->irq = 0;
|
||||
/* Non-fatal */
|
||||
} else {
|
||||
/* Enable some IRQs by default */
|
||||
regmap_update_bits(wm8962->regmap,
|
||||
WM8962_INTERRUPT_STATUS_2_MASK,
|
||||
WM8962_FLL_LOCK_EINT |
|
||||
WM8962_TEMP_SHUT_EINT |
|
||||
WM8962_FIFOS_ERR_EINT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_enable(&i2c->dev);
|
||||
pm_request_idle(&i2c->dev);
|
||||
|
||||
|
@@ -1,9 +1,10 @@
|
||||
config SND_DAVINCI_SOC
|
||||
tristate "SoC Audio for the TI DAVINCI chip"
|
||||
depends on ARCH_DAVINCI
|
||||
tristate "SoC Audio for the TI DAVINCI or AM33XX chip"
|
||||
depends on ARCH_DAVINCI || SOC_AM33XX
|
||||
help
|
||||
Platform driver for daVinci or AM33xx
|
||||
Say Y or M if you want to add support for codecs attached to
|
||||
the DAVINCI AC97 or I2S interface. You will also need
|
||||
the DAVINCI AC97, I2S, or McASP interface. You will also need
|
||||
to select the audio interfaces to support below.
|
||||
|
||||
config SND_DAVINCI_SOC_I2S
|
||||
@@ -15,6 +16,17 @@ config SND_DAVINCI_SOC_MCASP
|
||||
config SND_DAVINCI_SOC_VCIF
|
||||
tristate
|
||||
|
||||
config SND_AM33XX_SOC_EVM
|
||||
tristate "SoC Audio for the AM33XX chip based boards"
|
||||
depends on SND_DAVINCI_SOC && SOC_AM33XX
|
||||
select SND_SOC_TLV320AIC3X
|
||||
select SND_DAVINCI_SOC_MCASP
|
||||
help
|
||||
Say Y or M if you want to add support for SoC audio on AM33XX
|
||||
boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
|
||||
AM335X-EVMSK, and BeagelBone with AudioCape boards have this
|
||||
setup.
|
||||
|
||||
config SND_DAVINCI_SOC_EVM
|
||||
tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
|
||||
depends on SND_DAVINCI_SOC
|
||||
|
@@ -13,6 +13,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
|
||||
snd-soc-evm-objs := davinci-evm.o
|
||||
|
||||
obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
|
||||
obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o
|
||||
obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
|
||||
obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
|
||||
obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/edma.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
@@ -23,10 +24,16 @@
|
||||
#include <asm/dma.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <linux/edma.h>
|
||||
|
||||
#include "davinci-pcm.h"
|
||||
#include "davinci-i2s.h"
|
||||
#include "davinci-mcasp.h"
|
||||
|
||||
struct snd_soc_card_drvdata_davinci {
|
||||
unsigned sysclk;
|
||||
};
|
||||
|
||||
#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
|
||||
SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
|
||||
static int evm_hw_params(struct snd_pcm_substream *substream,
|
||||
@@ -35,27 +42,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_card *soc_card = codec->card;
|
||||
int ret = 0;
|
||||
unsigned sysclk;
|
||||
|
||||
/* ASP1 on DM355 EVM is clocked by an external oscillator */
|
||||
if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
|
||||
machine_is_davinci_dm365_evm())
|
||||
sysclk = 27000000;
|
||||
|
||||
/* ASP0 in DM6446 EVM is clocked by U55, as configured by
|
||||
* board-dm644x-evm.c using GPIOs from U18. There are six
|
||||
* options; here we "know" we use a 48 KHz sample rate.
|
||||
*/
|
||||
else if (machine_is_davinci_evm())
|
||||
sysclk = 12288000;
|
||||
|
||||
else if (machine_is_davinci_da830_evm() ||
|
||||
machine_is_davinci_da850_evm())
|
||||
sysclk = 24576000;
|
||||
|
||||
else
|
||||
return -EINVAL;
|
||||
unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
|
||||
snd_soc_card_get_drvdata(soc_card))->sysclk;
|
||||
|
||||
/* set codec DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
|
||||
@@ -133,13 +124,22 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct device_node *np = codec->card->dev->of_node;
|
||||
int ret;
|
||||
|
||||
/* Add davinci-evm specific widgets */
|
||||
snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
|
||||
ARRAY_SIZE(aic3x_dapm_widgets));
|
||||
|
||||
/* Set up davinci-evm specific audio path audio_map */
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
if (np) {
|
||||
ret = snd_soc_of_parse_audio_routing(codec->card,
|
||||
"ti,audio-routing");
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* Set up davinci-evm specific audio path audio_map */
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
}
|
||||
|
||||
/* not connected */
|
||||
snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
|
||||
@@ -243,35 +243,65 @@ static struct snd_soc_dai_link da850_evm_dai = {
|
||||
};
|
||||
|
||||
/* davinci dm6446 evm audio machine driver */
|
||||
/*
|
||||
* ASP0 in DM6446 EVM is clocked by U55, as configured by
|
||||
* board-dm644x-evm.c using GPIOs from U18. There are six
|
||||
* options; here we "know" we use a 48 KHz sample rate.
|
||||
*/
|
||||
static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
|
||||
.sysclk = 12288000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card dm6446_snd_soc_card_evm = {
|
||||
.name = "DaVinci DM6446 EVM",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &dm6446_evm_dai,
|
||||
.num_links = 1,
|
||||
.drvdata = &dm6446_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
/* davinci dm355 evm audio machine driver */
|
||||
/* ASP1 on DM355 EVM is clocked by an external oscillator */
|
||||
static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
|
||||
.sysclk = 27000000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card dm355_snd_soc_card_evm = {
|
||||
.name = "DaVinci DM355 EVM",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &dm355_evm_dai,
|
||||
.num_links = 1,
|
||||
.drvdata = &dm355_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
/* davinci dm365 evm audio machine driver */
|
||||
static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
|
||||
.sysclk = 27000000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card dm365_snd_soc_card_evm = {
|
||||
.name = "DaVinci DM365 EVM",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &dm365_evm_dai,
|
||||
.num_links = 1,
|
||||
.drvdata = &dm365_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
/* davinci dm6467 evm audio machine driver */
|
||||
static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
|
||||
.sysclk = 27000000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card dm6467_snd_soc_card_evm = {
|
||||
.name = "DaVinci DM6467 EVM",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = dm6467_evm_dai,
|
||||
.num_links = ARRAY_SIZE(dm6467_evm_dai),
|
||||
.drvdata = &dm6467_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
|
||||
.sysclk = 24576000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card da830_snd_soc_card = {
|
||||
@@ -279,6 +309,11 @@ static struct snd_soc_card da830_snd_soc_card = {
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &da830_evm_dai,
|
||||
.num_links = 1,
|
||||
.drvdata = &da830_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
|
||||
.sysclk = 24576000,
|
||||
};
|
||||
|
||||
static struct snd_soc_card da850_snd_soc_card = {
|
||||
@@ -286,8 +321,101 @@ static struct snd_soc_card da850_snd_soc_card = {
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &da850_evm_dai,
|
||||
.num_links = 1,
|
||||
.drvdata = &da850_snd_soc_card_drvdata,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
|
||||
/*
|
||||
* The struct is used as place holder. It will be completely
|
||||
* filled with data from dt node.
|
||||
*/
|
||||
static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
|
||||
.name = "TLV320AIC3X",
|
||||
.stream_name = "AIC3X",
|
||||
.codec_dai_name = "tlv320aic3x-hifi",
|
||||
.ops = &evm_ops,
|
||||
.init = evm_aic3x_init,
|
||||
};
|
||||
|
||||
static const struct of_device_id davinci_evm_dt_ids[] = {
|
||||
{
|
||||
.compatible = "ti,da830-evm-audio",
|
||||
.data = (void *) &evm_dai_tlv320aic3x,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
|
||||
|
||||
/* davinci evm audio machine driver */
|
||||
static struct snd_soc_card evm_soc_card = {
|
||||
.owner = THIS_MODULE,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static int davinci_evm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match =
|
||||
of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
|
||||
struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
|
||||
struct snd_soc_card_drvdata_davinci *drvdata = NULL;
|
||||
int ret = 0;
|
||||
|
||||
evm_soc_card.dai_link = dai;
|
||||
|
||||
dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
|
||||
if (!dai->codec_of_node)
|
||||
return -EINVAL;
|
||||
|
||||
dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
|
||||
if (!dai->cpu_of_node)
|
||||
return -EINVAL;
|
||||
|
||||
dai->platform_of_node = dai->cpu_of_node;
|
||||
|
||||
evm_soc_card.dev = &pdev->dev;
|
||||
ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
|
||||
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int davinci_evm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver davinci_evm_driver = {
|
||||
.probe = davinci_evm_probe,
|
||||
.remove = davinci_evm_remove,
|
||||
.driver = {
|
||||
.name = "davinci_evm",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(davinci_evm_dt_ids),
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_device *evm_snd_device;
|
||||
|
||||
static int __init evm_init(void)
|
||||
@@ -296,6 +424,15 @@ static int __init evm_init(void)
|
||||
int index;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If dtb is there, the devices will be created dynamically.
|
||||
* Only register platfrom driver structure.
|
||||
*/
|
||||
#if defined(CONFIG_OF)
|
||||
if (of_have_populated_dt())
|
||||
return platform_driver_register(&davinci_evm_driver);
|
||||
#endif
|
||||
|
||||
if (machine_is_davinci_evm()) {
|
||||
evm_snd_dev_data = &dm6446_snd_soc_card_evm;
|
||||
index = 0;
|
||||
@@ -331,6 +468,13 @@ static int __init evm_init(void)
|
||||
|
||||
static void __exit evm_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_OF)
|
||||
if (of_have_populated_dt()) {
|
||||
platform_driver_unregister(&davinci_evm_driver);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
platform_device_unregister(evm_snd_device);
|
||||
}
|
||||
|
||||
|
@@ -1001,18 +1001,40 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
|
||||
.name = "davinci-mcasp",
|
||||
};
|
||||
|
||||
/* Some HW specific values and defaults. The rest is filled in from DT. */
|
||||
static struct snd_platform_data dm646x_mcasp_pdata = {
|
||||
.tx_dma_offset = 0x400,
|
||||
.rx_dma_offset = 0x400,
|
||||
.asp_chan_q = EVENTQ_0,
|
||||
.version = MCASP_VERSION_1,
|
||||
};
|
||||
|
||||
static struct snd_platform_data da830_mcasp_pdata = {
|
||||
.tx_dma_offset = 0x2000,
|
||||
.rx_dma_offset = 0x2000,
|
||||
.asp_chan_q = EVENTQ_0,
|
||||
.version = MCASP_VERSION_2,
|
||||
};
|
||||
|
||||
static struct snd_platform_data omap2_mcasp_pdata = {
|
||||
.tx_dma_offset = 0,
|
||||
.rx_dma_offset = 0,
|
||||
.asp_chan_q = EVENTQ_0,
|
||||
.version = MCASP_VERSION_3,
|
||||
};
|
||||
|
||||
static const struct of_device_id mcasp_dt_ids[] = {
|
||||
{
|
||||
.compatible = "ti,dm646x-mcasp-audio",
|
||||
.data = (void *)MCASP_VERSION_1,
|
||||
.data = &dm646x_mcasp_pdata,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,da830-mcasp-audio",
|
||||
.data = (void *)MCASP_VERSION_2,
|
||||
.data = &da830_mcasp_pdata,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,omap2-mcasp-audio",
|
||||
.data = (void *)MCASP_VERSION_3,
|
||||
.compatible = "ti,am33xx-mcasp-audio",
|
||||
.data = &omap2_mcasp_pdata,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
@@ -1025,9 +1047,9 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
|
||||
struct snd_platform_data *pdata = NULL;
|
||||
const struct of_device_id *match =
|
||||
of_match_device(mcasp_dt_ids, &pdev->dev);
|
||||
struct of_phandle_args dma_spec;
|
||||
|
||||
const u32 *of_serial_dir32;
|
||||
u8 *of_serial_dir;
|
||||
u32 val;
|
||||
int i, ret = 0;
|
||||
|
||||
@@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
|
||||
pdata = pdev->dev.platform_data;
|
||||
return pdata;
|
||||
} else if (match) {
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
ret = -ENOMEM;
|
||||
goto nodata;
|
||||
}
|
||||
pdata = (struct snd_platform_data *) match->data;
|
||||
} else {
|
||||
/* control shouldn't reach here. something is wrong */
|
||||
ret = -EINVAL;
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
if (match->data)
|
||||
pdata->version = (u8)((int)match->data);
|
||||
|
||||
ret = of_property_read_u32(np, "op-mode", &val);
|
||||
if (ret >= 0)
|
||||
pdata->op_mode = val;
|
||||
@@ -1065,35 +1080,46 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
|
||||
pdata->tdm_slots = val;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "num-serializer", &val);
|
||||
if (ret >= 0)
|
||||
pdata->num_serializer = val;
|
||||
|
||||
of_serial_dir32 = of_get_property(np, "serial-dir", &val);
|
||||
val /= sizeof(u32);
|
||||
if (val != pdata->num_serializer) {
|
||||
dev_err(&pdev->dev,
|
||||
"num-serializer(%d) != serial-dir size(%d)\n",
|
||||
pdata->num_serializer, val);
|
||||
ret = -EINVAL;
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
if (of_serial_dir32) {
|
||||
of_serial_dir = devm_kzalloc(&pdev->dev,
|
||||
(sizeof(*of_serial_dir) * val),
|
||||
GFP_KERNEL);
|
||||
u8 *of_serial_dir = devm_kzalloc(&pdev->dev,
|
||||
(sizeof(*of_serial_dir) * val),
|
||||
GFP_KERNEL);
|
||||
if (!of_serial_dir) {
|
||||
ret = -ENOMEM;
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdata->num_serializer; i++)
|
||||
for (i = 0; i < val; i++)
|
||||
of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
|
||||
|
||||
pdata->num_serializer = val;
|
||||
pdata->serial_dir = of_serial_dir;
|
||||
}
|
||||
|
||||
ret = of_property_match_string(np, "dma-names", "tx");
|
||||
if (ret < 0)
|
||||
goto nodata;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
|
||||
&dma_spec);
|
||||
if (ret < 0)
|
||||
goto nodata;
|
||||
|
||||
pdata->tx_dma_channel = dma_spec.args[0];
|
||||
|
||||
ret = of_property_match_string(np, "dma-names", "rx");
|
||||
if (ret < 0)
|
||||
goto nodata;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
|
||||
&dma_spec);
|
||||
if (ret < 0)
|
||||
goto nodata;
|
||||
|
||||
pdata->rx_dma_channel = dma_spec.args[0];
|
||||
|
||||
ret = of_property_read_u32(np, "tx-num-evt", &val);
|
||||
if (ret >= 0)
|
||||
pdata->txnumevt = val;
|
||||
@@ -1124,7 +1150,7 @@ nodata:
|
||||
static int davinci_mcasp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct davinci_pcm_dma_params *dma_data;
|
||||
struct resource *mem, *ioarea, *res;
|
||||
struct resource *mem, *ioarea, *res, *dat;
|
||||
struct snd_platform_data *pdata;
|
||||
struct davinci_audio_dev *dev;
|
||||
int ret;
|
||||
@@ -1145,10 +1171,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "no mem resource?\n");
|
||||
return -ENODEV;
|
||||
dev_warn(dev->dev,
|
||||
"\"mpu\" mem resource not found, using index 0\n");
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "no mem resource?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
ioarea = devm_request_mem_region(&pdev->dev, mem->start,
|
||||
@@ -1182,40 +1213,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
||||
dev->rxnumevt = pdata->rxnumevt;
|
||||
dev->dev = &pdev->dev;
|
||||
|
||||
dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
|
||||
if (!dat)
|
||||
dat = mem;
|
||||
|
||||
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
dma_data->asp_chan_q = pdata->asp_chan_q;
|
||||
dma_data->ram_chan_q = pdata->ram_chan_q;
|
||||
dma_data->sram_pool = pdata->sram_pool;
|
||||
dma_data->sram_size = pdata->sram_size_playback;
|
||||
dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
|
||||
mem->start);
|
||||
dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
|
||||
|
||||
/* first TX, then RX */
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no DMA resource\n");
|
||||
ret = -ENODEV;
|
||||
goto err_release_clk;
|
||||
}
|
||||
|
||||
dma_data->channel = res->start;
|
||||
if (res)
|
||||
dma_data->channel = res->start;
|
||||
else
|
||||
dma_data->channel = pdata->tx_dma_channel;
|
||||
|
||||
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
|
||||
dma_data->asp_chan_q = pdata->asp_chan_q;
|
||||
dma_data->ram_chan_q = pdata->ram_chan_q;
|
||||
dma_data->sram_pool = pdata->sram_pool;
|
||||
dma_data->sram_size = pdata->sram_size_capture;
|
||||
dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
|
||||
mem->start);
|
||||
dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no DMA resource\n");
|
||||
ret = -ENODEV;
|
||||
goto err_release_clk;
|
||||
}
|
||||
if (res)
|
||||
dma_data->channel = res->start;
|
||||
else
|
||||
dma_data->channel = pdata->rx_dma_channel;
|
||||
|
||||
dma_data->channel = res->start;
|
||||
dev_set_drvdata(&pdev->dev, dev);
|
||||
ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
|
||||
&davinci_mcasp_dai[pdata->op_mode], 1);
|
||||
@@ -1251,12 +1278,51 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int davinci_mcasp_suspend(struct device *dev)
|
||||
{
|
||||
struct davinci_audio_dev *a = dev_get_drvdata(dev);
|
||||
void __iomem *base = a->base;
|
||||
|
||||
a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
|
||||
a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
|
||||
a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
|
||||
a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
|
||||
a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
|
||||
a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
|
||||
a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int davinci_mcasp_resume(struct device *dev)
|
||||
{
|
||||
struct davinci_audio_dev *a = dev_get_drvdata(dev);
|
||||
void __iomem *base = a->base;
|
||||
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
|
||||
mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops,
|
||||
davinci_mcasp_suspend,
|
||||
davinci_mcasp_resume);
|
||||
|
||||
static struct platform_driver davinci_mcasp_driver = {
|
||||
.probe = davinci_mcasp_probe,
|
||||
.remove = davinci_mcasp_remove,
|
||||
.driver = {
|
||||
.name = "davinci-mcasp",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &davinci_mcasp_pm_ops,
|
||||
.of_match_table = mcasp_dt_ids,
|
||||
},
|
||||
};
|
||||
@@ -1266,4 +1332,3 @@ module_platform_driver(davinci_mcasp_driver);
|
||||
MODULE_AUTHOR("Steve Chen");
|
||||
MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@@ -43,6 +43,18 @@ struct davinci_audio_dev {
|
||||
/* McASP FIFO related */
|
||||
u8 txnumevt;
|
||||
u8 rxnumevt;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct {
|
||||
u32 txfmtctl;
|
||||
u32 rxfmtctl;
|
||||
u32 txfmt;
|
||||
u32 rxfmt;
|
||||
u32 aclkxctl;
|
||||
u32 aclkrctl;
|
||||
u32 pdir;
|
||||
} context;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* DAVINCI_MCASP_H */
|
||||
|
@@ -963,7 +963,7 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
|
||||
@@ -982,7 +982,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config fsl_spdif_regmap_config = {
|
||||
@@ -1172,23 +1172,16 @@ static int fsl_spdif_probe(struct platform_device *pdev)
|
||||
/* Register with ASoC */
|
||||
dev_set_drvdata(&pdev->dev, spdif_priv);
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
|
||||
&spdif_priv->cpu_dai_drv, 1);
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
|
||||
&spdif_priv->cpu_dai_drv, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = imx_pcm_dma_init(pdev);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
|
||||
goto error_component;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error_component:
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1196,7 +1189,6 @@ error_component:
|
||||
static int fsl_spdif_remove(struct platform_device *pdev)
|
||||
{
|
||||
imx_pcm_dma_exit(pdev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -469,19 +469,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
|
||||
* parameters, then the second stream may be
|
||||
* constrained to the wrong sample rate or size.
|
||||
*/
|
||||
if (!first_runtime->sample_bits) {
|
||||
dev_err(substream->pcm->card->dev,
|
||||
"set sample size in %s stream first\n",
|
||||
substream->stream ==
|
||||
SNDRV_PCM_STREAM_PLAYBACK
|
||||
? "capture" : "playback");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
||||
if (first_runtime->sample_bits) {
|
||||
snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
||||
first_runtime->sample_bits,
|
||||
first_runtime->sample_bits);
|
||||
}
|
||||
}
|
||||
|
||||
ssi_private->second_stream = substream;
|
||||
@@ -748,7 +741,7 @@ static void fsl_ssi_ac97_init(void)
|
||||
fsl_ssi_setup(fsl_ac97_data);
|
||||
}
|
||||
|
||||
void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
||||
static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
||||
unsigned short val)
|
||||
{
|
||||
struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
|
||||
@@ -770,7 +763,7 @@ void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
|
||||
static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
|
||||
unsigned short reg)
|
||||
{
|
||||
struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
|
||||
@@ -936,7 +929,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
ssi_private->ssi_phys = res.start;
|
||||
|
||||
ssi_private->irq = irq_of_parse_and_map(np, 0);
|
||||
if (ssi_private->irq == 0) {
|
||||
if (!ssi_private->irq) {
|
||||
dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
|
||||
return -ENXIO;
|
||||
}
|
||||
@@ -1135,7 +1128,6 @@ static int fsl_ssi_remove(struct platform_device *pdev)
|
||||
if (ssi_private->ssi_on_imx)
|
||||
imx_pcm_dma_exit(pdev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
device_remove_file(&pdev->dev, &ssi_private->dev_attr);
|
||||
if (ssi_private->ssi_on_imx)
|
||||
clk_disable_unprepare(ssi_private->clk);
|
||||
|
@@ -66,13 +66,10 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
ssize_t ret;
|
||||
char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
char *buf;
|
||||
int port = (int)file->private_data;
|
||||
u32 pdcr, ptcr;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (audmux_clk) {
|
||||
ret = clk_prepare_enable(audmux_clk);
|
||||
if (ret)
|
||||
@@ -85,6 +82,10 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
|
||||
if (audmux_clk)
|
||||
clk_disable_unprepare(audmux_clk);
|
||||
|
||||
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
|
||||
pdcr, ptcr);
|
||||
|
||||
|
@@ -160,6 +160,7 @@ static struct platform_driver imx_mc13783_audio_driver = {
|
||||
.driver = {
|
||||
.name = "imx_mc13783",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = imx_mc13783_probe,
|
||||
.remove = imx_mc13783_remove
|
||||
|
@@ -25,12 +25,10 @@
|
||||
|
||||
static bool filter(struct dma_chan *chan, void *param)
|
||||
{
|
||||
struct snd_dmaengine_dai_dma_data *dma_data = param;
|
||||
|
||||
if (!imx_dma_is_general_purpose(chan))
|
||||
return false;
|
||||
|
||||
chan->private = dma_data->filter_data;
|
||||
chan->private = param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -159,7 +159,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
|
||||
data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
|
||||
data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
|
||||
|
||||
ret = snd_soc_register_card(&data->card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
|
||||
goto fail;
|
||||
@@ -186,7 +186,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_card(&data->card);
|
||||
clk_put(data->codec_clk);
|
||||
|
||||
return 0;
|
||||
@@ -202,6 +201,7 @@ static struct platform_driver imx_sgtl5000_driver = {
|
||||
.driver = {
|
||||
.name = "imx-sgtl5000",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
.of_match_table = imx_sgtl5000_dt_ids,
|
||||
},
|
||||
.probe = imx_sgtl5000_probe,
|
||||
|
@@ -87,7 +87,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto error_dir;
|
||||
|
||||
ret = snd_soc_register_card(&data->card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
|
||||
goto error_dir;
|
||||
@@ -119,8 +119,6 @@ static int imx_spdif_audio_remove(struct platform_device *pdev)
|
||||
if (data->txdev)
|
||||
platform_device_unregister(data->txdev);
|
||||
|
||||
snd_soc_unregister_card(&data->card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -613,7 +613,6 @@ static int imx_ssi_probe(struct platform_device *pdev)
|
||||
failed_pcm:
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
failed_register:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
clk_disable_unprepare(ssi->clk);
|
||||
failed_clk:
|
||||
snd_soc_set_ac97_ops(NULL);
|
||||
@@ -623,7 +622,6 @@ failed_clk:
|
||||
|
||||
static int imx_ssi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct imx_ssi *ssi = platform_get_drvdata(pdev);
|
||||
|
||||
if (!ssi->dma_init)
|
||||
@@ -637,7 +635,6 @@ static int imx_ssi_remove(struct platform_device *pdev)
|
||||
if (ssi->flags & IMX_SSI_USE_AC97)
|
||||
ac97_ssi = NULL;
|
||||
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
clk_disable_unprepare(ssi->clk);
|
||||
snd_soc_set_ac97_ops(NULL);
|
||||
|
||||
|
@@ -266,7 +266,7 @@ static int imx_wm8962_probe(struct platform_device *pdev)
|
||||
data->card.late_probe = imx_wm8962_late_probe;
|
||||
data->card.set_bias_level = imx_wm8962_set_bias_level;
|
||||
|
||||
ret = snd_soc_register_card(&data->card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
|
||||
goto clk_fail;
|
||||
@@ -296,7 +296,6 @@ static int imx_wm8962_remove(struct platform_device *pdev)
|
||||
|
||||
if (!IS_ERR(data->codec_clk))
|
||||
clk_disable_unprepare(data->codec_clk);
|
||||
snd_soc_unregister_card(&data->card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -311,6 +310,7 @@ static struct platform_driver imx_wm8962_driver = {
|
||||
.driver = {
|
||||
.name = "imx-wm8962",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
.of_match_table = imx_wm8962_dt_ids,
|
||||
},
|
||||
.probe = imx_wm8962_probe,
|
||||
|
@@ -27,6 +27,11 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
|
||||
if (!ret && daifmt)
|
||||
ret = snd_soc_dai_set_fmt(dai, daifmt);
|
||||
|
||||
if (ret == -ENOTSUPP) {
|
||||
dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (!ret && set->sysclk)
|
||||
ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
|
||||
|
||||
|
@@ -29,9 +29,7 @@
|
||||
#define KIRKWOOD_FORMATS \
|
||||
(SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S32_LE | \
|
||||
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
|
||||
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
|
||||
{
|
||||
@@ -161,7 +159,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
|
||||
* Enable Error interrupts. We're only ack'ing them but
|
||||
* it's useful for diagnostics
|
||||
*/
|
||||
writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK);
|
||||
writel((unsigned int)-1, priv->io + KIRKWOOD_ERR_MASK);
|
||||
}
|
||||
|
||||
dram = mv_mbus_dram_info();
|
||||
|
@@ -103,7 +103,7 @@ static void kirkwood_set_rate(struct snd_soc_dai *dai,
|
||||
{
|
||||
uint32_t clks_ctrl;
|
||||
|
||||
if (rate == 44100 || rate == 48000 || rate == 96000) {
|
||||
if (IS_ERR(priv->extclk)) {
|
||||
/* use internal dco for the supported rates
|
||||
* defined in kirkwood_i2s_dai */
|
||||
dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
|
||||
@@ -160,9 +160,11 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
|
||||
ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
|
||||
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||
KIRKWOOD_PLAYCTL_I2S_EN |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_EN;
|
||||
ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
|
||||
KIRKWOOD_RECCTL_I2S_EN;
|
||||
KIRKWOOD_RECCTL_I2S_EN |
|
||||
KIRKWOOD_RECCTL_SPDIF_EN;
|
||||
break;
|
||||
/*
|
||||
* doesn't work... S20_3LE != kirkwood 20bit format ?
|
||||
@@ -178,9 +180,11 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
|
||||
ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
|
||||
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||
KIRKWOOD_PLAYCTL_I2S_EN |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_EN;
|
||||
ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
|
||||
KIRKWOOD_RECCTL_I2S_EN;
|
||||
KIRKWOOD_RECCTL_I2S_EN |
|
||||
KIRKWOOD_RECCTL_SPDIF_EN;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
|
||||
@@ -240,6 +244,11 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
||||
ctl);
|
||||
}
|
||||
|
||||
if (dai->id == 0)
|
||||
ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
|
||||
else
|
||||
ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
/* configure */
|
||||
@@ -258,7 +267,8 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
/* stop audio, disable interrupts */
|
||||
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
||||
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_MUTE;
|
||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||
|
||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||
@@ -272,13 +282,15 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
||||
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
||||
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_MUTE;
|
||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
|
||||
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_MUTE);
|
||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||
break;
|
||||
|
||||
@@ -301,7 +313,13 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
/* configure */
|
||||
ctl = priv->ctl_rec;
|
||||
value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
|
||||
if (dai->id == 0)
|
||||
ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN; /* i2s */
|
||||
else
|
||||
ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
|
||||
|
||||
value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN |
|
||||
KIRKWOOD_RECCTL_SPDIF_EN);
|
||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
||||
|
||||
/* enable interrupts */
|
||||
@@ -361,9 +379,8 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
|
||||
static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
|
||||
{
|
||||
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned long value;
|
||||
unsigned int reg_data;
|
||||
|
||||
@@ -404,9 +421,10 @@ static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
|
||||
.set_fmt = kirkwood_i2s_set_fmt,
|
||||
};
|
||||
|
||||
|
||||
static struct snd_soc_dai_driver kirkwood_i2s_dai = {
|
||||
.probe = kirkwood_i2s_probe,
|
||||
static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
|
||||
{
|
||||
.name = "i2s",
|
||||
.id = 0,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
@@ -422,10 +440,32 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.ops = &kirkwood_i2s_dai_ops,
|
||||
},
|
||||
{
|
||||
.name = "spdif",
|
||||
.id = 1,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.ops = &kirkwood_i2s_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
|
||||
.probe = kirkwood_i2s_probe,
|
||||
static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
|
||||
{
|
||||
.name = "i2s",
|
||||
.id = 0,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
@@ -443,6 +483,28 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.ops = &kirkwood_i2s_dai_ops,
|
||||
},
|
||||
{
|
||||
.name = "spdif",
|
||||
.id = 1,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
||||
SNDRV_PCM_RATE_CONTINUOUS |
|
||||
SNDRV_PCM_RATE_KNOT,
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
||||
SNDRV_PCM_RATE_CONTINUOUS |
|
||||
SNDRV_PCM_RATE_KNOT,
|
||||
.formats = KIRKWOOD_I2S_FORMATS,
|
||||
},
|
||||
.ops = &kirkwood_i2s_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver kirkwood_i2s_component = {
|
||||
@@ -452,7 +514,7 @@ static const struct snd_soc_component_driver kirkwood_i2s_component = {
|
||||
static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
|
||||
struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
|
||||
struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
|
||||
struct kirkwood_dma_data *priv;
|
||||
struct resource *mem;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@@ -496,7 +558,10 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
priv->extclk = devm_clk_get(&pdev->dev, "extclk");
|
||||
if (!IS_ERR(priv->extclk)) {
|
||||
if (IS_ERR(priv->extclk)) {
|
||||
if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
} else {
|
||||
if (priv->extclk == priv->clk) {
|
||||
devm_clk_put(&pdev->dev, priv->extclk);
|
||||
priv->extclk = ERR_PTR(-EINVAL);
|
||||
@@ -521,7 +586,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
|
||||
soc_dai, 1);
|
||||
soc_dai, 2);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_component failed\n");
|
||||
goto err_component;
|
||||
@@ -532,6 +597,9 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
|
||||
goto err_platform;
|
||||
}
|
||||
|
||||
kirkwood_i2s_init(priv);
|
||||
|
||||
return 0;
|
||||
err_platform:
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
@@ -52,7 +52,7 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
|
||||
{
|
||||
.name = "CS42L51",
|
||||
.stream_name = "CS42L51 HiFi",
|
||||
.cpu_dai_name = "mvebu-audio",
|
||||
.cpu_dai_name = "i2s",
|
||||
.platform_name = "mvebu-audio",
|
||||
.codec_dai_name = "cs42l51-hifi",
|
||||
.codec_name = "cs42l51-codec.0-004a",
|
||||
|
@@ -68,7 +68,7 @@ static struct snd_soc_dai_link t5325_dai[] = {
|
||||
{
|
||||
.name = "ALC5621",
|
||||
.stream_name = "ALC5621 HiFi",
|
||||
.cpu_dai_name = "mvebu-audio",
|
||||
.cpu_dai_name = "i2s",
|
||||
.platform_name = "mvebu-audio",
|
||||
.codec_dai_name = "alc5621-hifi",
|
||||
.codec_name = "alc562x-codec.0-001a",
|
||||
|
@@ -123,8 +123,8 @@
|
||||
/* need to find where they come from */
|
||||
#define KIRKWOOD_SND_MIN_PERIODS 8
|
||||
#define KIRKWOOD_SND_MAX_PERIODS 16
|
||||
#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000
|
||||
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
|
||||
#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x800
|
||||
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000
|
||||
#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \
|
||||
* KIRKWOOD_SND_MAX_PERIODS)
|
||||
|
||||
|
@@ -400,7 +400,7 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
|
||||
}
|
||||
/* register the soc card */
|
||||
snd_soc_card_mfld.dev = &pdev->dev;
|
||||
ret_val = snd_soc_register_card(&snd_soc_card_mfld);
|
||||
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_mfld);
|
||||
if (ret_val) {
|
||||
pr_debug("snd_soc_register_card failed %d\n", ret_val);
|
||||
return ret_val;
|
||||
@@ -410,20 +410,12 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_mfld_mc_remove(struct platform_device *pdev)
|
||||
{
|
||||
pr_debug("snd_mfld_mc_remove called\n");
|
||||
snd_soc_unregister_card(&snd_soc_card_mfld);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver snd_mfld_mc_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "msic_audio",
|
||||
},
|
||||
.probe = snd_mfld_mc_probe,
|
||||
.remove = snd_mfld_mc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(snd_mfld_mc_driver);
|
||||
|
@@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
struct mxs_saif *master_saif;
|
||||
u32 delay;
|
||||
int ret;
|
||||
|
||||
master_saif = mxs_saif_get_master(saif);
|
||||
if (!master_saif)
|
||||
@@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if (saif->state == MXS_SAIF_STATE_RUNNING)
|
||||
return 0;
|
||||
|
||||
dev_dbg(cpu_dai->dev, "start\n");
|
||||
|
||||
clk_enable(master_saif->clk);
|
||||
if (!master_saif->mclk_in_use)
|
||||
__raw_writel(BM_SAIF_CTRL_RUN,
|
||||
master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
|
||||
ret = clk_enable(master_saif->clk);
|
||||
if (ret) {
|
||||
dev_err(saif->dev, "Failed to enable master clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the saif's master is not himself, we also need to enable
|
||||
* itself clk for its internal basic logic to work.
|
||||
*/
|
||||
if (saif != master_saif) {
|
||||
clk_enable(saif->clk);
|
||||
ret = clk_enable(saif->clk);
|
||||
if (ret) {
|
||||
dev_err(saif->dev, "Failed to enable master clock\n");
|
||||
clk_disable(master_saif->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
__raw_writel(BM_SAIF_CTRL_RUN,
|
||||
saif->base + SAIF_CTRL + MXS_SET_ADDR);
|
||||
}
|
||||
|
||||
if (!master_saif->mclk_in_use)
|
||||
__raw_writel(BM_SAIF_CTRL_RUN,
|
||||
master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
/*
|
||||
* write data to saif data register to trigger
|
||||
@@ -543,6 +558,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
}
|
||||
|
||||
master_saif->ongoing = 1;
|
||||
saif->state = MXS_SAIF_STATE_RUNNING;
|
||||
|
||||
dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
|
||||
__raw_readl(saif->base + SAIF_CTRL),
|
||||
@@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if (saif->state == MXS_SAIF_STATE_STOPPED)
|
||||
return 0;
|
||||
|
||||
dev_dbg(cpu_dai->dev, "stop\n");
|
||||
|
||||
/* wait a while for the current sample to complete */
|
||||
@@ -575,6 +594,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
}
|
||||
|
||||
master_saif->ongoing = 0;
|
||||
saif->state = MXS_SAIF_STATE_STOPPED;
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -768,8 +788,8 @@ static int mxs_saif_probe(struct platform_device *pdev)
|
||||
dev_warn(&pdev->dev, "failed to init clocks\n");
|
||||
}
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
|
||||
&mxs_saif_dai, 1);
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component,
|
||||
&mxs_saif_dai, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "register DAI failed\n");
|
||||
return ret;
|
||||
@@ -778,21 +798,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
|
||||
ret = mxs_pcm_platform_register(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
|
||||
goto failed_pdev_alloc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failed_pdev_alloc:
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxs_saif_remove(struct platform_device *pdev)
|
||||
{
|
||||
mxs_pcm_platform_unregister(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -124,6 +124,11 @@ struct mxs_saif {
|
||||
|
||||
u32 fifo_underrun;
|
||||
u32 fifo_overrun;
|
||||
|
||||
enum {
|
||||
MXS_SAIF_STATE_STOPPED,
|
||||
MXS_SAIF_STATE_RUNNING,
|
||||
} state;
|
||||
};
|
||||
|
||||
extern int mxs_saif_put_mclk(unsigned int saif_id);
|
||||
|
@@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = {
|
||||
.num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
|
||||
};
|
||||
|
||||
static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
|
||||
static int mxs_sgtl5000_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &mxs_sgtl5000;
|
||||
int ret, i;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *saif_np[2], *codec_np;
|
||||
int i;
|
||||
|
||||
if (!np)
|
||||
return 1; /* no device tree */
|
||||
|
||||
saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
|
||||
saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
|
||||
@@ -152,18 +150,6 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
|
||||
of_node_put(saif_np[0]);
|
||||
of_node_put(saif_np[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_sgtl5000_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &mxs_sgtl5000;
|
||||
int ret;
|
||||
|
||||
ret = mxs_sgtl5000_probe_dt(pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
|
||||
* The Sgtl5000 sysclk is derived from saif0 mclk and it's range
|
||||
|
@@ -490,14 +490,9 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
|
||||
|
||||
mcpdm->dev = &pdev->dev;
|
||||
|
||||
return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component,
|
||||
&omap_mcpdm_dai, 1);
|
||||
}
|
||||
|
||||
static int asoc_mcpdm_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
return 0;
|
||||
return devm_snd_soc_register_component(&pdev->dev,
|
||||
&omap_mcpdm_component,
|
||||
&omap_mcpdm_dai, 1);
|
||||
}
|
||||
|
||||
static const struct of_device_id omap_mcpdm_of_match[] = {
|
||||
@@ -514,7 +509,6 @@ static struct platform_driver asoc_mcpdm_driver = {
|
||||
},
|
||||
|
||||
.probe = asoc_mcpdm_probe,
|
||||
.remove = asoc_mcpdm_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(asoc_mcpdm_driver);
|
||||
|
@@ -338,9 +338,9 @@ static int omap_twl4030_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
snd_soc_card_set_drvdata(card, priv);
|
||||
ret = snd_soc_register_card(card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
|
||||
dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -357,7 +357,6 @@ static int omap_twl4030_remove(struct platform_device *pdev)
|
||||
snd_soc_jack_free_gpios(&priv->hs_jack,
|
||||
ARRAY_SIZE(hs_jack_gpios),
|
||||
hs_jack_gpios);
|
||||
snd_soc_unregister_card(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -163,6 +163,7 @@ static struct platform_driver mmp_driver = {
|
||||
.driver = {
|
||||
.name = "brownstone-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = brownstone_probe,
|
||||
.remove = brownstone_remove,
|
||||
|
@@ -329,6 +329,7 @@ static struct platform_driver corgi_driver = {
|
||||
.driver = {
|
||||
.name = "corgi-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = corgi_probe,
|
||||
.remove = corgi_remove,
|
||||
|
@@ -178,6 +178,7 @@ static struct platform_driver e740_driver = {
|
||||
.driver = {
|
||||
.name = "e740-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = e740_probe,
|
||||
.remove = e740_remove,
|
||||
|
@@ -160,6 +160,7 @@ static struct platform_driver e750_driver = {
|
||||
.driver = {
|
||||
.name = "e750-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = e750_probe,
|
||||
.remove = e750_remove,
|
||||
|
@@ -150,6 +150,7 @@ static struct platform_driver e800_driver = {
|
||||
.driver = {
|
||||
.name = "e800-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = e800_probe,
|
||||
.remove = e800_remove,
|
||||
|
@@ -91,6 +91,7 @@ static struct platform_driver imote2_driver = {
|
||||
.driver = {
|
||||
.name = "imote2-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = imote2_probe,
|
||||
.remove = imote2_remove,
|
||||
|
@@ -215,6 +215,7 @@ static struct platform_driver mioa701_wm9713_driver = {
|
||||
.driver = {
|
||||
.name = "mioa701-wm9713",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -455,8 +455,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
|
||||
priv->dai_fmt = (unsigned int) -1;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
return snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
|
||||
&mmp_sspa_dai, 1);
|
||||
return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
|
||||
&mmp_sspa_dai, 1);
|
||||
}
|
||||
|
||||
static int asoc_mmp_sspa_remove(struct platform_device *pdev)
|
||||
@@ -466,7 +466,6 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev)
|
||||
clk_disable(priv->audio_clk);
|
||||
clk_put(priv->audio_clk);
|
||||
clk_put(priv->sysclk);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -181,6 +181,7 @@ static struct platform_driver palm27x_wm9712_driver = {
|
||||
.driver = {
|
||||
.name = "palm27x-asoc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -303,6 +303,7 @@ static struct platform_driver poodle_driver = {
|
||||
.driver = {
|
||||
.name = "poodle-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = poodle_probe,
|
||||
.remove = poodle_remove,
|
||||
|
@@ -89,33 +89,6 @@ static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = {
|
||||
.filter_data = &pxa2xx_ac97_pcm_aux_mic_mono_req,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
|
||||
{
|
||||
return pxa2xx_ac97_hw_suspend();
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
|
||||
{
|
||||
return pxa2xx_ac97_hw_resume();
|
||||
}
|
||||
|
||||
#else
|
||||
#define pxa2xx_ac97_suspend NULL
|
||||
#define pxa2xx_ac97_resume NULL
|
||||
#endif
|
||||
|
||||
static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_remove(struct snd_soc_dai *dai)
|
||||
{
|
||||
pxa2xx_ac97_hw_remove(to_platform_device(dai->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
@@ -185,10 +158,6 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
|
||||
{
|
||||
.name = "pxa2xx-ac97",
|
||||
.ac97_control = 1,
|
||||
.probe = pxa2xx_ac97_probe,
|
||||
.remove = pxa2xx_ac97_remove,
|
||||
.suspend = pxa2xx_ac97_suspend,
|
||||
.resume = pxa2xx_ac97_resume,
|
||||
.playback = {
|
||||
.stream_name = "AC97 Playback",
|
||||
.channels_min = 2,
|
||||
@@ -246,6 +215,12 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = pxa2xx_ac97_hw_probe(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@@ -262,15 +237,34 @@ static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
snd_soc_set_ac97_ops(NULL);
|
||||
pxa2xx_ac97_hw_remove(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int pxa2xx_ac97_dev_suspend(struct device *dev)
|
||||
{
|
||||
return pxa2xx_ac97_hw_suspend();
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_dev_resume(struct device *dev)
|
||||
{
|
||||
return pxa2xx_ac97_hw_resume();
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops,
|
||||
pxa2xx_ac97_dev_suspend, pxa2xx_ac97_dev_resume);
|
||||
#endif
|
||||
|
||||
static struct platform_driver pxa2xx_ac97_driver = {
|
||||
.probe = pxa2xx_ac97_dev_probe,
|
||||
.remove = pxa2xx_ac97_dev_remove,
|
||||
.driver = {
|
||||
.name = "pxa2xx-ac97",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &pxa2xx_ac97_pm_ops,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -275,6 +275,7 @@ static struct platform_driver tosa_driver = {
|
||||
.driver = {
|
||||
.name = "tosa-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = tosa_probe,
|
||||
.remove = tosa_remove,
|
||||
|
@@ -160,6 +160,7 @@ static struct platform_driver ttc_dkb_driver = {
|
||||
.driver = {
|
||||
.name = "ttc-dkb-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = ttc_dkb_probe,
|
||||
.remove = ttc_dkb_remove,
|
||||
|
@@ -356,6 +356,7 @@ static struct snd_soc_dapm_widget bells_widgets[] = {
|
||||
|
||||
static struct snd_soc_dapm_route bells_routes[] = {
|
||||
{ "Sub CLK_SYS", NULL, "OPCLK" },
|
||||
{ "CLKIN", NULL, "OPCLK" },
|
||||
|
||||
{ "DMIC", NULL, "MICBIAS2" },
|
||||
{ "IN2L", NULL, "DMIC" },
|
||||
|
@@ -702,13 +702,6 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
writel(mod, i2s->addr + I2SMOD);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
snd_soc_dai_set_dma_data(dai, substream,
|
||||
(void *)&i2s->dma_playback);
|
||||
else
|
||||
snd_soc_dai_set_dma_data(dai, substream,
|
||||
(void *)&i2s->dma_capture);
|
||||
|
||||
i2s->frmclk = params_rate(params);
|
||||
|
||||
return 0;
|
||||
@@ -970,6 +963,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
|
||||
}
|
||||
clk_prepare_enable(i2s->clk);
|
||||
|
||||
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
|
||||
|
||||
if (other) {
|
||||
other->addr = i2s->addr;
|
||||
other->clk = i2s->clk;
|
||||
@@ -1060,7 +1055,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
|
||||
i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops;
|
||||
i2s->i2s_dai_drv.suspend = i2s_suspend;
|
||||
i2s->i2s_dai_drv.resume = i2s_resume;
|
||||
i2s->i2s_dai_drv.playback.channels_min = 2;
|
||||
i2s->i2s_dai_drv.playback.channels_min = 1;
|
||||
i2s->i2s_dai_drv.playback.channels_max = 2;
|
||||
i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES;
|
||||
i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
|
||||
@@ -1143,9 +1138,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Unable to get drvdata\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
snd_soc_register_component(&sec_dai->pdev->dev,
|
||||
&samsung_i2s_component,
|
||||
&sec_dai->i2s_dai_drv, 1);
|
||||
devm_snd_soc_register_component(&sec_dai->pdev->dev,
|
||||
&samsung_i2s_component,
|
||||
&sec_dai->i2s_dai_drv, 1);
|
||||
samsung_asoc_dma_platform_register(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -1258,8 +1253,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component,
|
||||
&pri_dai->i2s_dai_drv, 1);
|
||||
devm_snd_soc_register_component(&pri_dai->pdev->dev,
|
||||
&samsung_i2s_component,
|
||||
&pri_dai->i2s_dai_drv, 1);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
@@ -1294,7 +1290,6 @@ static int samsung_i2s_remove(struct platform_device *pdev)
|
||||
i2s->sec_dai = NULL;
|
||||
|
||||
samsung_asoc_dma_platform_unregister(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "../codecs/wm8994.h"
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -193,7 +194,7 @@ static int smdk_audio_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, board);
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
|
||||
@@ -201,23 +202,14 @@ static int smdk_audio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smdk_audio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver smdk_audio_driver = {
|
||||
.driver = {
|
||||
.name = "smdk-audio-wm8894",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(samsung_wm8994_of_match),
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = smdk_audio_probe,
|
||||
.remove = smdk_audio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(smdk_audio_driver);
|
||||
|
@@ -8,7 +8,6 @@
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/sh_clk.h>
|
||||
#include <mach/clock.h>
|
||||
#include "rsnd.h"
|
||||
|
||||
#define CLKA 0
|
||||
@@ -22,6 +21,7 @@ struct rsnd_adg {
|
||||
|
||||
int rate_of_441khz_div_6;
|
||||
int rate_of_48khz_div_6;
|
||||
u32 ckr;
|
||||
};
|
||||
|
||||
#define for_each_rsnd_clk(pos, adg, i) \
|
||||
@@ -116,6 +116,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
|
||||
|
||||
found_clock:
|
||||
|
||||
/* see rsnd_adg_ssi_clk_init() */
|
||||
rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr);
|
||||
rsnd_mod_write(mod, BRRA, 0x00000002); /* 1/6 */
|
||||
rsnd_mod_write(mod, BRRB, 0x00000002); /* 1/6 */
|
||||
|
||||
/*
|
||||
* This "mod" = "ssi" here.
|
||||
* we can get "ssi id" from mod
|
||||
@@ -182,9 +187,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
|
||||
}
|
||||
}
|
||||
|
||||
rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr);
|
||||
rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */
|
||||
rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */
|
||||
adg->ckr = ckr;
|
||||
}
|
||||
|
||||
int rsnd_adg_probe(struct platform_device *pdev,
|
||||
|
@@ -103,54 +103,9 @@
|
||||
* rsnd_platform functions
|
||||
*/
|
||||
#define rsnd_platform_call(priv, dai, func, param...) \
|
||||
(!(priv->info->func) ? -ENODEV : \
|
||||
(!(priv->info->func) ? 0 : \
|
||||
priv->info->func(param))
|
||||
|
||||
|
||||
/*
|
||||
* basic function
|
||||
*/
|
||||
u32 rsnd_read(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod, enum rsnd_reg reg)
|
||||
{
|
||||
void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
|
||||
|
||||
BUG_ON(!base);
|
||||
|
||||
return ioread32(base);
|
||||
}
|
||||
|
||||
void rsnd_write(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data)
|
||||
{
|
||||
void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
|
||||
BUG_ON(!base);
|
||||
|
||||
dev_dbg(dev, "w %p : %08x\n", base, data);
|
||||
|
||||
iowrite32(data, base);
|
||||
}
|
||||
|
||||
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 mask, u32 data)
|
||||
{
|
||||
void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 val;
|
||||
|
||||
BUG_ON(!base);
|
||||
|
||||
val = ioread32(base);
|
||||
val &= ~mask;
|
||||
val |= data & mask;
|
||||
iowrite32(val, base);
|
||||
|
||||
dev_dbg(dev, "s %p : %08x\n", base, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* rsnd_mod functions
|
||||
*/
|
||||
@@ -363,6 +318,9 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
|
||||
|
||||
struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
|
||||
{
|
||||
if ((id < 0) || (id >= rsnd_dai_nr(priv)))
|
||||
return NULL;
|
||||
|
||||
return priv->rdai + id;
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,11 @@
|
||||
#include "rsnd.h"
|
||||
|
||||
struct rsnd_gen_ops {
|
||||
int (*probe)(struct platform_device *pdev,
|
||||
struct rcar_snd_info *info,
|
||||
struct rsnd_priv *priv);
|
||||
void (*remove)(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
int (*path_init)(struct rsnd_priv *priv,
|
||||
struct rsnd_dai *rdai,
|
||||
struct rsnd_dai_stream *io);
|
||||
@@ -19,21 +24,97 @@ struct rsnd_gen_ops {
|
||||
struct rsnd_dai_stream *io);
|
||||
};
|
||||
|
||||
struct rsnd_gen_reg_map {
|
||||
int index; /* -1 : not supported */
|
||||
u32 offset_id; /* offset of ssi0, ssi1, ssi2... */
|
||||
u32 offset_adr; /* offset of SSICR, SSISR, ... */
|
||||
};
|
||||
|
||||
struct rsnd_gen {
|
||||
void __iomem *base[RSND_BASE_MAX];
|
||||
|
||||
struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
|
||||
struct rsnd_gen_ops *ops;
|
||||
|
||||
struct regmap *regmap;
|
||||
struct regmap_field *regs[RSND_REG_MAX];
|
||||
};
|
||||
|
||||
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
|
||||
|
||||
#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
|
||||
[id] = { \
|
||||
.reg = (unsigned int)gen->base[reg_id] + offset, \
|
||||
.lsb = 0, \
|
||||
.msb = 31, \
|
||||
.id_size = _id_size, \
|
||||
.id_offset = _id_offset, \
|
||||
}
|
||||
|
||||
/*
|
||||
* basic function
|
||||
*/
|
||||
static int rsnd_regmap_write32(void *context, const void *_data, size_t count)
|
||||
{
|
||||
struct rsnd_priv *priv = context;
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 *data = (u32 *)_data;
|
||||
u32 val = data[1];
|
||||
void __iomem *reg = (void *)data[0];
|
||||
|
||||
iowrite32(val, reg);
|
||||
|
||||
dev_dbg(dev, "w %p : %08x\n", reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsnd_regmap_read32(void *context,
|
||||
const void *_data, size_t reg_size,
|
||||
void *_val, size_t val_size)
|
||||
{
|
||||
struct rsnd_priv *priv = context;
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 *data = (u32 *)_data;
|
||||
u32 *val = (u32 *)_val;
|
||||
void __iomem *reg = (void *)data[0];
|
||||
|
||||
*val = ioread32(reg);
|
||||
|
||||
dev_dbg(dev, "r %p : %08x\n", reg, *val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regmap_bus rsnd_regmap_bus = {
|
||||
.write = rsnd_regmap_write32,
|
||||
.read = rsnd_regmap_read32,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
};
|
||||
|
||||
u32 rsnd_read(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod, enum rsnd_reg reg)
|
||||
{
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
u32 val;
|
||||
|
||||
regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void rsnd_write(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data)
|
||||
{
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
|
||||
regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
|
||||
}
|
||||
|
||||
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 mask, u32 data)
|
||||
{
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
|
||||
regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
|
||||
mask, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gen2
|
||||
* will be filled in the future
|
||||
@@ -98,44 +179,64 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct rsnd_gen_ops rsnd_gen1_ops = {
|
||||
.path_init = rsnd_gen1_path_init,
|
||||
.path_exit = rsnd_gen1_path_exit,
|
||||
};
|
||||
/* single address mapping */
|
||||
#define RSND_GEN1_S_REG(gen, reg, id, offset) \
|
||||
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
|
||||
|
||||
#define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
|
||||
do { \
|
||||
(g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \
|
||||
(g)->reg_map[RSND_REG_##i].offset_id = oi; \
|
||||
(g)->reg_map[RSND_REG_##i].offset_adr = oa; \
|
||||
} while (0)
|
||||
/* multi address mapping */
|
||||
#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
|
||||
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
|
||||
|
||||
static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
|
||||
static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
|
||||
{
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20);
|
||||
RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214);
|
||||
int i;
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct regmap_config regc;
|
||||
struct reg_field regf[RSND_REG_MAX] = {
|
||||
RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00),
|
||||
RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08),
|
||||
RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c),
|
||||
RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10),
|
||||
RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0),
|
||||
RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0),
|
||||
RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4),
|
||||
RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4),
|
||||
RSND_GEN1_M_REG(gen, SRU, BUSIF_ADINR, 0x214, 0x40),
|
||||
|
||||
RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c);
|
||||
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20);
|
||||
RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00),
|
||||
RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04),
|
||||
RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08),
|
||||
RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c),
|
||||
RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10),
|
||||
RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18),
|
||||
RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c),
|
||||
RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20),
|
||||
|
||||
RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00);
|
||||
RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04);
|
||||
RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08);
|
||||
RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c);
|
||||
RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20);
|
||||
RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40),
|
||||
RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40),
|
||||
RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40),
|
||||
RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40),
|
||||
RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40),
|
||||
};
|
||||
|
||||
memset(®c, 0, sizeof(regc));
|
||||
regc.reg_bits = 32;
|
||||
regc.val_bits = 32;
|
||||
|
||||
gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c);
|
||||
if (IS_ERR(gen->regmap)) {
|
||||
dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
|
||||
return PTR_ERR(gen->regmap);
|
||||
}
|
||||
|
||||
for (i = 0; i < RSND_REG_MAX; i++) {
|
||||
gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
|
||||
if (IS_ERR(gen->regs[i]))
|
||||
return PTR_ERR(gen->regs[i]);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsnd_gen1_probe(struct platform_device *pdev,
|
||||
@@ -147,6 +248,7 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
|
||||
struct resource *sru_res;
|
||||
struct resource *adg_res;
|
||||
struct resource *ssi_res;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* map address
|
||||
@@ -163,8 +265,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
|
||||
IS_ERR(gen->base[RSND_GEN1_SSI]))
|
||||
return -ENODEV;
|
||||
|
||||
gen->ops = &rsnd_gen1_ops;
|
||||
rsnd_gen1_reg_map_init(gen);
|
||||
ret = rsnd_gen1_regmap_init(priv, gen);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev, "Gen1 device probed\n");
|
||||
dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start,
|
||||
@@ -183,6 +286,13 @@ static void rsnd_gen1_remove(struct platform_device *pdev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct rsnd_gen_ops rsnd_gen1_ops = {
|
||||
.probe = rsnd_gen1_probe,
|
||||
.remove = rsnd_gen1_remove,
|
||||
.path_init = rsnd_gen1_path_init,
|
||||
.path_exit = rsnd_gen1_path_exit,
|
||||
};
|
||||
|
||||
/*
|
||||
* Gen
|
||||
*/
|
||||
@@ -204,46 +314,12 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv,
|
||||
return gen->ops->path_exit(priv, rdai, io);
|
||||
}
|
||||
|
||||
void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg)
|
||||
{
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
int index;
|
||||
u32 offset_id, offset_adr;
|
||||
|
||||
if (reg >= RSND_REG_MAX) {
|
||||
dev_err(dev, "rsnd_reg reg error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index = gen->reg_map[reg].index;
|
||||
offset_id = gen->reg_map[reg].offset_id;
|
||||
offset_adr = gen->reg_map[reg].offset_adr;
|
||||
|
||||
if (index < 0) {
|
||||
dev_err(dev, "unsupported reg access %d\n", reg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (offset_id && mod)
|
||||
offset_id *= rsnd_mod_id(mod);
|
||||
|
||||
/*
|
||||
* index/offset were set on gen1/gen2
|
||||
*/
|
||||
|
||||
return gen->base[index] + offset_id + offset_adr;
|
||||
}
|
||||
|
||||
int rsnd_gen_probe(struct platform_device *pdev,
|
||||
struct rcar_snd_info *info,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct rsnd_gen *gen;
|
||||
int i;
|
||||
|
||||
gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
|
||||
if (!gen) {
|
||||
@@ -251,30 +327,23 @@ int rsnd_gen_probe(struct platform_device *pdev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (rsnd_is_gen1(priv))
|
||||
gen->ops = &rsnd_gen1_ops;
|
||||
|
||||
if (!gen->ops) {
|
||||
dev_err(dev, "unknown generation R-Car sound device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv->gen = gen;
|
||||
|
||||
/*
|
||||
* see
|
||||
* rsnd_reg_get()
|
||||
* rsnd_gen_probe()
|
||||
*/
|
||||
for (i = 0; i < RSND_REG_MAX; i++)
|
||||
gen->reg_map[i].index = -1;
|
||||
|
||||
/*
|
||||
* init each module
|
||||
*/
|
||||
if (rsnd_is_gen1(priv))
|
||||
return rsnd_gen1_probe(pdev, info, priv);
|
||||
|
||||
dev_err(dev, "unknown generation R-Car sound device\n");
|
||||
|
||||
return -ENODEV;
|
||||
return gen->ops->probe(pdev, info, priv);
|
||||
}
|
||||
|
||||
void rsnd_gen_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
if (rsnd_is_gen1(priv))
|
||||
rsnd_gen1_remove(pdev, priv);
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
|
||||
gen->ops->remove(pdev, priv);
|
||||
}
|
||||
|
@@ -78,10 +78,6 @@ struct rsnd_dai_stream;
|
||||
#define rsnd_mod_bset(m, r, s, d) \
|
||||
rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
|
||||
|
||||
#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r)
|
||||
#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d)
|
||||
#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d)
|
||||
|
||||
u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
|
||||
void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data);
|
||||
@@ -285,6 +281,7 @@ int rsnd_scu_probe(struct platform_device *pdev,
|
||||
void rsnd_scu_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
|
||||
bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod);
|
||||
#define rsnd_scu_nr(priv) ((priv)->scu_nr)
|
||||
|
||||
/*
|
||||
|
@@ -146,20 +146,26 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod)
|
||||
{
|
||||
struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
|
||||
u32 flags = rsnd_scu_mode_flags(scu);
|
||||
|
||||
return !!(flags & RSND_SCU_USE_HPBIF);
|
||||
}
|
||||
|
||||
static int rsnd_scu_start(struct rsnd_mod *mod,
|
||||
struct rsnd_dai *rdai,
|
||||
struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||
struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 flags = rsnd_scu_mode_flags(scu);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* SCU will be used if it has RSND_SCU_USE_HPBIF flags
|
||||
*/
|
||||
if (!(flags & RSND_SCU_USE_HPBIF)) {
|
||||
if (!rsnd_scu_hpbif_is_enable(mod)) {
|
||||
/* it use PIO transter */
|
||||
dev_dbg(dev, "%s%d is not used\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod));
|
||||
|
@@ -101,29 +101,30 @@ struct rsnd_ssiu {
|
||||
#define rsnd_ssi_to_ssiu(ssi)\
|
||||
(((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
|
||||
|
||||
static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
|
||||
struct rsnd_ssiu *ssiu)
|
||||
static void rsnd_ssi_mode_set(struct rsnd_priv *priv,
|
||||
struct rsnd_dai *rdai,
|
||||
struct rsnd_ssi *ssi)
|
||||
{
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct rsnd_ssi *ssi;
|
||||
struct rsnd_mod *scu;
|
||||
struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
|
||||
int id = rsnd_mod_id(&ssi->mod);
|
||||
u32 flags;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod));
|
||||
|
||||
/*
|
||||
* SSI_MODE0
|
||||
*/
|
||||
ssiu->ssi_mode0 = 0;
|
||||
for_each_rsnd_ssi(ssi, priv, i) {
|
||||
flags = rsnd_ssi_mode_flags(ssi);
|
||||
|
||||
/* see also BUSIF_MODE */
|
||||
if (!(flags & RSND_SSI_DEPENDENT)) {
|
||||
ssiu->ssi_mode0 |= (1 << i);
|
||||
dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i);
|
||||
} else {
|
||||
dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i);
|
||||
}
|
||||
/* see also BUSIF_MODE */
|
||||
if (rsnd_scu_hpbif_is_enable(scu)) {
|
||||
ssiu->ssi_mode0 &= ~(1 << id);
|
||||
dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id);
|
||||
} else {
|
||||
ssiu->ssi_mode0 |= (1 << id);
|
||||
dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -132,7 +133,7 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
|
||||
#define ssi_parent_set(p, sync, adg, ext) \
|
||||
do { \
|
||||
ssi->parent = ssiu->ssi + p; \
|
||||
if (flags & RSND_SSI_CLK_FROM_ADG) \
|
||||
if (rsnd_rdai_is_clk_master(rdai)) \
|
||||
val = adg; \
|
||||
else \
|
||||
val = ext; \
|
||||
@@ -140,15 +141,11 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
|
||||
val |= sync; \
|
||||
} while (0)
|
||||
|
||||
ssiu->ssi_mode1 = 0;
|
||||
for_each_rsnd_ssi(ssi, priv, i) {
|
||||
flags = rsnd_ssi_mode_flags(ssi);
|
||||
|
||||
if (!(flags & RSND_SSI_CLK_PIN_SHARE))
|
||||
continue;
|
||||
flags = rsnd_ssi_mode_flags(ssi);
|
||||
if (flags & RSND_SSI_CLK_PIN_SHARE) {
|
||||
|
||||
val = 0;
|
||||
switch (i) {
|
||||
switch (id) {
|
||||
case 1:
|
||||
ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0));
|
||||
break;
|
||||
@@ -165,11 +162,6 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
|
||||
|
||||
ssiu->ssi_mode1 |= val;
|
||||
}
|
||||
}
|
||||
|
||||
static void rsnd_ssi_mode_set(struct rsnd_ssi *ssi)
|
||||
{
|
||||
struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
|
||||
|
||||
rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0);
|
||||
rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1);
|
||||
@@ -379,7 +371,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
|
||||
ssi->cr_own = cr;
|
||||
ssi->err = -1; /* ignore 1st error */
|
||||
|
||||
rsnd_ssi_mode_set(ssi);
|
||||
rsnd_ssi_mode_set(priv, rdai, ssi);
|
||||
|
||||
dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
|
||||
|
||||
@@ -706,8 +698,6 @@ int rsnd_ssi_probe(struct platform_device *pdev,
|
||||
rsnd_mod_init(priv, &ssi->mod, ops, i);
|
||||
}
|
||||
|
||||
rsnd_ssi_mode_init(priv, ssiu);
|
||||
|
||||
dev_dbg(dev, "ssi probed\n");
|
||||
|
||||
return 0;
|
||||
|
@@ -11,12 +11,9 @@
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <trace/events/asoc.h>
|
||||
|
||||
@@ -66,6 +63,85 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int snd_soc_cache_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
const struct snd_soc_codec_driver *codec_drv = codec->driver;
|
||||
size_t reg_size;
|
||||
|
||||
reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
|
||||
|
||||
mutex_init(&codec->cache_rw_mutex);
|
||||
|
||||
dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
|
||||
codec->name);
|
||||
|
||||
if (codec_drv->reg_cache_default)
|
||||
codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
|
||||
reg_size, GFP_KERNEL);
|
||||
else
|
||||
codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
|
||||
if (!codec->reg_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: keep in mind that this function might be called
|
||||
* multiple times.
|
||||
*/
|
||||
int snd_soc_cache_exit(struct snd_soc_codec *codec)
|
||||
{
|
||||
dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
|
||||
codec->name);
|
||||
if (!codec->reg_cache)
|
||||
return 0;
|
||||
kfree(codec->reg_cache);
|
||||
codec->reg_cache = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_cache_read: Fetch the value of a given register from the cache.
|
||||
*
|
||||
* @codec: CODEC to configure.
|
||||
* @reg: The register index.
|
||||
* @value: The value to be returned.
|
||||
*/
|
||||
int snd_soc_cache_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int *value)
|
||||
{
|
||||
if (!value)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
*value = snd_soc_get_cache_val(codec->reg_cache, reg,
|
||||
codec->driver->reg_word_size);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_cache_read);
|
||||
|
||||
/**
|
||||
* snd_soc_cache_write: Set the value of a given register in the cache.
|
||||
*
|
||||
* @codec: CODEC to configure.
|
||||
* @reg: The register index.
|
||||
* @value: The new register value.
|
||||
*/
|
||||
int snd_soc_cache_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
snd_soc_set_cache_val(codec->reg_cache, reg, value,
|
||||
codec->driver->reg_word_size);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_cache_write);
|
||||
|
||||
static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
@@ -78,8 +154,8 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
|
||||
ret = snd_soc_cache_read(codec, i, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (codec->reg_def_copy)
|
||||
if (snd_soc_get_cache_val(codec->reg_def_copy,
|
||||
if (codec_drv->reg_cache_default)
|
||||
if (snd_soc_get_cache_val(codec_drv->reg_cache_default,
|
||||
i, codec_drv->reg_word_size) == val)
|
||||
continue;
|
||||
|
||||
@@ -94,150 +170,6 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
snd_soc_set_cache_val(codec->reg_cache, reg, value,
|
||||
codec->driver->reg_word_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int *value)
|
||||
{
|
||||
*value = snd_soc_get_cache_val(codec->reg_cache, reg,
|
||||
codec->driver->reg_word_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
|
||||
{
|
||||
if (!codec->reg_cache)
|
||||
return 0;
|
||||
kfree(codec->reg_cache);
|
||||
codec->reg_cache = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
if (codec->reg_def_copy)
|
||||
codec->reg_cache = kmemdup(codec->reg_def_copy,
|
||||
codec->reg_size, GFP_KERNEL);
|
||||
else
|
||||
codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
|
||||
if (!codec->reg_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* an array of all supported compression types */
|
||||
static const struct snd_soc_cache_ops cache_types[] = {
|
||||
/* Flat *must* be the first entry for fallback */
|
||||
{
|
||||
.id = SND_SOC_FLAT_COMPRESSION,
|
||||
.name = "flat",
|
||||
.init = snd_soc_flat_cache_init,
|
||||
.exit = snd_soc_flat_cache_exit,
|
||||
.read = snd_soc_flat_cache_read,
|
||||
.write = snd_soc_flat_cache_write,
|
||||
.sync = snd_soc_flat_cache_sync
|
||||
},
|
||||
};
|
||||
|
||||
int snd_soc_cache_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
|
||||
if (cache_types[i].id == codec->compress_type)
|
||||
break;
|
||||
|
||||
/* Fall back to flat compression */
|
||||
if (i == ARRAY_SIZE(cache_types)) {
|
||||
dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
|
||||
codec->compress_type);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
mutex_init(&codec->cache_rw_mutex);
|
||||
codec->cache_ops = &cache_types[i];
|
||||
|
||||
if (codec->cache_ops->init) {
|
||||
if (codec->cache_ops->name)
|
||||
dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
|
||||
codec->cache_ops->name, codec->name);
|
||||
return codec->cache_ops->init(codec);
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: keep in mind that this function might be called
|
||||
* multiple times.
|
||||
*/
|
||||
int snd_soc_cache_exit(struct snd_soc_codec *codec)
|
||||
{
|
||||
if (codec->cache_ops && codec->cache_ops->exit) {
|
||||
if (codec->cache_ops->name)
|
||||
dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
|
||||
codec->cache_ops->name, codec->name);
|
||||
return codec->cache_ops->exit(codec);
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_cache_read: Fetch the value of a given register from the cache.
|
||||
*
|
||||
* @codec: CODEC to configure.
|
||||
* @reg: The register index.
|
||||
* @value: The value to be returned.
|
||||
*/
|
||||
int snd_soc_cache_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
|
||||
if (value && codec->cache_ops && codec->cache_ops->read) {
|
||||
ret = codec->cache_ops->read(codec, reg, value);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
return -ENOSYS;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_cache_read);
|
||||
|
||||
/**
|
||||
* snd_soc_cache_write: Set the value of a given register in the cache.
|
||||
*
|
||||
* @codec: CODEC to configure.
|
||||
* @reg: The register index.
|
||||
* @value: The new register value.
|
||||
*/
|
||||
int snd_soc_cache_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&codec->cache_rw_mutex);
|
||||
|
||||
if (codec->cache_ops && codec->cache_ops->write) {
|
||||
ret = codec->cache_ops->write(codec, reg, value);
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&codec->cache_rw_mutex);
|
||||
return -ENOSYS;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_cache_write);
|
||||
|
||||
/**
|
||||
* snd_soc_cache_sync: Sync the register cache with the hardware.
|
||||
*
|
||||
@@ -249,92 +181,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
|
||||
*/
|
||||
int snd_soc_cache_sync(struct snd_soc_codec *codec)
|
||||
{
|
||||
const char *name = "flat";
|
||||
int ret;
|
||||
const char *name;
|
||||
|
||||
if (!codec->cache_sync) {
|
||||
if (!codec->cache_sync)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!codec->cache_ops || !codec->cache_ops->sync)
|
||||
return -ENOSYS;
|
||||
|
||||
if (codec->cache_ops->name)
|
||||
name = codec->cache_ops->name;
|
||||
else
|
||||
name = "unknown";
|
||||
|
||||
if (codec->cache_ops->name)
|
||||
dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
|
||||
codec->cache_ops->name, codec->name);
|
||||
dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
|
||||
codec->name);
|
||||
trace_snd_soc_cache_sync(codec, name, "start");
|
||||
ret = codec->cache_ops->sync(codec);
|
||||
ret = snd_soc_flat_cache_sync(codec);
|
||||
if (!ret)
|
||||
codec->cache_sync = 0;
|
||||
trace_snd_soc_cache_sync(codec, name, "end");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
|
||||
|
||||
static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
const struct snd_soc_codec_driver *codec_drv;
|
||||
unsigned int min, max, index;
|
||||
|
||||
codec_drv = codec->driver;
|
||||
min = 0;
|
||||
max = codec_drv->reg_access_size - 1;
|
||||
do {
|
||||
index = (min + max) / 2;
|
||||
if (codec_drv->reg_access_default[index].reg == reg)
|
||||
return index;
|
||||
if (codec_drv->reg_access_default[index].reg < reg)
|
||||
min = index + 1;
|
||||
else
|
||||
max = index;
|
||||
} while (min <= max);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return 1;
|
||||
index = snd_soc_get_reg_access_index(codec, reg);
|
||||
if (index < 0)
|
||||
return 0;
|
||||
return codec->driver->reg_access_default[index].vol;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
|
||||
|
||||
int snd_soc_default_readable_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return 1;
|
||||
index = snd_soc_get_reg_access_index(codec, reg);
|
||||
if (index < 0)
|
||||
return 0;
|
||||
return codec->driver->reg_access_default[index].read;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
|
||||
|
||||
int snd_soc_default_writable_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return 1;
|
||||
index = snd_soc_get_reg_access_index(codec, reg);
|
||||
if (index < 0)
|
||||
return 0;
|
||||
return codec->driver->reg_access_default[index].write;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);
|
||||
|
@@ -1589,17 +1589,13 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
|
||||
soc_remove_codec(codec);
|
||||
}
|
||||
|
||||
static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
|
||||
enum snd_soc_compress_type compress_type)
|
||||
static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (codec->cache_init)
|
||||
return 0;
|
||||
|
||||
/* override the compress_type if necessary */
|
||||
if (compress_type && codec->compress_type != compress_type)
|
||||
codec->compress_type = compress_type;
|
||||
ret = snd_soc_cache_init(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev,
|
||||
@@ -1614,8 +1610,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
|
||||
static int snd_soc_instantiate_card(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
enum snd_soc_compress_type compress_type;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int ret, i, order, dai_fmt;
|
||||
|
||||
@@ -1639,19 +1633,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
|
||||
list_for_each_entry(codec, &codec_list, list) {
|
||||
if (codec->cache_init)
|
||||
continue;
|
||||
/* by default we don't override the compress_type */
|
||||
compress_type = 0;
|
||||
/* check to see if we need to override the compress_type */
|
||||
for (i = 0; i < card->num_configs; ++i) {
|
||||
codec_conf = &card->codec_conf[i];
|
||||
if (!strcmp(codec->name, codec_conf->dev_name)) {
|
||||
compress_type = codec_conf->compress_type;
|
||||
if (compress_type && compress_type
|
||||
!= codec->compress_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = snd_soc_init_codec_cache(codec, compress_type);
|
||||
ret = snd_soc_init_codec_cache(codec);
|
||||
if (ret < 0)
|
||||
goto base_error;
|
||||
}
|
||||
@@ -2297,13 +2279,6 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_write);
|
||||
|
||||
unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
|
||||
unsigned int reg, const void *data, size_t len)
|
||||
{
|
||||
return codec->bulk_write_raw(codec, reg, data, len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
|
||||
|
||||
/**
|
||||
* snd_soc_update_bits - update codec register bits
|
||||
* @codec: audio codec
|
||||
@@ -3575,6 +3550,22 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
|
||||
|
||||
/**
|
||||
* snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
|
||||
* @dai: DAI
|
||||
* @ratio Ratio of BCLK to Sample rate.
|
||||
*
|
||||
* Configures the DAI for a preset BCLK to sample rate ratio.
|
||||
*/
|
||||
int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
|
||||
{
|
||||
if (dai->driver && dai->driver->ops->set_bclk_ratio)
|
||||
return dai->driver->ops->set_bclk_ratio(dai, ratio);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
|
||||
|
||||
/**
|
||||
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
|
||||
* @dai: DAI
|
||||
@@ -4019,6 +4010,113 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count)
|
||||
snd_soc_unregister_dai(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_component - Register a component with the ASoC core
|
||||
*
|
||||
*/
|
||||
static int
|
||||
__snd_soc_register_component(struct device *dev,
|
||||
struct snd_soc_component *cmpnt,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai, bool allow_single_dai)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "component register %s\n", dev_name(dev));
|
||||
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to connecting component\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->name = fmt_single_name(dev, &cmpnt->id);
|
||||
if (!cmpnt->name) {
|
||||
dev_err(dev, "ASoC: Failed to simplifying name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->dev = dev;
|
||||
cmpnt->driver = cmpnt_drv;
|
||||
cmpnt->dai_drv = dai_drv;
|
||||
cmpnt->num_dai = num_dai;
|
||||
|
||||
/*
|
||||
* snd_soc_register_dai() uses fmt_single_name(), and
|
||||
* snd_soc_register_dais() uses fmt_multiple_name()
|
||||
* for dai->name which is used for name based matching
|
||||
*
|
||||
* this function is used from cpu/codec.
|
||||
* allow_single_dai flag can ignore "codec" driver reworking
|
||||
* since it had been used snd_soc_register_dais(),
|
||||
*/
|
||||
if ((1 == num_dai) && allow_single_dai)
|
||||
ret = snd_soc_register_dai(dev, dai_drv);
|
||||
else
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
goto error_component_name;
|
||||
}
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_add(&cmpnt->list, &component_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
|
||||
|
||||
return ret;
|
||||
|
||||
error_component_name:
|
||||
kfree(cmpnt->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int snd_soc_register_component(struct device *dev,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
|
||||
dai_drv, num_dai, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_component);
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_component - Unregister a component from the ASoC core
|
||||
*
|
||||
*/
|
||||
void snd_soc_unregister_component(struct device *dev)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
list_for_each_entry(cmpnt, &component_list, list) {
|
||||
if (dev == cmpnt->dev)
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, cmpnt->num_dai);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&cmpnt->list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
|
||||
kfree(cmpnt->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
|
||||
|
||||
/**
|
||||
* snd_soc_add_platform - Add a platform to the ASoC core
|
||||
* @dev: The parent device for the platform
|
||||
@@ -4165,7 +4263,6 @@ int snd_soc_register_codec(struct device *dev,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai)
|
||||
{
|
||||
size_t reg_size;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret, i;
|
||||
|
||||
@@ -4182,11 +4279,6 @@ int snd_soc_register_codec(struct device *dev,
|
||||
goto fail_codec;
|
||||
}
|
||||
|
||||
if (codec_drv->compress_type)
|
||||
codec->compress_type = codec_drv->compress_type;
|
||||
else
|
||||
codec->compress_type = SND_SOC_FLAT_COMPRESSION;
|
||||
|
||||
codec->write = codec_drv->write;
|
||||
codec->read = codec_drv->read;
|
||||
codec->volatile_register = codec_drv->volatile_register;
|
||||
@@ -4203,35 +4295,6 @@ int snd_soc_register_codec(struct device *dev,
|
||||
codec->num_dai = num_dai;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
/* allocate CODEC register cache */
|
||||
if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
|
||||
reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
|
||||
codec->reg_size = reg_size;
|
||||
/* it is necessary to make a copy of the default register cache
|
||||
* because in the case of using a compression type that requires
|
||||
* the default register cache to be marked as the
|
||||
* kernel might have freed the array by the time we initialize
|
||||
* the cache.
|
||||
*/
|
||||
if (codec_drv->reg_cache_default) {
|
||||
codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
|
||||
reg_size, GFP_KERNEL);
|
||||
if (!codec->reg_def_copy) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_codec_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
|
||||
if (!codec->volatile_register)
|
||||
codec->volatile_register = snd_soc_default_volatile_register;
|
||||
if (!codec->readable_register)
|
||||
codec->readable_register = snd_soc_default_readable_register;
|
||||
if (!codec->writable_register)
|
||||
codec->writable_register = snd_soc_default_writable_register;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_dai; i++) {
|
||||
fixup_codec_formats(&dai_drv[i].playback);
|
||||
fixup_codec_formats(&dai_drv[i].capture);
|
||||
@@ -4241,10 +4304,12 @@ int snd_soc_register_codec(struct device *dev,
|
||||
list_add(&codec->list, &codec_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
/* register any DAIs */
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
/* register component */
|
||||
ret = __snd_soc_register_component(dev, &codec->component,
|
||||
&codec_drv->component_driver,
|
||||
dai_drv, num_dai, false);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
|
||||
goto fail_codec_name;
|
||||
}
|
||||
|
||||
@@ -4279,7 +4344,7 @@ void snd_soc_unregister_codec(struct device *dev)
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, codec->num_dai);
|
||||
snd_soc_unregister_component(dev);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&codec->list);
|
||||
@@ -4288,98 +4353,11 @@ found:
|
||||
dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
|
||||
|
||||
snd_soc_cache_exit(codec);
|
||||
kfree(codec->reg_def_copy);
|
||||
kfree(codec->name);
|
||||
kfree(codec);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
|
||||
|
||||
|
||||
/**
|
||||
* snd_soc_register_component - Register a component with the ASoC core
|
||||
*
|
||||
*/
|
||||
int snd_soc_register_component(struct device *dev,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
int num_dai)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "component register %s\n", dev_name(dev));
|
||||
|
||||
cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
|
||||
if (!cmpnt) {
|
||||
dev_err(dev, "ASoC: Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->name = fmt_single_name(dev, &cmpnt->id);
|
||||
if (!cmpnt->name) {
|
||||
dev_err(dev, "ASoC: Failed to simplifying name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmpnt->dev = dev;
|
||||
cmpnt->driver = cmpnt_drv;
|
||||
cmpnt->num_dai = num_dai;
|
||||
|
||||
/*
|
||||
* snd_soc_register_dai() uses fmt_single_name(), and
|
||||
* snd_soc_register_dais() uses fmt_multiple_name()
|
||||
* for dai->name which is used for name based matching
|
||||
*/
|
||||
if (1 == num_dai)
|
||||
ret = snd_soc_register_dai(dev, dai_drv);
|
||||
else
|
||||
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
|
||||
goto error_component_name;
|
||||
}
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_add(&cmpnt->list, &component_list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
|
||||
|
||||
return ret;
|
||||
|
||||
error_component_name:
|
||||
kfree(cmpnt->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_component);
|
||||
|
||||
/**
|
||||
* snd_soc_unregister_component - Unregister a component from the ASoC core
|
||||
*
|
||||
*/
|
||||
void snd_soc_unregister_component(struct device *dev)
|
||||
{
|
||||
struct snd_soc_component *cmpnt;
|
||||
|
||||
list_for_each_entry(cmpnt, &component_list, list) {
|
||||
if (dev == cmpnt->dev)
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
snd_soc_unregister_dais(dev, cmpnt->num_dai);
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_del(&cmpnt->list);
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
|
||||
kfree(cmpnt->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
|
||||
|
||||
/* Retrieve a card's name from device tree */
|
||||
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
|
||||
const char *propname)
|
||||
@@ -4567,6 +4545,60 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
|
||||
|
||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||
const char **dai_name)
|
||||
{
|
||||
struct snd_soc_component *pos;
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
|
||||
ret = of_parse_phandle_with_args(of_node, "sound-dai",
|
||||
"#sound-dai-cells", 0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = -EPROBE_DEFER;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
list_for_each_entry(pos, &component_list, list) {
|
||||
if (pos->dev->of_node != args.np)
|
||||
continue;
|
||||
|
||||
if (pos->driver->of_xlate_dai_name) {
|
||||
ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
|
||||
} else {
|
||||
int id = -1;
|
||||
|
||||
switch (args.args_count) {
|
||||
case 0:
|
||||
id = 0; /* same as dai_drv[0] */
|
||||
break;
|
||||
case 1:
|
||||
id = args.args[0];
|
||||
break;
|
||||
default:
|
||||
/* not supported */
|
||||
break;
|
||||
}
|
||||
|
||||
if (id < 0 || id >= pos->num_dai) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
*dai_name = pos->dai_drv[id].name;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
of_node_put(args.np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
|
||||
|
||||
static int __init snd_soc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
@@ -59,31 +59,31 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
||||
/* dapm power sequences - make this per codec in the future */
|
||||
static int dapm_up_seq[] = {
|
||||
[snd_soc_dapm_pre] = 0,
|
||||
[snd_soc_dapm_supply] = 1,
|
||||
[snd_soc_dapm_regulator_supply] = 1,
|
||||
[snd_soc_dapm_clock_supply] = 1,
|
||||
[snd_soc_dapm_micbias] = 2,
|
||||
[snd_soc_dapm_supply] = 2,
|
||||
[snd_soc_dapm_micbias] = 3,
|
||||
[snd_soc_dapm_dai_link] = 2,
|
||||
[snd_soc_dapm_dai_in] = 3,
|
||||
[snd_soc_dapm_dai_out] = 3,
|
||||
[snd_soc_dapm_aif_in] = 3,
|
||||
[snd_soc_dapm_aif_out] = 3,
|
||||
[snd_soc_dapm_mic] = 4,
|
||||
[snd_soc_dapm_mux] = 5,
|
||||
[snd_soc_dapm_virt_mux] = 5,
|
||||
[snd_soc_dapm_value_mux] = 5,
|
||||
[snd_soc_dapm_dac] = 6,
|
||||
[snd_soc_dapm_switch] = 7,
|
||||
[snd_soc_dapm_mixer] = 7,
|
||||
[snd_soc_dapm_mixer_named_ctl] = 7,
|
||||
[snd_soc_dapm_pga] = 8,
|
||||
[snd_soc_dapm_adc] = 9,
|
||||
[snd_soc_dapm_out_drv] = 10,
|
||||
[snd_soc_dapm_hp] = 10,
|
||||
[snd_soc_dapm_spk] = 10,
|
||||
[snd_soc_dapm_line] = 10,
|
||||
[snd_soc_dapm_kcontrol] = 11,
|
||||
[snd_soc_dapm_post] = 12,
|
||||
[snd_soc_dapm_dai_in] = 4,
|
||||
[snd_soc_dapm_dai_out] = 4,
|
||||
[snd_soc_dapm_aif_in] = 4,
|
||||
[snd_soc_dapm_aif_out] = 4,
|
||||
[snd_soc_dapm_mic] = 5,
|
||||
[snd_soc_dapm_mux] = 6,
|
||||
[snd_soc_dapm_virt_mux] = 6,
|
||||
[snd_soc_dapm_value_mux] = 6,
|
||||
[snd_soc_dapm_dac] = 7,
|
||||
[snd_soc_dapm_switch] = 8,
|
||||
[snd_soc_dapm_mixer] = 8,
|
||||
[snd_soc_dapm_mixer_named_ctl] = 8,
|
||||
[snd_soc_dapm_pga] = 9,
|
||||
[snd_soc_dapm_adc] = 10,
|
||||
[snd_soc_dapm_out_drv] = 11,
|
||||
[snd_soc_dapm_hp] = 11,
|
||||
[snd_soc_dapm_spk] = 11,
|
||||
[snd_soc_dapm_line] = 11,
|
||||
[snd_soc_dapm_kcontrol] = 12,
|
||||
[snd_soc_dapm_post] = 13,
|
||||
};
|
||||
|
||||
static int dapm_down_seq[] = {
|
||||
@@ -109,10 +109,10 @@ static int dapm_down_seq[] = {
|
||||
[snd_soc_dapm_dai_in] = 10,
|
||||
[snd_soc_dapm_dai_out] = 10,
|
||||
[snd_soc_dapm_dai_link] = 11,
|
||||
[snd_soc_dapm_clock_supply] = 12,
|
||||
[snd_soc_dapm_regulator_supply] = 12,
|
||||
[snd_soc_dapm_supply] = 12,
|
||||
[snd_soc_dapm_post] = 13,
|
||||
[snd_soc_dapm_clock_supply] = 13,
|
||||
[snd_soc_dapm_regulator_supply] = 13,
|
||||
[snd_soc_dapm_post] = 14,
|
||||
};
|
||||
|
||||
static void pop_wait(u32 pop_time)
|
||||
@@ -409,6 +409,12 @@ static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
|
||||
mutex_unlock(&w->platform->mutex);
|
||||
}
|
||||
|
||||
static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
if (dapm->codec && dapm->codec->using_regmap)
|
||||
regmap_async_complete(dapm->codec->control_data);
|
||||
}
|
||||
|
||||
static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
|
||||
unsigned short reg, unsigned int mask, unsigned int value)
|
||||
{
|
||||
@@ -417,8 +423,9 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
|
||||
int ret;
|
||||
|
||||
if (w->codec && w->codec->using_regmap) {
|
||||
ret = regmap_update_bits_check(w->codec->control_data,
|
||||
reg, mask, value, &change);
|
||||
ret = regmap_update_bits_check_async(w->codec->control_data,
|
||||
reg, mask, value,
|
||||
&change);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
} else {
|
||||
@@ -499,18 +506,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
||||
int val;
|
||||
struct soc_mixer_control *mc = (struct soc_mixer_control *)
|
||||
w->kcontrol_news[i].private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
|
||||
val = soc_widget_read(w, reg);
|
||||
val = (val >> shift) & mask;
|
||||
if (invert)
|
||||
val = max - val;
|
||||
if (reg != SND_SOC_NOPM) {
|
||||
val = soc_widget_read(w, reg);
|
||||
val = (val >> shift) & mask;
|
||||
if (invert)
|
||||
val = max - val;
|
||||
p->connect = !!val;
|
||||
} else {
|
||||
p->connect = 0;
|
||||
}
|
||||
|
||||
p->connect = !!val;
|
||||
}
|
||||
break;
|
||||
case snd_soc_dapm_mux: {
|
||||
@@ -1197,6 +1208,8 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
int ret;
|
||||
|
||||
soc_dapm_async_complete(w->dapm);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
|
||||
ret = regulator_allow_bypass(w->regulator, false);
|
||||
@@ -1230,6 +1243,8 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w,
|
||||
if (!w->clk)
|
||||
return -EIO;
|
||||
|
||||
soc_dapm_async_complete(w->dapm);
|
||||
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
return clk_prepare_enable(w->clk);
|
||||
@@ -1422,6 +1437,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
|
||||
if (w->event && (w->event_flags & event)) {
|
||||
pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
|
||||
w->name, ev_name);
|
||||
soc_dapm_async_complete(w->dapm);
|
||||
trace_snd_soc_dapm_widget_event_start(w, event);
|
||||
ret = w->event(w, NULL, event);
|
||||
trace_snd_soc_dapm_widget_event_done(w, event);
|
||||
@@ -1494,6 +1510,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
||||
struct list_head *list, int event, bool power_up)
|
||||
{
|
||||
struct snd_soc_dapm_widget *w, *n;
|
||||
struct snd_soc_dapm_context *d;
|
||||
LIST_HEAD(pending);
|
||||
int cur_sort = -1;
|
||||
int cur_subseq = -1;
|
||||
@@ -1524,6 +1541,9 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
||||
cur_subseq);
|
||||
}
|
||||
|
||||
if (cur_dapm && w->dapm != cur_dapm)
|
||||
soc_dapm_async_complete(cur_dapm);
|
||||
|
||||
INIT_LIST_HEAD(&pending);
|
||||
cur_sort = -1;
|
||||
cur_subseq = INT_MIN;
|
||||
@@ -1582,6 +1602,10 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
||||
cur_dapm->seq_notifier(cur_dapm,
|
||||
i, cur_subseq);
|
||||
}
|
||||
|
||||
list_for_each_entry(d, &card->dapm_list, list) {
|
||||
soc_dapm_async_complete(d);
|
||||
}
|
||||
}
|
||||
|
||||
static void dapm_widget_update(struct snd_soc_card *card)
|
||||
@@ -1840,6 +1864,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
||||
*/
|
||||
switch (w->id) {
|
||||
case snd_soc_dapm_siggen:
|
||||
case snd_soc_dapm_vmid:
|
||||
break;
|
||||
case snd_soc_dapm_supply:
|
||||
case snd_soc_dapm_regulator_supply:
|
||||
@@ -2791,7 +2816,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
@@ -2804,7 +2829,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
kcontrol->id.name);
|
||||
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
if (dapm_kcontrol_is_powered(kcontrol))
|
||||
if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
|
||||
val = (snd_soc_read(codec, reg) >> shift) & mask;
|
||||
else
|
||||
val = dapm_kcontrol_get_value(kcontrol);
|
||||
@@ -2835,7 +2860,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
@@ -2857,19 +2882,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
|
||||
dapm_kcontrol_set_value(kcontrol, val);
|
||||
change = dapm_kcontrol_set_value(kcontrol, val);
|
||||
|
||||
mask = mask << shift;
|
||||
val = val << shift;
|
||||
if (reg != SND_SOC_NOPM) {
|
||||
mask = mask << shift;
|
||||
val = val << shift;
|
||||
|
||||
change = snd_soc_test_bits(codec, reg, mask, val);
|
||||
}
|
||||
|
||||
change = snd_soc_test_bits(codec, reg, mask, val);
|
||||
if (change) {
|
||||
update.kcontrol = kcontrol;
|
||||
update.reg = reg;
|
||||
update.mask = mask;
|
||||
update.val = val;
|
||||
if (reg != SND_SOC_NOPM) {
|
||||
update.kcontrol = kcontrol;
|
||||
update.reg = reg;
|
||||
update.mask = mask;
|
||||
update.val = val;
|
||||
|
||||
card->update = &update;
|
||||
card->update = &update;
|
||||
}
|
||||
|
||||
soc_dapm_mixer_update_power(card, kcontrol, connect);
|
||||
|
||||
|
86
sound/soc/soc-devres.c
Normal file
86
sound/soc/soc-devres.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* soc-devres.c -- ALSA SoC Audio Layer devres functions
|
||||
*
|
||||
* Copyright (C) 2013 Linaro Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
static void devm_component_release(struct device *dev, void *res)
|
||||
{
|
||||
snd_soc_unregister_component(*(struct device **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_snd_soc_register_component - resource managed component registration
|
||||
* @dev: Device used to manage component
|
||||
* @cmpnt_drv: Component driver
|
||||
* @dai_drv: DAI driver
|
||||
* @num_dai: Number of DAIs to register
|
||||
*
|
||||
* Register a component with automatic unregistration when the device is
|
||||
* unregistered.
|
||||
*/
|
||||
int devm_snd_soc_register_component(struct device *dev,
|
||||
const struct snd_soc_component_driver *cmpnt_drv,
|
||||
struct snd_soc_dai_driver *dai_drv, int num_dai)
|
||||
{
|
||||
struct device **ptr;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
|
||||
if (ret == 0) {
|
||||
*ptr = dev;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
|
||||
|
||||
static void devm_card_release(struct device *dev, void *res)
|
||||
{
|
||||
snd_soc_unregister_card(*(struct snd_soc_card **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_snd_soc_register_card - resource managed card registration
|
||||
* @dev: Device used to manage card
|
||||
* @card: Card to register
|
||||
*
|
||||
* Register a card with automatic unregistration when the device is
|
||||
* unregistered.
|
||||
*/
|
||||
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
|
||||
{
|
||||
struct device **ptr;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret == 0) {
|
||||
*ptr = dev;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
|
@@ -36,6 +36,15 @@ static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
|
||||
return container_of(p, struct dmaengine_pcm, platform);
|
||||
}
|
||||
|
||||
static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (!pcm->chan[substream->stream])
|
||||
return NULL;
|
||||
|
||||
return pcm->chan[substream->stream]->device->dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
|
||||
* @substream: PCM substream
|
||||
@@ -75,12 +84,19 @@ static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
|
||||
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
|
||||
int (*prepare_slave_config)(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct dma_slave_config *slave_config);
|
||||
struct dma_slave_config slave_config;
|
||||
int ret;
|
||||
|
||||
if (pcm->config->prepare_slave_config) {
|
||||
ret = pcm->config->prepare_slave_config(substream, params,
|
||||
&slave_config);
|
||||
if (!pcm->config)
|
||||
prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config;
|
||||
else
|
||||
prepare_slave_config = pcm->config->prepare_slave_config;
|
||||
|
||||
if (prepare_slave_config) {
|
||||
ret = prepare_slave_config(substream, params, &slave_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -92,6 +108,42 @@ static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
}
|
||||
|
||||
static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
|
||||
struct device *dma_dev = dmaengine_dma_dev(pcm, substream);
|
||||
struct dma_chan *chan = pcm->chan[substream->stream];
|
||||
struct snd_dmaengine_dai_dma_data *dma_data;
|
||||
struct dma_slave_caps dma_caps;
|
||||
struct snd_pcm_hardware hw;
|
||||
int ret;
|
||||
|
||||
if (pcm->config && pcm->config->pcm_hardware)
|
||||
return snd_soc_set_runtime_hwparams(substream,
|
||||
pcm->config->pcm_hardware);
|
||||
|
||||
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
memset(&hw, 0, sizeof(hw));
|
||||
hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_INTERLEAVED;
|
||||
hw.periods_min = 2;
|
||||
hw.periods_max = UINT_MAX;
|
||||
hw.period_bytes_min = 256;
|
||||
hw.period_bytes_max = dma_get_max_seg_size(dma_dev);
|
||||
hw.buffer_bytes_max = SIZE_MAX;
|
||||
hw.fifo_size = dma_data->fifo_size;
|
||||
|
||||
ret = dma_get_slave_caps(chan, &dma_caps);
|
||||
if (ret == 0) {
|
||||
if (dma_caps.cmd_pause)
|
||||
hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
|
||||
}
|
||||
|
||||
return snd_soc_set_runtime_hwparams(substream, &hw);
|
||||
}
|
||||
|
||||
static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
@@ -99,23 +151,13 @@ static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
|
||||
struct dma_chan *chan = pcm->chan[substream->stream];
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_set_runtime_hwparams(substream,
|
||||
pcm->config->pcm_hardware);
|
||||
ret = dmaengine_pcm_set_runtime_hwparams(substream);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return snd_dmaengine_pcm_open(substream, chan);
|
||||
}
|
||||
|
||||
static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (!pcm->chan[substream->stream])
|
||||
return NULL;
|
||||
|
||||
return pcm->chan[substream->stream]->device->dev;
|
||||
}
|
||||
|
||||
static void dmaengine_pcm_free(struct snd_pcm *pcm)
|
||||
{
|
||||
snd_pcm_lib_preallocate_free_for_all(pcm);
|
||||
@@ -126,6 +168,9 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
|
||||
struct snd_dmaengine_dai_dma_data *dma_data;
|
||||
|
||||
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0])
|
||||
return pcm->chan[0];
|
||||
@@ -134,22 +179,42 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
|
||||
return pcm->config->compat_request_channel(rtd, substream);
|
||||
|
||||
return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn,
|
||||
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
|
||||
dma_data->filter_data);
|
||||
}
|
||||
|
||||
static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
|
||||
const struct snd_dmaengine_pcm_config *config = pcm->config;
|
||||
struct device *dev = rtd->platform->dev;
|
||||
struct snd_dmaengine_dai_dma_data *dma_data;
|
||||
struct snd_pcm_substream *substream;
|
||||
size_t prealloc_buffer_size;
|
||||
size_t max_buffer_size;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (config && config->prealloc_buffer_size) {
|
||||
prealloc_buffer_size = config->prealloc_buffer_size;
|
||||
max_buffer_size = config->pcm_hardware->buffer_bytes_max;
|
||||
} else {
|
||||
prealloc_buffer_size = 512 * 1024;
|
||||
max_buffer_size = SIZE_MAX;
|
||||
}
|
||||
|
||||
|
||||
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
|
||||
substream = rtd->pcm->streams[i].substream;
|
||||
if (!substream)
|
||||
continue;
|
||||
|
||||
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
if (!pcm->chan[i] &&
|
||||
(pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME))
|
||||
pcm->chan[i] = dma_request_slave_channel(dev,
|
||||
dma_data->chan_name);
|
||||
|
||||
if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
|
||||
pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd,
|
||||
substream);
|
||||
@@ -165,8 +230,8 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||
ret = snd_pcm_lib_preallocate_pages(substream,
|
||||
SNDRV_DMA_TYPE_DEV,
|
||||
dmaengine_dma_dev(pcm, substream),
|
||||
config->prealloc_buffer_size,
|
||||
config->pcm_hardware->buffer_bytes_max);
|
||||
prealloc_buffer_size,
|
||||
max_buffer_size);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
}
|
||||
@@ -222,7 +287,9 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node)
|
||||
if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
|
||||
SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
|
||||
!dev->of_node)
|
||||
return;
|
||||
|
||||
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
|
||||
|
@@ -65,31 +65,6 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Primitive bulk write support for soc-cache. The data pointed to by
|
||||
* `data' needs to already be in the form the hardware expects. Any
|
||||
* data written through this function will not go through the cache as
|
||||
* it only handles writing to volatile or out of bounds registers.
|
||||
*
|
||||
* This is currently only supported for devices using the regmap API
|
||||
* wrappers.
|
||||
*/
|
||||
static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
|
||||
unsigned int reg,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
/* To ensure that we don't get out of sync with the cache, check
|
||||
* whether the base register is volatile or if we've directly asked
|
||||
* to bypass the cache. Out of bounds registers are considered
|
||||
* volatile.
|
||||
*/
|
||||
if (!codec->cache_bypass
|
||||
&& !snd_soc_codec_volatile_register(codec, reg)
|
||||
&& reg < codec->driver->reg_cache_size)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_raw_write(codec->control_data, reg, data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
|
||||
*
|
||||
@@ -119,7 +94,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
|
||||
memset(&config, 0, sizeof(config));
|
||||
codec->write = hw_write;
|
||||
codec->read = hw_read;
|
||||
codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
|
||||
|
||||
config.reg_bits = addr_bits;
|
||||
config.val_bits = data_bits;
|
||||
|
@@ -65,6 +65,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
struct snd_soc_jack_pin *pin;
|
||||
unsigned int sync = 0;
|
||||
int enable;
|
||||
|
||||
trace_snd_soc_jack_report(jack, mask, status);
|
||||
@@ -92,12 +93,16 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
|
||||
snd_soc_dapm_enable_pin(dapm, pin->pin);
|
||||
else
|
||||
snd_soc_dapm_disable_pin(dapm, pin->pin);
|
||||
|
||||
/* we need to sync for this case only */
|
||||
sync = 1;
|
||||
}
|
||||
|
||||
/* Report before the DAPM sync to help users updating micbias status */
|
||||
blocking_notifier_call_chain(&jack->notifier, jack->status, jack);
|
||||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
if (sync)
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
snd_jack_report(jack->jack, jack->status);
|
||||
|
||||
|
@@ -721,7 +721,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
|
||||
list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
|
||||
list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
|
||||
|
||||
dev_dbg(fe->dev, " connected new DPCM %s path %s %s %s\n",
|
||||
dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
|
||||
stream ? "capture" : "playback", fe->dai_link->name,
|
||||
stream ? "<-" : "->", be->dai_link->name);
|
||||
|
||||
@@ -749,7 +749,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
|
||||
if (dpcm->fe == fe)
|
||||
continue;
|
||||
|
||||
dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
|
||||
dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
|
||||
stream ? "capture" : "playback",
|
||||
dpcm->fe->dai_link->name,
|
||||
stream ? "<-" : "->", dpcm->be->dai_link->name);
|
||||
@@ -773,7 +773,7 @@ static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
|
||||
continue;
|
||||
|
||||
dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
|
||||
dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n",
|
||||
stream ? "capture" : "playback", fe->dai_link->name,
|
||||
stream ? "<-" : "->", dpcm->be->dai_link->name);
|
||||
|
||||
@@ -2116,7 +2116,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
|
||||
pcm->private_free = platform->driver->pcm_free;
|
||||
out:
|
||||
dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name,
|
||||
dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name,
|
||||
cpu_dai->name);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -75,7 +75,11 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
|
||||
|
||||
static int dummy_dma_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
|
||||
/* BE's dont need dummy params */
|
||||
if (!rtd->dai_link->no_pcm)
|
||||
snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -257,20 +257,12 @@ static int spdif_in_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_register_component(&pdev->dev, &spdif_in_component,
|
||||
&spdif_in_dai, 1);
|
||||
}
|
||||
|
||||
static int spdif_in_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
return devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
|
||||
&spdif_in_dai, 1);
|
||||
}
|
||||
|
||||
static struct platform_driver spdif_in_driver = {
|
||||
.probe = spdif_in_probe,
|
||||
.remove = spdif_in_remove,
|
||||
.driver = {
|
||||
.name = "spdif-in",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -280,7 +280,6 @@ static int spdif_out_probe(struct platform_device *pdev)
|
||||
struct spdif_out_dev *host;
|
||||
struct spear_spdif_platform_data *pdata;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host) {
|
||||
@@ -307,16 +306,8 @@ static int spdif_out_probe(struct platform_device *pdev)
|
||||
|
||||
dev_set_drvdata(&pdev->dev, host);
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
|
||||
&spdif_out_dai, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spdif_out_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
return devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
|
||||
&spdif_out_dai, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -357,7 +348,6 @@ static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \
|
||||
|
||||
static struct platform_driver spdif_out_driver = {
|
||||
.probe = spdif_out_probe,
|
||||
.remove = spdif_out_remove,
|
||||
.driver = {
|
||||
.name = "spdif-out",
|
||||
.owner = THIS_MODULE,
|
||||
|
@@ -100,6 +100,7 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
|
||||
{
|
||||
int channel;
|
||||
u32 reg, val;
|
||||
struct tegra30_ahub_cif_conf cif_conf;
|
||||
|
||||
channel = find_first_zero_bit(ahub->rx_usage,
|
||||
TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
|
||||
@@ -123,15 +124,21 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
|
||||
TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
|
||||
tegra30_apbif_write(reg, val);
|
||||
|
||||
cif_conf.threshold = 0;
|
||||
cif_conf.audio_channels = 2;
|
||||
cif_conf.client_channels = 2;
|
||||
cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
|
||||
cif_conf.truncate = 0;
|
||||
cif_conf.mono_conv = 0;
|
||||
|
||||
reg = TEGRA30_AHUB_CIF_RX_CTRL +
|
||||
(channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
|
||||
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
||||
(1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
||||
(1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
|
||||
TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
|
||||
TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
|
||||
TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
|
||||
tegra30_apbif_write(reg, val);
|
||||
ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -183,6 +190,7 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
|
||||
{
|
||||
int channel;
|
||||
u32 reg, val;
|
||||
struct tegra30_ahub_cif_conf cif_conf;
|
||||
|
||||
channel = find_first_zero_bit(ahub->tx_usage,
|
||||
TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
|
||||
@@ -206,15 +214,21 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
|
||||
TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
|
||||
tegra30_apbif_write(reg, val);
|
||||
|
||||
cif_conf.threshold = 0;
|
||||
cif_conf.audio_channels = 2;
|
||||
cif_conf.client_channels = 2;
|
||||
cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
|
||||
cif_conf.truncate = 0;
|
||||
cif_conf.mono_conv = 0;
|
||||
|
||||
reg = TEGRA30_AHUB_CIF_TX_CTRL +
|
||||
(channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
|
||||
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
||||
(1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
||||
(1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
|
||||
TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
|
||||
TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
|
||||
TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
|
||||
tegra30_apbif_write(reg, val);
|
||||
ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -437,13 +451,21 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
|
||||
|
||||
static struct tegra30_ahub_soc_data soc_data_tegra30 = {
|
||||
.clk_list_mask = CLK_LIST_MASK_TEGRA30,
|
||||
.set_audio_cif = tegra30_ahub_set_cif,
|
||||
};
|
||||
|
||||
static struct tegra30_ahub_soc_data soc_data_tegra114 = {
|
||||
.clk_list_mask = CLK_LIST_MASK_TEGRA114,
|
||||
.set_audio_cif = tegra30_ahub_set_cif,
|
||||
};
|
||||
|
||||
static struct tegra30_ahub_soc_data soc_data_tegra124 = {
|
||||
.clk_list_mask = CLK_LIST_MASK_TEGRA114,
|
||||
.set_audio_cif = tegra124_ahub_set_cif,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra30_ahub_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 },
|
||||
{ .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
|
||||
{ .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 },
|
||||
{},
|
||||
@@ -497,6 +519,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
|
||||
}
|
||||
dev_set_drvdata(&pdev->dev, ahub);
|
||||
|
||||
ahub->soc_data = soc_data;
|
||||
ahub->dev = &pdev->dev;
|
||||
|
||||
ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
|
||||
@@ -669,6 +692,70 @@ static struct platform_driver tegra30_ahub_driver = {
|
||||
};
|
||||
module_platform_driver(tegra30_ahub_driver);
|
||||
|
||||
void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
|
||||
struct tegra30_ahub_cif_conf *conf)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
value = (conf->threshold <<
|
||||
TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
||||
((conf->audio_channels - 1) <<
|
||||
TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
||||
((conf->client_channels - 1) <<
|
||||
TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
|
||||
(conf->audio_bits <<
|
||||
TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
|
||||
(conf->client_bits <<
|
||||
TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
|
||||
(conf->expand <<
|
||||
TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
|
||||
(conf->stereo_conv <<
|
||||
TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
|
||||
(conf->replicate <<
|
||||
TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
|
||||
(conf->direction <<
|
||||
TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
|
||||
(conf->truncate <<
|
||||
TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
|
||||
(conf->mono_conv <<
|
||||
TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
|
||||
|
||||
regmap_write(regmap, reg, value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif);
|
||||
|
||||
void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
|
||||
struct tegra30_ahub_cif_conf *conf)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
value = (conf->threshold <<
|
||||
TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
||||
((conf->audio_channels - 1) <<
|
||||
TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
||||
((conf->client_channels - 1) <<
|
||||
TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
|
||||
(conf->audio_bits <<
|
||||
TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
|
||||
(conf->client_bits <<
|
||||
TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
|
||||
(conf->expand <<
|
||||
TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
|
||||
(conf->stereo_conv <<
|
||||
TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
|
||||
(conf->replicate <<
|
||||
TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
|
||||
(conf->direction <<
|
||||
TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
|
||||
(conf->truncate <<
|
||||
TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
|
||||
(conf->mono_conv <<
|
||||
TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
|
||||
|
||||
regmap_write(regmap, reg, value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif);
|
||||
|
||||
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
|
||||
MODULE_DESCRIPTION("Tegra30 AHUB driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -25,16 +25,30 @@
|
||||
#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf
|
||||
#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
|
||||
|
||||
#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 24
|
||||
#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0x3f
|
||||
#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
|
||||
|
||||
/* Channel count minus 1 */
|
||||
#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24
|
||||
#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7
|
||||
#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
|
||||
|
||||
/* Channel count minus 1 */
|
||||
#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 20
|
||||
#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 0xf
|
||||
#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
|
||||
|
||||
/* Channel count minus 1 */
|
||||
#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
|
||||
#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7
|
||||
#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
|
||||
|
||||
/* Channel count minus 1 */
|
||||
#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
|
||||
#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 0xf
|
||||
#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
|
||||
|
||||
#define TEGRA30_AUDIOCIF_BITS_4 0
|
||||
#define TEGRA30_AUDIOCIF_BITS_8 1
|
||||
#define TEGRA30_AUDIOCIF_BITS_12 2
|
||||
@@ -86,7 +100,7 @@
|
||||
#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
|
||||
#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
|
||||
|
||||
#define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3
|
||||
#define TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT 3
|
||||
|
||||
#define TEGRA30_AUDIOCIF_DIRECTION_TX 0
|
||||
#define TEGRA30_AUDIOCIF_DIRECTION_RX 1
|
||||
@@ -468,8 +482,30 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
|
||||
enum tegra30_ahub_txcif txcif);
|
||||
extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
|
||||
|
||||
struct tegra30_ahub_cif_conf {
|
||||
unsigned int threshold;
|
||||
unsigned int audio_channels;
|
||||
unsigned int client_channels;
|
||||
unsigned int audio_bits;
|
||||
unsigned int client_bits;
|
||||
unsigned int expand;
|
||||
unsigned int stereo_conv;
|
||||
unsigned int replicate;
|
||||
unsigned int direction;
|
||||
unsigned int truncate;
|
||||
unsigned int mono_conv;
|
||||
};
|
||||
|
||||
void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
|
||||
struct tegra30_ahub_cif_conf *conf);
|
||||
void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
|
||||
struct tegra30_ahub_cif_conf *conf);
|
||||
|
||||
struct tegra30_ahub_soc_data {
|
||||
u32 clk_list_mask;
|
||||
void (*set_audio_cif)(struct regmap *regmap,
|
||||
unsigned int reg,
|
||||
struct tegra30_ahub_cif_conf *conf);
|
||||
/*
|
||||
* FIXME: There are many more differences in HW, such as:
|
||||
* - More APBIF channels.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user