RK3229 MS8416 MS8406调试

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分区问题解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值