1、I2S做从机模式,音频芯片做主模式
由于音频芯片做从模式声音可能会失真,所以必须使得I2S1做从模式,音频芯片做主模式
+ ms84x6 {
+ compatible = "rockchip,ms84x6";
+ pinctrl-0 = <&lk_ms84x6_io>;
+ //ms84x6_sda = <&gpio2 GPIO_A3 GPIO_ACTIVE_HIGH>;//<&gpio0 GPIO_A6 GPIO_ACTIVE_HIGH>;//<&gpio0 GPIO_A3 GPIO_ACTIVE_HIGH>;
+ //ms84x6_scl = <&gpio0 GPIO_D1 GPIO_ACTIVE_HIGH>;//<&gpio0 GPIO_A7 GPIO_ACTIVE_HIGH>;//<&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+ ms84x6_sda = <&gpio0 GPIO_A3 GPIO_ACTIVE_HIGH>;
+ ms84x6_scl = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+ ms84x6_reset= <&gpio3 GPIO_A0 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
&i2s1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s_mclk
+ &i2s_sclk
+ &i2s_lrckrx
+ &i2s_lrcktx
+ &i2s_sdi
+ &i2s_sdo0>;
status = "okay";
};
pcm_audio {
status = "okay";
compatible = "rockchip,rk322x-audio";
dais {
dai0 {
audio-codec = <&pcm_codec>;
audio-controller = <&i2s2>;
format = "i2s";
};
};
};
修改驱动使其为从机模式:
diff --git a/sound/soc/rockchip/rk_i2s.c b/sound/soc/rockchip/rk_i2s.c
index 8eca3f30a8df..1929dc84e4bf 100755
--- a/sound/soc/rockchip/rk_i2s.c
+++ b/sound/soc/rockchip/rk_i2s.c
@@ -45,7 +45,7 @@
#include "rk_i2s.h"
#define CLK_SET_LATER
-#define I2S_DEFAULT_FREQ (11289600)
+#define I2S_DEFAULT_FREQ (12288000)
#define I2S_DMA_BURST_SIZE (16) /* size * width: 16*4 = 64 bytes */
static DEFINE_SPINLOCK(lock);
@@ -64,6 +64,7 @@ struct rk_i2s_dev {
bool tx_start;
bool rx_start;
int xfer_mode; /* 0: i2s, 1: pcm */
+ int i2s_num; // 0-i2s0 , 1-i2s1, 2-i2s1
bool tx_always_on;
#ifdef CLK_SET_LATER
struct delayed_work clk_delayed_work;
@@ -109,7 +110,7 @@ static void rockchip_snd_xfer_stop(struct rk_i2s_dev *i2s)
static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
{
unsigned long flags;
-
+
spin_lock_irqsave(&lock, flags);
dev_dbg(i2s->dev, "%s: %d: on: %d\n", __func__, __LINE__, on);
@@ -129,7 +130,6 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_MASK, I2S_DMACR_TDE_DISABLE);
-
#if 0
if (!i2s->rx_start) {
regmap_update_bits(i2s->regmap, I2S_XFER,
@@ -235,22 +235,27 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
spin_lock_irqsave(&lock, flags);
mask = I2S_CKR_MSS_MASK;
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- /* Codec is slave, so set cpu master */
- val = I2S_CKR_MSS_MASTER;
- break;
- case SND_SOC_DAIFMT_CBM_CFM:
- /* Codec is master, so set cpu slave */
+ printk("wzh i2s->xfer_mode == %d\n", i2s->xfer_mode);
+
+ if (i2s->i2s_num == 1) {
val = I2S_CKR_MSS_SLAVE;
- break;
- default:
- ret = -EINVAL;
- goto err_fmt;
+ printk("i2s->i2s_num == 1\n");
+ } else {
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* Codec is slave, so set cpu master */
+ val = I2S_CKR_MSS_MASTER;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* Codec is master, so set cpu slave */
+ val = I2S_CKR_MSS_SLAVE;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err_fmt;
+ }
}
-
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
-
mask = I2S_TXCR_IBM_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
@@ -606,8 +611,8 @@ static const struct regmap_config rockchip_i2s_regmap_config = {
static int rockchip_i2s_probe(struct platform_device *pdev)
{
- struct device_node *node = pdev->dev.of_node;
struct rk_i2s_dev *i2s;
+ struct device_node *node = pdev->dev.of_node;
struct snd_soc_dai_driver *soc_dai;
struct resource *res;
void __iomem *regs;
@@ -620,7 +625,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
ret = -EINVAL;
goto err;
}
-
+
if (soc_is_rk3126b()) {
int sdi_src = 0;
@@ -653,6 +658,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
goto err;
}
+ i2s->i2s_num = pdev->id;
+
i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
@@ -701,7 +708,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
ret = PTR_ERR(i2s->regmap);
goto err;
}
-
+
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_dma_data.maxburst = I2S_DMA_BURST_SIZE;
@@ -759,7 +766,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
ret = of_property_read_u32(node, "rockchip,xfer-mode", &i2s->xfer_mode);
if (ret < 0)
i2s->xfer_mode = I2S_XFER_MODE;
-
+
if (PCM_XFER_MODE == i2s->xfer_mode) {
regmap_update_bits(i2s->regmap, I2S_TXCR,
I2S_TXCR_TFS_MASK,
@@ -768,7 +775,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
I2S_RXCR_TFS_MASK,
I2S_RXCR_TFS_PCM);
}
-
+
rockchip_snd_txctrl(i2s, 0);
rockchip_snd_rxctrl(i2s, 0);
注意ms8416需要获取采样率时其25脚必须提供外部时钟,这个时钟用的是I2S的MCLK 12.28M;
所以上面也修改了输出时钟是12.28M;
2、ms8416驱动
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/input-polldev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <linux/timex.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
//#include <linux/xxxec.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/wakelock.h>
//#include <linux/pwm.h>
//static struct pwm_device *pwm;
typedef unsigned char uchar;
typedef char schar;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
#define ES7243_IIC_DATA_MAX_NUM 256
#define MS8416_I2C_ADDRESS 0x20 //0x26
struct xxxms8416_iic_data {
uint32_t devAddress;
uint32_t regAddress;
uint8_t index;
uint8_t Flag16bit;
uint8_t data[ES7243_IIC_DATA_MAX_NUM];
uint16_t len;
};
#define VIDIOC_xxxMS8416_READ _IOWR('V', 5, struct xxxms8416_iic_data)
#define VIDIOC_xxxMS8416_WRITE _IOWR('V', 6, struct xxxms8416_iic_data)
#define VIDIOC_xxxMS8416_CONFIG _IOWR('V', 7, struct xxxms8416_iic_data)
#define xxxMS8416_READ_SAMPLE_RATE _IOR('S', 0x01, int)
static int gpio_scl;
static int gpio_sda;
static int gpio_rst;
#define MANI2CFREQ 1
#define SET_SCL0_1 gpio_direction_output(gpio_scl,1)
#define SET_SDA0_1 gpio_direction_output(gpio_sda,1)
#define SET_SCL1_1
#define SET_SDA1_1
#define SET_SCL2_1
#define SET_SDA2_1
#define SET_SCL0_0 gpio_direction_output(gpio_scl,0)
#define SET_SDA0_0 gpio_direction_output(gpio_sda,0)
#define SET_SCL1_0
#define SET_SDA1_0
#define SET_SCL2_0
#define SET_SDA2_0
#define GET_SDA0 gpio_get_value(gpio_sda)
#define GET_SDA1 (0) // Pin INOUT_SDA
#define GET_SDA2 (0) // Pin EEPROM_SDA
#define SCL0_IN
#define SCL0_OUT
#define SDA0_IN gpio_direction_input(gpio_sda)
#define SDA0_OUT
#define SCL1_IN
#define SCL1_OUT
#define SDA1_IN
#define SDA1_OUT
#define SCL2_IN
#define SCL2_OUT
#define SDA2_IN
#define SDA2_OUT
#define MS8416_REG_CONTROL0 0x00
#define MS8416_REG_CONTROL1 0x01
#define MS8416_REG_CONTROL2 0x02
#define MS8416_REG_CONTROL3 0x03
#define MS8416_REG_CONTROL4 0x04
#define MS8416_REG_CONTROL5 0x05
#define MS8416_REG_CONTROL6 0x06
static void I2CDelay(uint16 delay)
{
udelay(delay);
return;
}
// #define I2CDelay(us) delay_us(us)
// #define I2CDelay(us)
/*
PB0-1: index 0 I2C 0:SDA, 1:SCL
PB2-3: index 1 I2C 2:SDA, 3:SCL
PB4-5: index 2 I2C 4:SDA, 5:SCL
*/
static void ManReleaseScl(uint8 index)
{
switch(index)
{
case 0:
SCL0_IN;
break;
case 1:
SCL1_IN;
break;
case 2:
SCL2_IN;
break;
}
}
static void ManDriveScl(uint8 index)
{
switch(index)
{
case 0:
SCL0_OUT;
break;
case 1:
SCL1_OUT;
break;
case 2:
SCL2_OUT;
break;
}
}
static void ManReleaseSda(uint8 index)
{
switch(index)
{
case 0:
SDA0_IN;
break;
case 1:
SDA1_IN;
break;
case 2:
SDA2_IN;
break;
}
}
static void ManDriveSda(uint8 index)
{
switch(index)
{
case 0:
SDA0_OUT;
break;
case 1:
SDA1_OUT;
break;
case 2:
SDA2_OUT;
break;
}
}
static void ManSclHigh(uint8 index)
{
switch(index)
{
case 0:
SET_SCL0_1;
break;
case 1:
SET_SCL1_1;
break;
case 2:
SET_SCL2_1;
break;
}
}
static void ManSclLow(uint8 index)
{
switch(index)
{
case 0:
SET_SCL0_0;
break;
case 1:
SET_SCL1_0;
break;
case 2:
SET_SCL2_0;
break;
}
}
static void ManSdaHigh(uint8 index)
{
switch(index)
{
case 0:
SET_SDA0_1;
break;
case 1:
SET_SDA1_1;
break;
case 2:
SET_SDA2_1;
break;
}
}
static void ManSdaLow(uint8 index)
{
switch(index)
{
case 0:
SET_SDA0_0;
break;
case 1:
SET_SDA1_0;
break;
case 2:
SET_SDA2_0;
break;
}
}
static uint8 GetSdaValue(uint8 index)
{
uint8 value = 0;
switch(index)
{
case 0:
value = GET_SDA0;
break;
case 1:
value = GET_SDA1;
break;
case 2:
value = GET_SDA2;
break;
}
return value;
}
static uint8 ManGetAck(uint8 index)
{
uint8 value = 0;
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManReleaseSda(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
value = GetSdaValue(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
if(value == 0)
ManSdaLow(index);
else
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
return value;
}
static void ManSetAck(uint8 index, uint8 i2cdata)
{
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
if(i2cdata != 0)
ManSdaHigh(index);
else
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(2*MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
}
static void ManI2cStart(uint8 index)
{
ManDriveScl(index);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
}
static void ManI2cStop(uint8 index)
{
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManReleaseScl(index);
ManReleaseSda(index);
}
static void ManI2cRestart(uint8 index)
{
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
}
static uint8 ManI2cSendByte(uint8 index, uint8 i2cdata)
{
uint8 i;
uint32 value;
uint8 ack;
/* Send byte */
for(i=0;i<8;i++)
{
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
value = (i2cdata>>(7-i))&0x01;
if(value == 0)
ManSdaLow(index);
else
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
}
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
/* Release Sda to get ACK */
ManReleaseSda(index);
ack = ManGetAck(index);
ManDriveSda(index);
return ack;
}
static uint8 ManI2cReadByte(uint8 index, uint8 FinalByte)
{
uint8 i;
uint32 value = 0;
uint8 i2cdata = 0;
ManReleaseSda(index);
for(i=0;i<8;i++)
{
ManSclLow(index);
I2CDelay(2*MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
value = GetSdaValue(index);
if(value != 0)
{
i2cdata = (i2cdata<<1)+1;
printk("1\n");
}
else {
i2cdata = i2cdata<<1;
printk("0\n");
}
I2CDelay(MANI2CFREQ);
}
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
if(FinalByte == 0x0)
ManSetAck(index,0);
else
ManSetAck(index,1);
return i2cdata;
}
static uint8 ManI2cWrite(uint32 devAddress, uint32 regAddress, uint8 *i2cdata, uint16 count, uint8 index, uint8 Flag16bit)
{
uint8 value;
uint8 ack = 1;
uint16 i;
ManI2cStart(index);
value = devAddress & 0xfe;
ack = ManI2cSendByte(index, value);
if(Flag16bit == 1)
{
value = (regAddress>>8) & 0xff;
ManI2cSendByte(index, value);
}
value = regAddress & 0xff;
ManI2cSendByte(index, value);
for(i=0;i<count;i++)
{
if(i==count-1)
ManI2cSendByte(index, i2cdata[i]);
else
ManI2cSendByte(index, i2cdata[i]);
}
ManI2cStop(index);
//I2CDelay(0x3f);
if(ack == 0)
return 0;
else
return 1;
}
static uint8 ManI2cRead(uint32 devAddress, uint32 regAddress, uint8 *i2cdata, uint16 count, uint8 index, uint8 Flag16bit)
{
uint8 value;
uint8 ack = 1;
uint16 i;
ManI2cStart(index);
value = devAddress & 0xfe;
ack = ManI2cSendByte(index,value);//
if(Flag16bit == 1)
{
value = (regAddress>>8) & 0xff;
ManI2cSendByte(index, value);
}
value = regAddress & 0xff;
ManI2cSendByte(index,value);
ManI2cStop(index);
ManI2cStart(index);
//ManI2cRestart(index);
value = (devAddress & 0xff) | 0x01;
ManI2cSendByte(index,value);
for(i=0;i<count;i++)
{
if(i==count-1)
i2cdata[i] = ManI2cReadByte(index, 1);
else
i2cdata[i] = ManI2cReadByte(index, 0);
}
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManI2cStop(index);
//I2CDelay(0x3f);
if(ack == 0)
return 0;
else
return 1;
}
static void I2CWRNBYTE_CODEC(unsigned int regAddress,unsigned char data)
{
ManI2cWrite(MS8416_I2C_ADDRESS, regAddress, &data, 1, 0, 0);
}
static void codec_write(unsigned int devAddress,unsigned int regAddress,unsigned char data)
{
//ManI2cWrite(I2C_1, devAddress, regAddress,&data, 1, 0);
ManI2cWrite(MS8416_I2C_ADDRESS, regAddress, &data, 1, 0, 0);
}
static void codec_read(unsigned int regAddress,unsigned char *data)
{
ManI2cRead(MS8416_I2C_ADDRESS, regAddress, data, 1, 0, 0);
}
static int xxxms8416_open(struct inode *inode, struct file *file)
{
return 0;
}
static int xxxms8416_release(struct inode *inode, struct file *file)
{
return 0;
}
#if 0
static int xxxgsv_read(struct inode *inode, struct file *file)
{
//ManI2cRead(gdevAddress, gregAddress, data, count, gindex, gFlag16bit);
return 0;
}
static int xxxgsv_write(struct inode *inode, struct file *file)
{
//ManI2cWrite(gdevAddress, gregAddress, data, count, gindex, gFlag16bit);
return 0;
}
#endif
/************************************
获取当前音频流采样率
SR_NOW 根据RMCK的频率和OMCK的比例得到
以OMCK=24.576M为例
************************************/
typedef enum _tagSampleRate
{
SR_32=32,
SR_44=44,
SR_48=48,
SR_64=64,
SR_88=88,
SR_96=96,
SR_128=128,
SR_176=176,
SR_192=192,
SR_OFF=0xFF,
SR_NONE=0xFF,
}SampleRate;
SampleRate DAC_ReadSPDIFSampleRate(void)
{
uint8_t data[3]={0};
//SR_NOW = DAC_I2C_ReadByte(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL24);
ManI2cRead(MS8416_I2C_ADDRESS, 0x18, &data[0], 1, 0, 0);
printk("22xxxms8416_READ 0x18 : 0x%x \n", data[0]);
data[0] = ( data[0] + 1 ) & 0XFC ;
switch( data[0])
{ //24.576
case 0x2F:
case 0x30:
case 0x31:
printk("128khz\n");
return SR_128;
case 0x5F:
case 0x60:
case 0x61:
printk("64khz\n");
return SR_64;
case 0xBF:
case 0xC0:
case 0xC1:
printk("32khz\n");
return SR_32;
case 0x1F:
case 0x20:
case 0x21:
printk("192khz\n");
return SR_192;
case 0x3F:
case 0x40:
case 0x41:
printk("96khz\n");
return SR_96;
case 0x7F:
case 0x80:
case 0x81:
printk("48khz\n");
return SR_48;
case 0x22:
case 0x23:
case 0x24:
printk("176khz\n");
return SR_176;
case 0x44:
case 0x45:
case 0x46:
case 0x47:
printk("88khz\n");
return SR_88;
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
printk("44khz\n");
return SR_44;
default:
printk("0khz\n");
return SR_NONE;
}
}
static long xxxms8416_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
int rate = 0;
int ret = 0;
switch (cmd) {
case xxxMS8416_READ_SAMPLE_RATE:
rate = DAC_ReadSPDIFSampleRate();
if (copy_to_user((int __user *)arg, &rate, sizeof(int))) {
ret = -EFAULT;
}
default:
break;
}
return ret;
}
static ssize_t xxxms8416_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {
uint8_t data[3]={0};
ManI2cRead(0x20, 0x0B, &data[0], 1, 0, 0);
printk("22xxxms8416_READ 0x0B : 0x%x \n", data[0]);
ManI2cRead(0x20, 0x0D, &data[0], 1, 0, 0);
printk("22xxxms8416_READ 0x0D : 0x%x \n", data[0]);
ManI2cRead(0x20, 0x18, &data[0], 1, 0, 0);
printk("22xxxms8416_READ 0x18 : 0x%x \n", data[0]);
DAC_ReadSPDIFSampleRate();
return 0;
}
static struct file_operations xxxms8416_fops = {
.owner = THIS_MODULE,
.open = xxxms8416_open,
.release = xxxms8416_release,
.unlocked_ioctl = xxxms8416_ioctl,
.read = xxxms8416_read,
//.write = xxxms8416_write,
};
static struct miscdevice xxxms8416_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "xxx_ms",
.fops = &xxxms8416_fops,
};
extern void set_slave_mode();
extern int g_isMS8416;
static int xxxms8416_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int ret;
int err;
uint8_t data[3]={0};
uint8_t reg;
uint8_t i;
//int period;
printk("====xxxms8416_probe==\n");
g_isMS8416 = 1;
gpio_scl = of_get_named_gpio(np, "ms84x6_scl", 0);
if (!gpio_is_valid(gpio_scl)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_scl);
} else {
err = devm_gpio_request(&pdev->dev, gpio_scl, "ms84x6_scl");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_scl\n",
gpio_scl);
ret = err;
}
gpio_direction_output(gpio_scl, 1);
}
gpio_sda = of_get_named_gpio(np, "ms84x6_sda", 0);
if (!gpio_is_valid(gpio_sda)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_sda);
} else {
err = devm_gpio_request(&pdev->dev, gpio_sda, "ms84x6_sda");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_sda\n",
gpio_sda);
ret = err;
}
gpio_direction_output(gpio_sda, 1);
}
gpio_rst = of_get_named_gpio(np, "ms84x6_reset", 0);
if (!gpio_is_valid(gpio_rst)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_rst);
} else {
err = devm_gpio_request(&pdev->dev, gpio_rst, "ms84x6_reset");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_reset\n",
gpio_rst);
ret = err;
}
}
ret = misc_register(&xxxms8416_device);
if (ret) {
pr_err("xxxgsv_probe: xxxms8416_device register failed\n");
goto misc_register_failed;
}
int value = -1;
value = gpio_direction_input(gpio_sda);
if (value >= 0 ){
printk("value = %d gpio_direction_input(gpio_sda);\n",value);
}
value = gpio_get_value(gpio_sda);
printk("wzh gpio_sda value = %d\n", value);
value = gpio_direction_input(gpio_scl);
if (value >= 0) {
printk("value = %d gpio_direction_input(gpio_scl);\n",value);
}
value = gpio_get_value(gpio_scl);
printk("wzh gpio_scl value = %d\n", value);
//reset chip
gpio_direction_output(gpio_rst, 0);
usleep_range(5000, 5100);
gpio_direction_output(gpio_rst, 1);
usleep_range(500, 510);
ManI2cRead(0x20, 0x7f, &data[0], 1, 0, 0); //检查IIC是否连通,地址设置是否正确。
printk("xxxms8416_READ 0x20 : 0x%x \n", data[0]);
usleep_range(500, 510);
ManI2cRead(0x20, 0x7f, &data[0], 1, 0, 0); //检查IIC是否连通,地址设置是否正确。
printk("22xxxms8416_READ 0x20 : 0x%x \n", data[0]);
#if 1
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL0,0x00);
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL1,0x84); //0x84没有输入时候 RMCK自动切换到OMCK SDOUT=0
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL2,0x40); //去加重设为自动
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL3,0x00); //GPIO均没有使用
#if 0//Standby
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL4,0x40); //RMCK =Z
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL5,0x05); //BCxxx=Z LRCK=Z (Slave mode)
#else//work
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL4,0x80|(0<<3)); //RXP0
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL5,0x85); //z1模式
#endif
codec_write(MS8416_I2C_ADDRESS,MS8416_REG_CONTROL6,0x7F); //异常报错全开
#endif
usleep_range(5000, 5100);
ManI2cRead(0x20, MS8416_REG_CONTROL0, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL0 : 0x%x \n", data[0]);
ManI2cRead(0x20, MS8416_REG_CONTROL1, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL1 : 0x%x \n", data[0]);
ManI2cRead(0x20, MS8416_REG_CONTROL2, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL2 : 0x%x \n", data[0]);
ManI2cRead(0x20, MS8416_REG_CONTROL3, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL3 : 0x%x \n", data[0]);
ManI2cRead(0x20, MS8416_REG_CONTROL4, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL4 : 0x%x \n", data[0]);
ManI2cRead(0x20, MS8416_REG_CONTROL5, &data[0], 1, 0, 0);
printk("22xxxms8416_READ MS8416_REG_CONTROL5 : 0x%x \n", data[0]);
printk(KERN_INFO "xxxms8416 driver registered.\n");
return 0;
misc_register_failed:
misc_deregister(&xxxms8416_device);
gpio_free(gpio_scl);
gpio_free(gpio_sda);
return -1;
}
static int xxxms8416_remove(struct platform_device *pdev)
{
misc_deregister(&xxxms8416_device);
gpio_free(gpio_scl);
gpio_free(gpio_sda);
return 0;
}
static struct of_device_id xxxms8416_of_match[] = {
{ .compatible = "rockchip,xxx_ms" },
{ }
};
static struct platform_driver xxxms8416_driver = {
.probe = xxxms8416_probe,
.remove = xxxms8416_remove,
.driver = {
.name = "xxx_ms",
.of_match_table = of_match_ptr(xxxms8416_of_match),
.owner = THIS_MODULE,
},
};
static int xxxms8416_init(void)
{
int retval = 0;
retval = platform_driver_register(&xxxms8416_driver);
if (retval < 0) {
printk(KERN_ERR "%s retval=%d\n", __func__, retval);
return retval;
}
return 0;
}
static void xxxms8416_exit(void)
{
platform_driver_unregister(&xxxms8416_driver);
}
module_init(xxxms8416_init);
module_exit(xxxms8416_exit);
MODULE_AUTHOR("xxx,Inc.");
MODULE_DESCRIPTION("xxxms8416 driver");
MODULE_LICENSE("GPL");
3、ms8406驱动
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/input-polldev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <linux/timex.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
//#include <linux/xxxec.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/wakelock.h>
//#include <linux/pwm.h>
//static struct pwm_device *pwm;
typedef unsigned char uchar;
typedef char schar;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
extern unsigned int g_set_i2s1_mcxxx_fre;
#define ES7243_IIC_DATA_MAX_NUM 256
#define MS8406_I2C_ADDRESS 0x2C
struct xxxms8406_iic_data {
uint32_t devAddress;
uint32_t regAddress;
uint8_t index;
uint8_t Flag16bit;
uint8_t data[ES7243_IIC_DATA_MAX_NUM];
uint16_t len;
};
#define VIDIOC_xxxms8406_READ _IOWR('V', 5, struct xxxms8406_iic_data)
#define VIDIOC_xxxms8406_WRITE _IOWR('V', 6, struct xxxms8406_iic_data)
#define VIDIOC_xxxms8406_CONFIG _IOWR('V', 7, struct xxxms8406_iic_data)
#define MS8406_IOCTL_SET_BIT_RESOLUTION _IOW('G', 1, int)
#define MS8406_IOCTL_SET_SMPLE_RATE _IOW('G', 2, int)
static int gpio_scl;
static int gpio_sda;
static int gpio_rst;
#define MANI2CFREQ 1
#define SET_SCL0_1 gpio_direction_output(gpio_scl,1)
#define SET_SDA0_1 gpio_direction_output(gpio_sda,1)
#define SET_SCL1_1
#define SET_SDA1_1
#define SET_SCL2_1
#define SET_SDA2_1
#define SET_SCL0_0 gpio_direction_output(gpio_scl,0)
#define SET_SDA0_0 gpio_direction_output(gpio_sda,0)
#define SET_SCL1_0
#define SET_SDA1_0
#define SET_SCL2_0
#define SET_SDA2_0
#define GET_SDA0 gpio_get_value(gpio_sda)
#define GET_SDA1 (0) // Pin INOUT_SDA
#define GET_SDA2 (0) // Pin EEPROM_SDA
#define SCL0_IN
#define SCL0_OUT
#define SDA0_IN gpio_direction_input(gpio_sda)
#define SDA0_OUT
#define SCL1_IN
#define SCL1_OUT
#define SDA1_IN
#define SDA1_OUT
#define SCL2_IN
#define SCL2_OUT
#define SDA2_IN
#define SDA2_OUT
#define MS8406_REG_CONTROL0 0x00
#define MS8406_REG_CONTROL1 0x01
#define MS8406_REG_CONTROL2 0x02
#define MS8406_REG_CONTROL3 0x03
#define MS8406_REG_CONTROL4 0x04
#define MS8406_REG_CONTROL5 0x05
#define MS8406_REG_CONTROL6 0x06
#define xxxEC_EN 0
#if xxxEC_EN
#endif
static void I2CDelay(uint16 delay)
{
udelay(delay);
return;
}
// #define I2CDelay(us) delay_us(us)
// #define I2CDelay(us)
/*
PB0-1: index 0 I2C 0:SDA, 1:SCL
PB2-3: index 1 I2C 2:SDA, 3:SCL
PB4-5: index 2 I2C 4:SDA, 5:SCL
*/
static void ManReleaseScl(uint8 index)
{
switch(index)
{
case 0:
SCL0_IN;
break;
case 1:
SCL1_IN;
break;
case 2:
SCL2_IN;
break;
}
}
static void ManDriveScl(uint8 index)
{
switch(index)
{
case 0:
SCL0_OUT;
break;
case 1:
SCL1_OUT;
break;
case 2:
SCL2_OUT;
break;
}
}
static void ManReleaseSda(uint8 index)
{
switch(index)
{
case 0:
SDA0_IN;
break;
case 1:
SDA1_IN;
break;
case 2:
SDA2_IN;
break;
}
}
static void ManDriveSda(uint8 index)
{
switch(index)
{
case 0:
SDA0_OUT;
break;
case 1:
SDA1_OUT;
break;
case 2:
SDA2_OUT;
break;
}
}
static void ManSclHigh(uint8 index)
{
switch(index)
{
case 0:
SET_SCL0_1;
break;
case 1:
SET_SCL1_1;
break;
case 2:
SET_SCL2_1;
break;
}
}
static void ManSclLow(uint8 index)
{
switch(index)
{
case 0:
SET_SCL0_0;
break;
case 1:
SET_SCL1_0;
break;
case 2:
SET_SCL2_0;
break;
}
}
static void ManSdaHigh(uint8 index)
{
switch(index)
{
case 0:
SET_SDA0_1;
break;
case 1:
SET_SDA1_1;
break;
case 2:
SET_SDA2_1;
break;
}
}
static void ManSdaLow(uint8 index)
{
switch(index)
{
case 0:
SET_SDA0_0;
break;
case 1:
SET_SDA1_0;
break;
case 2:
SET_SDA2_0;
break;
}
}
static uint8 GetSdaValue(uint8 index)
{
uint8 value = 0;
switch(index)
{
case 0:
value = GET_SDA0;
break;
case 1:
value = GET_SDA1;
break;
case 2:
value = GET_SDA2;
break;
}
return value;
}
static uint8 ManGetAck(uint8 index)
{
uint8 value = 0;
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManReleaseSda(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
value = GetSdaValue(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
if(value == 0)
ManSdaLow(index);
else
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
return value;
}
static void ManSetAck(uint8 index, uint8 i2cdata)
{
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
if(i2cdata != 0)
ManSdaHigh(index);
else
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(2*MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
}
static void ManI2cStart(uint8 index)
{
ManDriveScl(index);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
}
static void ManI2cStop(uint8 index)
{
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManReleaseScl(index);
ManReleaseSda(index);
}
static void ManI2cRestart(uint8 index)
{
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
}
static uint8 ManI2cSendByte(uint8 index, uint8 i2cdata)
{
uint8 i;
uint32 value;
uint8 ack;
/* Send byte */
for(i=0;i<8;i++)
{
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
value = (i2cdata>>(7-i))&0x01;
if(value == 0)
ManSdaLow(index);
else
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
}
I2CDelay(MANI2CFREQ);
ManSclLow(index);
I2CDelay(MANI2CFREQ);
/* Release Sda to get ACK */
ManReleaseSda(index);
ack = ManGetAck(index);
ManDriveSda(index);
return ack;
}
static uint8 ManI2cReadByte(uint8 index, uint8 FinalByte)
{
uint8 i;
uint32 value = 0;
uint8 i2cdata = 0;
ManReleaseSda(index);
for(i=0;i<8;i++)
{
ManSclLow(index);
I2CDelay(2*MANI2CFREQ);
ManSclHigh(index);
I2CDelay(MANI2CFREQ);
value = GetSdaValue(index);
if(value != 0)
{
i2cdata = (i2cdata<<1)+1;
printk("1\n");
}
else {
i2cdata = i2cdata<<1;
printk("0\n");
}
I2CDelay(MANI2CFREQ);
}
ManSclLow(index);
I2CDelay(MANI2CFREQ);
ManDriveSda(index);
I2CDelay(MANI2CFREQ);
if(FinalByte == 0x0)
ManSetAck(index,0);
else
ManSetAck(index,1);
return i2cdata;
}
static uint8 ManI2cWrite(uint32 devAddress, uint32 regAddress, uint8 *i2cdata, uint16 count, uint8 index, uint8 Flag16bit)
{
uint8 value;
uint8 ack = 1;
uint16 i;
ManI2cStart(index);
value = devAddress & 0xfe;
ack = ManI2cSendByte(index, value);
if(Flag16bit == 1)
{
value = (regAddress>>8) & 0xff;
ManI2cSendByte(index, value);
}
value = regAddress & 0xff;
ManI2cSendByte(index, value);
for(i=0;i<count;i++)
{
if(i==count-1)
ManI2cSendByte(index, i2cdata[i]);
else
ManI2cSendByte(index, i2cdata[i]);
}
ManI2cStop(index);
//I2CDelay(0x3f);
if(ack == 0)
return 0;
else
return 1;
}
static uint8 ManI2cRead(uint32 devAddress, uint32 regAddress, uint8 *i2cdata, uint16 count, uint8 index, uint8 Flag16bit)
{
uint8 value;
uint8 ack = 1;
uint16 i;
ManI2cStart(index);
value = devAddress & 0xfe;
ack = ManI2cSendByte(index,value);//
if(Flag16bit == 1)
{
value = (regAddress>>8) & 0xff;
ManI2cSendByte(index, value);
}
value = regAddress & 0xff;
ManI2cSendByte(index,value);
ManI2cStop(index);
ManI2cStart(index);
//ManI2cRestart(index);
value = (devAddress & 0xff) | 0x01;
ManI2cSendByte(index,value);
for(i=0;i<count;i++)
{
if(i==count-1)
i2cdata[i] = ManI2cReadByte(index, 1);
else
i2cdata[i] = ManI2cReadByte(index, 0);
}
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManSdaHigh(index);
I2CDelay(MANI2CFREQ);
ManSdaLow(index);
I2CDelay(MANI2CFREQ);
ManI2cStop(index);
//I2CDelay(0x3f);
if(ack == 0)
return 0;
else
return 1;
}
static void I2CWRNBYTE_CODEC(unsigned int regAddress,unsigned char data)
{
ManI2cWrite(MS8406_I2C_ADDRESS, regAddress, &data, 1, 0, 0);
}
static void codec_write(unsigned int devAddress,unsigned int regAddress,unsigned char data)
{
//ManI2cWrite(I2C_1, devAddress, regAddress,&data, 1, 0);
ManI2cWrite(MS8406_I2C_ADDRESS, regAddress, &data, 1, 0, 0);
}
static void codec_read(unsigned int regAddress,unsigned char *data)
{
ManI2cRead(MS8406_I2C_ADDRESS, regAddress, data, 1, 0, 0);
}
static int xxxms8406_open(struct inode *inode, struct file *file)
{
return 0;
}
static int xxxms8406_release(struct inode *inode, struct file *file)
{
return 0;
}
#if 0
static int xxxgsv_read(struct inode *inode, struct file *file)
{
//ManI2cRead(gdevAddress, gregAddress, data, count, gindex, gFlag16bit);
return 0;
}
static int xxxgsv_write(struct inode *inode, struct file *file)
{
//ManI2cWrite(gdevAddress, gregAddress, data, count, gindex, gFlag16bit);
return 0;
}
#endif
static long xxxms8406_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
int bitRes = 0;
int smpleRate = 0;
uint8_t data[3]={0};
extern int xxx_update_syscxxx();
switch (cmd) {
case MS8406_IOCTL_SET_BIT_RESOLUTION:
if (copy_from_user(&bitRes, (int __user *)arg, sizeof(int))) {
return -EFAULT;
}
printk(KERN_INFO "xxxms8406_ioctl: Received SET_BIT_RESOLUTION : %d\n", bitRes);
//BIT5,BIT4
//00 - 24-bit resolution
//01 - 20-bit resolution
//10 - 16-bit resolution
if (bitRes == 16) {
codec_write(MS8406_I2C_ADDRESS, 0x05, 0xA5);
} else if (bitRes == 20) {
codec_write(MS8406_I2C_ADDRESS, 0x05, 0x95);
} else if (bitRes == 24) {
codec_write(MS8406_I2C_ADDRESS, 0x05, 0x85);
}
ManI2cRead(MS8406_I2C_ADDRESS, 0x05, &data[0], 1, 0, 0);
printk("xxxms8406_ioctl READ 0x05 : 0x%x \n", data[0]);
break;
case MS8406_IOCTL_SET_SMPLE_RATE:
if (copy_from_user(&smpleRate, (int __user *)arg, sizeof(int))) {
return -EFAULT;
}
printk(KERN_INFO "xxxms8406_ioctl: Received SET_SMPLE_RATE: %d\n", smpleRate);
//bit5 bit4
//00 - OMCK frequency is 256*Fs
//01 - OMCK frequency is 384*Fs
//10 - OMCK frequency is 512*Fs
//11 - OMCK frequency is 128*Fs
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x00); //停止运行
usleep_range(500, 510);
if (smpleRate == 32) {
g_set_i2s1_mcxxx_fre = 12288000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x10); //bit6:run 384Fs
} else if (smpleRate == 44) {
//44.1k
g_set_i2s1_mcxxx_fre = 11289600;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40); //bit6:run 256fs
} else if (smpleRate == 48) {
g_set_i2s1_mcxxx_fre = 24576000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x20); //bit6:run 512Fs
} else if (smpleRate == 64) { //不支持
g_set_i2s1_mcxxx_fre = 24576000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x10); //bit6:run 384Fs
} else if (smpleRate == 88) {
//88.2khz
g_set_i2s1_mcxxx_fre = 11289600;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x30); //bit6:run 128Fs
} else if (smpleRate == 96) {
g_set_i2s1_mcxxx_fre = 24576000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40); //bit6:run 256fs
} else if (smpleRate == 128) {//不支持
g_set_i2s1_mcxxx_fre = 32768000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40); //bit6:run 256fs
} else if (smpleRate == 176) {
//176.4
g_set_i2s1_mcxxx_fre = 22579200;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x30); //bit6:run 128Fs
} else if (smpleRate == 192) {
g_set_i2s1_mcxxx_fre = 24576000;
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40|0x30); //bit6:run 128Fs
}
ManI2cRead(MS8406_I2C_ADDRESS, 0x04, &data[0], 1, 0, 0);
printk("22xxxms8406_READ 0x04 : 0x%x \n", data[0]);
xxx_update_syscxxx();
break;
default:
return -EINVAL;
}
return 0;
}
static ssize_t xxxms8406_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {
uint8_t data[3]={0};
ManI2cRead(MS8406_I2C_ADDRESS, 0x04, &data[0], 1, 0, 0);
printk("22xxxms8406_READ 0x04 : 0x%x \n", data[0]);
usleep_range(5000, 5100);
ManI2cRead(MS8406_I2C_ADDRESS, 0x05, &data[0], 1, 0, 0);
printk("22xxxms8406_READ 0x05 : 0x%x \n", data[0]);
usleep_range(5000, 5100);
ManI2cRead(MS8406_I2C_ADDRESS, 0x7f, &data[0], 1, 0, 0); //读版本号
printk("xxxms8406_READ 0x7F : 0x%x \n", data[0]);
g_set_i2s1_mcxxx_fre = 12288000;
return 0;
}
static struct file_operations xxxms8406_fops = {
.owner = THIS_MODULE,
.open = xxxms8406_open,
.release = xxxms8406_release,
.unlocked_ioctl = xxxms8406_ioctl,
.read = xxxms8406_read,
//.write = xxxms8406_write,
};
static struct miscdevice xxxms8406_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "xxx_ms",
.fops = &xxxms8406_fops,
};
extern int g_isMS8416;
static int xxxms8406_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int ret;
int err;
uint8_t data[3]={0};
uint8_t reg;
uint8_t i;
//int period;
printk("====xxxms8406_probe==\n");
g_isMS8416 = 0;
gpio_scl = of_get_named_gpio(np, "ms84x6_scl", 0);
if (!gpio_is_valid(gpio_scl)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_scl);
} else {
err = devm_gpio_request(&pdev->dev, gpio_scl, "ms84x6_scl");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_scl\n",
gpio_scl);
ret = err;
}
gpio_direction_output(gpio_scl, 1);
}
gpio_sda = of_get_named_gpio(np, "ms84x6_sda", 0);
if (!gpio_is_valid(gpio_sda)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_sda);
} else {
err = devm_gpio_request(&pdev->dev, gpio_sda, "ms84x6_sda");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_sda\n",
gpio_sda);
ret = err;
}
gpio_direction_output(gpio_sda, 1);
}
gpio_rst = of_get_named_gpio(np, "ms84x6_reset", 0);
if (!gpio_is_valid(gpio_rst)) {
dev_err(&pdev->dev, "invalid host gpio%d\n", gpio_rst);
} else {
err = devm_gpio_request(&pdev->dev, gpio_rst, "ms84x6_reset");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ms84x6_reset\n",
gpio_rst);
ret = err;
}
}
ret = misc_register(&xxxms8406_device);
if (ret) {
pr_err("xxxgsv_probe: xxxms8406_device register failed\n");
goto misc_register_failed;
}
int value = -1;
value = gpio_direction_input(gpio_sda);
if (value >= 0 ){
printk("value = %d gpio_direction_input(gpio_sda);\n",value);
}
value = gpio_get_value(gpio_sda);
printk("wzh gpio_sda value = %d\n", value);
value = gpio_direction_input(gpio_scl);
if (value >= 0) {
printk("value = %d gpio_direction_input(gpio_scl);\n",value);
}
value = gpio_get_value(gpio_scl);
printk("wzh gpio_scl value = %d\n", value);
#if xxxEC_EN
ret = DrvSoftLockDecode();
if(ret) {
printk("xxxec DrvSoftLockDecode_failed\n");
//goto DrvSoftLockDecode_failed;
}
wake_lock_init(&wake_lock_sleep, WAKE_LOCK_SUSPEND, "wake_lock_sleep");
wake_lock(&wake_lock_sleep);
#endif
//reset chip
gpio_direction_output(gpio_rst, 0);
usleep_range(5000, 5100);
gpio_direction_output(gpio_rst, 1);
usleep_range(500, 510);
ManI2cRead(MS8406_I2C_ADDRESS, 0x7f, &data[0], 1, 0, 0); //读版本号
printk("xxxms8406_READ 0x7F : 0x%x \n", data[0]);
#if 1
usleep_range(500, 510);
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x00);
usleep_range(500, 510);
//codec_write(MS8406_I2C_ADDRESS, 0x04, 0x20); //512Fs
usleep_range(500, 510);
codec_write(MS8406_I2C_ADDRESS, 0x04, 0x40); //bit6:run
usleep_range(500, 510);
codec_write(MS8406_I2C_ADDRESS, 0x05, 0xA5); // BIT7:主模式 BIT5,BIT4:16BIT bit2:i2s模式 bit0:1 - 当 ILRCK 为高电平时,SDIN 数据用于正确的通道
usleep_range(500, 510);
ManI2cRead(MS8406_I2C_ADDRESS, 0x04, &data[0], 1, 0, 0);
printk("22xxxms8406_READ 0x04 : 0x%x \n", data[0]);
usleep_range(500, 510);
ManI2cRead(MS8406_I2C_ADDRESS, 0x05, &data[0], 1, 0, 0);
printk("22xxxms8406_READ 0x05 : 0x%x \n", data[0]);
usleep_range(500, 510);
ManI2cRead(MS8406_I2C_ADDRESS, 0x7f, &data[0], 1, 0, 0); //读版本号
printk("xxxms8406_READ 0x7F : 0x%x \n", data[0]);
#endif
usleep_range(5000, 5100);
printk(KERN_INFO "xxxms8406 driver registered.\n");
return 0;
misc_register_failed:
misc_deregister(&xxxms8406_device);
gpio_free(gpio_scl);
gpio_free(gpio_sda);
return -1;
}
static int xxxms8406_remove(struct platform_device *pdev)
{
misc_deregister(&xxxms8406_device);
gpio_free(gpio_scl);
gpio_free(gpio_sda);
return 0;
}
static struct of_device_id xxxms8406_of_match[] = {
{ .compatible = "rockchip,xxx_ms" },
{ }
};
static struct platform_driver xxxms8406_driver = {
.probe = xxxms8406_probe,
.remove = xxxms8406_remove,
.driver = {
.name = "xxx_ms",
.of_match_table = of_match_ptr(xxxms8406_of_match),
.owner = THIS_MODULE,
},
};
static int xxxms8406_init(void)
{
int retval = 0;
retval = platform_driver_register(&xxxms8406_driver);
if (retval < 0) {
printk(KERN_ERR "%s retval=%d\n", __func__, retval);
return retval;
}
return 0;
}
static void xxxms8406_exit(void)
{
platform_driver_unregister(&xxxms8406_driver);
}
module_init(xxxms8406_init);
module_exit(xxxms8406_exit);
MODULE_AUTHOR("xxx,Inc.");
MODULE_DESCRIPTION("xxxms8406 driver");
MODULE_LICENSE("GPL");
4、遇到的问题
1、配置i2s为从机模式
参考第一点的内容,下面是其手册对从机模式的描述
2、ms8416读取采样率的时候,25脚OMCK应该接外部时钟,以供参考
3、ms8416 RMCK/OLRCK/OSCLK 频率是多少?
12.288M,3.072M,48K
4、调试工具
tinyplay /dev/2024-04-29_171929.wav -D 0 -d 0 -r 48000
tinycap /dev/output.wav -D 0 -d 0 -c 2 -r 48000 -b 16 -t 10
5、录音遇到分区空间不足,导致声音混乱失真

刚开始是录制在data分区的,就是声音都失真了,导致调试好久都找不到原因,后面录制在/dev分区问题解决