SmartAudio/lichee/linux-4.9/sound/soc/codecs/es7243.c

973 lines
28 KiB
C

/*
* ALSA SoC ES7243 adc driver
*
* Author: David Yang, <yangxiaohua@everest-semi.com>
* or
* <info@everest-semi.com>
* Copyright: (C) 2017 Everest Semiconductor Co Ltd.,
*
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Notes:
* ES7243 is a stereo ADC of Everest
*
*/
#define DEBUG
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "es7243.h"
#define ES7243_TDM_ENABLE 0
#define ES7243_CHANNELS_MAX 2
#define ES7243_I2C_BUS_NUM 0
#define ES7243_CODEC_RW_TEST_EN 0
#define ES7243_IDLE_RESET_EN 1 // reset ES7243 when in idle time
#define ES7243_MATCH_DTS_EN \
0 // ES7243 match method select: 0: i2c_detect, 1:of_device_id
struct i2c_client *i2c_clt[(ES7243_CHANNELS_MAX) / 2];
/* codec private data */
struct es7243_priv {
struct regmap *regmap;
struct i2c_client *i2c;
unsigned int dmic_amic;
unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
unsigned int tdm;
struct delayed_work pcm_pop_work;
struct delayed_work pcm_pop_work1;
};
struct snd_soc_codec *tron_codec[4];
int es7243_init_reg = 0;
static int es7243_codec_num = 0;
static const struct regmap_config es7243_regmap_config = {
.reg_bits = 8, // Number of bits in a register address
.val_bits = 8, // Number of bits in a register value
};
/*
* ES7243 register cache
*/
static const u8 es7243_reg[] = {
0x00, 0x00, 0x10, 0x04, /* 0 */
0x02, 0x13, 0x00, 0x3f, /* 4 */
0x11, 0x00, 0xc0, 0xc0, /* 8 */
0x12, 0xa0, 0x40, /* 12 */
};
static const struct reg_default es7243_reg_defaults[] = {
{0x00, 0x00}, {0x01, 0x00}, {0x02, 0x10}, {0x03, 0x04}, /* 0 */
{0x04, 0x02}, {0x05, 0x13}, {0x06, 0x00}, {0x07, 0x3f}, /* 4 */
{0x08, 0x11}, {0x09, 0x00}, {0x0a, 0xc0}, {0x0b, 0xc0}, /* 8 */
{0x0c, 0x12}, {0x0d, 0xa0}, {0x0e, 0x40}, /* 12 */
};
static int es7243_read(u8 reg, u8 *rt_value, struct i2c_client *client) {
int ret;
u8 read_cmd[3] = {0};
u8 cmd_len = 0;
read_cmd[0] = reg;
cmd_len = 1;
if (client->adapter == NULL)
pr_err("es7243_read client->adapter==NULL\n");
ret = i2c_master_send(client, read_cmd, cmd_len);
if (ret != cmd_len) {
pr_err("es7243_read error1\n");
return -1;
}
ret = i2c_master_recv(client, rt_value, 1);
if (ret != 1) {
pr_err("es7243_read error2, ret = %d.\n", ret);
return -1;
}
return 0;
}
static int es7243_write(u8 reg, unsigned char value,
struct i2c_client *client) {
int ret = 0;
u8 write_cmd[2] = {0};
write_cmd[0] = reg;
write_cmd[1] = value;
ret = i2c_master_send(client, write_cmd, 2);
if (ret != 2) {
pr_err("es7243_write error->[REG-0x%02x,val-0x%02x]\n", reg, value);
return -1;
}
return 0;
}
static int es7243_update_bits(u8 reg, u8 mask, u8 value,
struct i2c_client *client) {
u8 val_old, val_new;
es7243_read(reg, &val_old, client);
val_new = (val_old & ~mask) | (value & mask);
if (val_new != val_old) {
es7243_write(reg, val_new, client);
}
return 0;
}
#if 0
static int es7243_multi_chips_read(u8 reg, unsigned char *rt_value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_read(reg, rt_value++, i2c_clt[i]);
}
return 0;
}
static int es7243_multi_chips_write(u8 reg, unsigned char value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_write(reg, value, i2c_clt[i]);
}
return 0;
}
#endif
#if 0
static int es7243_multi_chips_update_bits(u8 reg, u8 mask, u8 value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_update_bits(reg, mask, value, i2c_clt[i]);
}
return 0;
}
#endif
struct _coeff_div {
u32 mclk; // mclk frequency
u32 sr_rate; // sample rate
u8 speedmode; // speed mode,0=single,1=double,2=quad
u8 adc_clk_div; // adcclk and dacclk divider
u8 lrckdiv; // adclrck divider and daclrck divider
u8 bclkdiv; // sclk divider
u8 osr; // adc osr
};
/* codec hifi mclk clock divider coefficients */
static const struct _coeff_div coeff_div[] = {
/* 12.288MHZ */
{12288000, 8000, 0, 0x0c, 0x60, 24, 32},
{12288000, 12000, 0, 0x08, 0x40, 16, 32},
{12288000, 16000, 0, 0x06, 0x30, 12, 32},
{12288000, 24000, 0, 0x04, 0x20, 8, 32},
{12288000, 32000, 0, 0x03, 0x18, 6, 32},
{12288000, 48000, 0, 0x02, 0x10, 4, 32},
{12288000, 64000, 1, 0x03, 0x0c, 3, 32},
{12288000, 96000, 1, 0x02, 0x08, 2, 32},
/* 11.2896MHZ */
{11289600, 11025, 0, 0x08, 0x40, 16, 32},
{11289600, 22050, 0, 0x04, 0x20, 8, 32},
{11289600, 44100, 0, 0x02, 0x10, 4, 32},
{11289600, 88200, 1, 0x02, 0x08, 2, 32},
/* 12.000MHZ */
{12000000, 8000, 0, 0x0c, 0xbc, 30, 31},
{12000000, 11025, 0, 0x08, 0x44, 17, 34},
{12000000, 12000, 0, 0x08, 0xaa, 20, 31},
{12000000, 16000, 0, 0x06, 0x9e, 15, 31},
{12000000, 22050, 0, 0x04, 0x22, 8, 34},
{12000000, 24000, 0, 0x04, 0x94, 10, 31},
{12000000, 32000, 0, 0x03, 0x8a, 5, 31},
{12000000, 44100, 0, 0x02, 0x11, 4, 34},
{12000000, 48000, 0, 0x02, 0x85, 5, 31},
{12000000, 96000, 1, 0x02, 0x85, 1, 31},
};
static inline int get_coeff(int mclk, int rate) {
int i;
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
if (coeff_div[i].sr_rate == rate && coeff_div[i].mclk == mclk)
return i;
}
return -EINVAL;
}
/* The set of rates we can generate from the above for each SYSCLK */
static unsigned int rates_12288[] = {
8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
};
static struct snd_pcm_hw_constraint_list constraints_12288 = {
.count = ARRAY_SIZE(rates_12288),
.list = rates_12288,
};
static unsigned int rates_112896[] = {
8000,
11025,
22050,
44100,
};
static struct snd_pcm_hw_constraint_list constraints_112896 = {
.count = ARRAY_SIZE(rates_112896),
.list = rates_112896,
};
static unsigned int rates_12[] = {
8000, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 48000, 88235, 96000,
};
static struct snd_pcm_hw_constraint_list constraints_12 = {
.count = ARRAY_SIZE(rates_12),
.list = rates_12,
};
/*
* Note that this should be called from init rather than from hw_params.
*/
static int es7243_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
unsigned int freq, int dir) {
struct snd_soc_codec *codec = codec_dai->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
printk("es7243_set_dai_sysclk: %d\n", freq);
switch (freq) {
case 11289600:
case 22579200:
es7243->sysclk_constraints = &constraints_112896;
es7243->sysclk = freq;
return 0;
case 12288000:
case 24576000:
es7243->sysclk_constraints = &constraints_12288;
es7243->sysclk = freq;
return 0;
case 12000000:
case 24000000:
es7243->sysclk_constraints = &constraints_12;
es7243->sysclk = freq;
return 0;
}
return -EINVAL;
}
static int es7243_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) {
// struct snd_soc_codec *codec = codec_dai->codec;
u8 iface = 0;
u8 adciface = 0;
u8 i;
printk("es7243_set_dai_fmt:%d\n", fmt);
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_read(ES7243_SDPFMT_REG01, &adciface, i2c_clt[i]);
es7243_read(ES7243_MODECFG_REG00, &iface, i2c_clt[i]);
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: // MASTER MODE
iface |= 0x02;
break;
case SND_SOC_DAIFMT_CBS_CFS: // SLAVE MODE
iface &= 0xfd;
break;
default:
return -EINVAL;
}
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
adciface &= 0xFC;
break;
case SND_SOC_DAIFMT_RIGHT_J:
return -EINVAL;
case SND_SOC_DAIFMT_LEFT_J:
adciface &= 0xFC;
adciface |= 0x01;
break;
case SND_SOC_DAIFMT_DSP_A:
adciface &= 0xDC;
adciface |= 0x03;
break;
case SND_SOC_DAIFMT_DSP_B:
adciface &= 0xDC;
adciface |= 0x23;
break;
default:
return -EINVAL;
}
/* clock inversion */
adciface &= 0xbF;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
adciface &= 0xbF;
break;
case SND_SOC_DAIFMT_IB_IF:
adciface |= 0x60;
break;
case SND_SOC_DAIFMT_IB_NF:
adciface |= 0x40;
break;
case SND_SOC_DAIFMT_NB_IF:
adciface |= 0x20;
break;
default:
return -EINVAL;
}
// es7243_update_bits(ES7243_MODECFG_REG00, 0x02, iface, i2c_clt[i]);
// es7243_update_bits(ES7243_SDPFMT_REG01, 0x03, adciface, i2c_clt[i]);
}
return 0;
}
static void es7243_init_codec(struct snd_soc_codec *codec, u8 i) {
printk("Init es7243\n");
es7243_write(ES7243_MODECFG_REG00, 0x41,
i2c_clt[i]); // enter into hardware mode, mclk / 3
es7243_write(ES7243_STATECTL_REG06, 0x18, i2c_clt[i]); // soft reset codec
// es7243_write(ES7243_SDPFMT_REG01, 0xd3, i2c_clt[i]); //dsp for tdm mode,
// DSP-A, 32BIT, bclk invert
es7243_write(ES7243_SDPFMT_REG01, 0x0d, i2c_clt[i]); // lj-16bit
es7243_write(ES7243_LRCDIV_REG02, 0x10, i2c_clt[i]);
es7243_write(ES7243_BCKDIV_REG03, 0x04, i2c_clt[i]);
es7243_write(ES7243_CLKDIV_REG04, 0x02, i2c_clt[i]);
es7243_write(ES7243_MUTECTL_REG05, 0x1a, i2c_clt[i]);
es7243_write(ES7243_ANACTL1_REG08, 0x43,
i2c_clt[i]); // enable microphone input and pga gain for 27db
es7243_write(ES7243_ANACTL2_REG09, 0x3F, i2c_clt[i]);
es7243_write(ES7243_STATECTL_REG06, 0x00, i2c_clt[i]);
es7243_write(ES7243_MUTECTL_REG05, 0x12, i2c_clt[i]);
// if(i == 3) {
// es7243_write(ES7243_ANACTL1_REG08, 0x11, i2c_clt[i]);
//}
// else {
es7243_write(ES7243_ANACTL1_REG08, 0x43,
i2c_clt[i]); // enable microphone input and pga gain for 27db
//}
es7243_write(ES7243_STATECTL_REG06, 0x00, i2c_clt[i]);
}
static void es7243_unmute(struct snd_soc_codec *codec, u8 i) {
es7243_write(ES7243_MUTECTL_REG05, 0x13, i2c_clt[i]);
}
static void pcm_pop_work1_events(struct work_struct *work) {
int i;
printk("es8316--------pcm_pop_work_events\n");
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_unmute(tron_codec[(ES7243_CHANNELS_MAX / 2 - 1) - i],
(ES7243_CHANNELS_MAX / 2 - 1 - i));
}
es7243_init_reg = 1;
}
static void pcm_pop_work_events(struct work_struct *work) {
int i;
printk("es8316--------pcm_pop_work_events\n");
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_init_codec(tron_codec[i], i);
}
es7243_init_reg = 1;
}
static int es7243_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) {
struct snd_soc_codec *codec = dai->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
return 0;
/* The set of sample rates that can be supported depends on the
* MCLK supplied to the CODEC - enforce this.
*/
if (!es7243->sysclk) {
dev_err(codec->dev, "No MCLK configured, call set_sysclk() on init\n");
return -EINVAL;
}
snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
es7243->sysclk_constraints);
return 0;
}
static int es7243_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
u8 i, val;
if (es7243_init_reg == 0 || 1) {
printk(
"==================>>>>>>>>es8316_pcm_startup es8316_init_reg=0\n");
// schedule_delayed_work(&es7243->pcm_pop_work, msecs_to_jiffies(100));
schedule_delayed_work(&es7243->pcm_pop_work, 0);
schedule_delayed_work(&es7243->pcm_pop_work1, msecs_to_jiffies(700));
}
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_read(ES7243_MODECFG_REG00, &val,
i2c_clt[i]); // enter into hardware mode
printk("%d -- Reg 00 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_STATECTL_REG06, &val, i2c_clt[i]); // soft reset
// codec
printk("%d -- Reg 06 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_SDPFMT_REG01, &val,
i2c_clt[i]); // dsp for tdm mode, DSP-A, 16BIT
printk("%d -- Reg 01 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_LRCDIV_REG02, &val, i2c_clt[i]);
printk("%d -- Reg 02 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_BCKDIV_REG03, &val, i2c_clt[i]);
printk("%d -- Reg 03 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_CLKDIV_REG04, &val, i2c_clt[i]);
printk("%d -- Reg 04 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_MUTECTL_REG05, &val, i2c_clt[i]);
printk("%d -- Reg 05 ----> 0x%x!\n", __LINE__, val);
es7243_read(
ES7243_ANACTL1_REG08, &val,
i2c_clt[i]); // enable microphone input and pga gain for 27db
printk("%d -- Reg 08 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_ANACTL2_REG09, &val, i2c_clt[i]);
printk("%d -- Reg 09 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_STATECTL_REG06, &val, i2c_clt[i]);
printk("%d -- Reg 06 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_ANACTL0_REG07, &val,
i2c_clt[i]); // power up adc and analog input
printk("%d -- Reg 07 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_MUTECTL_REG05, &val, i2c_clt[i]);
printk("%d -- Reg 05 ----> 0x%x!\n", __LINE__, val);
}
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
/* bit size */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x0c, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S20_3LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x04, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S24_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x00, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S32_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x10, i2c_clt[i]);
break;
}
}
return 0;
}
static int es7243_mute(struct snd_soc_dai *dai, int mute) {
struct snd_soc_codec *codec = dai->codec;
u8 i;
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
dev_dbg(codec->dev, "%s %d\n", __func__, mute);
if (mute) {
// es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08,
// i2c_clt[i]);
} else {
// es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x00,
// i2c_clt[i]);
}
}
return 0;
}
static int es7243_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) {
u8 i;
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
switch (level) {
case SND_SOC_BIAS_ON:
dev_dbg(codec->dev, "%s on\n", __func__);
break;
case SND_SOC_BIAS_PREPARE:
dev_dbg(codec->dev, "%s prepare\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x00, i2c_clt[i]);
msleep(50);
break;
case SND_SOC_BIAS_STANDBY:
dev_dbg(codec->dev, "%s standby\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08, i2c_clt[i]);
es7243_update_bits(ES7243_STATECTL_REG06, 0x40, 0x00, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_ANACTL0_REG07, 0x0f, 0x00, i2c_clt[i]);
break;
case SND_SOC_BIAS_OFF:
dev_dbg(codec->dev, "%s off\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_ANACTL0_REG07, 0x0f, 0x0f, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_STATECTL_REG06, 0x40, 0x40, i2c_clt[i]);
break;
}
}
// codec->dapm.bias_level = level;
return 0;
}
#define es7243_RATES SNDRV_PCM_RATE_8000_96000
#define es7243_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
static struct snd_soc_dai_ops es7243_ops = {
.startup = es7243_pcm_startup,
.hw_params = es7243_pcm_hw_params,
.set_fmt = es7243_set_dai_fmt,
.set_sysclk = es7243_set_dai_sysclk,
.digital_mute = es7243_mute,
};
static struct snd_soc_dai_driver es7243_dai0 = {
.name = "es7243",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai1 = {
.name = "ES7243 HiFi 1",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai2 = {
.name = "ES7243 HiFi 2",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai3 = {
.name = "ES7243 HiFi 3",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver *es7243_dai[] = {
#if ES7243_CHANNELS_MAX > 0
&es7243_dai0,
#endif
#if ES7243_CHANNELS_MAX > 2
&es7243_dai1,
#endif
#if ES7243_CHANNELS_MAX > 4
&es7243_dai2,
#endif
#if ES7243_CHANNELS_MAX > 6
&es7243_dai3,
#endif
};
static int es7243_suspend(struct snd_soc_codec *codec) {
es7243_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int es7243_resume(struct snd_soc_codec *codec) {
snd_soc_cache_sync(codec);
es7243_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int es7243_probe(struct snd_soc_codec *codec) {
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
#if !ES7243_CODEC_RW_TEST_EN
// ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);//8,8
#else
codec->control_data =
devm_regmap_init_i2c(es7243->i2c, &es7243_regmap_config);
ret = PTR_RET(codec->control_data);
#endif
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
printk("begin->>>>>>>>>>%s!\n", __func__);
tron_codec[es7243_codec_num++] = codec;
INIT_DELAYED_WORK(&es7243->pcm_pop_work, pcm_pop_work_events);
INIT_DELAYED_WORK(&es7243->pcm_pop_work1, pcm_pop_work1_events);
return 0;
}
static int es7243_remove(struct snd_soc_codec *codec) {
es7243_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_es7243 = {
.probe = es7243_probe,
.remove = es7243_remove,
.suspend = es7243_suspend,
.resume = es7243_resume,
.set_bias_level = es7243_set_bias_level,
.idle_bias_off = true,
.reg_word_size = sizeof(u8),
#if ES7243_CODEC_RW_TEST_EN
.read = es7243_codec_read,
.write = es7243_codec_write,
#endif
};
static ssize_t es7243_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) {
int val = 0, flag = 0;
u8 i = 0, reg, num, value_w, value_r;
struct es7243_priv *es7243 = dev_get_drvdata(dev);
val = simple_strtol(buf, NULL, 16);
flag = (val >> 16) & 0xFF;
if (flag) {
reg = (val >> 8) & 0xFF;
value_w = val & 0xFF;
printk("\nWrite: start REG:0x%02x,val:0x%02x,count:0x%02x\n", reg,
value_w, flag);
while (flag--) {
es7243_write(reg, value_w, es7243->i2c);
printk("Write 0x%02x to REG:0x%02x\n", value_w, reg);
reg++;
}
} else {
reg = (val >> 8) & 0xFF;
num = val & 0xff;
printk("\nRead: start REG:0x%02x,count:0x%02x\n", reg, num);
do {
value_r = 0;
es7243_read(reg, &value_r, es7243->i2c);
printk("REG[0x%02x]: 0x%02x; ", reg, value_r);
reg++;
i++;
if ((i == num) || (i % 4 == 0))
printk("\n");
} while (i < num);
}
return count;
}
static ssize_t es7243_show(struct device *dev, struct device_attribute *attr,
char *buf) {
printk("echo flag|reg|val > es7243\n");
printk("eg read star addres=0x06,count 0x10:echo 0610 >es7243\n");
printk("eg write star addres=0x90,value=0x3c,count=4:echo 4903c >es7243\n");
// printk("eg write value:0xfe to address:0x06 :echo 106fe > es7243\n");
return 0;
}
static DEVICE_ATTR(es7243, 0644, es7243_show, es7243_store);
static struct attribute *es7243_debug_attrs[] = {
&dev_attr_es7243.attr,
NULL,
};
static struct attribute_group es7243_debug_attr_group = {
.name = "es7243_debug",
.attrs = es7243_debug_attrs,
};
//#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
*/
static int es7243_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id) {
struct es7243_priv *es7243;
int ret;
// struct device_node *np = i2c->dev.of_node;
printk("es7243_i2c_probe begin->>>>>>>>>>%s!\n", __func__);
es7243 = devm_kzalloc(&i2c->dev, sizeof(struct es7243_priv), GFP_KERNEL);
if (es7243 == NULL)
return -ENOMEM;
es7243->i2c = i2c;
es7243->tdm = ES7243_TDM_ENABLE; // to initialize tdm mode
dev_set_drvdata(&i2c->dev, es7243);
// i2c_set_clientdata(i2c, es7243);
// es7243->regmap = devm_regmap_init_i2c(i2c, &es7243_regmap);
// if (IS_ERR(es7243->regmap)) {
// ret = PTR_ERR(es7243->regmap);
// dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
// ret);
// return ret;
// }
printk("%s, drivedata:%d\n", __func__, i2c_id->driver_data);
if (i2c_id->driver_data < (ES7243_CHANNELS_MAX) / 2) {
i2c_clt[i2c_id->driver_data] = i2c;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_es7243,
es7243_dai[i2c_id->driver_data], 1);
if (ret < 0) {
kfree(es7243);
return ret;
}
printk("begin to registe codec:%s, ret:%d\n",
es7243_dai[i2c_id->driver_data]->name, ret);
}
ret = sysfs_create_group(&i2c->dev.kobj, &es7243_debug_attr_group);
if (ret) {
pr_err("failed to create attr group\n");
}
return ret;
}
static int __exit es7243_i2c_remove(struct i2c_client *i2c) {
snd_soc_unregister_codec(&i2c->dev);
kfree(i2c_get_clientdata(i2c));
return 0;
}
static int es7243_i2c_detect(struct i2c_client *client,
struct i2c_board_info *info) {
struct i2c_adapter *adapter = client->adapter;
if (adapter->nr == ES7243_I2C_BUS_NUM) {
if (client->addr == 0x10) {
strlcpy(info->type, "MicArray_3", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x11) {
strlcpy(info->type, "MicArray_2", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x12) {
strlcpy(info->type, "MicArray_1", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x13) {
strlcpy(info->type, "MicArray_0", I2C_NAME_SIZE);
return 0;
}
}
return -ENODEV;
}
static const unsigned short es7243_i2c_addr[] = {
#if ES7243_CHANNELS_MAX > 0
0x13,
#endif
#if ES7243_CHANNELS_MAX > 2
0x11,
#endif
#if ES7243_CHANNELS_MAX > 4
0x12,
#endif
#if ES7243_CHANNELS_MAX > 6
0x10,
#endif
I2C_CLIENT_END,
};
/*
* device tree source or i2c_board_info both use to transfer hardware
* information to linux kernel, use one of them wil be OK
*/
static struct i2c_board_info es7243_i2c_board_info[] = {
#if ES7243_CHANNELS_MAX > 0
{
I2C_BOARD_INFO("MicArray_0", 0x13),
}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{
I2C_BOARD_INFO("MicArray_1", 0x11),
}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{
I2C_BOARD_INFO("MicArray_2", 0x12),
}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{
I2C_BOARD_INFO("MicArray_3", 0x10),
}, // es7243_3
#endif
};
static const struct i2c_device_id es7243_i2c_id[] = {
#if ES7243_CHANNELS_MAX > 0
{"MicArray_0", 0}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{"MicArray_1", 1}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{"MicArray_2", 2}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{"MicArray_3", 3}, // es7243_3
#endif
{}};
MODULE_DEVICE_TABLE(i2c, es7243_i2c_id);
static const struct of_device_id es7243_dt_ids[] = {
#if ES7243_CHANNELS_MAX > 0
{
.compatible = "MicArray_0",
}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{
.compatible = "MicArray_1",
}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{
.compatible = "MicArray_2",
}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{
.compatible = "MicArray_3",
}, // es7243_3
#endif
};
MODULE_DEVICE_TABLE(of, es7243_dt_ids);
static struct i2c_driver es7243_i2c_driver = {
.driver =
{
.name = "es7243",
.owner = THIS_MODULE,
#if ES7243_MATCH_DTS_EN
.of_match_table = es7243_dt_ids,
#endif
},
.probe = es7243_i2c_probe,
.remove = __exit_p(es7243_i2c_remove),
.class = I2C_CLASS_HWMON,
.id_table = es7243_i2c_id,
#if !ES7243_MATCH_DTS_EN
.address_list = es7243_i2c_addr,
.detect = es7243_i2c_detect,
#endif
};
static int __init es7243_modinit(void) {
int ret, i;
struct i2c_adapter *adapter;
struct i2c_client *client;
printk("%s enter es7243\n", __func__);
// i2c_new_device(adapter, &tlv320_i2c_board_info[i]);
adapter = i2c_get_adapter(ES7243_I2C_BUS_NUM);
if (!adapter) {
printk("i2c_get_adapter() fail!\n");
return -ENODEV;
}
printk("%s() begin0000", __func__);
for (i = 0; i < ES7243_CHANNELS_MAX / 2; i++) {
client = i2c_new_device(adapter, &es7243_i2c_board_info[i]);
printk("%s() i2c_new_device, type:0x%x, addr:0x%x\n", __func__,
es7243_i2c_board_info[i].type, es7243_i2c_board_info[i].addr);
if (!client)
return -ENODEV;
}
i2c_put_adapter(adapter);
ret = i2c_add_driver(&es7243_i2c_driver);
if (ret != 0)
pr_err("Failed to register es7243 i2c driver : %d \n", ret);
return ret;
}
module_init(es7243_modinit);
static void __exit es7243_exit(void) {
//#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&es7243_i2c_driver);
//#endif
}
module_exit(es7243_exit);
MODULE_DESCRIPTION("ASoC ES7243 audio adc driver");
MODULE_AUTHOR(
"David Yang <yangxiaohua@everest-semi.com> / info@everest-semi.com");
MODULE_LICENSE("GPL v2");