audio: add HW resample for HDMIRX [1/1]

PD#SWPL-6118

Problem:
No resample will cause mismatch between
input and output if they are not at same
samplerate.

Solution:
Add resample for hdmirx case

Verify:
Local tested.

Change-Id: I298e401578bf49484d6b75fd736d2a74c38508e4
Signed-off-by: Shuai Li <shuai.li@amlogic.com>
This commit is contained in:
Shuai Li
2019-03-27 16:37:00 +08:00
committed by Jianxin Pan
parent 9b0245f273
commit 0663274a19
12 changed files with 213 additions and 109 deletions

View File

@@ -1458,8 +1458,9 @@
* NONE, * NONE,
* TDMIN_LB, 6 * TDMIN_LB, 6
* LOOPBACK, 7 * LOOPBACK, 7
* FRHDMIRX, 8
*/ */
resample_module = <3>; resample_module = <8>;
status = "okay"; status = "okay";
}; };

View File

@@ -1518,8 +1518,9 @@
* NONE, * NONE,
* TDMIN_LB, 6 * TDMIN_LB, 6
* LOOPBACK, 7 * LOOPBACK, 7
* FRHDMIRX, 8
*/ */
resample_module = <3>; resample_module = <8>;
status = "okay"; status = "okay";
}; };

View File

@@ -1455,8 +1455,9 @@
* NONE, * NONE,
* TDMIN_LB, 6 * TDMIN_LB, 6
* LOOPBACK, 7 * LOOPBACK, 7
* FRHDMIRX, 8
*/ */
resample_module = <3>; resample_module = <8>;
status = "okay"; status = "okay";
}; };

View File

@@ -1512,8 +1512,9 @@
* NONE, * NONE,
* TDMIN_LB, 6 * TDMIN_LB, 6
* LOOPBACK, 7 * LOOPBACK, 7
* FRHDMIRX, 8
*/ */
resample_module = <3>; resample_module = <8>;
status = "okay"; status = "okay";
}; };

View File

@@ -388,10 +388,10 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh)
if (to->chipinfo if (to->chipinfo
&& to->chipinfo->src_sel_ctrl) { && to->chipinfo->src_sel_ctrl) {
mask = 0xfff << 12 | 0xf << 8; mask = 0xfff << 12 | 0xf << 8;
val = (thresh-1) << 12 | 2 << 8; val = (thresh-2) << 12 | 2 << 8;
} else { } else {
mask = 0xff << 16 | 0xf << 8; mask = 0xff << 16 | 0xf << 8;
val = (thresh-1) << 16 | 2 << 8; val = (thresh-2) << 16 | 2 << 8;
} }
aml_audiobus_update_bits(actrl, reg, mask, val); aml_audiobus_update_bits(actrl, reg, mask, val);
@@ -479,28 +479,29 @@ void aml_toddr_write(struct toddr *to, unsigned int val)
aml_audiobus_write(actrl, reg, val); aml_audiobus_write(actrl, reg, val);
} }
/* not for tl1 */
void aml_toddr_set_resample(struct toddr *to, bool enable) static void aml_toddr_set_resample(struct toddr *to, bool enable)
{ {
struct aml_audio_controller *actrl = to->actrl; struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base; unsigned int reg_base = to->reg_base;
unsigned int reg; unsigned int reg;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); aml_audiobus_update_bits(actrl, reg, 1<<30, !!enable<<30);
} }
/* tl1 after */
void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, bool enable) static void aml_toddr_set_resample_ab(struct toddr *to,
enum resample_idx index, bool enable)
{ {
struct aml_audio_controller *actrl = to->actrl; struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base; unsigned int reg_base = to->reg_base;
unsigned int reg; unsigned int reg;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
if (asrc_src_sel == 0) if (index == RESAMPLE_A)
aml_audiobus_update_bits(actrl, reg, 1 << 27, enable << 27); aml_audiobus_update_bits(actrl, reg, 1 << 27, !!enable << 27);
else else if (index == RESAMPLE_B)
aml_audiobus_update_bits(actrl, reg, 1 << 26, enable << 26); aml_audiobus_update_bits(actrl, reg, 1 << 26, !!enable << 26);
} }
static void aml_resample_enable( static void aml_resample_enable(
@@ -508,12 +509,15 @@ static void aml_resample_enable(
struct toddr_attach *p_attach_resample, struct toddr_attach *p_attach_resample,
bool enable) bool enable)
{ {
if (!to) if (!to || !p_attach_resample) {
pr_err("%s(), NULL pointer.", __func__);
return; return;
}
if (to->chipinfo if (to->chipinfo
&& to->chipinfo->asrc_src_sel_ctrl) { && to->chipinfo->asrc_src_sel_ctrl) {
/* fix asrc_src_sel */ /* fix asrc_src_sel */
/*
switch (p_attach_resample->attach_module) { switch (p_attach_resample->attach_module) {
case LOOPBACK_A: case LOOPBACK_A:
to->asrc_src_sel = ASRC_LOOPBACK_A; to->asrc_src_sel = ASRC_LOOPBACK_A;
@@ -525,21 +529,24 @@ static void aml_resample_enable(
to->asrc_src_sel = to->fifo_id; to->asrc_src_sel = to->fifo_id;
break; break;
} }
*/
to->asrc_src_sel = p_attach_resample->attach_module;
} }
pr_info("toddr %d selects data to %s resample_%c for module:%s\n", pr_info("toddr %d selects data to %s resample_%c for module:%s\n",
to->fifo_id, to->fifo_id,
enable ? "enable" : "disable", enable ? "enable" : "disable",
(p_attach_resample->id == 0) ? 'a' : 'b', (p_attach_resample->id == RESAMPLE_A) ? 'a' : 'b',
toddr_src_get_str(p_attach_resample->attach_module) toddr_src_get_str(p_attach_resample->attach_module)
); );
if (enable) { if (enable) {
int bitwidth = to->bitdepth; int bitwidth = to->bitdepth;
/* channels and bit depth for resample */ /* channels and bit depth for resample */
if (to->chipinfo if (to->chipinfo
&& to->chipinfo->asrc_only_left_j && to->chipinfo->asrc_only_left_j
&& (to->src == SPDIFIN) /*&& (to->src == SPDIFIN)*/
&& (bitwidth == 32)) { && (bitwidth == 32)) {
struct aml_audio_controller *actrl = to->actrl; struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base; unsigned int reg_base = to->reg_base;
@@ -583,13 +590,14 @@ static void aml_resample_enable(
aml_toddr_set_resample(to, enable); aml_toddr_set_resample(to, enable);
} }
void aml_set_resample(int id, bool enable, int resample_module) void aml_set_resample(enum resample_idx id,
bool enable, enum toddr_src resample_module)
{ {
struct toddr_attach *p_attach_resample; struct toddr_attach *p_attach_resample;
struct toddr *to; struct toddr *to;
bool update_running = false; bool update_running = false;
if (id == 0) if (id == RESAMPLE_A)
p_attach_resample = &attach_resample_a; p_attach_resample = &attach_resample_a;
else else
p_attach_resample = &attach_resample_b; p_attach_resample = &attach_resample_b;
@@ -1370,13 +1378,13 @@ void frddr_deinit_without_mngr(unsigned int frddr_index)
audiobus_write(reg, 0x0); audiobus_write(reg, 0x0);
} }
static int toddr_src_idx = -1; static enum toddr_src toddr_src_idx = TODDR_INVAL;
static const char *const toddr_src_sel_texts[] = { static const char *const toddr_src_sel_texts[] = {
"TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN", "TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN",
"PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A", "PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A",
"FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB", "FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB",
"EARCRX_DMAC", "RESERVED", "RESERVED", "RESERVED", "EARCRX_DMAC", "RESERVED_0", "RESERVED_1", "RESERVED_2",
"VAD" "VAD"
}; };
@@ -1384,14 +1392,14 @@ static const struct soc_enum toddr_input_source_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(toddr_src_sel_texts), SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(toddr_src_sel_texts),
toddr_src_sel_texts); toddr_src_sel_texts);
int toddr_src_get(void) enum toddr_src toddr_src_get(void)
{ {
return toddr_src_idx; return toddr_src_idx;
} }
const char *toddr_src_get_str(int idx) const char *toddr_src_get_str(enum toddr_src idx)
{ {
if (idx < 0 || idx > 15) if (idx < TDMIN_A || idx > VAD)
return NULL; return NULL;
return toddr_src_sel_texts[idx]; return toddr_src_sel_texts[idx];
@@ -1409,6 +1417,8 @@ static int toddr_src_enum_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
toddr_src_idx = ucontrol->value.enumerated.item[0]; toddr_src_idx = ucontrol->value.enumerated.item[0];
/* also update to resample src */
//set_resample_source(toddr_src_idx);
return 0; return 0;
} }

View File

@@ -42,19 +42,29 @@ enum ddr_types {
* from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD * from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD
*/ */
enum toddr_src { enum toddr_src {
TDMIN_A, TODDR_INVAL = -1,
TDMIN_B, TDMIN_A = 0,
TDMIN_C, TDMIN_B = 1,
SPDIFIN, TDMIN_C = 2,
PDMIN, SPDIFIN = 3,
FRATV, /* NONE for axg, g12a, g12b */ PDMIN = 4,
TDMIN_LB, FRATV = 5, /* NONE for axg, g12a, g12b */
LOOPBACK_A, TDMIN_LB = 6,
FRHDMIRX, /* from tl1 chipset*/ LOOPBACK_A = 7,
LOOPBACK_B, FRHDMIRX = 8, /* from tl1 chipset*/
SPDIFIN_LB, LOOPBACK_B = 9,
EARCRX_DMAC, /* from sm1 chipset */ SPDIFIN_LB = 10,
VAD, EARCRX_DMAC = 11,/* from sm1 chipset */
RESERVED_0 = 12,
RESERVED_1 = 13,
RESERVED_2 = 14,
VAD = 15,
TODDR_SRC_MAX = 16
};
enum resample_idx {
RESAMPLE_A,
RESAMPLE_B
}; };
enum resample_src { enum resample_src {
@@ -177,7 +187,7 @@ struct toddr {
enum toddr_src src; enum toddr_src src;
unsigned int fifo_id; unsigned int fifo_id;
unsigned int asrc_src_sel; enum toddr_src asrc_src_sel;
int is_lb; /* check whether for loopback */ int is_lb; /* check whether for loopback */
int irq; int irq;
@@ -194,7 +204,7 @@ enum status {
struct toddr_attach { struct toddr_attach {
bool enable; bool enable;
int id; enum resample_idx id;
int status; int status;
/* which module should be attached, /* which module should be attached,
* check which toddr in use should be attached * check which toddr in use should be attached
@@ -259,7 +269,8 @@ unsigned int aml_toddr_read(struct toddr *to);
void aml_toddr_write(struct toddr *to, unsigned int val); void aml_toddr_write(struct toddr *to, unsigned int val);
/* resample */ /* resample */
void aml_set_resample(int id, bool enable, int resample_module); void aml_set_resample(enum resample_idx id,
bool enable, enum toddr_src resample_module);
/* power detect */ /* power detect */
void aml_pwrdet_enable(bool enable, int pwrdet_module); void aml_pwrdet_enable(bool enable, int pwrdet_module);
/* Voice Activity Detection */ /* Voice Activity Detection */
@@ -297,8 +308,8 @@ void aml_set_aed(bool enable, int aed_module);
void frddr_init_without_mngr(unsigned int frddr_index, unsigned int src0_sel); void frddr_init_without_mngr(unsigned int frddr_index, unsigned int src0_sel);
void frddr_deinit_without_mngr(unsigned int frddr_index); void frddr_deinit_without_mngr(unsigned int frddr_index);
int toddr_src_get(void); enum toddr_src toddr_src_get(void);
const char *toddr_src_get_str(int idx); const char *toddr_src_get_str(enum toddr_src idx);
int frddr_src_get(void); int frddr_src_get(void);
const char *frddr_src_get_str(int idx); const char *frddr_src_get_str(int idx);

View File

@@ -37,6 +37,7 @@
#include "ddr_mngr.h" #include "ddr_mngr.h"
#include "audio_utils.h" #include "audio_utils.h"
#include "frhdmirx_hw.h" #include "frhdmirx_hw.h"
#include "resample.h"
#include <linux/amlogic/media/sound/misc.h> #include <linux/amlogic/media/sound/misc.h>
@@ -371,6 +372,7 @@ static int extn_dai_startup(
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
resample_set_inner_rate(RESAMPLE_A);
return 0; return 0;
} }
@@ -378,6 +380,7 @@ static void extn_dai_shutdown(
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
//resample_set(RESAMPLE_A, RATE_OFF);
} }
static int extn_dai_prepare( static int extn_dai_prepare(
@@ -401,7 +404,7 @@ static int extn_dai_prepare(
} else { } else {
struct toddr *to = p_extn->tddr; struct toddr *to = p_extn->tddr;
unsigned int msb = 0, lsb = 0, toddr_type = 0; unsigned int msb = 0, lsb = 0, toddr_type = 0;
unsigned int src = toddr_src_get(); enum toddr_src src = toddr_src_get();
struct toddr_fmt fmt; struct toddr_fmt fmt;
if (bit_depth == 24) if (bit_depth == 24)
@@ -472,7 +475,7 @@ static int extn_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
struct extn *p_extn = snd_soc_dai_get_drvdata(cpu_dai); struct extn *p_extn = snd_soc_dai_get_drvdata(cpu_dai);
unsigned int src = toddr_src_get(); enum toddr_src src = toddr_src_get();
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:

View File

@@ -27,8 +27,6 @@
#include <sound/tlv.h> #include <sound/tlv.h>
#include "resample.h" #include "resample.h"
#include "resample_hw.h"
#include "ddr_mngr.h"
#include "regs.h" #include "regs.h"
#include "iomap.h" #include "iomap.h"
@@ -38,12 +36,12 @@
/*#define __PTM_RESAMPLE_CLK__*/ /*#define __PTM_RESAMPLE_CLK__*/
#define RESAMPLE_A 0 //#define RESAMPLE_A 0
#define RESAMPLE_B 1 //#define RESAMPLE_B 1
struct resample_chipinfo { struct resample_chipinfo {
int num; /* support resample a/b */ int num; /* support resample a/b */
int id; enum resample_idx id;
bool dividor_fn; bool dividor_fn;
}; };
@@ -60,15 +58,15 @@ struct audioresample {
struct resample_chipinfo *chipinfo; struct resample_chipinfo *chipinfo;
int id; enum resample_idx id;
/*which module should be resampled */ /*which module should be resampled */
int resample_module; enum toddr_src resample_module;
/* resample to the rate */ /* resample to the rate */
int out_rate; int out_rate;
/* sync with auge_resample_texts */ /* sync with auge_resample_texts */
int asrc_rate_idx; enum samplerate_index asrc_rate_idx;
bool enable; bool enable;
}; };
@@ -77,11 +75,11 @@ struct audioresample *s_resample_a;
struct audioresample *s_resample_b; struct audioresample *s_resample_b;
static struct audioresample *get_audioresample(int id) static struct audioresample *get_audioresample(enum resample_idx id)
{ {
struct audioresample *p_resample; struct audioresample *p_resample;
p_resample = ((id == 0) ? s_resample_a : s_resample_b); p_resample = ((id == RESAMPLE_A) ? s_resample_a : s_resample_b);
if (!p_resample) { if (!p_resample) {
pr_debug("Not init audio resample\n"); pr_debug("Not init audio resample\n");
@@ -93,7 +91,7 @@ static struct audioresample *get_audioresample(int id)
int get_resample_module_num(void) int get_resample_module_num(void)
{ {
struct audioresample *p_resample = get_audioresample(0); struct audioresample *p_resample = get_audioresample(RESAMPLE_A);
if (p_resample && p_resample->chipinfo) if (p_resample && p_resample->chipinfo)
return p_resample->chipinfo->num; return p_resample->chipinfo->num;
@@ -101,6 +99,32 @@ int get_resample_module_num(void)
return 1; return 1;
} }
int set_resample_source(enum resample_idx id, enum toddr_src src)
{
struct audioresample *p_resample = get_audioresample(id);
(void)p_resample;
(void)src;
//p_resample->resample_module = src;
return 0;
}
static int set_resample_rate_index(
enum resample_idx id, enum samplerate_index index)
{
struct audioresample *p_resample = get_audioresample(id);
p_resample->asrc_rate_idx = index;
return 0;
}
static enum samplerate_index get_resample_rate_index(
enum resample_idx id)
{
struct audioresample *p_resample = get_audioresample(id);
return p_resample->asrc_rate_idx;
}
static int resample_clk_set(struct audioresample *p_resample) static int resample_clk_set(struct audioresample *p_resample)
{ {
int ret = 0; int ret = 0;
@@ -126,7 +150,7 @@ static int resample_clk_set(struct audioresample *p_resample)
clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO); clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO);
clk_set_rate(p_resample->clk, 48000 * CLK_RATIO); clk_set_rate(p_resample->clk, 48000 * CLK_RATIO);
} }
#if 0
ret = clk_prepare_enable(p_resample->pll); ret = clk_prepare_enable(p_resample->pll);
if (ret) { if (ret) {
pr_err("Can't enable pll clock: %d\n", ret); pr_err("Can't enable pll clock: %d\n", ret);
@@ -146,6 +170,7 @@ static int resample_clk_set(struct audioresample *p_resample)
ret); ret);
return -EINVAL; return -EINVAL;
} }
#endif
pr_info("%s, resample_pll:%lu, sclk:%lu, clk:%lu\n", pr_info("%s, resample_pll:%lu, sclk:%lu, clk:%lu\n",
__func__, __func__,
@@ -153,9 +178,11 @@ static int resample_clk_set(struct audioresample *p_resample)
clk_get_rate(p_resample->sclk), clk_get_rate(p_resample->sclk),
clk_get_rate(p_resample->clk)); clk_get_rate(p_resample->clk));
} else { } else {
#if 0
clk_disable_unprepare(p_resample->clk); clk_disable_unprepare(p_resample->clk);
clk_disable_unprepare(p_resample->sclk); clk_disable_unprepare(p_resample->sclk);
clk_disable_unprepare(p_resample->pll); clk_disable_unprepare(p_resample->pll);
#endif
} }
return ret; return ret;
@@ -194,25 +221,25 @@ static const char *const auge_resample_texts[] = {
"Enable:192K", "Enable:192K",
}; };
static int resample_idx2rate(int index) static int resample_idx2rate(enum samplerate_index index)
{ {
int rate = 0; int rate = 0;
if (index == 0) if (index == RATE_OFF)
rate = 0; rate = 0;
else if (index == 1) else if (index == RATE_32K)
rate = 32000; rate = 32000;
else if (index == 2) else if (index == RATE_44K)
rate = 44100; rate = 44100;
else if (index == 3) else if (index == RATE_48K)
rate = 48000; rate = 48000;
else if (index == 4) else if (index == RATE_88K)
rate = 88200; rate = 88200;
else if (index == 5) else if (index == RATE_96K)
rate = 96000; rate = 96000;
else if (index == 6) else if (index == RATE_176K)
rate = 176400; rate = 176400;
else if (index == 7) else if (index == RATE_192K)
rate = 192000; rate = 192000;
return rate; return rate;
@@ -238,38 +265,51 @@ static int resample_get_enum(
return 0; return 0;
} }
int resample_set(int id, int index) int resample_set(enum resample_idx id, enum samplerate_index index)
{ {
int resample_rate = resample_idx2rate(index); int resample_rate = 0;
struct audioresample *p_resample = get_audioresample(id); struct audioresample *p_resample = get_audioresample(id);
int ret = 0;
pr_info("%s resample_%c to %s, last %s\n",
__func__,
(id == RESAMPLE_A) ? 'a' : 'b',
auge_resample_texts[index],
auge_resample_texts[p_resample->asrc_rate_idx]);
if (!p_resample) if (!p_resample)
return 0; return 0;
if (index == p_resample->asrc_rate_idx) //if (index == p_resample->asrc_rate_idx)
return 0; // return 0;
p_resample->asrc_rate_idx = index; p_resample->asrc_rate_idx = index;
pr_info("%s resample_%c %s\n", resample_rate = resample_idx2rate(index);
__func__, ret = audio_resample_set(p_resample, (bool)index, resample_rate);
(id == 0) ? 'a' : 'b', if (ret)
auge_resample_texts[index]); return ret;
if (audio_resample_set(p_resample, (bool)index, resample_rate)) if (index == RATE_OFF)
return 0;
if ((index == 0) || (resample_rate == 0))
resample_disable(p_resample->id); resample_disable(p_resample->id);
else { else {
resample_init(p_resample->id, resample_rate); resample_init(p_resample->id, resample_rate);
resample_set_hw_param(p_resample->id, index - 1); resample_set_hw_param(p_resample->id, index);
} }
return 0; return 0;
} }
int resample_set_inner_rate(enum resample_idx id)
{
enum samplerate_index index = get_resample_rate_index(id);
pr_debug("%s() index %d\n", __func__, id);
return resample_set(id, index);
}
static int resample_set_enum( static int resample_set_enum(
struct snd_kcontrol *kcontrol, struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
@@ -282,7 +322,8 @@ static int resample_set_enum(
return 0; return 0;
} }
resample_set(p_resample->id, index); set_resample_rate_index(p_resample->id, index);
resample_set_inner_rate(p_resample->id);
return 0; return 0;
} }
@@ -345,6 +386,10 @@ static const char *const auge_resample_module_texts[] = {
"FRHDMIRX", /* from tl1 chipset*/ "FRHDMIRX", /* from tl1 chipset*/
"LOOPBACK_B", "LOOPBACK_B",
"SPDIFIN_LB", "SPDIFIN_LB",
"RESERVED_0",
"RESERVED_1",
"RESERVED_2",
"RESERVED_3",
"VAD", "VAD",
}; };
@@ -388,7 +433,6 @@ static int resample_module_set_enum(
return 0; return 0;
} }
static const struct snd_kcontrol_new asrc_a_controls[] = { static const struct snd_kcontrol_new asrc_a_controls[] = {
SOC_ENUM_EXT("Hardware resample enable", SOC_ENUM_EXT("Hardware resample enable",
auge_resample_enum, auge_resample_enum,
@@ -566,6 +610,13 @@ static int resample_platform_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = clk_prepare_enable(p_resample->clk);
if (ret) {
pr_err("Can't enable resample_clk clock: %d\n",
ret);
return ret;
}
p_resample->dev = dev; p_resample->dev = dev;
if (p_chipinfo && p_chipinfo->id == 1) if (p_chipinfo && p_chipinfo->id == 1)

View File

@@ -17,10 +17,16 @@
#ifndef __AML_AUDIO_RESAMPLE_H__ #ifndef __AML_AUDIO_RESAMPLE_H__
#define __AML_AUDIO_RESAMPLE_H__ #define __AML_AUDIO_RESAMPLE_H__
#include "resample_hw.h"
extern int card_add_resample_kcontrols(struct snd_soc_card *card); extern int card_add_resample_kcontrols(struct snd_soc_card *card);
extern int resample_set(int id, int index); extern int resample_set(enum resample_idx id, enum samplerate_index index);
extern int get_resample_module_num(void); extern int get_resample_module_num(void);
int set_resample_source(enum resample_idx id, enum toddr_src src);
int resample_set_inner_rate(enum resample_idx id);
#endif #endif

View File

@@ -40,7 +40,7 @@ static u32 resample_coef_parameters_table[7][5] = {
{0x00800000, 0x0, 0x0, 0x0, 0x0}, {0x00800000, 0x0, 0x0, 0x0, 0x0},
}; };
void resample_enable(int id, bool enable) void resample_enable(enum resample_idx id, bool enable)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
@@ -58,7 +58,7 @@ void resample_enable(int id, bool enable)
enable << 28); enable << 28);
} }
int resample_init(int id, int input_sr) int resample_init(enum resample_idx id, int input_sr)
{ {
u16 Avg_cnt_init = 0; u16 Avg_cnt_init = 0;
unsigned int clk_rate = 167000000;//clk81; unsigned int clk_rate = 167000000;//clk81;
@@ -77,15 +77,15 @@ int resample_init(int id, int input_sr)
Avg_cnt_init); Avg_cnt_init);
audiobus_update_bits(reg, audiobus_update_bits(reg,
0x3 << 26 | 0x3ff << 16 | 0xffff << 0, 0x3 << 26 | 0x3ff << 16 | 0xffff,
0x0 << 26 | /* method0 */ 0x0 << 26 | /* method0 */
RESAMPLE_CNT_CONTROL << 16 | RESAMPLE_CNT_CONTROL << 16 |
Avg_cnt_init << 0); Avg_cnt_init);
return 0; return 0;
} }
int resample_disable(int id) int resample_disable(enum resample_idx id)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
@@ -95,15 +95,20 @@ int resample_disable(int id)
return 0; return 0;
} }
int resample_set_hw_param(int id, int index) int resample_set_hw_param(enum resample_idx id,
enum samplerate_index rate_index)
{ {
int i, reg, offset; int i, reg, offset;
if (rate_index < RATE_32K) {
pr_info("%s(), inval index %d", __func__, rate_index);
return -EINVAL;
}
offset = EE_AUDIO_RESAMPLEB_COEF0 - EE_AUDIO_RESAMPLEA_COEF0; offset = EE_AUDIO_RESAMPLEB_COEF0 - EE_AUDIO_RESAMPLEA_COEF0;
reg = EE_AUDIO_RESAMPLEA_COEF0 + offset * id; reg = EE_AUDIO_RESAMPLEA_COEF0 + offset * id;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
audiobus_write((reg + i), audiobus_write((reg + i),
resample_coef_parameters_table[index][i]); resample_coef_parameters_table[rate_index - 1][i]);
} }
offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2;
@@ -113,15 +118,15 @@ int resample_set_hw_param(int id, int index)
return 0; return 0;
} }
/* not avail for tl1 */
void resample_src_select(int src) void resample_src_select(int src)
{ {
audiobus_update_bits(EE_AUDIO_RESAMPLEA_CTRL0, audiobus_update_bits(EE_AUDIO_RESAMPLEA_CTRL0,
0x3 << 29, 0x3 << 29,
src << 29); src << 29);
} }
/* for tl1 and after */
void resample_src_select_ab(int id, int src) void resample_src_select_ab(enum resample_idx id, enum toddr_src src)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3;
int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id;
@@ -131,7 +136,7 @@ void resample_src_select_ab(int id, int src)
src << 16); src << 16);
} }
void resample_format_set(int id, int ch_num, int bits) void resample_format_set(enum resample_idx id, int ch_num, int bits)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3;
int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id;
@@ -140,7 +145,7 @@ void resample_format_set(int id, int ch_num, int bits)
ch_num << 8 | (bits - 1) << 0); ch_num << 8 | (bits - 1) << 0);
} }
int resample_ctrl_read(int id) int resample_ctrl_read(enum resample_idx id)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
@@ -148,7 +153,7 @@ int resample_ctrl_read(int id)
return audiobus_read(reg); return audiobus_read(reg);
} }
void resample_ctrl_write(int id, int value) void resample_ctrl_write(enum resample_idx id, int value)
{ {
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;

View File

@@ -17,15 +17,29 @@
#ifndef __AML_AUDIO_RESAMPLE_HW_H__ #ifndef __AML_AUDIO_RESAMPLE_HW_H__
#define __AML_AUDIO_RESAMPLE_HW_H__ #define __AML_AUDIO_RESAMPLE_HW_H__
extern void resample_enable(int id, bool enable); #include "ddr_mngr.h"
extern int resample_init(int id, int input_sr);
extern int resample_disable(int id);
extern int resample_set_hw_param(int id, int index);
extern void resample_src_select(int src);
extern void resample_src_select_ab(int id, int src);
extern void resample_format_set(int id, int ch_num, int bits);
extern int resample_ctrl_read(int id); enum samplerate_index {
extern void resample_ctrl_write(int id, int value); RATE_OFF,
RATE_32K,
RATE_44K,
RATE_48K,
RATE_88K,
RATE_96K,
RATE_176K,
RATE_192K,
};
extern void resample_enable(enum resample_idx id, bool enable);
extern int resample_init(enum resample_idx id, int input_sr);
extern int resample_disable(enum resample_idx id);
extern int resample_set_hw_param(enum resample_idx id,
enum samplerate_index rate_index);
extern void resample_src_select(int src);
extern void resample_src_select_ab(enum resample_idx id, enum toddr_src src);
extern void resample_format_set(enum resample_idx id, int ch_num, int bits);
extern int resample_ctrl_read(enum resample_idx id);
extern void resample_ctrl_write(enum resample_idx id, int value);
#endif #endif

View File

@@ -86,11 +86,11 @@ struct aml_spdif {
/* /*
* resample a/b do asrc for spdif in * resample a/b do asrc for spdif in
*/ */
unsigned int asrc_id; enum resample_idx asrc_id;
/* spdif in do asrc for pcm, /* spdif in do asrc for pcm,
* if raw data, disable it automatically. * if raw data, disable it automatically.
*/ */
unsigned int auto_asrc; enum samplerate_index auto_asrc;
/* check spdifin channel status for pcm or nonpcm */ /* check spdifin channel status for pcm or nonpcm */
struct timer_list timer; struct timer_list timer;
@@ -441,7 +441,7 @@ static void spdifin_audio_type_work_func(struct work_struct *work)
if (val & 0x2) if (val & 0x2)
/* nonpcm, resample disable */ /* nonpcm, resample disable */
resample_set(p_spdif->asrc_id, 0); resample_set(p_spdif->asrc_id, RATE_OFF);
else else
/* pcm, resample which rate ? */ /* pcm, resample which rate ? */
resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); resample_set(p_spdif->asrc_id, p_spdif->auto_asrc);
@@ -652,7 +652,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif)
#ifdef __SPDIFIN_AUDIO_TYPE_HW__ #ifdef __SPDIFIN_AUDIO_TYPE_HW__
/* resample disable, by hw */ /* resample disable, by hw */
if (!spdifin_check_audiotype_by_sw(p_spdif)) if (!spdifin_check_audiotype_by_sw(p_spdif))
resample_set(p_spdif->asrc_id, 0); resample_set(p_spdif->asrc_id, RATE_OFF);
#endif #endif
#endif #endif
} }
@@ -1075,7 +1075,7 @@ static void aml_dai_spdif_shutdown(
#ifdef __SPDIFIN_AUDIO_TYPE_HW__ #ifdef __SPDIFIN_AUDIO_TYPE_HW__
/* resample disabled, by hw */ /* resample disabled, by hw */
if (!spdifin_check_audiotype_by_sw(p_spdif)) if (!spdifin_check_audiotype_by_sw(p_spdif))
resample_set(p_spdif->asrc_id, 0); resample_set(p_spdif->asrc_id, RATE_OFF);
#endif #endif
clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->clk_spdifin);
clk_disable_unprepare(p_spdif->fixed_clk); clk_disable_unprepare(p_spdif->fixed_clk);