mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
audio: support 16ch i2s playback for SM1 [1/1]
PD#SWPL-5430 Problem: new function lane 6 and lane 8 Solution: support max 16 channel playback Verify: sm1_ac200, verify pass Change-Id: I3af42a0b68bca8804afa042ad4a506a379b9bf86 Signed-off-by: Zhe Wang <Zhe.Wang@amlogic.com> Conflicts: sound/soc/amlogic/auge/tdm.c
This commit is contained in:
@@ -1101,6 +1101,8 @@
|
||||
#sound-dai-cells = <0>;
|
||||
dai-tdm-lane-slot-mask-in = <0 1 0 0>;
|
||||
dai-tdm-lane-slot-mask-out = <1 0 0 0>;
|
||||
//dai-tdm-lane-slot-mask-in = <0 0 0 0 0 0 0 0>;
|
||||
//dai-tdm-lane-slot-mask-out = <1 1 1 1 1 1 1 1>;
|
||||
dai-tdm-clk-sel = <1>;
|
||||
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
|
||||
&clkc CLKID_MPLL1
|
||||
@@ -1269,11 +1271,21 @@
|
||||
drive-strength = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
tdmout_b: tdmout_b {
|
||||
mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */
|
||||
mux { /* GPIOA_1, GPIOA_2, GPIOA_3, GPIOA_4, */
|
||||
/* GPIOA_5, GPIOA_6, GPIOA_7, GPIOA_8, */
|
||||
/* GPIOA_9, GPIOA_0*/
|
||||
groups = "tdmb_sclk",
|
||||
"tdmb_fs",
|
||||
"tdmb_dout0";
|
||||
//"tdmb_dout1",
|
||||
//"tdmb_dout2",
|
||||
//"tdmb_dout3_a",
|
||||
//"tdmb_dout4_a",
|
||||
//"tdmb_dout5_a",
|
||||
//"tdmb_dout6_a",
|
||||
//"tdmb_dout7_a0";
|
||||
function = "tdmb_out";
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ CLOCK_GATE(audio_reserved5, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31);
|
||||
CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0);
|
||||
CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1);
|
||||
CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2);
|
||||
CLOCK_GATE(audio_earc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6);
|
||||
CLOCK_GATE(audio_earcrx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6);
|
||||
|
||||
static struct clk_gate *sm1_audio_clk_gates[] = {
|
||||
&audio_ddr_arb,
|
||||
@@ -109,7 +109,7 @@ static struct clk_gate *sm1_audio_clk_gates[] = {
|
||||
&audio_frddrd,
|
||||
&audio_toddrd,
|
||||
&audio_loopbackb,
|
||||
&audio_earc,
|
||||
&audio_earcrx,
|
||||
};
|
||||
|
||||
/* Array of all clocks provided by this provider */
|
||||
@@ -150,7 +150,7 @@ static struct clk_hw *sm1_audio_clk_hws[] = {
|
||||
[CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw,
|
||||
[CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw,
|
||||
[CLKID_AUDIO_GATE_EARCRX] = &audio_earc.hw,
|
||||
[CLKID_AUDIO_GATE_EARCRX] = &audio_earcrx.hw,
|
||||
};
|
||||
|
||||
static int sm1_clk_gates_init(struct clk **clks, void __iomem *iobase)
|
||||
|
||||
@@ -123,7 +123,7 @@ static const struct snd_pcm_hardware aml_tdm_hardware = {
|
||||
.period_bytes_max = 256 * 1024 * 2,
|
||||
.periods_min = 2,
|
||||
.periods_max = 1024,
|
||||
.buffer_bytes_max = 512 * 1024 * 2,
|
||||
.buffer_bytes_max = 1024 * 1024,
|
||||
|
||||
.rate_min = 8000,
|
||||
.rate_max = 384000,
|
||||
@@ -592,7 +592,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
aml_tdm_enable(p_tdm->actrl,
|
||||
substream->stream, p_tdm->id, true);
|
||||
udelay(100);
|
||||
aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, false);
|
||||
aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id,
|
||||
false, p_tdm->lane_cnt);
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->same_src_fn
|
||||
&& (p_tdm->samesource_sel >= 0)
|
||||
@@ -625,7 +626,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
0, substream->runtime->dma_bytes);
|
||||
mdelay(3);
|
||||
aml_frddr_enable(p_tdm->fddr, 0);
|
||||
aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, true);
|
||||
aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id,
|
||||
true, p_tdm->lane_cnt);
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->same_src_fn
|
||||
&& (p_tdm->samesource_sel >= 0)
|
||||
@@ -677,32 +679,31 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
unsigned int channels, int stream)
|
||||
{
|
||||
struct pcm_setting *setting = &p_tdm->setting;
|
||||
unsigned int lanes, swap_val;
|
||||
unsigned int lanes, swap_val = 0, swap_val1 = 0;
|
||||
unsigned int lane_mask;
|
||||
unsigned int set_num = 0;
|
||||
unsigned int i;
|
||||
//unsigned int swap0_val = 0, swap1_val = 0, lane_chs = 0;
|
||||
|
||||
pr_debug("asoc channels:%d, slots:%d\n", channels, setting->slots);
|
||||
pr_debug("asoc channels:%d, slots:%d, lane_cnt:%d\n",
|
||||
channels, setting->slots, p_tdm->lane_cnt);
|
||||
|
||||
swap_val = 0;
|
||||
// calc lanes by channels and slots
|
||||
/* calc lanes by channels and slots */
|
||||
lanes = (channels - 1) / setting->slots + 1;
|
||||
if (lanes > 4) {
|
||||
if (lanes > p_tdm->lane_cnt) {
|
||||
pr_err("lanes setting error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
// set lanes mask acordingly
|
||||
/* set lanes mask acordingly */
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->oe_fn
|
||||
&& p_tdm->setting.lane_oe_mask_out)
|
||||
lane_mask = setting->lane_oe_mask_out;
|
||||
else
|
||||
lane_mask = setting->lane_mask_out;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < p_tdm->lane_cnt; i++) {
|
||||
if (((1 << i) & lane_mask) && lanes) {
|
||||
aml_tdm_set_channel_mask(p_tdm->actrl,
|
||||
stream, p_tdm->id, i, setting->tx_mask);
|
||||
@@ -710,8 +711,10 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
}
|
||||
}
|
||||
swap_val = 0x76543210;
|
||||
if (p_tdm->lane_cnt > LANE_MAX1)
|
||||
swap_val1 = 0xfedcba98;
|
||||
aml_tdm_set_lane_channel_swap(p_tdm->actrl,
|
||||
stream, p_tdm->id, swap_val, 0x0);
|
||||
stream, p_tdm->id, swap_val, swap_val1);
|
||||
} else {
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->oe_fn
|
||||
@@ -720,20 +723,31 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
else
|
||||
lane_mask = setting->lane_mask_in;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < p_tdm->lane_cnt; i++) {
|
||||
if (i < lanes)
|
||||
aml_tdm_set_channel_mask(p_tdm->actrl,
|
||||
stream, p_tdm->id, i, setting->rx_mask);
|
||||
if ((1 << i) & lane_mask) {
|
||||
// each lane only L/R masked
|
||||
pr_info("tdmin set lane %d\n", i);
|
||||
swap_val |= (i * 2) << (set_num++ * 4);
|
||||
swap_val |= (i * 2 + 1) << (set_num++ * 4);
|
||||
if (((1 << i) & lane_mask) && (i < LANE_MAX1)) {
|
||||
/* each lane only L/R masked */
|
||||
pr_debug("tdmin set lane %d\n", i);
|
||||
swap_val |= (i * 2) <<
|
||||
(set_num++ * LANE_MAX1);
|
||||
swap_val |= (i * 2 + 1) <<
|
||||
(set_num++ * LANE_MAX1);
|
||||
}
|
||||
if (((1 << i) & lane_mask) && (i >= LANE_MAX1)
|
||||
&& (i < LANE_MAX3)) {
|
||||
/* each lane only L/R masked */
|
||||
pr_debug("tdmin set lane %d\n", i);
|
||||
swap_val1 |= (i * 2) <<
|
||||
(set_num++ * LANE_MAX1);
|
||||
swap_val1 |= (i * 2 + 1) <<
|
||||
(set_num++ * LANE_MAX1);
|
||||
}
|
||||
}
|
||||
|
||||
aml_tdm_set_lane_channel_swap(p_tdm->actrl,
|
||||
stream, p_tdm->id, swap_val, 0x0);
|
||||
stream, p_tdm->id, swap_val, swap_val1);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -1110,6 +1124,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
|
||||
lanes_lb_cnt);
|
||||
pr_debug("\tslots(%d), slot_width(%d)\n",
|
||||
slots, slot_width);
|
||||
|
||||
p_tdm->setting.tx_mask = tx_mask;
|
||||
p_tdm->setting.rx_mask = rx_mask;
|
||||
p_tdm->setting.slots = slots;
|
||||
@@ -1174,11 +1189,11 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
|
||||
in_src = ACODEC_ADC;
|
||||
}
|
||||
|
||||
if (in_lanes >= 0 && in_lanes <= 4)
|
||||
if (in_lanes > 0 && in_lanes <= LANE_MAX3)
|
||||
aml_tdm_set_slot_in(p_tdm->actrl,
|
||||
p_tdm->id, in_src, slot_width);
|
||||
|
||||
if (out_lanes >= 0 && out_lanes <= 4)
|
||||
if (out_lanes > 0 && out_lanes <= LANE_MAX3)
|
||||
aml_tdm_set_slot_out(p_tdm->actrl,
|
||||
p_tdm->id, slots, slot_width,
|
||||
force_oe, oe_val);
|
||||
@@ -1218,11 +1233,14 @@ static int aml_dai_tdm_mute_stream(struct snd_soc_dai *cpu_dai,
|
||||
struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
pr_debug("tdm playback mute: %d\n", mute);
|
||||
//aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute);
|
||||
pr_debug("tdm playback mute: %d, lane_cnt = %d\n",
|
||||
mute, p_tdm->lane_cnt);
|
||||
//aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id,
|
||||
// mute, p_tdm->lane_cnt);
|
||||
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
pr_debug("tdm capture mute: %d\n", mute);
|
||||
aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, mute);
|
||||
aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id,
|
||||
mute, p_tdm->lane_cnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1272,7 +1290,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = {
|
||||
.remove = aml_dai_tdm_remove,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.channels_max = 32,
|
||||
.rates = AML_DAI_TDM_RATES,
|
||||
.formats = AML_DAI_TDM_FORMATS,
|
||||
},
|
||||
@@ -1292,7 +1310,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = {
|
||||
.remove = aml_dai_tdm_remove,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.channels_max = 32,
|
||||
.rates = AML_DAI_TDM_RATES,
|
||||
.formats = AML_DAI_TDM_FORMATS,
|
||||
},
|
||||
@@ -1382,9 +1400,10 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
|
||||
p_tdm->id = p_chipinfo->id;
|
||||
if (!p_chipinfo->lane_cnt)
|
||||
p_chipinfo->lane_cnt = LANE_MAX1;
|
||||
else
|
||||
p_tdm->lane_cnt = p_chipinfo->lane_cnt;
|
||||
pr_info("%s, tdm ID = %u\n", __func__, p_tdm->id);
|
||||
|
||||
p_tdm->lane_cnt = p_chipinfo->lane_cnt;
|
||||
pr_info("%s, tdm ID = %u, lane_cnt = %d\n", __func__,
|
||||
p_tdm->id, p_tdm->lane_cnt);
|
||||
|
||||
/* get audio controller */
|
||||
node_prt = of_get_parent(node);
|
||||
@@ -1487,6 +1506,11 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
p_tdm->setting.lane_lb_mask_in = 0x0;
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"lane_mask_out = %x, lane_oe_mask_out = %x\n",
|
||||
p_tdm->setting.lane_mask_out,
|
||||
p_tdm->setting.lane_oe_mask_out);
|
||||
|
||||
p_tdm->clk = devm_clk_get(&pdev->dev, "clk_srcpll");
|
||||
if (IS_ERR(p_tdm->clk)) {
|
||||
dev_err(&pdev->dev, "Can't retrieve mpll2 clock\n");
|
||||
|
||||
@@ -545,21 +545,27 @@ void aml_tdm_set_channel_mask(
|
||||
unsigned int offset, reg;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (lane >= LANE_MAX1)
|
||||
if (lane >= LANE_MAX1) {
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK4
|
||||
- EE_AUDIO_TDMOUT_A_MASK4;
|
||||
else
|
||||
reg = EE_AUDIO_TDMOUT_A_MASK4 + offset * index;
|
||||
lane -= LANE_MAX1;
|
||||
} else {
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK0
|
||||
- EE_AUDIO_TDMOUT_A_MASK0;
|
||||
reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index;
|
||||
reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index;
|
||||
}
|
||||
} else {
|
||||
if (lane >= LANE_MAX1)
|
||||
if (lane >= LANE_MAX1) {
|
||||
offset = EE_AUDIO_TDMIN_B_MASK4
|
||||
- EE_AUDIO_TDMIN_A_MASK4;
|
||||
else
|
||||
reg = EE_AUDIO_TDMIN_A_MASK4 + offset * index;
|
||||
lane -= LANE_MAX1;
|
||||
} else {
|
||||
offset = EE_AUDIO_TDMIN_B_MASK0
|
||||
- EE_AUDIO_TDMIN_A_MASK0;
|
||||
reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index;
|
||||
reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index;
|
||||
}
|
||||
}
|
||||
|
||||
aml_audiobus_write(actrl, reg + lane, mask);
|
||||
@@ -749,12 +755,13 @@ void i2s_to_hdmitx_disable(void)
|
||||
void aml_tdm_mute_playback(
|
||||
struct aml_audio_controller *actrl,
|
||||
int tdm_index,
|
||||
bool mute)
|
||||
bool mute,
|
||||
int lane_cnt)
|
||||
{
|
||||
unsigned int offset, reg;
|
||||
unsigned int mute_mask = 0xffffffff;
|
||||
unsigned int mute_val = 0;
|
||||
int i = 0, lanes = 4;
|
||||
int i = 0;
|
||||
|
||||
if (mute)
|
||||
mute_val = 0xffffffff;
|
||||
@@ -762,19 +769,29 @@ void aml_tdm_mute_playback(
|
||||
offset = EE_AUDIO_TDMOUT_B_MUTE0
|
||||
- EE_AUDIO_TDMOUT_A_MUTE0;
|
||||
reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index;
|
||||
for (i = 0; i < lanes; i++)
|
||||
for (i = 0; i < LANE_MAX1; i++)
|
||||
aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val);
|
||||
|
||||
if (lane_cnt > LANE_MAX1) {
|
||||
offset = EE_AUDIO_TDMOUT_B_MUTE4
|
||||
- EE_AUDIO_TDMOUT_A_MUTE4;
|
||||
reg = EE_AUDIO_TDMOUT_A_MUTE4 + offset * tdm_index;
|
||||
for (i = 0; i < LANE_MAX1; i++)
|
||||
aml_audiobus_update_bits(actrl, reg + i,
|
||||
mute_mask, mute_val);
|
||||
}
|
||||
}
|
||||
|
||||
void aml_tdm_mute_capture(
|
||||
struct aml_audio_controller *actrl,
|
||||
int tdm_index,
|
||||
bool mute)
|
||||
bool mute,
|
||||
int lane_cnt)
|
||||
{
|
||||
unsigned int offset, reg;
|
||||
unsigned int mute_mask = 0xffffffff;
|
||||
unsigned int mute_val = 0;
|
||||
int i = 0, lanes = 4;
|
||||
int i = 0;
|
||||
|
||||
if (mute)
|
||||
mute_val = 0xffffffff;
|
||||
@@ -782,7 +799,17 @@ void aml_tdm_mute_capture(
|
||||
offset = EE_AUDIO_TDMIN_B_MUTE0
|
||||
- EE_AUDIO_TDMIN_A_MUTE0;
|
||||
reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index;
|
||||
for (i = 0; i < lanes; i++)
|
||||
aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val);
|
||||
for (i = 0; i < LANE_MAX1; i++)
|
||||
aml_audiobus_update_bits(actrl, reg + i,
|
||||
mute_mask, mute_val);
|
||||
|
||||
if (lane_cnt > LANE_MAX1) {
|
||||
offset = EE_AUDIO_TDMIN_B_MUTE4
|
||||
- EE_AUDIO_TDMIN_A_MUTE4;
|
||||
reg = EE_AUDIO_TDMIN_A_MUTE4 + offset * tdm_index;
|
||||
for (i = 0; i < LANE_MAX1; i++)
|
||||
aml_audiobus_update_bits(actrl, reg + i,
|
||||
mute_mask, mute_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +156,11 @@ extern void i2s_to_hdmitx_disable(void);
|
||||
void aml_tdm_mute_playback(
|
||||
struct aml_audio_controller *actrl,
|
||||
int index,
|
||||
bool mute);
|
||||
bool mute,
|
||||
int lane_cnt);
|
||||
void aml_tdm_mute_capture(
|
||||
struct aml_audio_controller *actrl,
|
||||
int tdm_index,
|
||||
bool mute);
|
||||
bool mute,
|
||||
int lane_cnt);
|
||||
#endif
|
||||
|
||||
@@ -728,7 +728,7 @@ static struct snd_soc_dai_driver ad82584f_dai = {
|
||||
.playback = {
|
||||
.stream_name = "HIFI Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.channels_max = 16,
|
||||
.rates = AD82584F_RATES,
|
||||
.formats = AD82584F_FORMATS,
|
||||
},
|
||||
|
||||
@@ -480,7 +480,7 @@ struct snd_soc_dai_driver aml_T9015_audio_dai[] = {
|
||||
.playback = {
|
||||
.stream_name = "HIFI Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.channels_max = 16,
|
||||
.rates = T9015_AUDIO_STEREO_RATES,
|
||||
.formats = T9015_AUDIO_FORMATS,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user