mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user