interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
status = "okay";
};
aml_pdm: pdm {
* TDMIN_LB,
* LOOPBACK,
*/
- resample_module = <4>;
+ resample_module = <3>;
status = "okay";
};
aml_pwrdet: pwrdet {
hi_th = <0x70000>;
lo_th = <0x16000>;
- status = "okay";
+ status = "disabled";
};
}; /* end of audiobus */
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, axg-power-detect";
+
+ interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, axg-power-detect";
+
+ interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, axg-power-detect";
+
+ interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, axg-power-detect";
+
+ interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
};
};
- /*aml-audio-card,dai-link@4 {
- * mclk-fs = <128>;
- * cpu {
- * sound-dai = <&aml_spdif>;
- * };
- * codec {
- * sound-dai = <&dummy_codec>;
- * };
- *};
- */
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ cpu {
+ sound-dai = <&aml_spdif>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
};
bt-dev{
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
- status = "disabled";
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
+ status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
};
};
- /*aml-audio-card,dai-link@4 {
- * mclk-fs = <128>;
- * cpu {
- * sound-dai = <&aml_spdif>;
- * };
- * codec {
- * sound-dai = <&dummy_codec>;
- * };
- *};
- */
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ cpu {
+ sound-dai = <&aml_spdif>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
};
bt-dev{
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
- status = "disabled";
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
+ status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
};
};
- /*aml-audio-card,dai-link@4 {
- * mclk-fs = <128>;
- * cpu {
- * sound-dai = <&aml_spdif>;
- * };
- * codec {
- * sound-dai = <&dummy_codec>;
- * };
- *};
- */
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ cpu {
+ sound-dai = <&aml_spdif>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
};
bt-dev{
interrupt-names = "irq_spdifin";
pinctrl-names = "spdif_pins";
pinctrl-0 = <&spdifout &spdifin>;
- status = "disabled";
+
+ /*
+ * whether do asrc for pcm.
+ * if raw data, asrc is disabled automatically
+ * 0: "Disable",
+ * 1: "Enable:32K",
+ * 2: "Enable:44K",
+ * 3: "Enable:48K",
+ * 4: "Enable:88K",
+ * 5: "Enable:96K",
+ * 6: "Enable:176K",
+ * 7: "Enable:192K",
+ */
+ auto_asrc = <0>;
+ status = "okay";
};
aml_pdm: pdm {
status = "okay";
};
+
+ audioresample: resample {
+ compatible = "amlogic, axg-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A,
+ * TDMIN_B,
+ * TDMIN_C,
+ * SPDIFIN,
+ * PDMIN,
+ * NONE,
+ * TDMIN_LB,
+ * LOOPBACK,
+ */
+ resample_module = <3>;
+ status = "okay";
+ };
}; /* end of audiobus */
&pinctrl_periphs {
aml_priv_to_props(priv, rtd->num);
unsigned int mclk = 0, mclk_fs = 0;
int i = 0, ret = 0;
+ int clk_dir = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ clk_dir = SND_SOC_CLOCK_OUT;
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ clk_dir = SND_SOC_CLOCK_IN;
if (priv->mclk_fs)
mclk_fs = priv->mclk_fs;
for (i = 0; i < rtd->num_codecs; i++) {
codec_dai = rtd->codec_dais[i];
-
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ clk_dir);
if (ret && ret != -ENOTSUPP)
goto err;
}
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
- SND_SOC_CLOCK_OUT);
+ clk_dir);
if (ret && ret != -ENOTSUPP)
goto err;
unsigned int msb_bit;
unsigned int lsb_bit;
unsigned int reg_base;
- unsigned int channels;
unsigned int bitdepth;
+ unsigned int channels;
+ unsigned int rate;
enum toddr_src src;
unsigned int fifo_id;
/* resample */
static struct toddr_attach attach_resample;
static void aml_check_resample(bool enable);
+static bool aml_check_resample_module(int src);
/* power detect */
static struct toddr_attach attach_pwrdet;
static void aml_check_pwrdet(bool enable);
+static bool aml_check_pwrdet_module(int src);
/* Audio EQ DRC */
static struct frddr_attach attach_aed;
static void aml_check_aed(bool enable, int dst);
+static bool aml_check_aed_module(int dst);
/* to DDRS */
static struct toddr *register_toddr_l(struct device *dev,
aml_audiobus_update_bits(actrl, reg, 1<<31, enable<<31);
/* check resample */
- aml_check_resample(enable);
+ if (aml_check_resample_module(to->src))
+ aml_check_resample(enable);
/* check power detect */
- aml_check_pwrdet(enable);
+ if (aml_check_pwrdet_module(to->src))
+ aml_check_pwrdet(enable);
+
+ if (!enable)
+ aml_audiobus_write(actrl, reg, 0x0);
}
void aml_toddr_select_src(struct toddr *to, enum toddr_src src)
aml_audiobus_write(actrl, reg, (thresh-1)<<16|2<<8);
}
-void aml_toddr_set_format(struct toddr *to,
- unsigned int type, unsigned int msb, unsigned int lsb,
- int ch_num, int bit_depth)
+void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
- to->channels = ch_num;
- to->bitdepth = bit_depth;
+ to->bitdepth = fmt->bit_depth;
+ to->channels = fmt->ch_num;
+ to->rate = fmt->rate;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
- aml_audiobus_update_bits(actrl, reg, 0x1fff<<3,
- type<<13|msb<<8|lsb<<3);
+ aml_audiobus_update_bits(actrl, reg,
+ 0x7 << 24 | 0x1fff << 3,
+ fmt->endian << 24 | fmt->type << 13 |
+ fmt->msb << 8 | fmt->lsb << 3);
}
-static void aml_set_resample(struct toddr *to,
- bool enable)
+void aml_toddr_insert_chanum(struct toddr *to)
+{
+ struct aml_audio_controller *actrl = to->actrl;
+ unsigned int reg_base = to->reg_base;
+ unsigned int reg;
+
+ reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
+ aml_audiobus_update_bits(actrl, reg, 1 << 24, 1 << 24);
+}
+
+unsigned int aml_toddr_read(struct toddr *to)
+{
+ struct aml_audio_controller *actrl = to->actrl;
+ unsigned int reg_base = to->reg_base;
+ unsigned int reg;
+
+ reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
+
+ return aml_audiobus_read(actrl, reg);
+}
+
+void aml_toddr_write(struct toddr *to, unsigned int val)
+{
+ struct aml_audio_controller *actrl = to->actrl;
+ unsigned int reg_base = to->reg_base;
+ unsigned int reg;
+
+ reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
+
+ aml_audiobus_write(actrl, reg, val);
+}
+
+void aml_toddr_set_resample(struct toddr *to, bool enable)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
+ pr_info("toddr selects data to %s resample\n",
+ enable ? "enable" : "disable");
+ reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
+ aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30);
+}
+
+static void aml_set_resample(struct toddr *to,
+ bool enable)
+{
if (enable) {
+ int bitwidth = to->bitdepth;
/* channels and bit depth for resample */
- resample_format_set(to->channels, to->bitdepth);
+ if ((to->src == SPDIFIN) && (bitwidth == 32)) {
+ struct aml_audio_controller *actrl = to->actrl;
+ unsigned int reg_base = to->reg_base;
+ unsigned int reg;
+ unsigned int endian, toddr_type;
+
+ /* TODO: fixed me */
+ pr_info("Warning: Not support 32bit sample rate for axg chipset\n");
+ bitwidth = 24;
+ endian = 5;
+ toddr_type = 4;
+
+ /* FIX ME */
+ reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0,
+ reg_base);
+ aml_audiobus_update_bits(actrl, reg,
+ 0x7 << 24 | 0x7 << 13,
+ endian << 24 | toddr_type << 13);
+ }
+ resample_format_set(to->channels, bitwidth);
/* toddr index for resample */
resample_src_select(to->fifo_id);
}
/* resample enable or not */
- reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
- aml_audiobus_update_bits(actrl, reg, 0x1 << 30, enable << 30);
+ resample_enable(enable);
+ /* select reample data */
+ aml_toddr_set_resample(to, enable);
}
void aml_resample_enable(bool enable, int resample_module)
{
- /* when try to enable resample, if toddr is not in used,
- * set resample status as ready
- */
attach_resample.enable = enable;
attach_resample.attach_module = resample_module;
- if (enable) {
- if ((attach_resample.status == DISABLED)
- || (attach_resample.status == READY)) {
- struct toddr *to = fetch_toddr_by_src(resample_module);
- if (!to) {
- attach_resample.status = READY;
- pr_info("not in capture, resample is ready");
- } else {
- attach_resample.status = RUNNING;
- aml_set_resample(to, enable);
- }
- }
- } else {
- if (attach_resample.status == RUNNING) {
- struct toddr *to = fetch_toddr_by_src(resample_module);
+ aml_check_resample(enable);
+}
- aml_set_resample(to, enable);
- }
- attach_resample.status = DISABLED;
- }
+static bool aml_check_resample_module(int src)
+{
+ bool is_module_resample = false;
+
+ if (attach_resample.enable
+ && (src == attach_resample.attach_module))
+ is_module_resample = true;
+
+ return is_module_resample;
}
+/*
+ * when try to enable resample, if toddr is not in used,
+ * set resample status as ready
+ */
static void aml_check_resample(bool enable)
{
/* resample in enable */
if (attach_resample.enable) {
if (enable) {
/* check whether ready ? */
- if (attach_resample.status == READY)
- aml_resample_enable(true,
+ if ((attach_resample.status == DISABLED)
+ || (attach_resample.status == READY)) {
+ struct toddr *to = fetch_toddr_by_src(
attach_resample.attach_module);
+
+ if (!to) {
+ attach_resample.status = READY;
+ pr_info("not in capture, Resample is ready\n");
+ } else {
+ attach_resample.status = RUNNING;
+ aml_set_resample(to, enable);
+ pr_info("Resample in running, module:%d, toddr:%d\n",
+ attach_resample.attach_module,
+ to->fifo_id);
+ }
+ }
} else {
- if (attach_resample.status == RUNNING)
- attach_resample.status = READY;
+ if (attach_resample.status == RUNNING) {
+ struct toddr *to = fetch_toddr_by_src(
+ attach_resample.attach_module);
+
+ aml_set_resample(to, enable);
+ attach_resample.status = DISABLED;
+ }
+ }
+ } else {
+ /* ensure resample is disabled */
+ struct toddr *to = fetch_toddr_by_src(
+ attach_resample.attach_module);
+
+ if (to) {
+ pr_info("Resample in running, disable it\n");
+
+ /* select reample data */
+ aml_toddr_set_resample(to, false);
+ /* update resample status */
+ attach_resample.status = DISABLED;
}
}
}
if (!to) {
attach_pwrdet.status = READY;
- pr_info("not in capture, power detect is ready");
+ pr_info("not in capture, power detect is ready\n");
} else {
attach_pwrdet.status = RUNNING;
aml_set_pwrdet(to, enable);
}
}
+static bool aml_check_pwrdet_module(int src)
+{
+ bool is_module_pwrdet = false;
+
+ if (attach_pwrdet.enable
+ && (src == attach_pwrdet.attach_module))
+ is_module_pwrdet = true;
+
+ return is_module_pwrdet;
+}
+
static void aml_check_pwrdet(bool enable)
{
/* power detect in enable */
aml_audiobus_write(actrl, reg, 0x0);
/* check for Audio EQ/DRC */
- aml_check_aed(enable, fr->dest);
+ if (aml_check_aed_module(fr->dest))
+ aml_check_aed(enable, fr->dest);
}
void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst)
}
}
+static bool aml_check_aed_module(int dst)
+{
+ bool is_module_aed = false;
+
+ if (attach_aed.enable
+ && (dst == attach_aed.attach_module))
+ is_module_aed = true;
+
+ return is_module_aed;
+}
+
static void aml_check_aed(bool enable, int dst)
{
/* check effect module is sync with crruent frddr dst */
SPDIFOUT_B,
};
+struct toddr_fmt {
+ unsigned int type;
+ unsigned int msb;
+ unsigned int lsb;
+ unsigned int endian;
+ unsigned int bit_depth;
+ unsigned int ch_num;
+ unsigned int rate;
+};
+
/* to ddrs */
int fetch_toddr_index_by_src(int toddr_src);
struct toddr *fetch_toddr_by_src(int toddr_src);
void aml_toddr_select_src(struct toddr *to, enum toddr_src);
void aml_toddr_enable(struct toddr *to, bool enable);
void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh);
-void aml_toddr_set_format(struct toddr *to,
- unsigned int type, unsigned int msb, unsigned int lsb,
- int ch_num, int bit_depth);
+void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt);
+void aml_toddr_insert_chanum(struct toddr *to);
+unsigned int aml_toddr_read(struct toddr *to);
+void aml_toddr_write(struct toddr *to, unsigned int val);
/* resample */
void aml_resample_enable(bool enable, int resample_module);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct toddr *to = p_pdm->tddr;
+ struct toddr_fmt fmt;
unsigned int osr = 192;
/* to ddr pdmin */
+ fmt.type = toddr_type;
+ fmt.msb = 31;
+ fmt.lsb = lsb;
+ fmt.endian = 0;
+ fmt.bit_depth = bitwidth;
+ fmt.ch_num = runtime->channels;
+ fmt.rate = runtime->rate;
aml_toddr_select_src(to, PDMIN);
- aml_toddr_set_format(to, toddr_type, 31, lsb,
- runtime->channels,
- bitwidth);
+ aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
aml_pdm_ctrl(p_pdm->actrl,
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "resample.h"
#include "resample_hw.h"
#include "ddr_mngr.h"
+#include "regs.h"
+#include "iomap.h"
#define DRV_NAME "audioresample"
+#define CLK_RATIO 256
+
struct resample_chipinfo {
bool dividor_fn;
};
/* resample to the rate */
int out_rate;
+ /* sync with auge_resample_texts */
+ int asr_idx;
+
bool enable;
};
if (p_resample->enable) {
ret = clk_prepare_enable(p_resample->clk);
if (ret) {
- pr_err("Can't enable resample_clk clock: %d\n", ret);
+ pr_err("Can't enable resample_clk clock: %d\n",
+ ret);
return -EINVAL;
}
+
ret = clk_prepare_enable(p_resample->sclk);
if (ret) {
- pr_err("Can't enable resample_src clock: %d\n", ret);
+ pr_err("Can't enable resample_src clock: %d\n",
+ ret);
return -EINVAL;
}
+
if (p_resample->out_rate) {
+ clk_set_rate(p_resample->pll,
+ p_resample->out_rate * CLK_RATIO * 2);
clk_set_rate(p_resample->sclk,
- p_resample->out_rate * 256);
+ p_resample->out_rate * CLK_RATIO);
clk_set_rate(p_resample->clk,
- p_resample->out_rate * 256);
+ p_resample->out_rate * CLK_RATIO);
} else {
/* defaule resample clk */
- clk_set_rate(p_resample->sclk, 48000 * 256);
- clk_set_rate(p_resample->clk, 48000 * 256);
+ clk_set_rate(p_resample->pll, 48000 * CLK_RATIO * 2);
+ clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO);
+ clk_set_rate(p_resample->clk, 48000 * CLK_RATIO);
}
ret = clk_prepare_enable(p_resample->pll);
static void audio_resample_init(struct audioresample *p_resample)
{
+ resample_clk_set(p_resample);
+
aml_resample_enable(p_resample->enable,
p_resample->resample_module);
-
- resample_clk_set(p_resample);
}
static int audio_resample_set(int enable, int rate)
return 0;
}
-static int auge_resample;
-
static const char *const auge_resample_texts[] = {
"Disable",
"Enable:32K",
"Enable:192K",
};
+static int resample_idx2rate(int index)
+{
+ int rate = 0;
+
+ if (index == 0)
+ rate = 0;
+ else if (index == 1)
+ rate = 32000;
+ else if (index == 2)
+ rate = 44100;
+ else if (index == 3)
+ rate = 48000;
+ else if (index == 4)
+ rate = 88200;
+ else if (index == 5)
+ rate = 96000;
+ else if (index == 6)
+ rate = 176400;
+ else if (index == 7)
+ rate = 192000;
+
+ return rate;
+}
+
static const struct soc_enum auge_resample_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(auge_resample_texts),
auge_resample_texts);
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- ucontrol->value.enumerated.item[0] = auge_resample;
+ struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = p_resample->asr_idx;
return 0;
}
-static int resample_set_enum(
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+int resample_set(int index)
{
-/* struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
- * struct aml_audio_private_data *p_aml_audio =
- * snd_soc_card_get_drvdata(card);
- * struct aml_card_info *p_cardinfo = p_aml_audio->cardinfo;
- */
- int index = ucontrol->value.enumerated.item[0];
- int resample_rate = 0;
+ int resample_rate = resample_idx2rate(index);
- if (index == 0)
- resample_rate = 0;
- else if (index == 1)
- resample_rate = 32000;
- else if (index == 2)
- resample_rate = 44100;
- else if (index == 3)
- resample_rate = 48000;
- else if (index == 4)
- resample_rate = 88200;
- else if (index == 5)
- resample_rate = 96000;
- else if (index == 6)
- resample_rate = 176400;
- else if (index == 7)
- resample_rate = 192000;
- else
+ if (index == s_resample->asr_idx)
return 0;
- auge_resample = index;
+ s_resample->asr_idx = index;
+
+ pr_info("%s %s\n",
+ __func__,
+ auge_resample_texts[index]);
if (audio_resample_set(index, resample_rate))
return 0;
- if (index == 0)
+ if ((index == 0) || (resample_rate == 0))
resample_disable();
else {
- resample_enable(resample_rate);
- // TODO: fixe me
+ resample_init(resample_rate);
+
resample_set_hw_param(index - 1);
}
-/*
- * if (index > 0
- * && p_aml_audio
- * && p_cardinfo)
- * p_cardinfo->set_resample_param(index - 1);
- */
+
+ return 0;
+}
+
+static int resample_set_enum(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int index = ucontrol->value.enumerated.item[0];
+
+ resample_set(index);
return 0;
}
return 0;
}
-static const struct snd_kcontrol_new snd_resample_controls[] = {
+/* resample module
+ * keep sync with enum toddr_src in ddr_mngr.h
+ */
+static const char *const auge_resample_module_texts[] = {
+ "TDMIN_A",
+ "TDMIN_B",
+ "TDMIN_C",
+ "SPDIFIN",
+ "PDMIN",
+ "NONE",
+ "TDMIN_LB",
+ "LOOPBACK",
+};
+
+static const struct soc_enum auge_resample_module_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(auge_resample_module_texts),
+ auge_resample_module_texts);
+
+static int resample_module_get_enum(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
+
+ if (!p_resample) {
+ pr_err("audio resample is not init\n");
+ return -EINVAL;
+ }
+
+ ucontrol->value.enumerated.item[0] = p_resample->resample_module;
+
+ return 0;
+}
+
+static int resample_module_set_enum(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
+
+ if (!p_resample) {
+ pr_err("audio resample is not init\n");
+ return -EINVAL;
+ }
- /* resample */
+ p_resample->resample_module = ucontrol->value.enumerated.item[0];
+
+ /* update info to ddr */
+ aml_resample_enable(p_resample->enable,
+ p_resample->resample_module);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new snd_resample_controls[] = {
SOC_ENUM_EXT("Hardware resample enable",
auge_resample_enum,
resample_get_enum,
EE_AUDIO_RESAMPLE_CTRL2, 0, 0xffffff, 0,
mixer_audiobus_read, mixer_audiobus_write,
NULL),
+ SOC_ENUM_EXT("Hardware resample module",
+ auge_resample_module_enum,
+ resample_module_get_enum,
+ resample_module_set_enum),
};
int card_add_resample_kcontrols(struct snd_soc_card *card)
{
- return snd_soc_add_card_controls(card,
- snd_resample_controls, ARRAY_SIZE(snd_resample_controls));
+ unsigned int idx;
+ int err;
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_resample_controls); idx++) {
+ err = snd_ctl_add(card->snd_card,
+ snd_ctl_new1(&snd_resample_controls[idx],
+ s_resample));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
}
static struct resample_chipinfo g12a_resample_chipinfo = {
extern int card_add_resample_kcontrols(struct snd_soc_card *card);
+extern int resample_set(int index);
#endif
* more details.
*
*/
+#include <linux/clk.h>
#include "resample_hw.h"
+#include "regs.h"
+#include "iomap.h"
/*Cnt_ctrl = mclk/fs_out-1 ; fest 256fs */
#define RESAMPLE_CNT_CONTROL 255
{0x00800000, 0x0, 0x0, 0x0, 0x0},
};
-int resample_enable(int input_sr)
+void resample_enable(bool enable)
+{
+ audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
+ 0x1 << 31,
+ 1 << 31);
+
+ audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
+ 0x1 << 31,
+ 0 << 31);
+
+ audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
+ 0x1 << 28,
+ enable << 28);
+}
+
+int resample_init(int input_sr)
{
u16 Avg_cnt_init = 0;
unsigned int clk_rate = 167000000;//clk81;
- Avg_cnt_init = (u16)(clk_rate * 4 / input_sr);
+ if (input_sr)
+ Avg_cnt_init = (u16)(clk_rate * 4 / input_sr);
+ else
+ pr_err("unsupport input sample rate:%d\n", input_sr);
+
pr_info("clk_rate = %u, input_sr = %d, Avg_cnt_init = %u\n",
clk_rate, input_sr, Avg_cnt_init);
- audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, (1 << 31));
- audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, 0);
- audiobus_write(EE_AUDIO_RESAMPLE_CTRL0,
- (1 << 28) /* enable */
- | (0 << 26) /* method0 */
- | (RESAMPLE_CNT_CONTROL << 16)
- | Avg_cnt_init);
+ audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
+ 0x3 << 26 | 0x3ff << 16 | 0xffff << 0,
+ 0x0 << 26 | /* method0 */
+ RESAMPLE_CNT_CONTROL << 16 |
+ Avg_cnt_init << 0);
return 0;
}
audiobus_write(EE_AUDIO_RESAMPLE_CTRL3,
ch_num << 8 | (bits - 1) << 0);
}
+
+int resample_ctrl_read(int idx)
+{
+ return audiobus_read(EE_AUDIO_RESAMPLE_CTRL0);
+}
+
+void resample_ctrl_write(int idx, int value)
+{
+ audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, value);
+}
*/
#ifndef __AML_AUDIO_RESAMPLE_HW_H__
#define __AML_AUDIO_RESAMPLE_HW_H__
-#include <linux/clk.h>
-#include "regs.h"
-#include "iomap.h"
-
-extern int resample_enable(int input_sr);
+extern void resample_enable(bool enable);
+extern int resample_init(int input_sr);
extern int resample_disable(void);
extern int resample_set_hw_param(int index);
extern void resample_src_select(int src);
extern void resample_format_set(int ch_num, int bits);
+extern int resample_ctrl_read(int idx);
+extern void resample_ctrl_write(int idx, int value);
+
#endif
#include "ddr_mngr.h"
#include "spdif_hw.h"
#include "audio_utils.h"
+#include "resample.h"
+#include "resample_hw.h"
#define DRV_NAME "aml_spdif"
/* Debug by PTM when bringup */
/* #define G12A_PTM */
+/* for debug */
+/*#define __SPDIFIN_INSERT_CHNUM__*/
+
struct spdif_chipinfo {
unsigned int id;
/* add ch_cnt to ch_num */
bool chnum_en;
- /* Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; */
- bool clr_irq_bits;
- /* find PaPb */
- bool irq_papb;
+ /*
+ * axg, clear all irq bits
+ * after axg, such as g12a, clear each bits
+ * Reg_clr_interrupt[7:0] for each bit of irq_status[7:0];
+ */
+ bool clr_irq_all_bits;
+ /* no PaPb irq */
+ bool irq_no_papb;
/* reg_hold_start_en; 1: add delay to match TDM out when share buff; */
bool hold_start;
/* eq/drc */
unsigned int id;
struct spdif_chipinfo *chipinfo;
unsigned int clk_cont; /* CONTINUOUS CLOCK */
+
+ /* spdif in do asrc for pcm,
+ * if raw data, disable it automatically.
+ */
+ unsigned int auto_asrc;
+ /* check spdifin channel status for pcm or nonpcm */
+ struct timer_list timer;
+ struct work_struct work;
+
+ /* spdif in reset for l/r channel swap when plug/unplug */
+ struct timer_list reset_timer;
+ /* timer is used */
+ int is_reset_timer_used;
+ /* reset timer counter */
+ int timer_counter;
+ /* 0: default, 1: spdif in firstly enable, 2: spdif in could be reset */
+ int sample_rate_detect_start;
+ /* is spdif in reset */
+ int is_reset;
+ int last_sample_rate_mode;
+
};
static const struct snd_pcm_hardware aml_spdif_hardware = {
.buffer_bytes_max = 256 * 1024,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
.channels_min = 2,
.channels_max = 32,
};
};
/* current sample mode and its sample rate */
-int sample_mode[] = {
- 24000,
- 32000,
- 44100,
- 46000,
- 48000,
- 96000,
- 192000,
-};
-
static const char *const spdifin_samplerate[] = {
"N/A",
- "24000",
"32000",
"44100",
- "46000",
"48000",
+ "88200",
"96000",
+ "176400",
"192000"
};
{6, 0x003, "PAUSE"},
{6, 0x100, "PAUSE"},
};
+
static const struct soc_enum spdif_audio_type_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts),
spdif_audio_type_texts);
-static int spdifin_audio_type_get_enum(
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int spdifin_check_audio_type(void)
{
- int audio_type = 0;
- int i;
int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info);
int pc = spdifin_get_audio_type();
+ int audio_type = 0;
+ int i;
for (i = 0; i < total_num; i++) {
if (pc == type_texts[i].pc) {
break;
}
}
- ucontrol->value.enumerated.item[0] = audio_type;
+
+ pr_info("%s audio type:%d\n", __func__, audio_type);
+
+ return audio_type;
+}
+
+static int spdifin_audio_type_get_enum(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] =
+ spdifin_check_audio_type();
return 0;
}
NULL),
};
+static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif)
+{
+ if (p_spdif
+ && p_spdif->chipinfo
+ && p_spdif->chipinfo->irq_no_papb)
+ return true;
+
+ return false;
+}
+
+static void spdifin_audio_type_start_timer(
+ struct aml_spdif *p_spdif)
+{
+ p_spdif->timer.expires = jiffies + 1;
+ add_timer(&p_spdif->timer);
+}
+
+static void spdifin_audio_type_stop_timer(
+ struct aml_spdif *p_spdif)
+{
+ del_timer(&p_spdif->timer);
+}
+
+static void spdifin_audio_type_timer_func(unsigned long data)
+{
+ struct aml_spdif *p_spdif = (struct aml_spdif *)data;
+ unsigned long delay = msecs_to_jiffies(1);
+
+ schedule_work(&p_spdif->work);
+ mod_timer(&p_spdif->timer, jiffies + delay);
+}
+
+static void spdifin_audio_type_work_func(struct work_struct *work)
+{
+ struct aml_spdif *p_spdif = container_of(
+ work, struct aml_spdif, work);
+
+ int val = spdifin_get_ch_status0to31();
+
+ /* auto resample ? */
+ if (!p_spdif->auto_asrc)
+ return;
+
+ if (val & 0x2)
+ /* nonpcm, resample disable */
+ resample_set(0);
+ else
+ /* pcm, resample which rate ? */
+ resample_set(p_spdif->auto_asrc);
+}
+
+static void spdifin_audio_type_detect_init(struct aml_spdif *p_spdif)
+{
+ init_timer(&p_spdif->timer);
+ p_spdif->timer.function = spdifin_audio_type_timer_func;
+ p_spdif->timer.data = (unsigned long)p_spdif;
+
+ INIT_WORK(&p_spdif->work, spdifin_audio_type_work_func);
+}
+
+static void spdifin_audio_type_detect_deinit(struct aml_spdif *p_spdif)
+{
+ cancel_work_sync(&p_spdif->work);
+}
+
+static void spdifin_fast_reset(struct aml_spdif *p_spdif)
+{
+ struct aml_audio_controller *actrl = p_spdif->actrl;
+ unsigned int tddr_val = aml_toddr_read(p_spdif->tddr);
+ unsigned int spdifin_ctrl_val = aml_spdif_ctrl_read(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id);
+ unsigned int asr_ctrl_val = 0;
+
+ pr_info("%s\n", __func__);
+
+ /* toddr disable */
+ tddr_val &= ~(1 << 31);
+ aml_toddr_write(p_spdif->tddr, tddr_val);
+
+ /* resample disable and reset */
+ if (p_spdif->auto_asrc) {
+ asr_ctrl_val = resample_ctrl_read(0);
+ asr_ctrl_val &= ~(1 << 28);
+ resample_ctrl_write(0, asr_ctrl_val);
+ asr_ctrl_val |= (1 << 31);
+ resample_ctrl_write(0, asr_ctrl_val);
+ asr_ctrl_val &= ~(1 << 31);
+ resample_ctrl_write(0, asr_ctrl_val);
+ }
+
+ /* spdif in disable and reset */
+ spdifin_ctrl_val &= ~(0x1 << 31);
+ aml_spdif_ctrl_write(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
+ spdifin_ctrl_val &= ~(0x3 << 28);
+ aml_spdif_ctrl_write(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
+ spdifin_ctrl_val |= (0x1 << 29);
+ aml_spdif_ctrl_write(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
+ spdifin_ctrl_val |= (0x1 << 28);
+ aml_spdif_ctrl_write(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
+
+ /* toddr enable */
+ tddr_val |= (1 << 31);
+ aml_toddr_write(p_spdif->tddr, tddr_val);
+
+ /* resample enable */
+ if (p_spdif->auto_asrc) {
+ asr_ctrl_val |= (1 << 28);
+ resample_ctrl_write(0, asr_ctrl_val);
+ }
+
+ /* spdif in enable */
+ spdifin_ctrl_val |= (0x1 << 31);
+ aml_spdif_ctrl_write(actrl,
+ SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
+}
+
+#define MAX_TIMER_COUNTER 30
+#define FIRST_DELAY 20
+
+static void spdifin_reset_timer(unsigned long data)
+{
+ struct aml_spdif *p_spdif = (struct aml_spdif *)data;
+ unsigned long delay = msecs_to_jiffies(1);
+ int intrpt_status = aml_spdifin_status_check(p_spdif->actrl);
+ int mode = (intrpt_status >> 28) & 0x7;
+
+ if ((p_spdif->last_sample_rate_mode != mode) ||
+ (p_spdif->last_sample_rate_mode == 0x7)) {
+
+ p_spdif->last_sample_rate_mode = mode;
+ p_spdif->timer_counter = 0;
+ mod_timer(&p_spdif->reset_timer, jiffies + delay);
+ } else if ((p_spdif->last_sample_rate_mode == mode) &&
+ (mode != 0x7)) {
+
+ if (p_spdif->timer_counter > MAX_TIMER_COUNTER) {
+ p_spdif->timer_counter = 0;
+
+ if (p_spdif->is_reset ||
+ (p_spdif->sample_rate_detect_start == 1)) {
+ p_spdif->is_reset = 0;
+ p_spdif->sample_rate_detect_start = 2;
+ if (p_spdif->is_reset_timer_used) {
+ p_spdif->is_reset_timer_used = 0;
+ del_timer(&p_spdif->reset_timer);
+ }
+ pr_debug("%s,last sample mode:0x%x, stop timer\n",
+ __func__,
+ p_spdif->last_sample_rate_mode);
+ } else {
+ p_spdif->last_sample_rate_mode = 0;
+
+ p_spdif->is_reset = 1;
+ spdifin_fast_reset(p_spdif);
+
+ delay = msecs_to_jiffies(FIRST_DELAY);
+ mod_timer(&p_spdif->reset_timer,
+ jiffies + delay);
+ }
+ } else {
+ p_spdif->timer_counter++;
+ mod_timer(&p_spdif->reset_timer, jiffies + delay);
+ }
+ }
+}
+
static void spdifin_status_event(struct aml_spdif *p_spdif)
{
int intrpt_status;
- if (p_spdif == NULL)
+ if (!p_spdif)
return;
- /*
- * interrupt status, check and clear by reg_clk_interrupt;
- */
+ /* interrupt status, check and clear by reg_clk_interrupt */
intrpt_status = aml_spdifin_status_check(p_spdif->actrl);
+ /* clear irq bits immediametely */
+ if (p_spdif->chipinfo)
+ aml_spdifin_clr_irq(p_spdif->actrl,
+ p_spdif->chipinfo->clr_irq_all_bits,
+ intrpt_status & 0xff);
+
if (intrpt_status & 0x1)
- pr_warn_once("over flow!!\n");
+ pr_info("over flow!!\n");
if (intrpt_status & 0x2)
- pr_warn_once("parity error\n");
+ pr_info("parity error\n");
if (intrpt_status & 0x4) {
int mode = (intrpt_status >> 28) & 0x7;
- pr_warn_once("sample mode changed\n");
- if (mode == 0x7) {
- pr_debug("Default value, not detect sample rate\n");
+ pr_debug("sample rate, mode:%x\n", mode);
+ if (/*(mode == 0x7) && */(!p_spdif->sample_rate_detect_start)) {
+ p_spdif->sample_rate_detect_start = 1;
+ pr_debug("spdif in sample rate started\n");
+ }
+
+ if (p_spdif->sample_rate_detect_start) {
+
+ p_spdif->last_sample_rate_mode = mode;
+
+ if (!p_spdif->is_reset_timer_used) {
+ unsigned long delay = msecs_to_jiffies(1);
+
+ if (p_spdif->sample_rate_detect_start == 1)
+ delay = msecs_to_jiffies(FIRST_DELAY);
+
+ setup_timer(&p_spdif->reset_timer,
+ spdifin_reset_timer,
+ (unsigned long)p_spdif);
+ mod_timer(&p_spdif->reset_timer,
+ jiffies + delay);
+ }
+ p_spdif->is_reset_timer_used++;
+ p_spdif->timer_counter = 0;
+ }
+
+ if ((mode == 0x7) ||
+ (((intrpt_status >> 18) & 0x3ff) == 0x3ff)) {
+ pr_info("Default value, not detect sample rate\n");
extcon_set_state(p_spdif->edev,
EXTCON_SPDIFIN_SAMPLERATE, 0);
} else if (mode >= 0) {
- pr_debug("Event: EXTCON_SPDIFIN_SAMPLERATE, new sample rate:%d\n",
- sample_mode[mode]);
+ if (p_spdif->last_sample_rate_mode != mode) {
+ pr_info("Event: EXTCON_SPDIFIN_SAMPLERATE, new sample rate:%s\n",
+ spdifin_samplerate[mode + 1]);
- extcon_set_state(p_spdif->edev,
- EXTCON_SPDIFIN_SAMPLERATE, 1);
+ /* resample enable, by hw */
+ if (!spdifin_check_audiotype_by_sw(p_spdif))
+ resample_set(p_spdif->auto_asrc);
+
+ extcon_set_state(p_spdif->edev,
+ EXTCON_SPDIFIN_SAMPLERATE, 1);
+ }
}
+ p_spdif->last_sample_rate_mode = mode;
+
}
if (intrpt_status & 0x8) {
- pr_warn_once("Pc changed, try to read spdifin audio type\n");
+ pr_info("Pc changed, try to read spdifin audio type\n");
+
extcon_set_state(p_spdif->edev,
EXTCON_SPDIFIN_AUDIOTYPE, 1);
- } else
+
+ /* resample disable, by hw */
+ if (!spdifin_check_audiotype_by_sw(p_spdif))
+ resample_set(0);
+ }
+ if (intrpt_status & 0x10)
+ pr_info("Pd changed\n");
+ if (intrpt_status & 0x20) {
+ pr_info("nonpcm to pcm\n");
extcon_set_state(p_spdif->edev,
EXTCON_SPDIFIN_AUDIOTYPE, 0);
- if (intrpt_status & 0x10)
- pr_warn_once("Pd changed\n");
- if (intrpt_status & 0x20)
- pr_warn_once("nonpcm to pcm\n");
+ /* resample to 48k, by hw */
+ if (!spdifin_check_audiotype_by_sw(p_spdif))
+ resample_set(p_spdif->auto_asrc);
+ }
if (intrpt_status & 0x40)
- pr_warn_once("valid changed\n");
+ pr_info("valid changed\n");
}
static irqreturn_t aml_spdif_ddr_isr(int irq, void *devid)
{
struct aml_spdif *p_spdif = (struct aml_spdif *)devid;
- aml_spdifin_status_check(p_spdif->actrl);
-
spdifin_status_event(p_spdif);
return IRQ_HANDLED;
struct aml_spdif *p_spdif;
int ret = 0;
- pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
+ pr_info("%s\n", __func__);
p_spdif = (struct aml_spdif *)dev_get_drvdata(dev);
p_spdif->irq_spdifin);
return ret;
}
+ if (spdifin_check_audiotype_by_sw(p_spdif))
+ spdifin_audio_type_detect_init(p_spdif);
+
+ p_spdif->sample_rate_detect_start = 0;
}
runtime->private_data = p_spdif;
struct snd_pcm_runtime *runtime = substream->runtime;
struct aml_spdif *p_spdif = runtime->private_data;
- pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
+ pr_info("%s\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
aml_audio_unregister_frddr(p_spdif->dev, substream);
} else {
aml_audio_unregister_toddr(p_spdif->dev, substream);
free_irq(p_spdif->irq_spdifin, p_spdif);
+
+ if (spdifin_check_audiotype_by_sw(p_spdif))
+ spdifin_audio_type_detect_deinit(p_spdif);
+
+ if (p_spdif->is_reset_timer_used) {
+ p_spdif->is_reset_timer_used = 0;
+ del_timer(&p_spdif->reset_timer);
+ }
+
+ /* clear extcon status */
+ if (p_spdif->id == 0) {
+ extcon_set_state(p_spdif->edev,
+ EXTCON_SPDIFIN_SAMPLERATE, 0);
+
+ extcon_set_state(p_spdif->edev,
+ EXTCON_SPDIFIN_AUDIOTYPE, 0);
+ }
}
runtime->private_data = NULL;
static int aml_spdif_trigger(struct snd_pcm_substream *substream, int cmd)
{
- return 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aml_spdif *p_spdif = runtime->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if ((spdifin_check_audiotype_by_sw(p_spdif))
+ && (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
+ spdifin_audio_type_start_timer(p_spdif);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_STOP:
+ if ((spdifin_check_audiotype_by_sw(p_spdif))
+ && (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
+ spdifin_audio_type_stop_timer(p_spdif);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
}
static int aml_spdif_prepare(struct snd_pcm_substream *substream)
__func__,
(p_spdif->id == 0) ? "a":"b",
p_spdif->clk_cont);
+
/* keep frddr when probe, after spdif_frddr_init done
* frddr can be released, and spdif outputs zero data
* without frddr used.
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
int ret = 0;
+ pr_info("%s\n", __func__);
+
if (p_spdif->id == SPDIF_A) {
ret = snd_soc_add_dai_controls(cpu_dai, snd_spdif_controls,
ARRAY_SIZE(snd_spdif_controls));
pr_err("%s, failed add snd spdif controls\n", __func__);
}
- pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
-
return 0;
}
static int aml_dai_spdif_remove(struct snd_soc_dai *cpu_dai)
{
- pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
+ pr_info("%s\n", __func__);
return 0;
}
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
int ret;
- pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
+ pr_info("%s stream:%d\n",
+ __func__,
+ substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pr_err("Can't enable pcm clk_spdifin clock: %d\n", ret);
goto err;
}
+ /* resample to 48k in default, by hw */
+ if (!spdifin_check_audiotype_by_sw(p_spdif))
+ resample_set(p_spdif->auto_asrc);
}
return 0;
{
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ pr_info("%s, stream:%d\n",
+ __func__,
+ substream->stream);
+
/* disable clock and gate */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (p_spdif->clk_cont) {
clk_disable_unprepare(p_spdif->sysclk);
clk_disable_unprepare(p_spdif->gate_spdifout);
} else {
+ /* resample disabled, by hw */
+ if (!spdifin_check_audiotype_by_sw(p_spdif))
+ resample_set(0);
+
clk_disable_unprepare(p_spdif->clk_spdifin);
clk_disable_unprepare(p_spdif->fixed_clk);
clk_disable_unprepare(p_spdif->gate_spdifin);
} else {
struct toddr *to = p_spdif->tddr;
+ struct toddr_fmt fmt;
unsigned int msb, lsb, toddr_type;
if (loopback_is_enable()) {
}
// to ddr spdifin
+ fmt.type = toddr_type;
+ fmt.msb = msb;
+ fmt.lsb = lsb;
+ fmt.endian = 0;
+ fmt.bit_depth = bit_depth;
+ fmt.ch_num = runtime->channels;
+ fmt.rate = runtime->rate;
aml_toddr_select_src(to, SPDIFIN);
- aml_toddr_set_format(to, toddr_type, msb, lsb,
- runtime->channels,
- bit_depth);
+ aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
+#ifdef __SPDIFIN_INSERT_CHNUM__
+ aml_toddr_insert_chanum(to);
+#endif
}
aml_spdif_fifo_ctrl(p_spdif->actrl, bit_depth,
substream->stream, p_spdif->id, fifo_id);
+#ifdef __SPDIFIN_INSERT_CHNUM__
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ aml_spdifin_chnum_en(p_spdif->actrl,
+ p_spdif->id, true);
+#endif
+
return 0;
}
aml_spdif_enable(p_spdif->actrl,
substream->stream, p_spdif->id, true);
+
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
return 0;
}
-
static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
unsigned int rate = params_rate(params);
int ret = 0;
- pr_info("%s\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
rate *= 128;
snd_soc_dai_set_sysclk(cpu_dai,
0, rate, SND_SOC_CLOCK_OUT);
} else {
- clk_set_rate(p_spdif->clk_spdifin, 250000000);
+ clk_set_rate(p_spdif->clk_spdifin, 500000000);
}
return ret;
static int aml_dai_set_spdif_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
- struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
-
- pr_info("asoc aml_dai_set_spdif_fmt, %#x, %p\n", fmt, p_spdif);
+ pr_info("%s , fmt %#x\n", __func__, fmt);
return 0;
}
{
unsigned int mpll_freq = 0;
- pr_info("asoc debug: %s-%d, sys freq:%d\n", __func__, __LINE__,
+ pr_info("%s, sys freq:%d\n",
+ __func__,
p_spdif->sysclk_freq);
+
if (p_spdif->sysclk_freq) {
unsigned int mul = 4;
int ret;
#ifdef G12A_PTM
mpll_freq = p_spdif->sysclk_freq * 57;
#endif
+ pr_info("\t finally sys freq:%d, mpll freq:%d\n",
+ p_spdif->sysclk_freq,
+ mpll_freq);
+
clk_set_rate(p_spdif->sysclk, mpll_freq);
clk_set_rate(p_spdif->clk_spdifout,
p_spdif->sysclk_freq);
static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
- struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ pr_info("%s, clk_id:%d, freq:%d, dir:%d\n",
+ __func__,
+ clk_id,
+ freq,
+ dir);
- p_spdif->sysclk_freq = freq;
- pr_info("aml_dai_set_spdif_sysclk, %d, %d, %d\n",
- clk_id, freq, dir);
+ if (dir == SND_SOC_CLOCK_OUT) {
+ struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
- aml_set_spdifclk(p_spdif);
+ p_spdif->sysclk_freq = freq;
+ aml_set_spdifclk(p_spdif);
+ }
return 0;
}
ret = extcon_dev_register(p_spdif->edev);
if (ret < 0)
pr_err("SPDIF IN extcon failed to register!!, ignore it\n");
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "auto_asrc", &p_spdif->auto_asrc);
+ if (ret < 0)
+ p_spdif->auto_asrc = 0;
+ pr_info("SPDIF id %d auto_asrc:%d\n",
+ p_spdif->id,
+ p_spdif->auto_asrc);
}
/* clock for spdif out */
}
struct spdif_chipinfo axg_spdif_chipinfo = {
- .id = SPDIF_A,
+ .id = SPDIF_A,
+ .irq_no_papb = true,
+ .clr_irq_all_bits = true,
};
struct spdif_chipinfo g12a_spdif_a_chipinfo = {
.id = SPDIF_A,
.chnum_en = true,
- .clr_irq_bits = true,
- .irq_papb = true,
.hold_start = true,
.eq_drc_en = true,
};
struct spdif_chipinfo g12a_spdif_b_chipinfo = {
.id = SPDIF_B,
.chnum_en = true,
- .clr_irq_bits = true,
- .irq_papb = true,
.hold_start = true,
.eq_drc_en = true,
};
of_device_get_match_data(dev);
if (p_spdif_chipinfo) {
aml_spdif->id = p_spdif_chipinfo->id;
- /* for spdif_b, clk be continuous,
+ /* for spdif output zero data, clk be continuous,
* and keep silence when no valid data
*/
- /*if (aml_spdif->id == 1)*/
- aml_spdif->clk_cont = 1;
+ aml_spdif->clk_cont = 1;
aml_spdif->chipinfo = p_spdif_chipinfo;
} else
/*#define G12A_PTM*/
/*#define G12A_PTM_LB_INTERNAL*/
+unsigned int aml_spdif_ctrl_read(struct aml_audio_controller *actrl,
+ int stream, int index)
+{
+ unsigned int offset, reg;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0;
+ reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index;
+ } else {
+ reg = EE_AUDIO_SPDIFIN_CTRL0;
+ }
+
+ return aml_audiobus_read(actrl, reg);
+}
+
+void aml_spdif_ctrl_write(struct aml_audio_controller *actrl,
+ int stream, int index, int val)
+{
+ unsigned int offset, reg;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0;
+ reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index;
+ } else {
+ reg = EE_AUDIO_SPDIFIN_CTRL0;
+ }
+
+ aml_audiobus_write(actrl, reg, val);
+}
+
+void aml_spdifin_chnum_en(struct aml_audio_controller *actrl,
+ int index, bool is_enable)
+{
+ unsigned int reg;
+
+ reg = EE_AUDIO_SPDIFIN_CTRL0;
+ aml_audiobus_update_bits(actrl, reg, 1 << 26, is_enable << 26);
+
+ pr_info("%s spdifin ctrl0:0x%x\n",
+ __func__,
+ aml_audiobus_read(actrl, reg));
+}
+
void aml_spdif_enable(
struct aml_audio_controller *actrl,
int stream,
{
unsigned int val;
- val = aml_audiobus_read(actrl,
- EE_AUDIO_SPDIFIN_STAT0);
+ val = aml_audiobus_read(actrl, EE_AUDIO_SPDIFIN_STAT0);
/* pr_info("\t--- spdif handles status0 %#x\n", val); */
-
- aml_audiobus_update_bits(actrl,
- EE_AUDIO_SPDIFIN_CTRL0,
- 1<<26,
- 1<<26);
- aml_audiobus_update_bits(actrl,
- EE_AUDIO_SPDIFIN_CTRL0,
- 1<<26,
- 0);
-
return val;
}
+void aml_spdifin_clr_irq(struct aml_audio_controller *actrl,
+ bool is_all_bits, int clr_bits_val)
+{
+ if (is_all_bits) {
+ aml_audiobus_update_bits(actrl,
+ EE_AUDIO_SPDIFIN_CTRL0,
+ 1 << 26,
+ 1 << 26);
+ aml_audiobus_update_bits(actrl,
+ EE_AUDIO_SPDIFIN_CTRL0,
+ 1 << 26,
+ 0);
+ } else
+ aml_audiobus_update_bits(actrl,
+ EE_AUDIO_SPDIFIN_CTRL6,
+ 0xff << 16,
+ clr_bits_val << 16);
+}
+
void aml_spdif_fifo_reset(
struct aml_audio_controller *actrl,
int stream, int index)
}
pr_info("%s, bit depth:%d, frddr type:%d, toddr:type:%d\n",
- __func__, bitwidth, frddr_type, toddr_type);
+ __func__,
+ bitwidth,
+ frddr_type,
+ toddr_type);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
unsigned int offset, reg;
reg,
1<<4);
} else {
- unsigned int lsb;
-
- if (bitwidth <= 24)
- lsb = 28 - bitwidth;
- else
- lsb = 4;
+ unsigned int spdifin_clk = 500000000;
+
+ /* sysclk/rate/32(bit)/2(ch)/2(bmc) */
+ unsigned int counter_32k = (spdifin_clk / (32000 * 64));
+ unsigned int counter_44k = (spdifin_clk / (44100 * 64));
+ unsigned int counter_48k = (spdifin_clk / (48000 * 64));
+ unsigned int counter_88k = (spdifin_clk / (88200 * 64));
+ unsigned int counter_96k = (spdifin_clk / (96000 * 64));
+ unsigned int counter_176k = (spdifin_clk / (176400 * 64));
+ unsigned int counter_192k = (spdifin_clk / (192000 * 64));
+ unsigned int mode0_th = 3 * (counter_32k + counter_44k) >> 1;
+ unsigned int mode1_th = 3 * (counter_44k + counter_48k) >> 1;
+ unsigned int mode2_th = 3 * (counter_48k + counter_88k) >> 1;
+ unsigned int mode3_th = 3 * (counter_88k + counter_96k) >> 1;
+ unsigned int mode4_th = 3 * (counter_96k + counter_176k) >> 1;
+ unsigned int mode5_th = 3 * (counter_176k + counter_192k) >> 1;
+ unsigned int mode0_timer = counter_32k >> 1;
+ unsigned int mode1_timer = counter_44k >> 1;
+ unsigned int mode2_timer = counter_48k >> 1;
+ unsigned int mode3_timer = counter_88k >> 1;
+ unsigned int mode4_timer = counter_96k >> 1;
+ unsigned int mode5_timer = (counter_176k >> 1);
+ unsigned int mode6_timer = (counter_192k >> 1);
- // 250M
-#ifdef G12A_PTM
- aml_audiobus_write(actrl,
- EE_AUDIO_SPDIFIN_CTRL1,
- 25000 << 0);
-#else
aml_audiobus_write(actrl,
EE_AUDIO_SPDIFIN_CTRL1,
- 0xff << 20 | 25000 << 0);
-#endif
+ 0xff << 20 | (spdifin_clk / 10000) << 0);
+
aml_audiobus_write(actrl,
EE_AUDIO_SPDIFIN_CTRL2,
- 140 << 20 | 100 << 10 | 86 << 0);
+ mode0_th << 20 |
+ mode1_th << 10 |
+ mode2_th << 0);
aml_audiobus_write(actrl,
EE_AUDIO_SPDIFIN_CTRL3,
- 83 << 20 | 60 << 10 | 30 << 0);
+ mode3_th << 20 |
+ mode4_th << 10 |
+ mode5_th << 0);
aml_audiobus_write(actrl,
EE_AUDIO_SPDIFIN_CTRL4,
- (81<<24) | /* reg_sample_mode0_timer */
- (61<<16) | /* reg_sample_mode1_timer */
- (44<<8) | /* reg_sample_mode2_timer*/
- (42<<0)
+ (mode0_timer << 24) |
+ (mode1_timer << 16) |
+ (mode2_timer << 8) |
+ (mode3_timer << 0)
);
-#ifdef G12A_PTM
- aml_audiobus_write(actrl,
- EE_AUDIO_SPDIFIN_CTRL5,
- (40<<24) |
- (20<<16) |
- (10<<8) |
- (0<<0)
- );
-#else
aml_audiobus_write(actrl,
EE_AUDIO_SPDIFIN_CTRL5,
- (40<<24) | /* reg_sample_mode4_timer = 5[31:24]; */
- (20<<16) | /* reg_sample_mode5_timer = 5[23:16]; */
- (9<<8) | /* reg_sample_mode6_timer = 5[15:8]; */
- (0<<0) /* reg_sample_mode7_timer = 5[7:0]; */
+ (mode4_timer << 24) |
+ (mode5_timer << 16) |
+ (mode6_timer << 8)
);
-#endif
aml_audiobus_update_bits(actrl,
EE_AUDIO_SPDIFIN_CTRL0,
- 0x3<<24|1<<12,
- 3<<24|1<<12);
+ 0x1 << 25 | 0x1 << 24 | 0xfff << 12,
+ 0x1 << 25 | 0x0 << 24 | 0xff << 12);
}
}
val = audiobus_read(EE_AUDIO_SPDIFIN_STAT0);
+ /* NA when check min width of two edges */
+ if (((val >> 18) & 0x3ff) == 0x3ff)
+ return 0x7;
+
return (val >> 28) & 0x7;
}
-int spdifin_get_audio_type(void)
+static int spdifin_get_channel_status(int sel)
{
unsigned int val;
- /* set ch_status_sel to read Pc*/
- audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0xf << 8, 0x6 << 8);
+ /* set ch_status_sel to channel status */
+ audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0xf << 8, sel << 8);
val = audiobus_read(EE_AUDIO_SPDIFIN_STAT1);
+ return val;
+}
+
+int spdifin_get_ch_status0to31(void)
+{
+ return spdifin_get_channel_status(0x0);
+}
+
+int spdifin_get_audio_type(void)
+{
+ unsigned int val;
+
+ /* set ch_status_sel to read Pc */
+ val = spdifin_get_channel_status(0x6);
+
return (val >> 16) & 0xff;
}
void spdifout_play_with_zerodata_free(unsigned int spdif_id)
{
- pr_info("%s, spdif id:%d\n", __func__, spdif_id);
+ pr_info("%s, spdif id:%d\n",
+ __func__,
+ spdif_id);
/* free frddr, then frddr in mngr */
frddr_deinit_without_mngr(spdif_id);
#include <linux/amlogic/media/sound/spdif_info.h>
+extern unsigned int aml_spdif_ctrl_read(struct aml_audio_controller *actrl,
+ int stream, int index);
+extern void aml_spdif_ctrl_write(struct aml_audio_controller *actrl,
+ int stream, int index, int val);
+extern void aml_spdifin_chnum_en(struct aml_audio_controller *actrl,
+ int index, bool is_enable);
extern void aml_spdif_enable(
struct aml_audio_controller *actrl,
int stream,
extern int aml_spdifin_status_check(
struct aml_audio_controller *actrl);
+extern void aml_spdifin_clr_irq(struct aml_audio_controller *actrl,
+ bool is_all_bits, int clr_bits_val);
extern void aml_spdif_fifo_reset(
struct aml_audio_controller *actrl,
extern int spdifin_get_sample_rate(void);
+extern int spdifin_get_ch_status0to31(void);
+
extern int spdifin_get_audio_type(void);
extern void spdif_set_channel_status_info(
enum toddr_src src;
unsigned int lsb = 32 - bit_depth;
unsigned int toddr_type;
+ struct toddr_fmt fmt;
switch (bit_depth) {
case 8:
return -EINVAL;
}
+ fmt.type = toddr_type;
+ fmt.msb = 31;
+ fmt.lsb = lsb;
+ fmt.endian = 0;
+ fmt.bit_depth = bit_depth;
+ fmt.ch_num = runtime->channels;
+ fmt.rate = runtime->rate;
aml_toddr_select_src(to, src);
- aml_toddr_set_format(to, toddr_type, 31, lsb,
- runtime->channels,
- bit_depth);
+ aml_toddr_set_format(to, &fmt);
aml_toddr_set_fifos(to, 0x40);
}