spdif_codec: spdif_codec{
#sound-dai-cells = <0>;
compatible = "amlogic, aml-spdif-codec";
- pinctrl-names = "audio_spdif";
- pinctrl-0 = <&audio_spdif_pins>;
+ pinctrl-names = "audio_spdif_out",
+ "audio_spdif_out_mute",
+ "audio_spdif_in",
+ "audio_spdif_in_mute";
+ pinctrl-0 = <&audio_spdif_out_pins>;
+ pinctrl-1 = <&audio_spdif_out_mute_pins>;
+ pinctrl-2 = <&audio_spdif_in_pins>;
+ pinctrl-3 = <&audio_spdif_in_mute_pins>;
};
pcm_codec: pcm_codec{
pinctrl-0 = <&aml_audio_i2s>;
/*avout mute gpio*/
mute_gpio-gpios = <&gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
+ /*switch ARC_IN & SPDIF_IN*/
+ source_switch-gpios = <&gpio GPIOZ_4 GPIO_ACTIVE_HIGH>;
/*analog amp mute*/
/*amp_mute_gpio-gpios = <&gpio GPIOZ_18 GPIO_ACTIVE_LOW>;*/
aux_dev = <&tas5707>;
};
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
- Speaker_Channel_Mask = "i2s_0/1";
+ Speaker0_Channel_Mask = "i2s_2/3";
DAC0_Channel_Mask = "i2s_2/3";
DAC1_Channel_Mask = "i2s_2/3";
EQ_DRC_Channel_Mask = "i2s_2/3";
};
};
/*spdif*/
- audio_spdif_pins: audio_spdif_pins {
- in_mux {
+ audio_spdif_out_pins: audio_spdif_out_pins {
+ mux {
+ groups = "spdif_out_z";
+ function = "spdif_out";
+ };
+ };
+ audio_spdif_out_mute_pins: audio_spdif_out_mute_pins {
+ mux {
+ groups = "GPIOZ_17";
+ function = "gpio_periphs";
+ };
+ };
+ audio_spdif_in_pins: audio_spdif_in_pins {
+ mux {
groups = "spdif_in_z18";
function = "spdif_in";
};
- out_mux {
- groups = "spdif_out_z";
- function = "spdif_out";
+ };
+ audio_spdif_in_mute_pins: audio_spdif_in_mute_pins {
+ mux {
+ groups = "GPIOZ_18";
+ function = "gpio_periphs";
};
};
/*pcm*/
spdif_codec: spdif_codec{
#sound-dai-cells = <0>;
compatible = "amlogic, aml-spdif-codec";
- pinctrl-names = "audio_spdif";
- pinctrl-0 = <&audio_spdif_pins>;
+ pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute";
+ pinctrl-0 = <&audio_spdif_out_pins>;
+ pinctrl-1 = <&audio_spdif_out_mute_pins>;
};
pcm_codec: pcm_codec{
};
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
- Speaker_Channel_Mask = "i2s_0/1";
+ Speaker0_Channel_Mask = "i2s_2/3";
DAC0_Channel_Mask = "i2s_2/3";
DAC1_Channel_Mask = "i2s_2/3";
EQ_DRC_Channel_Mask = "i2s_2/3";
};
};
/*spdif*/
- audio_spdif_pins: audio_spdif_pins {
- out_mux {
+ audio_spdif_out_pins: audio_spdif_out_pins {
+ mux {
groups = "spdif_out_dv";
function = "spdif_out";
};
};
+ audio_spdif_out_mute_pins: audio_spdif_out_mute_pins {
+ mux {
+ groups = "GPIODV_6";
+ function = "gpio_periphs";
+ };
+ };
/*pcm*/
aml_audio_pcm: aml_audio_pcm {
mux {
spdif_codec: spdif_codec{
#sound-dai-cells = <0>;
compatible = "amlogic, aml-spdif-codec";
- pinctrl-names = "audio_spdif";
- pinctrl-0 = <&audio_spdif_pins>;
+ pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute";
+ pinctrl-0 = <&audio_spdif_out_pins>;
+ pinctrl-1 = <&audio_spdif_out_mute_pins>;
};
pcm_codec: pcm_codec{
};
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
- Speaker_Channel_Mask = "i2s_0/1";
+ Speaker0_Channel_Mask = "i2s_2/3";
DAC0_Channel_Mask = "i2s_2/3";
DAC1_Channel_Mask = "i2s_2/3";
EQ_DRC_Channel_Mask = "i2s_2/3";
};
};
/*spdif*/
- audio_spdif_pins: audio_spdif_pins {
- out_mux {
+ /*spdif*/
+ audio_spdif_out_pins: audio_spdif_out_pins {
+ mux {
groups = "spdif_out_dv";
function = "spdif_out";
};
};
+ audio_spdif_out_mute_pins: audio_spdif_out_mute_pins {
+ mux {
+ groups = "GPIODV_6";
+ function = "gpio_periphs";
+ };
+ };
/*pcm*/
aml_audio_pcm: aml_audio_pcm {
mux {
spdif_codec: spdif_codec{
#sound-dai-cells = <0>;
compatible = "amlogic, aml-spdif-codec";
- pinctrl-names = "audio_spdif";
- pinctrl-0 = <&audio_spdif_pins>;
+ pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute";
+ pinctrl-0 = <&audio_spdif_out_pins>;
+ pinctrl-1 = <&audio_spdif_out_mute_pins>;
};
pcm_codec: pcm_codec{
};
Channel_Mask {
/*i2s has 4 pins, 8channel, mux output*/
- Speaker_Channel_Mask = "i2s_0/1";
+ Speaker0_Channel_Mask = "i2s_2/3";
DAC0_Channel_Mask = "i2s_2/3";
DAC1_Channel_Mask = "i2s_2/3";
EQ_DRC_Channel_Mask = "i2s_2/3";
};
};
/*spdif*/
- audio_spdif_pins: audio_spdif_pins {
- out_mux {
+ audio_spdif_out_pins: audio_spdif_out_pins {
+ mux {
groups = "spdif_out_dv";
function = "spdif_out";
};
};
+ audio_spdif_out_mute_pins: audio_spdif_out_mute_pins {
+ mux {
+ groups = "GPIODV_6";
+ function = "gpio_periphs";
+ };
+ };
/*pcm*/
aml_audio_pcm: aml_audio_pcm {
mux {
hdmitx_device.flag_3dss = 0;
hdmi_set_3d(&hdmitx_device, T3D_DISABLE, 0);
}
- } else if (strncmp(buf, "audio_", 6) == 0) {
- if (strncmp(buf+6, "off", 3) == 0) {
- hdmitx_audio_mute_op(0);
- pr_info(AUD "configure off\n");
- } else if (strncmp(buf+6, "on", 2) == 0) {
- hdmitx_audio_mute_op(1);
- pr_info(AUD "configure on\n");
- } else if (strncmp(buf+6, "auto", 4) == 0) {
- /* auto mode. if sink doesn't support current
- * audio format, then no audio output
- */
- hdmitx_device.tx_aud_cfg = 2;
- pr_info(AUD "configure auto\n");
- } else
- pr_info(AUD "configure error\n");
} else if (strncmp(buf, "sdr", 3) == 0) {
data.features = 0x00010100;
hdmitx_set_drm_pkt(&data);
return count;
}
-static ssize_t show_aud_mute(struct device *dev,
- struct device_attribute *attr, char *buf)
+void hdmitx_ext_set_audio_output(int enable)
{
- int pos = 0;
+ hdmitx_audio_mute_op(enable);
+}
- pos += snprintf(buf+pos, PAGE_SIZE, "%d\n",
- atomic_read(&(hdmitx_device.kref_audio_mute)));
- return pos;
+int hdmitx_ext_get_audio_status(void)
+{
+ return !!hdmitx_device.tx_aud_cfg;
}
-static ssize_t store_aud_mute(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
+void hdmitx_ext_set_i2s_mask(char ch_num, char ch_msk)
{
- atomic_t kref_audio_mute = hdmitx_device.kref_audio_mute;
+ struct hdmitx_dev *hdev = &hdmitx_device;
+ static unsigned int update_flag = -1;
- if (buf[0] == '1') {
- atomic_inc(&kref_audio_mute);
- if (atomic_read(&kref_audio_mute) == 1)
- hdmitx_audio_mute_op(0);
- }
- if (buf[0] == '0') {
- if (!(atomic_sub_and_test(0, &kref_audio_mute))) {
- atomic_dec(&kref_audio_mute);
- if (atomic_sub_and_test(0, &kref_audio_mute))
- hdmitx_audio_mute_op(1);
+ if (!((ch_num == 2) || (ch_num == 4) || (ch_num == 6)
+ || (ch_num == 8))) {
+ pr_info("err chn setting, must be 2, 4, 6 or 8, Rst as def\n");
+ hdev->aud_output_ch = 0;
+ if (update_flag != hdev->aud_output_ch) {
+ update_flag = hdev->aud_output_ch;
+ hdev->hdmi_ch = 0;
+ hdmitx_set_audio(hdev, &(hdev->cur_audio_param));
}
}
+ if (ch_msk == 0) {
+ pr_info("err chn msk, must larger than 0\n");
+ return;
+ }
+ hdev->aud_output_ch = (ch_num << 4) + ch_msk;
+ if (update_flag != hdev->aud_output_ch) {
+ update_flag = hdev->aud_output_ch;
+ hdev->hdmi_ch = 0;
+ hdmitx_set_audio(hdev, &(hdev->cur_audio_param));
+ }
+}
- hdmitx_device.kref_audio_mute = kref_audio_mute;
+char hdmitx_ext_get_i2s_mask(void)
+{
+ struct hdmitx_dev *hdev = &hdmitx_device;
- return count;
+ return hdev->aud_output_ch & 0xf;
}
static ssize_t show_vid_mute(struct device *dev,
return count;
}
-/* hdmitx audio output channel */
-static ssize_t show_aud_output_chs(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct hdmitx_dev *hdev = &hdmitx_device;
- int pos = 0;
-
- if (hdev->aud_output_ch)
- pos += snprintf(buf + pos, PAGE_SIZE,
- "Audio Output Channels: %x:%x\n",
- (hdev->aud_output_ch >> 4) & 0xf,
- (hdev->aud_output_ch & 0xf));
-
- return pos;
-}
-
-/*
- * aud_output_chs CONFIGURE:
- * [7:4] -- Output Channel Numbers, must be 2/4/6/8
- * [3:0] -- Output Channel Mask, matched as CH3/2/1/0 R/L
- */
-static ssize_t store_aud_output_chs(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct hdmitx_dev *hdev = &hdmitx_device;
- int tmp = -1;
- int ret = 0;
- unsigned long msk;
- static unsigned int update_flag = -1;
-
- if (isdigit(buf[0]))
- tmp = buf[0] - '0';
-
- if (!((tmp == 2) || (tmp == 4) || (tmp == 6) || (tmp == 8))) {
- pr_info("err chn setting, must be 2, 4, 6 or 8, Rst as def\n");
- hdev->aud_output_ch = 0;
- if (update_flag != hdev->aud_output_ch) {
- update_flag = hdev->aud_output_ch;
- hdev->hdmi_ch = 0;
- hdmitx_set_audio(hdev, &(hdev->cur_audio_param));
- }
- return count;
- }
-
- /* get channel no. For I2S, there are 4 I2S_in[3:0] */
- if ((buf[1] == ':') && (isxdigit(buf[2])))
- ret = kstrtoul(&buf[2], 16, &msk);
- else
- msk = 0;
- if (ret || (msk == 0)) {
- pr_info("err chn msk, must larger than 0\n");
- return count;
- }
-
- hdev->aud_output_ch = (tmp << 4) + msk;
-
- if (update_flag != hdev->aud_output_ch) {
- update_flag = hdev->aud_output_ch;
- hdev->hdmi_ch = 0;
- hdmitx_set_audio(hdev, &(hdev->cur_audio_param));
- }
- return count;
-}
-
/*
* 1: set avmute
* -1: clear avmute
static DEVICE_ATTR(disp_mode, 0664, show_disp_mode, store_disp_mode);
static DEVICE_ATTR(attr, 0664, show_attr, store_attr);
static DEVICE_ATTR(aud_mode, 0644, show_aud_mode, store_aud_mode);
-static DEVICE_ATTR(aud_mute, 0644, show_aud_mute, store_aud_mute);
static DEVICE_ATTR(vid_mute, 0644, show_vid_mute, store_vid_mute);
static DEVICE_ATTR(edid, 0644, show_edid, store_edid);
static DEVICE_ATTR(rawedid, 0444, show_rawedid, NULL);
static DEVICE_ATTR(dc_cap, 0444, show_dc_cap, NULL);
static DEVICE_ATTR(valid_mode, 0664, show_valid_mode, store_valid_mode);
static DEVICE_ATTR(aud_ch, 0664, show_aud_ch, store_aud_ch);
-static DEVICE_ATTR(aud_output_chs, 0664, show_aud_output_chs,
- store_aud_output_chs);
static DEVICE_ATTR(avmute, 0664, show_avmute, store_avmute);
static DEVICE_ATTR(vic, 0664, show_vic, store_vic);
static DEVICE_ATTR(phy, 0664, show_phy, store_phy);
ret = device_create_file(dev, &dev_attr_disp_mode);
ret = device_create_file(dev, &dev_attr_attr);
ret = device_create_file(dev, &dev_attr_aud_mode);
- ret = device_create_file(dev, &dev_attr_aud_mute);
ret = device_create_file(dev, &dev_attr_vid_mute);
ret = device_create_file(dev, &dev_attr_edid);
ret = device_create_file(dev, &dev_attr_rawedid);
ret = device_create_file(dev, &dev_attr_hdr_cap);
ret = device_create_file(dev, &dev_attr_dv_cap);
ret = device_create_file(dev, &dev_attr_aud_ch);
- ret = device_create_file(dev, &dev_attr_aud_output_chs);
ret = device_create_file(dev, &dev_attr_avmute);
ret = device_create_file(dev, &dev_attr_vic);
ret = device_create_file(dev, &dev_attr_phy);
device_remove_file(dev, &dev_attr_disp_mode);
device_remove_file(dev, &dev_attr_attr);
device_remove_file(dev, &dev_attr_aud_mode);
- device_remove_file(dev, &dev_attr_aud_mute);
device_remove_file(dev, &dev_attr_vid_mute);
device_remove_file(dev, &dev_attr_edid);
device_remove_file(dev, &dev_attr_rawedid);
device_remove_file(dev, &dev_attr_sspll);
device_remove_file(dev, &dev_attr_rxsense_policy);
device_remove_file(dev, &dev_attr_hdcp_pwr);
- device_remove_file(dev, &dev_attr_aud_output_chs);
device_remove_file(dev, &dev_attr_div40);
device_remove_file(dev, &dev_attr_hdcp_repeater);
device_remove_file(dev, &dev_attr_hdcp22_type);
void direct_hdcptx14_start(void);
void direct_hdcptx14_stop(void);
+/*
+ * HDMI TX output enable, such as ACRPacket/AudInfo/AudSample
+ * enable: 1, normal output; 0: disable output
+ */
+void hdmitx_ext_set_audio_output(int enable);
+
+/*
+ * return Audio output status
+ * 1: normal output status; 0: output disabled
+ */
+int hdmitx_ext_get_audio_status(void);
+
+/*
+ * For I2S interface, there are four input ports
+ * I2S_0/I2S_1/I2S_2/I2S_3
+ * ch_num: must be 2/4/6/8
+ * ch_msk: Mask for channel_num
+ * 2ch via I2S_0, set ch_num = 2 and ch_msk = 1
+ * 4ch via I2S_1/I2S_2, set set ch_num = 4 and ch_msk = 6
+ */
+void hdmitx_ext_set_i2s_mask(char ch_num, char ch_msk);
+
+/*
+ * get I2S mask
+ */
+char hdmitx_ext_get_i2s_mask(void);
+
#endif
#include <sound/initval.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
+#ifdef CONFIG_AMLOGIC_HDMITX
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h>
+#endif
#define DRV_NAME "spdif-dit"
static struct spdif_codec {
struct device *pdev;
- struct pinctrl *p_pinctrl;
- unsigned int spdif_pinmux;
- bool aml_audio_spdif_mute_flag;
+ struct pinctrl *p_pinctrl_out;
+ struct pinctrl_state *p_pinctrl_out_state;
+ struct pinctrl *p_pinctrl_out_mute;
+ struct pinctrl_state *p_pinctrl_out_mute_state;
+ bool spdif_pinmux_out;
+ struct pinctrl *p_pinctrl_in;
+ struct pinctrl_state *p_pinctrl_in_state;
+ struct pinctrl *p_pinctrl_in_mute;
+ struct pinctrl_state *p_pinctrl_in_mute_state;
+ bool spdif_pinmux_in;
+#ifdef CONFIG_AMLOGIC_HDMITX
+ bool aml_audio_hdmiout_mute_flag;
+#endif
} v_spdif_codec;
static struct snd_soc_dai_driver dit_stub_dai = {
void aml_spdif_pinmux_init(struct device *dev)
{
- if (!v_spdif_codec.spdif_pinmux) {
- v_spdif_codec.spdif_pinmux = 1;
- v_spdif_codec.p_pinctrl =
- devm_pinctrl_get_select(dev, "audio_spdif");
- if (IS_ERR(v_spdif_codec.p_pinctrl)) {
- v_spdif_codec.p_pinctrl = NULL;
- dev_err(dev, "aml_spdif_pinmux_init can't get pinctrl\n");
+ v_spdif_codec.p_pinctrl_out_mute =
+ devm_pinctrl_get_select(dev, "audio_spdif_out_mute");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_out_mute)) {
+ v_spdif_codec.p_pinctrl_out_mute = NULL;
+ dev_err(dev, "audio_spdif_out_mute can't get pinctrl\n");
+ } else {
+ v_spdif_codec.p_pinctrl_out_mute_state =
+ pinctrl_lookup_state(v_spdif_codec.p_pinctrl_out_mute,
+ "audio_spdif_out_mute");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_out_mute_state)) {
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_out_mute);
+ dev_err(dev, "audio_spdif_out_mute can't get pinctrl\n");
}
}
+
+ v_spdif_codec.p_pinctrl_out =
+ devm_pinctrl_get_select(dev, "audio_spdif_out");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_out)) {
+ v_spdif_codec.p_pinctrl_out = NULL;
+ dev_err(dev, "audio_spdif_out can't get pinctrl\n");
+ } else {
+ v_spdif_codec.p_pinctrl_out_state =
+ pinctrl_lookup_state(v_spdif_codec.p_pinctrl_out,
+ "audio_spdif_out");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_out_state)) {
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_out);
+ dev_err(dev, "audio_spdif_out can't get pinctrl\n");
+ }
+ }
+
+ v_spdif_codec.p_pinctrl_in_mute =
+ devm_pinctrl_get_select(dev, "audio_spdif_in_mute");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_in_mute)) {
+ v_spdif_codec.p_pinctrl_in_mute = NULL;
+ dev_err(dev, "audio_spdif_in_mute can't get pinctrl\n");
+ }
+ v_spdif_codec.p_pinctrl_in =
+ devm_pinctrl_get_select(dev, "audio_spdif_in");
+ if (IS_ERR(v_spdif_codec.p_pinctrl_in)) {
+ v_spdif_codec.p_pinctrl_in = NULL;
+ dev_err(dev, "audio_spdif_in can't get pinctrl\n");
+ }
}
void aml_spdif_pinmux_deinit(struct device *dev)
{
- dev_dbg(dev, "aml_spdif_mute\n");
- if (v_spdif_codec.spdif_pinmux) {
- v_spdif_codec.spdif_pinmux = 0;
- if (v_spdif_codec.p_pinctrl)
- devm_pinctrl_put(v_spdif_codec.p_pinctrl);
- }
+ if (v_spdif_codec.p_pinctrl_out)
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_out);
+
+ if (v_spdif_codec.p_pinctrl_out_mute)
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_out_mute);
+
+ if (v_spdif_codec.p_pinctrl_in)
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_in);
+
+ if (v_spdif_codec.p_pinctrl_in_mute)
+ devm_pinctrl_put(v_spdif_codec.p_pinctrl_in_mute);
}
+
static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
- v_spdif_codec.aml_audio_spdif_mute_flag =
- ucontrol->value.integer.value[0];
+ v_spdif_codec.spdif_pinmux_out =
+ ucontrol->value.integer.value[0];
pr_info("aml_audio_set_spdif_mute: flag=%d\n",
- v_spdif_codec.aml_audio_spdif_mute_flag);
+ v_spdif_codec.spdif_pinmux_out);
- if (v_spdif_codec.aml_audio_spdif_mute_flag)
- aml_spdif_pinmux_deinit(v_spdif_codec.pdev);
- else
- aml_spdif_pinmux_init(v_spdif_codec.pdev);
+ if (v_spdif_codec.spdif_pinmux_out == 0 &&
+ v_spdif_codec.p_pinctrl_out &&
+ v_spdif_codec.p_pinctrl_out_state)
+ pinctrl_select_state(v_spdif_codec.p_pinctrl_out,
+ v_spdif_codec.p_pinctrl_out_state);
+ else if (v_spdif_codec.spdif_pinmux_out == 1 &&
+ v_spdif_codec.p_pinctrl_out_mute &&
+ v_spdif_codec.p_pinctrl_out_mute_state)
+ pinctrl_select_state(v_spdif_codec.p_pinctrl_out_mute,
+ v_spdif_codec.p_pinctrl_out_mute_state);
return 0;
}
static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] =
- v_spdif_codec.aml_audio_spdif_mute_flag;
+ v_spdif_codec.spdif_pinmux_out;
return 0;
}
+#ifdef CONFIG_AMLOGIC_HDMITX
+/* call HDMITX API to enable/disable internal audio out */
+static int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = !hdmitx_ext_get_audio_status();
+
+ v_spdif_codec.aml_audio_hdmiout_mute_flag =
+ ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ bool mute = ucontrol->value.integer.value[0];
+
+ if (v_spdif_codec.aml_audio_hdmiout_mute_flag != mute) {
+ hdmitx_ext_set_audio_output(!mute);
+ v_spdif_codec.aml_audio_hdmiout_mute_flag = mute;
+ }
+ return 0;
+}
+
+static const char * const hdmi_out_channel_mask_texts[] = {
+ "SPDIF",
+ "2CH_I2S_0/1",
+ "2CH_I2S_2/3",
+ "2CH_I2S_4/5",
+ "2CH_I2S_6/7",
+ "4CH_I2S",
+ "6CH_I2S",
+ "8CH_I2S",
+};
+
+static const struct soc_enum hdmi_out_channel_mask_texts_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(hdmi_out_channel_mask_texts),
+ hdmi_out_channel_mask_texts);
+
+static int aml_get_hdmi_out_channel_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ char channel_mask = hdmitx_ext_get_i2s_mask();
+ int index = 0;
+
+ if (channel_mask == 0x1)
+ index = 1;
+ else if (channel_mask == 0x2)
+ index = 2;
+ else if (channel_mask == 0x4)
+ index = 3;
+ else if (channel_mask == 0x8)
+ index = 4;
+ else if (channel_mask == 0x3)
+ index = 5;
+ else if (channel_mask == 0x7)
+ index = 6;
+ else if (channel_mask == 0xf)
+ index = 7;
+ else
+ index = 0;
+ ucontrol->value.integer.value[0] = index;
+ return 0;
+}
+
+static int aml_set_hdmi_out_channel_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int index = ucontrol->value.integer.value[0];
+
+ if (index == 1)
+ hdmitx_ext_set_i2s_mask(2, 0x1);
+ else if (index == 2)
+ hdmitx_ext_set_i2s_mask(2, 0x2);
+ else if (index == 3)
+ hdmitx_ext_set_i2s_mask(2, 0x4);
+ else if (index == 4)
+ hdmitx_ext_set_i2s_mask(2, 0x8);
+ else if (index == 5)
+ hdmitx_ext_set_i2s_mask(4, 0x3);
+ else if (index == 6)
+ hdmitx_ext_set_i2s_mask(6, 0x7);
+ else if (index == 7)
+ hdmitx_ext_set_i2s_mask(8, 0xf);
+ return 0;
+}
+#endif
+
static const struct snd_kcontrol_new spdif_controls[] = {
SOC_SINGLE_BOOL_EXT("Audio spdif mute",
0, aml_audio_get_spdif_mute,
aml_audio_set_spdif_mute),
+#ifdef CONFIG_AMLOGIC_HDMITX
+ SOC_SINGLE_BOOL_EXT("Audio hdmi-out mute",
+ 0, aml_get_hdmi_out_audio,
+ aml_set_hdmi_out_audio),
+ SOC_ENUM_EXT("Audio hdmi-out channel mask",
+ hdmi_out_channel_mask_texts_enum,
+ aml_get_hdmi_out_channel_mask,
+ aml_set_hdmi_out_channel_mask),
+#endif
};
static int spdif_probe(struct snd_soc_codec *codec)
.probe = spdif_probe,
};
-static ssize_t spdif_mute_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- if (v_spdif_codec.spdif_pinmux)
- return sprintf(buf, "spdif_unmute\n");
- else
- return sprintf(buf, "spdif_mute\n");
-
-}
-
-static ssize_t spdif_mute_set(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- if (strncmp(buf, "spdif_mute", 10))
- aml_spdif_pinmux_init(dev);
- else if (strncmp(buf, "spdif_unmute", 12))
- aml_spdif_pinmux_deinit(dev);
- else
- dev_err(dev, "spdif set the wrong value\n");
-
- return count;
-}
-
-static DEVICE_ATTR(spdif_mute, 0660, spdif_mute_show, spdif_mute_set);
-
static int spdif_dit_probe(struct platform_device *pdev)
{
- int ret = device_create_file(&pdev->dev, &dev_attr_spdif_mute);
-
v_spdif_codec.pdev = &pdev->dev;
aml_spdif_pinmux_init(&pdev->dev);
- if (ret < 0)
- dev_err(&pdev->dev,
- "spdif: failed to add spdif_mute sysfs: %d\n", ret);
return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
&dit_stub_dai, 1);
static int spdif_dit_remove(struct platform_device *pdev)
{
aml_spdif_pinmux_deinit(&pdev->dev);
- device_remove_file(&pdev->dev, &dev_attr_spdif_mute);
snd_soc_unregister_codec(&pdev->dev);
return 0;
module_init(spdif_codec_init);
module_exit(spdif_codec_exit);
-MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
MODULE_DESCRIPTION("SPDIF dummy codec driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
#define DRV_NAME "aml_snd_card_tv"
-static int aml_audio_Hardware_resample;
-static int Speaker_Channel_Mask = 1;
-static int EQ_DRC_Channel_Mask;
-static int DAC0_Channel_Mask;
-static int DAC1_Channel_Mask;
-static int Spdif_samesource_Channel_Mask;
-
static unsigned int aml_EQ_param_length = 100;
static unsigned int aml_EQ_param[100] = {
/*channel 1 param*/
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- ucontrol->value.enumerated.item[0] = aml_audio_Hardware_resample;
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct aml_audio_private_data *p_aml_audio =
+ snd_soc_card_get_drvdata(card);
+ ucontrol->value.enumerated.item[0] =
+ p_aml_audio->aml_audio_Hardware_resample;
return 0;
}
else
return 0;
- aml_audio_Hardware_resample = index;
+ p_aml_audio->aml_audio_Hardware_resample = index;
if (index > 0
&& p_aml_audio
SND_SOC_DAPM_OUTPUT("LINEOUT"),
};
-int audio_in_GPIO;
-struct gpio_desc *av_source;
-static const char * const audio_in_switch_texts[] = { "AV", "Karaok"};
-
+static const char * const audio_in_switch_texts[] = { "SPDIF_IN", "ARC_IN"};
static const struct soc_enum audio_in_switch_enum = SOC_ENUM_SINGLE(
SND_SOC_NOPM, 0, ARRAY_SIZE(audio_in_switch_texts),
audio_in_switch_texts);
static int aml_get_audio_in_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) {
- if (audio_in_GPIO == 0) {
- ucontrol->value.enumerated.item[0] = 0;
- pr_info("audio in source: AV\n");
- } else if (audio_in_GPIO == 1) {
- ucontrol->value.enumerated.item[0] = 1;
- pr_info("audio in source: Karaok\n");
- }
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct aml_audio_private_data *p_aml_audio;
+
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+ ucontrol->value.integer.value[0] = p_aml_audio->audio_in_GPIO;
return 0;
}
static int aml_set_audio_in_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) {
+
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct aml_audio_private_data *p_aml_audio;
+
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+
if (ucontrol->value.enumerated.item[0] == 0) {
- gpiod_direction_output(av_source,
+ if (p_aml_audio->audio_in_GPIO_inv == 0) {
+ gpiod_direction_output(p_aml_audio->source_switch,
+ GPIOF_OUT_INIT_HIGH);
+ } else {
+ gpiod_direction_output(p_aml_audio->source_switch,
GPIOF_OUT_INIT_LOW);
- audio_in_GPIO = 0;
- pr_info("Set audio in source: AV\n");
+ }
+ p_aml_audio->audio_in_GPIO = 0;
} else if (ucontrol->value.enumerated.item[0] == 1) {
- gpiod_direction_output(av_source,
+ if (p_aml_audio->audio_in_GPIO_inv == 0) {
+ gpiod_direction_output(p_aml_audio->source_switch,
+ GPIOF_OUT_INIT_LOW);
+ } else {
+ gpiod_direction_output(p_aml_audio->source_switch,
GPIOF_OUT_INIT_HIGH);
- audio_in_GPIO = 1;
- pr_info("Set audio in source: Karaok\n");
+ }
+ p_aml_audio->audio_in_GPIO = 1;
}
return 0;
}
hp_controls, ARRAY_SIZE(hp_controls));
}
- /*It is used for KaraOK, */
- av_source = gpiod_get(card->dev, "av_source", GPIOD_OUT_LOW);
- if (!IS_ERR(av_source)) {
- pr_info("%s, make av_source gpio low!\n", __func__);
- gpiod_direction_output(av_source, GPIOF_OUT_INIT_LOW);
+ /*It is used for switch of ARC_IN & SPDIF_IN */
+ p_aml_audio->source_switch = gpiod_get(card->dev,
+ "source_switch", GPIOF_OUT_INIT_HIGH);
+ if (!IS_ERR(p_aml_audio->source_switch)) {
+ of_property_read_u32(card->dev->of_node, "source_switch_inv",
+ &p_aml_audio->audio_in_GPIO_inv);
+ if (p_aml_audio->audio_in_GPIO_inv == 0) {
+ gpiod_direction_output(p_aml_audio->source_switch,
+ GPIOF_OUT_INIT_HIGH);
+ } else {
+ gpiod_direction_output(p_aml_audio->source_switch,
+ GPIOF_OUT_INIT_LOW);
+ }
snd_soc_add_card_controls(card, av_controls,
ARRAY_SIZE(av_controls));
}
static void parse_speaker_channel_mask(struct snd_soc_card *card)
{
+ struct aml_audio_private_data *p_aml_audio;
struct device_node *np;
const char *str;
int ret;
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+
/* channel mask */
np = of_get_child_by_name(card->dev->of_node,
"Channel_Mask");
return;
}
- /* Speaker need Audio Effcet from user space by i2s2/3,
- * mux i2s2/3 to layout pin
- */
- of_property_read_string(np, "Speaker_Channel_Mask", &str);
+ /* ext Speaker mask*/
+ of_property_read_string(np, "Speaker0_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- Speaker_Channel_Mask = ret;
+ p_aml_audio->Speaker0_Channel_Mask = ret;
aml_aiu_update_bits(AIU_I2S_OUT_CFG,
- 0x3 << (Speaker_Channel_Mask * 2),
- 1 << (Speaker_Channel_Mask * 2));
- if (Speaker_Channel_Mask == 0) {
- aml_aiu_update_bits(AIU_I2S_OUT_CFG,
- 0x3 << 2, 0 << 2);
- }
+ 0x3, p_aml_audio->Speaker0_Channel_Mask);
+ }
+ of_property_read_string(np, "Speaker1_Channel_Mask", &str);
+ ret = check_channel_mask(str);
+ if (ret >= 0) {
+ p_aml_audio->Speaker1_Channel_Mask = ret;
+ aml_aiu_update_bits(AIU_I2S_OUT_CFG,
+ 0x3 << 2,
+ p_aml_audio->Speaker1_Channel_Mask << 2);
+ }
+ of_property_read_string(np, "Speaker2_Channel_Mask", &str);
+ ret = check_channel_mask(str);
+ if (ret >= 0) {
+ p_aml_audio->Speaker2_Channel_Mask = ret;
+ aml_aiu_update_bits(AIU_I2S_OUT_CFG,
+ 0x3 << 4,
+ p_aml_audio->Speaker2_Channel_Mask << 4);
+ }
+ of_property_read_string(np, "Speaker3_Channel_Mask", &str);
+ ret = check_channel_mask(str);
+ if (ret >= 0) {
+ p_aml_audio->Speaker3_Channel_Mask = ret;
+ aml_aiu_update_bits(AIU_I2S_OUT_CFG,
+ 0x3 << 6,
+ p_aml_audio->Speaker3_Channel_Mask << 6);
}
}
static void parse_dac_channel_mask(struct snd_soc_card *card)
{
+ struct aml_audio_private_data *p_aml_audio;
struct device_node *np;
const char *str;
int ret;
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+
/* channel mask */
np = of_get_child_by_name(card->dev->of_node,
"Channel_Mask");
of_property_read_string(np, "DAC0_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- DAC0_Channel_Mask = ret;
+ p_aml_audio->DAC0_Channel_Mask = ret;
aml_aiu_update_bits(AIU_ACODEC_CTRL, 0x3,
- DAC0_Channel_Mask);
+ p_aml_audio->DAC0_Channel_Mask);
}
/*Acodec DAC1 selects i2s source*/
of_property_read_string(np, "DAC1_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- DAC1_Channel_Mask = ret;
+ p_aml_audio->DAC1_Channel_Mask = ret;
aml_aiu_update_bits(AIU_ACODEC_CTRL, 0x3 << 8,
- DAC1_Channel_Mask << 8);
+ p_aml_audio->DAC1_Channel_Mask << 8);
}
}
static void parse_eqdrc_channel_mask(struct snd_soc_card *card)
{
+ struct aml_audio_private_data *p_aml_audio;
struct device_node *np;
const char *str;
int ret;
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+
/* channel mask */
np = of_get_child_by_name(card->dev->of_node,
"Channel_Mask");
of_property_read_string(np, "EQ_DRC_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- EQ_DRC_Channel_Mask = ret;
+ p_aml_audio->EQ_DRC_Channel_Mask = ret;
/*i2s in sel*/
aml_eqdrc_update_bits(AED_TOP_CTL, (0x7 << 1),
- (EQ_DRC_Channel_Mask << 1));
+ (p_aml_audio->EQ_DRC_Channel_Mask << 1));
aml_eqdrc_write(AED_ED_CTL, 1);
/* disable noise gate*/
aml_eqdrc_write(AED_NG_CTL, (3 << 30));
"Spdif_samesource_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- Spdif_samesource_Channel_Mask = ret;
+ p_aml_audio->Spdif_samesource_Channel_Mask = ret;
aml_aiu_update_bits(AIU_I2S_MISC, 0x7 << 5,
- Spdif_samesource_Channel_Mask << 5);
+ p_aml_audio->Spdif_samesource_Channel_Mask << 5);
}
}
/* spdif same source with i2s */
static void parse_samesource_channel_mask(struct snd_soc_card *card)
{
+ struct aml_audio_private_data *p_aml_audio;
struct device_node *np;
const char *str;
int ret;
+ p_aml_audio = snd_soc_card_get_drvdata(card);
+
/* channel mask */
np = of_get_child_by_name(card->dev->of_node,
"Channel_Mask");
"Spdif_samesource_Channel_Mask", &str);
ret = check_channel_mask(str);
if (ret >= 0) {
- Spdif_samesource_Channel_Mask = ret;
+ p_aml_audio->Spdif_samesource_Channel_Mask = ret;
aml_aiu_update_bits(AIU_I2S_MISC, 0x7 << 5,
- Spdif_samesource_Channel_Mask << 5);
+ p_aml_audio->Spdif_samesource_Channel_Mask << 5);
}
}
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
int atmos_edid_enable;
#endif
+ int aml_audio_Hardware_resample;
+ int Speaker0_Channel_Mask;
+ int Speaker1_Channel_Mask;
+ int Speaker2_Channel_Mask;
+ int Speaker3_Channel_Mask;
+ int EQ_DRC_Channel_Mask;
+ int DAC0_Channel_Mask;
+ int DAC1_Channel_Mask;
+ int Spdif_samesource_Channel_Mask;
+ int audio_in_GPIO;
+ int audio_in_GPIO_inv;
+ struct gpio_desc *source_switch;
};
struct codec_info {