* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-08 10:01 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Cc: john.cooper, chasedouglas, broonie, alsa-devel, Ryan Mallon, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The core support has been modified to move setting of the SPOL and ORIDE bits of the i2sclkdiv register, as well as the i2s pin strapping configuration, to a new function called ep93xx_i2s_acquire which is called from the audio board drivers. Ryan Mallon (3): EP93xx: Add i2s core support EP93xx: Add i2s audio driver EP93xx: Add Snapper CL15 i2s audio support arch/arm/mach-ep93xx/clock.c | 67 +++- arch/arm/mach-ep93xx/core.c | 67 +++ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 + arch/arm/mach-ep93xx/include/mach/platform.h | 3 + arch/arm/mach-ep93xx/snappercl15.c | 1 + sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/ep93xx/Kconfig | 18 + sound/soc/ep93xx/Makefile | 11 + sound/soc/ep93xx/ep93xx-i2s.c | 487 +++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-i2s.h | 18 + sound/soc/ep93xx/ep93xx-pcm.c | 319 +++++++++++++++ sound/soc/ep93xx/ep93xx-pcm.h | 22 + sound/soc/ep93xx/snappercl15.c | 150 +++++++ 14 files changed, 1174 insertions(+), 1 deletions(-) create mode 100644 sound/soc/ep93xx/Kconfig create mode 100644 sound/soc/ep93xx/Makefile create mode 100644 sound/soc/ep93xx/ep93xx-i2s.c create mode 100644 sound/soc/ep93xx/ep93xx-i2s.h create mode 100644 sound/soc/ep93xx/ep93xx-pcm.c create mode 100644 sound/soc/ep93xx/ep93xx-pcm.h create mode 100644 sound/soc/ep93xx/snappercl15.c ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-08 10:01 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The core support has been modified to move setting of the SPOL and ORIDE bits of the i2sclkdiv register, as well as the i2s pin strapping configuration, to a new function called ep93xx_i2s_acquire which is called from the audio board drivers. Ryan Mallon (3): EP93xx: Add i2s core support EP93xx: Add i2s audio driver EP93xx: Add Snapper CL15 i2s audio support arch/arm/mach-ep93xx/clock.c | 67 +++- arch/arm/mach-ep93xx/core.c | 67 +++ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 + arch/arm/mach-ep93xx/include/mach/platform.h | 3 + arch/arm/mach-ep93xx/snappercl15.c | 1 + sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/ep93xx/Kconfig | 18 + sound/soc/ep93xx/Makefile | 11 + sound/soc/ep93xx/ep93xx-i2s.c | 487 +++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-i2s.h | 18 + sound/soc/ep93xx/ep93xx-pcm.c | 319 +++++++++++++++ sound/soc/ep93xx/ep93xx-pcm.h | 22 + sound/soc/ep93xx/snappercl15.c | 150 +++++++ 14 files changed, 1174 insertions(+), 1 deletions(-) create mode 100644 sound/soc/ep93xx/Kconfig create mode 100644 sound/soc/ep93xx/Makefile create mode 100644 sound/soc/ep93xx/ep93xx-i2s.c create mode 100644 sound/soc/ep93xx/ep93xx-i2s.h create mode 100644 sound/soc/ep93xx/ep93xx-pcm.c create mode 100644 sound/soc/ep93xx/ep93xx-pcm.h create mode 100644 sound/soc/ep93xx/snappercl15.c ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-08 10:01 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Cc: john.cooper, chasedouglas, broonie, alsa-devel, Ryan Mallon, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Add core support for EP93xx i2s audio Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- arch/arm/mach-ep93xx/clock.c | 67 ++++++++++++++++++++++- arch/arm/mach-ep93xx/core.c | 67 +++++++++++++++++++++++ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 ++++ arch/arm/mach-ep93xx/include/mach/platform.h | 3 + 4 files changed, 146 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 5f80092..e782af1 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk); static int set_keytchclk_rate(struct clk *clk, unsigned long rate); static int set_div_rate(struct clk *clk, unsigned long rate); - +static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate); +static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate); static struct clk clk_xtali = { .rate = EP93XX_EXT_CLK_RATE, @@ -108,6 +109,29 @@ static struct clk clk_video = { .set_rate = set_div_rate, }; +static struct clk clk_i2s_mclk = { + .sw_locked = 1, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, + .set_rate = set_div_rate, +}; + +static struct clk clk_i2s_sclk = { + .sw_locked = 1, + .parent = &clk_i2s_mclk, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, + .set_rate = set_i2s_sclk_rate, +}; + +static struct clk clk_i2s_lrclk = { + .sw_locked = 1, + .parent = &clk_i2s_sclk, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, + .set_rate = set_i2s_lrclk_rate, +}; + /* DMA Clocks */ static struct clk clk_m2p0 = { .parent = &clk_h, @@ -186,6 +210,9 @@ static struct clk_lookup clocks[] = { INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), INIT_CK("ep93xx-fb", NULL, &clk_video), + INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk), + INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk), + INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk), INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), @@ -396,6 +423,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate) return 0; } +static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate) +{ + unsigned val = __raw_readl(clk->enable_reg); + + if (rate == clk_i2s_mclk.rate / 2) + ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, + clk->enable_reg); + else if (rate == clk_i2s_mclk.rate / 4) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, + clk->enable_reg); + else + return -EINVAL; + + clk_i2s_sclk.rate = rate; + return 0; +} + +static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate) +{ + unsigned val = __raw_readl(clk->enable_reg) & + ~EP93XX_I2SCLKDIV_LRDIV_MASK; + + if (rate == clk_i2s_sclk.rate / 32) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32, + clk->enable_reg); + else if (rate == clk_i2s_sclk.rate / 64) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64, + clk->enable_reg); + else if (rate == clk_i2s_sclk.rate / 128) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128, + clk->enable_reg); + else + return -EINVAL; + + clk_i2s_lrclk.rate = rate; + return 0; +} + int clk_set_rate(struct clk *clk, unsigned long rate) { if (clk->set_rate) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 90fb591..005af0f 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -617,6 +617,73 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev) } EXPORT_SYMBOL(ep93xx_keypad_release_gpio); +/************************************************************************* + * EP93xx I2S audio peripheral handling + *************************************************************************/ +static struct resource ep93xx_i2s_resource[] = { + { + .start = EP93XX_I2S_PHYS_BASE, + .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_i2s_device = { + .name = "ep93xx-i2s", + .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), + .resource = ep93xx_i2s_resource, +}; + +void __init ep93xx_register_i2s(void) +{ + platform_device_register(&ep93xx_i2s_device); +} + +#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ + EP93XX_SYSCON_DEVCFG_I2SONAC97) + +#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ + EP93XX_SYSCON_I2SCLKDIV_SPOL) + +int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config) +{ + unsigned val; + + /* Sanity check */ + if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK) + return -EINVAL; + if (i2s_config & ~EP93XX_I2SCLKDIV_MASK) + return -EINVAL; + + /* Must have only one of I2SONSSP/I2SONAC97 set */ + if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) == + (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97)) + return -EINVAL; + + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); + ep93xx_devcfg_set_bits(i2s_pins); + + /* + * This is potentially racy with the clock api for i2s_mclk, sclk and + * lrclk. Since the i2s driver is the only user of those clocks we + * rely on it to prevent parallel use of this function and the + * clock api for the i2s clocks. + */ + val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); + val &= ~EP93XX_I2SCLKDIV_MASK; + val |= i2s_config; + ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); + + return 0; +} +EXPORT_SYMBOL(ep93xx_i2s_acquire); + +void ep93xx_i2s_release(void) +{ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); +} +EXPORT_SYMBOL(ep93xx_i2s_release); extern void ep93xx_gpio_init(void); diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 93e2ecc..3fbb095 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -93,6 +93,7 @@ /* APB peripherals */ #define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) +#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000) #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) @@ -193,6 +194,15 @@ #define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) #define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) #define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 +#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c) +#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31) +#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29) +#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19) +#define EP93XX_I2SCLKDIV_SDIV (1 << 16) +#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17) +#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17) +#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17) +#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17) #define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index c6dc14d..0f2822d 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -43,6 +43,9 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev); void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); void ep93xx_keypad_release_gpio(struct platform_device *pdev); +void ep93xx_register_i2s(void); +int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config); +void ep93xx_i2s_release(void); void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 10:01 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Add core support for EP93xx i2s audio Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- arch/arm/mach-ep93xx/clock.c | 67 ++++++++++++++++++++++- arch/arm/mach-ep93xx/core.c | 67 +++++++++++++++++++++++ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 ++++ arch/arm/mach-ep93xx/include/mach/platform.h | 3 + 4 files changed, 146 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 5f80092..e782af1 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk); static int set_keytchclk_rate(struct clk *clk, unsigned long rate); static int set_div_rate(struct clk *clk, unsigned long rate); - +static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate); +static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate); static struct clk clk_xtali = { .rate = EP93XX_EXT_CLK_RATE, @@ -108,6 +109,29 @@ static struct clk clk_video = { .set_rate = set_div_rate, }; +static struct clk clk_i2s_mclk = { + .sw_locked = 1, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, + .set_rate = set_div_rate, +}; + +static struct clk clk_i2s_sclk = { + .sw_locked = 1, + .parent = &clk_i2s_mclk, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, + .set_rate = set_i2s_sclk_rate, +}; + +static struct clk clk_i2s_lrclk = { + .sw_locked = 1, + .parent = &clk_i2s_sclk, + .enable_reg = EP93XX_SYSCON_I2SCLKDIV, + .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, + .set_rate = set_i2s_lrclk_rate, +}; + /* DMA Clocks */ static struct clk clk_m2p0 = { .parent = &clk_h, @@ -186,6 +210,9 @@ static struct clk_lookup clocks[] = { INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), INIT_CK("ep93xx-fb", NULL, &clk_video), + INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk), + INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk), + INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk), INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), @@ -396,6 +423,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate) return 0; } +static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate) +{ + unsigned val = __raw_readl(clk->enable_reg); + + if (rate == clk_i2s_mclk.rate / 2) + ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, + clk->enable_reg); + else if (rate == clk_i2s_mclk.rate / 4) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, + clk->enable_reg); + else + return -EINVAL; + + clk_i2s_sclk.rate = rate; + return 0; +} + +static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate) +{ + unsigned val = __raw_readl(clk->enable_reg) & + ~EP93XX_I2SCLKDIV_LRDIV_MASK; + + if (rate == clk_i2s_sclk.rate / 32) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32, + clk->enable_reg); + else if (rate == clk_i2s_sclk.rate / 64) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64, + clk->enable_reg); + else if (rate == clk_i2s_sclk.rate / 128) + ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128, + clk->enable_reg); + else + return -EINVAL; + + clk_i2s_lrclk.rate = rate; + return 0; +} + int clk_set_rate(struct clk *clk, unsigned long rate) { if (clk->set_rate) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 90fb591..005af0f 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -617,6 +617,73 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev) } EXPORT_SYMBOL(ep93xx_keypad_release_gpio); +/************************************************************************* + * EP93xx I2S audio peripheral handling + *************************************************************************/ +static struct resource ep93xx_i2s_resource[] = { + { + .start = EP93XX_I2S_PHYS_BASE, + .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_i2s_device = { + .name = "ep93xx-i2s", + .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), + .resource = ep93xx_i2s_resource, +}; + +void __init ep93xx_register_i2s(void) +{ + platform_device_register(&ep93xx_i2s_device); +} + +#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ + EP93XX_SYSCON_DEVCFG_I2SONAC97) + +#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ + EP93XX_SYSCON_I2SCLKDIV_SPOL) + +int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config) +{ + unsigned val; + + /* Sanity check */ + if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK) + return -EINVAL; + if (i2s_config & ~EP93XX_I2SCLKDIV_MASK) + return -EINVAL; + + /* Must have only one of I2SONSSP/I2SONAC97 set */ + if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) == + (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97)) + return -EINVAL; + + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); + ep93xx_devcfg_set_bits(i2s_pins); + + /* + * This is potentially racy with the clock api for i2s_mclk, sclk and + * lrclk. Since the i2s driver is the only user of those clocks we + * rely on it to prevent parallel use of this function and the + * clock api for the i2s clocks. + */ + val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); + val &= ~EP93XX_I2SCLKDIV_MASK; + val |= i2s_config; + ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); + + return 0; +} +EXPORT_SYMBOL(ep93xx_i2s_acquire); + +void ep93xx_i2s_release(void) +{ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); +} +EXPORT_SYMBOL(ep93xx_i2s_release); extern void ep93xx_gpio_init(void); diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 93e2ecc..3fbb095 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -93,6 +93,7 @@ /* APB peripherals */ #define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) +#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000) #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) @@ -193,6 +194,15 @@ #define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) #define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) #define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 +#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c) +#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31) +#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29) +#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19) +#define EP93XX_I2SCLKDIV_SDIV (1 << 16) +#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17) +#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17) +#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17) +#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17) #define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index c6dc14d..0f2822d 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -43,6 +43,9 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev); void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); void ep93xx_keypad_release_gpio(struct platform_device *pdev); +void ep93xx_register_i2s(void); +int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config); +void ep93xx_i2s_release(void); void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* RE: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-08 15:01 ` H Hartley Sweeten -1 siblings, 0 replies; 38+ messages in thread From: H Hartley Sweeten @ 2010-06-08 15:01 UTC (permalink / raw) To: Ryan Mallon, linux-arm-kernel@lists.infradead.org Cc: john.cooper@third-harmonic.com, alsa-devel@alsa-project.org, broonie@opensource.wolfsonmicro.com, chasedouglas@gmail.com, r&d4@dave-tech.it, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: > > Add core support for EP93xx i2s audio > > Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Looks good. Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 15:01 ` H Hartley Sweeten 0 siblings, 0 replies; 38+ messages in thread From: H Hartley Sweeten @ 2010-06-08 15:01 UTC (permalink / raw) To: linux-arm-kernel On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: > > Add core support for EP93xx i2s audio > > Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Looks good. Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 15:01 ` H Hartley Sweeten @ 2010-06-08 19:27 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 19:27 UTC (permalink / raw) To: H Hartley Sweeten, broonie@opensource.wolfsonmicro.com Cc: john.cooper@third-harmonic.com, alsa-devel@alsa-project.org, chasedouglas@gmail.com, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk H Hartley Sweeten wrote: > On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: >> Add core support for EP93xx i2s audio >> >> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> > > Looks good. > > Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. Mark, do you want to apply the other two patches to your tree, or should they go via the arm tree? Thanks, ~Ryan ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 19:27 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 19:27 UTC (permalink / raw) To: linux-arm-kernel H Hartley Sweeten wrote: > On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: >> Add core support for EP93xx i2s audio >> >> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> > > Looks good. > > Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. Mark, do you want to apply the other two patches to your tree, or should they go via the arm tree? Thanks, ~Ryan ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 19:27 ` Ryan Mallon @ 2010-06-08 23:21 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 23:21 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper@third-harmonic.com, chasedouglas@gmail.com, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, H Hartley Sweeten, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk On 8 Jun 2010, at 20:27, Ryan Mallon wrote: > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. > Mark, do you want to apply the other two patches to your tree, or should > they go via the arm tree? I don't urgently mind for patch 1 since there's no build time dependency - in order to avoid possible merge issues in the ARM tree it's as well if it goes that way, though I can pick it up if it makes sense for you guys to keep stuff together and you don't anticipate colliding with any work in the arch/arm code for the CPU. Patch 3 I'll apply to ASoC tomorrow, it depends on the I2S driver for the CPU which is most definitely ASoC (and it's going to get caught up in the multi-CODEC API changes soon as well so would get build issues in -next if merged via a different tree anyway). ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 23:21 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 23:21 UTC (permalink / raw) To: linux-arm-kernel On 8 Jun 2010, at 20:27, Ryan Mallon wrote: > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. > Mark, do you want to apply the other two patches to your tree, or should > they go via the arm tree? I don't urgently mind for patch 1 since there's no build time dependency - in order to avoid possible merge issues in the ARM tree it's as well if it goes that way, though I can pick it up if it makes sense for you guys to keep stuff together and you don't anticipate colliding with any work in the arch/arm code for the CPU. Patch 3 I'll apply to ASoC tomorrow, it depends on the I2S driver for the CPU which is most definitely ASoC (and it's going to get caught up in the multi-CODEC API changes soon as well so would get build issues in -next if merged via a different tree anyway). ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 23:21 ` Mark Brown @ 2010-06-08 23:26 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 23:26 UTC (permalink / raw) To: Mark Brown Cc: john.cooper@third-harmonic.com, chasedouglas@gmail.com, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, H Hartley Sweeten, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk Mark Brown wrote: > On 8 Jun 2010, at 20:27, Ryan Mallon wrote: > >> Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. >> Mark, do you want to apply the other two patches to your tree, or should >> they go via the arm tree? > > I don't urgently mind for patch 1 since there's no build time dependency - in order to avoid possible merge issues in the ARM tree it's as well if it goes that way, though I can pick it up if it makes sense for you guys to keep stuff together and you don't anticipate colliding with any work in the arch/arm code for the CPU. > > Patch 3 I'll apply to ASoC tomorrow, it depends on the I2S driver for the CPU which is most definitely ASoC (and it's going to get caught up in the multi-CODEC API changes soon as well so would get build issues in -next if merged via a different tree anyway). > Patch 3 at least has a dependency on patch 1 for some #defines and the ep93xx_i2s functions calls. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 23:26 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 23:26 UTC (permalink / raw) To: linux-arm-kernel Mark Brown wrote: > On 8 Jun 2010, at 20:27, Ryan Mallon wrote: > >> Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. >> Mark, do you want to apply the other two patches to your tree, or should >> they go via the arm tree? > > I don't urgently mind for patch 1 since there's no build time dependency - in order to avoid possible merge issues in the ARM tree it's as well if it goes that way, though I can pick it up if it makes sense for you guys to keep stuff together and you don't anticipate colliding with any work in the arch/arm code for the CPU. > > Patch 3 I'll apply to ASoC tomorrow, it depends on the I2S driver for the CPU which is most definitely ASoC (and it's going to get caught up in the multi-CODEC API changes soon as well so would get build issues in -next if merged via a different tree anyway). > Patch 3 at least has a dependency on patch 1 for some #defines and the ep93xx_i2s functions calls. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan at bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 23:26 ` Ryan Mallon @ 2010-06-08 23:29 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 23:29 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper@third-harmonic.com, chasedouglas@gmail.com, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, H Hartley Sweeten, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk On 9 Jun 2010, at 00:26, Ryan Mallon wrote: > Patch 3 at least has a dependency on patch 1 for some #defines and the > ep93xx_i2s functions calls. Oh, in that case best if I take them both through ASoC unless someone anticipates issues there. I'll arrange things so they can also be merged into the ARM tree in case of issues. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 23:29 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 23:29 UTC (permalink / raw) To: linux-arm-kernel On 9 Jun 2010, at 00:26, Ryan Mallon wrote: > Patch 3 at least has a dependency on patch 1 for some #defines and the > ep93xx_i2s functions calls. Oh, in that case best if I take them both through ASoC unless someone anticipates issues there. I'll arrange things so they can also be merged into the ARM tree in case of issues. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 23:29 ` Mark Brown @ 2010-06-08 23:32 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 23:32 UTC (permalink / raw) To: Mark Brown Cc: john.cooper@third-harmonic.com, chasedouglas@gmail.com, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, H Hartley Sweeten, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk Mark Brown wrote: > On 9 Jun 2010, at 00:26, Ryan Mallon wrote: > >> Patch 3 at least has a dependency on patch 1 for some #defines and the >> ep93xx_i2s functions calls. > > Oh, in that case best if I take them both through ASoC unless someone anticipates issues there. I'll arrange things so they can also be merged into the ARM tree in case of issues. Ok, thanks. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 23:32 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 23:32 UTC (permalink / raw) To: linux-arm-kernel Mark Brown wrote: > On 9 Jun 2010, at 00:26, Ryan Mallon wrote: > >> Patch 3 at least has a dependency on patch 1 for some #defines and the >> ep93xx_i2s functions calls. > > Oh, in that case best if I take them both through ASoC unless someone anticipates issues there. I'll arrange things so they can also be merged into the ARM tree in case of issues. Ok, thanks. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan at bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* RE: [PATCH 1/3] EP93xx: Add i2s core support 2010-06-08 19:27 ` Ryan Mallon @ 2010-06-08 23:26 ` H Hartley Sweeten -1 siblings, 0 replies; 38+ messages in thread From: H Hartley Sweeten @ 2010-06-08 23:26 UTC (permalink / raw) To: Ryan Mallon, broonie@opensource.wolfsonmicro.com Cc: john.cooper@third-harmonic.com, alsa-devel@alsa-project.org, chasedouglas@gmail.com, linux-arm-kernel@lists.infradead.org, r&d4@dave-tech.it, dhuggins@cs.cmu.edu, marshall@coolbananas.co.nz, buytenh@wantstofly.org, lrg@slimlogic.co.uk On Tuesday, June 08, 2010 12:27 PM, Ryan Mallon wrote: > H Hartley Sweeten wrote: >> On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: >>> Add core support for EP93xx i2s audio >>> >>> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> >> >> Looks good. >> >> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> >> > > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. > Mark, do you want to apply the other two patches to your tree, or should > they go via the arm tree? Ryan, It appears Mark doesn't see ant reason to apply patch 1 to his tree. It's probably better to send that one thru Russell's patch system in case any other changes are made to the ep93xx core files. Regards, Hartley ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/3] EP93xx: Add i2s core support @ 2010-06-08 23:26 ` H Hartley Sweeten 0 siblings, 0 replies; 38+ messages in thread From: H Hartley Sweeten @ 2010-06-08 23:26 UTC (permalink / raw) To: linux-arm-kernel On Tuesday, June 08, 2010 12:27 PM, Ryan Mallon wrote: > H Hartley Sweeten wrote: >> On Tuesday, June 08, 2010 3:01 AM, Ryan Mallon wrote: >>> Add core support for EP93xx i2s audio >>> >>> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> >> >> Looks good. >> >> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> >> > > Okay, I have Liam and Hartley's acks on this one and Liam's on 3/3. > Mark, do you want to apply the other two patches to your tree, or should > they go via the arm tree? Ryan, It appears Mark doesn't see ant reason to apply patch 1 to his tree. It's probably better to send that one thru Russell's patch system in case any other changes are made to the ep93xx core files. Regards, Hartley ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 2/3] EP93xx: Add i2s audio driver 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-08 10:01 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Cc: john.cooper, chasedouglas, broonie, alsa-devel, Ryan Mallon, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Add pcm and i2s SoC audio drivers for EP93xx Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/ep93xx/Kconfig | 9 + sound/soc/ep93xx/Makefile | 8 + sound/soc/ep93xx/ep93xx-i2s.c | 487 +++++++++++++++++++++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-i2s.h | 18 ++ sound/soc/ep93xx/ep93xx-pcm.c | 319 +++++++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-pcm.h | 22 ++ 8 files changed, 865 insertions(+), 0 deletions(-) create mode 100644 sound/soc/ep93xx/Kconfig create mode 100644 sound/soc/ep93xx/Makefile create mode 100644 sound/soc/ep93xx/ep93xx-i2s.c create mode 100644 sound/soc/ep93xx/ep93xx-i2s.h create mode 100644 sound/soc/ep93xx/ep93xx-pcm.c create mode 100644 sound/soc/ep93xx/ep93xx-pcm.h diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index b1749bc..f7cb451 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -28,6 +28,7 @@ source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" source "sound/soc/blackfin/Kconfig" source "sound/soc/davinci/Kconfig" +source "sound/soc/ep93xx/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/imx/Kconfig" source "sound/soc/omap/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 1470141..55b711a 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SND_SOC) += atmel/ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += blackfin/ obj-$(CONFIG_SND_SOC) += davinci/ +obj-$(CONFIG_SND_SOC) += ep93xx/ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += imx/ obj-$(CONFIG_SND_SOC) += omap/ diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig new file mode 100644 index 0000000..ba66ac8 --- /dev/null +++ b/sound/soc/ep93xx/Kconfig @@ -0,0 +1,9 @@ +config SND_EP93XX_SOC + tristate "SoC Audio support for the Cirrus Logic EP93xx series" + depends on ARCH_EP93XX && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the EP93xx I2S interface. + +config SND_EP93XX_SOC_I2S + tristate diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile new file mode 100644 index 0000000..0239da3 --- /dev/null +++ b/sound/soc/ep93xx/Makefile @@ -0,0 +1,8 @@ +# EP93xx Platform Support +snd-soc-ep93xx-objs := ep93xx-pcm.o +snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o + +obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o +obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o + +# EP93XX Machine Support diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c new file mode 100644 index 0000000..00b9466 --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-i2s.c @@ -0,0 +1,487 @@ +/* + * linux/sound/soc/ep93xx-i2s.c + * EP93xx I2S driver + * + * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> + * + * Based on the original driver by: + * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail> + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/soc.h> + +#include <mach/hardware.h> +#include <mach/ep93xx-regs.h> +#include <mach/dma.h> + +#include "ep93xx-pcm.h" +#include "ep93xx-i2s.h" + +#define EP93XX_I2S_TXCLKCFG 0x00 +#define EP93XX_I2S_RXCLKCFG 0x04 +#define EP93XX_I2S_GLCTRL 0x0C + +#define EP93XX_I2S_TXLINCTRLDATA 0x28 +#define EP93XX_I2S_TXCTRL 0x2C +#define EP93XX_I2S_TXWRDLEN 0x30 +#define EP93XX_I2S_TX0EN 0x34 + +#define EP93XX_I2S_RXLINCTRLDATA 0x58 +#define EP93XX_I2S_RXCTRL 0x5C +#define EP93XX_I2S_RXWRDLEN 0x60 +#define EP93XX_I2S_RX0EN 0x64 + +#define EP93XX_I2S_WRDLEN_16 (0 << 0) +#define EP93XX_I2S_WRDLEN_24 (1 << 0) +#define EP93XX_I2S_WRDLEN_32 (2 << 0) + +#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ + +#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ +#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ +#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ +#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ +#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ + +struct ep93xx_i2s_info { + struct clk *mclk; + struct clk *sclk; + struct clk *lrclk; + struct ep93xx_pcm_dma_params *dma_params; + struct resource *mem; + void __iomem *regs; +}; + +struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { + [SNDRV_PCM_STREAM_PLAYBACK] = { + .name = "i2s-pcm-out", + .dma_port = EP93XX_DMA_M2P_PORT_I2S1, + }, + [SNDRV_PCM_STREAM_CAPTURE] = { + .name = "i2s-pcm-in", + .dma_port = EP93XX_DMA_M2P_PORT_I2S1, + }, +}; + +static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, + unsigned reg, unsigned val) +{ + __raw_writel(val, info->regs + reg); +} + +static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, + unsigned reg) +{ + return __raw_readl(info->regs + reg); +} + +static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Enable clocks */ + clk_enable(info->mclk); + clk_enable(info->sclk); + clk_enable(info->lrclk); + + /* Enable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); + } + + /* Enable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1); +} + +static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + /* Disable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0); + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Disable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); + + /* Disable clocks */ + clk_disable(info->lrclk); + clk_disable(info->sclk); + clk_disable(info->mclk); + } +} + +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + + snd_soc_dai_set_dma_data(cpu_dai, substream, + &info->dma_params[substream->stream]); + return 0; +} + +static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + + ep93xx_i2s_disable(info, substream->stream); +} + +static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct ep93xx_i2s_info *info = cpu_dai->private_data; + unsigned int clk_cfg, lin_ctrl; + + clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); + lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_LEFT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_RIGHT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* CPU is master */ + clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; + break; + + case SND_SOC_DAIFMT_CBM_CFM: + /* Codec is master */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + /* Negative bit clock, lrclk low on left word */ + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); + break; + + case SND_SOC_DAIFMT_NB_IF: + /* Negative bit clock, lrclk low on right word */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_NF: + /* Positive bit clock, lrclk low on left word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP; + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_IF: + /* Positive bit clock, lrclk low on right word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; + break; + } + + /* Write new register values */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); + return 0; +} + +static int ep93xx_i2s_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_dai *cpu_dai = rtd->dai->cpu_dai; + struct ep93xx_i2s_info *info = cpu_dai->private_data; + unsigned word_len, div, sdiv, lrdiv; + int found = 0, err; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + word_len = EP93XX_I2S_WRDLEN_16; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + word_len = EP93XX_I2S_WRDLEN_24; + break; + + case SNDRV_PCM_FORMAT_S32_LE: + word_len = EP93XX_I2S_WRDLEN_32; + break; + + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); + else + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); + + /* + * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values. + * If the lrclk is pulse length is larger than the word size, then the + * bit clock will be gated for the unused bits. + */ + div = (clk_get_rate(info->mclk) / params_rate(params)) * + params_channels(params); + for (sdiv = 2; sdiv <= 4; sdiv += 2) + for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1) + if (sdiv * lrdiv == div) { + found = 1; + goto out; + } +out: + if (!found) + return -EINVAL; + + err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); + if (err) + return err; + + err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); + if (err) + return err; + + ep93xx_i2s_enable(info, substream->stream); + return 0; +} + +static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + unsigned int freq, int dir) +{ + struct ep93xx_i2s_info *info = cpu_dai->private_data; + + if (dir == SND_SOC_CLOCK_IN || clk_id != 0) + return -EINVAL; + + return clk_set_rate(info->mclk, freq); +} + +#ifdef CONFIG_PM +static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = dai->private_data; + + if (!dai->active) + return; + + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); +} + +static int ep93xx_i2s_resume(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = dai->private_data; + + if (!dai->active) + return; + + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); +} +#else +#define ep93xx_i2s_suspend NULL +#define ep93xx_i2s_resume NULL +#endif + +static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { + .startup = ep93xx_i2s_startup, + .shutdown = ep93xx_i2s_shutdown, + .hw_params = ep93xx_i2s_hw_params, + .set_sysclk = ep93xx_i2s_set_sysclk, + .set_fmt = ep93xx_i2s_set_dai_fmt, +}; + +#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +struct snd_soc_dai ep93xx_i2s_dai = { + .name = "ep93xx-i2s", + .id = 0, + .symmetric_rates= 1, + .suspend = ep93xx_i2s_suspend, + .resume = ep93xx_i2s_resume, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = EP93XX_I2S_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = EP93XX_I2S_FORMATS, + }, + .ops = &ep93xx_i2s_dai_ops, +}; +EXPORT_SYMBOL_GPL(ep93xx_i2s_dai); + +static int ep93xx_i2s_probe(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info; + struct resource *res; + int err; + + info = kzalloc(sizeof(struct ep93xx_i2s_info), GFP_KERNEL); + if (!info) { + err = -ENOMEM; + goto fail; + } + + ep93xx_i2s_dai.dev = &pdev->dev; + ep93xx_i2s_dai.private_data = info; + info->dma_params = ep93xx_i2s_dma_params; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENODEV; + goto fail; + } + + info->mem = request_mem_region(res->start, resource_size(res), + pdev->name); + if (!info->mem) { + err = -EBUSY; + goto fail; + } + + info->regs = ioremap(info->mem->start, resource_size(info->mem)); + if (!info->regs) { + err = -ENXIO; + goto fail_release_mem; + } + + info->mclk = clk_get(&pdev->dev, "mclk"); + if (IS_ERR(info->mclk)) { + err = PTR_ERR(info->mclk); + goto fail_unmap_mem; + } + + info->sclk = clk_get(&pdev->dev, "sclk"); + if (IS_ERR(info->sclk)) { + err = PTR_ERR(info->sclk); + goto fail_put_mclk; + } + + info->lrclk = clk_get(&pdev->dev, "lrclk"); + if (IS_ERR(info->lrclk)) { + err = PTR_ERR(info->lrclk); + goto fail_put_sclk; + } + + err = snd_soc_register_dai(&ep93xx_i2s_dai); + if (err) + goto fail_put_lrclk; + + return 0; + +fail_put_lrclk: + clk_put(info->lrclk); +fail_put_sclk: + clk_put(info->sclk); +fail_put_mclk: + clk_put(info->mclk); +fail_unmap_mem: + iounmap(info->regs); +fail_release_mem: + release_mem_region(info->mem->start, resource_size(info->mem)); + kfree(info); +fail: + return err; +} + +static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; + + snd_soc_unregister_dai(&ep93xx_i2s_dai); + clk_put(info->lrclk); + clk_put(info->sclk); + clk_put(info->mclk); + iounmap(info->regs); + release_mem_region(info->mem->start, resource_size(info->mem)); + kfree(info); + return 0; +} + +static struct platform_driver ep93xx_i2s_driver = { + .probe = ep93xx_i2s_probe, + .remove = __devexit_p(ep93xx_i2s_remove), + .driver = { + .name = "ep93xx-i2s", + .owner = THIS_MODULE, + }, +}; + +static int __init ep93xx_i2s_init(void) +{ + return platform_driver_register(&ep93xx_i2s_driver); +} + +static void __exit ep93xx_i2s_exit(void) +{ + platform_driver_unregister(&ep93xx_i2s_driver); +} + +module_init(ep93xx_i2s_init); +module_exit(ep93xx_i2s_exit); + +MODULE_ALIAS("platform:ep93xx-i2s"); +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("EP93XX I2S driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h new file mode 100644 index 0000000..3bd4ebf --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-i2s.h @@ -0,0 +1,18 @@ +/* + * linux/sound/soc/ep93xx-i2s.h + * EP93xx I2S driver + * + * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.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 _EP93XX_SND_SOC_I2S_H +#define _EP93XX_SND_SOC_I2S_H + +extern struct snd_soc_dai ep93xx_i2s_dai; + +#endif /* _EP93XX_SND_SOC_I2S_H */ diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c new file mode 100644 index 0000000..4ba9384 --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -0,0 +1,319 @@ +/* + * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + * + * Rewritten for the SoC audio subsystem (Based on PXA2xx code): + * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.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/init.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <mach/dma.h> +#include <mach/hardware.h> +#include <mach/ep93xx-regs.h> + +#include "ep93xx-pcm.h" + +static const struct snd_pcm_hardware ep93xx_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = SNDRV_PCM_RATE_8000, + .rate_max = SNDRV_PCM_RATE_48000, + + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + + .buffer_bytes_max = 131072, + .period_bytes_min = 32, + .period_bytes_max = 32768, + .periods_min = 1, + .periods_max = 32, + .fifo_size = 32, +}; + +struct ep93xx_runtime_data +{ + struct ep93xx_dma_m2p_client cl; + struct ep93xx_pcm_dma_params *params; + int pointer_bytes; + struct tasklet_struct period_tasklet; + int periods; + struct ep93xx_dma_buffer buf[32]; +}; + +static void ep93xx_pcm_period_elapsed(unsigned long data) +{ + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; + snd_pcm_period_elapsed(substream); +} + +static void ep93xx_pcm_buffer_started(void *cookie, + struct ep93xx_dma_buffer *buf) +{ +} + +static void ep93xx_pcm_buffer_finished(void *cookie, + struct ep93xx_dma_buffer *buf, + int bytes, int error) +{ + struct snd_pcm_substream *substream = cookie; + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + if (buf == rtd->buf + rtd->periods - 1) + rtd->pointer_bytes = 0; + else + rtd->pointer_bytes += buf->size; + + if (!error) { + ep93xx_dma_m2p_submit_recursive(&rtd->cl, buf); + tasklet_schedule(&rtd->period_tasklet); + } else { + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + } +} + +static int ep93xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; + struct ep93xx_pcm_dma_params *dma_params; + struct ep93xx_runtime_data *rtd; + int ret; + + dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); + snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); + + rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); + if (!rtd) + return -ENOMEM; + + memset(&rtd->period_tasklet, 0, sizeof(rtd->period_tasklet)); + rtd->period_tasklet.func = ep93xx_pcm_period_elapsed; + rtd->period_tasklet.data = (unsigned long)substream; + + rtd->cl.name = dma_params->name; + rtd->cl.flags = dma_params->dma_port | EP93XX_DMA_M2P_IGNORE_ERROR | + ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + EP93XX_DMA_M2P_TX : EP93XX_DMA_M2P_RX); + rtd->cl.cookie = substream; + rtd->cl.buffer_started = ep93xx_pcm_buffer_started; + rtd->cl.buffer_finished = ep93xx_pcm_buffer_finished; + ret = ep93xx_dma_m2p_client_register(&rtd->cl); + if (ret < 0) { + kfree(rtd); + return ret; + } + + substream->runtime->private_data = rtd; + return 0; +} + +static int ep93xx_pcm_close(struct snd_pcm_substream *substream) +{ + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + ep93xx_dma_m2p_client_unregister(&rtd->cl); + kfree(rtd); + return 0; +} + +static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct ep93xx_runtime_data *rtd = runtime->private_data; + size_t totsize = params_buffer_bytes(params); + size_t period = params_period_bytes(params); + int i; + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = totsize; + + rtd->periods = (totsize + period - 1) / period; + for (i = 0; i < rtd->periods; i++) { + rtd->buf[i].bus_addr = runtime->dma_addr + (i * period); + rtd->buf[i].size = period; + if ((i + 1) * period > totsize) + rtd->buf[i].size = totsize - (i * period); + } + + return 0; +} + +static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + int ret; + int i; + + ret = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->pointer_bytes = 0; + for (i = 0; i < rtd->periods; i++) + ep93xx_dma_m2p_submit(&rtd->cl, rtd->buf + i); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ep93xx_dma_m2p_flush(&rtd->cl); + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + /* FIXME: implement this with sub-period granularity */ + return bytes_to_frames(runtime, rtd->pointer_bytes); +} + +static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops ep93xx_pcm_ops = { + .open = ep93xx_pcm_open, + .close = ep93xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = ep93xx_pcm_hw_params, + .hw_free = ep93xx_pcm_hw_free, + .trigger = ep93xx_pcm_trigger, + .pointer = ep93xx_pcm_pointer, + .mmap = ep93xx_pcm_mmap, +}; + +static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = ep93xx_pcm_hardware.buffer_bytes_max; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + buf->bytes = size; + + return (buf->area == NULL) ? -ENOMEM : 0; +} + +static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, + buf->addr); + buf->area = NULL; + } +} + +static u64 ep93xx_pcm_dmamask = 0xffffffff; + +static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &ep93xx_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = 0xffffffff; + + if (dai->playback.channels_min) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + return ret; + } + + if (dai->capture.channels_min) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + return ret; + } + + return 0; +} + +struct snd_soc_platform ep93xx_soc_platform = { + .name = "ep93xx-audio", + .pcm_ops = &ep93xx_pcm_ops, + .pcm_new = &ep93xx_pcm_new, + .pcm_free = &ep93xx_pcm_free_dma_buffers, +}; +EXPORT_SYMBOL_GPL(ep93xx_soc_platform); + +static int __init ep93xx_soc_platform_init(void) +{ + return snd_soc_register_platform(&ep93xx_soc_platform); +} + +static void __exit ep93xx_soc_platform_exit(void) +{ + snd_soc_unregister_platform(&ep93xx_soc_platform); +} + +module_init(ep93xx_soc_platform_init); +module_exit(ep93xx_soc_platform_exit); + +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h new file mode 100644 index 0000000..4ffdd3f --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-pcm.h @@ -0,0 +1,22 @@ +/* + * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + * + * 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 _EP93XX_SND_SOC_PCM_H +#define _EP93XX_SND_SOC_PCM_H + +struct ep93xx_pcm_dma_params { + char *name; + int dma_port; +}; + +extern struct snd_soc_platform ep93xx_soc_platform; + +#endif /* _EP93XX_SND_SOC_PCM_H */ -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 2/3] EP93xx: Add i2s audio driver @ 2010-06-08 10:01 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Add pcm and i2s SoC audio drivers for EP93xx Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/ep93xx/Kconfig | 9 + sound/soc/ep93xx/Makefile | 8 + sound/soc/ep93xx/ep93xx-i2s.c | 487 +++++++++++++++++++++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-i2s.h | 18 ++ sound/soc/ep93xx/ep93xx-pcm.c | 319 +++++++++++++++++++++++++++ sound/soc/ep93xx/ep93xx-pcm.h | 22 ++ 8 files changed, 865 insertions(+), 0 deletions(-) create mode 100644 sound/soc/ep93xx/Kconfig create mode 100644 sound/soc/ep93xx/Makefile create mode 100644 sound/soc/ep93xx/ep93xx-i2s.c create mode 100644 sound/soc/ep93xx/ep93xx-i2s.h create mode 100644 sound/soc/ep93xx/ep93xx-pcm.c create mode 100644 sound/soc/ep93xx/ep93xx-pcm.h diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index b1749bc..f7cb451 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -28,6 +28,7 @@ source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" source "sound/soc/blackfin/Kconfig" source "sound/soc/davinci/Kconfig" +source "sound/soc/ep93xx/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/imx/Kconfig" source "sound/soc/omap/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 1470141..55b711a 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SND_SOC) += atmel/ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += blackfin/ obj-$(CONFIG_SND_SOC) += davinci/ +obj-$(CONFIG_SND_SOC) += ep93xx/ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += imx/ obj-$(CONFIG_SND_SOC) += omap/ diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig new file mode 100644 index 0000000..ba66ac8 --- /dev/null +++ b/sound/soc/ep93xx/Kconfig @@ -0,0 +1,9 @@ +config SND_EP93XX_SOC + tristate "SoC Audio support for the Cirrus Logic EP93xx series" + depends on ARCH_EP93XX && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the EP93xx I2S interface. + +config SND_EP93XX_SOC_I2S + tristate diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile new file mode 100644 index 0000000..0239da3 --- /dev/null +++ b/sound/soc/ep93xx/Makefile @@ -0,0 +1,8 @@ +# EP93xx Platform Support +snd-soc-ep93xx-objs := ep93xx-pcm.o +snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o + +obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o +obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o + +# EP93XX Machine Support diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c new file mode 100644 index 0000000..00b9466 --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-i2s.c @@ -0,0 +1,487 @@ +/* + * linux/sound/soc/ep93xx-i2s.c + * EP93xx I2S driver + * + * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> + * + * Based on the original driver by: + * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail> + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/soc.h> + +#include <mach/hardware.h> +#include <mach/ep93xx-regs.h> +#include <mach/dma.h> + +#include "ep93xx-pcm.h" +#include "ep93xx-i2s.h" + +#define EP93XX_I2S_TXCLKCFG 0x00 +#define EP93XX_I2S_RXCLKCFG 0x04 +#define EP93XX_I2S_GLCTRL 0x0C + +#define EP93XX_I2S_TXLINCTRLDATA 0x28 +#define EP93XX_I2S_TXCTRL 0x2C +#define EP93XX_I2S_TXWRDLEN 0x30 +#define EP93XX_I2S_TX0EN 0x34 + +#define EP93XX_I2S_RXLINCTRLDATA 0x58 +#define EP93XX_I2S_RXCTRL 0x5C +#define EP93XX_I2S_RXWRDLEN 0x60 +#define EP93XX_I2S_RX0EN 0x64 + +#define EP93XX_I2S_WRDLEN_16 (0 << 0) +#define EP93XX_I2S_WRDLEN_24 (1 << 0) +#define EP93XX_I2S_WRDLEN_32 (2 << 0) + +#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ + +#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ +#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ +#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ +#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ +#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ + +struct ep93xx_i2s_info { + struct clk *mclk; + struct clk *sclk; + struct clk *lrclk; + struct ep93xx_pcm_dma_params *dma_params; + struct resource *mem; + void __iomem *regs; +}; + +struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { + [SNDRV_PCM_STREAM_PLAYBACK] = { + .name = "i2s-pcm-out", + .dma_port = EP93XX_DMA_M2P_PORT_I2S1, + }, + [SNDRV_PCM_STREAM_CAPTURE] = { + .name = "i2s-pcm-in", + .dma_port = EP93XX_DMA_M2P_PORT_I2S1, + }, +}; + +static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, + unsigned reg, unsigned val) +{ + __raw_writel(val, info->regs + reg); +} + +static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, + unsigned reg) +{ + return __raw_readl(info->regs + reg); +} + +static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Enable clocks */ + clk_enable(info->mclk); + clk_enable(info->sclk); + clk_enable(info->lrclk); + + /* Enable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); + } + + /* Enable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1); +} + +static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + /* Disable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0); + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Disable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); + + /* Disable clocks */ + clk_disable(info->lrclk); + clk_disable(info->sclk); + clk_disable(info->mclk); + } +} + +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + + snd_soc_dai_set_dma_data(cpu_dai, substream, + &info->dma_params[substream->stream]); + return 0; +} + +static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; + + ep93xx_i2s_disable(info, substream->stream); +} + +static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct ep93xx_i2s_info *info = cpu_dai->private_data; + unsigned int clk_cfg, lin_ctrl; + + clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); + lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_LEFT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_RIGHT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* CPU is master */ + clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; + break; + + case SND_SOC_DAIFMT_CBM_CFM: + /* Codec is master */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + /* Negative bit clock, lrclk low on left word */ + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); + break; + + case SND_SOC_DAIFMT_NB_IF: + /* Negative bit clock, lrclk low on right word */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_NF: + /* Positive bit clock, lrclk low on left word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP; + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_IF: + /* Positive bit clock, lrclk low on right word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; + break; + } + + /* Write new register values */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); + return 0; +} + +static int ep93xx_i2s_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_dai *cpu_dai = rtd->dai->cpu_dai; + struct ep93xx_i2s_info *info = cpu_dai->private_data; + unsigned word_len, div, sdiv, lrdiv; + int found = 0, err; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + word_len = EP93XX_I2S_WRDLEN_16; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + word_len = EP93XX_I2S_WRDLEN_24; + break; + + case SNDRV_PCM_FORMAT_S32_LE: + word_len = EP93XX_I2S_WRDLEN_32; + break; + + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); + else + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); + + /* + * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values. + * If the lrclk is pulse length is larger than the word size, then the + * bit clock will be gated for the unused bits. + */ + div = (clk_get_rate(info->mclk) / params_rate(params)) * + params_channels(params); + for (sdiv = 2; sdiv <= 4; sdiv += 2) + for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1) + if (sdiv * lrdiv == div) { + found = 1; + goto out; + } +out: + if (!found) + return -EINVAL; + + err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); + if (err) + return err; + + err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); + if (err) + return err; + + ep93xx_i2s_enable(info, substream->stream); + return 0; +} + +static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + unsigned int freq, int dir) +{ + struct ep93xx_i2s_info *info = cpu_dai->private_data; + + if (dir == SND_SOC_CLOCK_IN || clk_id != 0) + return -EINVAL; + + return clk_set_rate(info->mclk, freq); +} + +#ifdef CONFIG_PM +static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = dai->private_data; + + if (!dai->active) + return; + + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); +} + +static int ep93xx_i2s_resume(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = dai->private_data; + + if (!dai->active) + return; + + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); +} +#else +#define ep93xx_i2s_suspend NULL +#define ep93xx_i2s_resume NULL +#endif + +static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { + .startup = ep93xx_i2s_startup, + .shutdown = ep93xx_i2s_shutdown, + .hw_params = ep93xx_i2s_hw_params, + .set_sysclk = ep93xx_i2s_set_sysclk, + .set_fmt = ep93xx_i2s_set_dai_fmt, +}; + +#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +struct snd_soc_dai ep93xx_i2s_dai = { + .name = "ep93xx-i2s", + .id = 0, + .symmetric_rates= 1, + .suspend = ep93xx_i2s_suspend, + .resume = ep93xx_i2s_resume, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = EP93XX_I2S_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = EP93XX_I2S_FORMATS, + }, + .ops = &ep93xx_i2s_dai_ops, +}; +EXPORT_SYMBOL_GPL(ep93xx_i2s_dai); + +static int ep93xx_i2s_probe(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info; + struct resource *res; + int err; + + info = kzalloc(sizeof(struct ep93xx_i2s_info), GFP_KERNEL); + if (!info) { + err = -ENOMEM; + goto fail; + } + + ep93xx_i2s_dai.dev = &pdev->dev; + ep93xx_i2s_dai.private_data = info; + info->dma_params = ep93xx_i2s_dma_params; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENODEV; + goto fail; + } + + info->mem = request_mem_region(res->start, resource_size(res), + pdev->name); + if (!info->mem) { + err = -EBUSY; + goto fail; + } + + info->regs = ioremap(info->mem->start, resource_size(info->mem)); + if (!info->regs) { + err = -ENXIO; + goto fail_release_mem; + } + + info->mclk = clk_get(&pdev->dev, "mclk"); + if (IS_ERR(info->mclk)) { + err = PTR_ERR(info->mclk); + goto fail_unmap_mem; + } + + info->sclk = clk_get(&pdev->dev, "sclk"); + if (IS_ERR(info->sclk)) { + err = PTR_ERR(info->sclk); + goto fail_put_mclk; + } + + info->lrclk = clk_get(&pdev->dev, "lrclk"); + if (IS_ERR(info->lrclk)) { + err = PTR_ERR(info->lrclk); + goto fail_put_sclk; + } + + err = snd_soc_register_dai(&ep93xx_i2s_dai); + if (err) + goto fail_put_lrclk; + + return 0; + +fail_put_lrclk: + clk_put(info->lrclk); +fail_put_sclk: + clk_put(info->sclk); +fail_put_mclk: + clk_put(info->mclk); +fail_unmap_mem: + iounmap(info->regs); +fail_release_mem: + release_mem_region(info->mem->start, resource_size(info->mem)); + kfree(info); +fail: + return err; +} + +static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; + + snd_soc_unregister_dai(&ep93xx_i2s_dai); + clk_put(info->lrclk); + clk_put(info->sclk); + clk_put(info->mclk); + iounmap(info->regs); + release_mem_region(info->mem->start, resource_size(info->mem)); + kfree(info); + return 0; +} + +static struct platform_driver ep93xx_i2s_driver = { + .probe = ep93xx_i2s_probe, + .remove = __devexit_p(ep93xx_i2s_remove), + .driver = { + .name = "ep93xx-i2s", + .owner = THIS_MODULE, + }, +}; + +static int __init ep93xx_i2s_init(void) +{ + return platform_driver_register(&ep93xx_i2s_driver); +} + +static void __exit ep93xx_i2s_exit(void) +{ + platform_driver_unregister(&ep93xx_i2s_driver); +} + +module_init(ep93xx_i2s_init); +module_exit(ep93xx_i2s_exit); + +MODULE_ALIAS("platform:ep93xx-i2s"); +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("EP93XX I2S driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h new file mode 100644 index 0000000..3bd4ebf --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-i2s.h @@ -0,0 +1,18 @@ +/* + * linux/sound/soc/ep93xx-i2s.h + * EP93xx I2S driver + * + * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.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 _EP93XX_SND_SOC_I2S_H +#define _EP93XX_SND_SOC_I2S_H + +extern struct snd_soc_dai ep93xx_i2s_dai; + +#endif /* _EP93XX_SND_SOC_I2S_H */ diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c new file mode 100644 index 0000000..4ba9384 --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -0,0 +1,319 @@ +/* + * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + * + * Rewritten for the SoC audio subsystem (Based on PXA2xx code): + * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.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/init.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <mach/dma.h> +#include <mach/hardware.h> +#include <mach/ep93xx-regs.h> + +#include "ep93xx-pcm.h" + +static const struct snd_pcm_hardware ep93xx_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = SNDRV_PCM_RATE_8000, + .rate_max = SNDRV_PCM_RATE_48000, + + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + + .buffer_bytes_max = 131072, + .period_bytes_min = 32, + .period_bytes_max = 32768, + .periods_min = 1, + .periods_max = 32, + .fifo_size = 32, +}; + +struct ep93xx_runtime_data +{ + struct ep93xx_dma_m2p_client cl; + struct ep93xx_pcm_dma_params *params; + int pointer_bytes; + struct tasklet_struct period_tasklet; + int periods; + struct ep93xx_dma_buffer buf[32]; +}; + +static void ep93xx_pcm_period_elapsed(unsigned long data) +{ + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; + snd_pcm_period_elapsed(substream); +} + +static void ep93xx_pcm_buffer_started(void *cookie, + struct ep93xx_dma_buffer *buf) +{ +} + +static void ep93xx_pcm_buffer_finished(void *cookie, + struct ep93xx_dma_buffer *buf, + int bytes, int error) +{ + struct snd_pcm_substream *substream = cookie; + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + if (buf == rtd->buf + rtd->periods - 1) + rtd->pointer_bytes = 0; + else + rtd->pointer_bytes += buf->size; + + if (!error) { + ep93xx_dma_m2p_submit_recursive(&rtd->cl, buf); + tasklet_schedule(&rtd->period_tasklet); + } else { + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + } +} + +static int ep93xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; + struct ep93xx_pcm_dma_params *dma_params; + struct ep93xx_runtime_data *rtd; + int ret; + + dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); + snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); + + rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); + if (!rtd) + return -ENOMEM; + + memset(&rtd->period_tasklet, 0, sizeof(rtd->period_tasklet)); + rtd->period_tasklet.func = ep93xx_pcm_period_elapsed; + rtd->period_tasklet.data = (unsigned long)substream; + + rtd->cl.name = dma_params->name; + rtd->cl.flags = dma_params->dma_port | EP93XX_DMA_M2P_IGNORE_ERROR | + ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + EP93XX_DMA_M2P_TX : EP93XX_DMA_M2P_RX); + rtd->cl.cookie = substream; + rtd->cl.buffer_started = ep93xx_pcm_buffer_started; + rtd->cl.buffer_finished = ep93xx_pcm_buffer_finished; + ret = ep93xx_dma_m2p_client_register(&rtd->cl); + if (ret < 0) { + kfree(rtd); + return ret; + } + + substream->runtime->private_data = rtd; + return 0; +} + +static int ep93xx_pcm_close(struct snd_pcm_substream *substream) +{ + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + ep93xx_dma_m2p_client_unregister(&rtd->cl); + kfree(rtd); + return 0; +} + +static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct ep93xx_runtime_data *rtd = runtime->private_data; + size_t totsize = params_buffer_bytes(params); + size_t period = params_period_bytes(params); + int i; + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = totsize; + + rtd->periods = (totsize + period - 1) / period; + for (i = 0; i < rtd->periods; i++) { + rtd->buf[i].bus_addr = runtime->dma_addr + (i * period); + rtd->buf[i].size = period; + if ((i + 1) * period > totsize) + rtd->buf[i].size = totsize - (i * period); + } + + return 0; +} + +static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + int ret; + int i; + + ret = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->pointer_bytes = 0; + for (i = 0; i < rtd->periods; i++) + ep93xx_dma_m2p_submit(&rtd->cl, rtd->buf + i); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ep93xx_dma_m2p_flush(&rtd->cl); + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct ep93xx_runtime_data *rtd = substream->runtime->private_data; + + /* FIXME: implement this with sub-period granularity */ + return bytes_to_frames(runtime, rtd->pointer_bytes); +} + +static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops ep93xx_pcm_ops = { + .open = ep93xx_pcm_open, + .close = ep93xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = ep93xx_pcm_hw_params, + .hw_free = ep93xx_pcm_hw_free, + .trigger = ep93xx_pcm_trigger, + .pointer = ep93xx_pcm_pointer, + .mmap = ep93xx_pcm_mmap, +}; + +static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = ep93xx_pcm_hardware.buffer_bytes_max; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + buf->bytes = size; + + return (buf->area == NULL) ? -ENOMEM : 0; +} + +static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, + buf->addr); + buf->area = NULL; + } +} + +static u64 ep93xx_pcm_dmamask = 0xffffffff; + +static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &ep93xx_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = 0xffffffff; + + if (dai->playback.channels_min) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + return ret; + } + + if (dai->capture.channels_min) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + return ret; + } + + return 0; +} + +struct snd_soc_platform ep93xx_soc_platform = { + .name = "ep93xx-audio", + .pcm_ops = &ep93xx_pcm_ops, + .pcm_new = &ep93xx_pcm_new, + .pcm_free = &ep93xx_pcm_free_dma_buffers, +}; +EXPORT_SYMBOL_GPL(ep93xx_soc_platform); + +static int __init ep93xx_soc_platform_init(void) +{ + return snd_soc_register_platform(&ep93xx_soc_platform); +} + +static void __exit ep93xx_soc_platform_exit(void) +{ + snd_soc_unregister_platform(&ep93xx_soc_platform); +} + +module_init(ep93xx_soc_platform_init); +module_exit(ep93xx_soc_platform_exit); + +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h new file mode 100644 index 0000000..4ffdd3f --- /dev/null +++ b/sound/soc/ep93xx/ep93xx-pcm.h @@ -0,0 +1,22 @@ +/* + * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + * + * 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 _EP93XX_SND_SOC_PCM_H +#define _EP93XX_SND_SOC_PCM_H + +struct ep93xx_pcm_dma_params { + char *name; + int dma_port; +}; + +extern struct snd_soc_platform ep93xx_soc_platform; + +#endif /* _EP93XX_SND_SOC_PCM_H */ -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 2/3] EP93xx: Add i2s audio driver 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-08 10:05 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 10:05 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg On Tue, Jun 08, 2010 at 10:01:11PM +1200, Ryan Mallon wrote: > Add pcm and i2s SoC audio drivers for EP93xx > > Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> As I said yesterday I have applied this patch already. If there are any changes in the new version please send incremental patches updating the driver. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 2/3] EP93xx: Add i2s audio driver @ 2010-06-08 10:05 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 10:05 UTC (permalink / raw) To: linux-arm-kernel On Tue, Jun 08, 2010 at 10:01:11PM +1200, Ryan Mallon wrote: > Add pcm and i2s SoC audio drivers for EP93xx > > Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> As I said yesterday I have applied this patch already. If there are any changes in the new version please send incremental patches updating the driver. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 2/3] EP93xx: Add i2s audio driver 2010-06-08 10:05 ` Mark Brown @ 2010-06-08 10:09 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:09 UTC (permalink / raw) To: Mark Brown Cc: john.cooper, chasedouglas, alsa-devel, buytenh, r&d4, hartleys, lrg, marshall, linux-arm-kernel, dhuggins Mark Brown wrote: > On Tue, Jun 08, 2010 at 10:01:11PM +1200, Ryan Mallon wrote: >> Add pcm and i2s SoC audio drivers for EP93xx >> >> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> > > As I said yesterday I have applied this patch already. If there are any > changes in the new version please send incremental patches updating the > driver. There are no changes to the patch which you have picked up, only the other two. I reposted the whole series for completeness. Will post incremental patches if there are changes to patch 2/3. ~Ryan ^ permalink raw reply [flat|nested] 38+ messages in thread
* [alsa-devel] [PATCH 2/3] EP93xx: Add i2s audio driver @ 2010-06-08 10:09 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:09 UTC (permalink / raw) To: linux-arm-kernel Mark Brown wrote: > On Tue, Jun 08, 2010 at 10:01:11PM +1200, Ryan Mallon wrote: >> Add pcm and i2s SoC audio drivers for EP93xx >> >> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> > > As I said yesterday I have applied this patch already. If there are any > changes in the new version please send incremental patches updating the > driver. There are no changes to the patch which you have picked up, only the other two. I reposted the whole series for completeness. Will post incremental patches if there are changes to patch 2/3. ~Ryan ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 2/3] EP93xx: Add i2s audio driver 2010-06-08 10:09 ` [alsa-devel] " Ryan Mallon @ 2010-06-08 10:24 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 10:24 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg On Tue, Jun 08, 2010 at 10:09:27PM +1200, Ryan Mallon wrote: > There are no changes to the patch which you have picked up, only the > other two. I reposted the whole series for completeness. Will post > incremental patches if there are changes to patch 2/3. OK, please add something to that effect to the changelog when reposting without change so I know what's going on. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [alsa-devel] [PATCH 2/3] EP93xx: Add i2s audio driver @ 2010-06-08 10:24 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-08 10:24 UTC (permalink / raw) To: linux-arm-kernel On Tue, Jun 08, 2010 at 10:09:27PM +1200, Ryan Mallon wrote: > There are no changes to the patch which you have picked up, only the > other two. I reposted the whole series for completeness. Will post > incremental patches if there are changes to patch 2/3. OK, please add something to that effect to the changelog when reposting without change so I know what's going on. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 3/3] EP93xx: Add Snapper CL15 i2s audio support 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-08 10:01 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Cc: john.cooper, chasedouglas, broonie, alsa-devel, Ryan Mallon, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Add support for i2s audio on Bluewater Systems Snapper CL15 module Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- arch/arm/mach-ep93xx/snappercl15.c | 1 + sound/soc/ep93xx/Kconfig | 9 ++ sound/soc/ep93xx/Makefile | 3 + sound/soc/ep93xx/snappercl15.c | 150 ++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 0 deletions(-) create mode 100644 sound/soc/ep93xx/snappercl15.c diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 51134b0..fee53a4 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -157,6 +157,7 @@ static void __init snappercl15_init_machine(void) ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, ARRAY_SIZE(snappercl15_i2c_data)); ep93xx_register_fb(&snappercl15_fb_info); + ep93xx_register_i2s(); platform_device_register(&snappercl15_nand_device); } diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig index ba66ac8..f617f56 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/ep93xx/Kconfig @@ -7,3 +7,12 @@ config SND_EP93XX_SOC config SND_EP93XX_SOC_I2S tristate + +config SND_EP93XX_SOC_SNAPPERCL15 + tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" + depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 + select SND_EP93XX_SOC_I2S + select SND_SOC_TLV320AIC23 + help + Say Y or M here if you want to add support for I2S audio on the + Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile index 0239da3..272e60f 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/ep93xx/Makefile @@ -6,3 +6,6 @@ obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o # EP93XX Machine Support +snd-soc-snappercl15-objs := snappercl15.o + +obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c new file mode 100644 index 0000000..6495534 --- /dev/null +++ b/sound/soc/ep93xx/snappercl15.c @@ -0,0 +1,150 @@ +/* + * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module + * + * Copyright (C) 2008 Bluewater Systems Ltd + * Author: Ryan Mallon <ryan@bluewatersys.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> + +#include "../codecs/tlv320aic23.h" +#include "ep93xx-pcm.h" +#include "ep93xx-i2s.h" + +#define CODEC_CLOCK 5644800 + +static int snappercl15_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int err; + + err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + + err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_IN); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_OUT); + if (err) + return err; + + return 0; +} + +static struct snd_soc_ops snappercl15_ops = { + .hw_params = snappercl15_hw_params, +}; + +static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Jack", NULL, "LHPOUT"}, + {"Headphone Jack", NULL, "RHPOUT"}, + + {"LLINEIN", NULL, "Line In"}, + {"RLINEIN", NULL, "Line In"}, + + {"MICIN", NULL, "Mic Jack"}, +}; + +static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, + ARRAY_SIZE(tlv320aic23_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + return 0; +} + +static struct snd_soc_dai_link snappercl15_dai = { + .name = "tlv320aic23", + .stream_name = "AIC23", + .cpu_dai = &ep93xx_i2s_dai, + .codec_dai = &tlv320aic23_dai, + .init = snappercl15_tlv320aic23_init, + .ops = &snappercl15_ops, +}; + +static struct snd_soc_card snd_soc_snappercl15 = { + .name = "Snapper CL15", + .platform = &ep93xx_soc_platform, + .dai_link = &snappercl15_dai, + .num_links = 1, +}; + +static struct snd_soc_device snappercl15_snd_devdata = { + .card = &snd_soc_snappercl15, + .codec_dev = &soc_codec_dev_tlv320aic23, +}; + +static struct platform_device *snappercl15_snd_device; + +static int __init snappercl15_init(void) +{ + int ret; + + if (!machine_is_snapper_cl15()) + return -ENODEV; + + ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, + EP93XX_SYSCON_I2SCLKDIV_ORIDE | + EP93XX_SYSCON_I2SCLKDIV_SPOL); + if (ret) + return ret; + + snappercl15_snd_device = platform_device_alloc("soc-audio", -1); + if (!snappercl15_snd_device) + return -ENOMEM; + + platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); + snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev; + ret = platform_device_add(snappercl15_snd_device); + if (ret) + platform_device_put(snappercl15_snd_device); + + return ret; +} + +static void __exit snappercl15_exit(void) +{ + platform_device_unregister(snappercl15_snd_device); + ep93xx_i2s_release(); +} + +module_init(snappercl15_init); +module_exit(snappercl15_exit); + +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); +MODULE_LICENSE("GPL"); + -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 3/3] EP93xx: Add Snapper CL15 i2s audio support @ 2010-06-08 10:01 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-08 10:01 UTC (permalink / raw) To: linux-arm-kernel Add support for i2s audio on Bluewater Systems Snapper CL15 module Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> --- arch/arm/mach-ep93xx/snappercl15.c | 1 + sound/soc/ep93xx/Kconfig | 9 ++ sound/soc/ep93xx/Makefile | 3 + sound/soc/ep93xx/snappercl15.c | 150 ++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 0 deletions(-) create mode 100644 sound/soc/ep93xx/snappercl15.c diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 51134b0..fee53a4 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -157,6 +157,7 @@ static void __init snappercl15_init_machine(void) ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, ARRAY_SIZE(snappercl15_i2c_data)); ep93xx_register_fb(&snappercl15_fb_info); + ep93xx_register_i2s(); platform_device_register(&snappercl15_nand_device); } diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig index ba66ac8..f617f56 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/ep93xx/Kconfig @@ -7,3 +7,12 @@ config SND_EP93XX_SOC config SND_EP93XX_SOC_I2S tristate + +config SND_EP93XX_SOC_SNAPPERCL15 + tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" + depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 + select SND_EP93XX_SOC_I2S + select SND_SOC_TLV320AIC23 + help + Say Y or M here if you want to add support for I2S audio on the + Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile index 0239da3..272e60f 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/ep93xx/Makefile @@ -6,3 +6,6 @@ obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o # EP93XX Machine Support +snd-soc-snappercl15-objs := snappercl15.o + +obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c new file mode 100644 index 0000000..6495534 --- /dev/null +++ b/sound/soc/ep93xx/snappercl15.c @@ -0,0 +1,150 @@ +/* + * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module + * + * Copyright (C) 2008 Bluewater Systems Ltd + * Author: Ryan Mallon <ryan@bluewatersys.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> + +#include "../codecs/tlv320aic23.h" +#include "ep93xx-pcm.h" +#include "ep93xx-i2s.h" + +#define CODEC_CLOCK 5644800 + +static int snappercl15_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int err; + + err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + + err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_IN); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_OUT); + if (err) + return err; + + return 0; +} + +static struct snd_soc_ops snappercl15_ops = { + .hw_params = snappercl15_hw_params, +}; + +static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Jack", NULL, "LHPOUT"}, + {"Headphone Jack", NULL, "RHPOUT"}, + + {"LLINEIN", NULL, "Line In"}, + {"RLINEIN", NULL, "Line In"}, + + {"MICIN", NULL, "Mic Jack"}, +}; + +static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, + ARRAY_SIZE(tlv320aic23_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + return 0; +} + +static struct snd_soc_dai_link snappercl15_dai = { + .name = "tlv320aic23", + .stream_name = "AIC23", + .cpu_dai = &ep93xx_i2s_dai, + .codec_dai = &tlv320aic23_dai, + .init = snappercl15_tlv320aic23_init, + .ops = &snappercl15_ops, +}; + +static struct snd_soc_card snd_soc_snappercl15 = { + .name = "Snapper CL15", + .platform = &ep93xx_soc_platform, + .dai_link = &snappercl15_dai, + .num_links = 1, +}; + +static struct snd_soc_device snappercl15_snd_devdata = { + .card = &snd_soc_snappercl15, + .codec_dev = &soc_codec_dev_tlv320aic23, +}; + +static struct platform_device *snappercl15_snd_device; + +static int __init snappercl15_init(void) +{ + int ret; + + if (!machine_is_snapper_cl15()) + return -ENODEV; + + ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, + EP93XX_SYSCON_I2SCLKDIV_ORIDE | + EP93XX_SYSCON_I2SCLKDIV_SPOL); + if (ret) + return ret; + + snappercl15_snd_device = platform_device_alloc("soc-audio", -1); + if (!snappercl15_snd_device) + return -ENOMEM; + + platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); + snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev; + ret = platform_device_add(snappercl15_snd_device); + if (ret) + platform_device_put(snappercl15_snd_device); + + return ret; +} + +static void __exit snappercl15_exit(void) +{ + platform_device_unregister(snappercl15_snd_device); + ep93xx_i2s_release(); +} + +module_init(snappercl15_init); +module_exit(snappercl15_exit); + +MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); +MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); +MODULE_LICENSE("GPL"); + -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 0/3] EP93xx: Add i2s audio support 2010-06-08 10:01 ` Ryan Mallon @ 2010-06-09 10:17 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-09 10:17 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg On Tue, Jun 08, 2010 at 10:01:09PM +1200, Ryan Mallon wrote: > Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The > core support has been modified to move setting of the SPOL and ORIDE > bits of the i2sclkdiv register, as well as the i2s pin strapping > configuration, to a new function called ep93xx_i2s_acquire which is > called from the audio board drivers. I've now applied both patches. There was a trivial fixup required for the clocks due to an add/add overlap with the SPI clock - I think it's OK but please check. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-09 10:17 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-09 10:17 UTC (permalink / raw) To: linux-arm-kernel On Tue, Jun 08, 2010 at 10:01:09PM +1200, Ryan Mallon wrote: > Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The > core support has been modified to move setting of the SPOL and ORIDE > bits of the i2sclkdiv register, as well as the i2s pin strapping > configuration, to a new function called ep93xx_i2s_acquire which is > called from the audio board drivers. I've now applied both patches. There was a trivial fixup required for the clocks due to an add/add overlap with the SPI clock - I think it's OK but please check. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/3] EP93xx: Add i2s audio support 2010-06-09 10:17 ` Mark Brown @ 2010-06-09 21:40 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-09 21:40 UTC (permalink / raw) To: Mark Brown Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Mark Brown wrote: > On Tue, Jun 08, 2010 at 10:01:09PM +1200, Ryan Mallon wrote: >> Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The >> core support has been modified to move setting of the SPOL and ORIDE >> bits of the i2sclkdiv register, as well as the i2s pin strapping >> configuration, to a new function called ep93xx_i2s_acquire which is >> called from the audio board drivers. > > I've now applied both patches. There was a trivial fixup required for > the clocks due to an add/add overlap with the SPI clock - I think it's > OK but please check. Stupid question, but where was it applied? I can't find it in any of the branches at: http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-09 21:40 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-09 21:40 UTC (permalink / raw) To: linux-arm-kernel Mark Brown wrote: > On Tue, Jun 08, 2010 at 10:01:09PM +1200, Ryan Mallon wrote: >> Repost of the i2s audio series for ep93xx. Patch 2/3 is unchanged. The >> core support has been modified to move setting of the SPOL and ORIDE >> bits of the i2sclkdiv register, as well as the i2s pin strapping >> configuration, to a new function called ep93xx_i2s_acquire which is >> called from the audio board drivers. > > I've now applied both patches. There was a trivial fixup required for > the clocks due to an add/add overlap with the SPI clock - I think it's > OK but please check. Stupid question, but where was it applied? I can't find it in any of the branches at: http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan at bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/3] EP93xx: Add i2s audio support 2010-06-09 21:40 ` Ryan Mallon @ 2010-06-09 22:22 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-09 22:22 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg On 9 Jun 2010, at 22:40, Ryan Mallon wrote: > Stupid question, but where was it applied? I can't find it in any of the > branches at: > http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary Look in my kernel.org repository referenced in MAINTAINERS git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-09 22:22 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-09 22:22 UTC (permalink / raw) To: linux-arm-kernel On 9 Jun 2010, at 22:40, Ryan Mallon wrote: > Stupid question, but where was it applied? I can't find it in any of the > branches at: > http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary Look in my kernel.org repository referenced in MAINTAINERS git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/3] EP93xx: Add i2s audio support 2010-06-09 22:22 ` Mark Brown @ 2010-06-10 20:46 ` Ryan Mallon -1 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-10 20:46 UTC (permalink / raw) To: Mark Brown Cc: john.cooper, chasedouglas, alsa-devel, linux-arm-kernel, r&d4, hartleys, dhuggins, marshall, buytenh, lrg Mark Brown wrote: > On 9 Jun 2010, at 22:40, Ryan Mallon wrote: > >> Stupid question, but where was it applied? I can't find it in any of the >> branches at: >> http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary > > Look in my kernel.org repository referenced in MAINTAINERS > > git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git Builds and runs fine. Thanks, ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-10 20:46 ` Ryan Mallon 0 siblings, 0 replies; 38+ messages in thread From: Ryan Mallon @ 2010-06-10 20:46 UTC (permalink / raw) To: linux-arm-kernel Mark Brown wrote: > On 9 Jun 2010, at 22:40, Ryan Mallon wrote: > >> Stupid question, but where was it applied? I can't find it in any of the >> branches at: >> http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=summary > > Look in my kernel.org repository referenced in MAINTAINERS > > git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git Builds and runs fine. Thanks, ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan at bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/3] EP93xx: Add i2s audio support 2010-06-10 20:46 ` Ryan Mallon @ 2010-06-11 9:35 ` Mark Brown -1 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-11 9:35 UTC (permalink / raw) To: Ryan Mallon Cc: john.cooper, chasedouglas, alsa-devel, buytenh, r&d4, hartleys, lrg, marshall, linux-arm-kernel, dhuggins On Fri, Jun 11, 2010 at 08:46:29AM +1200, Ryan Mallon wrote: > Builds and runs fine. Excellent, thanks! ^ permalink raw reply [flat|nested] 38+ messages in thread
* [alsa-devel] [PATCH 0/3] EP93xx: Add i2s audio support @ 2010-06-11 9:35 ` Mark Brown 0 siblings, 0 replies; 38+ messages in thread From: Mark Brown @ 2010-06-11 9:35 UTC (permalink / raw) To: linux-arm-kernel On Fri, Jun 11, 2010 at 08:46:29AM +1200, Ryan Mallon wrote: > Builds and runs fine. Excellent, thanks! ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2010-06-11 9:35 UTC | newest] Thread overview: 38+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-06-08 10:01 [PATCH 0/3] EP93xx: Add i2s audio support Ryan Mallon 2010-06-08 10:01 ` Ryan Mallon 2010-06-08 10:01 ` [PATCH 1/3] EP93xx: Add i2s core support Ryan Mallon 2010-06-08 10:01 ` Ryan Mallon 2010-06-08 15:01 ` H Hartley Sweeten 2010-06-08 15:01 ` H Hartley Sweeten 2010-06-08 19:27 ` Ryan Mallon 2010-06-08 19:27 ` Ryan Mallon 2010-06-08 23:21 ` Mark Brown 2010-06-08 23:21 ` Mark Brown 2010-06-08 23:26 ` Ryan Mallon 2010-06-08 23:26 ` Ryan Mallon 2010-06-08 23:29 ` Mark Brown 2010-06-08 23:29 ` Mark Brown 2010-06-08 23:32 ` Ryan Mallon 2010-06-08 23:32 ` Ryan Mallon 2010-06-08 23:26 ` H Hartley Sweeten 2010-06-08 23:26 ` H Hartley Sweeten 2010-06-08 10:01 ` [PATCH 2/3] EP93xx: Add i2s audio driver Ryan Mallon 2010-06-08 10:01 ` Ryan Mallon 2010-06-08 10:05 ` Mark Brown 2010-06-08 10:05 ` Mark Brown 2010-06-08 10:09 ` Ryan Mallon 2010-06-08 10:09 ` [alsa-devel] " Ryan Mallon 2010-06-08 10:24 ` Mark Brown 2010-06-08 10:24 ` [alsa-devel] " Mark Brown 2010-06-08 10:01 ` [PATCH 3/3] EP93xx: Add Snapper CL15 i2s audio support Ryan Mallon 2010-06-08 10:01 ` Ryan Mallon 2010-06-09 10:17 ` [PATCH 0/3] EP93xx: Add " Mark Brown 2010-06-09 10:17 ` Mark Brown 2010-06-09 21:40 ` Ryan Mallon 2010-06-09 21:40 ` Ryan Mallon 2010-06-09 22:22 ` Mark Brown 2010-06-09 22:22 ` Mark Brown 2010-06-10 20:46 ` Ryan Mallon 2010-06-10 20:46 ` Ryan Mallon 2010-06-11 9:35 ` Mark Brown 2010-06-11 9:35 ` [alsa-devel] " Mark Brown
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.