mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
audio: fix pcm bclk
PD#141217: fix pcm bclk following sample rate, pcm format and slot number Change-Id: I4e1547c6c7c133a46a8c8b9a9d595adb7aa2771c Signed-off-by: Xing Wang <xing.wang@amlogic.com>
This commit is contained in:
@@ -36,7 +36,7 @@ static unsigned int pcmin_buffer_size;
|
||||
static unsigned int pcmout_buffer_addr;
|
||||
static unsigned int pcmout_buffer_size;
|
||||
|
||||
int valid_channel[] = {
|
||||
static int valid_channel[] = {
|
||||
0x1, /* slot number 1 */
|
||||
0x3, /* slot number 2 */
|
||||
0x7, /* slot number 3 */
|
||||
@@ -55,6 +55,9 @@ int valid_channel[] = {
|
||||
0xffff /* slot number 16 */
|
||||
};
|
||||
|
||||
/* counter for pcm clk used */
|
||||
static int aml_pcm_clk_count;
|
||||
|
||||
static uint32_t aml_read_cbus_bits(uint32_t reg, const uint32_t start,
|
||||
const uint32_t len)
|
||||
{
|
||||
@@ -117,11 +120,14 @@ RESET_FIFO:
|
||||
|
||||
if (flag) {
|
||||
unsigned int pcm_mode = 1;
|
||||
unsigned int valid_slot =
|
||||
valid_channel[substream->runtime->channels - 1];
|
||||
unsigned int num_slot = substream->runtime->channels;
|
||||
unsigned int valid_slot = valid_channel[num_slot - 1];
|
||||
unsigned int max_bits = 0xf;
|
||||
unsigned int valid_bits = 0xf;
|
||||
|
||||
/* whatever pcm out is enable */
|
||||
aml_pcm_clk_count++;
|
||||
|
||||
switch (substream->runtime->format) {
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
pcm_mode = 3;
|
||||
@@ -218,7 +224,7 @@ RESET_FIFO:
|
||||
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = num_slot - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
} else {
|
||||
@@ -234,7 +240,7 @@ RESET_FIFO:
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x1F;
|
||||
slot_offset_s = (num_slot << 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -242,7 +248,7 @@ RESET_FIFO:
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x1F;
|
||||
slot_offset_s = (num_slot << 1) - 8 - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -252,22 +258,31 @@ RESET_FIFO:
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0x7;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = (num_slot >> 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
aml_write_cbus(PCMOUT_CTRL2,
|
||||
aml_read_cbus(PCMOUT_CTRL2) |
|
||||
pr_info("pcm master in, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n",
|
||||
pcm_mode,
|
||||
valid_bits,
|
||||
valid_slot);
|
||||
|
||||
aml_write_cbus(PCMOUT_CTRL2,
|
||||
/* underrun use mute constant */
|
||||
(0 << 29) |
|
||||
/* pcmo max slot number in one frame*/
|
||||
(0xF << 22) |
|
||||
((num_slot - 1) << 22) |
|
||||
/* pcmo max bit number in one slot*/
|
||||
(valid_bits << 16) |
|
||||
(valid_slot << 0)
|
||||
);
|
||||
);
|
||||
aml_write_cbus(PCMOUT_CTRL1,
|
||||
aml_read_cbus(PCMOUT_CTRL1) |
|
||||
/* pcmo output data byte number. 00 : 8bits.
|
||||
* 01: 16bits. 10: 24bits. 11: 32bits
|
||||
*/
|
||||
(pcm_mode << 30) |
|
||||
/* use posedge of PCM clock to output data*/
|
||||
(0 << 28) |
|
||||
/* invert fs phase */
|
||||
@@ -285,14 +300,12 @@ RESET_FIFO:
|
||||
/* fs_o end postion slot bit counter number.*/
|
||||
(slot_offset_e << 0)
|
||||
);
|
||||
aml_write_cbus(PCMOUT_CTRL0,
|
||||
aml_read_cbus(PCMOUT_CTRL0) |
|
||||
(1 << 31) | /* enable */
|
||||
(1 << 29) /* master */
|
||||
);
|
||||
aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 31, 1 << 31);
|
||||
aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 29, 1 << 29);
|
||||
}
|
||||
} else {
|
||||
if (!pcm_out_is_enable()) {
|
||||
aml_pcm_clk_count--;
|
||||
if (aml_pcm_clk_count <= 0) {
|
||||
/* disable pcmout */
|
||||
aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 31, 0 << 31);
|
||||
}
|
||||
@@ -336,8 +349,8 @@ void pcm_in_enable(struct snd_pcm_substream *substream, int flag)
|
||||
|
||||
if (flag) {
|
||||
unsigned int pcm_mode = 1;
|
||||
unsigned int valid_slot =
|
||||
valid_channel[substream->runtime->channels - 1];
|
||||
unsigned int num_slot = substream->runtime->channels;
|
||||
unsigned int valid_slot = valid_channel[num_slot - 1];
|
||||
unsigned int max_bits = 0xf;
|
||||
unsigned int valid_bits = 0xf;
|
||||
|
||||
@@ -512,15 +525,15 @@ static void pcm_out_register_show(void)
|
||||
void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
{
|
||||
unsigned int pcm_mode = 1;
|
||||
unsigned int valid_slot =
|
||||
valid_channel[substream->runtime->channels - 1];
|
||||
unsigned int num_slot = substream->runtime->channels;
|
||||
unsigned int valid_slot = valid_channel[num_slot - 1];
|
||||
unsigned int valid_bits = 0xf;
|
||||
unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_B;
|
||||
unsigned int bit_offset_s, slot_offset_s, bit_offset_e, slot_offset_e;
|
||||
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = num_slot - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
} else {
|
||||
@@ -539,7 +552,7 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x1f;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x1F;
|
||||
slot_offset_s = (num_slot << 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -549,7 +562,7 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x17;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x17;
|
||||
slot_offset_s = (num_slot << 1) - 8 - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -563,13 +576,18 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x7;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0x7;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = (num_slot >> 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pr_info("pcm master out, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n",
|
||||
pcm_mode,
|
||||
valid_bits,
|
||||
valid_slot);
|
||||
|
||||
/* reset fifo */
|
||||
aml_cbus_update_bits(AUDOUT_CTRL, 1 << 30, 1 << 30);
|
||||
aml_cbus_update_bits(AUDOUT_CTRL, 1 << 30, 1 << 30);
|
||||
@@ -630,13 +648,12 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
aml_write_cbus(PCMOUT_CTRL3, 0); /* mute constant */
|
||||
|
||||
/* pcmout control2 */
|
||||
/* FS * 16 * 16 = BCLK */
|
||||
/* FS * 32 * 16 = BCLK */
|
||||
/* FS * valid bit * slot num = BCLK */
|
||||
aml_write_cbus(PCMOUT_CTRL2,
|
||||
/* underrun use mute constant */
|
||||
(0 << 29) |
|
||||
/* pcmo max slot number in one frame */
|
||||
(0xF << 22) |
|
||||
((num_slot - 1) << 22) |
|
||||
/* pcmo max bit number in one slot */
|
||||
(valid_bits << 16) |
|
||||
/* pcmo valid slot. each bit for one slot */
|
||||
@@ -689,6 +706,14 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
/*slave mode, sync fs with frame slot counter.*/
|
||||
(0 << 0)
|
||||
);
|
||||
|
||||
aml_pcm_clk_count++;
|
||||
} else {
|
||||
aml_pcm_clk_count--;
|
||||
if (aml_pcm_clk_count <= 0) {
|
||||
/* disable pcmout */
|
||||
aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 31, 0 << 31);
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("PCMOUT %s\n", flag ? "enable" : "disable");
|
||||
@@ -698,15 +723,15 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
{
|
||||
unsigned int pcm_mode = 1;
|
||||
unsigned int valid_slot =
|
||||
valid_channel[substream->runtime->channels - 1];
|
||||
unsigned int num_slot = substream->runtime->channels;
|
||||
unsigned int valid_slot = valid_channel[num_slot - 1];
|
||||
unsigned int valid_bits = 0xf;
|
||||
unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_A;
|
||||
unsigned int bit_offset_s, slot_offset_s, bit_offset_e, slot_offset_e;
|
||||
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = num_slot - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
} else {
|
||||
@@ -725,7 +750,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x1f;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x1F;
|
||||
slot_offset_s = (num_slot << 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -735,7 +760,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x1f;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0xF;
|
||||
slot_offset_s = 0x1F;
|
||||
slot_offset_s = (num_slot << 1) - 8 - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
@@ -749,14 +774,14 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
|
||||
valid_bits = 0x7;
|
||||
if (dsp_mode == SND_SOC_DAIFMT_DSP_A) {
|
||||
bit_offset_s = 0x7;
|
||||
slot_offset_s = 0xF;
|
||||
slot_offset_s = (num_slot >> 1) - 1;
|
||||
bit_offset_e = 0;
|
||||
slot_offset_e = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("pcm out, pcm mode:%d, valid bits:%x, valid slot:%x\n",
|
||||
pr_info("pcm out, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n",
|
||||
pcm_mode,
|
||||
valid_bits,
|
||||
valid_slot);
|
||||
|
||||
@@ -92,17 +92,25 @@ static int aml_pcm_dai_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct aml_pcm_runtime_data *prtd = runtime->private_data;
|
||||
struct aml_pcm *pcm = snd_soc_dai_get_drvdata(dai);
|
||||
int mclk_rate;
|
||||
int mclk_rate, pcm_bit;
|
||||
|
||||
pr_debug("***Entered %s\n", __func__);
|
||||
|
||||
/* set bclk */
|
||||
if (runtime->format == SNDRV_PCM_FORMAT_S32_LE)
|
||||
mclk_rate = runtime->rate * PCM_32BIT_MCLK_RATIO_SR;
|
||||
pcm_bit = 32;
|
||||
else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE)
|
||||
mclk_rate = runtime->rate * PCM_24BIT_MCLK_RATIO_SR;
|
||||
pcm_bit = 24;
|
||||
else
|
||||
mclk_rate = runtime->rate * PCM_DEFAULT_MCLK_RATIO_SR;
|
||||
pcm_bit = 16;
|
||||
|
||||
mclk_rate = runtime->rate * pcm_bit * runtime->channels;
|
||||
pr_info("%s rate:%d, bits:%d, channels:%d, mclk:%d\n",
|
||||
__func__,
|
||||
runtime->rate,
|
||||
pcm_bit,
|
||||
runtime->channels,
|
||||
mclk_rate);
|
||||
|
||||
aml_pcm_set_clk(pcm, mclk_rate);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user