faudio: add I2S samesrc channel mapping to spdif [1/1]

PD#SWPL-6147

Problem:
I2S has 8 channels but spdif only 2.
Need map every single i2s lane to spdif sharebuffer.

Solution:
Add the DTS setting MASKS as former does.

Verify:
Local tested.

Change-Id: If212fc1b9c937a42778682948773874951b8a55a
Signed-off-by: Shuai Li <shuai.li@amlogic.com>

Conflicts:
	sound/soc/amlogic/auge/tdm.c
This commit is contained in:
Shuai Li
2019-03-21 20:20:21 +08:00
committed by Dongjin Kim
parent 4b06ab36f0
commit 8ec1d0bb4e
8 changed files with 112 additions and 23 deletions

View File

@@ -963,6 +963,12 @@
acodec_adc = <1>;
status = "okay";
/* !!!For --TV platform-- ONLY */
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
Spdif_samesource_Channel_Mask = "i2s_2/3";
};
};
tdmb:tdm@1 {

View File

@@ -1268,6 +1268,12 @@
acodec_adc = <1>;
status = "okay";
/* !!!For --TV platform-- ONLY */
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
Spdif_samesource_Channel_Mask = "i2s_2/3";
};
};
tdmb:tdm@1 {

View File

@@ -984,6 +984,12 @@
acodec_adc = <1>;
status = "okay";
/* !!!For --TV platform-- ONLY */
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
Spdif_samesource_Channel_Mask = "i2s_2/3";
};
};
tdmb:tdm@1 {

View File

@@ -24,7 +24,7 @@
#include "spdif_hw.h"
static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream,
struct frddr *fr, int spdif_id)
struct frddr *fr, int spdif_id, int lane_i2s)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int bit_depth;
@@ -36,7 +36,8 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream,
aml_frddr_get_fifo_id(fr),
bit_depth,
runtime->channels,
true);
true,
lane_i2s);
/* spdif to hdmitx */
spdifout_to_hdmitx_ctrl(spdif_id);
@@ -63,7 +64,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream,
aml_frddr_get_fifo_id(fr),
bit_depth,
runtime->channels,
false);
false, 0);
return 0;
}
@@ -82,7 +83,7 @@ void sharebuffer_enable(int sel, bool enable, bool reenable)
}
int sharebuffer_prepare(struct snd_pcm_substream *substream,
void *pfrddr, int samesource_sel)
void *pfrddr, int samesource_sel, int lane_i2s)
{
struct frddr *fr = (struct frddr *)pfrddr;
@@ -95,7 +96,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream,
} else if (samesource_sel < 5) {
/* same source with spdif a/b */
sharebuffer_spdifout_prepare(substream,
fr, samesource_sel - 3);
fr, samesource_sel - 3, lane_i2s);
}
/* frddr, share buffer, src_sel1 */

View File

@@ -18,7 +18,7 @@
#define __AML_AUDIO_SHAREBUFFER_H__
extern int sharebuffer_prepare(struct snd_pcm_substream *substream,
void *pfrddr, int samesource_sel);
void *pfrddr, int samesource_sel, int lane_i2s);
extern int sharebuffer_free(struct snd_pcm_substream *substream,
void *pfrddr, int samesource_sel);
extern int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable);

View File

@@ -420,19 +420,31 @@ static void spdifout_clk_ctrl(int spdif_id, bool is_enable)
}
#endif
static void spdifout_fifo_ctrl(int spdif_id,
int fifo_id, int bitwidth, int channels)
int fifo_id, int bitwidth, int channels, int lane_i2s)
{
unsigned int frddr_type = spdifout_get_frddr_type(bitwidth);
unsigned int offset, reg, i, chmask = 0;
unsigned int swap_masks = 0;
/* spdif always masks two channel */
if (lane_i2s * 2 >= channels) {
pr_err("invalid lane(%d) and channels(%d)\n",
lane_i2s, channels);
return;
}
for (i = 0; i < channels; i++)
chmask |= (1 << i);
pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n",
swap_masks = (2 * lane_i2s) |
(2 * lane_i2s + 1) << 4;
pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits, chmask %#x, swap %#x\n",
(spdif_id == 0) ? "a":"b",
fifo_id,
frddr_type,
bitwidth);
bitwidth,
chmask,
swap_masks);
/* mask lane 0 L/R channels */
offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0;
@@ -449,7 +461,7 @@ static void spdifout_fifo_ctrl(int spdif_id,
offset = EE_AUDIO_SPDIFOUT_B_SWAP - EE_AUDIO_SPDIFOUT_SWAP;
reg = EE_AUDIO_SPDIFOUT_SWAP + offset * spdif_id;
audiobus_write(reg, 1<<4);
audiobus_write(reg, swap_masks);
}
static bool spdifout_is_enable(int spdif_id)
@@ -493,7 +505,7 @@ void spdifout_enable(int spdif_id, bool is_enable, bool reenable)
}
void spdifout_samesource_set(int spdif_index, int fifo_id,
int bitwidth, int channels, bool is_enable)
int bitwidth, int channels, bool is_enable, int lane_i2s)
{
int spdif_id;
@@ -503,7 +515,8 @@ void spdifout_samesource_set(int spdif_index, int fifo_id,
spdif_id = 0;
if (is_enable)
spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels);
spdifout_fifo_ctrl(spdif_id,
fifo_id, bitwidth, channels, lane_i2s);
}
int spdifin_get_sample_rate(void)
@@ -647,7 +660,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable)
/* spdif ctrl */
spdifout_fifo_ctrl(spdif_id,
frddr_index, bitwidth, runtime.channels);
frddr_index, bitwidth, runtime.channels, 0);
/* channel status info */
spdif_get_channel_status_info(&chsts, sample_rate);

View File

@@ -78,7 +78,7 @@ extern void aml_spdifout_get_aed_info(int spdifout_id,
extern void spdifout_to_hdmitx_ctrl(int spdif_index);
extern void spdifout_samesource_set(int spdif_index, int fifo_id,
int bitwidth, int channels, bool is_enable);
int bitwidth, int channels, bool is_enable, int lane_i2s);
extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable);
extern int spdifin_get_sample_rate(void);

View File

@@ -119,12 +119,16 @@ struct aml_tdm {
struct tdm_chipinfo *chipinfo;
/* share buffer with module */
int samesource_sel;
/* share buffer lane setting from DTS */
int lane_ss;
/* virtual link for i2s to hdmitx */
int i2s2hdmitx;
int acodec_adc;
uint last_mpll_freq;
uint last_mclk_freq;
uint last_fmt;
bool en_share;
};
static const struct snd_pcm_hardware aml_tdm_hardware = {
@@ -396,12 +400,11 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
p_tdm->chipinfo->same_src_fn
&& (p_tdm->samesource_sel >= 0)
&& (aml_check_sharebuffer_valid(p_tdm->fddr,
p_tdm->samesource_sel))) {
p_tdm->samesource_sel))
&& p_tdm->en_share) {
sharebuffer_prepare(substream,
fr, p_tdm->samesource_sel);
/* sharebuffer default uses spdif_a */
spdif_set_audio_clk(SPDIF_A, p_tdm->clk,
runtime->rate*128, 1);
fr, p_tdm->samesource_sel,
p_tdm->lane_ss);
}
/* i2s source to hdmix */
@@ -571,7 +574,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
&& p_tdm->chipinfo->same_src_fn
&& (p_tdm->samesource_sel >= 0)
&& (aml_check_sharebuffer_valid(p_tdm->fddr,
p_tdm->samesource_sel))) {
p_tdm->samesource_sel))
&& p_tdm->en_share) {
aml_spdifout_mute_without_actrl(0, false);
}
} else {
@@ -603,7 +607,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
&& p_tdm->chipinfo->same_src_fn
&& (p_tdm->samesource_sel >= 0)
&& (aml_check_sharebuffer_valid(p_tdm->fddr,
p_tdm->samesource_sel))) {
p_tdm->samesource_sel))
&& p_tdm->en_share) {
aml_spdifout_mute_without_actrl(0, true);
}
} else {
@@ -779,7 +784,8 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream,
&& (p_tdm->chipinfo->same_src_fn)
&& (p_tdm->samesource_sel >= 0)
&& (aml_check_sharebuffer_valid(p_tdm->fddr,
p_tdm->samesource_sel))) {
p_tdm->samesource_sel))
&& p_tdm->en_share) {
int mux = 0, ratio = 0;
sharebuffer_get_mclk_fs_ratio(p_tdm->samesource_sel,
@@ -831,7 +837,8 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream,
&& p_tdm->chipinfo->same_src_fn
&& (p_tdm->samesource_sel >= 0)
&& fr
&& (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel))) {
&& (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel))
&& p_tdm->en_share) {
sharebuffer_free(substream,
fr, p_tdm->samesource_sel);
}
@@ -1326,6 +1333,51 @@ static const struct of_device_id aml_tdm_device_id[] = {
};
MODULE_DEVICE_TABLE(of, aml_tdm_device_id);
static int check_channel_mask(const char *str)
{
int ret = -1;
if (!strncmp(str, "i2s_0/1", 7))
ret = 0;
else if (!strncmp(str, "i2s_2/3", 7))
ret = 1;
else if (!strncmp(str, "i2s_4/5", 7))
ret = 2;
else if (!strncmp(str, "i2s_6/7", 7))
ret = 3;
return ret;
}
/* spdif same source with i2s */
static void parse_samesrc_channel_mask(struct aml_tdm *p_tdm)
{
struct device_node *node = p_tdm->dev->of_node;
struct device_node *np = NULL;
const char *str = NULL;
int ret = 0;
/* channel mask */
np = of_get_child_by_name(node, "Channel_Mask");
if (np == NULL) {
pr_info("No channel mask node %s\n",
"Channel_Mask");
return;
}
/* If spdif is same source to i2s,
* it can be muxed to i2s 2 channels
*/
ret = of_property_read_string(np,
"Spdif_samesource_Channel_Mask", &str);
if (ret) {
pr_err("error:read Spdif_samesource_Channel_Mask\n");
return;
}
p_tdm->lane_ss = check_channel_mask(str);
pr_info("Channel_Mask: lane_ss = %d\n", p_tdm->lane_ss);
}
static int aml_tdm_platform_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -1482,8 +1534,13 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
}
p_tdm->dev = dev;
/* For debug to disable share buffer */
p_tdm->en_share = 1;
dev_set_drvdata(dev, p_tdm);
/* spdif same source with i2s */
parse_samesrc_channel_mask(p_tdm);
ret = devm_snd_soc_register_component(dev, &aml_tdm_component,
&aml_tdm_dai[p_tdm->id], 1);
if (ret) {