Merge branch 'topic/asoc' into for-linus
This commit is contained in:
commit
bb14eb0da7
@ -530,6 +530,7 @@ S: Maintained
|
||||
F: drivers/infiniband/hw/amso1100/
|
||||
|
||||
ANALOG DEVICES INC ASOC CODEC DRIVERS
|
||||
M: Lars-Peter Clausen <lars@metafoo.de>
|
||||
L: device-drivers-devel@blackfin.uclinux.org
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
W: http://wiki.analog.com/
|
||||
@ -7199,6 +7200,7 @@ T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
|
||||
W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
|
||||
S: Supported
|
||||
F: Documentation/hwmon/wm83??
|
||||
F: arch/arm/mach-s3c64xx/mach-crag6410*
|
||||
F: drivers/leds/leds-wm83*.c
|
||||
F: drivers/input/misc/wm831x-on.c
|
||||
F: drivers/input/touchscreen/wm831x-ts.c
|
||||
|
@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
|
||||
};
|
||||
|
||||
static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
|
||||
.id = TPA6130A2,
|
||||
.power_gpio = 98,
|
||||
};
|
||||
|
||||
|
@ -330,6 +330,38 @@ static void omap_init_audio(void)
|
||||
static inline void omap_init_audio(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
|
||||
|
||||
static struct omap_device_pm_latency omap_mcpdm_latency[] = {
|
||||
{
|
||||
.deactivate_func = omap_device_idle_hwmods,
|
||||
.activate_func = omap_device_enable_hwmods,
|
||||
.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
|
||||
},
|
||||
};
|
||||
|
||||
static void omap_init_mcpdm(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct omap_device *od;
|
||||
|
||||
oh = omap_hwmod_lookup("mcpdm");
|
||||
if (!oh) {
|
||||
printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
|
||||
return;
|
||||
}
|
||||
|
||||
od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
|
||||
omap_mcpdm_latency,
|
||||
ARRAY_SIZE(omap_mcpdm_latency), 0);
|
||||
if (IS_ERR(od))
|
||||
printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
|
||||
}
|
||||
#else
|
||||
static inline void omap_init_mcpdm(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
|
||||
|
||||
#include <plat/mcspi.h>
|
||||
@ -683,6 +715,7 @@ static int __init omap2_init_devices(void)
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
omap_init_audio();
|
||||
omap_init_mcpdm();
|
||||
omap_init_camera();
|
||||
omap_init_mbox();
|
||||
omap_init_mcspi();
|
||||
|
@ -5430,7 +5430,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
|
||||
&omap44xx_mcbsp4_hwmod,
|
||||
|
||||
/* mcpdm class */
|
||||
/* &omap44xx_mcpdm_hwmod, */
|
||||
&omap44xx_mcpdm_hwmod,
|
||||
|
||||
/* mcspi class */
|
||||
&omap44xx_mcspi1_hwmod,
|
||||
|
@ -74,41 +74,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
|
||||
|
||||
static struct resource mcpdm_resources[] = {
|
||||
{
|
||||
.name = "mcpdm_mem",
|
||||
.start = OMAP44XX_MCPDM_BASE,
|
||||
.end = OMAP44XX_MCPDM_BASE + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "mcpdm_irq",
|
||||
.start = OMAP44XX_IRQ_MCPDM,
|
||||
.end = OMAP44XX_IRQ_MCPDM,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device omap_mcpdm_device = {
|
||||
.name = "omap-mcpdm",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(mcpdm_resources),
|
||||
.resource = mcpdm_resources,
|
||||
};
|
||||
|
||||
static void omap_init_mcpdm(void)
|
||||
{
|
||||
(void) platform_device_register(&omap_mcpdm_device);
|
||||
}
|
||||
#else
|
||||
static inline void omap_init_mcpdm(void) {}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
|
||||
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
||||
|
||||
@ -291,7 +256,6 @@ static int __init omap_init_devices(void)
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
omap_init_rng();
|
||||
omap_init_mcpdm();
|
||||
omap_init_uwire();
|
||||
return 0;
|
||||
}
|
||||
|
@ -74,12 +74,12 @@ static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
|
||||
if (status & TWL6040_VIBLOCDET) {
|
||||
dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
|
||||
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
|
||||
TWL6040_VIBENAL);
|
||||
TWL6040_VIBENA);
|
||||
}
|
||||
if (status & TWL6040_VIBROCDET) {
|
||||
dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
|
||||
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
|
||||
TWL6040_VIBENAR);
|
||||
TWL6040_VIBENA);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -104,16 +104,16 @@ static void twl6040_vibra_enable(struct vibra_info *info)
|
||||
* overcurrent detection
|
||||
*/
|
||||
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
|
||||
TWL6040_VIBENAL | TWL6040_VIBCTRLL);
|
||||
TWL6040_VIBENA | TWL6040_VIBCTRL);
|
||||
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
|
||||
TWL6040_VIBENAR | TWL6040_VIBCTRLR);
|
||||
TWL6040_VIBENA | TWL6040_VIBCTRL);
|
||||
usleep_range(3000, 3500);
|
||||
}
|
||||
|
||||
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
|
||||
TWL6040_VIBENAL);
|
||||
TWL6040_VIBENA);
|
||||
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
|
||||
TWL6040_VIBENAR);
|
||||
TWL6040_VIBENA);
|
||||
|
||||
info->enabled = true;
|
||||
}
|
||||
@ -201,6 +201,13 @@ static int vibra_play(struct input_dev *input, void *data,
|
||||
struct vibra_info *info = input_get_drvdata(input);
|
||||
int ret;
|
||||
|
||||
/* Do not allow effect, while the routing is set to use audio */
|
||||
ret = twl6040_get_vibralr_status(info->twl6040);
|
||||
if (ret & TWL6040_VIBSEL) {
|
||||
dev_info(&input->dev, "Vibra is configured for audio\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
info->weak_speed = effect->u.rumble.weak_magnitude;
|
||||
info->strong_speed = effect->u.rumble.strong_magnitude;
|
||||
info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
|
||||
|
@ -34,17 +34,25 @@
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/twl6040.h>
|
||||
|
||||
#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
|
||||
|
||||
int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
|
||||
{
|
||||
int ret;
|
||||
u8 val = 0;
|
||||
|
||||
mutex_lock(&twl6040->io_mutex);
|
||||
/* Vibra control registers from cache */
|
||||
if (unlikely(reg == TWL6040_REG_VIBCTLL ||
|
||||
reg == TWL6040_REG_VIBCTLR)) {
|
||||
val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
|
||||
} else {
|
||||
ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&twl6040->io_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&twl6040->io_mutex);
|
||||
|
||||
return val;
|
||||
@ -57,6 +65,9 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
|
||||
|
||||
mutex_lock(&twl6040->io_mutex);
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
|
||||
/* Cache the vibra control registers */
|
||||
if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
|
||||
twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
|
||||
mutex_unlock(&twl6040->io_mutex);
|
||||
|
||||
return ret;
|
||||
@ -433,6 +444,18 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
|
||||
}
|
||||
EXPORT_SYMBOL(twl6040_get_sysclk);
|
||||
|
||||
/* Get the combined status of the vibra control register */
|
||||
int twl6040_get_vibralr_status(struct twl6040 *twl6040)
|
||||
{
|
||||
u8 status;
|
||||
|
||||
status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
|
||||
status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(twl6040_get_vibralr_status);
|
||||
|
||||
static struct resource twl6040_vibra_rsrc[] = {
|
||||
{
|
||||
.flags = IORESOURCE_IRQ,
|
||||
|
@ -243,6 +243,18 @@ static struct mfd_cell wm8994_devs[] = {
|
||||
* and should be handled via the standard regulator API supply
|
||||
* management.
|
||||
*/
|
||||
static const char *wm1811_main_supplies[] = {
|
||||
"DBVDD1",
|
||||
"DBVDD2",
|
||||
"DBVDD3",
|
||||
"DCVDD",
|
||||
"AVDD1",
|
||||
"AVDD2",
|
||||
"CPVDD",
|
||||
"SPKVDD1",
|
||||
"SPKVDD2",
|
||||
};
|
||||
|
||||
static const char *wm8994_main_supplies[] = {
|
||||
"DBVDD",
|
||||
"DCVDD",
|
||||
@ -401,6 +413,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
||||
}
|
||||
|
||||
switch (wm8994->type) {
|
||||
case WM1811:
|
||||
wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
|
||||
break;
|
||||
case WM8994:
|
||||
wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
|
||||
break;
|
||||
@ -421,6 +436,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
||||
}
|
||||
|
||||
switch (wm8994->type) {
|
||||
case WM1811:
|
||||
for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
|
||||
wm8994->supplies[i].supply = wm1811_main_supplies[i];
|
||||
break;
|
||||
case WM8994:
|
||||
for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
|
||||
wm8994->supplies[i].supply = wm8994_main_supplies[i];
|
||||
@ -454,6 +473,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
||||
goto err_enable;
|
||||
}
|
||||
switch (ret) {
|
||||
case 0x1811:
|
||||
devname = "WM1811";
|
||||
if (wm8994->type != WM1811)
|
||||
dev_warn(wm8994->dev, "Device registered as type %d\n",
|
||||
wm8994->type);
|
||||
wm8994->type = WM1811;
|
||||
break;
|
||||
case 0x8994:
|
||||
devname = "WM8994";
|
||||
if (wm8994->type != WM8994)
|
||||
@ -651,6 +677,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id wm8994_i2c_id[] = {
|
||||
{ "wm1811", WM1811 },
|
||||
{ "wm8994", WM8994 },
|
||||
{ "wm8958", WM8958 },
|
||||
{ }
|
||||
|
@ -1599,13 +1599,18 @@ static void regulator_disable_work(struct work_struct *work)
|
||||
int regulator_disable_deferred(struct regulator *regulator, int ms)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&rdev->mutex);
|
||||
rdev->deferred_disables++;
|
||||
mutex_unlock(&rdev->mutex);
|
||||
|
||||
return schedule_delayed_work(&rdev->disable_work,
|
||||
ret = schedule_delayed_work(&rdev->disable_work,
|
||||
msecs_to_jiffies(ms));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_disable_deferred);
|
||||
|
||||
|
@ -140,6 +140,14 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
||||
return (selector * 100000) + 900000;
|
||||
case WM8958:
|
||||
return (selector * 100000) + 1000000;
|
||||
case WM1811:
|
||||
switch (selector) {
|
||||
case 0:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return (selector * 100000) + 950000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -170,6 +178,11 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
|
||||
case WM8958:
|
||||
selector = (min_uV - 1000000) / 100000;
|
||||
break;
|
||||
case WM1811:
|
||||
selector = (min_uV - 950000) / 100000;
|
||||
if (selector == 0)
|
||||
selector = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -68,8 +68,6 @@
|
||||
#define TWL6040_REG_ACCCTL 0x2D
|
||||
#define TWL6040_REG_STATUS 0x2E
|
||||
|
||||
#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
|
||||
|
||||
/* INTID (0x03) fields */
|
||||
|
||||
#define TWL6040_THINT 0x01
|
||||
@ -122,34 +120,24 @@
|
||||
#define TWL6040_LPLLFIN 0x08
|
||||
#define TWL6040_HPLLSEL 0x10
|
||||
|
||||
/* HSLCTL (0x10) fields */
|
||||
/* HSLCTL/R (0x10/0x11) fields */
|
||||
|
||||
#define TWL6040_HSDACMODEL 0x02
|
||||
#define TWL6040_HSDRVMODEL 0x08
|
||||
#define TWL6040_HSDACENA (1 << 0)
|
||||
#define TWL6040_HSDACMODE (1 << 1)
|
||||
#define TWL6040_HSDRVMODE (1 << 3)
|
||||
|
||||
/* HSRCTL (0x11) fields */
|
||||
/* VIBCTLL/R (0x18/0x1A) fields */
|
||||
|
||||
#define TWL6040_HSDACMODER 0x02
|
||||
#define TWL6040_HSDRVMODER 0x08
|
||||
#define TWL6040_VIBENA (1 << 0)
|
||||
#define TWL6040_VIBSEL (1 << 1)
|
||||
#define TWL6040_VIBCTRL (1 << 2)
|
||||
#define TWL6040_VIBCTRL_P (1 << 3)
|
||||
#define TWL6040_VIBCTRL_N (1 << 4)
|
||||
|
||||
/* VIBCTLL (0x18) fields */
|
||||
|
||||
#define TWL6040_VIBENAL 0x01
|
||||
#define TWL6040_VIBCTRLL 0x04
|
||||
#define TWL6040_VIBCTRLLP 0x08
|
||||
#define TWL6040_VIBCTRLLN 0x10
|
||||
|
||||
/* VIBDATL (0x19) fields */
|
||||
/* VIBDATL/R (0x19/0x1B) fields */
|
||||
|
||||
#define TWL6040_VIBDAT_MAX 0x64
|
||||
|
||||
/* VIBCTLR (0x1A) fields */
|
||||
|
||||
#define TWL6040_VIBENAR 0x01
|
||||
#define TWL6040_VIBCTRLR 0x04
|
||||
#define TWL6040_VIBCTRLRP 0x08
|
||||
#define TWL6040_VIBCTRLRN 0x10
|
||||
|
||||
/* GPOCTL (0x1E) fields */
|
||||
|
||||
#define TWL6040_GPO1 0x01
|
||||
@ -197,6 +185,7 @@ struct twl6040 {
|
||||
int audpwron;
|
||||
int power_count;
|
||||
int rev;
|
||||
u8 vibra_ctrl_cache[2];
|
||||
|
||||
int pll;
|
||||
unsigned int sysclk;
|
||||
@ -221,10 +210,13 @@ int twl6040_get_pll(struct twl6040 *twl6040);
|
||||
unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
|
||||
int twl6040_irq_init(struct twl6040 *twl6040);
|
||||
void twl6040_irq_exit(struct twl6040 *twl6040);
|
||||
/* Get the combined status of the vibra control register */
|
||||
int twl6040_get_vibralr_status(struct twl6040 *twl6040);
|
||||
|
||||
static inline int twl6040_get_revid(struct twl6040 *twl6040)
|
||||
{
|
||||
return twl6040->rev;
|
||||
}
|
||||
|
||||
|
||||
#endif /* End of __TWL6040_CODEC_H__ */
|
||||
|
@ -20,6 +20,7 @@
|
||||
enum wm8994_type {
|
||||
WM8994 = 0,
|
||||
WM8958 = 1,
|
||||
WM1811 = 2,
|
||||
};
|
||||
|
||||
struct regulator_dev;
|
||||
|
@ -2069,6 +2069,10 @@
|
||||
/*
|
||||
* R96 (0x60) - Analogue HP (1)
|
||||
*/
|
||||
#define WM1811_HPOUT1_ATTN 0x0100 /* HPOUT1_ATTN */
|
||||
#define WM1811_HPOUT1_ATTN_MASK 0x0100 /* HPOUT1_ATTN */
|
||||
#define WM1811_HPOUT1_ATTN_SHIFT 8 /* HPOUT1_ATTN */
|
||||
#define WM1811_HPOUT1_ATTN_WIDTH 1 /* HPOUT1_ATTN */
|
||||
#define WM8994_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */
|
||||
#define WM8994_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */
|
||||
#define WM8994_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */
|
||||
|
@ -24,13 +24,13 @@ struct snd_pcm_substream;
|
||||
* Describes the physical PCM data formating and clocking. Add new formats
|
||||
* to the end.
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
|
||||
#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */
|
||||
#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
|
||||
#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */
|
||||
#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */
|
||||
#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
|
||||
#define SND_SOC_DAIFMT_PDM 6 /* Pulse density modulation */
|
||||
#define SND_SOC_DAIFMT_I2S 1 /* I2S mode */
|
||||
#define SND_SOC_DAIFMT_RIGHT_J 2 /* Right Justified mode */
|
||||
#define SND_SOC_DAIFMT_LEFT_J 3 /* Left Justified mode */
|
||||
#define SND_SOC_DAIFMT_DSP_A 4 /* L data MSB after FRM LRC */
|
||||
#define SND_SOC_DAIFMT_DSP_B 5 /* L data MSB during FRM LRC */
|
||||
#define SND_SOC_DAIFMT_AC97 6 /* AC97 */
|
||||
#define SND_SOC_DAIFMT_PDM 7 /* Pulse density modulation */
|
||||
|
||||
/* left and right justified also known as MSB and LSB respectively */
|
||||
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
|
||||
@ -42,8 +42,8 @@ struct snd_pcm_substream;
|
||||
* DAI bit clocks can be be gated (disabled) when the DAI is not
|
||||
* sending or receiving PCM data in a frame. This can be used to save power.
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
|
||||
#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
|
||||
#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */
|
||||
#define SND_SOC_DAIFMT_GATED (2 << 4) /* clock is gated */
|
||||
|
||||
/*
|
||||
* DAI hardware signal inversions.
|
||||
@ -51,10 +51,10 @@ struct snd_pcm_substream;
|
||||
* Specifies whether the DAI can also support inverted clocks for the specified
|
||||
* format.
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
|
||||
#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal BCLK + inv FRM */
|
||||
#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert BCLK + nor FRM */
|
||||
#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert BCLK + FRM */
|
||||
#define SND_SOC_DAIFMT_NB_NF (1 << 8) /* normal bit clock + frame */
|
||||
#define SND_SOC_DAIFMT_NB_IF (2 << 8) /* normal BCLK + inv FRM */
|
||||
#define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */
|
||||
#define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */
|
||||
|
||||
/*
|
||||
* DAI hardware clock masters.
|
||||
@ -63,10 +63,10 @@ struct snd_pcm_substream;
|
||||
* i.e. if the codec is clk and FRM master then the interface is
|
||||
* clk and frame slave.
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & FRM master */
|
||||
#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & FRM master */
|
||||
#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
|
||||
#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & FRM slave */
|
||||
#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & FRM master */
|
||||
#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk slave & FRM master */
|
||||
#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame slave */
|
||||
#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM slave */
|
||||
|
||||
#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
|
||||
#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
|
||||
@ -242,6 +242,9 @@ struct snd_soc_dai {
|
||||
void *playback_dma_data;
|
||||
void *capture_dma_data;
|
||||
|
||||
/* Symmetry data - only valid if symmetry is being enforced */
|
||||
unsigned int rate;
|
||||
|
||||
/* parent platform/codec */
|
||||
union {
|
||||
struct snd_soc_platform *platform;
|
||||
|
@ -381,6 +381,9 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
snd_soc_dapm_input = 0, /* input pin */
|
||||
@ -473,6 +476,8 @@ struct snd_soc_dapm_widget {
|
||||
unsigned char ext:1; /* has external widgets */
|
||||
unsigned char force:1; /* force state */
|
||||
unsigned char ignore_suspend:1; /* kept enabled over suspend */
|
||||
unsigned char new_power:1; /* power from this run */
|
||||
unsigned char power_checked:1; /* power checked this run */
|
||||
int subseq; /* sort within widget type */
|
||||
|
||||
int (*power_check)(struct snd_soc_dapm_widget *w);
|
||||
@ -492,6 +497,9 @@ struct snd_soc_dapm_widget {
|
||||
|
||||
/* used during DAPM updates */
|
||||
struct list_head power_list;
|
||||
struct list_head dirty;
|
||||
int inputs;
|
||||
int outputs;
|
||||
};
|
||||
|
||||
struct snd_soc_dapm_update {
|
||||
@ -537,4 +545,10 @@ struct snd_soc_dapm_widget_list {
|
||||
struct snd_soc_dapm_widget *widgets[0];
|
||||
};
|
||||
|
||||
struct snd_soc_dapm_stats {
|
||||
int power_checks;
|
||||
int path_checks;
|
||||
int neighbour_checks;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -28,13 +28,20 @@
|
||||
/*
|
||||
* Convenience kcontrol builders
|
||||
*/
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
|
||||
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
|
||||
.platform_max = xmax, .invert = xinvert})
|
||||
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
||||
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
|
||||
.invert = xinvert})
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
|
||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
|
||||
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
|
||||
#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert})
|
||||
#define SOC_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
@ -48,40 +55,36 @@
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert) }
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert) }
|
||||
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
@ -121,14 +124,13 @@
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
|
||||
#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
|
||||
xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.private_value = \
|
||||
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
|
||||
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
@ -146,20 +148,18 @@
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
|
||||
xmax, xinvert) }
|
||||
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_bool_ext, \
|
||||
@ -393,12 +393,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
#define snd_soc_get_volsw_2r snd_soc_get_volsw
|
||||
#define snd_soc_put_volsw_2r snd_soc_put_volsw
|
||||
int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||
@ -582,6 +578,7 @@ struct snd_soc_codec {
|
||||
|
||||
/* dapm */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
@ -713,6 +710,8 @@ struct snd_soc_dai_link {
|
||||
const char *cpu_dai_name;
|
||||
const char *codec_dai_name;
|
||||
|
||||
unsigned int dai_fmt; /* format to set on init */
|
||||
|
||||
/* Keep DAI active over suspend */
|
||||
unsigned int ignore_suspend:1;
|
||||
|
||||
@ -825,9 +824,11 @@ struct snd_soc_card {
|
||||
struct list_head widgets;
|
||||
struct list_head paths;
|
||||
struct list_head dapm_list;
|
||||
struct list_head dapm_dirty;
|
||||
|
||||
/* Generic DAPM context for the card */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_stats dapm_stats;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_card_root;
|
||||
@ -850,8 +851,6 @@ struct snd_soc_pcm_runtime {
|
||||
unsigned int complete:1;
|
||||
unsigned int dev_registered:1;
|
||||
|
||||
/* Symmetry data - only valid if symmetry is being enforced */
|
||||
unsigned int rate;
|
||||
long pmdown_time;
|
||||
|
||||
/* runtime devices */
|
||||
@ -946,6 +945,18 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
|
||||
INIT_LIST_HEAD(&card->dapm_list);
|
||||
}
|
||||
|
||||
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
|
||||
{
|
||||
if (mc->reg == mc->rreg && mc->shift == mc->rshift)
|
||||
return 0;
|
||||
/*
|
||||
* mc->reg == mc->rreg && mc->shift != mc->rshift, or
|
||||
* mc->reg != mc->rreg means that the control is
|
||||
* stereo (bits in one register or in two registers)
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
int snd_soc_util_init(void);
|
||||
void snd_soc_util_exit(void);
|
||||
|
||||
|
@ -23,13 +23,7 @@
|
||||
#ifndef TPA6130A2_PLAT_H
|
||||
#define TPA6130A2_PLAT_H
|
||||
|
||||
enum tpa_model {
|
||||
TPA6130A2,
|
||||
TPA6140A2,
|
||||
};
|
||||
|
||||
struct tpa6130a2_platform_data {
|
||||
enum tpa_model id;
|
||||
int power_gpio;
|
||||
};
|
||||
|
||||
|
27
include/sound/wm1250-ev1.h
Normal file
27
include/sound/wm1250-ev1.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1
|
||||
*
|
||||
* Copyright 2011 Wolfson Microelectronics. PLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_WM1250_EV1_H
|
||||
#define __LINUX_SND_WM1250_EV1_H
|
||||
|
||||
#define WM1250_EV1_NUM_GPIOS 5
|
||||
|
||||
#define WM1250_EV1_GPIO_CLK_ENA 0
|
||||
#define WM1250_EV1_GPIO_CLK_SEL0 1
|
||||
#define WM1250_EV1_GPIO_CLK_SEL1 2
|
||||
#define WM1250_EV1_GPIO_OSR 3
|
||||
#define WM1250_EV1_GPIO_MASTER 4
|
||||
|
||||
|
||||
struct wm1250_ev1_pdata {
|
||||
int gpios[WM1250_EV1_NUM_GPIOS];
|
||||
};
|
||||
|
||||
#endif
|
59
include/sound/wm5100.h
Normal file
59
include/sound/wm5100.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* linux/sound/wm5100.h -- Platform data for WM5100
|
||||
*
|
||||
* Copyright 2011 Wolfson Microelectronics. PLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_WM5100_H
|
||||
#define __LINUX_SND_WM5100_H
|
||||
|
||||
enum wm5100_in_mode {
|
||||
WM5100_IN_SE = 0,
|
||||
WM5100_IN_DIFF = 1,
|
||||
WM5100_IN_DMIC = 2,
|
||||
};
|
||||
|
||||
enum wm5100_dmic_sup {
|
||||
WM5100_DMIC_SUP_MICVDD = 0,
|
||||
WM5100_DMIC_SUP_MICBIAS1 = 1,
|
||||
WM5100_DMIC_SUP_MICBIAS2 = 2,
|
||||
WM5100_DMIC_SUP_MICBIAS3 = 3,
|
||||
};
|
||||
|
||||
enum wm5100_micdet_bias {
|
||||
WM5100_MICDET_MICBIAS1 = 0,
|
||||
WM5100_MICDET_MICBIAS2 = 1,
|
||||
WM5100_MICDET_MICBIAS3 = 2,
|
||||
};
|
||||
|
||||
struct wm5100_jack_mode {
|
||||
enum wm5100_micdet_bias bias;
|
||||
int hp_pol;
|
||||
int micd_src;
|
||||
};
|
||||
|
||||
#define WM5100_GPIO_SET 0x10000
|
||||
|
||||
struct wm5100_pdata {
|
||||
int reset; /** GPIO controlling /RESET, if any */
|
||||
int ldo_ena; /** GPIO controlling LODENA, if any */
|
||||
int hp_pol; /** GPIO controlling headset polarity, if any */
|
||||
int irq_flags;
|
||||
int gpio_base;
|
||||
|
||||
struct wm5100_jack_mode jack_modes[2];
|
||||
|
||||
/* Input pin mode selection */
|
||||
enum wm5100_in_mode in_mode[4];
|
||||
|
||||
/* DMIC supply selection */
|
||||
enum wm5100_dmic_sup dmic_sup[4];
|
||||
|
||||
int gpio_defaults[6];
|
||||
};
|
||||
|
||||
#endif
|
@ -216,6 +216,31 @@ DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
|
||||
|
||||
);
|
||||
|
||||
TRACE_EVENT(snd_soc_dapm_walk_done,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card),
|
||||
|
||||
TP_ARGS(card),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, card->name )
|
||||
__field( int, power_checks )
|
||||
__field( int, path_checks )
|
||||
__field( int, neighbour_checks )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, card->name);
|
||||
__entry->power_checks = card->dapm_stats.power_checks;
|
||||
__entry->path_checks = card->dapm_stats.path_checks;
|
||||
__entry->neighbour_checks = card->dapm_stats.neighbour_checks;
|
||||
),
|
||||
|
||||
TP_printk("%s: checks %d power, %d path, %d neighbour",
|
||||
__get_str(name), (int)__entry->power_checks,
|
||||
(int)__entry->path_checks, (int)__entry->neighbour_checks)
|
||||
);
|
||||
|
||||
TRACE_EVENT(snd_soc_jack_irq,
|
||||
|
||||
TP_PROTO(const char *name),
|
||||
|
@ -338,7 +338,6 @@ static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
|
||||
/* always connected pins */
|
||||
snd_soc_dapm_enable_pin(dapm, "Int Mic");
|
||||
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
|
||||
|
||||
|
@ -173,8 +173,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||
/* always connected */
|
||||
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
|
||||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
|
||||
snd_soc_dapm_enable_pin(dapm, "Line In");
|
||||
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
|
||||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
|
||||
static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct resource *r;
|
||||
struct resource *iores, *dmares;
|
||||
struct au1xpsc_audio_data *ctx;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
@ -235,29 +235,30 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
|
||||
|
||||
mutex_init(&ctx->lock);
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r) {
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores) {
|
||||
ret = -ENODEV;
|
||||
goto out0;
|
||||
}
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!request_mem_region(r->start, resource_size(r), pdev->name))
|
||||
if (!request_mem_region(iores->start, resource_size(iores),
|
||||
pdev->name))
|
||||
goto out0;
|
||||
|
||||
ctx->mmio = ioremap_nocache(r->start, resource_size(r));
|
||||
ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
|
||||
if (!ctx->mmio)
|
||||
goto out1;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!r)
|
||||
goto out1;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!r)
|
||||
goto out1;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
|
||||
|
||||
/* switch it on */
|
||||
WR(ctx, AC97_ENABLE, EN_D | EN_CE);
|
||||
@ -270,13 +271,15 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
|
||||
|
||||
ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
|
||||
if (ret)
|
||||
goto out1;
|
||||
goto out2;
|
||||
|
||||
ac97c_workdata = ctx;
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
iounmap(ctx->mmio);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
release_mem_region(iores->start, resource_size(iores));
|
||||
out0:
|
||||
kfree(ctx);
|
||||
return ret;
|
||||
|
@ -228,47 +228,50 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
|
||||
static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct resource *r;
|
||||
struct resource *iores, *dmares;
|
||||
struct au1xpsc_audio_data *ctx;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r) {
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores) {
|
||||
ret = -ENODEV;
|
||||
goto out0;
|
||||
}
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!request_mem_region(r->start, resource_size(r), pdev->name))
|
||||
if (!request_mem_region(iores->start, resource_size(iores),
|
||||
pdev->name))
|
||||
goto out0;
|
||||
|
||||
ctx->mmio = ioremap_nocache(r->start, resource_size(r));
|
||||
ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
|
||||
if (!ctx->mmio)
|
||||
goto out1;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!r)
|
||||
goto out1;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!r)
|
||||
goto out1;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
ret = snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
|
||||
if (ret)
|
||||
goto out1;
|
||||
goto out2;
|
||||
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
iounmap(ctx->mmio);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
release_mem_region(iores->start, resource_size(iores));
|
||||
out0:
|
||||
kfree(ctx);
|
||||
return ret;
|
||||
|
@ -364,7 +364,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
|
||||
static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct resource *r;
|
||||
struct resource *iores, *dmares;
|
||||
unsigned long sel;
|
||||
struct au1xpsc_audio_data *wd;
|
||||
|
||||
@ -374,29 +374,30 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||
|
||||
mutex_init(&wd->lock);
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r) {
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores) {
|
||||
ret = -ENODEV;
|
||||
goto out0;
|
||||
}
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!request_mem_region(r->start, resource_size(r), pdev->name))
|
||||
if (!request_mem_region(iores->start, resource_size(iores),
|
||||
pdev->name))
|
||||
goto out0;
|
||||
|
||||
wd->mmio = ioremap(r->start, resource_size(r));
|
||||
wd->mmio = ioremap(iores->start, resource_size(iores));
|
||||
if (!wd->mmio)
|
||||
goto out1;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!r)
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!r)
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
|
||||
|
||||
/* configuration: max dma trigger threshold, enable ac97 */
|
||||
wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
|
||||
@ -428,7 +429,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||
out2:
|
||||
iounmap(wd->mmio);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
release_mem_region(iores->start, resource_size(iores));
|
||||
out0:
|
||||
kfree(wd);
|
||||
return ret;
|
||||
|
@ -290,7 +290,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
|
||||
|
||||
static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *r;
|
||||
struct resource *iores, *dmares;
|
||||
unsigned long sel;
|
||||
int ret;
|
||||
struct au1xpsc_audio_data *wd;
|
||||
@ -299,29 +299,30 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
if (!wd)
|
||||
return -ENOMEM;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r) {
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores) {
|
||||
ret = -ENODEV;
|
||||
goto out0;
|
||||
}
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!request_mem_region(r->start, resource_size(r), pdev->name))
|
||||
if (!request_mem_region(iores->start, resource_size(iores),
|
||||
pdev->name))
|
||||
goto out0;
|
||||
|
||||
wd->mmio = ioremap(r->start, resource_size(r));
|
||||
wd->mmio = ioremap(iores->start, resource_size(iores));
|
||||
if (!wd->mmio)
|
||||
goto out1;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!r)
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!r)
|
||||
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (!dmares)
|
||||
goto out2;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
|
||||
wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
|
||||
|
||||
/* preserve PSC clock source set up by platform (dev.platform_data
|
||||
* is already occupied by soc layer)
|
||||
@ -355,7 +356,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
out2:
|
||||
iounmap(wd->mmio);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
release_mem_region(iores->start, resource_size(iores));
|
||||
out0:
|
||||
kfree(wd);
|
||||
return ret;
|
||||
|
@ -418,7 +418,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
|
||||
|
||||
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
|
||||
static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_card *card = rtd->card->snd_card;
|
||||
struct snd_soc_dai *dai = rtd->cpu_dai;
|
||||
|
@ -257,7 +257,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
|
||||
|
||||
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
|
||||
static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_card *card = rtd->card->snd_card;
|
||||
struct snd_soc_dai *dai = rtd->cpu_dai;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/88pm860x.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
|
||||
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
|
||||
PM860X_DAC_EN_2, 0, 0),
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
|
||||
PM860X_DAC_EN_2, 0, 0),
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
|
||||
PM860X_I2S_IFACE_3, 5, 1),
|
||||
SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
|
||||
SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
|
||||
SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
|
||||
@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
||||
{"Left ADC", NULL, "Left ADC MOD"},
|
||||
{"Right ADC", NULL, "Right ADC MOD"},
|
||||
|
||||
/* I2S Clock */
|
||||
{"I2S DIN", NULL, "I2S CLK"},
|
||||
{"I2S DIN1", NULL, "I2S CLK"},
|
||||
{"I2S DOUT", NULL, "I2S CLK"},
|
||||
|
||||
/* PCM/AIF1 Inputs */
|
||||
{"PCM SDO", NULL, "ADC Left Mux"},
|
||||
{"PCM SDO", NULL, "ADCR EC Mux"},
|
||||
@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
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);
|
||||
udelay(300);
|
||||
data = AUDIO_PLL | AUDIO_SECTION_RESET
|
||||
| AUDIO_SECTION_ON;
|
||||
pm860x_reg_write(codec->control_data, REG_MISC2, data);
|
||||
|
@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_MAX9850 if I2C
|
||||
select SND_SOC_MAX9877 if I2C
|
||||
select SND_SOC_PCM3008
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_SGTL5000 if I2C
|
||||
select SND_SOC_SN95031 if INTEL_SCU_IPC
|
||||
select SND_SOC_SPDIF
|
||||
@ -48,7 +49,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TLV320AIC23 if I2C
|
||||
select SND_SOC_TLV320AIC26 if SPI_MASTER
|
||||
select SND_SOC_TVL320AIC32X4 if I2C
|
||||
select SND_SOC_TLV320AIC32X4 if I2C
|
||||
select SND_SOC_TLV320AIC3X if I2C
|
||||
select SND_SOC_TPA6130A2 if I2C
|
||||
select SND_SOC_TLV320DAC33 if I2C
|
||||
@ -59,6 +60,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_WL1273 if MFD_WL1273_CORE
|
||||
select SND_SOC_WM1250_EV1 if I2C
|
||||
select SND_SOC_WM2000 if I2C
|
||||
select SND_SOC_WM5100 if I2C
|
||||
select SND_SOC_WM8350 if MFD_WM8350
|
||||
select SND_SOC_WM8400 if MFD_WM8400
|
||||
select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
|
||||
@ -218,6 +220,9 @@ config SND_SOC_MAX9850
|
||||
config SND_SOC_PCM3008
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
|
||||
#Freescale sgtl5000 codec
|
||||
config SND_SOC_SGTL5000
|
||||
tristate
|
||||
@ -244,7 +249,7 @@ config SND_SOC_TLV320AIC26
|
||||
tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
|
||||
depends on SPI
|
||||
|
||||
config SND_SOC_TVL320AIC32X4
|
||||
config SND_SOC_TLV320AIC32X4
|
||||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC3X
|
||||
@ -273,6 +278,9 @@ config SND_SOC_WL1273
|
||||
config SND_SOC_WM1250_EV1
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM5100
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8350
|
||||
tristate
|
||||
|
||||
|
@ -26,6 +26,7 @@ snd-soc-max98088-objs := max98088.o
|
||||
snd-soc-max98095-objs := max98095.o
|
||||
snd-soc-max9850-objs := max9850.o
|
||||
snd-soc-pcm3008-objs := pcm3008.o
|
||||
snd-soc-rt5631-objs := rt5631.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
snd-soc-sn95031-objs := sn95031.o
|
||||
@ -44,6 +45,7 @@ snd-soc-uda134x-objs := uda134x.o
|
||||
snd-soc-uda1380-objs := uda1380.o
|
||||
snd-soc-wl1273-objs := wl1273.o
|
||||
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
|
||||
snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
|
||||
snd-soc-wm8350-objs := wm8350.o
|
||||
snd-soc-wm8400-objs := wm8400.o
|
||||
snd-soc-wm8510-objs := wm8510.o
|
||||
@ -125,6 +127,7 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
|
||||
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
|
||||
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
|
||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
|
||||
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
|
||||
@ -134,7 +137,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||
obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
|
||||
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
|
||||
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
|
||||
@ -142,6 +145,7 @@ obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
|
||||
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
|
||||
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
|
||||
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
|
||||
obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o
|
||||
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
|
||||
obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
|
||||
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
|
||||
|
@ -103,12 +103,14 @@ static const struct snd_soc_dapm_route audio_paths[] = {
|
||||
static int ad193x_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
int reg;
|
||||
|
||||
reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
|
||||
reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
|
||||
(~AD193X_DAC_MASTER_MUTE);
|
||||
snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
|
||||
if (mute)
|
||||
snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
|
||||
AD193X_DAC_MASTER_MUTE,
|
||||
AD193X_DAC_MASTER_MUTE);
|
||||
else
|
||||
snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
|
||||
AD193X_DAC_MASTER_MUTE, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -262,7 +264,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int word_len = 0, reg = 0, master_rate = 0;
|
||||
int word_len = 0, master_rate = 0;
|
||||
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
@ -297,18 +299,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
|
||||
reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
|
||||
reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
|
||||
snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
|
||||
snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0,
|
||||
AD193X_PLL_INPUT_MASK, master_rate);
|
||||
|
||||
reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
|
||||
reg = (reg & (~AD193X_DAC_WORD_LEN_MASK))
|
||||
| (word_len << AD193X_DAC_WORD_LEN_SHFT);
|
||||
snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
|
||||
snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
|
||||
AD193X_DAC_WORD_LEN_MASK,
|
||||
word_len << AD193X_DAC_WORD_LEN_SHFT);
|
||||
|
||||
reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
|
||||
reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
|
||||
snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
|
||||
snd_soc_update_bits(codec, AD193X_ADC_CTRL1,
|
||||
AD193X_ADC_WORD_LEN_MASK, word_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#define AD193X_PLL_CLK_CTRL0 0x00
|
||||
#define AD193X_PLL_POWERDOWN 0x01
|
||||
#define AD193X_PLL_INPUT_MASK (~0x6)
|
||||
#define AD193X_PLL_INPUT_MASK 0x6
|
||||
#define AD193X_PLL_INPUT_256 (0 << 1)
|
||||
#define AD193X_PLL_INPUT_384 (1 << 1)
|
||||
#define AD193X_PLL_INPUT_512 (2 << 1)
|
||||
|
@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = {
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
.formats = SND_SOC_STD_AC97_FMTS, },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ad1980_dai);
|
||||
|
||||
static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
|
@ -974,7 +974,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
ctrl = 0;
|
||||
adau1373_dai->master = true;
|
||||
adau1373_dai->master = false;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
}
|
||||
|
||||
static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
int source, unsigned int freq, int dir)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
@ -458,6 +458,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
codec->control_data = to_i2c_client(codec->dev);
|
||||
|
||||
ret = adau1701_load_firmware(codec);
|
||||
if (ret)
|
||||
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* ads117x.h -- Driver for ads1174/8 ADC chips
|
||||
*
|
||||
* Copyright 2009 ShotSpotter Inc.
|
||||
* Author: Graeme Gregory <gg@slimlogic.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
extern struct snd_soc_dai_driver ads117x_dai;
|
||||
extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
|
@ -247,7 +247,7 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
|
||||
.probe = ak4104_probe,
|
||||
.remove = ak4104_remove,
|
||||
.reg_cache_size = AK4104_NUM_REGS,
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_word_size = sizeof(u8),
|
||||
};
|
||||
|
||||
static int ak4104_spi_probe(struct spi_device *spi)
|
||||
|
@ -34,74 +34,16 @@
|
||||
struct ak4535_priv {
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* ak4535 register cache
|
||||
*/
|
||||
static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
|
||||
0x0000, 0x0080, 0x0000, 0x0003,
|
||||
0x0002, 0x0000, 0x0011, 0x0001,
|
||||
0x0000, 0x0040, 0x0036, 0x0010,
|
||||
0x0000, 0x0000, 0x0057, 0x0000,
|
||||
};
|
||||
|
||||
/*
|
||||
* read ak4535 register cache
|
||||
*/
|
||||
static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= AK4535_CACHEREGNUM)
|
||||
return -1;
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* write ak4535 register cache
|
||||
*/
|
||||
static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
|
||||
u16 reg, unsigned int value)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= AK4535_CACHEREGNUM)
|
||||
return;
|
||||
cache[reg] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* write to the AK4535 register space
|
||||
*/
|
||||
static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 data[2];
|
||||
|
||||
/* data is
|
||||
* D15..D8 AK4535 register offset
|
||||
* D7...D0 register data
|
||||
*/
|
||||
data[0] = reg & 0xff;
|
||||
data[1] = value & 0xff;
|
||||
|
||||
ak4535_write_reg_cache(codec, reg, value);
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int ak4535_sync(struct snd_soc_codec *codec)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < AK4535_CACHEREGNUM; i++)
|
||||
r |= ak4535_write(codec, i, cache[i]);
|
||||
|
||||
return r;
|
||||
static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
|
||||
0x00, 0x80, 0x00, 0x03,
|
||||
0x02, 0x00, 0x11, 0x01,
|
||||
0x00, 0x40, 0x36, 0x10,
|
||||
0x00, 0x00, 0x57, 0x00,
|
||||
};
|
||||
|
||||
static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
|
||||
@ -304,7 +246,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
|
||||
u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5);
|
||||
int rate = params_rate(params), fs = 256;
|
||||
|
||||
if (rate)
|
||||
@ -323,7 +265,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
/* set rate */
|
||||
ak4535_write(codec, AK4535_MODE2, mode2);
|
||||
snd_soc_write(codec, AK4535_MODE2, mode2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -348,44 +290,37 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
/* use 32 fs for BCLK to save power */
|
||||
mode1 |= 0x4;
|
||||
|
||||
ak4535_write(codec, AK4535_MODE1, mode1);
|
||||
snd_soc_write(codec, AK4535_MODE1, mode1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak4535_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
u16 mute_reg = snd_soc_read(codec, AK4535_DAC);
|
||||
if (!mute)
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
|
||||
snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20);
|
||||
else
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak4535_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 i, mute_reg;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
|
||||
snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
i = ak4535_read_reg_cache(codec, AK4535_PM1);
|
||||
ak4535_write(codec, AK4535_PM1, i | 0x80);
|
||||
i = ak4535_read_reg_cache(codec, AK4535_PM2);
|
||||
ak4535_write(codec, AK4535_PM2, i & (~0x80));
|
||||
snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80);
|
||||
snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
i = ak4535_read_reg_cache(codec, AK4535_PM1);
|
||||
ak4535_write(codec, AK4535_PM1, i & (~0x80));
|
||||
snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
@ -428,7 +363,7 @@ static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int ak4535_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
ak4535_sync(codec);
|
||||
snd_soc_cache_sync(codec);
|
||||
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
@ -436,11 +371,15 @@ static int ak4535_resume(struct snd_soc_codec *codec)
|
||||
static int ak4535_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
|
||||
|
||||
codec->control_data = ak4535->control_data;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/* power on device */
|
||||
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
@ -461,8 +400,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
|
||||
.remove = ak4535_remove,
|
||||
.suspend = ak4535_suspend,
|
||||
.resume = ak4535_resume,
|
||||
.read = ak4535_read_reg_cache,
|
||||
.write = ak4535_write,
|
||||
.set_bias_level = ak4535_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(ak4535_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
@ -485,7 +422,6 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, ak4535);
|
||||
ak4535->control_data = i2c;
|
||||
ak4535->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
/* codec private data */
|
||||
struct ak4641_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
unsigned int sysclk;
|
||||
int deemph;
|
||||
int playback_fs;
|
||||
@ -226,7 +225,7 @@ static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0),
|
||||
SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
|
||||
SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
|
||||
|
||||
SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0),
|
||||
SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0),
|
||||
|
@ -156,81 +156,22 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
|
||||
struct ak4642_priv {
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* ak4642 register cache
|
||||
*/
|
||||
static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
|
||||
0x0000, 0x0000, 0x0001, 0x0000,
|
||||
0x0002, 0x0000, 0x0000, 0x0000,
|
||||
0x00e1, 0x00e1, 0x0018, 0x0000,
|
||||
0x00e1, 0x0018, 0x0011, 0x0008,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000,
|
||||
};
|
||||
|
||||
/*
|
||||
* read ak4642 register cache
|
||||
*/
|
||||
static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= AK4642_CACHEREGNUM)
|
||||
return -1;
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* write ak4642 register cache
|
||||
*/
|
||||
static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
|
||||
u16 reg, unsigned int value)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= AK4642_CACHEREGNUM)
|
||||
return;
|
||||
|
||||
cache[reg] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* write to the AK4642 register space
|
||||
*/
|
||||
static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 data[2];
|
||||
|
||||
/* data is
|
||||
* D15..D8 AK4642 register offset
|
||||
* D7...D0 register data
|
||||
*/
|
||||
data[0] = reg & 0xff;
|
||||
data[1] = value & 0xff;
|
||||
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2) {
|
||||
ak4642_write_reg_cache(codec, reg, value);
|
||||
return 0;
|
||||
} else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int ak4642_sync(struct snd_soc_codec *codec)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < AK4642_CACHEREGNUM; i++)
|
||||
r |= ak4642_write(codec, i, cache[i]);
|
||||
|
||||
return r;
|
||||
static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
|
||||
0x00, 0x00, 0x01, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0xe1, 0xe1, 0x18, 0x00,
|
||||
0xe1, 0x18, 0x11, 0x08,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static int ak4642_dai_startup(struct snd_pcm_substream *substream,
|
||||
@ -252,8 +193,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
|
||||
*/
|
||||
snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
|
||||
snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
|
||||
ak4642_write(codec, L_IVC, 0x91); /* volume */
|
||||
ak4642_write(codec, R_IVC, 0x91); /* volume */
|
||||
snd_soc_write(codec, L_IVC, 0x91); /* volume */
|
||||
snd_soc_write(codec, R_IVC, 0x91); /* volume */
|
||||
snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
|
||||
PMVCM | PMMIN | PMDAC);
|
||||
snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
|
||||
@ -272,9 +213,9 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
|
||||
* This operation came from example code of
|
||||
* "ASAHI KASEI AK4642" (japanese) manual p94.
|
||||
*/
|
||||
ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
|
||||
ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
|
||||
ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
|
||||
snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
|
||||
snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
|
||||
snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
|
||||
snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
|
||||
PMVCM | PMADL);
|
||||
snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
|
||||
@ -462,7 +403,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
|
||||
|
||||
static int ak4642_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
ak4642_sync(codec);
|
||||
snd_soc_cache_sync(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -470,11 +411,15 @@ static int ak4642_resume(struct snd_soc_codec *codec)
|
||||
static int ak4642_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
|
||||
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
codec->control_data = ak4642->control_data;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, ak4642_snd_controls,
|
||||
ARRAY_SIZE(ak4642_snd_controls));
|
||||
@ -485,8 +430,6 @@ static int ak4642_probe(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
|
||||
.probe = ak4642_probe,
|
||||
.resume = ak4642_resume,
|
||||
.read = ak4642_read_reg_cache,
|
||||
.write = ak4642_write,
|
||||
.reg_cache_size = ARRAY_SIZE(ak4642_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = ak4642_reg,
|
||||
@ -504,7 +447,6 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, ak4642);
|
||||
ak4642->control_data = i2c;
|
||||
ak4642->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -26,7 +26,6 @@
|
||||
/* codec private data */
|
||||
struct ak4671_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
/* ak4671 register cache & default register settings */
|
||||
@ -169,18 +168,15 @@ static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
u8 reg;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
|
||||
reg |= AK4671_MUTEN;
|
||||
snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
|
||||
snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
|
||||
AK4671_MUTEN, AK4671_MUTEN);
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
|
||||
reg &= ~AK4671_MUTEN;
|
||||
snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
|
||||
snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
|
||||
AK4671_MUTEN, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -576,15 +572,12 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
static int ak4671_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
|
||||
snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
|
||||
reg | AK4671_PMVCM);
|
||||
snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT,
|
||||
AK4671_PMVCM, AK4671_PMVCM);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
|
||||
@ -629,8 +622,6 @@ static int ak4671_probe(struct snd_soc_codec *codec)
|
||||
struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
@ -675,7 +666,6 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, ak4671);
|
||||
ak4671->control_data = client;
|
||||
ak4671->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
|
@ -40,7 +40,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
|
||||
/* codec private data */
|
||||
struct alc5623_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 id;
|
||||
unsigned int sysclk;
|
||||
u16 reg_cache[ALC5623_VENDOR_ID2+2];
|
||||
@ -54,8 +53,10 @@ static void alc5623_fill_cache(struct snd_soc_codec *codec)
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* not really efficient ... */
|
||||
codec->cache_bypass = 1;
|
||||
for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
|
||||
cache[i] = codec->hw_read(codec, i);
|
||||
cache[i] = snd_soc_read(codec, i);
|
||||
codec->cache_bypass = 0;
|
||||
}
|
||||
|
||||
static inline int alc5623_reset(struct snd_soc_codec *codec)
|
||||
@ -1049,7 +1050,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, alc5623);
|
||||
alc5623->control_data = client;
|
||||
alc5623->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
|
@ -128,7 +128,6 @@ static const char *supply_names[] = {
|
||||
/* Private data for the CS4270 */
|
||||
struct cs4270_private {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
unsigned int mclk; /* Input frequency of the MCLK pin */
|
||||
unsigned int mode; /* The mode (I2S or left-justified) */
|
||||
unsigned int slave_mode;
|
||||
@ -262,7 +261,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
/* set DAI format */
|
||||
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
@ -272,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "invalid dai format\n");
|
||||
ret = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set master/slave audio interface */
|
||||
@ -285,10 +283,11 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
break;
|
||||
default:
|
||||
/* all other modes are unsupported by the hardware */
|
||||
ret = -EINVAL;
|
||||
dev_err(codec->dev, "Unknown master/slave configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -490,8 +489,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
|
||||
codec->control_data = cs4270->control_data;
|
||||
|
||||
/* Tell ASoC what kind of I/O to use to read the registers. ASoC will
|
||||
* then do the I2C transactions itself.
|
||||
*/
|
||||
@ -604,7 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
|
||||
static int cs4270_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
struct i2c_client *i2c_client = codec->control_data;
|
||||
struct i2c_client *i2c_client = to_i2c_client(codec->dev);
|
||||
int reg;
|
||||
|
||||
regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
|
||||
@ -690,7 +687,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs4270);
|
||||
cs4270->control_data = i2c_client;
|
||||
cs4270->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
|
@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
|
||||
struct cs4271_private {
|
||||
/* SND_SOC_I2C or SND_SOC_SPI */
|
||||
enum snd_soc_control_type bus_type;
|
||||
void *control_data;
|
||||
unsigned int mclk;
|
||||
bool master;
|
||||
bool deemph;
|
||||
@ -466,8 +465,6 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
int gpio_nreset = -EINVAL;
|
||||
|
||||
codec->control_data = cs4271->control_data;
|
||||
|
||||
if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
|
||||
gpio_nreset = cs4271plat->gpio_nreset;
|
||||
|
||||
@ -555,7 +552,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, cs4271);
|
||||
cs4271->control_data = spi;
|
||||
cs4271->bus_type = SND_SOC_SPI;
|
||||
|
||||
return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
|
||||
@ -595,7 +591,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, cs4271);
|
||||
cs4271->control_data = client;
|
||||
cs4271->bus_type = SND_SOC_I2C;
|
||||
|
||||
return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
|
||||
|
@ -42,7 +42,6 @@ enum master_slave_mode {
|
||||
|
||||
struct cs42l51_private {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
unsigned int mclk;
|
||||
unsigned int audio_mode; /* The mode (I2S or left-justified) */
|
||||
enum master_slave_mode func;
|
||||
@ -57,7 +56,7 @@ struct cs42l51_private {
|
||||
static int cs42l51_fill_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 *cache = codec->reg_cache + 1;
|
||||
struct i2c_client *i2c_client = codec->control_data;
|
||||
struct i2c_client *i2c_client = to_i2c_client(codec->dev);
|
||||
s32 length;
|
||||
|
||||
length = i2c_smbus_read_i2c_block_data(i2c_client,
|
||||
@ -289,7 +288,6 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
@ -299,7 +297,7 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "invalid DAI format\n");
|
||||
ret = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
@ -310,11 +308,11 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
cs42l51->func = MODE_SLAVE_AUTO;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
dev_err(codec->dev, "Unknown master/slave configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cs42l51_ratios {
|
||||
@ -520,8 +518,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret, reg;
|
||||
|
||||
codec->control_data = cs42l51->control_data;
|
||||
|
||||
ret = cs42l51_fill_cache(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to fill register cache\n");
|
||||
@ -593,7 +589,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs42l51);
|
||||
cs42l51->control_data = i2c_client;
|
||||
cs42l51->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
|
@ -26,23 +26,41 @@
|
||||
#include <sound/tlv.h>
|
||||
|
||||
/* DA7210 register space */
|
||||
#define DA7210_CONTROL 0x01
|
||||
#define DA7210_STATUS 0x02
|
||||
#define DA7210_STARTUP1 0x03
|
||||
#define DA7210_STARTUP2 0x04
|
||||
#define DA7210_STARTUP3 0x05
|
||||
#define DA7210_MIC_L 0x07
|
||||
#define DA7210_MIC_R 0x08
|
||||
#define DA7210_AUX1_L 0x09
|
||||
#define DA7210_AUX1_R 0x0A
|
||||
#define DA7210_AUX2 0x0B
|
||||
#define DA7210_IN_GAIN 0x0C
|
||||
#define DA7210_INMIX_L 0x0D
|
||||
#define DA7210_INMIX_R 0x0E
|
||||
#define DA7210_ADC_HPF 0x0F
|
||||
#define DA7210_ADC 0x10
|
||||
#define DA7210_ADC_EQ1_2 0X11
|
||||
#define DA7210_ADC_EQ3_4 0x12
|
||||
#define DA7210_ADC_EQ5 0x13
|
||||
#define DA7210_DAC_HPF 0x14
|
||||
#define DA7210_DAC_L 0x15
|
||||
#define DA7210_DAC_R 0x16
|
||||
#define DA7210_DAC_SEL 0x17
|
||||
#define DA7210_SOFTMUTE 0x18
|
||||
#define DA7210_DAC_EQ1_2 0x19
|
||||
#define DA7210_DAC_EQ3_4 0x1A
|
||||
#define DA7210_DAC_EQ5 0x1B
|
||||
#define DA7210_OUTMIX_L 0x1C
|
||||
#define DA7210_OUTMIX_R 0x1D
|
||||
#define DA7210_OUT1_L 0x1E
|
||||
#define DA7210_OUT1_R 0x1F
|
||||
#define DA7210_OUT2 0x20
|
||||
#define DA7210_HP_L_VOL 0x21
|
||||
#define DA7210_HP_R_VOL 0x22
|
||||
#define DA7210_HP_CFG 0x23
|
||||
#define DA7210_ZERO_CROSS 0x24
|
||||
#define DA7210_DAI_SRC_SEL 0x25
|
||||
#define DA7210_DAI_CFG1 0x26
|
||||
#define DA7210_DAI_CFG3 0x28
|
||||
@ -50,6 +68,12 @@
|
||||
#define DA7210_PLL_DIV2 0x2A
|
||||
#define DA7210_PLL_DIV3 0x2B
|
||||
#define DA7210_PLL 0x2C
|
||||
#define DA7210_ALC_MAX 0x83
|
||||
#define DA7210_ALC_MIN 0x84
|
||||
#define DA7210_ALC_NOIS 0x85
|
||||
#define DA7210_ALC_ATT 0x86
|
||||
#define DA7210_ALC_REL 0x87
|
||||
#define DA7210_ALC_DEL 0x88
|
||||
#define DA7210_A_HID_UNLOCK 0x8A
|
||||
#define DA7210_A_TEST_UNLOCK 0x8B
|
||||
#define DA7210_A_PLL1 0x90
|
||||
@ -72,6 +96,7 @@
|
||||
#define DA7210_IN_R_EN (1 << 7)
|
||||
|
||||
/* ADC bit fields */
|
||||
#define DA7210_ADC_ALC_EN (1 << 0)
|
||||
#define DA7210_ADC_L_EN (1 << 3)
|
||||
#define DA7210_ADC_R_EN (1 << 7)
|
||||
|
||||
@ -105,12 +130,17 @@
|
||||
|
||||
/* DAI_CFG1 bit fields */
|
||||
#define DA7210_DAI_WORD_S16_LE (0 << 0)
|
||||
#define DA7210_DAI_WORD_S20_3LE (1 << 0)
|
||||
#define DA7210_DAI_WORD_S24_LE (2 << 0)
|
||||
#define DA7210_DAI_WORD_S32_LE (3 << 0)
|
||||
#define DA7210_DAI_FLEN_64BIT (1 << 2)
|
||||
#define DA7210_DAI_MODE_SLAVE (0 << 7)
|
||||
#define DA7210_DAI_MODE_MASTER (1 << 7)
|
||||
|
||||
/* DAI_CFG3 bit fields */
|
||||
#define DA7210_DAI_FORMAT_I2SMODE (0 << 0)
|
||||
#define DA7210_DAI_FORMAT_LEFT_J (1 << 0)
|
||||
#define DA7210_DAI_FORMAT_RIGHT_J (2 << 0)
|
||||
#define DA7210_DAI_OE (1 << 3)
|
||||
#define DA7210_DAI_EN (1 << 7)
|
||||
|
||||
@ -133,6 +163,43 @@
|
||||
#define DA7210_PLL_FS_96000 (0xF << 0)
|
||||
#define DA7210_PLL_EN (0x1 << 7)
|
||||
|
||||
/* SOFTMUTE bit fields */
|
||||
#define DA7210_RAMP_EN (1 << 6)
|
||||
|
||||
/* CONTROL bit fields */
|
||||
#define DA7210_NOISE_SUP_EN (1 << 3)
|
||||
|
||||
/* IN_GAIN bit fields */
|
||||
#define DA7210_INPGA_L_VOL (0x0F << 0)
|
||||
#define DA7210_INPGA_R_VOL (0xF0 << 0)
|
||||
|
||||
/* ZERO_CROSS bit fields */
|
||||
#define DA7210_AUX1_L_ZC (1 << 0)
|
||||
#define DA7210_AUX1_R_ZC (1 << 1)
|
||||
#define DA7210_HP_L_ZC (1 << 6)
|
||||
#define DA7210_HP_R_ZC (1 << 7)
|
||||
|
||||
/* AUX1_L bit fields */
|
||||
#define DA7210_AUX1_L_VOL (0x3F << 0)
|
||||
|
||||
/* AUX1_R bit fields */
|
||||
#define DA7210_AUX1_R_VOL (0x3F << 0)
|
||||
|
||||
/* Minimum INPGA and AUX1 volume to enable noise suppression */
|
||||
#define DA7210_INPGA_MIN_VOL_NS 0x0A /* 10.5dB */
|
||||
#define DA7210_AUX1_MIN_VOL_NS 0x35 /* 6dB */
|
||||
|
||||
/* OUT1_L bit fields */
|
||||
#define DA7210_OUT1_L_EN (1 << 7)
|
||||
|
||||
/* OUT1_R bit fields */
|
||||
#define DA7210_OUT1_R_EN (1 << 7)
|
||||
|
||||
/* OUT2 bit fields */
|
||||
#define DA7210_OUT2_OUTMIX_R (1 << 5)
|
||||
#define DA7210_OUT2_OUTMIX_L (1 << 6)
|
||||
#define DA7210_OUT2_EN (1 << 7)
|
||||
|
||||
#define DA7210_VERSION "0.0.1"
|
||||
|
||||
/*
|
||||
@ -144,24 +211,351 @@
|
||||
* mute : 0x10
|
||||
* reserved : 0x00 - 0x0F
|
||||
*
|
||||
* ** FIXME **
|
||||
*
|
||||
* Reserved area are considered as "mute".
|
||||
* -> min = -79.5 dB
|
||||
*/
|
||||
static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
|
||||
static const unsigned int hp_out_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(2),
|
||||
0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
|
||||
/* -54 dB to +15 dB */
|
||||
0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0),
|
||||
};
|
||||
|
||||
static const unsigned int lineout_vol_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(2),
|
||||
0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
|
||||
/* -54dB to 15dB */
|
||||
0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
|
||||
};
|
||||
|
||||
static const unsigned int mono_vol_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(2),
|
||||
0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1),
|
||||
/* -18dB to 6dB */
|
||||
0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0);
|
||||
|
||||
/* ADC and DAC high pass filter f0 value */
|
||||
static const char const *da7210_hpf_cutoff_txt[] = {
|
||||
"Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_dac_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da7210_adc_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
|
||||
|
||||
/* ADC and DAC voice (8kHz) high pass cutoff value */
|
||||
static const char const *da7210_vf_cutoff_txt[] = {
|
||||
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_dac_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da7210_adc_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
|
||||
|
||||
static const char *da7210_hp_mode_txt[] = {
|
||||
"Class H", "Class G"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_hp_mode_sel =
|
||||
SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
|
||||
|
||||
/* ALC can be enabled only if noise suppression is disabled */
|
||||
static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.integer.value[0]) {
|
||||
/* Check if noise suppression is enabled */
|
||||
if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) {
|
||||
dev_dbg(codec->dev,
|
||||
"Disable noise suppression to enable ALC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* If all conditions are met or we are actually disabling ALC */
|
||||
return snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
/* Noise suppression can be enabled only if following conditions are met
|
||||
* ALC disabled
|
||||
* ZC enabled for HP and AUX1 PGA
|
||||
* INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB
|
||||
* AUX1_L_VOL and AUX1_R_VOL >= 6 dB
|
||||
*/
|
||||
static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
u8 val;
|
||||
|
||||
if (ucontrol->value.integer.value[0]) {
|
||||
/* Check if ALC is enabled */
|
||||
if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN)
|
||||
goto err;
|
||||
|
||||
/* Check ZC for HP and AUX1 PGA */
|
||||
if ((snd_soc_read(codec, DA7210_ZERO_CROSS) &
|
||||
(DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC |
|
||||
DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC |
|
||||
DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC))
|
||||
goto err;
|
||||
|
||||
/* Check INPGA_L_VOL and INPGA_R_VOL */
|
||||
val = snd_soc_read(codec, DA7210_IN_GAIN);
|
||||
if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) ||
|
||||
(((val & DA7210_INPGA_R_VOL) >> 4) <
|
||||
DA7210_INPGA_MIN_VOL_NS))
|
||||
goto err;
|
||||
|
||||
/* Check AUX1_L_VOL and AUX1_R_VOL */
|
||||
if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) <
|
||||
DA7210_AUX1_MIN_VOL_NS) ||
|
||||
((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) <
|
||||
DA7210_AUX1_MIN_VOL_NS))
|
||||
goto err;
|
||||
}
|
||||
/* If all conditions are met or we are actually disabling Noise sup */
|
||||
return snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
|
||||
err:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new da7210_snd_controls[] = {
|
||||
|
||||
SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
|
||||
DA7210_HP_L_VOL, DA7210_HP_R_VOL,
|
||||
0, 0x3F, 0, hp_out_tlv),
|
||||
SOC_DOUBLE_R_TLV("Digital Playback Volume",
|
||||
DA7210_DAC_L, DA7210_DAC_R,
|
||||
0, 0x77, 1, dac_gain_tlv),
|
||||
SOC_DOUBLE_R_TLV("Lineout Playback Volume",
|
||||
DA7210_OUT1_L, DA7210_OUT1_R,
|
||||
0, 0x3f, 0, lineout_vol_tlv),
|
||||
SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0,
|
||||
mono_vol_tlv),
|
||||
|
||||
/* DAC Equalizer controls */
|
||||
SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0),
|
||||
SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
|
||||
/* ADC Equalizer controls */
|
||||
SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0),
|
||||
SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3,
|
||||
1, adc_eq_master_gain_tlv),
|
||||
SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1,
|
||||
eq_gain_tlv),
|
||||
|
||||
SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0),
|
||||
SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff),
|
||||
SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0),
|
||||
SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff),
|
||||
|
||||
SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0),
|
||||
SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff),
|
||||
SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0),
|
||||
SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff),
|
||||
|
||||
/* Mute controls */
|
||||
SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0),
|
||||
SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0),
|
||||
SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0),
|
||||
SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0),
|
||||
SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0),
|
||||
|
||||
/* Zero cross controls */
|
||||
SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0),
|
||||
SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0),
|
||||
SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0),
|
||||
SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0),
|
||||
|
||||
SOC_ENUM("Headphone Class", da7210_hp_mode_sel),
|
||||
|
||||
/* ALC controls */
|
||||
SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0,
|
||||
snd_soc_get_volsw, da7210_put_alc_sw),
|
||||
SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0),
|
||||
SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0),
|
||||
SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0),
|
||||
SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0),
|
||||
SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0),
|
||||
SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0),
|
||||
|
||||
SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1,
|
||||
0, snd_soc_get_volsw, da7210_put_noise_sup_sw),
|
||||
};
|
||||
|
||||
/*
|
||||
* DAPM Controls
|
||||
*
|
||||
* Current DAPM implementation covers almost all codec components e.g. IOs,
|
||||
* mixers, PGAs,ADC and DAC.
|
||||
*/
|
||||
/* In Mixer Left */
|
||||
static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = {
|
||||
SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0),
|
||||
};
|
||||
|
||||
/* In Mixer Right */
|
||||
static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = {
|
||||
SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0),
|
||||
};
|
||||
|
||||
/* Out Mixer Left */
|
||||
static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0),
|
||||
};
|
||||
|
||||
/* Out Mixer Right */
|
||||
static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0),
|
||||
};
|
||||
|
||||
/* Mono Mixer */
|
||||
static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = {
|
||||
SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0),
|
||||
};
|
||||
|
||||
/* DAPM widgets */
|
||||
static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = {
|
||||
/* Input Side */
|
||||
/* Input Lines */
|
||||
SND_SOC_DAPM_INPUT("MICL"),
|
||||
SND_SOC_DAPM_INPUT("MICR"),
|
||||
|
||||
/* Input PGAs */
|
||||
SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0),
|
||||
|
||||
/* Input Mixers */
|
||||
SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0,
|
||||
&da7210_dapm_inmixl_controls[0],
|
||||
ARRAY_SIZE(da7210_dapm_inmixl_controls)),
|
||||
|
||||
SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0,
|
||||
&da7210_dapm_inmixr_controls[0],
|
||||
ARRAY_SIZE(da7210_dapm_inmixr_controls)),
|
||||
|
||||
/* ADCs */
|
||||
SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1),
|
||||
SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1),
|
||||
|
||||
/* Output Side */
|
||||
/* DACs */
|
||||
SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1),
|
||||
SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1),
|
||||
|
||||
/* Output Mixers */
|
||||
SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0,
|
||||
&da7210_dapm_outmixl_controls[0],
|
||||
ARRAY_SIZE(da7210_dapm_outmixl_controls)),
|
||||
|
||||
SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0,
|
||||
&da7210_dapm_outmixr_controls[0],
|
||||
ARRAY_SIZE(da7210_dapm_outmixr_controls)),
|
||||
|
||||
SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
|
||||
&da7210_dapm_monomix_controls[0],
|
||||
ARRAY_SIZE(da7210_dapm_monomix_controls)),
|
||||
|
||||
/* Output PGAs */
|
||||
SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0),
|
||||
|
||||
/* Output Lines */
|
||||
SND_SOC_DAPM_OUTPUT("OUT1L"),
|
||||
SND_SOC_DAPM_OUTPUT("OUT1R"),
|
||||
SND_SOC_DAPM_OUTPUT("HPL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPR"),
|
||||
SND_SOC_DAPM_OUTPUT("OUT2"),
|
||||
};
|
||||
|
||||
/* DAPM audio route definition */
|
||||
static const struct snd_soc_dapm_route da7210_audio_map[] = {
|
||||
/* Dest Connecting Widget source */
|
||||
/* Input path */
|
||||
{"Mic Left", NULL, "MICL"},
|
||||
{"Mic Right", NULL, "MICR"},
|
||||
|
||||
{"In Mixer Left", "Mic Left Switch", "Mic Left"},
|
||||
{"In Mixer Left", "Mic Right Switch", "Mic Right"},
|
||||
|
||||
{"In Mixer Right", "Mic Right Switch", "Mic Right"},
|
||||
{"In Mixer Right", "Mic Left Switch", "Mic Left"},
|
||||
|
||||
{"INPGA Left", NULL, "In Mixer Left"},
|
||||
{"ADC Left", NULL, "INPGA Left"},
|
||||
|
||||
{"INPGA Right", NULL, "In Mixer Right"},
|
||||
{"ADC Right", NULL, "INPGA Right"},
|
||||
|
||||
/* Output path */
|
||||
{"Out Mixer Left", "DAC Left Switch", "DAC Left"},
|
||||
{"Out Mixer Right", "DAC Right Switch", "DAC Right"},
|
||||
|
||||
{"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"},
|
||||
{"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"},
|
||||
|
||||
{"OUTPGA Left Enable", NULL, "Out Mixer Left"},
|
||||
{"OUTPGA Right Enable", NULL, "Out Mixer Right"},
|
||||
|
||||
{"Out1 Left", NULL, "OUTPGA Left Enable"},
|
||||
{"OUT1L", NULL, "Out1 Left"},
|
||||
|
||||
{"Out1 Right", NULL, "OUTPGA Right Enable"},
|
||||
{"OUT1R", NULL, "Out1 Right"},
|
||||
|
||||
{"Headphone Left", NULL, "OUTPGA Left Enable"},
|
||||
{"HPL", NULL, "Headphone Left"},
|
||||
|
||||
{"Headphone Right", NULL, "OUTPGA Right Enable"},
|
||||
{"HPR", NULL, "Headphone Right"},
|
||||
|
||||
{"Out2 Mono", NULL, "Mono Mixer"},
|
||||
{"OUT2", NULL, "Out2 Mono"},
|
||||
};
|
||||
|
||||
/* Codec private data */
|
||||
struct da7210_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -188,72 +582,15 @@ static const u8 da7210_reg[] = {
|
||||
0x00, /* R88 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Read da7210 register cache
|
||||
*/
|
||||
static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg)
|
||||
static int da7210_volatile_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u8 *cache = codec->reg_cache;
|
||||
BUG_ON(reg >= ARRAY_SIZE(da7210_reg));
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the da7210 register space
|
||||
*/
|
||||
static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
|
||||
{
|
||||
u8 *cache = codec->reg_cache;
|
||||
u8 data[2];
|
||||
|
||||
BUG_ON(codec->driver->volatile_register);
|
||||
|
||||
data[0] = reg & 0xff;
|
||||
data[1] = value & 0xff;
|
||||
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EIO;
|
||||
|
||||
if (2 != codec->hw_write(codec->control_data, data, 2))
|
||||
return -EIO;
|
||||
|
||||
cache[reg] = value;
|
||||
switch (reg) {
|
||||
case DA7210_STATUS:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the da7210 register space.
|
||||
*/
|
||||
static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg)
|
||||
{
|
||||
if (DA7210_STATUS == reg)
|
||||
return i2c_smbus_read_byte_data(codec->control_data, reg);
|
||||
|
||||
return da7210_read_reg_cache(codec, reg);
|
||||
}
|
||||
|
||||
static int da7210_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
if (is_play) {
|
||||
/* Enable Out */
|
||||
snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
|
||||
snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
|
||||
|
||||
} else {
|
||||
/* Volume 7 */
|
||||
snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7);
|
||||
snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7);
|
||||
|
||||
/* Enable Mic */
|
||||
snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1);
|
||||
snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -266,93 +603,75 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
u32 dai_cfg1;
|
||||
u32 hpf_reg, hpf_mask, hpf_value;
|
||||
u32 fs, bypass;
|
||||
|
||||
/* set DAI source to Left and Right ADC */
|
||||
da7210_write(codec, DA7210_DAI_SRC_SEL,
|
||||
snd_soc_write(codec, DA7210_DAI_SRC_SEL,
|
||||
DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC);
|
||||
|
||||
/* Enable DAI */
|
||||
da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
|
||||
snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
|
||||
|
||||
dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1);
|
||||
dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
dai_cfg1 |= DA7210_DAI_WORD_S16_LE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
dai_cfg1 |= DA7210_DAI_WORD_S20_3LE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
dai_cfg1 |= DA7210_DAI_WORD_S24_LE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
dai_cfg1 |= DA7210_DAI_WORD_S32_LE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
|
||||
|
||||
hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
|
||||
DA7210_DAC_HPF : DA7210_ADC_HPF;
|
||||
snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
|
||||
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
fs = DA7210_PLL_FS_8000;
|
||||
hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
|
||||
hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
case 11025:
|
||||
fs = DA7210_PLL_FS_11025;
|
||||
hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
|
||||
hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
|
||||
bypass = 0;
|
||||
break;
|
||||
case 12000:
|
||||
fs = DA7210_PLL_FS_12000;
|
||||
hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
|
||||
hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
case 16000:
|
||||
fs = DA7210_PLL_FS_16000;
|
||||
hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
|
||||
hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
case 22050:
|
||||
fs = DA7210_PLL_FS_22050;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = 0;
|
||||
break;
|
||||
case 32000:
|
||||
fs = DA7210_PLL_FS_32000;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
case 44100:
|
||||
fs = DA7210_PLL_FS_44100;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = 0;
|
||||
break;
|
||||
case 48000:
|
||||
fs = DA7210_PLL_FS_48000;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
case 88200:
|
||||
fs = DA7210_PLL_FS_88200;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = 0;
|
||||
break;
|
||||
case 96000:
|
||||
fs = DA7210_PLL_FS_96000;
|
||||
hpf_mask = DA7210_VOICE_EN;
|
||||
hpf_value = 0;
|
||||
bypass = DA7210_PLL_BYP;
|
||||
break;
|
||||
default:
|
||||
@ -362,7 +681,6 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
|
||||
/* Disable active mode */
|
||||
snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
|
||||
|
||||
snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
|
||||
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
|
||||
snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
|
||||
|
||||
@ -382,13 +700,16 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
|
||||
u32 dai_cfg1;
|
||||
u32 dai_cfg3;
|
||||
|
||||
dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1);
|
||||
dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3);
|
||||
dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1);
|
||||
dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3);
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
dai_cfg1 |= DA7210_DAI_MODE_MASTER;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
dai_cfg1 |= DA7210_DAI_MODE_SLAVE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -401,6 +722,12 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -411,19 +738,32 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
|
||||
*/
|
||||
dai_cfg1 |= DA7210_DAI_FLEN_64BIT;
|
||||
|
||||
da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
|
||||
da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3);
|
||||
snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
|
||||
snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
|
||||
static int da7210_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB;
|
||||
|
||||
if (mute)
|
||||
snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4);
|
||||
else
|
||||
snd_soc_write(codec, DA7210_DAC_HPF, mute_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
/* DAI operations */
|
||||
static struct snd_soc_dai_ops da7210_dai_ops = {
|
||||
.startup = da7210_startup,
|
||||
.hw_params = da7210_hw_params,
|
||||
.set_fmt = da7210_set_dai_fmt,
|
||||
.digital_mute = da7210_mute,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver da7210_dai = {
|
||||
@ -451,11 +791,15 @@ static struct snd_soc_dai_driver da7210_dai = {
|
||||
static int da7210_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
|
||||
|
||||
codec->control_data = da7210->control_data;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME
|
||||
*
|
||||
@ -472,8 +816,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
||||
/*
|
||||
* make sure that DA7210 use bypass mode before start up
|
||||
*/
|
||||
da7210_write(codec, DA7210_STARTUP1, 0);
|
||||
da7210_write(codec, DA7210_PLL_DIV3,
|
||||
snd_soc_write(codec, DA7210_STARTUP1, 0);
|
||||
snd_soc_write(codec, DA7210_PLL_DIV3,
|
||||
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
|
||||
|
||||
/*
|
||||
@ -481,36 +825,70 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
||||
*/
|
||||
|
||||
/* Enable Left & Right MIC PGA and Mic Bias */
|
||||
da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
|
||||
da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
|
||||
snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
|
||||
snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
|
||||
|
||||
/* Enable Left and Right input PGA */
|
||||
da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
|
||||
da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
|
||||
snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
|
||||
snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
|
||||
|
||||
/* Enable Left and Right ADC */
|
||||
da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
|
||||
snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
|
||||
|
||||
/*
|
||||
* DAC settings
|
||||
*/
|
||||
|
||||
/* Enable Left and Right DAC */
|
||||
da7210_write(codec, DA7210_DAC_SEL,
|
||||
snd_soc_write(codec, DA7210_DAC_SEL,
|
||||
DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN |
|
||||
DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN);
|
||||
|
||||
/* Enable Left and Right out PGA */
|
||||
da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
|
||||
da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
|
||||
snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
|
||||
snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
|
||||
|
||||
/* Enable Left and Right HeadPhone PGA */
|
||||
da7210_write(codec, DA7210_HP_CFG,
|
||||
snd_soc_write(codec, DA7210_HP_CFG,
|
||||
DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN |
|
||||
DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN);
|
||||
|
||||
/* Enable ramp mode for DAC gain update */
|
||||
snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN);
|
||||
|
||||
/*
|
||||
* For DA7210 codec, there are two ways to enable/disable analog IOs
|
||||
* and ADC/DAC,
|
||||
* (1) Using "Enable Bit" of register associated with that IO
|
||||
* (or ADC/DAC)
|
||||
* e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg
|
||||
*
|
||||
* (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register
|
||||
* e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5)
|
||||
*
|
||||
* Out of these two methods, the one using STANDBY bits is preferred
|
||||
* way to enable/disable individual blocks. This is because STANDBY
|
||||
* registers are part of system controller which allows system power
|
||||
* up/down in a controlled, pop-free manner. Also, as per application
|
||||
* note of DA7210, STANDBY register bits are only effective if a
|
||||
* particular IO (or ADC/DAC) is already enabled using enable/disable
|
||||
* register bits. Keeping these things in mind, current DAPM
|
||||
* implementation manipulates only STANDBY bits.
|
||||
*
|
||||
* Overall implementation can be outlined as below,
|
||||
*
|
||||
* - "Enable bit" of an IO or ADC/DAC is used to enable it in probe()
|
||||
* - "STANDBY bit" is controlled by DAPM
|
||||
*/
|
||||
|
||||
/* Enable Line out amplifiers */
|
||||
snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN);
|
||||
snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN);
|
||||
snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN |
|
||||
DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R);
|
||||
|
||||
/* Diable PLL and bypass it */
|
||||
da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
|
||||
snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
|
||||
|
||||
/*
|
||||
* If 48kHz sound came, it use bypass mode,
|
||||
@ -521,25 +899,22 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
||||
* DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
|
||||
* see da7210_hw_params
|
||||
*/
|
||||
da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
|
||||
da7210_write(codec, DA7210_PLL_DIV2, 0x99);
|
||||
da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
|
||||
snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
|
||||
snd_soc_write(codec, DA7210_PLL_DIV2, 0x99);
|
||||
snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A |
|
||||
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
|
||||
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
|
||||
|
||||
/* As suggested by Dialog */
|
||||
da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
|
||||
da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
|
||||
da7210_write(codec, DA7210_A_PLL1, 0x01);
|
||||
da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
|
||||
da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
|
||||
da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
|
||||
snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
|
||||
snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
|
||||
snd_soc_write(codec, DA7210_A_PLL1, 0x01);
|
||||
snd_soc_write(codec, DA7210_A_CP_MODE, 0x7C);
|
||||
snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
|
||||
snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
|
||||
|
||||
/* Activate all enabled subsystem */
|
||||
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
|
||||
|
||||
snd_soc_add_controls(codec, da7210_snd_controls,
|
||||
ARRAY_SIZE(da7210_snd_controls));
|
||||
snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
|
||||
|
||||
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
|
||||
|
||||
@ -548,11 +923,18 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
|
||||
.probe = da7210_probe,
|
||||
.read = da7210_read,
|
||||
.write = da7210_write,
|
||||
.reg_cache_size = ARRAY_SIZE(da7210_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = da7210_reg,
|
||||
.volatile_register = da7210_volatile_register,
|
||||
|
||||
.controls = da7210_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(da7210_snd_controls),
|
||||
|
||||
.dapm_widgets = da7210_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets),
|
||||
.dapm_routes = da7210_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
@ -567,7 +949,6 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, da7210);
|
||||
da7210->control_data = i2c;
|
||||
da7210->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2007 Wolfson Microelectronics PLC.
|
||||
* Author: Graeme Gregory
|
||||
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
* graeme.gregory@wolfsonmicro.com
|
||||
* Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -40,7 +40,6 @@ struct max98088_cdata {
|
||||
|
||||
struct max98088_priv {
|
||||
enum max98088_type devtype;
|
||||
void *control_data;
|
||||
struct max98088_pdata *pdata;
|
||||
unsigned int sysclk;
|
||||
struct max98088_cdata dai[2];
|
||||
@ -1697,12 +1696,18 @@ static struct snd_soc_dai_driver max98088_dai[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static int max98088_get_channel(const char *name)
|
||||
static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"};
|
||||
|
||||
static int max98088_get_channel(struct snd_soc_codec *codec, const char *name)
|
||||
{
|
||||
if (strcmp(name, "EQ1 Mode") == 0)
|
||||
return 0;
|
||||
if (strcmp(name, "EQ2 Mode") == 0)
|
||||
return 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++)
|
||||
if (strcmp(name, eq_mode_name[i]) == 0)
|
||||
return i;
|
||||
|
||||
/* Shouldn't happen */
|
||||
dev_err(codec->dev, "Bad EQ channel name '%s'\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1807,10 +1812,13 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98088_pdata *pdata = max98088->pdata;
|
||||
int channel = max98088_get_channel(kcontrol->id.name);
|
||||
int channel = max98088_get_channel(codec, kcontrol->id.name);
|
||||
struct max98088_cdata *cdata;
|
||||
int sel = ucontrol->value.integer.value[0];
|
||||
|
||||
if (channel < 0)
|
||||
return channel;
|
||||
|
||||
cdata = &max98088->dai[channel];
|
||||
|
||||
if (sel >= pdata->eq_cfgcnt)
|
||||
@ -1835,9 +1843,12 @@ static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
|
||||
int channel = max98088_get_channel(kcontrol->id.name);
|
||||
int channel = max98088_get_channel(codec, kcontrol->id.name);
|
||||
struct max98088_cdata *cdata;
|
||||
|
||||
if (channel < 0)
|
||||
return channel;
|
||||
|
||||
cdata = &max98088->dai[channel];
|
||||
ucontrol->value.enumerated.item[0] = cdata->eq_sel;
|
||||
return 0;
|
||||
@ -1852,17 +1863,17 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
|
||||
int i, j;
|
||||
const char **t;
|
||||
int ret;
|
||||
|
||||
struct snd_kcontrol_new controls[] = {
|
||||
SOC_ENUM_EXT("EQ1 Mode",
|
||||
SOC_ENUM_EXT((char *)eq_mode_name[0],
|
||||
max98088->eq_enum,
|
||||
max98088_get_eq_enum,
|
||||
max98088_put_eq_enum),
|
||||
SOC_ENUM_EXT("EQ2 Mode",
|
||||
SOC_ENUM_EXT((char *)eq_mode_name[1],
|
||||
max98088->eq_enum,
|
||||
max98088_get_eq_enum,
|
||||
max98088_put_eq_enum),
|
||||
};
|
||||
BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name));
|
||||
|
||||
cfg = pdata->eq_cfg;
|
||||
cfgcnt = pdata->eq_cfgcnt;
|
||||
@ -2066,7 +2077,6 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
|
||||
max98088->devtype = id->driver_data;
|
||||
|
||||
i2c_set_clientdata(i2c, max98088);
|
||||
max98088->control_data = i2c;
|
||||
max98088->pdata = i2c->dev.platform_data;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -40,7 +40,6 @@ struct max98095_cdata {
|
||||
|
||||
struct max98095_priv {
|
||||
enum max98095_type devtype;
|
||||
void *control_data;
|
||||
struct max98095_pdata *pdata;
|
||||
unsigned int sysclk;
|
||||
struct max98095_cdata dai[3];
|
||||
@ -618,14 +617,13 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
|
||||
static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 data[2];
|
||||
int ret;
|
||||
|
||||
data[0] = reg;
|
||||
data[1] = value;
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
else
|
||||
return -EIO;
|
||||
codec->cache_bypass = 1;
|
||||
ret = snd_soc_write(codec, reg, value);
|
||||
codec->cache_bypass = 0;
|
||||
|
||||
return ret ? -EIO : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1992,12 +1990,19 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
|
||||
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
|
||||
}
|
||||
|
||||
static int max98095_get_bq_channel(const char *name)
|
||||
static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"};
|
||||
|
||||
static int max98095_get_bq_channel(struct snd_soc_codec *codec,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp(name, "Biquad1 Mode") == 0)
|
||||
return 0;
|
||||
if (strcmp(name, "Biquad2 Mode") == 0)
|
||||
return 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++)
|
||||
if (strcmp(name, bq_mode_name[i]) == 0)
|
||||
return i;
|
||||
|
||||
/* Shouldn't happen */
|
||||
dev_err(codec->dev, "Bad biquad channel name '%s'\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2007,14 +2012,15 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98095_pdata *pdata = max98095->pdata;
|
||||
int channel = max98095_get_bq_channel(kcontrol->id.name);
|
||||
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
|
||||
struct max98095_cdata *cdata;
|
||||
int sel = ucontrol->value.integer.value[0];
|
||||
struct max98095_biquad_cfg *coef_set;
|
||||
int fs, best, best_val, i;
|
||||
int regmask, regsave;
|
||||
|
||||
BUG_ON(channel > 1);
|
||||
if (channel < 0)
|
||||
return channel;
|
||||
|
||||
if (!pdata || !max98095->bq_textcnt)
|
||||
return 0;
|
||||
@ -2066,9 +2072,12 @@ static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
|
||||
int channel = max98095_get_bq_channel(kcontrol->id.name);
|
||||
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
|
||||
struct max98095_cdata *cdata;
|
||||
|
||||
if (channel < 0)
|
||||
return channel;
|
||||
|
||||
cdata = &max98095->dai[channel];
|
||||
ucontrol->value.enumerated.item[0] = cdata->bq_sel;
|
||||
|
||||
@ -2086,15 +2095,16 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
|
||||
struct snd_kcontrol_new controls[] = {
|
||||
SOC_ENUM_EXT("Biquad1 Mode",
|
||||
SOC_ENUM_EXT((char *)bq_mode_name[0],
|
||||
max98095->bq_enum,
|
||||
max98095_get_bq_enum,
|
||||
max98095_put_bq_enum),
|
||||
SOC_ENUM_EXT("Biquad2 Mode",
|
||||
SOC_ENUM_EXT((char *)bq_mode_name[1],
|
||||
max98095->bq_enum,
|
||||
max98095_get_bq_enum,
|
||||
max98095_put_bq_enum),
|
||||
};
|
||||
BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name));
|
||||
|
||||
cfg = pdata->bq_cfg;
|
||||
cfgcnt = pdata->bq_cfgcnt;
|
||||
@ -2337,7 +2347,6 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
max98095->devtype = id->driver_data;
|
||||
i2c_set_clientdata(i2c, max98095);
|
||||
max98095->control_data = i2c;
|
||||
max98095->pdata = i2c->dev.platform_data;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
|
||||
|
1773
sound/soc/codecs/rt5631.c
Normal file
1773
sound/soc/codecs/rt5631.c
Normal file
File diff suppressed because it is too large
Load Diff
701
sound/soc/codecs/rt5631.h
Normal file
701
sound/soc/codecs/rt5631.h
Normal file
@ -0,0 +1,701 @@
|
||||
#ifndef __RTCODEC5631_H__
|
||||
#define __RTCODEC5631_H__
|
||||
|
||||
|
||||
#define RT5631_RESET 0x00
|
||||
#define RT5631_SPK_OUT_VOL 0x02
|
||||
#define RT5631_HP_OUT_VOL 0x04
|
||||
#define RT5631_MONO_AXO_1_2_VOL 0x06
|
||||
#define RT5631_AUX_IN_VOL 0x0A
|
||||
#define RT5631_STEREO_DAC_VOL_1 0x0C
|
||||
#define RT5631_MIC_CTRL_1 0x0E
|
||||
#define RT5631_STEREO_DAC_VOL_2 0x10
|
||||
#define RT5631_ADC_CTRL_1 0x12
|
||||
#define RT5631_ADC_REC_MIXER 0x14
|
||||
#define RT5631_ADC_CTRL_2 0x16
|
||||
#define RT5631_VDAC_DIG_VOL 0x18
|
||||
#define RT5631_OUTMIXER_L_CTRL 0x1A
|
||||
#define RT5631_OUTMIXER_R_CTRL 0x1C
|
||||
#define RT5631_AXO1MIXER_CTRL 0x1E
|
||||
#define RT5631_AXO2MIXER_CTRL 0x20
|
||||
#define RT5631_MIC_CTRL_2 0x22
|
||||
#define RT5631_DIG_MIC_CTRL 0x24
|
||||
#define RT5631_MONO_INPUT_VOL 0x26
|
||||
#define RT5631_SPK_MIXER_CTRL 0x28
|
||||
#define RT5631_SPK_MONO_OUT_CTRL 0x2A
|
||||
#define RT5631_SPK_MONO_HP_OUT_CTRL 0x2C
|
||||
#define RT5631_SDP_CTRL 0x34
|
||||
#define RT5631_MONO_SDP_CTRL 0x36
|
||||
#define RT5631_STEREO_AD_DA_CLK_CTRL 0x38
|
||||
#define RT5631_PWR_MANAG_ADD1 0x3A
|
||||
#define RT5631_PWR_MANAG_ADD2 0x3B
|
||||
#define RT5631_PWR_MANAG_ADD3 0x3C
|
||||
#define RT5631_PWR_MANAG_ADD4 0x3E
|
||||
#define RT5631_GEN_PUR_CTRL_REG 0x40
|
||||
#define RT5631_GLOBAL_CLK_CTRL 0x42
|
||||
#define RT5631_PLL_CTRL 0x44
|
||||
#define RT5631_INT_ST_IRQ_CTRL_1 0x48
|
||||
#define RT5631_INT_ST_IRQ_CTRL_2 0x4A
|
||||
#define RT5631_GPIO_CTRL 0x4C
|
||||
#define RT5631_MISC_CTRL 0x52
|
||||
#define RT5631_DEPOP_FUN_CTRL_1 0x54
|
||||
#define RT5631_DEPOP_FUN_CTRL_2 0x56
|
||||
#define RT5631_JACK_DET_CTRL 0x5A
|
||||
#define RT5631_SOFT_VOL_CTRL 0x5C
|
||||
#define RT5631_ALC_CTRL_1 0x64
|
||||
#define RT5631_ALC_CTRL_2 0x65
|
||||
#define RT5631_ALC_CTRL_3 0x66
|
||||
#define RT5631_PSEUDO_SPATL_CTRL 0x68
|
||||
#define RT5631_INDEX_ADD 0x6A
|
||||
#define RT5631_INDEX_DATA 0x6C
|
||||
#define RT5631_EQ_CTRL 0x6E
|
||||
#define RT5631_VENDOR_ID 0x7A
|
||||
#define RT5631_VENDOR_ID1 0x7C
|
||||
#define RT5631_VENDOR_ID2 0x7E
|
||||
|
||||
/* Index of Codec Private Register definition */
|
||||
#define RT5631_EQ_BW_LOP 0x00
|
||||
#define RT5631_EQ_GAIN_LOP 0x01
|
||||
#define RT5631_EQ_FC_BP1 0x02
|
||||
#define RT5631_EQ_BW_BP1 0x03
|
||||
#define RT5631_EQ_GAIN_BP1 0x04
|
||||
#define RT5631_EQ_FC_BP2 0x05
|
||||
#define RT5631_EQ_BW_BP2 0x06
|
||||
#define RT5631_EQ_GAIN_BP2 0x07
|
||||
#define RT5631_EQ_FC_BP3 0x08
|
||||
#define RT5631_EQ_BW_BP3 0x09
|
||||
#define RT5631_EQ_GAIN_BP3 0x0a
|
||||
#define RT5631_EQ_BW_HIP 0x0b
|
||||
#define RT5631_EQ_GAIN_HIP 0x0c
|
||||
#define RT5631_EQ_HPF_A1 0x0d
|
||||
#define RT5631_EQ_HPF_A2 0x0e
|
||||
#define RT5631_EQ_HPF_GAIN 0x0f
|
||||
#define RT5631_EQ_PRE_VOL_CTRL 0x11
|
||||
#define RT5631_EQ_POST_VOL_CTRL 0x12
|
||||
#define RT5631_TEST_MODE_CTRL 0x39
|
||||
#define RT5631_CP_INTL_REG2 0x45
|
||||
#define RT5631_ADDA_MIXER_INTL_REG3 0x52
|
||||
#define RT5631_SPK_INTL_CTRL 0x56
|
||||
|
||||
|
||||
/* global definition */
|
||||
#define RT5631_L_MUTE (0x1 << 15)
|
||||
#define RT5631_L_MUTE_SHIFT 15
|
||||
#define RT5631_L_EN (0x1 << 14)
|
||||
#define RT5631_L_EN_SHIFT 14
|
||||
#define RT5631_R_MUTE (0x1 << 7)
|
||||
#define RT5631_R_MUTE_SHIFT 7
|
||||
#define RT5631_R_EN (0x1 << 6)
|
||||
#define RT5631_R_EN_SHIFT 6
|
||||
#define RT5631_VOL_MASK 0x1f
|
||||
#define RT5631_L_VOL_SHIFT 8
|
||||
#define RT5631_R_VOL_SHIFT 0
|
||||
|
||||
/* Speaker Output Control(0x02) */
|
||||
#define RT5631_SPK_L_VOL_SEL_MASK (0x1 << 14)
|
||||
#define RT5631_SPK_L_VOL_SEL_VMID (0x0 << 14)
|
||||
#define RT5631_SPK_L_VOL_SEL_SPKMIX_L (0x1 << 14)
|
||||
#define RT5631_SPK_R_VOL_SEL_MASK (0x1 << 6)
|
||||
#define RT5631_SPK_R_VOL_SEL_VMID (0x0 << 6)
|
||||
#define RT5631_SPK_R_VOL_SEL_SPKMIX_R (0x1 << 6)
|
||||
|
||||
/* Headphone Output Control(0x04) */
|
||||
#define RT5631_HP_L_VOL_SEL_MASK (0x1 << 14)
|
||||
#define RT5631_HP_L_VOL_SEL_VMID (0x0 << 14)
|
||||
#define RT5631_HP_L_VOL_SEL_OUTMIX_L (0x1 << 14)
|
||||
#define RT5631_HP_R_VOL_SEL_MASK (0x1 << 6)
|
||||
#define RT5631_HP_R_VOL_SEL_VMID (0x0 << 6)
|
||||
#define RT5631_HP_R_VOL_SEL_OUTMIX_R (0x1 << 6)
|
||||
|
||||
/* Output Control for AUXOUT/MONO(0x06) */
|
||||
#define RT5631_AUXOUT_1_VOL_SEL_MASK (0x1 << 14)
|
||||
#define RT5631_AUXOUT_1_VOL_SEL_VMID (0x0 << 14)
|
||||
#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L (0x1 << 14)
|
||||
#define RT5631_MUTE_MONO (0x1 << 13)
|
||||
#define RT5631_MUTE_MONO_SHIFT 13
|
||||
#define RT5631_AUXOUT_2_VOL_SEL_MASK (0x1 << 6)
|
||||
#define RT5631_AUXOUT_2_VOL_SEL_VMID (0x0 << 6)
|
||||
#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R (0x1 << 6)
|
||||
|
||||
/* Microphone Input Control 1(0x0E) */
|
||||
#define RT5631_MIC1_DIFF_INPUT_CTRL (0x1 << 15)
|
||||
#define RT5631_MIC1_DIFF_INPUT_SHIFT 15
|
||||
#define RT5631_MIC2_DIFF_INPUT_CTRL (0x1 << 7)
|
||||
#define RT5631_MIC2_DIFF_INPUT_SHIFT 7
|
||||
|
||||
/* Stereo DAC Digital Volume2(0x10) */
|
||||
#define RT5631_DAC_VOL_MASK 0xff
|
||||
|
||||
/* ADC Recording Mixer Control(0x14) */
|
||||
#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L (0x1 << 15)
|
||||
#define RT5631_M_OUTMIXL_RECMIXL_BIT 15
|
||||
#define RT5631_M_MIC1_TO_RECMIXER_L (0x1 << 14)
|
||||
#define RT5631_M_MIC1_RECMIXL_BIT 14
|
||||
#define RT5631_M_AXIL_TO_RECMIXER_L (0x1 << 13)
|
||||
#define RT5631_M_AXIL_RECMIXL_BIT 13
|
||||
#define RT5631_M_MONO_IN_TO_RECMIXER_L (0x1 << 12)
|
||||
#define RT5631_M_MONO_IN_RECMIXL_BIT 12
|
||||
#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R (0x1 << 7)
|
||||
#define RT5631_M_OUTMIXR_RECMIXR_BIT 7
|
||||
#define RT5631_M_MIC2_TO_RECMIXER_R (0x1 << 6)
|
||||
#define RT5631_M_MIC2_RECMIXR_BIT 6
|
||||
#define RT5631_M_AXIR_TO_RECMIXER_R (0x1 << 5)
|
||||
#define RT5631_M_AXIR_RECMIXR_BIT 5
|
||||
#define RT5631_M_MONO_IN_TO_RECMIXER_R (0x1 << 4)
|
||||
#define RT5631_M_MONO_IN_RECMIXR_BIT 4
|
||||
|
||||
/* Left Output Mixer Control(0x1A) */
|
||||
#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L (0x1 << 15)
|
||||
#define RT5631_M_RECMIXL_OUTMIXL_BIT 15
|
||||
#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L (0x1 << 14)
|
||||
#define RT5631_M_RECMIXR_OUTMIXL_BIT 14
|
||||
#define RT5631_M_DAC_L_TO_OUTMIXER_L (0x1 << 13)
|
||||
#define RT5631_M_DACL_OUTMIXL_BIT 13
|
||||
#define RT5631_M_MIC1_TO_OUTMIXER_L (0x1 << 12)
|
||||
#define RT5631_M_MIC1_OUTMIXL_BIT 12
|
||||
#define RT5631_M_MIC2_TO_OUTMIXER_L (0x1 << 11)
|
||||
#define RT5631_M_MIC2_OUTMIXL_BIT 11
|
||||
#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L (0x1 << 10)
|
||||
#define RT5631_M_MONO_INP_OUTMIXL_BIT 10
|
||||
#define RT5631_M_AXIL_TO_OUTMIXER_L (0x1 << 9)
|
||||
#define RT5631_M_AXIL_OUTMIXL_BIT 9
|
||||
#define RT5631_M_AXIR_TO_OUTMIXER_L (0x1 << 8)
|
||||
#define RT5631_M_AXIR_OUTMIXL_BIT 8
|
||||
#define RT5631_M_VDAC_TO_OUTMIXER_L (0x1 << 7)
|
||||
#define RT5631_M_VDAC_OUTMIXL_BIT 7
|
||||
|
||||
/* Right Output Mixer Control(0x1C) */
|
||||
#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R (0x1 << 15)
|
||||
#define RT5631_M_RECMIXL_OUTMIXR_BIT 15
|
||||
#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R (0x1 << 14)
|
||||
#define RT5631_M_RECMIXR_OUTMIXR_BIT 14
|
||||
#define RT5631_M_DAC_R_TO_OUTMIXER_R (0x1 << 13)
|
||||
#define RT5631_M_DACR_OUTMIXR_BIT 13
|
||||
#define RT5631_M_MIC1_TO_OUTMIXER_R (0x1 << 12)
|
||||
#define RT5631_M_MIC1_OUTMIXR_BIT 12
|
||||
#define RT5631_M_MIC2_TO_OUTMIXER_R (0x1 << 11)
|
||||
#define RT5631_M_MIC2_OUTMIXR_BIT 11
|
||||
#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R (0x1 << 10)
|
||||
#define RT5631_M_MONO_INN_OUTMIXR_BIT 10
|
||||
#define RT5631_M_AXIL_TO_OUTMIXER_R (0x1 << 9)
|
||||
#define RT5631_M_AXIL_OUTMIXR_BIT 9
|
||||
#define RT5631_M_AXIR_TO_OUTMIXER_R (0x1 << 8)
|
||||
#define RT5631_M_AXIR_OUTMIXR_BIT 8
|
||||
#define RT5631_M_VDAC_TO_OUTMIXER_R (0x1 << 7)
|
||||
#define RT5631_M_VDAC_OUTMIXR_BIT 7
|
||||
|
||||
/* Lout Mixer Control(0x1E) */
|
||||
#define RT5631_M_MIC1_TO_AXO1MIXER (0x1 << 15)
|
||||
#define RT5631_M_MIC1_AXO1MIX_BIT 15
|
||||
#define RT5631_M_MIC2_TO_AXO1MIXER (0x1 << 11)
|
||||
#define RT5631_M_MIC2_AXO1MIX_BIT 11
|
||||
#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER (0x1 << 7)
|
||||
#define RT5631_M_OUTMIXL_AXO1MIX_BIT 7
|
||||
#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER (0x1 << 6)
|
||||
#define RT5631_M_OUTMIXR_AXO1MIX_BIT 6
|
||||
|
||||
/* Rout Mixer Control(0x20) */
|
||||
#define RT5631_M_MIC1_TO_AXO2MIXER (0x1 << 15)
|
||||
#define RT5631_M_MIC1_AXO2MIX_BIT 15
|
||||
#define RT5631_M_MIC2_TO_AXO2MIXER (0x1 << 11)
|
||||
#define RT5631_M_MIC2_AXO2MIX_BIT 11
|
||||
#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER (0x1 << 7)
|
||||
#define RT5631_M_OUTMIXL_AXO2MIX_BIT 7
|
||||
#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER (0x1 << 6)
|
||||
#define RT5631_M_OUTMIXR_AXO2MIX_BIT 6
|
||||
|
||||
/* Micphone Input Control 2(0x22) */
|
||||
#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1
|
||||
#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2
|
||||
|
||||
#define RT5631_MIC1_BOOST_CTRL_MASK (0xf << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_BYPASS (0x0 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_20DB (0x1 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_24DB (0x2 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_30DB (0x3 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_35DB (0x4 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_40DB (0x5 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_34DB (0x6 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_50DB (0x7 << 12)
|
||||
#define RT5631_MIC1_BOOST_CTRL_52DB (0x8 << 12)
|
||||
#define RT5631_MIC1_BOOST_SHIFT 12
|
||||
|
||||
#define RT5631_MIC2_BOOST_CTRL_MASK (0xf << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_BYPASS (0x0 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_20DB (0x1 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_24DB (0x2 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_30DB (0x3 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_35DB (0x4 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_40DB (0x5 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_34DB (0x6 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_50DB (0x7 << 8)
|
||||
#define RT5631_MIC2_BOOST_CTRL_52DB (0x8 << 8)
|
||||
#define RT5631_MIC2_BOOST_SHIFT 8
|
||||
|
||||
#define RT5631_MICBIAS1_VOLT_CTRL_MASK (0x1 << 7)
|
||||
#define RT5631_MICBIAS1_VOLT_CTRL_90P (0x0 << 7)
|
||||
#define RT5631_MICBIAS1_VOLT_CTRL_75P (0x1 << 7)
|
||||
|
||||
#define RT5631_MICBIAS1_S_C_DET_MASK (0x1 << 6)
|
||||
#define RT5631_MICBIAS1_S_C_DET_DIS (0x0 << 6)
|
||||
#define RT5631_MICBIAS1_S_C_DET_ENA (0x1 << 6)
|
||||
|
||||
#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK (0x3 << 4)
|
||||
#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA (0x0 << 4)
|
||||
#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA (0x1 << 4)
|
||||
#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA (0x2 << 4)
|
||||
|
||||
#define RT5631_MICBIAS2_VOLT_CTRL_MASK (0x1 << 3)
|
||||
#define RT5631_MICBIAS2_VOLT_CTRL_90P (0x0 << 3)
|
||||
#define RT5631_MICBIAS2_VOLT_CTRL_75P (0x1 << 3)
|
||||
|
||||
#define RT5631_MICBIAS2_S_C_DET_MASK (0x1 << 2)
|
||||
#define RT5631_MICBIAS2_S_C_DET_DIS (0x0 << 2)
|
||||
#define RT5631_MICBIAS2_S_C_DET_ENA (0x1 << 2)
|
||||
|
||||
#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK (0x3)
|
||||
#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA (0x0)
|
||||
#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA (0x1)
|
||||
#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA (0x2)
|
||||
|
||||
|
||||
/* Digital Microphone Control(0x24) */
|
||||
#define RT5631_DMIC_ENA_MASK (0x1 << 15)
|
||||
#define RT5631_DMIC_ENA_SHIFT 15
|
||||
/* DMIC_ENA: DMIC to ADC Digital filter */
|
||||
#define RT5631_DMIC_ENA (0x1 << 15)
|
||||
/* DMIC_DIS: ADC mixer to ADC Digital filter */
|
||||
#define RT5631_DMIC_DIS (0x0 << 15)
|
||||
#define RT5631_DMIC_L_CH_MUTE (0x1 << 13)
|
||||
#define RT5631_DMIC_L_CH_MUTE_SHIFT 13
|
||||
#define RT5631_DMIC_R_CH_MUTE (0x1 << 12)
|
||||
#define RT5631_DMIC_R_CH_MUTE_SHIFT 12
|
||||
#define RT5631_DMIC_L_CH_LATCH_MASK (0x1 << 9)
|
||||
#define RT5631_DMIC_L_CH_LATCH_RISING (0x1 << 9)
|
||||
#define RT5631_DMIC_L_CH_LATCH_FALLING (0x0 << 9)
|
||||
#define RT5631_DMIC_R_CH_LATCH_MASK (0x1 << 8)
|
||||
#define RT5631_DMIC_R_CH_LATCH_RISING (0x1 << 8)
|
||||
#define RT5631_DMIC_R_CH_LATCH_FALLING (0x0 << 8)
|
||||
#define RT5631_DMIC_CLK_CTRL_MASK (0x3 << 4)
|
||||
#define RT5631_DMIC_CLK_CTRL_TO_128FS (0x0 << 4)
|
||||
#define RT5631_DMIC_CLK_CTRL_TO_64FS (0x1 << 4)
|
||||
#define RT5631_DMIC_CLK_CTRL_TO_32FS (0x2 << 4)
|
||||
|
||||
/* Microphone Input Volume(0x26) */
|
||||
#define RT5631_MONO_DIFF_INPUT_SHIFT 15
|
||||
|
||||
/* Speaker Mixer Control(0x28) */
|
||||
#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L (0x1 << 15)
|
||||
#define RT5631_M_RECMIXL_SPKMIXL_BIT 15
|
||||
#define RT5631_M_MIC1_P_TO_SPKMIXER_L (0x1 << 14)
|
||||
#define RT5631_M_MIC1P_SPKMIXL_BIT 14
|
||||
#define RT5631_M_DAC_L_TO_SPKMIXER_L (0x1 << 13)
|
||||
#define RT5631_M_DACL_SPKMIXL_BIT 13
|
||||
#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L (0x1 << 12)
|
||||
#define RT5631_M_OUTMIXL_SPKMIXL_BIT 12
|
||||
|
||||
#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R (0x1 << 7)
|
||||
#define RT5631_M_RECMIXR_SPKMIXR_BIT 7
|
||||
#define RT5631_M_MIC2_P_TO_SPKMIXER_R (0x1 << 6)
|
||||
#define RT5631_M_MIC2P_SPKMIXR_BIT 6
|
||||
#define RT5631_M_DAC_R_TO_SPKMIXER_R (0x1 << 5)
|
||||
#define RT5631_M_DACR_SPKMIXR_BIT 5
|
||||
#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R (0x1 << 4)
|
||||
#define RT5631_M_OUTMIXR_SPKMIXR_BIT 4
|
||||
|
||||
/* Speaker/Mono Output Control(0x2A) */
|
||||
#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER (0x1 << 15)
|
||||
#define RT5631_M_SPKVOLL_SPOLMIX_BIT 15
|
||||
#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER (0x1 << 14)
|
||||
#define RT5631_M_SPKVOLR_SPOLMIX_BIT 14
|
||||
#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER (0x1 << 13)
|
||||
#define RT5631_M_SPKVOLL_SPORMIX_BIT 13
|
||||
#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER (0x1 << 12)
|
||||
#define RT5631_M_SPKVOLR_SPORMIX_BIT 12
|
||||
#define RT5631_M_OUTVOL_L_TO_MONOMIXER (0x1 << 11)
|
||||
#define RT5631_M_OUTVOLL_MONOMIX_BIT 11
|
||||
#define RT5631_M_OUTVOL_R_TO_MONOMIXER (0x1 << 10)
|
||||
#define RT5631_M_OUTVOLR_MONOMIX_BIT 10
|
||||
|
||||
/* Speaker/Mono/HP Output Control(0x2C) */
|
||||
#define RT5631_SPK_L_MUX_SEL_MASK (0x3 << 14)
|
||||
#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L (0x0 << 14)
|
||||
#define RT5631_SPK_L_MUX_SEL_MONO_IN (0x1 << 14)
|
||||
#define RT5631_SPK_L_MUX_SEL_DAC_L (0x3 << 14)
|
||||
#define RT5631_SPK_L_MUX_SEL_SHIFT 14
|
||||
|
||||
#define RT5631_SPK_R_MUX_SEL_MASK (0x3 << 10)
|
||||
#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R (0x0 << 10)
|
||||
#define RT5631_SPK_R_MUX_SEL_MONO_IN (0x1 << 10)
|
||||
#define RT5631_SPK_R_MUX_SEL_DAC_R (0x3 << 10)
|
||||
#define RT5631_SPK_R_MUX_SEL_SHIFT 10
|
||||
|
||||
#define RT5631_MONO_MUX_SEL_MASK (0x3 << 6)
|
||||
#define RT5631_MONO_MUX_SEL_MONOMIXER (0x0 << 6)
|
||||
#define RT5631_MONO_MUX_SEL_MONO_IN (0x1 << 6)
|
||||
#define RT5631_MONO_MUX_SEL_SHIFT 6
|
||||
|
||||
#define RT5631_HP_L_MUX_SEL_MASK (0x1 << 3)
|
||||
#define RT5631_HP_L_MUX_SEL_HPVOL_L (0x0 << 3)
|
||||
#define RT5631_HP_L_MUX_SEL_DAC_L (0x1 << 3)
|
||||
#define RT5631_HP_L_MUX_SEL_SHIFT 3
|
||||
|
||||
#define RT5631_HP_R_MUX_SEL_MASK (0x1 << 2)
|
||||
#define RT5631_HP_R_MUX_SEL_HPVOL_R (0x0 << 2)
|
||||
#define RT5631_HP_R_MUX_SEL_DAC_R (0x1 << 2)
|
||||
#define RT5631_HP_R_MUX_SEL_SHIFT 2
|
||||
|
||||
/* Stereo I2S Serial Data Port Control(0x34) */
|
||||
#define RT5631_SDP_MODE_SEL_MASK (0x1 << 15)
|
||||
#define RT5631_SDP_MODE_SEL_MASTER (0x0 << 15)
|
||||
#define RT5631_SDP_MODE_SEL_SLAVE (0x1 << 15)
|
||||
|
||||
#define RT5631_SDP_ADC_CPS_SEL_MASK (0x3 << 10)
|
||||
#define RT5631_SDP_ADC_CPS_SEL_OFF (0x0 << 10)
|
||||
#define RT5631_SDP_ADC_CPS_SEL_U_LAW (0x1 << 10)
|
||||
#define RT5631_SDP_ADC_CPS_SEL_A_LAW (0x2 << 10)
|
||||
|
||||
#define RT5631_SDP_DAC_CPS_SEL_MASK (0x3 << 8)
|
||||
#define RT5631_SDP_DAC_CPS_SEL_OFF (0x0 << 8)
|
||||
#define RT5631_SDP_DAC_CPS_SEL_U_LAW (0x1 << 8)
|
||||
#define RT5631_SDP_DAC_CPS_SEL_A_LAW (0x2 << 8)
|
||||
/* 0:Normal 1:Invert */
|
||||
#define RT5631_SDP_I2S_BCLK_POL_CTRL (0x1 << 7)
|
||||
/* 0:Normal 1:Invert */
|
||||
#define RT5631_SDP_DAC_R_INV (0x1 << 6)
|
||||
/* 0:ADC data appear at left phase of LRCK
|
||||
* 1:ADC data appear at right phase of LRCK
|
||||
*/
|
||||
#define RT5631_SDP_ADC_DATA_L_R_SWAP (0x1 << 5)
|
||||
/* 0:DAC data appear at left phase of LRCK
|
||||
* 1:DAC data appear at right phase of LRCK
|
||||
*/
|
||||
#define RT5631_SDP_DAC_DATA_L_R_SWAP (0x1 << 4)
|
||||
|
||||
/* Data Length Slection */
|
||||
#define RT5631_SDP_I2S_DL_MASK (0x3 << 2)
|
||||
#define RT5631_SDP_I2S_DL_16 (0x0 << 2)
|
||||
#define RT5631_SDP_I2S_DL_20 (0x1 << 2)
|
||||
#define RT5631_SDP_I2S_DL_24 (0x2 << 2)
|
||||
#define RT5631_SDP_I2S_DL_8 (0x3 << 2)
|
||||
|
||||
/* PCM Data Format Selection */
|
||||
#define RT5631_SDP_I2S_DF_MASK (0x3)
|
||||
#define RT5631_SDP_I2S_DF_I2S (0x0)
|
||||
#define RT5631_SDP_I2S_DF_LEFT (0x1)
|
||||
#define RT5631_SDP_I2S_DF_PCM_A (0x2)
|
||||
#define RT5631_SDP_I2S_DF_PCM_B (0x3)
|
||||
|
||||
/* Stereo AD/DA Clock Control(0x38h) */
|
||||
#define RT5631_I2S_PRE_DIV_MASK (0x7 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_1 (0x0 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_2 (0x1 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_4 (0x2 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_8 (0x3 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_16 (0x4 << 13)
|
||||
#define RT5631_I2S_PRE_DIV_32 (0x5 << 13)
|
||||
/* CLOCK RELATIVE OF BCLK AND LCRK */
|
||||
#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK (0x1 << 12)
|
||||
#define RT5631_I2S_LRCK_SEL_64_BCLK (0x0 << 12) /* 64FS */
|
||||
#define RT5631_I2S_LRCK_SEL_32_BCLK (0x1 << 12) /* 32FS */
|
||||
|
||||
#define RT5631_DAC_OSR_SEL_MASK (0x3 << 10)
|
||||
#define RT5631_DAC_OSR_SEL_128FS (0x3 << 10)
|
||||
#define RT5631_DAC_OSR_SEL_64FS (0x3 << 10)
|
||||
#define RT5631_DAC_OSR_SEL_32FS (0x3 << 10)
|
||||
#define RT5631_DAC_OSR_SEL_16FS (0x3 << 10)
|
||||
|
||||
#define RT5631_ADC_OSR_SEL_MASK (0x3 << 8)
|
||||
#define RT5631_ADC_OSR_SEL_128FS (0x3 << 8)
|
||||
#define RT5631_ADC_OSR_SEL_64FS (0x3 << 8)
|
||||
#define RT5631_ADC_OSR_SEL_32FS (0x3 << 8)
|
||||
#define RT5631_ADC_OSR_SEL_16FS (0x3 << 8)
|
||||
|
||||
#define RT5631_ADDA_FILTER_CLK_SEL_256FS (0 << 7) /* 256FS */
|
||||
#define RT5631_ADDA_FILTER_CLK_SEL_384FS (1 << 7) /* 384FS */
|
||||
|
||||
/* Power managment addition 1 (0x3A) */
|
||||
#define RT5631_PWR_MAIN_I2S_EN (0x1 << 15)
|
||||
#define RT5631_PWR_MAIN_I2S_BIT 15
|
||||
#define RT5631_PWR_CLASS_D (0x1 << 12)
|
||||
#define RT5631_PWR_CLASS_D_BIT 12
|
||||
#define RT5631_PWR_ADC_L_CLK (0x1 << 11)
|
||||
#define RT5631_PWR_ADC_L_CLK_BIT 11
|
||||
#define RT5631_PWR_ADC_R_CLK (0x1 << 10)
|
||||
#define RT5631_PWR_ADC_R_CLK_BIT 10
|
||||
#define RT5631_PWR_DAC_L_CLK (0x1 << 9)
|
||||
#define RT5631_PWR_DAC_L_CLK_BIT 9
|
||||
#define RT5631_PWR_DAC_R_CLK (0x1 << 8)
|
||||
#define RT5631_PWR_DAC_R_CLK_BIT 8
|
||||
#define RT5631_PWR_DAC_REF (0x1 << 7)
|
||||
#define RT5631_PWR_DAC_REF_BIT 7
|
||||
#define RT5631_PWR_DAC_L_TO_MIXER (0x1 << 6)
|
||||
#define RT5631_PWR_DAC_L_TO_MIXER_BIT 6
|
||||
#define RT5631_PWR_DAC_R_TO_MIXER (0x1 << 5)
|
||||
#define RT5631_PWR_DAC_R_TO_MIXER_BIT 5
|
||||
|
||||
/* Power managment addition 2 (0x3B) */
|
||||
#define RT5631_PWR_OUTMIXER_L (0x1 << 15)
|
||||
#define RT5631_PWR_OUTMIXER_L_BIT 15
|
||||
#define RT5631_PWR_OUTMIXER_R (0x1 << 14)
|
||||
#define RT5631_PWR_OUTMIXER_R_BIT 14
|
||||
#define RT5631_PWR_SPKMIXER_L (0x1 << 13)
|
||||
#define RT5631_PWR_SPKMIXER_L_BIT 13
|
||||
#define RT5631_PWR_SPKMIXER_R (0x1 << 12)
|
||||
#define RT5631_PWR_SPKMIXER_R_BIT 12
|
||||
#define RT5631_PWR_RECMIXER_L (0x1 << 11)
|
||||
#define RT5631_PWR_RECMIXER_L_BIT 11
|
||||
#define RT5631_PWR_RECMIXER_R (0x1 << 10)
|
||||
#define RT5631_PWR_RECMIXER_R_BIT 10
|
||||
#define RT5631_PWR_MIC1_BOOT_GAIN (0x1 << 5)
|
||||
#define RT5631_PWR_MIC1_BOOT_GAIN_BIT 5
|
||||
#define RT5631_PWR_MIC2_BOOT_GAIN (0x1 << 4)
|
||||
#define RT5631_PWR_MIC2_BOOT_GAIN_BIT 4
|
||||
#define RT5631_PWR_MICBIAS1_VOL (0x1 << 3)
|
||||
#define RT5631_PWR_MICBIAS1_VOL_BIT 3
|
||||
#define RT5631_PWR_MICBIAS2_VOL (0x1 << 2)
|
||||
#define RT5631_PWR_MICBIAS2_VOL_BIT 2
|
||||
#define RT5631_PWR_PLL1 (0x1 << 1)
|
||||
#define RT5631_PWR_PLL1_BIT 1
|
||||
#define RT5631_PWR_PLL2 (0x1 << 0)
|
||||
#define RT5631_PWR_PLL2_BIT 0
|
||||
|
||||
/* Power managment addition 3(0x3C) */
|
||||
#define RT5631_PWR_VREF (0x1 << 15)
|
||||
#define RT5631_PWR_VREF_BIT 15
|
||||
#define RT5631_PWR_FAST_VREF_CTRL (0x1 << 14)
|
||||
#define RT5631_PWR_FAST_VREF_CTRL_BIT 14
|
||||
#define RT5631_PWR_MAIN_BIAS (0x1 << 13)
|
||||
#define RT5631_PWR_MAIN_BIAS_BIT 13
|
||||
#define RT5631_PWR_AXO1MIXER (0x1 << 11)
|
||||
#define RT5631_PWR_AXO1MIXER_BIT 11
|
||||
#define RT5631_PWR_AXO2MIXER (0x1 << 10)
|
||||
#define RT5631_PWR_AXO2MIXER_BIT 10
|
||||
#define RT5631_PWR_MONOMIXER (0x1 << 9)
|
||||
#define RT5631_PWR_MONOMIXER_BIT 9
|
||||
#define RT5631_PWR_MONO_DEPOP_DIS (0x1 << 8)
|
||||
#define RT5631_PWR_MONO_DEPOP_DIS_BIT 8
|
||||
#define RT5631_PWR_MONO_AMP_EN (0x1 << 7)
|
||||
#define RT5631_PWR_MONO_AMP_EN_BIT 7
|
||||
#define RT5631_PWR_CHARGE_PUMP (0x1 << 4)
|
||||
#define RT5631_PWR_CHARGE_PUMP_BIT 4
|
||||
#define RT5631_PWR_HP_L_AMP (0x1 << 3)
|
||||
#define RT5631_PWR_HP_L_AMP_BIT 3
|
||||
#define RT5631_PWR_HP_R_AMP (0x1 << 2)
|
||||
#define RT5631_PWR_HP_R_AMP_BIT 2
|
||||
#define RT5631_PWR_HP_DEPOP_DIS (0x1 << 1)
|
||||
#define RT5631_PWR_HP_DEPOP_DIS_BIT 1
|
||||
#define RT5631_PWR_HP_AMP_DRIVING (0x1 << 0)
|
||||
#define RT5631_PWR_HP_AMP_DRIVING_BIT 0
|
||||
|
||||
/* Power managment addition 4(0x3E) */
|
||||
#define RT5631_PWR_SPK_L_VOL (0x1 << 15)
|
||||
#define RT5631_PWR_SPK_L_VOL_BIT 15
|
||||
#define RT5631_PWR_SPK_R_VOL (0x1 << 14)
|
||||
#define RT5631_PWR_SPK_R_VOL_BIT 14
|
||||
#define RT5631_PWR_LOUT_VOL (0x1 << 13)
|
||||
#define RT5631_PWR_LOUT_VOL_BIT 13
|
||||
#define RT5631_PWR_ROUT_VOL (0x1 << 12)
|
||||
#define RT5631_PWR_ROUT_VOL_BIT 12
|
||||
#define RT5631_PWR_HP_L_OUT_VOL (0x1 << 11)
|
||||
#define RT5631_PWR_HP_L_OUT_VOL_BIT 11
|
||||
#define RT5631_PWR_HP_R_OUT_VOL (0x1 << 10)
|
||||
#define RT5631_PWR_HP_R_OUT_VOL_BIT 10
|
||||
#define RT5631_PWR_AXIL_IN_VOL (0x1 << 9)
|
||||
#define RT5631_PWR_AXIL_IN_VOL_BIT 9
|
||||
#define RT5631_PWR_AXIR_IN_VOL (0x1 << 8)
|
||||
#define RT5631_PWR_AXIR_IN_VOL_BIT 8
|
||||
#define RT5631_PWR_MONO_IN_P_VOL (0x1 << 7)
|
||||
#define RT5631_PWR_MONO_IN_P_VOL_BIT 7
|
||||
#define RT5631_PWR_MONO_IN_N_VOL (0x1 << 6)
|
||||
#define RT5631_PWR_MONO_IN_N_VOL_BIT 6
|
||||
|
||||
/* General Purpose Control Register(0x40) */
|
||||
#define RT5631_SPK_AMP_AUTO_RATIO_EN (0x1 << 15)
|
||||
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_MASK (0x7 << 12)
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_2_34 (0x0 << 12) /* 7.40DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_99 (0x1 << 12) /* 5.99DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_68 (0x2 << 12) /* 4.50DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_56 (0x3 << 12) /* 3.86DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_44 (0x4 << 12) /* 3.16DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_27 (0x5 << 12) /* 2.10DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_09 (0x6 << 12) /* 0.80DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_1_00 (0x7 << 12) /* 0.00DB */
|
||||
#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT 12
|
||||
|
||||
#define RT5631_STEREO_DAC_HI_PASS_FILT_EN (0x1 << 11)
|
||||
#define RT5631_STEREO_ADC_HI_PASS_FILT_EN (0x1 << 10)
|
||||
/* Select ADC Wind Filter Clock type */
|
||||
#define RT5631_ADC_WIND_FILT_MASK (0x3 << 4)
|
||||
#define RT5631_ADC_WIND_FILT_8_16_32K (0x0 << 4) /*8/16/32k*/
|
||||
#define RT5631_ADC_WIND_FILT_11_22_44K (0x1 << 4) /*11/22/44k*/
|
||||
#define RT5631_ADC_WIND_FILT_12_24_48K (0x2 << 4) /*12/24/48k*/
|
||||
#define RT5631_ADC_WIND_FILT_EN (0x1 << 3)
|
||||
/* SelectADC Wind Filter Corner Frequency */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_MASK (0x7 << 0)
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_82_113_122 (0x0 << 0) /* 82/113/122 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */
|
||||
#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */
|
||||
|
||||
/* Global Clock Control Register(0x42) */
|
||||
#define RT5631_SYSCLK_SOUR_SEL_MASK (0x3 << 14)
|
||||
#define RT5631_SYSCLK_SOUR_SEL_MCLK (0x0 << 14)
|
||||
#define RT5631_SYSCLK_SOUR_SEL_PLL (0x1 << 14)
|
||||
#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK (0x2 << 14)
|
||||
|
||||
#define RT5631_PLLCLK_SOUR_SEL_MASK (0x3 << 12)
|
||||
#define RT5631_PLLCLK_SOUR_SEL_MCLK (0x0 << 12)
|
||||
#define RT5631_PLLCLK_SOUR_SEL_BCLK (0x1 << 12)
|
||||
#define RT5631_PLLCLK_SOUR_SEL_VBCLK (0x2 << 12)
|
||||
|
||||
#define RT5631_PLLCLK_PRE_DIV1 (0x0 << 11)
|
||||
#define RT5631_PLLCLK_PRE_DIV2 (0x1 << 11)
|
||||
|
||||
/* PLL Control(0x44) */
|
||||
#define RT5631_PLL_CTRL_M_VAL(m) ((m)&0xf)
|
||||
#define RT5631_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4)
|
||||
#define RT5631_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8)
|
||||
|
||||
/* Internal Status and IRQ Control2(0x4A) */
|
||||
#define RT5631_ADC_DATA_SEL_MASK (0x3 << 14)
|
||||
#define RT5631_ADC_DATA_SEL_Disable (0x0 << 14)
|
||||
#define RT5631_ADC_DATA_SEL_MIC1 (0x1 << 14)
|
||||
#define RT5631_ADC_DATA_SEL_MIC1_SHIFT 14
|
||||
#define RT5631_ADC_DATA_SEL_MIC2 (0x2 << 14)
|
||||
#define RT5631_ADC_DATA_SEL_MIC2_SHIFT 15
|
||||
#define RT5631_ADC_DATA_SEL_STO (0x3 << 14)
|
||||
#define RT5631_ADC_DATA_SEL_SHIFT 14
|
||||
|
||||
/* GPIO Pin Configuration(0x4C) */
|
||||
#define RT5631_GPIO_PIN_FUN_SEL_MASK (0x1 << 15)
|
||||
#define RT5631_GPIO_PIN_FUN_SEL_IRQ (0x1 << 15)
|
||||
#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0 << 15)
|
||||
|
||||
#define RT5631_GPIO_DMIC_FUN_SEL_MASK (0x1 << 3)
|
||||
#define RT5631_GPIO_DMIC_FUN_SEL_DIMC (0x1 << 3)
|
||||
#define RT5631_GPIO_DMIC_FUN_SEL_GPIO (0x0 << 3)
|
||||
|
||||
#define RT5631_GPIO_PIN_CON_MASK (0x1 << 2)
|
||||
#define RT5631_GPIO_PIN_SET_INPUT (0x0 << 2)
|
||||
#define RT5631_GPIO_PIN_SET_OUTPUT (0x1 << 2)
|
||||
|
||||
/* De-POP function Control 1(0x54) */
|
||||
#define RT5631_POW_ON_SOFT_GEN (0x1 << 15)
|
||||
#define RT5631_EN_MUTE_UNMUTE_DEPOP (0x1 << 14)
|
||||
#define RT5631_EN_DEPOP2_FOR_HP (0x1 << 7)
|
||||
/* Power Down HPAMP_L Starts Up Signal */
|
||||
#define RT5631_PD_HPAMP_L_ST_UP (0x1 << 5)
|
||||
/* Power Down HPAMP_R Starts Up Signal */
|
||||
#define RT5631_PD_HPAMP_R_ST_UP (0x1 << 4)
|
||||
/* Enable left HP mute/unmute depop */
|
||||
#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP (0x1 << 1)
|
||||
/* Enable right HP mute/unmute depop */
|
||||
#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP (0x1 << 0)
|
||||
|
||||
/* De-POP Fnction Control(0x56) */
|
||||
#define RT5631_EN_ONE_BIT_DEPOP (0x1 << 15)
|
||||
#define RT5631_EN_CAP_FREE_DEPOP (0x1 << 14)
|
||||
|
||||
/* Jack Detect Control Register(0x5A) */
|
||||
#define RT5631_JD_USE_MASK (0x3 << 14)
|
||||
#define RT5631_JD_USE_JD2 (0x3 << 14)
|
||||
#define RT5631_JD_USE_JD1 (0x2 << 14)
|
||||
#define RT5631_JD_USE_GPIO (0x1 << 14)
|
||||
#define RT5631_JD_OFF (0x0 << 14)
|
||||
/* JD trigger enable for HP */
|
||||
#define RT5631_JD_HP_EN (0x1 << 11)
|
||||
#define RT5631_JD_HP_TRI_MASK (0x1 << 10)
|
||||
#define RT5631_JD_HP_TRI_HI (0x1 << 10)
|
||||
#define RT5631_JD_HP_TRI_LO (0x1 << 10)
|
||||
/* JD trigger enable for speaker LP/LN */
|
||||
#define RT5631_JD_SPK_L_EN (0x1 << 9)
|
||||
#define RT5631_JD_SPK_L_TRI_MASK (0x1 << 8)
|
||||
#define RT5631_JD_SPK_L_TRI_HI (0x1 << 8)
|
||||
#define RT5631_JD_SPK_L_TRI_LO (0x0 << 8)
|
||||
/* JD trigger enable for speaker RP/RN */
|
||||
#define RT5631_JD_SPK_R_EN (0x1 << 7)
|
||||
#define RT5631_JD_SPK_R_TRI_MASK (0x1 << 6)
|
||||
#define RT5631_JD_SPK_R_TRI_HI (0x1 << 6)
|
||||
#define RT5631_JD_SPK_R_TRI_LO (0x0 << 6)
|
||||
/* JD trigger enable for monoout */
|
||||
#define RT5631_JD_MONO_EN (0x1 << 5)
|
||||
#define RT5631_JD_MONO_TRI_MASK (0x1 << 4)
|
||||
#define RT5631_JD_MONO_TRI_HI (0x1 << 4)
|
||||
#define RT5631_JD_MONO_TRI_LO (0x0 << 4)
|
||||
/* JD trigger enable for Lout */
|
||||
#define RT5631_JD_AUX_1_EN (0x1 << 3)
|
||||
#define RT5631_JD_AUX_1_MASK (0x1 << 2)
|
||||
#define RT5631_JD_AUX_1_TRI_HI (0x1 << 2)
|
||||
#define RT5631_JD_AUX_1_TRI_LO (0x0 << 2)
|
||||
/* JD trigger enable for Rout */
|
||||
#define RT5631_JD_AUX_2_EN (0x1 << 1)
|
||||
#define RT5631_JD_AUX_2_MASK (0x1 << 0)
|
||||
#define RT5631_JD_AUX_2_TRI_HI (0x1 << 0)
|
||||
#define RT5631_JD_AUX_2_TRI_LO (0x0 << 0)
|
||||
|
||||
/* ALC CONTROL 1(0x64) */
|
||||
#define RT5631_ALC_ATTACK_RATE_MASK (0x1F << 8)
|
||||
#define RT5631_ALC_RECOVERY_RATE_MASK (0x1F << 0)
|
||||
|
||||
/* ALC CONTROL 2(0x65) */
|
||||
/* select Compensation gain for Noise gate function */
|
||||
#define RT5631_ALC_COM_NOISE_GATE_MASK (0xF << 0)
|
||||
|
||||
/* ALC CONTROL 3(0x66) */
|
||||
#define RT5631_ALC_FUN_MASK (0x3 << 14)
|
||||
#define RT5631_ALC_FUN_DIS (0x0 << 14)
|
||||
#define RT5631_ALC_ENA_DAC_PATH (0x1 << 14)
|
||||
#define RT5631_ALC_ENA_ADC_PATH (0x3 << 14)
|
||||
#define RT5631_ALC_PARA_UPDATE (0x1 << 13)
|
||||
#define RT5631_ALC_LIMIT_LEVEL_MASK (0x1F << 8)
|
||||
#define RT5631_ALC_NOISE_GATE_FUN_MASK (0x1 << 7)
|
||||
#define RT5631_ALC_NOISE_GATE_FUN_DIS (0x0 << 7)
|
||||
#define RT5631_ALC_NOISE_GATE_FUN_ENA (0x1 << 7)
|
||||
/* ALC noise gate hold data function */
|
||||
#define RT5631_ALC_NOISE_GATE_H_D_MASK (0x1 << 6)
|
||||
#define RT5631_ALC_NOISE_GATE_H_D_DIS (0x0 << 6)
|
||||
#define RT5631_ALC_NOISE_GATE_H_D_ENA (0x1 << 6)
|
||||
|
||||
/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
|
||||
#define RT5631_SPATIAL_CTRL_EN (0x1 << 15)
|
||||
#define RT5631_ALL_PASS_FILTER_EN (0x1 << 14)
|
||||
#define RT5631_PSEUDO_STEREO_EN (0x1 << 13)
|
||||
#define RT5631_STEREO_EXPENSION_EN (0x1 << 12)
|
||||
/* 3D gain parameter */
|
||||
#define RT5631_GAIN_3D_PARA_MASK (0x3 << 6)
|
||||
#define RT5631_GAIN_3D_PARA_1_00 (0x0 << 6) /* 3D gain 1.0 */
|
||||
#define RT5631_GAIN_3D_PARA_1_50 (0x1 << 6) /* 3D gain 1.5 */
|
||||
#define RT5631_GAIN_3D_PARA_2_00 (0x2 << 6) /* 3D gain 2.0 */
|
||||
/* 3D ratio parameter */
|
||||
#define RT5631_RATIO_3D_MASK (0x3 << 4)
|
||||
#define RT5631_RATIO_3D_0_0 (0x0 << 4) /* 3D ratio 0.0 */
|
||||
#define RT5631_RATIO_3D_0_66 (0x1 << 4) /* 3D ratio 0.66 */
|
||||
#define RT5631_RATIO_3D_1_0 (0x2 << 4) /* 3D ratio 1.0 */
|
||||
/* select samplerate for all pass filter */
|
||||
#define RT5631_APF_FUN_SLE_MASK (0x3 << 0)
|
||||
#define RT5631_APF_FUN_SEL_48K (0x3 << 0)
|
||||
#define RT5631_APF_FUN_SEL_44_1K (0x2 << 0)
|
||||
#define RT5631_APF_FUN_SEL_32K (0x1 << 0)
|
||||
#define RT5631_APF_FUN_DIS (0x0 << 0)
|
||||
|
||||
/* EQ CONTROL 1(0x6E) */
|
||||
#define RT5631_HW_EQ_PATH_SEL_MASK (0x1 << 15)
|
||||
#define RT5631_HW_EQ_PATH_SEL_DAC (0x0 << 15)
|
||||
#define RT5631_HW_EQ_PATH_SEL_ADC (0x1 << 15)
|
||||
#define RT5631_HW_EQ_UPDATE_CTRL (0x1 << 14)
|
||||
|
||||
#define RT5631_EN_HW_EQ_HPF2 (0x1 << 5)
|
||||
#define RT5631_EN_HW_EQ_HPF1 (0x1 << 4)
|
||||
#define RT5631_EN_HW_EQ_BP3 (0x1 << 3)
|
||||
#define RT5631_EN_HW_EQ_BP2 (0x1 << 2)
|
||||
#define RT5631_EN_HW_EQ_BP1 (0x1 << 1)
|
||||
#define RT5631_EN_HW_EQ_LPF (0x1 << 0)
|
||||
|
||||
|
||||
#endif /* __RTCODEC5631_H__ */
|
@ -131,16 +131,13 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
/* change mic bias resistor to 4Kohm */
|
||||
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
|
||||
SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
|
||||
SGTL5000_BIAS_R_MASK,
|
||||
SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
/*
|
||||
* SGTL5000_BIAS_R_8k as mask to clean the two bits
|
||||
* of mic bias and output impedance
|
||||
*/
|
||||
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
|
||||
SGTL5000_BIAS_R_8k, 0);
|
||||
SGTL5000_BIAS_R_MASK, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -726,7 +723,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL,
|
||||
SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
|
||||
i2s_ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -757,7 +756,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev)
|
||||
|
||||
/* set voltage to register */
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
|
||||
(0x1 << 4) - 1, reg);
|
||||
SGTL5000_LINREG_VDDD_MASK, reg);
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_LINEREG_D_POWERUP,
|
||||
@ -783,7 +782,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev)
|
||||
|
||||
/* clear voltage info */
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
|
||||
(0x1 << 4) - 1, 0);
|
||||
SGTL5000_LINREG_VDDD_MASK, 0);
|
||||
|
||||
ldo->enabled = 0;
|
||||
|
||||
@ -809,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
|
||||
int voltage)
|
||||
{
|
||||
struct ldo_regulator *ldo;
|
||||
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
|
||||
|
||||
@ -843,6 +843,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
|
||||
|
||||
return ret;
|
||||
}
|
||||
sgtl5000->ldo = ldo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1116,7 +1117,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
|
||||
|
||||
/* set voltage to register */
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
|
||||
(0x1 << 4) - 1, 0x8);
|
||||
SGTL5000_LINREG_VDDD_MASK, 0x8);
|
||||
|
||||
/*
|
||||
* if vddd linear reg has been enabled,
|
||||
@ -1147,8 +1148,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
|
||||
vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
|
||||
vag << SGTL5000_ANA_GND_SHIFT,
|
||||
vag << SGTL5000_ANA_GND_SHIFT);
|
||||
SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
|
||||
|
||||
/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
|
||||
vag = vddio / 2;
|
||||
@ -1162,9 +1162,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
|
||||
SGTL5000_LINE_OUT_GND_STP;
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
|
||||
vag << SGTL5000_LINE_OUT_GND_SHIFT |
|
||||
SGTL5000_LINE_OUT_CURRENT_360u <<
|
||||
SGTL5000_LINE_OUT_CURRENT_SHIFT,
|
||||
SGTL5000_LINE_OUT_CURRENT_MASK |
|
||||
SGTL5000_LINE_OUT_GND_MASK,
|
||||
vag << SGTL5000_LINE_OUT_GND_SHIFT |
|
||||
SGTL5000_LINE_OUT_CURRENT_360u <<
|
||||
SGTL5000_LINE_OUT_CURRENT_SHIFT);
|
||||
|
@ -280,7 +280,7 @@
|
||||
/*
|
||||
* SGTL5000_CHIP_MIC_CTRL
|
||||
*/
|
||||
#define SGTL5000_BIAS_R_MASK 0x0200
|
||||
#define SGTL5000_BIAS_R_MASK 0x0300
|
||||
#define SGTL5000_BIAS_R_SHIFT 8
|
||||
#define SGTL5000_BIAS_R_WIDTH 2
|
||||
#define SGTL5000_BIAS_R_off 0x0
|
||||
|
@ -102,7 +102,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
|
||||
{
|
||||
int base_addr, chnl_addr;
|
||||
int value;
|
||||
static int channel_index;
|
||||
int channel_index;
|
||||
|
||||
/* Index of the first channel in which the stop bit is set */
|
||||
channel_index = find_free_channel(sn95031_codec);
|
||||
@ -161,7 +161,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
|
||||
pr_debug("mic bias = %dmV\n", mic_bias);
|
||||
return mic_bias;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
|
||||
/*end - adc helper functions */
|
||||
|
||||
static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
|
||||
@ -716,7 +715,7 @@ static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
|
||||
.hw_params = sn95031_pcm_hw_params,
|
||||
};
|
||||
|
||||
struct snd_soc_dai_driver sn95031_dais[] = {
|
||||
static struct snd_soc_dai_driver sn95031_dais[] = {
|
||||
{
|
||||
.name = "SN95031 Headset",
|
||||
.playback = {
|
||||
@ -827,7 +826,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
pr_debug("codec_probe called\n");
|
||||
|
||||
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
|
||||
/* PCM interface config
|
||||
|
@ -59,6 +59,7 @@ struct ssm2602_priv {
|
||||
struct snd_pcm_substream *slave_substream;
|
||||
|
||||
enum ssm2602_type type;
|
||||
unsigned int clk_out_pwr;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -342,12 +343,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
|
||||
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
|
||||
|
||||
if (mute)
|
||||
snd_soc_write(codec, SSM2602_APDIGI,
|
||||
mute_reg | APDIGI_ENABLE_DAC_MUTE);
|
||||
snd_soc_update_bits(codec, SSM2602_APDIGI,
|
||||
APDIGI_ENABLE_DAC_MUTE,
|
||||
APDIGI_ENABLE_DAC_MUTE);
|
||||
else
|
||||
snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
|
||||
snd_soc_update_bits(codec, SSM2602_APDIGI,
|
||||
APDIGI_ENABLE_DAC_MUTE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -356,6 +359,11 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN) {
|
||||
if (clk_id != SSM2602_SYSCLK)
|
||||
return -EINVAL;
|
||||
|
||||
switch (freq) {
|
||||
case 11289600:
|
||||
case 12000000:
|
||||
@ -363,10 +371,35 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
case 16934400:
|
||||
case 18432000:
|
||||
ssm2602->sysclk = freq;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
unsigned int mask;
|
||||
|
||||
switch (clk_id) {
|
||||
case SSM2602_CLK_CLKOUT:
|
||||
mask = PWR_CLK_OUT_PDN;
|
||||
break;
|
||||
case SSM2602_CLK_XTO:
|
||||
mask = PWR_OSC_PDN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (freq == 0)
|
||||
ssm2602->clk_out_pwr |= mask;
|
||||
else
|
||||
ssm2602->clk_out_pwr &= ~mask;
|
||||
|
||||
snd_soc_update_bits(codec, SSM2602_PWR,
|
||||
PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
@ -430,23 +463,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 reg = snd_soc_read(codec, SSM2602_PWR);
|
||||
reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
/* vref/mid, osc on, dac unmute */
|
||||
snd_soc_write(codec, SSM2602_PWR, reg);
|
||||
/* vref/mid on, osc and clkout on if enabled */
|
||||
snd_soc_update_bits(codec, SSM2602_PWR,
|
||||
PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
|
||||
ssm2602->clk_out_pwr);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* everything off except vref/vmid, */
|
||||
snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
|
||||
snd_soc_update_bits(codec, SSM2602_PWR,
|
||||
PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
|
||||
PWR_CLK_OUT_PDN | PWR_OSC_PDN);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* everything off, dac mute, inactive */
|
||||
snd_soc_write(codec, SSM2602_PWR, 0xffff);
|
||||
/* everything off */
|
||||
snd_soc_update_bits(codec, SSM2602_PWR,
|
||||
PWR_POWER_OFF, PWR_POWER_OFF);
|
||||
break;
|
||||
|
||||
}
|
||||
@ -505,12 +542,12 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
|
||||
static int ssm2602_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret, reg;
|
||||
int ret;
|
||||
|
||||
reg = snd_soc_read(codec, SSM2602_LOUT1V);
|
||||
snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
|
||||
reg = snd_soc_read(codec, SSM2602_ROUT1V);
|
||||
snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
|
||||
snd_soc_update_bits(codec, SSM2602_LOUT1V,
|
||||
LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
|
||||
snd_soc_update_bits(codec, SSM2602_ROUT1V,
|
||||
ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
|
||||
|
||||
ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
|
||||
ARRAY_SIZE(ssm2602_snd_controls));
|
||||
@ -543,7 +580,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
|
||||
static int ssm260x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, reg;
|
||||
int ret;
|
||||
|
||||
pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
|
||||
|
||||
@ -560,10 +597,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* set the update bits */
|
||||
reg = snd_soc_read(codec, SSM2602_LINVOL);
|
||||
snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
|
||||
reg = snd_soc_read(codec, SSM2602_RINVOL);
|
||||
snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
|
||||
snd_soc_update_bits(codec, SSM2602_LINVOL,
|
||||
LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
|
||||
snd_soc_update_bits(codec, SSM2602_RINVOL,
|
||||
RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
|
||||
/*select Line in as default input*/
|
||||
snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
|
||||
APANA_ENABLE_MIC_BOOST);
|
||||
@ -577,7 +614,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remove everything here */
|
||||
|
@ -116,6 +116,10 @@
|
||||
|
||||
#define SSM2602_CACHEREGNUM 10
|
||||
|
||||
#define SSM2602_SYSCLK 0
|
||||
enum ssm2602_clk {
|
||||
SSM2602_SYSCLK,
|
||||
SSM2602_CLK_CLKOUT,
|
||||
SSM2602_CLK_XTO
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -756,25 +756,19 @@ static int sta32x_probe(struct snd_soc_codec *codec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read reg reset values into cache */
|
||||
for (i = 0; i < STA32X_REGISTER_COUNT; i++)
|
||||
snd_soc_cache_write(codec, i, sta32x_regs[i]);
|
||||
|
||||
/* preserve reset values of reserved register bits */
|
||||
snd_soc_cache_write(codec, STA32X_CONFC,
|
||||
codec->hw_read(codec, STA32X_CONFC));
|
||||
snd_soc_cache_write(codec, STA32X_CONFE,
|
||||
codec->hw_read(codec, STA32X_CONFE));
|
||||
snd_soc_cache_write(codec, STA32X_CONFF,
|
||||
codec->hw_read(codec, STA32X_CONFF));
|
||||
snd_soc_cache_write(codec, STA32X_MMUTE,
|
||||
codec->hw_read(codec, STA32X_MMUTE));
|
||||
snd_soc_cache_write(codec, STA32X_AUTO1,
|
||||
codec->hw_read(codec, STA32X_AUTO1));
|
||||
snd_soc_cache_write(codec, STA32X_AUTO3,
|
||||
codec->hw_read(codec, STA32X_AUTO3));
|
||||
snd_soc_cache_write(codec, STA32X_C3CFG,
|
||||
codec->hw_read(codec, STA32X_C3CFG));
|
||||
/* Chip documentation explicitly requires that the reset values
|
||||
* of reserved register bits are left untouched.
|
||||
* 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, STA32X_CONFC, 0xc2);
|
||||
snd_soc_cache_write(codec, STA32X_CONFE, 0xc2);
|
||||
snd_soc_cache_write(codec, STA32X_CONFF, 0x5c);
|
||||
snd_soc_cache_write(codec, STA32X_MMUTE, 0x10);
|
||||
snd_soc_cache_write(codec, STA32X_AUTO1, 0x60);
|
||||
snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
|
||||
snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
|
||||
|
||||
/* FIXME enable thermal warning adjustment and recovery */
|
||||
snd_soc_update_bits(codec, STA32X_CONFA,
|
||||
@ -837,6 +831,7 @@ static const struct snd_soc_codec_driver sta32x_codec = {
|
||||
.resume = sta32x_resume,
|
||||
.reg_cache_size = STA32X_REGISTER_COUNT,
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = sta32x_regs,
|
||||
.volatile_register = sta32x_reg_is_volatile,
|
||||
.set_bias_level = sta32x_set_bias_level,
|
||||
.controls = sta32x_snd_controls,
|
||||
|
@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
|
||||
};
|
||||
|
||||
/*
|
||||
* read tlv320aic23 register cache
|
||||
*/
|
||||
static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
|
||||
*codec, unsigned int reg)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= ARRAY_SIZE(tlv320aic23_reg))
|
||||
return -1;
|
||||
return cache[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* write tlv320aic23 register cache
|
||||
*/
|
||||
static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
|
||||
u8 reg, u16 value)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
if (reg >= ARRAY_SIZE(tlv320aic23_reg))
|
||||
return;
|
||||
cache[reg] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* write to the tlv320aic23 register space
|
||||
*/
|
||||
static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
|
||||
u8 data[2];
|
||||
|
||||
/* TLV320AIC23 has 7 bit address and 9 bits of data
|
||||
* so we need to switch one data bit into reg and rest
|
||||
* of data into val
|
||||
*/
|
||||
|
||||
if (reg > 9 && reg != 15) {
|
||||
printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (reg << 1) | (value >> 8 & 0x01);
|
||||
data[1] = value & 0xff;
|
||||
|
||||
tlv320aic23_write_reg_cache(codec, reg, value);
|
||||
|
||||
if (codec->hw_write(codec->control_data, data, 2) == 2)
|
||||
return 0;
|
||||
|
||||
printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
|
||||
value, reg);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const char *rec_src_text[] = { "Line", "Mic" };
|
||||
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
|
||||
|
||||
@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
*/
|
||||
val = (val >= 4) ? 4 : (3 - val);
|
||||
|
||||
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
|
||||
tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
|
||||
reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0);
|
||||
snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
u16 val;
|
||||
|
||||
val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
|
||||
val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
|
||||
val = val >> 6;
|
||||
val = (val >= 4) ? 4 : (3 - val);
|
||||
ucontrol->value.integer.value[0] = val;
|
||||
@ -159,15 +102,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
|
||||
}
|
||||
|
||||
#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
|
||||
.put = snd_soc_tlv320aic23_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
|
||||
static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
|
||||
TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
|
||||
@ -178,8 +112,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
|
||||
TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
|
||||
SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
|
||||
SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
|
||||
SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
|
||||
6, 4, 0, sidetone_vol_tlv),
|
||||
SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0,
|
||||
snd_soc_tlv320aic23_get_volsw,
|
||||
snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv),
|
||||
SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
|
||||
};
|
||||
|
||||
@ -240,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
|
||||
/* AIC23 driver data */
|
||||
struct aic23 {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
int mclk;
|
||||
int requested_adc;
|
||||
int requested_dac;
|
||||
@ -352,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac)
|
||||
static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
|
||||
u32 *sample_rate_adc, u32 *sample_rate_dac)
|
||||
{
|
||||
int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
|
||||
int src = snd_soc_read(codec, TLV320AIC23_SRATE);
|
||||
int sr = (src >> 2) & 0x0f;
|
||||
int val = (mclk / bosr_usb_divisor_table[src & 3]);
|
||||
int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
|
||||
@ -376,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
|
||||
__func__, sample_rate_adc, sample_rate_dac);
|
||||
return -EINVAL;
|
||||
}
|
||||
tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
|
||||
snd_soc_write(codec, TLV320AIC23_SRATE, data);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
u32 adc, dac;
|
||||
@ -415,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
iface_reg =
|
||||
tlv320aic23_read_reg_cache(codec,
|
||||
TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
|
||||
iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
break;
|
||||
@ -431,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
|
||||
iface_reg |= (0x03 << 2);
|
||||
break;
|
||||
}
|
||||
tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
|
||||
snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -443,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
|
||||
/* set active */
|
||||
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -458,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
|
||||
/* deactivate */
|
||||
if (!codec->active) {
|
||||
udelay(50);
|
||||
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
|
||||
}
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
aic23->requested_dac = 0;
|
||||
@ -471,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 reg;
|
||||
|
||||
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
|
||||
reg = snd_soc_read(codec, TLV320AIC23_DIGT);
|
||||
if (mute)
|
||||
reg |= TLV320AIC23_DACM_MUTE;
|
||||
|
||||
else
|
||||
reg &= ~TLV320AIC23_DACM_MUTE;
|
||||
|
||||
tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
|
||||
snd_soc_write(codec, TLV320AIC23_DIGT, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -489,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
u16 iface_reg;
|
||||
|
||||
iface_reg =
|
||||
tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
|
||||
iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
|
||||
|
||||
/* set master/slave audio interface */
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
@ -524,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
|
||||
}
|
||||
|
||||
tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
|
||||
snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -540,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
|
||||
u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
/* vref/mid, osc on, dac unmute */
|
||||
reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
|
||||
TLV320AIC23_DAC_OFF);
|
||||
tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
|
||||
snd_soc_write(codec, TLV320AIC23_PWR, reg);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* everything off except vref/vmid, */
|
||||
tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
|
||||
TLV320AIC23_CLK_OFF);
|
||||
snd_soc_write(codec, TLV320AIC23_PWR,
|
||||
reg | TLV320AIC23_CLK_OFF);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* everything off, dac mute, inactive */
|
||||
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
|
||||
tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
|
||||
snd_soc_write(codec, TLV320AIC23_PWR, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
@ -606,13 +538,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec,
|
||||
|
||||
static int tlv320aic23_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
u16 reg;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) {
|
||||
u16 val = tlv320aic23_read_reg_cache(codec, reg);
|
||||
tlv320aic23_write(codec, reg, val);
|
||||
}
|
||||
snd_soc_cache_sync(codec);
|
||||
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
@ -621,46 +547,52 @@ 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 reg;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
|
||||
codec->control_data = aic23->control_data;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
codec->hw_read = NULL;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset codec */
|
||||
tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
|
||||
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);
|
||||
|
||||
tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
|
||||
snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
|
||||
|
||||
/* Unmute input */
|
||||
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
|
||||
tlv320aic23_write(codec, TLV320AIC23_LINVOL,
|
||||
(reg & (~TLV320AIC23_LIM_MUTED)) |
|
||||
(TLV320AIC23_LRS_ENABLED));
|
||||
snd_soc_update_bits(codec, TLV320AIC23_LINVOL,
|
||||
TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
|
||||
|
||||
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
|
||||
tlv320aic23_write(codec, TLV320AIC23_RINVOL,
|
||||
(reg & (~TLV320AIC23_LIM_MUTED)) |
|
||||
TLV320AIC23_LRS_ENABLED);
|
||||
snd_soc_update_bits(codec, TLV320AIC23_RINVOL,
|
||||
TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
|
||||
|
||||
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
|
||||
tlv320aic23_write(codec, TLV320AIC23_ANLG,
|
||||
(reg) & (~TLV320AIC23_BYPASS_ON) &
|
||||
(~TLV320AIC23_MICM_MUTED));
|
||||
snd_soc_update_bits(codec, TLV320AIC23_ANLG,
|
||||
TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
|
||||
0);
|
||||
|
||||
/* Default output volume */
|
||||
tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
|
||||
TLV320AIC23_DEFAULT_OUT_VOL &
|
||||
TLV320AIC23_OUT_VOL_MASK);
|
||||
tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
|
||||
TLV320AIC23_DEFAULT_OUT_VOL &
|
||||
TLV320AIC23_OUT_VOL_MASK);
|
||||
snd_soc_write(codec, TLV320AIC23_LCHNVOL,
|
||||
TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
|
||||
snd_soc_write(codec, TLV320AIC23_RCHNVOL,
|
||||
TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
|
||||
|
||||
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
|
||||
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
|
||||
|
||||
snd_soc_add_controls(codec, tlv320aic23_snd_controls,
|
||||
ARRAY_SIZE(tlv320aic23_snd_controls));
|
||||
@ -682,8 +614,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
|
||||
.remove = tlv320aic23_remove,
|
||||
.suspend = tlv320aic23_suspend,
|
||||
.resume = tlv320aic23_resume,
|
||||
.read = tlv320aic23_read_reg_cache,
|
||||
.write = tlv320aic23_write,
|
||||
.set_bias_level = tlv320aic23_set_bias_level,
|
||||
.dapm_widgets = tlv320aic23_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
|
||||
@ -710,7 +640,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, aic23);
|
||||
aic23->control_data = i2c;
|
||||
aic23->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -528,40 +528,33 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 value;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
if (aic32x4->master) {
|
||||
/* Switch on PLL */
|
||||
value = snd_soc_read(codec, AIC32X4_PLLPR);
|
||||
snd_soc_write(codec, AIC32X4_PLLPR,
|
||||
(value | AIC32X4_PLLEN));
|
||||
snd_soc_update_bits(codec, AIC32X4_PLLPR,
|
||||
AIC32X4_PLLEN, AIC32X4_PLLEN);
|
||||
|
||||
/* Switch on NDAC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_NDAC);
|
||||
snd_soc_write(codec, AIC32X4_NDAC,
|
||||
value | AIC32X4_NDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_NDAC,
|
||||
AIC32X4_NDACEN, AIC32X4_NDACEN);
|
||||
|
||||
/* Switch on MDAC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_MDAC);
|
||||
snd_soc_write(codec, AIC32X4_MDAC,
|
||||
value | AIC32X4_MDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_MDAC,
|
||||
AIC32X4_MDACEN, AIC32X4_MDACEN);
|
||||
|
||||
/* Switch on NADC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_NADC);
|
||||
snd_soc_write(codec, AIC32X4_NADC,
|
||||
value | AIC32X4_MDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_NADC,
|
||||
AIC32X4_NADCEN, AIC32X4_NADCEN);
|
||||
|
||||
/* Switch on MADC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_MADC);
|
||||
snd_soc_write(codec, AIC32X4_MADC,
|
||||
value | AIC32X4_MDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_MADC,
|
||||
AIC32X4_MADCEN, AIC32X4_MADCEN);
|
||||
|
||||
/* Switch on BCLK_N Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_BCLKN);
|
||||
snd_soc_write(codec, AIC32X4_BCLKN,
|
||||
value | AIC32X4_BCLKEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_BCLKN,
|
||||
AIC32X4_BCLKEN, AIC32X4_BCLKEN);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
@ -569,34 +562,28 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (aic32x4->master) {
|
||||
/* Switch off PLL */
|
||||
value = snd_soc_read(codec, AIC32X4_PLLPR);
|
||||
snd_soc_write(codec, AIC32X4_PLLPR,
|
||||
(value & ~AIC32X4_PLLEN));
|
||||
snd_soc_update_bits(codec, AIC32X4_PLLPR,
|
||||
AIC32X4_PLLEN, 0);
|
||||
|
||||
/* Switch off NDAC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_NDAC);
|
||||
snd_soc_write(codec, AIC32X4_NDAC,
|
||||
value & ~AIC32X4_NDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_NDAC,
|
||||
AIC32X4_NDACEN, 0);
|
||||
|
||||
/* Switch off MDAC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_MDAC);
|
||||
snd_soc_write(codec, AIC32X4_MDAC,
|
||||
value & ~AIC32X4_MDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_MDAC,
|
||||
AIC32X4_MDACEN, 0);
|
||||
|
||||
/* Switch off NADC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_NADC);
|
||||
snd_soc_write(codec, AIC32X4_NADC,
|
||||
value & ~AIC32X4_NDACEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_NADC,
|
||||
AIC32X4_NADCEN, 0);
|
||||
|
||||
/* Switch off MADC Divider */
|
||||
value = snd_soc_read(codec, AIC32X4_MADC);
|
||||
snd_soc_write(codec, AIC32X4_MADC,
|
||||
value & ~AIC32X4_MDACEN);
|
||||
value = snd_soc_read(codec, AIC32X4_BCLKN);
|
||||
snd_soc_update_bits(codec, AIC32X4_MADC,
|
||||
AIC32X4_MADCEN, 0);
|
||||
|
||||
/* Switch off BCLK_N Divider */
|
||||
snd_soc_write(codec, AIC32X4_BCLKN,
|
||||
value & ~AIC32X4_BCLKEN);
|
||||
snd_soc_update_bits(codec, AIC32X4_BCLKN,
|
||||
AIC32X4_BCLKEN, 0);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -685,10 +672,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* Mic PGA routing */
|
||||
if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
|
||||
if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
|
||||
snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
|
||||
}
|
||||
if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
|
||||
if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
|
||||
snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,6 @@ struct aic3x_priv {
|
||||
struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
|
||||
enum snd_soc_control_type control_type;
|
||||
struct aic3x_setup_data *setup;
|
||||
void *control_data;
|
||||
unsigned int sysclk;
|
||||
struct list_head list;
|
||||
int master;
|
||||
@ -138,7 +137,10 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
|
||||
if (reg >= AIC3X_CACHEREGNUM)
|
||||
return -1;
|
||||
|
||||
*value = codec->hw_read(codec, reg);
|
||||
codec->cache_bypass = 1;
|
||||
*value = snd_soc_read(codec, reg);
|
||||
codec->cache_bypass = 0;
|
||||
|
||||
cache[reg] = *value;
|
||||
|
||||
return 0;
|
||||
@ -198,6 +200,10 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
||||
else
|
||||
/* old connection must be powered down */
|
||||
path->connect = invert ? 1 : 0;
|
||||
|
||||
dapm_mark_dirty(path->source, "tlv320aic3x source");
|
||||
dapm_mark_dirty(path->sink, "tlv320aic3x sink");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1383,7 +1389,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
||||
int ret, i;
|
||||
|
||||
INIT_LIST_HEAD(&aic3x->list);
|
||||
codec->control_data = aic3x->control_data;
|
||||
aic3x->codec = codec;
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
|
||||
@ -1495,9 +1500,9 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
|
||||
*/
|
||||
|
||||
static const struct i2c_device_id aic3x_i2c_id[] = {
|
||||
[AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
|
||||
[AIC3X_MODEL_33] = { "tlv320aic33", 0 },
|
||||
[AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
|
||||
{ "tlv320aic3x", AIC3X_MODEL_3X },
|
||||
{ "tlv320aic33", AIC3X_MODEL_33 },
|
||||
{ "tlv320aic3007", AIC3X_MODEL_3007 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
|
||||
@ -1512,7 +1517,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
struct aic3x_pdata *pdata = i2c->dev.platform_data;
|
||||
struct aic3x_priv *aic3x;
|
||||
int ret;
|
||||
const struct i2c_device_id *tbl;
|
||||
|
||||
aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
|
||||
if (aic3x == NULL) {
|
||||
@ -1520,7 +1524,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
aic3x->control_data = i2c;
|
||||
aic3x->control_type = SND_SOC_I2C;
|
||||
|
||||
i2c_set_clientdata(i2c, aic3x);
|
||||
@ -1531,11 +1534,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
|
||||
aic3x->gpio_reset = -1;
|
||||
}
|
||||
|
||||
for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
|
||||
if (!strcmp(tbl->name, id->name))
|
||||
break;
|
||||
}
|
||||
aic3x->model = tbl - aic3x_i2c_id;
|
||||
aic3x->model = id->driver_data;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_aic3x, &aic3x_dai, 1);
|
||||
|
@ -55,13 +55,13 @@
|
||||
#define BURST_BASEFREQ_HZ 49152000
|
||||
|
||||
#define SAMPLES_TO_US(rate, samples) \
|
||||
(1000000000 / ((rate * 1000) / samples))
|
||||
(1000000000 / (((rate) * 1000) / (samples)))
|
||||
|
||||
#define US_TO_SAMPLES(rate, us) \
|
||||
(rate / (1000000 / (us < 1000000 ? us : 1000000)))
|
||||
((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000)))
|
||||
|
||||
#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
|
||||
((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
|
||||
(((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
|
||||
|
||||
static void dac33_calculate_times(struct snd_pcm_substream *substream);
|
||||
static int dac33_prepare_chip(struct snd_pcm_substream *substream);
|
||||
@ -627,18 +627,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
||||
{"RIGHT_LO", NULL, "Codec Power"},
|
||||
};
|
||||
|
||||
static int dac33_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets,
|
||||
ARRAY_SIZE(dac33_dapm_widgets));
|
||||
/* set up audio path interconnects */
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dac33_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
@ -1451,15 +1439,11 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, dac33_snd_controls,
|
||||
ARRAY_SIZE(dac33_snd_controls));
|
||||
/* Only add the FIFO controls, if we have valid IRQ number */
|
||||
if (dac33->irq >= 0)
|
||||
snd_soc_add_controls(codec, dac33_mode_snd_controls,
|
||||
ARRAY_SIZE(dac33_mode_snd_controls));
|
||||
|
||||
dac33_add_widgets(codec);
|
||||
|
||||
err_power:
|
||||
return ret;
|
||||
}
|
||||
@ -1502,6 +1486,13 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
|
||||
.remove = dac33_soc_remove,
|
||||
.suspend = dac33_soc_suspend,
|
||||
.resume = dac33_soc_resume,
|
||||
|
||||
.controls = dac33_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(dac33_snd_controls),
|
||||
.dapm_widgets = dac33_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets),
|
||||
.dapm_routes = audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(audio_map),
|
||||
};
|
||||
|
||||
#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
|
||||
|
@ -33,6 +33,11 @@
|
||||
|
||||
#include "tpa6130a2.h"
|
||||
|
||||
enum tpa_model {
|
||||
TPA6130A2,
|
||||
TPA6140A2,
|
||||
};
|
||||
|
||||
static struct i2c_client *tpa6130a2_client;
|
||||
|
||||
/* This struct is used to save the context */
|
||||
@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
data->power_gpio = pdata->power_gpio;
|
||||
data->id = pdata->id;
|
||||
data->id = id->driver_data;
|
||||
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
|
||||
switch (data->id) {
|
||||
default:
|
||||
dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
|
||||
pdata->id);
|
||||
data->id);
|
||||
case TPA6130A2:
|
||||
regulator = "Vdd";
|
||||
break;
|
||||
@ -469,7 +474,8 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tpa6130a2_id[] = {
|
||||
{ "tpa6130a2", 0 },
|
||||
{ "tpa6130a2", TPA6130A2 },
|
||||
{ "tpa6140a2", TPA6140A2 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
|
||||
|
@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
|
||||
* Inverting not going to help with these.
|
||||
* Custom volsw and volsw_2r get/put functions to handle these gain bits.
|
||||
*/
|
||||
#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
|
||||
xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw_twl4030, \
|
||||
.put = snd_soc_put_volsw_twl4030, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
|
||||
.max = xmax, .invert = xinvert} }
|
||||
#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
|
||||
xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_r2_twl4030,\
|
||||
.put = snd_soc_put_volsw_r2_twl4030, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.rshift = xshift, .max = xmax, .invert = xinvert} }
|
||||
#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
|
||||
SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
|
||||
xinvert, tlv_array)
|
||||
|
||||
static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
|
||||
TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
|
||||
|
||||
/* Separate output gain controls */
|
||||
SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume",
|
||||
TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
|
||||
4, 3, 0, output_tvl),
|
||||
4, 3, 0, snd_soc_get_volsw_r2_twl4030,
|
||||
snd_soc_put_volsw_r2_twl4030, output_tvl),
|
||||
|
||||
SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
|
||||
TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
|
||||
SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
|
||||
TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030,
|
||||
snd_soc_put_volsw_twl4030, output_tvl),
|
||||
|
||||
SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume",
|
||||
TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
|
||||
4, 3, 0, output_tvl),
|
||||
4, 3, 0, snd_soc_get_volsw_r2_twl4030,
|
||||
snd_soc_put_volsw_r2_twl4030, output_tvl),
|
||||
|
||||
SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
|
||||
TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
|
||||
SOC_SINGLE_EXT_TLV("Earpiece Playback Volume",
|
||||
TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030,
|
||||
snd_soc_put_volsw_twl4030, output_ear_tvl),
|
||||
|
||||
/* Common capture gain controls */
|
||||
SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
|
||||
@ -1633,17 +1609,6 @@ static const struct snd_soc_dapm_route intercon[] = {
|
||||
|
||||
};
|
||||
|
||||
static int twl4030_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets,
|
||||
ARRAY_SIZE(twl4030_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl4030_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
@ -2265,9 +2230,6 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
|
||||
|
||||
twl4030_init_chip(codec);
|
||||
|
||||
snd_soc_add_controls(codec, twl4030_snd_controls,
|
||||
ARRAY_SIZE(twl4030_snd_controls));
|
||||
twl4030_add_widgets(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2293,6 +2255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
|
||||
.reg_cache_size = sizeof(twl4030_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = twl4030_reg,
|
||||
|
||||
.controls = twl4030_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(twl4030_snd_controls),
|
||||
.dapm_widgets = twl4030_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets),
|
||||
.dapm_routes = intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(intercon),
|
||||
};
|
||||
|
||||
static int __devinit twl4030_codec_probe(struct platform_device *pdev)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,8 +22,21 @@
|
||||
#ifndef __TWL6040_H__
|
||||
#define __TWL6040_H__
|
||||
|
||||
enum twl6040_trim {
|
||||
TWL6040_TRIM_TRIM1 = 0,
|
||||
TWL6040_TRIM_TRIM2,
|
||||
TWL6040_TRIM_TRIM3,
|
||||
TWL6040_TRIM_HSOTRIM,
|
||||
TWL6040_TRIM_HFOTRIM,
|
||||
TWL6040_TRIM_INVAL,
|
||||
};
|
||||
|
||||
#define TWL6040_HSF_TRIM_LEFT(x) (x & 0x0f)
|
||||
#define TWL6040_HSF_TRIM_RIGHT(x) ((x >> 4) & 0x0f)
|
||||
|
||||
void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
|
||||
struct snd_soc_jack *jack, int report);
|
||||
int twl6040_get_clk_id(struct snd_soc_codec *codec);
|
||||
int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
|
||||
|
||||
#endif /* End of __TWL6040_H__ */
|
||||
|
@ -462,7 +462,6 @@ static int wl1273_probe(struct snd_soc_codec *codec)
|
||||
wl1273->core = *core;
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, wl1273);
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
r = snd_soc_add_controls(codec, wl1273_controls,
|
||||
ARRAY_SIZE(wl1273_controls));
|
||||
|
@ -12,10 +12,59 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/wm1250-ev1.h>
|
||||
|
||||
static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = {
|
||||
"WM1250 CLK_ENA",
|
||||
"WM1250 CLK_SEL0",
|
||||
"WM1250 CLK_SEL1",
|
||||
"WM1250 OSR",
|
||||
"WM1250 MASTER",
|
||||
};
|
||||
|
||||
struct wm1250_priv {
|
||||
struct gpio gpios[WM1250_EV1_NUM_GPIOS];
|
||||
};
|
||||
|
||||
static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev);
|
||||
int ena;
|
||||
|
||||
if (wm1250)
|
||||
ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio;
|
||||
else
|
||||
ena = -1;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (ena >= 0)
|
||||
gpio_set_value_cansleep(ena, 1);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
if (ena >= 0)
|
||||
gpio_set_value_cansleep(ena, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
|
||||
@ -53,12 +102,67 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
|
||||
.num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
|
||||
.dapm_routes = wm1250_ev1_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
|
||||
|
||||
.set_bias_level = wm1250_ev1_set_bias_level,
|
||||
.idle_bias_off = true,
|
||||
};
|
||||
|
||||
static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
|
||||
struct wm1250_priv *wm1250;
|
||||
int i, ret;
|
||||
|
||||
if (!pdata)
|
||||
return 0;
|
||||
|
||||
wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
|
||||
if (!wm1250) {
|
||||
dev_err(&i2c->dev, "Unable to allocate private data\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) {
|
||||
wm1250->gpios[i].gpio = pdata->gpios[i];
|
||||
wm1250->gpios[i].label = wm1250_gpio_names[i];
|
||||
wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW;
|
||||
}
|
||||
wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH;
|
||||
wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH;
|
||||
|
||||
ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&i2c->dev, wm1250);
|
||||
|
||||
return ret;
|
||||
|
||||
err_alloc:
|
||||
kfree(wm1250);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wm1250_ev1_free(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
|
||||
|
||||
if (wm1250) {
|
||||
gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
|
||||
kfree(wm1250);
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
int id, board, rev;
|
||||
int id, board, rev, ret;
|
||||
|
||||
dev_set_drvdata(&i2c->dev, NULL);
|
||||
|
||||
board = i2c_smbus_read_byte_data(i2c, 0);
|
||||
if (board < 0) {
|
||||
@ -76,13 +180,25 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
|
||||
|
||||
dev_info(&i2c->dev, "revision %d\n", rev + 1);
|
||||
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
|
||||
ret = wm1250_ev1_pdata(i2c);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
|
||||
&wm1250_ev1_dai, 1);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
|
||||
wm1250_ev1_free(i2c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
|
||||
{
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
wm1250_ev1_free(i2c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1531
sound/soc/codecs/wm5100-tables.c
Normal file
1531
sound/soc/codecs/wm5100-tables.c
Normal file
File diff suppressed because it is too large
Load Diff
2809
sound/soc/codecs/wm5100.c
Normal file
2809
sound/soc/codecs/wm5100.c
Normal file
File diff suppressed because it is too large
Load Diff
5155
sound/soc/codecs/wm5100.h
Normal file
5155
sound/soc/codecs/wm5100.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -355,7 +355,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
|
||||
ret = snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -392,23 +392,9 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
|
||||
break;
|
||||
}
|
||||
|
||||
return snd_soc_get_volsw_2r(kcontrol, ucontrol);
|
||||
return snd_soc_get_volsw(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
/* double control with volume update */
|
||||
#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
|
||||
xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE | \
|
||||
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.rshift = xshift, .max = xmax, .invert = xinvert}, }
|
||||
|
||||
static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
|
||||
static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
|
||||
static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
|
||||
@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = {
|
||||
static const struct snd_kcontrol_new wm8350_snd_controls[] = {
|
||||
SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
|
||||
SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume",
|
||||
WM8350_DAC_DIGITAL_VOLUME_L,
|
||||
WM8350_DAC_DIGITAL_VOLUME_R,
|
||||
0, 255, 0, dac_pcm_tlv),
|
||||
0, 255, 0, wm8350_get_volsw_2r,
|
||||
wm8350_put_volsw_2r_vu, dac_pcm_tlv),
|
||||
SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
|
||||
SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
|
||||
SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
|
||||
SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
|
||||
SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume",
|
||||
WM8350_ADC_DIGITAL_VOLUME_L,
|
||||
WM8350_ADC_DIGITAL_VOLUME_R,
|
||||
0, 255, 0, adc_pcm_tlv),
|
||||
0, 255, 0, wm8350_get_volsw_2r,
|
||||
wm8350_put_volsw_2r_vu, adc_pcm_tlv),
|
||||
SOC_DOUBLE_TLV("Capture Sidetone Volume",
|
||||
WM8350_ADC_DIVIDER,
|
||||
8, 4, 15, 1, capture_sd_tlv),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Capture Volume",
|
||||
WM8350_LEFT_INPUT_VOLUME,
|
||||
WM8350_RIGHT_INPUT_VOLUME,
|
||||
2, 63, 0, pre_amp_tlv),
|
||||
2, 63, 0, wm8350_get_volsw_2r,
|
||||
wm8350_put_volsw_2r_vu, pre_amp_tlv),
|
||||
SOC_DOUBLE_R("Capture ZC Switch",
|
||||
WM8350_LEFT_INPUT_VOLUME,
|
||||
WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
|
||||
@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("Out4 Capture Volume",
|
||||
WM8350_INPUT_MIXER_VOLUME,
|
||||
1, 7, 0, out_mix_tlv),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume",
|
||||
WM8350_LOUT1_VOLUME,
|
||||
WM8350_ROUT1_VOLUME,
|
||||
2, 63, 0, out_pga_tlv),
|
||||
2, 63, 0, wm8350_get_volsw_2r,
|
||||
wm8350_put_volsw_2r_vu, out_pga_tlv),
|
||||
SOC_DOUBLE_R("Out1 Playback ZC Switch",
|
||||
WM8350_LOUT1_VOLUME,
|
||||
WM8350_ROUT1_VOLUME, 13, 1, 0),
|
||||
SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume",
|
||||
WM8350_LOUT2_VOLUME,
|
||||
WM8350_ROUT2_VOLUME,
|
||||
2, 63, 0, out_pga_tlv),
|
||||
2, 63, 0, wm8350_get_volsw_2r,
|
||||
wm8350_put_volsw_2r_vu, out_pga_tlv),
|
||||
SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
|
||||
WM8350_ROUT2_VOLUME, 13, 1, 0),
|
||||
SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
|
||||
|
@ -383,7 +383,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
|
||||
(1 << WM8400_AINRMUX_PWR))) {
|
||||
reg |= WM8400_AINR_ENA;
|
||||
} else {
|
||||
reg &= ~WM8400_AINL_ENA;
|
||||
reg &= ~WM8400_AINR_ENA;
|
||||
}
|
||||
wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
|
||||
|
||||
|
@ -480,6 +480,8 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
|
||||
power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
|
||||
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Initial cap charge at VMID 5k */
|
||||
snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
|
||||
mdelay(100);
|
||||
@ -541,18 +543,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8510_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -406,7 +406,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
|
||||
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, i;
|
||||
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
|
||||
wm8523->rate_constraint.count =
|
||||
ARRAY_SIZE(wm8523->rate_constraint_list);
|
||||
|
@ -213,7 +213,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
|
||||
reg_cache[reg] = 0;
|
||||
reg_cache[reg2] = 0;
|
||||
|
||||
ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
|
||||
ret = snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -224,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
|
||||
xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
|
||||
.max = xmax, .invert = xinvert} }
|
||||
|
||||
static const struct snd_kcontrol_new wm8580_snd_controls[] = {
|
||||
SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
|
||||
SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",
|
||||
WM8580_DIGITAL_ATTENUATION_DACL1,
|
||||
WM8580_DIGITAL_ATTENUATION_DACR1,
|
||||
0, 0xff, 0, dac_tlv),
|
||||
SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
|
||||
0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
|
||||
SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",
|
||||
WM8580_DIGITAL_ATTENUATION_DACL2,
|
||||
WM8580_DIGITAL_ATTENUATION_DACR2,
|
||||
0, 0xff, 0, dac_tlv),
|
||||
SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
|
||||
0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
|
||||
SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",
|
||||
WM8580_DIGITAL_ATTENUATION_DACL3,
|
||||
WM8580_DIGITAL_ATTENUATION_DACR3,
|
||||
0, 0xff, 0, dac_tlv),
|
||||
0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
|
||||
|
||||
SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
|
||||
SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
|
||||
@ -442,8 +430,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
|
||||
/* Always disable the PLL - it is not safe to leave it running
|
||||
* while reprogramming it.
|
||||
*/
|
||||
reg = snd_soc_read(codec, WM8580_PWRDN2);
|
||||
snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
|
||||
snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask);
|
||||
|
||||
if (!freq_in || !freq_out)
|
||||
return 0;
|
||||
@ -461,8 +448,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
|
||||
snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
|
||||
|
||||
/* All done, turn it on */
|
||||
reg = snd_soc_read(codec, WM8580_PWRDN2);
|
||||
snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
|
||||
snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -760,7 +746,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
|
||||
static int wm8580_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 reg;
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
@ -769,20 +754,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Power up and get individual control of the DACs */
|
||||
reg = snd_soc_read(codec, WM8580_PWRDN1);
|
||||
reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
|
||||
snd_soc_write(codec, WM8580_PWRDN1, reg);
|
||||
snd_soc_update_bits(codec, WM8580_PWRDN1,
|
||||
WM8580_PWRDN1_PWDN |
|
||||
WM8580_PWRDN1_ALLDACPD, 0);
|
||||
|
||||
/* Make VMID high impedance */
|
||||
reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
|
||||
reg &= ~0x100;
|
||||
snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
|
||||
snd_soc_update_bits(codec, WM8580_ADC_CONTROL1,
|
||||
0x100, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
reg = snd_soc_read(codec, WM8580_PWRDN1);
|
||||
snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
|
||||
snd_soc_update_bits(codec, WM8580_PWRDN1,
|
||||
WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2006 Wolfson Microelectronics
|
||||
*
|
||||
* Author: Mike Arthur <linux@wolfsonmicro.com>
|
||||
* Author: Mike Arthur <Mike.Arthur@wolfsonmicro.com>
|
||||
*
|
||||
* Based on wm8731.c by Richard Purdie
|
||||
*
|
||||
@ -287,7 +287,6 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wm8711_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
@ -300,6 +299,9 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -346,25 +348,14 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8711_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8711_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, reg;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
|
||||
if (ret < 0) {
|
||||
@ -381,10 +372,8 @@ static int wm8711_probe(struct snd_soc_codec *codec)
|
||||
wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* Latch the update bits */
|
||||
reg = snd_soc_read(codec, WM8711_LOUT1V);
|
||||
snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8711_ROUT1V);
|
||||
snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
|
||||
snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100);
|
||||
|
||||
snd_soc_add_controls(codec, wm8711_snd_controls,
|
||||
ARRAY_SIZE(wm8711_snd_controls));
|
||||
|
@ -427,9 +427,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
int ret;
|
||||
u16 reg;
|
||||
|
||||
switch (level) {
|
||||
@ -444,16 +442,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
|
||||
if (cache[i] == wm8731_reg[i])
|
||||
continue;
|
||||
|
||||
data[0] = (i << 1) | ((cache[i] >> 8)
|
||||
& 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
snd_soc_cache_sync(codec);
|
||||
}
|
||||
|
||||
/* Clear PWROFF, gate CLKOUT, everything else as-is */
|
||||
|
@ -339,10 +339,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
iface |= 0x0004;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
iface |= 0x0003;
|
||||
iface |= 0x000C;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
iface |= 0x0013;
|
||||
iface |= 0x001C;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -404,15 +404,7 @@ static struct snd_soc_dai_driver wm8741_dai = {
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8741_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
u16 *cache = codec->reg_cache;
|
||||
int i;
|
||||
|
||||
/* RESTORE REG Cache */
|
||||
for (i = 0; i < WM8741_REGISTER_COUNT; i++) {
|
||||
if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i)
|
||||
continue;
|
||||
snd_soc_write(codec, i, cache[i]);
|
||||
}
|
||||
snd_soc_cache_sync(codec);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@ -462,7 +454,7 @@ static int wm8741_probe(struct snd_soc_codec *codec)
|
||||
WM8741_UPDATELM, WM8741_UPDATELM);
|
||||
snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
|
||||
WM8741_UPDATERL, WM8741_UPDATERL);
|
||||
snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
|
||||
snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
|
||||
WM8741_UPDATERM, WM8741_UPDATERM);
|
||||
|
||||
snd_soc_add_controls(codec, wm8741_snd_controls,
|
||||
|
@ -616,6 +616,8 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Set VMID to 5k */
|
||||
snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
|
||||
|
||||
@ -673,28 +675,14 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8750_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
|
||||
if (i == WM8750_RESET)
|
||||
continue;
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8750_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
|
||||
int reg, ret;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
|
||||
if (ret < 0) {
|
||||
@ -712,22 +700,14 @@ static int wm8750_probe(struct snd_soc_codec *codec)
|
||||
wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* set the update bits */
|
||||
reg = snd_soc_read(codec, WM8750_LDAC);
|
||||
snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_RDAC);
|
||||
snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_LOUT1V);
|
||||
snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_ROUT1V);
|
||||
snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_LOUT2V);
|
||||
snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_ROUT2V);
|
||||
snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_LINVOL);
|
||||
snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8750_RINVOL);
|
||||
snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100);
|
||||
|
||||
snd_soc_add_controls(codec, wm8750_snd_controls,
|
||||
ARRAY_SIZE(wm8750_snd_controls));
|
||||
|
@ -1455,8 +1455,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
|
||||
/* set the update bits */
|
||||
snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
|
||||
|
@ -308,6 +308,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Disable the global powerdown; DAPM does the rest */
|
||||
snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
|
||||
}
|
||||
@ -379,21 +381,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8776_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
|
||||
if (cache[i] == wm8776_reg[i])
|
||||
continue;
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wm8782_probe,
|
||||
.remove = wm8782_remove,
|
||||
.remove = __devexit_p(wm8782_remove),
|
||||
};
|
||||
|
||||
static int __init wm8782_init(void)
|
||||
|
@ -110,8 +110,8 @@
|
||||
|
||||
#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1
|
||||
#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100
|
||||
#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e)
|
||||
#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
|
||||
#define WM8900_REG_CLOCKING1_BCLK_MASK 0x01e
|
||||
#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000
|
||||
|
||||
#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
|
||||
#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
|
||||
@ -135,7 +135,7 @@
|
||||
#define WM8900_REG_HPCTL1_HP_SHORT 0x08
|
||||
#define WM8900_REG_HPCTL1_HP_SHORT2 0x04
|
||||
|
||||
#define WM8900_LRC_MASK 0xfc00
|
||||
#define WM8900_LRC_MASK 0x03ff
|
||||
|
||||
struct wm8900_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
@ -742,26 +742,20 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
|
||||
{
|
||||
struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
|
||||
struct _fll_div fll_div;
|
||||
unsigned int reg;
|
||||
|
||||
if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
|
||||
return 0;
|
||||
|
||||
/* The digital side should be disabled during any change. */
|
||||
reg = snd_soc_read(codec, WM8900_REG_POWER1);
|
||||
snd_soc_write(codec, WM8900_REG_POWER1,
|
||||
reg & (~WM8900_REG_POWER1_FLL_ENA));
|
||||
snd_soc_update_bits(codec, WM8900_REG_POWER1,
|
||||
WM8900_REG_POWER1_FLL_ENA, 0);
|
||||
|
||||
/* Disable the FLL? */
|
||||
if (!freq_in || !freq_out) {
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING1,
|
||||
reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
|
||||
|
||||
reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
|
||||
snd_soc_write(codec, WM8900_REG_FLLCTL1,
|
||||
reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
|
||||
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
|
||||
WM8900_REG_CLOCKING1_MCLK_SRC, 0);
|
||||
snd_soc_update_bits(codec, WM8900_REG_FLLCTL1,
|
||||
WM8900_REG_FLLCTL1_OSC_ENA, 0);
|
||||
wm8900->fll_in = freq_in;
|
||||
wm8900->fll_out = freq_out;
|
||||
|
||||
@ -796,15 +790,14 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
|
||||
else
|
||||
snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
|
||||
|
||||
reg = snd_soc_read(codec, WM8900_REG_POWER1);
|
||||
snd_soc_write(codec, WM8900_REG_POWER1,
|
||||
reg | WM8900_REG_POWER1_FLL_ENA);
|
||||
snd_soc_update_bits(codec, WM8900_REG_POWER1,
|
||||
WM8900_REG_POWER1_FLL_ENA,
|
||||
WM8900_REG_POWER1_FLL_ENA);
|
||||
|
||||
reenable:
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING1,
|
||||
reg | WM8900_REG_CLOCKING1_MCLK_SRC);
|
||||
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
|
||||
WM8900_REG_CLOCKING1_MCLK_SRC,
|
||||
WM8900_REG_CLOCKING1_MCLK_SRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -818,43 +811,35 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
|
||||
int div_id, int div)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
unsigned int reg;
|
||||
|
||||
switch (div_id) {
|
||||
case WM8900_BCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING1,
|
||||
div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
|
||||
WM8900_REG_CLOCKING1_BCLK_MASK, div);
|
||||
break;
|
||||
case WM8900_OPCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING1,
|
||||
div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
|
||||
WM8900_REG_CLOCKING1_OPCLK_MASK, div);
|
||||
break;
|
||||
case WM8900_DAC_LRCLK:
|
||||
reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
|
||||
snd_soc_write(codec, WM8900_REG_AUDIO4,
|
||||
div | (reg & WM8900_LRC_MASK));
|
||||
snd_soc_update_bits(codec, WM8900_REG_AUDIO4,
|
||||
WM8900_LRC_MASK, div);
|
||||
break;
|
||||
case WM8900_ADC_LRCLK:
|
||||
reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
|
||||
snd_soc_write(codec, WM8900_REG_AUDIO3,
|
||||
div | (reg & WM8900_LRC_MASK));
|
||||
snd_soc_update_bits(codec, WM8900_REG_AUDIO3,
|
||||
WM8900_LRC_MASK, div);
|
||||
break;
|
||||
case WM8900_DAC_CLKDIV:
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING2,
|
||||
div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
|
||||
WM8900_REG_CLOCKING2_DAC_CLKDIV, div);
|
||||
break;
|
||||
case WM8900_ADC_CLKDIV:
|
||||
reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
|
||||
snd_soc_write(codec, WM8900_REG_CLOCKING2,
|
||||
div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
|
||||
snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
|
||||
WM8900_REG_CLOCKING2_ADC_CLKDIV, div);
|
||||
break;
|
||||
case WM8900_LRCLK_MODE:
|
||||
reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
|
||||
snd_soc_write(codec, WM8900_REG_DACCTRL,
|
||||
div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
|
||||
snd_soc_update_bits(codec, WM8900_REG_DACCTRL,
|
||||
WM8900_REG_DACCTRL_AIF_LRCLKRATE, div);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1037,12 +1022,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
/* Enable thermal shutdown */
|
||||
reg = snd_soc_read(codec, WM8900_REG_GPIO);
|
||||
snd_soc_write(codec, WM8900_REG_GPIO,
|
||||
reg | WM8900_REG_GPIO_TEMP_ENA);
|
||||
reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
|
||||
snd_soc_write(codec, WM8900_REG_ADDCTL,
|
||||
reg | WM8900_REG_ADDCTL_TEMP_SD);
|
||||
snd_soc_update_bits(codec, WM8900_REG_GPIO,
|
||||
WM8900_REG_GPIO_TEMP_ENA,
|
||||
WM8900_REG_GPIO_TEMP_ENA);
|
||||
snd_soc_update_bits(codec, WM8900_REG_ADDCTL,
|
||||
WM8900_REG_ADDCTL_TEMP_SD,
|
||||
WM8900_REG_ADDCTL_TEMP_SD);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
@ -1205,26 +1190,16 @@ static int wm8900_probe(struct snd_soc_codec *codec)
|
||||
wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* Latch the volume update bits */
|
||||
snd_soc_write(codec, WM8900_REG_LINVOL,
|
||||
snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_RINVOL,
|
||||
snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_LOUT1CTL,
|
||||
snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_ROUT1CTL,
|
||||
snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_LOUT2CTL,
|
||||
snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_ROUT2CTL,
|
||||
snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_LDAC_DV,
|
||||
snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_RDAC_DV,
|
||||
snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_LADC_DV,
|
||||
snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
|
||||
snd_soc_write(codec, WM8900_REG_RADC_DV,
|
||||
snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100);
|
||||
|
||||
/* Set the DAC and mixer output bias */
|
||||
snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
|
||||
|
@ -50,7 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
|
||||
struct wm8904_priv {
|
||||
|
||||
enum wm8904_type devtype;
|
||||
void *control_data;
|
||||
|
||||
struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
|
||||
|
||||
@ -2540,7 +2539,6 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
wm8904->devtype = id->driver_data;
|
||||
i2c_set_clientdata(i2c, wm8904);
|
||||
wm8904->control_data = i2c;
|
||||
wm8904->pdata = i2c->dev.platform_data;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -43,9 +43,19 @@
|
||||
struct wm8940_priv {
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
static int wm8940_volatile_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WM8940_SOFTRESET:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u16 wm8940_reg_defaults[] = {
|
||||
0x8940, /* Soft Reset */
|
||||
0x0000, /* Power 1 */
|
||||
@ -460,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
|
||||
ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = snd_soc_cache_sync(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* ensure bufioen and biasen */
|
||||
pwr_reg |= (1 << 2) | (1 << 3);
|
||||
/* set vmid to 300k for standby */
|
||||
@ -470,6 +488,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -660,30 +680,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8940_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
u8 data[3];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware
|
||||
* Could use auto incremented writes to speed this up
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
|
||||
data[0] = i;
|
||||
data[1] = (cache[i] & 0xFF00) >> 8;
|
||||
data[2] = cache[i] & 0x00FF;
|
||||
ret = codec->hw_write(codec->control_data, data, 3);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
else if (ret != 3) {
|
||||
ret = -EIO;
|
||||
goto error_ret;
|
||||
}
|
||||
}
|
||||
ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8940_probe(struct snd_soc_codec *codec)
|
||||
@ -693,7 +691,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
u16 reg;
|
||||
|
||||
codec->control_data = wm8940->control_data;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
@ -744,6 +741,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
|
||||
.reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = wm8940_reg_defaults,
|
||||
.volatile_register = wm8940_volatile_register,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, wm8940);
|
||||
wm8940->control_data = i2c;
|
||||
wm8940->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
|
@ -72,7 +72,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
|
||||
|
||||
struct wm8960_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
enum snd_soc_bias_level level);
|
||||
struct snd_soc_dapm_widget *lout1;
|
||||
@ -575,6 +574,8 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Enable anti-pop features */
|
||||
snd_soc_write(codec, WM8960_APOP1,
|
||||
WM8960_POBCTRL | WM8960_SOFT_ST |
|
||||
@ -677,6 +678,9 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
|
||||
WM8960_VREF | WM8960_VMID_MASK, 0);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_cache_sync(codec);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -902,16 +906,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
static int wm8960_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
@ -925,7 +919,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
|
||||
u16 reg;
|
||||
|
||||
wm8960->set_bias_level = wm8960_set_bias_level_out3;
|
||||
codec->control_data = wm8960->control_data;
|
||||
|
||||
if (!pdata) {
|
||||
dev_warn(codec->dev, "No platform data supplied\n");
|
||||
@ -1015,7 +1008,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
i2c_set_clientdata(i2c, wm8960);
|
||||
wm8960->control_type = SND_SOC_I2C;
|
||||
wm8960->control_data = i2c;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_wm8960, &wm8960_dai, 1);
|
||||
|
@ -974,7 +974,9 @@ static int wm8961_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* This isn't volatile - readback doesn't correspond to write */
|
||||
reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
|
||||
codec->cache_bypass = 1;
|
||||
reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
|
||||
codec->cache_bypass = 0;
|
||||
dev_info(codec->dev, "WM8961 family %d revision %c\n",
|
||||
(reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
|
||||
((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
|
||||
|
@ -2139,7 +2139,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
u16 *reg_cache = codec->reg_cache;
|
||||
int ret;
|
||||
|
||||
/* Apply the update (if any) */
|
||||
@ -2148,16 +2147,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
|
||||
/* If the left PGA is enabled hit that VU bit... */
|
||||
if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
|
||||
return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
|
||||
reg_cache[WM8962_SPKOUTL_VOLUME]);
|
||||
ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
|
||||
if (ret & WM8962_SPKOUTL_PGA_ENA) {
|
||||
snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
|
||||
snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ...otherwise the right. The VU is stereo. */
|
||||
if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
|
||||
return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
|
||||
reg_cache[WM8962_SPKOUTR_VOLUME]);
|
||||
if (ret & WM8962_SPKOUTR_PGA_ENA)
|
||||
snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
|
||||
snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *cap_hpf_mode_text[] = {
|
||||
@ -2498,7 +2500,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
u16 *reg_cache = codec->reg_cache;
|
||||
int reg;
|
||||
|
||||
switch (w->shift) {
|
||||
@ -2521,7 +2522,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
return snd_soc_write(codec, reg, reg_cache[reg]);
|
||||
return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
@ -2667,7 +2668,7 @@ SND_SOC_DAPM_INPUT("IN4R"),
|
||||
SND_SOC_DAPM_INPUT("Beep"),
|
||||
SND_SOC_DAPM_INPUT("DMICDAT"),
|
||||
|
||||
SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
|
||||
SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
|
||||
@ -2688,7 +2689,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
|
||||
SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
|
||||
mixinr, ARRAY_SIZE(mixinr)),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
|
||||
SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
|
||||
SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
|
||||
@ -2767,18 +2768,18 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
|
||||
|
||||
{ "MICBIAS", NULL, "SYSCLK" },
|
||||
|
||||
{ "DMIC", NULL, "DMICDAT" },
|
||||
{ "DMIC_ENA", NULL, "DMICDAT" },
|
||||
|
||||
{ "ADCL", NULL, "SYSCLK" },
|
||||
{ "ADCL", NULL, "TOCLK" },
|
||||
{ "ADCL", NULL, "MIXINL" },
|
||||
{ "ADCL", NULL, "DMIC" },
|
||||
{ "ADCL", NULL, "DMIC_ENA" },
|
||||
{ "ADCL", NULL, "DSP2" },
|
||||
|
||||
{ "ADCR", NULL, "SYSCLK" },
|
||||
{ "ADCR", NULL, "TOCLK" },
|
||||
{ "ADCR", NULL, "MIXINR" },
|
||||
{ "ADCR", NULL, "DMIC" },
|
||||
{ "ADCR", NULL, "DMIC_ENA" },
|
||||
{ "ADCR", NULL, "DSP2" },
|
||||
|
||||
{ "STL", "Left", "ADCL" },
|
||||
@ -3223,9 +3224,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
int aif0 = 0;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif0 |= WM8962_LRCLK_INV;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif0 |= WM8962_LRCLK_INV | 3;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif0 |= 3;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
|
@ -546,6 +546,9 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* mute dac and set vmid to 500k, enable VREF */
|
||||
snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
|
||||
break;
|
||||
@ -605,20 +608,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8971_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
u16 reg;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
|
||||
if (i + 1 == WM8971_RESET)
|
||||
continue;
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* charge wm8971 caps */
|
||||
@ -660,25 +651,14 @@ static int wm8971_probe(struct snd_soc_codec *codec)
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
/* set the update bits */
|
||||
reg = snd_soc_read(codec, WM8971_LDAC);
|
||||
snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8971_RDAC);
|
||||
snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
|
||||
|
||||
reg = snd_soc_read(codec, WM8971_LOUT1V);
|
||||
snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8971_ROUT1V);
|
||||
snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
|
||||
|
||||
reg = snd_soc_read(codec, WM8971_LOUT2V);
|
||||
snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8971_ROUT2V);
|
||||
snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
|
||||
|
||||
reg = snd_soc_read(codec, WM8971_LINVOL);
|
||||
snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8971_RINVOL);
|
||||
snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
|
||||
|
||||
snd_soc_add_controls(codec, wm8971_snd_controls,
|
||||
ARRAY_SIZE(wm8971_snd_controls));
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2006-2009 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Liam Girdwood <linux@wolfsonmicro.com>
|
||||
* Author: Liam Girdwood <Liam.Girdwood@wolfsonmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -530,6 +530,8 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
|
||||
power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
|
||||
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Initial cap charge at VMID 5k */
|
||||
snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
|
||||
mdelay(100);
|
||||
@ -589,18 +591,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8974_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,6 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
|
||||
/* codec private data */
|
||||
struct wm8978_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
unsigned int f_pllout;
|
||||
unsigned int f_mclk;
|
||||
unsigned int f_256fs;
|
||||
@ -955,7 +954,6 @@ static int wm8978_probe(struct snd_soc_codec *codec)
|
||||
* default hardware setting
|
||||
*/
|
||||
wm8978->sysclk = WM8978_PLL;
|
||||
codec->control_data = wm8978->control_data;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
@ -1016,7 +1014,6 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, wm8978);
|
||||
wm8978->control_data = i2c;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_wm8978, &wm8978_dai, 1);
|
||||
|
@ -1007,7 +1007,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983);
|
||||
ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -55,7 +55,6 @@ struct wm8988_priv {
|
||||
struct snd_pcm_hw_constraint_list *sysclk_constraints;
|
||||
};
|
||||
|
||||
|
||||
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
|
||||
|
||||
/*
|
||||
@ -676,6 +675,8 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* VREF, VMID=2x5k */
|
||||
snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
|
||||
|
||||
@ -736,21 +737,7 @@ static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8988_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < WM8988_NUM_REG; i++) {
|
||||
if (i == WM8988_RESET)
|
||||
continue;
|
||||
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -759,7 +746,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
|
||||
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret = 0;
|
||||
u16 reg;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
|
||||
if (ret < 0) {
|
||||
@ -774,16 +760,11 @@ static int wm8988_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* set the update bits (we always update left then right) */
|
||||
reg = snd_soc_read(codec, WM8988_RADC);
|
||||
snd_soc_write(codec, WM8988_RADC, reg | 0x100);
|
||||
reg = snd_soc_read(codec, WM8988_RDAC);
|
||||
snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8988_ROUT1V);
|
||||
snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8988_ROUT2V);
|
||||
snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
|
||||
reg = snd_soc_read(codec, WM8988_RINVOL);
|
||||
snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
|
||||
snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100);
|
||||
snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100);
|
||||
|
||||
wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
|
@ -36,10 +36,17 @@ struct wm8990_priv {
|
||||
unsigned int pcmclk;
|
||||
};
|
||||
|
||||
/*
|
||||
* wm8990 register cache. Note that register 0 is not included in the
|
||||
* cache.
|
||||
*/
|
||||
static int wm8990_volatile_register(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WM8990_RESET:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const u16 wm8990_reg[] = {
|
||||
0x8990, /* R0 - Reset */
|
||||
0x0000, /* R1 - Power Management (1) */
|
||||
@ -394,7 +401,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
|
||||
(1 << WM8990_AINRMUX_PWR_BIT))) {
|
||||
reg |= WM8990_AINR_ENA;
|
||||
} else {
|
||||
reg &= ~WM8990_AINL_ENA;
|
||||
reg &= ~WM8990_AINR_ENA;
|
||||
}
|
||||
snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
|
||||
|
||||
@ -974,7 +981,6 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
|
||||
static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
|
||||
int source, unsigned int freq_in, unsigned int freq_out)
|
||||
{
|
||||
u16 reg;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct _pll_div pll_div;
|
||||
|
||||
@ -982,13 +988,12 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
|
||||
pll_factors(&pll_div, freq_out * 4, freq_in);
|
||||
|
||||
/* Turn on PLL */
|
||||
reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
|
||||
reg |= WM8990_PLL_ENA;
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
|
||||
snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
|
||||
WM8990_PLL_ENA, WM8990_PLL_ENA);
|
||||
|
||||
/* sysclk comes from PLL */
|
||||
reg = snd_soc_read(codec, WM8990_CLOCKING_2);
|
||||
snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
|
||||
snd_soc_update_bits(codec, WM8990_CLOCKING_2,
|
||||
WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC);
|
||||
|
||||
/* set up N , fractional mode and pre-divisor if necessary */
|
||||
snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
|
||||
@ -996,10 +1001,9 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
|
||||
snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
|
||||
snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
|
||||
} else {
|
||||
/* Turn on PLL */
|
||||
reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
|
||||
reg &= ~WM8990_PLL_ENA;
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
|
||||
/* Turn off PLL */
|
||||
snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
|
||||
WM8990_PLL_ENA, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1077,28 +1081,23 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
|
||||
int div_id, int div)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
u16 reg;
|
||||
|
||||
switch (div_id) {
|
||||
case WM8990_MCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
|
||||
~WM8990_MCLK_DIV_MASK;
|
||||
snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
|
||||
snd_soc_update_bits(codec, WM8990_CLOCKING_2,
|
||||
WM8990_MCLK_DIV_MASK, div);
|
||||
break;
|
||||
case WM8990_DACCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
|
||||
~WM8990_DAC_CLKDIV_MASK;
|
||||
snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
|
||||
snd_soc_update_bits(codec, WM8990_CLOCKING_2,
|
||||
WM8990_DAC_CLKDIV_MASK, div);
|
||||
break;
|
||||
case WM8990_ADCCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
|
||||
~WM8990_ADC_CLKDIV_MASK;
|
||||
snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
|
||||
snd_soc_update_bits(codec, WM8990_CLOCKING_2,
|
||||
WM8990_ADC_CLKDIV_MASK, div);
|
||||
break;
|
||||
case WM8990_BCLK_DIV:
|
||||
reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
|
||||
~WM8990_BCLK_DIV_MASK;
|
||||
snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
|
||||
snd_soc_update_bits(codec, WM8990_CLOCKING_1,
|
||||
WM8990_BCLK_DIV_MASK, div);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1156,7 +1155,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
|
||||
static int wm8990_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 val;
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
@ -1164,13 +1163,18 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
/* VMID=2*50k */
|
||||
val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
|
||||
~WM8990_VMID_MODE_MASK;
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
|
||||
snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
|
||||
WM8990_VMID_MODE_MASK, 0x2);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = snd_soc_cache_sync(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable all output discharge bits */
|
||||
snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
|
||||
WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
|
||||
@ -1225,9 +1229,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
|
||||
}
|
||||
|
||||
/* VMID=2*250k */
|
||||
val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
|
||||
~WM8990_VMID_MODE_MASK;
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
|
||||
snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
|
||||
WM8990_VMID_MODE_MASK, 0x4);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -1241,8 +1244,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
|
||||
WM8990_BUFIOEN);
|
||||
|
||||
/* mute DAC */
|
||||
val = snd_soc_read(codec, WM8990_DAC_CTRL);
|
||||
snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
|
||||
snd_soc_update_bits(codec, WM8990_DAC_CTRL,
|
||||
WM8990_DAC_MUTE, WM8990_DAC_MUTE);
|
||||
|
||||
/* Enable any disabled outputs */
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
|
||||
@ -1319,19 +1322,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
||||
static int wm8990_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u8 data[2];
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
|
||||
if (i + 1 == WM8990_RESET)
|
||||
continue;
|
||||
data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
|
||||
data[1] = cache[i] & 0x00ff;
|
||||
codec->hw_write(codec->control_data, data, 2);
|
||||
}
|
||||
|
||||
wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
@ -1343,7 +1333,6 @@ static int wm8990_resume(struct snd_soc_codec *codec)
|
||||
static int wm8990_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
u16 reg;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
|
||||
if (ret < 0) {
|
||||
@ -1356,15 +1345,14 @@ static int wm8990_probe(struct snd_soc_codec *codec)
|
||||
/* charge output caps */
|
||||
wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
|
||||
snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
|
||||
snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4,
|
||||
WM8990_ALRCGPIO1, WM8990_ALRCGPIO1);
|
||||
|
||||
reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
|
||||
~WM8990_GPIO1_SEL_MASK;
|
||||
snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
|
||||
snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2,
|
||||
WM8990_GPIO1_SEL_MASK, 1);
|
||||
|
||||
reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
|
||||
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
|
||||
snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
|
||||
WM8990_OPCLK_ENA, WM8990_OPCLK_ENA);
|
||||
|
||||
snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
|
||||
snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
|
||||
@ -1392,6 +1380,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
|
||||
.reg_cache_size = ARRAY_SIZE(wm8990_reg),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = wm8990_reg,
|
||||
.volatile_register = wm8990_volatile_register,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2007-2010 Wolfson Microelectronics PLC.
|
||||
* Author: Graeme Gregory
|
||||
* linux@wolfsonmicro.com
|
||||
* Graeme.Gregory@wolfsonmicro.com
|
||||
*
|
||||
* 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
|
||||
@ -393,7 +393,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
|
||||
(1 << WM8991_AINRMUX_PWR_BIT)))
|
||||
reg |= WM8991_AINR_ENA;
|
||||
else
|
||||
reg &= ~WM8991_AINL_ENA;
|
||||
reg &= ~WM8991_AINR_ENA;
|
||||
|
||||
snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
|
||||
return 0;
|
||||
@ -1264,7 +1264,6 @@ static int wm8991_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8991_priv *wm8991;
|
||||
int ret;
|
||||
unsigned int reg;
|
||||
|
||||
wm8991 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
@ -1282,19 +1281,18 @@ static int wm8991_probe(struct snd_soc_codec *codec)
|
||||
|
||||
wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
|
||||
snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
|
||||
snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
|
||||
WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
|
||||
|
||||
reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
|
||||
~WM8991_GPIO1_SEL_MASK;
|
||||
snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
|
||||
snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
|
||||
WM8991_GPIO1_SEL_MASK, 1);
|
||||
|
||||
reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
|
||||
snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
|
||||
WM8991_VMID_MODE_MASK);
|
||||
snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
|
||||
WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
|
||||
WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
|
||||
|
||||
reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
|
||||
snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
|
||||
snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
|
||||
WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
|
||||
|
||||
snd_soc_write(codec, WM8991_DAC_CTRL, 0);
|
||||
snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
|
||||
|
@ -208,7 +208,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
|
||||
static int configure_clock(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||||
int old, new;
|
||||
int change, new;
|
||||
|
||||
/* Bring up the AIF clocks first */
|
||||
configure_aif_clock(codec, 0);
|
||||
@ -229,14 +229,11 @@ static int configure_clock(struct snd_soc_codec *codec)
|
||||
else
|
||||
new = 0;
|
||||
|
||||
old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC;
|
||||
|
||||
/* If there's no change then we're done. */
|
||||
if (old == new)
|
||||
change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
|
||||
WM8994_SYSCLK_SRC, new);
|
||||
if (!change)
|
||||
return 0;
|
||||
|
||||
snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new);
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
|
||||
return 0;
|
||||
@ -283,6 +280,7 @@ static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0);
|
||||
|
||||
#define WM8994_DRC_SWITCH(xname, reg, shift) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
@ -703,6 +701,13 @@ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
|
||||
7, 1, ng_tlv),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm1811_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0,
|
||||
mixin_boost_tlv),
|
||||
SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
|
||||
mixin_boost_tlv),
|
||||
};
|
||||
|
||||
static int clk_sys_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
@ -1414,7 +1419,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
|
||||
SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
|
||||
|
||||
@ -2053,6 +2058,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
|
||||
WM8958_CP_DISCH);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM1811:
|
||||
if (wm8994->revision < 2) {
|
||||
snd_soc_write(codec, 0x102, 0x3);
|
||||
snd_soc_write(codec, 0x5d, 0x7e);
|
||||
snd_soc_write(codec, 0x5e, 0x0);
|
||||
snd_soc_write(codec, 0x102, 0x0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Discharge LINEOUT1 & 2 */
|
||||
@ -2168,10 +2182,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
|
||||
/* The AIF2 format configuration needs to be mirrored to AIF3
|
||||
* on WM8958 if it's in use so just do it all the time. */
|
||||
if (control->type == WM8958 && dai->id == 2)
|
||||
switch (control->type) {
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
if (dai->id == 2)
|
||||
snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
|
||||
WM8994_AIF1_LRCLK_INV |
|
||||
WM8958_AIF3_FMT_MASK, aif1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, aif1_reg,
|
||||
WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV |
|
||||
@ -2213,7 +2235,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct wm8994 *control = codec->control_data;
|
||||
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||||
int aif1_reg;
|
||||
int aif2_reg;
|
||||
@ -2256,14 +2277,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
|
||||
dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (control->type) {
|
||||
case WM8958:
|
||||
aif1_reg = WM8958_AIF3_CONTROL_1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2384,6 +2397,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
|
||||
switch (dai->id) {
|
||||
case 3:
|
||||
switch (control->type) {
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
aif1_reg = WM8958_AIF3_CONTROL_1;
|
||||
break;
|
||||
@ -2424,7 +2438,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
|
||||
rate_reg = WM8994_AIF1_RATE;
|
||||
break;
|
||||
case 2:
|
||||
rate_reg = WM8994_AIF1_RATE;
|
||||
rate_reg = WM8994_AIF2_RATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2614,6 +2628,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
case WM8994:
|
||||
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
|
||||
break;
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
|
||||
WM8958_MICD_ENA, 0);
|
||||
@ -2682,6 +2697,7 @@ static int wm8994_resume(struct snd_soc_codec *codec)
|
||||
snd_soc_update_bits(codec, WM8994_MICBIAS,
|
||||
WM8994_MICD_ENA, WM8994_MICD_ENA);
|
||||
break;
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
if (wm8994->jack_cb)
|
||||
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
|
||||
@ -2980,8 +2996,13 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
||||
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm8994 *control = codec->control_data;
|
||||
|
||||
if (control->type != WM8958)
|
||||
switch (control->type) {
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (jack) {
|
||||
if (!cb) {
|
||||
@ -3135,6 +3156,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
||||
wm8994->hubs.dcs_readback_mode = 1;
|
||||
break;
|
||||
|
||||
case WM1811:
|
||||
wm8994->hubs.dcs_readback_mode = 2;
|
||||
wm8994->hubs.no_series_update = 1;
|
||||
|
||||
switch (wm8994->revision) {
|
||||
case 0:
|
||||
case 1:
|
||||
wm8994->hubs.dcs_codes_l = -9;
|
||||
wm8994->hubs.dcs_codes_r = -5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
|
||||
WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3195,6 +3234,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
||||
break;
|
||||
|
||||
case WM8958:
|
||||
case WM1811:
|
||||
if (wm8994->micdet_irq) {
|
||||
ret = request_threaded_irq(wm8994->micdet_irq, NULL,
|
||||
wm8958_mic_irq,
|
||||
@ -3357,6 +3397,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
||||
ARRAY_SIZE(wm8994_dac_widgets));
|
||||
}
|
||||
break;
|
||||
|
||||
case WM1811:
|
||||
snd_soc_add_controls(codec, wm8958_snd_controls,
|
||||
ARRAY_SIZE(wm8958_snd_controls));
|
||||
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
|
||||
ARRAY_SIZE(wm8958_dapm_widgets));
|
||||
snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
|
||||
ARRAY_SIZE(wm8994_lateclk_widgets));
|
||||
snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
|
||||
ARRAY_SIZE(wm8994_adc_widgets));
|
||||
snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
|
||||
ARRAY_SIZE(wm8994_dac_widgets));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -3393,6 +3446,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
||||
|
||||
wm8958_dsp2_init(codec);
|
||||
break;
|
||||
case WM1811:
|
||||
snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
|
||||
ARRAY_SIZE(wm8994_lateclk_intercon));
|
||||
snd_soc_dapm_add_routes(dapm, wm8958_intercon,
|
||||
ARRAY_SIZE(wm8958_intercon));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3448,6 +3507,7 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
|
||||
wm8994);
|
||||
break;
|
||||
|
||||
case WM1811:
|
||||
case WM8958:
|
||||
if (wm8994->micdet_irq)
|
||||
free_irq(wm8994->micdet_irq, wm8994);
|
||||
|
@ -485,7 +485,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
|
||||
static int configure_clock(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8995_priv *wm8995;
|
||||
int old, new;
|
||||
int change, new;
|
||||
|
||||
wm8995 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
@ -509,14 +509,10 @@ static int configure_clock(struct snd_soc_codec *codec)
|
||||
else
|
||||
new = 0;
|
||||
|
||||
old = snd_soc_read(codec, WM8995_CLOCKING_1) & WM8995_SYSCLK_SRC;
|
||||
|
||||
/* If there's no change then we're done. */
|
||||
if (old == new)
|
||||
return 0;
|
||||
|
||||
snd_soc_update_bits(codec, WM8995_CLOCKING_1,
|
||||
change = snd_soc_update_bits(codec, WM8995_CLOCKING_1,
|
||||
WM8995_SYSCLK_SRC_MASK, new);
|
||||
if (!change)
|
||||
return 0;
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
|
||||
@ -1573,9 +1569,16 @@ static int wm8995_resume(struct snd_soc_codec *codec)
|
||||
static int wm8995_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8995_priv *wm8995;
|
||||
int i;
|
||||
|
||||
wm8995 = snd_soc_codec_get_drvdata(codec);
|
||||
wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i)
|
||||
regulator_unregister_notifier(wm8995->supplies[i].consumer,
|
||||
&wm8995->disable_nb[i]);
|
||||
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -641,6 +641,14 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
|
||||
|
||||
SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
|
||||
SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
|
||||
|
||||
SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
|
||||
SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
|
||||
SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
|
||||
|
||||
SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
|
||||
SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
|
||||
SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8996_eq_controls[] = {
|
||||
@ -1105,9 +1113,9 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
|
||||
SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
|
||||
WM8996_POWER_MANAGEMENT_4, 8, 0),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0,
|
||||
SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
|
||||
WM8996_POWER_MANAGEMENT_6, 9, 0),
|
||||
SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1,
|
||||
SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
|
||||
WM8996_POWER_MANAGEMENT_6, 8, 0),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
|
||||
@ -1912,7 +1920,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
|
||||
snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
|
||||
lrclk);
|
||||
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
|
||||
WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
|
||||
WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2698,7 +2706,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
|
||||
init_completion(&wm8996->fll_lock);
|
||||
|
||||
dapm->idle_bias_off = true;
|
||||
dapm->bias_level = SND_SOC_BIAS_OFF;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
|
||||
if (ret != 0) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user