Skip to content

Commit 860d38f

Browse files
committed
Fix: i2c access fail when AC108 as master, support make DEBUG=1
1 parent 1901914 commit 860d38f

File tree

4 files changed

+70
-42
lines changed

4 files changed

+70
-42
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ obj-m += snd-soc-wm8960.o
77
obj-m += snd-soc-ac108.o
88
obj-m += snd-soc-simple-card.o
99

10+
ifdef DEBUG
11+
ifneq ($(DEBUG),0)
12+
ccflags-y += -DDEBUG -DAC101_DEBG
13+
endif
14+
endif
15+
1016

1117
all:
1218
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

ac101.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
* the License, or (at your option) any later version.
2121
*
2222
*/
23-
#undef AC101_DEBG
23+
24+
/* #undef AC101_DEBG
25+
* use 'make DEBUG=1' to enable debugging
26+
*/
2427
#include <linux/module.h>
2528
#include <sound/pcm.h>
2629
#include <sound/pcm_params.h>
@@ -292,22 +295,17 @@ static int ac101_aif1clk(struct snd_soc_codec* codec, int event) {
292295
unsigned long flags;
293296
int ret;
294297

295-
AC101_DBG("%s() L%d event=%d pre_up/%d post_down/%d\n", __func__, __LINE__,
296-
event, SND_SOC_DAPM_PRE_PMU, SND_SOC_DAPM_POST_PMD);
297-
298-
298+
/* I know it will degrades performance, but I have no choice */
299+
spin_lock_irqsave(&ac10x->lock, flags);
299300
switch (event) {
300301
case SND_SOC_DAPM_PRE_PMU:
301302
if (ac10x->aif1_clken == 0){
302-
/* I know it will degrades performance, but I have no choice */
303-
spin_lock_irqsave(&ac10x->lock, flags);
304303

305304
/* enable aif1clk & sysclk */
306305
ret = ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<AIF1CLK_ENA), (0x1<<AIF1CLK_ENA));
307306
ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1));
308307
ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1));
309308
ret = ret || ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<SYSCLK_ENA), (0x1<<SYSCLK_ENA));
310-
spin_unlock_irqrestore(&ac10x->lock, flags);
311309

312310
if (ret) {
313311
AC101_DBG("%s() L%d start sysclk failed\n", __func__, __LINE__);
@@ -319,15 +317,11 @@ static int ac101_aif1clk(struct snd_soc_codec* codec, int event) {
319317
break;
320318
case SND_SOC_DAPM_POST_PMD:
321319
if (ac10x->aif1_clken != 0) {
322-
/* I know it will degrades performance, but I have no choice */
323-
spin_lock_irqsave(&ac10x->lock, flags);
324-
325320
/* disable aif1clk & sysclk */
326321
ret = ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<AIF1CLK_ENA),(0x0<<AIF1CLK_ENA));
327322
ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x0<<MOD_CLK_AIF1));
328323
ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x0<<MOD_RESET_AIF1));
329324
ret = ret || ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<SYSCLK_ENA), (0x0<<SYSCLK_ENA));
330-
spin_unlock_irqrestore(&ac10x->lock, flags);
331325

332326
if (ret) {
333327
AC101_DBG("%s() L%d stop sysclk failed\n", __func__, __LINE__);
@@ -338,6 +332,10 @@ static int ac101_aif1clk(struct snd_soc_codec* codec, int event) {
338332
break;
339333
}
340334
}
335+
spin_unlock_irqrestore(&ac10x->lock, flags);
336+
337+
AC101_DBG("%s() L%d event=%d pre_up/%d post_down/%d\n", __func__, __LINE__,
338+
event, SND_SOC_DAPM_PRE_PMU, SND_SOC_DAPM_POST_PMD);
341339

342340
return 0;
343341
}
@@ -478,8 +476,8 @@ static const struct pll_div codec_pll_div[] = {
478476
{5644800, _FREQ_22_579K, 1, 12, 0}, /* accurate, 22050 * 256 */
479477
{6000000, _FREQ_22_579K, 38, 429, 0}, /*((429+0*0.2)*6000000)/(38*(2*1+1))*/
480478
{11289600, _FREQ_22_579K, 1, 6, 0}, /* accurate, 44100 * 256 */
481-
{13000000, _FREQ_22_579K, 19, 99, 0},
482-
{19200000, _FREQ_22_579K, 25, 88, 1},
479+
{13000000, _FREQ_22_579K, 19, 99, 0},
480+
{19200000, _FREQ_22_579K, 25, 88, 1},
483481
{24000000, _FREQ_22_579K, 63, 177, 4}, /* 22577778 Hz */
484482

485483
{128000, _FREQ_24_576K, 1, 576, 0},
@@ -1178,6 +1176,12 @@ int ac101_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
11781176
return ret;
11791177
}
11801178

1179+
/* Chip reset */
1180+
/*
1181+
ret = regmap_write(ac10x->regmap101, CHIP_AUDIO_RST, 0);
1182+
msleep(50);
1183+
*/
1184+
11811185
ret = regmap_read(ac10x->regmap101, CHIP_AUDIO_RST, &v);
11821186
if (ret < 0) {
11831187
dev_err(&i2c->dev, "failed to read vendor ID: %d\n", ret);

ac108.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
* it under the terms of the GNU General Public License version 2 as
99
* published by the Free Software Foundation.
1010
*/
11-
#undef DEBUG
11+
12+
/* #undef DEBUG
13+
* use 'make DEBUG=1' to enable debugging
14+
*/
1215
#include <linux/module.h>
1316
#include <linux/moduleparam.h>
1417
#include <linux/init.h>
@@ -547,10 +550,6 @@ static int ac108_config_pll(struct ac10x_priv *ac10x, unsigned rate, unsigned lr
547550
/*0x18: PLL clk lock enable*/
548551
ac108_multi_update_bits(PLL_LOCK_CTRL, 0x1 << PLL_LOCK_EN, 0x1 << PLL_LOCK_EN, ac10x);
549552

550-
/*0x10: PLL Common voltage Enable, PLL Enable,PLL loop divider factor detection enable*/
551-
ac108_multi_update_bits(PLL_CTRL1, 0x01 << PLL_EN | 0x01 << PLL_COM_EN | 0x01 << PLL_NDET,
552-
0x01 << PLL_EN | 0x01 << PLL_COM_EN | 0x01 << PLL_NDET, ac10x);
553-
554553
/**
555554
* 0x20: enable pll, pll source from mclk/bclk, sysclk source from pll, enable sysclk
556555
*/
@@ -670,8 +669,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
670669

671670
/* Master mode, to clear cpu_dai fifos, output bclk without lrck */
672671
ac10x_read(I2S_CTRL, &v, ac10x->i2cmap[_MASTER_INDEX]);
673-
if (v & (0x02 << LRCK_IOEN)) {
674-
ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN, 0x02 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
672+
if (v & (0x01 << BCLK_IOEN)) {
673+
ac10x_update_bits(I2S_CTRL, 0x1 << LRCK_IOEN, 0x0 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
675674
}
676675

677676
switch (params_format(params)) {
@@ -792,6 +791,11 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
792791
*/
793792
ac108_multi_chips_slots(ac10x, channels);
794793

794+
/*0x21: Module clock enable<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
795+
ac108_multi_write(MOD_CLK_EN, 1 << I2S | 1 << ADC_DIGITAL | 1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
796+
/*0x22: Module reset de-asserted<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
797+
ac108_multi_write(MOD_RST_CTRL, 1 << I2S | 1 << ADC_DIGITAL | 1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
798+
795799
dev_dbg(dai->dev, "%s() stream=%s ---\n", __func__,
796800
snd_pcm_stream_str(substream));
797801

@@ -851,7 +855,7 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
851855
ac108_multi_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN | 0x03 << SDO1_EN | 0x1 << TXEN | 0x1 << GEN,
852856
0x00 << LRCK_IOEN | 0x03 << SDO1_EN | 0x1 << TXEN | 0x1 << GEN, ac10x);
853857
/* multi_chips: only one chip set as Master, and the others also need to set as Slave */
854-
ac10x_update_bits(I2S_CTRL, 0x3 << LRCK_IOEN, 0x2 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
858+
ac10x_update_bits(I2S_CTRL, 0x3 << LRCK_IOEN, 0x01 << BCLK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
855859
break;
856860
} else {
857861
/* TODO: Both cpu_dai and codec_dai(AC108) be set as slave in DTS */
@@ -863,8 +867,8 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
863867
* 0x30:chip is slave mode, BCLK & LRCK input,enable SDO1_EN and
864868
* SDO2_EN, Transmitter Block Enable, Globe Enable
865869
*/
866-
ac108_multi_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN | 0x03 << SDO1_EN | 0x1 << TXEN | 0x1 << GEN,
867-
0x00 << LRCK_IOEN | 0x03 << SDO1_EN | 0x1 << TXEN | 0x1 << GEN, ac10x);
870+
ac108_multi_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN | 0x03 << SDO1_EN | 0x0 << TXEN | 0x0 << GEN,
871+
0x00 << LRCK_IOEN | 0x03 << SDO1_EN | 0x0 << TXEN | 0x0 << GEN, ac10x);
868872
break;
869873
default:
870874
pr_err("AC108 Master/Slave mode config error:%u\n\n", (fmt & SND_SOC_DAIFMT_MASTER_MASK) >> 12);
@@ -930,13 +934,6 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
930934
return -EINVAL;
931935
}
932936

933-
#if 0
934-
/* revert LRCK polarity if it's single chip (master mode) */
935-
if (ac10x->tdm_chips_cnt < 2) {
936-
lrck_polarity = (lrck_polarity == LRCK_LEFT_HIGH_RIGHT_LOW)?
937-
LRCK_LEFT_LOW_RIGHT_HIGH: LRCK_LEFT_HIGH_RIGHT_LOW;
938-
}
939-
#endif
940937
ac108_configure_power(ac10x);
941938

942939
/**
@@ -987,14 +984,16 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
987984
* due to miss channels order in cpu_dai, we meed defer the clock starting.
988985
*/
989986
static int ac108_set_clock(int y_start_n_stop) {
987+
unsigned long flags;
990988
u8 r;
991989

992990
dev_dbg(ac10x->codec->dev, "%s() L%d start:%d\n", __func__, __LINE__, y_start_n_stop);
993991

992+
spin_lock_irqsave(&ac10x->lock, flags);
994993
if (y_start_n_stop) {
995994
/* enable lrck clock */
996995
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
997-
if (r & (0x02 << LRCK_IOEN)) {
996+
if (r & (0x01 << BCLK_IOEN)) {
998997
ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN, 0x03 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
999998
}
1000999

@@ -1005,10 +1004,11 @@ static int ac108_set_clock(int y_start_n_stop) {
10051004
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
10061005
if (r & (0x01 << LRCK_IOEN)) {
10071006
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x1 << TXEN | 0x0 << GEN, ac10x);
1008-
ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN, 0x02 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
1007+
ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN, 0x01 << BCLK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
10091008
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x1 << TXEN | 0x1 << GEN, ac10x);
10101009
}
10111010
}
1011+
spin_unlock_irqrestore(&ac10x->lock, flags);
10121012

10131013
return 0;
10141014
}
@@ -1028,6 +1028,7 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
10281028
{
10291029
struct snd_soc_codec *codec = dai->codec;
10301030
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
1031+
unsigned long flags;
10311032
int ret = 0;
10321033
u8 r;
10331034

@@ -1036,10 +1037,12 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
10361037
snd_pcm_stream_str(substream),
10371038
cmd);
10381039

1040+
spin_lock_irqsave(&ac10x->lock, flags);
1041+
10391042
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
10401043
ac101_trigger(substream, cmd, dai);
10411044
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1042-
return 0;
1045+
goto __ret;
10431046
}
10441047
}
10451048

@@ -1049,27 +1052,39 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
10491052
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
10501053
/* disable global clock if lrck disabled */
10511054
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
1052-
if ((r & (0x02 << LRCK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
1055+
if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
10531056
/* disable global clock */
10541057
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x1 << TXEN | 0x0 << GEN, ac10x);
10551058
}
10561059

1057-
/*0x21: Module clock enable<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
1058-
ac108_multi_write(MOD_CLK_EN, 1 << I2S | 1 << ADC_DIGITAL | 1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
1059-
1060-
/*0x22: Module reset de-asserted<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
1061-
ac108_multi_write(MOD_RST_CTRL, 1 << I2S | 1 << ADC_DIGITAL | 1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
1060+
/*0x10: PLL Common voltage enable, PLL enable */
1061+
ac108_multi_update_bits(PLL_CTRL1, 0x01 << PLL_EN | 0x01 << PLL_COM_EN,
1062+
0x01 << PLL_EN | 0x01 << PLL_COM_EN, ac10x);
10621063

1064+
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
1065+
/* enable global clock */
1066+
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x1 << TXEN | 0x1 << GEN, ac10x);
1067+
}
10631068
/* delayed clock starting, move to simple_card_trigger() */
10641069
break;
10651070
case SNDRV_PCM_TRIGGER_STOP:
10661071
case SNDRV_PCM_TRIGGER_SUSPEND:
10671072
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1073+
/*0x10: PLL Common voltage disable, PLL disable */
1074+
ac108_multi_update_bits(PLL_CTRL1, 0x01 << PLL_EN | 0x01 << PLL_COM_EN,
1075+
0x00 << PLL_EN | 0x00 << PLL_COM_EN, ac10x);
1076+
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
1077+
/* disable global clock */
1078+
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x0 << TXEN | 0x0 << GEN, ac10x);
1079+
}
10681080
break;
10691081
default:
10701082
ret = -EINVAL;
10711083
}
10721084

1085+
__ret:
1086+
spin_unlock_irqrestore(&ac10x->lock, flags);
1087+
10731088
return ret;
10741089
}
10751090

@@ -1378,6 +1393,9 @@ static int ac108_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i
13781393
ac10x->i2c101 = i2c;
13791394
i2c_set_clientdata(i2c, ac10x);
13801395
ret = ac101_probe(i2c, i2c_id);
1396+
if (ret) {
1397+
return ret;
1398+
}
13811399
goto __ret;
13821400
}
13831401

simple-card.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* it under the terms of the GNU General Public License version 2 as
99
* published by the Free Software Foundation.
1010
*/
11-
#undef DEBUG
11+
/* #undef DEBUG */
1212
#include <linux/clk.h>
1313
#include <linux/device.h>
1414
#include <linux/gpio.h>
@@ -240,7 +240,7 @@ static int asoc_simple_card_trigger(struct snd_pcm_substream *substream, int cmd
240240
ret = -EINVAL;
241241
}
242242

243-
return 0;
243+
return ret;
244244
}
245245

246246
static struct snd_soc_ops asoc_simple_card_ops = {

0 commit comments

Comments
 (0)