1167 lines
35 KiB
C
1167 lines
35 KiB
C
/*
|
|
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
|
|
*/
|
|
|
|
#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/init.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/io.h>
|
|
|
|
#include <linux/miscdevice.h>
|
|
#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>
|
|
|
|
#ifndef __LITEOS__
|
|
#include <linux/i2c-dev.h>
|
|
#endif
|
|
#ifdef __LITEOS__
|
|
#include <linux/cdev.h>
|
|
#include <linux/device.h>
|
|
#include "i2c_bsp.h"
|
|
#endif
|
|
|
|
#include "es8388.h"
|
|
#include "securec.h"
|
|
|
|
#ifdef OT_FPGA
|
|
#define ES8388_I2C_ADAPTER_ID 0
|
|
#else
|
|
#define ES8388_I2C_ADAPTER_ID 0
|
|
#endif
|
|
|
|
#define CHIP_NUM 1
|
|
#define DEV_NAME "es8388"
|
|
#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 g_iic_device_addr[CHIP_NUM] = {0x20};
|
|
|
|
static struct i2c_board_info g_board_info = {
|
|
I2C_BOARD_INFO("es8388", 0x20),
|
|
};
|
|
|
|
static struct i2c_client* g_es8388_client = NULL;
|
|
|
|
static unsigned int g_open_cnt = 0;
|
|
static unsigned int g_chip_count = 1;
|
|
|
|
static int es8388_device_init(unsigned int num);
|
|
|
|
#ifndef __LITEOS__
|
|
static unsigned char ot_i2c_read(unsigned char dev_addr, unsigned int reg_addr,
|
|
unsigned int reg_addr_num, unsigned int data_byte_num)
|
|
{
|
|
unsigned char tmp_buf0[4]; /* 4: buf len */
|
|
unsigned char tmp_buf1[4]; /* 4: buf len */
|
|
int ret;
|
|
int ret_data = 0xFF;
|
|
int idx = 0;
|
|
static struct i2c_client client;
|
|
static struct i2c_msg msg[2]; /* 2: msg len */
|
|
|
|
if (g_es8388_client == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
ret = memcpy_s(&client, sizeof(client), g_es8388_client, sizeof(*g_es8388_client));
|
|
if (ret != EOK) {
|
|
return -1;
|
|
}
|
|
|
|
msg[0].addr = (dev_addr >> 1);
|
|
msg[0].flags = client.flags & I2C_M_TEN;
|
|
msg[0].len = reg_addr_num;
|
|
msg[0].buf = tmp_buf0;
|
|
|
|
/* reg_addr config */
|
|
if (reg_addr_num == 1) {
|
|
tmp_buf0[idx++] = reg_addr & 0xff;
|
|
} else {
|
|
tmp_buf0[idx++] = (reg_addr >> 8) & 0xff; /* 8: offset */
|
|
tmp_buf0[idx++] = reg_addr & 0xff;
|
|
}
|
|
|
|
msg[1].addr = (dev_addr >> 1);
|
|
msg[1].flags = client.flags & I2C_M_TEN;
|
|
msg[1].flags |= I2C_M_RD;
|
|
msg[1].len = data_byte_num;
|
|
msg[1].buf = tmp_buf1;
|
|
|
|
while (1) {
|
|
ret = i2c_transfer(client.adapter, msg, 2); /* 2: len */
|
|
if (ret == 2) { /* 2: return len */
|
|
if (data_byte_num == 2) { /* 2: data num */
|
|
ret_data = tmp_buf1[1] | (tmp_buf1[0] << 8); /* 8: offset */
|
|
} else {
|
|
ret_data = tmp_buf1[0];
|
|
}
|
|
break;
|
|
} else if ((ret == -EAGAIN) && (in_atomic() || irqs_disabled())) {
|
|
continue;
|
|
} else {
|
|
dprintk(0, "i2c_transfer error, ret=%d.\n", ret);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret_data;
|
|
}
|
|
|
|
static int ot_i2c_write(unsigned char dev_addr, unsigned int reg_addr,
|
|
unsigned int reg_addr_num, unsigned int data, unsigned int data_byte_num)
|
|
{
|
|
unsigned char tmp_buf[8]; /* 8: buf len */
|
|
int ret;
|
|
int idx = 0;
|
|
static struct i2c_client client;
|
|
|
|
if (g_es8388_client == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
ret = memcpy_s(&client, sizeof(client), g_es8388_client, sizeof(*g_es8388_client));
|
|
if (ret != EOK) {
|
|
return -1;
|
|
}
|
|
|
|
client.addr = (dev_addr >> 1);
|
|
|
|
/* reg_addr config */
|
|
if (reg_addr_num == 1) {
|
|
tmp_buf[idx++] = reg_addr & 0xff;
|
|
} else {
|
|
tmp_buf[idx++] = (reg_addr >> 8) & 0xff; /* 8: offset */
|
|
tmp_buf[idx++] = reg_addr & 0xff;
|
|
}
|
|
|
|
/* data config */
|
|
if (data_byte_num == 1) {
|
|
tmp_buf[idx++] = data;
|
|
} else {
|
|
tmp_buf[idx++] = (data >> 8) & 0xff; /* 8: offset */
|
|
tmp_buf[idx++] = data & 0xff;
|
|
}
|
|
|
|
while (1) {
|
|
ret = i2c_master_send(&client, tmp_buf, idx);
|
|
if (ret == idx) {
|
|
break;
|
|
} else if ((ret == -EAGAIN) && (in_atomic() || irqs_disabled())) {
|
|
continue;
|
|
} else {
|
|
dprintk(0, "i2c_master_send error, ret=%d.\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned char es8388_read(unsigned char dev_addr, unsigned char reg_addr)
|
|
{
|
|
return ot_i2c_read(dev_addr, reg_addr, 1, 1);
|
|
}
|
|
|
|
int es8388_write(unsigned char dev_addr, unsigned char reg_addr, unsigned char data)
|
|
{
|
|
return ot_i2c_write(dev_addr, reg_addr, 1, data, 1);
|
|
}
|
|
#else
|
|
int es8388_write(unsigned char dev_addr, unsigned char reg_addr, unsigned char value)
|
|
{
|
|
return ot_test_i2c_write(dev_addr, reg_addr, 1, value, 1);
|
|
}
|
|
|
|
int es8388_read(unsigned char dev_addr, unsigned char reg_addr)
|
|
{
|
|
return ot_test_i2c_read(dev_addr, reg_addr, 1, 1);
|
|
}
|
|
#endif
|
|
|
|
void es8388_reg_dump(unsigned int reg_num)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; i < reg_num; i++) {
|
|
printk("reg%d =%x,", i, es8388_read(g_iic_device_addr[0], i));
|
|
if ((i + 1) % 8 == 0) { /* 8: print num per line */
|
|
printk("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void es8388_codec_soft_reset(unsigned int chip_num)
|
|
{
|
|
unsigned int i2c_dev;
|
|
|
|
if (chip_num >= CHIP_NUM) {
|
|
return;
|
|
}
|
|
|
|
i2c_dev = g_iic_device_addr[chip_num];
|
|
|
|
es8388_write(i2c_dev, 0x02, 0xF3); /* stop STM and DLL, power down DAC&ADC vref. */
|
|
es8388_write(i2c_dev, 0x08, 0x00); /* I2S salve, BCLKDIV auto. */
|
|
es8388_write(i2c_dev, 0x2B, 0x80); /* ADC and DAC have the same LRCK. */
|
|
es8388_write(i2c_dev, 0x00, 0x16);
|
|
es8388_write(i2c_dev, 0x01, 0x72);
|
|
es8388_write(i2c_dev, 0x03, 0xF0); /* Power off ADC and LIN/RIN input. */
|
|
es8388_write(i2c_dev, 0x04, 0xC0); /* power off DAC and LOUT&ROUT. */
|
|
es8388_write(i2c_dev, 0x07, 0x7C); /* VSEL normal */
|
|
|
|
/* ADC SET */
|
|
es8388_write(i2c_dev, 0x09, 0x00); /* Mic Boost PGA = 0dB. */
|
|
es8388_write(i2c_dev, 0x0A, 0x50); /* LINSEL = LINPUT2, RINSEL = RINPUT2. */
|
|
es8388_write(i2c_dev, 0x0B, 0x02); /* select LIN1 and RIN1 as differential pair */
|
|
es8388_write(i2c_dev, 0x0C, 0x0C); /* I2S, 16bit, Ldata = LADC, Rdata= RADC. */
|
|
es8388_write(i2c_dev, 0x0D, 0x02); /* MCLK/LRCK = 256. */
|
|
es8388_write(i2c_dev, 0x10, 0x00); /* LADC VOL = 0dB. */
|
|
es8388_write(i2c_dev, 0x11, 0x00); /* RADC VOL = 0dB. */
|
|
|
|
/* ALC SET */
|
|
es8388_write(i2c_dev, 0x12, 0x22); /* ALCSEL = off, PGA MAXGAIN = 17.5dB, MINGAIN = 0dB. */
|
|
es8388_write(i2c_dev, 0x13, 0xA0); /* ALCLVL = -1.5dB, ALCHLD = 0ms. */
|
|
es8388_write(i2c_dev, 0x14, 0x05); /* ALCDCY = 420ms, ALCATK = 3.328ms. */
|
|
es8388_write(i2c_dev, 0x15, 0x06); /* ALCMODE = Normal. */
|
|
es8388_write(i2c_dev, 0x16, 0x90); /* Noise gate = disable. */
|
|
|
|
/* DAC SET */
|
|
es8388_write(i2c_dev, 0x17, 0x18); /* I2S, 16bit, Ldata = LDAC, Rdata= RDAC. */
|
|
es8388_write(i2c_dev, 0x18, 0x02); /* MCLK/LRCK = 256. */
|
|
es8388_write(i2c_dev, 0x19, 0x02); /* DACMute = normal. */
|
|
es8388_write(i2c_dev, 0x1A, 0x00); /* LDAC VOL = 0dB. */
|
|
es8388_write(i2c_dev, 0x1B, 0x00); /* RDAC VOL = 0dB. */
|
|
es8388_write(i2c_dev, 0x26, 0x00); /* LMIXSEL = LIN1, RMIXSEL = RIN1. */
|
|
es8388_write(i2c_dev, 0x27, 0xB8); /* LIN signal to left mixer disable. */
|
|
es8388_write(i2c_dev, 0x2A, 0xB8); /* RIN signal to right mixer disable. */
|
|
es8388_write(i2c_dev, 0x2E, 0x1E); /* LOUT1VOL = 0dB. */
|
|
es8388_write(i2c_dev, 0x2F, 0x1E); /* ROUT1VOL = 0dB. */
|
|
es8388_write(i2c_dev, 0x30, 0x1E); /* LOUT2VOL = 0dB */
|
|
es8388_write(i2c_dev, 0x31, 0x1E); /* ROUT2VOL = 0dB */
|
|
|
|
es8388_write(i2c_dev, 0x02, 0x00); /* start STM and DLL, power on DAC&ADC vref. */
|
|
}
|
|
|
|
/*
|
|
* device open. set counter
|
|
*/
|
|
static int es8388_open(struct inode *inode, struct file *file)
|
|
{
|
|
(void)inode;
|
|
(void)file;
|
|
if (g_open_cnt == 0) {
|
|
g_open_cnt++;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Close device, Do nothing!
|
|
*/
|
|
static int es8388_close(struct inode *inode, struct file *file)
|
|
{
|
|
(void)inode;
|
|
(void)file;
|
|
g_open_cnt--;
|
|
return 0;
|
|
}
|
|
|
|
static void es8388_set_adc_mclk_lrclk_ratio(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg13_ctrl reg13_ctrl;
|
|
reg13_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG13_ADC_CONTROL5);
|
|
reg13_ctrl.bit.adc_fs_ratio = audio_ctrl->clk_div;
|
|
es8388_write(i2c_dev, ES8388_REG13_ADC_CONTROL5, reg13_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_dac_mclk_lrclk_ratio(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg24_ctrl reg24_ctrl;
|
|
reg24_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG24_DAC_CONTROL2);
|
|
reg24_ctrl.bit.dac_fs_ratio = audio_ctrl->clk_div;
|
|
es8388_write(i2c_dev, ES8388_REG24_DAC_CONTROL2, reg24_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_mclk_bclk_ratio(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg8_ctrl reg8_ctrl;
|
|
reg8_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL);
|
|
reg8_ctrl.bit.bclk_div = audio_ctrl->clk_div;
|
|
es8388_write(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL, reg8_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_adc_polarity_and_offset(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg12_ctrl reg12_ctrl;
|
|
reg12_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG12_ADC_CONTROL4);
|
|
reg12_ctrl.bit.adc_lr_p = audio_ctrl->clk_polarity;
|
|
es8388_write(i2c_dev, ES8388_REG12_ADC_CONTROL4, reg12_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_dac_polarity_and_offset(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg23_ctrl reg23_ctrl;
|
|
reg23_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG23_DAC_CONTROL1);
|
|
reg23_ctrl.bit.dac_lr_p = audio_ctrl->clk_polarity;
|
|
es8388_write(i2c_dev, ES8388_REG23_DAC_CONTROL1, reg23_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_master_mode(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg8_ctrl reg8_ctrl;
|
|
reg8_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL);
|
|
reg8_ctrl.bit.msc = audio_ctrl->ctrl_mode;
|
|
es8388_write(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL, reg8_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_bclk_dir(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg8_ctrl reg8_ctrl;
|
|
reg8_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL);
|
|
reg8_ctrl.bit.bclk_inv = audio_ctrl->clk_polarity;
|
|
es8388_write(i2c_dev, ES8388_REG8_MASTER_MODE_CONTROL, reg8_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_adc_data_width(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg12_ctrl reg12_ctrl;
|
|
reg12_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG12_ADC_CONTROL4);
|
|
reg12_ctrl.bit.adc_wl = audio_ctrl->data_length;
|
|
es8388_write(i2c_dev, ES8388_REG12_ADC_CONTROL4, reg12_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_dac_data_width(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg23_ctrl reg23_ctrl;
|
|
reg23_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG23_DAC_CONTROL1);
|
|
reg23_ctrl.bit.dac_wl = audio_ctrl->data_length;
|
|
es8388_write(i2c_dev, ES8388_REG23_DAC_CONTROL1, reg23_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_adc_data_format(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg12_ctrl reg12_ctrl;
|
|
reg12_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG12_ADC_CONTROL4);
|
|
reg12_ctrl.bit.adc_format = audio_ctrl->data_format;
|
|
es8388_write(i2c_dev, ES8388_REG12_ADC_CONTROL4, reg12_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_dac_data_format(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg23_ctrl reg23_ctrl;
|
|
reg23_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG23_DAC_CONTROL1);
|
|
reg23_ctrl.bit.dac_format = audio_ctrl->data_format;
|
|
es8388_write(i2c_dev, ES8388_REG23_DAC_CONTROL1, reg23_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_input_select(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg10_ctrl reg10_ctrl;
|
|
reg10_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG10_ADC_CONTROL2);
|
|
reg10_ctrl.bit.lin_sel = audio_ctrl->audio_in_select;
|
|
es8388_write(i2c_dev, ES8388_REG10_ADC_CONTROL2, reg10_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_input_select(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg10_ctrl reg10_ctrl;
|
|
reg10_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG10_ADC_CONTROL2);
|
|
reg10_ctrl.bit.rin_sel = audio_ctrl->audio_in_select;
|
|
es8388_write(i2c_dev, ES8388_REG10_ADC_CONTROL2, reg10_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_input_gain(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg9_ctrl reg9_ctrl;
|
|
reg9_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG9_ADC_CONTROL1);
|
|
reg9_ctrl.bit.mic_amp_l = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG9_ADC_CONTROL1, reg9_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_input_gain(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg9_ctrl reg9_ctrl;
|
|
reg9_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG9_ADC_CONTROL1);
|
|
reg9_ctrl.bit.mic_amp_r = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG9_ADC_CONTROL1, reg9_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_adc_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg16_ctrl reg16_ctrl;
|
|
reg16_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG16_ADC_CONTROL8);
|
|
reg16_ctrl.bit.ladc_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG16_ADC_CONTROL8, reg16_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_adc_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg17_ctrl reg17_ctrl;
|
|
reg17_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG17_ADC_CONTROL9);
|
|
reg17_ctrl.bit.radc_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG17_ADC_CONTROL9, reg17_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_adc_mute(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg15_ctrl reg15_ctrl;
|
|
reg15_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG15_ADC_CONTROL7);
|
|
reg15_ctrl.bit.adc_mute = audio_ctrl->if_mute;
|
|
es8388_write(i2c_dev, ES8388_REG15_ADC_CONTROL7, reg15_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_dac_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg26_ctrl reg26_ctrl;
|
|
reg26_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG26_DAC_CONTROL4);
|
|
reg26_ctrl.bit.ldac_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG26_DAC_CONTROL4, reg26_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_dac_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg27_ctrl reg27_ctrl;
|
|
reg27_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG27_DAC_CONTROL5);
|
|
reg27_ctrl.bit.rdac_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG27_DAC_CONTROL5, reg27_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_output1_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg46_ctrl reg46_ctrl;
|
|
reg46_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG46_DAC_CONTROL24);
|
|
reg46_ctrl.bit.lout1_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG46_DAC_CONTROL24, reg46_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_output2_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg48_ctrl reg48_ctrl;
|
|
reg48_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG48_DAC_CONTROL26);
|
|
reg48_ctrl.bit.lout2_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG48_DAC_CONTROL26, reg48_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_output1_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg47_ctrl reg47_ctrl;
|
|
reg47_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG47_DAC_CONTROL25);
|
|
reg47_ctrl.bit.rout1_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG47_DAC_CONTROL25, reg47_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_output2_volume(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg49_ctrl reg49_ctrl;
|
|
reg49_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG49_DAC_CONTROL27);
|
|
reg49_ctrl.bit.rout2_vol = audio_ctrl->volume;
|
|
es8388_write(i2c_dev, ES8388_REG49_DAC_CONTROL27, reg49_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_dac_mute(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg25_ctrl reg25_ctrl;
|
|
reg25_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG25_DAC_CONTROL3);
|
|
reg25_ctrl.bit.dac_mute = audio_ctrl->if_mute;
|
|
es8388_write(i2c_dev, ES8388_REG25_DAC_CONTROL3, reg25_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_input_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg3_ctrl reg3_ctrl;
|
|
reg3_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT);
|
|
reg3_ctrl.bit.pdn_ainl = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT, reg3_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_input_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg3_ctrl reg3_ctrl;
|
|
reg3_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT);
|
|
reg3_ctrl.bit.pdn_ainr = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT, reg3_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_adc_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg3_ctrl reg3_ctrl;
|
|
reg3_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT);
|
|
reg3_ctrl.bit.pdn_adcl = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT, reg3_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_adc_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg3_ctrl reg3_ctrl;
|
|
reg3_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT);
|
|
reg3_ctrl.bit.pdn_adcr = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG3_ADC_POWER_MANAGEMENT, reg3_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_dac_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.pdn_dacl = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_dac_power(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.pdn_dacr = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_output1_enable(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.lout1 = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_output1_enable(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.rout1 = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_left_output2_enable(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.lout2 = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static void es8388_set_right_output2_enable(unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
es8388_reg4_ctrl reg4_ctrl;
|
|
reg4_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT);
|
|
reg4_ctrl.bit.rout2 = audio_ctrl->if_powerup;
|
|
es8388_write(i2c_dev, ES8388_REG4_DAC_POWER_MANAGEMENT, reg4_ctrl.b8);
|
|
return;
|
|
}
|
|
|
|
static int ioctl_clk(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_ADC_MCLK_LRCLK_RATIO:
|
|
es8388_set_adc_mclk_lrclk_ratio(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_DAC_MCLK_LRCLK_RATIO:
|
|
es8388_set_dac_mclk_lrclk_ratio(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_MCLK_BCLK_RATIO:
|
|
es8388_set_mclk_bclk_ratio(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_ADC_POLARITY_AND_OFFSET:
|
|
es8388_set_adc_polarity_and_offset(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_DAC_POLARITY_AND_OFFSET:
|
|
es8388_set_dac_polarity_and_offset(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_MASTER_MODE:
|
|
es8388_set_master_mode(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_BCLK_DIR:
|
|
es8388_set_bclk_dir(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_data(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_ADC_DATA_WIDTH:
|
|
es8388_set_adc_data_width(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_DAC_DATA_WIDTH:
|
|
es8388_set_dac_data_width(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_ADC_DATA_FORMAT:
|
|
es8388_set_adc_data_format(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_DAC_DATA_FORMAT:
|
|
es8388_set_dac_data_format(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_input_select(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_LEFT_INPUT_SELECT:
|
|
es8388_set_left_input_select(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_INPUT_SELECT:
|
|
es8388_set_right_input_select(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_input_volume(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
/* input volume control */
|
|
case OT_ES8388_SET_LFET_INPUT_GAIN:
|
|
es8388_set_left_input_gain(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_INPUT_GAIN:
|
|
es8388_set_right_input_gain(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_ADC_VOLUME:
|
|
es8388_set_left_adc_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_ADC_VOLUME:
|
|
es8388_set_right_adc_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_ADC_MUTE:
|
|
es8388_set_adc_mute(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_output_volume(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_LFET_DAC_VOLUME:
|
|
es8388_set_left_dac_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_DAC_VOLUME:
|
|
es8388_set_right_dac_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_OUTPUT1_VOLUME:
|
|
es8388_set_left_output1_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_OUTPUT2_VOLUME:
|
|
es8388_set_left_output2_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_OUTPUT1_VOLUME:
|
|
es8388_set_right_output1_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_OUTPUT2_VOLUME:
|
|
es8388_set_right_output2_volume(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_DAC_MUTE:
|
|
es8388_set_dac_mute(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_input_power(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_LFET_INPUT_POWER:
|
|
es8388_set_left_input_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_INPUT_POWER:
|
|
es8388_set_right_input_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_ADC_POWER:
|
|
es8388_set_left_adc_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_ADC_POWER:
|
|
es8388_set_right_adc_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_output_power(unsigned int cmd, unsigned int i2c_dev, const ot_es8388_audio_ctrl *audio_ctrl)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SET_LFET_DAC_POWER:
|
|
es8388_set_left_dac_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_DAC_POWER:
|
|
es8388_set_right_dac_power(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_OUTPUT1_ENABLE:
|
|
es8388_set_left_output1_enable(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_OUTPUT1_ENABLE:
|
|
es8388_set_right_output1_enable(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_LFET_OUTPUT2_ENABLE:
|
|
es8388_set_left_output2_enable(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
case OT_ES8388_SET_RIGHT_OUTPUT2_ENABLE:
|
|
es8388_set_right_output2_enable(i2c_dev, audio_ctrl);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_control(unsigned int cmd, unsigned int chip_num)
|
|
{
|
|
switch (cmd) {
|
|
case OT_ES8388_SOFT_RESET:
|
|
es8388_codec_soft_reset(chip_num);
|
|
break;
|
|
|
|
case OT_ES8388_REG_DUMP:
|
|
es8388_reg_dump(ES8388_REG_NUM);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int es8388_ioctl_adp_other(unsigned int cmd, unsigned int i2c_dev,
|
|
const ot_es8388_audio_ctrl *audio_ctrl, unsigned int chip_num)
|
|
{
|
|
switch (cmd) {
|
|
/* output volume */
|
|
case OT_ES8388_SET_LFET_DAC_VOLUME:
|
|
case OT_ES8388_SET_RIGHT_DAC_VOLUME:
|
|
case OT_ES8388_SET_LFET_OUTPUT1_VOLUME:
|
|
case OT_ES8388_SET_LFET_OUTPUT2_VOLUME:
|
|
case OT_ES8388_SET_RIGHT_OUTPUT1_VOLUME:
|
|
case OT_ES8388_SET_RIGHT_OUTPUT2_VOLUME:
|
|
case OT_ES8388_SET_DAC_MUTE:
|
|
return ioctl_output_volume(cmd, i2c_dev, audio_ctrl);
|
|
|
|
/* input power */
|
|
case OT_ES8388_SET_LFET_INPUT_POWER:
|
|
case OT_ES8388_SET_RIGHT_INPUT_POWER:
|
|
case OT_ES8388_SET_LFET_ADC_POWER:
|
|
case OT_ES8388_SET_RIGHT_ADC_POWER:
|
|
return ioctl_input_power(cmd, i2c_dev, audio_ctrl);
|
|
|
|
/* output power */
|
|
case OT_ES8388_SET_LFET_DAC_POWER:
|
|
case OT_ES8388_SET_RIGHT_DAC_POWER:
|
|
case OT_ES8388_SET_LFET_OUTPUT1_ENABLE:
|
|
case OT_ES8388_SET_RIGHT_OUTPUT1_ENABLE:
|
|
case OT_ES8388_SET_LFET_OUTPUT2_ENABLE:
|
|
case OT_ES8388_SET_RIGHT_OUTPUT2_ENABLE:
|
|
return ioctl_output_power(cmd, i2c_dev, audio_ctrl);
|
|
|
|
/* control */
|
|
case OT_ES8388_SOFT_RESET:
|
|
case OT_ES8388_REG_DUMP:
|
|
return ioctl_control(cmd, chip_num);
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static int es8388_ioctl_adp(unsigned int cmd, unsigned int i2c_dev,
|
|
const ot_es8388_audio_ctrl *audio_ctrl, unsigned int chip_num)
|
|
{
|
|
switch (cmd) {
|
|
/* clk */
|
|
case OT_ES8388_SET_ADC_MCLK_LRCLK_RATIO:
|
|
case OT_ES8388_SET_DAC_MCLK_LRCLK_RATIO:
|
|
case OT_ES8388_SET_MCLK_BCLK_RATIO:
|
|
case OT_ES8388_SET_ADC_POLARITY_AND_OFFSET:
|
|
case OT_ES8388_SET_DAC_POLARITY_AND_OFFSET:
|
|
case OT_ES8388_SET_MASTER_MODE:
|
|
case OT_ES8388_SET_BCLK_DIR:
|
|
return ioctl_clk(cmd, i2c_dev, audio_ctrl);
|
|
|
|
/* data */
|
|
case OT_ES8388_SET_ADC_DATA_WIDTH:
|
|
case OT_ES8388_SET_DAC_DATA_WIDTH:
|
|
case OT_ES8388_SET_ADC_DATA_FORMAT:
|
|
case OT_ES8388_SET_DAC_DATA_FORMAT:
|
|
return ioctl_data(cmd, i2c_dev, audio_ctrl);
|
|
/* input select */
|
|
case OT_ES8388_SET_LEFT_INPUT_SELECT:
|
|
case OT_ES8388_SET_RIGHT_INPUT_SELECT:
|
|
return ioctl_input_select(cmd, i2c_dev, audio_ctrl);
|
|
|
|
/* input volume */
|
|
case OT_ES8388_SET_LFET_INPUT_GAIN:
|
|
case OT_ES8388_SET_RIGHT_INPUT_GAIN:
|
|
case OT_ES8388_SET_LFET_ADC_VOLUME:
|
|
case OT_ES8388_SET_RIGHT_ADC_VOLUME:
|
|
case OT_ES8388_SET_ADC_MUTE:
|
|
return ioctl_input_volume(cmd, i2c_dev, audio_ctrl);
|
|
|
|
default:
|
|
return es8388_ioctl_adp_other(cmd, i2c_dev, audio_ctrl, chip_num);
|
|
}
|
|
}
|
|
|
|
#ifndef __LITEOS__
|
|
static long es8388_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
#else
|
|
static long es8388_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
#endif
|
|
{
|
|
unsigned int __user *argp = (unsigned int __user *)(uintptr_t)arg;
|
|
unsigned int chip_num;
|
|
unsigned int i2c_dev;
|
|
int ret;
|
|
ot_es8388_audio_ctrl temp = {0};
|
|
ot_es8388_audio_ctrl *audio_ctrl = NULL;
|
|
|
|
(void)file;
|
|
|
|
if (argp != NULL) {
|
|
if (copy_from_user(&temp, argp, sizeof(ot_es8388_audio_ctrl))) {
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
audio_ctrl = (ot_es8388_audio_ctrl*)(&temp);
|
|
chip_num = audio_ctrl->chip_num;
|
|
if (chip_num >= CHIP_NUM) {
|
|
return -1;
|
|
}
|
|
i2c_dev = g_iic_device_addr[chip_num];
|
|
|
|
ret = es8388_ioctl_adp(cmd, i2c_dev, audio_ctrl, chip_num);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifndef __LITEOS__
|
|
/*
|
|
* The various file operations we support.
|
|
*/
|
|
static struct file_operations g_es8388_fops = {
|
|
.owner = THIS_MODULE,
|
|
.unlocked_ioctl = es8388_ioctl,
|
|
.open = es8388_open,
|
|
.release = es8388_close,
|
|
#ifdef CONFIG_COMPAT
|
|
.compat_ioctl = es8388_ioctl
|
|
#endif
|
|
};
|
|
#else
|
|
static struct file_operations_vfs g_es8388_fops = {
|
|
.ioctl = es8388_ioctl,
|
|
.open = es8388_open,
|
|
.close = es8388_close,
|
|
};
|
|
#endif
|
|
|
|
#ifndef __LITEOS__
|
|
static struct miscdevice g_es8388_dev = {
|
|
MISC_DYNAMIC_MINOR,
|
|
DEV_NAME,
|
|
&g_es8388_fops,
|
|
};
|
|
|
|
static int set_chip_count(const char *val, const struct kernel_param *kp)
|
|
{
|
|
int ret, chip_cnt;
|
|
|
|
(void)kp;
|
|
|
|
ret = kstrtoint(val, 10, &chip_cnt); /* 10: number base */
|
|
if (ret < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (chip_cnt < 0 || chip_cnt > CHIP_NUM) {
|
|
printk("chip_count = %d err.\n", chip_cnt);
|
|
return -EINVAL;
|
|
}
|
|
|
|
g_chip_count = chip_cnt;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct kernel_param_ops g_es8388_para_ops = {
|
|
.set = set_chip_count,
|
|
};
|
|
|
|
module_param_cb(g_chip_count, &g_es8388_para_ops, &g_chip_count, 0644);
|
|
|
|
MODULE_PARM_DESC(g_chip_count, "the es8388 num of our device using, default 1");
|
|
|
|
static int es8388_reboot(struct notifier_block *self, unsigned long data, void *pdata)
|
|
{
|
|
unsigned int i;
|
|
unsigned int i2c_dev;
|
|
es8388_reg25_ctrl reg25_ctrl;
|
|
|
|
(void)self;
|
|
(void)data;
|
|
(void)pdata;
|
|
|
|
for (i = 0; i < g_chip_count; i++) {
|
|
if (i >= CHIP_NUM) {
|
|
break;
|
|
}
|
|
|
|
i2c_dev = g_iic_device_addr[i];
|
|
|
|
/* mute output */
|
|
reg25_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG25_DAC_CONTROL3);
|
|
reg25_ctrl.bit.dac_mute = ES8388_MUTE_ENABLE;
|
|
es8388_write(i2c_dev, ES8388_REG25_DAC_CONTROL3, reg25_ctrl.b8);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct notifier_block g_es8388_reboot_notifier = {
|
|
.notifier_call = es8388_reboot,
|
|
};
|
|
#endif
|
|
|
|
static int es8388_device_init(unsigned int num)
|
|
{
|
|
/* init codec configs. */
|
|
unsigned char temp;
|
|
unsigned int i2c_dev;
|
|
|
|
if (num >= CHIP_NUM) {
|
|
return -1;
|
|
}
|
|
|
|
i2c_dev = g_iic_device_addr[num];
|
|
|
|
/* test i2c if ok */
|
|
temp = es8388_read(i2c_dev, 0x2);
|
|
es8388_write(i2c_dev, 0x2, 0xaa);
|
|
if (es8388_read(i2c_dev, 0x2) != 0xaa) {
|
|
dprintk(0, "init es8388(%d) error", num);
|
|
return -1;
|
|
}
|
|
es8388_write(i2c_dev, 0x2, temp);
|
|
|
|
es8388_codec_soft_reset(num);
|
|
|
|
#ifndef __LITEOS__
|
|
register_reboot_notifier(&g_es8388_reboot_notifier);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int es8388_device_exit(unsigned int num)
|
|
{
|
|
es8388_reg25_ctrl reg25_ctrl;
|
|
unsigned int i2c_dev;
|
|
|
|
if (num >= CHIP_NUM) {
|
|
return -1;
|
|
}
|
|
|
|
i2c_dev = g_iic_device_addr[num];
|
|
|
|
/* mute output */
|
|
reg25_ctrl.b8 = es8388_read(i2c_dev, ES8388_REG25_DAC_CONTROL3);
|
|
reg25_ctrl.bit.dac_mute = ES8388_MUTE_ENABLE;
|
|
es8388_write(i2c_dev, ES8388_REG25_DAC_CONTROL3, reg25_ctrl.b8);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef __LITEOS__
|
|
struct i2c_client g_es8388_client_obj;
|
|
struct i2c_client *ot_es8388_i2c_client_init(void)
|
|
{
|
|
g_es8388_client_obj.addr = g_iic_device_addr[0];
|
|
g_es8388_client_obj.flags = 0x00;
|
|
|
|
client_attach(&g_es8388_client_obj, ES8388_I2C_ADAPTER_ID);
|
|
|
|
return &g_es8388_client_obj;
|
|
}
|
|
#endif
|
|
|
|
static int i2c_client_init(void)
|
|
{
|
|
#ifdef __LITEOS__
|
|
g_es8388_client = ot_es8388_i2c_client_init();
|
|
#else
|
|
struct i2c_adapter *i2c_adap = i2c_get_adapter(ES8388_I2C_ADAPTER_ID);
|
|
g_es8388_client = i2c_new_device(i2c_adap, &g_board_info);
|
|
i2c_put_adapter(i2c_adap);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static void i2c_client_exit(void)
|
|
{
|
|
if (g_es8388_client != NULL) {
|
|
i2c_unregister_device(g_es8388_client);
|
|
g_es8388_client = NULL;
|
|
}
|
|
}
|
|
|
|
static int __init es8388_init(void)
|
|
{
|
|
unsigned int i, ret;
|
|
|
|
#ifndef __LITEOS__
|
|
ret = misc_register(&g_es8388_dev);
|
|
#else
|
|
ret = register_driver("/dev/es8388", &g_es8388_fops, 0666, 0);
|
|
#endif
|
|
if (ret) {
|
|
dprintk(0, "could not register es8388 device");
|
|
return -1;
|
|
}
|
|
|
|
i2c_client_init();
|
|
for (i = 0; i < g_chip_count; i++) {
|
|
if (es8388_device_init(i) < 0) {
|
|
goto init_fail;
|
|
}
|
|
}
|
|
printk("load es8388.ko ....OK!\n");
|
|
return 0;
|
|
|
|
init_fail:
|
|
#ifndef __LITEOS__
|
|
misc_deregister(&g_es8388_dev);
|
|
#else
|
|
unregister_driver("/dev/es8388");
|
|
#endif
|
|
printk("load es8388.ko ....failed!\n");
|
|
return -1;
|
|
}
|
|
|
|
static void __exit es8388_exit(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < g_chip_count; i++) {
|
|
es8388_device_exit(i);
|
|
}
|
|
|
|
#ifndef __LITEOS__
|
|
unregister_reboot_notifier(&g_es8388_reboot_notifier);
|
|
|
|
misc_deregister(&g_es8388_dev);
|
|
#else
|
|
unregister_driver("/dev/es8388");
|
|
#endif
|
|
i2c_client_exit();
|
|
|
|
printk("unload es8388.ko ....OK!\n");
|
|
}
|
|
|
|
module_init(es8388_init);
|
|
module_exit(es8388_exit);
|
|
MODULE_LICENSE("GPL");
|