From 3ad3f9322b68c0c04b07fbce4ed6bdcbf051a9b6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E6=9E=97=E8=BE=89=E8=BE=89?= Date: Fri, 28 May 2010 14:51:36 +0000 Subject: [PATCH] add i2s codec pcm driver --- arch/arm/include/asm/dma.h | 5 +- arch/arm/mach-rk2818/board-midsdk.c | 9 +++- arch/arm/mach-rk2818/clock.c | 2 +- arch/arm/mach-rk2818/devices.c | 22 ++++++++- arch/arm/mach-rk2818/devices.h | 1 + arch/arm/mach-rk2818/dma.c | 12 +++++ arch/arm/mach-rk2818/include/mach/board.h | 5 -- sound/soc/Kconfig | 2 +- sound/soc/Makefile | 1 + sound/soc/codecs/wm8988.c | 56 +++++++++++++++++++---- 10 files changed, 96 insertions(+), 19 deletions(-) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index b0f667faf601..008b67fb4297 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -97,7 +97,9 @@ extern void set_dma_sg(unsigned int chan, struct scatterlist *sg, int nr_sg); */ extern void __set_dma_addr(unsigned int chan, void *addr); #define set_dma_addr(chan, addr) \ - __set_dma_addr(chan, bus_to_virt(addr)) + __set_dma_addr(chan, addr) + //__set_dma_addr(chan, bus_to_virt(addr)) + /* Set the DMA byte count for this channel * @@ -132,4 +134,5 @@ extern int get_dma_residue(unsigned int chan); */ extern void set_dma_handler (unsigned int chan, void (*irq_handler) (int, void *), void *data); +extern int dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst); #endif /* __ASM_ARM_DMA_H */ diff --git a/arch/arm/mach-rk2818/board-midsdk.c b/arch/arm/mach-rk2818/board-midsdk.c index 91c7fd467acc..75b94bd1677a 100644 --- a/arch/arm/mach-rk2818/board-midsdk.c +++ b/arch/arm/mach-rk2818/board-midsdk.c @@ -300,7 +300,13 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .flags = 0, }, #endif - {} +#if defined (CONFIG_SND_SOC_WM8988) + { + .type = "wm8988", + .addr = 0x1a, + .flags = 0, + } +#endif }; static struct i2c_board_info __initdata board_i2c1_devices[] = { #if defined (CONFIG_RTC_HYM8563) @@ -400,6 +406,7 @@ static struct platform_device *devices[] __initdata = { &rk2818_device_sdmmc1, #endif &rk2818_device_spim, + &rk2818_device_i2s, #if defined(CONFIG_ANDROID_PMEM) &rk2818_device_pmem, #endif diff --git a/arch/arm/mach-rk2818/clock.c b/arch/arm/mach-rk2818/clock.c index 9298ec18d1f5..1607ebb414f0 100644 --- a/arch/arm/mach-rk2818/clock.c +++ b/arch/arm/mach-rk2818/clock.c @@ -911,7 +911,7 @@ static struct clk_lookup clks[] = { CLK1(deblocking_rv), CLK1(lcdc), CLK1(vip), - CLK1(i2s), + CLK("rk2818_i2s","i2s",&i2s_clk), CLK("rk2818_sdmmc.0", "sdmmc", &sdmmc0_clk), CLK1(ebrom), CLK1(gpio0), diff --git a/arch/arm/mach-rk2818/devices.c b/arch/arm/mach-rk2818/devices.c index 638e9c0eec4c..0b9130859cf3 100644 --- a/arch/arm/mach-rk2818/devices.c +++ b/arch/arm/mach-rk2818/devices.c @@ -325,13 +325,33 @@ struct platform_device rk2818_device_adckey = { .id = -1, .dev.parent = &rk2818_device_adc.dev, }; +/* + *rk2818 i2s + */ +static struct resource resources_i2s[] = { + { + .start = IRQ_NR_I2S, + .end = IRQ_NR_I2S, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK2818_I2S_PHYS, + .end = RK2818_I2S_PHYS + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, +}; +struct platform_device rk2818_device_i2s = { + .name = "rk2818_i2s", + .id = 0, + .num_resources = ARRAY_SIZE(resources_i2s), + .resource = resources_i2s, +}; struct platform_device rk2818_device_battery = { .name = "rk2818-battery", .id = -1, }; - /* * rk2818 dsp device */ diff --git a/arch/arm/mach-rk2818/devices.h b/arch/arm/mach-rk2818/devices.h index 2affc341bee4..4eca8fe1406f 100644 --- a/arch/arm/mach-rk2818/devices.h +++ b/arch/arm/mach-rk2818/devices.h @@ -31,6 +31,7 @@ extern struct platform_device rk2818_device_sdmmc1; extern struct rk2818_sdmmc_platform_data default_sdmmc0_data; extern struct rk2818_sdmmc_platform_data default_sdmmc1_data; extern struct platform_device rk2818_device_dm9k; +extern struct platform_device rk2818_device_i2s; extern struct platform_device rk2818_device_pmem; extern struct platform_device rk2818_device_fb; extern struct platform_device rk2818_device_adc; diff --git a/arch/arm/mach-rk2818/dma.c b/arch/arm/mach-rk2818/dma.c index 684e221e181e..fb0b3ab014a9 100644 --- a/arch/arm/mach-rk2818/dma.c +++ b/arch/arm/mach-rk2818/dma.c @@ -631,6 +631,18 @@ static irqreturn_t rk28_dma_irq_handler(int irq, void *dev_id) } +int dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst) +{ + u32 phy_ch = channel; + if (src != NULL) + *src = read_dma_reg(DWDMA_SAR(phy_ch)); + if (dst != NULL) + *dst = read_dma_reg(DWDMA_DAR(phy_ch)); + + return 0; +} +EXPORT_SYMBOL(dma_getposition); + static struct dma_ops rk2818_dma_ops = { .request = rk28_dma_request, .free = rk28_dma_free, diff --git a/arch/arm/mach-rk2818/include/mach/board.h b/arch/arm/mach-rk2818/include/mach/board.h index ed9651f27cf7..aaac178001c8 100644 --- a/arch/arm/mach-rk2818/include/mach/board.h +++ b/arch/arm/mach-rk2818/include/mach/board.h @@ -23,11 +23,6 @@ /* platform device data structures */ struct platform_device; struct i2c_client; -struct RK2818_mddi_platform_data -{ - void (*panel_power)(int on); - unsigned has_vsync_irq:1; -}; struct rk2818_sdmmc_platform_data { unsigned int host_caps; unsigned int host_ocr_avail; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index b1749bc67979..36258a0b546b 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -36,7 +36,7 @@ source "sound/soc/s3c24xx/Kconfig" source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" source "sound/soc/txx9/Kconfig" - +source "sound/soc/rk2818/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 0c5eac01bf2e..6adaa55b42e9 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC) += s3c24xx/ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += txx9/ +obj-$(CONFIG_SND_SOC) += rk2818/ diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 3f530f8a972a..ca5b56d0fb8b 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -27,8 +27,18 @@ #include #include +#include +#include + #include "wm8988.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) do { } while (0) +#endif + /* * wm8988 register cache * We can't read the WM8988 register space when we @@ -191,6 +201,8 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, else adctl2 |= 0x4; + DBG("Enter::%s----%d, adctl2 = %x\n",__FUNCTION__,__LINE__,adctl2); + return snd_soc_write(codec, WM8988_ADCTL2, adctl2); } @@ -495,7 +507,9 @@ static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct wm8988_priv *wm8988 = codec->private_data; - + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + switch (freq) { case 11289600: case 18432000: @@ -576,6 +590,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } + DBG("Enter::%s----%d iface=%x\n",__FUNCTION__,__LINE__,iface); snd_soc_write(codec, WM8988_IFACE, iface); return 0; } @@ -585,10 +600,11 @@ static int wm8988_pcm_startup(struct snd_pcm_substream *substream, { struct snd_soc_codec *codec = dai->codec; struct wm8988_priv *wm8988 = codec->private_data; - + /* The set of sample rates that can be supported depends on the * MCLK supplied to the CODEC - enforce this. */ + DBG("Enter::%s----%d wm8988->sysclk=%d\n",__FUNCTION__,__LINE__,wm8988->sysclk); if (!wm8988->sysclk) { dev_err(codec->dev, "No MCLK configured, call set_sysclk() on init\n"); @@ -613,7 +629,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; int coeff; - + coeff = get_coeff(wm8988->sysclk, params_rate(params)); if (coeff < 0) { coeff = get_coeff(wm8988->sysclk / 2, params_rate(params)); @@ -640,6 +656,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, iface |= 0x000c; break; } + DBG("Enter::%s----%d iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params)); /* set iface & srate */ snd_soc_write(codec, WM8988_IFACE, iface); @@ -654,7 +671,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7; - + DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute); if (mute) snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8); else @@ -666,7 +683,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; - + DBG("Enter::%s----%d level =%d\n",__FUNCTION__,__LINE__,level); switch (level) { case SND_SOC_BIAS_ON: break; @@ -735,7 +752,7 @@ static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; - + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -747,7 +764,7 @@ static int wm8988_resume(struct platform_device *pdev) int i; u8 data[2]; u16 *cache = codec->reg_cache; - + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /* Sync reg_cache with the hardware */ for (i = 0; i < WM8988_NUM_REG; i++) { if (i == WM8988_RESET) @@ -866,7 +883,13 @@ static int wm8988_register(struct wm8988_priv *wm8988, dev_err(codec->dev, "Failed to issue reset\n"); goto err; } - +#if 1 + /*disable speaker */ + gpio_request(RK2818_PIN_PF7, "WM8988"); + rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL_NAME, IOMUXA_GPIO1_A3B7); + gpio_direction_output(RK2818_PIN_PF7,GPIO_HIGH); + +#endif /* set the update bits (we always update left then right) */ reg = snd_soc_read(codec, WM8988_RADC); snd_soc_write(codec, WM8988_RADC, reg | 0x100); @@ -877,7 +900,22 @@ static int wm8988_register(struct wm8988_priv *wm8988, reg = snd_soc_read(codec, WM8988_ROUT2V); snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100); reg = snd_soc_read(codec, WM8988_RINVOL); - snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); + snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); + + snd_soc_write(codec, WM8988_LOUTM1, 0x120); + snd_soc_write(codec, WM8988_ROUTM2, 0x120); + snd_soc_write(codec, WM8988_LOUTM2, 0x0070); + snd_soc_write(codec, WM8988_ROUTM1, 0x0070); + + snd_soc_write(codec, WM8988_LOUT1V, 0x017f); + snd_soc_write(codec, WM8988_ROUT1V, 0x017f); + snd_soc_write(codec, WM8988_LDAC, 0xff); + snd_soc_write(codec, WM8988_RDAC, 0x1ff);//vol set + + snd_soc_write(codec, WM8988_SRATE,0x100); ///SET MCLK/8 + snd_soc_write(codec, WM8988_PWR1, 0x1cc); ///(0x80|0x40|0x20|0x08|0x04|0x10|0x02)); + snd_soc_write(codec, WM8988_PWR2, 0x1e0); //power r l out1 + wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); -- 2.34.1