ASoC: aw882xx driver update

This is Awinic official release, the key change is i2c_read function,
use i2c_transfer to replace the old one, add thread_lock to protect
i2c operation safety, in order to resolve a potential no sound risk
after supporting different audio scenarios feature.

NO_PROP_NEEDED: aw882xx doesn't use in bq-shm2018 products.

Change-Id: I3daeb35c6a349c65bdb723d7f12430634abbf8f2
Signed-off-by: zhouwl <zhouwl@lenovo.com>
Reviewed-on: https://gerrit.mot.com/1537490
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Hujun Liao <liaohj@motorola.com>
Reviewed-by: Wen Xie <xiewen3@motorola.com>
Submit-Approved: Jira Key
Reviewed-by: Yunfei Guo <guoyf2@motorola.com>
This commit is contained in:
zhouwl 2020-04-20 13:00:46 +08:00 • committed by Wanlong Zhou
commit 6204f33cd5
3 changed files with 56 additions and 18 deletions

View file

@ -173,25 +173,36 @@ static int aw882xx_i2c_writes(struct aw882xx *aw882xx,
}
static int aw882xx_i2c_reads(struct aw882xx *aw882xx,
unsigned char reg_addr, unsigned char *buf, unsigned int len)
unsigned char reg_addr, unsigned char *data_buf, unsigned int data_len)
{
int ret = -1;
int ret;
struct i2c_msg msg[] = {
[0] = {
.addr = aw882xx->i2c->addr,
.flags = 0,
.len = sizeof(uint8_t),
.buf = &reg_addr,
},
[1] = {
.addr = aw882xx->i2c->addr,
.flags = I2C_M_RD,
.len = data_len,
.buf = data_buf,
},
};
ret = i2c_smbus_write_byte(aw882xx->i2c, reg_addr);
ret = i2c_transfer(aw882xx->i2c->adapter, msg, ARRAY_SIZE(msg));
if (ret < 0) {
pr_err("%s: i2c master send error, ret=%d\n",
__func__, ret);
return ret;
}
ret = i2c_master_recv(aw882xx->i2c, buf, len);
if (ret != len) {
} else if (ret != AW882XX_I2C_READ_MSG_NUM) {
pr_err("%s: couldn't read registers, return %d bytes\n",
__func__, ret);
return ret;
return -ENXIO;
}
return ret;
return 0;
}
static int aw882xx_i2c_write(struct aw882xx *aw882xx,
@ -343,7 +354,7 @@ static int aw882xx_sysst_check(struct aw882xx *aw882xx)
for (i = 0; i < AW882XX_SYSST_CHECK_MAX; i++) {
aw882xx_i2c_read(aw882xx, AW882XX_SYSST_REG, &reg_val);
if ((reg_val & (~AW882XX_SYSST_CHECK_MASK)) ==
if (((reg_val & (~AW882XX_SYSST_CHECK_MASK)) & AW882XX_SYSST_CHECK) ==
AW882XX_SYSST_CHECK) {
ret = 0;
break;
@ -453,9 +464,11 @@ static int aw882xx_set_vcalb(struct aw882xx *aw882xx)
static void aw882xx_send_cali_re_to_dsp(struct aw882xx *aw882xx)
{
int ret;
ret = aw_send_afe_cal_apr(AFE_PARAM_ID_AWDSP_RX_RE_L,
&aw882xx->cali_re, sizeof(int32_t), true);
int ret = 0;
if ((aw882xx != NULL) && (aw882xx->cali_re != ERRO_CALI_VALUE)) {
ret = aw_send_afe_cal_apr(AFE_PARAM_ID_AWDSP_RX_RE_L,
&aw882xx->cali_re, sizeof(int32_t), true);
}
if (ret)
pr_err("%s : set cali re to dsp failed 0x%x\n",
__func__ , AFE_PARAM_ID_AWDSP_RX_RE_L);
@ -469,9 +482,9 @@ static void aw882xx_start(struct aw882xx *aw882xx)
ret = aw882xx_get_cali_re_form_nv(&cali_re);
if (ret < 0) {
cali_re = (DEFAULT_CALI_VALUE << 12);
cali_re = ERRO_CALI_VALUE;
pr_err("%s: use default vaule %d",
__func__ , DEFAULT_CALI_VALUE);
__func__ , ERRO_CALI_VALUE);
}
ret = aw882xx_set_cali_re(aw882xx, cali_re);
if (ret < 0)
@ -1223,6 +1236,7 @@ static int aw882xx_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct aw882xx *aw882xx = snd_soc_codec_get_drvdata(codec);
unsigned int rate = 0;
uint32_t cco_mux_value;
int reg_value = 0;
int width = 0;
@ -1240,30 +1254,40 @@ static int aw882xx_hw_params(struct snd_pcm_substream *substream,
switch (rate) {
case 8000:
reg_value = AW882XX_I2SSR_8KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_8_16_32KHZ_VALUE;
break;
case 16000:
reg_value = AW882XX_I2SSR_16KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_8_16_32KHZ_VALUE;
break;
case 32000:
reg_value = AW882XX_I2SSR_32KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_8_16_32KHZ_VALUE;
break;
case 44100:
reg_value = AW882XX_I2SSR_44P1KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE;
break;
case 48000:
reg_value = AW882XX_I2SSR_48KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE;
break;
case 96000:
reg_value = AW882XX_I2SSR_96KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE;
break;
case 192000:
reg_value = AW882XX_I2SSR_192KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE;
break;
default:
reg_value = AW882XX_I2SSR_48KHZ_VALUE;
cco_mux_value = AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE;
pr_err("%s: rate can not support\n", __func__);
break;
}
aw882xx_i2c_write_bits(aw882xx, AW882XX_PLLCTRL1_REG,
AW882XX_I2S_CCO_MUX_MASK, cco_mux_value);
/* set chip rate */
if (-1 != reg_value) {

View file

@ -7,6 +7,7 @@
* (See Linux kernel documentation: Documentation/i2c/writing-clients)
*/
#define MAX_I2C_BUFFER_SIZE 65536
#define AW882XX_I2C_READ_MSG_NUM 2
#define AW882XX_FLAG_START_ON_MUTE (1 << 0)
#define AW882XX_FLAG_SKIP_INTERRUPTS (1 << 1)
@ -25,6 +26,7 @@
#define DEFAULT_CALI_VALUE (7)
#define ERRO_CALI_VALUE (0)
#define AFE_PARAM_ID_AWDSP_RX_SET_ENABLE (0x10013D11)
#define AFE_PARAM_ID_AWDSP_RX_PARAMS (0x10013D12)
#define AFE_PARAM_ID_AWDSP_TX_SET_ENABLE (0x10013D13)

View file

@ -407,9 +407,7 @@ const unsigned char aw882xx_reg_access[AW882XX_REG_MAX] = {
AW882XX_PLLS_LOCKED_VALUE))
#define AW882XX_SYSST_CHECK \
(AW882XX_BSTS_FINISHED_VALUE | \
AW882XX_SWS_SWITCHING_VALUE | \
AW882XX_CLKS_TRIG_VALUE | \
(AW882XX_CLKS_TRIG_VALUE | \
AW882XX_PLLS_LOCKED_VALUE)
#define AW882XX_IIS_CHECK_MASK \
@ -1176,6 +1174,20 @@ const unsigned char aw882xx_reg_access[AW882XX_REG_MAX] = {
#define AW882XX_I2SSR_MASK \
(~(((1<<AW882XX_I2SSR_BITS_LEN)-1)<<AW882XX_I2SSR_START_BIT))
/* I2S CCO_UMX */
#define AW882XX_I2S_CCO_MUX_START_BIT (14)
#define AW882XX_I2S_CCO_MUX_BITS_LEN (1)
#define AW882XX_I2S_CCO_MUX_MASK \
(~(((1<<AW882XX_I2S_CCO_MUX_BITS_LEN)-1)<<AW882XX_I2S_CCO_MUX_START_BIT))
#define AW882XX_I2S_CCO_MUX_8_16_32KHZ_BIT_VALUE (0)
#define AW882XX_I2S_CCO_MUX_8_16_32KHZ_VALUE \
(AW882XX_I2S_CCO_MUX_8_16_32KHZ_BIT_VALUE<<AW882XX_I2S_CCO_MUX_START_BIT)
#define AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_BIT_VALUE (1)
#define AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_VALUE \
(AW882XX_I2S_CCO_MUX_EXC_8_16_32KHZ_BIT_VALUE<<AW882XX_I2S_CCO_MUX_START_BIT)
#define AW882XX_I2SSR_8KHZ (0)
#define AW882XX_I2SSR_8KHZ_VALUE \
(AW882XX_I2SSR_8KHZ << AW882XX_I2SSR_START_BIT)