mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
update i2s codec
This commit is contained in:
@@ -329,6 +329,16 @@ static struct platform_device *devices[] __initdata = {
|
||||
#ifdef CONFIG_FB_ROCKCHIP
|
||||
&device_fb,
|
||||
#endif
|
||||
#ifdef CONFIG_SND_RK29_SOC_I2S_8CH
|
||||
&rk_device_iis0_8ch,
|
||||
#endif
|
||||
#ifdef CONFIG_SND_RK29_SOC_I2S_2CH
|
||||
&rk_device_iis1_2ch,
|
||||
#endif
|
||||
#ifdef CONFIG_SND_RK_SOC_I2S2_2CH
|
||||
&rk_device_iis2_2ch,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
// i2c
|
||||
@@ -343,7 +353,18 @@ static struct i2c_board_info __initdata i2c0_info[] = {
|
||||
.platform_data = &mma8452_info,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SND_SOC_RK1000)
|
||||
{
|
||||
.type = "rk1000_i2c_codec",
|
||||
.addr = 0x60,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
.type = "rk1000_control",
|
||||
.addr = 0x40,
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -792,6 +792,104 @@ static struct platform_device device_ipp = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SND_RK29_SOC_I2S
|
||||
static struct resource rk_iis0_8ch_resource[] = {
|
||||
[0] = {
|
||||
.start = RK30_I2S0_8CH_PHYS,
|
||||
.end = RK30_I2S0_8CH_PHYS + RK30_I2S0_8CH_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S0_8CH_TX,
|
||||
.end = DMACH_I2S0_8CH_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S0_8CH_RX,
|
||||
.end = DMACH_I2S0_8CH_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = IRQ_I2S0_8CH,
|
||||
.end = IRQ_I2S0_8CH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device rk_device_iis0_8ch = {
|
||||
.name = "rk29_i2s",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(rk_iis0_8ch_resource),
|
||||
.resource = rk_iis0_8ch_resource,
|
||||
};
|
||||
|
||||
static struct resource rk_iis1_2ch_resource[] = {
|
||||
[0] = {
|
||||
.start = RK30_I2S1_2CH_PHYS,
|
||||
.end = RK30_I2S1_2CH_PHYS + RK30_I2S1_2CH_SIZE -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S1_2CH_TX,
|
||||
.end = DMACH_I2S1_2CH_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S1_2CH_RX,
|
||||
.end = DMACH_I2S1_2CH_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = IRQ_I2S1_2CH,
|
||||
.end = IRQ_I2S1_2CH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device rk_device_iis1_2ch = {
|
||||
.name = "rk29_i2s",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(rk_iis1_2ch_resource),
|
||||
.resource = rk_iis1_2ch_resource,
|
||||
};
|
||||
|
||||
static struct resource rk_iis2_2ch_resource[] = {
|
||||
[0] = {
|
||||
.start = RK30_I2S2_2CH_PHYS,
|
||||
.end = RK30_I2S2_2CH_PHYS + RK30_I2S2_2CH_SIZE -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = DMACH_I2S2_2CH_TX,
|
||||
.end = DMACH_I2S2_2CH_TX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = DMACH_I2S2_2CH_RX,
|
||||
.end = DMACH_I2S2_2CH_RX,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[3] = {
|
||||
.start = IRQ_I2S2_2CH,
|
||||
.end = IRQ_I2S2_2CH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device rk_device_iis2_2ch = {
|
||||
.name = "rk29_i2s",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(rk_iis2_2ch_resource),
|
||||
.resource = rk_iis2_2ch_resource,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static struct platform_device rk29_device_pcm = {
|
||||
.name = "rockchip-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KEYS_RK29
|
||||
extern struct rk29_keys_platform_data rk29_keys_pdata;
|
||||
static struct platform_device device_keys = {
|
||||
@@ -891,6 +989,7 @@ static int __init rk30_init_devices(void)
|
||||
#ifdef CONFIG_FIQ_DEBUGGER
|
||||
rk_serial_debug_init(RK30_UART1_PHYS, IRQ_UART1, IRQ_UART_SIGNAL, -1);
|
||||
#endif
|
||||
platform_device_register(&rk29_device_pcm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,4 +46,9 @@ void __init rk30_clock_init(void);
|
||||
|
||||
extern struct sys_timer rk30_timer;
|
||||
|
||||
|
||||
extern struct platform_device rk_device_iis2_2ch;
|
||||
extern struct platform_device rk_device_iis1_2ch;
|
||||
extern struct platform_device rk_device_iis0_8ch;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
#define GPIO0C_GPIO0C3 0
|
||||
#define GPIO0C_I2S1_2CH_LRCK_TX 1
|
||||
#define GPIO0C_GPIO0C2 0
|
||||
#define GPIO0C_I2S_8CH_LRCK_RX 1
|
||||
#define GPIO0C_I2S1_2CH_LRCK_RX 1
|
||||
#define GPIO0C_GPIO0C1 0
|
||||
#define GPIO0C_I2S1_2CH_SCLK 1
|
||||
#define GPIO0C_GPIO0C0 0
|
||||
@@ -87,13 +87,13 @@
|
||||
#define GPIO0D_I2S2_2CH_SDO 1
|
||||
#define GPIO0D_SMC_ADDR1 2
|
||||
#define GPIO0D_GPIO0D4 0
|
||||
#define GPIO0D_I2S1_2CH_SDI 1
|
||||
#define GPIO0D_I2S2_2CH_SDI 1
|
||||
#define GPIO0D_SMC_ADDR0 2
|
||||
#define GPIO0D_GPIO0D3 0
|
||||
#define GPIO0D_I2S1_2CH_LRCK_TX 1
|
||||
#define GPIO0D_I2S2_2CH_LRCK_TX 1
|
||||
#define GPIO0D_SMC_ADV_N 2
|
||||
#define GPIO0D_GPIO0D2 0
|
||||
#define GPIO0D_I2S1_2CH_LRCK_RX 1
|
||||
#define GPIO0D_I2S2_2CH_LRCK_RX 1
|
||||
#define GPIO0D_SMC_OE_N 2
|
||||
#define GPIO0D_GPIO0D1 0
|
||||
#define GPIO0D_I2S2_2CH_SCLK 1
|
||||
@@ -606,7 +606,7 @@
|
||||
#define GPIO0C5_I2S12CHSDO_NAME "gpio0c5_i2s12chsdo_name"
|
||||
#define GPIO0C4_I2S12CHSDI_NAME "gpio0c4_i2s12chsdi_name"
|
||||
#define GPIO0C3_I2S12CHLRCKTX_NAME "gpio0c3_i2s12chlrcktx_name"
|
||||
#define GPIO0C2_I2S8CHLRCKRX_NAME "gpio0c2_i2s8chlrckrx_name"
|
||||
#define GPIO0C2_I2S12CHLRCKRX_NAME "gpio0c2_i2s12chlrckrx_name"
|
||||
#define GPIO0C1_I2S12CHSCLK_NAME "gpio0c1_i2s12chsclk_name"
|
||||
#define GPIO0C0_I2S12CHCLK_NAME "gpio0c0_i2s12chclk_name"
|
||||
|
||||
@@ -615,9 +615,9 @@
|
||||
#define GPIO0D7_PWM3_NAME "gpio0d7_pwm3_name"
|
||||
#define GPIO0D6_PWM2_NAME "gpio0d6_pwm2_name"
|
||||
#define GPIO0D5_I2S22CHSDO_SMCADDR1_NAME "gpio0d5_i2s22chsdo_smcaddr1_name"
|
||||
#define GPIO0D4_I2S12CHSDI_SMCADDR0_NAME "gpio0d4_i2s12chsdi_smcaddr0_name"
|
||||
#define GPIO0D3_I2S12CHLRCKTX_SMCADVN_NAME "gpio0d3_i2s12chlrcktx_smcadvn_name"
|
||||
#define GPIO0D2_I2S12CHLRCKRX_SMCOEN_NAME "gpio0d2_i2s12chlrckrx_smcoen_name"
|
||||
#define GPIO0D4_I2S22CHSDI_SMCADDR0_NAME "gpio0d4_i2s22chsdi_smcaddr0_name"
|
||||
#define GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME "gpio0d3_i2s22chlrcktx_smcadvn_name"
|
||||
#define GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME "gpio0d2_i2s22chlrckrx_smcoen_name"
|
||||
#define GPIO0D1_I2S22CHSCLK_SMCWEN_NAME "gpio0d1_i2s22chsclk_smcwen_name"
|
||||
#define GPIO0D0_I2S22CHCLK_SMCCSN0_NAME "gpio0d0_i2s22chclk_smccsn0_name"
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ MUX_CFG(GPIO0C6_TRACECLK_SMCADDR2_NAME, GPIO0C, 12, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C5_I2S12CHSDO_NAME, GPIO0C, 10, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C4_I2S12CHSDI_NAME, GPIO0C, 8, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C, 6, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C2_I2S8CHLRCKRX_NAME, GPIO0C, 4, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C, 4, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C, 2, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0C0_I2S12CHCLK_NAME, GPIO0C, 0, 2, 0, DEFAULT)
|
||||
|
||||
@@ -63,9 +63,9 @@ MUX_CFG(GPIO0C0_I2S12CHCLK_NAME, GPIO0C, 0, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D7_PWM3_NAME, GPIO0D, 14, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D6_PWM2_NAME, GPIO0D, 12, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D, 10, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D4_I2S12CHSDI_SMCADDR0_NAME, GPIO0D, 8, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D3_I2S12CHLRCKTX_SMCADVN_NAME, GPIO0D, 6, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D2_I2S12CHLRCKRX_SMCOEN_NAME, GPIO0D, 4, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D, 8, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D, 6, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D, 4, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D, 2, 2, 0, DEFAULT)
|
||||
MUX_CFG(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D, 0, 2, 0, DEFAULT)
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ config SND_SOC_WM9713
|
||||
|
||||
config SND_SOC_RK1000
|
||||
tristate
|
||||
depends on RK1000_CONTROL
|
||||
# depends on RK1000_CONTROL
|
||||
|
||||
# Amp
|
||||
config SND_SOC_LM4857
|
||||
|
||||
667
sound/soc/codecs/rk1000_codec.c
Normal file → Executable file
667
sound/soc/codecs/rk1000_codec.c
Normal file → Executable file
@@ -18,21 +18,32 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <trace/events/asoc.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
#include "rk1000_codec.h"
|
||||
|
||||
#define RK1000_CODEC_PROC
|
||||
#ifdef RK1000_CODEC_PROC
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/vmalloc.h>
|
||||
char debug_write_read = 0;
|
||||
#endif
|
||||
/*
|
||||
* Debug
|
||||
*/
|
||||
#if 0
|
||||
#if 1
|
||||
#define DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
@@ -45,7 +56,9 @@
|
||||
|
||||
#define OUT_CAPLESS (0) //<2F>Ƿ<EFBFBD>Ϊ<EFBFBD><EFBFBD><DEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1:<3A><EFBFBD><DEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0:<3A>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
///static u32 gVolReg = 0x0f; ///0x0f; //<2F><><EFBFBD>ڼ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
|
||||
static struct snd_soc_codec *rk1000_codec_codec;
|
||||
|
||||
//static u32 gVolReg = 0x0f; ///0x0f; //<2F><><EFBFBD>ڼ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
|
||||
//static u32 gCodecVol = 0x0f;
|
||||
static u8 gR0AReg = 0; //<2F><><EFBFBD>ڼ<EFBFBD>¼R0A<30>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ڸı<DAB8><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰͨ<C7B0><CDA8>R0Aֹͣclk
|
||||
static u8 gR0BReg = 0; //<2F><><EFBFBD>ڼ<EFBFBD>¼R0B<30>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ڸı<DAB8><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰͨ<C7B0><CDA8>R0Bֹͣinterplate<74><65>decimation
|
||||
@@ -60,16 +73,18 @@ static const u16 rk1000_codec_reg[] = {
|
||||
0x0005, 0x0004, 0x00fd, 0x00f3, /* 0 */
|
||||
0x0003, 0x0000, 0x0000, 0x0000, /* 4 */
|
||||
0x0000, 0x0005, 0x0000, 0x0000, /* 8 */
|
||||
0x0097, 0x0097, 0x0097, 0x0097, /* 12 */
|
||||
0x0097, 0x0097, 0x00cc, 0x0000, /* 16 */
|
||||
0x0000, 0x00f1, 0x0090, 0x00ff, /* 20 */
|
||||
0x00ff, 0x00ff, 0x009c, 0x0000, /* 24 */
|
||||
0x0000, 0x00ff, 0x00ff, 0x00ff, /* 28 */
|
||||
0x0097, 0x0097, 0x0097, 0x0097, /* 0x0a */
|
||||
0x0097, 0x0097, 0x00cc, 0x0000, /* 0x10 */
|
||||
0x0000, 0x00f1, 0x0090, 0x00ff, /* 0x14 */
|
||||
0x00ff, 0x00ff, 0x009c, 0x0000, /* 0x18 */
|
||||
0x0000, 0x00ff, 0x00ff, 0x00ff, /* 0x1a */
|
||||
};
|
||||
|
||||
|
||||
/* codec private data */
|
||||
struct rk1000_codec_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
|
||||
unsigned int sysclk;
|
||||
struct snd_soc_codec codec;
|
||||
struct snd_pcm_hw_constraint_list *sysclk_constraints;
|
||||
@@ -100,7 +115,7 @@ static unsigned int rk1000_codec_read(struct snd_soc_codec *codec, unsigned int
|
||||
xfer[0].flags = I2C_M_RD;
|
||||
xfer[0].len = 1;
|
||||
xfer[0].buf = ®
|
||||
|
||||
xfer[0].scl_rate = 100*1000;
|
||||
ret = i2c_transfer(client->adapter, xfer, 1);
|
||||
if (ret != 1) {
|
||||
dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
|
||||
@@ -109,6 +124,7 @@ static unsigned int rk1000_codec_read(struct snd_soc_codec *codec, unsigned int
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* write rk1000 register cache
|
||||
*/
|
||||
@@ -126,16 +142,16 @@ static int rk1000_codec_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
{
|
||||
u8 data[2];
|
||||
struct i2c_client *i2c;
|
||||
DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
|
||||
DBG("Enter-%s::reg=0x%02X, value=0x%02X\n",__FUNCTION__, reg, value);
|
||||
data[0] = value & 0x00ff;
|
||||
rk1000_codec_write_reg_cache (codec, reg, value);
|
||||
i2c = (struct i2c_client *)codec->control_data;
|
||||
i2c->addr = (i2c->addr & 0x60)|reg;
|
||||
if (codec->hw_write(codec->control_data, data, 1) == 1){
|
||||
DBG("================%s Run OK================\n",__FUNCTION__,__LINE__);
|
||||
// DBG("================%s Run OK====%d============\n",__FUNCTION__,__LINE__);
|
||||
return 0;
|
||||
}else{
|
||||
DBG("================%s Run EIO================\n",__FUNCTION__,__LINE__);
|
||||
DBG("================%s Run EIO=======%d=========\n",__FUNCTION__,__LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -370,9 +386,9 @@ static int rk1000_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct rk1000_codec_priv *rk1000_codec = codec->private_data;
|
||||
struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
switch (freq) {
|
||||
case 11289600:
|
||||
@@ -463,23 +479,25 @@ static int rk1000_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
static int rk1000_codec_pcm_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct rk1000_codec_priv *rk1000_codec = codec->private_data;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* The set of sample rates that can be supported depends on the
|
||||
* MCLK supplied to the CODEC - enforce this.
|
||||
*/
|
||||
DBG("Enter::%s----%d rk1000_codec->sysclk=%d\n",__FUNCTION__,__LINE__,rk1000_codec->sysclk);
|
||||
if (!rk1000_codec->sysclk) {
|
||||
dev_err(codec->dev,
|
||||
"No MCLK configured, call set_sysclk() on init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
// if (!rk1000_codec->sysclk) {
|
||||
// dev_err(codec->dev,
|
||||
// "No MCLK configured, call set_sysclk() on init\n");
|
||||
// return -EINVAL;
|
||||
// }
|
||||
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
#if 0
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
rk1000_codec->sysclk_constraints);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -488,13 +506,14 @@ static int rk1000_codec_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct rk1000_codec_priv *rk1000_codec = codec->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
u16 iface = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
|
||||
u16 srate = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180;
|
||||
int coeff;
|
||||
|
||||
|
||||
rk1000_codec->sysclk = 12000000;
|
||||
/*by Vincent Hsiung for EQ Vol Change*/
|
||||
#define HW_PARAMS_FLAG_EQVOL_ON 0x21
|
||||
#define HW_PARAMS_FLAG_EQVOL_OFF 0x22
|
||||
@@ -546,64 +565,71 @@ static int rk1000_codec_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
DBG("Enter::%s----%d iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params));
|
||||
|
||||
rk1000_codec_write(codec,ACCELCODEC_R0C, 0x17);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD>clk<6C><6B>EN_INT<4E><54>disable<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>bclk<6C><6B>Ƶֵ<C6B5><D6B5><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD>codec<65>ڲ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>
|
||||
//<2F><><EFBFBD>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҿ<EFBFBD><D2BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>codec<65><63>I2S_DATAOUT<55>Ͽ<EFBFBD>Ҳһ<D2B2><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rk1000_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD>clk<6C><6B>EN_INT<4E><54>disable<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>bclk<6C><6B>Ƶֵ<C6B5><D6B5><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD>codec<65>ڲ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>
|
||||
//<2F><><EFBFBD>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҿ<EFBFBD><D2BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>codec<65><63>I2S_DATAOUT<55>Ͽ<EFBFBD>Ҳһ<D2B2><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rk1000_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00
|
||||
|
||||
/* set iface & srate */
|
||||
rk1000_codec_write(codec, ACCELCODEC_R09, iface);
|
||||
if (coeff >= 0){
|
||||
rk1000_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE);
|
||||
rk1000_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk);
|
||||
if (coeff >= 0)
|
||||
{
|
||||
// rk1000_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE);
|
||||
rk1000_codec_write(codec, ACCELCODEC_R0A, 0xa0);
|
||||
// rk1000_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk);
|
||||
}
|
||||
rk1000_codec_write(codec,ACCELCODEC_R0B, gR0BReg);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R0B, gR0BReg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PhaseOut(struct snd_soc_codec *codec,u32 nStep, u32 us)
|
||||
{
|
||||
DBG("%s[%d]\n",__FUNCTION__,__LINE__);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0x0F|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0x0F|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR
|
||||
udelay(us);
|
||||
}
|
||||
|
||||
void PhaseIn(struct snd_soc_codec *codec,u32 nStep, u32 us)
|
||||
{
|
||||
DBG("%s[%d]\n",__FUNCTION__,__LINE__);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0x0f|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0x0f|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR
|
||||
udelay(us);
|
||||
}
|
||||
|
||||
static int rk1000_codec_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
|
||||
DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
|
||||
|
||||
if (mute){
|
||||
PhaseOut(codec,1, 5000);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
|
||||
}else{
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); ///|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE);
|
||||
PhaseIn(codec,1, 5000);
|
||||
///if(gCodecVol != 0){
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
|
||||
//}
|
||||
rk1000_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM
|
||||
#if 0
|
||||
/*disable speaker */
|
||||
rockchip_mux_api_set(SPK_IOMUX_PIN_NAME, SPK_IOMUX_PIN_DIR);
|
||||
GPIOSetPinDirection(SPK_CTRL_PIN,GPIO_OUT);
|
||||
GPIOSetPinLevel(SPK_CTRL_PIN,GPIO_HIGH);
|
||||
#endif
|
||||
if (mute)
|
||||
{
|
||||
PhaseOut(codec,1, 5000);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
|
||||
}
|
||||
else
|
||||
{
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); ///|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE);
|
||||
PhaseIn(codec,1, 5000);
|
||||
// if(gCodecVol != 0)
|
||||
{
|
||||
rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
|
||||
}
|
||||
return 0;
|
||||
rk1000_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM
|
||||
#if 0
|
||||
/*disable speaker */
|
||||
rockchip_mux_api_set(SPK_IOMUX_PIN_NAME, SPK_IOMUX_PIN_DIR);
|
||||
GPIOSetPinDirection(SPK_CTRL_PIN,GPIO_OUT);
|
||||
GPIOSetPinLevel(SPK_CTRL_PIN,GPIO_HIGH);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1000_codec_set_bias_level(struct snd_soc_codec *codec,
|
||||
@@ -621,7 +647,7 @@ static int rk1000_codec_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
/* VREF, VMID=2x5k */
|
||||
rk1000_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
|
||||
|
||||
@@ -637,7 +663,7 @@ static int rk1000_codec_set_bias_level(struct snd_soc_codec *codec,
|
||||
rk1000_codec_write(codec, ACCELCODEC_R1D, 0x0000);
|
||||
break;
|
||||
}
|
||||
codec->bias_level = level;
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -654,40 +680,37 @@ static struct snd_soc_dai_ops rk1000_codec_ops = {
|
||||
.digital_mute = rk1000_codec_mute,
|
||||
};
|
||||
|
||||
struct snd_soc_dai rk1000_codec_dai = {
|
||||
.name = "rk1000_codec",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK1000_CODEC_RATES,
|
||||
.formats = RK1000_CODEC_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK1000_CODEC_RATES,
|
||||
.formats = RK1000_CODEC_FORMATS,
|
||||
},
|
||||
.ops = &rk1000_codec_ops,
|
||||
.symmetric_rates = 1,
|
||||
static struct snd_soc_dai_driver rk1000_codec_dai[] = {
|
||||
{
|
||||
.name = "rk1000_codec",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK1000_CODEC_RATES,
|
||||
.formats = RK1000_CODEC_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK1000_CODEC_RATES,
|
||||
.formats = RK1000_CODEC_FORMATS,
|
||||
},
|
||||
.ops = &rk1000_codec_ops,
|
||||
.symmetric_rates = 1,
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(rk1000_codec_dai);
|
||||
|
||||
static int rk1000_codec_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
static int rk1000_codec_suspend(struct snd_soc_codec *codec, 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__);
|
||||
rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1000_codec_resume(struct platform_device *pdev)
|
||||
static int rk1000_codec_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
int i;
|
||||
u8 data[2];
|
||||
struct i2c_client *i2c;
|
||||
@@ -707,113 +730,8 @@ static int rk1000_codec_resume(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec *rk1000_codec_codec;
|
||||
|
||||
static int rk1000_codec_probe(struct platform_device *pdev)
|
||||
static void rk1000_reg_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
|
||||
if (rk1000_codec_codec == NULL) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
socdev->card->codec = rk1000_codec_codec;
|
||||
codec = rk1000_codec_codec;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, rk1000_codec_snd_controls,
|
||||
ARRAY_SIZE(rk1000_codec_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, rk1000_codec_dapm_widgets,
|
||||
ARRAY_SIZE(rk1000_codec_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
|
||||
ret = snd_soc_init_card(socdev);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to register card: %d\n", ret);
|
||||
goto card_err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
card_err:
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
pcm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1000_codec_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_rk1000_codec = {
|
||||
.probe = rk1000_codec_probe,
|
||||
.remove = rk1000_codec_remove,
|
||||
.suspend = rk1000_codec_suspend,
|
||||
.resume = rk1000_codec_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_rk1000_codec);
|
||||
|
||||
static int rk1000_codec_register(struct rk1000_codec_priv *rk1000_codec,
|
||||
enum snd_soc_control_type control)
|
||||
{
|
||||
struct snd_soc_codec *codec = &rk1000_codec->codec;
|
||||
int ret;
|
||||
|
||||
if (rk1000_codec_codec) {
|
||||
dev_err(codec->dev, "Another rk1000 codec is registered\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
codec->private_data = rk1000_codec;
|
||||
codec->name = "RK1000_CODEC";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &rk1000_codec_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->reg_cache_size = ARRAY_SIZE(rk1000_codec->reg_cache);
|
||||
codec->reg_cache = &rk1000_codec->reg_cache;
|
||||
codec->bias_level = SND_SOC_BIAS_OFF;
|
||||
codec->set_bias_level = rk1000_codec_set_bias_level;
|
||||
|
||||
memcpy(codec->reg_cache, rk1000_codec_reg,
|
||||
sizeof(rk1000_codec_reg));
|
||||
|
||||
codec->write = rk1000_codec_write;
|
||||
codec->read = rk1000_codec_read;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
|
||||
//ret = snd_soc_codec_set_cache_io(codec, 0, 8, control);
|
||||
//if (ret < 0) {
|
||||
//dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
//goto err;
|
||||
//}
|
||||
|
||||
#if 0 //fzf rk2818 is SPK_CTL
|
||||
gpio_request(RK2818_PIN_PF7, "rk1000_codec");
|
||||
rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL_NAME, IOMUXA_GPIO1_A3B7);
|
||||
gpio_direction_output(RK2818_PIN_PF7,GPIO_HIGH);
|
||||
|
||||
#endif
|
||||
#if 1
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1D, 0x00);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0xFF); //AOL
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0xFF); //AOR
|
||||
@@ -867,7 +785,7 @@ static int rk1000_codec_register(struct rk1000_codec_priv *rk1000_codec,
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1B, 0x32);
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); ///0x00); //use default value
|
||||
|
||||
///dac mode
|
||||
//dac mode
|
||||
rk1000_codec_write(codec,ACCELCODEC_R17, 0xBF); //AOL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rk1000_codec_write(codec,ACCELCODEC_R18, 0xBF); //AOR
|
||||
|
||||
@@ -892,88 +810,102 @@ static int rk1000_codec_register(struct rk1000_codec_priv *rk1000_codec,
|
||||
rk1000_codec_write(codec,ACCELCODEC_R14, 0x00);
|
||||
gR1314Reg = 0x00;
|
||||
rk1000_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); //0x00); //use default value
|
||||
#endif
|
||||
}
|
||||
|
||||
rk1000_codec_set_bias_level(&rk1000_codec->codec, SND_SOC_BIAS_STANDBY);
|
||||
static int rk1000_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct rk1000_codec_priv *rk1000_codec_priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
rk1000_codec_dai.dev = codec->dev;
|
||||
int ret = 0;
|
||||
DBG("%s::%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
rk1000_codec_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
|
||||
codec->control_data = rk1000_codec_priv->control_data;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, rk1000_codec_priv->control_type);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto err;
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
codec->reg_cache = kmemdup(rk1000_codec_reg, sizeof(rk1000_codec_reg), GFP_KERNEL);
|
||||
if (codec->reg_cache == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_soc_register_dai(&rk1000_codec_dai);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
|
||||
snd_soc_unregister_codec(codec);
|
||||
goto err_codec;
|
||||
}
|
||||
rk1000_reg_init(codec);
|
||||
// snd_soc_add_controls(codec, rk1000_codec_snd_controls,
|
||||
// ARRAY_SIZE(rk1000_codec_snd_controls));
|
||||
// snd_soc_dapm_new_controls(codec, rk1000_codec_dapm_widgets,
|
||||
// ARRAY_SIZE(rk1000_codec_dapm_widgets));
|
||||
// snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
return 0;
|
||||
|
||||
err_codec:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err:
|
||||
kfree(rk1000_codec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rk1000_codec_unregister(struct rk1000_codec_priv *rk1000_codec)
|
||||
static int rk1000_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
rk1000_codec_set_bias_level(&rk1000_codec->codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_unregister_dai(&rk1000_codec_dai);
|
||||
snd_soc_unregister_codec(&rk1000_codec->codec);
|
||||
kfree(rk1000_codec);
|
||||
rk1000_codec_codec = NULL;
|
||||
struct rk1000_codec_priv *rk1000_codec_priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
kfree(rk1000_codec_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
static int rk1000_codec_i2c_probe(struct i2c_client *i2c,
|
||||
static struct snd_soc_codec_driver soc_codec_dev_rk1000_codec = {
|
||||
.probe = rk1000_codec_probe,
|
||||
.remove = rk1000_codec_remove,
|
||||
.suspend = rk1000_codec_suspend,
|
||||
.resume = rk1000_codec_resume,
|
||||
.set_bias_level = rk1000_codec_set_bias_level,
|
||||
.read = rk1000_codec_read,
|
||||
.write = rk1000_codec_write,
|
||||
// .readable_register = rk1000_codec_read_reg_cache,
|
||||
// .writable_register = rk1000_codec_write_reg_cache,
|
||||
// .volatile_register = wm8994_volatile,
|
||||
.reg_cache_size = ARRAY_SIZE(rk1000_codec_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = rk1000_codec_reg,
|
||||
};
|
||||
|
||||
#ifdef RK1000_CODEC_PROC
|
||||
static int rk1000_codec_proc_init(void);
|
||||
#endif
|
||||
|
||||
static __devinit int rk1000_codec_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rk1000_codec_priv *rk1000_codec;
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
int ret;
|
||||
DBG("%s::%d\n",__FUNCTION__,__LINE__);
|
||||
rk1000_codec = kzalloc(sizeof(struct rk1000_codec_priv), GFP_KERNEL);
|
||||
if (rk1000_codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &rk1000_codec->codec;
|
||||
|
||||
i2c_set_clientdata(i2c, rk1000_codec);
|
||||
codec->control_data = i2c;
|
||||
rk1000_codec->control_type = SND_SOC_I2C;
|
||||
rk1000_codec->control_data = i2c;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rk1000_codec,
|
||||
rk1000_codec_dai, ARRAY_SIZE(rk1000_codec_dai));
|
||||
if (ret < 0)
|
||||
kfree(rk1000_codec);
|
||||
|
||||
#ifdef RK1000_CODEC_PROC
|
||||
rk1000_codec_proc_init();
|
||||
#endif
|
||||
|
||||
codec->dev = &i2c->dev;
|
||||
|
||||
return rk1000_codec_register(rk1000_codec, SND_SOC_I2C);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1000_codec_i2c_remove(struct i2c_client *client)
|
||||
static __devexit int rk1000_codec_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rk1000_codec_priv *rk1000_codec = i2c_get_clientdata(client);
|
||||
rk1000_codec_unregister(rk1000_codec);
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int rk1000_codec_i2c_suspend(struct i2c_client *client, pm_message_t msg)
|
||||
{
|
||||
return snd_soc_suspend_device(&client->dev);
|
||||
}
|
||||
|
||||
static int rk1000_codec_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
return snd_soc_resume_device(&client->dev);
|
||||
}
|
||||
#else
|
||||
#define rk1000_codec_i2c_suspend NULL
|
||||
#define rk1000_codec_i2c_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id rk1000_codec_i2c_id[] = {
|
||||
{ "rk1000_i2c_codec", 0 },
|
||||
{ }
|
||||
@@ -987,21 +919,15 @@ static struct i2c_driver rk1000_codec_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rk1000_codec_i2c_probe,
|
||||
.remove = rk1000_codec_i2c_remove,
|
||||
.suspend = rk1000_codec_i2c_suspend,
|
||||
.resume = rk1000_codec_i2c_resume,
|
||||
.remove = __devexit_p(rk1000_codec_i2c_remove),
|
||||
.id_table = rk1000_codec_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static int __init rk1000_codec_modinit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&rk1000_codec_i2c_driver);
|
||||
if (ret != 0)
|
||||
pr_err("rk1000 codec: Unable to register I2C driver: %d\n", ret);
|
||||
return ret;
|
||||
DBG("%s::%d\n",__FUNCTION__,__LINE__);
|
||||
return i2c_add_driver(&rk1000_codec_i2c_driver);
|
||||
}
|
||||
module_init(rk1000_codec_modinit);
|
||||
|
||||
@@ -1011,6 +937,229 @@ static void __exit rk1000_codec_exit(void)
|
||||
}
|
||||
module_exit(rk1000_codec_exit);
|
||||
|
||||
#ifdef RK1000_CODEC_PROC
|
||||
void rk1000_codec_reg_read(void)
|
||||
{
|
||||
struct snd_soc_codec *codec = rk1000_codec_codec;
|
||||
int i;
|
||||
unsigned int data;
|
||||
|
||||
for (i=0; i<=0x1f; i++){
|
||||
data = rk1000_codec_read(codec, i);
|
||||
printk("reg[0x%x]=0x%x\n",i,data);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t rk1000_codec_proc_write(struct file *file, const char __user *buffer,
|
||||
unsigned long len, void *data)
|
||||
{
|
||||
char *cookie_pot;
|
||||
char *p;
|
||||
int reg;
|
||||
int value;
|
||||
|
||||
cookie_pot = (char *)vmalloc( len );
|
||||
if (!cookie_pot)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (copy_from_user( cookie_pot, buffer, len ))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
switch(cookie_pot[0])
|
||||
{
|
||||
case 'd':
|
||||
case 'D':
|
||||
debug_write_read ++;
|
||||
debug_write_read %= 2;
|
||||
if(debug_write_read != 0)
|
||||
printk("Debug read and write reg on\n");
|
||||
else
|
||||
printk("Debug read and write reg off\n");
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
printk("Read reg debug\n");
|
||||
if(cookie_pot[1] ==':')
|
||||
{
|
||||
debug_write_read = 1;
|
||||
strsep(&cookie_pot,":");
|
||||
while((p=strsep(&cookie_pot,",")))
|
||||
{
|
||||
reg = simple_strtol(p,NULL,16);
|
||||
value = rk1000_codec_read(rk1000_codec_codec,reg);
|
||||
printk("rk1000_codec_read:0x%04x = 0x%04x",reg,value);
|
||||
}
|
||||
debug_write_read = 0;
|
||||
printk("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("Error Read reg debug.\n");
|
||||
printk("For example: echo 'r:22,23,24,25'>wm8994_ts\n");
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
printk("Write reg debug\n");
|
||||
if(cookie_pot[1] ==':')
|
||||
{
|
||||
debug_write_read = 1;
|
||||
strsep(&cookie_pot,":");
|
||||
while((p=strsep(&cookie_pot,"=")))
|
||||
{
|
||||
reg = simple_strtol(p,NULL,16);
|
||||
p=strsep(&cookie_pot,",");
|
||||
value = simple_strtol(p,NULL,16);
|
||||
rk1000_codec_write(rk1000_codec_codec,reg,value);
|
||||
printk("rk1000_codec_write:0x%04x = 0x%04x\n",reg,value);
|
||||
}
|
||||
debug_write_read = 0;
|
||||
printk("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("Error Write reg debug.\n");
|
||||
printk("For example: w:22=0,23=0,24=0,25=0\n");
|
||||
}
|
||||
break;
|
||||
case 'p'://enable pa
|
||||
rk1000_codec_reg_read();
|
||||
break;
|
||||
default:
|
||||
printk("Help for rk1000_codec_ts .\n-->The Cmd list: \n");
|
||||
printk("-->'d&&D' Open or Off the debug\n");
|
||||
printk("-->'r&&R' Read reg debug,Example: echo 'r:22,23,24,25'>rk1000_codec_ts\n");
|
||||
printk("-->'w&&W' Write reg debug,Example: echo 'w:22=0,23=0,24=0,25=0'>rk1000_codec_ts\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static const struct file_operations rk1000_codec_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
//.open = snd_mem_proc_open,
|
||||
//.read = seq_read,
|
||||
//#ifdef CONFIG_PCI
|
||||
// .write = rk1000_codec_proc_write,
|
||||
//#endif
|
||||
//.llseek = seq_lseek,
|
||||
//.release = single_release,
|
||||
};
|
||||
|
||||
static int rk1000_codec_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *rk1000_codec_proc_entry;
|
||||
rk1000_codec_proc_entry = create_proc_entry("driver/rk1000_codec", 0777, NULL);
|
||||
if(rk1000_codec_proc_entry != NULL)
|
||||
{
|
||||
rk1000_codec_proc_entry->write_proc = rk1000_codec_proc_write;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("create rk1000_codec proc error !\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
int reg_send_data(struct i2c_client *client, const char start_reg,
|
||||
const char *buf, int count, unsigned int scl_rate)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msg;
|
||||
char tx_buf[count + 1];
|
||||
|
||||
tx_buf[0] = start_reg;
|
||||
memcpy(tx_buf+1, buf, count);
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.buf = tx_buf;
|
||||
msg.len = count +1;
|
||||
msg.flags = client->flags;
|
||||
msg.scl_rate = scl_rate;
|
||||
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1000_control_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
char data[4] = {0x88, 0x0d, 0x22, 0x00};
|
||||
// reg[0x00] = 0x88, --> ADC_CON
|
||||
// reg[0x01] = 0x0d, --> CODEC_CON
|
||||
// reg[0x02] = 0x22, --> I2C_CON
|
||||
// reg[0x03] = 0x00, --> TVE_CON
|
||||
#ifdef CONFIG_SND_SOC_RK1000
|
||||
data[1] = 0x00;
|
||||
#endif
|
||||
|
||||
DBG("%s::%d\n",__FUNCTION__,__LINE__);
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
{
|
||||
dev_err(&client->dev, "i2c bus does not support the rk1000_control\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
msleep(50);
|
||||
ret = reg_send_data(client, 0x00, data, 4, 100 * 1000);
|
||||
#if 1
|
||||
printk("i2c write ret = 0x%x\n",ret);
|
||||
memset(data,0,sizeof(data));
|
||||
ret = i2c_master_reg8_recv(client, 0, data, (int)4, 20*1000);
|
||||
printk("i2c read reg %x, %x, %x, %x ret=x%x\n",data[0],data[1],data[2],data[3],ret);
|
||||
#endif
|
||||
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1000_control_remove(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rk1000_control_id[] = {
|
||||
{ "rk1000_control", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rk1000_control_id);
|
||||
|
||||
static struct i2c_driver rk1000_control_driver = {
|
||||
.driver = {
|
||||
.name = "rk1000_control",
|
||||
},
|
||||
.probe = rk1000_control_probe,
|
||||
.remove = rk1000_control_remove,
|
||||
.id_table = rk1000_control_id,
|
||||
};
|
||||
|
||||
static int __init rk1000_control_init(void)
|
||||
{
|
||||
return i2c_add_driver(&rk1000_control_driver);
|
||||
}
|
||||
|
||||
static void __exit rk1000_control_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rk1000_control_driver);
|
||||
}
|
||||
|
||||
module_init(rk1000_control_init);
|
||||
module_exit(rk1000_control_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC RK1000 CODEC driver");
|
||||
MODULE_AUTHOR("lhh lhh@rock-chips.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
||||
4
sound/soc/codecs/rk1000_codec.h
Normal file → Executable file
4
sound/soc/codecs/rk1000_codec.h
Normal file → Executable file
@@ -259,7 +259,7 @@
|
||||
#define LINE_2_MIXER_GAIN (0x5) //left and right PA gain
|
||||
#define RK1000_CODEC_NUM_REG 0x20
|
||||
|
||||
extern struct snd_soc_dai rk1000_codec_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_rk1000_codec;
|
||||
//extern struct snd_soc_dai rk1000_codec_dai;
|
||||
//extern struct snd_soc_codec_device soc_codec_dev_rk1000_codec;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
config SND_RK29_SOC
|
||||
tristate "SoC Audio for the rockchip RK29 System-on-Chip"
|
||||
depends on ARCH_RK29 && SND_SOC
|
||||
tristate "SoC Audio for the rockchip RK29/RK30 System-on-Chip"
|
||||
depends on (ARCH_RK29 || ARCH_RK30)&& SND_SOC
|
||||
help
|
||||
Say Y or M if you want to add support for codecs attached to
|
||||
the ROCKCHIP IIS interface. You will also need
|
||||
@@ -9,21 +9,28 @@ config SND_RK29_SOC
|
||||
config SND_RK29_SOC_I2S
|
||||
tristate
|
||||
|
||||
config SND_RK29_SOC_I2S_2CH
|
||||
bool "Soc RK29 I2S 2 Channel support"
|
||||
default n
|
||||
depends on SND_RK29_SOC_I2S
|
||||
help
|
||||
This supports the use of the 2 Channel I2S interface on rk29 processors.
|
||||
|
||||
config SND_RK29_SOC_I2S_8CH
|
||||
bool "Soc RK29 I2S 8 Channel support"
|
||||
bool "Soc RK29 I2S 8 Channel support(I2S0)"
|
||||
default y
|
||||
depends on SND_RK29_SOC_I2S
|
||||
help
|
||||
This supports the use of the 8 Channel I2S interface on rk29 processors.
|
||||
|
||||
if SND_RK29_SOC_I2S_2CH || SND_RK29_SOC_I2S_8CH
|
||||
config SND_RK29_SOC_I2S_2CH
|
||||
bool "Soc RK29 I2S 2 Channel support(I2S1)"
|
||||
default n
|
||||
depends on SND_RK29_SOC_I2S
|
||||
help
|
||||
This supports the use of the 2 Channel I2S interface on rk29 processors.
|
||||
|
||||
config SND_RK_SOC_I2S2_2CH
|
||||
bool "Soc RK29 I2S 2 Channel support(I2S2)"
|
||||
default n
|
||||
depends on SND_RK29_SOC_I2S && ARCH_RK30
|
||||
help
|
||||
This supports the use of the 2 Channel I2S2 interface on rk30 processors.
|
||||
|
||||
if SND_RK29_SOC_I2S_2CH || SND_RK29_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH
|
||||
choice
|
||||
bool "Set i2s on DMA event mode"
|
||||
default SND_I2S_DMA_EVENT_STATIC
|
||||
@@ -37,7 +44,7 @@ endif
|
||||
|
||||
config SND_RK29_SOC_WM8988
|
||||
tristate "SoC I2S Audio support for rockchip - WM8988"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_WM8988
|
||||
help
|
||||
@@ -46,7 +53,7 @@ config SND_RK29_SOC_WM8988
|
||||
|
||||
config SND_RK29_SOC_WM8900
|
||||
tristate "SoC I2S Audio support for rockchip - WM8900"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_WM8900
|
||||
help
|
||||
@@ -54,7 +61,7 @@ config SND_RK29_SOC_WM8900
|
||||
with the WM8900.
|
||||
config SND_RK29_SOC_RT5621
|
||||
tristate "SoC I2S Audio support for rockchip - rt5621"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_RT5621
|
||||
help
|
||||
@@ -62,7 +69,7 @@ config SND_RK29_SOC_RT5621
|
||||
with the rt5621.
|
||||
config SND_RK29_SOC_RT5631
|
||||
tristate "SoC I2S Audio support for rockchip - RT5631"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_RT5631
|
||||
help
|
||||
@@ -71,7 +78,7 @@ config SND_RK29_SOC_RT5631
|
||||
|
||||
config SND_RK29_SOC_RT5625
|
||||
tristate "SoC I2S Audio support for rockchip - RT5625"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_RT5625
|
||||
help
|
||||
@@ -80,7 +87,7 @@ config SND_RK29_SOC_RT5625
|
||||
|
||||
config SND_RK29_SOC_WM8994
|
||||
tristate "SoC I2S Audio support for rockchip - WM8994"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_WM8994
|
||||
help
|
||||
@@ -89,7 +96,7 @@ config SND_RK29_SOC_WM8994
|
||||
|
||||
config SND_RK29_SOC_CS42L52
|
||||
tristate "SoC I2S Audio support for rockchip - CS42L52"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_CS42L52
|
||||
help
|
||||
@@ -98,7 +105,7 @@ config SND_RK29_SOC_CS42L52
|
||||
|
||||
config SND_RK29_SOC_AIC3111
|
||||
tristate "SoC I2S Audio support for rockchip - AIC3111"
|
||||
depends on SND_RK29_SOC && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_TLV320AIC3111
|
||||
help
|
||||
@@ -107,7 +114,7 @@ config SND_RK29_SOC_AIC3111
|
||||
|
||||
config SND_RK29_SOC_RK1000
|
||||
tristate "SoC I2S Audio support for rockchip - RK1000"
|
||||
depends on SND_RK29_SOC && RK1000_CONTROL && I2C_RK29
|
||||
depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30)
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_RK1000
|
||||
help
|
||||
@@ -116,7 +123,8 @@ config SND_RK29_SOC_RK1000
|
||||
|
||||
if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_RT5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 || SND_RK29_SOC_AIC3111
|
||||
choice
|
||||
prompt "Set i2s type"
|
||||
bool "Set i2s type"
|
||||
default SND_RK29_CODEC_SOC_SLAVE
|
||||
config SND_RK29_CODEC_SOC_MASTER
|
||||
tristate "Codec run in Master"
|
||||
|
||||
|
||||
@@ -27,13 +27,21 @@
|
||||
#include <sound/soc.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/rk29-dma-pl330.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/cru.h>
|
||||
|
||||
#else
|
||||
#include <mach/board.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/io.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <plat/dma-pl330.h>
|
||||
#endif
|
||||
#include "rk29_pcm.h"
|
||||
#include "rk29_i2s.h"
|
||||
|
||||
@@ -52,15 +60,15 @@ struct rk29_i2s_info {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
|
||||
u32 feature;
|
||||
u32 feature;
|
||||
|
||||
struct clk *iis_clk;
|
||||
struct clk *iis_pclk;
|
||||
|
||||
unsigned char master;
|
||||
unsigned char master;
|
||||
|
||||
struct rockchip_pcm_dma_params *dma_playback;
|
||||
struct rockchip_pcm_dma_params *dma_capture;
|
||||
struct rockchip_pcm_dma_params *dma_playback;
|
||||
struct rockchip_pcm_dma_params *dma_capture;
|
||||
|
||||
u32 suspend_iismod;
|
||||
u32 suspend_iiscon;
|
||||
@@ -127,7 +135,7 @@ static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = {
|
||||
};
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#ifdef ARCH_RK29
|
||||
static u32 i2s0_clk_enter(void)
|
||||
{
|
||||
u32 clk = cru_readl(CRU_CLKSEL3_CON);
|
||||
@@ -143,7 +151,7 @@ static void i2s0_clk_exit(u32 clk)
|
||||
mdelay(1);
|
||||
}
|
||||
#else
|
||||
static u32 i2s0_clk_enter()
|
||||
static u32 i2s0_clk_enter(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -288,11 +296,11 @@ static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
|
||||
* Set Rockchip I2S DAI format
|
||||
*/
|
||||
static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
unsigned int fmt)
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct rk29_i2s_info *i2s = to_info(cpu_dai);
|
||||
u32 tx_ctl,rx_ctl;
|
||||
|
||||
struct rk29_i2s_info *i2s = to_info(cpu_dai);
|
||||
u32 tx_ctl,rx_ctl;
|
||||
#ifdef ARCH_RK29
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
tx_ctl = readl(&(pheadi2s->I2S_TXCR));
|
||||
@@ -309,26 +317,48 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
default:
|
||||
I2S_DBG("unknwon master/slave format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
u32 iis_ckr_value;//clock generation register
|
||||
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_RSJM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_LSJM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_NOR;
|
||||
break;
|
||||
default:
|
||||
I2S_DBG("Unknown data format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
|
||||
tx_ctl = readl(&(pheadi2s->I2S_TXCR));
|
||||
iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
iis_ckr_value &= ~I2S_MODE_MASK;
|
||||
iis_ckr_value |= I2S_MASTER_MODE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
iis_ckr_value &= ~I2S_MODE_MASK;
|
||||
iis_ckr_value |= I2S_SLAVE_MODE;
|
||||
break;
|
||||
default:
|
||||
I2S_DBG("unknwon master/slave format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
|
||||
#endif
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_RSJM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_LSJM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
|
||||
tx_ctl |= I2S_BUS_MODE_NOR;
|
||||
break;
|
||||
default:
|
||||
I2S_DBG("Unknown data format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
|
||||
#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621)
|
||||
rx_ctl = tx_ctl;
|
||||
rx_ctl &= ~I2S_MODE_MASK;
|
||||
@@ -337,9 +367,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
#else
|
||||
writel(tx_ctl, &(pheadi2s->I2S_TXCR));
|
||||
#endif
|
||||
rx_ctl = tx_ctl & 0x00007FFF;
|
||||
writel(rx_ctl, &(pheadi2s->I2S_RXCR));
|
||||
return 0;
|
||||
rx_ctl = tx_ctl & 0x00007FFF;
|
||||
writel(rx_ctl, &(pheadi2s->I2S_RXCR));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
@@ -354,15 +384,9 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
#endif
|
||||
u32 iismod;
|
||||
u32 dmarc;
|
||||
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
/*by Vincent Hsiung for EQ Vol Change*/
|
||||
#define HW_PARAMS_FLAG_EQVOL_ON 0x21
|
||||
#define HW_PARAMS_FLAG_EQVOL_OFF 0x22
|
||||
if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
u32 iis_ckr_value;//clock generation register
|
||||
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
@@ -383,7 +407,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
/* Working copies of register */
|
||||
iismod = readl(&(pheadi2s->I2S_TXCR));
|
||||
//iismod &= (~((1<<5)-1));
|
||||
|
||||
// iismod &= (~((1<<5)-1));
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
iismod |= SAMPLE_DATA_8bit;
|
||||
@@ -392,33 +417,43 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
iismod |= I2S_DATA_WIDTH(15);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
iismod |= I2S_DATA_WIDTH(19);
|
||||
break;
|
||||
iismod |= I2S_DATA_WIDTH(19);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
iismod |= I2S_DATA_WIDTH(23);
|
||||
break;
|
||||
iismod |= I2S_DATA_WIDTH(23);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
iismod |= I2S_DATA_WIDTH(31);
|
||||
break;
|
||||
}
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
iismod &= ~I2S_SLAVE_MODE;
|
||||
#endif
|
||||
iismod |= I2S_DATA_WIDTH(31);
|
||||
break;
|
||||
}
|
||||
#ifdef ARCH29
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
iismod &= ~I2S_SLAVE_MODE;
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
iismod |= I2S_SLAVE_MODE;
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
iismod |= I2S_SLAVE_MODE;
|
||||
#endif
|
||||
#else
|
||||
iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
iis_ckr_value &= ~I2S_SLAVE_MODE;
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
iis_ckr_value |= I2S_SLAVE_MODE;
|
||||
#endif
|
||||
writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
|
||||
#endif
|
||||
// writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
|
||||
dmarc = readl(&(pheadi2s->I2S_DMACR));
|
||||
|
||||
//writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
|
||||
dmarc = readl(&(pheadi2s->I2S_DMACR));
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dmarc = ((dmarc & 0xFFFFFE00) | 16);
|
||||
else
|
||||
dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dmarc = ((dmarc & 0xFFFFFE00) | 16);
|
||||
else
|
||||
dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
|
||||
|
||||
writel(dmarc, &(pheadi2s->I2S_DMACR));
|
||||
I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
|
||||
writel(dmarc, &(pheadi2s->I2S_DMACR));
|
||||
I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
|
||||
#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621)
|
||||
dmarc = iismod;
|
||||
dmarc &= ~I2S_MODE_MASK;
|
||||
@@ -427,25 +462,24 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
#else
|
||||
writel(iismod, &(pheadi2s->I2S_TXCR));
|
||||
#endif
|
||||
iismod = iismod & 0x00007FFF;
|
||||
writel(iismod, &(pheadi2s->I2S_RXCR));
|
||||
return 0;
|
||||
iismod = iismod & 0x00007FFF;
|
||||
writel(iismod, &(pheadi2s->I2S_RXCR));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai);
|
||||
#else
|
||||
struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai);
|
||||
#endif
|
||||
bool stopI2S = false;
|
||||
bool stopI2S = false;
|
||||
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
switch (cmd) {
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
@@ -467,9 +501,9 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* Set Rockchip Clock source
|
||||
@@ -477,14 +511,14 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st
|
||||
static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct rk29_i2s_info *i2s;
|
||||
struct rk29_i2s_info *i2s;
|
||||
|
||||
i2s = to_info(cpu_dai);
|
||||
i2s = to_info(cpu_dai);
|
||||
|
||||
I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
|
||||
I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
|
||||
/*add scu clk source and enable clk*/
|
||||
clk_set_rate(i2s->iis_clk, freq);
|
||||
return 0;
|
||||
// clk_set_rate(i2s->iis_clk, freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -493,19 +527,20 @@ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
|
||||
int div_id, int div)
|
||||
{
|
||||
struct rk29_i2s_info *i2s;
|
||||
u32 reg;
|
||||
/*
|
||||
struct rk29_i2s_info *i2s;
|
||||
u32 reg;
|
||||
|
||||
i2s = to_info(cpu_dai);
|
||||
i2s = to_info(cpu_dai);
|
||||
|
||||
/*stereo mode MCLK/SCK=4*/
|
||||
//stereo mode MCLK/SCK=4
|
||||
|
||||
reg = readl(&(pheadi2s->I2S_TXCKR));
|
||||
reg = readl(&(pheadi2s->I2S_TXCKR));
|
||||
|
||||
I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
|
||||
I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
|
||||
|
||||
/*when i2s in master mode ,must set codec pll div*/
|
||||
switch (div_id) {
|
||||
//when i2s in master mode ,must set codec pll div
|
||||
switch (div_id) {
|
||||
case ROCKCHIP_DIV_BCLK:
|
||||
reg &= ~I2S_TX_SCLK_DIV_MASK;
|
||||
reg |= I2S_TX_SCLK_DIV(div);
|
||||
@@ -519,36 +554,26 @@ static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
writel(reg, &(pheadi2s->I2S_TXCKR));
|
||||
writel(reg, &(pheadi2s->I2S_RXCKR));
|
||||
return 0;
|
||||
}
|
||||
writel(reg, &(pheadi2s->I2S_TXCKR));
|
||||
writel(reg, &(pheadi2s->I2S_RXCKR));
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid duplicating clock code, allow machine driver to
|
||||
* get the clockrate from here.
|
||||
*/
|
||||
u32 rockchip_i2s_get_clockrate(void)
|
||||
{
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
return 0; ///clk_get_rate(s3c24xx_i2s.iis_clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
//clk_disable(clk);
|
||||
return 0;
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
// clk_disable(clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
//clk_enable(clk);
|
||||
return 0;
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
// clk_enable(clk);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define rockchip_i2s_suspend NULL
|
||||
@@ -578,7 +603,7 @@ static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_d
|
||||
#endif
|
||||
{
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
switch(dai->id) {
|
||||
case 0:
|
||||
rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
|
||||
@@ -605,6 +630,40 @@ static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_d
|
||||
I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
#else
|
||||
switch(dai->id) {
|
||||
case 0:
|
||||
rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI);
|
||||
rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK);
|
||||
rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK);
|
||||
rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX);
|
||||
rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX);
|
||||
rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0);
|
||||
rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1);
|
||||
rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2);
|
||||
rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3);
|
||||
break;
|
||||
case 1:
|
||||
rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK);
|
||||
rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK);
|
||||
rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX);
|
||||
rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX);
|
||||
rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI);
|
||||
rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO);
|
||||
break;
|
||||
case 2:
|
||||
rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK);
|
||||
rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK);
|
||||
rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX);
|
||||
rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX);
|
||||
rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI);
|
||||
rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO);
|
||||
break;
|
||||
default:
|
||||
I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -614,13 +673,13 @@ static int rk29_i2s_probe(struct platform_device *pdev,
|
||||
#else
|
||||
struct snd_soc_dai *dai,
|
||||
#endif
|
||||
struct rk29_i2s_info *i2s,
|
||||
unsigned long base)
|
||||
struct rk29_i2s_info *i2s,
|
||||
unsigned long base)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
struct resource *res;
|
||||
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
|
||||
i2s->dev = dev;
|
||||
|
||||
@@ -674,28 +733,30 @@ static int rk29_i2s_probe(struct platform_device *pdev,
|
||||
|
||||
static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_i2s_info *i2s;
|
||||
struct rk29_i2s_info *i2s;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
struct snd_soc_dai_driver *dai;
|
||||
#else
|
||||
struct snd_soc_dai *dai;
|
||||
#endif
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id);
|
||||
I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id);
|
||||
|
||||
if(pdev->id >= MAX_I2S) {
|
||||
dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if(pdev->id >= MAX_I2S) {
|
||||
dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2s = &rk29_i2s[pdev->id];
|
||||
dai = &rk29_i2s_dai[pdev->id];
|
||||
i2s = &rk29_i2s[pdev->id];
|
||||
dai = &rk29_i2s_dai[pdev->id];
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
|
||||
dai->dev = &pdev->dev;
|
||||
#endif
|
||||
dai->id = pdev->id;
|
||||
dai->symmetric_rates = 1;
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
if(pdev->id == 0) {
|
||||
dai->name = "rk29_i2s.0";
|
||||
dai->playback.channels_min = 2;
|
||||
@@ -705,6 +766,26 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
|
||||
dai->playback.channels_min = 2;
|
||||
dai->playback.channels_max = 2;
|
||||
}
|
||||
#else
|
||||
switch(pdev->id)
|
||||
{
|
||||
case 0:
|
||||
dai->name = "rk29_i2s.0";
|
||||
dai->playback.channels_min = 2;
|
||||
dai->playback.channels_max = 8;
|
||||
break;
|
||||
case 1:
|
||||
dai->name = "rk29_i2s.1";
|
||||
dai->playback.channels_min = 2;
|
||||
dai->playback.channels_max = 2;
|
||||
break;
|
||||
case 2:
|
||||
dai->name = "rk29_i2s.2";
|
||||
dai->playback.channels_min = 2;
|
||||
dai->playback.channels_max = 2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
dai->playback.rates = ROCKCHIP_I2S_RATES;
|
||||
dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
|
||||
dai->capture.channels_min = 2;
|
||||
@@ -716,11 +797,10 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
|
||||
dai->suspend = rockchip_i2s_suspend;
|
||||
dai->resume = rockchip_i2s_resume;
|
||||
|
||||
//i2s->feature |= S3C_FEATURE_CDCLKCON;
|
||||
|
||||
i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id];
|
||||
i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id];
|
||||
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
if (pdev->id == 1) {
|
||||
i2s->dma_capture->channel = DMACH_I2S_2CH_RX;
|
||||
i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF;
|
||||
@@ -732,7 +812,29 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
|
||||
i2s->dma_playback->channel = DMACH_I2S_8CH_TX;
|
||||
i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF;
|
||||
}
|
||||
|
||||
#else
|
||||
switch(pdev->id)
|
||||
{
|
||||
case 0:
|
||||
i2s->dma_capture->channel = DMACH_I2S0_8CH_RX;
|
||||
i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF;
|
||||
i2s->dma_playback->channel = DMACH_I2S0_8CH_TX;
|
||||
i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF;
|
||||
break;
|
||||
case 1:
|
||||
i2s->dma_capture->channel = DMACH_I2S1_2CH_RX;
|
||||
i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF;
|
||||
i2s->dma_playback->channel = DMACH_I2S1_2CH_TX;
|
||||
i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF;
|
||||
break;
|
||||
case 2:
|
||||
i2s->dma_capture->channel = DMACH_I2S2_2CH_RX;
|
||||
i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF;
|
||||
i2s->dma_playback->channel = DMACH_I2S2_2CH_TX;
|
||||
i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
i2s->dma_capture->client = &rk29_dma_client_in;
|
||||
i2s->dma_capture->dma_size = 4;
|
||||
i2s->dma_capture->flag = 0; //add by sxj, used for burst change
|
||||
@@ -752,7 +854,7 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
clk_enable(i2s->iis_clk);
|
||||
clk_set_rate(i2s->iis_clk, 11289600);
|
||||
// clk_set_rate(i2s->iis_clk, 11289600);
|
||||
ret = rk29_i2s_probe(pdev, dai, i2s, 0);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
@@ -771,7 +873,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int __devexit rockchip_i2s_remove(struct platform_device *pdev)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
@@ -779,7 +880,6 @@ static int __devexit rockchip_i2s_remove(struct platform_device *pdev)
|
||||
#else
|
||||
snd_soc_unregister_dai(&rk29_i2s_dai);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -794,8 +894,8 @@ static struct platform_driver rockchip_i2s_driver = {
|
||||
|
||||
static int __init rockchip_i2s_init(void)
|
||||
{
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
|
||||
I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
|
||||
|
||||
return platform_driver_register(&rockchip_i2s_driver);
|
||||
}
|
||||
module_init(rockchip_i2s_init);
|
||||
@@ -815,6 +915,7 @@ MODULE_LICENSE("GPL");
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#ifdef ARCK_RK29
|
||||
static int proc_i2s_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct rk29_i2s_info *i2s=&rk29_i2s[0];
|
||||
@@ -834,6 +935,24 @@ static int proc_i2s_show(struct seq_file *s, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static int proc_i2s_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct rk29_i2s_info *i2s=&rk29_i2s[1];
|
||||
printk("========Show I2S reg========\n");
|
||||
|
||||
printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR)));
|
||||
printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR)));
|
||||
printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR)));
|
||||
printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR)));
|
||||
printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR)));
|
||||
printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR)));
|
||||
printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER)));
|
||||
|
||||
printk("========Show I2S reg========\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static int proc_i2s_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_i2s_show, NULL);
|
||||
@@ -850,7 +969,6 @@ static int __init i2s_proc_init(void)
|
||||
{
|
||||
proc_create("i2s_reg", 0, NULL, &proc_i2s_fops);
|
||||
return 0;
|
||||
|
||||
}
|
||||
late_initcall(i2s_proc_init);
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
|
||||
#ifndef _ROCKCHIP_IIS_H
|
||||
#define _ROCKCHIP_IIS_H
|
||||
@@ -22,10 +23,13 @@
|
||||
#define CHANNEL_2_EN (1<<15)
|
||||
#define CHANNEL_3_EN (2<<15)
|
||||
#define CHANNLE_4_EN (3<<15)
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
#define TX_MODE_MASTER (0<<13)
|
||||
#define TX_MODE_SLAVE (1<<13)
|
||||
|
||||
#else
|
||||
#define TX_MODE_MASTER (0<<27)
|
||||
#define TX_MODE_SLAVE (1<<27)
|
||||
#endif
|
||||
|
||||
#define RESET_TX (1<<17)
|
||||
#define RESET_RX (1<<16)
|
||||
@@ -94,11 +98,15 @@
|
||||
|
||||
#define I2S_HWT_16BIT (0<<14)
|
||||
#define I2S_HWT_32BIT (1<<14)
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
#define I2S_MASTER_MODE (0<<13)
|
||||
#define I2S_SLAVE_MODE (1<<13)
|
||||
#define I2S_MODE_MASK (1<<13)
|
||||
|
||||
#else
|
||||
#define I2S_MASTER_MODE (0<<27)
|
||||
#define I2S_SLAVE_MODE (1<<27)
|
||||
#define I2S_MODE_MASK (1<<27)
|
||||
#endif
|
||||
#define I2S_JUSTIFIED_RIGHT (0<<12)
|
||||
#define I2S_JUSTIFIED_LEFT (1<<12)
|
||||
|
||||
@@ -179,6 +187,7 @@
|
||||
#define I2S_TXR_BUFF 0x20
|
||||
#define I2S_RXR_BUFF 0x24
|
||||
|
||||
#ifdef ARCH_RK29
|
||||
//I2S Registers
|
||||
typedef volatile struct tagIIS_STRUCT
|
||||
{
|
||||
@@ -196,12 +205,28 @@ typedef volatile struct tagIIS_STRUCT
|
||||
unsigned int I2S_TXRST;
|
||||
unsigned int I2S_RXRST;
|
||||
}I2S_REG,*pI2S_REG;
|
||||
#else
|
||||
typedef volatile struct tagIIS_STRUCT
|
||||
{
|
||||
unsigned int I2S_TXCR;//0xF 0
|
||||
unsigned int I2S_RXCR;//0xF 4
|
||||
unsigned int I2S_CKR;//0x3F 8
|
||||
unsigned int I2S_FIFOLR;//c
|
||||
unsigned int I2S_DMACR;//0x001F0110 10
|
||||
unsigned int I2S_INTCR;//0x01F00000 14
|
||||
unsigned int I2S_INTSR;//0x00 18
|
||||
unsigned int I2S_XFER;//0x00000003 1c
|
||||
unsigned int I2S_CLR;//20
|
||||
unsigned int I2S_TXDR;//24
|
||||
unsigned int I2S_RXDR;
|
||||
}I2S_REG,*pI2S_REG;
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
extern struct snd_soc_dai_driver rk29_i2s_dai[];
|
||||
#else
|
||||
extern struct snd_soc_dai rk29_i2s_dai[];
|
||||
#endif
|
||||
//extern void rockchip_add_device_i2s(void);
|
||||
|
||||
#endif /* _ROCKCHIP_IIS_H */
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
@@ -24,10 +25,15 @@
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <mach/hardware.h>
|
||||
#ifdef ARCH_RK29
|
||||
#include <mach/dma.h>
|
||||
|
||||
#else
|
||||
#include <plat/dma-pl330.h>
|
||||
#endif
|
||||
#include "rk29_pcm.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
@@ -173,7 +179,7 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
|
||||
#endif
|
||||
unsigned long totbytes = params_buffer_bytes(params);
|
||||
int ret = 0;
|
||||
// int ret = 0;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
/*by Vincent Hsiung for EQ Vol Change*/
|
||||
@@ -278,7 +284,7 @@ static int rockchip_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
}
|
||||
DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, prtd->params->dma_addr);
|
||||
ret = rk29_dma_config(prtd->params->channel,
|
||||
prtd->params->dma_size, 16);
|
||||
prtd->params->dma_size, 1);
|
||||
|
||||
DBG("Enter:%s, %d, ret = %d, Channel=%d, Size=%d\n",
|
||||
__FUNCTION__, __LINE__, ret, prtd->params->channel,
|
||||
@@ -509,9 +515,8 @@ static int rockchip_pcm_new(struct snd_card *card,
|
||||
struct snd_soc_dai *dai, struct snd_pcm *pcm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
|
||||
if (!card->dev->dma_mask)
|
||||
card->dev->dma_mask = &rockchip_pcm_dmamask;
|
||||
if (!card->dev->coherent_dma_mask)
|
||||
@@ -551,7 +556,7 @@ static struct snd_soc_platform_driver rockchip_pcm_platform = {
|
||||
|
||||
static int __devinit rockchip_pcm_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
return snd_soc_register_platform(&pdev->dev, &rockchip_pcm_platform);
|
||||
}
|
||||
|
||||
@@ -572,7 +577,7 @@ static struct platform_driver rockchip_pcm_driver = {
|
||||
|
||||
static int __init snd_rockchip_pcm_init(void)
|
||||
{
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
return platform_driver_register(&rockchip_pcm_driver);
|
||||
}
|
||||
module_init(snd_rockchip_pcm_init);
|
||||
@@ -593,7 +598,7 @@ EXPORT_SYMBOL_GPL(rk29_soc_platform);
|
||||
|
||||
static int __init rockchip_soc_platform_init(void)
|
||||
{
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
|
||||
return snd_soc_register_platform(&rk29_soc_platform);
|
||||
}
|
||||
module_init(rockchip_soc_platform_init);
|
||||
@@ -610,3 +615,4 @@ MODULE_AUTHOR("rockchip");
|
||||
MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
|
||||
153
sound/soc/rk29/rk29_rk1000codec.c
Normal file → Executable file
153
sound/soc/rk29/rk29_rk1000codec.c
Normal file → Executable file
@@ -19,12 +19,11 @@
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include "../codecs/rk1000_codec.h"
|
||||
#include "rk29_pcm.h"
|
||||
#include "rk29_i2s.h"
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
#define DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
@@ -33,145 +32,97 @@
|
||||
static int rk29_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;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int ret;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
/*by Vincent Hsiung for EQ Vol Change*/
|
||||
#define HW_PARAMS_FLAG_EQVOL_ON 0x21
|
||||
#define HW_PARAMS_FLAG_EQVOL_OFF 0x22
|
||||
if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
|
||||
{
|
||||
ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set codec DAI configuration */
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* set cpu DAI configuration */
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
/* set codec DAI configuration */
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* set cpu DAI configuration */
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
//<2F><><EFBFBD>÷<EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD>֣<EFBFBD><D6A3><EFBFBD>ʱδ<CAB1><CEB4><EFBFBD><EFBFBD>
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_LINE("Audio Out", NULL),
|
||||
SND_SOC_DAPM_LINE("Line in", NULL),
|
||||
SND_SOC_DAPM_MIC("Micn", NULL),
|
||||
SND_SOC_DAPM_MIC("Micp", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map[]= {
|
||||
|
||||
{"Audio Out", NULL, "LOUT1"},
|
||||
{"Audio Out", NULL, "ROUT1"},
|
||||
{"Line in", NULL, "RINPUT1"},
|
||||
{"Line in", NULL, "LINPUT1"},
|
||||
{"Micn", NULL, "RINPUT2"},
|
||||
{"Micp", NULL, "LINPUT2"},
|
||||
};
|
||||
|
||||
/*
|
||||
* Logic for a rk1000 codec as connected on a rockchip board.
|
||||
*/
|
||||
static int rk29_rk1000_codec_init(struct snd_soc_codec *codec)
|
||||
static int rk29_rk1000_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai = &codec->dai[0];
|
||||
int ret;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
|
||||
12000000, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to set WM8988 SYSCLK: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add specific widgets */
|
||||
snd_soc_dapm_new_controls(codec, rk29_dapm_widgets,
|
||||
ARRAY_SIZE(rk29_dapm_widgets));
|
||||
|
||||
/* Set up specific audio path audio_mapnects */
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
snd_soc_dapm_sync(codec);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops rk29_ops = {
|
||||
.hw_params = rk29_hw_params,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link rk29_dai = {
|
||||
.name = "RK1000_CODEC",
|
||||
static struct snd_soc_dai_link rk29_dai[] = {
|
||||
{
|
||||
.name = "RK1000",
|
||||
.stream_name = "RK1000 CODEC PCM",
|
||||
.cpu_dai = &rk29_i2s_dai,
|
||||
.codec_dai = &rk1000_codec_dai,
|
||||
.platform_name = "rockchip-audio",
|
||||
.codec_name = "RK1000_CODEC.0-0060",
|
||||
.codec_dai_name = "rk1000_codec",
|
||||
.cpu_dai_name = "rk29_i2s.1",
|
||||
.init = rk29_rk1000_codec_init,
|
||||
.ops = &rk29_ops,
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_card snd_soc_card_rk29 = {
|
||||
.name = "RK1000_CODEC",
|
||||
.platform = &rk29_soc_platform,
|
||||
.dai_link = &rk29_dai,
|
||||
.num_links = 1,
|
||||
.name = "RK29_RK1000",
|
||||
.dai_link = rk29_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
|
||||
static struct snd_soc_device rk29_snd_devdata = {
|
||||
.card = &snd_soc_card_rk29,
|
||||
.codec_dev = &soc_codec_dev_rk1000_codec,
|
||||
};
|
||||
|
||||
static struct platform_device *rk29_snd_device;
|
||||
|
||||
static int __init audio_card_init(void)
|
||||
{
|
||||
int ret =0;
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
rk29_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!rk29_snd_device) {
|
||||
DBG("platform device allocation failed\n");
|
||||
printk("platform device allocation failed\n");
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata);
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
rk29_snd_devdata.dev = &rk29_snd_device->dev;
|
||||
|
||||
platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);
|
||||
ret = platform_device_add(rk29_snd_device);
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
if (ret) {
|
||||
DBG("platform device add failed\n");
|
||||
platform_device_put(rk29_snd_device);
|
||||
printk("platform device add failed\n");
|
||||
platform_device_put(rk29_snd_device);
|
||||
}
|
||||
printk("audio_card_init end....\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit audio_card_exit(void)
|
||||
{
|
||||
platform_device_unregister(rk29_snd_device);
|
||||
|
||||
Reference in New Issue
Block a user