add i2s codec pcm driver

This commit is contained in:
林辉辉
2010-05-28 14:51:36 +00:00
committed by 黄涛
parent 068c5feda7
commit 3ad3f9322b
10 changed files with 96 additions and 19 deletions

View File

@@ -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 */

View File

@@ -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

View File

@@ -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),

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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"

View File

@@ -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/

View File

@@ -27,8 +27,18 @@
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#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);