分析hisi soc移植的音频驱动芯片,TLV320AIC3101音频驱动驱动源码。TLV320AIC3101提供了三个文件

tlv320.h

/* extdrv/peripheral/ada/tlv320.h for Linux .

#ifndef _INC_TLV320AIC31
#define  _INC_TLV320AIC31	

#define     IN2LR_2_LEFT_ADC_CTRL 0x0
#define     IN2LR_2_RIGTH_ADC_CTRL 0x1
#define     IN1L_2_LEFT_ADC_CTRL 0x2
#define     IN1R_2_RIGHT_ADC_CTRL 0x3
#define     PGAL_2_HPLOUT_VOL_CTRL 0x4
#define     PGAR_2_HPLOUT_VOL_CTRL 0x5
#define     DACL1_2_HPLOUT_VOL_CTRL 0x6
#define     DACR1_2_HPLOUT_VOL_CTRL 0x7
#define     HPLOUT_OUTPUT_LEVEL_CTRL 0x8 
#define     PGAL_2_HPLCOM_VOL_CTRL 0x9
#define     PGAR_2_HPLCOM_VOL_CTRL 0xa
#define     DACL1_2_HPLCOM_VOL_CTRL 0xb
#define     DACR1_2_HPLCOM_VOL_CTRL 0xc
#define     HPLCOM_OUTPUT_LEVEL_CTRL 0xd
#define     PGAR_2_HPROUT_VOL_CTRL 0xf
#define     DACR1_2_HPROUT_VOL_CTRL 0x10
#define     HPROUT_OUTPUT_LEVEL_CTRL 0x11
#define     PGAR_2_HPRCOM_VOL_CTRL 0x12
#define     DACR1_2_HPRCOM_VOL_CTRL 0X13
#define     HPRCOM_OUTPUT_LEVEL_CTRL 0x14
#define     PGAL_2_LEFT_LOP_VOL_CTRL 0x15
#define     DACL1_2_LEFT_LOP_VOL_CTRL 0x16
#define     LEFT_LOP_OUTPUT_LEVEL_CTRL 0x17
#define     PGAR_2_RIGHT_LOP_VOL_CTRL 0x18
#define     DACR1_2_RIGHT_LOP_VOL_CTRL 0x19
#define     RIGHT_LOP_OUTPUT_LEVEL_CTRL 0x20
#define     SET_ADC_SAMPLE 0x21
#define     SET_DAC_SAMPLE 0x22
#define     SET_DATA_LENGTH 0x23
#define     SET_CTRL_MODE 0x24
#define     LEFT_DAC_VOL_CTRL 0x25
#define     RIGHT_DAC_VOL_CTRL 0x26
#define     LEFT_DAC_POWER_SETUP 0x27
#define     RIGHT_DAC_POWER_SETUP 0x28
#define     DAC_OUT_SWITCH_CTRL 0x29
#define     LEFT_ADC_PGA_CTRL 0x30
#define     RIGHT_ADC_PGA_CTRL 0x31
#define     TLV320AIC31_REG_DUMP 0x32
#define     SOFT_RESET 0x33
#define     SET_TRANSFER_MODE 0x34
#define     SET_SERIAL_DATA_OFFSET 0X35

/*
0: ADC Fs = Fsref/1     48		44
1: ADC Fs = Fsref/1.5	32	
2: ADC Fs = Fsref/2		24		22
3: ADC Fs = Fsref/2.5	20
4: ADC Fs = Fsref/3		16
5: ADC Fs = Fsref/3.5	13.7
6: ADC Fs = Fsref/4		12		11
7: ADC Fs = Fsref/4.5	10.6
8: ADC Fs = Fsref/5		9.6
9: ADC Fs = Fsref/5.5
a: ADC Fs = Fsref / 6	8
*/
#define     AC31_SET_8K_SAMPLERATE	                0xa
#define     AC31_SET_12K_SAMPLERATE	                0x6
#define     AC31_SET_16K_SAMPLERATE	                0x4
#define     AC31_SET_24K_SAMPLERATE	                0x2
#define     AC31_SET_32K_SAMPLERATE	                0x1
#define     AC31_SET_48K_SAMPLERATE	                0x0

#define     AC31_SET_11_025K_SAMPLERATE	                0x6
#define     AC31_SET_22_05K_SAMPLERATE	                0x2
#define     AC31_SET_44_1K_SAMPLERATE	                0x0

#define     AC31_SET_SLAVE_MODE                      0
#define     AC31_SET_MASTER_MODE                     1

#define     AC31_SET_16BIT_WIDTH                      0
#define     AC31_SET_20BIT_WIDTH                      1
#define     AC31_SET_24BIT_WIDTH                      2
#define     AC31_SET_32BIT_WIDTH                      3		

typedef enum Audio_In_
{
    IN1L =0,
    IN1R =1,
    IN2L =2,
    IN2R =3,
}Audio_In;
typedef enum Audio_Out_
{
    LINE_OUT_R=0,
    LINE_OUT_L,
    HPL,
    HPR,
}Audio_Out;
typedef struct 
{
    unsigned int chip_num:3;
    unsigned int audio_in_out:2;
    unsigned int if_mute_route:1;
    unsigned int if_powerup:1;
    unsigned int input_level:7;
    unsigned int sample:4;
    unsigned int if_44100hz_series:1;
    unsigned int data_length:2;
    unsigned int ctrl_mode:1;
    unsigned int dac_path:2;
    unsigned int trans_mode:2;
    unsigned int reserved :6;
    unsigned int data_offset:8;
    unsigned int sampleRate;
}Audio_Ctrl;
#endif

tlv320aic31_def.h

#ifndef _INC_TLV320AIC31_DEF
#define _INC_TLV320AIC31_DEF


typedef union
{
    struct
    {
        unsigned char reserved2 : 4;
        unsigned char bit_work_dri_ctrl: 1;
        unsigned char reserved1: 1;
        unsigned char work_clock_dic_ctrl: 1;
        unsigned char bit_clock_dic_ctrl: 1;
    } bit;
    unsigned char b8;
} Ctrl_Mode;

typedef union
{
    struct
    {
        unsigned char input_vol_level_ctrl: 7;
        unsigned char if_mute_route: 1;
    } bit;
    unsigned char b8;
} Adc_Pga_Dac_Gain_Ctrl;

typedef union
{
    struct
    {
        unsigned char in2r_adc_input_level_sample: 4;
        unsigned char in2l_adc_input_level_sample: 4;
    } bit;
    unsigned char b8;
} In2_Adc_Ctrl_Sample;

typedef union
{
    struct
    {
        unsigned adc_pga_step_ctrl: 2;
        unsigned adc_ch_power_ctrl: 1;
        unsigned char in1_adc_input_level: 4;
        unsigned char mode: 1;
    } bit;
    unsigned char b8;
} In1_Adc_Ctrl;

typedef union
{
    struct
    {
        unsigned char reserved: 4;
        unsigned char data_length: 2;
        unsigned char transfer_mode: 2;
    } bit;
    unsigned char b8;
} Serial_Int_Ctrl;

typedef union
{
    struct
    {
        unsigned char power_status: 1;
        unsigned char vol_ctrl_status: 1;
        unsigned char power_down_ctrl: 1;
        unsigned char if_mute: 1;
        unsigned char output_level: 4;
    } bit;
    unsigned char b8;
} Line_Hpcom_Out_Ctrl;
typedef union
{
    struct
    {
        unsigned char reserved1: 1;
        unsigned char right_dac_datapath_ctrl: 2;
        unsigned char left_dac_datapath_ctrl: 2;
        unsigned char reserved2: 3;
    } bit;
    unsigned char b8;
} Codec_Datapath_Setup_Ctrl;
typedef union
{
    struct
    {
        unsigned char reserved: 6;
        unsigned char right_dac_power_ctrl: 1;
        unsigned char left_dac_power_ctrl: 1;
    } bit;
    unsigned char b8;
} DAC_POWER_CTRL;
typedef union
{
    struct
    {
        unsigned char reserved: 4;
        unsigned char right_dac_swi_ctrl: 2;
        unsigned char left_dac_swi_ctrl: 2;
    } bit;
    unsigned char b8;
} DAC_OUTPUT_SWIT_CTRL;

typedef union
{
    struct
    {
        unsigned char serial_data_offset: 8;
    } bit;
    unsigned char b8;
} Serial_Data_Offset_Ctrl;
#endif

tlv320aic31.c

#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
//#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#ifndef CONFIG_HISI_SNAPSHOT_BOOT
#include <linux/miscdevice.h>
#endif
#include <linux/delay.h>

#include <linux/proc_fs.h>
#include <linux/poll.h>

#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>

#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

#include "tlv320aic31.h"
#include "tlv320aic31_def.h"

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
#include "himedia.h"
#endif

#define CHIP_NUM 1
#define DEV_NAME "tlv320aic31"
#define DEBUG_LEVEL 1
#define DPRINTK(level,fmt,args...) do{ if(level < DEBUG_LEVEL)\
            printk(KERN_INFO "%s [%s ,%d]: " fmt "\n",DEV_NAME,__FUNCTION__,__LINE__,##args);\
    }while(0)

unsigned int IIC_device_addr[CHIP_NUM] = {0x30};

static struct i2c_board_info hi_info =
{
    I2C_BOARD_INFO("tlv320aic31", 0x30),
};

static struct i2c_client* tlv_client;


static unsigned int  open_cnt = 0;
static int chip_count = 1;

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
static struct himedia_device s_stTlv320aic31Device;
#endif

static int tlv320aic31_device_init(unsigned int num);

int tlv320aic31_write(unsigned char chip_addr, unsigned char reg_addr, unsigned char value)
{
    int ret;
    unsigned char buf[2];
    struct i2c_client* client = tlv_client;

    buf[0] = reg_addr;
    buf[1] = value;

    ret = i2c_master_send(client, buf, 2);
    return ret;
}

int tlv320aic31_read(unsigned char chip_addr, unsigned char reg_addr)
{
    int ret_data = 0xFF;
    int ret;
    struct i2c_client* client = tlv_client;
    unsigned char buf[2];

    buf[0] = reg_addr;
    ret = i2c_master_recv(client, buf, 1);
    if (ret >= 0)
    {
        ret_data = buf[0];
    }
    return ret_data;
}

void tlv320aic31_reg_dump(unsigned int reg_num)
{
    unsigned int i = 0;
    for (i = 0; i < reg_num; i++)
    {
        printk("reg%d =%x,", i, tlv320aic31_read(IIC_device_addr[0], i));
        if ((i + 1) % 8 == 0)
        {
            printk("\n");
        }
    }
}
void soft_reset(unsigned int chip_num)
{
    /*soft reset*/
    tlv320aic31_write(IIC_device_addr[chip_num], 0x1, 0x80);
    msleep(10);
    /*CLKDIV_IN uses MCLK*/
    tlv320aic31_write(IIC_device_addr[chip_num], 102, 0x32);

#if 1
    /*PLL disable and select Q value*/
    tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x10);
#else
    /*PLL enable */
    tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x82);/* P=2 */
    tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x1c);/* J=28 */
    tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x2c);
    tlv320aic31_write(IIC_device_addr[chip_num], 6, 0x8);/* reg 5 and 6 set D=2818*/
    tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1);/* R=1 */
#endif
    /*left and right DAC open*/
    tlv320aic31_write(IIC_device_addr[chip_num], 7,  0xa);/* FSref = 48 kHz */

    /*sample*/
    tlv320aic31_write(IIC_device_addr[chip_num], 2,  0xaa);/* FS = FSref/6 */

    /*ctrl mode*/
    tlv320aic31_write(IIC_device_addr[chip_num], 8,  0xf0);/* master mode */

    /*Audio Serial Data Interface Control*/
    tlv320aic31_write(IIC_device_addr[chip_num], 9,  0x7);/* I2S mode,16bit */

    /*Audio Codec Digital Filter Control Register*/
    tlv320aic31_write(IIC_device_addr[chip_num], 12,  0x50);

    //tlv320aic31_write(IIC_device_addr[chip_num], 25,  0x0);
    tlv320aic31_write(IIC_device_addr[chip_num], 25,  0x40);
    tlv320aic31_write(IIC_device_addr[chip_num], 17,  0xf);
    tlv320aic31_write(IIC_device_addr[chip_num], 18,  0xf0);

    tlv320aic31_write(IIC_device_addr[chip_num], 15,  0x0);
    tlv320aic31_write(IIC_device_addr[chip_num], 16,  0x0);
    //tlv320aic31_write(IIC_device_addr[chip_num], 19,  0x7c);
    //tlv320aic31_write(IIC_device_addr[chip_num], 22,  0x7c);

    tlv320aic31_write(IIC_device_addr[chip_num], 19,  0x04);
    tlv320aic31_write(IIC_device_addr[chip_num], 22,  0x04);
    tlv320aic31_write(IIC_device_addr[chip_num], 28,  0x0);
    tlv320aic31_write(IIC_device_addr[chip_num], 31,  0x0);

    /*out ac-coupled*/
    tlv320aic31_write(IIC_device_addr[chip_num], 14, 0x80);

    /*left and right DAC power on*/
    tlv320aic31_write(IIC_device_addr[chip_num], 37, 0xc0);

    /*out common-mode voltage, DTS2014123002762*/
    //tlv320aic31_write(IIC_device_addr[chip_num], 40, 0x80);

    /*out path select*/
    tlv320aic31_write(IIC_device_addr[chip_num], 41, 0x1);

    /*out path select DTS2014123002762 change delay time from 2s to 200ms*/
    tlv320aic31_write(IIC_device_addr[chip_num], 42, 0x78);

    /*left DAC not muted*/
    tlv320aic31_write(IIC_device_addr[chip_num], 43, 0x0);

    /*right DAC not muted*/
    tlv320aic31_write(IIC_device_addr[chip_num], 44, 0x0);

    tlv320aic31_write(IIC_device_addr[chip_num], 47, 0x80);

    /*HPLOUT is not muted*/
    //tlv320aic31_write(IIC_device_addr[chip_num], 51, 0x04);

    tlv320aic31_write(IIC_device_addr[chip_num], 64, 0x80);
    /*HPROUT is not muted*/
    //tlv320aic31_write(IIC_device_addr[chip_num], 65, 0x9f);

    /*out short circuit protection*/
    tlv320aic31_write(IIC_device_addr[chip_num], 38, 0x3e);

}

/*
 *	device open. set counter
 */
static int tlv320aic31_open(struct inode* inode, struct file* file)
{
    if (0 == open_cnt++)
    {
        return 0;
    }
    return -1 ;
}

/*
 *	Close device, Do nothing!
 */
static int tlv320aic31_close(struct inode* inode , struct file* file)
{
    open_cnt--;
    return 0;
}

//static int tlv320aic31_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long tlv320aic31_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
{
    unsigned int __user* argp = (unsigned int __user*)arg;
    unsigned int chip_num;
    Audio_Ctrl temp;
    Audio_Ctrl* audio_ctrl;
    Codec_Datapath_Setup_Ctrl codec_datapath_setup_ctrl;
    DAC_OUTPUT_SWIT_CTRL dac_output_swit_ctrl;
    DAC_POWER_CTRL dac_power_ctrl;
    In1_Adc_Ctrl in1_adc_ctrl ;
    In2_Adc_Ctrl_Sample in2_adc_ctrl_sample ;
    Adc_Pga_Dac_Gain_Ctrl adc_pga_dac_gain_ctrl;
    Line_Hpcom_Out_Ctrl line_hpcom_out_ctrl;
    Serial_Int_Ctrl serial_int_ctrl;
    Serial_Data_Offset_Ctrl serial_data_offset_ctrl;
    Ctrl_Mode ctrl_mode;

    if (argp != NULL)
    {
        if (copy_from_user(&temp, argp, sizeof(Audio_Ctrl)))
        {
            return -EFAULT;
        }
    }
    audio_ctrl = (Audio_Ctrl*)(&temp);
    chip_num = audio_ctrl->chip_num;
    switch (cmd)
    {
        case IN2LR_2_LEFT_ADC_CTRL:
            in2_adc_ctrl_sample.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 17);
            in2_adc_ctrl_sample.bit.in2l_adc_input_level_sample = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 17, in2_adc_ctrl_sample.b8);
            break;
        case IN2LR_2_RIGTH_ADC_CTRL:
            in2_adc_ctrl_sample.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 18);
            in2_adc_ctrl_sample.bit.in2r_adc_input_level_sample = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 18, in2_adc_ctrl_sample.b8);

            break;
        case IN1L_2_LEFT_ADC_CTRL:
            in1_adc_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 19);
            in1_adc_ctrl.bit.in1_adc_input_level = audio_ctrl->input_level;
            in1_adc_ctrl.bit.adc_ch_power_ctrl = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 19, in1_adc_ctrl.b8);
            break;
        case IN1R_2_RIGHT_ADC_CTRL:
            in1_adc_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 22);
            in1_adc_ctrl.bit.in1_adc_input_level = audio_ctrl->input_level;
            in1_adc_ctrl.bit.adc_ch_power_ctrl = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 22, in1_adc_ctrl.b8);
            break;
        case PGAL_2_HPLOUT_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 46);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 46, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACL1_2_HPLOUT_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 47);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 47, adc_pga_dac_gain_ctrl.b8);
            break;
        case HPLOUT_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 51);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level = audio_ctrl->input_level;
            line_hpcom_out_ctrl.bit.power_status = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 51, line_hpcom_out_ctrl.b8);
            break;
        case PGAL_2_HPLCOM_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 53);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 53, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACL1_2_HPLCOM_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 54);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 54, adc_pga_dac_gain_ctrl.b8);
            break;
        case HPLCOM_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 58);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level =  audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 58, line_hpcom_out_ctrl.b8);
            break;
        case PGAR_2_HPROUT_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 63);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 63, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACR1_2_HPROUT_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 64);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 64, adc_pga_dac_gain_ctrl.b8);
            break;
        case HPROUT_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 65);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level = audio_ctrl->input_level;
            line_hpcom_out_ctrl.bit.power_status = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 65, line_hpcom_out_ctrl.b8);
            break;
        case PGAR_2_HPRCOM_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 70);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 70, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACR1_2_HPRCOM_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 71);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 71, adc_pga_dac_gain_ctrl.b8);
            break;
        case HPRCOM_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 72);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level =  audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 72, line_hpcom_out_ctrl.b8);
            break;
        case PGAL_2_LEFT_LOP_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 81);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 81, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACL1_2_LEFT_LOP_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 82);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 82, adc_pga_dac_gain_ctrl.b8);
            break;
        case LEFT_LOP_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 86);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level =  audio_ctrl->input_level;
            line_hpcom_out_ctrl.bit.power_status =  audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 86, line_hpcom_out_ctrl.b8);
            break;
        case PGAR_2_RIGHT_LOP_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 91);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 91, adc_pga_dac_gain_ctrl.b8);
            break;
        case DACR1_2_RIGHT_LOP_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 92);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 92, adc_pga_dac_gain_ctrl.b8);
            break;
        case RIGHT_LOP_OUTPUT_LEVEL_CTRL:
            line_hpcom_out_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 93);
            line_hpcom_out_ctrl.bit.if_mute = audio_ctrl->if_mute_route;
            line_hpcom_out_ctrl.bit.output_level =  audio_ctrl->input_level;
            line_hpcom_out_ctrl.bit.power_status =  audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 93, line_hpcom_out_ctrl.b8);
            break;
        case SET_ADC_SAMPLE:
            in2_adc_ctrl_sample.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 2);
            in2_adc_ctrl_sample.bit.in2l_adc_input_level_sample = audio_ctrl->sample;
            tlv320aic31_write(IIC_device_addr[chip_num], 2, in2_adc_ctrl_sample.b8);
            break;
        case SET_DAC_SAMPLE:
            in2_adc_ctrl_sample.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 2);
            in2_adc_ctrl_sample.bit.in2r_adc_input_level_sample = audio_ctrl->sample;
            tlv320aic31_write(IIC_device_addr[chip_num], 2, in2_adc_ctrl_sample.b8);
            //printk("set SET_DAC_SAMPLE,audio_ctrl->sample=%x\n",audio_ctrl->sample);
            break;
        case SET_DATA_LENGTH:
            serial_int_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 9);;
            serial_int_ctrl.bit.data_length = audio_ctrl->data_length;
            //tlv320aic31_write(IIC_device_addr[chip_num],9,serial_int_ctrl.b8);
            break;
        case SET_TRANSFER_MODE:
            serial_int_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 9);
            serial_int_ctrl.bit.transfer_mode = audio_ctrl->trans_mode;
            tlv320aic31_write(IIC_device_addr[chip_num], 9, serial_int_ctrl.b8);
            break;
        case SET_CTRL_MODE:
            //tlv320aic31_write(IIC_device_addr[chip_num],0x1,0x80);
            //udelay(50);
            ctrl_mode.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 8);
            ctrl_mode.bit.bit_clock_dic_ctrl =  audio_ctrl->ctrl_mode;
            ctrl_mode.bit.work_clock_dic_ctrl =  audio_ctrl->ctrl_mode;
            ctrl_mode.bit.bit_work_dri_ctrl =  audio_ctrl->ctrl_mode;
            tlv320aic31_write(IIC_device_addr[chip_num], 8, ctrl_mode.b8);

            /* clock config */
            /* aic31, aiao mclk */
            switch (audio_ctrl->sampleRate)
            {
                case 8000:
                case 16000:
                case 32000:
                {
                    /* 32K series sampling rate */
                    tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81);  /* P=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x30);  /* J=12 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x0);   /* reg 5 and 6 set D=0000*/
                    tlv320aic31_write(IIC_device_addr[chip_num], 6, 0x0);
                    codec_datapath_setup_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 7);
                    codec_datapath_setup_ctrl.b8 &= 0x7f;   /* FSref = 48 kHz */
                    tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
                    tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1);  /* R=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 101, 0x0);
                    tlv320aic31_write(IIC_device_addr[chip_num], 102, 0xc2);
                }
                break;
                case 12000:
                case 24000:
                case 48000:
                {
                    /* 48K series sampling rate */
                    tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81);  /* P=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x20);  /* J=8 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x0);   /* reg 5 and 6 set D=0000*/
                    tlv320aic31_write(IIC_device_addr[chip_num], 6, 0x0);
                    codec_datapath_setup_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 7);
                    codec_datapath_setup_ctrl.b8 &= 0x7f;   /* FSref = 48 kHz */
                    tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
                    tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1);  /* R=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 101, 0x0);
                    tlv320aic31_write(IIC_device_addr[chip_num], 102, 0xc2);
                }
                break;
                case 11025:
                case 22050:
                case 44100:
                {
                    /* 44.1K series sampling rate */
                    tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81);  /* P=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x20);  /* J=7 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x00);  /* reg 5 and 6 set D=0000*/
                    tlv320aic31_write(IIC_device_addr[chip_num], 6, 0x00);
                    codec_datapath_setup_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 7);
                    codec_datapath_setup_ctrl.b8 |= 0x80;   /* FSref = 44.1 kHz */
                    tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
                    tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1);  /* R=1 */
                    tlv320aic31_write(IIC_device_addr[chip_num], 101, 0x0);
                    tlv320aic31_write(IIC_device_addr[chip_num], 102, 0xc2);
                }
                break;

                default:
                    printk("aic31 unsupport sampleRate %d\n", audio_ctrl->sampleRate);
                    return -1;
            }


        case LEFT_DAC_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 43);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 43, adc_pga_dac_gain_ctrl.b8);
            break;
        case RIGHT_DAC_VOL_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 44);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 44, adc_pga_dac_gain_ctrl.b8);
            break;
        case LEFT_DAC_POWER_SETUP:
            codec_datapath_setup_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 7);
            codec_datapath_setup_ctrl.bit.left_dac_datapath_ctrl = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
            dac_power_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 37);
            dac_power_ctrl.bit.left_dac_power_ctrl =  audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 37, dac_power_ctrl.b8);
            break;
        case RIGHT_DAC_POWER_SETUP:
            codec_datapath_setup_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 7);
            codec_datapath_setup_ctrl.bit.right_dac_datapath_ctrl = audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
            dac_power_ctrl.b8 =  tlv320aic31_read(IIC_device_addr[chip_num], 37);
            dac_power_ctrl.bit.right_dac_power_ctrl =  audio_ctrl->if_powerup;
            tlv320aic31_write(IIC_device_addr[chip_num], 37, dac_power_ctrl.b8);
            break;
        case DAC_OUT_SWITCH_CTRL:
            dac_output_swit_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 41);
            dac_output_swit_ctrl.bit.left_dac_swi_ctrl =  audio_ctrl->dac_path;
            dac_output_swit_ctrl.bit.right_dac_swi_ctrl = audio_ctrl->dac_path;
            tlv320aic31_write(IIC_device_addr[chip_num], 41, dac_output_swit_ctrl.b8);
            break;
        case LEFT_ADC_PGA_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 15);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 15, adc_pga_dac_gain_ctrl.b8);
            break;
        case RIGHT_ADC_PGA_CTRL:
            adc_pga_dac_gain_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 16);
            adc_pga_dac_gain_ctrl.bit.if_mute_route = audio_ctrl->if_mute_route;
            adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
            tlv320aic31_write(IIC_device_addr[chip_num], 16, adc_pga_dac_gain_ctrl.b8);
            break;
        case SET_SERIAL_DATA_OFFSET:
            serial_data_offset_ctrl.b8 = tlv320aic31_read(IIC_device_addr[chip_num], 10);
            serial_data_offset_ctrl.bit.serial_data_offset = audio_ctrl->data_offset;
            tlv320aic31_write(IIC_device_addr[chip_num], 10, serial_data_offset_ctrl.b8);
            break;
        case SOFT_RESET:
            //printk("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__, __LINE__, "invalid attribute");
            soft_reset(chip_num);
            break;
        case TLV320AIC31_REG_DUMP:
            tlv320aic31_reg_dump(102);
            break;
        default:
            break;
    }
    return 0;
}

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
static int tlv320aic31_freeze(struct himedia_device* pdev)
{
    printk(KERN_ALERT "%s  %d\n", __FUNCTION__, __LINE__);
    return 0;
}

static int tlv320aic31_restore(struct himedia_device* pdev)
{
    int i;

    for (i = 0; i < chip_count; i++)
    {
        if (tlv320aic31_device_init(i) < 0)
        {
            printk(KERN_ALERT "%s  %d, tlv320aic31 device init fail!\n", __FUNCTION__, __LINE__);
            return -1;
        }
    }
    printk(KERN_ALERT "%s  %d\n", __FUNCTION__, __LINE__);
    return 0;
}
#endif

/*
 *  The various file operations we support.
 */

static struct file_operations tlv320aic31_fops =
{
    .owner		= THIS_MODULE,
    .unlocked_ioctl		= tlv320aic31_ioctl,
    .open		= tlv320aic31_open,
    .release	= tlv320aic31_close
};

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
struct himedia_ops stTlv320aic31DrvOps =
{
    .pm_freeze = tlv320aic31_freeze,
    .pm_restore  = tlv320aic31_restore
};
#else
static struct miscdevice tlv320aic31_dev =
{
    MISC_DYNAMIC_MINOR,
    DEV_NAME,
    &tlv320aic31_fops,
};
#endif

static int set_chip_count(const char* val, const struct kernel_param* kp)
{
    int ret;
    int chip_count;

    ret = kstrtoint(val, 10, &chip_count);
    if (ret < 0)
    {
        return -EINVAL;
    }

    if (chip_count < 0 || chip_count > CHIP_NUM)
    {
        printk("chip_count%d err. \n", chip_count);
        return -EINVAL;
    }
    return 0;
}

static struct kernel_param_ops alv320_para_ops =
{
    .set = set_chip_count,
};

#if 0
module_param(chip_count, int, 0);
#else
module_param_cb(chip_count, &alv320_para_ops, &chip_count, 0644);

#endif
MODULE_PARM_DESC(chip_count, "the num we device uses the tlv320aic31,default 1");

static int tlv320aic31_reboot(struct notifier_block* self, unsigned long data, void* pdata)
{
    unsigned int i;

    for (i = 0; i < chip_count; i++)
    {
        /* HPLOUT is mute */
        tlv320aic31_write(IIC_device_addr[i], 51, 0x04);

        /* HPROUT is mute */
        tlv320aic31_write(IIC_device_addr[i], 65, 0x04);
    }

    printk("Func:%s, line:%d######\n", __FUNCTION__, __LINE__);
    return 0;
}

static struct notifier_block tlv320aic31_reboot_notifier =
{
    .notifier_call = tlv320aic31_reboot,
};

static int tlv320aic31_device_init(unsigned int num)
{
    /* inite codec configs.*/
    unsigned char temp = 0;
    temp = tlv320aic31_read(IIC_device_addr[num], 0x2);
    tlv320aic31_write(IIC_device_addr[0], 0x2, 0xaa);
    if ( tlv320aic31_read(IIC_device_addr[num], 0x2) != 0xaa)
    {
        DPRINTK(0, "init aic31(%d) error", num);
        return -1;
    }
    tlv320aic31_write(IIC_device_addr[num], 0x2, temp);

    soft_reset(num);

    /* reboot_notifier */
    register_reboot_notifier(&tlv320aic31_reboot_notifier);

    return 0;
}

static int tlv320aic31_device_exit(unsigned int num)
{
    /* HPLOUT is mute */
    tlv320aic31_write(IIC_device_addr[num], 51, 0x04);

    /* HPROUT is mute */
    tlv320aic31_write(IIC_device_addr[num], 65, 0x04);

    return 0;
}

static int i2c_client_init(void)
{
    struct i2c_adapter* i2c_adap;

    // tlv_aic31 use i2c0
    i2c_adap = i2c_get_adapter(0);
    if (NULL == i2c_adap)
    {
        printk("find i2c adapter fail. \n");
        return -1;
    }
    tlv_client = i2c_new_device(i2c_adap, &hi_info);

    i2c_put_adapter(i2c_adap);

    return 0;
}

static void i2c_client_exit(void)
{
    i2c_unregister_device(tlv_client);
}

static int __init tlv320aic31_init(void)
{
    unsigned int i, ret;

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
    snprintf(s_stTlv320aic31Device.devfs_name, sizeof(s_stTlv320aic31Device.devfs_name), DEV_NAME);

    s_stTlv320aic31Device.minor  = HIMEDIA_DYNAMIC_MINOR;
    s_stTlv320aic31Device.fops   = &tlv320aic31_fops;
    s_stTlv320aic31Device.drvops = &stTlv320aic31DrvOps;
    s_stTlv320aic31Device.owner  = THIS_MODULE;

    ret = himedia_register(&s_stTlv320aic31Device);
    if (ret)
    {
        DPRINTK(0, "could not register tlv320aic31 device");
        return -1;
    }
#else
    ret = misc_register(&tlv320aic31_dev);
    if (ret)
    {
        DPRINTK(0, "could not register tlv320aic31 device");
        return -1;
    }
#endif

    i2c_client_init();
    for (i = 0; i < chip_count; i++)
    {
        if (tlv320aic31_device_init(i) < 0)
        {
            goto init_fail;
        }
    }
    DPRINTK(1, "tlv320aic31 driver init successful!");
    printk("load tlv320aic31.ko  ok!\n");
    return ret;
init_fail:
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
    himedia_unregister(&s_stTlv320aic31Device);
#else
    misc_deregister(&tlv320aic31_dev);
#endif
    DPRINTK(0, "tlv320aic31 device init fail,deregister it!");
    return -1;
}

static void __exit tlv320aic31_exit(void)
{
    unsigned int i;

    for (i = 0; i < chip_count; i++)
    {
        tlv320aic31_device_exit(i);
    }

    unregister_reboot_notifier(&tlv320aic31_reboot_notifier);

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
    himedia_unregister(&s_stTlv320aic31Device);
#else
    misc_deregister(&tlv320aic31_dev);
#endif

    i2c_client_exit();

    DPRINTK(1, "deregister tlv320aic31");
    printk("rmmod tlv320aic31.ko  ok!\n");
}

module_init(tlv320aic31_init);
module_exit(tlv320aic31_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hisilicon");

TLV320AIC3101这个芯片商写的驱动,可以看到,非常简单,就是个字符设备,一个字符设备的那一套流程,提供file_opration函数集操作接口,read,write,ioctl设置音频参数。然后套上i2c,i2c驱动的外壳。

static struct file_operations tlv320aic31_fops =
{
    .owner		= THIS_MODULE,
    .unlocked_ioctl		= tlv320aic31_ioctl,
    .open		= tlv320aic31_open,
    .release	= tlv320aic31_close
};

然后调用音频的驱动框架ALSA,注册到了hisi封装的多媒体框架,himedia_register来注册
填充drvier,如果用hisi的框架,没有就注册到了misc框架

#ifdef CONFIG_HISI_SNAPSHOT_BOOT
struct himedia_ops stTlv320aic31DrvOps =
{
    .pm_freeze = tlv320aic31_freeze,
    .pm_restore  = tlv320aic31_restore
};
#else
static struct miscdevice tlv320aic31_dev =
{
    MISC_DYNAMIC_MINOR,
    DEV_NAME,
    &tlv320aic31_fops,
};
#endif

himedia_register注册到hisi的多媒体框架,如果是别家的,源码,是alsa框架接口

#ifdef CONFIG_HISI_SNAPSHOT_BOOT

    s_stTlv320aic31Device.minor  = HIMEDIA_DYNAMIC_MINOR;
    s_stTlv320aic31Device.fops   = &tlv320aic31_fops;
    s_stTlv320aic31Device.drvops = &stTlv320aic31DrvOps;
    s_stTlv320aic31Device.owner  = THIS_MODULE;

    ret = himedia_register(&s_stTlv320aic31Device);
    if (ret)
    {
        DPRINTK(0, "could not register tlv320aic31 device");
        return -1;
    }
#else
    ret = misc_register(&tlv320aic31_dev);
    if (ret)
    {
        DPRINTK(0, "could not register tlv320aic31 device");
        return -1;
    }
#endif

注册一个i2c设备

static int i2c_client_init(void)
{
    struct i2c_adapter* i2c_adap;

    // tlv_aic31 use i2c0
    i2c_adap = i2c_get_adapter(0);
    if (NULL == i2c_adap)
    {
        printk("find i2c adapter fail. \n");
        return -1;
    }
    tlv_client = i2c_new_device(i2c_adap, &hi_info);

    i2c_put_adapter(i2c_adap);

    return 0;
}

然后将这两个驱动,提交给内核,注册加载,可以看到,这是老内核提供的一种方法,没有用udev的方式,和dts。因为这个文件非常老,好像是2006年写的了。现在应该是dts,新的方法写的。

static int __init tlv320aic31_init(void)
{
   himedia_register(&s_stTlv320aic31Device);
   i2c_client_init();
}

module_init(tlv320aic31_init);
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐