audio: auge: optimize fifo depth according to chipset [1/1]

PD#SWPL-19687

Problem:
VAD cannot wake up the system, cause of ddr does not run.
each toddr fifo depth is different, but constant value for all.

Solution:
Modify the fifo depth according to chipset.

Verify:
ab301

Change-Id: Ia543ef84ba46086ac310e95764b1db82a548229e
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
Signed-off-by: chunlong.cao <chunlong.cao@amlogic.com>
This commit is contained in:
Xing Wang
2020-03-06 15:39:37 +08:00
committed by Chris
parent 13ce610152
commit f4300f8ef4
9 changed files with 213 additions and 66 deletions

View File

@@ -375,21 +375,34 @@ void aml_toddr_select_src(struct toddr *to, enum toddr_src src)
}
}
void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh)
void aml_toddr_set_fifos(struct toddr *to, unsigned int threshold)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg, mask, val;
if (threshold < FIFO_BURST) {
pr_warn("%s, please check threshold:%d less than burst\n",
__func__, threshold);
threshold = FIFO_BURST;
}
to->threshold = threshold;
/*
* the threshold in bytes, register value is:
* val = (threshold / burst) - 1
*/
threshold /= FIFO_BURST;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
if (to->chipinfo
&& to->chipinfo->src_sel_ctrl) {
mask = 0xfff << 12 | 0xf << 8;
val = (thresh-2) << 12 | 2 << 8;
val = (threshold - 1) << 12 | 2 << 8;
} else {
mask = 0xff << 16 | 0xf << 8;
val = (thresh-2) << 16 | 2 << 8;
val = (threshold - 1) << 16 | 2 << 8;
}
aml_audiobus_update_bits(actrl, reg, mask, val);
@@ -400,24 +413,6 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh)
}
}
void aml_toddr_update_fifos_rd_th(struct toddr *to, int th)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg, mask, val;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
if (to->chipinfo
&& to->chipinfo->src_sel_ctrl) {
mask = 0xfff << 12;
val = (th - 1) << 12;
} else {
mask = 0xff << 16;
val = (th - 1) << 16;
}
aml_audiobus_update_bits(actrl, reg, mask, val);
}
void aml_toddr_force_finish(struct toddr *to)
{
struct aml_audio_controller *actrl = to->actrl;
@@ -1297,16 +1292,30 @@ void aml_frddr_select_dst_ss(struct frddr *fr,
}
void aml_frddr_set_fifos(struct frddr *fr,
unsigned int depth, unsigned int thresh)
unsigned int depth, unsigned int threshold)
{
struct aml_audio_controller *actrl = fr->actrl;
unsigned int reg_base = fr->reg_base;
unsigned int reg;
if (depth < FIFO_BURST) {
pr_warn("%s, please check depth:%d less than burst\n",
__func__, depth);
depth = FIFO_BURST;
}
if (threshold < FIFO_BURST) {
pr_warn("%s, please check threshold:%d less than burst\n",
__func__, threshold);
threshold = FIFO_BURST;
}
depth /= FIFO_BURST;
threshold /= FIFO_BURST;
reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL1, reg_base);
aml_audiobus_update_bits(actrl, reg,
0xffff<<16 | 0xf<<8,
(depth - 1)<<24 | (thresh - 1)<<16 | 2<<8);
0xffff << 16 | 0xf << 8,
(depth - 1) << 24 | (threshold - 1) << 16 | 2 << 8);
if (fr->chipinfo && fr->chipinfo->ugt) {
reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base);
@@ -1634,16 +1643,42 @@ int card_add_ddr_kcontrols(struct snd_soc_card *card)
return 0;
}
static const struct fifo_info ddr_2k_and_1k[] = {
{DDR_A, FIFO_DEPTH_2K},
{DDR_B, FIFO_DEPTH_1K},
{DDR_C, FIFO_DEPTH_1K},
{DDR_D, FIFO_DEPTH_1K},
};
static const struct fifo_info ddr_32k_and_1k[] = {
{DDR_A, FIFO_DEPTH_32K},
{DDR_B, FIFO_DEPTH_1K},
{DDR_C, FIFO_DEPTH_1K},
{DDR_D, FIFO_DEPTH_1K},
{DDR_E, FIFO_DEPTH_1K},
};
static const struct fifo_info ddr_512[] = {
{DDR_A, FIFO_DEPTH_512},
{DDR_B, FIFO_DEPTH_512},
};
static struct ddr_chipinfo axg_ddr_chipinfo = {
.int_start_same_addr = true,
.asrc_only_left_j = true,
.wakeup = 1,
.fifo_num = 3,
.toddr_info = ddr_2k_and_1k,
.frddr_info = ddr_2k_and_1k,
};
static struct ddr_chipinfo g12a_ddr_chipinfo = {
.same_src_fn = true,
.asrc_only_left_j = true,
.wakeup = 1,
.fifo_num = 3,
.toddr_info = ddr_2k_and_1k,
.frddr_info = ddr_2k_and_1k,
};
static struct ddr_chipinfo tl1_ddr_chipinfo = {
@@ -1651,8 +1686,10 @@ static struct ddr_chipinfo tl1_ddr_chipinfo = {
.ugt = true,
.src_sel_ctrl = true,
.asrc_src_sel_ctrl = true,
.fifo_num = 4,
.wakeup = 2,
.fifo_num = 4,
.toddr_info = ddr_32k_and_1k,
.frddr_info = ddr_2k_and_1k,
};
static struct ddr_chipinfo sm1_ddr_chipinfo = {
@@ -1660,8 +1697,10 @@ static struct ddr_chipinfo sm1_ddr_chipinfo = {
.ugt = true,
.src_sel_ctrl = true,
.asrc_src_sel_ctrl = true,
.fifo_num = 4,
.wakeup = 2,
.fifo_num = 4,
.toddr_info = ddr_32k_and_1k,
.frddr_info = ddr_2k_and_1k,
};
static const struct of_device_id aml_ddr_mngr_device_id[] = {
@@ -1784,18 +1823,20 @@ static int aml_ddr_mngr_platform_probe(struct platform_device *pdev)
toddrs[i].irq =
platform_get_irq_byname(pdev,
ddr_get_toddr_name_by_idx(i));
toddrs[i].reg_base = ddr_get_toddr_base_addr_by_idx(i);
toddrs[i].fifo_id = i;
toddrs[i].chipinfo = p_ddr_chipinfo;
toddrs[i].actrl = actrl;
toddrs[i].reg_base = ddr_get_toddr_base_addr_by_idx(i);
toddrs[i].fifo_id = i;
toddrs[i].fifo_depth = p_ddr_chipinfo->toddr_info[i].depth;
toddrs[i].chipinfo = p_ddr_chipinfo;
toddrs[i].actrl = actrl;
frddrs[i].irq =
frddrs[i].irq =
platform_get_irq_byname(pdev,
ddr_get_frddr_name_by_idx(i));
frddrs[i].reg_base = ddr_get_frddr_base_addr_by_idx(i);
frddrs[i].fifo_id = i;
frddrs[i].chipinfo = p_ddr_chipinfo;
frddrs[i].actrl = actrl;
frddrs[i].reg_base = ddr_get_frddr_base_addr_by_idx(i);
frddrs[i].fifo_id = i;
frddrs[i].fifo_depth = p_ddr_chipinfo->frddr_info[i].depth;
frddrs[i].chipinfo = p_ddr_chipinfo;
frddrs[i].actrl = actrl;
dev_info(&pdev->dev, "%d, irqs toddr %d, frddr %d\n",
i, toddrs[i].irq, frddrs[i].irq);

View File

@@ -31,14 +31,22 @@
#define MEMIF_INT_FIFO_DEPTH BIT(5)
#define MEMIF_INT_MASK GENMASK(7, 0)
#define TODDR_FIFO_CNT GENMASK(19, 8)
#define FRDDR_FIFO_CNT GENMASK(17, 8)
#define TODDR_FIFO_CNT GENMASK(19, 8)
#define FRDDR_FIFO_CNT GENMASK(17, 8)
#define FIFO_BURST 8
#define FIFO_DEPTH_32K 0x8000
#define FIFO_DEPTH_2K 0x800
#define FIFO_DEPTH_1K 0x400
#define FIFO_DEPTH_512 0x200
enum ddr_num {
DDR_A,
DDR_B,
DDR_C,
DDR_D,
DDR_E,
DDR_MAX,
};
enum ddr_types {
@@ -117,6 +125,12 @@ struct toddr_fmt {
unsigned int rate;
};
struct fifo_info {
unsigned int idx;
/* bytes */
unsigned int depth;
};
struct ddr_chipinfo {
/* INT and Start address is same or separated */
bool int_start_same_addr;
@@ -152,6 +166,8 @@ struct ddr_chipinfo {
* 4: 4 toddr, tl1
*/
int fifo_num;
const struct fifo_info *toddr_info;
const struct fifo_info *frddr_info;
/* power detect or VAD
* 0: disabled
@@ -174,9 +190,11 @@ struct toddr {
unsigned int start_addr;
unsigned int end_addr;
unsigned int threshold;
enum toddr_src src;
unsigned int fifo_id;
unsigned int fifo_depth;
int is_lb; /* check whether for loopback */
int irq;
@@ -222,6 +240,7 @@ struct frddr {
struct aml_audio_controller *actrl;
unsigned int reg_base;
enum ddr_num fifo_id;
unsigned int fifo_depth;
unsigned int channels;
unsigned int msb;
@@ -258,8 +277,7 @@ unsigned int aml_toddr_get_position(struct toddr *to);
unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel);
void aml_toddr_select_src(struct toddr *to, enum toddr_src);
void aml_toddr_enable(struct toddr *to, bool enable);
void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh);
void aml_toddr_update_fifos_rd_th(struct toddr *to, int th);
void aml_toddr_set_fifos(struct toddr *to, unsigned int threshold);
void aml_toddr_force_finish(struct toddr *to);
void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt);
@@ -302,7 +320,7 @@ extern void aml_frddr_select_dst_ss(struct frddr *fr,
int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel);
void aml_frddr_set_fifos(struct frddr *fr,
unsigned int depth, unsigned int thresh);
unsigned int depth, unsigned int threshold);
unsigned int aml_frddr_get_fifo_id(struct frddr *fr);
void aml_frddr_set_format(struct frddr *fr,
unsigned int chnum,

View File

@@ -393,19 +393,38 @@ static int earc_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct earc *p_earc = runtime->private_data;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
struct frddr *fr = p_earc->fddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, fr->fifo_depth);
threshold /= 2;
/* Use all the fifo */
aml_frddr_set_fifos(fr, fr->fifo_depth, threshold);
aml_frddr_set_buf(fr, start_addr, end_addr);
aml_frddr_set_intrpt(fr, int_addr);
} else {
struct toddr *to = p_earc->tddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, to->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
}
@@ -539,7 +558,6 @@ static int earc_dai_prepare(
bit_depth - 1,
frddr_type);
aml_frddr_select_dst(fr, dst);
aml_frddr_set_fifos(fr, 0x40, 0x20);
earctx_dmac_init(p_earc->tx_top_map, p_earc->tx_dmac_map);
earctx_dmac_set_format(p_earc->tx_dmac_map,
@@ -590,7 +608,6 @@ static int earc_dai_prepare(
aml_toddr_select_src(to, src);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
earcrx_dmac_init(p_earc->rx_top_map, p_earc->rx_dmac_map);
earcrx_arc_init(p_earc->rx_dmac_map);

View File

@@ -297,19 +297,38 @@ static int extn_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct extn *p_extn = runtime->private_data;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
struct frddr *fr = p_extn->fddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, fr->fifo_depth);
threshold /= 2;
/* Use all the fifo */
aml_frddr_set_fifos(fr, fr->fifo_depth, threshold);
aml_frddr_set_buf(fr, start_addr, end_addr);
aml_frddr_set_intrpt(fr, int_addr);
} else {
struct toddr *to = p_extn->tddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, to->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
}
@@ -470,7 +489,6 @@ static int extn_dai_prepare(
frddr_src_get_str(dst));
aml_frddr_select_dst(fr, dst);
aml_frddr_set_fifos(fr, 0x40, 0x20);
} else {
struct toddr *to = p_extn->tddr;
unsigned int msb = 0, lsb = 0, toddr_type = 0;
@@ -542,7 +560,6 @@ static int extn_dai_prepare(
aml_toddr_select_src(to, src);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
}
return 0;

View File

@@ -202,14 +202,24 @@ static int loopback_prepare(struct snd_pcm_substream *ss)
struct snd_pcm_runtime *runtime = ss->runtime;
struct loopback *p_loopback = runtime->private_data;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
if (ss->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct toddr *to = p_loopback->tddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, to->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
}
@@ -693,7 +703,6 @@ static int loopback_dai_prepare(
aml_toddr_select_src(to, src);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
switch (p_loopback->datain_src) {
case DATAIN_TDMA:

View File

@@ -648,7 +648,6 @@ static int aml_pdm_close(struct snd_pcm_substream *substream)
return 0;
}
static int aml_pdm_hw_params(
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -682,10 +681,20 @@ static int aml_pdm_prepare(
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct toddr *to = p_pdm->tddr;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, p_pdm->tddr->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
@@ -880,7 +889,6 @@ static int aml_pdm_dai_prepare(
fmt.rate = runtime->rate;
aml_toddr_select_src(to, PDMIN);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
/* force pdm sysclk to 24m */
if (p_pdm->isLowPower) {

View File

@@ -958,19 +958,38 @@ static int aml_spdif_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct aml_spdif *p_spdif = runtime->private_data;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
struct frddr *fr = p_spdif->fddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, fr->fifo_depth);
threshold /= 2;
/* Use all the fifo */
aml_frddr_set_fifos(fr, fr->fifo_depth, threshold);
aml_frddr_set_buf(fr, start_addr, end_addr);
aml_frddr_set_intrpt(fr, int_addr);
} else {
struct toddr *to = p_spdif->tddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, to->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
}
@@ -1238,7 +1257,6 @@ static int aml_dai_spdif_prepare(
bit_depth - 1,
spdifout_get_frddr_type(bit_depth));
aml_frddr_select_dst(fr, dst);
aml_frddr_set_fifos(fr, 0x40, 0x20);
/* check channel status info, and set them */
spdif_get_channel_status_info(&chsts, runtime->rate);
@@ -1296,7 +1314,6 @@ static int aml_dai_spdif_prepare(
fmt.rate = runtime->rate;
aml_toddr_select_src(to, SPDIFIN);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
#ifdef __SPDIFIN_INSERT_CHNUM__
aml_toddr_insert_chanum(to);
#endif

View File

@@ -386,10 +386,12 @@ static int aml_tdm_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct aml_tdm *p_tdm = runtime->private_data;
unsigned int start_addr, end_addr, int_addr;
unsigned int period, threshold;
start_addr = runtime->dma_addr;
end_addr = start_addr + runtime->dma_bytes - 8;
int_addr = frames_to_bytes(runtime, runtime->period_size)/8;
end_addr = start_addr + runtime->dma_bytes - FIFO_BURST;
period = frames_to_bytes(runtime, runtime->period_size);
int_addr = period / FIFO_BURST;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
struct frddr *fr = p_tdm->fddr;
@@ -410,11 +412,29 @@ static int aml_tdm_prepare(struct snd_pcm_substream *substream)
aml_spdif_out_reset(p_tdm->samesource_sel - 3,
offset);
}
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, fr->fifo_depth);
threshold /= 2;
/* Use all the fifo */
aml_frddr_set_fifos(fr, fr->fifo_depth, threshold);
aml_frddr_set_buf(fr, start_addr, end_addr);
aml_frddr_set_intrpt(fr, int_addr);
} else {
struct toddr *to = p_tdm->tddr;
/*
* Contrast minimum of period and fifo depth,
* and set the value as half.
*/
threshold = min(period, to->fifo_depth);
threshold /= 2;
aml_toddr_set_fifos(to, threshold);
aml_toddr_set_buf(to, start_addr, end_addr);
aml_toddr_set_intrpt(to, int_addr);
}
@@ -538,7 +558,6 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
bit_depth - 1,
tdmout_get_frddr_type(bit_depth));
aml_frddr_select_dst(fr, dst);
aml_frddr_set_fifos(fr, 0x40, 0x20);
} else {
struct toddr *to = p_tdm->tddr;
enum toddr_src src;
@@ -611,7 +630,6 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
fmt.rate = runtime->rate;
aml_toddr_select_src(to, src);
aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
}
return 0;

View File

@@ -80,6 +80,7 @@ struct vad {
unsigned int start_last;
unsigned int end_last;
unsigned int addr;
unsigned int threshold;
int switch_buffer;
/* vad flag interrupt */
@@ -581,8 +582,9 @@ void vad_update_buffer(int isvad)
p_vad->start_last = tddr->start_addr;
p_vad->end_last = tddr->end_addr;
p_vad->threshold = tddr->threshold;
rd_th = 0x800;
rd_th = tddr->fifo_depth * 3 / 4;
pr_debug("Switch to VAD buffer\n");
pr_debug("\t ASAL start:%x, end:%x, bytes:%d\n",
@@ -599,12 +601,12 @@ void vad_update_buffer(int isvad)
pr_debug("Switch to ALSA buffer\n");
start = p_vad->start_last;
end = p_vad->end_last;
rd_th = 0x40;
rd_th = p_vad->threshold;
vad_set_trunk_data_readable(true);
}
aml_toddr_set_buf(p_vad->tddr, start, end);
aml_toddr_force_finish(p_vad->tddr);
aml_toddr_update_fifos_rd_th(p_vad->tddr, rd_th);
aml_toddr_set_fifos(p_vad->tddr, rd_th);
p_vad->addr = 0;
}