Merge branch 'topic/asoc' into for-linus
This commit is contained in:
commit
6db9a0f326
|
@ -5176,7 +5176,7 @@ SAMSUNG AUDIO (ASoC) DRIVERS
|
|||
M: Jassi Brar <jassi.brar@samsung.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: sound/soc/s3c24xx
|
||||
F: sound/soc/samsung
|
||||
|
||||
TLG2300 VIDEO4LINUX-2 DRIVER
|
||||
M: Huang Shijie <shijie8@gmail.com>
|
||||
|
|
|
@ -171,7 +171,7 @@ static void __init openrd_init(void)
|
|||
|
||||
kirkwood_i2c_init();
|
||||
|
||||
if (machine_is_openrd_client()) {
|
||||
if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
|
||||
i2c_register_board_info(0, i2c_board_info,
|
||||
ARRAY_SIZE(i2c_board_info));
|
||||
kirkwood_audio_init();
|
||||
|
|
|
@ -387,7 +387,7 @@ static struct platform_device *h1940_devices[] __initdata = {
|
|||
&s3c_device_wdt,
|
||||
&s3c_device_i2c0,
|
||||
&s3c_device_iis,
|
||||
&s3c_device_pcm,
|
||||
&samsung_asoc_dma,
|
||||
&s3c_device_usbgadget,
|
||||
&h1940_device_leds,
|
||||
&h1940_device_bluetooth,
|
||||
|
|
|
@ -692,7 +692,7 @@ static struct platform_device *rx1950_devices[] __initdata = {
|
|||
&s3c_device_wdt,
|
||||
&s3c_device_i2c0,
|
||||
&s3c_device_iis,
|
||||
&s3c_device_pcm,
|
||||
&samsung_asoc_dma,
|
||||
&s3c_device_usbgadget,
|
||||
&s3c_device_rtc,
|
||||
&s3c_device_nand,
|
||||
|
|
|
@ -695,7 +695,7 @@ static struct clksrc_clk clksrcs[] = {
|
|||
}, {
|
||||
.clk = {
|
||||
.name = "audio-bus",
|
||||
.id = -1, /* There's only one IISv4 port */
|
||||
.id = 2,
|
||||
.ctrlbit = S3C6410_CLKCON_SCLK_AUDIO2,
|
||||
.enable = s3c64xx_sclk_ctrl,
|
||||
},
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
#include <plat/audio.h>
|
||||
#include <plat/gpio-cfg.h>
|
||||
|
||||
static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
|
||||
static const char *rclksrc[] = {
|
||||
[0] = "iis",
|
||||
[1] = "audio-bus",
|
||||
};
|
||||
|
||||
static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
|
||||
{
|
||||
unsigned int base;
|
||||
|
||||
|
@ -33,6 +38,12 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
|
|||
case 1:
|
||||
base = S3C64XX_GPE(0);
|
||||
break;
|
||||
case 2:
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5));
|
||||
return 0;
|
||||
default:
|
||||
printk(KERN_DEBUG "Invalid I2S Controller number: %d\n",
|
||||
pdev->id);
|
||||
|
@ -44,16 +55,6 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev)
|
||||
{
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource s3c64xx_iis0_resource[] = {
|
||||
[0] = {
|
||||
.start = S3C64XX_PA_IIS0,
|
||||
|
@ -72,17 +73,22 @@ static struct resource s3c64xx_iis0_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2s0_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.src_clk = rclksrc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis0 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
|
||||
.resource = s3c64xx_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s0_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis0);
|
||||
|
@ -105,17 +111,13 @@ static struct resource s3c64xx_iis1_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2s1_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis1 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
|
||||
.resource = s3c64xx_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s1_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis1);
|
||||
|
@ -138,17 +140,23 @@ static struct resource s3c64xx_iisv4_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2sv4_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2sv4_cfg_gpio,
|
||||
static struct s3c_audio_pdata i2sv4_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN,
|
||||
.src_clk = rclksrc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iisv4 = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_iisv4_resource),
|
||||
.resource = s3c64xx_iisv4_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2sv4_pdata,
|
||||
.platform_data = &i2sv4_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iisv4);
|
||||
|
@ -288,7 +296,7 @@ static struct s3c_audio_pdata s3c_ac97_pdata;
|
|||
static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device s3c64xx_device_ac97 = {
|
||||
.name = "s3c-ac97",
|
||||
.name = "samsung-ac97",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_ac97_resource),
|
||||
.resource = s3c64xx_ac97_resource,
|
||||
|
@ -307,16 +315,3 @@ void __init s3c64xx_ac97_setup_gpio(int num)
|
|||
else
|
||||
s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
|
||||
}
|
||||
|
||||
static u64 s3c_device_audio_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device s3c_device_pcm = {
|
||||
.name = "s3c24xx-pcm-audio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL(s3c_device_pcm);
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
|
|||
&s3c_device_fb,
|
||||
&s3c_device_ohci,
|
||||
&s3c_device_usb_hsotg,
|
||||
&s3c_device_pcm,
|
||||
&samsung_asoc_dma,
|
||||
&s3c64xx_device_iisv4,
|
||||
&samsung_device_keypad,
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev)
|
|||
base = S5P6442_GPC1(0);
|
||||
break;
|
||||
|
||||
case -1:
|
||||
case 0:
|
||||
base = S5P6442_GPC0(0);
|
||||
break;
|
||||
|
||||
|
@ -42,8 +42,19 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2s_pdata = {
|
||||
static const char *rclksrc_v35[] = {
|
||||
[0] = "busclk",
|
||||
[1] = "i2sclk",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv35_pdata = {
|
||||
.cfg_gpio = s5p6442_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR,
|
||||
.src_clk = rclksrc_v35,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5p6442_iis0_resource[] = {
|
||||
|
@ -62,15 +73,34 @@ static struct resource s5p6442_iis0_resource[] = {
|
|||
.end = DMACH_I2S0_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = DMACH_I2S0S_TX,
|
||||
.end = DMACH_I2S0S_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5p6442_device_iis0 = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5p6442_iis0_resource),
|
||||
.resource = s5p6442_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv35_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *rclksrc_v3[] = {
|
||||
[0] = "iis",
|
||||
[1] = "sclk_audio",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
.cfg_gpio = s5p6442_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.src_clk = rclksrc_v3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -93,12 +123,12 @@ static struct resource s5p6442_iis1_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5p6442_device_iis1 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5p6442_iis1_resource),
|
||||
.resource = s5p6442_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ static struct clk init_clocks_disable[] = {
|
|||
.enable = s5p64x0_pclk_ctrl,
|
||||
.ctrlbit = (1 << 25),
|
||||
}, {
|
||||
.name = "i2s_v40",
|
||||
.name = "iis",
|
||||
.id = 0,
|
||||
.parent = &clk_pclk_low.clk,
|
||||
.enable = s5p64x0_pclk_ctrl,
|
||||
|
|
|
@ -256,7 +256,7 @@ static struct clk init_clocks_disable[] = {
|
|||
.ctrlbit = (1 << 22),
|
||||
}, {
|
||||
.name = "iis",
|
||||
.id = -1,
|
||||
.id = 0,
|
||||
.parent = &clk_pclk_low.clk,
|
||||
.enable = s5p64x0_pclk_ctrl,
|
||||
.ctrlbit = (1 << 26),
|
||||
|
|
|
@ -19,15 +19,19 @@
|
|||
#include <mach/dma.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
static int s5p6440_cfg_i2s(struct platform_device *pdev)
|
||||
static const char *rclksrc[] = {
|
||||
[0] = "iis",
|
||||
[1] = "sclk_audio2",
|
||||
};
|
||||
|
||||
static int s5p64x0_cfg_i2s(struct platform_device *pdev)
|
||||
{
|
||||
/* configure GPIO for i2s port */
|
||||
switch (pdev->id) {
|
||||
case -1:
|
||||
case 0:
|
||||
s3c_gpio_cfgpin_range(S5P6440_GPR(4), 5, S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(5));
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
|
@ -36,31 +40,14 @@ static int s5p6440_cfg_i2s(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int s5p6450_cfg_i2s(struct platform_device *pdev)
|
||||
{
|
||||
/* configure GPIO for i2s port */
|
||||
switch (pdev->id) {
|
||||
case -1:
|
||||
s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5));
|
||||
s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata s5p6440_i2s_pdata = {
|
||||
.cfg_gpio = s5p6440_cfg_i2s,
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s5p6450_i2s_pdata = {
|
||||
.cfg_gpio = s5p6450_cfg_i2s,
|
||||
static struct s3c_audio_pdata s5p64x0_i2s_pdata = {
|
||||
.cfg_gpio = s5p64x0_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN,
|
||||
.src_clk = rclksrc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5p64x0_iis0_resource[] = {
|
||||
|
@ -82,22 +69,22 @@ static struct resource s5p64x0_iis0_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5p6440_device_iis = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5p64x0_iis0_resource),
|
||||
.resource = s5p64x0_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s5p6440_i2s_pdata,
|
||||
.platform_data = &s5p64x0_i2s_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5p6450_device_iis0 = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5p64x0_iis0_resource),
|
||||
.resource = s5p64x0_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s5p6450_i2s_pdata,
|
||||
.platform_data = &s5p64x0_i2s_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -23,17 +23,14 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev)
|
|||
{
|
||||
/* configure GPIO for i2s port */
|
||||
switch (pdev->id) {
|
||||
case 0: /* Dedicated pins */
|
||||
break;
|
||||
case 1:
|
||||
s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4));
|
||||
break;
|
||||
|
||||
case -1: /* Dedicated pins */
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
|
@ -42,8 +39,20 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2s_pdata = {
|
||||
static const char *rclksrc_v5[] = {
|
||||
[0] = "iis",
|
||||
[1] = "i2sclkd2",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv5_pdata = {
|
||||
.cfg_gpio = s5pc100_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
|
||||
| QUIRK_NEED_RSTCLR,
|
||||
.src_clk = rclksrc_v5,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pc100_iis0_resource[] = {
|
||||
|
@ -62,15 +71,34 @@ static struct resource s5pc100_iis0_resource[] = {
|
|||
.end = DMACH_I2S0_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = DMACH_I2S0S_TX,
|
||||
.end = DMACH_I2S0S_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pc100_device_iis0 = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_iis0_resource),
|
||||
.resource = s5pc100_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv5_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *rclksrc_v3[] = {
|
||||
[0] = "iis",
|
||||
[1] = "sclk_audio",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
.cfg_gpio = s5pc100_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.src_clk = rclksrc_v3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -93,12 +121,12 @@ static struct resource s5pc100_iis1_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5pc100_device_iis1 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_iis1_resource),
|
||||
.resource = s5pc100_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -121,12 +149,12 @@ static struct resource s5pc100_iis2_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5pc100_device_iis2 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_iis2_resource),
|
||||
.resource = s5pc100_iis2_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -253,7 +281,7 @@ static struct s3c_audio_pdata s3c_ac97_pdata = {
|
|||
static u64 s5pc100_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device s5pc100_device_ac97 = {
|
||||
.name = "s3c-ac97",
|
||||
.name = "samsung-ac97",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_ac97_resource),
|
||||
.resource = s5pc100_ac97_resource,
|
||||
|
|
|
@ -96,6 +96,7 @@ static struct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = {
|
|||
|
||||
/* I2C0 */
|
||||
static struct i2c_board_info i2c_devs0[] __initdata = {
|
||||
{I2C_BOARD_INFO("wm8580", 0x1b),},
|
||||
};
|
||||
|
||||
/* I2C1 */
|
||||
|
@ -190,6 +191,7 @@ static struct platform_device *smdkc100_devices[] __initdata = {
|
|||
&s3c_device_ts,
|
||||
&s3c_device_wdt,
|
||||
&smdkc100_lcd_powerdev,
|
||||
&samsung_asoc_dma,
|
||||
&s5pc100_device_iis0,
|
||||
&samsung_device_keypad,
|
||||
&s5pc100_device_ac97,
|
||||
|
|
|
@ -467,20 +467,20 @@ static struct clk init_clocks_disable[] = {
|
|||
.enable = s5pv210_clk_ip3_ctrl,
|
||||
.ctrlbit = (1<<21),
|
||||
}, {
|
||||
.name = "i2s_v50",
|
||||
.name = "iis",
|
||||
.id = 0,
|
||||
.parent = &clk_p,
|
||||
.enable = s5pv210_clk_ip3_ctrl,
|
||||
.ctrlbit = (1<<4),
|
||||
}, {
|
||||
.name = "i2s_v32",
|
||||
.id = 0,
|
||||
.name = "iis",
|
||||
.id = 1,
|
||||
.parent = &clk_p,
|
||||
.enable = s5pv210_clk_ip3_ctrl,
|
||||
.ctrlbit = (1 << 5),
|
||||
}, {
|
||||
.name = "i2s_v32",
|
||||
.id = 1,
|
||||
.name = "iis",
|
||||
.id = 2,
|
||||
.parent = &clk_p,
|
||||
.enable = s5pv210_clk_ip3_ctrl,
|
||||
.ctrlbit = (1 << 6),
|
||||
|
|
|
@ -19,22 +19,24 @@
|
|||
#include <mach/dma.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
static const char *rclksrc[] = {
|
||||
[0] = "busclk",
|
||||
[1] = "i2sclk",
|
||||
};
|
||||
|
||||
static int s5pv210_cfg_i2s(struct platform_device *pdev)
|
||||
{
|
||||
/* configure GPIO for i2s port */
|
||||
switch (pdev->id) {
|
||||
case 0:
|
||||
s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
case 1:
|
||||
s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
|
||||
break;
|
||||
|
||||
case -1:
|
||||
s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
|
@ -43,8 +45,15 @@ static int s5pv210_cfg_i2s(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata s3c_i2s_pdata = {
|
||||
static struct s3c_audio_pdata i2sv5_pdata = {
|
||||
.cfg_gpio = s5pv210_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
|
||||
| QUIRK_NEED_RSTCLR,
|
||||
.src_clk = rclksrc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv210_iis0_resource[] = {
|
||||
|
@ -63,15 +72,34 @@ static struct resource s5pv210_iis0_resource[] = {
|
|||
.end = DMACH_I2S0_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = DMACH_I2S0S_TX,
|
||||
.end = DMACH_I2S0S_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv210_device_iis0 = {
|
||||
.name = "s3c64xx-iis-v4",
|
||||
.id = -1,
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_iis0_resource),
|
||||
.resource = s5pv210_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv5_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *rclksrc_v3[] = {
|
||||
[0] = "iis",
|
||||
[1] = "audio-bus",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
.cfg_gpio = s5pv210_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.src_clk = rclksrc_v3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -94,12 +122,12 @@ static struct resource s5pv210_iis1_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5pv210_device_iis1 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_iis1_resource),
|
||||
.resource = s5pv210_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -122,12 +150,12 @@ static struct resource s5pv210_iis2_resource[] = {
|
|||
};
|
||||
|
||||
struct platform_device s5pv210_device_iis2 = {
|
||||
.name = "s3c64xx-iis",
|
||||
.name = "samsung-i2s",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_iis2_resource),
|
||||
.resource = s5pv210_iis2_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_i2s_pdata,
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -283,7 +311,7 @@ static struct s3c_audio_pdata s3c_ac97_pdata = {
|
|||
static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device s5pv210_device_ac97 = {
|
||||
.name = "s3c-ac97",
|
||||
.name = "samsung-ac97",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_ac97_resource),
|
||||
.resource = s5pv210_ac97_resource,
|
||||
|
|
|
@ -11,6 +11,7 @@ if ARCH_S5PV310
|
|||
|
||||
config CPU_S5PV310
|
||||
bool
|
||||
select S3C_PL330_DMA
|
||||
help
|
||||
Enable S5PV310 CPU support
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ obj- :=
|
|||
# Core support for S5PV310 system
|
||||
|
||||
obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o
|
||||
obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o gpiolib.o irq-eint.o
|
||||
obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
|
||||
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
|
@ -27,6 +27,7 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o
|
|||
|
||||
# device support
|
||||
|
||||
obj-y += dev-audio.o
|
||||
obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o
|
||||
obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o
|
||||
obj-$(CONFIG_S5PV310_SETUP_I2C3) += setup-i2c3.o
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
/* linux/arch/arm/mach-s5pv310/dev-audio.c
|
||||
*
|
||||
* Copyright (c) 2010 Samsung Electronics Co. Ltd
|
||||
* Jaswinder Singh <jassi.brar@samsung.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.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/audio.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/dma.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
static const char *rclksrc[] = {
|
||||
[0] = "busclk",
|
||||
[1] = "i2sclk",
|
||||
};
|
||||
|
||||
static int s5pv310_cfg_i2s(struct platform_device *pdev)
|
||||
{
|
||||
/* configure GPIO for i2s port */
|
||||
switch (pdev->id) {
|
||||
case 0:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 7, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
case 1:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(2));
|
||||
break;
|
||||
case 2:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(4));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata i2sv5_pdata = {
|
||||
.cfg_gpio = s5pv310_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
|
||||
| QUIRK_NEED_RSTCLR,
|
||||
.src_clk = rclksrc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_i2s0_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_I2S0,
|
||||
.end = S5PV310_PA_I2S0 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S0_TX,
|
||||
.end = DMACH_I2S0_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S0_RX,
|
||||
.end = DMACH_I2S0_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = DMACH_I2S0S_TX,
|
||||
.end = DMACH_I2S0S_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_i2s0 = {
|
||||
.name = "samsung-i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_i2s0_resource),
|
||||
.resource = s5pv310_i2s0_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv5_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *rclksrc_v3[] = {
|
||||
[0] = "sclk_i2s",
|
||||
[1] = "no_such_clock",
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
.cfg_gpio = s5pv310_cfg_i2s,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_NO_MUXPSR,
|
||||
.src_clk = rclksrc_v3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_i2s1_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_I2S1,
|
||||
.end = S5PV310_PA_I2S1 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S1_TX,
|
||||
.end = DMACH_I2S1_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S1_RX,
|
||||
.end = DMACH_I2S1_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_i2s1 = {
|
||||
.name = "samsung-i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_i2s1_resource),
|
||||
.resource = s5pv310_i2s1_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_i2s2_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_I2S2,
|
||||
.end = S5PV310_PA_I2S2 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S2_TX,
|
||||
.end = DMACH_I2S2_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S2_RX,
|
||||
.end = DMACH_I2S2_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_i2s2 = {
|
||||
.name = "samsung-i2s",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_i2s2_resource),
|
||||
.resource = s5pv310_i2s2_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
/* PCM Controller platform_devices */
|
||||
|
||||
static int s5pv310_pcm_cfg_gpio(struct platform_device *pdev)
|
||||
{
|
||||
switch (pdev->id) {
|
||||
case 0:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 5, S3C_GPIO_SFN(3));
|
||||
break;
|
||||
case 1:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(3));
|
||||
break;
|
||||
case 2:
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(3));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "Invalid PCM Controller number!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm_pdata = {
|
||||
.cfg_gpio = s5pv310_pcm_cfg_gpio,
|
||||
};
|
||||
|
||||
static struct resource s5pv310_pcm0_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_PCM0,
|
||||
.end = S5PV310_PA_PCM0 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_PCM0_TX,
|
||||
.end = DMACH_PCM0_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_PCM0_RX,
|
||||
.end = DMACH_PCM0_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_pcm0 = {
|
||||
.name = "samsung-pcm",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_pcm0_resource),
|
||||
.resource = s5pv310_pcm0_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_pcm_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_pcm1_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_PCM1,
|
||||
.end = S5PV310_PA_PCM1 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_PCM1_TX,
|
||||
.end = DMACH_PCM1_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_PCM1_RX,
|
||||
.end = DMACH_PCM1_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_pcm1 = {
|
||||
.name = "samsung-pcm",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_pcm1_resource),
|
||||
.resource = s5pv310_pcm1_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_pcm_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_pcm2_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_PCM2,
|
||||
.end = S5PV310_PA_PCM2 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_PCM2_TX,
|
||||
.end = DMACH_PCM2_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_PCM2_RX,
|
||||
.end = DMACH_PCM2_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device s5pv310_device_pcm2 = {
|
||||
.name = "samsung-pcm",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_pcm2_resource),
|
||||
.resource = s5pv310_pcm2_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_pcm_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
/* AC97 Controller platform devices */
|
||||
|
||||
static int s5pv310_ac97_cfg_gpio(struct platform_device *pdev)
|
||||
{
|
||||
return s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(4));
|
||||
}
|
||||
|
||||
static struct resource s5pv310_ac97_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_AC97,
|
||||
.end = S5PV310_PA_AC97 + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_AC97_PCMOUT,
|
||||
.end = DMACH_AC97_PCMOUT,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_AC97_PCMIN,
|
||||
.end = DMACH_AC97_PCMIN,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = DMACH_AC97_MICIN,
|
||||
.end = DMACH_AC97_MICIN,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[4] = {
|
||||
.start = IRQ_AC97,
|
||||
.end = IRQ_AC97,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.cfg_gpio = s5pv310_ac97_cfg_gpio,
|
||||
};
|
||||
|
||||
static u64 s5pv310_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device s5pv310_device_ac97 = {
|
||||
.name = "samsung-ac97",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_ac97_resource),
|
||||
.resource = s5pv310_ac97_resource,
|
||||
.dev = {
|
||||
.platform_data = &s3c_ac97_pdata,
|
||||
.dma_mask = &s5pv310_ac97_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
/* S/PDIF Controller platform_device */
|
||||
|
||||
static int s5pv310_spdif_cfg_gpio(struct platform_device *pdev)
|
||||
{
|
||||
s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 2, S3C_GPIO_SFN(3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource s5pv310_spdif_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_SPDIF,
|
||||
.end = S5PV310_PA_SPDIF + 0x100 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_SPDIF,
|
||||
.end = DMACH_SPDIF,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata samsung_spdif_pdata = {
|
||||
.cfg_gpio = s5pv310_spdif_cfg_gpio,
|
||||
};
|
||||
|
||||
static u64 s5pv310_spdif_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device s5pv310_device_spdif = {
|
||||
.name = "samsung-spdif",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_spdif_resource),
|
||||
.resource = s5pv310_spdif_resource,
|
||||
.dev = {
|
||||
.platform_data = &samsung_spdif_pdata,
|
||||
.dma_mask = &s5pv310_spdif_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <plat/devs.h>
|
||||
#include <plat/irqs.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <plat/s3c-pl330-pdata.h>
|
||||
|
||||
static u64 dma_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource s5pv310_pdma0_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_PDMA0,
|
||||
.end = S5PV310_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA0,
|
||||
.end = IRQ_PDMA0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pv310_pdma0_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_PCM0_RX,
|
||||
[1] = DMACH_PCM0_TX,
|
||||
[2] = DMACH_PCM2_RX,
|
||||
[3] = DMACH_PCM2_TX,
|
||||
[4] = DMACH_MSM_REQ0,
|
||||
[5] = DMACH_MSM_REQ2,
|
||||
[6] = DMACH_SPI0_RX,
|
||||
[7] = DMACH_SPI0_TX,
|
||||
[8] = DMACH_SPI2_RX,
|
||||
[9] = DMACH_SPI2_TX,
|
||||
[10] = DMACH_I2S0S_TX,
|
||||
[11] = DMACH_I2S0_RX,
|
||||
[12] = DMACH_I2S0_TX,
|
||||
[13] = DMACH_I2S2_RX,
|
||||
[14] = DMACH_I2S2_TX,
|
||||
[15] = DMACH_UART0_RX,
|
||||
[16] = DMACH_UART0_TX,
|
||||
[17] = DMACH_UART2_RX,
|
||||
[18] = DMACH_UART2_TX,
|
||||
[19] = DMACH_UART4_RX,
|
||||
[20] = DMACH_UART4_TX,
|
||||
[21] = DMACH_SLIMBUS0_RX,
|
||||
[22] = DMACH_SLIMBUS0_TX,
|
||||
[23] = DMACH_SLIMBUS2_RX,
|
||||
[24] = DMACH_SLIMBUS2_TX,
|
||||
[25] = DMACH_SLIMBUS4_RX,
|
||||
[26] = DMACH_SLIMBUS4_TX,
|
||||
[27] = DMACH_AC97_MICIN,
|
||||
[28] = DMACH_AC97_PCMIN,
|
||||
[29] = DMACH_AC97_PCMOUT,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device s5pv310_device_pdma0 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_pdma0_resource),
|
||||
.resource = s5pv310_pdma0_resource,
|
||||
.dev = {
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pv310_pdma0_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv310_pdma1_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV310_PA_PDMA1,
|
||||
.end = S5PV310_PA_PDMA1 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA1,
|
||||
.end = IRQ_PDMA1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pv310_pdma1_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_PCM0_RX,
|
||||
[1] = DMACH_PCM0_TX,
|
||||
[2] = DMACH_PCM1_RX,
|
||||
[3] = DMACH_PCM1_TX,
|
||||
[4] = DMACH_MSM_REQ1,
|
||||
[5] = DMACH_MSM_REQ3,
|
||||
[6] = DMACH_SPI1_RX,
|
||||
[7] = DMACH_SPI1_TX,
|
||||
[8] = DMACH_I2S0S_TX,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S1_RX,
|
||||
[12] = DMACH_I2S1_TX,
|
||||
[13] = DMACH_UART0_RX,
|
||||
[14] = DMACH_UART0_TX,
|
||||
[15] = DMACH_UART1_RX,
|
||||
[16] = DMACH_UART1_TX,
|
||||
[17] = DMACH_UART3_RX,
|
||||
[18] = DMACH_UART3_TX,
|
||||
[19] = DMACH_SLIMBUS1_RX,
|
||||
[20] = DMACH_SLIMBUS1_TX,
|
||||
[21] = DMACH_SLIMBUS3_RX,
|
||||
[22] = DMACH_SLIMBUS3_TX,
|
||||
[23] = DMACH_SLIMBUS5_RX,
|
||||
[24] = DMACH_SLIMBUS5_TX,
|
||||
[25] = DMACH_SLIMBUS0AUX_RX,
|
||||
[26] = DMACH_SLIMBUS0AUX_TX,
|
||||
[27] = DMACH_SPDIF,
|
||||
[28] = DMACH_MAX,
|
||||
[29] = DMACH_MAX,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device s5pv310_device_pdma1 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pv310_pdma1_resource),
|
||||
.resource = s5pv310_pdma1_resource,
|
||||
.dev = {
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pv310_pdma1_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *s5pv310_dmacs[] __initdata = {
|
||||
&s5pv310_device_pdma0,
|
||||
&s5pv310_device_pdma1,
|
||||
};
|
||||
|
||||
static int __init s5pv310_dma_init(void)
|
||||
{
|
||||
platform_add_devices(s5pv310_dmacs, ARRAY_SIZE(s5pv310_dmacs));
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(s5pv310_dma_init);
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common S3C DMA API driver for PL330 */
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
|
@ -54,6 +54,9 @@
|
|||
#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
|
||||
#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
|
||||
|
||||
#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
|
||||
#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
|
||||
|
||||
#define IRQ_TIMER0_VIC COMBINER_IRQ(22, 0)
|
||||
#define IRQ_TIMER1_VIC COMBINER_IRQ(22, 1)
|
||||
#define IRQ_TIMER2_VIC COMBINER_IRQ(22, 2)
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
#define S5PV310_PA_GIC_DIST (0x10501000)
|
||||
#define S5PV310_PA_L2CC (0x10502000)
|
||||
|
||||
/* DMA */
|
||||
#define S5PV310_PA_MDMA 0x10810000
|
||||
#define S5PV310_PA_PDMA0 0x12680000
|
||||
#define S5PV310_PA_PDMA1 0x12690000
|
||||
|
||||
#define S5PV310_PA_GPIO1 (0x11400000)
|
||||
#define S5PV310_PA_GPIO2 (0x11000000)
|
||||
#define S5PV310_PA_GPIO3 (0x03860000)
|
||||
|
@ -60,6 +65,22 @@
|
|||
|
||||
#define S5PV310_PA_SROMC (0x12570000)
|
||||
|
||||
/* S/PDIF */
|
||||
#define S5PV310_PA_SPDIF 0xE1100000
|
||||
|
||||
/* I2S */
|
||||
#define S5PV310_PA_I2S0 0x03830000
|
||||
#define S5PV310_PA_I2S1 0xE3100000
|
||||
#define S5PV310_PA_I2S2 0xE2A00000
|
||||
|
||||
/* PCM */
|
||||
#define S5PV310_PA_PCM0 0x03840000
|
||||
#define S5PV310_PA_PCM1 0x13980000
|
||||
#define S5PV310_PA_PCM2 0x13990000
|
||||
|
||||
/* AC97 */
|
||||
#define S5PV310_PA_AC97 0x139A0000
|
||||
|
||||
#define S5PV310_PA_UART (0x13800000)
|
||||
|
||||
#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET))
|
||||
|
|
|
@ -729,6 +729,10 @@ static struct platform_device fsi_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct platform_device fsi_ak4643_device = {
|
||||
.name = "sh_fsi2_a_ak4643",
|
||||
};
|
||||
|
||||
static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
|
||||
.clock_source = LCDC_CLK_EXTERNAL,
|
||||
.ch[0] = {
|
||||
|
@ -927,6 +931,7 @@ static struct platform_device *ap4evb_devices[] __initdata = {
|
|||
&sdhi1_device,
|
||||
&usb1_host_device,
|
||||
&fsi_device,
|
||||
&fsi_ak4643_device,
|
||||
&sh_mmcif_device,
|
||||
&lcdc1_device,
|
||||
&lcdc_device,
|
||||
|
|
|
@ -259,21 +259,6 @@ struct platform_device s3c_device_iis = {
|
|||
|
||||
EXPORT_SYMBOL(s3c_device_iis);
|
||||
|
||||
/* ASoC PCM DMA */
|
||||
|
||||
static u64 s3c_device_audio_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device s3c_device_pcm = {
|
||||
.name = "s3c24xx-pcm-audio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(s3c_device_pcm);
|
||||
|
||||
/* RTC */
|
||||
|
||||
static struct resource s3c_rtc_resource[] = {
|
||||
|
@ -496,8 +481,10 @@ static struct resource s3c_ac97_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static u64 s3c_device_audio_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device s3c_device_ac97 = {
|
||||
.name = "s3c-ac97",
|
||||
.name = "samsung-ac97",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s3c_ac97_resource),
|
||||
.resource = s3c_ac97_resource,
|
||||
|
|
|
@ -17,6 +17,7 @@ obj-y += clock.o
|
|||
obj-y += pwm-clock.o
|
||||
obj-y += gpio.o
|
||||
obj-y += gpio-config.o
|
||||
obj-y += dev-asocdma.o
|
||||
|
||||
obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT) += gpiolib.o
|
||||
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* linux/arch/arm/plat-samsung/dev-asocdma.c
|
||||
*
|
||||
* Copyright (c) 2010 Samsung Electronics Co. Ltd
|
||||
* Jaswinder Singh <jassi.brar@samsung.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.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <plat/devs.h>
|
||||
|
||||
static u64 audio_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
struct platform_device samsung_asoc_dma = {
|
||||
.name = "samsung-audio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &audio_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL(samsung_asoc_dma);
|
|
@ -25,10 +25,34 @@ extern void s3c64xx_ac97_setup_gpio(int);
|
|||
#define S5PC100_SPDIF_GPG3 1
|
||||
extern void s5pc100_spdif_setup_gpio(int);
|
||||
|
||||
struct samsung_i2s {
|
||||
/* If the Primary DAI has 5.1 Channels */
|
||||
#define QUIRK_PRI_6CHAN (1 << 0)
|
||||
/* If the I2S block has a Stereo Overlay Channel */
|
||||
#define QUIRK_SEC_DAI (1 << 1)
|
||||
/*
|
||||
* If the I2S block has no internal prescalar or MUX (I2SMOD[10] bit)
|
||||
* The Machine driver must provide suitably set clock to the I2S block.
|
||||
*/
|
||||
#define QUIRK_NO_MUXPSR (1 << 2)
|
||||
#define QUIRK_NEED_RSTCLR (1 << 3)
|
||||
/* Quirks of the I2S controller */
|
||||
u32 quirks;
|
||||
|
||||
/*
|
||||
* Array of clock names that can be used to generate I2S signals.
|
||||
* Also corresponds to clocks of I2SMOD[10]
|
||||
*/
|
||||
const char **src_clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s3c_audio_pdata - common platform data for audio device drivers
|
||||
* @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
|
||||
*/
|
||||
struct s3c_audio_pdata {
|
||||
int (*cfg_gpio)(struct platform_device *);
|
||||
union {
|
||||
struct samsung_i2s i2s;
|
||||
} type;
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ extern struct platform_device s3c64xx_device_iisv4;
|
|||
extern struct platform_device s3c64xx_device_spi0;
|
||||
extern struct platform_device s3c64xx_device_spi1;
|
||||
|
||||
extern struct platform_device s3c_device_pcm;
|
||||
extern struct platform_device samsung_asoc_dma;
|
||||
|
||||
extern struct platform_device s3c64xx_device_pcm0;
|
||||
extern struct platform_device s3c64xx_device_pcm1;
|
||||
|
@ -96,6 +96,15 @@ extern struct platform_device s5pv210_device_iis1;
|
|||
extern struct platform_device s5pv210_device_iis2;
|
||||
extern struct platform_device s5pv210_device_spdif;
|
||||
|
||||
extern struct platform_device s5pv310_device_ac97;
|
||||
extern struct platform_device s5pv310_device_pcm0;
|
||||
extern struct platform_device s5pv310_device_pcm1;
|
||||
extern struct platform_device s5pv310_device_pcm2;
|
||||
extern struct platform_device s5pv310_device_i2s0;
|
||||
extern struct platform_device s5pv310_device_i2s1;
|
||||
extern struct platform_device s5pv310_device_i2s2;
|
||||
extern struct platform_device s5pv310_device_spdif;
|
||||
|
||||
extern struct platform_device s5p6442_device_pcm0;
|
||||
extern struct platform_device s5p6442_device_pcm1;
|
||||
extern struct platform_device s5p6442_device_iis0;
|
||||
|
|
|
@ -318,6 +318,10 @@ static struct platform_device fsi_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct platform_device fsi_ak4642_device = {
|
||||
.name = "sh_fsi_a_ak4642",
|
||||
};
|
||||
|
||||
/* KEYSC in SoC (Needs SW33-2 set to ON) */
|
||||
static struct sh_keysc_info keysc_info = {
|
||||
.mode = SH_KEYSC_MODE_1,
|
||||
|
@ -590,6 +594,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
|
|||
&sh7724_usb0_host_device,
|
||||
&sh7724_usb1_gadget_device,
|
||||
&fsi_device,
|
||||
&fsi_ak4642_device,
|
||||
&sdhi0_cn7_device,
|
||||
&sdhi1_cn8_device,
|
||||
&irda_device,
|
||||
|
|
|
@ -35,6 +35,29 @@ static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
|
|||
return container_of(chip, struct wm8994_gpio, gpio_chip);
|
||||
}
|
||||
|
||||
static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
|
||||
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
|
||||
|
||||
switch (wm8994->type) {
|
||||
case WM8958:
|
||||
switch (offset) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
|
||||
|
@ -136,6 +159,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||
static struct gpio_chip template_chip = {
|
||||
.label = "wm8994",
|
||||
.owner = THIS_MODULE,
|
||||
.request = wm8994_gpio_request,
|
||||
.direction_input = wm8994_gpio_direction_in,
|
||||
.get = wm8994_gpio_get,
|
||||
.direction_output = wm8994_gpio_direction_out,
|
||||
|
|
|
@ -218,6 +218,18 @@ static const char *wm8994_main_supplies[] = {
|
|||
"SPKVDD2",
|
||||
};
|
||||
|
||||
static const char *wm8958_main_supplies[] = {
|
||||
"DBVDD1",
|
||||
"DBVDD2",
|
||||
"DBVDD3",
|
||||
"DCVDD",
|
||||
"AVDD1",
|
||||
"AVDD2",
|
||||
"CPVDD",
|
||||
"SPKVDD1",
|
||||
"SPKVDD2",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8994_device_suspend(struct device *dev)
|
||||
{
|
||||
|
@ -239,7 +251,7 @@ static int wm8994_device_suspend(struct device *dev)
|
|||
if (ret < 0)
|
||||
dev_err(dev, "Failed to save LDO registers: %d\n", ret);
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
|
||||
ret = regulator_bulk_disable(wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to disable supplies: %d\n", ret);
|
||||
|
@ -254,7 +266,7 @@ static int wm8994_device_resume(struct device *dev)
|
|||
struct wm8994 *wm8994 = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
|
||||
ret = regulator_bulk_enable(wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to enable supplies: %d\n", ret);
|
||||
|
@ -305,9 +317,10 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
|
|||
/*
|
||||
* Instantiate the generic non-control parts of the device.
|
||||
*/
|
||||
static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
|
||||
static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
||||
{
|
||||
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
|
||||
const char *devname;
|
||||
int ret, i;
|
||||
|
||||
mutex_init(&wm8994->io_lock);
|
||||
|
@ -323,25 +336,48 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
|
|||
goto err;
|
||||
}
|
||||
|
||||
switch (wm8994->type) {
|
||||
case WM8994:
|
||||
wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
|
||||
break;
|
||||
case WM8958:
|
||||
wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
|
||||
ARRAY_SIZE(wm8994_main_supplies),
|
||||
wm8994->num_supplies,
|
||||
GFP_KERNEL);
|
||||
if (!wm8994->supplies) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
|
||||
wm8994->supplies[i].supply = wm8994_main_supplies[i];
|
||||
|
||||
ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies),
|
||||
switch (wm8994->type) {
|
||||
case WM8994:
|
||||
for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
|
||||
wm8994->supplies[i].supply = wm8994_main_supplies[i];
|
||||
break;
|
||||
case WM8958:
|
||||
for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++)
|
||||
wm8994->supplies[i].supply = wm8958_main_supplies[i];
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
|
||||
goto err_supplies;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
|
||||
ret = regulator_bulk_enable(wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
|
||||
|
@ -353,7 +389,22 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
|
|||
dev_err(wm8994->dev, "Failed to read ID register\n");
|
||||
goto err_enable;
|
||||
}
|
||||
if (ret != 0x8994) {
|
||||
switch (ret) {
|
||||
case 0x8994:
|
||||
devname = "WM8994";
|
||||
if (wm8994->type != WM8994)
|
||||
dev_warn(wm8994->dev, "Device registered as type %d\n",
|
||||
wm8994->type);
|
||||
wm8994->type = WM8994;
|
||||
break;
|
||||
case 0x8958:
|
||||
devname = "WM8958";
|
||||
if (wm8994->type != WM8958)
|
||||
dev_warn(wm8994->dev, "Device registered as type %d\n",
|
||||
wm8994->type);
|
||||
wm8994->type = WM8958;
|
||||
break;
|
||||
default:
|
||||
dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
|
||||
ret);
|
||||
ret = -EINVAL;
|
||||
|
@ -370,14 +421,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
|
|||
switch (ret) {
|
||||
case 0:
|
||||
case 1:
|
||||
dev_warn(wm8994->dev, "revision %c not fully supported\n",
|
||||
'A' + ret);
|
||||
if (wm8994->type == WM8994)
|
||||
dev_warn(wm8994->dev,
|
||||
"revision %c not fully supported\n",
|
||||
'A' + ret);
|
||||
break;
|
||||
default:
|
||||
dev_info(wm8994->dev, "revision %c\n", 'A' + ret);
|
||||
break;
|
||||
}
|
||||
|
||||
dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret);
|
||||
|
||||
if (pdata) {
|
||||
wm8994->irq_base = pdata->irq_base;
|
||||
|
@ -423,10 +476,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
|
|||
err_irq:
|
||||
wm8994_irq_exit(wm8994);
|
||||
err_enable:
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
|
||||
regulator_bulk_disable(wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
err_get:
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
|
||||
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
||||
err_supplies:
|
||||
kfree(wm8994->supplies);
|
||||
err:
|
||||
|
@ -439,9 +492,9 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
|
|||
{
|
||||
mfd_remove_devices(wm8994->dev);
|
||||
wm8994_irq_exit(wm8994);
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
|
||||
regulator_bulk_disable(wm8994->num_supplies,
|
||||
wm8994->supplies);
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
|
||||
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
||||
kfree(wm8994->supplies);
|
||||
kfree(wm8994);
|
||||
}
|
||||
|
@ -506,8 +559,9 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
|
|||
wm8994->read_dev = wm8994_i2c_read_device;
|
||||
wm8994->write_dev = wm8994_i2c_write_device;
|
||||
wm8994->irq = i2c->irq;
|
||||
wm8994->type = id->driver_data;
|
||||
|
||||
return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
|
||||
return wm8994_device_init(wm8994, i2c->irq);
|
||||
}
|
||||
|
||||
static int wm8994_i2c_remove(struct i2c_client *i2c)
|
||||
|
@ -535,7 +589,8 @@ static int wm8994_i2c_resume(struct i2c_client *i2c)
|
|||
#endif
|
||||
|
||||
static const struct i2c_device_id wm8994_i2c_id[] = {
|
||||
{ "wm8994", 0 },
|
||||
{ "wm8994", WM8994 },
|
||||
{ "wm8958", WM8958 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
|
||||
|
|
|
@ -131,10 +131,19 @@ static struct regulator_ops wm8994_ldo1_ops = {
|
|||
static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
if (selector > WM8994_LDO2_MAX_SELECTOR)
|
||||
return -EINVAL;
|
||||
|
||||
return (selector * 100000) + 900000;
|
||||
switch (ldo->wm8994->type) {
|
||||
case WM8994:
|
||||
return (selector * 100000) + 900000;
|
||||
case WM8958:
|
||||
return (selector * 100000) + 1000000;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev)
|
||||
|
@ -157,7 +166,17 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
|
|||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int selector, v;
|
||||
|
||||
selector = (min_uV - 900000) / 100000;
|
||||
switch (ldo->wm8994->type) {
|
||||
case WM8994:
|
||||
selector = (min_uV - 900000) / 100000;
|
||||
break;
|
||||
case WM8958:
|
||||
selector = (min_uV - 1000000) / 100000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v = wm8994_ldo2_list_voltage(rdev, selector);
|
||||
if (v < 0 || v > max_uV)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
enum wm8994_type {
|
||||
WM8994 = 0,
|
||||
WM8958 = 1,
|
||||
};
|
||||
|
||||
struct regulator_dev;
|
||||
struct regulator_bulk_data;
|
||||
|
||||
|
@ -48,6 +53,8 @@ struct wm8994 {
|
|||
struct mutex io_lock;
|
||||
struct mutex irq_lock;
|
||||
|
||||
enum wm8994_type type;
|
||||
|
||||
struct device *dev;
|
||||
int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
|
||||
int bytes, void *dest);
|
||||
|
@ -68,6 +75,7 @@ struct wm8994 {
|
|||
u16 gpio_regs[WM8994_NUM_GPIO_REGS];
|
||||
|
||||
struct regulator_dev *dbvdd;
|
||||
int num_supplies;
|
||||
struct regulator_bulk_data *supplies;
|
||||
};
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ struct wm8994_ldo_pdata {
|
|||
|
||||
#define WM8994_DRC_REGS 5
|
||||
#define WM8994_EQ_REGS 20
|
||||
#define WM8958_MBC_CUTOFF_REGS 20
|
||||
#define WM8958_MBC_COEFF_REGS 48
|
||||
|
||||
/**
|
||||
* DRC configurations are specified with a label and a set of register
|
||||
|
@ -59,6 +61,18 @@ struct wm8994_retune_mobile_cfg {
|
|||
u16 regs[WM8994_EQ_REGS];
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiband compressor configurations are specified with a label and
|
||||
* two sets of values to write. Configurations are expected to be
|
||||
* generated using the multiband compressor configuration panel in
|
||||
* WISCE - see http://www.wolfsonmicro.com/wisce/
|
||||
*/
|
||||
struct wm8958_mbc_cfg {
|
||||
const char *name;
|
||||
u16 cutoff_regs[WM8958_MBC_CUTOFF_REGS];
|
||||
u16 coeff_regs[WM8958_MBC_COEFF_REGS];
|
||||
};
|
||||
|
||||
struct wm8994_pdata {
|
||||
int gpio_base;
|
||||
|
||||
|
@ -78,6 +92,9 @@ struct wm8994_pdata {
|
|||
int num_retune_mobile_cfgs;
|
||||
struct wm8994_retune_mobile_cfg *retune_mobile_cfgs;
|
||||
|
||||
int num_mbc_cfgs;
|
||||
struct wm8958_mbc_cfg *mbc_cfgs;
|
||||
|
||||
/* LINEOUT can be differential or single ended */
|
||||
unsigned int lineout1_diff:1;
|
||||
unsigned int lineout2_diff:1;
|
||||
|
|
|
@ -64,12 +64,16 @@
|
|||
#define WM8994_LDO_1 0x3B
|
||||
#define WM8994_LDO_2 0x3C
|
||||
#define WM8994_CHARGE_PUMP_1 0x4C
|
||||
#define WM8958_CHARGE_PUMP_2 0x4D
|
||||
#define WM8994_CLASS_W_1 0x51
|
||||
#define WM8994_DC_SERVO_1 0x54
|
||||
#define WM8994_DC_SERVO_2 0x55
|
||||
#define WM8994_DC_SERVO_4 0x57
|
||||
#define WM8994_DC_SERVO_READBACK 0x58
|
||||
#define WM8994_ANALOGUE_HP_1 0x60
|
||||
#define WM8958_MIC_DETECT_1 0xD0
|
||||
#define WM8958_MIC_DETECT_2 0xD1
|
||||
#define WM8958_MIC_DETECT_3 0xD2
|
||||
#define WM8994_CHIP_REVISION 0x100
|
||||
#define WM8994_CONTROL_INTERFACE 0x101
|
||||
#define WM8994_WRITE_SEQUENCER_CTRL_1 0x110
|
||||
|
@ -109,6 +113,10 @@
|
|||
#define WM8994_AIF2DAC_LRCLK 0x315
|
||||
#define WM8994_AIF2DAC_DATA 0x316
|
||||
#define WM8994_AIF2ADC_DATA 0x317
|
||||
#define WM8958_AIF3_CONTROL_1 0x320
|
||||
#define WM8958_AIF3_CONTROL_2 0x321
|
||||
#define WM8958_AIF3DAC_DATA 0x322
|
||||
#define WM8958_AIF3ADC_DATA 0x323
|
||||
#define WM8994_AIF1_ADC1_LEFT_VOLUME 0x400
|
||||
#define WM8994_AIF1_ADC1_RIGHT_VOLUME 0x401
|
||||
#define WM8994_AIF1_DAC1_LEFT_VOLUME 0x402
|
||||
|
@ -242,6 +250,83 @@
|
|||
#define WM8994_INTERRUPT_STATUS_2_MASK 0x739
|
||||
#define WM8994_INTERRUPT_CONTROL 0x740
|
||||
#define WM8994_IRQ_DEBOUNCE 0x748
|
||||
#define WM8958_DSP2_PROGRAM 0x900
|
||||
#define WM8958_DSP2_CONFIG 0x901
|
||||
#define WM8958_DSP2_MAGICNUM 0xA00
|
||||
#define WM8958_DSP2_RELEASEYEAR 0xA01
|
||||
#define WM8958_DSP2_RELEASEMONTHDAY 0xA02
|
||||
#define WM8958_DSP2_RELEASETIME 0xA03
|
||||
#define WM8958_DSP2_VERMAJMIN 0xA04
|
||||
#define WM8958_DSP2_VERBUILD 0xA05
|
||||
#define WM8958_DSP2_EXECCONTROL 0xA0D
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1 0x2200
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_2 0x2201
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C2_1 0x2202
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C2_2 0x2203
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C3_1 0x2204
|
||||
#define WM8958_MBC_BAND_2_LOWER_CUTOFF_C3_2 0x2205
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C2_1 0x2206
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C2_2 0x2207
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C3_1 0x2208
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C3_2 0x2209
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C1_1 0x220A
|
||||
#define WM8958_MBC_BAND_2_UPPER_CUTOFF_C1_2 0x220B
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C1_1 0x220C
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C1_2 0x220D
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C2_1 0x220E
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C2_2 0x220F
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C3_1 0x2210
|
||||
#define WM8958_MBC_BAND_1_UPPER_CUTOFF_C3_2 0x2211
|
||||
#define WM8958_MBC_BAND_1_LOWER_CUTOFF_1 0x2212
|
||||
#define WM8958_MBC_BAND_1_LOWER_CUTOFF_2 0x2213
|
||||
#define WM8958_MBC_BAND_1_K_1 0x2400
|
||||
#define WM8958_MBC_BAND_1_K_2 0x2401
|
||||
#define WM8958_MBC_BAND_1_N1_1 0x2402
|
||||
#define WM8958_MBC_BAND_1_N1_2 0x2403
|
||||
#define WM8958_MBC_BAND_1_N2_1 0x2404
|
||||
#define WM8958_MBC_BAND_1_N2_2 0x2405
|
||||
#define WM8958_MBC_BAND_1_N3_1 0x2406
|
||||
#define WM8958_MBC_BAND_1_N3_2 0x2407
|
||||
#define WM8958_MBC_BAND_1_N4_1 0x2408
|
||||
#define WM8958_MBC_BAND_1_N4_2 0x2409
|
||||
#define WM8958_MBC_BAND_1_N5_1 0x240A
|
||||
#define WM8958_MBC_BAND_1_N5_2 0x240B
|
||||
#define WM8958_MBC_BAND_1_X1_1 0x240C
|
||||
#define WM8958_MBC_BAND_1_X1_2 0x240D
|
||||
#define WM8958_MBC_BAND_1_X2_1 0x240E
|
||||
#define WM8958_MBC_BAND_1_X2_2 0x240F
|
||||
#define WM8958_MBC_BAND_1_X3_1 0x2410
|
||||
#define WM8958_MBC_BAND_1_X3_2 0x2411
|
||||
#define WM8958_MBC_BAND_1_ATTACK_1 0x2412
|
||||
#define WM8958_MBC_BAND_1_ATTACK_2 0x2413
|
||||
#define WM8958_MBC_BAND_1_DECAY_1 0x2414
|
||||
#define WM8958_MBC_BAND_1_DECAY_2 0x2415
|
||||
#define WM8958_MBC_BAND_2_K_1 0x2416
|
||||
#define WM8958_MBC_BAND_2_K_2 0x2417
|
||||
#define WM8958_MBC_BAND_2_N1_1 0x2418
|
||||
#define WM8958_MBC_BAND_2_N1_2 0x2419
|
||||
#define WM8958_MBC_BAND_2_N2_1 0x241A
|
||||
#define WM8958_MBC_BAND_2_N2_2 0x241B
|
||||
#define WM8958_MBC_BAND_2_N3_1 0x241C
|
||||
#define WM8958_MBC_BAND_2_N3_2 0x241D
|
||||
#define WM8958_MBC_BAND_2_N4_1 0x241E
|
||||
#define WM8958_MBC_BAND_2_N4_2 0x241F
|
||||
#define WM8958_MBC_BAND_2_N5_1 0x2420
|
||||
#define WM8958_MBC_BAND_2_N5_2 0x2421
|
||||
#define WM8958_MBC_BAND_2_X1_1 0x2422
|
||||
#define WM8958_MBC_BAND_2_X1_2 0x2423
|
||||
#define WM8958_MBC_BAND_2_X2_1 0x2424
|
||||
#define WM8958_MBC_BAND_2_X2_2 0x2425
|
||||
#define WM8958_MBC_BAND_2_X3_1 0x2426
|
||||
#define WM8958_MBC_BAND_2_X3_2 0x2427
|
||||
#define WM8958_MBC_BAND_2_ATTACK_1 0x2428
|
||||
#define WM8958_MBC_BAND_2_ATTACK_2 0x2429
|
||||
#define WM8958_MBC_BAND_2_DECAY_1 0x242A
|
||||
#define WM8958_MBC_BAND_2_DECAY_2 0x242B
|
||||
#define WM8958_MBC_B2_PG2_1 0x242C
|
||||
#define WM8958_MBC_B2_PG2_2 0x242D
|
||||
#define WM8958_MBC_B1_PG2_1 0x242E
|
||||
#define WM8958_MBC_B1_PG2_2 0x242F
|
||||
#define WM8994_WRITE_SEQUENCER_0 0x3000
|
||||
#define WM8994_WRITE_SEQUENCER_1 0x3001
|
||||
#define WM8994_WRITE_SEQUENCER_2 0x3002
|
||||
|
@ -992,6 +1077,12 @@
|
|||
/*
|
||||
* R6 (0x06) - Power Management (6)
|
||||
*/
|
||||
#define WM8958_AIF3ADC_SRC_MASK 0x0600 /* AIF3ADC_SRC - [10:9] */
|
||||
#define WM8958_AIF3ADC_SRC_SHIFT 9 /* AIF3ADC_SRC - [10:9] */
|
||||
#define WM8958_AIF3ADC_SRC_WIDTH 2 /* AIF3ADC_SRC - [10:9] */
|
||||
#define WM8958_AIF2DAC_SRC_MASK 0x0180 /* AIF2DAC_SRC - [8:7] */
|
||||
#define WM8958_AIF2DAC_SRC_SHIFT 7 /* AIF2DAC_SRC - [8:7] */
|
||||
#define WM8958_AIF2DAC_SRC_WIDTH 2 /* AIF2DAC_SRC - [8:7] */
|
||||
#define WM8994_AIF3_TRI 0x0020 /* AIF3_TRI */
|
||||
#define WM8994_AIF3_TRI_MASK 0x0020 /* AIF3_TRI */
|
||||
#define WM8994_AIF3_TRI_SHIFT 5 /* AIF3_TRI */
|
||||
|
@ -1835,6 +1926,14 @@
|
|||
#define WM8994_CP_ENA_SHIFT 15 /* CP_ENA */
|
||||
#define WM8994_CP_ENA_WIDTH 1 /* CP_ENA */
|
||||
|
||||
/*
|
||||
* R77 (0x4D) - Charge Pump (2)
|
||||
*/
|
||||
#define WM8958_CP_DISCH 0x8000 /* CP_DISCH */
|
||||
#define WM8958_CP_DISCH_MASK 0x8000 /* CP_DISCH */
|
||||
#define WM8958_CP_DISCH_SHIFT 15 /* CP_DISCH */
|
||||
#define WM8958_CP_DISCH_WIDTH 1 /* CP_DISCH */
|
||||
|
||||
/*
|
||||
* R81 (0x51) - Class W (1)
|
||||
*/
|
||||
|
@ -1951,6 +2050,46 @@
|
|||
#define WM8994_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */
|
||||
#define WM8994_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */
|
||||
|
||||
/*
|
||||
* R208 (0xD0) - Mic Detect 1
|
||||
*/
|
||||
#define WM8958_MICD_BIAS_STARTTIME_MASK 0xF000 /* MICD_BIAS_STARTTIME - [15:12] */
|
||||
#define WM8958_MICD_BIAS_STARTTIME_SHIFT 12 /* MICD_BIAS_STARTTIME - [15:12] */
|
||||
#define WM8958_MICD_BIAS_STARTTIME_WIDTH 4 /* MICD_BIAS_STARTTIME - [15:12] */
|
||||
#define WM8958_MICD_RATE_MASK 0x0F00 /* MICD_RATE - [11:8] */
|
||||
#define WM8958_MICD_RATE_SHIFT 8 /* MICD_RATE - [11:8] */
|
||||
#define WM8958_MICD_RATE_WIDTH 4 /* MICD_RATE - [11:8] */
|
||||
#define WM8958_MICD_DBTIME 0x0002 /* MICD_DBTIME */
|
||||
#define WM8958_MICD_DBTIME_MASK 0x0002 /* MICD_DBTIME */
|
||||
#define WM8958_MICD_DBTIME_SHIFT 1 /* MICD_DBTIME */
|
||||
#define WM8958_MICD_DBTIME_WIDTH 1 /* MICD_DBTIME */
|
||||
#define WM8958_MICD_ENA 0x0001 /* MICD_ENA */
|
||||
#define WM8958_MICD_ENA_MASK 0x0001 /* MICD_ENA */
|
||||
#define WM8958_MICD_ENA_SHIFT 0 /* MICD_ENA */
|
||||
#define WM8958_MICD_ENA_WIDTH 1 /* MICD_ENA */
|
||||
|
||||
/*
|
||||
* R209 (0xD1) - Mic Detect 2
|
||||
*/
|
||||
#define WM8958_MICD_LVL_SEL_MASK 0x00FF /* MICD_LVL_SEL - [7:0] */
|
||||
#define WM8958_MICD_LVL_SEL_SHIFT 0 /* MICD_LVL_SEL - [7:0] */
|
||||
#define WM8958_MICD_LVL_SEL_WIDTH 8 /* MICD_LVL_SEL - [7:0] */
|
||||
|
||||
/*
|
||||
* R210 (0xD2) - Mic Detect 3
|
||||
*/
|
||||
#define WM8958_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */
|
||||
#define WM8958_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */
|
||||
#define WM8958_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */
|
||||
#define WM8958_MICD_VALID 0x0002 /* MICD_VALID */
|
||||
#define WM8958_MICD_VALID_MASK 0x0002 /* MICD_VALID */
|
||||
#define WM8958_MICD_VALID_SHIFT 1 /* MICD_VALID */
|
||||
#define WM8958_MICD_VALID_WIDTH 1 /* MICD_VALID */
|
||||
#define WM8958_MICD_STS 0x0001 /* MICD_STS */
|
||||
#define WM8958_MICD_STS_MASK 0x0001 /* MICD_STS */
|
||||
#define WM8958_MICD_STS_SHIFT 0 /* MICD_STS */
|
||||
#define WM8958_MICD_STS_WIDTH 1 /* MICD_STS */
|
||||
|
||||
/*
|
||||
* R256 (0x100) - Chip Revision
|
||||
*/
|
||||
|
@ -2069,6 +2208,14 @@
|
|||
/*
|
||||
* R520 (0x208) - Clocking (1)
|
||||
*/
|
||||
#define WM8958_DSP2CLK_ENA 0x4000 /* DSP2CLK_ENA */
|
||||
#define WM8958_DSP2CLK_ENA_MASK 0x4000 /* DSP2CLK_ENA */
|
||||
#define WM8958_DSP2CLK_ENA_SHIFT 14 /* DSP2CLK_ENA */
|
||||
#define WM8958_DSP2CLK_ENA_WIDTH 1 /* DSP2CLK_ENA */
|
||||
#define WM8958_DSP2CLK_SRC 0x1000 /* DSP2CLK_SRC */
|
||||
#define WM8958_DSP2CLK_SRC_MASK 0x1000 /* DSP2CLK_SRC */
|
||||
#define WM8958_DSP2CLK_SRC_SHIFT 12 /* DSP2CLK_SRC */
|
||||
#define WM8958_DSP2CLK_SRC_WIDTH 1 /* DSP2CLK_SRC */
|
||||
#define WM8994_TOCLK_ENA 0x0010 /* TOCLK_ENA */
|
||||
#define WM8994_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */
|
||||
#define WM8994_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */
|
||||
|
@ -2552,6 +2699,63 @@
|
|||
#define WM8994_AIF2ADCR_DAT_INV_SHIFT 0 /* AIF2ADCR_DAT_INV */
|
||||
#define WM8994_AIF2ADCR_DAT_INV_WIDTH 1 /* AIF2ADCR_DAT_INV */
|
||||
|
||||
/*
|
||||
* R800 (0x320) - AIF3 Control (1)
|
||||
*/
|
||||
#define WM8958_AIF3_LRCLK_INV 0x0080 /* AIF3_LRCLK_INV */
|
||||
#define WM8958_AIF3_LRCLK_INV_MASK 0x0080 /* AIF3_LRCLK_INV */
|
||||
#define WM8958_AIF3_LRCLK_INV_SHIFT 7 /* AIF3_LRCLK_INV */
|
||||
#define WM8958_AIF3_LRCLK_INV_WIDTH 1 /* AIF3_LRCLK_INV */
|
||||
#define WM8958_AIF3_WL_MASK 0x0060 /* AIF3_WL - [6:5] */
|
||||
#define WM8958_AIF3_WL_SHIFT 5 /* AIF3_WL - [6:5] */
|
||||
#define WM8958_AIF3_WL_WIDTH 2 /* AIF3_WL - [6:5] */
|
||||
#define WM8958_AIF3_FMT_MASK 0x0018 /* AIF3_FMT - [4:3] */
|
||||
#define WM8958_AIF3_FMT_SHIFT 3 /* AIF3_FMT - [4:3] */
|
||||
#define WM8958_AIF3_FMT_WIDTH 2 /* AIF3_FMT - [4:3] */
|
||||
|
||||
/*
|
||||
* R801 (0x321) - AIF3 Control (2)
|
||||
*/
|
||||
#define WM8958_AIF3DAC_BOOST_MASK 0x0C00 /* AIF3DAC_BOOST - [11:10] */
|
||||
#define WM8958_AIF3DAC_BOOST_SHIFT 10 /* AIF3DAC_BOOST - [11:10] */
|
||||
#define WM8958_AIF3DAC_BOOST_WIDTH 2 /* AIF3DAC_BOOST - [11:10] */
|
||||
#define WM8958_AIF3DAC_COMP 0x0010 /* AIF3DAC_COMP */
|
||||
#define WM8958_AIF3DAC_COMP_MASK 0x0010 /* AIF3DAC_COMP */
|
||||
#define WM8958_AIF3DAC_COMP_SHIFT 4 /* AIF3DAC_COMP */
|
||||
#define WM8958_AIF3DAC_COMP_WIDTH 1 /* AIF3DAC_COMP */
|
||||
#define WM8958_AIF3DAC_COMPMODE 0x0008 /* AIF3DAC_COMPMODE */
|
||||
#define WM8958_AIF3DAC_COMPMODE_MASK 0x0008 /* AIF3DAC_COMPMODE */
|
||||
#define WM8958_AIF3DAC_COMPMODE_SHIFT 3 /* AIF3DAC_COMPMODE */
|
||||
#define WM8958_AIF3DAC_COMPMODE_WIDTH 1 /* AIF3DAC_COMPMODE */
|
||||
#define WM8958_AIF3ADC_COMP 0x0004 /* AIF3ADC_COMP */
|
||||
#define WM8958_AIF3ADC_COMP_MASK 0x0004 /* AIF3ADC_COMP */
|
||||
#define WM8958_AIF3ADC_COMP_SHIFT 2 /* AIF3ADC_COMP */
|
||||
#define WM8958_AIF3ADC_COMP_WIDTH 1 /* AIF3ADC_COMP */
|
||||
#define WM8958_AIF3ADC_COMPMODE 0x0002 /* AIF3ADC_COMPMODE */
|
||||
#define WM8958_AIF3ADC_COMPMODE_MASK 0x0002 /* AIF3ADC_COMPMODE */
|
||||
#define WM8958_AIF3ADC_COMPMODE_SHIFT 1 /* AIF3ADC_COMPMODE */
|
||||
#define WM8958_AIF3ADC_COMPMODE_WIDTH 1 /* AIF3ADC_COMPMODE */
|
||||
#define WM8958_AIF3_LOOPBACK 0x0001 /* AIF3_LOOPBACK */
|
||||
#define WM8958_AIF3_LOOPBACK_MASK 0x0001 /* AIF3_LOOPBACK */
|
||||
#define WM8958_AIF3_LOOPBACK_SHIFT 0 /* AIF3_LOOPBACK */
|
||||
#define WM8958_AIF3_LOOPBACK_WIDTH 1 /* AIF3_LOOPBACK */
|
||||
|
||||
/*
|
||||
* R802 (0x322) - AIF3DAC Data
|
||||
*/
|
||||
#define WM8958_AIF3DAC_DAT_INV 0x0001 /* AIF3DAC_DAT_INV */
|
||||
#define WM8958_AIF3DAC_DAT_INV_MASK 0x0001 /* AIF3DAC_DAT_INV */
|
||||
#define WM8958_AIF3DAC_DAT_INV_SHIFT 0 /* AIF3DAC_DAT_INV */
|
||||
#define WM8958_AIF3DAC_DAT_INV_WIDTH 1 /* AIF3DAC_DAT_INV */
|
||||
|
||||
/*
|
||||
* R803 (0x323) - AIF3ADC Data
|
||||
*/
|
||||
#define WM8958_AIF3ADC_DAT_INV 0x0001 /* AIF3ADC_DAT_INV */
|
||||
#define WM8958_AIF3ADC_DAT_INV_MASK 0x0001 /* AIF3ADC_DAT_INV */
|
||||
#define WM8958_AIF3ADC_DAT_INV_SHIFT 0 /* AIF3ADC_DAT_INV */
|
||||
#define WM8958_AIF3ADC_DAT_INV_WIDTH 1 /* AIF3ADC_DAT_INV */
|
||||
|
||||
/*
|
||||
* R1024 (0x400) - AIF1 ADC1 Left Volume
|
||||
*/
|
||||
|
@ -4289,4 +4493,102 @@
|
|||
#define WM8994_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */
|
||||
#define WM8994_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */
|
||||
|
||||
/*
|
||||
* R2304 (0x900) - DSP2_Program
|
||||
*/
|
||||
#define WM8958_DSP2_ENA 0x0001 /* DSP2_ENA */
|
||||
#define WM8958_DSP2_ENA_MASK 0x0001 /* DSP2_ENA */
|
||||
#define WM8958_DSP2_ENA_SHIFT 0 /* DSP2_ENA */
|
||||
#define WM8958_DSP2_ENA_WIDTH 1 /* DSP2_ENA */
|
||||
|
||||
/*
|
||||
* R2305 (0x901) - DSP2_Config
|
||||
*/
|
||||
#define WM8958_MBC_SEL_MASK 0x0030 /* MBC_SEL - [5:4] */
|
||||
#define WM8958_MBC_SEL_SHIFT 4 /* MBC_SEL - [5:4] */
|
||||
#define WM8958_MBC_SEL_WIDTH 2 /* MBC_SEL - [5:4] */
|
||||
#define WM8958_MBC_ENA 0x0001 /* MBC_ENA */
|
||||
#define WM8958_MBC_ENA_MASK 0x0001 /* MBC_ENA */
|
||||
#define WM8958_MBC_ENA_SHIFT 0 /* MBC_ENA */
|
||||
#define WM8958_MBC_ENA_WIDTH 1 /* MBC_ENA */
|
||||
|
||||
/*
|
||||
* R2560 (0xA00) - DSP2_MagicNum
|
||||
*/
|
||||
#define WM8958_DSP2_MAGIC_NUM_MASK 0xFFFF /* DSP2_MAGIC_NUM - [15:0] */
|
||||
#define WM8958_DSP2_MAGIC_NUM_SHIFT 0 /* DSP2_MAGIC_NUM - [15:0] */
|
||||
#define WM8958_DSP2_MAGIC_NUM_WIDTH 16 /* DSP2_MAGIC_NUM - [15:0] */
|
||||
|
||||
/*
|
||||
* R2561 (0xA01) - DSP2_ReleaseYear
|
||||
*/
|
||||
#define WM8958_DSP2_RELEASE_YEAR_MASK 0xFFFF /* DSP2_RELEASE_YEAR - [15:0] */
|
||||
#define WM8958_DSP2_RELEASE_YEAR_SHIFT 0 /* DSP2_RELEASE_YEAR - [15:0] */
|
||||
#define WM8958_DSP2_RELEASE_YEAR_WIDTH 16 /* DSP2_RELEASE_YEAR - [15:0] */
|
||||
|
||||
/*
|
||||
* R2562 (0xA02) - DSP2_ReleaseMonthDay
|
||||
*/
|
||||
#define WM8958_DSP2_RELEASE_MONTH_MASK 0xFF00 /* DSP2_RELEASE_MONTH - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_MONTH_SHIFT 8 /* DSP2_RELEASE_MONTH - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_MONTH_WIDTH 8 /* DSP2_RELEASE_MONTH - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_DAY_MASK 0x00FF /* DSP2_RELEASE_DAY - [7:0] */
|
||||
#define WM8958_DSP2_RELEASE_DAY_SHIFT 0 /* DSP2_RELEASE_DAY - [7:0] */
|
||||
#define WM8958_DSP2_RELEASE_DAY_WIDTH 8 /* DSP2_RELEASE_DAY - [7:0] */
|
||||
|
||||
/*
|
||||
* R2563 (0xA03) - DSP2_ReleaseTime
|
||||
*/
|
||||
#define WM8958_DSP2_RELEASE_HOURS_MASK 0xFF00 /* DSP2_RELEASE_HOURS - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_HOURS_SHIFT 8 /* DSP2_RELEASE_HOURS - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_HOURS_WIDTH 8 /* DSP2_RELEASE_HOURS - [15:8] */
|
||||
#define WM8958_DSP2_RELEASE_MINS_MASK 0x00FF /* DSP2_RELEASE_MINS - [7:0] */
|
||||
#define WM8958_DSP2_RELEASE_MINS_SHIFT 0 /* DSP2_RELEASE_MINS - [7:0] */
|
||||
#define WM8958_DSP2_RELEASE_MINS_WIDTH 8 /* DSP2_RELEASE_MINS - [7:0] */
|
||||
|
||||
/*
|
||||
* R2564 (0xA04) - DSP2_VerMajMin
|
||||
*/
|
||||
#define WM8958_DSP2_MAJOR_VER_MASK 0xFF00 /* DSP2_MAJOR_VER - [15:8] */
|
||||
#define WM8958_DSP2_MAJOR_VER_SHIFT 8 /* DSP2_MAJOR_VER - [15:8] */
|
||||
#define WM8958_DSP2_MAJOR_VER_WIDTH 8 /* DSP2_MAJOR_VER - [15:8] */
|
||||
#define WM8958_DSP2_MINOR_VER_MASK 0x00FF /* DSP2_MINOR_VER - [7:0] */
|
||||
#define WM8958_DSP2_MINOR_VER_SHIFT 0 /* DSP2_MINOR_VER - [7:0] */
|
||||
#define WM8958_DSP2_MINOR_VER_WIDTH 8 /* DSP2_MINOR_VER - [7:0] */
|
||||
|
||||
/*
|
||||
* R2565 (0xA05) - DSP2_VerBuild
|
||||
*/
|
||||
#define WM8958_DSP2_BUILD_VER_MASK 0xFFFF /* DSP2_BUILD_VER - [15:0] */
|
||||
#define WM8958_DSP2_BUILD_VER_SHIFT 0 /* DSP2_BUILD_VER - [15:0] */
|
||||
#define WM8958_DSP2_BUILD_VER_WIDTH 16 /* DSP2_BUILD_VER - [15:0] */
|
||||
|
||||
/*
|
||||
* R2573 (0xA0D) - DSP2_ExecControl
|
||||
*/
|
||||
#define WM8958_DSP2_STOPC 0x0020 /* DSP2_STOPC */
|
||||
#define WM8958_DSP2_STOPC_MASK 0x0020 /* DSP2_STOPC */
|
||||
#define WM8958_DSP2_STOPC_SHIFT 5 /* DSP2_STOPC */
|
||||
#define WM8958_DSP2_STOPC_WIDTH 1 /* DSP2_STOPC */
|
||||
#define WM8958_DSP2_STOPS 0x0010 /* DSP2_STOPS */
|
||||
#define WM8958_DSP2_STOPS_MASK 0x0010 /* DSP2_STOPS */
|
||||
#define WM8958_DSP2_STOPS_SHIFT 4 /* DSP2_STOPS */
|
||||
#define WM8958_DSP2_STOPS_WIDTH 1 /* DSP2_STOPS */
|
||||
#define WM8958_DSP2_STOPI 0x0008 /* DSP2_STOPI */
|
||||
#define WM8958_DSP2_STOPI_MASK 0x0008 /* DSP2_STOPI */
|
||||
#define WM8958_DSP2_STOPI_SHIFT 3 /* DSP2_STOPI */
|
||||
#define WM8958_DSP2_STOPI_WIDTH 1 /* DSP2_STOPI */
|
||||
#define WM8958_DSP2_STOP 0x0004 /* DSP2_STOP */
|
||||
#define WM8958_DSP2_STOP_MASK 0x0004 /* DSP2_STOP */
|
||||
#define WM8958_DSP2_STOP_SHIFT 2 /* DSP2_STOP */
|
||||
#define WM8958_DSP2_STOP_WIDTH 1 /* DSP2_STOP */
|
||||
#define WM8958_DSP2_RUNR 0x0002 /* DSP2_RUNR */
|
||||
#define WM8958_DSP2_RUNR_MASK 0x0002 /* DSP2_RUNR */
|
||||
#define WM8958_DSP2_RUNR_SHIFT 1 /* DSP2_RUNR */
|
||||
#define WM8958_DSP2_RUNR_WIDTH 1 /* DSP2_RUNR */
|
||||
#define WM8958_DSP2_RUN 0x0001 /* DSP2_RUN */
|
||||
#define WM8958_DSP2_RUN_MASK 0x0001 /* DSP2_RUN */
|
||||
#define WM8958_DSP2_RUN_SHIFT 0 /* DSP2_RUN */
|
||||
#define WM8958_DSP2_RUN_WIDTH 1 /* DSP2_RUN */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _INCLUDE_SOUND_ALC5623_H
|
||||
#define _INCLUDE_SOUND_ALC5623_H
|
||||
struct alc5623_platform_data {
|
||||
/* configure : */
|
||||
/* Lineout/Speaker Amps Vmid ratio control */
|
||||
/* enable/disable adc/dac high pass filters */
|
||||
unsigned int add_ctrl;
|
||||
/* configure : */
|
||||
/* output to enable when jack is low */
|
||||
/* output to enable when jack is high */
|
||||
/* jack detect (gpio/nc/jack detect [12] */
|
||||
unsigned int jack_det_ctrl;
|
||||
};
|
||||
#endif
|
||||
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
struct snd_pcm_substream;
|
||||
|
||||
/*
|
||||
|
@ -205,7 +203,7 @@ struct snd_soc_dai_driver {
|
|||
int (*resume)(struct snd_soc_dai *dai);
|
||||
|
||||
/* ops */
|
||||
struct snd_soc_dai_ops *ops;
|
||||
const struct snd_soc_dai_ops *ops;
|
||||
|
||||
/* DAI capabilities */
|
||||
struct snd_soc_pcm_stream capture;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
/* widget has no PM register bit */
|
||||
#define SND_SOC_NOPM -1
|
||||
|
@ -72,6 +71,10 @@
|
|||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
|
||||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols)\
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
|
@ -90,6 +93,9 @@
|
|||
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
|
||||
|
@ -116,6 +122,11 @@
|
|||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
|
@ -140,6 +151,11 @@
|
|||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||
|
@ -219,13 +235,6 @@
|
|||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, \
|
||||
power) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
|
||||
((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
|
@ -233,15 +242,6 @@
|
|||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, \
|
||||
power, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
|
||||
((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
|
@ -297,6 +297,7 @@ enum snd_soc_dapm_type;
|
|||
struct snd_soc_dapm_path;
|
||||
struct snd_soc_dapm_pin;
|
||||
struct snd_soc_dapm_route;
|
||||
struct snd_soc_dapm_context;
|
||||
|
||||
int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
|
@ -324,16 +325,16 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *uncontrol);
|
||||
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *uncontrol);
|
||||
int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
|
||||
int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
||||
const struct snd_soc_dapm_widget *widget);
|
||||
int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
|
||||
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
|
||||
const struct snd_soc_dapm_widget *widget,
|
||||
int num);
|
||||
|
||||
/* dapm path setup */
|
||||
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_free(struct snd_soc_codec *codec);
|
||||
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
|
||||
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
|
||||
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
|
||||
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
|
||||
const struct snd_soc_dapm_route *route, int num);
|
||||
|
||||
/* dapm events */
|
||||
|
@ -343,27 +344,33 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card);
|
|||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm);
|
||||
|
||||
/* dapm audio pin control and status */
|
||||
int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
|
||||
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_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_force_enable_pin(struct snd_soc_codec *codec,
|
||||
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
|
||||
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
|
||||
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_codec *codec, const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
snd_soc_dapm_input = 0, /* input pin */
|
||||
snd_soc_dapm_output, /* output pin */
|
||||
snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */
|
||||
snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */
|
||||
snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */
|
||||
snd_soc_dapm_mixer, /* mixes several analog signals together */
|
||||
snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */
|
||||
snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */
|
||||
snd_soc_dapm_out_drv, /* output driver */
|
||||
snd_soc_dapm_adc, /* analog to digital converter */
|
||||
snd_soc_dapm_dac, /* digital to analog converter */
|
||||
snd_soc_dapm_micbias, /* microphone bias (power) */
|
||||
|
@ -425,6 +432,7 @@ struct snd_soc_dapm_widget {
|
|||
char *sname; /* stream name */
|
||||
struct snd_soc_codec *codec;
|
||||
struct list_head list;
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
/* dapm control */
|
||||
short reg; /* negative reg = no direct dapm */
|
||||
|
@ -461,4 +469,35 @@ struct snd_soc_dapm_widget {
|
|||
struct list_head power_list;
|
||||
};
|
||||
|
||||
struct snd_soc_dapm_update {
|
||||
struct snd_soc_dapm_widget *widget;
|
||||
struct snd_kcontrol *kcontrol;
|
||||
int reg;
|
||||
int mask;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* DAPM context */
|
||||
struct snd_soc_dapm_context {
|
||||
int n_widgets; /* number of widgets in this context */
|
||||
enum snd_soc_bias_level bias_level;
|
||||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||
|
||||
struct snd_soc_dapm_update *update;
|
||||
|
||||
struct device *dev; /* from parent - for debug */
|
||||
struct snd_soc_codec *codec; /* parent codec */
|
||||
struct snd_soc_card *card; /* parent card */
|
||||
|
||||
/* used during DAPM updates */
|
||||
int dev_power;
|
||||
struct list_head list;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dapm;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -222,10 +222,8 @@ enum snd_soc_bias_level {
|
|||
|
||||
struct snd_jack;
|
||||
struct snd_soc_card;
|
||||
struct snd_soc_device;
|
||||
struct snd_soc_pcm_stream;
|
||||
struct snd_soc_ops;
|
||||
struct snd_soc_dai_mode;
|
||||
struct snd_soc_pcm_runtime;
|
||||
struct snd_soc_dai;
|
||||
struct snd_soc_dai_driver;
|
||||
|
@ -235,9 +233,10 @@ struct snd_soc_platform_driver;
|
|||
struct snd_soc_codec;
|
||||
struct snd_soc_codec_driver;
|
||||
struct soc_enum;
|
||||
struct snd_soc_ac97_ops;
|
||||
struct snd_soc_jack;
|
||||
struct snd_soc_jack_pin;
|
||||
struct snd_soc_cache_ops;
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct snd_soc_jack_gpio;
|
||||
|
@ -253,17 +252,30 @@ enum snd_soc_control_type {
|
|||
SND_SOC_SPI,
|
||||
};
|
||||
|
||||
enum snd_soc_compress_type {
|
||||
SND_SOC_FLAT_COMPRESSION = 1,
|
||||
SND_SOC_LZO_COMPRESSION,
|
||||
SND_SOC_RBTREE_COMPRESSION
|
||||
};
|
||||
|
||||
int snd_soc_register_platform(struct device *dev,
|
||||
struct snd_soc_platform_driver *platform_drv);
|
||||
void snd_soc_unregister_platform(struct device *dev);
|
||||
int snd_soc_register_codec(struct device *dev,
|
||||
struct snd_soc_codec_driver *codec_drv,
|
||||
const struct snd_soc_codec_driver *codec_drv,
|
||||
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
||||
void snd_soc_unregister_codec(struct device *dev);
|
||||
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
|
||||
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
|
||||
int addr_bits, int data_bits,
|
||||
enum snd_soc_control_type control);
|
||||
int snd_soc_cache_sync(struct snd_soc_codec *codec);
|
||||
int snd_soc_cache_init(struct snd_soc_codec *codec);
|
||||
int snd_soc_cache_exit(struct snd_soc_codec *codec);
|
||||
int snd_soc_cache_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int value);
|
||||
int snd_soc_cache_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int *value);
|
||||
|
||||
/* Utility functions to get clock rates from various things */
|
||||
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
|
||||
|
@ -420,23 +432,37 @@ struct snd_soc_ops {
|
|||
int (*trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
/* SoC cache ops */
|
||||
struct snd_soc_cache_ops {
|
||||
const char *name;
|
||||
enum snd_soc_compress_type id;
|
||||
int (*init)(struct snd_soc_codec *codec);
|
||||
int (*exit)(struct snd_soc_codec *codec);
|
||||
int (*read)(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int *value);
|
||||
int (*write)(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value);
|
||||
int (*sync)(struct snd_soc_codec *codec);
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
const char *name;
|
||||
const char *name_prefix;
|
||||
int id;
|
||||
struct device *dev;
|
||||
struct snd_soc_codec_driver *driver;
|
||||
const struct snd_soc_codec_driver *driver;
|
||||
|
||||
struct mutex mutex;
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
int num_dai;
|
||||
enum snd_soc_compress_type compress_type;
|
||||
|
||||
/* runtime */
|
||||
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
|
||||
unsigned int active;
|
||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||
unsigned int cache_only:1; /* Suppress writes to hardware */
|
||||
unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
|
||||
unsigned int suspended:1; /* Codec is in suspend PM state */
|
||||
|
@ -444,25 +470,25 @@ struct snd_soc_codec {
|
|||
unsigned int ac97_registered:1; /* Codec has been AC97 registered */
|
||||
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
||||
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
|
||||
unsigned int cache_init:1; /* codec cache has been initialized */
|
||||
|
||||
/* codec IO */
|
||||
void *control_data; /* codec control (i2c/3wire) data */
|
||||
hw_write_t hw_write;
|
||||
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
|
||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||
void *reg_cache;
|
||||
const void *reg_def_copy;
|
||||
const struct snd_soc_cache_ops *cache_ops;
|
||||
struct mutex cache_rw_mutex;
|
||||
|
||||
/* dapm */
|
||||
u32 pop_time;
|
||||
struct list_head dapm_widgets;
|
||||
struct list_head dapm_paths;
|
||||
enum snd_soc_bias_level bias_level;
|
||||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
struct dentry *debugfs_reg;
|
||||
struct dentry *debugfs_pop_time;
|
||||
struct dentry *debugfs_dapm;
|
||||
#endif
|
||||
};
|
||||
|
@ -488,6 +514,7 @@ struct snd_soc_codec_driver {
|
|||
short reg_cache_step;
|
||||
short reg_word_size;
|
||||
const void *reg_cache_default;
|
||||
enum snd_soc_compress_type compress_type;
|
||||
|
||||
/* codec bias level */
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
|
@ -554,6 +581,30 @@ struct snd_soc_dai_link {
|
|||
struct snd_soc_ops *ops;
|
||||
};
|
||||
|
||||
struct snd_soc_codec_conf {
|
||||
const char *dev_name;
|
||||
|
||||
/*
|
||||
* optional map of kcontrol, widget and path name prefixes that are
|
||||
* associated per device
|
||||
*/
|
||||
const char *name_prefix;
|
||||
|
||||
/*
|
||||
* set this to the desired compression type if you want to
|
||||
* override the one supplied in codec->driver->compress_type
|
||||
*/
|
||||
enum snd_soc_compress_type compress_type;
|
||||
};
|
||||
|
||||
struct snd_soc_aux_dev {
|
||||
const char *name; /* Codec name */
|
||||
const char *codec_name; /* for multi-codec */
|
||||
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
int (*init)(struct snd_soc_dapm_context *dapm);
|
||||
};
|
||||
|
||||
/* SoC card */
|
||||
struct snd_soc_card {
|
||||
const char *name;
|
||||
|
@ -579,6 +630,8 @@ struct snd_soc_card {
|
|||
/* callbacks */
|
||||
int (*set_bias_level)(struct snd_soc_card *,
|
||||
enum snd_soc_bias_level level);
|
||||
int (*set_bias_level_post)(struct snd_soc_card *,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
long pmdown_time;
|
||||
|
||||
|
@ -588,12 +641,35 @@ struct snd_soc_card {
|
|||
struct snd_soc_pcm_runtime *rtd;
|
||||
int num_rtd;
|
||||
|
||||
/* optional codec specific configuration */
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
int num_configs;
|
||||
|
||||
/*
|
||||
* optional auxiliary devices such as amplifiers or codecs with DAI
|
||||
* link unused
|
||||
*/
|
||||
struct snd_soc_aux_dev *aux_dev;
|
||||
int num_aux_devs;
|
||||
struct snd_soc_pcm_runtime *rtd_aux;
|
||||
int num_aux_rtd;
|
||||
|
||||
struct work_struct deferred_resume_work;
|
||||
|
||||
/* lists of probed devices belonging to this card */
|
||||
struct list_head codec_dev_list;
|
||||
struct list_head platform_dev_list;
|
||||
struct list_head dai_dev_list;
|
||||
|
||||
struct list_head widgets;
|
||||
struct list_head paths;
|
||||
struct list_head dapm_list;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_card_root;
|
||||
struct dentry *debugfs_pop_time;
|
||||
#endif
|
||||
u32 pop_time;
|
||||
};
|
||||
|
||||
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
|
||||
|
@ -639,17 +715,9 @@ struct soc_enum {
|
|||
};
|
||||
|
||||
/* codec IO */
|
||||
static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
return codec->driver->read(codec, reg);
|
||||
}
|
||||
|
||||
static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int val)
|
||||
{
|
||||
return codec->driver->write(codec, reg, val);
|
||||
}
|
||||
unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
|
||||
unsigned int snd_soc_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int val);
|
||||
|
||||
/* device driver data */
|
||||
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM asoc
|
||||
|
||||
#if !defined(_TRACE_ASOC_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_ASOC_H
|
||||
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
struct snd_soc_jack;
|
||||
struct snd_soc_codec;
|
||||
struct snd_soc_card;
|
||||
struct snd_soc_dapm_widget;
|
||||
|
||||
/*
|
||||
* Log register events
|
||||
*/
|
||||
DECLARE_EVENT_CLASS(snd_soc_reg,
|
||||
|
||||
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val),
|
||||
|
||||
TP_ARGS(codec, reg, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, codec->name )
|
||||
__field( int, id )
|
||||
__field( unsigned int, reg )
|
||||
__field( unsigned int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, codec->name);
|
||||
__entry->id = codec->id;
|
||||
__entry->reg = reg;
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("codec=%s.%d reg=%x val=%x", __get_str(name),
|
||||
(int)__entry->id, (unsigned int)__entry->reg,
|
||||
(unsigned int)__entry->val)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_reg, snd_soc_reg_write,
|
||||
|
||||
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val),
|
||||
|
||||
TP_ARGS(codec, reg, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_reg, snd_soc_reg_read,
|
||||
|
||||
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val),
|
||||
|
||||
TP_ARGS(codec, reg, val)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(snd_soc_card,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card, int val),
|
||||
|
||||
TP_ARGS(card, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, card->name )
|
||||
__field( int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, card->name);
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("card=%s val=%d", __get_str(name), (int)__entry->val)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_card, snd_soc_bias_level_start,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card, int val),
|
||||
|
||||
TP_ARGS(card, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_card, snd_soc_bias_level_done,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card, int val),
|
||||
|
||||
TP_ARGS(card, val)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(snd_soc_dapm_basic,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card),
|
||||
|
||||
TP_ARGS(card),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, card->name )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, card->name);
|
||||
),
|
||||
|
||||
TP_printk("card=%s", __get_str(name))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_dapm_basic, snd_soc_dapm_start,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card),
|
||||
|
||||
TP_ARGS(card)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_dapm_basic, snd_soc_dapm_done,
|
||||
|
||||
TP_PROTO(struct snd_soc_card *card),
|
||||
|
||||
TP_ARGS(card)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(snd_soc_dapm_widget,
|
||||
|
||||
TP_PROTO(struct snd_soc_dapm_widget *w, int val),
|
||||
|
||||
TP_ARGS(w, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, w->name )
|
||||
__field( int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, w->name);
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("widget=%s val=%d", __get_str(name),
|
||||
(int)__entry->val)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_power,
|
||||
|
||||
TP_PROTO(struct snd_soc_dapm_widget *w, int val),
|
||||
|
||||
TP_ARGS(w, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_start,
|
||||
|
||||
TP_PROTO(struct snd_soc_dapm_widget *w, int val),
|
||||
|
||||
TP_ARGS(w, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
|
||||
|
||||
TP_PROTO(struct snd_soc_dapm_widget *w, int val),
|
||||
|
||||
TP_ARGS(w, val)
|
||||
|
||||
);
|
||||
|
||||
TRACE_EVENT(snd_soc_jack_irq,
|
||||
|
||||
TP_PROTO(const char *name),
|
||||
|
||||
TP_ARGS(name),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, name )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, name);
|
||||
),
|
||||
|
||||
TP_printk("%s", __get_str(name))
|
||||
);
|
||||
|
||||
TRACE_EVENT(snd_soc_jack_report,
|
||||
|
||||
TP_PROTO(struct snd_soc_jack *jack, int mask, int val),
|
||||
|
||||
TP_ARGS(jack, mask, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, jack->jack->name )
|
||||
__field( int, mask )
|
||||
__field( int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, jack->jack->name);
|
||||
__entry->mask = mask;
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("jack=%s %x/%x", __get_str(name), (int)__entry->val,
|
||||
(int)__entry->mask)
|
||||
);
|
||||
|
||||
TRACE_EVENT(snd_soc_jack_notify,
|
||||
|
||||
TP_PROTO(struct snd_soc_jack *jack, int val),
|
||||
|
||||
TP_ARGS(jack, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, jack->jack->name )
|
||||
__field( int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, jack->jack->name);
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("jack=%s %x", __get_str(name), (int)__entry->val)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_ASOC_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
|
@ -20,6 +20,21 @@ menuconfig SND_SOC
|
|||
|
||||
if SND_SOC
|
||||
|
||||
config SND_SOC_CACHE_LZO
|
||||
bool "Support LZO compression for register caches"
|
||||
select LZO_COMPRESS
|
||||
select LZO_DECOMPRESS
|
||||
---help---
|
||||
Select this to enable LZO compression for register caches.
|
||||
This will allow machine or CODEC drivers to compress register
|
||||
caches in memory, reducing the memory consumption at the
|
||||
expense of performance. If this is not present and is used
|
||||
the system will fall back to uncompressed caches.
|
||||
|
||||
Usually it is safe to disable this option, where cache
|
||||
compression in used the rbtree option will typically perform
|
||||
better.
|
||||
|
||||
config SND_SOC_AC97_BUS
|
||||
bool
|
||||
|
||||
|
@ -36,7 +51,7 @@ source "sound/soc/nuc900/Kconfig"
|
|||
source "sound/soc/omap/Kconfig"
|
||||
source "sound/soc/kirkwood/Kconfig"
|
||||
source "sound/soc/pxa/Kconfig"
|
||||
source "sound/soc/s3c24xx/Kconfig"
|
||||
source "sound/soc/samsung/Kconfig"
|
||||
source "sound/soc/s6000/Kconfig"
|
||||
source "sound/soc/sh/Kconfig"
|
||||
source "sound/soc/txx9/Kconfig"
|
||||
|
|
|
@ -14,7 +14,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/
|
|||
obj-$(CONFIG_SND_SOC) += omap/
|
||||
obj-$(CONFIG_SND_SOC) += kirkwood/
|
||||
obj-$(CONFIG_SND_SOC) += pxa/
|
||||
obj-$(CONFIG_SND_SOC) += s3c24xx/
|
||||
obj-$(CONFIG_SND_SOC) += samsung/
|
||||
obj-$(CONFIG_SND_SOC) += s6000/
|
||||
obj-$(CONFIG_SND_SOC) += sh/
|
||||
obj-$(CONFIG_SND_SOC) += txx9/
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include <mach/at32ap700x.h>
|
||||
#include <mach/portmux.h>
|
||||
|
@ -318,27 +317,28 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Add DAPM widgets
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
|
||||
snd_soc_dapm_new_control(codec, &playpaq_dapm_widgets[i]);
|
||||
snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Setup audio path interconnects
|
||||
*/
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
|
||||
|
||||
/* always connected pins */
|
||||
snd_soc_dapm_enable_pin(codec, "Int Mic");
|
||||
snd_soc_dapm_enable_pin(codec, "Ext Spk");
|
||||
snd_soc_dapm_sync(codec);
|
||||
snd_soc_dapm_enable_pin(dapm, "Int Mic");
|
||||
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -140,6 +139,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
|||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
printk(KERN_DEBUG
|
||||
|
@ -154,25 +154,25 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
|||
}
|
||||
|
||||
/* Add specific widgets */
|
||||
snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets,
|
||||
ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
|
||||
/* Set up specific audio path interconnects */
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
/* not connected */
|
||||
snd_soc_dapm_nc_pin(codec, "RLINEIN");
|
||||
snd_soc_dapm_nc_pin(codec, "LLINEIN");
|
||||
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
|
||||
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
|
||||
|
||||
#ifdef ENABLE_MIC_INPUT
|
||||
snd_soc_dapm_enable_pin(codec, "Int Mic");
|
||||
snd_soc_dapm_enable_pin(dapm, "Int Mic");
|
||||
#else
|
||||
snd_soc_dapm_nc_pin(codec, "Int Mic");
|
||||
snd_soc_dapm_nc_pin(dapm, "Int Mic");
|
||||
#endif
|
||||
|
||||
/* always connected */
|
||||
snd_soc_dapm_enable_pin(codec, "Ext Spk");
|
||||
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
|
||||
|
||||
snd_soc_dapm_sync(codec);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -105,19 +104,20 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
/* Add afeb9260 specific widgets */
|
||||
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
|
||||
ARRAY_SIZE(tlv320aic23_dapm_widgets));
|
||||
|
||||
/* Set up afeb9260 specific audio path audio_map */
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
snd_soc_dapm_enable_pin(codec, "Headphone Jack");
|
||||
snd_soc_dapm_enable_pin(codec, "Line In");
|
||||
snd_soc_dapm_enable_pin(codec, "Mic Jack");
|
||||
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
|
||||
snd_soc_dapm_enable_pin(dapm, "Line In");
|
||||
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
|
||||
|
||||
snd_soc_dapm_sync(codec);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-au1x00/au1xxx_psc.h>
|
||||
#include <asm/mach-au1x00/au1xxx_dbdma.h>
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include <asm/blackfin.h>
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include <asm/blackfin.h>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include <asm/blackfin.h>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/jack.h>
|
||||
#include <trace/events/asoc.h>
|
||||
|
||||
#include "88pm860x-codec.h"
|
||||
|
||||
|
@ -146,7 +146,6 @@ struct pm860x_priv {
|
|||
|
||||
int irq[4];
|
||||
unsigned char name[4][MAX_NAME_LEN];
|
||||
unsigned char reg_cache[REG_CACHE_SIZE];
|
||||
};
|
||||
|
||||
/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
|
||||
|
@ -1172,7 +1171,7 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Enable Audio PLL & Audio section */
|
||||
data = AUDIO_PLL | AUDIO_SECTION_RESET
|
||||
| AUDIO_SECTION_ON;
|
||||
|
@ -1185,7 +1184,7 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
|||
pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1263,6 +1262,12 @@ static irqreturn_t pm860x_codec_handler(int irq, void *data)
|
|||
mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt
|
||||
| pm860x->det.hp_det;
|
||||
|
||||
#ifndef CONFIG_SND_SOC_88PM860X_MODULE
|
||||
if (status & (HEADSET_STATUS | MIC_STATUS | SHORT_HS1 | SHORT_HS2 |
|
||||
SHORT_LO1 | SHORT_LO2))
|
||||
trace_snd_soc_jack_irq(dev_name(pm860x->codec->dev));
|
||||
#endif
|
||||
|
||||
if ((pm860x->det.hp_det & SND_JACK_HEADPHONE)
|
||||
&& (status & HEADSET_STATUS))
|
||||
report |= SND_JACK_HEADPHONE;
|
||||
|
@ -1346,6 +1351,7 @@ EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect);
|
|||
static int pm860x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int i, ret;
|
||||
|
||||
pm860x->codec = codec;
|
||||
|
@ -1358,7 +1364,7 @@ static int pm860x_probe(struct snd_soc_codec *codec)
|
|||
pm860x->name[i], pm860x);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to request IRQ!\n");
|
||||
goto out_irq;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1369,22 +1375,20 @@ static int pm860x_probe(struct snd_soc_codec *codec)
|
|||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to fill register cache: %d\n",
|
||||
ret);
|
||||
goto out_codec;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, pm860x_snd_controls,
|
||||
ARRAY_SIZE(pm860x_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, pm860x_dapm_widgets,
|
||||
ARRAY_SIZE(pm860x_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
return 0;
|
||||
|
||||
out_codec:
|
||||
i = 3;
|
||||
out_irq:
|
||||
for (; i >= 0; i--)
|
||||
out:
|
||||
while (--i >= 0)
|
||||
free_irq(pm860x->irq[i], pm860x);
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pm860x_remove(struct snd_soc_codec *codec)
|
||||
|
|
|
@ -22,6 +22,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_AK4535 if I2C
|
||||
select SND_SOC_AK4642 if I2C
|
||||
select SND_SOC_AK4671 if I2C
|
||||
select SND_SOC_ALC5623 if I2C
|
||||
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
|
||||
select SND_SOC_CS42L51 if I2C
|
||||
select SND_SOC_CS4270 if I2C
|
||||
|
@ -54,9 +55,11 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_WM8727
|
||||
select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8737 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8770 if SPI_MASTER
|
||||
select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8900 if I2C
|
||||
|
@ -75,6 +78,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_WM8990 if I2C
|
||||
select SND_SOC_WM8993 if I2C
|
||||
select SND_SOC_WM8994 if MFD_WM8994
|
||||
select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM9081 if I2C
|
||||
select SND_SOC_WM9090 if I2C
|
||||
select SND_SOC_WM9705 if SND_SOC_AC97_BUS
|
||||
|
@ -130,6 +134,9 @@ config SND_SOC_AK4642
|
|||
config SND_SOC_AK4671
|
||||
tristate
|
||||
|
||||
config SND_SOC_ALC5623
|
||||
tristate
|
||||
|
||||
config SND_SOC_CQ0093VC
|
||||
tristate
|
||||
|
||||
|
@ -160,6 +167,9 @@ config SND_SOC_L3
|
|||
config SND_SOC_DA7210
|
||||
tristate
|
||||
|
||||
config SND_SOC_DMIC
|
||||
tristate
|
||||
|
||||
config SND_SOC_MAX98088
|
||||
tristate
|
||||
|
||||
|
@ -231,6 +241,9 @@ config SND_SOC_WM8728
|
|||
config SND_SOC_WM8731
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8737
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8741
|
||||
tristate
|
||||
|
||||
|
@ -240,6 +253,9 @@ config SND_SOC_WM8750
|
|||
config SND_SOC_WM8753
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8770
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8776
|
||||
tristate
|
||||
|
||||
|
@ -294,6 +310,9 @@ config SND_SOC_WM8993
|
|||
config SND_SOC_WM8994
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8995
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM9081
|
||||
tristate
|
||||
|
||||
|
@ -318,3 +337,4 @@ config SND_SOC_WM2000
|
|||
|
||||
config SND_SOC_WM9090
|
||||
tristate
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@ snd-soc-cs42l51-objs := cs42l51.o
|
|||
snd-soc-cs4270-objs := cs4270.o
|
||||
snd-soc-cx20442-objs := cx20442.o
|
||||
snd-soc-da7210-objs := da7210.o
|
||||
snd-soc-dmic-objs := dmic.o
|
||||
snd-soc-l3-objs := l3.o
|
||||
snd-soc-max98088-objs := max98088.o
|
||||
snd-soc-pcm3008-objs := pcm3008.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
snd-soc-spdif-objs := spdif_transciever.o
|
||||
snd-soc-ssm2602-objs := ssm2602.o
|
||||
snd-soc-stac9766-objs := stac9766.o
|
||||
|
@ -38,9 +40,11 @@ snd-soc-wm8711-objs := wm8711.o
|
|||
snd-soc-wm8727-objs := wm8727.o
|
||||
snd-soc-wm8728-objs := wm8728.o
|
||||
snd-soc-wm8731-objs := wm8731.o
|
||||
snd-soc-wm8737-objs := wm8737.o
|
||||
snd-soc-wm8741-objs := wm8741.o
|
||||
snd-soc-wm8750-objs := wm8750.o
|
||||
snd-soc-wm8753-objs := wm8753.o
|
||||
snd-soc-wm8770-objs := wm8770.o
|
||||
snd-soc-wm8776-objs := wm8776.o
|
||||
snd-soc-wm8804-objs := wm8804.o
|
||||
snd-soc-wm8900-objs := wm8900.o
|
||||
|
@ -58,7 +62,8 @@ snd-soc-wm8985-objs := wm8985.o
|
|||
snd-soc-wm8988-objs := wm8988.o
|
||||
snd-soc-wm8990-objs := wm8990.o
|
||||
snd-soc-wm8993-objs := wm8993.o
|
||||
snd-soc-wm8994-objs := wm8994.o
|
||||
snd-soc-wm8994-objs := wm8994.o wm8994-tables.o
|
||||
snd-soc-wm8995-objs := wm8995.o
|
||||
snd-soc-wm9081-objs := wm9081.o
|
||||
snd-soc-wm9705-objs := wm9705.o
|
||||
snd-soc-wm9712-objs := wm9712.o
|
||||
|
@ -88,10 +93,12 @@ obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
|
|||
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
|
||||
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
|
||||
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
|
||||
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
|
||||
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
|
||||
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
|
||||
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
|
||||
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
|
||||
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
|
||||
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
|
@ -113,9 +120,11 @@ obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
|
|||
obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
|
||||
obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
|
||||
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
|
||||
obj-$(CONFIG_SND_SOC_WM8737) += snd-soc-wm8737.o
|
||||
obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o
|
||||
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
|
||||
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
|
||||
obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o
|
||||
obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
|
||||
obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o
|
||||
obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
|
||||
|
@ -134,6 +143,7 @@ obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
|
|||
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
|
||||
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
|
||||
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
|
||||
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
|
||||
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
|
||||
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
|
||||
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include "ad1836.h"
|
||||
|
||||
|
@ -220,6 +219,7 @@ static struct snd_soc_dai_driver ad1836_dai = {
|
|||
static int ad1836_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret = 0;
|
||||
|
||||
codec->control_data = ad1836->control_data;
|
||||
|
@ -227,7 +227,6 @@ static int ad1836_probe(struct snd_soc_codec *codec)
|
|||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n",
|
||||
ret);
|
||||
kfree(ad1836);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -252,9 +251,9 @@ static int ad1836_probe(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_add_controls(codec, ad1836_snd_controls,
|
||||
ARRAY_SIZE(ad1836_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets,
|
||||
ARRAY_SIZE(ad1836_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,10 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "ad193x.h"
|
||||
|
||||
/* codec private data */
|
||||
struct ad193x_priv {
|
||||
u8 reg_cache[AD193X_NUM_REGS];
|
||||
enum snd_soc_control_type bus_type;
|
||||
void *control_data;
|
||||
int sysclk;
|
||||
|
@ -353,6 +351,7 @@ static struct snd_soc_dai_driver ad193x_dai = {
|
|||
static int ad193x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
codec->control_data = ad193x->control_data;
|
||||
|
@ -363,7 +362,6 @@ static int ad193x_probe(struct snd_soc_codec *codec)
|
|||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n",
|
||||
ret);
|
||||
kfree(ad193x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -385,9 +383,9 @@ static int ad193x_probe(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_add_controls(codec, ad193x_snd_controls,
|
||||
ARRAY_SIZE(ad193x_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, ad193x_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, ad193x_dapm_widgets,
|
||||
ARRAY_SIZE(ad193x_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <sound/ac97_codec.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include "ad1980.h"
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "ak4535.h"
|
||||
|
@ -290,10 +289,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int ak4535_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, ak4535_dapm_widgets,
|
||||
ARRAY_SIZE(ak4535_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, ak4535_dapm_widgets,
|
||||
ARRAY_SIZE(ak4535_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -366,9 +366,9 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||
static int ak4535_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
|
||||
u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
if (!mute)
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg);
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
|
||||
else
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
return 0;
|
||||
|
@ -381,11 +381,11 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec,
|
|||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg);
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
|
@ -399,7 +399,7 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec,
|
|||
ak4535_write(codec, AK4535_PM1, i & (~0x80));
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -28,7 +27,6 @@
|
|||
struct ak4671_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[AK4671_CACHEREGNUM];
|
||||
};
|
||||
|
||||
/* ak4671 register cache & default register settings */
|
||||
|
@ -437,10 +435,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int ak4671_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets,
|
||||
ARRAY_SIZE(ak4671_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, ak4671_dapm_widgets,
|
||||
ARRAY_SIZE(ak4671_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -602,7 +601,7 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* alc5623.h -- alc562[123] ALSA Soc Audio driver
|
||||
*
|
||||
* Copyright 2008 Realtek Microelectronics
|
||||
* Copyright 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
*
|
||||
* Author: flove <flove@realtek.com>
|
||||
* Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
*
|
||||
* 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 _ALC5623_H
|
||||
#define _ALC5623_H
|
||||
|
||||
#define ALC5623_RESET 0x00
|
||||
/* 5621 5622 5623 */
|
||||
/* speaker output vol 2 2 */
|
||||
/* line output vol 4 2 */
|
||||
/* HP output vol 4 0 4 */
|
||||
#define ALC5623_SPK_OUT_VOL 0x02
|
||||
#define ALC5623_HP_OUT_VOL 0x04
|
||||
#define ALC5623_MONO_AUX_OUT_VOL 0x06
|
||||
#define ALC5623_AUXIN_VOL 0x08
|
||||
#define ALC5623_LINE_IN_VOL 0x0A
|
||||
#define ALC5623_STEREO_DAC_VOL 0x0C
|
||||
#define ALC5623_MIC_VOL 0x0E
|
||||
#define ALC5623_MIC_ROUTING_CTRL 0x10
|
||||
#define ALC5623_ADC_REC_GAIN 0x12
|
||||
#define ALC5623_ADC_REC_MIXER 0x14
|
||||
#define ALC5623_SOFT_VOL_CTRL_TIME 0x16
|
||||
/* ALC5623_OUTPUT_MIXER_CTRL : */
|
||||
/* same remark as for reg 2 line vs speaker */
|
||||
#define ALC5623_OUTPUT_MIXER_CTRL 0x1C
|
||||
#define ALC5623_MIC_CTRL 0x22
|
||||
|
||||
#define ALC5623_DAI_CONTROL 0x34
|
||||
#define ALC5623_DAI_SDP_MASTER_MODE (0 << 15)
|
||||
#define ALC5623_DAI_SDP_SLAVE_MODE (1 << 15)
|
||||
#define ALC5623_DAI_I2S_PCM_MODE (1 << 14)
|
||||
#define ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL (1 << 7)
|
||||
#define ALC5623_DAI_ADC_DATA_L_R_SWAP (1 << 5)
|
||||
#define ALC5623_DAI_DAC_DATA_L_R_SWAP (1 << 4)
|
||||
#define ALC5623_DAI_I2S_DL_MASK (3 << 2)
|
||||
#define ALC5623_DAI_I2S_DL_32 (3 << 2)
|
||||
#define ALC5623_DAI_I2S_DL_24 (2 << 2)
|
||||
#define ALC5623_DAI_I2S_DL_20 (1 << 2)
|
||||
#define ALC5623_DAI_I2S_DL_16 (0 << 2)
|
||||
#define ALC5623_DAI_I2S_DF_PCM (3 << 0)
|
||||
#define ALC5623_DAI_I2S_DF_LEFT (2 << 0)
|
||||
#define ALC5623_DAI_I2S_DF_RIGHT (1 << 0)
|
||||
#define ALC5623_DAI_I2S_DF_I2S (0 << 0)
|
||||
|
||||
#define ALC5623_STEREO_AD_DA_CLK_CTRL 0x36
|
||||
#define ALC5623_COMPANDING_CTRL 0x38
|
||||
|
||||
#define ALC5623_PWR_MANAG_ADD1 0x3A
|
||||
#define ALC5623_PWR_ADD1_MAIN_I2S_EN (1 << 15)
|
||||
#define ALC5623_PWR_ADD1_ZC_DET_PD_EN (1 << 14)
|
||||
#define ALC5623_PWR_ADD1_MIC1_BIAS_EN (1 << 11)
|
||||
#define ALC5623_PWR_ADD1_SHORT_CURR_DET_EN (1 << 10)
|
||||
#define ALC5623_PWR_ADD1_SOFTGEN_EN (1 << 8) /* rsvd on 5622 */
|
||||
#define ALC5623_PWR_ADD1_DEPOP_BUF_HP (1 << 6) /* rsvd on 5622 */
|
||||
#define ALC5623_PWR_ADD1_HP_OUT_AMP (1 << 5)
|
||||
#define ALC5623_PWR_ADD1_HP_OUT_ENH_AMP (1 << 4) /* rsvd on 5622 */
|
||||
#define ALC5623_PWR_ADD1_DEPOP_BUF_AUX (1 << 2)
|
||||
#define ALC5623_PWR_ADD1_AUX_OUT_AMP (1 << 1)
|
||||
#define ALC5623_PWR_ADD1_AUX_OUT_ENH_AMP (1 << 0) /* rsvd on 5622 */
|
||||
|
||||
#define ALC5623_PWR_MANAG_ADD2 0x3C
|
||||
#define ALC5623_PWR_ADD2_LINEOUT (1 << 15) /* rt5623 */
|
||||
#define ALC5623_PWR_ADD2_CLASS_AB (1 << 15) /* rt5621 */
|
||||
#define ALC5623_PWR_ADD2_CLASS_D (1 << 14) /* rt5621 */
|
||||
#define ALC5623_PWR_ADD2_VREF (1 << 13)
|
||||
#define ALC5623_PWR_ADD2_PLL (1 << 12)
|
||||
#define ALC5623_PWR_ADD2_DAC_REF_CIR (1 << 10)
|
||||
#define ALC5623_PWR_ADD2_L_DAC_CLK (1 << 9)
|
||||
#define ALC5623_PWR_ADD2_R_DAC_CLK (1 << 8)
|
||||
#define ALC5623_PWR_ADD2_L_ADC_CLK_GAIN (1 << 7)
|
||||
#define ALC5623_PWR_ADD2_R_ADC_CLK_GAIN (1 << 6)
|
||||
#define ALC5623_PWR_ADD2_L_HP_MIXER (1 << 5)
|
||||
#define ALC5623_PWR_ADD2_R_HP_MIXER (1 << 4)
|
||||
#define ALC5623_PWR_ADD2_SPK_MIXER (1 << 3)
|
||||
#define ALC5623_PWR_ADD2_MONO_MIXER (1 << 2)
|
||||
#define ALC5623_PWR_ADD2_L_ADC_REC_MIXER (1 << 1)
|
||||
#define ALC5623_PWR_ADD2_R_ADC_REC_MIXER (1 << 0)
|
||||
|
||||
#define ALC5623_PWR_MANAG_ADD3 0x3E
|
||||
#define ALC5623_PWR_ADD3_MAIN_BIAS (1 << 15)
|
||||
#define ALC5623_PWR_ADD3_AUXOUT_L_VOL_AMP (1 << 14)
|
||||
#define ALC5623_PWR_ADD3_AUXOUT_R_VOL_AMP (1 << 13)
|
||||
#define ALC5623_PWR_ADD3_SPK_OUT (1 << 12)
|
||||
#define ALC5623_PWR_ADD3_HP_L_OUT_VOL (1 << 10)
|
||||
#define ALC5623_PWR_ADD3_HP_R_OUT_VOL (1 << 9)
|
||||
#define ALC5623_PWR_ADD3_LINEIN_L_VOL (1 << 7)
|
||||
#define ALC5623_PWR_ADD3_LINEIN_R_VOL (1 << 6)
|
||||
#define ALC5623_PWR_ADD3_AUXIN_L_VOL (1 << 5)
|
||||
#define ALC5623_PWR_ADD3_AUXIN_R_VOL (1 << 4)
|
||||
#define ALC5623_PWR_ADD3_MIC1_FUN_CTRL (1 << 3)
|
||||
#define ALC5623_PWR_ADD3_MIC2_FUN_CTRL (1 << 2)
|
||||
#define ALC5623_PWR_ADD3_MIC1_BOOST_AD (1 << 1)
|
||||
#define ALC5623_PWR_ADD3_MIC2_BOOST_AD (1 << 0)
|
||||
|
||||
#define ALC5623_ADD_CTRL_REG 0x40
|
||||
|
||||
#define ALC5623_GLOBAL_CLK_CTRL_REG 0x42
|
||||
#define ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL (1 << 15)
|
||||
#define ALC5623_GBL_CLK_SYS_SOUR_SEL_MCLK (0 << 15)
|
||||
#define ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK (1 << 14)
|
||||
#define ALC5623_GBL_CLK_PLL_SOUR_SEL_MCLK (0 << 14)
|
||||
#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV8 (3 << 1)
|
||||
#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV4 (2 << 1)
|
||||
#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV2 (1 << 1)
|
||||
#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV1 (0 << 1)
|
||||
#define ALC5623_GBL_CLK_PLL_PRE_DIV2 (1 << 0)
|
||||
#define ALC5623_GBL_CLK_PLL_PRE_DIV1 (0 << 0)
|
||||
|
||||
#define ALC5623_PLL_CTRL 0x44
|
||||
#define ALC5623_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8)
|
||||
#define ALC5623_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4)
|
||||
#define ALC5623_PLL_CTRL_M_VAL(m) ((m)&0xf)
|
||||
|
||||
#define ALC5623_GPIO_OUTPUT_PIN_CTRL 0x4A
|
||||
#define ALC5623_GPIO_PIN_CONFIG 0x4C
|
||||
#define ALC5623_GPIO_PIN_POLARITY 0x4E
|
||||
#define ALC5623_GPIO_PIN_STICKY 0x50
|
||||
#define ALC5623_GPIO_PIN_WAKEUP 0x52
|
||||
#define ALC5623_GPIO_PIN_STATUS 0x54
|
||||
#define ALC5623_GPIO_PIN_SHARING 0x56
|
||||
#define ALC5623_OVER_CURR_STATUS 0x58
|
||||
#define ALC5623_JACK_DET_CTRL 0x5A
|
||||
|
||||
#define ALC5623_MISC_CTRL 0x5E
|
||||
#define ALC5623_MISC_DISABLE_FAST_VREG (1 << 15)
|
||||
#define ALC5623_MISC_SPK_CLASS_AB_OC_PD (1 << 13) /* 5621 */
|
||||
#define ALC5623_MISC_SPK_CLASS_AB_OC_DET (1 << 12) /* 5621 */
|
||||
#define ALC5623_MISC_HP_DEPOP_MODE3_EN (1 << 10)
|
||||
#define ALC5623_MISC_HP_DEPOP_MODE2_EN (1 << 9)
|
||||
#define ALC5623_MISC_HP_DEPOP_MODE1_EN (1 << 8)
|
||||
#define ALC5623_MISC_AUXOUT_DEPOP_MODE3_EN (1 << 6)
|
||||
#define ALC5623_MISC_AUXOUT_DEPOP_MODE2_EN (1 << 5)
|
||||
#define ALC5623_MISC_AUXOUT_DEPOP_MODE1_EN (1 << 4)
|
||||
#define ALC5623_MISC_M_DAC_L_INPUT (1 << 3)
|
||||
#define ALC5623_MISC_M_DAC_R_INPUT (1 << 2)
|
||||
#define ALC5623_MISC_IRQOUT_INV_CTRL (1 << 0)
|
||||
|
||||
#define ALC5623_PSEDUEO_SPATIAL_CTRL 0x60
|
||||
#define ALC5623_EQ_CTRL 0x62
|
||||
#define ALC5623_EQ_MODE_ENABLE 0x66
|
||||
#define ALC5623_AVC_CTRL 0x68
|
||||
#define ALC5623_HID_CTRL_INDEX 0x6A
|
||||
#define ALC5623_HID_CTRL_DATA 0x6C
|
||||
#define ALC5623_VENDOR_ID1 0x7C
|
||||
#define ALC5623_VENDOR_ID2 0x7E
|
||||
|
||||
#define ALC5623_PLL_FR_MCLK 0
|
||||
#define ALC5623_PLL_FR_BCK 1
|
||||
#endif
|
|
@ -36,8 +36,6 @@
|
|||
#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>
|
||||
|
@ -116,7 +114,7 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
|
|||
DAVINCI_VC_REG12_POWER_ALL_OFF);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -106,6 +106,21 @@
|
|||
#define CS4270_MUTE_DAC_A 0x01
|
||||
#define CS4270_MUTE_DAC_B 0x02
|
||||
|
||||
/* Power-on default values for the registers
|
||||
*
|
||||
* This array contains the power-on default values of the registers, with the
|
||||
* exception of the "CHIPID" register (01h). The lower four bits of that
|
||||
* register contain the hardware revision, so it is treated as volatile.
|
||||
*
|
||||
* Also note that on the CS4270, the first readable register is 1, but ASoC
|
||||
* assumes the first register is 0. Therfore, the array must have an entry for
|
||||
* register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't
|
||||
* be read.
|
||||
*/
|
||||
static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = {
|
||||
0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const char *supply_names[] = {
|
||||
"va", "vd", "vlc"
|
||||
};
|
||||
|
@ -114,7 +129,6 @@ static const char *supply_names[] = {
|
|||
struct cs4270_private {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[CS4270_NUMREGS];
|
||||
unsigned int mclk; /* Input frequency of the MCLK pin */
|
||||
unsigned int mode; /* The mode (I2S or left-justified) */
|
||||
unsigned int slave_mode;
|
||||
|
@ -179,6 +193,20 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
|
|||
/* The number of MCLK/LRCK ratios supported by the CS4270 */
|
||||
#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios)
|
||||
|
||||
static int cs4270_reg_is_readable(unsigned int reg)
|
||||
{
|
||||
return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG);
|
||||
}
|
||||
|
||||
static int cs4270_reg_is_volatile(unsigned int reg)
|
||||
{
|
||||
/* Unreadable registers are considered volatile */
|
||||
if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
|
||||
return 1;
|
||||
|
||||
return reg == CS4270_CHIPID;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_set_dai_sysclk - determine the CS4270 samples rates.
|
||||
* @codec_dai: the codec DAI
|
||||
|
@ -263,97 +291,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_fill_cache - pre-fill the CS4270 register cache.
|
||||
* @codec: the codec for this CS4270
|
||||
*
|
||||
* This function fills in the CS4270 register cache by reading the register
|
||||
* values from the hardware.
|
||||
*
|
||||
* This CS4270 registers are cached to avoid excessive I2C I/O operations.
|
||||
* After the initial read to pre-fill the cache, the CS4270 never updates
|
||||
* the register values, so we won't have a cache coherency problem.
|
||||
*
|
||||
* We use the auto-increment feature of the CS4270 to read all registers in
|
||||
* one shot.
|
||||
*/
|
||||
static int cs4270_fill_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 *cache = codec->reg_cache;
|
||||
struct i2c_client *i2c_client = codec->control_data;
|
||||
s32 length;
|
||||
|
||||
length = i2c_smbus_read_i2c_block_data(i2c_client,
|
||||
CS4270_FIRSTREG | CS4270_I2C_INCR, CS4270_NUMREGS, cache);
|
||||
|
||||
if (length != CS4270_NUMREGS) {
|
||||
dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
|
||||
i2c_client->addr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_read_reg_cache - read from the CS4270 register cache.
|
||||
* @codec: the codec for this CS4270
|
||||
* @reg: the register to read
|
||||
*
|
||||
* This function returns the value for a given register. It reads only from
|
||||
* the register cache, not the hardware itself.
|
||||
*
|
||||
* This CS4270 registers are cached to avoid excessive I2C I/O operations.
|
||||
* After the initial read to pre-fill the cache, the CS4270 never updates
|
||||
* the register values, so we won't have a cache coherency problem.
|
||||
*/
|
||||
static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
u8 *cache = codec->reg_cache;
|
||||
|
||||
if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
|
||||
return -EIO;
|
||||
|
||||
return cache[reg - CS4270_FIRSTREG];
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_i2c_write - write to a CS4270 register via the I2C bus.
|
||||
* @codec: the codec for this CS4270
|
||||
* @reg: the register to write
|
||||
* @value: the value to write to the register
|
||||
*
|
||||
* This function writes the given value to the given CS4270 register, and
|
||||
* also updates the register cache.
|
||||
*
|
||||
* Note that we don't use the hw_write function pointer of snd_soc_codec.
|
||||
* That's because it's too clunky: the hw_write_t prototype does not match
|
||||
* i2c_smbus_write_byte_data(), and it's just another layer of overhead.
|
||||
*/
|
||||
static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
u8 *cache = codec->reg_cache;
|
||||
|
||||
if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
|
||||
return -EIO;
|
||||
|
||||
/* Only perform an I2C operation if the new value is different */
|
||||
if (cache[reg - CS4270_FIRSTREG] != value) {
|
||||
struct i2c_client *client = codec->control_data;
|
||||
if (i2c_smbus_write_byte_data(client, reg, value)) {
|
||||
dev_err(codec->dev, "i2c write failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* We've written to the hardware, so update the cache */
|
||||
cache[reg - CS4270_FIRSTREG] = value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_hw_params - program the CS4270 with the given hardware parameters.
|
||||
* @substream: the audio stream
|
||||
|
@ -551,15 +488,16 @@ static struct snd_soc_dai_driver cs4270_dai = {
|
|||
static int cs4270_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret, reg;
|
||||
int i, ret;
|
||||
|
||||
codec->control_data = cs4270->control_data;
|
||||
|
||||
/* The I2C interface is set up, so pre-fill our register cache */
|
||||
|
||||
ret = cs4270_fill_cache(codec);
|
||||
/* Tell ASoC what kind of I/O to use to read the registers. ASoC will
|
||||
* then do the I2C transactions itself.
|
||||
*/
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to fill register cache\n");
|
||||
dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -568,10 +506,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
|
|||
* this feature disabled by default. An application (e.g. alsactl) can
|
||||
* re-enabled it by using the controls.
|
||||
*/
|
||||
|
||||
reg = cs4270_read_reg_cache(codec, CS4270_MUTE);
|
||||
reg &= ~CS4270_MUTE_AUTO;
|
||||
ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
|
||||
ret = snd_soc_update_bits(codec, CS4270_MUTE, CS4270_MUTE_AUTO, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "i2c write failed\n");
|
||||
return ret;
|
||||
|
@ -582,10 +517,8 @@ static int cs4270_probe(struct snd_soc_codec *codec)
|
|||
* playback has started. An application (e.g. alsactl) can
|
||||
* re-enabled it by using the controls.
|
||||
*/
|
||||
|
||||
reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
|
||||
reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
|
||||
ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
|
||||
ret = snd_soc_update_bits(codec, CS4270_TRANS,
|
||||
CS4270_TRANS_SOFT | CS4270_TRANS_ZERO, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "i2c write failed\n");
|
||||
return ret;
|
||||
|
@ -708,15 +641,16 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)
|
|||
* Assign this variable to the codec_dev field of the machine driver's
|
||||
* snd_soc_device structure.
|
||||
*/
|
||||
static struct snd_soc_codec_driver soc_codec_device_cs4270 = {
|
||||
.probe = cs4270_probe,
|
||||
.remove = cs4270_remove,
|
||||
.suspend = cs4270_soc_suspend,
|
||||
.resume = cs4270_soc_resume,
|
||||
.read = cs4270_read_reg_cache,
|
||||
.write = cs4270_i2c_write,
|
||||
.reg_cache_size = CS4270_NUMREGS,
|
||||
.reg_word_size = sizeof(u8),
|
||||
static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
|
||||
.probe = cs4270_probe,
|
||||
.remove = cs4270_remove,
|
||||
.suspend = cs4270_soc_suspend,
|
||||
.resume = cs4270_soc_resume,
|
||||
.volatile_register = cs4270_reg_is_volatile,
|
||||
.readable_register = cs4270_reg_is_readable,
|
||||
.reg_cache_size = CS4270_LASTREG + 1,
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = cs4270_default_reg_cache,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
@ -47,7 +46,6 @@ struct cs42l51_private {
|
|||
unsigned int mclk;
|
||||
unsigned int audio_mode; /* The mode (I2S or left-justified) */
|
||||
enum master_slave_mode func;
|
||||
u8 reg_cache[CS42L51_NUMREGS];
|
||||
};
|
||||
|
||||
#define CS42L51_FORMATS ( \
|
||||
|
@ -519,6 +517,7 @@ static struct snd_soc_dai_driver cs42l51_dai = {
|
|||
static int cs42l51_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret, reg;
|
||||
|
||||
codec->control_data = cs42l51->control_data;
|
||||
|
@ -550,9 +549,9 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_add_controls(codec, cs42l51_snd_controls,
|
||||
ARRAY_SIZE(cs42l51_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, cs42l51_dapm_widgets,
|
||||
ARRAY_SIZE(cs42l51_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, cs42l51_routes,
|
||||
snd_soc_dapm_add_routes(dapm, cs42l51_routes,
|
||||
ARRAY_SIZE(cs42l51_routes));
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "cx20442.h"
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
|||
struct cx20442_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[1];
|
||||
};
|
||||
|
||||
#define CX20442_PM 0x0
|
||||
|
@ -89,10 +88,11 @@ static const struct snd_soc_dapm_route cx20442_audio_map[] = {
|
|||
|
||||
static int cx20442_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets,
|
||||
ARRAY_SIZE(cx20442_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, cx20442_audio_map,
|
||||
snd_soc_dapm_new_controls(dapm, cx20442_dapm_widgets,
|
||||
ARRAY_SIZE(cx20442_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, cx20442_audio_map,
|
||||
ARRAY_SIZE(cx20442_audio_map));
|
||||
|
||||
return 0;
|
||||
|
@ -263,7 +263,7 @@ static void v253_close(struct tty_struct *tty)
|
|||
/* Prevent the codec driver from further accessing the modem */
|
||||
codec->hw_write = NULL;
|
||||
cx20442->control_data = NULL;
|
||||
codec->pop_time = 0;
|
||||
codec->card->pop_time = 0;
|
||||
}
|
||||
|
||||
/* Line discipline .hangup() */
|
||||
|
@ -291,7 +291,7 @@ static void v253_receive(struct tty_struct *tty,
|
|||
/* Set up codec driver access to modem controls */
|
||||
cx20442->control_data = tty;
|
||||
codec->hw_write = (hw_write_t)tty->ops->write;
|
||||
codec->pop_time = 1;
|
||||
codec->card->pop_time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
cx20442->control_data = NULL;
|
||||
codec->hw_write = NULL;
|
||||
codec->pop_time = 0;
|
||||
codec->card->pop_time = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* dmic.c -- SoC audio for Generic Digital MICs
|
||||
*
|
||||
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
static struct snd_soc_dai_driver dmic_dai = {
|
||||
.name = "dmic-hifi",
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE
|
||||
| SNDRV_PCM_FMTBIT_S24_LE
|
||||
| SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_dmic = {};
|
||||
|
||||
static int __devinit dmic_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_dmic, &dmic_dai, 1);
|
||||
}
|
||||
|
||||
static int __devexit dmic_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:dmic-codec");
|
||||
|
||||
static struct platform_driver dmic_driver = {
|
||||
.driver = {
|
||||
.name = "dmic-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = dmic_dev_probe,
|
||||
.remove = __devexit_p(dmic_dev_remove),
|
||||
};
|
||||
|
||||
static int __init dmic_init(void)
|
||||
{
|
||||
return platform_driver_register(&dmic_driver);
|
||||
}
|
||||
module_init(dmic_init);
|
||||
|
||||
static void __exit dmic_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&dmic_driver);
|
||||
}
|
||||
module_exit(dmic_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Generic DMIC driver");
|
||||
MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -22,7 +22,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#define JZ4740_REG_CODEC_1 0x0
|
||||
|
@ -266,7 +265,7 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* The only way to clear the suspend flag is to reset the codec */
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF)
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
jz4740_codec_wakeup(codec);
|
||||
|
||||
mask = JZ4740_CODEC_1_VREF_DISABLE |
|
||||
|
@ -288,23 +287,25 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
}
|
||||
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
|
||||
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
|
||||
|
||||
snd_soc_add_controls(codec, jz4740_codec_controls,
|
||||
ARRAY_SIZE(jz4740_codec_controls));
|
||||
|
||||
snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, jz4740_codec_dapm_widgets,
|
||||
ARRAY_SIZE(jz4740_codec_dapm_widgets));
|
||||
|
||||
snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
|
||||
snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes,
|
||||
ARRAY_SIZE(jz4740_codec_dapm_routes));
|
||||
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -1229,15 +1228,17 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int max98088_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, max98088_dapm_widgets,
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, max98088_dapm_widgets,
|
||||
ARRAY_SIZE(max98088_dapm_widgets));
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
snd_soc_add_controls(codec, max98088_snd_controls,
|
||||
ARRAY_SIZE(max98088_snd_controls));
|
||||
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
snd_soc_dapm_new_widgets(dapm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1622,7 +1623,7 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF)
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
max98088_sync_cache(codec);
|
||||
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
|
@ -1635,7 +1636,7 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
|
|||
codec->cache_sync = 1;
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "ssm2602.h"
|
||||
|
@ -207,10 +206,11 @@ static const struct snd_soc_dapm_route audio_conn[] = {
|
|||
|
||||
static int ssm2602_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, ssm2602_dapm_widgets,
|
||||
ARRAY_SIZE(ssm2602_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn));
|
||||
snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets,
|
||||
ARRAY_SIZE(ssm2602_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_conn, ARRAY_SIZE(audio_conn));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,
|
|||
stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
|
@ -391,11 +390,12 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
|
|||
|
||||
static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
|
||||
ARRAY_SIZE(tlv320aic23_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
|
||||
ARRAY_SIZE(tlv320aic23_dapm_widgets));
|
||||
/* set up audio path interconnects */
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
|
|||
tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "tlv320aic26.h"
|
||||
|
@ -31,7 +30,6 @@ MODULE_LICENSE("GPL");
|
|||
struct aic26 {
|
||||
struct spi_device *spi;
|
||||
struct snd_soc_codec codec;
|
||||
u16 reg_cache[AIC26_NUM_REGS]; /* shadow registers */
|
||||
int master;
|
||||
int datfm;
|
||||
int mclk;
|
||||
|
@ -355,7 +353,6 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
|
|||
*/
|
||||
static int aic26_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, err, i, reg;
|
||||
|
||||
dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
|
||||
|
@ -373,7 +370,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
|
|||
aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
|
||||
/* Fill register cache */
|
||||
for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
|
||||
for (i = 0; i < codec->driver->reg_cache_size; i++)
|
||||
aic26_reg_read(codec, i);
|
||||
|
||||
/* Register the sysfs files for debugging */
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/tlv320aic3x.h>
|
||||
|
@ -61,6 +60,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
|
|||
"DRVDD", /* ADC Analog and Output Driver Voltage */
|
||||
};
|
||||
|
||||
static LIST_HEAD(reset_list);
|
||||
|
||||
struct aic3x_priv;
|
||||
|
||||
struct aic3x_disable_nb {
|
||||
|
@ -77,6 +78,7 @@ struct aic3x_priv {
|
|||
struct aic3x_setup_data *setup;
|
||||
void *control_data;
|
||||
unsigned int sysclk;
|
||||
struct list_head list;
|
||||
int master;
|
||||
int gpio_reset;
|
||||
int power;
|
||||
|
@ -183,7 +185,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
|||
|
||||
if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
|
||||
/* find dapm widget path assoc with kcontrol */
|
||||
list_for_each_entry(path, &widget->codec->dapm_paths, list) {
|
||||
list_for_each_entry(path, &widget->dapm->card->paths, list) {
|
||||
if (path->kcontrol != kcontrol)
|
||||
continue;
|
||||
|
||||
|
@ -199,7 +201,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
|||
}
|
||||
|
||||
if (found)
|
||||
snd_soc_dapm_sync(widget->codec);
|
||||
snd_soc_dapm_sync(widget->dapm);
|
||||
}
|
||||
|
||||
ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
|
||||
|
@ -788,17 +790,19 @@ static const struct snd_soc_dapm_route intercon_3007[] = {
|
|||
static int aic3x_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
|
||||
ARRAY_SIZE(aic3x_dapm_widgets));
|
||||
|
||||
/* set up audio path interconnects */
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
if (aic3x->model == AIC3X_MODEL_3007) {
|
||||
snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets,
|
||||
snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
|
||||
ARRAY_SIZE(aic3007_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007));
|
||||
snd_soc_dapm_add_routes(dapm, intercon_3007,
|
||||
ARRAY_SIZE(intercon_3007));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1075,7 +1079,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
|
|||
* Put codec to reset and require cache sync as at least one
|
||||
* of the supplies was disabled
|
||||
*/
|
||||
if (aic3x->gpio_reset >= 0)
|
||||
if (gpio_is_valid(aic3x->gpio_reset))
|
||||
gpio_set_value(aic3x->gpio_reset, 0);
|
||||
aic3x->codec->cache_sync = 1;
|
||||
}
|
||||
|
@ -1102,7 +1106,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
|
|||
if (!codec->cache_sync)
|
||||
goto out;
|
||||
|
||||
if (aic3x->gpio_reset >= 0) {
|
||||
if (gpio_is_valid(aic3x->gpio_reset)) {
|
||||
udelay(1);
|
||||
gpio_set_value(aic3x->gpio_reset, 1);
|
||||
}
|
||||
|
@ -1135,7 +1139,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY &&
|
||||
aic3x->master) {
|
||||
/* enable pll */
|
||||
reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
|
||||
|
@ -1146,7 +1150,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_STANDBY:
|
||||
if (!aic3x->power)
|
||||
aic3x_set_power(codec, 1);
|
||||
if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE &&
|
||||
aic3x->master) {
|
||||
/* disable pll */
|
||||
reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
|
||||
|
@ -1159,7 +1163,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
|
|||
aic3x_set_power(codec, 0);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1344,14 +1348,28 @@ static int aic3x_init(struct snd_soc_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x)
|
||||
{
|
||||
struct aic3x_priv *a;
|
||||
|
||||
list_for_each_entry(a, &reset_list, list) {
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
aic3x->gpio_reset == a->gpio_reset)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int aic3x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, i;
|
||||
|
||||
INIT_LIST_HEAD(&aic3x->list);
|
||||
codec->control_data = aic3x->control_data;
|
||||
aic3x->codec = codec;
|
||||
codec->idle_bias_off = 1;
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
|
||||
if (ret != 0) {
|
||||
|
@ -1359,7 +1377,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (aic3x->gpio_reset >= 0) {
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
|
||||
if (ret != 0)
|
||||
goto err_gpio;
|
||||
|
@ -1405,6 +1424,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
|
||||
|
||||
aic3x_add_widgets(codec);
|
||||
list_add(&aic3x->list, &reset_list);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1414,10 +1434,10 @@ err_notif:
|
|||
&aic3x->disable_nb[i].nb);
|
||||
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
|
||||
err_get:
|
||||
if (aic3x->gpio_reset >= 0)
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x))
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
err_gpio:
|
||||
kfree(aic3x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1447,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
|
|||
int i;
|
||||
|
||||
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
if (aic3x->gpio_reset >= 0) {
|
||||
list_del(&aic3x->list);
|
||||
if (gpio_is_valid(aic3x->gpio_reset) &&
|
||||
!aic3x_is_shared_reset(aic3x)) {
|
||||
gpio_set_value(aic3x->gpio_reset, 0);
|
||||
gpio_free(aic3x->gpio_reset);
|
||||
}
|
||||
|
@ -1523,21 +1545,6 @@ static struct i2c_driver aic3x_i2c_driver = {
|
|||
.remove = aic3x_i2c_remove,
|
||||
.id_table = aic3x_i2c_id,
|
||||
};
|
||||
|
||||
static inline void aic3x_i2c_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&aic3x_i2c_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "%s: error regsitering i2c driver, %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
static inline void aic3x_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&aic3x_i2c_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init aic3x_modinit(void)
|
||||
|
|
|
@ -36,21 +36,21 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include <sound/tlv320dac33-plat.h>
|
||||
#include "tlv320dac33.h"
|
||||
|
||||
#define DAC33_BUFFER_SIZE_BYTES 24576 /* bytes, 12288 16 bit words,
|
||||
* 6144 stereo */
|
||||
#define DAC33_BUFFER_SIZE_SAMPLES 6144
|
||||
|
||||
#define NSAMPLE_MAX 5700
|
||||
|
||||
#define MODE7_LTHR 10
|
||||
#define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10)
|
||||
/*
|
||||
* The internal FIFO is 24576 bytes long
|
||||
* It can be configured to hold 16bit or 24bit samples
|
||||
* In 16bit configuration the FIFO can hold 6144 stereo samples
|
||||
* In 24bit configuration the FIFO can hold 4096 stereo samples
|
||||
*/
|
||||
#define DAC33_FIFO_SIZE_16BIT 6144
|
||||
#define DAC33_FIFO_SIZE_24BIT 4096
|
||||
#define DAC33_MODE7_MARGIN 10 /* Safety margin for FIFO in Mode7 */
|
||||
|
||||
#define BURST_BASEFREQ_HZ 49152000
|
||||
|
||||
|
@ -100,16 +100,11 @@ struct tlv320dac33_priv {
|
|||
unsigned int refclk;
|
||||
|
||||
unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */
|
||||
unsigned int nsample_min; /* nsample should not be lower than
|
||||
* this */
|
||||
unsigned int nsample_max; /* nsample should not be higher than
|
||||
* this */
|
||||
enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */
|
||||
unsigned int fifo_size; /* Size of the FIFO in samples */
|
||||
unsigned int nsample; /* burst read amount from host */
|
||||
int mode1_latency; /* latency caused by the i2c writes in
|
||||
* us */
|
||||
int auto_fifo_config; /* Configure the FIFO based on the
|
||||
* period size */
|
||||
u8 burst_bclkdiv; /* BCLK divider value in burst mode */
|
||||
unsigned int burst_rate; /* Interface speed in Burst modes */
|
||||
|
||||
|
@ -303,7 +298,6 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
|
|||
if (unlikely(!dac33->chip_power))
|
||||
return;
|
||||
|
||||
/* 44-46: DAC Control Registers */
|
||||
/* A : DAC sample rate Fsref/1.5 */
|
||||
dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0));
|
||||
/* B : DAC src=normal, not muted */
|
||||
|
@ -316,8 +310,6 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
|
|||
clock source = internal osc (?) */
|
||||
dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
|
||||
|
||||
dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
|
||||
|
||||
/* Restore only selected registers (gains mostly) */
|
||||
dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL,
|
||||
dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL));
|
||||
|
@ -328,6 +320,10 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
|
|||
dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL));
|
||||
dac33_write(codec, DAC33_LINER_TO_RLO_VOL,
|
||||
dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL));
|
||||
|
||||
dac33_write(codec, DAC33_OUT_AMP_CTRL,
|
||||
dac33_read_reg_cache(codec, DAC33_OUT_AMP_CTRL));
|
||||
|
||||
}
|
||||
|
||||
static inline int dac33_read_id(struct snd_soc_codec *codec)
|
||||
|
@ -357,6 +353,21 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
|
|||
dac33_write(codec, DAC33_PWR_CTRL, reg);
|
||||
}
|
||||
|
||||
static inline void dac33_disable_digital(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
/* Stop the DAI clock */
|
||||
reg = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
|
||||
reg &= ~DAC33_BCLKON;
|
||||
dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg);
|
||||
|
||||
/* Power down the Oscillator, and DACs */
|
||||
reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
|
||||
reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
|
||||
dac33_write(codec, DAC33_PWR_CTRL, reg);
|
||||
}
|
||||
|
||||
static int dac33_hard_power(struct snd_soc_codec *codec, int power)
|
||||
{
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
|
@ -405,7 +416,7 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int playback_event(struct snd_soc_dapm_widget *w,
|
||||
static int dac33_playback_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec);
|
||||
|
@ -417,77 +428,13 @@ static int playback_event(struct snd_soc_dapm_widget *w,
|
|||
dac33_prepare_chip(dac33->substream);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
dac33_disable_digital(w->codec);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dac33_get_nsample(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = dac33->nsample;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dac33_set_nsample(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
if (dac33->nsample == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < dac33->nsample_min ||
|
||||
ucontrol->value.integer.value[0] > dac33->nsample_max) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
dac33->nsample = ucontrol->value.integer.value[0];
|
||||
/* Re calculate the burst time */
|
||||
dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate,
|
||||
dac33->nsample);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dac33_get_uthr(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = dac33->uthr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dac33_set_uthr(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
if (dac33->substream)
|
||||
return -EBUSY;
|
||||
|
||||
if (dac33->uthr == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < (MODE7_LTHR + 10) ||
|
||||
ucontrol->value.integer.value[0] > MODE7_UTHR)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
dac33->uthr = ucontrol->value.integer.value[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -572,13 +519,6 @@ static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
|
|||
dac33_get_fifo_mode, dac33_set_fifo_mode),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = {
|
||||
SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
|
||||
dac33_get_nsample, dac33_set_nsample),
|
||||
SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0,
|
||||
dac33_get_uthr, dac33_set_uthr),
|
||||
};
|
||||
|
||||
/* Analog bypass */
|
||||
static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
|
||||
SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1);
|
||||
|
@ -586,6 +526,25 @@ static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
|
|||
static const struct snd_kcontrol_new dac33_dapm_abypassr_control =
|
||||
SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1);
|
||||
|
||||
/* LOP L/R invert selection */
|
||||
static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"};
|
||||
|
||||
static const struct soc_enum dac33_left_lom_enum =
|
||||
SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3,
|
||||
ARRAY_SIZE(dac33_lr_lom_texts),
|
||||
dac33_lr_lom_texts);
|
||||
|
||||
static const struct snd_kcontrol_new dac33_dapm_left_lom_control =
|
||||
SOC_DAPM_ENUM("Route", dac33_left_lom_enum);
|
||||
|
||||
static const struct soc_enum dac33_right_lom_enum =
|
||||
SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2,
|
||||
ARRAY_SIZE(dac33_lr_lom_texts),
|
||||
dac33_lr_lom_texts);
|
||||
|
||||
static const struct snd_kcontrol_new dac33_dapm_right_lom_control =
|
||||
SOC_DAPM_ENUM("Route", dac33_right_lom_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("LEFT_LO"),
|
||||
SND_SOC_DAPM_OUTPUT("RIGHT_LO"),
|
||||
|
@ -593,8 +552,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_INPUT("LINEL"),
|
||||
SND_SOC_DAPM_INPUT("LINER"),
|
||||
|
||||
SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0),
|
||||
SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0),
|
||||
SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0),
|
||||
|
||||
/* Analog bypass */
|
||||
SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0,
|
||||
|
@ -602,12 +561,30 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0,
|
||||
&dac33_dapm_abypassr_control),
|
||||
|
||||
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power",
|
||||
SND_SOC_DAPM_MUX("Left LOM Inverted From", SND_SOC_NOPM, 0, 0,
|
||||
&dac33_dapm_left_lom_control),
|
||||
SND_SOC_DAPM_MUX("Right LOM Inverted From", SND_SOC_NOPM, 0, 0,
|
||||
&dac33_dapm_right_lom_control),
|
||||
/*
|
||||
* For DAPM path, when only the anlog bypass path is enabled, and the
|
||||
* LOP inverted from the corresponding DAC side.
|
||||
* This is needed, so we can attach the DAC power supply in this case.
|
||||
*/
|
||||
SND_SOC_DAPM_PGA("Left Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Right Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier",
|
||||
DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
|
||||
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power",
|
||||
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier",
|
||||
DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
|
||||
|
||||
SND_SOC_DAPM_PRE("Prepare Playback", playback_event),
|
||||
SND_SOC_DAPM_SUPPLY("Left DAC Power",
|
||||
DAC33_LDAC_PWR_CTRL, 2, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("Right DAC Power",
|
||||
DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event),
|
||||
SND_SOC_DAPM_POST("Post Playback", dac33_playback_event),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map[] = {
|
||||
|
@ -615,24 +592,39 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
{"Analog Left Bypass", "Switch", "LINEL"},
|
||||
{"Analog Right Bypass", "Switch", "LINER"},
|
||||
|
||||
{"Output Left Amp Power", NULL, "DACL"},
|
||||
{"Output Right Amp Power", NULL, "DACR"},
|
||||
{"Output Left Amplifier", NULL, "DACL"},
|
||||
{"Output Right Amplifier", NULL, "DACR"},
|
||||
|
||||
{"Output Left Amp Power", NULL, "Analog Left Bypass"},
|
||||
{"Output Right Amp Power", NULL, "Analog Right Bypass"},
|
||||
{"Left Bypass PGA", NULL, "Analog Left Bypass"},
|
||||
{"Right Bypass PGA", NULL, "Analog Right Bypass"},
|
||||
|
||||
{"Left LOM Inverted From", "DAC", "Left Bypass PGA"},
|
||||
{"Right LOM Inverted From", "DAC", "Right Bypass PGA"},
|
||||
{"Left LOM Inverted From", "LOP", "Analog Left Bypass"},
|
||||
{"Right LOM Inverted From", "LOP", "Analog Right Bypass"},
|
||||
|
||||
{"Output Left Amplifier", NULL, "Left LOM Inverted From"},
|
||||
{"Output Right Amplifier", NULL, "Right LOM Inverted From"},
|
||||
|
||||
{"DACL", NULL, "Left DAC Power"},
|
||||
{"DACR", NULL, "Right DAC Power"},
|
||||
|
||||
{"Left Bypass PGA", NULL, "Left DAC Power"},
|
||||
{"Right Bypass PGA", NULL, "Right DAC Power"},
|
||||
|
||||
/* output */
|
||||
{"LEFT_LO", NULL, "Output Left Amp Power"},
|
||||
{"RIGHT_LO", NULL, "Output Right Amp Power"},
|
||||
{"LEFT_LO", NULL, "Output Left Amplifier"},
|
||||
{"RIGHT_LO", NULL, "Output Right Amplifier"},
|
||||
};
|
||||
|
||||
static int dac33_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, dac33_dapm_widgets,
|
||||
ARRAY_SIZE(dac33_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets,
|
||||
ARRAY_SIZE(dac33_dapm_widgets));
|
||||
/* set up audio path interconnects */
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -640,16 +632,18 @@ static int dac33_add_widgets(struct snd_soc_codec *codec)
|
|||
static int dac33_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
dac33_soft_power(codec, 1);
|
||||
if (!dac33->substream)
|
||||
dac33_soft_power(codec, 1);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Coming from OFF, switch on the codec */
|
||||
ret = dac33_hard_power(codec, 1);
|
||||
if (ret != 0)
|
||||
|
@ -660,14 +654,14 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* Do not power off, when the codec is already off */
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF)
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
return 0;
|
||||
ret = dac33_hard_power(codec, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -705,7 +699,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
|
|||
spin_unlock_irq(&dac33->lock);
|
||||
|
||||
dac33_write16(codec, DAC33_PREFILL_MSB,
|
||||
DAC33_THRREG(MODE7_LTHR));
|
||||
DAC33_THRREG(DAC33_MODE7_MARGIN));
|
||||
|
||||
/* Enable Upper Threshold IRQ */
|
||||
dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MUT);
|
||||
|
@ -815,6 +809,8 @@ static int dac33_startup(struct snd_pcm_substream *substream,
|
|||
/* Stream started, save the substream pointer */
|
||||
dac33->substream = substream;
|
||||
|
||||
snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -826,18 +822,17 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
|
|||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
dac33->substream = NULL;
|
||||
|
||||
/* Reset the nSample restrictions */
|
||||
dac33->nsample_min = 0;
|
||||
dac33->nsample_max = NSAMPLE_MAX;
|
||||
}
|
||||
|
||||
#define CALC_BURST_RATE(bclkdiv, bclk_per_sample) \
|
||||
(BURST_BASEFREQ_HZ / bclkdiv / bclk_per_sample)
|
||||
static int dac33_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* Check parameters for validity */
|
||||
switch (params_rate(params)) {
|
||||
|
@ -852,6 +847,12 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
dac33->fifo_size = DAC33_FIFO_SIZE_16BIT;
|
||||
dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
dac33->fifo_size = DAC33_FIFO_SIZE_24BIT;
|
||||
dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64);
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "unsupported format %d\n",
|
||||
|
@ -906,6 +907,9 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
|
|||
aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16);
|
||||
fifoctrl_a |= DAC33_WIDTH;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
aictrl_a |= (DAC33_NCYCL_32 | DAC33_WLEN_24);
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "unsupported format %d\n",
|
||||
substream->runtime->format);
|
||||
|
@ -1040,7 +1044,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
|
|||
dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C,
|
||||
dac33->burst_bclkdiv);
|
||||
else
|
||||
dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32);
|
||||
if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE)
|
||||
dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32);
|
||||
else
|
||||
dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 16);
|
||||
|
||||
switch (dac33->fifo_mode) {
|
||||
case DAC33_FIFO_MODE1:
|
||||
|
@ -1053,7 +1060,8 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
|
|||
* at the bottom, and also at the top of the FIFO
|
||||
*/
|
||||
dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr));
|
||||
dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR));
|
||||
dac33_write16(codec, DAC33_LTHR_MSB,
|
||||
DAC33_THRREG(DAC33_MODE7_MARGIN));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1082,42 +1090,21 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
|
|||
/* Number of samples under i2c latency */
|
||||
dac33->alarm_threshold = US_TO_SAMPLES(rate,
|
||||
dac33->mode1_latency);
|
||||
nsample_limit = DAC33_BUFFER_SIZE_SAMPLES -
|
||||
dac33->alarm_threshold;
|
||||
nsample_limit = dac33->fifo_size - dac33->alarm_threshold;
|
||||
|
||||
if (dac33->auto_fifo_config) {
|
||||
if (period_size <= dac33->alarm_threshold)
|
||||
/*
|
||||
* Configure nSamaple to number of periods,
|
||||
* which covers the latency requironment.
|
||||
*/
|
||||
dac33->nsample = period_size *
|
||||
((dac33->alarm_threshold / period_size) +
|
||||
(dac33->alarm_threshold % period_size ?
|
||||
1 : 0));
|
||||
else if (period_size > nsample_limit)
|
||||
dac33->nsample = nsample_limit;
|
||||
else
|
||||
dac33->nsample = period_size;
|
||||
} else {
|
||||
/* nSample time shall not be shorter than i2c latency */
|
||||
dac33->nsample_min = dac33->alarm_threshold;
|
||||
if (period_size <= dac33->alarm_threshold)
|
||||
/*
|
||||
* nSample should not be bigger than alsa buffer minus
|
||||
* size of one period to avoid overruns
|
||||
* Configure nSamaple to number of periods,
|
||||
* which covers the latency requironment.
|
||||
*/
|
||||
dac33->nsample_max = substream->runtime->buffer_size -
|
||||
period_size;
|
||||
|
||||
if (dac33->nsample_max > nsample_limit)
|
||||
dac33->nsample_max = nsample_limit;
|
||||
|
||||
/* Correct the nSample if it is outside of the ranges */
|
||||
if (dac33->nsample < dac33->nsample_min)
|
||||
dac33->nsample = dac33->nsample_min;
|
||||
if (dac33->nsample > dac33->nsample_max)
|
||||
dac33->nsample = dac33->nsample_max;
|
||||
}
|
||||
dac33->nsample = period_size *
|
||||
((dac33->alarm_threshold / period_size) +
|
||||
(dac33->alarm_threshold % period_size ?
|
||||
1 : 0));
|
||||
else if (period_size > nsample_limit)
|
||||
dac33->nsample = nsample_limit;
|
||||
else
|
||||
dac33->nsample = period_size;
|
||||
|
||||
dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate,
|
||||
dac33->nsample);
|
||||
|
@ -1125,19 +1112,16 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
|
|||
dac33->t_stamp2 = 0;
|
||||
break;
|
||||
case DAC33_FIFO_MODE7:
|
||||
if (dac33->auto_fifo_config) {
|
||||
dac33->uthr = UTHR_FROM_PERIOD_SIZE(
|
||||
period_size,
|
||||
rate,
|
||||
dac33->burst_rate) + 9;
|
||||
if (dac33->uthr > MODE7_UTHR)
|
||||
dac33->uthr = MODE7_UTHR;
|
||||
if (dac33->uthr < (MODE7_LTHR + 10))
|
||||
dac33->uthr = (MODE7_LTHR + 10);
|
||||
}
|
||||
dac33->uthr = UTHR_FROM_PERIOD_SIZE(period_size, rate,
|
||||
dac33->burst_rate) + 9;
|
||||
if (dac33->uthr > (dac33->fifo_size - DAC33_MODE7_MARGIN))
|
||||
dac33->uthr = dac33->fifo_size - DAC33_MODE7_MARGIN;
|
||||
if (dac33->uthr < (DAC33_MODE7_MARGIN + 10))
|
||||
dac33->uthr = (DAC33_MODE7_MARGIN + 10);
|
||||
|
||||
dac33->mode7_us_to_lthr =
|
||||
SAMPLES_TO_US(substream->runtime->rate,
|
||||
dac33->uthr - MODE7_LTHR + 1);
|
||||
dac33->uthr - DAC33_MODE7_MARGIN + 1);
|
||||
dac33->t_stamp1 = 0;
|
||||
break;
|
||||
default:
|
||||
|
@ -1255,8 +1239,8 @@ static snd_pcm_sframes_t dac33_dai_delay(
|
|||
samples += (samples_in - samples_out);
|
||||
|
||||
if (likely(samples > 0))
|
||||
delay = samples > DAC33_BUFFER_SIZE_SAMPLES ?
|
||||
DAC33_BUFFER_SIZE_SAMPLES : samples;
|
||||
delay = samples > dac33->fifo_size ?
|
||||
dac33->fifo_size : samples;
|
||||
else
|
||||
delay = 0;
|
||||
}
|
||||
|
@ -1308,7 +1292,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
|
|||
samples_in = US_TO_SAMPLES(
|
||||
dac33->burst_rate,
|
||||
time_delta);
|
||||
delay = MODE7_LTHR + samples_in - samples_out;
|
||||
delay = DAC33_MODE7_MARGIN + samples_in - samples_out;
|
||||
|
||||
if (unlikely(delay > uthr))
|
||||
delay = uthr;
|
||||
|
@ -1415,7 +1399,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
|
|||
|
||||
codec->control_data = dac33->control_data;
|
||||
codec->hw_write = (hw_write_t) i2c_master_send;
|
||||
codec->idle_bias_off = 1;
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
dac33->codec = codec;
|
||||
|
||||
/* Read the tlv320dac33 ID registers */
|
||||
|
@ -1459,14 +1443,10 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_add_controls(codec, dac33_snd_controls,
|
||||
ARRAY_SIZE(dac33_snd_controls));
|
||||
/* Only add the FIFO controls, if we have valid IRQ number */
|
||||
if (dac33->irq >= 0) {
|
||||
if (dac33->irq >= 0)
|
||||
snd_soc_add_controls(codec, dac33_mode_snd_controls,
|
||||
ARRAY_SIZE(dac33_mode_snd_controls));
|
||||
/* FIFO usage controls only, if autoio config is not selected */
|
||||
if (!dac33->auto_fifo_config)
|
||||
snd_soc_add_controls(codec, dac33_fifo_snd_controls,
|
||||
ARRAY_SIZE(dac33_fifo_snd_controls));
|
||||
}
|
||||
|
||||
dac33_add_widgets(codec);
|
||||
|
||||
err_power:
|
||||
|
@ -1515,7 +1495,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
|
|||
|
||||
#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000)
|
||||
#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
|
||||
#define DAC33_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_ops dac33_dai_ops = {
|
||||
.startup = dac33_startup,
|
||||
|
@ -1563,17 +1543,11 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
|
|||
|
||||
dac33->power_gpio = pdata->power_gpio;
|
||||
dac33->burst_bclkdiv = pdata->burst_bclkdiv;
|
||||
/* Pre calculate the burst rate */
|
||||
dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32;
|
||||
dac33->keep_bclk = pdata->keep_bclk;
|
||||
dac33->auto_fifo_config = pdata->auto_fifo_config;
|
||||
dac33->mode1_latency = pdata->mode1_latency;
|
||||
if (!dac33->mode1_latency)
|
||||
dac33->mode1_latency = 10000; /* 10ms */
|
||||
dac33->irq = client->irq;
|
||||
dac33->nsample = NSAMPLE_MAX;
|
||||
dac33->nsample_max = NSAMPLE_MAX;
|
||||
dac33->uthr = MODE7_UTHR;
|
||||
/* Disable FIFO use by default */
|
||||
dac33->fifo_mode = DAC33_FIFO_BYPASS;
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <sound/tpa6130a2-plat.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "tpa6130a2.h"
|
||||
|
@ -42,7 +41,7 @@ struct tpa6130a2_data {
|
|||
unsigned char regs[TPA6130A2_CACHEREGNUM];
|
||||
struct regulator *supply;
|
||||
int power_gpio;
|
||||
unsigned char power_state;
|
||||
u8 power_state:1;
|
||||
enum tpa_model id;
|
||||
};
|
||||
|
||||
|
@ -117,7 +116,7 @@ static int tpa6130a2_initialize(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tpa6130a2_power(int power)
|
||||
static int tpa6130a2_power(u8 power)
|
||||
{
|
||||
struct tpa6130a2_data *data;
|
||||
u8 val;
|
||||
|
@ -127,17 +126,19 @@ static int tpa6130a2_power(int power)
|
|||
data = i2c_get_clientdata(tpa6130a2_client);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (power && !data->power_state) {
|
||||
/* Power on */
|
||||
if (data->power_gpio >= 0)
|
||||
gpio_set_value(data->power_gpio, 1);
|
||||
if (power == data->power_state)
|
||||
goto exit;
|
||||
|
||||
if (power) {
|
||||
ret = regulator_enable(data->supply);
|
||||
if (ret != 0) {
|
||||
dev_err(&tpa6130a2_client->dev,
|
||||
"Failed to enable supply: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
/* Power on */
|
||||
if (data->power_gpio >= 0)
|
||||
gpio_set_value(data->power_gpio, 1);
|
||||
|
||||
data->power_state = 1;
|
||||
ret = tpa6130a2_initialize();
|
||||
|
@ -150,12 +151,7 @@ static int tpa6130a2_power(int power)
|
|||
data->power_state = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Clear SWS */
|
||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
||||
val &= ~TPA6130A2_SWS;
|
||||
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
|
||||
} else if (!power && data->power_state) {
|
||||
} else {
|
||||
/* set SWS */
|
||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
||||
val |= TPA6130A2_SWS;
|
||||
|
@ -300,6 +296,7 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
|
|||
/* Enable amplifier */
|
||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
||||
val |= channel;
|
||||
val &= ~TPA6130A2_SWS;
|
||||
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
|
||||
|
||||
/* Unmute channel */
|
||||
|
@ -320,72 +317,24 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
|
|||
}
|
||||
}
|
||||
|
||||
static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
if (enable) {
|
||||
ret = tpa6130a2_power(1);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
|
||||
1);
|
||||
} else {
|
||||
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
|
||||
0);
|
||||
ret = tpa6130a2_power(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM,
|
||||
0, 0, NULL, 0, tpa6130a2_left_event,
|
||||
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM,
|
||||
0, 0, NULL, 0, tpa6130a2_right_event,
|
||||
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM,
|
||||
0, 0, tpa6130a2_supply_event,
|
||||
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
|
||||
/* Outputs */
|
||||
SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
|
||||
SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map[] = {
|
||||
{"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"},
|
||||
{"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"},
|
||||
|
||||
{"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"},
|
||||
{"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
|
||||
|
||||
int tpa6130a2_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
|
@ -396,18 +345,12 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
|
|||
|
||||
data = i2c_get_clientdata(tpa6130a2_client);
|
||||
|
||||
snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
|
||||
ARRAY_SIZE(tpa6130a2_dapm_widgets));
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
if (data->id == TPA6140A2)
|
||||
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);
|
||||
|
||||
|
|
|
@ -57,5 +57,6 @@
|
|||
#define TPA6130A2_VERSION_MASK (0x0f)
|
||||
|
||||
extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
|
||||
extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
|
||||
|
||||
#endif /* __TPA6130A2_H__ */
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -233,6 +232,16 @@ static int twl4030_write(struct snd_soc_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void twl4030_wait_ms(int time)
|
||||
{
|
||||
if (time < 60) {
|
||||
time *= 1000;
|
||||
usleep_range(time, time + 500);
|
||||
} else {
|
||||
msleep(time);
|
||||
}
|
||||
}
|
||||
|
||||
static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
|
||||
{
|
||||
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
|
||||
|
@ -338,10 +347,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
|
|||
twl4030_write(codec, TWL4030_REG_ANAMICL,
|
||||
reg | TWL4030_CNCL_OFFSET_START);
|
||||
|
||||
/* wait for offset cancellation to complete */
|
||||
/*
|
||||
* Wait for offset cancellation to complete.
|
||||
* Since this takes a while, do not slam the i2c.
|
||||
* Start polling the status after ~20ms.
|
||||
*/
|
||||
msleep(20);
|
||||
do {
|
||||
/* this takes a little while, so don't slam i2c */
|
||||
udelay(2000);
|
||||
usleep_range(1000, 2000);
|
||||
twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
|
||||
TWL4030_REG_ANAMICL);
|
||||
} while ((i++ < 100) &&
|
||||
|
@ -725,9 +738,12 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
|
|||
/* Base values for ramp delay calculation: 2^19 - 2^26 */
|
||||
unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
|
||||
8388608, 16777216, 33554432, 67108864};
|
||||
unsigned int delay;
|
||||
|
||||
hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
|
||||
hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
|
||||
delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
|
||||
twl4030->sysclk) + 1;
|
||||
|
||||
/* Enable external mute control, this dramatically reduces
|
||||
* the pop-noise */
|
||||
|
@ -751,16 +767,14 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
|
|||
hs_pop |= TWL4030_RAMP_EN;
|
||||
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
|
||||
/* Wait ramp delay time + 1, so the VMID can settle */
|
||||
mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
|
||||
twl4030->sysclk) + 1);
|
||||
twl4030_wait_ms(delay);
|
||||
} else {
|
||||
/* Headset ramp-down _not_ according to
|
||||
* the TRM, but in a way that it is working */
|
||||
hs_pop &= ~TWL4030_RAMP_EN;
|
||||
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
|
||||
/* Wait ramp delay time + 1, so the VMID can settle */
|
||||
mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
|
||||
twl4030->sysclk) + 1);
|
||||
twl4030_wait_ms(delay);
|
||||
/* Bypass the reg_cache to mute the headset */
|
||||
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
|
||||
hs_gain & (~0x0f),
|
||||
|
@ -835,7 +849,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
|
|||
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
|
||||
|
||||
if (twl4030->digimic_delay)
|
||||
mdelay(twl4030->digimic_delay);
|
||||
twl4030_wait_ms(twl4030->digimic_delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1621,10 +1635,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int twl4030_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
|
||||
ARRAY_SIZE(twl4030_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets,
|
||||
ARRAY_SIZE(twl4030_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1638,14 +1653,14 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF)
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
twl4030_codec_enable(codec, 1);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
twl4030_codec_enable(codec, 0);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1709,6 +1724,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
|
||||
if (twl4030->master_substream) {
|
||||
twl4030->slave_substream = substream;
|
||||
/* The DAI has one configuration for playback and capture, so
|
||||
|
@ -1833,7 +1849,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
|
|||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
format |= TWL4030_DATA_WIDTH_16S_16W;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
format |= TWL4030_DATA_WIDTH_32S_24W;
|
||||
break;
|
||||
default:
|
||||
|
@ -2166,7 +2182,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
|
|||
}
|
||||
|
||||
#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
|
||||
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
|
||||
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
|
||||
.startup = twl4030_startup,
|
||||
|
@ -2245,7 +2261,7 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_codec_set_drvdata(codec, twl4030);
|
||||
/* Set the defaults, and power up the codec */
|
||||
twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
|
||||
codec->idle_bias_off = 1;
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
|
||||
twl4030_init_chip(codec);
|
||||
|
||||
|
@ -2257,9 +2273,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
|
|||
|
||||
static int twl4030_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* Reset registers to their chip default before leaving */
|
||||
twl4030_reset_registers(codec);
|
||||
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
kfree(twl4030);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2291,10 +2310,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
|
|||
|
||||
static int __devexit twl4030_codec_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
kfree(twl4030);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -79,6 +79,7 @@
|
|||
|
||||
/* INTMR (0x04) fields */
|
||||
|
||||
#define TWL6040_PLUGMSK 0x02
|
||||
#define TWL6040_READYMSK 0x40
|
||||
#define TWL6040_ALLINT_MSK 0x7B
|
||||
|
||||
|
@ -135,4 +136,11 @@
|
|||
#define TWL6040_HPPLL_ID 1
|
||||
#define TWL6040_LPPLL_ID 2
|
||||
|
||||
/* STATUS (0x2E) fields */
|
||||
|
||||
#define TWL6040_PLUGCOMP 0x02
|
||||
|
||||
void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
|
||||
struct snd_soc_jack *jack, int report);
|
||||
|
||||
#endif /* End of __TWL6040_H__ */
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include <sound/uda134x.h>
|
||||
|
@ -389,7 +388,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
|
|||
pd->power(0);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <sound/control.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/uda1380.h>
|
||||
|
||||
|
@ -36,7 +35,6 @@
|
|||
/* codec private data */
|
||||
struct uda1380_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
u16 reg_cache[UDA1380_CACHEREGNUM];
|
||||
unsigned int dac_clk;
|
||||
struct work_struct work;
|
||||
void *control_data;
|
||||
|
@ -414,10 +412,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int uda1380_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
|
||||
ARRAY_SIZE(uda1380_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
|
||||
ARRAY_SIZE(uda1380_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -603,7 +602,7 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
|
|||
int reg;
|
||||
struct uda1380_platform_data *pdata = codec->dev->platform_data;
|
||||
|
||||
if (codec->bias_level == level)
|
||||
if (codec->dapm.bias_level == level)
|
||||
return 0;
|
||||
|
||||
switch (level) {
|
||||
|
@ -613,7 +612,7 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
|
|||
uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (gpio_is_valid(pdata->gpio_power)) {
|
||||
gpio_set_value(pdata->gpio_power, 1);
|
||||
mdelay(1);
|
||||
|
@ -636,7 +635,7 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
|
|||
for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++)
|
||||
set_bit(reg - 0x10, &uda1380_cache_dirty);
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc-dai.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "wl1273.h"
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -705,6 +704,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
/* Called from the machine driver */
|
||||
int wm2000_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
if (!wm2000_i2c) {
|
||||
|
@ -712,12 +712,12 @@ int wm2000_add_controls(struct snd_soc_codec *codec)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_new_controls(codec, wm2000_dapm_widgets,
|
||||
ret = snd_soc_dapm_new_controls(dapm, wm2000_dapm_widgets,
|
||||
ARRAY_SIZE(wm2000_dapm_widgets));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <trace/events/asoc.h>
|
||||
|
||||
#include "wm8350.h"
|
||||
|
||||
|
@ -54,6 +54,7 @@ struct wm8350_output {
|
|||
|
||||
struct wm8350_jack_data {
|
||||
struct snd_soc_jack *jack;
|
||||
struct delayed_work work;
|
||||
int report;
|
||||
int short_report;
|
||||
};
|
||||
|
@ -230,8 +231,9 @@ static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
|
|||
*/
|
||||
static void wm8350_pga_work(struct work_struct *work)
|
||||
{
|
||||
struct snd_soc_codec *codec =
|
||||
container_of(work, struct snd_soc_codec, delayed_work.work);
|
||||
struct snd_soc_dapm_context *dapm =
|
||||
container_of(work, struct snd_soc_dapm_context, delayed_work.work);
|
||||
struct snd_soc_codec *codec = dapm->codec;
|
||||
struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm8350_output *out1 = &wm8350_data->out1,
|
||||
*out2 = &wm8350_data->out2;
|
||||
|
@ -302,8 +304,8 @@ static int pga_event(struct snd_soc_dapm_widget *w,
|
|||
out->ramp = WM8350_RAMP_UP;
|
||||
out->active = 1;
|
||||
|
||||
if (!delayed_work_pending(&codec->delayed_work))
|
||||
schedule_delayed_work(&codec->delayed_work,
|
||||
if (!delayed_work_pending(&codec->dapm.delayed_work))
|
||||
schedule_delayed_work(&codec->dapm.delayed_work,
|
||||
msecs_to_jiffies(1));
|
||||
break;
|
||||
|
||||
|
@ -311,8 +313,8 @@ static int pga_event(struct snd_soc_dapm_widget *w,
|
|||
out->ramp = WM8350_RAMP_DOWN;
|
||||
out->active = 0;
|
||||
|
||||
if (!delayed_work_pending(&codec->delayed_work))
|
||||
schedule_delayed_work(&codec->delayed_work,
|
||||
if (!delayed_work_pending(&codec->dapm.delayed_work))
|
||||
schedule_delayed_work(&codec->dapm.delayed_work,
|
||||
msecs_to_jiffies(1));
|
||||
break;
|
||||
}
|
||||
|
@ -786,9 +788,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8350_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(codec,
|
||||
ret = snd_soc_dapm_new_controls(dapm,
|
||||
wm8350_dapm_widgets,
|
||||
ARRAY_SIZE(wm8350_dapm_widgets));
|
||||
if (ret != 0) {
|
||||
|
@ -797,7 +800,7 @@ static int wm8350_add_widgets(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
/* set up audio paths */
|
||||
ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "DAPM route register failed\n");
|
||||
return ret;
|
||||
|
@ -1184,7 +1187,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies),
|
||||
priv->supplies);
|
||||
if (ret != 0)
|
||||
|
@ -1317,7 +1320,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
|
|||
priv->supplies);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1334,37 +1337,13 @@ static int wm8350_resume(struct snd_soc_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
|
||||
static void wm8350_hp_work(struct wm8350_data *priv,
|
||||
struct wm8350_jack_data *jack,
|
||||
u16 mask)
|
||||
{
|
||||
struct wm8350_data *priv = data;
|
||||
struct wm8350 *wm8350 = priv->codec.control_data;
|
||||
u16 reg;
|
||||
int report;
|
||||
int mask;
|
||||
struct wm8350_jack_data *jack = NULL;
|
||||
|
||||
switch (irq - wm8350->irq_base) {
|
||||
case WM8350_IRQ_CODEC_JCK_DET_L:
|
||||
jack = &priv->hpl;
|
||||
mask = WM8350_JACK_L_LVL;
|
||||
break;
|
||||
|
||||
case WM8350_IRQ_CODEC_JCK_DET_R:
|
||||
jack = &priv->hpr;
|
||||
mask = WM8350_JACK_R_LVL;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (!jack->jack) {
|
||||
dev_warn(wm8350->dev, "Jack interrupt called with no jack\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Debounce */
|
||||
msleep(200);
|
||||
|
||||
reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
|
||||
if (reg & mask)
|
||||
|
@ -1374,6 +1353,54 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
|
|||
|
||||
snd_soc_jack_report(jack->jack, report, jack->report);
|
||||
|
||||
}
|
||||
|
||||
static void wm8350_hpl_work(struct work_struct *work)
|
||||
{
|
||||
struct wm8350_data *priv =
|
||||
container_of(work, struct wm8350_data, hpl.work.work);
|
||||
|
||||
wm8350_hp_work(priv, &priv->hpl, WM8350_JACK_L_LVL);
|
||||
}
|
||||
|
||||
static void wm8350_hpr_work(struct work_struct *work)
|
||||
{
|
||||
struct wm8350_data *priv =
|
||||
container_of(work, struct wm8350_data, hpr.work.work);
|
||||
|
||||
wm8350_hp_work(priv, &priv->hpr, WM8350_JACK_R_LVL);
|
||||
}
|
||||
|
||||
static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
|
||||
{
|
||||
struct wm8350_data *priv = data;
|
||||
struct wm8350 *wm8350 = priv->codec.control_data;
|
||||
struct wm8350_jack_data *jack = NULL;
|
||||
|
||||
switch (irq - wm8350->irq_base) {
|
||||
case WM8350_IRQ_CODEC_JCK_DET_L:
|
||||
#ifndef CONFIG_SND_SOC_WM8350_MODULE
|
||||
trace_snd_soc_jack_irq("WM8350 HPL");
|
||||
#endif
|
||||
jack = &priv->hpl;
|
||||
break;
|
||||
|
||||
case WM8350_IRQ_CODEC_JCK_DET_R:
|
||||
#ifndef CONFIG_SND_SOC_WM8350_MODULE
|
||||
trace_snd_soc_jack_irq("WM8350 HPR");
|
||||
#endif
|
||||
jack = &priv->hpr;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (device_may_wakeup(wm8350->dev))
|
||||
pm_wakeup_event(wm8350->dev, 250);
|
||||
|
||||
schedule_delayed_work(&jack->work, 200);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -1436,6 +1463,10 @@ static irqreturn_t wm8350_mic_handler(int irq, void *data)
|
|||
u16 reg;
|
||||
int report = 0;
|
||||
|
||||
#ifndef CONFIG_SND_SOC_WM8350_MODULE
|
||||
trace_snd_soc_jack_irq("WM8350 mic");
|
||||
#endif
|
||||
|
||||
reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
|
||||
if (reg & WM8350_JACK_MICSCD_LVL)
|
||||
report |= priv->mic.short_report;
|
||||
|
@ -1550,7 +1581,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
|
|||
/* Put the codec into reset if it wasn't already */
|
||||
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
|
||||
|
||||
INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
|
||||
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work);
|
||||
INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work);
|
||||
INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work);
|
||||
|
||||
/* Enable the codec */
|
||||
wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
|
||||
|
@ -1640,9 +1673,12 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)
|
|||
priv->hpr.jack = NULL;
|
||||
priv->mic.jack = NULL;
|
||||
|
||||
cancel_delayed_work_sync(&priv->hpl.work);
|
||||
cancel_delayed_work_sync(&priv->hpr.work);
|
||||
|
||||
/* if there was any work waiting then we run it now and
|
||||
* wait for its completion */
|
||||
flush_delayed_work_sync(&codec->delayed_work);
|
||||
flush_delayed_work_sync(&codec->dapm.delayed_work);
|
||||
|
||||
wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -911,10 +910,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8400_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8400_dapm_widgets,
|
||||
ARRAY_SIZE(wm8400_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, wm8400_dapm_widgets,
|
||||
ARRAY_SIZE(wm8400_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(power),
|
||||
&power[0]);
|
||||
if (ret != 0) {
|
||||
|
@ -1306,7 +1306,7 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
}
|
||||
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "wm8510.h"
|
||||
|
@ -216,10 +215,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8510_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8510_dapm_widgets,
|
||||
ARRAY_SIZE(wm8510_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, wm8510_dapm_widgets,
|
||||
ARRAY_SIZE(wm8510_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_STANDBY:
|
||||
power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
|
||||
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Initial cap charge at VMID 5k */
|
||||
snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
|
||||
mdelay(100);
|
||||
|
@ -495,7 +495,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
}
|
||||
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -109,10 +108,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int wm8523_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets,
|
||||
ARRAY_SIZE(wm8523_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets,
|
||||
ARRAY_SIZE(wm8523_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
|
||||
wm8523->supplies);
|
||||
if (ret != 0) {
|
||||
|
@ -366,7 +366,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
|
|||
wm8523->supplies);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/div64.h>
|
||||
|
@ -191,7 +190,6 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
|
|||
struct wm8580_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
|
||||
u16 reg_cache[WM8580_MAX_REGISTER + 1];
|
||||
struct pll_state a;
|
||||
struct pll_state b;
|
||||
int sysclk[2];
|
||||
|
@ -302,10 +300,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8580_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets,
|
||||
ARRAY_SIZE(wm8580_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets,
|
||||
ARRAY_SIZE(wm8580_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -507,13 +506,13 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
/* Look up the SYSCLK ratio; accept only exact matches */
|
||||
ratio = wm8580->sysclk[dai->id] / params_rate(params);
|
||||
ratio = wm8580->sysclk[dai->driver->id] / params_rate(params);
|
||||
for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
|
||||
if (ratio == wm8580_sysclk_ratios[i])
|
||||
break;
|
||||
if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
|
||||
dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
|
||||
wm8580->sysclk[dai->id], params_rate(params));
|
||||
wm8580->sysclk[dai->driver->id], params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
paifa |= i;
|
||||
|
@ -716,7 +715,7 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
|||
|
||||
switch (clk_id) {
|
||||
case WM8580_CLKSRC_ADCMCLK:
|
||||
if (dai->id != WM8580_DAI_PAIFTX)
|
||||
if (dai->driver->id != WM8580_DAI_PAIFTX)
|
||||
return -EINVAL;
|
||||
sel = 0 << sel_shift;
|
||||
break;
|
||||
|
@ -735,7 +734,7 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
|||
}
|
||||
|
||||
/* We really should validate PLL settings but not yet */
|
||||
wm8580->sysclk[dai->id] = freq;
|
||||
wm8580->sysclk[dai->driver->id] = freq;
|
||||
|
||||
return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
|
||||
}
|
||||
|
@ -767,7 +766,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
|
|||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Power up and get individual control of the DACs */
|
||||
reg = snd_soc_read(codec, WM8580_PWRDN1);
|
||||
reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
|
||||
|
@ -785,7 +784,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -905,7 +904,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
|
|||
.set_bias_level = wm8580_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(wm8580_reg),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = &wm8580_reg,
|
||||
.reg_cache_default = wm8580_reg,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
|
@ -34,7 +33,6 @@
|
|||
/* codec private data */
|
||||
struct wm8711_priv {
|
||||
enum snd_soc_control_type bus_type;
|
||||
u16 reg_cache[WM8711_CACHEREGNUM];
|
||||
unsigned int sysclk;
|
||||
};
|
||||
|
||||
|
@ -93,10 +91,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int wm8711_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8711_dapm_widgets,
|
||||
ARRAY_SIZE(wm8711_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, wm8711_dapm_widgets,
|
||||
ARRAY_SIZE(wm8711_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -318,7 +317,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, WM8711_PWR, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -73,10 +72,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int wm8728_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets,
|
||||
ARRAY_SIZE(wm8728_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, wm8728_dapm_widgets,
|
||||
ARRAY_SIZE(wm8728_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_ON:
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Power everything up... */
|
||||
reg = snd_soc_read(codec, WM8728_DACCTL);
|
||||
snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
|
||||
|
@ -197,7 +197,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -44,9 +43,10 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
|
|||
struct wm8731_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
|
||||
u16 reg_cache[WM8731_CACHEREGNUM];
|
||||
unsigned int sysclk;
|
||||
int sysclk_type;
|
||||
int playback_fs;
|
||||
bool deemph;
|
||||
};
|
||||
|
||||
|
||||
|
@ -65,16 +65,79 @@ static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
|
|||
#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
|
||||
|
||||
static const char *wm8731_input_select[] = {"Line In", "Mic"};
|
||||
static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
|
||||
|
||||
static const struct soc_enum wm8731_enum[] = {
|
||||
SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
|
||||
SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
|
||||
};
|
||||
static const struct soc_enum wm8731_insel_enum =
|
||||
SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select);
|
||||
|
||||
static int wm8731_deemph[] = { 0, 32000, 44100, 48000 };
|
||||
|
||||
static int wm8731_set_deemph(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
|
||||
int val, i, best;
|
||||
|
||||
/* If we're using deemphasis select the nearest available sample
|
||||
* rate.
|
||||
*/
|
||||
if (wm8731->deemph) {
|
||||
best = 1;
|
||||
for (i = 2; i < ARRAY_SIZE(wm8731_deemph); i++) {
|
||||
if (abs(wm8731_deemph[i] - wm8731->playback_fs) <
|
||||
abs(wm8731_deemph[best] - wm8731->playback_fs))
|
||||
best = i;
|
||||
}
|
||||
|
||||
val = best << 1;
|
||||
} else {
|
||||
best = 0;
|
||||
val = 0;
|
||||
}
|
||||
|
||||
dev_dbg(codec->dev, "Set deemphasis %d (%dHz)\n",
|
||||
best, wm8731_deemph[best]);
|
||||
|
||||
return snd_soc_update_bits(codec, WM8731_APDIGI, 0x6, val);
|
||||
}
|
||||
|
||||
static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = wm8731->deemph;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
|
||||
int deemph = ucontrol->value.enumerated.item[0];
|
||||
int ret = 0;
|
||||
|
||||
if (deemph > 1)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
if (wm8731->deemph != deemph) {
|
||||
wm8731->deemph = deemph;
|
||||
|
||||
wm8731_set_deemph(codec);
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 2000, 0);
|
||||
|
||||
static const struct snd_kcontrol_new wm8731_snd_controls[] = {
|
||||
|
||||
|
@ -87,7 +150,7 @@ SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
|
|||
in_tlv),
|
||||
SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
|
||||
|
||||
SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
|
||||
SOC_SINGLE_TLV("Mic Boost Volume", WM8731_APANA, 0, 1, 0, mic_tlv),
|
||||
SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
|
||||
|
||||
SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
|
||||
|
@ -96,7 +159,8 @@ SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
|
|||
SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
|
||||
SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
|
||||
|
||||
SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
|
||||
SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0,
|
||||
wm8731_get_deemph, wm8731_put_deemph),
|
||||
};
|
||||
|
||||
/* Output Mixer */
|
||||
|
@ -108,7 +172,7 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
|||
|
||||
/* Input mux */
|
||||
static const struct snd_kcontrol_new wm8731_input_mux_controls =
|
||||
SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
|
||||
SOC_DAPM_ENUM("Input Select", wm8731_insel_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
|
||||
|
@ -165,10 +229,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int wm8731_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
|
||||
ARRAY_SIZE(wm8731_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets,
|
||||
ARRAY_SIZE(wm8731_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -239,6 +304,8 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
|
|||
u16 srate = (coeff_div[i].sr << 2) |
|
||||
(coeff_div[i].bosr << 1) | coeff_div[i].usb;
|
||||
|
||||
wm8731->playback_fs = params_rate(params);
|
||||
|
||||
snd_soc_write(codec, WM8731_SRATE, srate);
|
||||
|
||||
/* bit size */
|
||||
|
@ -253,6 +320,8 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
|
|||
break;
|
||||
}
|
||||
|
||||
wm8731_set_deemph(codec);
|
||||
|
||||
snd_soc_write(codec, WM8731_IFACE, iface);
|
||||
return 0;
|
||||
}
|
||||
|
@ -319,7 +388,7 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_dapm_sync(codec);
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -399,7 +468,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
|
||||
wm8731->supplies);
|
||||
if (ret != 0)
|
||||
|
@ -428,7 +497,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
|
|||
wm8731->supplies);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -542,7 +611,6 @@ err_regulator_enable:
|
|||
err_regulator_get:
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
|
||||
|
||||
kfree(wm8731);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,754 @@
|
|||
/*
|
||||
* wm8737.c -- WM8737 ALSA SoC Audio driver
|
||||
*
|
||||
* 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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "wm8737.h"
|
||||
|
||||
#define WM8737_NUM_SUPPLIES 4
|
||||
static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = {
|
||||
"DCVDD",
|
||||
"DBVDD",
|
||||
"AVDD",
|
||||
"MVDD",
|
||||
};
|
||||
|
||||
/* codec private data */
|
||||
struct wm8737_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES];
|
||||
unsigned int mclk;
|
||||
};
|
||||
|
||||
static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = {
|
||||
0x00C3, /* R0 - Left PGA volume */
|
||||
0x00C3, /* R1 - Right PGA volume */
|
||||
0x0007, /* R2 - AUDIO path L */
|
||||
0x0007, /* R3 - AUDIO path R */
|
||||
0x0000, /* R4 - 3D Enhance */
|
||||
0x0000, /* R5 - ADC Control */
|
||||
0x0000, /* R6 - Power Management */
|
||||
0x000A, /* R7 - Audio Format */
|
||||
0x0000, /* R8 - Clocking */
|
||||
0x000F, /* R9 - MIC Preamp Control */
|
||||
0x0003, /* R10 - Misc Bias Control */
|
||||
0x0000, /* R11 - Noise Gate */
|
||||
0x007C, /* R12 - ALC1 */
|
||||
0x0000, /* R13 - ALC2 */
|
||||
0x0032, /* R14 - ALC3 */
|
||||
};
|
||||
|
||||
static int wm8737_reset(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_write(codec, WM8737_RESET, 0);
|
||||
}
|
||||
|
||||
static const unsigned int micboost_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(4),
|
||||
0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0),
|
||||
1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
|
||||
2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0),
|
||||
3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0),
|
||||
};
|
||||
static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -1200, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(alc_target_tlv, -1800, 100, 0);
|
||||
|
||||
static const char *micbias_enum_text[] = {
|
||||
"25%",
|
||||
"50%",
|
||||
"75%",
|
||||
"100%",
|
||||
};
|
||||
|
||||
static const struct soc_enum micbias_enum =
|
||||
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text);
|
||||
|
||||
static const char *low_cutoff_text[] = {
|
||||
"Low", "High"
|
||||
};
|
||||
|
||||
static const struct soc_enum low_3d =
|
||||
SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text);
|
||||
|
||||
static const char *high_cutoff_text[] = {
|
||||
"High", "Low"
|
||||
};
|
||||
|
||||
static const struct soc_enum high_3d =
|
||||
SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text);
|
||||
|
||||
static const char *alc_fn_text[] = {
|
||||
"Disabled", "Right", "Left", "Stereo"
|
||||
};
|
||||
|
||||
static const struct soc_enum alc_fn =
|
||||
SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text);
|
||||
|
||||
static const char *alc_hold_text[] = {
|
||||
"0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms",
|
||||
"170.56ms", "341.12ms", "682.24ms", "1.364s", "2.728s", "5.458s",
|
||||
"10.916s", "21.832s", "43.691s"
|
||||
};
|
||||
|
||||
static const struct soc_enum alc_hold =
|
||||
SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text);
|
||||
|
||||
static const char *alc_atk_text[] = {
|
||||
"8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms",
|
||||
"1.075s", "2.15s", "4.3s", "8.6s"
|
||||
};
|
||||
|
||||
static const struct soc_enum alc_atk =
|
||||
SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text);
|
||||
|
||||
static const char *alc_dcy_text[] = {
|
||||
"33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s",
|
||||
"4.3s", "8.6s", "17.2s", "34.41s"
|
||||
};
|
||||
|
||||
static const struct soc_enum alc_dcy =
|
||||
SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text);
|
||||
|
||||
static const struct snd_kcontrol_new wm8737_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
|
||||
6, 3, 0, micboost_tlv),
|
||||
SOC_DOUBLE_R("Mic Boost Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
|
||||
4, 1, 0),
|
||||
SOC_DOUBLE("Mic ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
|
||||
3, 1, 0),
|
||||
|
||||
SOC_DOUBLE_R_TLV("Capture Volume", WM8737_LEFT_PGA_VOLUME,
|
||||
WM8737_RIGHT_PGA_VOLUME, 0, 255, 0, pga_tlv),
|
||||
SOC_DOUBLE("Capture ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
|
||||
2, 1, 0),
|
||||
|
||||
SOC_DOUBLE("INPUT1 DC Bias Switch", WM8737_MISC_BIAS_CONTROL, 0, 1, 1, 0),
|
||||
|
||||
SOC_ENUM("Mic PGA Bias", micbias_enum),
|
||||
SOC_SINGLE("ADC Low Power Switch", WM8737_ADC_CONTROL, 2, 1, 0),
|
||||
SOC_SINGLE("High Pass Filter Switch", WM8737_ADC_CONTROL, 0, 1, 1),
|
||||
SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0),
|
||||
|
||||
SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0),
|
||||
SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0),
|
||||
SOC_ENUM("3D Low Cut-off", low_3d),
|
||||
SOC_ENUM("3D High Cut-off", low_3d),
|
||||
SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv),
|
||||
|
||||
SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0),
|
||||
SOC_SINGLE_TLV("Noise Gate Threshold Volume", WM8737_NOISE_GATE, 2, 7, 0,
|
||||
ng_tlv),
|
||||
|
||||
SOC_ENUM("ALC", alc_fn),
|
||||
SOC_SINGLE_TLV("ALC Max Gain Volume", WM8737_ALC1, 4, 7, 0, alc_max_tlv),
|
||||
SOC_SINGLE_TLV("ALC Target Volume", WM8737_ALC1, 0, 15, 0, alc_target_tlv),
|
||||
SOC_ENUM("ALC Hold Time", alc_hold),
|
||||
SOC_SINGLE("ALC ZC Switch", WM8737_ALC2, 4, 1, 0),
|
||||
SOC_ENUM("ALC Attack Time", alc_atk),
|
||||
SOC_ENUM("ALC Decay Time", alc_dcy),
|
||||
};
|
||||
|
||||
static const char *linsel_text[] = {
|
||||
"LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC",
|
||||
};
|
||||
|
||||
static const struct soc_enum linsel_enum =
|
||||
SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text);
|
||||
|
||||
static const struct snd_kcontrol_new linsel_mux =
|
||||
SOC_DAPM_ENUM("LINSEL", linsel_enum);
|
||||
|
||||
|
||||
static const char *rinsel_text[] = {
|
||||
"RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC",
|
||||
};
|
||||
|
||||
static const struct soc_enum rinsel_enum =
|
||||
SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text);
|
||||
|
||||
static const struct snd_kcontrol_new rinsel_mux =
|
||||
SOC_DAPM_ENUM("RINSEL", rinsel_enum);
|
||||
|
||||
static const char *bypass_text[] = {
|
||||
"Direct", "Preamp"
|
||||
};
|
||||
|
||||
static const struct soc_enum lbypass_enum =
|
||||
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text);
|
||||
|
||||
static const struct snd_kcontrol_new lbypass_mux =
|
||||
SOC_DAPM_ENUM("Left Bypass", lbypass_enum);
|
||||
|
||||
|
||||
static const struct soc_enum rbypass_enum =
|
||||
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text);
|
||||
|
||||
static const struct snd_kcontrol_new rbypass_mux =
|
||||
SOC_DAPM_ENUM("Left Bypass", rbypass_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget wm8737_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("LINPUT1"),
|
||||
SND_SOC_DAPM_INPUT("LINPUT2"),
|
||||
SND_SOC_DAPM_INPUT("LINPUT3"),
|
||||
SND_SOC_DAPM_INPUT("RINPUT1"),
|
||||
SND_SOC_DAPM_INPUT("RINPUT2"),
|
||||
SND_SOC_DAPM_INPUT("RINPUT3"),
|
||||
SND_SOC_DAPM_INPUT("LACIN"),
|
||||
SND_SOC_DAPM_INPUT("RACIN"),
|
||||
|
||||
SND_SOC_DAPM_MUX("LINSEL", SND_SOC_NOPM, 0, 0, &linsel_mux),
|
||||
SND_SOC_DAPM_MUX("RINSEL", SND_SOC_NOPM, 0, 0, &rinsel_mux),
|
||||
|
||||
SND_SOC_DAPM_MUX("Left Preamp Mux", SND_SOC_NOPM, 0, 0, &lbypass_mux),
|
||||
SND_SOC_DAPM_MUX("Right Preamp Mux", SND_SOC_NOPM, 0, 0, &rbypass_mux),
|
||||
|
||||
SND_SOC_DAPM_PGA("PGAL", WM8737_POWER_MANAGEMENT, 5, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("PGAR", WM8737_POWER_MANAGEMENT, 4, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_DAC("ADCL", NULL, WM8737_POWER_MANAGEMENT, 3, 0),
|
||||
SND_SOC_DAPM_DAC("ADCR", NULL, WM8737_POWER_MANAGEMENT, 2, 0),
|
||||
|
||||
SND_SOC_DAPM_AIF_OUT("AIF", "Capture", 0, WM8737_POWER_MANAGEMENT, 6, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route intercon[] = {
|
||||
{ "LINSEL", "LINPUT1", "LINPUT1" },
|
||||
{ "LINSEL", "LINPUT2", "LINPUT2" },
|
||||
{ "LINSEL", "LINPUT3", "LINPUT3" },
|
||||
{ "LINSEL", "LINPUT1 DC", "LINPUT1" },
|
||||
|
||||
{ "RINSEL", "RINPUT1", "RINPUT1" },
|
||||
{ "RINSEL", "RINPUT2", "RINPUT2" },
|
||||
{ "RINSEL", "RINPUT3", "RINPUT3" },
|
||||
{ "RINSEL", "RINPUT1 DC", "RINPUT1" },
|
||||
|
||||
{ "Left Preamp Mux", "Preamp", "LINSEL" },
|
||||
{ "Left Preamp Mux", "Direct", "LACIN" },
|
||||
|
||||
{ "Right Preamp Mux", "Preamp", "RINSEL" },
|
||||
{ "Right Preamp Mux", "Direct", "RACIN" },
|
||||
|
||||
{ "PGAL", NULL, "Left Preamp Mux" },
|
||||
{ "PGAR", NULL, "Right Preamp Mux" },
|
||||
|
||||
{ "ADCL", NULL, "PGAL" },
|
||||
{ "ADCR", NULL, "PGAR" },
|
||||
|
||||
{ "AIF", NULL, "ADCL" },
|
||||
{ "AIF", NULL, "ADCR" },
|
||||
};
|
||||
|
||||
static int wm8737_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_new_controls(dapm, wm8737_dapm_widgets,
|
||||
ARRAY_SIZE(wm8737_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* codec mclk clock divider coefficients */
|
||||
static const struct {
|
||||
u32 mclk;
|
||||
u32 rate;
|
||||
u8 usb;
|
||||
u8 sr;
|
||||
} coeff_div[] = {
|
||||
{ 12288000, 8000, 0, 0x4 },
|
||||
{ 12288000, 12000, 0, 0x8 },
|
||||
{ 12288000, 16000, 0, 0xa },
|
||||
{ 12288000, 24000, 0, 0x1c },
|
||||
{ 12288000, 32000, 0, 0xc },
|
||||
{ 12288000, 48000, 0, 0 },
|
||||
{ 12288000, 96000, 0, 0xe },
|
||||
|
||||
{ 11289600, 8000, 0, 0x14 },
|
||||
{ 11289600, 11025, 0, 0x18 },
|
||||
{ 11289600, 22050, 0, 0x1a },
|
||||
{ 11289600, 44100, 0, 0x10 },
|
||||
{ 11289600, 88200, 0, 0x1e },
|
||||
|
||||
{ 18432000, 8000, 0, 0x5 },
|
||||
{ 18432000, 12000, 0, 0x9 },
|
||||
{ 18432000, 16000, 0, 0xb },
|
||||
{ 18432000, 24000, 0, 0x1b },
|
||||
{ 18432000, 32000, 0, 0xd },
|
||||
{ 18432000, 48000, 0, 0x1 },
|
||||
{ 18432000, 96000, 0, 0x1f },
|
||||
|
||||
{ 16934400, 8000, 0, 0x15 },
|
||||
{ 16934400, 11025, 0, 0x19 },
|
||||
{ 16934400, 22050, 0, 0x1b },
|
||||
{ 16934400, 44100, 0, 0x11 },
|
||||
{ 16934400, 88200, 0, 0x1f },
|
||||
|
||||
{ 12000000, 8000, 1, 0x4 },
|
||||
{ 12000000, 11025, 1, 0x19 },
|
||||
{ 12000000, 12000, 1, 0x8 },
|
||||
{ 12000000, 16000, 1, 0xa },
|
||||
{ 12000000, 22050, 1, 0x1b },
|
||||
{ 12000000, 24000, 1, 0x1c },
|
||||
{ 12000000, 32000, 1, 0xc },
|
||||
{ 12000000, 44100, 1, 0x11 },
|
||||
{ 12000000, 48000, 1, 0x0 },
|
||||
{ 12000000, 88200, 1, 0x1f },
|
||||
{ 12000000, 96000, 1, 0xe },
|
||||
};
|
||||
|
||||
static int wm8737_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
u16 clocking = 0;
|
||||
u16 af = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
|
||||
if (coeff_div[i].rate != params_rate(params))
|
||||
continue;
|
||||
|
||||
if (coeff_div[i].mclk == wm8737->mclk)
|
||||
break;
|
||||
|
||||
if (coeff_div[i].mclk == wm8737->mclk * 2) {
|
||||
clocking |= WM8737_CLKDIV2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(coeff_div)) {
|
||||
dev_err(codec->dev, "%dHz MCLK can't support %dHz\n",
|
||||
wm8737->mclk, params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT);
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
af |= 0x8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
af |= 0x10;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
af |= 0x18;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT, WM8737_WL_MASK, af);
|
||||
snd_soc_update_bits(codec, WM8737_CLOCKING,
|
||||
WM8737_USB_MODE | WM8737_CLKDIV2 | WM8737_SR_MASK,
|
||||
clocking);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8737_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 wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
|
||||
if (freq == coeff_div[i].mclk ||
|
||||
freq == coeff_div[i].mclk * 2) {
|
||||
wm8737->mclk = freq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err(codec->dev, "MCLK rate %dHz not supported\n", freq);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int wm8737_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
u16 af = 0;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
af |= WM8737_MS;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
af |= 0x2;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
af |= 0x1;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
af |= 0x3;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
af |= 0x13;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
af |= WM8737_LRP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT,
|
||||
WM8737_FORMAT_MASK | WM8737_LRP | WM8737_MS, af);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8737_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
/* VMID at 2*75k */
|
||||
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
|
||||
WM8737_VMIDSEL_MASK, 0);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
|
||||
wm8737->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to enable supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_cache_sync(codec);
|
||||
|
||||
/* Fast VMID ramp at 2*2.5k */
|
||||
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
|
||||
WM8737_VMIDSEL_MASK, 0x4);
|
||||
|
||||
/* Bring VMID up */
|
||||
snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT,
|
||||
WM8737_VMID_MASK |
|
||||
WM8737_VREF_MASK,
|
||||
WM8737_VMID_MASK |
|
||||
WM8737_VREF_MASK);
|
||||
|
||||
msleep(500);
|
||||
}
|
||||
|
||||
/* VMID at 2*300k */
|
||||
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
|
||||
WM8737_VMIDSEL_MASK, 2);
|
||||
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT,
|
||||
WM8737_VMID_MASK | WM8737_VREF_MASK, 0);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies),
|
||||
wm8737->supplies);
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WM8737_RATES SNDRV_PCM_RATE_8000_96000
|
||||
|
||||
#define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_ops wm8737_dai_ops = {
|
||||
.hw_params = wm8737_hw_params,
|
||||
.set_sysclk = wm8737_set_dai_sysclk,
|
||||
.set_fmt = wm8737_set_dai_fmt,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver wm8737_dai = {
|
||||
.name = "wm8737",
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2, /* Mono modes not yet supported */
|
||||
.channels_max = 2,
|
||||
.rates = WM8737_RATES,
|
||||
.formats = WM8737_FORMATS,
|
||||
},
|
||||
.ops = &wm8737_dai_ops,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8737_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
{
|
||||
wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8737_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wm8737_suspend NULL
|
||||
#define wm8737_resume NULL
|
||||
#endif
|
||||
|
||||
static int wm8737_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, i;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++)
|
||||
wm8737->supplies[i].supply = wm8737_supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies),
|
||||
wm8737->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
|
||||
wm8737->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
|
||||
goto err_get;
|
||||
}
|
||||
|
||||
ret = wm8737_reset(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to issue reset\n");
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8737_LEFT_PGA_VOLUME, WM8737_LVU,
|
||||
WM8737_LVU);
|
||||
snd_soc_update_bits(codec, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU,
|
||||
WM8737_RVU);
|
||||
|
||||
wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* Bias level configuration will have done an extra enable */
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
|
||||
|
||||
snd_soc_add_controls(codec, wm8737_snd_controls,
|
||||
ARRAY_SIZE(wm8737_snd_controls));
|
||||
wm8737_add_widgets(codec);
|
||||
|
||||
return 0;
|
||||
|
||||
err_enable:
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
|
||||
err_get:
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm8737_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_wm8737 = {
|
||||
.probe = wm8737_probe,
|
||||
.remove = wm8737_remove,
|
||||
.suspend = wm8737_suspend,
|
||||
.resume = wm8737_resume,
|
||||
.set_bias_level = wm8737_set_bias_level,
|
||||
|
||||
.reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = wm8737_reg,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct wm8737_priv *wm8737;
|
||||
int ret;
|
||||
|
||||
wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL);
|
||||
if (wm8737 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, wm8737);
|
||||
wm8737->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_wm8737, &wm8737_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(wm8737);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static __devexit int wm8737_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id wm8737_i2c_id[] = {
|
||||
{ "wm8737", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id);
|
||||
|
||||
static struct i2c_driver wm8737_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "wm8737",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wm8737_i2c_probe,
|
||||
.remove = __devexit_p(wm8737_i2c_remove),
|
||||
.id_table = wm8737_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static int __devinit wm8737_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct wm8737_priv *wm8737;
|
||||
int ret;
|
||||
|
||||
wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL);
|
||||
if (wm8737 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
wm8737->control_type = SND_SOC_SPI;
|
||||
spi_set_drvdata(spi, wm8737);
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_wm8737, &wm8737_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(wm8737);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit wm8737_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
kfree(spi_get_drvdata(spi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver wm8737_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm8737",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wm8737_spi_probe,
|
||||
.remove = __devexit_p(wm8737_spi_remove),
|
||||
};
|
||||
#endif /* CONFIG_SPI_MASTER */
|
||||
|
||||
static int __init wm8737_modinit(void)
|
||||
{
|
||||
int ret;
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
ret = i2c_add_driver(&wm8737_i2c_driver);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
ret = spi_register_driver(&wm8737_spi_driver);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR "Failed to register WM8737 SPI driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
module_init(wm8737_modinit);
|
||||
|
||||
static void __exit wm8737_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
spi_unregister_driver(&wm8737_spi_driver);
|
||||
#endif
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
i2c_del_driver(&wm8737_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(wm8737_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC WM8737 driver");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,322 @@
|
|||
#ifndef _WM8737_H
|
||||
#define _WM8737_H
|
||||
|
||||
/*
|
||||
* wm8737.c -- WM8523 ALSA SoC Audio driver
|
||||
*
|
||||
* 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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register values.
|
||||
*/
|
||||
#define WM8737_LEFT_PGA_VOLUME 0x00
|
||||
#define WM8737_RIGHT_PGA_VOLUME 0x01
|
||||
#define WM8737_AUDIO_PATH_L 0x02
|
||||
#define WM8737_AUDIO_PATH_R 0x03
|
||||
#define WM8737_3D_ENHANCE 0x04
|
||||
#define WM8737_ADC_CONTROL 0x05
|
||||
#define WM8737_POWER_MANAGEMENT 0x06
|
||||
#define WM8737_AUDIO_FORMAT 0x07
|
||||
#define WM8737_CLOCKING 0x08
|
||||
#define WM8737_MIC_PREAMP_CONTROL 0x09
|
||||
#define WM8737_MISC_BIAS_CONTROL 0x0A
|
||||
#define WM8737_NOISE_GATE 0x0B
|
||||
#define WM8737_ALC1 0x0C
|
||||
#define WM8737_ALC2 0x0D
|
||||
#define WM8737_ALC3 0x0E
|
||||
#define WM8737_RESET 0x0F
|
||||
|
||||
#define WM8737_REGISTER_COUNT 16
|
||||
#define WM8737_MAX_REGISTER 0x0F
|
||||
|
||||
/*
|
||||
* Field Definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* R0 (0x00) - Left PGA volume
|
||||
*/
|
||||
#define WM8737_LVU 0x0100 /* LVU */
|
||||
#define WM8737_LVU_MASK 0x0100 /* LVU */
|
||||
#define WM8737_LVU_SHIFT 8 /* LVU */
|
||||
#define WM8737_LVU_WIDTH 1 /* LVU */
|
||||
#define WM8737_LINVOL_MASK 0x00FF /* LINVOL - [7:0] */
|
||||
#define WM8737_LINVOL_SHIFT 0 /* LINVOL - [7:0] */
|
||||
#define WM8737_LINVOL_WIDTH 8 /* LINVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R1 (0x01) - Right PGA volume
|
||||
*/
|
||||
#define WM8737_RVU 0x0100 /* RVU */
|
||||
#define WM8737_RVU_MASK 0x0100 /* RVU */
|
||||
#define WM8737_RVU_SHIFT 8 /* RVU */
|
||||
#define WM8737_RVU_WIDTH 1 /* RVU */
|
||||
#define WM8737_RINVOL_MASK 0x00FF /* RINVOL - [7:0] */
|
||||
#define WM8737_RINVOL_SHIFT 0 /* RINVOL - [7:0] */
|
||||
#define WM8737_RINVOL_WIDTH 8 /* RINVOL - [7:0] */
|
||||
|
||||
/*
|
||||
* R2 (0x02) - AUDIO path L
|
||||
*/
|
||||
#define WM8737_LINSEL_MASK 0x0180 /* LINSEL - [8:7] */
|
||||
#define WM8737_LINSEL_SHIFT 7 /* LINSEL - [8:7] */
|
||||
#define WM8737_LINSEL_WIDTH 2 /* LINSEL - [8:7] */
|
||||
#define WM8737_LMICBOOST_MASK 0x0060 /* LMICBOOST - [6:5] */
|
||||
#define WM8737_LMICBOOST_SHIFT 5 /* LMICBOOST - [6:5] */
|
||||
#define WM8737_LMICBOOST_WIDTH 2 /* LMICBOOST - [6:5] */
|
||||
#define WM8737_LMBE 0x0010 /* LMBE */
|
||||
#define WM8737_LMBE_MASK 0x0010 /* LMBE */
|
||||
#define WM8737_LMBE_SHIFT 4 /* LMBE */
|
||||
#define WM8737_LMBE_WIDTH 1 /* LMBE */
|
||||
#define WM8737_LMZC 0x0008 /* LMZC */
|
||||
#define WM8737_LMZC_MASK 0x0008 /* LMZC */
|
||||
#define WM8737_LMZC_SHIFT 3 /* LMZC */
|
||||
#define WM8737_LMZC_WIDTH 1 /* LMZC */
|
||||
#define WM8737_LPZC 0x0004 /* LPZC */
|
||||
#define WM8737_LPZC_MASK 0x0004 /* LPZC */
|
||||
#define WM8737_LPZC_SHIFT 2 /* LPZC */
|
||||
#define WM8737_LPZC_WIDTH 1 /* LPZC */
|
||||
#define WM8737_LZCTO_MASK 0x0003 /* LZCTO - [1:0] */
|
||||
#define WM8737_LZCTO_SHIFT 0 /* LZCTO - [1:0] */
|
||||
#define WM8737_LZCTO_WIDTH 2 /* LZCTO - [1:0] */
|
||||
|
||||
/*
|
||||
* R3 (0x03) - AUDIO path R
|
||||
*/
|
||||
#define WM8737_RINSEL_MASK 0x0180 /* RINSEL - [8:7] */
|
||||
#define WM8737_RINSEL_SHIFT 7 /* RINSEL - [8:7] */
|
||||
#define WM8737_RINSEL_WIDTH 2 /* RINSEL - [8:7] */
|
||||
#define WM8737_RMICBOOST_MASK 0x0060 /* RMICBOOST - [6:5] */
|
||||
#define WM8737_RMICBOOST_SHIFT 5 /* RMICBOOST - [6:5] */
|
||||
#define WM8737_RMICBOOST_WIDTH 2 /* RMICBOOST - [6:5] */
|
||||
#define WM8737_RMBE 0x0010 /* RMBE */
|
||||
#define WM8737_RMBE_MASK 0x0010 /* RMBE */
|
||||
#define WM8737_RMBE_SHIFT 4 /* RMBE */
|
||||
#define WM8737_RMBE_WIDTH 1 /* RMBE */
|
||||
#define WM8737_RMZC 0x0008 /* RMZC */
|
||||
#define WM8737_RMZC_MASK 0x0008 /* RMZC */
|
||||
#define WM8737_RMZC_SHIFT 3 /* RMZC */
|
||||
#define WM8737_RMZC_WIDTH 1 /* RMZC */
|
||||
#define WM8737_RPZC 0x0004 /* RPZC */
|
||||
#define WM8737_RPZC_MASK 0x0004 /* RPZC */
|
||||
#define WM8737_RPZC_SHIFT 2 /* RPZC */
|
||||
#define WM8737_RPZC_WIDTH 1 /* RPZC */
|
||||
#define WM8737_RZCTO_MASK 0x0003 /* RZCTO - [1:0] */
|
||||
#define WM8737_RZCTO_SHIFT 0 /* RZCTO - [1:0] */
|
||||
#define WM8737_RZCTO_WIDTH 2 /* RZCTO - [1:0] */
|
||||
|
||||
/*
|
||||
* R4 (0x04) - 3D Enhance
|
||||
*/
|
||||
#define WM8737_DIV2 0x0080 /* DIV2 */
|
||||
#define WM8737_DIV2_MASK 0x0080 /* DIV2 */
|
||||
#define WM8737_DIV2_SHIFT 7 /* DIV2 */
|
||||
#define WM8737_DIV2_WIDTH 1 /* DIV2 */
|
||||
#define WM8737_3DLC 0x0040 /* 3DLC */
|
||||
#define WM8737_3DLC_MASK 0x0040 /* 3DLC */
|
||||
#define WM8737_3DLC_SHIFT 6 /* 3DLC */
|
||||
#define WM8737_3DLC_WIDTH 1 /* 3DLC */
|
||||
#define WM8737_3DUC 0x0020 /* 3DUC */
|
||||
#define WM8737_3DUC_MASK 0x0020 /* 3DUC */
|
||||
#define WM8737_3DUC_SHIFT 5 /* 3DUC */
|
||||
#define WM8737_3DUC_WIDTH 1 /* 3DUC */
|
||||
#define WM8737_3DDEPTH_MASK 0x001E /* 3DDEPTH - [4:1] */
|
||||
#define WM8737_3DDEPTH_SHIFT 1 /* 3DDEPTH - [4:1] */
|
||||
#define WM8737_3DDEPTH_WIDTH 4 /* 3DDEPTH - [4:1] */
|
||||
#define WM8737_3DE 0x0001 /* 3DE */
|
||||
#define WM8737_3DE_MASK 0x0001 /* 3DE */
|
||||
#define WM8737_3DE_SHIFT 0 /* 3DE */
|
||||
#define WM8737_3DE_WIDTH 1 /* 3DE */
|
||||
|
||||
/*
|
||||
* R5 (0x05) - ADC Control
|
||||
*/
|
||||
#define WM8737_MONOMIX_MASK 0x0180 /* MONOMIX - [8:7] */
|
||||
#define WM8737_MONOMIX_SHIFT 7 /* MONOMIX - [8:7] */
|
||||
#define WM8737_MONOMIX_WIDTH 2 /* MONOMIX - [8:7] */
|
||||
#define WM8737_POLARITY_MASK 0x0060 /* POLARITY - [6:5] */
|
||||
#define WM8737_POLARITY_SHIFT 5 /* POLARITY - [6:5] */
|
||||
#define WM8737_POLARITY_WIDTH 2 /* POLARITY - [6:5] */
|
||||
#define WM8737_HPOR 0x0010 /* HPOR */
|
||||
#define WM8737_HPOR_MASK 0x0010 /* HPOR */
|
||||
#define WM8737_HPOR_SHIFT 4 /* HPOR */
|
||||
#define WM8737_HPOR_WIDTH 1 /* HPOR */
|
||||
#define WM8737_LP 0x0004 /* LP */
|
||||
#define WM8737_LP_MASK 0x0004 /* LP */
|
||||
#define WM8737_LP_SHIFT 2 /* LP */
|
||||
#define WM8737_LP_WIDTH 1 /* LP */
|
||||
#define WM8737_MONOUT 0x0002 /* MONOUT */
|
||||
#define WM8737_MONOUT_MASK 0x0002 /* MONOUT */
|
||||
#define WM8737_MONOUT_SHIFT 1 /* MONOUT */
|
||||
#define WM8737_MONOUT_WIDTH 1 /* MONOUT */
|
||||
#define WM8737_ADCHPD 0x0001 /* ADCHPD */
|
||||
#define WM8737_ADCHPD_MASK 0x0001 /* ADCHPD */
|
||||
#define WM8737_ADCHPD_SHIFT 0 /* ADCHPD */
|
||||
#define WM8737_ADCHPD_WIDTH 1 /* ADCHPD */
|
||||
|
||||
/*
|
||||
* R6 (0x06) - Power Management
|
||||
*/
|
||||
#define WM8737_VMID 0x0100 /* VMID */
|
||||
#define WM8737_VMID_MASK 0x0100 /* VMID */
|
||||
#define WM8737_VMID_SHIFT 8 /* VMID */
|
||||
#define WM8737_VMID_WIDTH 1 /* VMID */
|
||||
#define WM8737_VREF 0x0080 /* VREF */
|
||||
#define WM8737_VREF_MASK 0x0080 /* VREF */
|
||||
#define WM8737_VREF_SHIFT 7 /* VREF */
|
||||
#define WM8737_VREF_WIDTH 1 /* VREF */
|
||||
#define WM8737_AI 0x0040 /* AI */
|
||||
#define WM8737_AI_MASK 0x0040 /* AI */
|
||||
#define WM8737_AI_SHIFT 6 /* AI */
|
||||
#define WM8737_AI_WIDTH 1 /* AI */
|
||||
#define WM8737_PGL 0x0020 /* PGL */
|
||||
#define WM8737_PGL_MASK 0x0020 /* PGL */
|
||||
#define WM8737_PGL_SHIFT 5 /* PGL */
|
||||
#define WM8737_PGL_WIDTH 1 /* PGL */
|
||||
#define WM8737_PGR 0x0010 /* PGR */
|
||||
#define WM8737_PGR_MASK 0x0010 /* PGR */
|
||||
#define WM8737_PGR_SHIFT 4 /* PGR */
|
||||
#define WM8737_PGR_WIDTH 1 /* PGR */
|
||||
#define WM8737_ADL 0x0008 /* ADL */
|
||||
#define WM8737_ADL_MASK 0x0008 /* ADL */
|
||||
#define WM8737_ADL_SHIFT 3 /* ADL */
|
||||
#define WM8737_ADL_WIDTH 1 /* ADL */
|
||||
#define WM8737_ADR 0x0004 /* ADR */
|
||||
#define WM8737_ADR_MASK 0x0004 /* ADR */
|
||||
#define WM8737_ADR_SHIFT 2 /* ADR */
|
||||
#define WM8737_ADR_WIDTH 1 /* ADR */
|
||||
#define WM8737_MICBIAS_MASK 0x0003 /* MICBIAS - [1:0] */
|
||||
#define WM8737_MICBIAS_SHIFT 0 /* MICBIAS - [1:0] */
|
||||
#define WM8737_MICBIAS_WIDTH 2 /* MICBIAS - [1:0] */
|
||||
|
||||
/*
|
||||
* R7 (0x07) - Audio Format
|
||||
*/
|
||||
#define WM8737_SDODIS 0x0080 /* SDODIS */
|
||||
#define WM8737_SDODIS_MASK 0x0080 /* SDODIS */
|
||||
#define WM8737_SDODIS_SHIFT 7 /* SDODIS */
|
||||
#define WM8737_SDODIS_WIDTH 1 /* SDODIS */
|
||||
#define WM8737_MS 0x0040 /* MS */
|
||||
#define WM8737_MS_MASK 0x0040 /* MS */
|
||||
#define WM8737_MS_SHIFT 6 /* MS */
|
||||
#define WM8737_MS_WIDTH 1 /* MS */
|
||||
#define WM8737_LRP 0x0010 /* LRP */
|
||||
#define WM8737_LRP_MASK 0x0010 /* LRP */
|
||||
#define WM8737_LRP_SHIFT 4 /* LRP */
|
||||
#define WM8737_LRP_WIDTH 1 /* LRP */
|
||||
#define WM8737_WL_MASK 0x000C /* WL - [3:2] */
|
||||
#define WM8737_WL_SHIFT 2 /* WL - [3:2] */
|
||||
#define WM8737_WL_WIDTH 2 /* WL - [3:2] */
|
||||
#define WM8737_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */
|
||||
#define WM8737_FORMAT_SHIFT 0 /* FORMAT - [1:0] */
|
||||
#define WM8737_FORMAT_WIDTH 2 /* FORMAT - [1:0] */
|
||||
|
||||
/*
|
||||
* R8 (0x08) - Clocking
|
||||
*/
|
||||
#define WM8737_AUTODETECT 0x0080 /* AUTODETECT */
|
||||
#define WM8737_AUTODETECT_MASK 0x0080 /* AUTODETECT */
|
||||
#define WM8737_AUTODETECT_SHIFT 7 /* AUTODETECT */
|
||||
#define WM8737_AUTODETECT_WIDTH 1 /* AUTODETECT */
|
||||
#define WM8737_CLKDIV2 0x0040 /* CLKDIV2 */
|
||||
#define WM8737_CLKDIV2_MASK 0x0040 /* CLKDIV2 */
|
||||
#define WM8737_CLKDIV2_SHIFT 6 /* CLKDIV2 */
|
||||
#define WM8737_CLKDIV2_WIDTH 1 /* CLKDIV2 */
|
||||
#define WM8737_SR_MASK 0x003E /* SR - [5:1] */
|
||||
#define WM8737_SR_SHIFT 1 /* SR - [5:1] */
|
||||
#define WM8737_SR_WIDTH 5 /* SR - [5:1] */
|
||||
#define WM8737_USB_MODE 0x0001 /* USB MODE */
|
||||
#define WM8737_USB_MODE_MASK 0x0001 /* USB MODE */
|
||||
#define WM8737_USB_MODE_SHIFT 0 /* USB MODE */
|
||||
#define WM8737_USB_MODE_WIDTH 1 /* USB MODE */
|
||||
|
||||
/*
|
||||
* R9 (0x09) - MIC Preamp Control
|
||||
*/
|
||||
#define WM8737_RBYPEN 0x0008 /* RBYPEN */
|
||||
#define WM8737_RBYPEN_MASK 0x0008 /* RBYPEN */
|
||||
#define WM8737_RBYPEN_SHIFT 3 /* RBYPEN */
|
||||
#define WM8737_RBYPEN_WIDTH 1 /* RBYPEN */
|
||||
#define WM8737_LBYPEN 0x0004 /* LBYPEN */
|
||||
#define WM8737_LBYPEN_MASK 0x0004 /* LBYPEN */
|
||||
#define WM8737_LBYPEN_SHIFT 2 /* LBYPEN */
|
||||
#define WM8737_LBYPEN_WIDTH 1 /* LBYPEN */
|
||||
#define WM8737_MBCTRL_MASK 0x0003 /* MBCTRL - [1:0] */
|
||||
#define WM8737_MBCTRL_SHIFT 0 /* MBCTRL - [1:0] */
|
||||
#define WM8737_MBCTRL_WIDTH 2 /* MBCTRL - [1:0] */
|
||||
|
||||
/*
|
||||
* R10 (0x0A) - Misc Bias Control
|
||||
*/
|
||||
#define WM8737_VMIDSEL_MASK 0x000C /* VMIDSEL - [3:2] */
|
||||
#define WM8737_VMIDSEL_SHIFT 2 /* VMIDSEL - [3:2] */
|
||||
#define WM8737_VMIDSEL_WIDTH 2 /* VMIDSEL - [3:2] */
|
||||
#define WM8737_LINPUT1_DC_BIAS_ENABLE 0x0002 /* LINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_LINPUT1_DC_BIAS_ENABLE_MASK 0x0002 /* LINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_LINPUT1_DC_BIAS_ENABLE_SHIFT 1 /* LINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_LINPUT1_DC_BIAS_ENABLE_WIDTH 1 /* LINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_RINPUT1_DC_BIAS_ENABLE 0x0001 /* RINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_RINPUT1_DC_BIAS_ENABLE_MASK 0x0001 /* RINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_RINPUT1_DC_BIAS_ENABLE_SHIFT 0 /* RINPUT1 DC BIAS ENABLE */
|
||||
#define WM8737_RINPUT1_DC_BIAS_ENABLE_WIDTH 1 /* RINPUT1 DC BIAS ENABLE */
|
||||
|
||||
/*
|
||||
* R11 (0x0B) - Noise Gate
|
||||
*/
|
||||
#define WM8737_NGTH_MASK 0x001C /* NGTH - [4:2] */
|
||||
#define WM8737_NGTH_SHIFT 2 /* NGTH - [4:2] */
|
||||
#define WM8737_NGTH_WIDTH 3 /* NGTH - [4:2] */
|
||||
#define WM8737_NGAT 0x0001 /* NGAT */
|
||||
#define WM8737_NGAT_MASK 0x0001 /* NGAT */
|
||||
#define WM8737_NGAT_SHIFT 0 /* NGAT */
|
||||
#define WM8737_NGAT_WIDTH 1 /* NGAT */
|
||||
|
||||
/*
|
||||
* R12 (0x0C) - ALC1
|
||||
*/
|
||||
#define WM8737_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
|
||||
#define WM8737_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
|
||||
#define WM8737_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
|
||||
#define WM8737_MAX_GAIN_MASK 0x0070 /* MAX GAIN - [6:4] */
|
||||
#define WM8737_MAX_GAIN_SHIFT 4 /* MAX GAIN - [6:4] */
|
||||
#define WM8737_MAX_GAIN_WIDTH 3 /* MAX GAIN - [6:4] */
|
||||
#define WM8737_ALCL_MASK 0x000F /* ALCL - [3:0] */
|
||||
#define WM8737_ALCL_SHIFT 0 /* ALCL - [3:0] */
|
||||
#define WM8737_ALCL_WIDTH 4 /* ALCL - [3:0] */
|
||||
|
||||
/*
|
||||
* R13 (0x0D) - ALC2
|
||||
*/
|
||||
#define WM8737_ALCZCE 0x0010 /* ALCZCE */
|
||||
#define WM8737_ALCZCE_MASK 0x0010 /* ALCZCE */
|
||||
#define WM8737_ALCZCE_SHIFT 4 /* ALCZCE */
|
||||
#define WM8737_ALCZCE_WIDTH 1 /* ALCZCE */
|
||||
#define WM8737_HLD_MASK 0x000F /* HLD - [3:0] */
|
||||
#define WM8737_HLD_SHIFT 0 /* HLD - [3:0] */
|
||||
#define WM8737_HLD_WIDTH 4 /* HLD - [3:0] */
|
||||
|
||||
/*
|
||||
* R14 (0x0E) - ALC3
|
||||
*/
|
||||
#define WM8737_DCY_MASK 0x00F0 /* DCY - [7:4] */
|
||||
#define WM8737_DCY_SHIFT 4 /* DCY - [7:4] */
|
||||
#define WM8737_DCY_WIDTH 4 /* DCY - [7:4] */
|
||||
#define WM8737_ATK_MASK 0x000F /* ATK - [3:0] */
|
||||
#define WM8737_ATK_SHIFT 0 /* ATK - [3:0] */
|
||||
#define WM8737_ATK_WIDTH 4 /* ATK - [3:0] */
|
||||
|
||||
/*
|
||||
* R15 (0x0F) - Reset
|
||||
*/
|
||||
#define WM8737_RESET_MASK 0x01FF /* RESET - [8:0] */
|
||||
#define WM8737_RESET_SHIFT 0 /* RESET - [8:0] */
|
||||
#define WM8737_RESET_WIDTH 9 /* RESET - [8:0] */
|
||||
|
||||
#endif
|
|
@ -24,7 +24,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
|
@ -94,10 +93,11 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
static int wm8741_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8741_dapm_widgets,
|
||||
ARRAY_SIZE(wm8741_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
|
||||
snd_soc_dapm_new_controls(dapm, wm8741_dapm_widgets,
|
||||
ARRAY_SIZE(wm8741_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
|
|||
.resume = wm8741_resume,
|
||||
.reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_default = &wm8741_reg_defaults,
|
||||
.reg_cache_default = wm8741_reg_defaults,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "wm8750.h"
|
||||
|
@ -53,7 +52,6 @@ static const u16 wm8750_reg[] = {
|
|||
struct wm8750_priv {
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
|
||||
};
|
||||
|
||||
#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
|
||||
|
@ -399,10 +397,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8750_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
|
||||
ARRAY_SIZE(wm8750_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
|
||||
ARRAY_SIZE(wm8750_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -615,7 +614,7 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
|
|||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* Set VMID to 5k */
|
||||
snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
|
||||
|
||||
|
@ -630,7 +629,7 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, WM8750_PWR1, 0x0001);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <asm/div64.h>
|
||||
|
@ -623,10 +622,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
|
||||
static int wm8753_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
|
||||
ARRAY_SIZE(wm8753_dapm_widgets));
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
|
||||
ARRAY_SIZE(wm8753_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1245,7 +1245,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
|
|||
snd_soc_write(codec, WM8753_PWR1, 0x0001);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1435,9 +1435,11 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
|
|||
|
||||
static void wm8753_work(struct work_struct *work)
|
||||
{
|
||||
struct snd_soc_codec *codec =
|
||||
container_of(work, struct snd_soc_codec, delayed_work.work);
|
||||
wm8753_set_bias_level(codec, codec->bias_level);
|
||||
struct snd_soc_dapm_context *dapm =
|
||||
container_of(work, struct snd_soc_dapm_context,
|
||||
delayed_work.work);
|
||||
struct snd_soc_codec *codec = dapm->codec;
|
||||
wm8753_set_bias_level(codec, dapm->bias_level);
|
||||
}
|
||||
|
||||
static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
|
@ -1466,10 +1468,10 @@ static int wm8753_resume(struct snd_soc_codec *codec)
|
|||
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* charge wm8753 caps */
|
||||
if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
|
||||
if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
|
||||
wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
|
||||
codec->bias_level = SND_SOC_BIAS_ON;
|
||||
schedule_delayed_work(&codec->delayed_work,
|
||||
codec->dapm.bias_level = SND_SOC_BIAS_ON;
|
||||
schedule_delayed_work(&codec->dapm.delayed_work,
|
||||
msecs_to_jiffies(caps_charge));
|
||||
}
|
||||
|
||||
|
@ -1481,7 +1483,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)
|
|||
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
|
||||
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
|
||||
if (ret < 0) {
|
||||
|
@ -1500,7 +1502,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)
|
|||
|
||||
/* charge output caps */
|
||||
wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
|
||||
schedule_delayed_work(&codec->delayed_work,
|
||||
schedule_delayed_work(&codec->dapm.delayed_work,
|
||||
msecs_to_jiffies(caps_charge));
|
||||
|
||||
/* set the update bits */
|
||||
|
@ -1525,7 +1527,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)
|
|||
/* power down chip */
|
||||
static int wm8753_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
flush_delayed_work_sync(&codec->delayed_work);
|
||||
flush_delayed_work_sync(&codec->dapm.delayed_work);
|
||||
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,749 @@
|
|||
/*
|
||||
* wm8770.c -- WM8770 ALSA SoC Audio driver
|
||||
*
|
||||
* Copyright 2010 Wolfson Microelectronics plc
|
||||
*
|
||||
* Author: Dimitris Papastamos <dp@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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "wm8770.h"
|
||||
|
||||
#define WM8770_NUM_SUPPLIES 3
|
||||
static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
|
||||
"AVDD1",
|
||||
"AVDD2",
|
||||
"DVDD"
|
||||
};
|
||||
|
||||
static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
|
||||
0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0, 0x90, 0,
|
||||
0, 0x22, 0x22, 0x3e,
|
||||
0xc, 0xc, 0x100, 0x189,
|
||||
0x189, 0x8770
|
||||
};
|
||||
|
||||
struct wm8770_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
|
||||
struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
|
||||
struct snd_soc_codec *codec;
|
||||
int sysclk;
|
||||
};
|
||||
|
||||
static int vout12supply_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
static int vout34supply_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
|
||||
/*
|
||||
* We can't use the same notifier block for more than one supply and
|
||||
* there's no way I can see to get from a callback to the caller
|
||||
* except container_of().
|
||||
*/
|
||||
#define WM8770_REGULATOR_EVENT(n) \
|
||||
static int wm8770_regulator_event_##n(struct notifier_block *nb, \
|
||||
unsigned long event, void *data) \
|
||||
{ \
|
||||
struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
|
||||
disable_nb[n]); \
|
||||
if (event & REGULATOR_EVENT_DISABLE) { \
|
||||
wm8770->codec->cache_sync = 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
WM8770_REGULATOR_EVENT(0)
|
||||
WM8770_REGULATOR_EVENT(1)
|
||||
WM8770_REGULATOR_EVENT(2)
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 100, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -12750, 50, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_alg_tlv, -12700, 100, 1);
|
||||
|
||||
static const char *dac_phase_text[][2] = {
|
||||
{ "DAC1 Normal", "DAC1 Inverted" },
|
||||
{ "DAC2 Normal", "DAC2 Inverted" },
|
||||
{ "DAC3 Normal", "DAC3 Inverted" },
|
||||
{ "DAC4 Normal", "DAC4 Inverted" },
|
||||
};
|
||||
|
||||
static const struct soc_enum dac_phase[] = {
|
||||
SOC_ENUM_DOUBLE(WM8770_DACPHASE, 0, 1, 2, dac_phase_text[0]),
|
||||
SOC_ENUM_DOUBLE(WM8770_DACPHASE, 2, 3, 2, dac_phase_text[1]),
|
||||
SOC_ENUM_DOUBLE(WM8770_DACPHASE, 4, 5, 2, dac_phase_text[2]),
|
||||
SOC_ENUM_DOUBLE(WM8770_DACPHASE, 6, 7, 2, dac_phase_text[3]),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8770_snd_controls[] = {
|
||||
/* global DAC playback controls */
|
||||
SOC_SINGLE_TLV("DAC Playback Volume", WM8770_MSDIGVOL, 0, 255, 0,
|
||||
dac_dig_tlv),
|
||||
SOC_SINGLE("DAC Playback Switch", WM8770_DACMUTE, 4, 1, 1),
|
||||
SOC_SINGLE("DAC Playback ZC Switch", WM8770_DACCTRL1, 0, 1, 0),
|
||||
|
||||
/* global VOUT playback controls */
|
||||
SOC_SINGLE_TLV("VOUT Playback Volume", WM8770_MSALGVOL, 0, 127, 0,
|
||||
dac_alg_tlv),
|
||||
SOC_SINGLE("VOUT Playback ZC Switch", WM8770_MSALGVOL, 7, 1, 0),
|
||||
|
||||
/* VOUT1/2/3/4 specific controls */
|
||||
SOC_DOUBLE_R_TLV("VOUT1 Playback Volume", WM8770_VOUT1LVOL,
|
||||
WM8770_VOUT1RVOL, 0, 127, 0, dac_alg_tlv),
|
||||
SOC_DOUBLE_R("VOUT1 Playback ZC Switch", WM8770_VOUT1LVOL,
|
||||
WM8770_VOUT1RVOL, 7, 1, 0),
|
||||
SOC_DOUBLE_R_TLV("VOUT2 Playback Volume", WM8770_VOUT2LVOL,
|
||||
WM8770_VOUT2RVOL, 0, 127, 0, dac_alg_tlv),
|
||||
SOC_DOUBLE_R("VOUT2 Playback ZC Switch", WM8770_VOUT2LVOL,
|
||||
WM8770_VOUT2RVOL, 7, 1, 0),
|
||||
SOC_DOUBLE_R_TLV("VOUT3 Playback Volume", WM8770_VOUT3LVOL,
|
||||
WM8770_VOUT3RVOL, 0, 127, 0, dac_alg_tlv),
|
||||
SOC_DOUBLE_R("VOUT3 Playback ZC Switch", WM8770_VOUT3LVOL,
|
||||
WM8770_VOUT3RVOL, 7, 1, 0),
|
||||
SOC_DOUBLE_R_TLV("VOUT4 Playback Volume", WM8770_VOUT4LVOL,
|
||||
WM8770_VOUT4RVOL, 0, 127, 0, dac_alg_tlv),
|
||||
SOC_DOUBLE_R("VOUT4 Playback ZC Switch", WM8770_VOUT4LVOL,
|
||||
WM8770_VOUT4RVOL, 7, 1, 0),
|
||||
|
||||
/* DAC1/2/3/4 specific controls */
|
||||
SOC_DOUBLE_R_TLV("DAC1 Playback Volume", WM8770_DAC1LVOL,
|
||||
WM8770_DAC1RVOL, 0, 255, 0, dac_dig_tlv),
|
||||
SOC_SINGLE("DAC1 Deemphasis Switch", WM8770_DACCTRL2, 0, 1, 0),
|
||||
SOC_ENUM("DAC1 Phase", dac_phase[0]),
|
||||
SOC_DOUBLE_R_TLV("DAC2 Playback Volume", WM8770_DAC2LVOL,
|
||||
WM8770_DAC2RVOL, 0, 255, 0, dac_dig_tlv),
|
||||
SOC_SINGLE("DAC2 Deemphasis Switch", WM8770_DACCTRL2, 1, 1, 0),
|
||||
SOC_ENUM("DAC2 Phase", dac_phase[1]),
|
||||
SOC_DOUBLE_R_TLV("DAC3 Playback Volume", WM8770_DAC3LVOL,
|
||||
WM8770_DAC3RVOL, 0, 255, 0, dac_dig_tlv),
|
||||
SOC_SINGLE("DAC3 Deemphasis Switch", WM8770_DACCTRL2, 2, 1, 0),
|
||||
SOC_ENUM("DAC3 Phase", dac_phase[2]),
|
||||
SOC_DOUBLE_R_TLV("DAC4 Playback Volume", WM8770_DAC4LVOL,
|
||||
WM8770_DAC4RVOL, 0, 255, 0, dac_dig_tlv),
|
||||
SOC_SINGLE("DAC4 Deemphasis Switch", WM8770_DACCTRL2, 3, 1, 0),
|
||||
SOC_ENUM("DAC4 Phase", dac_phase[3]),
|
||||
|
||||
/* ADC specific controls */
|
||||
SOC_DOUBLE_R_TLV("Capture Volume", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
|
||||
0, 31, 0, adc_tlv),
|
||||
SOC_DOUBLE_R("Capture Switch", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
|
||||
5, 1, 1),
|
||||
|
||||
/* other controls */
|
||||
SOC_SINGLE("ADC 128x Oversampling Switch", WM8770_MSTRCTRL, 3, 1, 0),
|
||||
SOC_SINGLE("ADC Highpass Filter Switch", WM8770_IFACECTRL, 8, 1, 1)
|
||||
};
|
||||
|
||||
static const char *ain_text[] = {
|
||||
"AIN1", "AIN2", "AIN3", "AIN4",
|
||||
"AIN5", "AIN6", "AIN7", "AIN8"
|
||||
};
|
||||
|
||||
static const struct soc_enum ain_enum =
|
||||
SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
|
||||
|
||||
static const struct snd_kcontrol_new ain_mux =
|
||||
SOC_DAPM_ENUM("Capture Mux", ain_enum);
|
||||
|
||||
static const struct snd_kcontrol_new vout1_mix_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC1 Switch", WM8770_OUTMUX1, 0, 1, 0),
|
||||
SOC_DAPM_SINGLE("AUX1 Switch", WM8770_OUTMUX1, 1, 1, 0),
|
||||
SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 2, 1, 0)
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new vout2_mix_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC2 Switch", WM8770_OUTMUX1, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("AUX2 Switch", WM8770_OUTMUX1, 4, 1, 0),
|
||||
SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 5, 1, 0)
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new vout3_mix_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC3 Switch", WM8770_OUTMUX2, 0, 1, 0),
|
||||
SOC_DAPM_SINGLE("AUX3 Switch", WM8770_OUTMUX2, 1, 1, 0),
|
||||
SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 2, 1, 0)
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new vout4_mix_controls[] = {
|
||||
SOC_DAPM_SINGLE("DAC4 Switch", WM8770_OUTMUX2, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 4, 1, 0)
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget wm8770_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AUX1"),
|
||||
SND_SOC_DAPM_INPUT("AUX2"),
|
||||
SND_SOC_DAPM_INPUT("AUX3"),
|
||||
|
||||
SND_SOC_DAPM_INPUT("AIN1"),
|
||||
SND_SOC_DAPM_INPUT("AIN2"),
|
||||
SND_SOC_DAPM_INPUT("AIN3"),
|
||||
SND_SOC_DAPM_INPUT("AIN4"),
|
||||
SND_SOC_DAPM_INPUT("AIN5"),
|
||||
SND_SOC_DAPM_INPUT("AIN6"),
|
||||
SND_SOC_DAPM_INPUT("AIN7"),
|
||||
SND_SOC_DAPM_INPUT("AIN8"),
|
||||
|
||||
SND_SOC_DAPM_MUX("Capture Mux", WM8770_ADCMUX, 8, 1, &ain_mux),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADC", "Capture", WM8770_PWDNCTRL, 1, 1),
|
||||
|
||||
SND_SOC_DAPM_DAC("DAC1", "Playback", WM8770_PWDNCTRL, 2, 1),
|
||||
SND_SOC_DAPM_DAC("DAC2", "Playback", WM8770_PWDNCTRL, 3, 1),
|
||||
SND_SOC_DAPM_DAC("DAC3", "Playback", WM8770_PWDNCTRL, 4, 1),
|
||||
SND_SOC_DAPM_DAC("DAC4", "Playback", WM8770_PWDNCTRL, 5, 1),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("VOUT12 Supply", SND_SOC_NOPM, 0, 0,
|
||||
vout12supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_SUPPLY("VOUT34 Supply", SND_SOC_NOPM, 0, 0,
|
||||
vout34supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER("VOUT1 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
vout1_mix_controls, ARRAY_SIZE(vout1_mix_controls)),
|
||||
SND_SOC_DAPM_MIXER("VOUT2 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
vout2_mix_controls, ARRAY_SIZE(vout2_mix_controls)),
|
||||
SND_SOC_DAPM_MIXER("VOUT3 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
vout3_mix_controls, ARRAY_SIZE(vout3_mix_controls)),
|
||||
SND_SOC_DAPM_MIXER("VOUT4 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
vout4_mix_controls, ARRAY_SIZE(vout4_mix_controls)),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("VOUT1"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT2"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT3"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT4")
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route wm8770_intercon[] = {
|
||||
{ "Capture Mux", "AIN1", "AIN1" },
|
||||
{ "Capture Mux", "AIN2", "AIN2" },
|
||||
{ "Capture Mux", "AIN3", "AIN3" },
|
||||
{ "Capture Mux", "AIN4", "AIN4" },
|
||||
{ "Capture Mux", "AIN5", "AIN5" },
|
||||
{ "Capture Mux", "AIN6", "AIN6" },
|
||||
{ "Capture Mux", "AIN7", "AIN7" },
|
||||
{ "Capture Mux", "AIN8", "AIN8" },
|
||||
|
||||
{ "ADC", NULL, "Capture Mux" },
|
||||
|
||||
{ "VOUT1 Mixer", NULL, "VOUT12 Supply" },
|
||||
{ "VOUT1 Mixer", "DAC1 Switch", "DAC1" },
|
||||
{ "VOUT1 Mixer", "AUX1 Switch", "AUX1" },
|
||||
{ "VOUT1 Mixer", "Bypass Switch", "Capture Mux" },
|
||||
|
||||
{ "VOUT2 Mixer", NULL, "VOUT12 Supply" },
|
||||
{ "VOUT2 Mixer", "DAC2 Switch", "DAC2" },
|
||||
{ "VOUT2 Mixer", "AUX2 Switch", "AUX2" },
|
||||
{ "VOUT2 Mixer", "Bypass Switch", "Capture Mux" },
|
||||
|
||||
{ "VOUT3 Mixer", NULL, "VOUT34 Supply" },
|
||||
{ "VOUT3 Mixer", "DAC3 Switch", "DAC3" },
|
||||
{ "VOUT3 Mixer", "AUX3 Switch", "AUX3" },
|
||||
{ "VOUT3 Mixer", "Bypass Switch", "Capture Mux" },
|
||||
|
||||
{ "VOUT4 Mixer", NULL, "VOUT34 Supply" },
|
||||
{ "VOUT4 Mixer", "DAC4 Switch", "DAC4" },
|
||||
{ "VOUT4 Mixer", "Bypass Switch", "Capture Mux" },
|
||||
|
||||
{ "VOUT1", NULL, "VOUT1 Mixer" },
|
||||
{ "VOUT2", NULL, "VOUT2 Mixer" },
|
||||
{ "VOUT3", NULL, "VOUT3 Mixer" },
|
||||
{ "VOUT4", NULL, "VOUT4 Mixer" }
|
||||
};
|
||||
|
||||
static int vout12supply_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
codec = w->codec;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0x180);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vout34supply_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
codec = w->codec;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0x180);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8770_reset(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_write(codec, WM8770_RESET, 0);
|
||||
}
|
||||
|
||||
static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
int iface, master;
|
||||
|
||||
codec = dai->codec;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
master = 0x100;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
master = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iface = 0;
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
iface |= 0x2;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
iface |= 0x1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
iface |= 0xc;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
iface |= 0x8;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
iface |= 0x4;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8770_IFACECTRL, 0xf, iface);
|
||||
snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x100, master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const int mclk_ratios[] = {
|
||||
128,
|
||||
192,
|
||||
256,
|
||||
384,
|
||||
512,
|
||||
768
|
||||
};
|
||||
|
||||
static int wm8770_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct wm8770_priv *wm8770;
|
||||
int i;
|
||||
int iface;
|
||||
int shift;
|
||||
int ratio;
|
||||
|
||||
codec = dai->codec;
|
||||
wm8770 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
iface = 0;
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
iface |= 0x10;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
iface |= 0x20;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
iface |= 0x30;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (substream->stream) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
i = 0;
|
||||
shift = 4;
|
||||
break;
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
i = 2;
|
||||
shift = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Only need to set MCLK/LRCLK ratio if we're master */
|
||||
if (snd_soc_read(codec, WM8770_MSTRCTRL) & 0x100) {
|
||||
for (; i < ARRAY_SIZE(mclk_ratios); ++i) {
|
||||
ratio = wm8770->sysclk / params_rate(params);
|
||||
if (ratio == mclk_ratios[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mclk_ratios)) {
|
||||
dev_err(codec->dev,
|
||||
"Unable to configure MCLK ratio %d/%d\n",
|
||||
wm8770->sysclk, params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
|
||||
|
||||
snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x7 << shift,
|
||||
i << shift);
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, WM8770_IFACECTRL, 0x30, iface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8770_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
codec = dai->codec;
|
||||
return snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10,
|
||||
!!mute << 4);
|
||||
}
|
||||
|
||||
static int wm8770_set_sysclk(struct snd_soc_dai *dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct wm8770_priv *wm8770;
|
||||
|
||||
codec = dai->codec;
|
||||
wm8770 = snd_soc_codec_get_drvdata(codec);
|
||||
wm8770->sysclk = freq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wm8770_sync_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
u16 *cache;
|
||||
|
||||
if (!codec->cache_sync)
|
||||
return;
|
||||
|
||||
codec->cache_only = 0;
|
||||
cache = codec->reg_cache;
|
||||
for (i = 0; i < codec->driver->reg_cache_size; i++) {
|
||||
if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
|
||||
continue;
|
||||
snd_soc_write(codec, i, cache[i]);
|
||||
}
|
||||
codec->cache_sync = 0;
|
||||
}
|
||||
|
||||
static int wm8770_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
int ret;
|
||||
struct wm8770_priv *wm8770;
|
||||
|
||||
wm8770 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
|
||||
wm8770->supplies);
|
||||
if (ret) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to enable supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
wm8770_sync_cache(codec);
|
||||
/* global powerup */
|
||||
snd_soc_write(codec, WM8770_PWDNCTRL, 0);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* global powerdown */
|
||||
snd_soc_write(codec, WM8770_PWDNCTRL, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies),
|
||||
wm8770->supplies);
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_ops wm8770_dai_ops = {
|
||||
.digital_mute = wm8770_mute,
|
||||
.hw_params = wm8770_hw_params,
|
||||
.set_fmt = wm8770_set_fmt,
|
||||
.set_sysclk = wm8770_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver wm8770_dai = {
|
||||
.name = "wm8770-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = WM8770_FORMATS
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = WM8770_FORMATS
|
||||
},
|
||||
.ops = &wm8770_dai_ops,
|
||||
.symmetric_rates = 1
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm8770_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
{
|
||||
wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8770_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wm8770_suspend NULL
|
||||
#define wm8770_resume NULL
|
||||
#endif
|
||||
|
||||
static int wm8770_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8770_priv *wm8770;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
wm8770 = snd_soc_codec_get_drvdata(codec);
|
||||
wm8770->codec = codec;
|
||||
|
||||
codec->dapm.idle_bias_off = 1;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
|
||||
wm8770->supplies[i].supply = wm8770_supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
|
||||
wm8770->supplies);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
|
||||
wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
|
||||
wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
|
||||
|
||||
/* This should really be moved into the regulator core */
|
||||
for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
|
||||
ret = regulator_register_notifier(wm8770->supplies[i].consumer,
|
||||
&wm8770->disable_nb[i]);
|
||||
if (ret) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to register regulator notifier: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
|
||||
wm8770->supplies);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
|
||||
goto err_reg_get;
|
||||
}
|
||||
|
||||
ret = wm8770_reset(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
|
||||
goto err_reg_enable;
|
||||
}
|
||||
|
||||
wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
/* latch the volume update bits */
|
||||
snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_VOUT1RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_VOUT2RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_VOUT3RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_VOUT4RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_DAC1RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_DAC2RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_DAC3RVOL, 0x100, 0x100);
|
||||
snd_soc_update_bits(codec, WM8770_DAC4RVOL, 0x100, 0x100);
|
||||
|
||||
/* mute all DACs */
|
||||
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
|
||||
|
||||
snd_soc_add_controls(codec, wm8770_snd_controls,
|
||||
ARRAY_SIZE(wm8770_snd_controls));
|
||||
snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
|
||||
ARRAY_SIZE(wm8770_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
|
||||
ARRAY_SIZE(wm8770_intercon));
|
||||
return 0;
|
||||
|
||||
err_reg_enable:
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
|
||||
err_reg_get:
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm8770_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm8770_priv *wm8770;
|
||||
int i;
|
||||
|
||||
wm8770 = snd_soc_codec_get_drvdata(codec);
|
||||
wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
|
||||
regulator_unregister_notifier(wm8770->supplies[i].consumer,
|
||||
&wm8770->disable_nb[i]);
|
||||
regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
|
||||
.probe = wm8770_probe,
|
||||
.remove = wm8770_remove,
|
||||
.suspend = wm8770_suspend,
|
||||
.resume = wm8770_resume,
|
||||
.set_bias_level = wm8770_set_bias_level,
|
||||
.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
|
||||
.reg_word_size = sizeof (u16),
|
||||
.reg_cache_default = wm8770_reg_defs
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static int __devinit wm8770_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct wm8770_priv *wm8770;
|
||||
int ret;
|
||||
|
||||
wm8770 = kzalloc(sizeof(struct wm8770_priv), GFP_KERNEL);
|
||||
if (!wm8770)
|
||||
return -ENOMEM;
|
||||
|
||||
wm8770->control_type = SND_SOC_SPI;
|
||||
spi_set_drvdata(spi, wm8770);
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_wm8770, &wm8770_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(wm8770);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit wm8770_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
kfree(spi_get_drvdata(spi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver wm8770_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm8770",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wm8770_spi_probe,
|
||||
.remove = __devexit_p(wm8770_spi_remove)
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init wm8770_modinit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
ret = spi_register_driver(&wm8770_spi_driver);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
module_init(wm8770_modinit);
|
||||
|
||||
static void __exit wm8770_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
spi_unregister_driver(&wm8770_spi_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(wm8770_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC WM8770 driver");
|
||||
MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* wm8770.h -- WM8770 ASoC driver
|
||||
*
|
||||
* Copyright 2010 Wolfson Microelectronics plc
|
||||
*
|
||||
* Author: Dimitris Papastamos <dp@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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _WM8770_H
|
||||
#define _WM8770_H
|
||||
|
||||
/* Registers */
|
||||
#define WM8770_VOUT1LVOL 0
|
||||
#define WM8770_VOUT1RVOL 0x1
|
||||
#define WM8770_VOUT2LVOL 0x2
|
||||
#define WM8770_VOUT2RVOL 0x3
|
||||
#define WM8770_VOUT3LVOL 0x4
|
||||
#define WM8770_VOUT3RVOL 0x5
|
||||
#define WM8770_VOUT4LVOL 0x6
|
||||
#define WM8770_VOUT4RVOL 0x7
|
||||
#define WM8770_MSALGVOL 0x8
|
||||
#define WM8770_DAC1LVOL 0x9
|
||||
#define WM8770_DAC1RVOL 0xa
|
||||
#define WM8770_DAC2LVOL 0xb
|
||||
#define WM8770_DAC2RVOL 0xc
|
||||
#define WM8770_DAC3LVOL 0xd
|
||||
#define WM8770_DAC3RVOL 0xe
|
||||
#define WM8770_DAC4LVOL 0xf
|
||||
#define WM8770_DAC4RVOL 0x10
|
||||
#define WM8770_MSDIGVOL 0x11
|
||||
#define WM8770_DACPHASE 0x12
|
||||
#define WM8770_DACCTRL1 0x13
|
||||
#define WM8770_DACMUTE 0x14
|
||||
#define WM8770_DACCTRL2 0x15
|
||||
#define WM8770_IFACECTRL 0x16
|
||||
#define WM8770_MSTRCTRL 0x17
|
||||
#define WM8770_PWDNCTRL 0x18
|
||||
#define WM8770_ADCLCTRL 0x19
|
||||
#define WM8770_ADCRCTRL 0x1a
|
||||
#define WM8770_ADCMUX 0x1b
|
||||
#define WM8770_OUTMUX1 0x1c
|
||||
#define WM8770_OUTMUX2 0x1d
|
||||
#define WM8770_RESET 0x31
|
||||
|
||||
#define WM8770_CACHEREGNUM 0x20
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue