From 659be832df94011d3eedbb510a0c8d9c828ca8bb Mon Sep 17 00:00:00 2001 From: hongmin hua Date: Tue, 27 Mar 2018 19:40:05 +0800 Subject: [PATCH] cec: add the control of arc line[1/2] PD#159184: cec: add the control of arc line add audio control interface for switch Change-Id: I7981451c449435e5974c8321d99fc6c31e66f957 Signed-off-by: hongmin hua Signed-off-by: Zhe Wang --- drivers/amlogic/cec/hdmi_ao_cec.c | 21 +- drivers/amlogic/cec/hdmi_ao_cec.h | 2 +- .../media/vout/hdmi_tx/hdmi_tx_cec_20.h | 1 + sound/soc/amlogic/meson/tv.c | 291 +++++++++++++++++- sound/soc/amlogic/meson/tv.h | 6 + 5 files changed, 312 insertions(+), 9 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index c9ee1334e504..cbb8fb76eab4 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -806,6 +806,18 @@ static void cec_clear_logical_addr(void) udelay(100); } +void cec_enable_arc_pin(bool enable) +{ + /* select arc according arg */ + if (enable) + hdmirx_wr_top(TOP_ARCTX_CNTL, 0x01); + else + hdmirx_wr_top(TOP_ARCTX_CNTL, 0x00); + CEC_INFO("set arc en:%d, reg:%lx\n", + enable, hdmirx_rd_top(TOP_ARCTX_CNTL)); +} +EXPORT_SYMBOL(cec_enable_arc_pin); + int cec_rx_buf_check(void) { unsigned int rx_num_msg; @@ -2312,13 +2324,8 @@ static long hdmitx_cec_ioctl(struct file *f, break; case CEC_IOC_SET_ARC_ENABLE: - /* select arc according arg */ - if (arg) - hdmirx_wr_top(TOP_ARCTX_CNTL, 0x01); - else - hdmirx_wr_top(TOP_ARCTX_CNTL, 0x00); - CEC_INFO("set arc en:%ld, reg:%lx\n", - arg, hdmirx_rd_top(TOP_ARCTX_CNTL)); + CEC_INFO("Ioc set arc pin\n"); + cec_enable_arc_pin(arg); break; default: diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index a6d8ebf4fcab..586dfb4f6104 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -18,7 +18,7 @@ #ifndef __AO_CEC_H__ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "2018/03/09\n" +#define CEC_DRIVER_VERSION "2018/03/27\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "cec" diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h index 78e69ca4a504..6e3bf3e5d5a1 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h @@ -327,5 +327,6 @@ enum cec_device_menu_state_e { int cec_ll_tx(const unsigned char *msg, unsigned char len); int cec_ll_rx(unsigned char *msg, unsigned char *len); +extern void cec_enable_arc_pin(bool enable); #endif diff --git a/sound/soc/amlogic/meson/tv.c b/sound/soc/amlogic/meson/tv.c index ccf4e74aae32..307b93812367 100644 --- a/sound/soc/amlogic/meson/tv.c +++ b/sound/soc/amlogic/meson/tv.c @@ -43,6 +43,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_AO_CEC +#include +#endif #include "i2s.h" #include "audio_hw.h" @@ -422,6 +425,261 @@ static int set_internal_EQ_volume( return 0; } +#ifdef CONFIG_AMLOGIC_AO_CEC +/* call HDMI CEC API to enable arc audio */ +static void aml_switch_arc_audio(bool enable) +{ + cec_enable_arc_pin(enable); +} +static int aml_get_arc_audio(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); + ucontrol->value.integer.value[0] = p_aml_audio->arc_enable; + return 0; +} +static int aml_set_arc_audio(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; + bool enable = ucontrol->value.integer.value[0]; + + p_aml_audio = snd_soc_card_get_drvdata(card); + aml_switch_arc_audio(enable); + p_aml_audio->arc_enable = enable; + return 0; +} +#endif + +#ifdef CONFIG_TVIN_HDMI +/* call HDMI CEC API to enable arc audio */ +static int aml_set_atmos_audio_edid(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; + bool enable = ucontrol->value.integer.value[0]; + + p_aml_audio = snd_soc_card_get_drvdata(card); + rx_set_atmos_flag(enable); + p_aml_audio->atmos_edid_enable = enable; + return 0; +} +static int aml_get_atmos_audio_edid(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); + ucontrol->value.integer.value[0] = p_aml_audio->atmos_edid_enable; + return 0; +} +/* copy from drivers/amlogic/tvin/hdmirx/hdmirx_drv.h */ +struct hdmi_in_audio_status { + /*audio packets received*/ + bool aud_rcv_flag; + /*audio stable status*/ + bool aud_stb_flag; + /*audio sample rate*/ + int aud_sr; + /*audio channel count*/ + /*0: refer to stream header,*/ + /*1: 2ch, 2: 3ch, 3: 4ch, 4: 5ch,*/ + /*5: 6ch, 6: 7ch, 7: 8ch*/ + int aud_channel_cnt; + /*audio coding type*/ + /*0: refer to stream header, 1: IEC60958 PCM,*/ + /*2: AC-3, 3: MPEG1 (Layers 1 and 2),*/ + /*4: MP3 (MPEG1 Layer 3), 5: MPEG2 (multichannel),*/ + /*6: AAC, 7: DTS, 8: ATRAC, 9: One Bit Audio,*/ + /*10: Dolby Digital Plus, 11: DTS-HD,*/ + /*12: MAT (MLP), 13: DST, 14: WMA Pro*/ + int aud_type; +}; +static const char *const hdmi_in_is_stable[] = { + "false", + "true" +}; +static const char *const hdmi_in_samplerate[] = { + "N/A", + "32000", + "44100", + "48000", + "88200", + "96000", + "176400", + "192000" +}; +static const char *const hdmi_in_channels[] = { + "NONE", + "2", + "3", + "4", + "5", + "6", + "7", + "8" +}; +enum HDMIIN_format { + REFER_TO_HEADER = 0, + LPCM = 1, + AC3, + MPEG1, + MP3, + MPEG2, + AAC, + DTS, + ATRAC, + ONE_BIT_AUDIO, + DDP, + DTS_HD, + MAT, + DST, + WMA_PRO +}; +static const char * const hdmi_in_format[] = { + "REFER_TO_HEADER", + "LPCM", + "AC3", + "MPEG1", + "MP3", + "MPEG2", + "AAC", + "DTS", + "ATRAC", + "ONE_BIT_AUDIO", + "DDP", + "DTS_HD", + "MAT", + "DST", + "WMA_PRO" +}; +static const struct soc_enum hdmi_in_status_enum[] = { + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_is_stable), + hdmi_in_is_stable), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_samplerate), + hdmi_in_samplerate), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_channels), + hdmi_in_channels), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_format), + hdmi_in_format) +}; +static int aml_get_hdmiin_audio_stable(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hdmi_in_audio_status aud_sts; + struct rx_audio_stat_s *rx_aud_sts; + + rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts; + rx_get_audio_status(rx_aud_sts); + ucontrol->value.integer.value[0] = aud_sts.aud_rcv_flag; + return 0; +} +static int aml_get_hdmiin_audio_samplerate(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hdmi_in_audio_status aud_sts; + struct rx_audio_stat_s *rx_aud_sts; + int val = 0; + + rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts; + rx_get_audio_status(rx_aud_sts); + switch (aud_sts.aud_sr) { + case 0: + val = 0; + break; + case 32000: + val = 1; + break; + case 44100: + val = 2; + break; + case 48000: + val = 3; + break; + case 88200: + val = 4; + break; + case 96000: + val = 5; + break; + case 176400: + val = 6; + break; + case 192000: + val = 7; + break; + default: + pr_err("HDMIRX samplerate not support: %d\n", aud_sts.aud_sr); + break; + } + ucontrol->value.integer.value[0] = val; + return 0; +} +static int aml_get_hdmiin_audio_channels(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rx_audio_stat_s *rx_aud_sts; + struct hdmi_in_audio_status aud_sts; + + rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts; + rx_get_audio_status(rx_aud_sts); + if (aud_sts.aud_channel_cnt <= 7) + ucontrol->value.integer.value[0] = aud_sts.aud_channel_cnt; + return 0; +} +static int aml_get_hdmiin_audio_format(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rx_audio_stat_s *rx_aud_sts; + struct hdmi_in_audio_status aud_sts; + + rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts; + rx_get_audio_status(rx_aud_sts); + if (aud_sts.aud_type <= 14) + ucontrol->value.integer.value[0] = aud_sts.aud_type; + return 0; +} +#endif /* CONFIG_TVIN_HDMI */ +#ifdef CONFIG_AM_DVB +static const char *const atv_audio_is_stable[] = { + "false", + "true" +}; +static const struct soc_enum atv_audio_status_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(atv_audio_is_stable), + atv_audio_is_stable); +static int aml_get_atv_audio_stable(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int state = 0; + + aml_fe_get_atvaudio_state(&state); + ucontrol->value.integer.value[0] = state; + return 0; +} +#endif /* CONFIG_AM_DVB */ +#ifdef CONFIG_TVIN_VDIN +static const char *const av_audio_is_stable[] = { + "false", + "true" +}; +static const struct soc_enum av_audio_status_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(av_audio_is_stable), + av_audio_is_stable); +static int aml_get_av_audio_stable(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = tvin_get_av_status(); + return 0; +} +#endif /* CONFIG_TVIN_VDIN */ + static const struct snd_kcontrol_new av_controls[] = { SOC_ENUM_EXT("AudioIn Switch", audio_in_switch_enum, @@ -449,7 +707,38 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { hardware_resample_enum, aml_hardware_resample_get_enum, aml_hardware_resample_set_enum), - +#ifdef CONFIG_AMLOGIC_AO_CEC + SOC_SINGLE_BOOL_EXT("HDMI ARC Switch", 0, + aml_get_arc_audio, + aml_set_arc_audio), +#endif +#ifdef CONFIG_TVIN_HDMI + SOC_ENUM_EXT("HDMIIN audio stable", hdmi_in_status_enum[0], + aml_get_hdmiin_audio_stable, + NULL), + SOC_ENUM_EXT("HDMIIN audio samplerate", hdmi_in_status_enum[1], + aml_get_hdmiin_audio_samplerate, + NULL), + SOC_ENUM_EXT("HDMIIN audio channels", hdmi_in_status_enum[2], + aml_get_hdmiin_audio_channels, + NULL), + SOC_ENUM_EXT("HDMIIN audio format", hdmi_in_status_enum[3], + aml_get_hdmiin_audio_format, + NULL), + SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch", 0, + aml_get_atmos_audio_edid, + aml_set_atmos_audio_edid), +#endif +#ifdef CONFIG_AM_DVB + SOC_ENUM_EXT("ATV audio stable", atv_audio_status_enum, + aml_get_atv_audio_stable, + NULL), +#endif +#ifdef CONFIG_TVIN_VDIN + SOC_ENUM_EXT("AV audio stable", av_audio_status_enum, + aml_get_av_audio_stable, + NULL), +#endif }; static int aml_get_eqdrc_reg(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/amlogic/meson/tv.h b/sound/soc/amlogic/meson/tv.h index 56719344fcff..ab04e427bfe7 100644 --- a/sound/soc/amlogic/meson/tv.h +++ b/sound/soc/amlogic/meson/tv.h @@ -68,6 +68,12 @@ struct aml_audio_private_data { /* tv info */ struct aml_card_info *cardinfo; +#ifdef CONFIG_AMLOGIC_AO_CEC + int arc_enable; +#endif +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI + int atmos_edid_enable; +#endif }; struct codec_info {