mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
add i2s codec pcm driver
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user