Commit d71f4cec authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/asoc' into for-linus

Conflicts:
	sound/soc/codecs/ad1938.c
parents 19008bda ad8332c1
...@@ -605,7 +605,11 @@ static __init void dm365_evm_init(void) ...@@ -605,7 +605,11 @@ static __init void dm365_evm_init(void)
/* maybe setup mmc1/etc ... _after_ mmc0 */ /* maybe setup mmc1/etc ... _after_ mmc0 */
evm_init_cpld(); evm_init_cpld();
#ifdef CONFIG_SND_DM365_AIC3X_CODEC
dm365_init_asp(&dm365_evm_snd_data); dm365_init_asp(&dm365_evm_snd_data);
#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
dm365_init_vc(&dm365_evm_snd_data);
#endif
dm365_init_rtc(); dm365_init_rtc();
dm365_init_ks(&dm365evm_ks_data); dm365_init_ks(&dm365evm_ks_data);
......
...@@ -187,32 +187,28 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = { ...@@ -187,32 +187,28 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
.phys_base = OMAP44XX_MCBSP1_BASE, .phys_base = OMAP44XX_MCBSP1_BASE,
.dma_rx_sync = OMAP44XX_DMA_MCBSP1_RX, .dma_rx_sync = OMAP44XX_DMA_MCBSP1_RX,
.dma_tx_sync = OMAP44XX_DMA_MCBSP1_TX, .dma_tx_sync = OMAP44XX_DMA_MCBSP1_TX,
.rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = OMAP44XX_IRQ_MCBSP1,
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
.ops = &omap2_mcbsp_ops, .ops = &omap2_mcbsp_ops,
}, },
{ {
.phys_base = OMAP44XX_MCBSP2_BASE, .phys_base = OMAP44XX_MCBSP2_BASE,
.dma_rx_sync = OMAP44XX_DMA_MCBSP2_RX, .dma_rx_sync = OMAP44XX_DMA_MCBSP2_RX,
.dma_tx_sync = OMAP44XX_DMA_MCBSP2_TX, .dma_tx_sync = OMAP44XX_DMA_MCBSP2_TX,
.rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = OMAP44XX_IRQ_MCBSP2,
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
.ops = &omap2_mcbsp_ops, .ops = &omap2_mcbsp_ops,
}, },
{ {
.phys_base = OMAP44XX_MCBSP3_BASE, .phys_base = OMAP44XX_MCBSP3_BASE,
.dma_rx_sync = OMAP44XX_DMA_MCBSP3_RX, .dma_rx_sync = OMAP44XX_DMA_MCBSP3_RX,
.dma_tx_sync = OMAP44XX_DMA_MCBSP3_TX, .dma_tx_sync = OMAP44XX_DMA_MCBSP3_TX,
.rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = OMAP44XX_IRQ_MCBSP3,
.tx_irq = INT_24XX_MCBSP3_IRQ_TX,
.ops = &omap2_mcbsp_ops, .ops = &omap2_mcbsp_ops,
}, },
{ {
.phys_base = OMAP44XX_MCBSP4_BASE, .phys_base = OMAP44XX_MCBSP4_BASE,
.dma_rx_sync = OMAP44XX_DMA_MCBSP4_RX, .dma_rx_sync = OMAP44XX_DMA_MCBSP4_RX,
.dma_tx_sync = OMAP44XX_DMA_MCBSP4_TX, .dma_tx_sync = OMAP44XX_DMA_MCBSP4_TX,
.rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = OMAP44XX_IRQ_MCBSP4,
.tx_irq = INT_24XX_MCBSP4_IRQ_TX,
.ops = &omap2_mcbsp_ops, .ops = &omap2_mcbsp_ops,
}, },
}; };
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <mach/regs-mem.h> #include <mach/regs-mem.h>
#include <mach/regs-lcd.h> #include <mach/regs-lcd.h>
#include <mach/regs-sdi.h> #include <mach/regs-sdi.h>
#include <plat/regs-s3c2412-iis.h>
#include <plat/regs-iis.h> #include <plat/regs-iis.h>
#include <plat/regs-spi.h> #include <plat/regs-spi.h>
...@@ -119,13 +118,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = { ...@@ -119,13 +118,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
.name = "i2s-sdi", .name = "i2s-sdi",
.channels = MAP(S3C2412_DMAREQSEL_I2SRX), .channels = MAP(S3C2412_DMAREQSEL_I2SRX),
.channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX), .channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX),
.hw_addr.from = S3C2410_PA_IIS + S3C2412_IISRXD,
}, },
[DMACH_I2S_OUT] = { [DMACH_I2S_OUT] = {
.name = "i2s-sdo", .name = "i2s-sdo",
.channels = MAP(S3C2412_DMAREQSEL_I2STX), .channels = MAP(S3C2412_DMAREQSEL_I2STX),
.channels_rx = MAP(S3C2412_DMAREQSEL_I2STX), .channels_rx = MAP(S3C2412_DMAREQSEL_I2STX),
.hw_addr.to = S3C2410_PA_IIS + S3C2412_IISTXD,
}, },
[DMACH_USB_EP1] = { [DMACH_USB_EP1] = {
.name = "usb-ep1", .name = "usb-ep1",
......
...@@ -149,6 +149,8 @@ ...@@ -149,6 +149,8 @@
#define OMAP_MCBSP_REG_WAKEUPEN 0xA8 #define OMAP_MCBSP_REG_WAKEUPEN 0xA8
#define OMAP_MCBSP_REG_XCCR 0xAC #define OMAP_MCBSP_REG_XCCR 0xAC
#define OMAP_MCBSP_REG_RCCR 0xB0 #define OMAP_MCBSP_REG_RCCR 0xB0
#define OMAP_MCBSP_REG_XBUFFSTAT 0xB4
#define OMAP_MCBSP_REG_RBUFFSTAT 0xB8
#define OMAP_MCBSP_REG_SSELCR 0xBC #define OMAP_MCBSP_REG_SSELCR 0xBC
#define OMAP_ST_REG_REV 0x00 #define OMAP_ST_REG_REV 0x00
...@@ -471,6 +473,8 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); ...@@ -471,6 +473,8 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
u16 omap_mcbsp_get_tx_delay(unsigned int id);
u16 omap_mcbsp_get_rx_delay(unsigned int id);
int omap_mcbsp_get_dma_op_mode(unsigned int id); int omap_mcbsp_get_dma_op_mode(unsigned int id);
#else #else
static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
...@@ -479,6 +483,8 @@ static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) ...@@ -479,6 +483,8 @@ static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
{ } { }
static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; } static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
#endif #endif
int omap_mcbsp_request(unsigned int id); int omap_mcbsp_request(unsigned int id);
......
...@@ -489,7 +489,7 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) ...@@ -489,7 +489,7 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
{ {
struct omap_mcbsp *mcbsp; struct omap_mcbsp *mcbsp;
if (!cpu_is_omap34xx()) if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
return; return;
if (!omap_mcbsp_check_valid_id(id)) { if (!omap_mcbsp_check_valid_id(id)) {
...@@ -511,7 +511,7 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) ...@@ -511,7 +511,7 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
{ {
struct omap_mcbsp *mcbsp; struct omap_mcbsp *mcbsp;
if (!cpu_is_omap34xx()) if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
return; return;
if (!omap_mcbsp_check_valid_id(id)) { if (!omap_mcbsp_check_valid_id(id)) {
...@@ -560,6 +560,61 @@ u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) ...@@ -560,6 +560,61 @@ u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
} }
EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
#define MCBSP2_FIFO_SIZE 0x500 /* 1024 + 256 locations */
#define MCBSP1345_FIFO_SIZE 0x80 /* 128 locations */
/*
* omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
*/
u16 omap_mcbsp_get_tx_delay(unsigned int id)
{
struct omap_mcbsp *mcbsp;
u16 buffstat;
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return -ENODEV;
}
mcbsp = id_to_mcbsp_ptr(id);
/* Returns the number of free locations in the buffer */
buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
/* Number of slots are different in McBSP ports */
if (mcbsp->id == 2)
return MCBSP2_FIFO_SIZE - buffstat;
else
return MCBSP1345_FIFO_SIZE - buffstat;
}
EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
/*
* omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
* to reach the threshold value (when the DMA will be triggered to read it)
*/
u16 omap_mcbsp_get_rx_delay(unsigned int id)
{
struct omap_mcbsp *mcbsp;
u16 buffstat, threshold;
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return -ENODEV;
}
mcbsp = id_to_mcbsp_ptr(id);
/* Returns the number of used locations in the buffer */
buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
/* RX threshold */
threshold = MCBSP_READ(mcbsp, THRSH1);
/* Return the number of location till we reach the threshold limit */
if (threshold <= buffstat)
return 0;
else
return threshold - buffstat;
}
EXPORT_SYMBOL(omap_mcbsp_get_rx_delay);
/* /*
* omap_mcbsp_get_dma_op_mode just return the current configured * omap_mcbsp_get_dma_op_mode just return the current configured
* operating mode for the mcbsp channel * operating mode for the mcbsp channel
...@@ -587,7 +642,7 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) ...@@ -587,7 +642,7 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
* Enable wakup behavior, smart idle and all wakeups * Enable wakup behavior, smart idle and all wakeups
* REVISIT: some wakeups may be unnecessary * REVISIT: some wakeups may be unnecessary
*/ */
if (cpu_is_omap34xx()) { if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
u16 syscon; u16 syscon;
syscon = MCBSP_READ(mcbsp, SYSCON); syscon = MCBSP_READ(mcbsp, SYSCON);
...@@ -610,7 +665,7 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) ...@@ -610,7 +665,7 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
/* /*
* Disable wakup behavior, smart idle and all wakeups * Disable wakup behavior, smart idle and all wakeups
*/ */
if (cpu_is_omap34xx()) { if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
u16 syscon; u16 syscon;
syscon = MCBSP_READ(mcbsp, SYSCON); syscon = MCBSP_READ(mcbsp, SYSCON);
...@@ -724,14 +779,17 @@ int omap_mcbsp_request(unsigned int id) ...@@ -724,14 +779,17 @@ int omap_mcbsp_request(unsigned int id)
goto err_clk_disable; goto err_clk_disable;
} }
init_completion(&mcbsp->rx_irq_completion); if (mcbsp->rx_irq) {
err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, init_completion(&mcbsp->rx_irq_completion);
err = request_irq(mcbsp->rx_irq,
omap_mcbsp_rx_irq_handler,
0, "McBSP", (void *)mcbsp); 0, "McBSP", (void *)mcbsp);
if (err != 0) { if (err != 0) {
dev_err(mcbsp->dev, "Unable to request RX IRQ %d " dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
"for McBSP%d\n", mcbsp->rx_irq, "for McBSP%d\n", mcbsp->rx_irq,
mcbsp->id); mcbsp->id);
goto err_free_irq; goto err_free_irq;
}
} }
} }
...@@ -781,7 +839,8 @@ void omap_mcbsp_free(unsigned int id) ...@@ -781,7 +839,8 @@ void omap_mcbsp_free(unsigned int id)
if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
/* Free IRQs */ /* Free IRQs */
free_irq(mcbsp->rx_irq, (void *)mcbsp); if (mcbsp->rx_irq)
free_irq(mcbsp->rx_irq, (void *)mcbsp);
free_irq(mcbsp->tx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp);
} }
...@@ -855,7 +914,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) ...@@ -855,7 +914,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
} }
if (cpu_is_omap2430() || cpu_is_omap34xx()) { if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
/* Release the transmitter and receiver */ /* Release the transmitter and receiver */
w = MCBSP_READ_CACHE(mcbsp, XCCR); w = MCBSP_READ_CACHE(mcbsp, XCCR);
w &= ~(tx ? XDISABLE : 0); w &= ~(tx ? XDISABLE : 0);
...@@ -885,7 +944,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) ...@@ -885,7 +944,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
/* Reset transmitter */ /* Reset transmitter */
tx &= 1; tx &= 1;
if (cpu_is_omap2430() || cpu_is_omap34xx()) { if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
w = MCBSP_READ_CACHE(mcbsp, XCCR); w = MCBSP_READ_CACHE(mcbsp, XCCR);
w |= (tx ? XDISABLE : 0); w |= (tx ? XDISABLE : 0);
MCBSP_WRITE(mcbsp, XCCR, w); MCBSP_WRITE(mcbsp, XCCR, w);
...@@ -895,7 +954,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) ...@@ -895,7 +954,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
/* Reset receiver */ /* Reset receiver */
rx &= 1; rx &= 1;
if (cpu_is_omap2430() || cpu_is_omap34xx()) { if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
w = MCBSP_READ_CACHE(mcbsp, RCCR); w = MCBSP_READ_CACHE(mcbsp, RCCR);
w |= (rx ? RDISABLE : 0); w |= (rx ? RDISABLE : 0);
MCBSP_WRITE(mcbsp, RCCR, w); MCBSP_WRITE(mcbsp, RCCR, w);
......
...@@ -81,6 +81,18 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -81,6 +81,18 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
} }
static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
if (!wm8994->irq_base)
return -EINVAL;
return wm8994->irq_base + offset;
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{ {
......
...@@ -53,6 +53,10 @@ config MFD_SH_MOBILE_SDHI ...@@ -53,6 +53,10 @@ config MFD_SH_MOBILE_SDHI
This driver supports the SDHI hardware block found in many This driver supports the SDHI hardware block found in many
SuperH Mobile SoCs. SuperH Mobile SoCs.
config MFD_DAVINCI_VOICECODEC
tristate
select MFD_CORE
config MFD_DM355EVM_MSP config MFD_DM355EVM_MSP
bool "DaVinci DM355 EVM microcontroller" bool "DaVinci DM355 EVM microcontroller"
depends on I2C && MACH_DAVINCI_DM355_EVM depends on I2C && MACH_DAVINCI_DM355_EVM
...@@ -297,9 +301,9 @@ config MFD_WM8350_I2C ...@@ -297,9 +301,9 @@ config MFD_WM8350_I2C
selected to enable support for the functionality of the chip. selected to enable support for the functionality of the chip.
config MFD_WM8994 config MFD_WM8994
tristate "Support Wolfson Microelectronics WM8994" bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE select MFD_CORE
depends on I2C depends on I2C=y && GENERIC_HARDIRQS
help help
The WM8994 is a highly integrated hi-fi CODEC designed for The WM8994 is a highly integrated hi-fi CODEC designed for
smartphone applicatiosn. As well as audio functionality it smartphone applicatiosn. As well as audio functionality it
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
...@@ -25,7 +26,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o ...@@ -25,7 +26,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_MENELAUS) += menelaus.o
......
/*
* DaVinci Voice Codec Core Interface for TI platforms
*
* Copyright (C) 2010 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.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 Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <sound/pcm.h>
#include <linux/mfd/davinci_voicecodec.h>
u32 davinci_vc_read(struct davinci_vc *davinci_vc, int reg)
{
return __raw_readl(davinci_vc->base + reg);
}
void davinci_vc_write(struct davinci_vc *davinci_vc,
int reg, u32 val)
{
__raw_writel(val, davinci_vc->base + reg);
}
static int __init davinci_vc_probe(struct platform_device *pdev)
{
struct davinci_vc *davinci_vc;
struct resource *res, *mem;
struct mfd_cell *cell = NULL;
int ret;
davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL);
if (!davinci_vc) {
dev_dbg(&pdev->dev,
"could not allocate memory for private data\n");
return -ENOMEM;
}
davinci_vc->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(davinci_vc->clk)) {
dev_dbg(&pdev->dev,
"could not get the clock for voice codec\n");
ret = -ENODEV;
goto fail1;
}
clk_enable(davinci_vc->clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no mem resource\n");
ret = -ENODEV;
goto fail2;
}
davinci_vc->pbase = res->start;
davinci_vc->base_size = resource_size(res);
mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size,
pdev->name);
if (!mem) {
dev_err(&pdev->dev, "VCIF region already claimed\n");
ret = -EBUSY;
goto fail2;
}
davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size);
if (!davinci_vc->base) {
dev_err(&pdev->dev, "can't ioremap mem resource.\n");
ret = -ENOMEM;
goto fail3;
}
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
return -ENXIO;
}
davinci_vc->davinci_vcif.dma_tx_channel = res->start;
davinci_vc->davinci_vcif.dma_tx_addr =
(dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_WFIFO);
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
return -ENXIO;
}
davinci_vc->davinci_vcif.dma_rx_channel = res->start;
davinci_vc->davinci_vcif.dma_rx_addr =
(dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_RFIFO);
davinci_vc->dev = &pdev->dev;
davinci_vc->pdev = pdev;
/* Voice codec interface client */
cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
cell->name = "davinci_vcif";
cell->driver_data = davinci_vc;
/* Voice codec CQ93VC client */
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
cell->name = "cq93vc";
cell->driver_data = davinci_vc;
ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
DAVINCI_VC_CELLS, NULL, 0);
if (ret != 0) {
dev_err(&pdev->dev, "fail to register client devices\n");
goto fail4;
}
return 0;
fail4:
iounmap(davinci_vc->base);
fail3:
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
fail2:
clk_disable(davinci_vc->clk);
clk_put(davinci_vc->clk);
davinci_vc->clk = NULL;
fail1:
kfree(davinci_vc);
return ret;
}
static int __devexit davinci_vc_remove(struct platform_device *pdev)
{
struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
mfd_remove_devices(&pdev->dev);
iounmap(davinci_vc->base);
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
clk_disable(davinci_vc->clk);
clk_put(davinci_vc->clk);
davinci_vc->clk = NULL;
kfree(davinci_vc);
return 0;
}
static struct platform_driver davinci_vc_driver = {
.driver = {
.name = "davinci_voicecodec",
.owner = THIS_MODULE,
},
.remove = __devexit_p(davinci_vc_remove),
};
static int __init davinci_vc_init(void)
{
return platform_driver_probe(&davinci_vc_driver, davinci_vc_probe);
}
module_init(davinci_vc_init);
static void __exit davinci_vc_exit(void)
{
platform_driver_unregister(&davinci_vc_driver);
}
module_exit(davinci_vc_exit);
MODULE_AUTHOR("Miguel Aguilar");
MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface");
MODULE_LICENSE("GPL");
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
#endif #endif
#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\ #if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
defined(CONFIG_SND_SOC_TWL6030) || defined(CONFIG_SND_SOC_TWL6030_MODULE) defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
#define twl_has_codec() true #define twl_has_codec() true
#else #else
#define twl_has_codec() false #define twl_has_codec() false
...@@ -708,7 +708,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) ...@@ -708,7 +708,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* Phoenix*/ /* Phoenix*/
if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
child = add_child(sub_chip_id, "twl6030_codec", child = add_child(sub_chip_id, "twl6040_codec",
pdata->codec, sizeof(*pdata->codec), pdata->codec, sizeof(*pdata->codec),
false, 0, 0); false, 0, 0);
if (IS_ERR(child)) if (IS_ERR(child))
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h> #include <linux/mfd/wm831x/pdata.h>
#include <linux/mfd/wm831x/gpio.h>
#include <linux/mfd/wm831x/irq.h> #include <linux/mfd/wm831x/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -388,12 +389,41 @@ static void wm831x_irq_mask(unsigned int irq) ...@@ -388,12 +389,41 @@ static void wm831x_irq_mask(unsigned int irq)
wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
} }
static int wm831x_irq_set_type(unsigned int irq, unsigned int type)
{
struct wm831x *wm831x = get_irq_chip_data(irq);
int val;
irq = irq - wm831x->irq_base;
if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11)
return -EINVAL;
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
val = WM831X_GPN_INT_MODE;
break;
case IRQ_TYPE_EDGE_RISING:
val = WM831X_GPN_POL;
break;
case IRQ_TYPE_EDGE_FALLING:
val = 0;
break;
default:
return -EINVAL;
}
return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
}
static struct irq_chip wm831x_irq_chip = { static struct irq_chip wm831x_irq_chip = {
.name = "wm831x", .name = "wm831x",
.bus_lock = wm831x_irq_lock, .bus_lock = wm831x_irq_lock,
.bus_sync_unlock = wm831x_irq_sync_unlock, .bus_sync_unlock = wm831x_irq_sync_unlock,
.mask = wm831x_irq_mask, .mask = wm831x_irq_mask,
.unmask = wm831x_irq_unmask, .unmask = wm831x_irq_unmask,
.set_type = wm831x_irq_set_type,
}; };
/* The processing of the primary interrupt occurs in a thread so that /* The processing of the primary interrupt occurs in a thread so that
......
...@@ -173,9 +173,34 @@ static struct mfd_cell wm8994_regulator_devs[] = { ...@@ -173,9 +173,34 @@ static struct mfd_cell wm8994_regulator_devs[] = {
{ .name = "wm8994-ldo", .id = 2 }, { .name = "wm8994-ldo", .id = 2 },
}; };
static struct resource wm8994_codec_resources[] = {
{
.start = WM8994_IRQ_TEMP_SHUT,
.end = WM8994_IRQ_TEMP_WARN,
.flags = IORESOURCE_IRQ,
},
};
static struct resource wm8994_gpio_resources[] = {
{
.start = WM8994_IRQ_GPIO(1),
.end = WM8994_IRQ_GPIO(11),
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell wm8994_devs[] = { static struct mfd_cell wm8994_devs[] = {
{ .name = "wm8994-codec" }, {
{ .name = "wm8994-gpio" }, .name = "wm8994-codec",
.num_resources = ARRAY_SIZE(wm8994_codec_resources),
.resources = wm8994_codec_resources,
},
{
.name = "wm8994-gpio",
.num_resources = ARRAY_SIZE(wm8994_gpio_resources),
.resources = wm8994_gpio_resources,
},
}; };
/* /*
...@@ -236,6 +261,11 @@ static int wm8994_device_resume(struct device *dev) ...@@ -236,6 +261,11 @@ static int wm8994_device_resume(struct device *dev)
return ret; return ret;
} }
ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
if (ret < 0)
dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);
ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2, ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
&wm8994->ldo_regs); &wm8994->ldo_regs);
if (ret < 0) if (ret < 0)
...@@ -348,6 +378,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) ...@@ -348,6 +378,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
if (pdata) { if (pdata) {
wm8994->irq_base = pdata->irq_base;
wm8994->gpio_base = pdata->gpio_base; wm8994->gpio_base = pdata->gpio_base;
/* GPIO configuration is only applied if it's non-zero */ /* GPIO configuration is only applied if it's non-zero */
...@@ -375,16 +406,20 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) ...@@ -375,16 +406,20 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
WM8994_LDO1_DISCH, 0); WM8994_LDO1_DISCH, 0);
} }
wm8994_irq_init(wm8994);
ret = mfd_add_devices(wm8994->dev, -1, ret = mfd_add_devices(wm8994->dev, -1,
wm8994_devs, ARRAY_SIZE(wm8994_devs), wm8994_devs, ARRAY_SIZE(wm8994_devs),
NULL, 0); NULL, 0);
if (ret != 0) { if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret); dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
goto err_enable; goto err_irq;
} }
return 0; return 0;
err_irq:
wm8994_irq_exit(wm8994);
err_enable: err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
wm8994->supplies); wm8994->supplies);
...@@ -401,6 +436,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) ...@@ -401,6 +436,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
static void wm8994_device_exit(struct wm8994 *wm8994) static void wm8994_device_exit(struct wm8994 *wm8994)
{ {
mfd_remove_devices(wm8994->dev); mfd_remove_devices(wm8994->dev);
wm8994_irq_exit(wm8994);
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
wm8994->supplies); wm8994->supplies);
regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
...@@ -469,6 +505,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, ...@@ -469,6 +505,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994->control_data = i2c; wm8994->control_data = i2c;
wm8994->read_dev = wm8994_i2c_read_device; wm8994->read_dev = wm8994_i2c_read_device;
wm8994->write_dev = wm8994_i2c_write_device; wm8994->write_dev = wm8994_i2c_write_device;
wm8994->irq = i2c->irq;
return wm8994_device_init(wm8994, id->driver_data, i2c->irq); return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
} }
......
/*
* wm8994-irq.c -- Interrupt controller support for Wolfson WM8994
*
* Copyright 2010 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/mfd/wm8994/core.h>
#include <linux/mfd/wm8994/registers.h>
#include <linux/delay.h>
struct wm8994_irq_data {
int reg;
int mask;
};
static struct wm8994_irq_data wm8994_irqs[] = {
[WM8994_IRQ_TEMP_SHUT] = {
.reg = 2,
.mask = WM8994_TEMP_SHUT_EINT,
},
[WM8994_IRQ_MIC1_DET] = {
.reg = 2,
.mask = WM8994_MIC1_DET_EINT,
},
[WM8994_IRQ_MIC1_SHRT] = {
.reg = 2,
.mask = WM8994_MIC1_SHRT_EINT,
},
[WM8994_IRQ_MIC2_DET] = {
.reg = 2,
.mask = WM8994_MIC2_DET_EINT,
},
[WM8994_IRQ_MIC2_SHRT] = {
.reg = 2,
.mask = WM8994_MIC2_SHRT_EINT,
},
[WM8994_IRQ_FLL1_LOCK] = {
.reg = 2,
.mask = WM8994_FLL1_LOCK_EINT,
},
[WM8994_IRQ_FLL2_LOCK] = {
.reg = 2,
.mask = WM8994_FLL2_LOCK_EINT,
},
[WM8994_IRQ_SRC1_LOCK] = {
.reg = 2,
.mask = WM8994_SRC1_LOCK_EINT,
},
[WM8994_IRQ_SRC2_LOCK] = {
.reg = 2,
.mask = WM8994_SRC2_LOCK_EINT,
},
[WM8994_IRQ_AIF1DRC1_SIG_DET] = {
.reg = 2,
.mask = WM8994_AIF1DRC1_SIG_DET,
},
[WM8994_IRQ_AIF1DRC2_SIG_DET] = {
.reg = 2,
.mask = WM8994_AIF1DRC2_SIG_DET_EINT,
},
[WM8994_IRQ_AIF2DRC_SIG_DET] = {
.reg = 2,
.mask = WM8994_AIF2DRC_SIG_DET_EINT,
},
[WM8994_IRQ_FIFOS_ERR] = {
.reg = 2,
.mask = WM8994_FIFOS_ERR_EINT,
},
[WM8994_IRQ_WSEQ_DONE] = {
.reg = 2,
.mask = WM8994_WSEQ_DONE_EINT,
},
[WM8994_IRQ_DCS_DONE] = {
.reg = 2,
.mask = WM8994_DCS_DONE_EINT,
},
[WM8994_IRQ_TEMP_WARN] = {
.reg = 2,
.mask = WM8994_TEMP_WARN_EINT,
},
[WM8994_IRQ_GPIO(1)] = {
.reg = 1,
.mask = WM8994_GP1_EINT,
},
[WM8994_IRQ_GPIO(2)] = {
.reg = 1,
.mask = WM8994_GP2_EINT,
},
[WM8994_IRQ_GPIO(3)] = {
.reg = 1,
.mask = WM8994_GP3_EINT,
},
[WM8994_IRQ_GPIO(4)] = {
.reg = 1,
.mask = WM8994_GP4_EINT,
},
[WM8994_IRQ_GPIO(5)] = {
.reg = 1,
.mask = WM8994_GP5_EINT,
},
[WM8994_IRQ_GPIO(6)] = {
.reg = 1,
.mask = WM8994_GP6_EINT,
},
[WM8994_IRQ_GPIO(7)] = {
.reg = 1,
.mask = WM8994_GP7_EINT,
},
[WM8994_IRQ_GPIO(8)] = {
.reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(9)] = {
.reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(10)] = {
.reg = 1,
.mask = WM8994_GP10_EINT,
},
[WM8994_IRQ_GPIO(11)] = {
.reg = 1,
.mask = WM8994_GP11_EINT,
},
};
static inline int irq_data_to_status_reg(struct wm8994_irq_data *irq_data)
{
return WM8994_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
}
static inline int irq_data_to_mask_reg(struct wm8994_irq_data *irq_data)
{
return WM8994_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
}
static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
int irq)
{
return &wm8994_irqs[irq - wm8994->irq_base];
}
static void wm8994_irq_lock(unsigned int irq)
{
struct wm8994 *wm8994 = get_irq_chip_data(irq);
mutex_lock(&wm8994->irq_lock);
}
static void wm8994_irq_sync_unlock(unsigned int irq)
{
struct wm8994 *wm8994 = get_irq_chip_data(irq);
int i;
for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
/* If there's been a change in the mask write it back
* to the hardware. */
if (wm8994->irq_masks_cur[i] != wm8994->irq_masks_cache[i]) {
wm8994->irq_masks_cache[i] = wm8994->irq_masks_cur[i];
wm8994_reg_write(wm8994,
WM8994_INTERRUPT_STATUS_1_MASK + i,
wm8994->irq_masks_cur[i]);
}
}
mutex_unlock(&wm8994->irq_lock);
}
static void wm8994_irq_unmask(unsigned int irq)
{
struct wm8994 *wm8994 = get_irq_chip_data(irq);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
static void wm8994_irq_mask(unsigned int irq)
{
struct wm8994 *wm8994 = get_irq_chip_data(irq);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
}
static struct irq_chip wm8994_irq_chip = {
.name = "wm8994",
.bus_lock = wm8994_irq_lock,
.bus_sync_unlock = wm8994_irq_sync_unlock,
.mask = wm8994_irq_mask,
.unmask = wm8994_irq_unmask,
};
/* The processing of the primary interrupt occurs in a thread so that
* we can interact with the device over I2C or SPI. */
static irqreturn_t wm8994_irq_thread(int irq, void *data)
{
struct wm8994 *wm8994 = data;
unsigned int i;
u16 status[WM8994_NUM_IRQ_REGS];
int ret;
ret = wm8994_bulk_read(wm8994, WM8994_INTERRUPT_STATUS_1,
WM8994_NUM_IRQ_REGS, status);
if (ret < 0) {
dev_err(wm8994->dev, "Failed to read interrupt status: %d\n",
ret);
return IRQ_NONE;
}
/* Apply masking */
for (i = 0; i < WM8994_NUM_IRQ_REGS; i++)
status[i] &= ~wm8994->irq_masks_cur[i];
/* Report */
for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
handle_nested_irq(wm8994->irq_base + i);
}
/* Ack any unmasked IRQs */
for (i = 0; i < ARRAY_SIZE(status); i++) {
if (status[i])
wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1 + i,
status[i]);
}
return IRQ_HANDLED;
}
int wm8994_irq_init(struct wm8994 *wm8994)
{
int i, cur_irq, ret;
mutex_init(&wm8994->irq_lock);
/* Mask the individual interrupt sources */
for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
wm8994->irq_masks_cur[i] = 0xffff;
wm8994->irq_masks_cache[i] = 0xffff;
wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK + i,
0xffff);
}
if (!wm8994->irq) {
dev_warn(wm8994->dev,
"No interrupt specified, no interrupts\n");
wm8994->irq_base = 0;
return 0;
}
if (!wm8994->irq_base) {
dev_err(wm8994->dev,
"No interrupt base specified, no interrupts\n");
return 0;
}
/* Register them with genirq */
for (cur_irq = wm8994->irq_base;
cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
cur_irq++) {
set_irq_chip_data(cur_irq, wm8994);
set_irq_chip_and_handler(cur_irq, &wm8994_irq_chip,
handle_edge_irq);
set_irq_nested_thread(cur_irq, 1);
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
set_irq_noprobe(cur_irq);
#endif
}
ret = request_threaded_irq(wm8994->irq, NULL, wm8994_irq_thread,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"wm8994", wm8994);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to request IRQ %d: %d\n",
wm8994->irq, ret);
return ret;
}
/* Enable top level interrupt if it was masked */
wm8994_reg_write(wm8994, WM8994_INTERRUPT_CONTROL, 0);
return 0;
}
void wm8994_irq_exit(struct wm8994 *wm8994)
{
if (wm8994->irq)
free_irq(wm8994->irq, wm8994);
}
...@@ -569,9 +569,9 @@ struct twl4030_codec_data { ...@@ -569,9 +569,9 @@ struct twl4030_codec_data {
struct twl4030_codec_audio_data *audio; struct twl4030_codec_audio_data *audio;
struct twl4030_codec_vibra_data *vibra; struct twl4030_codec_vibra_data *vibra;
/* twl6030 */ /* twl6040 */
int audpwron_gpio; /* audio power-on gpio */ int audpwron_gpio; /* audio power-on gpio */
int naudint_irq; /* audio interrupt */ int naudint_irq; /* audio interrupt */
}; };
struct twl4030_platform_data { struct twl4030_platform_data {
......
/*
* DaVinci Voice Codec Core Interface for TI platforms
*
* Copyright (C) 2010 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.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 Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LINUX_MFD_DAVINCI_VOICECODEC_H_
#define __LINUX_MFD_DAVINIC_VOICECODEC_H_
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <mach/edma.h>
/*
* Register values.
*/
#define DAVINCI_VC_PID 0x00
#define DAVINCI_VC_CTRL 0x04
#define DAVINCI_VC_INTEN 0x08
#define DAVINCI_VC_INTSTATUS 0x0c
#define DAVINCI_VC_INTCLR 0x10
#define DAVINCI_VC_EMUL_CTRL 0x14
#define DAVINCI_VC_RFIFO 0x20
#define DAVINCI_VC_WFIFO 0x24
#define DAVINCI_VC_FIFOSTAT 0x28
#define DAVINCI_VC_TST_CTRL 0x2C
#define DAVINCI_VC_REG05 0x94
#define DAVINCI_VC_REG09 0xA4
#define DAVINCI_VC_REG12 0xB0
/* DAVINCI_VC_CTRL bit fields */
#define DAVINCI_VC_CTRL_MASK 0x5500
#define DAVINCI_VC_CTRL_RSTADC BIT(0)
#define DAVINCI_VC_CTRL_RSTDAC BIT(1)
#define DAVINCI_VC_CTRL_RD_BITS_8 BIT(4)
#define DAVINCI_VC_CTRL_RD_UNSIGNED BIT(5)
#define DAVINCI_VC_CTRL_WD_BITS_8 BIT(6)
#define DAVINCI_VC_CTRL_WD_UNSIGNED BIT(7)
#define DAVINCI_VC_CTRL_RFIFOEN BIT(8)
#define DAVINCI_VC_CTRL_RFIFOCL BIT(9)
#define DAVINCI_VC_CTRL_RFIFOMD_WORD_1 BIT(10)
#define DAVINCI_VC_CTRL_WFIFOEN BIT(12)
#define DAVINCI_VC_CTRL_WFIFOCL BIT(13)
#define DAVINCI_VC_CTRL_WFIFOMD_WORD_1 BIT(14)
/* DAVINCI_VC_INT bit fields */
#define DAVINCI_VC_INT_MASK 0x3F
#define DAVINCI_VC_INT_RDRDY_MASK BIT(0)
#define DAVINCI_VC_INT_RERROVF_MASK BIT(1)
#define DAVINCI_VC_INT_RERRUDR_MASK BIT(2)
#define DAVINCI_VC_INT_WDREQ_MASK BIT(3)
#define DAVINCI_VC_INT_WERROVF_MASKBIT BIT(4)
#define DAVINCI_VC_INT_WERRUDR_MASK BIT(5)
/* DAVINCI_VC_REG05 bit fields */
#define DAVINCI_VC_REG05_PGA_GAIN 0x07
/* DAVINCI_VC_REG09 bit fields */
#define DAVINCI_VC_REG09_MUTE 0x40
#define DAVINCI_VC_REG09_DIG_ATTEN 0x3F
/* DAVINCI_VC_REG12 bit fields */
#define DAVINCI_VC_REG12_POWER_ALL_ON 0xFD
#define DAVINCI_VC_REG12_POWER_ALL_OFF 0x00
#define DAVINCI_VC_CELLS 2
enum davinci_vc_cells {
DAVINCI_VC_VCIF_CELL,
DAVINCI_VC_CQ93VC_CELL,
};
struct davinci_vcif {
struct platform_device *pdev;
u32 dma_tx_channel;
u32 dma_rx_channel;
dma_addr_t dma_tx_addr;
dma_addr_t dma_rx_addr;
};
struct cq93vc {
struct platform_device *pdev;
struct snd_soc_codec *codec;
u32 sysclk;
};
struct davinci_vc;
struct davinci_vc {
/* Device data */
struct device *dev;
struct platform_device *pdev;
struct clk *clk;
/* Memory resources */
void __iomem *base;
resource_size_t pbase;
size_t base_size;
/* MFD cells */
struct mfd_cell cells[DAVINCI_VC_CELLS];
/* Client devices */
struct davinci_vcif davinci_vcif;
struct cq93vc cq93vc;
};
#endif
...@@ -492,6 +492,8 @@ ...@@ -492,6 +492,8 @@
*/ */
#define WM8350_JACK_L_LVL 0x0800 #define WM8350_JACK_L_LVL 0x0800
#define WM8350_JACK_R_LVL 0x0400 #define WM8350_JACK_R_LVL 0x0400
#define WM8350_JACK_MICSCD_LVL 0x0200
#define WM8350_JACK_MICSD_LVL 0x0100
/* /*
* WM8350 Platform setup * WM8350 Platform setup
......
...@@ -15,14 +15,38 @@ ...@@ -15,14 +15,38 @@
#ifndef __MFD_WM8994_CORE_H__ #ifndef __MFD_WM8994_CORE_H__
#define __MFD_WM8994_CORE_H__ #define __MFD_WM8994_CORE_H__
#include <linux/interrupt.h>
struct regulator_dev; struct regulator_dev;
struct regulator_bulk_data; struct regulator_bulk_data;
#define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_GPIO_REGS 11
#define WM8994_NUM_LDO_REGS 2 #define WM8994_NUM_LDO_REGS 2
#define WM8994_NUM_IRQ_REGS 2
#define WM8994_IRQ_TEMP_SHUT 0
#define WM8994_IRQ_MIC1_DET 1
#define WM8994_IRQ_MIC1_SHRT 2
#define WM8994_IRQ_MIC2_DET 3
#define WM8994_IRQ_MIC2_SHRT 4
#define WM8994_IRQ_FLL1_LOCK 5
#define WM8994_IRQ_FLL2_LOCK 6
#define WM8994_IRQ_SRC1_LOCK 7
#define WM8994_IRQ_SRC2_LOCK 8
#define WM8994_IRQ_AIF1DRC1_SIG_DET 9
#define WM8994_IRQ_AIF1DRC2_SIG_DET 10
#define WM8994_IRQ_AIF2DRC_SIG_DET 11
#define WM8994_IRQ_FIFOS_ERR 12
#define WM8994_IRQ_WSEQ_DONE 13
#define WM8994_IRQ_DCS_DONE 14
#define WM8994_IRQ_TEMP_WARN 15
/* GPIOs in the chip are numbered from 1-11 */
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
struct wm8994 { struct wm8994 {
struct mutex io_lock; struct mutex io_lock;
struct mutex irq_lock;
struct device *dev; struct device *dev;
int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
...@@ -33,6 +57,11 @@ struct wm8994 { ...@@ -33,6 +57,11 @@ struct wm8994 {
void *control_data; void *control_data;
int gpio_base; int gpio_base;
int irq_base;
int irq;
u16 irq_masks_cur[WM8994_NUM_IRQ_REGS];
u16 irq_masks_cache[WM8994_NUM_IRQ_REGS];
/* Used over suspend/resume */ /* Used over suspend/resume */
u16 ldo_regs[WM8994_NUM_LDO_REGS]; u16 ldo_regs[WM8994_NUM_LDO_REGS];
...@@ -51,4 +80,26 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, ...@@ -51,4 +80,26 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
int count, u16 *buf); int count, u16 *buf);
/* Helper to save on boilerplate */
static inline int wm8994_request_irq(struct wm8994 *wm8994, int irq,
irq_handler_t handler, const char *name,
void *data)
{
if (!wm8994->irq_base)
return -EINVAL;
return request_threaded_irq(wm8994->irq_base + irq, NULL, handler,
IRQF_TRIGGER_RISING, name,
data);
}
static inline void wm8994_free_irq(struct wm8994 *wm8994, int irq, void *data)
{
if (!wm8994->irq_base)
return;
free_irq(wm8994->irq_base + irq, data);
}
int wm8994_irq_init(struct wm8994 *wm8994);
void wm8994_irq_exit(struct wm8994 *wm8994);
#endif #endif
...@@ -70,6 +70,7 @@ struct wm8994_pdata { ...@@ -70,6 +70,7 @@ struct wm8994_pdata {
struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO]; struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO];
int irq_base; /** Base IRQ number for WM8994, required for IRQs */
int num_drc_cfgs; int num_drc_cfgs;
struct wm8994_drc_cfg *drc_cfgs; struct wm8994_drc_cfg *drc_cfgs;
......
...@@ -182,6 +182,12 @@ struct snd_soc_dai_ops { ...@@ -182,6 +182,12 @@ struct snd_soc_dai_ops {
struct snd_soc_dai *); struct snd_soc_dai *);
int (*trigger)(struct snd_pcm_substream *, int, int (*trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *); struct snd_soc_dai *);
/*
* For hardware based FIFO caused delay reporting.
* Optional.
*/
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *);
}; };
/* /*
...@@ -215,7 +221,6 @@ struct snd_soc_dai { ...@@ -215,7 +221,6 @@ struct snd_soc_dai {
unsigned int symmetric_rates:1; unsigned int symmetric_rates:1;
/* DAI runtime info */ /* DAI runtime info */
struct snd_pcm_runtime *runtime;
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
unsigned int active; unsigned int active;
unsigned char pop_wait:1; unsigned char pop_wait:1;
......
...@@ -339,6 +339,9 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin); ...@@ -339,6 +339,9 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin); int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin); int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
int snd_soc_dapm_sync(struct snd_soc_codec *codec); int snd_soc_dapm_sync(struct snd_soc_codec *codec);
int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec,
const char *pin);
int snd_soc_dapm_ignore_suspend(struct snd_soc_codec *codec, const char *pin);
/* dapm widget types */ /* dapm widget types */
enum snd_soc_dapm_type { enum snd_soc_dapm_type {
...@@ -425,9 +428,8 @@ struct snd_soc_dapm_widget { ...@@ -425,9 +428,8 @@ struct snd_soc_dapm_widget {
unsigned char connected:1; /* connected codec pin */ unsigned char connected:1; /* connected codec pin */
unsigned char new:1; /* cnew complete */ unsigned char new:1; /* cnew complete */
unsigned char ext:1; /* has external widgets */ unsigned char ext:1; /* has external widgets */
unsigned char muted:1; /* muted for pop reduction */ unsigned char force:1; /* force state */
unsigned char suspend:1; /* was active before suspend */ unsigned char ignore_suspend:1; /* kept enabled over suspend */
unsigned char pmdown:1; /* waiting for timeout */
int (*power_check)(struct snd_soc_dapm_widget *w); int (*power_check)(struct snd_soc_dapm_widget *w);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/notifier.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -29,10 +30,10 @@ ...@@ -29,10 +30,10 @@
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \ ((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \ {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
.invert = xinvert}) .platform_max = xmax, .invert = xinvert})
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \ ((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .max = xmax, .invert = xinvert}) {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
#define SOC_SINGLE(xname, reg, shift, max, invert) \ #define SOC_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
...@@ -52,14 +53,14 @@ ...@@ -52,14 +53,14 @@
.put = snd_soc_put_volsw, \ .put = snd_soc_put_volsw, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \ {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw_2r, \ .info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \ #define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
...@@ -69,7 +70,7 @@ ...@@ -69,7 +70,7 @@
.put = snd_soc_put_volsw, \ .put = snd_soc_put_volsw, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right,\ {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
...@@ -79,7 +80,7 @@ ...@@ -79,7 +80,7 @@
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
...@@ -88,7 +89,8 @@ ...@@ -88,7 +89,8 @@
.info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \ .info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
.put = snd_soc_put_volsw_s8, \ .put = snd_soc_put_volsw_s8, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .min = xmin, .max = xmax} } {.reg = xreg, .min = xmin, .max = xmax, \
.platform_max = xmax} }
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
.max = xmax, .texts = xtexts } .max = xmax, .texts = xtexts }
...@@ -125,7 +127,7 @@ ...@@ -125,7 +127,7 @@
.get = xhandler_get, .put = xhandler_put, \ .get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \ {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \ xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
...@@ -145,7 +147,7 @@ ...@@ -145,7 +147,7 @@
.get = xhandler_get, .put = xhandler_put, \ .get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \ {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \ xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
...@@ -156,7 +158,7 @@ ...@@ -156,7 +158,7 @@
.get = xhandler_get, .put = xhandler_put, \ .get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} } .max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_bool_ext, \ .info = snd_soc_info_bool_ext, \
...@@ -212,6 +214,7 @@ struct snd_soc_dai_mode; ...@@ -212,6 +214,7 @@ struct snd_soc_dai_mode;
struct snd_soc_pcm_runtime; struct snd_soc_pcm_runtime;
struct snd_soc_dai; struct snd_soc_dai;
struct snd_soc_platform; struct snd_soc_platform;
struct snd_soc_dai_link;
struct snd_soc_codec; struct snd_soc_codec;
struct soc_enum; struct soc_enum;
struct snd_soc_ac97_ops; struct snd_soc_ac97_ops;
...@@ -260,6 +263,10 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, ...@@ -260,6 +263,10 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_pin *pins); struct snd_soc_jack_pin *pins);
void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
struct notifier_block *nb);
void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
struct notifier_block *nb);
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios); struct snd_soc_jack_gpio *gpios);
...@@ -320,6 +327,8 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, ...@@ -320,6 +327,8 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_soc_limit_volume(struct snd_soc_codec *codec,
const char *name, int max);
/** /**
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
...@@ -363,6 +372,7 @@ struct snd_soc_jack { ...@@ -363,6 +372,7 @@ struct snd_soc_jack {
struct snd_soc_card *card; struct snd_soc_card *card;
struct list_head pins; struct list_head pins;
int status; int status;
struct blocking_notifier_head notifier;
}; };
/* SoC PCM stream information */ /* SoC PCM stream information */
...@@ -374,7 +384,7 @@ struct snd_soc_pcm_stream { ...@@ -374,7 +384,7 @@ struct snd_soc_pcm_stream {
unsigned int rate_max; /* max rate */ unsigned int rate_max; /* max rate */
unsigned int channels_min; /* min channels */ unsigned int channels_min; /* min channels */
unsigned int channels_max; /* max channels */ unsigned int channels_max; /* max channels */
unsigned int active:1; /* stream is in use */ unsigned int active; /* stream is in use */
void *dma_data; /* used by platform code */ void *dma_data; /* used by platform code */
}; };
...@@ -407,7 +417,7 @@ struct snd_soc_codec { ...@@ -407,7 +417,7 @@ struct snd_soc_codec {
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
unsigned int active; unsigned int active;
unsigned int pcm_devs; unsigned int pcm_devs;
void *private_data; void *drvdata;
/* codec IO */ /* codec IO */
void *control_data; /* codec control (i2c/3wire) data */ void *control_data; /* codec control (i2c/3wire) data */
...@@ -462,14 +472,21 @@ struct snd_soc_platform { ...@@ -462,14 +472,21 @@ struct snd_soc_platform {
int (*probe)(struct platform_device *pdev); int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev); int (*remove)(struct platform_device *pdev);
int (*suspend)(struct snd_soc_dai *dai); int (*suspend)(struct snd_soc_dai_link *dai_link);
int (*resume)(struct snd_soc_dai *dai); int (*resume)(struct snd_soc_dai_link *dai_link);
/* pcm creation and destruction */ /* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
struct snd_pcm *); struct snd_pcm *);
void (*pcm_free)(struct snd_pcm *); void (*pcm_free)(struct snd_pcm *);
/*
* For platform caused delay reporting.
* Optional.
*/
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *);
/* platform stream ops */ /* platform stream ops */
struct snd_pcm_ops *pcm_ops; struct snd_pcm_ops *pcm_ops;
}; };
...@@ -489,6 +506,9 @@ struct snd_soc_dai_link { ...@@ -489,6 +506,9 @@ struct snd_soc_dai_link {
/* codec/machine specific init - e.g. add machine controls */ /* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_codec *codec); int (*init)(struct snd_soc_codec *codec);
/* Keep DAI active over suspend */
unsigned int ignore_suspend:1;
/* Symmetry requirements */ /* Symmetry requirements */
unsigned int symmetric_rates:1; unsigned int symmetric_rates:1;
...@@ -553,7 +573,7 @@ struct snd_soc_pcm_runtime { ...@@ -553,7 +573,7 @@ struct snd_soc_pcm_runtime {
/* mixer control */ /* mixer control */
struct soc_mixer_control { struct soc_mixer_control {
int min, max; int min, max, platform_max;
unsigned int reg, rreg, shift, rshift, invert; unsigned int reg, rreg, shift, rshift, invert;
}; };
...@@ -583,6 +603,17 @@ static inline unsigned int snd_soc_write(struct snd_soc_codec *codec, ...@@ -583,6 +603,17 @@ static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
return codec->write(codec, reg, val); return codec->write(codec, reg, val);
} }
static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
void *data)
{
codec->drvdata = data;
}
static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
{
return codec->drvdata;
}
#include <sound/soc-dai.h> #include <sound/soc-dai.h>
#endif #endif
/*
* Platform data for Texas Instruments TLV320AIC3x codec
*
* Author: Jarkko Nikula <jhnikula@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __TLV320AIC3x_H__
#define __TLV320AIC3x_H__
struct aic3x_pdata {
int gpio_reset; /* < 0 if not used */
};
#endif
\ No newline at end of file
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
struct tlv320dac33_platform_data { struct tlv320dac33_platform_data {
int power_gpio; int power_gpio;
int keep_bclk; /* Keep the BCLK running in FIFO modes */
u8 burst_bclkdiv; u8 burst_bclkdiv;
}; };
......
...@@ -21,6 +21,7 @@ struct uda134x_platform_data { ...@@ -21,6 +21,7 @@ struct uda134x_platform_data {
#define UDA134X_UDA1340 1 #define UDA134X_UDA1340 1
#define UDA134X_UDA1341 2 #define UDA134X_UDA1341 2
#define UDA134X_UDA1344 3 #define UDA134X_UDA1344 3
#define UDA134X_UDA1345 4
}; };
#endif /* _UDA134X_H */ #endif /* _UDA134X_H */
This diff is collapsed.
...@@ -15,8 +15,111 @@ ...@@ -15,8 +15,111 @@
#ifndef __MFD_WM8994_PDATA_H__ #ifndef __MFD_WM8994_PDATA_H__
#define __MFD_WM8994_PDATA_H__ #define __MFD_WM8994_PDATA_H__
#define WM8904_DRC_REGS 4 /* Used to enable configuration of a GPIO to all zeros */
#define WM8904_EQ_REGS 25 #define WM8904_GPIO_NO_CONFIG 0x8000
/*
* R6 (0x06) - Mic Bias Control 0
*/
#define WM8904_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
#define WM8904_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
#define WM8904_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
#define WM8904_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
#define WM8904_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
#define WM8904_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
#define WM8904_MICDET_ENA 0x0002 /* MICDET_ENA */
#define WM8904_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
#define WM8904_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
#define WM8904_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
#define WM8904_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
#define WM8904_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
#define WM8904_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
#define WM8904_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
/*
* R7 (0x07) - Mic Bias Control 1
*/
#define WM8904_MIC_DET_FILTER_ENA 0x8000 /* MIC_DET_FILTER_ENA */
#define WM8904_MIC_DET_FILTER_ENA_MASK 0x8000 /* MIC_DET_FILTER_ENA */
#define WM8904_MIC_DET_FILTER_ENA_SHIFT 15 /* MIC_DET_FILTER_ENA */
#define WM8904_MIC_DET_FILTER_ENA_WIDTH 1 /* MIC_DET_FILTER_ENA */
#define WM8904_MIC_SHORT_FILTER_ENA 0x4000 /* MIC_SHORT_FILTER_ENA */
#define WM8904_MIC_SHORT_FILTER_ENA_MASK 0x4000 /* MIC_SHORT_FILTER_ENA */
#define WM8904_MIC_SHORT_FILTER_ENA_SHIFT 14 /* MIC_SHORT_FILTER_ENA */
#define WM8904_MIC_SHORT_FILTER_ENA_WIDTH 1 /* MIC_SHORT_FILTER_ENA */
#define WM8904_MICBIAS_SEL_MASK 0x0007 /* MICBIAS_SEL - [2:0] */
#define WM8904_MICBIAS_SEL_SHIFT 0 /* MICBIAS_SEL - [2:0] */
#define WM8904_MICBIAS_SEL_WIDTH 3 /* MICBIAS_SEL - [2:0] */
/*
* R121 (0x79) - GPIO Control 1
*/
#define WM8904_GPIO1_PU 0x0020 /* GPIO1_PU */
#define WM8904_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
#define WM8904_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
#define WM8904_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
#define WM8904_GPIO1_PD 0x0010 /* GPIO1_PD */
#define WM8904_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
#define WM8904_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
#define WM8904_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
#define WM8904_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
#define WM8904_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
#define WM8904_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
/*
* R122 (0x7A) - GPIO Control 2
*/
#define WM8904_GPIO2_PU 0x0020 /* GPIO2_PU */
#define WM8904_GPIO2_PU_MASK 0x0020 /* GPIO2_PU */
#define WM8904_GPIO2_PU_SHIFT 5 /* GPIO2_PU */
#define WM8904_GPIO2_PU_WIDTH 1 /* GPIO2_PU */
#define WM8904_GPIO2_PD 0x0010 /* GPIO2_PD */
#define WM8904_GPIO2_PD_MASK 0x0010 /* GPIO2_PD */
#define WM8904_GPIO2_PD_SHIFT 4 /* GPIO2_PD */
#define WM8904_GPIO2_PD_WIDTH 1 /* GPIO2_PD */
#define WM8904_GPIO2_SEL_MASK 0x000F /* GPIO2_SEL - [3:0] */
#define WM8904_GPIO2_SEL_SHIFT 0 /* GPIO2_SEL - [3:0] */
#define WM8904_GPIO2_SEL_WIDTH 4 /* GPIO2_SEL - [3:0] */
/*
* R123 (0x7B) - GPIO Control 3
*/
#define WM8904_GPIO3_PU 0x0020 /* GPIO3_PU */
#define WM8904_GPIO3_PU_MASK 0x0020 /* GPIO3_PU */
#define WM8904_GPIO3_PU_SHIFT 5 /* GPIO3_PU */
#define WM8904_GPIO3_PU_WIDTH 1 /* GPIO3_PU */
#define WM8904_GPIO3_PD 0x0010 /* GPIO3_PD */
#define WM8904_GPIO3_PD_MASK 0x0010 /* GPIO3_PD */
#define WM8904_GPIO3_PD_SHIFT 4 /* GPIO3_PD */
#define WM8904_GPIO3_PD_WIDTH 1 /* GPIO3_PD */
#define WM8904_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
#define WM8904_GPIO3_SEL_SHIFT 0 /* GPIO3_SEL - [3:0] */
#define WM8904_GPIO3_SEL_WIDTH 4 /* GPIO3_SEL - [3:0] */
/*
* R124 (0x7C) - GPIO Control 4
*/
#define WM8904_GPI7_ENA 0x0200 /* GPI7_ENA */
#define WM8904_GPI7_ENA_MASK 0x0200 /* GPI7_ENA */
#define WM8904_GPI7_ENA_SHIFT 9 /* GPI7_ENA */
#define WM8904_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
#define WM8904_GPI8_ENA 0x0100 /* GPI8_ENA */
#define WM8904_GPI8_ENA_MASK 0x0100 /* GPI8_ENA */
#define WM8904_GPI8_ENA_SHIFT 8 /* GPI8_ENA */
#define WM8904_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
#define WM8904_GPIO_BCLK_MODE_ENA 0x0080 /* GPIO_BCLK_MODE_ENA */
#define WM8904_GPIO_BCLK_MODE_ENA_MASK 0x0080 /* GPIO_BCLK_MODE_ENA */
#define WM8904_GPIO_BCLK_MODE_ENA_SHIFT 7 /* GPIO_BCLK_MODE_ENA */
#define WM8904_GPIO_BCLK_MODE_ENA_WIDTH 1 /* GPIO_BCLK_MODE_ENA */
#define WM8904_GPIO_BCLK_SEL_MASK 0x000F /* GPIO_BCLK_SEL - [3:0] */
#define WM8904_GPIO_BCLK_SEL_SHIFT 0 /* GPIO_BCLK_SEL - [3:0] */
#define WM8904_GPIO_BCLK_SEL_WIDTH 4 /* GPIO_BCLK_SEL - [3:0] */
#define WM8904_MIC_REGS 2
#define WM8904_GPIO_REGS 4
#define WM8904_DRC_REGS 4
#define WM8904_EQ_REGS 25
/** /**
* DRC configurations are specified with a label and a set of register * DRC configurations are specified with a label and a set of register
...@@ -52,6 +155,9 @@ struct wm8904_pdata { ...@@ -52,6 +155,9 @@ struct wm8904_pdata {
int num_retune_mobile_cfgs; int num_retune_mobile_cfgs;
struct wm8904_retune_mobile_cfg *retune_mobile_cfgs; struct wm8904_retune_mobile_cfg *retune_mobile_cfgs;
u32 gpio_cfg[WM8904_GPIO_REGS];
u32 mic_cfg[WM8904_MIC_REGS];
}; };
#endif #endif
/*
* wm8960.h -- WM8960 Soc Audio driver platform data
*
* 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 _WM8960_PDATA_H
#define _WM8960_PDATA_H
#define WM8960_DRES_400R 0
#define WM8960_DRES_200R 1
#define WM8960_DRES_600R 2
#define WM8960_DRES_150R 3
#define WM8960_DRES_MAX 3
struct wm8960_data {
bool capless; /* Headphone outputs configured in capless mode */
int dres; /* Discharge resistance for headphone outputs */
};
#endif
/*
* linux/sound/wm9090.h -- Platform data for WM9090
*
* Copyright 2009, 2010 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_WM9090_H
#define __LINUX_SND_WM9090_H
struct wm9090_platform_data {
/* Line inputs 1 & 2 can optionally be differential */
unsigned int lin1_diff:1;
unsigned int lin2_diff:1;
/* AGC configuration. This is intended to protect the speaker
* against overdriving and will therefore depend on the
* hardware setup with incorrect runtime configuration
* potentially causing hardware damage.
*/
unsigned int agc_ena:1;
u16 agc[3];
};
#endif
...@@ -415,9 +415,12 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) ...@@ -415,9 +415,12 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int atmel_pcm_suspend(struct snd_soc_dai *dai) static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
{ {
struct snd_pcm_runtime *runtime = dai->runtime; struct snd_pcm *pcm = dai_link->pcm;
struct snd_pcm_str *stream = &pcm->streams[0];
struct snd_pcm_substream *substream = stream->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd; struct atmel_runtime_data *prtd;
struct atmel_pcm_dma_params *params; struct atmel_pcm_dma_params *params;
...@@ -439,9 +442,12 @@ static int atmel_pcm_suspend(struct snd_soc_dai *dai) ...@@ -439,9 +442,12 @@ static int atmel_pcm_suspend(struct snd_soc_dai *dai)
return 0; return 0;
} }
static int atmel_pcm_resume(struct snd_soc_dai *dai) static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
{ {
struct snd_pcm_runtime *runtime = dai->runtime; struct snd_pcm *pcm = dai_link->pcm;
struct snd_pcm_str *stream = &pcm->streams[0];
struct snd_pcm_substream *substream = stream->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd; struct atmel_runtime_data *prtd;
struct atmel_pcm_dma_params *params; struct atmel_pcm_dma_params *params;
......
...@@ -49,13 +49,14 @@ config SND_BF5XX_SOC_AD1836 ...@@ -49,13 +49,14 @@ config SND_BF5XX_SOC_AD1836
help help
Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
config SND_BF5XX_SOC_AD1938 config SND_BF5XX_SOC_AD193X
tristate "SoC AD1938 Audio support for Blackfin" tristate "SoC AD193X Audio support for Blackfin"
depends on SND_BF5XX_TDM depends on SND_BF5XX_TDM
select SND_BF5XX_SOC_TDM select SND_BF5XX_SOC_TDM
select SND_SOC_AD1938 select SND_SOC_AD193X
help help
Say Y if you want to add support for AD1938 codec on Blackfin. Say Y if you want to add support for AD193X codec on Blackfin.
This driver supports AD1936, AD1937, AD1938 and AD1939.
config SND_BF5XX_AC97 config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip" tristate "SoC AC97 Audio for the ADI BF5xx chip"
......
...@@ -20,10 +20,10 @@ snd-ad1836-objs := bf5xx-ad1836.o ...@@ -20,10 +20,10 @@ snd-ad1836-objs := bf5xx-ad1836.o
snd-ad1980-objs := bf5xx-ad1980.o snd-ad1980-objs := bf5xx-ad1980.o
snd-ssm2602-objs := bf5xx-ssm2602.o snd-ssm2602-objs := bf5xx-ssm2602.o
snd-ad73311-objs := bf5xx-ad73311.o snd-ad73311-objs := bf5xx-ad73311.o
snd-ad1938-objs := bf5xx-ad1938.o snd-ad193x-objs := bf5xx-ad193x.o
obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
/* /*
* File: sound/soc/blackfin/bf5xx-ad1938.c * File: sound/soc/blackfin/bf5xx-ad193x.c
* Author: Barry Song <Barry.Song@analog.com> * Author: Barry Song <Barry.Song@analog.com>
* *
* Created: Thur June 4 2009 * Created: Thur June 4 2009
* Description: Board driver for ad1938 sound chip * Description: Board driver for ad193x sound chip
* *
* Bugs: Enter bugs at http://blackfin.uclinux.org/ * Bugs: Enter bugs at http://blackfin.uclinux.org/
* *
...@@ -38,15 +38,15 @@ ...@@ -38,15 +38,15 @@
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/portmux.h> #include <asm/portmux.h>
#include "../codecs/ad1938.h" #include "../codecs/ad193x.h"
#include "bf5xx-sport.h" #include "bf5xx-sport.h"
#include "bf5xx-tdm-pcm.h" #include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h" #include "bf5xx-tdm.h"
static struct snd_soc_card bf5xx_ad1938; static struct snd_soc_card bf5xx_ad193x;
static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
...@@ -55,7 +55,7 @@ static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) ...@@ -55,7 +55,7 @@ static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
...@@ -89,61 +89,61 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, ...@@ -89,61 +89,61 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static struct snd_soc_ops bf5xx_ad1938_ops = { static struct snd_soc_ops bf5xx_ad193x_ops = {
.startup = bf5xx_ad1938_startup, .startup = bf5xx_ad193x_startup,
.hw_params = bf5xx_ad1938_hw_params, .hw_params = bf5xx_ad193x_hw_params,
}; };
static struct snd_soc_dai_link bf5xx_ad1938_dai = { static struct snd_soc_dai_link bf5xx_ad193x_dai = {
.name = "ad1938", .name = "ad193x",
.stream_name = "AD1938", .stream_name = "AD193X",
.cpu_dai = &bf5xx_tdm_dai, .cpu_dai = &bf5xx_tdm_dai,
.codec_dai = &ad1938_dai, .codec_dai = &ad193x_dai,
.ops = &bf5xx_ad1938_ops, .ops = &bf5xx_ad193x_ops,
}; };
static struct snd_soc_card bf5xx_ad1938 = { static struct snd_soc_card bf5xx_ad193x = {
.name = "bf5xx_ad1938", .name = "bf5xx_ad193x",
.platform = &bf5xx_tdm_soc_platform, .platform = &bf5xx_tdm_soc_platform,
.dai_link = &bf5xx_ad1938_dai, .dai_link = &bf5xx_ad193x_dai,
.num_links = 1, .num_links = 1,
}; };
static struct snd_soc_device bf5xx_ad1938_snd_devdata = { static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
.card = &bf5xx_ad1938, .card = &bf5xx_ad193x,
.codec_dev = &soc_codec_dev_ad1938, .codec_dev = &soc_codec_dev_ad193x,
}; };
static struct platform_device *bfxx_ad1938_snd_device; static struct platform_device *bfxx_ad193x_snd_device;
static int __init bf5xx_ad1938_init(void) static int __init bf5xx_ad193x_init(void)
{ {
int ret; int ret;
bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1); bfxx_ad193x_snd_device = platform_device_alloc("soc-audio", -1);
if (!bfxx_ad1938_snd_device) if (!bfxx_ad193x_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata); platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata);
bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev; bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
ret = platform_device_add(bfxx_ad1938_snd_device); ret = platform_device_add(bfxx_ad193x_snd_device);
if (ret) if (ret)
platform_device_put(bfxx_ad1938_snd_device); platform_device_put(bfxx_ad193x_snd_device);
return ret; return ret;
} }
static void __exit bf5xx_ad1938_exit(void) static void __exit bf5xx_ad193x_exit(void)
{ {
platform_device_unregister(bfxx_ad1938_snd_device); platform_device_unregister(bfxx_ad193x_snd_device);
} }
module_init(bf5xx_ad1938_init); module_init(bf5xx_ad193x_init);
module_exit(bf5xx_ad1938_exit); module_exit(bf5xx_ad193x_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Barry Song"); MODULE_AUTHOR("Barry Song");
MODULE_DESCRIPTION("ALSA SoC AD1938 board driver"); MODULE_DESCRIPTION("ALSA SoC AD193X board driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -34,33 +34,7 @@ ...@@ -34,33 +34,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin_sport.h>
struct sport_register {
u16 tcr1; u16 reserved0;
u16 tcr2; u16 reserved1;
u16 tclkdiv; u16 reserved2;
u16 tfsdiv; u16 reserved3;
u32 tx;
u32 reserved_l0;
u32 rx;
u32 reserved_l1;
u16 rcr1; u16 reserved4;
u16 rcr2; u16 reserved5;
u16 rclkdiv; u16 reserved6;
u16 rfsdiv; u16 reserved7;
u16 stat; u16 reserved8;
u16 chnl; u16 reserved9;
u16 mcmc1; u16 reserved10;
u16 mcmc2; u16 reserved11;
u32 mtcs0;
u32 mtcs1;
u32 mtcs2;
u32 mtcs3;
u32 mrcs0;
u32 mrcs1;
u32 mrcs2;
u32 mrcs3;
};
#define DESC_ELEMENT_COUNT 9 #define DESC_ELEMENT_COUNT 9
......
...@@ -13,7 +13,7 @@ config SND_SOC_ALL_CODECS ...@@ -13,7 +13,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_L3 select SND_SOC_L3
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
select SND_SOC_AD1836 if SPI_MASTER select SND_SOC_AD1836 if SPI_MASTER
select SND_SOC_AD1938 if SPI_MASTER select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD1980 if SND_SOC_AC97_BUS
select SND_SOC_ADS117X select SND_SOC_ADS117X
select SND_SOC_AD73311 if I2C select SND_SOC_AD73311 if I2C
...@@ -21,6 +21,7 @@ config SND_SOC_ALL_CODECS ...@@ -21,6 +21,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AK4535 if I2C select SND_SOC_AK4535 if I2C
select SND_SOC_AK4642 if I2C select SND_SOC_AK4642 if I2C
select SND_SOC_AK4671 if I2C select SND_SOC_AK4671 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS4270 if I2C select SND_SOC_CS4270 if I2C
select SND_SOC_MAX9877 if I2C select SND_SOC_MAX9877 if I2C
select SND_SOC_DA7210 if I2C select SND_SOC_DA7210 if I2C
...@@ -34,6 +35,7 @@ config SND_SOC_ALL_CODECS ...@@ -34,6 +35,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TPA6130A2 if I2C select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C select SND_SOC_TLV320DAC33 if I2C
select SND_SOC_TWL4030 if TWL4030_CORE select SND_SOC_TWL4030 if TWL4030_CORE
select SND_SOC_TWL6040 if TWL4030_CORE
select SND_SOC_UDA134X select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C select SND_SOC_UDA1380 if I2C
select SND_SOC_WM2000 if I2C select SND_SOC_WM2000 if I2C
...@@ -64,6 +66,7 @@ config SND_SOC_ALL_CODECS ...@@ -64,6 +66,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8993 if I2C select SND_SOC_WM8993 if I2C
select SND_SOC_WM8994 if MFD_WM8994 select SND_SOC_WM8994 if MFD_WM8994
select SND_SOC_WM9081 if I2C select SND_SOC_WM9081 if I2C
select SND_SOC_WM9090 if I2C
select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9705 if SND_SOC_AC97_BUS
select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS
select SND_SOC_WM9713 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS
...@@ -90,7 +93,7 @@ config SND_SOC_AC97_CODEC ...@@ -90,7 +93,7 @@ config SND_SOC_AC97_CODEC
config SND_SOC_AD1836 config SND_SOC_AD1836
tristate tristate
config SND_SOC_AD1938 config SND_SOC_AD193X
tristate tristate
config SND_SOC_AD1980 config SND_SOC_AD1980
...@@ -114,6 +117,9 @@ config SND_SOC_AK4642 ...@@ -114,6 +117,9 @@ config SND_SOC_AK4642
config SND_SOC_AK4671 config SND_SOC_AK4671
tristate tristate
config SND_SOC_CQ0093VC
tristate
# Cirrus Logic CS4270 Codec # Cirrus Logic CS4270 Codec
config SND_SOC_CS4270 config SND_SOC_CS4270
tristate tristate
...@@ -164,6 +170,9 @@ config SND_SOC_TWL4030 ...@@ -164,6 +170,9 @@ config SND_SOC_TWL4030
select TWL4030_CODEC select TWL4030_CODEC
tristate tristate
config SND_SOC_TWL6040
tristate
config SND_SOC_UDA134X config SND_SOC_UDA134X
tristate tristate
...@@ -269,3 +278,6 @@ config SND_SOC_TPA6130A2 ...@@ -269,3 +278,6 @@ config SND_SOC_TPA6130A2
config SND_SOC_WM2000 config SND_SOC_WM2000
tristate tristate
config SND_SOC_WM9090
tristate
snd-soc-ac97-objs := ac97.o snd-soc-ac97-objs := ac97.o
snd-soc-ad1836-objs := ad1836.o snd-soc-ad1836-objs := ad1836.o
snd-soc-ad1938-objs := ad1938.o snd-soc-ad193x-objs := ad193x.o
snd-soc-ad1980-objs := ad1980.o snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o snd-soc-ad73311-objs := ad73311.o
snd-soc-ads117x-objs := ads117x.o snd-soc-ads117x-objs := ads117x.o
...@@ -8,6 +8,7 @@ snd-soc-ak4104-objs := ak4104.o ...@@ -8,6 +8,7 @@ snd-soc-ak4104-objs := ak4104.o
snd-soc-ak4535-objs := ak4535.o snd-soc-ak4535-objs := ak4535.o
snd-soc-ak4642-objs := ak4642.o snd-soc-ak4642-objs := ak4642.o
snd-soc-ak4671-objs := ak4671.o snd-soc-ak4671-objs := ak4671.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs4270-objs := cs4270.o snd-soc-cs4270-objs := cs4270.o
snd-soc-cx20442-objs := cx20442.o snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o snd-soc-da7210-objs := da7210.o
...@@ -21,6 +22,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o ...@@ -21,6 +22,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-tlv320dac33-objs := tlv320dac33.o
snd-soc-twl4030-objs := twl4030.o snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o snd-soc-uda1380-objs := uda1380.o
snd-soc-wm8350-objs := wm8350.o snd-soc-wm8350-objs := wm8350.o
...@@ -59,10 +61,11 @@ snd-soc-wm-hubs-objs := wm_hubs.o ...@@ -59,10 +61,11 @@ snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-max9877-objs := max9877.o snd-soc-max9877-objs := max9877.o
snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-wm2000-objs := wm2000.o snd-soc-wm2000-objs := wm2000.o
snd-soc-wm9090-objs := wm9090.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
...@@ -70,6 +73,7 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o ...@@ -70,6 +73,7 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
...@@ -83,6 +87,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o ...@@ -83,6 +87,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
...@@ -121,3 +126,4 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o ...@@ -121,3 +126,4 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
...@@ -278,7 +278,7 @@ static int ad1836_register(struct ad1836_priv *ad1836) ...@@ -278,7 +278,7 @@ static int ad1836_register(struct ad1836_priv *ad1836)
mutex_init(&codec->mutex); mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = ad1836; snd_soc_codec_set_drvdata(codec, ad1836);
codec->reg_cache = ad1836->reg_cache; codec->reg_cache = ad1836->reg_cache;
codec->reg_cache_size = AD1836_NUM_REGS; codec->reg_cache_size = AD1836_NUM_REGS;
codec->name = "AD1836"; codec->name = "AD1836";
......
/*
* File: sound/soc/codecs/ad1836.h
* Based on:
* Author: Barry Song <Barry.Song@analog.com>
*
* Created: May 25, 2009
* Description: definitions for AD1938 registers
*
* Modified:
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __AD1938_H__
#define __AD1938_H__
#define AD1938_PLL_CLK_CTRL0 0
#define AD1938_PLL_POWERDOWN 0x01
#define AD1938_PLL_CLK_CTRL1 1
#define AD1938_DAC_CTRL0 2
#define AD1938_DAC_POWERDOWN 0x01
#define AD1938_DAC_SERFMT_MASK 0xC0
#define AD1938_DAC_SERFMT_STEREO (0 << 6)
#define AD1938_DAC_SERFMT_TDM (1 << 6)
#define AD1938_DAC_CTRL1 3
#define AD1938_DAC_2_CHANNELS 0
#define AD1938_DAC_4_CHANNELS 1
#define AD1938_DAC_8_CHANNELS 2
#define AD1938_DAC_16_CHANNELS 3
#define AD1938_DAC_CHAN_SHFT 1
#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT)
#define AD1938_DAC_LCR_MASTER (1 << 4)
#define AD1938_DAC_BCLK_MASTER (1 << 5)
#define AD1938_DAC_LEFT_HIGH (1 << 3)
#define AD1938_DAC_BCLK_INV (1 << 7)
#define AD1938_DAC_CTRL2 4
#define AD1938_DAC_WORD_LEN_MASK 0xC
#define AD1938_DAC_MASTER_MUTE 1
#define AD1938_DAC_CHNL_MUTE 5
#define AD1938_DACL1_MUTE 0
#define AD1938_DACR1_MUTE 1
#define AD1938_DACL2_MUTE 2
#define AD1938_DACR2_MUTE 3
#define AD1938_DACL3_MUTE 4
#define AD1938_DACR3_MUTE 5
#define AD1938_DACL4_MUTE 6
#define AD1938_DACR4_MUTE 7
#define AD1938_DAC_L1_VOL 6
#define AD1938_DAC_R1_VOL 7
#define AD1938_DAC_L2_VOL 8
#define AD1938_DAC_R2_VOL 9
#define AD1938_DAC_L3_VOL 10
#define AD1938_DAC_R3_VOL 11
#define AD1938_DAC_L4_VOL 12
#define AD1938_DAC_R4_VOL 13
#define AD1938_ADC_CTRL0 14
#define AD1938_ADC_POWERDOWN 0x01
#define AD1938_ADC_HIGHPASS_FILTER 1
#define AD1938_ADCL1_MUTE 2
#define AD1938_ADCR1_MUTE 3
#define AD1938_ADCL2_MUTE 4
#define AD1938_ADCR2_MUTE 5
#define AD1938_ADC_CTRL1 15
#define AD1938_ADC_SERFMT_MASK 0x60
#define AD1938_ADC_SERFMT_STEREO (0 << 5)
#define AD1938_ADC_SERFMT_TDM (1 << 2)
#define AD1938_ADC_SERFMT_AUX (2 << 5)
#define AD1938_ADC_WORD_LEN_MASK 0x3
#define AD1938_ADC_CTRL2 16
#define AD1938_ADC_2_CHANNELS 0
#define AD1938_ADC_4_CHANNELS 1
#define AD1938_ADC_8_CHANNELS 2
#define AD1938_ADC_16_CHANNELS 3
#define AD1938_ADC_CHAN_SHFT 4
#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT)
#define AD1938_ADC_LCR_MASTER (1 << 3)
#define AD1938_ADC_BCLK_MASTER (1 << 6)
#define AD1938_ADC_LEFT_HIGH (1 << 2)
#define AD1938_ADC_BCLK_INV (1 << 1)
#define AD1938_NUM_REGS 17
extern struct snd_soc_dai ad1938_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad1938;
#endif
/*
* AD193X Audio Codec driver
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#ifndef __AD193X_H__
#define __AD193X_H__
#define AD193X_PLL_CLK_CTRL0 0x800
#define AD193X_PLL_POWERDOWN 0x01
#define AD193X_PLL_CLK_CTRL1 0x801
#define AD193X_DAC_CTRL0 0x802
#define AD193X_DAC_POWERDOWN 0x01
#define AD193X_DAC_SERFMT_MASK 0xC0
#define AD193X_DAC_SERFMT_STEREO (0 << 6)
#define AD193X_DAC_SERFMT_TDM (1 << 6)
#define AD193X_DAC_CTRL1 0x803
#define AD193X_DAC_2_CHANNELS 0
#define AD193X_DAC_4_CHANNELS 1
#define AD193X_DAC_8_CHANNELS 2
#define AD193X_DAC_16_CHANNELS 3
#define AD193X_DAC_CHAN_SHFT 1
#define AD193X_DAC_CHAN_MASK (3 << AD193X_DAC_CHAN_SHFT)
#define AD193X_DAC_LCR_MASTER (1 << 4)
#define AD193X_DAC_BCLK_MASTER (1 << 5)
#define AD193X_DAC_LEFT_HIGH (1 << 3)
#define AD193X_DAC_BCLK_INV (1 << 7)
#define AD193X_DAC_CTRL2 0x804
#define AD193X_DAC_WORD_LEN_MASK 0xC
#define AD193X_DAC_MASTER_MUTE 1
#define AD193X_DAC_CHNL_MUTE 0x805
#define AD193X_DACL1_MUTE 0
#define AD193X_DACR1_MUTE 1
#define AD193X_DACL2_MUTE 2
#define AD193X_DACR2_MUTE 3
#define AD193X_DACL3_MUTE 4
#define AD193X_DACR3_MUTE 5
#define AD193X_DACL4_MUTE 6
#define AD193X_DACR4_MUTE 7
#define AD193X_DAC_L1_VOL 0x806
#define AD193X_DAC_R1_VOL 0x807
#define AD193X_DAC_L2_VOL 0x808
#define AD193X_DAC_R2_VOL 0x809
#define AD193X_DAC_L3_VOL 0x80a
#define AD193X_DAC_R3_VOL 0x80b
#define AD193X_DAC_L4_VOL 0x80c
#define AD193X_DAC_R4_VOL 0x80d
#define AD193X_ADC_CTRL0 0x80e
#define AD193X_ADC_POWERDOWN 0x01
#define AD193X_ADC_HIGHPASS_FILTER 1
#define AD193X_ADCL1_MUTE 2
#define AD193X_ADCR1_MUTE 3
#define AD193X_ADCL2_MUTE 4
#define AD193X_ADCR2_MUTE 5
#define AD193X_ADC_CTRL1 0x80f
#define AD193X_ADC_SERFMT_MASK 0x60
#define AD193X_ADC_SERFMT_STEREO (0 << 5)
#define AD193X_ADC_SERFMT_TDM (1 << 2)
#define AD193X_ADC_SERFMT_AUX (2 << 5)
#define AD193X_ADC_WORD_LEN_MASK 0x3
#define AD193X_ADC_CTRL2 0x810
#define AD193X_ADC_2_CHANNELS 0
#define AD193X_ADC_4_CHANNELS 1
#define AD193X_ADC_8_CHANNELS 2
#define AD193X_ADC_16_CHANNELS 3
#define AD193X_ADC_CHAN_SHFT 4
#define AD193X_ADC_CHAN_MASK (3 << AD193X_ADC_CHAN_SHFT)
#define AD193X_ADC_LCR_MASTER (1 << 3)
#define AD193X_ADC_BCLK_MASTER (1 << 6)
#define AD193X_ADC_LEFT_HIGH (1 << 2)
#define AD193X_ADC_BCLK_INV (1 << 1)
#define AD193X_NUM_REGS 17
extern struct snd_soc_dai ad193x_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad193x;
#endif
...@@ -222,7 +222,7 @@ static int ak4104_spi_probe(struct spi_device *spi) ...@@ -222,7 +222,7 @@ static int ak4104_spi_probe(struct spi_device *spi)
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->dai = &ak4104_dai; codec->dai = &ak4104_dai;
codec->num_dai = 1; codec->num_dai = 1;
codec->private_data = ak4104; snd_soc_codec_set_drvdata(codec, ak4104);
codec->control_data = spi; codec->control_data = spi;
codec->reg_cache = ak4104->reg_cache; codec->reg_cache = ak4104->reg_cache;
codec->reg_cache_size = AK4104_NUM_REGS; codec->reg_cache_size = AK4104_NUM_REGS;
......
...@@ -302,7 +302,7 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -302,7 +302,7 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct ak4535_priv *ak4535 = codec->private_data; struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
ak4535->sysclk = freq; ak4535->sysclk = freq;
return 0; return 0;
...@@ -315,7 +315,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, ...@@ -315,7 +315,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct ak4535_priv *ak4535 = codec->private_data; struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
int rate = params_rate(params), fs = 256; int rate = params_rate(params), fs = 256;
...@@ -446,7 +446,6 @@ static int ak4535_resume(struct platform_device *pdev) ...@@ -446,7 +446,6 @@ static int ak4535_resume(struct platform_device *pdev)
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
ak4535_sync(codec); ak4535_sync(codec);
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
ak4535_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
...@@ -600,7 +599,7 @@ static int ak4535_probe(struct platform_device *pdev) ...@@ -600,7 +599,7 @@ static int ak4535_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
codec->private_data = ak4535; snd_soc_codec_set_drvdata(codec, ak4535);
socdev->card->codec = codec; socdev->card->codec = codec;
mutex_init(&codec->mutex); mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
...@@ -617,7 +616,7 @@ static int ak4535_probe(struct platform_device *pdev) ...@@ -617,7 +616,7 @@ static int ak4535_probe(struct platform_device *pdev)
#endif #endif
if (ret != 0) { if (ret != 0) {
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
kfree(codec); kfree(codec);
} }
return ret; return ret;
...@@ -639,7 +638,7 @@ static int ak4535_remove(struct platform_device *pdev) ...@@ -639,7 +638,7 @@ static int ak4535_remove(struct platform_device *pdev)
i2c_unregister_device(codec->control_data); i2c_unregister_device(codec->control_data);
i2c_del_driver(&ak4535_i2c_driver); i2c_del_driver(&ak4535_i2c_driver);
#endif #endif
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
kfree(codec); kfree(codec);
return 0; return 0;
......
...@@ -81,12 +81,39 @@ ...@@ -81,12 +81,39 @@
#define AK4642_CACHEREGNUM 0x25 #define AK4642_CACHEREGNUM 0x25
/* PW_MGMT2 */
#define HPMTN (1 << 6)
#define PMHPL (1 << 5)
#define PMHPR (1 << 4)
#define MS (1 << 3) /* master/slave select */
#define MCKO (1 << 1)
#define PMPLL (1 << 0)
#define PMHP_MASK (PMHPL | PMHPR)
#define PMHP PMHP_MASK
/* MD_CTL1 */
#define PLL3 (1 << 7)
#define PLL2 (1 << 6)
#define PLL1 (1 << 5)
#define PLL0 (1 << 4)
#define PLL_MASK (PLL3 | PLL2 | PLL1 | PLL0)
#define BCKO_MASK (1 << 3)
#define BCKO_64 BCKO_MASK
/* MD_CTL2 */
#define FS0 (1 << 0)
#define FS1 (1 << 1)
#define FS2 (1 << 2)
#define FS3 (1 << 5)
#define FS_MASK (FS0 | FS1 | FS2 | FS3)
struct snd_soc_codec_device soc_codec_dev_ak4642; struct snd_soc_codec_device soc_codec_dev_ak4642;
/* codec private data */ /* codec private data */
struct ak4642_priv { struct ak4642_priv {
struct snd_soc_codec codec; struct snd_soc_codec codec;
unsigned int sysclk;
}; };
static struct snd_soc_codec *ak4642_codec; static struct snd_soc_codec *ak4642_codec;
...@@ -177,17 +204,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, ...@@ -177,17 +204,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* *
* PLL, Master Mode * PLL, Master Mode
* Audio I/F Format :MSB justified (ADC & DAC) * Audio I/F Format :MSB justified (ADC & DAC)
* Sampling Frequency: 44.1kHz * Digital Volume: -8dB
* Digital Volume: −8dB
* Bass Boost Level : Middle * Bass Boost Level : Middle
* *
* This operation came from example code of * This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p97. * "ASAHI KASEI AK4642" (japanese) manual p97.
*
* Example code use 0x39, 0x79 value for 0x01 address,
* But we need MCKO (0x02) bit now
*/ */
ak4642_write(codec, 0x05, 0x27);
ak4642_write(codec, 0x0f, 0x09); ak4642_write(codec, 0x0f, 0x09);
ak4642_write(codec, 0x0e, 0x19); ak4642_write(codec, 0x0e, 0x19);
ak4642_write(codec, 0x09, 0x91); ak4642_write(codec, 0x09, 0x91);
...@@ -195,15 +217,14 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, ...@@ -195,15 +217,14 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
ak4642_write(codec, 0x0a, 0x28); ak4642_write(codec, 0x0a, 0x28);
ak4642_write(codec, 0x0d, 0x28); ak4642_write(codec, 0x0d, 0x28);
ak4642_write(codec, 0x00, 0x64); ak4642_write(codec, 0x00, 0x64);
ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */ snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */ snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
} else { } else {
/* /*
* start stereo input * start stereo input
* *
* PLL Master Mode * PLL Master Mode
* Audio I/F Format:MSB justified (ADC & DAC) * Audio I/F Format:MSB justified (ADC & DAC)
* Sampling Frequency:44.1kHz
* Pre MIC AMP:+20dB * Pre MIC AMP:+20dB
* MIC Power On * MIC Power On
* ALC setting:Refer to Table 35 * ALC setting:Refer to Table 35
...@@ -212,7 +233,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, ...@@ -212,7 +233,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of * This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p94. * "ASAHI KASEI AK4642" (japanese) manual p94.
*/ */
ak4642_write(codec, 0x05, 0x27);
ak4642_write(codec, 0x02, 0x05); ak4642_write(codec, 0x02, 0x05);
ak4642_write(codec, 0x06, 0x3c); ak4642_write(codec, 0x06, 0x3c);
ak4642_write(codec, 0x08, 0xe1); ak4642_write(codec, 0x08, 0xe1);
...@@ -233,8 +253,8 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, ...@@ -233,8 +253,8 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
if (is_play) { if (is_play) {
/* stop headphone output */ /* stop headphone output */
ak4642_write(codec, 0x01, 0x3b); snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0);
ak4642_write(codec, 0x01, 0x0b); snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
ak4642_write(codec, 0x00, 0x40); ak4642_write(codec, 0x00, 0x40);
ak4642_write(codec, 0x0e, 0x11); ak4642_write(codec, 0x0e, 0x11);
ak4642_write(codec, 0x0f, 0x08); ak4642_write(codec, 0x0f, 0x08);
...@@ -250,9 +270,111 @@ static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai, ...@@ -250,9 +270,111 @@ static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct ak4642_priv *ak4642 = codec->private_data; u8 pll;
switch (freq) {
case 11289600:
pll = PLL2;
break;
case 12288000:
pll = PLL2 | PLL0;
break;
case 12000000:
pll = PLL2 | PLL1;
break;
case 24000000:
pll = PLL2 | PLL1 | PLL0;
break;
case 13500000:
pll = PLL3 | PLL2;
break;
case 27000000:
pll = PLL3 | PLL2 | PLL0;
break;
default:
return -EINVAL;
}
snd_soc_update_bits(codec, MD_CTL1, PLL_MASK, pll);
return 0;
}
static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
u8 data;
u8 bcko;
data = MCKO | PMPLL; /* use MCKO */
bcko = 0;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
data |= MS;
bcko = BCKO_64;
break;
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
snd_soc_update_bits(codec, PW_MGMT2, MS, data);
snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
return 0;
}
static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
u8 rate;
switch (params_rate(params)) {
case 7350:
rate = FS2;
break;
case 8000:
rate = 0;
break;
case 11025:
rate = FS2 | FS0;
break;
case 12000:
rate = FS0;
break;
case 14700:
rate = FS2 | FS1;
break;
case 16000:
rate = FS1;
break;
case 22050:
rate = FS2 | FS1 | FS0;
break;
case 24000:
rate = FS1 | FS0;
break;
case 29400:
rate = FS3 | FS2 | FS1;
break;
case 32000:
rate = FS3 | FS1;
break;
case 44100:
rate = FS3 | FS2 | FS1 | FS0;
break;
case 48000:
rate = FS3 | FS1 | FS0;
break;
default:
return -EINVAL;
break;
}
snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate);
ak4642->sysclk = freq;
return 0; return 0;
} }
...@@ -260,6 +382,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = { ...@@ -260,6 +382,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
.startup = ak4642_dai_startup, .startup = ak4642_dai_startup,
.shutdown = ak4642_dai_shutdown, .shutdown = ak4642_dai_shutdown,
.set_sysclk = ak4642_dai_set_sysclk, .set_sysclk = ak4642_dai_set_sysclk,
.set_fmt = ak4642_dai_set_fmt,
.hw_params = ak4642_dai_hw_params,
}; };
struct snd_soc_dai ak4642_dai = { struct snd_soc_dai ak4642_dai = {
...@@ -277,6 +401,7 @@ struct snd_soc_dai ak4642_dai = { ...@@ -277,6 +401,7 @@ struct snd_soc_dai ak4642_dai = {
.rates = SNDRV_PCM_RATE_8000_48000, .rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE }, .formats = SNDRV_PCM_FMTBIT_S16_LE },
.ops = &ak4642_dai_ops, .ops = &ak4642_dai_ops,
.symmetric_rates = 1,
}; };
EXPORT_SYMBOL_GPL(ak4642_dai); EXPORT_SYMBOL_GPL(ak4642_dai);
...@@ -307,7 +432,7 @@ static int ak4642_init(struct ak4642_priv *ak4642) ...@@ -307,7 +432,7 @@ static int ak4642_init(struct ak4642_priv *ak4642)
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = ak4642; snd_soc_codec_set_drvdata(codec, ak4642);
codec->name = "AK4642"; codec->name = "AK4642";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = ak4642_read_reg_cache; codec->read = ak4642_read_reg_cache;
...@@ -338,26 +463,6 @@ static int ak4642_init(struct ak4642_priv *ak4642) ...@@ -338,26 +463,6 @@ static int ak4642_init(struct ak4642_priv *ak4642)
goto reg_cache_err; goto reg_cache_err;
} }
/*
* clock setting
*
* Audio I/F Format: MSB justified (ADC & DAC)
* BICK frequency at Master Mode: 64fs
* Input Master Clock Select at PLL Mode: 11.2896MHz
* MCKO: Enable
* Sampling Frequency: 44.1kHz
*
* This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p89.
*
* please fix-me
*/
ak4642_write(codec, 0x01, 0x08);
ak4642_write(codec, 0x04, 0x4a);
ak4642_write(codec, 0x05, 0x27);
ak4642_write(codec, 0x00, 0x40);
ak4642_write(codec, 0x01, 0x0b);
return ret; return ret;
reg_cache_err: reg_cache_err:
......
...@@ -702,7 +702,7 @@ static int ak4671_register(struct ak4671_priv *ak4671, ...@@ -702,7 +702,7 @@ static int ak4671_register(struct ak4671_priv *ak4671,
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = ak4671; snd_soc_codec_set_drvdata(codec, ak4671);
codec->name = "AK4671"; codec->name = "AK4671";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->bias_level = SND_SOC_BIAS_OFF; codec->bias_level = SND_SOC_BIAS_OFF;
......
/*
* ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
*
* Copyright (C) 2010 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.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 Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/mfd/davinci_voicecodec.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <mach/dm365.h>
#include "cq93vc.h"
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
unsigned int reg)
{
struct davinci_vc *davinci_vc = codec->control_data;
return readl(davinci_vc->base + reg);
}
static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
struct davinci_vc *davinci_vc = codec->control_data;
writel(value, davinci_vc->base + reg);
return 0;
}
static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
};
static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
if (mute)
cq93vc_write(codec, DAVINCI_VC_REG09,
reg | DAVINCI_VC_REG09_MUTE);
else
cq93vc_write(codec, DAVINCI_VC_REG09, reg);
return 0;
}
static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct davinci_vc *davinci_vc = codec->control_data;
switch (freq) {
case 22579200:
case 27000000:
case 33868800:
davinci_vc->cq93vc.sysclk = freq;
return 0;
}
return -EINVAL;
}
static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
switch (level) {
case SND_SOC_BIAS_ON:
cq93vc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_ON);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
cq93vc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_OFF);
break;
case SND_SOC_BIAS_OFF:
/* force all power off */
cq93vc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_OFF);
break;
}
codec->bias_level = level;
return 0;
}
#define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
#define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
static struct snd_soc_dai_ops cq93vc_dai_ops = {
.digital_mute = cq93vc_mute,
.set_sysclk = cq93vc_set_dai_sysclk,
};
struct snd_soc_dai cq93vc_dai = {
.name = "CQ93VC",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = CQ93VC_RATES,
.formats = CQ93VC_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = CQ93VC_RATES,
.formats = CQ93VC_FORMATS,},
.ops = &cq93vc_dai_ops,
};
EXPORT_SYMBOL_GPL(cq93vc_dai);
static int cq93vc_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static struct snd_soc_codec *cq93vc_codec;
static int cq93vc_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
struct snd_soc_codec *codec;
int ret;
socdev->card->codec = cq93vc_codec;
codec = socdev->card->codec;
/* Register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
dev_err(dev, "%s: failed to create pcms\n", pdev->name);
return ret;
}
/* Set controls */
snd_soc_add_controls(codec, cq93vc_snd_controls,
ARRAY_SIZE(cq93vc_snd_controls));
/* Off, with power on */
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int cq93vc_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0;
}
struct snd_soc_codec_device soc_codec_dev_cq93vc = {
.probe = cq93vc_probe,
.remove = cq93vc_remove,
.resume = cq93vc_resume,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
static __init int cq93vc_codec_probe(struct platform_device *pdev)
{
struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
int ret;
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL) {
dev_dbg(davinci_vc->dev,
"could not allocate memory for codec data\n");
return -ENOMEM;
}
davinci_vc->cq93vc.codec = codec;
cq93vc_dai.dev = &pdev->dev;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
codec->dev = &pdev->dev;
codec->name = "CQ93VC";
codec->owner = THIS_MODULE;
codec->read = cq93vc_read;
codec->write = cq93vc_write;
codec->set_bias_level = cq93vc_set_bias_level;
codec->dai = &cq93vc_dai;
codec->num_dai = 1;
codec->control_data = davinci_vc;
cq93vc_codec = codec;
ret = snd_soc_register_codec(codec);
if (ret) {
dev_err(davinci_vc->dev, "failed to register codec\n");
goto fail1;
}
ret = snd_soc_register_dai(&cq93vc_dai);
if (ret) {
dev_err(davinci_vc->dev, "could register dai\n");
goto fail2;
}
return 0;
fail2:
snd_soc_unregister_codec(codec);
fail1:
kfree(codec);
cq93vc_codec = NULL;
return ret;
}
static int __devexit cq93vc_codec_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
snd_soc_unregister_dai(&cq93vc_dai);
snd_soc_unregister_codec(&codec);
kfree(codec);
cq93vc_codec = NULL;
return 0;
}
static struct platform_driver cq93vc_codec_driver = {
.driver = {
.name = "cq93vc",
.owner = THIS_MODULE,
},
.probe = cq93vc_codec_probe,
.remove = __devexit_p(cq93vc_codec_remove),
};
static __init int cq93vc_init(void)
{
return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe);
}
module_init(cq93vc_init);
static __exit void cq93vc_exit(void)
{
platform_driver_unregister(&cq93vc_codec_driver);
}
module_exit(cq93vc_exit);
MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
MODULE_AUTHOR("Miguel Aguilar");
MODULE_LICENSE("GPL");
/*
* ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
*
* Copyright (C) 2010 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.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 Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CQ93VC_H
#define _CQ93VC_H
extern struct snd_soc_dai cq93vc_dai;
extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
#endif
...@@ -211,7 +211,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -211,7 +211,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
unsigned int rates = 0; unsigned int rates = 0;
unsigned int rate_min = -1; unsigned int rate_min = -1;
unsigned int rate_max = 0; unsigned int rate_max = 0;
...@@ -270,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -270,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format) unsigned int format)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret = 0; int ret = 0;
/* set DAI format */ /* set DAI format */
...@@ -412,7 +412,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, ...@@ -412,7 +412,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret; int ret;
unsigned int i; unsigned int i;
unsigned int rate; unsigned int rate;
...@@ -491,7 +491,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, ...@@ -491,7 +491,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute) static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int reg6; int reg6;
reg6 = snd_soc_read(codec, CS4270_MUTE); reg6 = snd_soc_read(codec, CS4270_MUTE);
...@@ -524,7 +524,7 @@ static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol, ...@@ -524,7 +524,7 @@ static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int left = !ucontrol->value.integer.value[0]; int left = !ucontrol->value.integer.value[0];
int right = !ucontrol->value.integer.value[1]; int right = !ucontrol->value.integer.value[1];
...@@ -600,7 +600,7 @@ static int cs4270_probe(struct platform_device *pdev) ...@@ -600,7 +600,7 @@ static int cs4270_probe(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = cs4270_codec; struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int i, ret; int i, ret;
/* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
...@@ -657,7 +657,7 @@ static int cs4270_remove(struct platform_device *pdev) ...@@ -657,7 +657,7 @@ static int cs4270_remove(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = cs4270_codec; struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
snd_soc_free_pcms(socdev); snd_soc_free_pcms(socdev);
regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
...@@ -730,7 +730,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, ...@@ -730,7 +730,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->dai = &cs4270_dai; codec->dai = &cs4270_dai;
codec->num_dai = 1; codec->num_dai = 1;
codec->private_data = cs4270; snd_soc_codec_set_drvdata(codec, cs4270);
codec->control_data = i2c_client; codec->control_data = i2c_client;
codec->read = cs4270_read_reg_cache; codec->read = cs4270_read_reg_cache;
codec->write = cs4270_i2c_write; codec->write = cs4270_i2c_write;
...@@ -843,7 +843,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); ...@@ -843,7 +843,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
{ {
struct snd_soc_codec *codec = cs4270_codec; struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int reg, ret; int reg, ret;
reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
...@@ -863,7 +863,7 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) ...@@ -863,7 +863,7 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
static int cs4270_soc_resume(struct platform_device *pdev) static int cs4270_soc_resume(struct platform_device *pdev)
{ {
struct snd_soc_codec *codec = cs4270_codec; struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = codec->private_data; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c_client = codec->control_data; struct i2c_client *i2c_client = codec->control_data;
int reg; int reg;
......
...@@ -387,7 +387,7 @@ static int cx20442_register(struct cx20442_priv *cx20442) ...@@ -387,7 +387,7 @@ static int cx20442_register(struct cx20442_priv *cx20442)
codec->name = "CX20442"; codec->name = "CX20442";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->private_data = cx20442; snd_soc_codec_set_drvdata(codec, cx20442);
codec->dai = &cx20442_dai; codec->dai = &cx20442_dai;
codec->num_dai = 1; codec->num_dai = 1;
......
...@@ -56,8 +56,14 @@ ...@@ -56,8 +56,14 @@
#define DA7210_DAI_SRC_SEL 0x25 #define DA7210_DAI_SRC_SEL 0x25
#define DA7210_DAI_CFG1 0x26 #define DA7210_DAI_CFG1 0x26
#define DA7210_DAI_CFG3 0x28 #define DA7210_DAI_CFG3 0x28
#define DA7210_PLL_DIV1 0x29
#define DA7210_PLL_DIV2 0x2A
#define DA7210_PLL_DIV3 0x2B #define DA7210_PLL_DIV3 0x2B
#define DA7210_PLL 0x2C #define DA7210_PLL 0x2C
#define DA7210_A_HID_UNLOCK 0x8A
#define DA7210_A_TEST_UNLOCK 0x8B
#define DA7210_A_PLL1 0x90
#define DA7210_A_CP_MODE 0xA7
/* STARTUP1 bit fields */ /* STARTUP1 bit fields */
#define DA7210_SC_MST_EN (1 << 0) #define DA7210_SC_MST_EN (1 << 0)
...@@ -75,15 +81,14 @@ ...@@ -75,15 +81,14 @@
/* INMIX_R bit fields */ /* INMIX_R bit fields */
#define DA7210_IN_R_EN (1 << 7) #define DA7210_IN_R_EN (1 << 7)
/* ADC_HPF bit fields */
#define DA7210_ADC_VOICE_EN (1 << 7)
/* ADC bit fields */ /* ADC bit fields */
#define DA7210_ADC_L_EN (1 << 3) #define DA7210_ADC_L_EN (1 << 3)
#define DA7210_ADC_R_EN (1 << 7) #define DA7210_ADC_R_EN (1 << 7)
/* DAC_HPF fields */ /* DAC/ADC HPF fields */
#define DA7210_DAC_VOICE_EN (1 << 7) #define DA7210_VOICE_F0_MASK (0x7 << 4)
#define DA7210_VOICE_F0_25 (1 << 4)
#define DA7210_VOICE_EN (1 << 7)
/* DAC_SEL bit fields */ /* DAC_SEL bit fields */
#define DA7210_DAC_L_SRC_DAI_L (4 << 0) #define DA7210_DAC_L_SRC_DAI_L (4 << 0)
...@@ -124,7 +129,19 @@ ...@@ -124,7 +129,19 @@
#define DA7210_PLL_BYP (1 << 6) #define DA7210_PLL_BYP (1 << 6)
/* PLL bit fields */ /* PLL bit fields */
#define DA7210_PLL_FS_48000 (11 << 0) #define DA7210_PLL_FS_MASK (0xF << 0)
#define DA7210_PLL_FS_8000 (0x1 << 0)
#define DA7210_PLL_FS_11025 (0x2 << 0)
#define DA7210_PLL_FS_12000 (0x3 << 0)
#define DA7210_PLL_FS_16000 (0x5 << 0)
#define DA7210_PLL_FS_22050 (0x6 << 0)
#define DA7210_PLL_FS_24000 (0x7 << 0)
#define DA7210_PLL_FS_32000 (0x9 << 0)
#define DA7210_PLL_FS_44100 (0xA << 0)
#define DA7210_PLL_FS_48000 (0xB << 0)
#define DA7210_PLL_FS_88200 (0xE << 0)
#define DA7210_PLL_FS_96000 (0xF << 0)
#define DA7210_PLL_EN (0x1 << 7)
#define DA7210_VERSION "0.0.1" #define DA7210_VERSION "0.0.1"
...@@ -165,7 +182,7 @@ static const u8 da7210_reg[] = { ...@@ -165,7 +182,7 @@ static const u8 da7210_reg[] = {
static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg) static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg)
{ {
u8 *cache = codec->reg_cache; u8 *cache = codec->reg_cache;
BUG_ON(reg > ARRAY_SIZE(da7210_reg)); BUG_ON(reg >= ARRAY_SIZE(da7210_reg));
return cache[reg]; return cache[reg];
} }
...@@ -242,7 +259,8 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, ...@@ -242,7 +259,8 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
u32 dai_cfg1; u32 dai_cfg1;
u32 reg, mask; u32 hpf_reg, hpf_mask, hpf_value;
u32 fs, bypass;
/* set DAI source to Left and Right ADC */ /* set DAI source to Left and Right ADC */
da7210_write(codec, DA7210_DAI_SRC_SEL, da7210_write(codec, DA7210_DAI_SRC_SEL,
...@@ -266,25 +284,84 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, ...@@ -266,25 +284,84 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
/* FIXME hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
* DA7210_DAC_HPF : DA7210_ADC_HPF;
* It support 48K only now
*/
switch (params_rate(params)) { 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: case 48000:
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { fs = DA7210_PLL_FS_48000;
reg = DA7210_DAC_HPF; hpf_mask = DA7210_VOICE_EN;
mask = DA7210_DAC_VOICE_EN; hpf_value = 0;
} else { bypass = DA7210_PLL_BYP;
reg = DA7210_ADC_HPF; break;
mask = DA7210_ADC_VOICE_EN; 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; break;
default: default:
return -EINVAL; return -EINVAL;
} }
snd_soc_update_bits(codec, reg, mask, 0); /* 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);
/* Enable active mode */
snd_soc_update_bits(codec, DA7210_STARTUP1,
DA7210_SC_MST_EN, DA7210_SC_MST_EN);
return 0; return 0;
} }
...@@ -362,6 +439,7 @@ struct snd_soc_dai da7210_dai = { ...@@ -362,6 +439,7 @@ struct snd_soc_dai da7210_dai = {
.formats = DA7210_FORMATS, .formats = DA7210_FORMATS,
}, },
.ops = &da7210_dai_ops, .ops = &da7210_dai_ops,
.symmetric_rates = 1,
}; };
EXPORT_SYMBOL_GPL(da7210_dai); EXPORT_SYMBOL_GPL(da7210_dai);
...@@ -383,7 +461,7 @@ static int da7210_init(struct da7210_priv *da7210) ...@@ -383,7 +461,7 @@ static int da7210_init(struct da7210_priv *da7210)
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = da7210; snd_soc_codec_set_drvdata(codec, da7210);
codec->name = "DA7210"; codec->name = "DA7210";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = da7210_read; codec->read = da7210_read;
...@@ -416,8 +494,22 @@ static int da7210_init(struct da7210_priv *da7210) ...@@ -416,8 +494,22 @@ static int da7210_init(struct da7210_priv *da7210)
/* FIXME /* FIXME
* *
* This driver use fixed value here * This driver use fixed value here
* And below settings expects MCLK = 12.288MHz
*
* When you select different MCLK, please check...
* DA7210_PLL_DIV1 val
* DA7210_PLL_DIV2 val
* DA7210_PLL_DIV3 val
* DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
*/ */
/*
* make sure that DA7210 use bypass mode before start up
*/
da7210_write(codec, DA7210_STARTUP1, 0);
da7210_write(codec, DA7210_PLL_DIV3,
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
/* /*
* ADC settings * ADC settings
*/ */
...@@ -454,9 +546,28 @@ static int da7210_init(struct da7210_priv *da7210) ...@@ -454,9 +546,28 @@ static int da7210_init(struct da7210_priv *da7210)
/* Diable PLL and bypass it */ /* Diable PLL and bypass it */
da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
/* Bypass PLL and set MCLK freq rang to 10-20MHz */ /*
da7210_write(codec, DA7210_PLL_DIV3, * If 48kHz sound came, it use bypass mode,
* and when it is 44.1kHz, it use PLL.
*
* This time, this driver sets PLL always ON
* and controls bypass/PLL mode by switching
* 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 |
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); 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);
/* Activate all enabled subsystem */ /* Activate all enabled subsystem */
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
......
...@@ -140,6 +140,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0), ...@@ -140,6 +140,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0),
SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
...@@ -277,7 +278,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, ...@@ -277,7 +278,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct ssm2602_priv *ssm2602 = codec->private_data; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = codec->control_data; struct i2c_client *i2c = codec->control_data;
u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
int i = get_coeff(ssm2602->sysclk, params_rate(params)); int i = get_coeff(ssm2602->sysclk, params_rate(params));
...@@ -322,7 +323,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, ...@@ -322,7 +323,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct ssm2602_priv *ssm2602 = codec->private_data; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = codec->control_data; struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime; struct snd_pcm_runtime *master_runtime;
...@@ -373,7 +374,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, ...@@ -373,7 +374,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct ssm2602_priv *ssm2602 = codec->private_data; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
/* deactivate */ /* deactivate */
if (!codec->active) if (!codec->active)
...@@ -401,7 +402,7 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -401,7 +402,7 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct ssm2602_priv *ssm2602 = codec->private_data; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
switch (freq) { switch (freq) {
case 11289600: case 11289600:
case 12000000: case 12000000:
...@@ -559,7 +560,6 @@ static int ssm2602_resume(struct platform_device *pdev) ...@@ -559,7 +560,6 @@ static int ssm2602_resume(struct platform_device *pdev)
codec->hw_write(codec->control_data, data, 2); codec->hw_write(codec->control_data, data, 2);
} }
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
ssm2602_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
...@@ -605,8 +605,7 @@ static int ssm2602_init(struct snd_soc_device *socdev) ...@@ -605,8 +605,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V);
ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
/*select Line in as default input*/ /*select Line in as default input*/
ssm2602_write(codec, SSM2602_APANA, ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC |
APANA_ENABLE_MIC_BOOST); APANA_ENABLE_MIC_BOOST);
ssm2602_write(codec, SSM2602_PWR, 0); ssm2602_write(codec, SSM2602_PWR, 0);
...@@ -727,7 +726,7 @@ static int ssm2602_probe(struct platform_device *pdev) ...@@ -727,7 +726,7 @@ static int ssm2602_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
codec->private_data = ssm2602; snd_soc_codec_set_drvdata(codec, ssm2602);
socdev->card->codec = codec; socdev->card->codec = codec;
mutex_init(&codec->mutex); mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
...@@ -760,7 +759,7 @@ static int ssm2602_remove(struct platform_device *pdev) ...@@ -760,7 +759,7 @@ static int ssm2602_remove(struct platform_device *pdev)
i2c_unregister_device(codec->control_data); i2c_unregister_device(codec->control_data);
i2c_del_driver(&ssm2602_i2c_driver); i2c_del_driver(&ssm2602_i2c_driver);
#endif #endif
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
kfree(codec); kfree(codec);
return 0; return 0;
......
...@@ -289,9 +289,6 @@ static int stac9766_codec_resume(struct platform_device *pdev) ...@@ -289,9 +289,6 @@ static int stac9766_codec_resume(struct platform_device *pdev)
} }
stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
stac9766_set_bias_level(codec, SND_SOC_BIAS_ON);
return 0; return 0;
} }
...@@ -410,7 +407,7 @@ static int stac9766_codec_probe(struct platform_device *pdev) ...@@ -410,7 +407,7 @@ static int stac9766_codec_probe(struct platform_device *pdev)
pcm_err: pcm_err:
snd_soc_free_ac97_codec(codec); snd_soc_free_ac97_codec(codec);
codec_err: codec_err:
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
cache_err: cache_err:
kfree(socdev->card->codec); kfree(socdev->card->codec);
socdev->card->codec = NULL; socdev->card->codec = NULL;
......
...@@ -634,7 +634,6 @@ static int tlv320aic23_resume(struct platform_device *pdev) ...@@ -634,7 +634,6 @@ static int tlv320aic23_resume(struct platform_device *pdev)
} }
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
......
...@@ -49,7 +49,7 @@ struct aic26 { ...@@ -49,7 +49,7 @@ struct aic26 {
static unsigned int aic26_reg_read(struct snd_soc_codec *codec, static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
unsigned int reg) unsigned int reg)
{ {
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
u16 *cache = codec->reg_cache; u16 *cache = codec->reg_cache;
u16 cmd, value; u16 cmd, value;
u8 buffer[2]; u8 buffer[2];
...@@ -93,7 +93,7 @@ static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec, ...@@ -93,7 +93,7 @@ static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value) unsigned int value)
{ {
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
u16 *cache = codec->reg_cache; u16 *cache = codec->reg_cache;
u16 cmd; u16 cmd;
u8 buffer[4]; u8 buffer[4];
...@@ -132,7 +132,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, ...@@ -132,7 +132,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
int fsref, divisor, wlen, pval, jval, dval, qval; int fsref, divisor, wlen, pval, jval, dval, qval;
u16 reg; u16 reg;
...@@ -199,7 +199,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, ...@@ -199,7 +199,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
static int aic26_mute(struct snd_soc_dai *dai, int mute) static int aic26_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN); u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n", dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
...@@ -218,7 +218,7 @@ static int aic26_set_sysclk(struct snd_soc_dai *codec_dai, ...@@ -218,7 +218,7 @@ static int aic26_set_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i," dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i,"
" freq=%i, dir=%i)\n", " freq=%i, dir=%i)\n",
...@@ -235,7 +235,7 @@ static int aic26_set_sysclk(struct snd_soc_dai *codec_dai, ...@@ -235,7 +235,7 @@ static int aic26_set_sysclk(struct snd_soc_dai *codec_dai,
static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct aic26 *aic26 = codec->private_data; struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n", dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n",
codec_dai, fmt); codec_dai, fmt);
...@@ -431,7 +431,7 @@ static int aic26_spi_probe(struct spi_device *spi) ...@@ -431,7 +431,7 @@ static int aic26_spi_probe(struct spi_device *spi)
/* Setup what we can in the codec structure so that the register /* Setup what we can in the codec structure so that the register
* access functions will work as expected. More will be filled * access functions will work as expected. More will be filled
* out when it is probed by the SoC CODEC part of this driver */ * out when it is probed by the SoC CODEC part of this driver */
aic26->codec.private_data = aic26; snd_soc_codec_set_drvdata(&aic26->codec, aic26);
aic26->codec.name = "aic26"; aic26->codec.name = "aic26";
aic26->codec.owner = THIS_MODULE; aic26->codec.owner = THIS_MODULE;
aic26->codec.dai = &aic26_dai; aic26->codec.dai = &aic26_dai;
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -47,16 +49,25 @@ ...@@ -47,16 +49,25 @@
#include <sound/soc-dapm.h> #include <sound/soc-dapm.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/tlv320aic3x.h>
#include "tlv320aic3x.h" #include "tlv320aic3x.h"
#define AIC3X_VERSION "0.2" #define AIC3X_NUM_SUPPLIES 4
static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
"IOVDD", /* I/O Voltage */
"DVDD", /* Digital Core Voltage */
"AVDD", /* Analog DAC Voltage */
"DRVDD", /* ADC Analog and Output Driver Voltage */
};
/* codec private data */ /* codec private data */
struct aic3x_priv { struct aic3x_priv {
struct snd_soc_codec codec; struct snd_soc_codec codec;
struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
unsigned int sysclk; unsigned int sysclk;
int master; int master;
int gpio_reset;
}; };
/* /*
...@@ -764,7 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, ...@@ -764,7 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct aic3x_priv *aic3x = codec->private_data; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
u16 d, pll_d = 1; u16 d, pll_d = 1;
...@@ -931,7 +942,7 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -931,7 +942,7 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct aic3x_priv *aic3x = codec->private_data; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
aic3x->sysclk = freq; aic3x->sysclk = freq;
return 0; return 0;
...@@ -941,7 +952,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -941,7 +952,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct aic3x_priv *aic3x = codec->private_data; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
u8 iface_areg, iface_breg; u8 iface_areg, iface_breg;
int delay = 0; int delay = 0;
...@@ -995,12 +1006,13 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -995,12 +1006,13 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int aic3x_set_bias_level(struct snd_soc_codec *codec, static int aic3x_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct aic3x_priv *aic3x = codec->private_data; struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
u8 reg; u8 reg;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* all power is driven by DAPM system */ break;
case SND_SOC_BIAS_PREPARE:
if (aic3x->master) { if (aic3x->master) {
/* enable pll */ /* enable pll */
reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
...@@ -1008,48 +1020,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, ...@@ -1008,48 +1020,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
reg | PLL_ENABLE); reg | PLL_ENABLE);
} }
break; break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* /* fall through and disable pll */
* all power is driven by DAPM system,
* so output power is safe if bypass was set
*/
if (aic3x->master) {
/* disable pll */
reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
aic3x_write(codec, AIC3X_PLL_PROGA_REG,
reg & ~PLL_ENABLE);
}
break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
/* force all power off */
reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL);
aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON);
reg = aic3x_read_reg_cache(codec, LINE1R_2_RADC_CTRL);
aic3x_write(codec, LINE1R_2_RADC_CTRL, reg & ~RADC_PWR_ON);
reg = aic3x_read_reg_cache(codec, DAC_PWR);
aic3x_write(codec, DAC_PWR, reg & ~(LDAC_PWR_ON | RDAC_PWR_ON));
reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL);
aic3x_write(codec, HPLOUT_CTRL, reg & ~HPLOUT_PWR_ON);
reg = aic3x_read_reg_cache(codec, HPROUT_CTRL);
aic3x_write(codec, HPROUT_CTRL, reg & ~HPROUT_PWR_ON);
reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL);
aic3x_write(codec, HPLCOM_CTRL, reg & ~HPLCOM_PWR_ON);
reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL);
aic3x_write(codec, HPRCOM_CTRL, reg & ~HPRCOM_PWR_ON);
reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL);
aic3x_write(codec, MONOLOPM_CTRL, reg & ~MONOLOPM_PWR_ON);
reg = aic3x_read_reg_cache(codec, LLOPM_CTRL);
aic3x_write(codec, LLOPM_CTRL, reg & ~LLOPM_PWR_ON);
reg = aic3x_read_reg_cache(codec, RLOPM_CTRL);
aic3x_write(codec, RLOPM_CTRL, reg & ~RLOPM_PWR_ON);
if (aic3x->master) { if (aic3x->master) {
/* disable pll */ /* disable pll */
reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
...@@ -1171,7 +1144,7 @@ static int aic3x_resume(struct platform_device *pdev) ...@@ -1171,7 +1144,7 @@ static int aic3x_resume(struct platform_device *pdev)
codec->hw_write(codec->control_data, data, 2); codec->hw_write(codec->control_data, data, 2);
} }
aic3x_set_bias_level(codec, codec->suspend_bias_level); aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
} }
...@@ -1309,6 +1282,13 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) ...@@ -1309,6 +1282,13 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_dai(&aic3x_dai);
snd_soc_unregister_codec(&aic3x->codec); snd_soc_unregister_codec(&aic3x->codec);
if (aic3x->gpio_reset >= 0) {
gpio_set_value(aic3x->gpio_reset, 0);
gpio_free(aic3x->gpio_reset);
}
regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
kfree(aic3x); kfree(aic3x);
aic3x_codec = NULL; aic3x_codec = NULL;
...@@ -1330,6 +1310,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, ...@@ -1330,6 +1310,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
{ {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct aic3x_priv *aic3x; struct aic3x_priv *aic3x;
struct aic3x_pdata *pdata = i2c->dev.platform_data;
int ret, i;
aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
if (aic3x == NULL) { if (aic3x == NULL) {
...@@ -1339,13 +1321,53 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, ...@@ -1339,13 +1321,53 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
codec = &aic3x->codec; codec = &aic3x->codec;
codec->dev = &i2c->dev; codec->dev = &i2c->dev;
codec->private_data = aic3x; snd_soc_codec_set_drvdata(codec, aic3x);
codec->control_data = i2c; codec->control_data = i2c;
codec->hw_write = (hw_write_t) i2c_master_send; codec->hw_write = (hw_write_t) i2c_master_send;
i2c_set_clientdata(i2c, aic3x); i2c_set_clientdata(i2c, aic3x);
aic3x->gpio_reset = -1;
if (pdata && pdata->gpio_reset >= 0) {
ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
if (ret != 0)
goto err_gpio;
aic3x->gpio_reset = pdata->gpio_reset;
gpio_direction_output(aic3x->gpio_reset, 0);
}
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
aic3x->supplies[i].supply = aic3x_supply_names[i];
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
aic3x->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
goto err_get;
}
ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
aic3x->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
goto err_enable;
}
if (aic3x->gpio_reset >= 0) {
udelay(1);
gpio_set_value(aic3x->gpio_reset, 1);
}
return aic3x_register(codec); return aic3x_register(codec);
err_enable:
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
err_get:
if (aic3x->gpio_reset >= 0)
gpio_free(aic3x->gpio_reset);
err_gpio:
kfree(aic3x);
return ret;
} }
static int aic3x_i2c_remove(struct i2c_client *client) static int aic3x_i2c_remove(struct i2c_client *client)
......
This diff is collapsed.
...@@ -36,24 +36,14 @@ ...@@ -36,24 +36,14 @@
static struct i2c_client *tpa6130a2_client; static struct i2c_client *tpa6130a2_client;
#define TPA6130A2_NUM_SUPPLIES 2
static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
"CPVSS",
"Vdd",
};
static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
"HPVdd",
"AVdd",
};
/* This struct is used to save the context */ /* This struct is used to save the context */
struct tpa6130a2_data { struct tpa6130a2_data {
struct mutex mutex; struct mutex mutex;
unsigned char regs[TPA6130A2_CACHEREGNUM]; unsigned char regs[TPA6130A2_CACHEREGNUM];
struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; struct regulator *supply;
int power_gpio; int power_gpio;
unsigned char power_state; unsigned char power_state;
enum tpa_model id;
}; };
static int tpa6130a2_i2c_read(int reg) static int tpa6130a2_i2c_read(int reg)
...@@ -135,11 +125,10 @@ static int tpa6130a2_power(int power) ...@@ -135,11 +125,10 @@ static int tpa6130a2_power(int power)
if (data->power_gpio >= 0) if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 1); gpio_set_value(data->power_gpio, 1);
ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), ret = regulator_enable(data->supply);
data->supplies);
if (ret != 0) { if (ret != 0) {
dev_err(&tpa6130a2_client->dev, dev_err(&tpa6130a2_client->dev,
"Failed to enable supplies: %d\n", ret); "Failed to enable supply: %d\n", ret);
goto exit; goto exit;
} }
...@@ -160,11 +149,10 @@ static int tpa6130a2_power(int power) ...@@ -160,11 +149,10 @@ static int tpa6130a2_power(int power)
if (data->power_gpio >= 0) if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 0); gpio_set_value(data->power_gpio, 0);
ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies), ret = regulator_disable(data->supply);
data->supplies);
if (ret != 0) { if (ret != 0) {
dev_err(&tpa6130a2_client->dev, dev_err(&tpa6130a2_client->dev,
"Failed to disable supplies: %d\n", ret); "Failed to disable supply: %d\n", ret);
goto exit; goto exit;
} }
...@@ -176,7 +164,7 @@ static int tpa6130a2_power(int power) ...@@ -176,7 +164,7 @@ static int tpa6130a2_power(int power)
return ret; return ret;
} }
static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
...@@ -184,7 +172,8 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, ...@@ -184,7 +172,8 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
struct tpa6130a2_data *data; struct tpa6130a2_data *data;
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
unsigned int mask = mc->max; int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
BUG_ON(tpa6130a2_client == NULL); BUG_ON(tpa6130a2_client == NULL);
...@@ -197,13 +186,13 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, ...@@ -197,13 +186,13 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
if (invert) if (invert)
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
mask - ucontrol->value.integer.value[0]; max - ucontrol->value.integer.value[0];
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
return 0; return 0;
} }
static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
...@@ -211,7 +200,8 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, ...@@ -211,7 +200,8 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
struct tpa6130a2_data *data; struct tpa6130a2_data *data;
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
unsigned int mask = mc->max; int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
unsigned int val = (ucontrol->value.integer.value[0] & mask); unsigned int val = (ucontrol->value.integer.value[0] & mask);
unsigned int val_reg; unsigned int val_reg;
...@@ -220,7 +210,7 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, ...@@ -220,7 +210,7 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
data = i2c_get_clientdata(tpa6130a2_client); data = i2c_get_clientdata(tpa6130a2_client);
if (invert) if (invert)
val = mask - val; val = max - val;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
...@@ -260,10 +250,24 @@ static const unsigned int tpa6130_tlv[] = { ...@@ -260,10 +250,24 @@ static const unsigned int tpa6130_tlv[] = {
static const struct snd_kcontrol_new tpa6130a2_controls[] = { static const struct snd_kcontrol_new tpa6130a2_controls[] = {
SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
tpa6130a2_get_reg, tpa6130a2_set_reg, tpa6130a2_get_volsw, tpa6130a2_put_volsw,
tpa6130_tlv), tpa6130_tlv),
}; };
static const unsigned int tpa6140_tlv[] = {
TLV_DB_RANGE_HEAD(3),
0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0),
9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0),
17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0),
};
static const struct snd_kcontrol_new tpa6140a2_controls[] = {
SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume",
TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0,
tpa6130a2_get_volsw, tpa6130a2_put_volsw,
tpa6140_tlv),
};
/* /*
* Enable or disable channel (left or right) * Enable or disable channel (left or right)
* The bit number for mute and amplifier are the same per channel: * The bit number for mute and amplifier are the same per channel:
...@@ -355,8 +359,8 @@ static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { ...@@ -355,8 +359,8 @@ static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
0, 0, tpa6130a2_supply_event, 0, 0, tpa6130a2_supply_event,
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
/* Outputs */ /* Outputs */
SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL), SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL), SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
}; };
static const struct snd_soc_dapm_route audio_map[] = { static const struct snd_soc_dapm_route audio_map[] = {
...@@ -369,13 +373,22 @@ static const struct snd_soc_dapm_route audio_map[] = { ...@@ -369,13 +373,22 @@ static const struct snd_soc_dapm_route audio_map[] = {
int tpa6130a2_add_controls(struct snd_soc_codec *codec) int tpa6130a2_add_controls(struct snd_soc_codec *codec)
{ {
struct tpa6130a2_data *data;
BUG_ON(tpa6130a2_client == NULL);
data = i2c_get_clientdata(tpa6130a2_client);
snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
ARRAY_SIZE(tpa6130a2_dapm_widgets)); ARRAY_SIZE(tpa6130a2_dapm_widgets));
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
return snd_soc_add_controls(codec, tpa6130a2_controls, if (data->id == TPA6140A2)
ARRAY_SIZE(tpa6130a2_controls)); return snd_soc_add_controls(codec, tpa6140a2_controls,
ARRAY_SIZE(tpa6140a2_controls));
else
return snd_soc_add_controls(codec, tpa6130a2_controls,
ARRAY_SIZE(tpa6130a2_controls));
} }
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
...@@ -386,7 +399,8 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, ...@@ -386,7 +399,8 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
struct device *dev; struct device *dev;
struct tpa6130a2_data *data; struct tpa6130a2_data *data;
struct tpa6130a2_platform_data *pdata; struct tpa6130a2_platform_data *pdata;
int i, ret; const char *regulator;
int ret;
dev = &client->dev; dev = &client->dev;
...@@ -408,6 +422,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, ...@@ -408,6 +422,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
data->power_gpio = pdata->power_gpio; data->power_gpio = pdata->power_gpio;
data->id = pdata->id;
mutex_init(&data->mutex); mutex_init(&data->mutex);
...@@ -426,26 +441,22 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, ...@@ -426,26 +441,22 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
gpio_direction_output(data->power_gpio, 0); gpio_direction_output(data->power_gpio, 0);
} }
switch (pdata->id) { switch (data->id) {
default:
dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
pdata->id);
case TPA6130A2: case TPA6130A2:
for (i = 0; i < ARRAY_SIZE(data->supplies); i++) regulator = "Vdd";
data->supplies[i].supply = tpa6130a2_supply_names[i];
break; break;
case TPA6140A2: case TPA6140A2:
for (i = 0; i < ARRAY_SIZE(data->supplies); i++) regulator = "AVdd";
data->supplies[i].supply = tpa6140a2_supply_names[i];;
break; break;
default:
dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
pdata->id);
for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
data->supplies[i].supply = tpa6130a2_supply_names[i];
} }
ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), data->supply = regulator_get(dev, regulator);
data->supplies); if (IS_ERR(data->supply)) {
if (ret != 0) { ret = PTR_ERR(data->supply);
dev_err(dev, "Failed to request supplies: %d\n", ret); dev_err(dev, "Failed to request supply: %d\n", ret);
goto err_regulator; goto err_regulator;
} }
...@@ -468,7 +479,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, ...@@ -468,7 +479,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
return 0; return 0;
err_power: err_power:
regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); regulator_put(data->supply);
err_regulator: err_regulator:
if (data->power_gpio >= 0) if (data->power_gpio >= 0)
gpio_free(data->power_gpio); gpio_free(data->power_gpio);
...@@ -489,7 +500,7 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client) ...@@ -489,7 +500,7 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
if (data->power_gpio >= 0) if (data->power_gpio >= 0)
gpio_free(data->power_gpio); gpio_free(data->power_gpio);
regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); regulator_put(data->supply);
kfree(data); kfree(data);
tpa6130a2_client = NULL; tpa6130a2_client = NULL;
......
This diff is collapsed.
This diff is collapsed.
/*
* ALSA SoC TWL6040 codec driver
*
* Author: Misael Lopez Cruz <x0052729@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __TWL6040_H__
#define __TWL6040_H__
#define TWL6040_REG_ASICID 0x01
#define TWL6040_REG_ASICREV 0x02
#define TWL6040_REG_INTID 0x03
#define TWL6040_REG_INTMR 0x04
#define TWL6040_REG_NCPCTL 0x05
#define TWL6040_REG_LDOCTL 0x06
#define TWL6040_REG_HPPLLCTL 0x07
#define TWL6040_REG_LPPLLCTL 0x08
#define TWL6040_REG_LPPLLDIV 0x09
#define TWL6040_REG_AMICBCTL 0x0A
#define TWL6040_REG_DMICBCTL 0x0B
#define TWL6040_REG_MICLCTL 0x0C
#define TWL6040_REG_MICRCTL 0x0D
#define TWL6040_REG_MICGAIN 0x0E
#define TWL6040_REG_LINEGAIN 0x0F
#define TWL6040_REG_HSLCTL 0x10
#define TWL6040_REG_HSRCTL 0x11
#define TWL6040_REG_HSGAIN 0x12
#define TWL6040_REG_EARCTL 0x13
#define TWL6040_REG_HFLCTL 0x14
#define TWL6040_REG_HFLGAIN 0x15
#define TWL6040_REG_HFRCTL 0x16
#define TWL6040_REG_HFRGAIN 0x17
#define TWL6040_REG_VIBCTLL 0x18
#define TWL6040_REG_VIBDATL 0x19
#define TWL6040_REG_VIBCTLR 0x1A
#define TWL6040_REG_VIBDATR 0x1B
#define TWL6040_REG_HKCTL1 0x1C
#define TWL6040_REG_HKCTL2 0x1D
#define TWL6040_REG_GPOCTL 0x1E
#define TWL6040_REG_ALB 0x1F
#define TWL6040_REG_DLB 0x20
#define TWL6040_REG_TRIM1 0x28
#define TWL6040_REG_TRIM2 0x29
#define TWL6040_REG_TRIM3 0x2A
#define TWL6040_REG_HSOTRIM 0x2B
#define TWL6040_REG_HFOTRIM 0x2C
#define TWL6040_REG_ACCCTL 0x2D
#define TWL6040_REG_STATUS 0x2E
#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
#define TWL6040_VIOREGNUM 18
#define TWL6040_VDDREGNUM 21
/* INTID (0x03) fields */
#define TWL6040_THINT 0x01
#define TWL6040_PLUGINT 0x02
#define TWL6040_UNPLUGINT 0x04
#define TWL6040_HOOKINT 0x08
#define TWL6040_HFINT 0x10
#define TWL6040_VIBINT 0x20
#define TWL6040_READYINT 0x40
/* INTMR (0x04) fields */
#define TWL6040_READYMSK 0x40
#define TWL6040_ALLINT_MSK 0x7B
/* NCPCTL (0x05) fields */
#define TWL6040_NCPENA 0x01
#define TWL6040_NCPOPEN 0x40
/* LDOCTL (0x06) fields */
#define TWL6040_LSLDOENA 0x01
#define TWL6040_HSLDOENA 0x04
#define TWL6040_REFENA 0x40
#define TWL6040_OSCENA 0x80
/* HPPLLCTL (0x07) fields */
#define TWL6040_HPLLENA 0x01
#define TWL6040_HPLLRST 0x02
#define TWL6040_HPLLBP 0x04
#define TWL6040_HPLLSQRENA 0x08
#define TWL6040_HPLLSQRBP 0x10
#define TWL6040_MCLK_12000KHZ (0 << 5)
#define TWL6040_MCLK_19200KHZ (1 << 5)
#define TWL6040_MCLK_26000KHZ (2 << 5)
#define TWL6040_MCLK_38400KHZ (3 << 5)
#define TWL6040_MCLK_MSK 0x60
/* LPPLLCTL (0x08) fields */
#define TWL6040_LPLLENA 0x01
#define TWL6040_LPLLRST 0x02
#define TWL6040_LPLLSEL 0x04
#define TWL6040_LPLLFIN 0x08
#define TWL6040_HPLLSEL 0x10
/* HSLCTL (0x10) fields */
#define TWL6040_HSDACMODEL 0x02
#define TWL6040_HSDRVMODEL 0x08
/* HSRCTL (0x11) fields */
#define TWL6040_HSDACMODER 0x02
#define TWL6040_HSDRVMODER 0x08
/* ACCCTL (0x2D) fields */
#define TWL6040_RESETSPLIT 0x04
#define TWL6040_SYSCLK_SEL_LPPLL 1
#define TWL6040_SYSCLK_SEL_HPPLL 2
#define TWL6040_HPPLL_ID 1
#define TWL6040_LPPLL_ID 2
extern struct snd_soc_dai twl6040_dai;
extern struct snd_soc_codec_device soc_codec_dev_twl6040;
#endif /* End of __TWL6040_H__ */
...@@ -175,7 +175,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, ...@@ -175,7 +175,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct uda134x_priv *uda134x = codec->private_data; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
struct snd_pcm_runtime *master_runtime; struct snd_pcm_runtime *master_runtime;
if (uda134x->master_substream) { if (uda134x->master_substream) {
...@@ -208,7 +208,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, ...@@ -208,7 +208,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct uda134x_priv *uda134x = codec->private_data; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
if (uda134x->master_substream == substream) if (uda134x->master_substream == substream)
uda134x->master_substream = uda134x->slave_substream; uda134x->master_substream = uda134x->slave_substream;
...@@ -223,7 +223,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, ...@@ -223,7 +223,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct uda134x_priv *uda134x = codec->private_data; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
u8 hw_params; u8 hw_params;
if (substream == uda134x->slave_substream) { if (substream == uda134x->slave_substream) {
...@@ -295,7 +295,7 @@ static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -295,7 +295,7 @@ static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct uda134x_priv *uda134x = codec->private_data; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__, pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
clk_id, freq, dir); clk_id, freq, dir);
...@@ -317,7 +317,7 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -317,7 +317,7 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct uda134x_priv *uda134x = codec->private_data; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
pr_debug("%s fmt: %08X\n", __func__, fmt); pr_debug("%s fmt: %08X\n", __func__, fmt);
...@@ -432,6 +432,14 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), ...@@ -432,6 +432,14 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
}; };
static const struct snd_kcontrol_new uda1345_snd_controls[] = {
SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
};
static struct snd_soc_dai_ops uda134x_dai_ops = { static struct snd_soc_dai_ops uda134x_dai_ops = {
.startup = uda134x_startup, .startup = uda134x_startup,
.shutdown = uda134x_shutdown, .shutdown = uda134x_shutdown,
...@@ -487,6 +495,7 @@ static int uda134x_soc_probe(struct platform_device *pdev) ...@@ -487,6 +495,7 @@ static int uda134x_soc_probe(struct platform_device *pdev)
case UDA134X_UDA1340: case UDA134X_UDA1340:
case UDA134X_UDA1341: case UDA134X_UDA1341:
case UDA134X_UDA1344: case UDA134X_UDA1344:
case UDA134X_UDA1345:
break; break;
default: default:
printk(KERN_ERR "UDA134X SoC codec: " printk(KERN_ERR "UDA134X SoC codec: "
...@@ -504,7 +513,7 @@ static int uda134x_soc_probe(struct platform_device *pdev) ...@@ -504,7 +513,7 @@ static int uda134x_soc_probe(struct platform_device *pdev)
uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
if (uda134x == NULL) if (uda134x == NULL)
goto priv_err; goto priv_err;
codec->private_data = uda134x; snd_soc_codec_set_drvdata(codec, uda134x);
codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
GFP_KERNEL); GFP_KERNEL);
...@@ -552,6 +561,10 @@ static int uda134x_soc_probe(struct platform_device *pdev) ...@@ -552,6 +561,10 @@ static int uda134x_soc_probe(struct platform_device *pdev)
ret = snd_soc_add_controls(codec, uda1341_snd_controls, ret = snd_soc_add_controls(codec, uda1341_snd_controls,
ARRAY_SIZE(uda1341_snd_controls)); ARRAY_SIZE(uda1341_snd_controls));
break; break;
case UDA134X_UDA1345:
ret = snd_soc_add_controls(codec, uda1345_snd_controls,
ARRAY_SIZE(uda1345_snd_controls));
break;
default: default:
printk(KERN_ERR "%s unknown codec type: %d", printk(KERN_ERR "%s unknown codec type: %d",
__func__, pd->model); __func__, pd->model);
...@@ -568,7 +581,7 @@ static int uda134x_soc_probe(struct platform_device *pdev) ...@@ -568,7 +581,7 @@ static int uda134x_soc_probe(struct platform_device *pdev)
pcm_err: pcm_err:
kfree(codec->reg_cache); kfree(codec->reg_cache);
reg_err: reg_err:
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
priv_err: priv_err:
kfree(codec); kfree(codec);
return ret; return ret;
...@@ -586,7 +599,7 @@ static int uda134x_soc_remove(struct platform_device *pdev) ...@@ -586,7 +599,7 @@ static int uda134x_soc_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev); snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev); snd_soc_dapm_free(socdev);
kfree(codec->private_data); kfree(snd_soc_codec_get_drvdata(codec));
kfree(codec->reg_cache); kfree(codec->reg_cache);
kfree(codec); kfree(codec);
......
...@@ -476,7 +476,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -476,7 +476,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct uda1380_priv *uda1380 = codec->private_data; struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
switch (cmd) { switch (cmd) {
...@@ -670,7 +670,6 @@ static int uda1380_resume(struct platform_device *pdev) ...@@ -670,7 +670,6 @@ static int uda1380_resume(struct platform_device *pdev)
codec->hw_write(codec->control_data, data, 2); codec->hw_write(codec->control_data, data, 2);
} }
uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
uda1380_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
...@@ -774,7 +773,7 @@ static int uda1380_register(struct uda1380_priv *uda1380) ...@@ -774,7 +773,7 @@ static int uda1380_register(struct uda1380_priv *uda1380)
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = uda1380; snd_soc_codec_set_drvdata(codec, uda1380);
codec->name = "UDA1380"; codec->name = "UDA1380";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = uda1380_read_reg_cache; codec->read = uda1380_read_reg_cache;
......
This diff is collapsed.
...@@ -25,5 +25,8 @@ enum wm8350_jack { ...@@ -25,5 +25,8 @@ enum wm8350_jack {
int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
struct snd_soc_jack *jack, int report); struct snd_soc_jack *jack, int report);
int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack,
int detect_report, int short_report);
#endif #endif
This diff is collapsed.
...@@ -557,7 +557,7 @@ static int wm8510_resume(struct platform_device *pdev) ...@@ -557,7 +557,7 @@ static int wm8510_resume(struct platform_device *pdev)
codec->hw_write(codec->control_data, data, 2); codec->hw_write(codec->control_data, data, 2);
} }
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8510_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
......
...@@ -138,7 +138,7 @@ static int wm8523_startup(struct snd_pcm_substream *substream, ...@@ -138,7 +138,7 @@ static int wm8523_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct wm8523_priv *wm8523 = codec->private_data; struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
/* The set of sample rates that can be supported depends on the /* The set of sample rates that can be supported depends on the
* MCLK supplied to the CODEC - enforce this. * MCLK supplied to the CODEC - enforce this.
...@@ -164,7 +164,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, ...@@ -164,7 +164,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8523_priv *wm8523 = codec->private_data; struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
int i; int i;
u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2); u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2);
...@@ -211,7 +211,7 @@ static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -211,7 +211,7 @@ static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct wm8523_priv *wm8523 = codec->private_data; struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
unsigned int val; unsigned int val;
int i; int i;
...@@ -318,7 +318,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -318,7 +318,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int wm8523_set_bias_level(struct snd_soc_codec *codec, static int wm8523_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct wm8523_priv *wm8523 = codec->private_data; struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
int ret, i; int ret, i;
switch (level) { switch (level) {
...@@ -489,7 +489,7 @@ static int wm8523_register(struct wm8523_priv *wm8523, ...@@ -489,7 +489,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,
INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths); INIT_LIST_HEAD(&codec->dapm_paths);
codec->private_data = wm8523; snd_soc_codec_set_drvdata(codec, wm8523);
codec->name = "WM8523"; codec->name = "WM8523";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->bias_level = SND_SOC_BIAS_OFF; codec->bias_level = SND_SOC_BIAS_OFF;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment