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 {
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 {
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 {
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 {
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 {
#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;
aml_frddr_get_fifo_id(fr),
bit_depth,
runtime->channels,
- true);
+ true,
+ lane_i2s);
/* spdif to hdmitx */
spdifout_to_hdmitx_ctrl(spdif_id);
aml_frddr_get_fifo_id(fr),
bit_depth,
runtime->channels,
- false);
+ false, 0);
return 0;
}
}
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;
} 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 */
#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);
}
#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;
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)
}
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;
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)
/* 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);
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);
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 = {
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);
+ fr, p_tdm->samesource_sel,
+ p_tdm->lane_ss);
}
/* i2s source to hdmix */
&& (p_tdm->samesource_sel >= 0)
&& (aml_check_sharebuffer_valid(p_tdm->fddr,
p_tdm->samesource_sel))
- )
+ && p_tdm->en_share)
sharebuffer_trigger(cmd,
p_tdm->samesource_sel,
p_tdm->chipinfo->same_src_spdif_reen);
&& 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 {
&& 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 {
&& (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,
&& 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);
}
};
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;
}
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) {