From abf5acf549cb57c2acff1bf8286ed80238e358df Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Wed, 8 Feb 2017 19:02:48 +0800 Subject: [PATCH] hdmitx: add hdmitx driver PD#138714: add hdmitx driver Change-Id: Iffe4a2a88633d3e3d67ba1aec4c6ea5c2a912aec Signed-off-by: Zongdong Jiao --- MAINTAINERS | 7 + arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts | 19 + arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 19 + arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts | 19 + arch/arm64/boot/dts/amlogic/gxm_skt.dts | 19 + arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/media/vout/Kconfig | 1 + drivers/amlogic/media/vout/Makefile | 1 + drivers/amlogic/media/vout/hdmitx/Kconfig | 12 + drivers/amlogic/media/vout/hdmitx/Makefile | 3 + .../media/vout/hdmitx/hdmi_common/Makefile | 3 + .../vout/hdmitx/hdmi_common/hdmi_parameters.c | 2019 +++++++ .../media/vout/hdmitx/hdmi_tx_20/Makefile | 8 + .../hdcp22/ESMHostLibDriverErrors.h | 49 + .../hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h | 167 + .../vout/hdmitx/hdmi_tx_20/hdcp22/Makefile | 1 + .../hdmi_tx_20/hdcp22/elliptic_std_def.h | 78 + .../hdmi_tx_20/hdcp22/elliptic_system_types.h | 79 + .../vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c | 1213 +++++ .../hdmi_tx_20/hdcp22/host_driver_linux_if.h | 152 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c | 238 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 2406 +++++++++ .../vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c | 155 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h | 35 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 3064 +++++++++++ .../vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c | 59 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c | 774 +++ .../media/vout/hdmitx/hdmi_tx_20/hw/Makefile | 2 + .../media/vout/hdmitx/hdmi_tx_20/hw/common.h | 54 + .../vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c | 1013 ++++ .../media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h | 45 + .../vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c | 600 +++ .../vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h | 97 + .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c | 205 + .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 4628 +++++++++++++++++ .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h | 1059 ++++ .../media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c | 879 ++++ .../media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h | 58 + .../media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c | 92 + .../media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c | 330 ++ .../vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c | 90 + .../vout/hdmitx/hdmi_tx_20/hw/mach_reg.h | 834 +++ .../media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c | 305 ++ .../media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c | 60 + .../vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h | 21 + .../media/vout/hdmi_tx/enc_clk_config.h | 50 + .../amlogic/media/vout/hdmi_tx/hdmi_common.h | 578 ++ .../amlogic/media/vout/hdmi_tx/hdmi_config.h | 78 + .../media/vout/hdmi_tx/hdmi_info_global.h | 339 ++ .../media/vout/hdmi_tx/hdmi_tx_cec_20.h | 329 ++ .../media/vout/hdmi_tx/hdmi_tx_compliance.h | 28 + .../amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h | 93 + .../amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h | 24 + .../media/vout/hdmi_tx/hdmi_tx_module.h | 592 +++ include/linux/amlogic/media/vout/vinfo.h | 54 + .../linux/amlogic/media/vout/vout_notify.h | 2 +- 56 files changed, 23139 insertions(+), 1 deletion(-) create mode 100644 drivers/amlogic/media/vout/hdmitx/Kconfig create mode 100644 drivers/amlogic/media/vout/hdmitx/Makefile create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_common/Makefile create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/Makefile create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostLibDriverErrors.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/Makefile create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_std_def.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_system_types.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/host_driver_linux_if.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/common.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c create mode 100644 drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/enc_clk_config.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_config.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_info_global.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_compliance.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h create mode 100644 include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h diff --git a/MAINTAINERS b/MAINTAINERS index 4e10b1d7c82a..f2896f698d5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13464,6 +13464,13 @@ AMLOGIC reboot M: Jianxin Pan F: drivers/amlogic/reboot/* +HDMITX OUTPUT DRIVER +M: Zongdong Jiao +S: Maintained +F: drivers/amlogic/media/vout/hdmitx/* +F: drivers/amlogic/media/vout/hdmitx/hdcp/* +F: include/linux/amlogic/media/vout/hdmi_tx/* + AMLOGIC DWC_OTG USB M: Yue Wang F: drivers/amlogic/usb/* diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts index f625cf4892cb..6202f2532022 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts @@ -200,6 +200,25 @@ status = "okay"; }; + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="hdmitx_hpd", "hdmitx_ddc"; + pinctrl-0=<&hdmitx_hpd>; + pinctrl-1=<&hdmitx_ddc>; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + product_desc = "MBox Meson Ref"; /* Max Chars: 16 */ + }; + }; + pwm { compatible = "amlogic, meson-pwm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index b9589ecaa1ce..c86846170cdf 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -278,6 +278,25 @@ status = "okay"; }; + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="hdmitx_hpd", "hdmitx_ddc"; + pinctrl-0=<&hdmitx_hpd>; + pinctrl-1=<&hdmitx_ddc>; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + product_desc = "MBox Meson Ref"; /* Max Chars: 16 */ + }; + }; + pwm { compatible = "amlogic, meson-pwm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index 6922f2bf9939..a87c39f55a78 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -277,6 +277,25 @@ status = "okay"; }; + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="hdmitx_hpd", "hdmitx_ddc"; + pinctrl-0=<&hdmitx_hpd>; + pinctrl-1=<&hdmitx_ddc>; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + product_desc = "MBox Meson Ref"; /* Max Chars: 16 */ + }; + }; + pwm { compatible = "amlogic, meson-pwm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_skt.dts b/arch/arm64/boot/dts/amlogic/gxm_skt.dts index 7e7b687bdecf..78811453172e 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_skt.dts @@ -245,6 +245,25 @@ interrupts = <0 89 1>; interrupt-names = "rdma"; }; + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="hdmitx_hpd", "hdmitx_ddc"; + pinctrl-0=<&hdmitx_hpd>; + pinctrl-1=<&hdmitx_ddc>; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + ranges; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + product_desc = "MBox Meson Ref"; /* Max Chars: 16 */ + }; + }; }; &efuse { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 6eaff5855c60..ea32db602e66 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -206,6 +206,7 @@ CONFIG_AMLOGIC_MEDIA_FB=y CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA=y CONFIG_AMLOGIC_MEDIA_FB_OSD2_ENABLE=y CONFIG_AMLOGIC_MEDIA_FB_OSD2_CURSOR=y +CONFIG_AMLOGIC_HDMITX=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y diff --git a/drivers/amlogic/media/vout/Kconfig b/drivers/amlogic/media/vout/Kconfig index 1afa614d7ce9..56f047765cfd 100644 --- a/drivers/amlogic/media/vout/Kconfig +++ b/drivers/amlogic/media/vout/Kconfig @@ -17,6 +17,7 @@ if AMLOGIC_VOUT source "drivers/amlogic/media/vout/vout_serve/Kconfig" source "drivers/amlogic/media/vout/cvbs/Kconfig" source "drivers/amlogic/media/vout/vdac/Kconfig" +source "drivers/amlogic/media/vout/hdmitx/Kconfig" endif diff --git a/drivers/amlogic/media/vout/Makefile b/drivers/amlogic/media/vout/Makefile index 186b11a59782..27deec7de4d8 100644 --- a/drivers/amlogic/media/vout/Makefile +++ b/drivers/amlogic/media/vout/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_AMLOGIC_VOUT_SERVE) += vout_serve/ obj-$(CONFIG_AMLOGIC_CVBS_OUTPUT) += cvbs/ obj-$(CONFIG_AMLOGIC_VDAC) += vdac/ +obj-$(CONFIG_AMLOGIC_HDMITX) += hdmitx/ diff --git a/drivers/amlogic/media/vout/hdmitx/Kconfig b/drivers/amlogic/media/vout/hdmitx/Kconfig new file mode 100644 index 000000000000..a977b4eada70 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/Kconfig @@ -0,0 +1,12 @@ +# +# HDMITX +# +menu "Amlogic HDMITX Module" + +config AMLOGIC_HDMITX + bool "HDMITX Output Enable" + default n + help + HDMITX Output Enable + +endmenu diff --git a/drivers/amlogic/media/vout/hdmitx/Makefile b/drivers/amlogic/media/vout/hdmitx/Makefile new file mode 100644 index 000000000000..38426ca6d7ae --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/Makefile @@ -0,0 +1,3 @@ +ifdef CONFIG_AMLOGIC_HDMITX +obj-$(CONFIG_AMLOGIC_HDMITX) += hdmi_tx_20/ hdmi_common/ +endif diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/Makefile b/drivers/amlogic/media/vout/hdmitx/hdmi_common/Makefile new file mode 100644 index 000000000000..6964e1c3a618 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/Makefile @@ -0,0 +1,3 @@ +obj-y += hdmi_common.o + +hdmi_common-objs := hdmi_parameters.o diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c new file mode 100644 index 000000000000..322e7e83c506 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -0,0 +1,2019 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +static struct hdmi_format_para fmt_para_1920x1080p60_16x9 = { + .vic = HDMI_1920x1080p60_16x9, + .name = "1920x1080p60hz", + .sname = "1080p60hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 148500, + .timing = { + .pixel_freq = 148500, + .frac_freq = 148352, + .h_freq = 67500, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2200, + .h_blank = 280, + .h_front = 88, + .h_sync = 44, + .h_back = 148, + .v_active = 1080, + .v_total = 1125, + .v_blank = 45, + .v_front = 4, + .v_sync = 5, + .v_back = 36, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080p60hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080p30_16x9 = { + .vic = HDMI_1920x1080p30_16x9, + .name = "1920x1080p30hz", + .sname = "1080p30hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .frac_freq = 74176, + .h_freq = 67500, + .v_freq = 30000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2200, + .h_blank = 280, + .h_front = 88, + .h_sync = 44, + .h_back = 148, + .v_active = 1080, + .v_total = 1125, + .v_blank = 45, + .v_front = 4, + .v_sync = 5, + .v_back = 36, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080p30hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 30, + .sync_duration_den = 1, + .video_clk = 74250000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080p50_16x9 = { + .vic = HDMI_1920x1080p50_16x9, + .name = "1920x1080p50hz", + .sname = "1080p50hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 148500, + .timing = { + .pixel_freq = 148500, + .h_freq = 56250, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2640, + .h_blank = 720, + .h_front = 528, + .h_sync = 44, + .h_back = 148, + .v_active = 1080, + .v_total = 1125, + .v_blank = 45, + .v_front = 4, + .v_sync = 5, + .v_back = 36, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080p50hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 148500000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080p25_16x9 = { + .vic = HDMI_1920x1080p25_16x9, + .name = "1920x1080p25hz", + .sname = "1080p25hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .h_freq = 56250, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2640, + .h_blank = 720, + .h_front = 528, + .h_sync = 44, + .h_back = 148, + .v_active = 1080, + .v_total = 1125, + .v_blank = 45, + .v_front = 4, + .v_sync = 5, + .v_back = 36, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080p25hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 25, + .sync_duration_den = 1, + .video_clk = 74250000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080p24_16x9 = { + .vic = HDMI_1920x1080p24_16x9, + .name = "1920x1080p24hz", + .sname = "1080p24hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .frac_freq = 74176, + .h_freq = 27000, + .v_freq = 24000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2750, + .h_blank = 830, + .h_front = 638, + .h_sync = 44, + .h_back = 148, + .v_active = 1080, + .v_total = 1125, + .v_blank = 45, + .v_front = 4, + .v_sync = 5, + .v_back = 36, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080p24hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 24, + .sync_duration_den = 1, + .video_clk = 74250000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p30_16x9 = { + .vic = HDMI_3840x2160p30_16x9, + .name = "3840x2160p30hz", + .sname = "2160p30hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .frac_freq = 296703, + .h_freq = 67500, + .v_freq = 30000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 4400, + .h_blank = 560, + .h_front = 176, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p30hz", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 30, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p60_16x9 = { + .vic = HDMI_3840x2160p60_16x9, + .name = "3840x2160p60hz", + .sname = "2160p60hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 1, + .tmds_clk_div40 = 1, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .frac_freq = 593407, + .h_freq = 135000, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 4400, + .h_blank = 560, + .h_front = 176, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p60hz", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p50_16x9 = { + .vic = HDMI_3840x2160p50_16x9, + .name = "3840x2160p50hz", + .sname = "2160p50hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 1, + .tmds_clk_div40 = 1, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .h_freq = 112500, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 5280, + .h_blank = 1440, + .h_front = 1056, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p50hz", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p25_16x9 = { + .vic = HDMI_3840x2160p25_16x9, + .name = "3840x2160p25hz", + .sname = "2160p25hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .h_freq = 56250, + .v_freq = 25000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 5280, + .h_blank = 1440, + .h_front = 1056, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p25hz", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 25, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p24_16x9 = { + .vic = HDMI_3840x2160p24_16x9, + .name = "3840x2160p24hz", + .sname = "2160p24hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .frac_freq = 296703, + .h_freq = 54000, + .v_freq = 24000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 5500, + .h_blank = 1660, + .h_front = 1276, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p24hz", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 24, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p24_256x135 = { + .vic = HDMI_4096x2160p24_256x135, + .name = "4096x2160p24hz", + .sname = "smpte24hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .frac_freq = 296703, + .h_freq = 54000, + .v_freq = 24000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 5500, + .h_blank = 1404, + .h_front = 1020, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte24hz", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 24, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p25_256x135 = { + .vic = HDMI_4096x2160p25_256x135, + .name = "4096x2160p25hz", + .sname = "smpte25hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .h_freq = 56250, + .v_freq = 25000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 5280, + .h_blank = 1184, + .h_front = 968, + .h_sync = 88, + .h_back = 128, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte25hz", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 25, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p30_256x135 = { + .vic = HDMI_4096x2160p30_256x135, + .name = "4096x2160p30hz", + .sname = "smpte30hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 297000, + .timing = { + .pixel_freq = 297000, + .frac_freq = 296703, + .h_freq = 67500, + .v_freq = 30000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 4400, + .h_blank = 304, + .h_front = 88, + .h_sync = 88, + .h_back = 128, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte30hz", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 30, + .sync_duration_den = 1, + .video_clk = 297000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p50_256x135 = { + .vic = HDMI_4096x2160p50_256x135, + .name = "4096x2160p50hz", + .sname = "smpte50hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 1, + .tmds_clk_div40 = 1, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .h_freq = 112500, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 5280, + .h_blank = 1184, + .h_front = 968, + .h_sync = 88, + .h_back = 128, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte50hz", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p60_256x135 = { + .vic = HDMI_4096x2160p60_256x135, + .name = "4096x2160p60hz", + .sname = "smpte60hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 1, + .tmds_clk_div40 = 1, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .frac_freq = 593407, + .h_freq = 135000, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 4400, + .h_blank = 304, + .h_front = 88, + .h_sync = 88, + .h_back = 128, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte60hz", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080i60_16x9 = { + .vic = HDMI_1920x1080i60_16x9, + .name = "1920x1080i60hz", + .sname = "1080i60hz", + .pixel_repetition_factor = 0, + .progress_mode = 0, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .frac_freq = 74176, + .h_freq = 33750, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2200, + .h_blank = 280, + .h_front = 88, + .h_sync = 44, + .h_back = 148, + .v_active = 1080/2, + .v_total = 1125, + .v_blank = 45/2, + .v_front = 2, + .v_sync = 5, + .v_back = 15, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080i60hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1920x1080i50_16x9 = { + .vic = HDMI_1920x1080i50_16x9, + .name = "1920x1080i50hz", + .sname = "1080i50hz", + .pixel_repetition_factor = 0, + .progress_mode = 0, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .h_freq = 28125, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1920, + .h_total = 2640, + .h_blank = 720, + .h_front = 528, + .h_sync = 44, + .h_back = 148, + .v_active = 1080/2, + .v_total = 1125, + .v_blank = 45/2, + .v_front = 2, + .v_sync = 5, + .v_back = 15, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "1080i50hz", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 148500000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1280x720p60_16x9 = { + .vic = HDMI_1280x720p60_16x9, + .name = "1280x720p60hz", + .sname = "720p60hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .frac_freq = 74176, + .h_freq = 45000, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1280, + .h_total = 1650, + .h_blank = 370, + .h_front = 110, + .h_sync = 40, + .h_back = 220, + .v_active = 720, + .v_total = 750, + .v_blank = 30, + .v_front = 5, + .v_sync = 5, + .v_back = 20, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "720p60hz", + .mode = VMODE_HDMI, + .width = 1280, + .height = 720, + .field_height = 720, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 74250000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_1280x720p50_16x9 = { + .vic = HDMI_1280x720p50_16x9, + .name = "1280x720p50hz", + .sname = "720p50hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 74250, + .timing = { + .pixel_freq = 74250, + .h_freq = 37500, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 1280, + .h_total = 1980, + .h_blank = 700, + .h_front = 440, + .h_sync = 40, + .h_back = 220, + .v_active = 720, + .v_total = 750, + .v_blank = 30, + .v_front = 5, + .v_sync = 5, + .v_back = 20, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "720p50hz", + .mode = VMODE_HDMI, + .width = 1280, + .height = 720, + .field_height = 720, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 74250000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_720x480p60_16x9 = { + .vic = HDMI_720x480p60_16x9, + .name = "720x480p60hz", + .sname = "480p60hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 27027, + .timing = { + .pixel_freq = 27027, + .frac_freq = 27000, + .h_freq = 31469, + .v_freq = 59940, + .vsync_polarity = 0, + .hsync_polarity = 0, + .h_active = 720, + .h_total = 858, + .h_blank = 138, + .h_front = 16, + .h_sync = 62, + .h_back = 60, + .v_active = 480, + .v_total = 525, + .v_blank = 45, + .v_front = 9, + .v_sync = 6, + .v_back = 30, + .v_sync_ln = 7, + }, + .hdmitx_vinfo = { + .name = "480p60hz", + .mode = VMODE_HDMI, + .width = 720, + .height = 480, + .field_height = 480, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 27000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_720x480i60_16x9 = { + .vic = HDMI_720x480i60_16x9, + .name = "720x480i60hz", + .sname = "480i60hz", + .pixel_repetition_factor = 1, + .progress_mode = 0, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 27027, + .timing = { + .pixel_freq = 27027, + .frac_freq = 27000, + .h_freq = 15734, + .v_freq = 59940, + .vsync_polarity = 0, + .hsync_polarity = 0, + .h_active = 1440, + .h_total = 1716, + .h_blank = 276, + .h_front = 38, + .h_sync = 124, + .h_back = 114, + .v_active = 480/2, + .v_total = 525, + .v_blank = 45/2, + .v_front = 4, + .v_sync = 3, + .v_back = 15, + .v_sync_ln = 4, + }, + .hdmitx_vinfo = { + .name = "480i60hz", + .mode = VMODE_HDMI, + .width = 720, + .height = 480, + .field_height = 240, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 27000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_720x576p50_16x9 = { + .vic = HDMI_720x576p50_16x9, + .name = "720x576p50hz", + .sname = "576p50hz", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 27000, + .timing = { + .pixel_freq = 27000, + .h_freq = 31250, + .v_freq = 50000, + .vsync_polarity = 0, + .hsync_polarity = 0, + .h_active = 720, + .h_total = 864, + .h_blank = 144, + .h_front = 12, + .h_sync = 64, + .h_back = 68, + .v_active = 576, + .v_total = 625, + .v_blank = 49, + .v_front = 5, + .v_sync = 5, + .v_back = 39, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "576p50hz", + .mode = VMODE_HDMI, + .width = 720, + .height = 576, + .field_height = 576, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 27000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_720x576i50_16x9 = { + .vic = HDMI_720x576i50_16x9, + .name = "720x576i50hz", + .sname = "576i50hz", + .pixel_repetition_factor = 1, + .progress_mode = 0, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 27000, + .timing = { + .pixel_freq = 27000, + .h_freq = 15625, + .v_freq = 50000, + .vsync_polarity = 0, + .hsync_polarity = 0, + .h_active = 1440, + .h_total = 1728, + .h_blank = 288, + .h_front = 24, + .h_sync = 126, + .h_back = 138, + .v_active = 576/2, + .v_total = 625, + .v_blank = 49/2, + .v_front = 2, + .v_sync = 3, + .v_back = 19, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "576i50hz", + .mode = VMODE_HDMI, + .width = 720, + .height = 576, + .field_height = 288, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 27000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +/* the following are for Y420 mode*/ + +static struct hdmi_format_para fmt_para_3840x2160p50_16x9_y420 = { + .vic = HDMI_3840x2160p50_16x9_Y420, + .name = "3840x2160p50hz420", + .sname = "2160p50hz420", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .h_freq = 112500, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 5280, + .h_blank = 1440, + .h_front = 1056, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p50hz420", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_4096x2160p50_256x135_y420 = { + .vic = HDMI_4096x2160p50_256x135_Y420, + .name = "4096x2160p50hz420", + .sname = "smpte50hz420", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .h_freq = 112500, + .v_freq = 50000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 5280, + .h_blank = 1184, + .h_front = 968, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte50hz420", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 50, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_3840x2160p60_16x9_y420 = { + .vic = HDMI_3840x2160p60_16x9_Y420, + .name = "3840x2160p60hz420", + .sname = "2160p60hz420", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .frac_freq = 593407, + .h_freq = 135000, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 3840, + .h_total = 4400, + .h_blank = 560, + .h_front = 176, + .h_sync = 88, + .h_back = 296, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "2160p60hz420", + .mode = VMODE_HDMI, + .width = 3840, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + + +static struct hdmi_format_para fmt_para_4096x2160p60_256x135_y420 = { + .vic = HDMI_4096x2160p60_256x135_Y420, + .name = "4096x2160p60hz420", + .sname = "smpte60hz420", + .pixel_repetition_factor = 0, + .progress_mode = 1, + .scrambler_en = 0, + .tmds_clk_div40 = 0, + .tmds_clk = 594000, + .timing = { + .pixel_freq = 594000, + .frac_freq = 593407, + .h_freq = 135000, + .v_freq = 60000, + .vsync_polarity = 1, + .hsync_polarity = 1, + .h_active = 4096, + .h_total = 4400, + .h_blank = 304, + .h_front = 88, + .h_sync = 88, + .h_back = 128, + .v_active = 2160, + .v_total = 2250, + .v_blank = 90, + .v_front = 8, + .v_sync = 10, + .v_back = 72, + .v_sync_ln = 1, + }, + .hdmitx_vinfo = { + .name = "smpte60hz420", + .mode = VMODE_HDMI, + .width = 4096, + .height = 2160, + .field_height = 2160, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 594000000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +static struct hdmi_format_para fmt_para_non_hdmi_fmt = { + .vic = HDMI_Unknown, + .name = "invalid", + .sname = "invalid", +}; + +/* null mode is used for HDMI, such as current mode is 1080p24hz + * but want to switch to 1080p 23.976hz + * so 'echo null > /sys/class/display/mode' firstly, then set + * 'echo 1 > /sys/class/amhdmitx/amhdmitx0/frac_rate_policy' + * and 'echo 1080p24hz > /sys/class/display/mode' + */ +static struct hdmi_format_para fmt_para_null_hdmi_fmt = { + .vic = HDMI_Unknown, + .name = "null", + .sname = "null", + .hdmitx_vinfo = { + .name = "null", + .mode = VMODE_HDMI, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, + .viu_color_fmt = COLOR_FMT_YUV444, + }, +}; + +/* end of Y420 modes*/ + +static struct hdmi_format_para *all_fmt_paras[] = { + &fmt_para_3840x2160p60_16x9, + &fmt_para_3840x2160p50_16x9, + &fmt_para_3840x2160p30_16x9, + &fmt_para_3840x2160p25_16x9, + &fmt_para_3840x2160p24_16x9, + &fmt_para_4096x2160p24_256x135, + &fmt_para_4096x2160p25_256x135, + &fmt_para_4096x2160p30_256x135, + &fmt_para_4096x2160p50_256x135, + &fmt_para_4096x2160p60_256x135, + &fmt_para_1920x1080p25_16x9, + &fmt_para_1920x1080p30_16x9, + &fmt_para_1920x1080p50_16x9, + &fmt_para_1920x1080p60_16x9, + &fmt_para_1920x1080p24_16x9, + &fmt_para_1920x1080i60_16x9, + &fmt_para_1920x1080i50_16x9, + &fmt_para_1280x720p60_16x9, + &fmt_para_1280x720p50_16x9, + &fmt_para_720x480p60_16x9, + &fmt_para_720x480i60_16x9, + &fmt_para_720x576p50_16x9, + &fmt_para_720x576i50_16x9, + &fmt_para_3840x2160p60_16x9_y420, + &fmt_para_4096x2160p60_256x135_y420, + &fmt_para_3840x2160p50_16x9_y420, + &fmt_para_4096x2160p50_256x135_y420, + &fmt_para_null_hdmi_fmt, + &fmt_para_non_hdmi_fmt, + NULL, +}; + +struct hdmi_format_para *hdmi_get_fmt_paras(enum hdmi_vic vic) +{ + int i; + + for (i = 0; all_fmt_paras[i] != NULL; i++) { + if (vic == all_fmt_paras[i]->vic) + return all_fmt_paras[i]; + } + return &fmt_para_non_hdmi_fmt; +} + +struct hdmi_format_para *hdmi_match_dtd_paras(struct dtd *t) +{ + int i; + + if (!t) + return NULL; + for (i = 0; all_fmt_paras[i]; i++) { + /* + * struct hdmi_format_para.timing.pixel_freq must divide 10 + * to match with t->pixel_clock + */ + if ((t->pixel_clock == all_fmt_paras[i]->timing.pixel_freq / 10) + && (t->h_active == all_fmt_paras[i]->timing.h_active) && + (t->h_blank == all_fmt_paras[i]->timing.h_blank) && + (t->v_active == all_fmt_paras[i]->timing.v_active) && + (t->v_blank == all_fmt_paras[i]->timing.v_blank) && + (t->h_sync_offset == all_fmt_paras[i]->timing.h_front) && + (t->h_sync == all_fmt_paras[i]->timing.h_sync) && + (t->v_sync_offset == all_fmt_paras[i]->timing.v_front) && + (t->v_sync == all_fmt_paras[i]->timing.v_sync) + ) + return all_fmt_paras[i]; + } + + return NULL; +} + +static struct parse_cd parse_cd_[] = { + {COLORDEPTH_24B, "8bit",}, + {COLORDEPTH_30B, "10bit"}, + {COLORDEPTH_36B, "12bit"}, + {COLORDEPTH_48B, "16bit"}, +}; + +static struct parse_cs parse_cs_[] = { + {COLORSPACE_RGB444, "rgb",}, + {COLORSPACE_YUV422, "422",}, + {COLORSPACE_YUV444, "444",}, + {COLORSPACE_YUV420, "420",}, +}; + +static struct parse_cr parse_cr_[] = { + {COLORRANGE_LIM, "limit",}, + {COLORRANGE_FUL, "full",}, +}; + +const char *hdmi_get_str_cd(struct hdmi_format_para *para) +{ + int i; + + for (i = 0; i < sizeof(parse_cd_) / sizeof(struct parse_cd); i++) { + if (para->cd == parse_cd_[i].cd) + return parse_cd_[i].name; + } + return NULL; +} + +const char *hdmi_get_str_cs(struct hdmi_format_para *para) +{ + int i; + + for (i = 0; i < sizeof(parse_cs_) / sizeof(struct parse_cs); i++) { + if (para->cs == parse_cs_[i].cs) + return parse_cs_[i].name; + } + return NULL; +} + +const char *hdmi_get_str_cr(struct hdmi_format_para *para) +{ + int i; + + for (i = 0; i < sizeof(parse_cr_) / sizeof(struct parse_cr); i++) { + if (para->cr == parse_cr_[i].cr) + return parse_cr_[i].name; + } + return NULL; +} + +/* parse the string from "dhmitx output FORMAT" */ +static void hdmi_parse_attr(struct hdmi_format_para *para, char const *name) +{ + int i; + + /* parse color depth */ + for (i = 0; i < sizeof(parse_cd_) / sizeof(struct parse_cd); i++) { + if (strstr(name, parse_cd_[i].name)) { + para->cd = parse_cd_[i].cd; + break; + } + } + /* set default value */ + if (i == sizeof(parse_cd_) / sizeof(struct parse_cd)) + para->cd = COLORDEPTH_24B; + + /* parse color space */ + for (i = 0; i < sizeof(parse_cs_) / sizeof(struct parse_cs); i++) { + if (strstr(name, parse_cs_[i].name)) { + para->cs = parse_cs_[i].cs; + break; + } + } + /* set default value */ + if (i == sizeof(parse_cs_) / sizeof(struct parse_cs)) + para->cs = COLORSPACE_YUV444; + + /* parse color range */ + for (i = 0; i < sizeof(parse_cr_) / sizeof(struct parse_cr); i++) { + if (strstr(name, parse_cr_[i].name)) { + para->cr = parse_cr_[i].cr; + break; + } + } + /* set default value */ + if (i == sizeof(parse_cr_) / sizeof(struct parse_cr)) + para->cr = COLORRANGE_FUL; +} + +/* + * Parameter 'name' can be 1080p60hz, or 1920x1080p60hz + * or 3840x2160p60hz, 2160p60hz + * or 3840x2160p60hz420, 2160p60hz420 (Y420 mode) + */ +struct hdmi_format_para *hdmi_get_fmt_name(char const *name, char const *attr) +{ + int i; + char *lname; + enum hdmi_vic vic = HDMI_Unknown; + struct hdmi_format_para *para = NULL; + + if (!name) + return NULL; + + for (i = 0; all_fmt_paras[i]; i++) { + lname = all_fmt_paras[i]->name; + if (lname && (strncmp(name, lname, strlen(lname)) == 0)) { + vic = all_fmt_paras[i]->vic; + break; + } + lname = all_fmt_paras[i]->sname; + if (lname && (strncmp(name, lname, strlen(lname)) == 0)) { + vic = all_fmt_paras[i]->vic; + break; + } + } + if ((vic != HDMI_Unknown) && (i != sizeof(all_fmt_paras) / + sizeof(struct hdmi_format_para *))) { + para = all_fmt_paras[i]; + memset(¶->ext_name[0], 0, sizeof(para->ext_name)); + memcpy(¶->ext_name[0], name, strlen(name)); + hdmi_parse_attr(para, name); + hdmi_parse_attr(para, attr); + } else { + para = &fmt_para_non_hdmi_fmt; + hdmi_parse_attr(para, name); + hdmi_parse_attr(para, attr); + } + if (strstr(name, "420")) + para->cs = COLORSPACE_YUV420; + return para; +} + +struct vinfo_s *hdmi_get_valid_vinfo(char *mode) +{ + int i; + struct vinfo_s *info = NULL; + char mode_[32]; + + /* the string of mode contains char NF */ + memset(mode_, 0, sizeof(mode_)); + strncpy(mode_, mode, sizeof(mode_)); + for (i = 0; i < sizeof(mode_); i++) + if (mode_[i] == 10) + mode_[i] = 0; + + for (i = 0; all_fmt_paras[i]; i++) { + if (strncmp(all_fmt_paras[i]->hdmitx_vinfo.name, mode_, + strlen(mode_)) == 0) { + info = &all_fmt_paras[i]->hdmitx_vinfo; + break; + } + } + return info; +} + +/* For check all format parameters only */ +void check_detail_fmt(void) +{ + int i; + struct hdmi_format_para *p; + struct hdmi_cea_timing *t; + + pr_warn("VIC Hactive Vactive I/P Htotal Hblank Vtotal Vblank Hfreq Vfreq Pfreq\n"); + for (i = 0; all_fmt_paras[i] != NULL; i++) { + p = all_fmt_paras[i]; + t = &p->timing; + pr_warn("%s[%d] %d %d %c %d %d %d %d %d %d %d\n", + all_fmt_paras[i]->name, all_fmt_paras[i]->vic, + t->h_active, t->v_active, + (p->progress_mode) ? 'P' : 'I', + t->h_total, t->h_blank, t->v_total, t->v_blank, + t->h_freq, t->v_freq, t->pixel_freq); + } + + pr_warn("\nVIC Hfront Hsync Hback Hpol Vfront Vsync Vback Vpol Ln\n"); + for (i = 0; all_fmt_paras[i] != NULL; i++) { + p = all_fmt_paras[i]; + t = &p->timing; + pr_warn("%s[%d] %d %d %d %c %d %d %d %c %d\n", + all_fmt_paras[i]->name, all_fmt_paras[i]->vic, + t->h_front, t->h_sync, t->h_back, + (t->hsync_polarity) ? 'P' : 'N', + t->v_front, t->v_sync, t->v_back, + (t->vsync_polarity) ? 'P' : 'N', + t->v_sync_ln); + } + + pr_warn("\nCheck Horizon parameter\n"); + for (i = 0; all_fmt_paras[i] != NULL; i++) { + p = all_fmt_paras[i]; + t = &p->timing; + if (t->h_total != (t->h_active + t->h_blank)) + pr_warn("VIC[%d] Ht[%d] != (Ha[%d] + Hb[%d])\n", + all_fmt_paras[i]->vic, t->h_total, t->h_active, + t->h_blank); + if (t->h_blank != (t->h_front + t->h_sync + t->h_back)) + pr_warn("VIC[%d] Hb[%d] != (Hf[%d] + Hs[%d] + Hb[%d])\n", + all_fmt_paras[i]->vic, t->h_blank, + t->h_front, t->h_sync, t->h_back); + } + + pr_warn("\nCheck Vertical parameter\n"); + for (i = 0; all_fmt_paras[i] != NULL; i++) { + p = all_fmt_paras[i]; + t = &p->timing; + if (t->v_total != (t->v_active + t->v_blank)) + pr_warn("VIC[%d] Vt[%d] != (Va[%d] + Vb[%d]\n", + all_fmt_paras[i]->vic, t->v_total, t->v_active, + t->v_blank); + if ((t->v_blank != (t->v_front + t->v_sync + t->v_back)) + & (p->progress_mode == 1)) + pr_warn("VIC[%d] Vb[%d] != (Vf[%d] + Vs[%d] + Vb[%d])\n", + all_fmt_paras[i]->vic, t->v_blank, + t->v_front, t->v_sync, t->v_back); + if ((t->v_blank/2 != (t->v_front + t->v_sync + t->v_back)) + & (p->progress_mode == 0)) + pr_warn("VIC[%d] Vb[%d] != (Vf[%d] + Vs[%d] + Vb[%d])\n", + all_fmt_paras[i]->vic, t->v_blank, t->v_front, + t->v_sync, t->v_back); + } +} + +/* Recommended N and Expected CTS for 32kHz */ +struct hdmi_audio_fs_ncts aud_32k_para = { + .array[0] = { + .tmds_clk = 25175, + .n = 4576, + .cts = 28125, + .n_36bit = 9152, + .cts_36bit = 84375, + .n_48bit = 4576, + .cts_48bit = 56250, + }, + .array[1] = { + .tmds_clk = 25200, + .n = 4096, + .cts = 25200, + .n_36bit = 4096, + .cts_36bit = 37800, + .n_48bit = 4096, + .cts_48bit = 50400, + }, + .array[2] = { + .tmds_clk = 27000, + .n = 4096, + .cts = 27000, + .n_36bit = 4096, + .cts_36bit = 40500, + .n_48bit = 4096, + .cts_48bit = 54000, + }, + .array[3] = { + .tmds_clk = 27027, + .n = 4096, + .cts = 27027, + .n_36bit = 8192, + .cts_36bit = 81081, + .n_48bit = 4096, + .cts_48bit = 54054, + }, + .array[4] = { + .tmds_clk = 54000, + .n = 4096, + .cts = 54000, + .n_36bit = 4096, + .cts_36bit = 81000, + .n_48bit = 4096, + .cts_48bit = 108000, + }, + .array[5] = { + .tmds_clk = 54054, + .n = 4096, + .cts = 54054, + .n_36bit = 4096, + .cts_36bit = 81081, + .n_48bit = 4096, + .cts_48bit = 108108, + }, + .array[6] = { + .tmds_clk = 74176, + .n = 11648, + .cts = 210937, + .n_36bit = 11648, + .cts_36bit = 316406, + .n_48bit = 11648, + .cts_48bit = 421875, + }, + .array[7] = { + .tmds_clk = 74250, + .n = 4096, + .cts = 74250, + .n_36bit = 4096, + .cts_36bit = 111375, + .n_48bit = 4096, + .cts_48bit = 148500, + }, + .array[8] = { + .tmds_clk = 148352, + .n = 11648, + .cts = 421875, + .n_36bit = 11648, + .cts_36bit = 632812, + .n_48bit = 11648, + .cts_48bit = 843750, + }, + .array[9] = { + .tmds_clk = 148500, + .n = 4096, + .cts = 148500, + .n_36bit = 4096, + .cts_36bit = 222750, + .n_48bit = 4096, + .cts_48bit = 297000, + }, + .array[10] = { + .tmds_clk = 296703, + .n = 5824, + .cts = 421875, + }, + .array[11] = { + .tmds_clk = 297000, + .n = 3072, + .cts = 222750, + }, + .array[12] = { + .tmds_clk = 593407, + .n = 5824, + .cts = 843750, + }, + .array[13] = { + .tmds_clk = 594000, + .n = 3072, + .cts = 445500, + }, + .def_n = 4096, +}; + +/* Recommended N and Expected CTS for 44.1kHz and Multiples */ +struct hdmi_audio_fs_ncts aud_44k1_para = { + .array[0] = { + .tmds_clk = 25175, + .n = 7007, + .cts = 31250, + .n_36bit = 7007, + .cts_36bit = 46875, + .n_48bit = 7007, + .cts_48bit = 62500, + }, + .array[1] = { + .tmds_clk = 25200, + .n = 6272, + .cts = 28000, + .n_36bit = 6272, + .cts_36bit = 42000, + .n_48bit = 6272, + .cts_48bit = 56000, + }, + .array[2] = { + .tmds_clk = 27000, + .n = 6272, + .cts = 30000, + .n_36bit = 6272, + .cts_36bit = 45000, + .n_48bit = 6272, + .cts_48bit = 60000, + }, + .array[3] = { + .tmds_clk = 27027, + .n = 6272, + .cts = 30030, + .n_36bit = 6272, + .cts_36bit = 45045, + .n_48bit = 6272, + .cts_48bit = 60060, + }, + .array[4] = { + .tmds_clk = 54000, + .n = 6272, + .cts = 60000, + .n_36bit = 6272, + .cts_36bit = 90000, + .n_48bit = 6272, + .cts_48bit = 120000, + }, + .array[5] = { + .tmds_clk = 54054, + .n = 6272, + .cts = 60060, + .n_36bit = 6272, + .cts_36bit = 90090, + .n_48bit = 6272, + .cts_48bit = 120120, + }, + .array[6] = { + .tmds_clk = 74176, + .n = 17836, + .cts = 234375, + .n_36bit = 17836, + .cts_36bit = 351562, + .n_48bit = 17836, + .cts_48bit = 468750, + }, + .array[7] = { + .tmds_clk = 74250, + .n = 6272, + .cts = 82500, + .n_36bit = 6272, + .cts_36bit = 123750, + .n_48bit = 6272, + .cts_48bit = 165000, + }, + .array[8] = { + .tmds_clk = 148352, + .n = 8918, + .cts = 234375, + .n_36bit = 17836, + .cts_36bit = 703125, + .n_48bit = 8918, + .cts_48bit = 468750, + }, + .array[9] = { + .tmds_clk = 148500, + .n = 6272, + .cts = 165000, + .n_36bit = 6272, + .cts_36bit = 247500, + .n_48bit = 6272, + .cts_48bit = 330000, + }, + .array[10] = { + .tmds_clk = 296703, + .n = 4459, + .cts = 234375, + }, + .array[11] = { + .tmds_clk = 297000, + .n = 4707, + .cts = 247500, + }, + .array[12] = { + .tmds_clk = 593407, + .n = 8918, + .cts = 937500, + }, + .array[13] = { + .tmds_clk = 594000, + .n = 9408, + .cts = 990000, + }, + .def_n = 6272, +}; + +/* Recommended N and Expected CTS for 48kHz and Multiples */ +struct hdmi_audio_fs_ncts aud_48k_para = { + .array[0] = { + .tmds_clk = 25175, + .n = 6864, + .cts = 28125, + .n_36bit = 9152, + .cts_36bit = 58250, + .n_48bit = 6864, + .cts_48bit = 56250, + }, + .array[1] = { + .tmds_clk = 25200, + .n = 6144, + .cts = 25200, + .n_36bit = 6144, + .cts_36bit = 37800, + .n_48bit = 6144, + .cts_48bit = 50400, + }, + .array[2] = { + .tmds_clk = 27000, + .n = 6144, + .cts = 27000, + .n_36bit = 6144, + .cts_36bit = 40500, + .n_48bit = 6144, + .cts_48bit = 54000, + }, + .array[3] = { + .tmds_clk = 27027, + .n = 6144, + .cts = 27027, + .n_36bit = 8192, + .cts_36bit = 54054, + .n_48bit = 6144, + .cts_48bit = 54054, + }, + .array[4] = { + .tmds_clk = 54000, + .n = 6144, + .cts = 54000, + .n_36bit = 6144, + .cts_36bit = 81000, + .n_48bit = 6144, + .cts_48bit = 108000, + }, + .array[5] = { + .tmds_clk = 54054, + .n = 6144, + .cts = 54054, + .n_36bit = 6144, + .cts_36bit = 81081, + .n_48bit = 6144, + .cts_48bit = 108108, + }, + .array[6] = { + .tmds_clk = 74176, + .n = 11648, + .cts = 140625, + .n_36bit = 11648, + .cts_36bit = 210937, + .n_48bit = 11648, + .cts_48bit = 281250, + }, + .array[7] = { + .tmds_clk = 74250, + .n = 6144, + .cts = 74250, + .n_36bit = 6144, + .cts_36bit = 111375, + .n_48bit = 6144, + .cts_48bit = 148500, + }, + .array[8] = { + .tmds_clk = 148352, + .n = 5824, + .cts = 140625, + .n_36bit = 11648, + .cts_36bit = 421875, + .n_48bit = 5824, + .cts_48bit = 281250, + }, + .array[9] = { + .tmds_clk = 148500, + .n = 6144, + .cts = 148500, + .n_36bit = 6144, + .cts_36bit = 222750, + .n_48bit = 6144, + .cts_48bit = 297000, + }, + .array[10] = { + .tmds_clk = 296703, + .n = 5824, + .cts = 281250, + }, + .array[11] = { + .tmds_clk = 297000, + .n = 5120, + .cts = 247500, + }, + .array[12] = { + .tmds_clk = 593407, + .n = 5824, + .cts = 562500, + }, + .array[13] = { + .tmds_clk = 594000, + .n = 6144, + .cts = 594000, + }, + .def_n = 6144, +}; + +static struct hdmi_audio_fs_ncts *all_aud_paras[] = { + &aud_32k_para, + &aud_44k1_para, + &aud_48k_para, + NULL, +}; + +unsigned int hdmi_get_aud_n_paras(enum hdmi_audio_fs fs, + enum hdmi_color_depth cd, unsigned int tmds_clk) +{ + struct hdmi_audio_fs_ncts *p = NULL; + unsigned int i, n; + unsigned int N_multiples = 1; + + pr_info("hdmitx: fs = %d, cd = %d, tmds_clk = %d\n", fs, cd, tmds_clk); + switch (fs) { + case FS_32K: + p = all_aud_paras[0]; + N_multiples = 1; + break; + case FS_44K1: + p = all_aud_paras[1]; + N_multiples = 1; + break; + case FS_88K2: + p = all_aud_paras[1]; + N_multiples = 2; + break; + case FS_176K4: + p = all_aud_paras[1]; + N_multiples = 4; + break; + case FS_48K: + p = all_aud_paras[2]; + N_multiples = 1; + break; + case FS_96K: + p = all_aud_paras[2]; + N_multiples = 2; + break; + case FS_192K: + p = all_aud_paras[2]; + N_multiples = 4; + break; + default: /* Default as FS_48K */ + p = all_aud_paras[2]; + N_multiples = 1; + break; + } + for (i = 0; i < AUDIO_PARA_MAX_NUM; i++) { + if (tmds_clk == p->array[i].tmds_clk) + break; + } + + if (i < AUDIO_PARA_MAX_NUM) + if ((cd == COLORDEPTH_24B) || (cd == COLORDEPTH_30B)) + n = p->array[i].n ? p->array[i].n : p->def_n; + else if (cd == COLORDEPTH_36B) + n = p->array[i].n_36bit ? + p->array[i].n_36bit : p->def_n; + else if (cd == COLORDEPTH_48B) + n = p->array[i].n_48bit ? + p->array[i].n_48bit : p->def_n; + else + n = p->array[i].n ? p->array[i].n : p->def_n; + else + n = p->def_n; + return n * N_multiples; +} +/*--------------------------------------------------------------*/ +/* for csc coef */ + +static unsigned char coef_yc444_rgb_24bit_601[] = { + 0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e, + 0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a, + 0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b +}; + +static unsigned char coef_yc444_rgb_24bit_709[] = { + 0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7, + 0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d, + 0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25 +}; + + +static struct hdmi_csc_coef_table hdmi_csc_coef[] = { + {COLORSPACE_YUV444, COLORSPACE_RGB444, COLORDEPTH_24B, 0, + sizeof(coef_yc444_rgb_24bit_601), coef_yc444_rgb_24bit_601}, + {COLORSPACE_YUV444, COLORSPACE_RGB444, COLORDEPTH_24B, 1, + sizeof(coef_yc444_rgb_24bit_709), coef_yc444_rgb_24bit_709}, +}; + +unsigned int hdmi_get_csc_coef( + unsigned int input_format, unsigned int output_format, + unsigned int color_depth, unsigned int color_format, + unsigned char **coef_array, unsigned int *coef_length) +{ + unsigned int i = 0, max = 0; + + max = sizeof(hdmi_csc_coef)/sizeof(struct hdmi_csc_coef_table); + + for (i = 0; i < max; i++) { + if ((input_format == hdmi_csc_coef[i].input_format) && + (output_format == hdmi_csc_coef[i].output_format) && + (color_depth == hdmi_csc_coef[i].color_depth) && + (color_format == hdmi_csc_coef[i].color_format)) { + *coef_array = hdmi_csc_coef[i].coef; + *coef_length = hdmi_csc_coef[i].coef_length; + return 0; + } + } + + coef_array = NULL; + *coef_length = 0; + + return 1; +} + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/Makefile b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/Makefile new file mode 100644 index 000000000000..0ae698116ee9 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/Makefile @@ -0,0 +1,8 @@ +obj-$(CONFIG_AMLOGIC_HDMITX) += hdmitx20.o + +hdmitx20-objs := hdmi_tx_main.o hdmi_tx_video.o hdmi_tx_audio.o hdmi_tx_edid.o \ + hdmi_tx_audio.o hdmi_tx_hdcp.o hdmi_tx_scdc.o \ + +obj-$(CONFIG_AMLOGIC_HDMITX) += hw/ hdcp22/ + +#EXTRA_CFLAGS += -O2 diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostLibDriverErrors.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostLibDriverErrors.h new file mode 100644 index 000000000000..5bc8247e003f --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostLibDriverErrors.h @@ -0,0 +1,49 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostLibDriverErrors.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ESMDRIVERERROR_H_ +#define _ESMDRIVERERROR_H_ + +/** + * \defgroup HostLibErrors General Library Errors + * + * The following are error code definitions produced + * by the API library. + * + * \addtogroup HostLibErrors + * @{ + * + */ + +#define ESM_HL_DRIVER_SUCCESS 0 +#define ESM_HL_DRIVER_FAILED (-1) +#define ESM_HL_DRIVER_NO_MEMORY (-2) +#define ESM_HL_DRIVER_NO_ACCESS (-3) +#define ESM_HL_DRIVER_INVALID_PARAM (-4) +#define ESM_HL_DRIVER_TOO_MANY_ESM_DEVICES (-5) +#define ESM_HL_DRIVER_USER_DEFINED_ERROR (-6) +/* anything beyond this error code is user defined */ + +/* End of APIErrors group */ +/** + * @} + */ +/** + * @} + */ + +#endif diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h new file mode 100644 index 000000000000..a9d5f6cfd8c6 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h @@ -0,0 +1,167 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/ESMHostTypes.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ESMHOSTTYPES_H_ +#define _ESMHOSTTYPES_H_ + +#include "elliptic_std_def.h" +#include "elliptic_system_types.h" + +/* return type for all functions */ +#define ESM_STATUS ELP_STATUS + +/** + * \defgroup InitFlags Initialization Flags + * + * Options which can be set when calling ESM_Initialize(). + * + * \addtogroup InitFlags + * @{ + */ +#define ESM_INIT_FLAG_IRQ_SUPPORTED (1ul << 0) +/** + * @} + */ + +/** + * \defgroup LogTypes Log message types + * + * These are the defined log message types. + * + * \addtogroup LogTypes + * @{ + */ +#define ESM_LOG_TYPE_TEXT 0xfd /* Normal text log message. */ +#define ESM_LOG_TYPE_BINARY 0xfc /* Binary dump message. */ +/** + * @} + */ + +/** + * \details + * + * This structure contains the ESM's last internal status when queried. + * + */ +struct esm_status_t { + /** + * The ESM Exception vector has the following bitfields: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
HW/SWException Line NumberException FlagType
Bit 31
hardware = 1, software = 0
Bits 30..10Bits 9..1
See \ref ExFlagDefines
Bit 0
notify = 1, abort = 0
+ */ + uint32_t esm_exception; + /* Indicates that the synchronization lost. */ + uint32_t esm_sync_lost; + /* Indicates that the last AKE Start command was passed. */ + uint32_t esm_auth_pass; + /* Indicates that the last AKE Start command has failed. */ + uint32_t esm_auth_fail; +}; + +/** + * \details + * + * This structure will be filled when ESM firmware successfully started + * and it contains ESM buffers configuration values. + * + */ +struct esm_config_t { + /* Indicates what ESM firmware running: 0-unknown; 1-RX; 2-TX. */ + uint32_t esm_type; + /* Indicates maximum size of a topology slot memory. */ + uint32_t topo_buffer_size; + /* Indicates amount of topology slot memories. */ + uint8_t topo_slots; + /* Indicates maximum size of the topology seed memory. */ + uint8_t topo_seed_buffer_size; + /* Indicates maximum size of the logging memory. */ + uint32_t log_buffer_size; + /* Indicates maximum size of the mailbox memory. */ + uint32_t mb_buffer_size; + /* Indicates maximum size of the exceptions memory. */ + uint32_t exceptions_buffer_size; + /* Indicates maximum size of the TX SRM memory. */ + uint32_t srm_buffer_size; + /* Indicates maximum size of the TX Pairing memory.*/ + uint32_t pairing_buffer_size; +}; + +/** + * \details + * + * This structure contains a text log message which can be displayed + * directly to the user. + */ +struct esm_logmsg_text_t { + char *file; /* Firmware source filename. */ + char *msg; /* Human-readable log message. */ + uint16_t line; /* Firmware source line number. */ +}; + +struct esm_logmsg_bin_t { + char *msg; /* Human-readable description. */ + uint8_t *data; /* Pointer to first byte of data. */ + uint16_t datalen; /* Number of data bytes. */ +}; + +/** + * \details + * + * This structure contains a parsed log message from the ESM. The ESM + * has different types of log messages, which are distinguished by the + * type value. The actual message (which depends on the type) can be + * accessed through the appropriate union member. + */ +struct esm_logmsg_t { + /* Raw (unparsed) message length (in bytes). */ + uint16_t rawlen; + /* Type of log message. + * See \ref LogTypes for a list of supported message types. + */ + uint8_t type; + /* Log message ID (-1 if no ID). */ + int32_t id; + /* Pointer to raw (unparsed) message. */ + uint8_t *raw; + + union { + /* Normal text log message. + * Only valid if type is #ESM_LOG_TYPE_TEXT. + */ + struct esm_logmsg_text_t *text; + /*Binary dump message. + * Only valid if type is #ESM_LOG_TYPE_BINARY. + */ + struct esm_logmsg_bin_t *bin; + } u; /* Union for decoded message data. */ +}; + +#endif + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/Makefile b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/Makefile new file mode 100644 index 000000000000..0c0d8622c267 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/Makefile @@ -0,0 +1 @@ +obj-y += hdcp_main.o \ No newline at end of file diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_std_def.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_std_def.h new file mode 100644 index 000000000000..d6188ef6d0df --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_std_def.h @@ -0,0 +1,78 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_std_def.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __ELLIPTIC_STD_DEF_H__ +#define __ELLIPTIC_STD_DEF_H__ + +#ifndef __KERNEL__ +/** + * \defgroup CALDef Common Definitions + * + * This section defines the common shared types + * + * \addtogroup CALDef + * @{ + * + */ + +/** + * \defgroup SysStdTypes Standard Types + * This section defines the common SHARED STANDARD types + * \addtogroup SysStdTypes + * @{ + * + */ + +/** + * \ingroup SysStdTypes Standard Types + * include \n + * > - C89 compliant: if this is not available then add your definition here + * + */ + /* C89 compliant - if this is not available then add your definition here */ +#include +/** + * \ingroup SysStdTypes Standard Types + * include \n + * > - C99 compliant: if this is not available then add your definition here + * + */ + /* C99 compliant - if this is not available then add your definition here */ +#include +/** + * \ingroup SysStdTypes Standard Types + * include \n + * > - C89 compliant: if this is not available then add your definition here + * + */ +/* C89 compliant - if this is not available then add your definition here */ +#include + +/** + * @} + */ +/** + * @} + */ + +#else +#include +#include +#endif + +#endif /* __ELLIPTIC_STD_DEF_H__ */ + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_system_types.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_system_types.h new file mode 100644 index 000000000000..fe0da833660e --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_system_types.h @@ -0,0 +1,79 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/elliptic_system_types.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __ELLIPTIC_SYSTEM_TYPE_H__ +#define __ELLIPTIC_SYSTEM_TYPE_H__ + +/** + * \defgroup CALDef Common Definitions + * + * This section defines the common shared types + * + * \addtogroup CALDef + * \{ + * + */ + +/** + * \defgroup SysTypes System Types + * + * This section defines the common SHARED SYSTEM types + * + * \addtogroup SysTypes + * \{ + * + */ + +/* System types definitions. */ +#define ELP_STATUS int16_t +#define ELP_SYSTEM_INFO int16_t +#define ELP_SYSTEM_BIG_ENDIAN 0 +#define ELP_SYSTEM_LITLLE_ENDIAN 1 + +/* PRNG definitions. */ +#define PRINT_FUNC printf_ptr +#define PRINT_FUNC_DECL int32_t (*PRINT_FUNC)(const void *str, ...) +#define PRNG_FUNC prng +#define PRNG_FUNC2 prng2 +#define PRNG_FUNC_DECL uint8_t (*PRNG_FUNC)(void *, void *, uint8_t) +#define PRNG_FUNC2_DECL uint32_t (*PRNG_FUNC2)(void *, void *, uint32_t) + +struct elp_std_prng_info { + void *prng_inst; + + PRNG_FUNC_DECL; +}; + +struct elp_std_prng_info2 { + void *prng_inst; + + PRNG_FUNC2_DECL; +}; + +#define ELP_STD_PRNG_INFO elp_std_prng_info +#define ELP_STD_PRNG_INFO2 elp_std_prng_info2 + +/** + * \} + */ + +/** + * \} + */ + +#endif + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c new file mode 100644 index 000000000000..b243291d65e7 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c @@ -0,0 +1,1213 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/hdcp_main.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "host_driver_linux_if.h" + +#include "../hw/hdmi_tx_reg.h" +#include "../hw/mach_reg.h" + +#define ESM_DEVICE_MAJOR 58 +#define MAX_ESM_DEVICES 6 + +/* ESM Device */ +struct esm_device { + int allocated; + int code_loaded; + int code_is_phys_mem; + ulong code_base; + ulong code_size; + uint8_t *code; + int data_is_phys_mem; + ulong data_base; + ulong data_size; + uint8_t *data; + ulong hpi_base; + ulong hpi_size; + uint8_t *hpi; + int hpi_mem_region_requested; +}; + +static void hdcp22_hw_init(void); +static void set_pkf_duk_nonce(void); + +/* Configuration parameters */ +static int verbose; +static int nonce_mode = 1; /* 1: use HW nonce 0: use SW nonce */ + +/* Constant strings */ +static const char *MY_TAG = "ESM HLD: "; +static const char *ESM_DEVICE_NAME = "esm"; +static const char *ESM_DEVICE_CLASS = "elliptic"; + +/* Linux device, class and range */ +static int device_created; +static struct device *device; +static int device_range_registered; +static int device_class_created; +static struct class *device_class; + +/* ESM devices */ +static struct esm_device esm_devices[MAX_ESM_DEVICES]; + +/* + * Processing of the requests from the userspace + */ +/* Loads the firmware */ +static long cmd_load_code(struct esm_device *esm, + struct esm_hld_ioctl_load_code *request) +{ + unsigned long ret = 0; + uint8_t *kernel_code; + struct esm_hld_ioctl_load_code krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_load_code)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + + if (verbose) { + pr_info("%scmd_load_code: code=%p code_size=0x%x\n", + MY_TAG, krequest.code, krequest.code_size); + } + + if (esm->code_loaded == 1) { + pr_info("%scmd_load_code: Code already loaded.\n", MY_TAG); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + } else { + if (krequest.code_size > esm->code_size) { + pr_info("%sCode larger than memory (0x%x > 0x%lx).\n", + MY_TAG, krequest.code_size, esm->code_size); + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + } else { + kernel_code = kmalloc(krequest.code_size, GFP_KERNEL); + + if (kernel_code) { + /* No Endian shift */ + ret = copy_from_user(esm->code, krequest.code, + krequest.code_size); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + + kfree(kernel_code); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) + pr_info("%scopying firmware to code memory region.\n", + MY_TAG); + } else { + pr_info("%sFailed to allocate (code_size=0x%x)\n", + MY_TAG, krequest.code_size); + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + } + } + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_load_code)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + esm->code_loaded = + (krequest.returned_status == ESM_HL_DRIVER_SUCCESS); + + return 0; +} + +static long cmd_load_code32(struct esm_device *esm, + struct compact_esm_hld_ioctl_load_code *request) +{ + unsigned long ret = 0; + ulong r; + struct compact_esm_hld_ioctl_load_code __user *uf = request; + uint8_t *kernel_code; + struct compact_esm_hld_ioctl_load_code krequest; + + memset(&krequest, 0, sizeof(struct compact_esm_hld_ioctl_load_code)); + r = get_user(krequest.code, &uf->code); + r |= get_user(krequest.code_size, &uf->code_size); + if (r) + return -EFAULT; + + if (esm->code_loaded == 1) { + pr_info("%scmd_load_code: Code already loaded.\n", MY_TAG); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + } else { + if (krequest.code_size > esm->code_size) { + pr_info("%sCode size larger than code memory (0x%x > 0x%lx).\n", + MY_TAG, krequest.code_size, esm->code_size); + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + } else { + kernel_code = kmalloc(krequest.code_size, GFP_KERNEL); + + if (kernel_code) { + pr_info("%s[%d]\n", __func__, __LINE__); + /* No Endian shift */ + ret = copy_from_user(esm->code, compat_ptr(krequest.code), + krequest.code_size); + if (ret) + pr_info("copy %ld Bytes\n", ret); + + kfree(kernel_code); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) + pr_info("%scopying firmware to code memory region.\n", + MY_TAG); + } else { + pr_info("%sFailed to allocat memory (code_size=0x%x)\n", + MY_TAG, krequest.code_size); + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + } + } + } + + ret = copy_to_user(request, &krequest, + sizeof(struct compact_esm_hld_ioctl_load_code)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + esm->code_loaded = + (krequest.returned_status == ESM_HL_DRIVER_SUCCESS); + + return 0; +} + +/* Returns the physical address of the code */ +static long cmd_get_code_phys_addr(struct esm_device *esm, + struct esm_hld_ioctl_get_code_phys_addr *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_get_code_phys_addr krequest; + + krequest.returned_phys_addr = esm->code_base; + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%scmd_get_code_phys_addr: returning code_base=0x%x\n", + MY_TAG, krequest.returned_phys_addr); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_get_code_phys_addr)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Returns the physical address of the data */ +static long cmd_get_data_phys_addr(struct esm_device *esm, + struct esm_hld_ioctl_get_data_phys_addr *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_get_data_phys_addr krequest; + + krequest.returned_phys_addr = esm->data_base; + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%scmd_get_data_phys_addr: returning data_base=0x%x\n", + MY_TAG, krequest.returned_phys_addr); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_get_data_phys_addr)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Returns the size of the data memory region */ +static long cmd_get_data_size(struct esm_device *esm, + struct esm_hld_ioctl_get_data_size *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_get_data_size krequest; + + krequest.returned_data_size = esm->data_size; + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%scmd_get_data_size: returning data_size=0x%x\n", + MY_TAG, krequest.returned_data_size); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_get_data_size)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Reads a single 32-bit HPI register */ +static long cmd_hpi_read(struct esm_device *esm, + struct esm_hld_ioctl_hpi_read *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_hpi_read krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_hpi_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%scmd_hpi_read: Reading register at offset 0x%x\n", + MY_TAG, krequest.offset); + } + + if (esm->hpi) { + krequest.returned_data = hdcp22_rd_reg(krequest.offset); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%scmd_hpi_read: Returning data=0x%x\n", + MY_TAG, krequest.returned_data); + } + } else { + krequest.returned_data = 0; + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_hpi_read: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_hpi_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Writes a single 32-bit HPI register */ +static long cmd_hpi_write(struct esm_device *esm, + struct esm_hld_ioctl_hpi_write *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_hpi_write krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_hpi_write)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (krequest.offset == 0x40) { + hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1); + hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_CTRL, 0x6); + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 1, 5, 1); + udelay(10); + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 0, 5, 1); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MASK, 0); + hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MUTE, 0); + set_pkf_duk_nonce(); + } + if (verbose) { + pr_info("%sWriting 0x%X to register at offset 0x%X\n", + MY_TAG, krequest.data, krequest.offset); + } + + if (esm->hpi) { + hdcp22_wr_reg(krequest.offset, (uint32_t)krequest.data); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%sWrote 0x%X to register at offset 0x%X\n", + MY_TAG, krequest.data, krequest.offset); + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_hpi_write: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_hpi_write)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Reads from a region of the data memory */ +static long cmd_data_read(struct esm_device *esm, + struct esm_hld_ioctl_data_read *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_data_read krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_data_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%sReading %u bytes at offset offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.offset); + } + + if (esm->data) { + if (krequest.offset + krequest.nbytes > esm->data_size) { + krequest.returned_status = ESM_HL_DRIVER_INVALID_PARAM; + pr_info("%scmd_data_read: Invalid offset and size.\n", + MY_TAG); + } else { + ret = copy_to_user(krequest.dest_buf, + esm->data + krequest.offset, krequest.nbytes); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%sreading %u at offset 0x%x\n", + MY_TAG, krequest.nbytes, + krequest.offset); + } + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_data_read: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_data_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Reads from a region of the data memory */ +static long cmd_data_read32(struct esm_device *esm, + struct compact_esm_hld_ioctl_data_read *request) +{ + unsigned long ret = 0; + struct compact_esm_hld_ioctl_data_read krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct compact_esm_hld_ioctl_data_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%sReading %u offset offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.offset); + } + + if (esm->data) { + if (krequest.offset + krequest.nbytes > esm->data_size) { + krequest.returned_status = ESM_HL_DRIVER_INVALID_PARAM; + pr_info("%scmd_data_read: Invalid offset and size.\n", + MY_TAG); + } else { + ret = copy_to_user(compat_ptr(krequest.dest_buf), + esm->data + krequest.offset, krequest.nbytes); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%sreading %u bytes at offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.offset); + } + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_data_read: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct compact_esm_hld_ioctl_data_read)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Writes to a region of the data memory */ +static long cmd_data_write(struct esm_device *esm, + struct esm_hld_ioctl_data_write *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_data_write krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_data_write)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%sWriting %u bytes to data memory at offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.offset); + } + + if (esm->data) { + if (krequest.offset + krequest.nbytes > esm->data_size) { + krequest.returned_status = ESM_HL_DRIVER_INVALID_PARAM; + pr_info("%scmd_data_write: Invalid offset and size.\n", + MY_TAG); + } else { + ret = copy_from_user(esm->data + krequest.offset, + krequest.src_buf, krequest.nbytes); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%swriting %u to 0x%x\n", + MY_TAG, krequest.nbytes, + krequest.offset); + } + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_data_write: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_data_write)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Writes to a region of the data memory */ +static long cmd_data_write32(struct esm_device *esm, + struct compact_esm_hld_ioctl_data_write *request) +{ + unsigned long ret = 0; + struct compact_esm_hld_ioctl_data_write krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct compact_esm_hld_ioctl_data_write)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%sWriting %u bytes to memory at offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.offset); + } + + if (esm->data) { + if (krequest.offset + krequest.nbytes > esm->data_size) { + krequest.returned_status = ESM_HL_DRIVER_INVALID_PARAM; + pr_info("%scmd_data_write: Invalid offset and size.\n", + MY_TAG); + } else { + ret = copy_from_user(esm->data + krequest.offset, + compat_ptr(krequest.src_buf), krequest.nbytes); + if (ret) + pr_info("copy %ld Bytes\n", ret); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%swriting %u at offset 0x%x\n", + MY_TAG, krequest.nbytes, + krequest.offset); + } + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_data_write: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct compact_esm_hld_ioctl_data_write)); + if (ret) + pr_info("copy %ld Bytes\n", ret); + return 0; +} + +/* Sets a region of the data memory to a given 8-bit value */ +static long cmd_data_set(struct esm_device *esm, + struct esm_hld_ioctl_data_set *request) +{ + unsigned long ret = 0; + struct esm_hld_ioctl_data_set krequest; + + ret = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_data_set)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + if (verbose) { + pr_info("%sSetting %u bytes (data=0x%x) from offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.data, + krequest.offset); + } + + if (esm->data) { + if (krequest.offset + krequest.nbytes > esm->data_size) { + krequest.returned_status = ESM_HL_DRIVER_INVALID_PARAM; + pr_info("%scmd_data_set: Invalid offset and size.\n", + MY_TAG); + } else { + memset(esm->data + krequest.offset, krequest.data, + krequest.nbytes); + krequest.returned_status = ESM_HL_DRIVER_SUCCESS; + + if (verbose) { + pr_info("%ssetting %u data=0x%x offset 0x%x\n", + MY_TAG, krequest.nbytes, krequest.data, + krequest.offset); + } + } + } else { + krequest.returned_status = ESM_HL_DRIVER_NO_MEMORY; + pr_info("%scmd_data_set: No memory.\n", MY_TAG); + } + + ret = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_data_set)); + if (ret) + pr_info("copy left %ld Bytes\n", ret); + return 0; +} + +/* Opens an ESM device. Associates a device file to an ESM device. */ +static long cmd_esm_open(struct file *f, + struct esm_hld_ioctl_esm_open *request) +{ + unsigned long r = 0; + int i; + struct esm_device *esm = esm_devices; + int ret = ESM_HL_DRIVER_SUCCESS; + struct esm_hld_ioctl_esm_open krequest; + + r = copy_from_user(&krequest, request, + sizeof(struct esm_hld_ioctl_esm_open)); + if (r) + pr_info("copy left %ld Bytes\n", r); + f->private_data = NULL; + /* Look for a matching ESM device (based on HPI address) */ + for (i = MAX_ESM_DEVICES; i--; esm++) { + if (esm->allocated && (krequest.hpi_base == esm->hpi_base)) { + /* Found it */ + f->private_data = esm; + break; + } + } + + if (!f->private_data) { + /* Not found. Allocate a new ESM device. */ + esm = esm_devices; + + for (i = MAX_ESM_DEVICES; i--; esm++) { + if (!esm->allocated) { + dma_addr_t dh; + char region_name[20]; + + esm->allocated = 1; + esm->hpi_base = krequest.hpi_base; + /* this can be static since the HPI + * interface will not change + */ + esm->hpi_size = 0x100; + esm->code_base = krequest.code_base; + esm->code_size = krequest.code_size; + esm->data_base = krequest.data_base; + esm->data_size = krequest.data_size; + + pr_info("%sNew ESM device:\n\n", MY_TAG); + pr_info(" hpi_base: 0x%lx\n", esm->hpi_base); + pr_info(" hpi_size: 0x%lx\n", esm->hpi_size); + pr_info(" code_base: 0x%lx\n", esm->code_base); + pr_info(" code_size: 0x%lx\n", esm->code_size); + pr_info(" data_base: 0x%lx\n", esm->data_base); + pr_info(" data_size: 0x%lx\n\n", + esm->data_size); + + /* Initialize the code memory */ + if (esm->code_base) { + esm->code_is_phys_mem = 1; + esm->code = + phys_to_virt(esm->code_base); + pr_info("Code is at PhyAddr 0x%lx\n", + esm->code_base); + } else { + esm->code = dma_alloc_coherent( + (struct device *)esm, + esm->code_size, &dh, + GFP_KERNEL); + + if (!esm->code) { + pr_info("%sFailed alloca (%ld bytes)\n", + MY_TAG, esm->code_size); + ret = ESM_HL_DRIVER_NO_MEMORY; + break; + } + esm->code_base = dh; + pr_info("%sBase allocated: phys=0x%lx virt=%p\n", + MY_TAG, esm->code_base, esm->code); + } + + /* Initialize the data memory */ + if (esm->data_base) { + esm->data_is_phys_mem = 1; + esm->data = phys_to_virt(esm->data_base); + pr_info("Data is at physical address 0x%lx\n", + esm->code_base); + } else { + esm->data = dma_alloc_coherent((struct device *)esm, + esm->data_size, &dh, GFP_KERNEL); + + if (!esm->data) { + pr_info("%sFailed to allocate (%ld bytes)\n", + MY_TAG, esm->data_size); + ret = ESM_HL_DRIVER_NO_MEMORY; + break; + } + + esm->data_base = dh; + pr_info("%sBaseAddr of allocated: phys=0x%lx virt=%p\n", + MY_TAG, esm->data_base, esm->data); + } + + /* Init HPI access */ + sprintf(region_name, "ESM-%lX", esm->hpi_base); + request_mem_region(esm->hpi_base, esm->hpi_size, region_name); + esm->hpi_mem_region_requested = 1; + esm->hpi = ioremap_nocache(esm->hpi_base, esm->hpi_size); + + /* Associate the Linux file to the ESM device */ + f->private_data = esm; + break; + } + } + } + + if (!f->private_data) { + pr_info("%scmd_esm_open: Too many ESM devices.\n", MY_TAG); + ret = ESM_HL_DRIVER_TOO_MANY_ESM_DEVICES; + } + + krequest.returned_status = ret; + r = copy_to_user(request, &krequest, + sizeof(struct esm_hld_ioctl_esm_open)); + if (r) + pr_info("copy left %ld Bytes\n", r); + return 0; +} + +/* + * Linux Device + */ + +/* The device has been opened */ +static int device_open(struct inode *inode, struct file *filp) +{ + if (verbose) + pr_info("%sDevice opened.\n", MY_TAG); + + /* No associated ESM device yet. + * Use IOCTL ESM_HLD_IOCTL_ESM_OPEN to associate an ESM + * to the opened device file. + */ + filp->private_data = NULL; + + return 0; +} + +/* The device has been closed */ +static int device_release(struct inode *inode, struct file *filp) +{ + if (verbose) + pr_info("%sDevice released.\n", MY_TAG); + + + return 0; +} + +/* IOCTL operation on the device */ +static long device_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + arg = (unsigned long)compat_ptr(arg); + + switch (cmd) { + case ESM_HLD_IOCTL_LOAD_CODE: + return cmd_load_code( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_load_code *)arg); + + case ESM_HLD_IOCTL_LOAD_CODE32: + return cmd_load_code32( + (struct esm_device *)f->private_data, + (struct compact_esm_hld_ioctl_load_code *)arg); + + case ESM_HLD_IOCTL_GET_CODE_PHYS_ADDR: + return cmd_get_code_phys_addr( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_get_code_phys_addr *)arg); + + case ESM_HLD_IOCTL_GET_DATA_PHYS_ADDR: + return cmd_get_data_phys_addr( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_get_data_phys_addr *)arg); + + case ESM_HLD_IOCTL_GET_DATA_SIZE: + return cmd_get_data_size( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_get_data_size *)arg); + + case ESM_HLD_IOCTL_HPI_READ: + return cmd_hpi_read( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_hpi_read *)arg); + + case ESM_HLD_IOCTL_HPI_WRITE: + return cmd_hpi_write( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_hpi_write *)arg); + + case ESM_HLD_IOCTL_DATA_READ: + return cmd_data_read( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_data_read *)arg); + + case ESM_HLD_IOCTL_DATA_READ32: + return cmd_data_read32( + (struct esm_device *)f->private_data, + (struct compact_esm_hld_ioctl_data_read *)arg); + + case ESM_HLD_IOCTL_DATA_WRITE: + return cmd_data_write( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_data_write *)arg); + + case ESM_HLD_IOCTL_DATA_WRITE32: + return cmd_data_write32( + (struct esm_device *)f->private_data, + (struct compact_esm_hld_ioctl_data_write *)arg); + + case ESM_HLD_IOCTL_DATA_SET: + return cmd_data_set( + (struct esm_device *)f->private_data, + (struct esm_hld_ioctl_data_set *)arg); + + case ESM_HLD_IOCTL_ESM_OPEN: + return cmd_esm_open(f, (struct esm_hld_ioctl_esm_open *)arg); + } + + + return -1; +} + +static void dump_device_info(struct esm_device *dev) +{ + pr_info(" allocated = %d\n", dev->allocated); + pr_info(" code_loaded = %d\n", dev->code_loaded); + pr_info(" code_is_phys_mem = %d\n", dev->code_is_phys_mem); + pr_info(" code_base = 0x%lx\n", dev->code_base); + pr_info(" code_size = %lu\n", dev->code_size); + pr_info(" code = 0x%p\n", dev->code); + pr_info(" data_is_phys_mem = %d\n", dev->data_is_phys_mem); + pr_info(" data_base = 0x%lx\n", dev->data_base); + pr_info(" data_size = %lu\n", dev->data_size); + pr_info(" data = 0x%p\n", dev->data); + pr_info(" hpi_base = 0x%lx\n", dev->hpi_base); + pr_info(" hpi_size = %lu\n", dev->hpi_size); + pr_info(" hpi = 0x%p\n", dev->hpi); + pr_info(" hpi_mem_region_requested = %d\n", + dev->hpi_mem_region_requested); +} + +static void dump_device_raw(const uint8_t *buf, uint32_t size) +{ + uint32_t i; + + pr_info("Dump Addr: 0x%p Size: %d\n", buf, size); + pr_info("==============DUMP START==============\n"); + for (i = 0; i < size; i += 8) + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], + buf[i+5], buf[i+6], buf[i+7]); + pr_info("==============DUMP END ==============\n"); +} + +#define DUMP_SECTION(prefix, start, end) \ +do { \ + if (start > end) { \ + pr_info("Error start = 0x%x > end = 0x%x\n", (uint32_t)start, \ + (uint32_t)end); \ + break; \ + } \ + pr_info("Dump %s\n", prefix); \ + for (addr = start; addr < end + 1; addr++) { \ + val = hdmitx_rd_reg(addr); \ + if (val) \ + pr_info("[0x%08x]: 0x%08x\n", addr, val); \ + } \ +} while (0) + +static void dump_snps_regs(void) +{ + unsigned int addr; + unsigned int val; + + DUMP_SECTION("TOP", HDMITX_TOP_SW_RESET, HDMITX_TOP_STAT0); + DUMP_SECTION("TOPSec", HDMITX_TOP_SKP_CNTL_STAT, HDMITX_TOP_DUK_3); + DUMP_SECTION("TOP", HDMITX_TOP_INFILTER, HDMITX_TOP_NSEC_SCRATCH); + DUMP_SECTION("TOPSec", HDMITX_TOP_SEC_SCRATCH, HDMITX_TOP_SEC_SCRATCH); + DUMP_SECTION("TOP", HDMITX_TOP_DONT_TOUCH0, HDMITX_TOP_DONT_TOUCH1); + DUMP_SECTION("DWC", HDMITX_DWC_DESIGN_ID, HDMITX_DWC_CSC_LIMIT_DN_LSB); + DUMP_SECTION("DWCSec", HDMITX_DWC_A_HDCPCFG0, HDMITX_DWC_A_HDCPCFG1); + DUMP_SECTION("DWC", HDMITX_DWC_A_HDCPOBS0, HDMITX_DWC_A_KSVMEMCTRL); + /* Exclude HDMITX_DWC_HDCP_BSTATUS_0 to HDMITX_DWC_HDCPREG_RMLCTL */ + DUMP_SECTION("DWC", HDMITX_DWC_HDCPREG_RMLSTS, + HDMITX_DWC_HDCPREG_RMLSTS); + DUMP_SECTION("DWCSec", HDMITX_DWC_HDCPREG_SEED0, + HDMITX_DWC_HDCPREG_DPK6); + DUMP_SECTION("DWC", HDMITX_DWC_HDCP22REG_ID, + HDMITX_DWC_HDCP22REG_ID); + DUMP_SECTION("DWCSec", HDMITX_DWC_HDCP22REG_CTRL, + HDMITX_DWC_HDCP22REG_CTRL); + DUMP_SECTION("DWC", HDMITX_DWC_HDCP22REG_CTRL1, + HDMITX_DWC_I2CM_SCDC_UPDATE1); +} + +#define DBG_HELP_STR \ + "dev_infoN: show the Nth esm devices info\n" \ + "dumpesm: deump ESM registers\n" \ + "dumpsnps: dump SNPS registers\n" \ + "reset: reset ESM cpu\n" + +static ssize_t show_debug(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + static const char *dbg_help = DBG_HELP_STR; + + pos += snprintf(buf+pos, PAGE_SIZE, "%s", dbg_help); + return pos; +} + +static ssize_t store_debug(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long idx; + + if (strncmp(buf, "dev_info", 8) == 0) { + ret = kstrtoul(buf+8, 10, &idx); + if (idx >= MAX_ESM_DEVICES) + pr_info("MAX_ESM_DEVICES is %d\n", MAX_ESM_DEVICES); + else { + pr_info("esm_devices NO %lu\n", idx); + dump_device_info(&esm_devices[idx]); + } + return 16; + } + if (strncmp(buf, "dumpsnps", 8) == 0) { + dump_snps_regs(); + return 16; + } + if (strncmp(buf, "dumpesm", 7) == 0) { + uint32_t i; + uint32_t val; + + for (i = 0; i < 0x100; i += 4) { + val = hdcp22_rd_reg(i); + if (val) + pr_info("hdcp22 0x%02x: 0x%08x\n", i, val); + } + return 16; + } + if (strncmp(buf, "dumpcode", 8) == 0) { + ret = kstrtoul(buf+8, 10, &idx); + if (idx >= MAX_ESM_DEVICES) + pr_info("MAX_ESM_DEVICES is %d\n", MAX_ESM_DEVICES); + else { + pr_info("esm_devices NO %lu\n", idx); + dump_device_raw((uint8_t *)esm_devices[idx].code, + esm_devices[idx].code_size); + } + return 16; + } + if (strncmp(buf, "dumpdata", 8) == 0) { + ret = kstrtoul(buf+8, 10, &idx); + if (idx >= MAX_ESM_DEVICES) + pr_info("MAX_ESM_DEVICES is %d\n", MAX_ESM_DEVICES); + else { + pr_info("esm_devices NO %lu\n", idx); + dump_device_raw((uint8_t *)esm_devices[idx].data, + esm_devices[idx].data_size); + } + return 16; + } + if (strncmp(buf, "dumphpi", 7) == 0) { + ret = kstrtoul(buf+7, 10, &idx); + if (idx >= MAX_ESM_DEVICES) + pr_info("MAX_ESM_DEVICES is %d\n", MAX_ESM_DEVICES); + else { + pr_info("esm_devices NO %lu\n", idx); + dump_device_raw((uint8_t *)esm_devices[idx].hpi, + esm_devices[idx].hpi_size); + } + return 16; + } + if (strncmp(buf, "reset", 5) == 0) { + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 1, 5, 1); + mdelay(2); + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 0, 5, 1); + pr_info("reset done\n"); + } + return 16; +} + +static DEVICE_ATTR(debug, 0644, show_debug, store_debug); + +/* Creates the device required to interface with the HLD driver */ +static int create_device(void) +{ + int ret = 0; + + pr_info("%sCreating device '%s'...\n", + MY_TAG, ESM_DEVICE_NAME); + + device = device_create(device_class, NULL, MKDEV(ESM_DEVICE_MAJOR, 0), + NULL, ESM_DEVICE_NAME); + + if (IS_ERR(device)) { + pr_info("%sFailed to create device '%s'.\n", + MY_TAG, ESM_DEVICE_NAME); + return PTR_ERR(device); + } + ret = device_create_file(device, &dev_attr_debug); + device_created = 1; + pr_info("%sDevice '%s' has been created.\n", + MY_TAG, ESM_DEVICE_NAME); + + return 0; +} + +/* Destroys the interface device */ +static void end_device(void) +{ + int i; + struct esm_device *esm = esm_devices; + + if (device_created) { + pr_info("%sDeleting device '%s'...\n", + MY_TAG, ESM_DEVICE_NAME); + device_remove_file(device, &dev_attr_debug); + device_destroy(device_class, MKDEV(ESM_DEVICE_MAJOR, 0)); + device_created = 0; + } + + for (i = MAX_ESM_DEVICES; i--; esm++) { + if (esm->allocated) { + if (esm->code && !esm->code_is_phys_mem) { + dma_addr_t dh = (dma_addr_t)esm->code_base; + + dma_free_coherent(NULL, esm->code_size, + esm->code, dh); + } + + if (esm->data && !esm->data_is_phys_mem) { + dma_addr_t dh = (dma_addr_t)esm->data_base; + + dma_free_coherent(NULL, esm->data_size, + esm->data, dh); + } + + if (esm->hpi) + iounmap(esm->hpi); + + if (esm->hpi_mem_region_requested) + release_mem_region(esm->hpi_base, + esm->hpi_size); + } + } + + memset(esm_devices, 0, sizeof(esm_devices)); +} + +/* + * Linux device class and range + */ +/* Table of the supported operations on ESM devices */ +static const struct file_operations device_file_operations = { + .open = device_open, + .release = device_release, +/* .unlocked_ioctl = device_ioctl, */ + .compat_ioctl = device_ioctl, + .owner = THIS_MODULE, +}; + +static int register_device_range(void) +{ + int ret; + + pr_info("%sRegistering device range '%s'...\n", + MY_TAG, ESM_DEVICE_NAME); + + ret = register_chrdev(ESM_DEVICE_MAJOR, ESM_DEVICE_NAME, + &device_file_operations); + + if (ret < 0) { + pr_info("%sFailed to register device range '%s'.\n", + MY_TAG, ESM_DEVICE_NAME); + return ret; + } + + pr_info("%sDevice range '%s' has been registered.\n", + MY_TAG, ESM_DEVICE_NAME); + device_range_registered = 1; + + return 0; +} + +static void unregister_device_range(void) +{ + if (device_range_registered) { + pr_info("%sUnregistering device range '%s'...\n", + MY_TAG, ESM_DEVICE_NAME); + unregister_chrdev(ESM_DEVICE_MAJOR, ESM_DEVICE_NAME); + device_range_registered = 0; + } +} + +/* + * Creates the interface device class. + * Note: Attributes could be created for that class. + * Not required at this time. + */ +static int create_device_class(void) +{ + pr_info("%sCreating class /sys/class/%s...\n", + MY_TAG, ESM_DEVICE_CLASS); + + device_class = class_create(THIS_MODULE, ESM_DEVICE_CLASS); + + if (IS_ERR(device_class)) { + pr_info("%sFailed to create device class /sys/class/%s.\n", + MY_TAG, ESM_DEVICE_CLASS); + return PTR_ERR(device_class); + } + + device_class_created = 1; + pr_info("%sThe class /sys/class/%s has been created.\n", + MY_TAG, ESM_DEVICE_CLASS); + + return 0; +} + +/* Ends the device class of the ESM devices */ +static void end_device_class(void) +{ + if (device_class_created) { + pr_info("%sDeleting the device class /sys/class/%s...\n", + MY_TAG, ESM_DEVICE_CLASS); + class_destroy(device_class); + device_class_created = 0; + } +} + +static void set_pkf_duk_nonce(void) +{ + /* Configure duk/pkf */ + hdmitx_hdcp_opr(0xc); + if (nonce_mode == 1) + hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xf); + else { + hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xe); +/* Configure nonce[127:0]. + * MSB must be written the last to assert nonce_vld signal. + */ + hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x32107654); + hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xba98fedc); + hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0xcdef89ab); + hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x45670123); + hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x76543210); + hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xfedcba98); + hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0x89abcdef); + hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x01234567); + } + mdelay(10); +} + +static void hdcp22_hw_init(void) +{ + hdmitx_set_reg_bits(HDMITX_DWC_FC_INVIDCONF, 1, 7, 1); + hdmitx_wr_reg(HDMITX_DWC_A_HDCPCFG1, 0x7); + hdmitx_wr_reg(HDMITX_DWC_A_HDCPCFG0, 0x53); + hd_set_reg_bits(P_HHI_GCLK_MPEG2, 1, 3, 1); + hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); + /* Enable skpclk to HDCP2.2 IP */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 7, 1); + /* Enable esmclk to HDCP2.2 IP */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 6, 1); + /* Enable tmds_clk to HDCP2.2 IP */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 5, 1); +#if 0 + /* sw_reset_hdcp22: to reset HDCP2.2 IP */ + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 1, 5, 1); + mdelay(10); + hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 0, 5, 1); +#endif + set_pkf_duk_nonce(); +} + +/* + * Initialization/termination of the module + */ +static int __init hld_init(void) +{ + struct hdmitx_dev *hdmitx_device = get_hdmitx_device(); + + pr_info("%sInitializing...\n", MY_TAG); + if (hdmitx_device->hdtx_dev == NULL) { + pr_info("%sExit for null device of hdmitx!\n", MY_TAG); + return -ENODEV; + } + + memset(esm_devices, 0, sizeof(esm_devices)); + + if ((register_device_range() == 0) && (create_device_class() == 0) && + (create_device() == 0)) + pr_info("%sDone initializing the HLD driver.\n", + MY_TAG); + + else + pr_info("%sFailed to initialize the HLD driver.\n", + MY_TAG); + + hdcp22_hw_init(); + return 0; +} + +static void __exit hld_exit(void) +{ + struct hdmitx_dev *hdmitx_device = get_hdmitx_device(); + + pr_info("%sExiting...\n", MY_TAG); + if (hdmitx_device->hdtx_dev == NULL) { + pr_info("%sExit for null device of hdmitx!\n", MY_TAG); + return; + } + + end_device(); + end_device_class(); + unregister_device_range(); + pr_info("%sDone.\n", MY_TAG); +} + +module_init(hld_init); +module_exit(hld_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Elliptic Technologies"); +MODULE_DESCRIPTION("ESM Linux Host Library Driver"); + +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Enable (1) or disable (0) the debug traces."); + +module_param(nonce_mode, int, 0644); +MODULE_PARM_DESC(nonce_mode, "Enable (1) or disable (0) the debug traces."); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/host_driver_linux_if.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/host_driver_linux_if.h new file mode 100644 index 000000000000..d7adf570132e --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/host_driver_linux_if.h @@ -0,0 +1,152 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdcp22/host_driver_linux_if.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _HOST_LIB_DRIVER_LINUX_IF_H_ +#define _HOST_LIB_DRIVER_LINUX_IF_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#include "ESMHostTypes.h" +#include "ESMHostLibDriverErrors.h" + +/* ESM_HLD_IOCTL_LOAD_CODE */ +struct esm_hld_ioctl_load_code { + uint8_t *code; + uint32_t code_size; + ESM_STATUS returned_status; +}; + +struct compact_esm_hld_ioctl_load_code { + compat_uptr_t code; + uint32_t code_size; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_GET_CODE_PHYS_ADDR */ +struct esm_hld_ioctl_get_code_phys_addr { + uint32_t returned_phys_addr; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_GET_DATA_PHYS_ADDR */ +struct esm_hld_ioctl_get_data_phys_addr { + uint32_t returned_phys_addr; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_GET_DATA_SIZE */ +struct esm_hld_ioctl_get_data_size { + uint32_t returned_data_size; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_HPI_READ */ +struct esm_hld_ioctl_hpi_read { + uint32_t offset; + uint32_t returned_data; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_HPI_WRITE */ +struct esm_hld_ioctl_hpi_write { + uint32_t offset; + uint32_t data; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_DATA_READ */ +struct esm_hld_ioctl_data_read { + uint32_t offset; + uint32_t nbytes; + uint8_t *dest_buf; + ESM_STATUS returned_status; +}; + +struct compact_esm_hld_ioctl_data_read { + uint32_t offset; + uint32_t nbytes; + compat_uptr_t dest_buf; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_DATA_WRITE */ +struct esm_hld_ioctl_data_write { + uint32_t offset; + uint32_t nbytes; + uint8_t *src_buf; + ESM_STATUS returned_status; +}; + +struct compact_esm_hld_ioctl_data_write { + uint32_t offset; + uint32_t nbytes; + compat_uptr_t src_buf; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_DATA_SET */ +struct esm_hld_ioctl_data_set { + uint32_t offset; + uint32_t nbytes; + uint8_t data; + ESM_STATUS returned_status; +}; + +/* ESM_HLD_IOCTL_ESM_OPEN */ +struct esm_hld_ioctl_esm_open { + uint32_t hpi_base; + uint32_t code_base; + uint32_t code_size; + uint32_t data_base; + uint32_t data_size; + ESM_STATUS returned_status; +}; + +/* IOCTL commands */ +#define ESM_HLD_IOC_MAGIC 'E' +#define ESM_HLD_IOCTL_LOAD_CODE \ + _IOWR(ESM_HLD_IOC_MAGIC, 1000, struct esm_hld_ioctl_load_code) +#define ESM_HLD_IOCTL_GET_CODE_PHYS_ADDR \ + _IOR(ESM_HLD_IOC_MAGIC, 1001, struct esm_hld_ioctl_get_code_phys_addr) +#define ESM_HLD_IOCTL_GET_DATA_PHYS_ADDR \ + _IOR(ESM_HLD_IOC_MAGIC, 1002, struct esm_hld_ioctl_get_data_phys_addr) +#define ESM_HLD_IOCTL_GET_DATA_SIZE \ + _IOR(ESM_HLD_IOC_MAGIC, 1003, struct esm_hld_ioctl_get_data_size) +#define ESM_HLD_IOCTL_HPI_READ \ + _IOWR(ESM_HLD_IOC_MAGIC, 1004, struct esm_hld_ioctl_hpi_read) +#define ESM_HLD_IOCTL_HPI_WRITE \ + _IOWR(ESM_HLD_IOC_MAGIC, 1005, struct esm_hld_ioctl_hpi_write) +#define ESM_HLD_IOCTL_DATA_READ \ + _IOWR(ESM_HLD_IOC_MAGIC, 1006, struct esm_hld_ioctl_data_read) +#define ESM_HLD_IOCTL_DATA_WRITE \ + _IOWR(ESM_HLD_IOC_MAGIC, 1007, struct esm_hld_ioctl_data_write) +#define ESM_HLD_IOCTL_DATA_SET \ + _IOWR(ESM_HLD_IOC_MAGIC, 1008, struct esm_hld_ioctl_data_set) +#define ESM_HLD_IOCTL_ESM_OPEN \ + _IOWR(ESM_HLD_IOC_MAGIC, 1009, struct esm_hld_ioctl_esm_open) +#define ESM_HLD_IOCTL_LOAD_CODE32 \ + _IOWR(ESM_HLD_IOC_MAGIC, 1000, struct compact_esm_hld_ioctl_load_code) +#define ESM_HLD_IOCTL_DATA_READ32 \ + _IOWR(ESM_HLD_IOC_MAGIC, 1006, struct compact_esm_hld_ioctl_data_read) +#define ESM_HLD_IOCTL_DATA_WRITE32 \ + _IOWR(ESM_HLD_IOC_MAGIC, 1007, struct compact_esm_hld_ioctl_data_write) + +#endif /* _HOST_LIB_DRIVER_LINUX_IF_H_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c new file mode 100644 index 000000000000..a9c5a15af528 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c @@ -0,0 +1,238 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#undef PCM_USE_INFOFRAME + +static const unsigned char channel_status_freq[] = { + 0x0, + 0x3, /*32K*/ + 0x0, /*44.1k*/ + 0x2, /*48k*/ + 0x8, /*88.2k*/ + 0xa, /*96k*/ + 0xc, /*176.4k*/ + 0xe, /*192k*/ +}; + +static const unsigned char channel_status_sample_word_length[] = { + 0x0, + 0x2, /*16 bits*/ + 0x3, /*20 bits*/ + 0xb /*24 bits*/ +}; + +void hdmi_tx_set_N_CTS(unsigned int N_value, unsigned int CTS) +{ +} + +static void hdmi_tx_construct_aud_packet( + struct hdmitx_audpara *audio_param, unsigned char *AUD_DB, + unsigned char *CHAN_STAT_BUF, int hdmi_ch) +{ +#ifndef PCM_USE_INFOFRAME + if (audio_param->type == CT_PCM) { + hdmi_print(INF, AUD "Audio Type: PCM\n"); + if (AUD_DB) { + /*Note: HDMI Spec V1.4 Page 154*/ + if ((audio_param->channel_num == CC_2CH) || + (audio_param->channel_num == + CC_REFER_TO_STREAM)) + AUD_DB[0] = 0; + else + AUD_DB[0] = (0<<4)|(audio_param->channel_num); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[2] = 0x0; + if (audio_param->channel_num == CC_6CH) + AUD_DB[3] = 0xb; + else if (audio_param->channel_num == CC_8CH) { + if (hdmi_ch == CC_6CH) + AUD_DB[3] = 0x0b; + else + AUD_DB[3] = 0x13; + } else + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + if (CHAN_STAT_BUF) { + CHAN_STAT_BUF[2] = 0x10|(audio_param->channel_num+1); + CHAN_STAT_BUF[24+2] = 0x20|(audio_param->channel_num+1); + CHAN_STAT_BUF[3] = CHAN_STAT_BUF[24+3] = + channel_status_freq[audio_param->sample_rate]; + CHAN_STAT_BUF[4] = CHAN_STAT_BUF[24+4] = + channel_status_sample_word_length[ + audio_param->sample_size]| + ((~channel_status_freq[ + audio_param->sample_rate])<<4); + } + } else if (audio_param->type == CT_AC_3) { + hdmi_print(INF, AUD "Audio Type: AC3\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_AC_3<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_MPEG1) { + hdmi_print(INF, AUD "Audio Type: MPEG1\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_MPEG1<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_MP3) { + hdmi_print(INF, AUD "Audio Type: MP3\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_MP3<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_MPEG2) { + hdmi_print(INF, AUD "Audio Type: MPEG2\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_MPEG2<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_AAC) { + hdmi_print(INF, AUD "Audio Type: AAC\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_AAC<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_DTS) { + hdmi_print(INF, AUD "Audio Type: DTS\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_DTS<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_ATRAC) { + hdmi_print(INF, AUD "Audio Type: ATRAC\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_ATRAC<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_ONE_BIT_AUDIO) { + hdmi_print(INF, AUD "Audio Type: One Bit Audio\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_ONE_BIT_AUDIO<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_DOLBY_D) { + hdmi_print(INF, AUD "Audio Type: Dobly Digital +\n"); + if (AUD_DB) { + AUD_DB[0] = + (FS_REFER_TO_STREAM<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + if (CHAN_STAT_BUF) { + CHAN_STAT_BUF[0] = CHAN_STAT_BUF[24+0] = 0x2; + CHAN_STAT_BUF[3] = CHAN_STAT_BUF[24+3] = 0x1e; + CHAN_STAT_BUF[4] = CHAN_STAT_BUF[24+4] = 0x1; + } + } else if (audio_param->type == CT_DTS_HD) { + hdmi_print(INF, AUD "Audio Type: DTS-HD\n"); + if (AUD_DB) { + AUD_DB[0] = + (FS_REFER_TO_STREAM<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_MAT) { + hdmi_print(INF, AUD "Audio Type: MAT(MLP)\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_MAT<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_DST) { + hdmi_print(INF, AUD "Audio Type: DST\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_DST<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else if (audio_param->type == CT_WMA) { + hdmi_print(INF, AUD "Audio Type: WMA Pro\n"); + if (AUD_DB) { + AUD_DB[0] = (CT_WMA<<4)|(CC_REFER_TO_STREAM); + AUD_DB[1] = (FS_REFER_TO_STREAM<<2)|SS_REFER_TO_STREAM; + AUD_DB[3] = 0; + AUD_DB[4] = 0; + } + } else { + ; + } + AUD_DB[0] = AUD_DB[0] & 0xf;/*bit[7:4] always set to 0 in HDMI*/ + AUD_DB[1] = 0; /*always set to 0 in HDMI*/ +#endif +} + +int hdmitx_set_audio(struct hdmitx_dev *hdmitx_device, + struct hdmitx_audpara *audio_param, int hdmi_ch) +{ + int i, ret = -1; + unsigned char AUD_DB[32]; + unsigned char CHAN_STAT_BUF[24*2]; + + for (i = 0; i < 32; i++) + AUD_DB[i] = 0; + for (i = 0; i < (24*2); i++) + CHAN_STAT_BUF[i] = 0; + if (hdmitx_device->HWOp.SetAudMode(hdmitx_device, + audio_param) >= 0) { + hdmi_tx_construct_aud_packet(audio_param, AUD_DB, + CHAN_STAT_BUF, hdmi_ch); + + hdmitx_device->HWOp.SetAudioInfoFrame(AUD_DB, CHAN_STAT_BUF); + ret = 0; + } + return ret; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c new file mode 100644 index 000000000000..ddfbb955b779 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -0,0 +1,2406 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +/* #include */ +/* #include "hw/hdmi_tx_reg.h" */ +#include +#include +#include +/* #include */ + +#include +#include +#include +#include + +#define CEA_DATA_BLOCK_COLLECTION_ADDR_1StP 0x04 +#define VIDEO_TAG 0x40 +#define AUDIO_TAG 0x20 +#define VENDOR_TAG 0x60 +#define SPEAKER_TAG 0x80 + +#define HDMI_EDID_BLOCK_TYPE_RESERVED 0 +#define HDMI_EDID_BLOCK_TYPE_AUDIO 1 +#define HDMI_EDID_BLOCK_TYPE_VIDEO 2 +#define HDMI_EDID_BLOCK_TYPE_VENDER 3 +#define HDMI_EDID_BLOCK_TYPE_SPEAKER 4 +#define HDMI_EDID_BLOCK_TYPE_VESA 5 +#define HDMI_EDID_BLOCK_TYPE_RESERVED2 6 +#define HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG 7 + +#define EXTENSION_VENDOR_SPECIFIC 0x1 +#define EXTENSION_COLORMETRY_TAG 0x5 +/* DRM stands for "Dynamic Range and Mastering " */ +#define EXTENSION_DRM_TAG 0x6 +/* Video Format Preference Data block */ +#define EXTENSION_VFPDB_TAG 0xd +#define EXTENSION_Y420_VDB_TAG 0xe +#define EXTENSION_Y420_CMDB_TAG 0xf + +#define EDID_DETAILED_TIMING_DES_BLOCK0_POS 0x36 +#define EDID_DETAILED_TIMING_DES_BLOCK1_POS 0x48 +#define EDID_DETAILED_TIMING_DES_BLOCK2_POS 0x5A +#define EDID_DETAILED_TIMING_DES_BLOCK3_POS 0x6C + +/* EDID Descrptor Tag */ +#define TAG_PRODUCT_SERIAL_NUMBER 0xFF +#define TAG_ALPHA_DATA_STRING 0xFE +#define TAG_RANGE_LIMITS 0xFD +#define TAG_DISPLAY_PRODUCT_NAME_STRING 0xFC /* MONITOR NAME */ +#define TAG_COLOR_POINT_DATA 0xFB +#define TAG_STANDARD_TIMINGS 0xFA +#define TAG_DISPLAY_COLOR_MANAGEMENT 0xF9 +#define TAG_CVT_TIMING_CODES 0xF8 +#define TAG_ESTABLISHED_TIMING_III 0xF7 +#define TAG_DUMMY_DES 0x10 + +static unsigned char __nosavedata edid_checkvalue[4] = {0}; +static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf); +static void Edid_DTD_parsing(struct rx_cap *pRXCap, unsigned char *data); + +static void edid_save_checkvalue(unsigned char *buf, unsigned int block_cnt) +{ + unsigned int i, length, max; + + if (buf == NULL) + return; + + length = sizeof(edid_checkvalue); + memset(edid_checkvalue, 0x00, length); + + max = (block_cnt > length)?length:block_cnt; + + for (i = 0; i < max; i++) + edid_checkvalue[i] = *(buf+(i+1)*128-1); +} + +static int Edid_DecodeHeader(struct hdmitx_info *info, unsigned char *buff) +{ + int i, ret = 0; + + if (!(buff[0] | buff[7])) { + for (i = 1; i < 7; i++) { + if (buff[i] != 0xFF) + ret = -1; + } + } else + ret = -1; + return ret; +} + +static void Edid_ReceiverBrandNameParse(struct rx_cap *pRxCap, + unsigned char *data) +{ + int i; + unsigned char uppercase[26] = { 0 }; + unsigned char brand[3]; + + /* Fill array uppercase with 'A' to 'Z' */ + for (i = 0; i < 26; i++) + uppercase[i] = 'A' + i; + + brand[0] = data[0] >> 2; + brand[1] = ((data[0] & 0x3) << 3) + (data[1] >> 5); + brand[2] = data[1] & 0x1f; + + for (i = 0; i < 3; i++) + pRxCap->ReceiverBrandName[i] = uppercase[brand[i] - 1]; +} + +static int Edid_find_name_block(unsigned char *data) +{ + int ret = 0; + int i; + + for (i = 0; i < 3; i++) { + if (data[i]) + return ret; + } + if (data[3] == 0xfc) + ret = 1; + return ret; +} + +static void Edid_ReceiverProductNameParse(struct rx_cap *pRxCap, + unsigned char *data) +{ + int i = 0; + /* some Display Product name end with 0x20, not 0x0a + */ + while ((data[i] != 0x0a) && (data[i] != 0x20) && (i < 13)) { + pRxCap->ReceiverProductName[i] = data[i]; + i++; + } + pRxCap->ReceiverProductName[i] = '\0'; +} + +void Edid_DecodeStandardTiming(struct hdmitx_info *info, + unsigned char *Data, unsigned char length) +{ + unsigned char i, TmpVal; + int hor_pixel, frame_rate; + + for (i = 0; i < length; i++) { + if ((Data[i*2] != 0x01) && (Data[i*2 + 1] != 0x01)) { + hor_pixel = (int)((Data[i*2]+31)*8); + TmpVal = Data[i*2 + 1] & 0xC0; + + frame_rate = (int)((Data[i*2 + 1]) & 0x3F) + 60; + + if ((hor_pixel == 720) && (frame_rate == 30)) + info->hdmi_sup_480i = 1; + else if ((hor_pixel == 720) && (frame_rate == 25)) + info->hdmi_sup_576i = 1; + else if ((hor_pixel == 720) && (frame_rate == 60)) + info->hdmi_sup_480p = 1; + else if ((hor_pixel == 720) && (frame_rate == 50)) + info->hdmi_sup_576p = 1; + else if ((hor_pixel == 1280) && (frame_rate == 60)) + info->hdmi_sup_720p_60hz = 1; + else if ((hor_pixel == 1280) && (frame_rate == 50)) + info->hdmi_sup_720p_50hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 30)) + info->hdmi_sup_1080i_60hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 25)) + info->hdmi_sup_1080i_50hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 60)) + info->hdmi_sup_1080p_60hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 50)) + info->hdmi_sup_1080p_50hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 24)) + info->hdmi_sup_1080p_24hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 25)) + info->hdmi_sup_1080p_25hz = 1; + else if ((hor_pixel == 1920) && (frame_rate == 30)) + info->hdmi_sup_1080p_30hz = 1; + } + } +} + +/* ----------------------------------------------------------- */ +void Edid_CompareTimingDescriptors(struct hdmitx_info *info, + unsigned char *Data) +{ +} + + +/* ----------------------------------------------------------- */ +void Edid_ParseCEADetailedTimingDescriptors(struct hdmitx_info *info, + unsigned char blk_mun, unsigned char BaseAddr, + unsigned char *buff) +{ + unsigned char index_edid; + + for (index_edid = 0; index_edid < blk_mun; index_edid++) { + Edid_CompareTimingDescriptors(info, &buff[BaseAddr]); + BaseAddr += 18; + /* there is not the TimingDescriptors */ + if ((BaseAddr + 18) > 0x7d) + break; + } +} + +static struct vsdb_phyaddr vsdb_local = {0}; +int get_vsdb_phy_addr(struct vsdb_phyaddr *vsdb) +{ + vsdb = &vsdb_local; + return vsdb->valid; +} + +static void set_vsdb_phy_addr(struct vsdb_phyaddr *vsdb, + unsigned char *edid_offset) +{ + vsdb->a = (edid_offset[4] >> 4) & 0xf; + vsdb->b = (edid_offset[4] >> 0) & 0xf; + vsdb->c = (edid_offset[5] >> 4) & 0xf; + vsdb->d = (edid_offset[5] >> 0) & 0xf; + vsdb_local = *vsdb; + vsdb->valid = 1; +} + +static void set_vsdb_dc_cap(struct rx_cap *pRXCap, + unsigned char *edid_offset) +{ + pRXCap->dc_y444 = !!(edid_offset[6] & (1 << 3)); + pRXCap->dc_30bit = !!(edid_offset[6] & (1 << 4)); + pRXCap->dc_36bit = !!(edid_offset[6] & (1 << 5)); + pRXCap->dc_48bit = !!(edid_offset[6] & (1 << 6)); +} + +static void set_vsdb_dc_420_cap(struct rx_cap *pRXCap, + unsigned char *edid_offset) +{ + pRXCap->dc_30bit_420 = !!(edid_offset[6] & (1 << 0)); + pRXCap->dc_36bit_420 = !!(edid_offset[6] & (1 << 1)); + pRXCap->dc_48bit_420 = !!(edid_offset[6] & (1 << 2)); +} + +/* Special FBC check */ +static int check_fbc_special(unsigned char *edid_dat) +{ + if ((edid_dat[250] == 0xfb) && (edid_dat[251] == 0x0c)) + return 1; + else + return 0; +} + +int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev, + unsigned char *buff) +{ + int ret = 0; + struct hdmitx_info *info = &(hdev->hdmi_info); + unsigned char VSpecificBoundary, BlockAddr, len; + int temp_addr = 0; + + VSpecificBoundary = buff[2]; + + if (VSpecificBoundary < 4) + ret = -1; + BlockAddr = CEA_DATA_BLOCK_COLLECTION_ADDR_1StP; + while (BlockAddr < VSpecificBoundary) { + len = buff[BlockAddr] & 0x1F; + if ((buff[BlockAddr] & 0xE0) == VENDOR_TAG) + break; + temp_addr = BlockAddr + len + 1; + if (temp_addr >= VSpecificBoundary) + break; + BlockAddr = BlockAddr + len + 1; + } + + set_vsdb_phy_addr(&info->vsdb_phy_addr, &buff[BlockAddr]); + if ((check_fbc_special(&hdev->EDID_buf[0])) || + (check_fbc_special(&hdev->EDID_buf1[0]))) + rx_edid_physical_addr(0, 0, 0, 0); + else + rx_edid_physical_addr(info->vsdb_phy_addr.a, + info->vsdb_phy_addr.b, + info->vsdb_phy_addr.c, + info->vsdb_phy_addr.d); + set_vsdb_dc_cap(&hdev->RXCap, &buff[BlockAddr]); + + if (temp_addr >= VSpecificBoundary) + ret = -1; + else { + if ((buff[BlockAddr + 1] != 0x03) || + (buff[BlockAddr + 2] != 0x0C) || + (buff[BlockAddr + 3] != 0x0)) + ret = -1; + } + return ret; +} + +/* ----------------------------------------------------------- */ +void Edid_MonitorCapable861(struct hdmitx_info *info, + unsigned char edid_flag) +{ + if (edid_flag & 0x80) + info->support_underscan_flag = 1; + if (edid_flag & 0x40) + info->support_basic_audio_flag = 1; + if (edid_flag & 0x20) + info->support_ycbcr444_flag = 1; + if (edid_flag & 0x10) + info->support_ycbcr422_flag = 1; +} + + +/* ----------------------------------------------------------- */ +static void Edid_ParsingVideoDATABlock(struct hdmitx_info *info, + unsigned char *buff, unsigned char BaseAddr, + unsigned char NBytes) +{ + unsigned char i; + + NBytes &= 0x1F; + for (i = 0; i < NBytes; i++) { + switch (buff[i + BaseAddr]&0x7F) { + case 6: + case 7: + info->hdmi_sup_480i = 1; + break; + case 21: + case 22: + info->hdmi_sup_576i = 1; + break; + case 2: + case 3: + info->hdmi_sup_480p = 1; + break; + case 17: + case 18: + info->hdmi_sup_576p = 1; + break; + case 4: + info->hdmi_sup_720p_60hz = 1; + break; + case 19: + info->hdmi_sup_720p_50hz = 1; + break; + case 5: + info->hdmi_sup_1080i_60hz = 1; + break; + case 20: + info->hdmi_sup_1080i_50hz = 1; + break; + case 16: + info->hdmi_sup_1080p_60hz = 1; + break; + case 31: + info->hdmi_sup_1080p_50hz = 1; + break; + case 32: + info->hdmi_sup_1080p_24hz = 1; + break; + case 33: + info->hdmi_sup_1080p_25hz = 1; + break; + case 34: + info->hdmi_sup_1080p_30hz = 1; + break; + default: + break; + } + } +} + +/* ----------------------------------------------------------- */ +static void Edid_ParsingAudioDATABlock(struct hdmitx_info *info, + unsigned char *Data, unsigned char BaseAddr, + unsigned char NBytes) +{ + unsigned char AudioFormatCode; + int i = BaseAddr; + NBytes &= 0x1F; + do { + AudioFormatCode = (Data[i]&0xF8)>>3; + switch (AudioFormatCode) { + case 1: + info->tv_audio_info._60958_PCM.support_flag = 1; + info->tv_audio_info._60958_PCM.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._60958_PCM._192k = + 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._60958_PCM._176k = + 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._60958_PCM._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._60958_PCM._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._60958_PCM._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._60958_PCM._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._60958_PCM._32k = 1; + if ((Data[i+2]&0x04)) + info->tv_audio_info._60958_PCM._24bit = 1; + if ((Data[i+2]&0x02)) + info->tv_audio_info._60958_PCM._20bit = 1; + if ((Data[i+2]&0x01)) + info->tv_audio_info._60958_PCM._16bit = 1; + break; + case 2: + info->tv_audio_info._AC3.support_flag = 1; + info->tv_audio_info._AC3.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._AC3._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._AC3._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._AC3._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._AC3._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._AC3._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._AC3._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._AC3._32k = 1; + info->tv_audio_info._AC3._max_bit = + Data[i+2]; + break; + case 3: + info->tv_audio_info._MPEG1.support_flag = 1; + info->tv_audio_info._MPEG1.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._MPEG1._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._MPEG1._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._MPEG1._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._MPEG1._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._MPEG1._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._MPEG1._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._MPEG1._32k = 1; + info->tv_audio_info._MPEG1._max_bit = + Data[i+2]; + break; + case 4: + info->tv_audio_info._MP3.support_flag = 1; + info->tv_audio_info._MP3.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._MP3._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._MP3._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._MP3._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._MP3._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._MP3._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._MP3._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._MP3._32k = 1; + info->tv_audio_info._MP3._max_bit = Data[i+2]; + break; + case 5: + info->tv_audio_info._MPEG2.support_flag = 1; + info->tv_audio_info._MPEG2.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._MPEG2._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._MPEG2._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._MPEG2._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._MPEG2._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._MPEG2._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._MPEG2._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._MPEG2._32k = 1; + info->tv_audio_info._MPEG2._max_bit = Data[i+2]; + break; + case 6: + info->tv_audio_info._AAC.support_flag = 1; + info->tv_audio_info._AAC.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._AAC._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._AAC._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._AAC._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._AAC._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._AAC._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._AAC._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._AAC._32k = 1; + info->tv_audio_info._AAC._max_bit = Data[i+2]; + break; + case 7: + info->tv_audio_info._DTS.support_flag = 1; + info->tv_audio_info._DTS.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._DTS._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._DTS._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._DTS._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._DTS._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._DTS._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._DTS._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._DTS._32k = 1; + info->tv_audio_info._DTS._max_bit = Data[i+2]; + break; + case 8: + info->tv_audio_info._ATRAC.support_flag = 1; + info->tv_audio_info._ATRAC.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._ATRAC._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._ATRAC._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._ATRAC._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._ATRAC._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._ATRAC._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._ATRAC._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._ATRAC._32k = 1; + info->tv_audio_info._ATRAC._max_bit = Data[i+2]; + break; + case 9: + info->tv_audio_info._One_Bit_Audio.support_flag = 1; + info->tv_audio_info._One_Bit_Audio.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._One_Bit_Audio._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._One_Bit_Audio._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._One_Bit_Audio._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._One_Bit_Audio._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._One_Bit_Audio._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._One_Bit_Audio._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._One_Bit_Audio._32k = 1; + info->tv_audio_info._One_Bit_Audio._max_bit = + Data[i+2]; + break; + case 10: + info->tv_audio_info._Dolby.support_flag = 1; + info->tv_audio_info._Dolby.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._Dolby._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._Dolby._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._Dolby._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._Dolby._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._Dolby._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._Dolby._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._Dolby._32k = 1; + info->tv_audio_info._Dolby._max_bit = Data[i+2]; + break; + + case 11: + info->tv_audio_info._DTS_HD.support_flag = 1; + info->tv_audio_info._DTS_HD.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._DTS_HD._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._DTS_HD._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._DTS_HD._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._DTS_HD._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._DTS_HD._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._DTS_HD._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._DTS_HD._32k = 1; + info->tv_audio_info._DTS_HD._max_bit = + Data[i+2]; + break; + case 12: + info->tv_audio_info._MAT.support_flag = 1; + info->tv_audio_info._MAT.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._MAT._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._MAT._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._MAT._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._MAT._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._MAT._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._MAT._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._MAT._32k = 1; + info->tv_audio_info._MAT._max_bit = Data[i+2]; + break; + + case 13: + info->tv_audio_info._ATRAC.support_flag = 1; + info->tv_audio_info._ATRAC.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._DST._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._DST._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._DST._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._DST._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._DST._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._DST._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._DST._32k = 1; + info->tv_audio_info._DST._max_bit = Data[i+2]; + break; + + case 14: + info->tv_audio_info._WMA.support_flag = 1; + info->tv_audio_info._WMA.max_channel_num = + (Data[i]&0x07); + if ((Data[i+1]&0x40)) + info->tv_audio_info._WMA._192k = 1; + if ((Data[i+1]&0x20)) + info->tv_audio_info._WMA._176k = 1; + if ((Data[i+1]&0x10)) + info->tv_audio_info._WMA._96k = 1; + if ((Data[i+1]&0x08)) + info->tv_audio_info._WMA._88k = 1; + if ((Data[i+1]&0x04)) + info->tv_audio_info._WMA._48k = 1; + if ((Data[i+1]&0x02)) + info->tv_audio_info._WMA._44k = 1; + if ((Data[i+1]&0x01)) + info->tv_audio_info._WMA._32k = 1; + info->tv_audio_info._WMA._max_bit = Data[i+2]; + break; + + default: + break; + } + i += 3; + } while (i < (NBytes + BaseAddr)); +} + +/* ----------------------------------------------------------- */ +static void Edid_ParsingSpeakerDATABlock(struct hdmitx_info *info, + unsigned char *buff, unsigned char BaseAddr) +{ + int ii; + + for (ii = 1; ii < 0x80; ) { + switch (buff[BaseAddr] & ii) { + case 0x40: + info->tv_audio_info.speaker_allocation.rlc_rrc = 1; + break; + + case 0x20: + info->tv_audio_info.speaker_allocation.flc_frc = 1; + break; + + case 0x10: + info->tv_audio_info.speaker_allocation.rc = 1; + break; + + case 0x08: + info->tv_audio_info.speaker_allocation.rl_rr = 1; + break; + + case 0x04: + info->tv_audio_info.speaker_allocation.fc = 1; + break; + + case 0x02: + info->tv_audio_info.speaker_allocation.lfe = 1; + break; + + case 0x01: + info->tv_audio_info.speaker_allocation.fl_fr = 1; + break; + + default: + break; + } + ii = ii << 1; + } +} + +static void Edid_ParsingVendSpec(struct rx_cap *pRXCap, + unsigned char *buf) +{ + struct dv_info *dv = &pRXCap->dv_info; + unsigned char *dat = buf; + unsigned char len; + unsigned char pos = 0; + + len = dat[pos] & 0x1f; + pos++; + + if (dat[pos] == 1) + pos++; + else { + pr_info("hdmitx: edid: parsing fail %s[%d]\n", __func__, + __LINE__); + return; + } + + dv->ieeeoui = dat[pos++]; + dv->ieeeoui += dat[pos++] << 8; + dv->ieeeoui += dat[pos++] << 16; + + dv->ver = (dat[pos] >> 5) & 0x7; + /* Refer to DV 2.6 Page 11 */ + if (dv->ver == 0) { + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; + dv->sup_global_dimming = (dat[pos] >> 2) & 0x1; + pos++; + dv->vers.ver0.chrom_red_primary_x = + (dat[pos+1] << 8) | (dat[pos] >> 4); + dv->vers.ver0.chrom_red_primary_y = + (dat[pos+2] << 8) | (dat[pos] & 0xf); + pos += 3; + dv->vers.ver0.chrom_green_primary_x = + (dat[pos+1] << 8) | (dat[pos] >> 4); + dv->vers.ver0.chrom_green_primary_y = + (dat[pos+2] << 8) | (dat[pos] & 0xf); + pos += 3; + dv->vers.ver0.chrom_blue_primary_x = + (dat[pos+1] << 8) | (dat[pos] >> 4); + dv->vers.ver0.chrom_blue_primary_y = + (dat[pos+2] << 8) | (dat[pos] & 0xf); + pos += 3; + dv->vers.ver0.chrom_white_primary_x = + (dat[pos+1] << 8) | (dat[pos] >> 4); + dv->vers.ver0.chrom_white_primary_y = + (dat[pos+2] << 8) | (dat[pos] & 0xf); + pos += 3; + dv->vers.ver0.target_min_pq = + (dat[pos+1] << 8) | (dat[pos] >> 4); + dv->vers.ver0.target_max_pq = + (dat[pos+2] << 8) | (dat[pos] & 0xf); + pos += 3; + dv->vers.ver0.dm_major_ver = dat[pos] >> 4; + dv->vers.ver0.dm_minor_ver = dat[pos] & 0xf; + pos++; + } + /* Refer to DV 2.6 Page 14 */ + if (dv->ver == 1) { + dv->vers.ver1.dm_version = (dat[pos] >> 2) & 0x7; + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; + pos++; + dv->sup_global_dimming = dat[pos] & 0x1; + dv->vers.ver1.target_max_lum = dat[pos] >> 1; + pos++; + dv->colorimetry = dat[pos] & 0x1; + dv->vers.ver1.target_min_lum = dat[pos] >> 1; + pos += 2; /* byte8 is reserved as 0 */ + dv->vers.ver1.chrom_red_primary_x = dat[pos++]; + dv->vers.ver1.chrom_red_primary_y = dat[pos++]; + dv->vers.ver1.chrom_green_primary_x = dat[pos++]; + dv->vers.ver1.chrom_green_primary_y = dat[pos++]; + dv->vers.ver1.chrom_blue_primary_x = dat[pos++]; + dv->vers.ver1.chrom_blue_primary_y = dat[pos++]; + } + if (pos > len) + pr_info("hdmitx: edid: maybe invalid dv%d data\n", dv->ver); +} + +/* ----------------------------------------------------------- */ +static int Edid_ParsingY420VDBBlock(struct rx_cap *pRXCap, + unsigned char *buf) +{ + unsigned char tag = 0, ext_tag = 0, data_end = 0; + unsigned int pos = 0; + int i = 0, found = 0; + + tag = (buf[pos] >> 5) & 0x7; + data_end = (buf[pos] & 0x1f)+1; + pos++; + ext_tag = buf[pos]; + + if ((tag != 0x7) || (ext_tag != 0xe)) + goto INVALID_Y420VDB; + + pos++; + while (pos < data_end) { + if (pRXCap->VIC_count < VIC_MAX_NUM) { + for (i = 0; i < pRXCap->VIC_count; i++) { + if (pRXCap->VIC[i] == buf[pos]) { + pRXCap->VIC[i] = + HDMITX_VIC420_OFFSET + buf[pos]; + found = 1; + /* Here we do not break,because + * some EDID may have the same + * repeated VICs + */ + } + } + if (found == 0) { + pRXCap->VIC[pRXCap->VIC_count] = + HDMITX_VIC420_OFFSET + buf[pos]; + pRXCap->VIC_count++; + } + } + pos++; + } + + return 0; + +INVALID_Y420VDB: + pr_info("[%s] it's not a valid y420vdb!\n", __func__); + return -1; +} + +static int Edid_ParsingDRMBlock(struct rx_cap *pRXCap, + unsigned char *buf) +{ + unsigned char tag = 0, ext_tag = 0, data_end = 0; + unsigned int pos = 0; + + tag = (buf[pos] >> 5) & 0x7; + data_end = (buf[pos] & 0x1f); + pos++; + ext_tag = buf[pos]; + if ((tag != HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG) + || (ext_tag != EXTENSION_DRM_TAG)) + goto INVALID_DRM; + pos++; + pRXCap->hdr_sup_eotf_sdr = !!(buf[pos] & (0x1 << 0)); + pRXCap->hdr_sup_eotf_hdr = !!(buf[pos] & (0x1 << 1)); + pRXCap->hdr_sup_eotf_smpte_st_2084 = !!(buf[pos] & (0x1 << 2)); + pRXCap->hdr_sup_eotf_future = !!(buf[pos] & (0x1 << 3)); + pos++; + pRXCap->hdr_sup_SMD_type1 = !!(buf[pos] & (0x1 << 0)); + pos++; + if (data_end == 3) + return 0; + if (data_end == 4) { + pRXCap->hdr_lum_max = buf[pos]; + return 0; + } + if (data_end == 5) { + pRXCap->hdr_lum_max = buf[pos]; + pRXCap->hdr_lum_avg = buf[pos + 1]; + return 0; + } + if (data_end == 6) { + pRXCap->hdr_lum_max = buf[pos]; + pRXCap->hdr_lum_avg = buf[pos + 1]; + pRXCap->hdr_lum_min = buf[pos + 2]; + return 0; + } + return 0; +INVALID_DRM: + pr_info("[%s] it's not a valid DRM\n", __func__); + return -1; +} + +static int Edid_ParsingVFPDB(struct rx_cap *pRXCap, unsigned char *buf) +{ + unsigned int len = buf[0] & 0x1f; + enum hdmi_vic svr = HDMI_Unknown; + + if (buf[1] != EXTENSION_VFPDB_TAG) + return 0; + if (len < 2) + return 0; + + svr = buf[2]; + if (((svr >= 1) && (svr <= 127)) || + ((svr >= 193) && (svr <= 253))) { + pRXCap->flag_vfpdb = 1; + pRXCap->preferred_mode = svr; + pr_info("preferred mode 0 srv %d\n", pRXCap->preferred_mode); + return 1; + } + if ((svr >= 129) && (svr <= 144)) { + pRXCap->flag_vfpdb = 1; + pRXCap->preferred_mode = pRXCap->dtd[svr - 129].vic; + pr_info("preferred mode 0 dtd %d\n", pRXCap->preferred_mode); + return 1; + } + return 0; +} + +/* ----------------------------------------------------------- */ +static int Edid_ParsingY420CMDBBlock(struct hdmitx_info *info, + unsigned char *buf) +{ + unsigned char tag = 0, ext_tag = 0, length = 0, data_end = 0; + unsigned int pos = 0, i = 0; + + tag = (buf[pos] >> 5) & 0x7; + length = buf[pos] & 0x1f; + data_end = length + 1; + pos++; + ext_tag = buf[pos]; + + if ((tag != 0x7) || (ext_tag != 0xf)) + goto INVALID_Y420CMDB; + + if (length == 1) { + info->y420_all_vic = 1; + return 0; + } + + info->bitmap_length = 0; + info->bitmap_valid = 0; + memset(info->y420cmdb_bitmap, 0x00, Y420CMDB_MAX); + + pos++; + if (pos < data_end) { + info->bitmap_length = data_end - pos; + info->bitmap_valid = 1; + } + while (pos < data_end) { + if (i < VIC_MAX_NUM) + info->y420cmdb_bitmap[i] = buf[pos]; + pos++; + i++; + } + + return 0; + +INVALID_Y420CMDB: + pr_info("[%s] it's not a valid y420cmdb!\n", __func__); + return -1; + +} + +static int Edid_Y420CMDB_fill_all_vic(struct hdmitx_dev *hdmitx_device) +{ + struct rx_cap *rxcap = &(hdmitx_device->RXCap); + struct hdmitx_info *info = &(hdmitx_device->hdmi_info); + unsigned int count = rxcap->VIC_count; + unsigned int a, b; + + if (info->y420_all_vic != 1) + return 1; + + a = count/8; + a = (a >= Y420CMDB_MAX)?Y420CMDB_MAX:a; + b = count%8; + + if (a > 0) + memset(&(info->y420cmdb_bitmap[0]), 0xff, a); + + if ((b != 0) && (a < Y420CMDB_MAX)) + info->y420cmdb_bitmap[a] = (((1 << b) - 1) << (8-b)); + + info->bitmap_length = (b == 0) ? a : (a + 1); + info->bitmap_valid = (info->bitmap_length != 0)?1:0; + + return 0; +} + +static int Edid_Y420CMDB_PostProcess(struct hdmitx_dev *hdmitx_device) +{ + unsigned int i = 0, j = 0, valid = 0; + struct rx_cap *rxcap = &(hdmitx_device->RXCap); + struct hdmitx_info *info = &(hdmitx_device->hdmi_info); + unsigned char *p = NULL; + + if (info->y420_all_vic == 1) + Edid_Y420CMDB_fill_all_vic(hdmitx_device); + + if (info->bitmap_valid == 0) + goto PROCESS_END; + + for (i = 0; i < info->bitmap_length; i++) { + p = &(info->y420cmdb_bitmap[i]); + for (j = 0; j < 8; j++) { + valid = ((*p >> j) & 0x1); + if (valid != 0) { + rxcap->VIC[rxcap->VIC_count] = + HDMITX_VIC420_OFFSET + rxcap->VIC[i*8+j]; + rxcap->VIC_count++; + } + } + } + +PROCESS_END: + return 0; +} + +static void Edid_Y420CMDB_Reset(struct hdmitx_info *info) +{ + info->bitmap_valid = 0; + info->bitmap_length = 0; + info->y420_all_vic = 0; + memset(info->y420cmdb_bitmap, 0x00, Y420CMDB_MAX); +} + +static char *rptx_edid_aud; +static char rptx_edid_buf[512]; +MODULE_PARM_DESC(rptx_edid_aud, "\n receive_edid\n"); +module_param(rptx_edid_aud, charp, 0444); + +/* ----------------------------------------------------------- */ +int Edid_ParsingCEADataBlockCollection(struct hdmitx_info *info, + unsigned char *buff) +{ + unsigned char AddrTag, D, Addr, Data; + int temp_addr, i, len, pos; + + /* Byte number offset d where Detailed Timing data begins */ + D = buff[2]; + Addr = 4; + + AddrTag = Addr; + do { + Data = buff[AddrTag]; + switch (Data&0xE0) { + case VIDEO_TAG: + if ((Addr + (Data&0x1f)) < D) + Edid_ParsingVideoDATABlock(info, buff, + Addr + 1, (Data & 0x1F)); + break; + + case AUDIO_TAG: + len = (Data & 0x1f) + 1; + rx_set_receiver_edid(&buff[AddrTag], len); + for (pos = 0, i = 0; i < len; i++) + pos += sprintf(rptx_edid_buf+pos, "%02x", + buff[AddrTag + i]); + rptx_edid_buf[pos + 1] = 0; + if ((Addr + (Data&0x1f)) < D) + Edid_ParsingAudioDATABlock(info, buff, + Addr + 1, (Data & 0x1F)); + break; + + case SPEAKER_TAG: + if ((Addr + (Data&0x1f)) < D) + Edid_ParsingSpeakerDATABlock(info, buff, + Addr + 1); + break; + + case VENDOR_TAG: + if ((Addr + (Data&0x1f)) < D) { + if ((buff[Addr + 1] != 0x03) || + (buff[Addr + 2] != 0x0c) || + (buff[Addr + 3] != 0x00)) { + info->auth_state = HDCP_NO_AUTH; + } + if ((Data&0x1f) > 5) { + if (buff[Addr + 6] & 0x80) + info->support_ai_flag = 1; + } + } + break; + + default: + break; + } + Addr += (Data & 0x1F); /* next Tag Address */ + AddrTag = ++Addr; + Data = buff[Addr]; + temp_addr = Addr + (Data & 0x1F); + if (temp_addr >= D) /* force to break; */ + break; + } while (Addr < D); + + return 0; +} + +/* ----------------------------------------------------------- */ + +/* parse Sink 3D information */ +static int hdmitx_edid_3d_parse(struct rx_cap *pRXCap, unsigned char *dat, + unsigned int size) +{ + int j = 0; + unsigned int base = 0; + unsigned int pos = base + 1; + + if (dat[base] & (1 << 7)) + pos += 2; + if (dat[base] & (1 << 6)) + pos += 2; + if (dat[base] & (1 << 5)) { + pRXCap->threeD_present = dat[pos] >> 7; + pRXCap->threeD_Multi_present = (dat[pos] >> 5) & 0x3; + pos += 1; + pRXCap->hdmi_vic_LEN = dat[pos] >> 5; + pRXCap->HDMI_3D_LEN = dat[pos] & 0x1f; + pos += pRXCap->hdmi_vic_LEN + 1; + + if (pRXCap->threeD_Multi_present == 0x01) { + pRXCap->threeD_Structure_ALL_15_0 = + (dat[pos] << 8) + dat[pos+1]; + pRXCap->threeD_MASK_15_0 = 0; + pos += 2; + } + if (pRXCap->threeD_Multi_present == 0x02) { + pRXCap->threeD_Structure_ALL_15_0 = + (dat[pos] << 8) + dat[pos+1]; + pos += 2; + pRXCap->threeD_MASK_15_0 = (dat[pos] << 8) + dat[pos+1]; + pos += 2; + } + } + while (pos < size) { + if ((dat[pos] & 0xf) < 0x8) { + /* frame packing */ + if ((dat[pos] & 0xf) == T3D_FRAME_PACKING) + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] + & 0xf0) >> 4)]].frame_packing = 1; + /* top and bottom */ + if ((dat[pos] & 0xf) == T3D_TAB) + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] + & 0xf0) >> 4)]].top_and_bottom = 1; + pos += 1; + } else { + /* SidebySide */ + if ((dat[pos] & 0xf) == T3D_SBS_HALF) + if ((dat[pos+1] >> 4) < 0xb) + pRXCap->support_3d_format[pRXCap->VIC[ + ((dat[pos] & 0xf0) >> 4)]] + .side_by_side = 1; + pos += 2; + } + } + if (pRXCap->threeD_MASK_15_0 == 0) { + for (j = 0; (j < 16) && (j < pRXCap->VIC_count); j++) { + pRXCap->support_3d_format[pRXCap->VIC[j]].frame_packing + = 1; + pRXCap->support_3d_format[pRXCap->VIC[j]].top_and_bottom + = 1; + pRXCap->support_3d_format[pRXCap->VIC[j]].side_by_side + = 1; + } + } else { + for (j = 0; j < 16; j++) { + if (((pRXCap->threeD_MASK_15_0) >> j) & 0x1) { + /* frame packing */ + if (pRXCap->threeD_Structure_ALL_15_0 + & (1 << 0)) + pRXCap->support_3d_format[pRXCap-> + VIC[j]].frame_packing = 1; + /* top and bottom */ + if (pRXCap->threeD_Structure_ALL_15_0 + & (1 << 6)) + pRXCap->support_3d_format[pRXCap-> + VIC[j]].top_and_bottom = 1; + /* top and bottom */ + if (pRXCap->threeD_Structure_ALL_15_0 + & (1 << 8)) + pRXCap->support_3d_format[pRXCap-> + VIC[j]].side_by_side = 1; + } + } + } + return 1; +} + +/* parse Sink 4k2k information */ +static void hdmitx_edid_4k2k_parse(struct rx_cap *pRXCap, unsigned char *dat, + unsigned int size) +{ + if ((size > 4) || (size == 0)) { + hdmi_print(ERR, EDID + "HDMI: 4k2k in edid out of range, SIZE = %d\n", + size); + return; + } + while (size--) { + if (*dat == 1) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_30; + else if (*dat == 2) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_25; + else if (*dat == 3) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_24; + else if (*dat == 4) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_smpte_24; + else + ; + dat++; + pRXCap->VIC_count++; + } +} + +static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, + unsigned char *BlockBuf) +{ + unsigned char offset, End; + unsigned char count; + unsigned char tag; + int i, tmp, idx; + unsigned char *vfpdb_offset = NULL; + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + + if (BlockBuf[0] != 0x02) + return -1; /* not a CEA BLOCK. */ + End = BlockBuf[2]; /* CEA description. */ + pRXCap->native_Mode = BlockBuf[3]; + pRXCap->number_of_dtd += BlockBuf[3] & 0xf; + + pRXCap->VIC_count = 0; + pRXCap->native_VIC = 0xff; + + Edid_Y420CMDB_Reset(&(hdmitx_device->hdmi_info)); + + for (offset = 4 ; offset < End ; ) { + tag = BlockBuf[offset] >> 5; + count = BlockBuf[offset] & 0x1f; + switch (tag) { + case HDMI_EDID_BLOCK_TYPE_AUDIO: + pRXCap->AUD_count = count/3; + offset++; + for (i = 0 ; i < pRXCap->AUD_count ; i++) { + pRXCap->RxAudioCap[i].audio_format_code = + (BlockBuf[offset + i * 3]>>3)&0xf; + pRXCap->RxAudioCap[i].channel_num_max = + BlockBuf[offset + i * 3]&0x7; + pRXCap->RxAudioCap[i].freq_cc = + BlockBuf[offset + i * 3 + 1]&0x7f; + pRXCap->RxAudioCap[i].cc3 = + BlockBuf[offset + i * 3 + 2]&0x7; + } + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_VIDEO: + offset++; + for (i = 0 ; i < count ; i++) { + unsigned char VIC; + + VIC = BlockBuf[offset + i] & (~0x80); + pRXCap->VIC[pRXCap->VIC_count] = VIC; + if (BlockBuf[offset + i] & 0x80) + pRXCap->native_VIC = VIC; + pRXCap->VIC_count++; + } + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_VENDER: + offset++; + if ((BlockBuf[offset] == 0x03) && + (BlockBuf[offset+1] == 0x0c) && + (BlockBuf[offset+2] == 0x00)) + pRXCap->IEEEOUI = 0x000c03; + else + goto case_hf; + pRXCap->ColorDeepSupport = + (unsigned long)BlockBuf[offset+5]; + pRXCap->Max_TMDS_Clock1 = + (unsigned long)BlockBuf[offset+6]; + if (count > 7) { + tmp = BlockBuf[offset+7]; + idx = offset + 8; + if (tmp & (1<<6)) + idx += 2; + if (tmp & (1<<7)) + idx += 2; + if (tmp & (1<<5)) { + idx += 1; + /* valid 4k */ + if (BlockBuf[idx] & 0xe0) { + hdmitx_edid_4k2k_parse( + pRXCap, + &BlockBuf[idx + 1], + BlockBuf[idx] >> 5); + } + /* valid 3D */ + if (BlockBuf[idx-1] & 0xe0) { + hdmitx_edid_3d_parse( + pRXCap, + &BlockBuf[offset+7], + count - 7); + } + } + } + goto case_next; +case_hf: + if ((BlockBuf[offset] == 0xd8) && + (BlockBuf[offset+1] == 0x5d) && + (BlockBuf[offset+2] == 0xc4)) + pRXCap->HF_IEEEOUI = 0xd85dc4; + pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; + pRXCap->scdc_present = + !!(BlockBuf[offset+5] & (1 << 7)); + pRXCap->scdc_rr_capable = + !!(BlockBuf[offset+5] & (1 << 6)); + pRXCap->lte_340mcsc_scramble = + !!(BlockBuf[offset+5] & (1 << 3)); + set_vsdb_dc_420_cap(&hdmitx_device->RXCap, + &BlockBuf[offset]); +case_next: + offset += count; /* ignore the remaind. */ + break; + + case HDMI_EDID_BLOCK_TYPE_SPEAKER: + offset++; + pRXCap->RxSpeakerAllocation = BlockBuf[offset]; + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_VESA: + offset++; + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG: + { + unsigned char ext_tag = 0; + + ext_tag = BlockBuf[offset+1]; + switch (ext_tag) { + case EXTENSION_VENDOR_SPECIFIC: + Edid_ParsingVendSpec(pRXCap, + &BlockBuf[offset]); + break; + case EXTENSION_COLORMETRY_TAG: + pRXCap->colorimetry_data = + BlockBuf[offset + 2]; + break; + case EXTENSION_DRM_TAG: + Edid_ParsingDRMBlock(pRXCap, + &BlockBuf[offset]); + break; + case EXTENSION_VFPDB_TAG: +/* Just record VFPDB offset address, call Edid_ParsingVFPDB() after DTD + * parsing, in case that + * SVR >=129 and SVR <=144, Interpret as the Kth DTD in the EDID, + * where K = SVR – 128 (for K=1 to 16) + */ + vfpdb_offset = &BlockBuf[offset]; + break; + case EXTENSION_Y420_VDB_TAG: + Edid_ParsingY420VDBBlock(pRXCap, + &BlockBuf[offset]); + break; + case EXTENSION_Y420_CMDB_TAG: + Edid_ParsingY420CMDBBlock( + &(hdmitx_device->hdmi_info), + &BlockBuf[offset]); + break; + default: + break; + } + } + offset += count+1; + break; + + case HDMI_EDID_BLOCK_TYPE_RESERVED: + offset++; + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_RESERVED2: + offset++; + offset += count; + break; + + default: + break; + } + } + + Edid_Y420CMDB_PostProcess(hdmitx_device); + hdmitx_device->vic_count = pRXCap->VIC_count; + + idx = BlockBuf[3] & 0xf; + for (i = 0; i < idx; i++) + Edid_DTD_parsing(pRXCap, &BlockBuf[BlockBuf[2] + i * 18]); + if (vfpdb_offset) + Edid_ParsingVFPDB(pRXCap, vfpdb_offset); + + return 0; +} + +/* add default VICs for DVI case */ +static void hdmitx_edid_set_default_vic(struct hdmitx_dev *hdmitx_device) +{ + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + + pRXCap->VIC_count = 0x3; + pRXCap->VIC[0] = HDMI_720x480p60_16x9; + pRXCap->VIC[1] = HDMI_1280x720p60_16x9; + pRXCap->VIC[2] = HDMI_1920x1080p60_16x9; + pRXCap->native_VIC = HDMI_720x480p60_16x9; + hdmitx_device->vic_count = pRXCap->VIC_count; + hdmi_print(IMP, EDID "HDMI: set default vic\n"); +} + +#if 0 +#define PRINT_HASH(hash) \ + { \ + pr_info("%s:%d ", __func__, __LINE__); int __i; \ + for (__i = 0; __i < 20; __i++) \ + pr_info("%02x,", hash[__i]); \ + pr_info("\n");\ + } +#else +#define PRINT_HASH(hash) +#endif + +static int edid_hash_calc(unsigned char *hash, const char *data, + unsigned int len) +{ +#if 0 + struct scatterlist sg; + + struct crypto_hash *tfm; + struct hash_desc desc; + + tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); + PRINT_HASH(hash); + if (IS_ERR(tfm)) + return -EINVAL; + + PRINT_HASH(hash); + /* ... set up the scatterlists ... */ + sg_init_one(&sg, (u8 *) data, len); + desc.tfm = tfm; + desc.flags = 0; + + + + if (crypto_hash_digest(&desc, &sg, len, hash)) + return -EINVAL; + + err = crypto_ahash_digest(req); + ahash_request_zero(req); + + PRINT_HASH(hash); + crypto_free_hash(tfm); +#endif + return 1; +} + +static int hdmitx_edid_search_IEEEOUI(char *buf) +{ + int i; + + for (i = 0; i < 0x180; i++) { + if ((buf[i] == 0x03) && (buf[i+1] == 0x0c) && + (buf[i+2] == 0x00)) + return 1; + } + return 0; +} + +/* check EDID strictly */ +static int edid_check_valid(unsigned char *buf) +{ + unsigned int chksum = 0; + unsigned int i = 0; + + /* check block 0 first 8 bytes */ + if ((buf[0] != 0) && (buf[7] != 0)) + return 0; + for (i = 1; i < 7; i++) { + if (buf[i] != 0xff) + return 0; + } + + /* check block 0 checksum */ + for (chksum = 0, i = 0; i < 0x80; i++) + chksum += buf[i]; + + if ((chksum & 0xff) != 0) + return 0; + + /* check Extension flag at block 0 */ + if (buf[0x7e] == 0) + return 0; + + /* check block 1 extension tag */ + if (buf[0x80] != 0x2) + return 0; + + /* check block 1 checksum */ + for (chksum = 0, i = 0x80; i < 0x100; i++) + chksum += buf[i]; + + if ((chksum & 0xff) != 0) + return 0; + + return 1; +} + +/* retrun 1 valid edid */ +int check_dvi_hdmi_edid_valid(unsigned char *buf) +{ + unsigned int chksum = 0; + unsigned int i = 0; + + /* check block 0 first 8 bytes */ + if ((buf[0] != 0) && (buf[7] != 0)) + return 0; + for (i = 1; i < 7; i++) { + if (buf[i] != 0xff) + return 0; + } + + /* check block 0 checksum */ + for (chksum = 0, i = 0; i < 0x80; i++) + chksum += buf[i]; + if ((chksum & 0xff) != 0) + return 0; + + if (buf[0x7e] == 0)/* check Extension flag at block 0 */ + return 1; + else if (buf[0x80] != 0x2)/* check block 1 extension tag */ + return 0; + + /* check block 1 checksum */ + for (chksum = 0, i = 0x80; i < 0x100; i++) + chksum += buf[i]; + if ((chksum & 0xff) != 0) + return 0; + + /* check block 2 checksum */ + if (buf[0x7e] > 1) { + for (chksum = 0, i = 0x100; i < 0x180; i++) + chksum += buf[i]; + if ((chksum & 0xff) != 0) + return 0; + } + + /* check block 3 checksum */ + if (buf[0x7e] > 2) { + for (chksum = 0, i = 0x180; i < 0x200; i++) + chksum += buf[i]; + if ((chksum & 0xff) != 0) + return 0; + } + + return 1; +} + +static void Edid_ManufactureDateParse(struct rx_cap *pRxCap, + unsigned char *data) +{ + if (data == NULL) + return; + + /* week: + * 0: not specified + * 0x1~0x36: valid week + * 0x37~0xfe: reserved + * 0xff: model year is specified + */ + if ((data[0] == 0) || ((data[0] >= 0x37) && (data[0] <= 0xfe))) + pRxCap->manufacture_week = 0; + else + pRxCap->manufacture_week = data[0]; + + /* year: + * 0x0~0xf: reserved + * 0x10~0xff: year of manufacture, + * or model year(if specified by week=0xff) + */ + pRxCap->manufacture_year = + (data[1] <= 0xf)?0:data[1]; +} + +static void Edid_VersionParse(struct rx_cap *pRxCap, + unsigned char *data) +{ + if (data == NULL) + return; + + /* + * 0x1: edid version 1 + * 0x0,0x2~0xff: reserved + */ + pRxCap->edid_version = (data[0] == 0x1)?1:0; + + /* + * 0x0~0x4: revision number + * 0x5~0xff: reserved + */ + pRxCap->edid_revision = (data[1] < 0x5)?data[1]:0; +} + +/* if edid block 0 are all zeros, then consider RX as HDMI device */ +static int edid_zero_data(unsigned char *buf) +{ + int sum = 0; + int i = 0; + + for (i = 0; i < 128; i++) + sum += buf[i]; + + if (sum == 0) + return 1; + else + return 0; +} + +static void dump_dtd_info(struct dtd *t) +{ + pr_info("%s[%d]\n", __func__, __LINE__); +#define PR(a) pr_info("%s %d\n", #a, t->a) + PR(pixel_clock); + PR(h_active); + PR(h_blank); + PR(v_active); + PR(v_blank); + PR(h_sync_offset); + PR(h_sync); + PR(v_sync_offset); + PR(v_sync); +} + +static void Edid_DTD_parsing(struct rx_cap *pRXCap, unsigned char *data) +{ + struct hdmi_format_para *para = NULL; + struct dtd *t = &pRXCap->dtd[pRXCap->dtd_idx]; + + memset(t, 0, sizeof(struct dtd)); + t->pixel_clock = data[0] + (data[1] << 8); + t->h_active = (((data[4] >> 4) & 0xf) << 8) + data[2]; + t->h_blank = ((data[4] & 0xf) << 8) + data[3]; + t->v_active = (((data[7] >> 4) & 0xf) << 8) + data[5]; + t->v_blank = ((data[7] & 0xf) << 8) + data[6]; + t->h_sync_offset = (((data[11] >> 6) & 0x3) << 8) + data[8]; + t->h_sync = (((data[11] >> 4) & 0x3) << 8) + data[9]; + t->v_sync_offset = (((data[11] >> 2) & 0x3) << 4) + + ((data[10] >> 4) & 0xf); + t->v_sync = (((data[11] >> 0) & 0x3) << 4) + ((data[10] >> 0) & 0xf); +/* + * Special handling of 1080i60hz, 1080i50hz + */ + if ((t->pixel_clock == 7425) && (t->h_active == 1920) && + (t->v_active == 1080)) { + t->v_active = t->v_active / 2; + t->v_blank = t->v_blank / 2; + } +/* + * Special handling of 480i60hz, 576i50hz + */ + if (((((t->flags) >> 1) & 0x3) == 0) && (t->h_active == 1440)) { + if (t->pixel_clock == 2700) /* 576i50hz */ + goto next; + if ((t->pixel_clock - 2700) < 10) /* 480i60hz */ + t->pixel_clock = 2702; +next: + t->v_active = t->v_active / 2; + t->v_blank = t->v_blank / 2; + } +/* + * call hdmi_match_dtd_paras() to check t is matched with VIC + */ + para = hdmi_match_dtd_paras(t); + if (para) { + t->vic = para->vic; + pRXCap->preferred_mode = pRXCap->dtd[0].vic; /* Select dtd0 */ + pr_info("hdmitx: get dtd%d vic: %d\n", + pRXCap->dtd_idx, para->vic); + pRXCap->dtd_idx++; + } else + dump_dtd_info(t); +} + +int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) +{ + unsigned char CheckSum; + unsigned char zero_numbers; + unsigned char BlockCount; + unsigned char *EDID_buf; + int i, j, ret_val; + int idx[4]; + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + struct vinfo_s *info = NULL; + + if (check_dvi_hdmi_edid_valid(hdmitx_device->EDID_buf)) { + EDID_buf = hdmitx_device->EDID_buf; + hdmitx_device->edid_parsing = 1; + memcpy(hdmitx_device->EDID_buf1, hdmitx_device->EDID_buf, + EDID_MAX_BLOCK * 128); + } else + EDID_buf = hdmitx_device->EDID_buf1; + hdmitx_device->edid_ptr = EDID_buf; + hdmi_print(0, "EDID Parser:\n"); + memset(rptx_edid_buf, 0, sizeof(rptx_edid_buf)); + rptx_edid_aud = &rptx_edid_buf[0]; + /* Calculate the EDID hash for special use */ + memset(hdmitx_device->EDID_hash, 0, + ARRAY_SIZE(hdmitx_device->EDID_hash)); + edid_hash_calc(hdmitx_device->EDID_hash, hdmitx_device->EDID_buf, 256); + + ret_val = Edid_DecodeHeader(&hdmitx_device->hdmi_info, &EDID_buf[0]); + +/* if(ret_val == -1) */ +/* return -1; */ + + for (i = 0, CheckSum = 0 ; i < 128 ; i++) { + CheckSum += EDID_buf[i]; + CheckSum &= 0xFF; + } + + if (CheckSum != 0) { + hdmi_print(0, "PLUGIN_DVI_OUT\n"); + /* return -1 ; */ + } + + Edid_ReceiverBrandNameParse(&hdmitx_device->RXCap, &EDID_buf[8]); + + idx[0] = EDID_DETAILED_TIMING_DES_BLOCK0_POS; + idx[1] = EDID_DETAILED_TIMING_DES_BLOCK1_POS; + idx[2] = EDID_DETAILED_TIMING_DES_BLOCK2_POS; + idx[3] = EDID_DETAILED_TIMING_DES_BLOCK3_POS; + for (i = 0; i < 4; i++) { + if ((EDID_buf[idx[i]]) && (EDID_buf[idx[i] + 1])) + Edid_DTD_parsing(pRXCap, &EDID_buf[idx[i]]); + + if (Edid_find_name_block(&EDID_buf[idx[i]])) + Edid_ReceiverProductNameParse(&hdmitx_device->RXCap, + &EDID_buf[idx[i]+5]); + } + + Edid_ManufactureDateParse(&hdmitx_device->RXCap, &EDID_buf[16]); + + Edid_VersionParse(&hdmitx_device->RXCap, &EDID_buf[18]); + + Edid_DecodeStandardTiming(&hdmitx_device->hdmi_info, &EDID_buf[26], 8); + Edid_ParseCEADetailedTimingDescriptors(&hdmitx_device->hdmi_info, + 4, 0x36, &EDID_buf[0]); + + BlockCount = EDID_buf[0x7E]; + hdmitx_device->RXCap.blk0_chksum = EDID_buf[0x7F]; + + if (BlockCount == 0) { + hdmi_print(0, "EDID BlockCount=0\n"); + hdmitx_edid_set_default_vic(hdmitx_device); + + /* DVI case judgement: only contains one block and + * checksum valid + */ + CheckSum = 0; + zero_numbers = 0; + for (i = 0; i < 128; i++) { + CheckSum += EDID_buf[i]; + if (EDID_buf[i] == 0) + zero_numbers++; + } + hdmi_print(INF, EDID "edid blk0 checksum:%d ext_flag:%d\n", + CheckSum, EDID_buf[0x7e]); + if ((CheckSum & 0xff) == 0) + hdmitx_device->RXCap.IEEEOUI = 0; + else + hdmitx_device->RXCap.IEEEOUI = 0x0c03; + if (zero_numbers > 120) + hdmitx_device->RXCap.IEEEOUI = 0x0c03; + + return 0; /* do nothing. */ + } + + /* Note: some DVI monitor have more than 1 block */ + if ((BlockCount == 1) && (EDID_buf[0x81] == 1)) { + hdmitx_device->RXCap.IEEEOUI = 0; + hdmitx_device->RXCap.VIC_count = 0x3; + hdmitx_device->RXCap.VIC[0] = HDMI_720x480p60_16x9; + hdmitx_device->RXCap.VIC[1] = HDMI_1280x720p60_16x9; + hdmitx_device->RXCap.VIC[2] = HDMI_1920x1080p60_16x9; + hdmitx_device->RXCap.native_VIC = HDMI_720x480p60_16x9; + hdmitx_device->vic_count = hdmitx_device->RXCap.VIC_count; + hdmi_print(IMP, EDID "HDMI: set default vic\n"); + return 0; + } else if (BlockCount > EDID_MAX_BLOCK) { + BlockCount = EDID_MAX_BLOCK; + } + + for (i = 1 ; i <= BlockCount ; i++) { + if ((BlockCount > 1) && (i == 1)) + CheckSum = 0; /* ignore the block1 data */ + else { + if (((BlockCount == 1) && (i == 1)) || + ((BlockCount > 1) && (i == 2))) + Edid_Parse_check_HDMI_VSDB( + hdmitx_device, + &EDID_buf[i * 128]); + + for (j = 0, CheckSum = 0 ; j < 128 ; j++) { + CheckSum += EDID_buf[i*128 + j]; + CheckSum &= 0xFF; + } + if (CheckSum == 0) { + Edid_MonitorCapable861( + &hdmitx_device->hdmi_info, + EDID_buf[i * 128 + 3]); + ret_val = Edid_ParsingCEADataBlockCollection( + &hdmitx_device->hdmi_info, + &EDID_buf[i * 128]); + Edid_ParseCEADetailedTimingDescriptors( + &hdmitx_device->hdmi_info, 5, + EDID_buf[i * 128 + 2], + &EDID_buf[i * 128]); + } + } + + if (EDID_buf[i*128+0] == 0x2) { + if (hdmitx_edid_block_parse(hdmitx_device, + &(EDID_buf[i*128])) >= 0) { + if (hdmitx_device->RXCap.IEEEOUI == 0x0c03) + break; + } + } + } + +/* + * Because DTDs are not able to represent some Video Formats, which can be + * represented as SVDs and might be preferred by Sinks, the first DTD in the + * base EDID data structure and the first SVD in the first CEA Extension can + * differ. When the first DTD and SVD do not match and the total number of + * DTDs defining Native Video Formats in the whole EDID is zero, the first + * SVD shall take precedence. + */ + if (!pRXCap->flag_vfpdb && (pRXCap->preferred_mode != pRXCap->VIC[0]) && + (pRXCap->number_of_dtd == 0)) { + pr_info("hdmitx: edid: change preferred_mode from %d to %d\n", + pRXCap->preferred_mode, pRXCap->VIC[0]); + pRXCap->preferred_mode = pRXCap->VIC[0]; + } + + if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { + pRXCap->IEEEOUI = 0x0c03; + pr_info("hdmitx: edid: find IEEEOUT\n"); + } else { + pRXCap->IEEEOUI = 0x0; + pr_info("hdmitx: edid: not find IEEEOUT\n"); + } + + if ((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0) || + (pRXCap->VIC_count == 0)) + hdmitx_edid_set_default_vic(hdmitx_device); + + /* strictly DVI device judgement */ + /* valid EDID & no audio tag & no IEEEOUI */ + if (edid_check_valid(&EDID_buf[0]) && + !hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { + pRXCap->IEEEOUI = 0x0; + pr_info("hdmitx: edid: sink is DVI device\n"); + } else + pRXCap->IEEEOUI = 0x0c03; + + if (edid_zero_data(EDID_buf)) + pRXCap->IEEEOUI = 0x0c03; + + edid_save_checkvalue(EDID_buf, BlockCount+1); + +#if 1 + i = hdmitx_edid_dump(hdmitx_device, (char *)(hdmitx_device->tmp_buf), + HDMI_TMP_BUF_SIZE); + hdmitx_device->tmp_buf[i] = 0; + hdmi_print(0, "\n"); +#endif + if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { + pRXCap->IEEEOUI = 0x0c03; + pr_info("hdmitx: Invalid edid, consider RX as HDMI device\n"); + } + /* update RX HDR information */ + info = get_current_vinfo(); + if (info) { + info->hdr_info.hdr_support = (pRXCap->hdr_sup_eotf_sdr << 0) + | (pRXCap->hdr_sup_eotf_hdr << 1) + | (pRXCap->hdr_sup_eotf_smpte_st_2084 << 2); + info->hdr_info.lumi_max = pRXCap->hdr_lum_max; + info->hdr_info.lumi_avg = pRXCap->hdr_lum_avg; + info->hdr_info.lumi_min = pRXCap->hdr_lum_min; + pr_info("hdmitx: update RX hdr info %x\n", + info->hdr_info.hdr_support); + } + return 0; + +} + +static struct dispmode_vic dispmode_vic_tab[] = { + {"480i60hz", HDMI_480i60_16x9}, + {"480p60hz", HDMI_480p60_16x9}, + {"576i50hz", HDMI_576i50_16x9}, + {"576p50hz", HDMI_576p50_16x9}, + {"720p50hz", HDMI_720p50}, + {"720p60hz", HDMI_720p60}, + {"1080i50hz", HDMI_1080i50}, + {"1080i60hz", HDMI_1080i60}, + {"1080p50hz", HDMI_1080p50}, + {"1080p30hz", HDMI_1080p30}, + {"1080p25hz", HDMI_1080p25}, + {"1080p24hz", HDMI_1080p24}, + {"1080p60hz", HDMI_1080p60}, + {"2160p30hz", HDMI_4k2k_30}, + {"2160p25hz", HDMI_4k2k_25}, + {"2160p24hz", HDMI_4k2k_24}, + {"smpte24hz", HDMI_4k2k_smpte_24}, + {"smpte25hz", HDMI_4096x2160p25_256x135}, + {"smpte30hz", HDMI_4096x2160p30_256x135}, + {"smpte50hz", HDMI_4096x2160p50_256x135}, + {"smpte50hz420", HDMI_4096x2160p50_256x135_Y420}, + {"smpte60hz", HDMI_4096x2160p60_256x135}, + {"smpte60hz420", HDMI_4096x2160p60_256x135_Y420}, + {"2160p60hz", HDMI_4k2k_60}, + {"2160p50hz", HDMI_4k2k_50}, + {"2160p60hz420", HDMI_3840x2160p60_16x9_Y420}, + {"2160p50hz420", HDMI_3840x2160p50_16x9_Y420}, +}; + +int hdmitx_edid_VIC_support(enum hdmi_vic vic) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dispmode_vic_tab); i++) { + if (vic == dispmode_vic_tab[i].VIC) + return 1; + } + + return 0; +} + +enum hdmi_vic hdmitx_edid_vic_tab_map_vic(const char *disp_mode) +{ + enum hdmi_vic vic = HDMI_Unknown; + int i; + + for (i = 0; i < ARRAY_SIZE(dispmode_vic_tab); i++) { + if (strcmp(disp_mode, dispmode_vic_tab[i].disp_mode) == 0) { + vic = dispmode_vic_tab[i].VIC; + break; + } + } + + if (vic == HDMI_Unknown) + hdmi_print(INF, EDID "not find mapped vic\n"); + + return vic; +} + +const char *hdmitx_edid_vic_tab_map_string(enum hdmi_vic vic) +{ + int i; + const char *disp_str = NULL; + + for (i = 0; i < ARRAY_SIZE(dispmode_vic_tab); i++) { + if (vic == dispmode_vic_tab[i].VIC) { + disp_str = dispmode_vic_tab[i].disp_mode; + break; + } + } + + return disp_str; +} + +const char *hdmitx_edid_vic_to_string(enum hdmi_vic vic) +{ + int i; + const char *disp_str = NULL; + + for (i = 0; i < ARRAY_SIZE(dispmode_vic_tab); i++) { + if (vic == dispmode_vic_tab[i].VIC) { + disp_str = dispmode_vic_tab[i].disp_mode; + break; + } + } + + return disp_str; +} + +/* For some TV's EDID, there maybe exist some information ambiguous. + * Such as EDID declears support 2160p60hz(Y444 8bit), but no valid + * Max_TMDS_Clock2 to indicate that it can support 5.94G signal. + */ +bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, + struct hdmi_format_para *para) +{ + bool valid = 0; + struct rx_cap *pRXCap = NULL; + unsigned int rx_max_tmds_clk = 0; + unsigned int calc_tmds_clk = 0; + int i = 0; + int svd_flag = 0; + + if (!hdev || !para) + return 0; + + if (strcmp(para->sname, "invalid") == 0) + return 0; + /* exclude such as: 2160p60hz YCbCr444 10bit */ + switch (para->vic) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_3840x2160p50_64x27: + case HDMI_3840x2160p60_64x27: + if ((para->cs == COLORSPACE_RGB444) || + (para->cs == COLORSPACE_YUV444)) + if (para->cd != COLORDEPTH_24B) + return 0; + if (para->cs == COLORSPACE_YUV422) + if (para->cd != COLORDEPTH_48B) + return 0; + break; + default: + break; + } + + pRXCap = &(hdev->RXCap); + + /* DVI case, only 8bit */ + if (pRXCap->IEEEOUI != 0x0c03) { + if (para->cd != COLORDEPTH_24B) + return 0; + } + + /* target mode is not contained at RX SVD */ + for (i = 0; (i < pRXCap->VIC_count) && (i < VIC_MAX_NUM); i++) { + if ((para->vic & 0xff) == (pRXCap->VIC[i] & 0xff)) + svd_flag = 1; + } + if (svd_flag == 0) + return 0; + + /* Get RX Max_TMDS_Clock */ + if (pRXCap->Max_TMDS_Clock2) + rx_max_tmds_clk = pRXCap->Max_TMDS_Clock2 * 5; + else { + /* Default min is 74.25 / 5 */ + if (pRXCap->Max_TMDS_Clock1 < 0xf) + pRXCap->Max_TMDS_Clock1 = 0x1e; + rx_max_tmds_clk = pRXCap->Max_TMDS_Clock1 * 5; + } + + calc_tmds_clk = para->tmds_clk; + if (para->cs == COLORSPACE_YUV420) + calc_tmds_clk = calc_tmds_clk / 2; + if (para->cs != COLORSPACE_YUV422) { + switch (para->cd) { + case COLORDEPTH_30B: + calc_tmds_clk = calc_tmds_clk * 5 / 4; + break; + case COLORDEPTH_36B: + calc_tmds_clk = calc_tmds_clk * 3 / 2; + break; + case COLORDEPTH_48B: + calc_tmds_clk = calc_tmds_clk * 2; + break; + case COLORDEPTH_24B: + default: + calc_tmds_clk = calc_tmds_clk * 1; + break; + } + } + calc_tmds_clk = calc_tmds_clk / 1000; + pr_info("RX tmds clk: %d Calc clk: %d\n", rx_max_tmds_clk, + calc_tmds_clk); + if (calc_tmds_clk < rx_max_tmds_clk) + valid = 1; + else + valid = 0; + + return valid; +} + +/* + * For some TVs, their EDID declare support 2160p60hz(>3.4Gbps) on SVDs, + * but no HF_IEEEOUT, so consider they don't support that format. + */ +static enum hdmi_vic hdmitx_edid_recheck_format(struct hdmitx_dev *hdev, + enum hdmi_vic vic) +{ + struct rx_cap *pRXCap = &(hdev->RXCap); + + switch (vic) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_3840x2160p50_64x27: + case HDMI_3840x2160p60_64x27: + break; + default: + return vic; + } + + if (!pRXCap->HF_IEEEOUI || ((pRXCap->Max_TMDS_Clock2 * 5) < 340)) + vic = HDMI_Unknown; + return vic; +} + +/* force_flag: 0 means check with RX's edid */ +/* 1 means no check wich RX's edid */ +enum hdmi_vic hdmitx_edid_get_VIC(struct hdmitx_dev *hdev, + const char *disp_mode, char force_flag) +{ + struct rx_cap *pRXCap = &(hdev->RXCap); + int j; + enum hdmi_vic vic = hdmitx_edid_vic_tab_map_vic(disp_mode); + + if (vic != HDMI_Unknown) { + if (force_flag == 0) { + for (j = 0 ; j < pRXCap->VIC_count ; j++) { + if (pRXCap->VIC[j] == vic) + break; + } + if (j >= pRXCap->VIC_count) + vic = HDMI_Unknown; + } + } + vic = hdmitx_edid_recheck_format(hdev, vic); + return vic; +} + +const char *hdmitx_edid_get_native_VIC(struct hdmitx_dev *hdmitx_device) +{ + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + + return hdmitx_edid_vic_tab_map_string(pRXCap->native_VIC); +} + +/* Clear HDMI Hardware Module EDID RAM and EDID Buffer */ +void hdmitx_edid_ram_buffer_clear(struct hdmitx_dev *hdmitx_device) +{ + unsigned int i = 0; + + /* Clear HDMI Hardware Module EDID RAM */ + hdmitx_device->HWOp.CntlDDC(hdmitx_device, DDC_EDID_CLEAR_RAM, 0); + + /* Clear EDID Buffer */ + for (i = 0; i < EDID_MAX_BLOCK*128; i++) + hdmitx_device->EDID_buf[i] = 0; + for (i = 0; i < EDID_MAX_BLOCK*128; i++) + hdmitx_device->EDID_buf1[i] = 0; +} + +/* Clear the Parse result of HDMI Sink's EDID. */ +void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device) +{ + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + + memset(pRXCap, 0, sizeof(struct rx_cap)); + + /* Note: in most cases, we think that rx is tv and the default + * IEEEOUI is HDMI Identifier + */ + pRXCap->IEEEOUI = 0x000c03; + + hdmitx_device->vic_count = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.b = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.c = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.d = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.valid = 0; + memset(&vsdb_local, 0, sizeof(struct vsdb_phyaddr)); + memset(&hdmitx_device->EDID_hash[0], 0, + sizeof(hdmitx_device->EDID_hash)); + hdmitx_device->edid_parsing = 0; +} + +/* + * print one block data of edid + */ +#define TMP_EDID_BUF_SIZE (256+8) +static void hdmitx_edid_blk_print(unsigned char *blk, unsigned int blk_idx) +{ + unsigned int i, pos; + unsigned char *tmp_buf = NULL; + + tmp_buf = kmalloc(TMP_EDID_BUF_SIZE, GFP_KERNEL); + if (!tmp_buf) + return; + + memset(tmp_buf, 0, sizeof(TMP_EDID_BUF_SIZE)); + hdmi_print(INF, EDID "blk%d raw data\n", blk_idx); + for (i = 0, pos = 0; i < 128; i++) { + pos += sprintf(tmp_buf + pos, "%02x", blk[i]); + if (((i+1) & 0x1f) == 0) /* print 32bytes a line */ + pos += sprintf(tmp_buf + pos, "\n"); + } + pos += sprintf(tmp_buf + pos, "\n"); + pr_info("%s\n", tmp_buf); + kfree(tmp_buf); +} + +/* + * check EDID buf contains valid block numbers + */ +static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf) +{ + unsigned int valid_blk_no = 0; + unsigned int i = 0, j = 0; + unsigned int tmp_chksum = 0; + + for (j = 0; j < EDID_MAX_BLOCK; j++) { + for (i = 0; i < 128; i++) + tmp_chksum += buf[i + j*128]; + if (tmp_chksum != 0) { + valid_blk_no++; + if ((tmp_chksum & 0xff) == 0) + hdmi_print(INF, EDID "check sum valid\n"); + else + hdmi_print(INF, EDID "check sum invalid\n"); + } + tmp_chksum = 0; + } + return valid_blk_no; +} + +/* + * suppose DDC read EDID two times successfully, + * then compare EDID_buf and EDID_buf1. + * if same, just print out EDID_buf raw data, else print out 2 buffers + */ +void hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device) +{ + unsigned int i = 0; + unsigned int err_no = 0; + unsigned char *buf0 = hdmitx_device->EDID_buf; + unsigned char *buf1 = hdmitx_device->EDID_buf1; + unsigned int valid_blk_no = 0; + unsigned int blk_idx = 0; + + for (i = 0; i < EDID_MAX_BLOCK*128; i++) { + if (buf0[i] != buf1[i]) + err_no++; + } + + if (err_no == 0) { + /* calculate valid edid block numbers */ + valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); + + if (valid_blk_no == 0) + hdmi_print(ERR, EDID "raw data are all zeroes\n"); + else { + for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) + hdmitx_edid_blk_print(&buf0[blk_idx*128], + blk_idx); + } + } else { + hdmi_print(ERR, EDID "%d errors between two reading\n", err_no); + valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); + for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) + hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx); + + valid_blk_no = hdmitx_edid_check_valid_blocks(buf1); + for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) + hdmitx_edid_blk_print(&buf1[blk_idx*128], blk_idx); + } +} + +int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, + int buffer_len) +{ + int i, pos = 0; + struct rx_cap *pRXCap = &(hdmitx_device->RXCap); + + pos += snprintf(buffer+pos, buffer_len-pos, + "Rx Brand Name: %s\n", pRXCap->ReceiverBrandName); + pos += snprintf(buffer+pos, buffer_len-pos, + "Rx Product Name: %s\n", pRXCap->ReceiverProductName); + + pos += snprintf(buffer+pos, buffer_len-pos, + "Manufacture Week: %d\n", pRXCap->manufacture_week); + pos += snprintf(buffer+pos, buffer_len-pos, + "Manufacture Year: %d\n", pRXCap->manufacture_year+1990); + + pos += snprintf(buffer+pos, buffer_len-pos, + "EDID Version: %d.%d\n", + pRXCap->edid_version, pRXCap->edid_revision); + + pos += snprintf(buffer+pos, buffer_len-pos, + "EDID block number: 0x%x\n", hdmitx_device->EDID_buf[0x7e]); + pos += snprintf(buffer+pos, buffer_len-pos, + "blk0 chksum: 0x%02x\n", pRXCap->blk0_chksum); + + pos += snprintf(buffer+pos, buffer_len-pos, + "Source Physical Address[a.b.c.d]: %x.%x.%x.%x\n", + hdmitx_device->hdmi_info.vsdb_phy_addr.a, + hdmitx_device->hdmi_info.vsdb_phy_addr.b, + hdmitx_device->hdmi_info.vsdb_phy_addr.c, + hdmitx_device->hdmi_info.vsdb_phy_addr.d); + + pos += snprintf(buffer+pos, buffer_len-pos, + "native Mode %x, VIC (native %d):\n", + pRXCap->native_Mode, pRXCap->native_VIC); + + pos += snprintf(buffer+pos, buffer_len-pos, + "ColorDeepSupport %x\n", pRXCap->ColorDeepSupport); + + for (i = 0 ; i < pRXCap->VIC_count ; i++) { + pos += snprintf(buffer+pos, buffer_len-pos, "%d ", + pRXCap->VIC[i]); + } + pos += snprintf(buffer+pos, buffer_len-pos, "\n"); + pos += snprintf(buffer+pos, buffer_len-pos, + "Audio {format, channel, freq, cce}\n"); + for (i = 0; i < pRXCap->AUD_count; i++) { + pos += snprintf(buffer+pos, buffer_len-pos, + "{%d, %d, %x, %x}\n", + pRXCap->RxAudioCap[i].audio_format_code, + pRXCap->RxAudioCap[i].channel_num_max, + pRXCap->RxAudioCap[i].freq_cc, + pRXCap->RxAudioCap[i].cc3); + } + pos += snprintf(buffer+pos, buffer_len-pos, + "Speaker Allocation: %x\n", pRXCap->RxSpeakerAllocation); + pos += snprintf(buffer+pos, buffer_len-pos, "Vendor: 0x%x\n", + pRXCap->IEEEOUI); + + pos += snprintf(buffer+pos, buffer_len-pos, + "MaxTMDSClock1 %d MHz\n", pRXCap->Max_TMDS_Clock1 * 5); + + if (pRXCap->HF_IEEEOUI) { + pos += snprintf(buffer+pos, buffer_len-pos, "Vendor2: 0x%x\n", + pRXCap->HF_IEEEOUI); + pos += snprintf(buffer+pos, buffer_len-pos, + "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); + } + if (pRXCap->colorimetry_data) + pos += snprintf(buffer+pos, buffer_len-pos, + "ColorMetry: 0x%x\n", pRXCap->colorimetry_data); + pos += snprintf(buffer+pos, buffer_len-pos, "SCDC: %x\n", + pRXCap->scdc_present); + pos += snprintf(buffer+pos, buffer_len-pos, "RR_Cap: %x\n", + pRXCap->scdc_rr_capable); + pos += snprintf(buffer+pos, buffer_len-pos, "LTE_340M_Scramble: %x\n", + pRXCap->lte_340mcsc_scramble); + + if (pRXCap->dv_info.ieeeoui == 0x00d046) + pos += snprintf(buffer+pos, buffer_len-pos, + " DolbyVision%d", pRXCap->dv_info.ver); + if (pRXCap->hdr_sup_eotf_smpte_st_2084) + pos += snprintf(buffer+pos, buffer_len-pos, " HDR"); + if (pRXCap->dc_y444 || pRXCap->dc_30bit || pRXCap->dc_30bit_420) + pos += snprintf(buffer+pos, buffer_len-pos, " DeepColor"); + pos += snprintf(buffer+pos, buffer_len-pos, "\n"); + + /* for checkvalue which maybe used by application to adjust + * whether edid is changed + */ + pos += snprintf(buffer+pos, buffer_len-pos, + "checkvalue: 0x%02x%02x%02x%02x\n", + edid_checkvalue[0], + edid_checkvalue[1], + edid_checkvalue[2], + edid_checkvalue[3]); + + return pos; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c new file mode 100644 index 000000000000..e985610b3b51 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c @@ -0,0 +1,155 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +/* #include */ +#include "hdmi_tx_hdcp.h" +/* + * hdmi_tx_hdcp.c + * version 1.1 + */ + +/* android ics switch device */ +static struct extcon_dev hdcp_dev = { + .name = "hdcp", +}; + +/* For most cases, we don't use HDCP + * If using HDCP, need add follow command in boot/init.rc and + * recovery/boot/init.rc + * write /sys/module/hdmitx/parameters/hdmi_output_force 0 + */ +static int hdmi_output_force = 1; +static int hdmi_authenticated; +static int hdmi_hdcp_process = 1; + +/* Notic: the HDCP key setting has been moved to uboot + * On MBX project, it is too late for HDCP get from + * other devices + */ + +/* verify ksv, 20 ones and 20 zeroes */ +int hdcp_ksv_valid(unsigned char *dat) +{ + int i, j, one_num = 0; + + for (i = 0; i < 5; i++) { + for (j = 0; j < 8; j++) { + if ((dat[i] >> j) & 0x1) + one_num++; + } + } + return one_num == 20; +} + +static struct timer_list hdcp_monitor_timer; +static void hdcp_monitor_func(unsigned long arg) +{ + /* static int hdcp_auth_flag = 0; */ + struct hdmitx_dev *hdev = (struct hdmitx_dev *)hdcp_monitor_timer.data; + + if ((hdev->HWOp.Cntl) && (hdev->log & (HDMI_LOG_HDCP))) + hdev->HWOp.Cntl(hdev, HDMITX_HDCP_MONITOR, 1); + + mod_timer(&hdcp_monitor_timer, jiffies + 2 * HZ); +} + +static int hdmitx_hdcp_task(void *data) +{ + struct hdmitx_dev *hdev = (struct hdmitx_dev *)data; + + init_timer(&hdcp_monitor_timer); + hdcp_monitor_timer.data = (ulong) data; + hdcp_monitor_timer.function = hdcp_monitor_func; + hdcp_monitor_timer.expires = jiffies + HZ; + add_timer(&hdcp_monitor_timer); + + while (hdev->hpd_event != 0xff) { + hdmi_authenticated = hdev->HWOp.CntlDDC(hdev, + DDC_HDCP_GET_AUTH, 0); + extcon_set_state(&hdcp_dev, 0, hdmi_authenticated); //TO_DO___49 + msleep_interruptible(200); + } + + return 0; +} + +static int __init hdmitx_hdcp_init(void) +{ + struct hdmitx_dev *hdev = get_hdmitx_device(); + + hdmi_print(IMP, SYS "hdmitx_hdcp_init\n"); + if (hdev->hdtx_dev == NULL) { + hdmi_print(IMP, SYS "exit for null device of hdmitx!\n"); + return -ENODEV; + } + + extcon_dev_register(&hdcp_dev); + + hdev->task_hdcp = kthread_run(hdmitx_hdcp_task, (void *)hdev, + "kthread_hdcp"); + + return 0; +} + +static void __exit hdmitx_hdcp_exit(void) +{ + extcon_dev_unregister(&hdcp_dev); +} + + +MODULE_PARM_DESC(hdmi_authenticated, "\n hdmi_authenticated\n"); +module_param(hdmi_authenticated, int, 0444); + +MODULE_PARM_DESC(hdmi_hdcp_process, "\n hdmi_hdcp_process\n"); +module_param(hdmi_hdcp_process, int, 0664); + +MODULE_PARM_DESC(hdmi_output_force, "\n hdmi_output_force\n"); +module_param(hdmi_output_force, int, 0664); + + +module_init(hdmitx_hdcp_init); +module_exit(hdmitx_hdcp_exit); +MODULE_DESCRIPTION("AMLOGIC HDMI TX HDCP driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h new file mode 100644 index 000000000000..44f1e029adea --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h @@ -0,0 +1,35 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMI_TX_HDCP_H +#define __HDMI_TX_HDCP_H +/* + * hdmi_tx_hdcp.c + * version 1.0 + */ + +/* Notic: the HDCP key setting has been moved to uboot + * On MBX project, it is too late for HDCP get from + * other devices + */ + +/* int task_tx_key_setting(unsigned force_wrong); */ + +int hdcp_ksv_valid(unsigned char *dat); + +#endif + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c new file mode 100644 index 000000000000..7718d23bacf1 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -0,0 +1,3064 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ + +/* #include */ +#include "hdmi_tx_hdcp.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +/* #include */ +#include +#include +#include +#include +#include +#include "hw/tvenc_conf.h" +#ifdef CONFIG_INSTABOOT +#include +#endif + +#define DEVICE_NAME "amhdmitx" +#define HDMI_TX_COUNT 32 +#define HDMI_TX_POOL_NUM 6 +#define HDMI_TX_RESOURCE_NUM 4 +#define HDMI_TX_PWR_CTRL_NUM 6 + +static dev_t hdmitx_id; +static struct class *hdmitx_class; +static int set_disp_mode_auto(void); +struct vinfo_s *hdmi_get_current_vinfo(void); +static void hdmitx_get_edid(struct hdmitx_dev *hdev); +static void hdmitx_set_drm_pkt(struct master_display_info_s *data); +static void hdmitx_set_vsif_pkt(enum eotf_type type, uint8_t tunnel_mode); +static int check_fbc_special(unsigned char *edid_dat); +static int hdcp_tst_sig; +static DEFINE_MUTEX(setclk_mutex); +static char fmt_attr[16]; + +#ifndef CONFIG_AMLOGIC_VOUT +/* Fake vinfo */ +struct vinfo_s vinfo_1080p60hz = { + .name = "1080p60hz", + .mode = VMODE_1080P, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, +}; +struct vinfo_s *get_current_vinfo(void) +{ + return &vinfo_1080p60hz; +} +#endif + +struct hdmi_config_platform_data *hdmi_pdata; + +static struct hdmitx_dev hdmitx_device; +static struct extcon_dev sdev = { /* android ics switch device */ + .name = "hdmi", +}; +static struct extcon_dev hdmi_audio = { + .name = "hdmi_audio", +}; +static struct extcon_dev hdmi_power = { /* android ics switch device */ + .name = "hdmi_power", +}; +static struct extcon_dev hdmi_hdr = { + .name = "hdmi_hdr", +}; + +static int hdmi_init; +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +static void hdmitx_early_suspend(struct early_suspend *h) +{ + const struct vinfo_s *info = hdmi_get_current_vinfo(); + struct hdmitx_dev *phdmi = (struct hdmitx_dev *)h->param; + + if (info && (strncmp(info->name, "panel", 5) == 0 + || strncmp(info->name, "null", 4) == 0)) + return; + phdmi->hpd_lock = 1; + hdcp_tst_sig = 1; + pr_info("%s[%d] set hdcp_pwr as %d\n", __func__, __LINE__, + hdcp_tst_sig); + msleep(20); + phdmi->HWOp.CntlMisc(phdmi, MISC_AVMUTE_OP, SET_AVMUTE); + mdelay(100); + hdmi_print(IMP, SYS "HDMITX: early suspend\n"); + phdmi->HWOp.Cntl((struct hdmitx_dev *)h->param, + HDMITX_EARLY_SUSPEND_RESUME_CNTL, HDMITX_EARLY_SUSPEND); + phdmi->cur_VIC = HDMI_Unknown; + phdmi->output_blank_flag = 0; + phdmi->HWOp.CntlDDC(phdmi, DDC_HDCP_MUX_INIT, 1); + phdmi->HWOp.CntlDDC(phdmi, DDC_HDCP_OP, HDCP14_OFF); + extcon_set_state(&hdmi_power, 0, 0); + phdmi->HWOp.CntlConfig(&hdmitx_device, CONF_CLR_AVI_PACKET, 0); + phdmi->HWOp.CntlConfig(&hdmitx_device, CONF_CLR_VSDB_PACKET, 0); +} + +static int hdmitx_is_hdmi_vmode(char *mode_name) +{ + enum hdmi_vic vic = hdmitx_edid_vic_tab_map_vic(mode_name); + + if (vic == HDMI_Unknown) + return 0; + + return 1; +} + +static void hdmitx_late_resume(struct early_suspend *h) +{ + const struct vinfo_s *info = hdmi_get_current_vinfo(); + struct hdmitx_dev *phdmi = (struct hdmitx_dev *)h->param; + + hdcp_tst_sig = 0; + if (info && (strncmp(info->name, "panel", 5) == 0 || + strncmp(info->name, "null", 4) == 0)) { + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_VIDEO_BLANK_OP, VIDEO_UNBLANK); + return; + } + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_VIDEO_BLANK_OP, + VIDEO_BLANK); + + if (hdmitx_is_hdmi_vmode(info->name) == 1) + phdmi->HWOp.CntlMisc(&hdmitx_device, MISC_HPLL_FAKE, 0); + + phdmi->hpd_lock = 0; + + /* update status for hpd and switch/state */ + hdmitx_device.hpd_state = !!(hdmitx_device.HWOp.CntlMisc(&hdmitx_device, + MISC_HPD_GPI_ST, 0)); + /*force to get EDID after resume for Amplifer Power case*/ + if (hdmitx_device.hpd_state) + hdmitx_get_edid(phdmi); + + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AUDIO_MUTE_OP, AUDIO_MUTE); + set_disp_mode_auto(); + extcon_set_state(&sdev, 0, hdmitx_device.hpd_state); + extcon_set_state(&hdmi_power, 0, hdmitx_device.hpd_state); + pr_info("amhdmitx: late resume module %d\n", __LINE__); + phdmi->HWOp.Cntl((struct hdmitx_dev *)h->param, + HDMITX_EARLY_SUSPEND_RESUME_CNTL, HDMITX_LATE_RESUME); + hdmi_print(INF, SYS "late resume\n"); +} + +static struct early_suspend hdmitx_early_suspend_handler = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 10, + .suspend = hdmitx_early_suspend, + .resume = hdmitx_late_resume, + .param = &hdmitx_device, +}; +#endif + +/* Set avmute_set signal to HDMIRX */ +static int hdmitx_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct hdmitx_dev *hdev = container_of(nb, struct hdmitx_dev, nb); + + hdev->HWOp.CntlMisc(hdev, MISC_AVMUTE_OP, SET_AVMUTE); + mdelay(100); + hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); + hdev->HWOp.CntlMisc(hdev, MISC_HPLL_OP, HPLL_DISABLE); + return NOTIFY_OK; +} + +/* static struct hdmitx_info hdmi_info; */ +#define INIT_FLAG_VDACOFF 0x1 + /* unplug powerdown */ +#define INIT_FLAG_POWERDOWN 0x2 + +#define INIT_FLAG_NOT_LOAD 0x80 + +int hdmi_ch = 1; /* 1: 2ch */ + +static unsigned char init_flag; +#undef DISABLE_AUDIO +/* if set to 1, then HDMI will output no audio */ +/* In KTV case, HDMI output Picture only, and Audio is driven by other + * sources. + */ +unsigned char hdmi_audio_off_flag; +/* + * 0, do not unmux hpd when off or unplug ; + * 1, unmux hpd when unplug; + * 2, unmux hpd when unplug or off; + */ +static int hpdmode = 1; +/* 0xffff=disable; 0=PRBS 11; 1=PRBS 15; 2=PRBS 7; 3=PRBS 31*/ +static int hdmi_prbs_mode = 0xffff; +static int hdmi_detect_when_booting = 1; +/* 1: error 2: important 3: normal 4: detailed */ +static int debug_level = INF; + +int get_cur_vout_index(void) +/* + * return value: 1, vout; 2, vout2; + */ +{ + int vout_index = 1; + return vout_index; +} + +struct vinfo_s *hdmi_get_current_vinfo(void) +{ + struct vinfo_s *info; + + info = get_current_vinfo(); + return info; +} + +static int set_disp_mode(const char *mode) +{ + int ret = -1; + enum hdmi_vic vic; + + vic = hdmitx_edid_get_VIC(&hdmitx_device, mode, 1); + if (strncmp(mode, "2160p30hz", strlen("2160p30hz")) == 0) + vic = HDMI_4k2k_30; + else if (strncmp(mode, "2160p25hz", strlen("2160p25hz")) == 0) + vic = HDMI_4k2k_25; + else if (strncmp(mode, "2160p24hz", strlen("2160p24hz")) == 0) + vic = HDMI_4k2k_24; + else if (strncmp(mode, "smpte24hz", strlen("smpte24hz")) == 0) + vic = HDMI_4k2k_smpte_24; + else + ;/* nothing */ + + if (strncmp(mode, "1080p60hz", strlen("1080p60hz")) == 0) + vic = HDMI_1080p60; + if (strncmp(mode, "1080p50hz", strlen("1080p50hz")) == 0) + vic = HDMI_1080p50; + + if (vic != HDMI_Unknown) { + hdmitx_device.mux_hpd_if_pin_high_flag = 1; + if (hdmitx_device.vic_count == 0) { + if (hdmitx_device.unplug_powerdown) + return 0; + } + } +#if 0 + set_vmode_enc_hw(vic); +#endif + hdmitx_device.cur_VIC = HDMI_Unknown; + ret = hdmitx_set_display(&hdmitx_device, vic); + if (ret >= 0) { + hdmitx_device.HWOp.Cntl(&hdmitx_device, + HDMITX_AVMUTE_CNTL, AVMUTE_CLEAR); + hdmitx_device.cur_VIC = vic; + hdmitx_device.audio_param_update_flag = 1; + hdmitx_device.auth_process_timer = AUTH_PROCESS_TIME; + } + + if (hdmitx_device.cur_VIC == HDMI_Unknown) { + if (hpdmode == 2) { + /* edid will be read again when hpd is muxed and + * it is high + */ + hdmitx_edid_clear(&hdmitx_device); + hdmitx_device.mux_hpd_if_pin_high_flag = 0; + } + if (hdmitx_device.HWOp.Cntl) { + hdmitx_device.HWOp.Cntl(&hdmitx_device, + HDMITX_HWCMD_TURNOFF_HDMIHW, + (hpdmode == 2)?1:0); + } + } + + return ret; +} + +static void hdmitx_pre_display_init(void) +{ + hdmitx_device.cur_VIC = HDMI_Unknown; + hdmitx_device.auth_process_timer = AUTH_PROCESS_TIME; + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_VIDEO_BLANK_OP, VIDEO_BLANK); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AUDIO_MUTE_OP, AUDIO_MUTE); + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_MUX_INIT, 1); + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_OP, HDCP14_OFF); + /* msleep(10); */ + hdmitx_device.HWOp.CntlMisc(&hdmitx_device, MISC_TMDS_PHY_OP, + TMDS_PHY_DISABLE); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_CLR_AVI_PACKET, 0); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_CLR_VSDB_PACKET, 0); +} + +/* fr_tab[] + * 1080p24hz, 24:1 + * 1080p23.976hz, 2997:125 + * 25/50/100/200hz, no change + */ +static struct frac_rate_table fr_tab[] = { + {"24hz", 24, 1, 2997, 125}, + {"30hz", 30, 1, 2997, 100}, + {"60hz", 60, 1, 2997, 50}, + {"120hz", 120, 1, 2997, 25}, + {"240hz", 120, 1, 5994, 25}, + {NULL}, +}; + +static void recalc_vinfo_sync_duration(struct vinfo_s *info, unsigned int frac) +{ + struct frac_rate_table *fr = &fr_tab[0]; + + while (fr->hz) { + if (strstr(info->name, fr->hz)) { + if (frac) { + info->sync_duration_num = fr->sync_num_dec; + info->sync_duration_den = fr->sync_den_dec; + } else { + info->sync_duration_num = fr->sync_num_int; + info->sync_duration_den = fr->sync_den_int; + } + break; + } + fr++; + } +} + +static int set_disp_mode_auto(void) +{ + int ret = -1; + struct vinfo_s *info = NULL; + struct hdmitx_dev *hdev = &hdmitx_device; + struct hdmi_format_para *para = NULL; + unsigned char mode[32]; + enum hdmi_vic vic = HDMI_Unknown; + /* vic_ready got from IP */ + enum hdmi_vic vic_ready = hdev->HWOp.GetState( + hdev, STAT_VIDEO_VIC, 0); + + memset(mode, 0, sizeof(mode)); + + /* get current vinfo */ + info = hdmi_get_current_vinfo(); + hdmi_print(IMP, VID "get current mode: %s\n", + info ? info->name : "null"); + if (info == NULL) + return -1; + + info->fresh_tx_hdr_pkt = hdmitx_set_drm_pkt; + info->fresh_tx_vsif_pkt = hdmitx_set_vsif_pkt; + info->dv_info = &hdev->RXCap.dv_info; + info->hdr_info.hdr_support = (hdev->RXCap.hdr_sup_eotf_sdr << 0) + | (hdev->RXCap.hdr_sup_eotf_hdr << 1) + | (hdev->RXCap.hdr_sup_eotf_smpte_st_2084 << 2); + info->hdr_info.lumi_max = hdev->RXCap.hdr_lum_max; + info->hdr_info.lumi_avg = hdev->RXCap.hdr_lum_avg; + info->hdr_info.lumi_min = hdev->RXCap.hdr_lum_min; + pr_info("hdmitx: update rx hdr info %x\n", + info->hdr_info.hdr_support); + + /* If info->name equals to cvbs, then set mode to I mode to hdmi + */ + if ((strncmp(info->name, "480cvbs", 7) == 0) || + (strncmp(info->name, "576cvbs", 7) == 0) || + (strncmp(info->name, "panel", 5) == 0) || + (strncmp(info->name, "null", 4) == 0)) { + hdmi_print(ERR, VID "%s not valid hdmi mode\n", info->name); + hdev->HWOp.CntlConfig(hdev, CONF_CLR_AVI_PACKET, 0); + hdev->HWOp.CntlConfig(hdev, CONF_CLR_VSDB_PACKET, 0); + hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); + hdev->HWOp.CntlConfig(hdev, CONF_VIDEO_BLANK_OP, VIDEO_UNBLANK); + hdev->para = para = hdmi_get_fmt_name("invalid", fmt_attr); + return -1; + } + memcpy(mode, info->name, strlen(info->name)); + if (strstr(mode, "fp")) { + int i = 0; + + for (; mode[i]; i++) { + if ((mode[i] == 'f') && (mode[i + 1] == 'p')) { + /* skip "f", 1080fp60hz -> 1080p60hz */ + do { + mode[i] = mode[i + 1]; + i++; + } while (mode[i]); + break; + } + } + } + + para = hdmi_get_fmt_name(mode, fmt_attr); + hdev->para = para; + /* msleep(500); */ + vic = hdmitx_edid_get_VIC(hdev, mode, 1); + if (strncmp(info->name, "2160p30hz", strlen("2160p30hz")) == 0) { + vic = HDMI_4k2k_30; + } else if (strncmp(info->name, "2160p25hz", + strlen("2160p25hz")) == 0) { + vic = HDMI_4k2k_25; + } else if (strncmp(info->name, "2160p24hz", + strlen("2160p24hz")) == 0) { + vic = HDMI_4k2k_24; + } else if (strncmp(info->name, "smpte24hz", + strlen("smpte24hz")) == 0) + vic = HDMI_4k2k_smpte_24; + else { + /* nothing */ + } + if ((vic_ready != HDMI_Unknown) && (vic_ready == vic)) { + hdmi_print(IMP, SYS "[%s] ALREADY init VIC = %d\n", + __func__, vic); + if (hdev->RXCap.IEEEOUI == 0) { + /* DVI case judgement. In uboot, directly output HDMI + * mode + */ + hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, + DVI_MODE); + hdmi_print(IMP, SYS "change to DVI mode\n"); + } else if ((hdev->RXCap.IEEEOUI == 0xc03) && + (hdev->HWOp.CntlConfig(hdev, CONF_GET_HDMI_DVI_MODE, 0) + == DVI_MODE)) { + hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, + HDMI_MODE); + hdmi_print(IMP, SYS "change to HDMI mode\n"); + } + hdev->cur_VIC = vic; + hdev->output_blank_flag = 1; + hdev->ready = 1; + return 1; + } + hdmitx_pre_display_init(); + + hdev->cur_VIC = HDMI_Unknown; +/* if vic is HDMI_Unknown, hdmitx_set_display will disable HDMI */ + ret = hdmitx_set_display(hdev, vic); + pr_info("%s %d %d\n", info->name, info->sync_duration_num, + info->sync_duration_den); + recalc_vinfo_sync_duration(info, hdev->frac_rate_policy); + pr_info("%s %d %d\n", info->name, info->sync_duration_num, + info->sync_duration_den); + if (ret >= 0) { + hdev->HWOp.Cntl(hdev, HDMITX_AVMUTE_CNTL, AVMUTE_CLEAR); + hdev->cur_VIC = vic; + hdev->audio_param_update_flag = 1; + hdev->auth_process_timer = AUTH_PROCESS_TIME; + } + if (hdev->cur_VIC == HDMI_Unknown) { + if (hpdmode == 2) { + /* edid will be read again when hpd is muxed + * and it is high + */ + hdmitx_edid_clear(hdev); + hdev->mux_hpd_if_pin_high_flag = 0; + } + /* If current display is NOT panel, needn't TURNOFF_HDMIHW */ + if (strncmp(mode, "panel", 5) == 0) { + hdev->HWOp.Cntl(hdev, HDMITX_HWCMD_TURNOFF_HDMIHW, + (hpdmode == 2)?1:0); + } + } + hdmitx_set_audio(hdev, &(hdev->cur_audio_param), hdmi_ch); + hdev->output_blank_flag = 1; + if (hdev->hdcp_mode == 1) { + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_ON); + } + if (hdev->hdcp_mode == 2) { + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 2); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP22_ON); + } + hdev->ready = 1; + return ret; +} + +/*disp_mode attr*/ +static ssize_t show_disp_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "VIC:%d\n", + hdmitx_device.cur_VIC); + return pos; +} + +static ssize_t store_disp_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + set_disp_mode(buf); + return count; +} + +static ssize_t show_attr(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "%s\n\r", fmt_attr); + return pos; +} + +static ssize_t store_attr(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + memcpy(fmt_attr, buf, sizeof(fmt_attr)); + return count; +} + +/*aud_mode attr*/ +static ssize_t show_aud_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t store_aud_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + /* set_disp_mode(buf); */ + struct hdmitx_audpara *audio_param = + &(hdmitx_device.cur_audio_param); + if (strncmp(buf, "32k", 3) == 0) + audio_param->sample_rate = FS_32K; + else if (strncmp(buf, "44.1k", 5) == 0) + audio_param->sample_rate = FS_44K1; + else if (strncmp(buf, "48k", 3) == 0) + audio_param->sample_rate = FS_48K; + else { + hdmitx_device.force_audio_flag = 0; + return count; + } + audio_param->type = CT_PCM; + audio_param->channel_num = CC_2CH; + audio_param->sample_size = SS_16BITS; + + hdmitx_device.audio_param_update_flag = 1; + hdmitx_device.force_audio_flag = 1; + + return count; +} + +/*edid attr*/ +static ssize_t show_edid(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return hdmitx_edid_dump(&hdmitx_device, buf, PAGE_SIZE); +} + +static int dump_edid_data(unsigned int type, char *path) +{ + struct file *filp = NULL; + loff_t pos = 0; + char line[128] = {0}; + mm_segment_t old_fs = get_fs(); + unsigned int i = 0, j = 0, k = 0, size = 0, block_cnt = 0; + + set_fs(KERNEL_DS); + filp = filp_open(path, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("[%s] failed to open/create file: |%s|\n", + __func__, path); + goto PROCESS_END; + } + + block_cnt = hdmitx_device.EDID_buf[0x7e] + 1; + if (type == 1) { + /* dump as bin file*/ + size = vfs_write(filp, hdmitx_device.EDID_buf, + block_cnt*128, &pos); + } else if (type == 2) { + /* dump as txt file*/ + + for (i = 0; i < block_cnt; i++) { + for (j = 0; j < 8; j++) { + for (k = 0; k < 16; k++) { + snprintf((char *)&line[k*6], 7, + "0x%02x, ", + hdmitx_device.EDID_buf[i*128+j*16+k]); + } + line[16*6-1] = '\n'; + line[16*6] = 0x0; + pos = (i*8+j)*16*6; + size += vfs_write(filp, line, 16*6, &pos); + } + } + } + + pr_info("[%s] write %d bytes to file %s\n", __func__, size, path); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + +PROCESS_END: + set_fs(old_fs); + return 0; +} + +unsigned int use_loaded_edid; +static int load_edid_data(unsigned int type, char *path) +{ + struct file *filp = NULL; + loff_t pos = 0; + mm_segment_t old_fs = get_fs(); + + struct kstat stat; + unsigned int length = 0, max_len = EDID_MAX_BLOCK * 128; + char *buf = NULL; + + set_fs(KERNEL_DS); + + filp = filp_open(path, O_RDONLY, 0444); + if (IS_ERR(filp)) { + pr_info("[%s] failed to open file: |%s|\n", __func__, path); + goto PROCESS_END; + } + + vfs_stat(path, &stat); + + length = (stat.size > max_len)?max_len:stat.size; + + buf = kmalloc(length, GFP_KERNEL); + if (buf == NULL) + goto PROCESS_END; + + vfs_read(filp, buf, length, &pos); + + memcpy(hdmitx_device.EDID_buf, buf, length); + + kfree(buf); + filp_close(filp, NULL); + + pr_info("[%s] %d bytes loaded from file %s\n", __func__, length, path); + + hdmitx_edid_clear(&hdmitx_device); + hdmitx_edid_parse(&hdmitx_device); + pr_info("[%s] new edid loaded!\n", __func__); + +PROCESS_END: + set_fs(old_fs); + return 0; +} + +static ssize_t store_edid(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int argn = 0; + char *p = NULL, *para = NULL, *argv[8] = {NULL}; + unsigned int path_length = 0; + + p = kstrdup(buf, GFP_KERNEL); + if (p == NULL) + return count; + + do { + para = strsep(&p, " "); + if (para != NULL) { + argv[argn] = para; + argn++; + if (argn > 7) + break; + } + } while (para != NULL); + + if (buf[0] == 'h') { + int i; + + hdmi_print(INF, EDID "EDID hash value:\n"); + for (i = 0; i < 20; i++) + pr_info("%02x", hdmitx_device.EDID_hash[i]); + pr_info("\n"); + } + if (buf[0] == 'd') { + int ii, jj; + unsigned long block_idx; + int ret; + + ret = kstrtoul(buf+1, 16, &block_idx); + if (block_idx < EDID_MAX_BLOCK) { + for (ii = 0; ii < 8; ii++) { + for (jj = 0; jj < 16; jj++) { + hdmi_print(INF, "%02x ", + hdmitx_device.EDID_buf[block_idx*128+ii*16+jj]); + } + hdmi_print(INF, "\n"); + } + hdmi_print(INF, "\n"); + } + } + if (buf[0] == 'e') { + int ii, jj; + unsigned long block_idx; + int ret; + + ret = kstrtoul(buf+1, 16, &block_idx); + if (block_idx < EDID_MAX_BLOCK) { + for (ii = 0; ii < 8; ii++) { + for (jj = 0; jj < 16; jj++) { + hdmi_print(INF, "%02x ", + hdmitx_device.EDID_buf1[block_idx*128+ii*16+jj]); + } + hdmi_print(INF, "\n"); + } + hdmi_print(INF, "\n"); + } + } + + if (!strncmp(argv[0], "save", strlen("save"))) { + unsigned int type = 0; + + if (argn != 3) { + pr_info("[%s] cmd format: save bin/txt edid_file_path\n", + __func__); + goto PROCESS_END; + } + if (!strncmp(argv[1], "bin", strlen("bin"))) + type = 1; + else if (!strncmp(argv[1], "txt", strlen("txt"))) + type = 2; + + if ((type == 1) || (type == 2)) { + /* clean '\n' from file path*/ + path_length = strlen(argv[2]); + if (argv[2][path_length-1] == '\n') + argv[2][path_length-1] = 0x0; + + dump_edid_data(type, argv[2]); + } + } else if (!strncmp(argv[0], "load", strlen("load"))) { + if (argn != 2) { + pr_info("[%s] cmd format: load edid_file_path\n", + __func__); + goto PROCESS_END; + } + + /* clean '\n' from file path*/ + path_length = strlen(argv[1]); + if (argv[1][path_length-1] == '\n') + argv[1][path_length-1] = 0x0; + load_edid_data(0, argv[1]); + } + +PROCESS_END: + kfree(p); + return 16; +} + +/* rawedid attr */ +static ssize_t show_rawedid(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + int i; + struct hdmitx_dev *hdev = &hdmitx_device; + int num; + + /* prevent null prt */ + if (!hdev->edid_ptr) + hdev->edid_ptr = hdev->EDID_buf; + + if (hdev->edid_ptr[0x7e] < 4) + num = (hdev->edid_ptr[0x7e]+1)*0x80; + else + num = 0x100; + + for (i = 0; i < num; i++) + pos += snprintf(buf+pos, PAGE_SIZE, "%02x", hdev->edid_ptr[i]); + + pos += snprintf(buf+pos, PAGE_SIZE, "\n"); + + return pos; +} + +/* + * edid_parsing attr + * If RX edid data are all correct, HEAD(00 ff ff ff ff ff ff 00), checksum, + * version, etc), then return "ok". Otherwise, "ng" + */ +static ssize_t show_edid_parsing(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct hdmitx_dev *hdev = &hdmitx_device; + + if (hdev->edid_parsing) + pos += snprintf(buf+pos, PAGE_SIZE, "ok\n"); + else + pos += snprintf(buf+pos, PAGE_SIZE, "ng\n"); + + return pos; +} + +void hdmitx_audio_mute_op(unsigned int flag) +{ + hdmitx_device.tx_aud_cfg = flag; + if (flag == 0) + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AUDIO_MUTE_OP, AUDIO_MUTE); + else + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AUDIO_MUTE_OP, AUDIO_UNMUTE); +} +EXPORT_SYMBOL(hdmitx_audio_mute_op); + +static void hdr_work_func(struct work_struct *work) +{ + struct hdmitx_dev *hdev = + container_of(work, struct hdmitx_dev, work_hdr); + + if (hdev->hdr_src_feature == 0) { + unsigned char DRM_HB[3] = {0x87, 0x1, 26}; + unsigned char DRM_DB[26] = {0x0}; + + hdev->HWOp.SetPacket(HDMI_PACKET_DRM, DRM_DB, DRM_HB); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, CLR_AVI_BT2020); + msleep(1500); + if (hdev->hdr_src_feature == 0) + hdev->HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); + } + /* switch_set_state(&hdmi_hdr, hdev->hdr_src_feature); */ +} + +#define GET_LOW8BIT(a) ((a) & 0xff) +#define GET_HIGH8BIT(a) (((a) >> 8) & 0xff) +static void hdmitx_set_drm_pkt(struct master_display_info_s *data) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + unsigned char DRM_HB[3] = {0x87, 0x1, 26}; + unsigned char DRM_DB[26] = {0x0}; + static int hdr_state; + + if ((!data) || (!(hdev->RXCap.hdr_sup_eotf_smpte_st_2084) && + !(hdev->RXCap.hdr_sup_eotf_hdr) && + !(hdev->RXCap.hdr_sup_eotf_sdr))) { + hdev->hdr_src_feature = 0; + DRM_HB[1] = 0; + DRM_HB[2] = 0; + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_AVI_BT2020, + CLR_AVI_BT2020); + return; + } + + hdev->hdr_src_feature = (((data->features >> 16) & 0xff) == 0x9); + if (hdr_state != hdev->hdr_src_feature) { + hdr_state = hdev->hdr_src_feature; + schedule_work(&hdev->work_hdr); + } + + /* update DRM data */ + if ((hdev->RXCap.hdr_sup_eotf_smpte_st_2084) && hdev->hdr_src_feature) + DRM_DB[0] = 0x02; /* SMPTE ST 2084 */ + else { + memset(DRM_DB, 0, sizeof(DRM_DB)); + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_AVI_BT2020, + CLR_AVI_BT2020); + return; + } + DRM_DB[1] = 0x0; + DRM_DB[2] = GET_LOW8BIT(data->primaries[0][0]); + DRM_DB[3] = GET_HIGH8BIT(data->primaries[0][0]); + DRM_DB[4] = GET_LOW8BIT(data->primaries[0][1]); + DRM_DB[5] = GET_HIGH8BIT(data->primaries[0][1]); + DRM_DB[6] = GET_LOW8BIT(data->primaries[1][0]); + DRM_DB[7] = GET_HIGH8BIT(data->primaries[1][0]); + DRM_DB[8] = GET_LOW8BIT(data->primaries[1][1]); + DRM_DB[9] = GET_HIGH8BIT(data->primaries[1][1]); + DRM_DB[10] = GET_LOW8BIT(data->primaries[2][0]); + DRM_DB[11] = GET_HIGH8BIT(data->primaries[2][0]); + DRM_DB[12] = GET_LOW8BIT(data->primaries[2][1]); + DRM_DB[13] = GET_HIGH8BIT(data->primaries[2][1]); + DRM_DB[14] = GET_LOW8BIT(data->white_point[0]); + DRM_DB[15] = GET_HIGH8BIT(data->white_point[0]); + DRM_DB[16] = GET_LOW8BIT(data->white_point[1]); + DRM_DB[17] = GET_HIGH8BIT(data->white_point[1]); + DRM_DB[18] = GET_LOW8BIT(data->luminance[0]); + DRM_DB[19] = GET_HIGH8BIT(data->luminance[0]); + DRM_DB[20] = GET_LOW8BIT(data->luminance[1]); + DRM_DB[21] = GET_HIGH8BIT(data->luminance[1]); + DRM_DB[22] = GET_LOW8BIT(data->max_content); + DRM_DB[23] = GET_HIGH8BIT(data->max_content); + DRM_DB[24] = GET_LOW8BIT(data->max_frame_average); + DRM_DB[25] = GET_HIGH8BIT(data->max_frame_average); + + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, DRM_DB, DRM_HB); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_AVI_BT2020, + SET_AVI_BT2020); +} + +static void hdmitx_set_vsif_pkt(enum eotf_type type, uint8_t tunnel_mode) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + unsigned char VEN_HB[3] = {0x81, 0x01}; + unsigned char VEN_DB[24] = {0x00}; + unsigned char len = 0; + unsigned int vic = hdev->cur_VIC; + unsigned int hdmi_vic_4k_flag = 0; + + if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL) { + pr_info("hdmitx: not support DolbyVision\n"); + return; + } + + if ((vic == HDMI_3840x2160p30_16x9) || + (vic == HDMI_3840x2160p25_16x9) || + (vic == HDMI_3840x2160p24_16x9) || + (vic == HDMI_4096x2160p24_256x135)) + hdmi_vic_4k_flag = 1; + + switch (type) { + case EOTF_T_DOLBYVISION: + len = 0x18; + break; + case EOTF_T_HDR10: + len = 0x05; + break; + case EOTF_T_SDR: + len = 0x05; + break; + case EOTF_T_NULL: + default: + len = 0x05; + break; + } + + VEN_HB[2] = len; + VEN_DB[0] = 0x03; + VEN_DB[1] = 0x0c; + VEN_DB[2] = 0x00; + VEN_DB[3] = 0x00; + + if (hdmi_vic_4k_flag) { + VEN_DB[3] = 0x20; + if (vic == HDMI_3840x2160p30_16x9) + VEN_DB[4] = 0x1; + else if (vic == HDMI_3840x2160p25_16x9) + VEN_DB[4] = 0x2; + else if (vic == HDMI_3840x2160p24_16x9) + VEN_DB[4] = 0x3; + else if (vic == HDMI_4096x2160p24_256x135) + VEN_DB[4] = 0x4; + else + VEN_DB[4] = 0x0; + } + + if (type == EOTF_T_DOLBYVISION) { + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); + if (tunnel_mode == 1) { + hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, + COLORSPACE_RGB444); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, + RGB_RANGE_FUL); + } else { + hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, + COLORSPACE_YUV422); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, + YCC_RANGE_FUL); + } + } else { + if (hdmi_vic_4k_flag) + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); + else + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, NULL); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, + hdev->para->cs); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, RGB_RANGE_LIM); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, YCC_RANGE_LIM); + } +} + +/*config attr*/ +static ssize_t show_config(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + unsigned char *conf; + struct hdmitx_dev *hdev = &hdmitx_device; + + pos += snprintf(buf+pos, PAGE_SIZE, "cur_VIC: %d\n", hdev->cur_VIC); + if (hdev->cur_video_param) + pos += snprintf(buf+pos, PAGE_SIZE, + "cur_video_param->VIC=%d\n", + hdev->cur_video_param->VIC); + if (hdev->para) { + pos += snprintf(buf+pos, PAGE_SIZE, "cd = %d\n", + hdev->para->cd); + pos += snprintf(buf+pos, PAGE_SIZE, "cs = %d\n", + hdev->para->cs); + } + + switch (hdev->tx_aud_cfg) { + case 0: + conf = "off"; + break; + case 1: + conf = "on"; + break; + case 2: + conf = "auto"; + break; + default: + conf = "none"; + } + pos += snprintf(buf+pos, PAGE_SIZE, "audio config: %s\n", conf); + + if (hdev->flag_3dfp) + conf = "FramePacking"; + else if (hdev->flag_3dss) + conf = "SidebySide"; + else if (hdev->flag_3dtb) + conf = "TopButtom"; + else + conf = "off"; + pos += snprintf(buf+pos, PAGE_SIZE, "3D config: %s\n", conf); + return pos; +} + +static ssize_t store_config(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret = 0; + + pr_info("hdmitx: config: %s\n", buf); + if (strncmp(buf, "force", 5) == 0) + hdmitx_device.disp_switch_config = DISP_SWITCH_FORCE; + else if (strncmp(buf, "edid", 4) == 0) + hdmitx_device.disp_switch_config = DISP_SWITCH_EDID; + else if (strncmp(buf, "unplug_powerdown", 16) == 0) { + if (buf[16] == '0') + hdmitx_device.unplug_powerdown = 0; + else + hdmitx_device.unplug_powerdown = 1; + } else if (strncmp(buf, "3d", 2) == 0) { + /* Second, set 3D parameters */ + if (strncmp(buf+2, "tb", 2) == 0) { + hdmitx_device.flag_3dtb = 1; + hdmitx_device.flag_3dss = 0; + hdmitx_device.flag_3dfp = 0; + hdmi_set_3d(&hdmitx_device, T3D_TAB, 0); + } else if ((strncmp(buf+2, "lr", 2) == 0) || + (strncmp(buf+2, "ss", 2) == 0)) { + unsigned long sub_sample_mode = 0; + + hdmitx_device.flag_3dtb = 0; + hdmitx_device.flag_3dss = 1; + hdmitx_device.flag_3dfp = 0; + if (buf[2]) + ret = kstrtoul(buf+2, 10, + &sub_sample_mode); + /* side by side */ + hdmi_set_3d(&hdmitx_device, T3D_SBS_HALF, + sub_sample_mode); + } else if (strncmp(buf+2, "fp", 2) == 0) { + hdmitx_device.flag_3dtb = 0; + hdmitx_device.flag_3dss = 0; + hdmitx_device.flag_3dfp = 1; + hdmi_set_3d(&hdmitx_device, T3D_FRAME_PACKING, 0); + } else if (strncmp(buf+2, "off", 3) == 0) { + hdmitx_device.flag_3dfp = 0; + hdmitx_device.flag_3dtb = 0; + 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); + hdmi_print(IMP, AUD "configure off\n"); + } else if (strncmp(buf+6, "on", 2) == 0) { + hdmitx_audio_mute_op(1); + hdmi_print(IMP, 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; + hdmi_print(IMP, AUD "configure auto\n"); + } else + hdmi_print(ERR, AUD "configure error\n"); + } else if (strncmp(buf, "drm", 3) == 0) { + unsigned char DRM_HB[3] = {0x87, 0x1, 26}; + unsigned char DRM_DB[26] = { + 0x00, 0x00, 0xc2, 0x33, 0xc4, 0x86, 0x4c, 0x1d, + 0xb8, 0x0b, 0xd0, 0x84, 0x80, 0x3e, 0x13, 0x3d, + 0x42, 0x40, 0x4c, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + }; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, + DRM_DB, DRM_HB); + } else if (strncmp(buf, "vsif", 4) == 0) + hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1'); + + return 16; +} + + +static ssize_t store_debug(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + hdmitx_device.HWOp.DebugFun(&hdmitx_device, buf); + return count; +} + +/* support format lists */ +const char *disp_mode_t[] = { +#if 0 + "480i60hz", + "576i50hz", +#endif + "480p60hz", + "576p50hz", + "720p60hz", + "1080i60hz", + "1080p60hz", + "720p50hz", + "1080i50hz", + "1080p30hz", + "1080p50hz", + "1080p25hz", + "1080p24hz", + "2160p30hz", + "2160p25hz", + "2160p24hz", + "smpte24hz", + "smpte25hz", + "smpte30hz", + "smpte50hz", + "smpte60hz", + "smpte50hz420", + "smpte60hz420", + "2160p50hz", + "2160p60hz", + "2160p50hz420", + "2160p60hz420", + NULL +}; + +/**/ +static ssize_t show_disp_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, pos = 0; + const char *native_disp_mode = + hdmitx_edid_get_native_VIC(&hdmitx_device); + enum hdmi_vic vic; + + if (hdmitx_device.tv_no_edid) { + pos += snprintf(buf+pos, PAGE_SIZE, "null edid\n"); + } else { + for (i = 0; disp_mode_t[i]; i++) { + vic = hdmitx_edid_get_VIC(&hdmitx_device, + disp_mode_t[i], 0); + if (vic != HDMI_Unknown) { + pos += snprintf(buf+pos, PAGE_SIZE, "%s", + disp_mode_t[i]); + if (native_disp_mode && (strcmp( + native_disp_mode, + disp_mode_t[i]) == 0)) { + pos += snprintf(buf+pos, PAGE_SIZE, + "*\n"); + } else + pos += snprintf(buf+pos, PAGE_SIZE, "\n"); + } + } + } + return pos; +} + +static ssize_t show_preferred_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct rx_cap *pRXCap = &hdmitx_device.RXCap; + + pos += snprintf(buf+pos, PAGE_SIZE, "%s\n", + hdmitx_edid_vic_to_string(pRXCap->preferred_mode)); + + return pos; +} + +/**/ +static int local_support_3dfp(enum hdmi_vic vic) +{ + switch (vic) { + case HDMI_1280x720p50_16x9: + case HDMI_1280x720p60_16x9: + case HDMI_1920x1080p24_16x9: + case HDMI_1920x1080p25_16x9: + case HDMI_1920x1080p30_16x9: + case HDMI_1920x1080p50_16x9: + case HDMI_1920x1080p60_16x9: + return 1; + default: + return 0; + } +} +static ssize_t show_disp_cap_3d(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, pos = 0; + int j = 0; + enum hdmi_vic vic; + + pos += snprintf(buf+pos, PAGE_SIZE, "3D support lists:\n"); + for (i = 0; disp_mode_t[i]; i++) { + if (strstr(disp_mode_t[i], "2160p") || + strstr(disp_mode_t[i], "smpte")) + continue; + vic = hdmitx_edid_get_VIC(&hdmitx_device, + disp_mode_t[i], 0); + for (j = 0; j < hdmitx_device.RXCap.VIC_count; j++) { + if (vic == hdmitx_device.RXCap.VIC[j]) + break; + } + pos += snprintf(buf+pos, PAGE_SIZE, "\n%s ", + disp_mode_t[i]); + if (local_support_3dfp(vic) + && (hdmitx_device.RXCap.support_3d_format[ + hdmitx_device.RXCap.VIC[j]].frame_packing == 1)) { + pos += snprintf(buf+pos, PAGE_SIZE, + "FramePacking "); + } + if (hdmitx_device.RXCap.support_3d_format[ + hdmitx_device.RXCap.VIC[j]].top_and_bottom == 1){ + pos += snprintf(buf+pos, PAGE_SIZE, + "TopBottom "); + } + if (hdmitx_device.RXCap.support_3d_format[ + hdmitx_device.RXCap.VIC[j]].side_by_side == 1) { + pos += snprintf(buf+pos, PAGE_SIZE, + "SidebySide "); + } + } + pos += snprintf(buf+pos, PAGE_SIZE, "\n"); + + return pos; +} + +/**/ +static ssize_t show_aud_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, pos = 0, j; + static const char * const aud_coding_type[] = { + "ReferToStreamHeader", "PCM", "AC-3", "MPEG1", "MP3", + "MPEG2", "AAC", "DTS", "ATRAC", "OneBitAudio", + "Dobly_Digital+", "DTS-HD", "MAT", "DST", "WMA_Pro", + "Reserved", NULL}; + static const char * const aud_sampling_frequency[] = { + "ReferToStreamHeader", "32", "44.1", "48", "88.2", "96", + "176.4", "192", NULL}; + static const char * const aud_sample_size[] = {"ReferToStreamHeader", + "16", "20", "24", NULL}; + + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + + pos += snprintf(buf + pos, PAGE_SIZE, + "CodingType MaxChannels SamplingFreq SampleSize\n"); + for (i = 0; i < pRXCap->AUD_count; i++) { + pos += snprintf(buf + pos, PAGE_SIZE, "%s, %d ch, ", + aud_coding_type[pRXCap->RxAudioCap[i]. + audio_format_code], + pRXCap->RxAudioCap[i].channel_num_max + 1); + for (j = 0; j < 7; j++) { + if (pRXCap->RxAudioCap[i].freq_cc & (1 << j)) + pos += snprintf(buf + pos, PAGE_SIZE, "%s/", + aud_sampling_frequency[j+1]); + } + pos += snprintf(buf + pos - 1, PAGE_SIZE, " kHz, "); + for (j = 0; j < 3; j++) { + if (pRXCap->RxAudioCap[i].cc3 & (1 << j)) + pos += snprintf(buf + pos, PAGE_SIZE, "%s/", + aud_sample_size[j+1]); + } + pos += snprintf(buf + pos - 1, PAGE_SIZE, " bit\n"); + } + + return pos; +} + +/**/ +static ssize_t show_dc_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + enum hdmi_vic vic = HDMI_Unknown; + int pos = 0; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + +#if 0 + if (pRXCap->dc_48bit_420) + pos += snprintf(buf + pos, PAGE_SIZE, "420,16bit\n"); + if (pRXCap->dc_36bit_420) + pos += snprintf(buf + pos, PAGE_SIZE, "420,12bit\n"); +#endif + if (pRXCap->dc_30bit_420) { + pos += snprintf(buf + pos, PAGE_SIZE, "420,10bit\n"); + pos += snprintf(buf + pos, PAGE_SIZE, "420,8bit\n"); + } else { + vic = hdmitx_edid_get_VIC(&hdmitx_device, "2160p60hz420", 0); + if (vic != HDMI_Unknown) { + pos += snprintf(buf + pos, PAGE_SIZE, "420,8bit\n"); + goto next444; + } + vic = hdmitx_edid_get_VIC(&hdmitx_device, "2160p50hz420", 0); + if (vic != HDMI_Unknown) { + pos += snprintf(buf + pos, PAGE_SIZE, "420,8bit\n"); + goto next444; + } + } +next444: + if (pRXCap->dc_y444) { +#if 0 + if (pRXCap->dc_36bit) + pos += snprintf(buf + pos, PAGE_SIZE, "444,12bit\n"); + if (pRXCap->dc_36bit) + pos += snprintf(buf + pos, PAGE_SIZE, "422,12bit\n"); +#endif + if (pRXCap->dc_30bit) { + pos += snprintf(buf + pos, PAGE_SIZE, "444,10bit\n"); + pos += snprintf(buf + pos, PAGE_SIZE, "444,8bit\n"); + } +#if 0 + if (pRXCap->dc_48bit) + pos += snprintf(buf + pos, PAGE_SIZE, "444,16bit\n"); +#endif + if (pRXCap->dc_30bit) { + pos += snprintf(buf + pos, PAGE_SIZE, "422,10bit\n"); + pos += snprintf(buf + pos, PAGE_SIZE, "422,8bit\n"); + goto nextrgb; + } + } else { + if (pRXCap->native_Mode & (1 << 5)) + pos += snprintf(buf + pos, PAGE_SIZE, "444,8bit\n"); + if (pRXCap->native_Mode & (1 << 4)) + pos += snprintf(buf + pos, PAGE_SIZE, "422,8bit\n"); + } +nextrgb: +#if 0 + if (pRXCap->dc_48bit) + pos += snprintf(buf + pos, PAGE_SIZE, "rgb,16bit\n"); + if (pRXCap->dc_36bit) + pos += snprintf(buf + pos, PAGE_SIZE, "rgb,12bit\n"); +#endif + if (pRXCap->dc_30bit) + pos += snprintf(buf + pos, PAGE_SIZE, "rgb,10bit\n"); + pos += snprintf(buf + pos, PAGE_SIZE, "rgb,8bit\n"); + return pos; +} + +static bool valid_mode; +static char cvalid_mode[32]; +static ssize_t show_valid_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct hdmi_format_para *para = NULL; + + if (cvalid_mode[0]) + para = hdmi_get_fmt_name(cvalid_mode, cvalid_mode); + if (para) { + pr_info("sname = %s\n", para->sname); + pr_info("char_clk = %d\n", para->tmds_clk); + pr_info("cd = %d\n", para->cd); + pr_info("cs = %d\n", para->cs); + } + + valid_mode = hdmitx_edid_check_valid_mode(&hdmitx_device, para); + + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n\r", valid_mode); + + return pos; +} + +static ssize_t store_valid_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + memset(cvalid_mode, 0, sizeof(cvalid_mode)); + memcpy(cvalid_mode, buf, sizeof(cvalid_mode)); + cvalid_mode[31] = '\0'; + return count; +} + + +/**/ +static ssize_t show_hdr_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + + pos += snprintf(buf + pos, PAGE_SIZE, "Supported EOTF:\n"); + pos += snprintf(buf + pos, PAGE_SIZE, " Traditional SDR: %d\n", + pRXCap->hdr_sup_eotf_sdr); + pos += snprintf(buf + pos, PAGE_SIZE, " Traditional HDR: %d\n", + pRXCap->hdr_sup_eotf_hdr); + pos += snprintf(buf + pos, PAGE_SIZE, " SMPTE ST 2084: %d\n", + pRXCap->hdr_sup_eotf_smpte_st_2084); + pos += snprintf(buf + pos, PAGE_SIZE, " Future EOTF: %d\n", + pRXCap->hdr_sup_eotf_future); + pos += snprintf(buf + pos, PAGE_SIZE, "Supported SMD type1: %d\n", + pRXCap->hdr_sup_SMD_type1); + pos += snprintf(buf + pos, PAGE_SIZE, "Luminance Data\n"); + pos += snprintf(buf + pos, PAGE_SIZE, " Max: %d\n", + pRXCap->hdr_lum_max); + pos += snprintf(buf + pos, PAGE_SIZE, " Avg: %d\n", + pRXCap->hdr_lum_avg); + pos += snprintf(buf + pos, PAGE_SIZE, " Min: %d\n", + pRXCap->hdr_lum_min); + + return pos; +} + +static ssize_t show_dv_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + const struct dv_info *dv = &(hdmitx_device.RXCap.dv_info); + + if (dv->ieeeoui != 0x00d046) + return pos; + pos += snprintf(buf + pos, PAGE_SIZE, + "DolbyVision%d RX support list:\n", dv->ver); + if (dv->sup_yuv422_12bit) + pos += snprintf(buf + pos, PAGE_SIZE, " yuv422_12bit\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + " 2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30"); + if (dv->sup_global_dimming) + pos += snprintf(buf + pos, PAGE_SIZE, " global dimming\n"); + if (dv->colorimetry) + pos += snprintf(buf + pos, PAGE_SIZE, " colorimetry\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + " IEEEOUI: 0x%06x\n", dv->ieeeoui); + if (dv->ver == 0) + pos += snprintf(buf + pos, PAGE_SIZE, " DM Ver: %x:%x\n", + dv->vers.ver0.dm_major_ver, dv->vers.ver0.dm_minor_ver); + if (dv->ver == 1) + pos += snprintf(buf + pos, PAGE_SIZE, " DM Ver: %x\n", + dv->vers.ver1.dm_version); + + return pos; +} + +static ssize_t show_aud_ch(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf + pos, PAGE_SIZE, + "hdmi_channel = %d ch\n", hdmi_ch ? hdmi_ch + 1 : 0); + return pos; +} + +static ssize_t store_aud_ch(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (strncmp(buf, "6ch", 3) == 0) + hdmi_ch = 5; + else if (strncmp(buf, "8ch", 3) == 0) + hdmi_ch = 7; + else if (strncmp(buf, "2ch", 3) == 0) + hdmi_ch = 1; + else + return count; + + hdmitx_device.audio_param_update_flag = 1; + hdmitx_device.force_audio_flag = 1; + + 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; + hdmitx_set_audio(hdev, &(hdev->cur_audio_param), 0); + } + 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; + hdmitx_set_audio(hdev, &(hdev->cur_audio_param), 0); + } + return count; +} + +/* + * 1: set avmute + * -1: clear avmute + * 0: off avmute + */ +static ssize_t store_avmute(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int cmd = OFF_AVMUTE; + + if (strncmp(buf, "-1", 2) == 0) + cmd = CLR_AVMUTE; + else if (strncmp(buf, "0", 1) == 0) + cmd = OFF_AVMUTE; + else if (strncmp(buf, "1", 1) == 0) + cmd = SET_AVMUTE; + else + pr_info("set avmute wrong: %s\n", buf); + + hdmitx_device.HWOp.CntlMisc(&hdmitx_device, MISC_AVMUTE_OP, cmd); + return count; +} + +static ssize_t show_avmute(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +/* + * 0: clear vic + */ +static ssize_t store_vic(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + + if (strncmp(buf, "0", 1) == 0) { + hdev->HWOp.CntlConfig(hdev, CONF_CLR_AVI_PACKET, 0); + hdev->HWOp.CntlConfig(hdev, CONF_CLR_VSDB_PACKET, 0); + } + + return count; +} + +static ssize_t show_vic(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + enum hdmi_vic vic = HDMI_Unknown; + int pos = 0; + + vic = hdev->HWOp.GetState(hdev, STAT_VIDEO_VIC, 0); + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n", vic); + + return pos; +} + +/* + * 1: enable hdmitx phy + * 0: disable hdmitx phy + */ +static ssize_t store_phy(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int cmd = TMDS_PHY_ENABLE; + + if (strncmp(buf, "0", 1) == 0) + cmd = TMDS_PHY_DISABLE; + else if (strncmp(buf, "1", 1) == 0) + cmd = TMDS_PHY_ENABLE; + else + pr_info("hdmitx: set phy wrong: %s\n", buf); + + hdmitx_device.HWOp.CntlMisc(&hdmitx_device, MISC_TMDS_PHY_OP, cmd); + return count; +} + +static ssize_t show_phy(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t store_frac_rate(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int val = 0; + + if (isdigit(buf[0])) { + val = buf[0] - '0'; + pr_info("hdmitx: set frac_rate_policy as %d\n", val); + if ((val == 0) || (val == 1)) + hdmitx_device.frac_rate_policy = val; + else + pr_info("only accept as 0 or 1\n"); + } + + return count; +} + +static ssize_t show_frac_rate(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n", + hdmitx_device.frac_rate_policy); + + return pos; +} + +static ssize_t store_hdcp_clkdis(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + pr_info("set hdcp clkdis: %s\n", buf); + + hdmitx_device.HWOp.CntlMisc(&hdmitx_device, MISC_HDCP_CLKDIS, + (buf[0] == '1') ? 1 : 0); + return count; +} + +static ssize_t show_hdcp_clkdis(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t store_hdcp_pwr(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] == '1') { + hdcp_tst_sig = 1; + pr_info("%s[%d] set hdcp_pwr as %d\n", __func__, __LINE__, + hdcp_tst_sig); + } + return count; +} + +static ssize_t show_hdcp_pwr(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n", !!hdcp_tst_sig); + if (hdcp_tst_sig == 1) { + hdcp_tst_sig = 0; + pr_info("%s[%d] set hdcp_pwr as %d\n", __func__, __LINE__, + hdcp_tst_sig); + } + return pos; +} + +static ssize_t store_hdcp_byp(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_BYP, 0); + + return count; +} + +static int lstore; +static ssize_t show_hdcp_lstore(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + if (lstore < 0x10) { + lstore = 0; + if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_14_LSTORE, 0)) + lstore += 1; + if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_22_LSTORE, 0)) + lstore += 2; + } + if (lstore & 0x1) + pos += snprintf(buf + pos, PAGE_SIZE, "14\n"); + if (lstore & 0x2) + pos += snprintf(buf + pos, PAGE_SIZE, "22\n"); + if ((lstore & 0xf) == 0) + pos += snprintf(buf + pos, PAGE_SIZE, "00\n"); + return pos; +} + +static ssize_t store_hdcp_lstore(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + pr_info("hdcp: set lstore as %s\n", buf); + if (strncmp(buf, "0", 1) == 0) + lstore = 0x10; + if (strncmp(buf, "11", 2) == 0) + lstore = 0x11; + if (strncmp(buf, "12", 2) == 0) + lstore = 0x12; + if (strncmp(buf, "13", 2) == 0) + lstore = 0x13; + + return count; +} + +static unsigned int div40 = -1; +static ssize_t show_div40(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + if (div40 != -1) + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n", div40); + + return pos; +} + +static ssize_t store_div40(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + + hdev->HWOp.CntlDDC(hdev, DDC_SCDC_DIV40_SCRAMB, buf[0] == '1'); + div40 = (buf[0] == '1'); + + return count; +} + +static ssize_t show_hdcp_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + switch (hdmitx_device.hdcp_mode) { + case 1: + pos += snprintf(buf + pos, PAGE_SIZE, "14"); + break; + case 2: + pos += snprintf(buf + pos, PAGE_SIZE, "22"); + break; + default: + pos += snprintf(buf + pos, PAGE_SIZE, "off"); + break; + } + + return pos; +} + +static ssize_t store_hdcp_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + pr_info("hdcp: set mode as %s\n", buf); + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_MUX_INIT, 1); + if (strncmp(buf, "-1", 2) == 0) { + hdmitx_device.hdcp_mode = -1; + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP14_OFF); + } + if (strncmp(buf, "0", 1) == 0) + hdmitx_device.hdcp_mode = 0; + if (strncmp(buf, "1", 1) == 0) { + pr_info("%s[%d]", __func__, __LINE__); + hdmitx_device.hdcp_mode = 1; + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP14_ON); + } + if (strncmp(buf, "2", 1) == 0) { + hdmitx_device.hdcp_mode = 2; + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_MUX_INIT, 2); + } + + return count; +} + +void direct_hdcptx14_start(void) +{ + pr_info("%s[%d]", __func__, __LINE__); + hdmitx_device.hdcp_mode = 1; + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP14_ON); +} +EXPORT_SYMBOL(direct_hdcptx14_start); + +void direct_hdcptx14_stop(void) +{ + pr_info("%s[%d]", __func__, __LINE__); + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP14_OFF); +} +EXPORT_SYMBOL(direct_hdcptx14_stop); + +static ssize_t store_hdcp_ctrl(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_14_LSTORE, + 0) == 0) + return count; + dev_warn(dev, "hdmitx20: %s\n", buf); + if (strncmp(buf, "stop", 4) == 0) { + if (strncmp(buf+4, "14", 2) == 0) + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP14_OFF); + if (strncmp(buf+4, "22", 2) == 0) + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_OP, HDCP22_OFF); + } + + return count; +} + +static ssize_t show_hdcp_ctrl(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t show_hdcp_ksv_info(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0, i; + char bksv_buf[5]; + + hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_GET_BKSV, + (unsigned long int)bksv_buf); + + pos += snprintf(buf+pos, PAGE_SIZE, "HDCP14 BKSV: "); + for (i = 0; i < 5; i++) { + pos += snprintf(buf+pos, PAGE_SIZE, "%02x", + bksv_buf[i]); + } + pos += snprintf(buf+pos, PAGE_SIZE, " %s\n", + hdcp_ksv_valid(bksv_buf) ? "Valid" : "Invalid"); + + return pos; +} + +/* Special FBC check */ +static int check_fbc_special(unsigned char *edid_dat) +{ + if ((edid_dat[250] == 0xfb) && (edid_dat[251] == 0x0c)) + return 1; + else + return 0; +} + +static ssize_t show_hdcp_ver(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + uint32_t ver = 0; + + if (check_fbc_special(&hdmitx_device.EDID_buf[0]) + || check_fbc_special(&hdmitx_device.EDID_buf1[0])) { + pos += snprintf(buf+pos, PAGE_SIZE, "00\n\r"); + return pos; + } + + /* if TX don't have HDCP22 key, skip RX hdcp22 ver */ + if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device, + DDC_HDCP_22_LSTORE, 0) == 0) + goto next; + + /* Detect RX support HDCP22 */ + ver = hdcp_rd_hdcp22_ver(); + if (ver) { + pos += snprintf(buf+pos, PAGE_SIZE, "22\n\r"); + pos += snprintf(buf+pos, PAGE_SIZE, "14\n\r"); + return pos; + } +next: /* Detect RX support HDCP14 */ + /* Here, must assume RX support HDCP14, otherwise affect 1A-03 */ + if (ver == 0) { + pos += snprintf(buf+pos, PAGE_SIZE, "14\n\r"); + return pos; + } + + /* RX NOT support HDCP */ + pos += snprintf(buf+pos, PAGE_SIZE, "00\n\r"); + return pos; +} + +static ssize_t show_hpd_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "%d", + hdmitx_device.hpd_state); + return pos; +} + +static ssize_t show_hdmi_init(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "%d\n\r", hdmi_init); + return pos; +} +static ssize_t show_ready(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "%d\r\n", + hdmitx_device.ready); + return pos; +} + +static ssize_t store_ready(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (strncmp(buf, "0", 1) == 0) + hdmitx_device.ready = 0; + if (strncmp(buf, "1", 1) == 1) + hdmitx_device.ready = 1; + return count; +} + +static ssize_t show_support_3d(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf+pos, PAGE_SIZE, "%d\n", + hdmitx_device.RXCap.threeD_present); + return pos; +} + +void hdmi_print(int dbg_lvl, const char *fmt, ...) +{ + va_list args; +#if 0 + if (dbg_lvl == OFF) + return; +#endif + if (dbg_lvl <= debug_level) { + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); + } +} + +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(edid, 0644, show_edid, store_edid); +static DEVICE_ATTR(rawedid, 0444, show_rawedid, NULL); +static DEVICE_ATTR(edid_parsing, 0444, show_edid_parsing, NULL); +static DEVICE_ATTR(config, 0664, show_config, + store_config); +static DEVICE_ATTR(debug, 0200, NULL, store_debug); +static DEVICE_ATTR(disp_cap, 0444, show_disp_cap, NULL); +static DEVICE_ATTR(preferred_mode, 0444, show_preferred_mode, NULL); +static DEVICE_ATTR(aud_cap, 0444, show_aud_cap, NULL); +static DEVICE_ATTR(hdr_cap, 0444, show_hdr_cap, NULL); +static DEVICE_ATTR(dv_cap, 0444, show_dv_cap, 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); +static DEVICE_ATTR(frac_rate_policy, 0664, + show_frac_rate, store_frac_rate); +static DEVICE_ATTR(hdcp_clkdis, 0664, show_hdcp_clkdis, + store_hdcp_clkdis); +static DEVICE_ATTR(hdcp_pwr, 0664, show_hdcp_pwr, + store_hdcp_pwr); +static DEVICE_ATTR(hdcp_byp, 0200, NULL, store_hdcp_byp); +static DEVICE_ATTR(hdcp_mode, 0664, show_hdcp_mode, + store_hdcp_mode); +static DEVICE_ATTR(hdcp_lstore, 0664, show_hdcp_lstore, + store_hdcp_lstore); +static DEVICE_ATTR(div40, 0664, show_div40, store_div40); +static DEVICE_ATTR(hdcp_ctrl, 0664, show_hdcp_ctrl, + store_hdcp_ctrl); +static DEVICE_ATTR(disp_cap_3d, 0444, show_disp_cap_3d, NULL); +static DEVICE_ATTR(hdcp_ksv_info, 0444, show_hdcp_ksv_info, NULL); +static DEVICE_ATTR(hdcp_ver, 0444, show_hdcp_ver, NULL); +static DEVICE_ATTR(hpd_state, 0444, show_hpd_state, NULL); +static DEVICE_ATTR(hdmi_init, 0444, show_hdmi_init, NULL); +static DEVICE_ATTR(ready, 0664, show_ready, store_ready); +static DEVICE_ATTR(support_3d, 0444, show_support_3d, NULL); + +struct vinfo_s *hdmi_info; +static struct vinfo_s *hdmitx_get_current_info(void) +{ + return hdmi_info; +} + +static int hdmitx_set_current_vmode(enum vmode_e mode) +{ +pr_info("%s[%d]\n", __func__, __LINE__); + set_disp_mode_auto(); + + return 0; +} + +static enum vmode_e hdmitx_validate_vmode(char *mode) +{ + struct vinfo_s *info = hdmi_get_valid_vinfo(mode); + +pr_info("%s[%d]\n", __func__, __LINE__); + if (info) { + hdmi_info = info; + return VMODE_HDMI; + } +pr_info("%s[%d]\n", __func__, __LINE__); + return VMODE_MAX; +} + +static int hdmitx_vmode_is_supported(enum vmode_e mode) +{ /* TODO */ +pr_info("%s[%d]\n", __func__, __LINE__); + return true; +} + +static int hdmitx_module_disable(enum vmode_e cur_vmod) +{ /* TODO */ +pr_info("%s[%d]\n", __func__, __LINE__); + return 0; +} + + +static struct vout_server_s hdmitx_server = { + .name = "vout_hdmitx_server", + .op = { + .get_vinfo = hdmitx_get_current_info, + .set_vmode = hdmitx_set_current_vmode, + .validate_vmode = hdmitx_validate_vmode, + .vmode_is_supported = hdmitx_vmode_is_supported, + .disable = hdmitx_module_disable, +#ifdef CONFIG_PM + .vout_suspend = NULL, + .vout_resume = NULL, +#endif + }, +}; + + +#include +#include +#include +#include +#include + +static struct rate_map_fs map_fs[] = { + {0, FS_REFER_TO_STREAM}, + {32000, FS_32K}, + {44100, FS_44K1}, + {48000, FS_48K}, + {88200, FS_88K2}, + {96000, FS_96K}, + {176400, FS_176K4}, + {192000, FS_192K}, +}; + +static enum hdmi_audio_fs aud_samp_rate_map(unsigned int rate) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(map_fs); i++) { + if (map_fs[i].rate == rate) { + hdmi_print(IMP, AUD "aout notify rate %d\n", + rate); + return map_fs[i].fs; + } + } + hdmi_print(IMP, AUD "get FS_MAX\n"); + return FS_MAX; +} + +static unsigned char *aud_type_string[] = { + "CT_REFER_TO_STREAM", + "CT_PCM", + "CT_AC_3", + "CT_MPEG1", + "CT_MP3", + "CT_MPEG2", + "CT_AAC", + "CT_DTS", + "CT_ATRAC", + "CT_ONE_BIT_AUDIO", + "CT_DOLBY_D", + "CT_DTS_HD", + "CT_MAT", + "CT_DST", + "CT_WMA", + "CT_MAX", +}; + +static struct size_map aud_size_map_ss[] = { + {0, SS_REFER_TO_STREAM}, + {16, SS_16BITS}, + {20, SS_20BITS}, + {24, SS_24BITS}, + {32, SS_MAX}, +}; + +static enum hdmi_audio_sampsize aud_size_map(unsigned int bits) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(aud_size_map_ss); i++) { + if (bits == aud_size_map_ss[i].sample_bits) { + hdmi_print(IMP, AUD "aout notify size %d\n", + bits); + return aud_size_map_ss[i].ss; + } + } + hdmi_print(IMP, AUD "get SS_MAX\n"); + return SS_MAX; +} + +static int hdmitx_notify_callback_a(struct notifier_block *block, + unsigned long cmd, void *para); +static struct notifier_block hdmitx_notifier_nb_a = { + .notifier_call = hdmitx_notify_callback_a, +}; +static int hdmitx_notify_callback_a(struct notifier_block *block, + unsigned long cmd, void *para) +{ + int i, audio_check = 0; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + struct snd_pcm_substream *substream = + (struct snd_pcm_substream *)para; + struct hdmitx_audpara *audio_param = + &(hdmitx_device.cur_audio_param); + enum hdmi_audio_fs n_rate = aud_samp_rate_map(substream->runtime->rate); + enum hdmi_audio_sampsize n_size = + aud_size_map(substream->runtime->sample_bits); + + hdmitx_device.audio_param_update_flag = 0; + hdmitx_device.audio_notify_flag = 0; + + if (audio_param->sample_rate != n_rate) { + audio_param->sample_rate = n_rate; + hdmitx_device.audio_param_update_flag = 1; + } + + if (audio_param->type != cmd) { + audio_param->type = cmd; + hdmi_print(INF, AUD "aout notify format %s\n", + aud_type_string[audio_param->type & 0xff]); + hdmitx_device.audio_param_update_flag = 1; + } + + if (audio_param->sample_size != n_size) { + audio_param->sample_size = n_size; + hdmitx_device.audio_param_update_flag = 1; + } + + if (audio_param->channel_num != + (substream->runtime->channels - 1)) { + audio_param->channel_num = + substream->runtime->channels - 1; + hdmitx_device.audio_param_update_flag = 1; + } + if (hdmitx_device.tx_aud_cfg == 2) { + hdmi_print(INF, AUD "auto mode\n"); + /* Detect whether Rx is support current audio format */ + for (i = 0; i < pRXCap->AUD_count; i++) { + if (pRXCap->RxAudioCap[i].audio_format_code == cmd) + audio_check = 1; + } + /* sink don't support current audio mode */ + if ((!audio_check) && (cmd != CT_PCM)) { + pr_info("Sink not support this audio format %lu\n", + cmd); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AUDIO_MUTE_OP, AUDIO_MUTE); + hdmitx_device.audio_param_update_flag = 0; + } + } + if (hdmitx_device.audio_param_update_flag == 0) + hdmi_print(INF, AUD "no update\n"); + else + hdmitx_device.audio_notify_flag = 1; + + + if ((!hdmi_audio_off_flag) && + (hdmitx_device.audio_param_update_flag)) { + /* plug-in & update audio param */ + if (hdmitx_device.hpd_state == 1) { + hdmitx_set_audio(&hdmitx_device, + &(hdmitx_device.cur_audio_param), hdmi_ch); + if ((hdmitx_device.audio_notify_flag == 1) || + (hdmitx_device.audio_step == 1)) { + hdmitx_device.audio_notify_flag = 0; + hdmitx_device.audio_step = 0; + } + hdmitx_device.audio_param_update_flag = 0; + hdmi_print(INF, AUD "set audio param\n"); + } + } + + + return 0; +} + +struct i2c_client *i2c_edid_client; + +static DEFINE_MUTEX(getedid_mutex); +static void hdmitx_get_edid(struct hdmitx_dev *hdev) +{ + mutex_lock(&getedid_mutex); + /* TODO hdmitx_edid_ram_buffer_clear(hdev); */ + hdev->HWOp.CntlDDC(hdev, DDC_RESET_EDID, 0); + hdev->HWOp.CntlDDC(hdev, DDC_PIN_MUX_OP, PIN_MUX); + /* start reading edid frist time */ + hdev->HWOp.CntlDDC(hdev, DDC_EDID_READ_DATA, 0); + hdev->HWOp.CntlDDC(hdev, DDC_EDID_GET_DATA, 0); + /* If EDID is not correct at first time, then retry */ + if (!check_dvi_hdmi_edid_valid(hdev->EDID_buf)) { + msleep(40); + /* start reading edid second time */ + hdev->HWOp.CntlDDC(hdev, DDC_EDID_READ_DATA, 0); + hdev->HWOp.CntlDDC(hdev, DDC_EDID_GET_DATA, 1); + } + hdmitx_edid_clear(hdev); + hdmitx_edid_parse(hdev); + hdmitx_edid_buf_compare_print(hdev); + mutex_unlock(&getedid_mutex); +} + +static void hdmitx_hpd_plugin_handler(struct work_struct *work) +{ + char bksv_buf[5]; + struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, + struct hdmitx_dev, work_hpd_plugin); + + if (!(hdev->hdmitx_event & (HDMI_TX_HPD_PLUGIN))) + return; + mutex_lock(&setclk_mutex); + pr_info("hdmitx: plugin\n"); + hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN; + /* start reading E-EDID */ + rx_repeat_hpd_state(1); + hdmitx_get_edid(hdev); + if (check_fbc_special(&hdev->EDID_buf[0]) + || check_fbc_special(&hdev->EDID_buf1[0])) + rx_set_repeater_support(0); + else + rx_set_repeater_support(1); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_GET_BKSV, + (unsigned long int)bksv_buf); + rx_set_receive_hdcp(bksv_buf, 1, 1, 0, 0); + set_disp_mode_auto(); + hdmitx_set_audio(hdev, &(hdev->cur_audio_param), hdmi_ch); + hdev->hpd_state = 1; + extcon_set_state(&sdev, 0, 1); + extcon_set_state(&hdmi_audio, 0, 1); + + mutex_unlock(&setclk_mutex); +} + +static void clear_hdr_info(struct hdmitx_dev *hdev) +{ + struct vinfo_s *info = get_current_vinfo(); + + if (info) { + info->hdr_info.hdr_support = 0; + info->hdr_info.lumi_max = 0; + info->hdr_info.lumi_avg = 0; + info->hdr_info.lumi_min = 0; + pr_info("hdmitx: clear RX hdr info\n"); + } +} + +static void hdmitx_hpd_plugout_handler(struct work_struct *work) +{ + struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, + struct hdmitx_dev, work_hpd_plugout); + + if (!(hdev->hdmitx_event & (HDMI_TX_HPD_PLUGOUT))) + return; + hdev->hdcp_mode = 0; + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF); + mutex_lock(&setclk_mutex); + pr_info("hdmitx: plugout\n"); + if (!!(hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0))) { + pr_info("hdmitx: hpd gpi high\n"); + hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; + mutex_unlock(&setclk_mutex); + return; + } + hdev->ready = 0; + rx_repeat_hpd_state(0); + hdev->HWOp.CntlConfig(hdev, CONF_CLR_AVI_PACKET, 0); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1); + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF); + hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); + hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; + hdev->HWOp.CntlMisc(hdev, MISC_ESM_RESET, 0); + clear_hdr_info(hdev); + hdmitx_edid_clear(hdev); + hdmitx_edid_ram_buffer_clear(hdev); + hdev->hpd_state = 0; + extcon_set_state(&sdev, 0, 0); + extcon_set_state(&hdmi_audio, 0, 0); + mutex_unlock(&setclk_mutex); +} + +static void hdmitx_internal_intr_handler(struct work_struct *work) +{ + struct hdmitx_dev *hdev = container_of((struct work_struct *)work, + struct hdmitx_dev, work_internal_intr); + + hdev->HWOp.DebugFun(hdev, "dumpintr"); +} + +int get_hpd_state(void) +{ + int ret; + + mutex_lock(&setclk_mutex); + ret = hdmitx_device.hpd_state; + mutex_unlock(&setclk_mutex); + + return ret; +} +EXPORT_SYMBOL(get_hpd_state); + +/****************************** + * hdmitx kernel task + *******************************/ +int tv_audio_support(int type, struct rx_cap *pRXCap) +{ + int i, audio_check = 0; + + for (i = 0; i < pRXCap->AUD_count; i++) { + if (pRXCap->RxAudioCap[i].audio_format_code == type) + audio_check = 1; + } + return audio_check; +} + +static int hdmi_task_handle(void *data) +{ + struct hdmitx_dev *hdmitx_device = (struct hdmitx_dev *)data; + + sdev.state = !!(hdmitx_device->HWOp.CntlMisc(hdmitx_device, + MISC_HPD_GPI_ST, 0)); + hdmitx_device->hpd_state = sdev.state; + extcon_set_state(&hdmi_power, 0, hdmitx_device->hpd_state); + INIT_WORK(&hdmitx_device->work_hdr, hdr_work_func); + +/* When init hdmi, clear the hdmitx module edid ram and edid buffer. */ + hdmitx_edid_ram_buffer_clear(hdmitx_device); + + hdmitx_device->hdmi_wq = alloc_workqueue(DEVICE_NAME, + WQ_HIGHPRI | WQ_CPU_INTENSIVE, 0); + INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugin, + hdmitx_hpd_plugin_handler); + INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugout, + hdmitx_hpd_plugout_handler); + INIT_WORK(&hdmitx_device->work_internal_intr, + hdmitx_internal_intr_handler); + + hdmitx_device->tx_aud_cfg = 1; /* default audio configure is on */ + if (init_flag & INIT_FLAG_POWERDOWN) { + /* power down */ + hdmitx_device->unplug_powerdown = 1; + hdmitx_device->HWOp.Cntl(hdmitx_device, + HDMITX_HWCMD_TURNOFF_HDMIHW, (hpdmode != 0)?1:0); + } else + hdmitx_device->HWOp.Cntl(hdmitx_device, + HDMITX_HWCMD_MUX_HPD, 0); + + hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_IP_INTR_MASN_RST, 0); + hdmitx_device->HWOp.Cntl(hdmitx_device, + HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH, 0); + + hdmitx_device->HWOp.SetupIRQ(hdmitx_device); + hdmi_init = 1; + return 0; +} + +/* Linux */ +/***************************** + * hdmitx driver file_operations + * + ******************************/ +static int amhdmitx_open(struct inode *node, struct file *file) +{ + struct hdmitx_dev *hdmitx_in_devp; + + /* Get the per-device structure that contains this cdev */ + hdmitx_in_devp = container_of(node->i_cdev, struct hdmitx_dev, cdev); + file->private_data = hdmitx_in_devp; + + return 0; + +} + + +static int amhdmitx_release(struct inode *node, struct file *file) +{ + /* struct hdmitx_dev *hdmitx_in_devp = file->private_data; */ + + /* Reset file pointer */ + + /* Release some other fields */ + /* ... */ + return 0; +} + +static const struct file_operations amhdmitx_fops = { + .owner = THIS_MODULE, + .open = amhdmitx_open, + .release = amhdmitx_release, +/* .ioctl = amhdmitx_ioctl, */ +}; + +struct hdmitx_dev *get_hdmitx_device(void) +{ + return &hdmitx_device; +} +EXPORT_SYMBOL(get_hdmitx_device); + +static int get_dt_vend_init_data(struct device_node *np, + struct vendor_info_data *vend) +{ + int ret; + + ret = of_property_read_string(np, "vendor_name", + (const char **)&(vend->vendor_name)); + if (ret) + hdmi_print(INF, SYS "not find vendor name\n"); + + ret = of_property_read_u32(np, "vendor_id", &(vend->vendor_id)); + if (ret) + hdmi_print(INF, SYS "not find vendor id\n"); + + ret = of_property_read_string(np, "product_desc", + (const char **)&(vend->product_desc)); + if (ret) + hdmi_print(INF, SYS "not find product desc\n"); + return 0; +} + +static int amhdmitx_probe(struct platform_device *pdev) +{ + int r, ret = 0; + struct pinctrl *p; + struct device *dev; + +#ifdef CONFIG_OF + int val; + phandle phandle; + struct device_node *init_data; +#endif + + hdmitx_device.hdtx_dev = &pdev->dev; + /* init para for NULL protection */ + hdmitx_device.para = hdmi_get_fmt_name("invalid", fmt_attr); + hdmi_print(IMP, SYS "amhdmitx_probe\n"); + + r = alloc_chrdev_region(&hdmitx_id, 0, HDMI_TX_COUNT, + DEVICE_NAME); + if (r < 0) { + hdmi_print(INF, SYS + "Can't register major for amhdmitx device\n"); + return r; + } + + hdmitx_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(hdmitx_class)) { + unregister_chrdev_region(hdmitx_id, HDMI_TX_COUNT); + return -1; + /* return PTR_ERR(aoe_class); */ + } + + hdmitx_device.unplug_powerdown = 0; + hdmitx_device.vic_count = 0; + hdmitx_device.auth_process_timer = 0; + hdmitx_device.force_audio_flag = 0; + hdmitx_device.hdcp_mode = -1; /* no hdcp by default */ + hdmitx_device.ready = 0; + +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&hdmitx_early_suspend_handler); +#endif + hdmitx_device.nb.notifier_call = hdmitx_reboot_notifier; + register_reboot_notifier(&hdmitx_device.nb); + if ((init_flag&INIT_FLAG_POWERDOWN) && (hpdmode == 2)) + hdmitx_device.mux_hpd_if_pin_high_flag = 0; + else + hdmitx_device.mux_hpd_if_pin_high_flag = 1; + hdmitx_device.audio_param_update_flag = 0; + cdev_init(&(hdmitx_device.cdev), &amhdmitx_fops); + hdmitx_device.cdev.owner = THIS_MODULE; + cdev_add(&(hdmitx_device.cdev), hdmitx_id, HDMI_TX_COUNT); + + dev = device_create(hdmitx_class, NULL, hdmitx_id, NULL, + "amhdmitx%d", 0); /* kernel>=2.6.27 */ + + if (dev == NULL) { + hdmi_print(ERR, SYS "device_create create error\n"); + class_destroy(hdmitx_class); + r = -EEXIST; + return r; + } + hdmitx_device.hdtx_dev = dev; + 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_edid); + ret = device_create_file(dev, &dev_attr_rawedid); + ret = device_create_file(dev, &dev_attr_edid_parsing); + ret = device_create_file(dev, &dev_attr_config); + ret = device_create_file(dev, &dev_attr_debug); + ret = device_create_file(dev, &dev_attr_disp_cap); + ret = device_create_file(dev, &dev_attr_preferred_mode); + ret = device_create_file(dev, &dev_attr_disp_cap_3d); + ret = device_create_file(dev, &dev_attr_aud_cap); + 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); + ret = device_create_file(dev, &dev_attr_frac_rate_policy); + ret = device_create_file(dev, &dev_attr_hdcp_clkdis); + ret = device_create_file(dev, &dev_attr_hdcp_pwr); + ret = device_create_file(dev, &dev_attr_hdcp_ksv_info); + ret = device_create_file(dev, &dev_attr_hdcp_ver); + ret = device_create_file(dev, &dev_attr_hdcp_byp); + ret = device_create_file(dev, &dev_attr_hdcp_mode); + ret = device_create_file(dev, &dev_attr_hdcp_lstore); + ret = device_create_file(dev, &dev_attr_div40); + ret = device_create_file(dev, &dev_attr_hdcp_ctrl); + ret = device_create_file(dev, &dev_attr_hpd_state); + ret = device_create_file(dev, &dev_attr_hdmi_init); + ret = device_create_file(dev, &dev_attr_ready); + ret = device_create_file(dev, &dev_attr_support_3d); + ret = device_create_file(dev, &dev_attr_dc_cap); + ret = device_create_file(dev, &dev_attr_valid_mode); + + vout_register_server(&hdmitx_server); +#ifdef CONFIG_SND_SOC + aout_register_client(&hdmitx_notifier_nb_a); +#else + r = r ? (long int)&hdmitx_notifier_nb_a : + (long int)&hdmitx_notifier_nb_a; +#endif + +#ifdef CONFIG_OF + if (pdev->dev.of_node) { + memset(&hdmitx_device.config_data, 0, + sizeof(struct hdmi_config_platform_data)); +/* HPD pinctrl */ + if (of_get_property(pdev->dev.of_node, "pinctrl-names", NULL)) { + ret = of_property_read_string_index(pdev->dev.of_node, + "pinctrl-names", 0, &hdmitx_device.hpd_pin); + if (!ret) + p = devm_pinctrl_get_select(&pdev->dev, + hdmitx_device.hpd_pin); + } +/* DDC pinctrl */ + if (of_get_property(pdev->dev.of_node, "pinctrl-names", NULL)) { + ret = of_property_read_string_index(pdev->dev.of_node, + "pinctrl-names", 1, &hdmitx_device.ddc_pin); + if (!ret) + p = devm_pinctrl_get_select(&pdev->dev, + hdmitx_device.ddc_pin); + } + +/* Get vendor information */ + ret = of_property_read_u32(pdev->dev.of_node, + "vend-data", &val); + if (ret) + hdmi_print(INF, SYS "not find match init-data\n"); + if (ret == 0) { + phandle = val; + init_data = of_find_node_by_phandle(phandle); + if (!init_data) + hdmi_print(INF, SYS "not find device node\n"); + hdmitx_device.config_data.vend_data = kzalloc( + sizeof(struct vendor_info_data), GFP_KERNEL); + if (!hdmitx_device.config_data.vend_data) + hdmi_print(INF, SYS + "can not get vend_data dat\n"); + ret = get_dt_vend_init_data(init_data, + hdmitx_device.config_data.vend_data); + if (ret) + hdmi_print(INF, SYS "not find vend_init_data\n"); + } +/* Get power control */ + ret = of_property_read_u32(pdev->dev.of_node, + "pwr-ctrl", &val); + if (ret) + hdmi_print(INF, SYS "not find match pwr-ctl\n"); + if (ret == 0) { + phandle = val; + init_data = of_find_node_by_phandle(phandle); + if (!init_data) + hdmi_print(INF, SYS "not find device node\n"); + hdmitx_device.config_data.pwr_ctl = kzalloc((sizeof( + struct hdmi_pwr_ctl)) * HDMI_TX_PWR_CTRL_NUM, + GFP_KERNEL); + if (!hdmitx_device.config_data.pwr_ctl) + hdmi_print(INF, SYS"can not get pwr_ctl mem\n"); + memset(hdmitx_device.config_data.pwr_ctl, 0, + sizeof(struct hdmi_pwr_ctl)); + if (ret) + hdmi_print(INF, SYS "not find pwr_ctl\n"); + } + } + +#else + hdmi_pdata = pdev->dev.platform_data; + if (!hdmi_pdata) { + hdmi_print(INF, SYS "not get platform data\n"); + r = -ENOENT; + } else { + hdmi_print(INF, SYS "get hdmi platform data\n"); + } +#endif + hdmitx_device.irq_hpd = platform_get_irq_byname(pdev, "hdmitx_hpd"); + if (hdmitx_device.irq_hpd == -ENXIO) { + pr_err("%s: ERROR: hdmitx hpd irq No not found\n", + __func__); + return -ENXIO; + } + pr_info("hdmitx hpd irq = %d\n", hdmitx_device.irq_hpd); + + extcon_dev_register(&sdev); + extcon_dev_register(&hdmi_audio); + extcon_dev_register(&hdmi_power); + extcon_dev_register(&hdmi_hdr); + + hdmitx_init_parameters(&hdmitx_device.hdmi_info); + HDMITX_Meson_Init(&hdmitx_device); + hdmitx_device.task = kthread_run(hdmi_task_handle, + &hdmitx_device, "kthread_hdmi"); + + if (r < 0) { + hdmi_print(INF, SYS "register switch dev failed\n"); + return r; + } + return r; +} + +static int amhdmitx_remove(struct platform_device *pdev) +{ + struct device *dev = hdmitx_device.hdtx_dev; + + extcon_dev_unregister(&sdev); + extcon_dev_unregister(&hdmi_audio); + extcon_dev_unregister(&hdmi_power); + extcon_dev_unregister(&hdmi_hdr); + cancel_work_sync(&hdmitx_device.work_hdr); + + if (hdmitx_device.HWOp.UnInit) + hdmitx_device.HWOp.UnInit(&hdmitx_device); + hdmitx_device.hpd_event = 0xff; + kthread_stop(hdmitx_device.task); + vout_unregister_server(&hdmitx_server); +#ifdef CONFIG_SND_SOC + aout_unregister_client(&hdmitx_notifier_nb_a); +#endif + + /* Remove the cdev */ + 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_edid); + device_remove_file(dev, &dev_attr_rawedid); + device_remove_file(dev, &dev_attr_edid_parsing); + device_remove_file(dev, &dev_attr_config); + device_remove_file(dev, &dev_attr_debug); + device_remove_file(dev, &dev_attr_disp_cap); + device_remove_file(dev, &dev_attr_disp_cap_3d); + device_remove_file(dev, &dev_attr_hdr_cap); + device_remove_file(dev, &dev_attr_dv_cap); + device_remove_file(dev, &dev_attr_dc_cap); + device_remove_file(dev, &dev_attr_valid_mode); + device_remove_file(dev, &dev_attr_hpd_state); + device_remove_file(dev, &dev_attr_hdmi_init); + device_remove_file(dev, &dev_attr_ready); + device_remove_file(dev, &dev_attr_support_3d); + device_remove_file(dev, &dev_attr_avmute); + device_remove_file(dev, &dev_attr_vic); + device_remove_file(dev, &dev_attr_frac_rate_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); + + cdev_del(&hdmitx_device.cdev); + + device_destroy(hdmitx_class, hdmitx_id); + + class_destroy(hdmitx_class); + +/* TODO */ +/* kfree(hdmi_pdata->phy_data); */ +/* kfree(hdmi_pdata); */ + + unregister_chrdev_region(hdmitx_id, HDMI_TX_COUNT); + return 0; +} + +#ifdef CONFIG_PM +static int amhdmitx_suspend(struct platform_device *pdev, + pm_message_t state) +{ + return 0; +} + +static int amhdmitx_resume(struct platform_device *pdev) +{ + hdcp_tst_sig = 0; + pr_info("amhdmitx: resume module %d\n", __LINE__); + return 0; +} +#endif + +#ifdef CONFIG_INSTABOOT +static unsigned char __nosavedata EDID_buf_save[EDID_MAX_BLOCK * 128]; +static unsigned char __nosavedata EDID_buf1_save[EDID_MAX_BLOCK * 128]; +static unsigned char __nosavedata EDID_hash_save[20]; +static struct rx_cap __nosavedata RXCap_save; +static struct hdmitx_info __nosavedata hdmi_info_save; + +static void save_device_param(void) +{ + memcpy(EDID_buf_save, hdmitx_device.EDID_buf, EDID_MAX_BLOCK * 128); + memcpy(EDID_buf1_save, hdmitx_device.EDID_buf1, EDID_MAX_BLOCK * 128); + memcpy(EDID_hash_save, hdmitx_device.EDID_hash, 20); + memcpy(&RXCap_save, &hdmitx_device.RXCap, sizeof(struct rx_cap)); + memcpy(&hdmi_info_save, &hdmitx_device.hdmi_info, + sizeof(struct hdmitx_info)); +} + +static void restore_device_param(void) +{ + memcpy(hdmitx_device.EDID_buf, EDID_buf_save, EDID_MAX_BLOCK * 128); + memcpy(hdmitx_device.EDID_buf1, EDID_buf1_save, EDID_MAX_BLOCK * 128); + memcpy(hdmitx_device.EDID_hash, EDID_hash_save, 20); + memcpy(&hdmitx_device.RXCap, &RXCap_save, sizeof(struct rx_cap)); + memcpy(&hdmitx_device.hdmi_info, &hdmi_info_save, + sizeof(struct hdmitx_info)); +} + +static int amhdmitx_realdata_save(void) +{ + save_device_param(); + return 0; +} + +static void amhdmitx_realdata_restore(void) +{ + restore_device_param(); +} + +static struct instaboot_realdata_ops amhdmitx_realdata_ops = { + .save = amhdmitx_realdata_save, + .restore = amhdmitx_realdata_restore, +}; + +static int amhdmitx_restore(struct device *dev) +{ + int current_hdmi_state = !!(hdmitx_device.HWOp.CntlMisc(&hdmitx_device, + MISC_HPD_GPI_ST, 0)); + char *vout_mode = get_vout_mode_internal(); + + if (strstr(vout_mode, "cvbs") && current_hdmi_state == 1) { + mutex_lock(&setclk_mutex); + sdev.state = 0; + hdmitx_device.hpd_state = sdev.state; + mutex_unlock(&setclk_mutex); + pr_info("resend hdmi plug in event\n"); + hdmitx_device.hdmitx_event |= HDMI_TX_HPD_PLUGIN; + hdmitx_device.hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; + PREPARE_DELAYED_WORK(&hdmitx_device.work_hpd_plugin, + hdmitx_hpd_plugin_handler); + queue_delayed_work(hdmitx_device.hdmi_wq, + &hdmitx_device.work_hpd_plugin, 2 * HZ); + } else { + mutex_lock(&setclk_mutex); + sdev.state = current_hdmi_state; + hdmitx_device.hpd_state = sdev.state; + mutex_unlock(&setclk_mutex); + } + return 0; +} +static int amhdmitx_pm_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return amhdmitx_suspend(pdev, PMSG_SUSPEND); +} +static int amhdmitx_pm_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return amhdmitx_resume(pdev); +} +static const struct dev_pm_ops amhdmitx_pm = { + .restore = amhdmitx_restore, + .suspend = amhdmitx_pm_suspend, + .resume = amhdmitx_pm_resume, +}; +#endif + +#ifdef CONFIG_OF +static const struct of_device_id meson_amhdmitx_dt_match[] = { + { + .compatible = "amlogic, amhdmitx", + }, + {}, +}; +#else +#define meson_amhdmitx_dt_match NULL +#endif +static struct platform_driver amhdmitx_driver = { + .probe = amhdmitx_probe, + .remove = amhdmitx_remove, +#ifdef CONFIG_PM + .suspend = amhdmitx_suspend, + .resume = amhdmitx_resume, +#endif + .driver = { + .name = DEVICE_NAME, + .owner = THIS_MODULE, + .of_match_table = meson_amhdmitx_dt_match, +#ifdef CONFIG_HIBERNATION + .pm = &amhdmitx_pm, +#endif + } +}; + +static int amhdmitx_device_init(struct hdmitx_dev *hdmi_dev) +{ + if (hdmi_dev == NULL) + return 1; + + hdmi_dev->hdtx_dev = NULL; + + return 0; +} + +static int __init amhdmitx_init(void) +{ + if (init_flag&INIT_FLAG_NOT_LOAD) + return 0; + + hdmi_print(IMP, SYS "amhdmitx_init\n"); + hdmi_print(IMP, SYS "Ver: %s\n", HDMITX_VER); + + amhdmitx_device_init(&hdmitx_device); + + if (platform_driver_register(&amhdmitx_driver)) { + hdmi_print(ERR, SYS + "failed to register amhdmitx module\n"); +#if 0 + platform_device_del(amhdmi_tx_device); + platform_device_put(amhdmi_tx_device); +#endif + return -ENODEV; + } +#ifdef CONFIG_INSTABOOT + INIT_LIST_HEAD(&amhdmitx_realdata_ops.node); + register_instaboot_realdata_ops(&amhdmitx_realdata_ops); +#endif + return 0; +} + + + + +static void __exit amhdmitx_exit(void) +{ + hdmi_print(INF, SYS "amhdmitx_exit\n"); + platform_driver_unregister(&amhdmitx_driver); +/* \\ platform_device_unregister(amhdmi_tx_device); */ +/* \\ amhdmi_tx_device = NULL; */ +#ifdef CONFIG_INSTABOOT + unregister_instaboot_realdata_ops(&amhdmitx_realdata_ops); +#endif +} + +/* module_init(amhdmitx_init); */ +subsys_initcall(amhdmitx_init); +module_exit(amhdmitx_exit); + +MODULE_DESCRIPTION("AMLOGIC HDMI TX driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0.0"); + +/* besides characters defined in separator, '\"' are used as separator; + * and any characters in '\"' will not act as separator + */ +static char *next_token_ex(char *separator, char *buf, unsigned int size, + unsigned int offset, unsigned int *token_len, + unsigned int *token_offset) +{ + char *pToken = NULL; + char last_separator = 0; + char trans_char_flag = 0; + + if (buf) { + for (; offset < size; offset++) { + int ii = 0; + char ch; + + if (buf[offset] == '\\') { + trans_char_flag = 1; + continue; + } + while (((ch = separator[ii++]) != buf[offset]) && (ch)) + ; + if (ch) { + if (!pToken) { + continue; + } else { + if (last_separator != '"') { + *token_len = (unsigned int) + (buf + offset - pToken); + *token_offset = offset; + return pToken; + } + } + } else if (!pToken) { + if (trans_char_flag && (buf[offset] == '"')) + last_separator = buf[offset]; + pToken = &buf[offset]; + } else if ((trans_char_flag && (buf[offset] == '"')) + && (last_separator == '"')) { + *token_len = (unsigned int)(buf + offset - pToken - 2); + *token_offset = offset + 1; + return pToken + 1; + } + trans_char_flag = 0; + } + if (pToken) { + *token_len = (unsigned int)(buf + offset - pToken); + *token_offset = offset; + } + } + return pToken; +} + +static int __init hdmitx_boot_para_setup(char *s) +{ + char separator[] = {' ', ',', ';', 0x0}; + char *token; + unsigned int token_len, token_offset, offset = 0; + int size = strlen(s); + + do { + token = next_token_ex(separator, s, size, offset, + &token_len, &token_offset); + if (token) { + if ((token_len == 3) + && (strncmp(token, "off", token_len) == 0)) { + init_flag |= INIT_FLAG_NOT_LOAD; + } + } + offset = token_offset; + } while (token); + return 0; +} + +__setup("hdmitx=", hdmitx_boot_para_setup); + +MODULE_PARM_DESC(hdmi_detect_when_booting, "\n hdmi_detect_when_booting\n"); +module_param(hdmi_detect_when_booting, int, 0664); + +MODULE_PARM_DESC(hdmi_prbs_mode, "\n hdmi_prbs_mode\n"); +module_param(hdmi_prbs_mode, int, 0664); + +MODULE_PARM_DESC(debug_level, "\n debug_level\n"); +module_param(debug_level, int, 0664); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c new file mode 100644 index 000000000000..46393d577c0f --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c @@ -0,0 +1,59 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +static struct timer_list scdc_tmds_cfg_timer; +static int cnt; + +static void tmds_config(unsigned long arg) +{ + struct hdmitx_dev *hdev = (struct hdmitx_dev *)arg; + uint8_t st = 0; + + /* TMDS 1/40 & Scramble */ + scdc_wr_sink(TMDS_CFG, hdev->para->tmds_clk_div40 ? 0x3 : 0); + scdc_wr_sink(TMDS_CFG, hdev->para->tmds_clk_div40 ? 0x3 : 0); + scdc_rd_sink(SCRAMBLER_ST, &st); + cnt++; + if ((hdev->para->tmds_clk_div40) && (st & 0x1)) { + pr_info("hdmitx20: rx scrambler status\n"); + return; + } + if ((hdev->para->tmds_clk_div40) && (cnt < 3)) + mod_timer(&scdc_tmds_cfg_timer, jiffies + HZ / 2); + else + cnt = 0; +} + +void scdc_config(void *hdev) +{ + static int init_flag; + + if (!init_flag) { + init_flag = 1; + init_timer(&scdc_tmds_cfg_timer); + scdc_tmds_cfg_timer.data = (ulong)hdev; + scdc_tmds_cfg_timer.function = tmds_config; + scdc_tmds_cfg_timer.expires = jiffies; + add_timer(&scdc_tmds_cfg_timer); + return; + } + mod_timer(&scdc_tmds_cfg_timer, jiffies); +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c new file mode 100644 index 000000000000..b58fbd177538 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -0,0 +1,774 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static unsigned char hdmi_output_rgb; +static void hdmitx_set_spd_info(struct hdmitx_dev *hdmitx_device); +static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdmitx_device, + enum hdmi_vic VideoCode); + +static struct hdmitx_vidpara hdmi_tx_video_params[] = { + { + .VIC = HDMI_640x480p60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480p60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480p60_16x9, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480p60_16x9_rpt, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_4_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_720p60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080i60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480i60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_2_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480i60_16x9, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_2_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_480i60_16x9_rpt, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_4_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1440x480p60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080p60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576p50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576p50_16x9, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576p50_16x9_rpt, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_4_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_720p50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080i50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576i50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_2_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_4_3, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576i50_16x9, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_2_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_576i50_16x9_rpt, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = HDMI_4_TIMES_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU601, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080p50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080p24, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080p25, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_1080p30, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_30, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_25, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_24, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_smpte_24, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4096x2160p25_256x135, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4096x2160p30_256x135, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4096x2160p50_256x135, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4096x2160p60_256x135, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_60, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_50, + .color_prefer = COLORSPACE_RGB444, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_60_y420, + .color_prefer = COLORSPACE_YUV420, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_50_y420, + .color_prefer = COLORSPACE_YUV420, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_smpte_60_y420, + .color_prefer = COLORSPACE_YUV420, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, + { + .VIC = HDMI_4k2k_smpte_50_y420, + .color_prefer = COLORSPACE_YUV420, + .color_depth = COLORDEPTH_24B, + .bar_info = B_BAR_VERT_HORIZ, + .repeat_time = NO_REPEAT, + .aspect_ratio = TV_ASPECT_RATIO_16_9, + .cc = CC_ITU709, + .ss = SS_SCAN_UNDER, + .sc = SC_SCALE_HORIZ_VERT, + }, +}; + +static struct hdmitx_vidpara *hdmi_get_video_param( + enum hdmi_vic VideoCode) +{ + struct hdmitx_vidpara *video_param = NULL; + int i; + int count = ARRAY_SIZE(hdmi_tx_video_params); + + for (i = 0; i < count; i++) { + if (VideoCode == hdmi_tx_video_params[i].VIC) + break; + } + if (i < count) + video_param = &(hdmi_tx_video_params[i]); + return video_param; +} + +static void hdmi_tx_construct_avi_packet( + struct hdmitx_vidpara *video_param, char *AVI_DB) +{ + unsigned char color, bar_info, aspect_ratio, cc, ss, sc, ec = 0; + + ss = video_param->ss; + bar_info = video_param->bar_info; + if (video_param->color == COLORSPACE_YUV444) + color = 2; + else if (video_param->color == COLORSPACE_YUV422) + color = 1; + else + color = 0; + AVI_DB[0] = (ss) | (bar_info << 2) | (1<<4) | (color << 5); + + aspect_ratio = video_param->aspect_ratio; + cc = video_param->cc; + /*HDMI CT 7-24*/ + AVI_DB[1] = 8 | (aspect_ratio << 4) | (cc << 6); + + sc = video_param->sc; + if (video_param->cc == CC_ITU601) + ec = 0; + if (video_param->cc == CC_ITU709) + /*according to CEA-861-D, all other values are reserved*/ + ec = 1; + AVI_DB[2] = (sc) | (ec << 4); + + AVI_DB[3] = video_param->VIC; + if ((video_param->VIC == HDMI_4k2k_30) || + (video_param->VIC == HDMI_4k2k_25) || + (video_param->VIC == HDMI_4k2k_24) || + (video_param->VIC == HDMI_4k2k_smpte_24)) + /*HDMI Spec V1.4b P151*/ + AVI_DB[3] = 0; + + AVI_DB[4] = video_param->repeat_time; +} + +/************************************ + * hdmitx protocol level interface + *************************************/ + +void hdmitx_init_parameters(struct hdmitx_info *info) +{ + memset(info, 0, sizeof(struct hdmitx_info)); + + info->video_out_changing_flag = 1; + + info->audio_flag = 1; + info->audio_info.type = CT_REFER_TO_STREAM; + info->audio_info.format = AF_I2S; + info->audio_info.fs = FS_44K1; + info->audio_info.ss = SS_16BITS; + info->audio_info.channels = CC_2CH; + info->audio_out_changing_flag = 1; + + info->auto_hdcp_ri_flag = 1; + info->hw_sha_calculator_flag = 1; + +} + +/* + * HDMI Identifier = 0x000c03 + * If not, treated as a DVI Device + */ +static int is_dvi_device(struct rx_cap *pRXCap) +{ + if (pRXCap->IEEEOUI != 0x000c03) + return 1; + else + return 0; +} + +void hdmitx_output_rgb(void) +{ + hdmi_output_rgb = 1; +} + +int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) +{ + struct hdmitx_vidpara *param = NULL; + enum hdmi_vic vic; + int i, ret = -1; + unsigned char AVI_DB[32]; + unsigned char AVI_HB[32]; + + AVI_HB[0] = TYPE_AVI_INFOFRAMES; + AVI_HB[1] = AVI_INFOFRAMES_VERSION; + AVI_HB[2] = AVI_INFOFRAMES_LENGTH; + for (i = 0; i < 32; i++) + AVI_DB[i] = 0; + + vic = hdev->HWOp.GetState(hdev, STAT_VIDEO_VIC, 0); + hdmi_print(IMP, SYS "already init VIC = %d Now VIC = %d\n", + vic, VideoCode); + if ((vic != HDMI_Unknown) && (vic == VideoCode)) { + hdev->cur_VIC = vic; + /* return 1; */ + } + + param = hdmi_get_video_param(VideoCode); + hdev->cur_video_param = param; + if (param) { + param->color = param->color_prefer; + if (hdmi_output_rgb) { + param->color = COLORSPACE_RGB444; + } else { + /* HDMI CT 7-24 Pixel Encoding + * YCbCr to YCbCr Sink + */ + switch (hdev->RXCap.native_Mode & 0x30) { + case 0x20:/*bit5==1, then support YCBCR444 + RGB*/ + case 0x30: + param->color = COLORSPACE_YUV444; + break; + case 0x10:/*bit4==1, then support YCBCR422 + RGB*/ + param->color = COLORSPACE_YUV422; + break; + default: + param->color = COLORSPACE_RGB444; + } + /* For Y420 modes */ + switch (VideoCode) { + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + param->color = COLORSPACE_YUV420; + break; + default: + break; + } + if (param->color == COLORSPACE_RGB444) { + hdev->para->cs = hdev->cur_video_param->color; + pr_info("hdmitx: rx edid only support RGB format\n"); + } + + } + if (hdev->HWOp.SetDispMode(hdev) >= 0) { + /* HDMI CT 7-33 DVI Sink, no HDMI VSDB nor any + * other VSDB, No GB or DI expected + * TMDS_MODE[hdmi_config] + * 0: DVI Mode 1: HDMI Mode + */ + if (is_dvi_device(&hdev->RXCap)) { + hdmi_print(1, "Sink is DVI device\n"); + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, DVI_MODE); + } else { + hdmi_print(1, "Sink is HDMI device\n"); + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, HDMI_MODE); + } + hdmi_tx_construct_avi_packet(param, (char *)AVI_DB); + + if ((VideoCode == HDMI_4k2k_30) || + (VideoCode == HDMI_4k2k_25) || + (VideoCode == HDMI_4k2k_24) || + (VideoCode == HDMI_4k2k_smpte_24)) + hdmi_set_vend_spec_infofram(hdev, VideoCode); + else if ((!hdev->flag_3dfp) && (!hdev->flag_3dtb) && + (!hdev->flag_3dss)) + hdmi_set_vend_spec_infofram(hdev, 0); + else + ; + ret = 0; + } + } + hdmitx_set_spd_info(hdev); +#if 0 + hdmitx_special_handler_video(hdev); +#endif + return ret; +} + +static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, + enum hdmi_vic VideoCode) +{ + int i; + unsigned char VEN_DB[6]; + unsigned char VEN_HB[3]; + + VEN_HB[0] = 0x81; + VEN_HB[1] = 0x01; + VEN_HB[2] = 0x5; + + for (i = 0; i < 0x6; i++) + VEN_DB[i] = 0; + VEN_DB[0] = 0x03; + VEN_DB[1] = 0x0c; + VEN_DB[2] = 0x00; + VEN_DB[3] = 0x20; /* 4k x 2k Spec P156 */ + if (VideoCode == 0) { /* For non-4kx2k mode setting */ + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, VEN_HB); + return; + } + if (VideoCode == HDMI_4k2k_30) + VEN_DB[4] = 0x1; + else if (VideoCode == HDMI_4k2k_25) + VEN_DB[4] = 0x2; + else if (VideoCode == HDMI_4k2k_24) + VEN_DB[4] = 0x3; + else if (VideoCode == HDMI_4k2k_smpte_24) + VEN_DB[4] = 0x4; + else + ; + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); +} + +int hdmi_set_3d(struct hdmitx_dev *hdev, int type, unsigned int param) +{ + int i; + unsigned char VEN_DB[6]; + unsigned char VEN_HB[3]; + + VEN_HB[0] = 0x81; + VEN_HB[1] = 0x01; + VEN_HB[2] = 0x6; + if (type == T3D_DISABLE) + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, VEN_HB); + else { + for (i = 0; i < 0x6; i++) + VEN_DB[i] = 0; + VEN_DB[0] = 0x03; + VEN_DB[1] = 0x0c; + VEN_DB[2] = 0x00; + VEN_DB[3] = 0x40; + VEN_DB[4] = type<<4; + VEN_DB[5] = param<<4; + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); + } + return 0; + +} + +/* Set Source Product Descriptor InfoFrame + */ +static void hdmitx_set_spd_info(struct hdmitx_dev *hdev) +{ + unsigned char SPD_DB[25] = {0x00}; + unsigned char SPD_HB[3] = {0x83, 0x1, 0x19}; + unsigned int len = 0; + struct vendor_info_data *vend_data; + + if (hdev->config_data.vend_data) + vend_data = hdev->config_data.vend_data; + else { + hdmi_print(INF, SYS "packet: can\'t get vendor data\n"); + return; + } + if (vend_data->vendor_name) { + len = strlen(vend_data->vendor_name); + strncpy(&SPD_DB[0], vend_data->vendor_name, + (len > 8) ? 8 : len); + } + if (vend_data->product_desc) { + len = strlen(vend_data->product_desc); + strncpy(&SPD_DB[8], vend_data->product_desc, + (len > 16) ? 16 : len); + } + SPD_DB[24] = 0x1; + hdev->HWOp.SetPacket(HDMI_SOURCE_DESCRIPTION, SPD_DB, SPD_HB); +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile new file mode 100644 index 000000000000..14c44c03ac7b --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/Makefile @@ -0,0 +1,2 @@ +obj-y += hdmi_tx_hw.o reg_ops.o sec_ops.o enc_cfg_hw.o hdmi_tx_ddc.o hdcpVerify.o +obj-y += hw_gxbb.o hw_gxtvbb.o hw_gxl.o hw_clk.o diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/common.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/common.h new file mode 100644 index 000000000000..9ada740901ea --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/common.h @@ -0,0 +1,54 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/common.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMITX_HW_COMMON_H__ +#define __HDMITX_HW_COMMON_H__ + +#include +#include +#include "mach_reg.h" +#include "hdmi_tx_reg.h" +/* + * HDMITX HPD HW related operations + */ +enum hpd_op { + HPD_INIT_DISABLE_PULLUP, + HPD_INIT_SET_FILTER, + HPD_IS_HPD_MUXED, + HPD_MUX_HPD, + HPD_UNMUX_HPD, + HPD_READ_HPD_GPIO, +}; + +int hdmitx_hpd_hw_op_gxbb(enum hpd_op cmd); +int read_hpd_gpio_gxbb(void); +int hdmitx_ddc_hw_op_gxbb(enum ddc_op cmd); + +int hdmitx_hpd_hw_op_gxtvbb(enum hpd_op cmd); +int read_hpd_gpio_gxtvbb(void); +int hdmitx_ddc_hw_op_gxtvbb(enum ddc_op cmd); + +int hdmitx_hpd_hw_op_gxl(enum hpd_op cmd); +int read_hpd_gpio_gxl(void); +int hdmitx_ddc_hw_op_gxl(enum ddc_op cmd); +void set_gxl_hpll_clk_out(unsigned int frac_rate, unsigned int clk); +void set_hpll_sspll_gxl(enum hdmi_vic vic); +void set_hpll_od1_gxl(unsigned int div); +void set_hpll_od2_gxl(unsigned int div); +void set_hpll_od3_gxl(unsigned int div); + +#endif diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c new file mode 100644 index 000000000000..b931b413f8eb --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c @@ -0,0 +1,1013 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mach_reg.h" + +#define MREG_END_MARKER 0xFFFF + +static const struct reg_s tvregs_720p[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_VENC_DVI_SETTING, 0x2029}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0019}, + {P_ENCP_VIDEO_YFP1_HTIME, 648}, + {P_ENCP_VIDEO_YFP2_HTIME, 3207}, + {P_ENCP_VIDEO_MAX_PXCNT, 3299}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 80}, + {P_ENCP_VIDEO_HSPULS_END, 240}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 80}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 688}, + {P_ENCP_VIDEO_VSPULS_END, 3248}, + {P_ENCP_VIDEO_VSPULS_BLINE, 4}, + {P_ENCP_VIDEO_VSPULS_ELINE, 8}, + {P_ENCP_VIDEO_HAVON_BEGIN, 648}, + {P_ENCP_VIDEO_HAVON_END, 3207}, + {P_ENCP_VIDEO_VAVON_BLINE, 29}, + {P_ENCP_VIDEO_VAVON_ELINE, 748}, + {P_ENCP_VIDEO_HSO_BEGIN, 256}, + {P_ENCP_VIDEO_HSO_END, 168}, + {P_ENCP_VIDEO_VSO_BEGIN, 168}, + {P_ENCP_VIDEO_VSO_END, 256}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_MAX_LNCNT, 749}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_720p_50hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_VENC_DVI_SETTING, 0x202d}, + {P_ENCP_VIDEO_MAX_PXCNT, 3959}, + {P_ENCP_VIDEO_MAX_LNCNT, 749}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 80}, + {P_ENCP_VIDEO_HSPULS_END, 240}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 80}, + {P_ENCP_VIDEO_HAVON_BEGIN, 648}, + {P_ENCP_VIDEO_HAVON_END, 3207}, + {P_ENCP_VIDEO_HSO_BEGIN, 128}, + {P_ENCP_VIDEO_HSO_END, 208}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 688}, + {P_ENCP_VIDEO_VSPULS_END, 3248}, + {P_ENCP_VIDEO_VSPULS_BLINE, 4}, + {P_ENCP_VIDEO_VSPULS_ELINE, 8}, + {P_ENCP_VIDEO_VAVON_BLINE, 29}, + {P_ENCP_VIDEO_VAVON_ELINE, 748}, + {P_ENCP_VIDEO_VSO_BEGIN, 128}, + {P_ENCP_VIDEO_VSO_END, 128}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_YFP1_HTIME, 648}, + {P_ENCP_VIDEO_YFP2_HTIME, 3207}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0019}, + {P_ENCP_VIDEO_SYNC_MODE, 0x407}, + {P_ENCP_VIDEO_YC_DLY, 0}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_480i[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCI_CFILT_CTRL, 0x12}, + {P_ENCI_CFILT_CTRL2, 0x12}, + {P_VENC_DVI_SETTING, 0}, + {P_ENCI_VIDEO_MODE, 0}, + {P_ENCI_VIDEO_MODE_ADV, 0}, + {P_ENCI_SYNC_HSO_BEGIN, 5}, + {P_ENCI_SYNC_HSO_END, 129}, + {P_ENCI_SYNC_VSO_EVNLN, 0x0003}, + {P_ENCI_SYNC_VSO_ODDLN, 0x0104}, + {P_ENCI_MACV_MAX_AMP, 0x810b}, + {P_VENC_VIDEO_PROG_MODE, 0xf0}, + {P_ENCI_VIDEO_MODE, 0x08}, + {P_ENCI_VIDEO_MODE_ADV, 0x26}, + {P_ENCI_VIDEO_SCH, 0x20}, + {P_ENCI_SYNC_MODE, 0x07}, + {P_ENCI_DBG_PX_RST, 0}, + {P_ENCI_VFIFO2VD_CTL, 0x4e01}, + {P_VPU_VIU_VENC_MUX_CTRL, 0x5}, + {P_ENCI_VFIFO2VD_PIXEL_START, 0xf3,}, + {P_ENCI_VFIFO2VD_PIXEL_END, 0x0693,}, + {P_ENCI_VFIFO2VD_LINE_TOP_START, 0x12,}, + {P_ENCI_VFIFO2VD_LINE_TOP_END, 0x102,}, + {P_ENCI_VFIFO2VD_LINE_BOT_START, 0x13,}, + {P_ENCI_VFIFO2VD_LINE_BOT_END, 0x103,}, + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_480p[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_FILT_CTRL, 0x2052}, + {P_VENC_DVI_SETTING, 0x21}, + {P_ENCP_VIDEO_MODE, 0x4000}, + {P_ENCP_VIDEO_MODE_ADV, 9}, + {P_ENCP_VIDEO_YFP1_HTIME, 244}, + {P_ENCP_VIDEO_YFP2_HTIME, 1630}, + {P_ENCP_VIDEO_MAX_PXCNT, 1715}, + {P_ENCP_VIDEO_MAX_LNCNT, 524}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 0x22}, + {P_ENCP_VIDEO_HSPULS_END, 0xa0}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 88}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 0}, + {P_ENCP_VIDEO_VSPULS_END, 1589}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 5}, + {P_ENCP_VIDEO_HAVON_BEGIN, 249}, + {P_ENCP_VIDEO_HAVON_END, 1689}, + {P_ENCP_VIDEO_VAVON_BLINE, 42}, + {P_ENCP_VIDEO_VAVON_ELINE, 521}, + {P_ENCP_VIDEO_SYNC_MODE, 0x07}, + {P_VENC_VIDEO_PROG_MODE, 0x0}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x3}, + {P_ENCP_VIDEO_HSO_END, 0x5}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x3}, + {P_ENCP_VIDEO_VSO_END, 0x5}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_SY_VAL, 8}, + {P_ENCP_VIDEO_SY2_VAL, 0x1d8}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_DACSEL_0, 0x3102}, + {P_ENCP_DACSEL_1, 0x0054}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_576i[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_VENC_DVI_SETTING, 0}, + {P_ENCI_VIDEO_MODE, 0}, + {P_ENCI_VIDEO_MODE_ADV, 0}, + {P_ENCI_SYNC_HSO_BEGIN, 3}, + {P_ENCI_SYNC_HSO_END, 129}, + {P_ENCI_SYNC_VSO_EVNLN, 0x0003}, + {P_ENCI_SYNC_VSO_ODDLN, 0x0104}, + {P_ENCI_MACV_MAX_AMP, 0x8107}, + {P_VENC_VIDEO_PROG_MODE, 0xff}, + {P_ENCI_VIDEO_MODE, 0x13}, + {P_ENCI_VIDEO_MODE_ADV, 0x26}, + {P_ENCI_VIDEO_SCH, 0x28}, + {P_ENCI_SYNC_MODE, 0x07}, + {P_ENCI_YC_DELAY, 0x333}, + {P_ENCI_VFIFO2VD_PIXEL_START, 0x010b}, + {P_ENCI_VFIFO2VD_PIXEL_END, 0x06ab}, + {P_ENCI_VFIFO2VD_LINE_TOP_START, 0x0016}, + {P_ENCI_VFIFO2VD_LINE_TOP_END, 0x0136}, + {P_ENCI_VFIFO2VD_LINE_BOT_START, 0x0017}, + {P_ENCI_VFIFO2VD_LINE_BOT_END, 0x0137}, + {P_ENCI_DBG_PX_RST, 0}, + {P_ENCI_VFIFO2VD_CTL, 0x4e01}, + {P_VPU_VIU_VENC_MUX_CTRL, 0x5}, + {P_ENCI_VFIFO2VD_PIXEL_START, 0x010b}, + {P_ENCI_VFIFO2VD_PIXEL_END, 0x06ab}, + {P_ENCI_VFIFO2VD_LINE_TOP_START, 0x0016}, + {P_ENCI_VFIFO2VD_LINE_TOP_END, 0x0136}, + {P_ENCI_VFIFO2VD_LINE_BOT_START, 0x0017}, + {P_ENCI_VFIFO2VD_LINE_BOT_END, 0x0137}, + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_576p[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_FILT_CTRL, 0x52}, + {P_VENC_DVI_SETTING, 0x21}, + {P_ENCP_VIDEO_MODE, 0x4000}, + {P_ENCP_VIDEO_MODE_ADV, 9}, + {P_ENCP_VIDEO_YFP1_HTIME, 235}, + {P_ENCP_VIDEO_YFP2_HTIME, 1674}, + {P_ENCP_VIDEO_MAX_PXCNT, 1727}, + {P_ENCP_VIDEO_MAX_LNCNT, 624}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 0}, + {P_ENCP_VIDEO_HSPULS_END, 0x80}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 88}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 0}, + {P_ENCP_VIDEO_VSPULS_END, 1599}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 235}, + {P_ENCP_VIDEO_HAVON_END, 1674}, + {P_ENCP_VIDEO_VAVON_BLINE, 44}, + {P_ENCP_VIDEO_VAVON_ELINE, 619}, + {P_ENCP_VIDEO_SYNC_MODE, 0x07}, + {P_VENC_VIDEO_PROG_MODE, 0x0}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x80}, + {P_ENCP_VIDEO_HSO_END, 0x0}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x0}, + {P_ENCP_VIDEO_VSO_END, 0x5}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_SY_VAL, 8}, + {P_ENCP_VIDEO_SY2_VAL, 0x1d8}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080i[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_VENC_DVI_SETTING, 0x2029}, + {P_ENCP_VIDEO_MAX_PXCNT, 4399}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 88}, + {P_ENCP_VIDEO_HSPULS_END, 264}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 88}, + {P_ENCP_VIDEO_HAVON_BEGIN, 516}, + {P_ENCP_VIDEO_HAVON_END, 4355}, + {P_ENCP_VIDEO_HSO_BEGIN, 264}, + {P_ENCP_VIDEO_HSO_END, 176}, + {P_ENCP_VIDEO_EQPULS_BEGIN, 2288}, + {P_ENCP_VIDEO_EQPULS_END, 2464}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 440}, + {P_ENCP_VIDEO_VSPULS_END, 2200}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_EQPULS_BLINE, 0}, + {P_ENCP_VIDEO_EQPULS_ELINE, 4}, + {P_ENCP_VIDEO_VAVON_BLINE, 20}, + {P_ENCP_VIDEO_VAVON_ELINE, 559}, + {P_ENCP_VIDEO_VSO_BEGIN, 88}, + {P_ENCP_VIDEO_VSO_END, 88}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_YFP1_HTIME, 516}, + {P_ENCP_VIDEO_YFP2_HTIME, 4355}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCP_VIDEO_OFLD_VOAV_OFST, 0x11}, + {P_ENCP_VIDEO_MODE, 0x5ffc}, + {P_ENCP_VIDEO_MODE_ADV, 0x0019}, + {P_ENCP_VIDEO_SYNC_MODE, 0x207}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080i_50hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_VENC_DVI_SETTING, 0x202d}, + {P_ENCP_VIDEO_MAX_PXCNT, 5279}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 88}, + {P_ENCP_VIDEO_HSPULS_END, 264}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 88}, + {P_ENCP_VIDEO_HAVON_BEGIN, 526}, + {P_ENCP_VIDEO_HAVON_END, 4365}, + {P_ENCP_VIDEO_HSO_BEGIN, 142}, + {P_ENCP_VIDEO_HSO_END, 230}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 440}, + {P_ENCP_VIDEO_VSPULS_END, 2200}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_VAVON_BLINE, 20}, + {P_ENCP_VIDEO_VAVON_ELINE, 559}, + {P_ENCP_VIDEO_VSO_BEGIN, 142}, + {P_ENCP_VIDEO_VSO_END, 142}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_YFP1_HTIME, 526}, + {P_ENCP_VIDEO_YFP2_HTIME, 4365}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCP_VIDEO_OFLD_VOAV_OFST, 0x11}, + {P_ENCP_VIDEO_MODE, 0x5ffc}, + {P_ENCP_VIDEO_MODE_ADV, 0x0019}, + {P_ENCP_VIDEO_SYNC_MODE, 0x7}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080p[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1052}, + {P_VENC_DVI_SETTING, 0x0001}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0018}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 2060}, + {P_ENCP_VIDEO_MAX_PXCNT, 2199}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 2067}, + {P_ENCP_VIDEO_VAVON_BLINE, 41}, + {P_ENCP_VIDEO_VAVON_ELINE, 1120}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100}, + {P_ENCP_VIDEO_VSO_END, 2164}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080p_30hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1052}, + {P_VENC_DVI_SETTING, 0x0001}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0018}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 2060}, + {P_ENCP_VIDEO_MAX_PXCNT, 2199}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 2067}, + {P_ENCP_VIDEO_VAVON_BLINE, 41}, + {P_ENCP_VIDEO_VAVON_ELINE, 1120}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100}, + {P_ENCP_VIDEO_VSO_END, 2164}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080p_50hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_VENC_DVI_SETTING, 0x000d}, + {P_ENCP_VIDEO_MAX_PXCNT, 2639}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 44}, + {P_ENCP_VIDEO_HSPULS_END, 132}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_HAVON_BEGIN, 271}, + {P_ENCP_VIDEO_HAVON_END, 2190}, + {P_ENCP_VIDEO_HSO_BEGIN, 79}, + {P_ENCP_VIDEO_HSO_END, 123}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 220}, + {P_ENCP_VIDEO_VSPULS_END, 2140}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_EQPULS_BLINE, 0}, + {P_ENCP_VIDEO_EQPULS_ELINE, 4}, + {P_ENCP_VIDEO_VAVON_BLINE, 41}, + {P_ENCP_VIDEO_VAVON_ELINE, 1120}, + {P_ENCP_VIDEO_VSO_BEGIN, 79}, + {P_ENCP_VIDEO_VSO_END, 79}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_YFP1_HTIME, 271}, + {P_ENCP_VIDEO_YFP2_HTIME, 2190}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0018}, + {P_ENCP_VIDEO_SYNC_MODE, 0x7}, + {P_ENCP_VIDEO_YC_DLY, 0}, + {P_ENCP_VIDEO_RGB_CTRL, 2}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_1080p_24hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1052}, + {P_VENC_DVI_SETTING, 0x000d}, + {P_ENCP_VIDEO_MAX_PXCNT, 2749}, + {P_ENCP_VIDEO_MAX_LNCNT, 1124}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 44}, + {P_ENCP_VIDEO_HSPULS_END, 132}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_HAVON_BEGIN, 271}, + {P_ENCP_VIDEO_HAVON_END, 2190}, + {P_ENCP_VIDEO_HSO_BEGIN, 79}, + {P_ENCP_VIDEO_HSO_END, 123}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 220}, + {P_ENCP_VIDEO_VSPULS_END, 2140}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_EQPULS_BLINE, 0}, + {P_ENCP_VIDEO_EQPULS_ELINE, 4}, + {P_ENCP_VIDEO_VAVON_BLINE, 41}, + {P_ENCP_VIDEO_VAVON_ELINE, 1120}, + {P_ENCP_VIDEO_VSO_BEGIN, 79}, + {P_ENCP_VIDEO_VSO_END, 79}, + {P_ENCP_VIDEO_VSO_BLINE, 0}, + {P_ENCP_VIDEO_VSO_ELINE, 5}, + {P_ENCP_VIDEO_YFP1_HTIME, 271}, + {P_ENCP_VIDEO_YFP2_HTIME, 2190}, + {P_VENC_VIDEO_PROG_MODE, 0x100}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0018}, + {P_ENCP_VIDEO_SYNC_MODE, 0x7}, + {P_ENCP_VIDEO_YC_DLY, 0}, + {P_ENCP_VIDEO_RGB_CTRL, 2}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_30hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0008}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 140+3840}, + {P_ENCP_VIDEO_MAX_PXCNT, 3840+560-1}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156+1920}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059+1920}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 3987}, + {P_ENCP_VIDEO_VAVON_BLINE, 89}, + {P_ENCP_VIDEO_VAVON_ELINE, 2248}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156+1920}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100+1920}, + {P_ENCP_VIDEO_VSO_END, 2164+1920}, + {P_ENCP_VIDEO_VSO_BLINE, 51}, + {P_ENCP_VIDEO_VSO_ELINE, 53}, + {P_ENCP_VIDEO_MAX_LNCNT, 2249}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_25hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0008}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 140+3840}, + {P_ENCP_VIDEO_MAX_PXCNT, 3840+1440-1}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156+1920}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059+1920}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 3987}, + {P_ENCP_VIDEO_VAVON_BLINE, 89}, + {P_ENCP_VIDEO_VAVON_ELINE, 2248}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156+1920}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100+1920}, + {P_ENCP_VIDEO_VSO_END, 2164+1920}, + {P_ENCP_VIDEO_VSO_BLINE, 51}, + {P_ENCP_VIDEO_VSO_ELINE, 53}, + {P_ENCP_VIDEO_MAX_LNCNT, 2249}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_24hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0008}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 140+3840}, + {P_ENCP_VIDEO_MAX_PXCNT, 3840+1660-1}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156+1920}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059+1920}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 3987}, + {P_ENCP_VIDEO_VAVON_BLINE, 89}, + {P_ENCP_VIDEO_VAVON_ELINE, 2248}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156+1920}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100+1920}, + {P_ENCP_VIDEO_VSO_END, 2164+1920}, + {P_ENCP_VIDEO_VSO_BLINE, 51}, + {P_ENCP_VIDEO_VSO_ELINE, 53}, + {P_ENCP_VIDEO_MAX_LNCNT, 2249}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_smpte[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040}, + {P_ENCP_VIDEO_MODE_ADV, 0x0008}, + {P_ENCP_VIDEO_YFP1_HTIME, 140}, + {P_ENCP_VIDEO_YFP2_HTIME, 140+3840+256}, + {P_ENCP_VIDEO_MAX_PXCNT, 4096+1404-1}, + {P_ENCP_VIDEO_HSPULS_BEGIN, 2156+1920}, + {P_ENCP_VIDEO_HSPULS_END, 44}, + {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, + {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, + {P_ENCP_VIDEO_VSPULS_END, 2059+1920}, + {P_ENCP_VIDEO_VSPULS_BLINE, 0}, + {P_ENCP_VIDEO_VSPULS_ELINE, 4}, + {P_ENCP_VIDEO_HAVON_BEGIN, 148}, + {P_ENCP_VIDEO_HAVON_END, 3987+256}, + {P_ENCP_VIDEO_VAVON_BLINE, 89}, + {P_ENCP_VIDEO_VAVON_ELINE, 2248}, + {P_ENCP_VIDEO_HSO_BEGIN, 44}, + {P_ENCP_VIDEO_HSO_END, 2156+1920+256}, + {P_ENCP_VIDEO_VSO_BEGIN, 2100+1920+256}, + {P_ENCP_VIDEO_VSO_END, 2164+1920+256}, + {P_ENCP_VIDEO_VSO_BLINE, 51}, + {P_ENCP_VIDEO_VSO_ELINE, 53}, + {P_ENCP_VIDEO_MAX_LNCNT, 2249}, + {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_smpte_25hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x149F,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xD8,}, + {P_ENCP_VIDEO_HAVON_END, 0x10D7,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x52,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C1,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x58,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_smpte_30hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x112F,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xD8,}, + {P_ENCP_VIDEO_HAVON_END, 0x10D7,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x52,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C1,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x58,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_smpte_50hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x149F,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xD8,}, + {P_ENCP_VIDEO_HAVON_END, 0x10D7,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x52,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C1,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x58,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_4k2k_smpte_60hz[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x112F,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xD8,}, + {P_ENCP_VIDEO_HAVON_END, 0x10D7,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x52,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C1,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x58,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, + {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, + {P_ENCP_VIDEO_EN, 1}, + {P_ENCI_VIDEO_EN, 0}, + {MREG_END_MARKER, 0}, +}; +struct vic_tvregs_set { + enum hdmi_vic vic; + const struct reg_s *reg_setting; +}; + +/* Using HDMI VIC as index */ +static struct vic_tvregs_set tvregsTab[] = { + {HDMI_720x480i60_16x9, tvregs_480i}, + {HDMI_2880x480i60_16x9, tvregs_480i}, + {HDMI_720x480p60_16x9, tvregs_480p}, + {HDMI_2880x240p60_16x9, tvregs_480p}, + {HDMI_720x576i50_16x9, tvregs_576i}, + {HDMI_2880x576i50_16x9, tvregs_576i}, + {HDMI_720x576p50_16x9, tvregs_576p}, + {HDMI_2880x576p50_16x9, tvregs_576p}, + {HDMI_1280x720p60_16x9, tvregs_720p}, + {HDMI_1920x1080i60_16x9, tvregs_1080i}, + {HDMI_1920x1080p60_16x9, tvregs_1080p}, + {HDMI_1280x720p50_16x9, tvregs_720p_50hz}, + {HDMI_1920x1080i50_16x9, tvregs_1080i_50hz}, + {HDMI_1920x1080p50_16x9, tvregs_1080p_50hz}, + {HDMI_1920x1080p25_16x9, tvregs_1080p_50hz}, + {HDMI_1920x1080p30_16x9, tvregs_1080p_30hz}, + {HDMI_1920x1080p24_16x9, tvregs_1080p_24hz}, + {HDMI_3840x2160p30_16x9, tvregs_4k2k_30hz}, + {HDMI_3840x2160p25_16x9, tvregs_4k2k_25hz}, + {HDMI_3840x2160p24_16x9, tvregs_4k2k_24hz}, + {HDMI_4096x2160p24_256x135, tvregs_4k2k_smpte}, + {HDMI_4096x2160p25_256x135, tvregs_4k2k_smpte_25hz}, + {HDMI_4096x2160p30_256x135, tvregs_4k2k_smpte_30hz}, + {HDMI_4096x2160p50_256x135, tvregs_4k2k_smpte_50hz}, + {HDMI_4096x2160p60_256x135, tvregs_4k2k_smpte_60hz}, + {HDMI_4096x2160p60_256x135_Y420, tvregs_4k2k_smpte_60hz}, + {HDMI_4096x2160p50_256x135_Y420, tvregs_4k2k_smpte_50hz}, + {HDMI_3840x2160p60_16x9, tvregs_4k2k_30hz}, + {HDMI_3840x2160p50_16x9, tvregs_4k2k_25hz}, + {HDMI_3840x2160p60_16x9_Y420, tvregs_4k2k_30hz}, + {HDMI_3840x2160p50_16x9_Y420, tvregs_4k2k_25hz}, +}; + +static inline void setreg(const struct reg_s *r) +{ + hd_write_reg(r->reg, r->val); + /* printk("[0x%x] = 0x%x\n", r->reg, r->val); */ +} + +static const struct reg_s *tvregs_setting_mode(enum hdmi_vic vic) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(tvregsTab); i++) { + if (vic == tvregsTab[i].vic) + return tvregsTab[i].reg_setting; + } + return NULL; +} + +void set_vmode_enc_hw(enum hdmi_vic vic) +{ + const struct reg_s *s = tvregs_setting_mode(vic); + /* Turn off VDAC, no need any more for HDMITX */ + hd_set_reg_bits(P_VENC_VDAC_SETTING, 0x1f, 0, 5); + + if (s) { + pr_info("hdmitx: set enc for VIC: %d\n", vic); + while (s->reg != MREG_END_MARKER) + setreg(s++); + } else + pr_info("hdmitx: not find VIC: %d\n", vic); +} + +/* + * For 3D FramePacket Setting + */ +static const struct reg_s tvregs_3dfp_1080p60[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x897,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, + {P_ENCP_VIDEO_HAVON_END, 0x83F,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x29,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C5,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x2C,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0x5,}, + {P_ENCP_DVI_HSO_BEGIN, 0x2,}, + {P_ENCP_DVI_HSO_END, 0x2E,}, + {P_ENCP_DVI_VSO_BLINE_EVN, 0x0,}, + {P_ENCP_DVI_VSO_BLINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_ELINE_EVN, 0x5,}, + {P_ENCP_DVI_VSO_ELINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_BEGIN_EVN, 0x2,}, + {P_ENCP_DVI_VSO_BEGIN_ODD, 0x0,}, + {P_ENCP_DVI_VSO_END_EVN, 0x2,}, + {P_ENCP_DVI_VSO_END_ODD, 0x0,}, + {P_ENCP_DE_H_BEGIN, 0xC2,}, + {P_ENCP_DE_H_END, 0x842,}, + {P_ENCP_DE_V_BEGIN_EVEN, 0x29,}, + {P_ENCP_DE_V_END_EVEN, 0x8C6,}, + {P_ENCP_DE_V_BEGIN_ODD, 0x0,}, + {P_ENCP_DE_V_END_ODD, 0x0,}, + + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_3dfp_1080p24[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xABD,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, + {P_ENCP_VIDEO_HAVON_END, 0x83F,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x29,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C5,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x2C,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0x5,}, + {P_ENCP_DVI_HSO_BEGIN, 0x2,}, + {P_ENCP_DVI_HSO_END, 0x2E,}, + {P_ENCP_DVI_VSO_BLINE_EVN, 0x0,}, + {P_ENCP_DVI_VSO_BLINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_ELINE_EVN, 0x5,}, + {P_ENCP_DVI_VSO_ELINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_BEGIN_EVN, 0x2,}, + {P_ENCP_DVI_VSO_BEGIN_ODD, 0x0,}, + {P_ENCP_DVI_VSO_END_EVN, 0x2,}, + {P_ENCP_DVI_VSO_END_ODD, 0x0,}, + {P_ENCP_DE_H_BEGIN, 0xC2,}, + {P_ENCP_DE_H_END, 0x842,}, + {P_ENCP_DE_V_BEGIN_EVEN, 0x29,}, + {P_ENCP_DE_V_END_EVEN, 0x8C6,}, + {P_ENCP_DE_V_BEGIN_ODD, 0x0,}, + {P_ENCP_DE_V_END_ODD, 0x0,}, + + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_3dfp_1080p50[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xA4F,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, + {P_ENCP_VIDEO_HAVON_END, 0x83F,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x29,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x8C5,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x2C,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0x5,}, + {P_ENCP_DVI_HSO_BEGIN, 0x2,}, + {P_ENCP_DVI_HSO_END, 0x2E,}, + {P_ENCP_DVI_VSO_BLINE_EVN, 0x0,}, + {P_ENCP_DVI_VSO_BLINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_ELINE_EVN, 0x5,}, + {P_ENCP_DVI_VSO_ELINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_BEGIN_EVN, 0x2,}, + {P_ENCP_DVI_VSO_BEGIN_ODD, 0x0,}, + {P_ENCP_DVI_VSO_END_EVN, 0x2,}, + {P_ENCP_DVI_VSO_END_ODD, 0x0,}, + {P_ENCP_DE_H_BEGIN, 0xC2,}, + {P_ENCP_DE_H_END, 0x842,}, + {P_ENCP_DE_V_BEGIN_EVEN, 0x29,}, + {P_ENCP_DE_V_END_EVEN, 0x8C6,}, + {P_ENCP_DE_V_BEGIN_ODD, 0x0,}, + {P_ENCP_DE_V_END_ODD, 0x0,}, + + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_3dfp_720p50[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x7BB,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x5DB,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0x104,}, + {P_ENCP_VIDEO_HAVON_END, 0x603,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x19,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x5D6,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x28,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0x5,}, + {P_ENCP_DVI_HSO_BEGIN, 0x2,}, + {P_ENCP_DVI_HSO_END, 0x2A,}, + {P_ENCP_DVI_VSO_BLINE_EVN, 0x0,}, + {P_ENCP_DVI_VSO_BLINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_ELINE_EVN, 0x5,}, + {P_ENCP_DVI_VSO_ELINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_BEGIN_EVN, 0x2,}, + {P_ENCP_DVI_VSO_BEGIN_ODD, 0x0,}, + {P_ENCP_DVI_VSO_END_EVN, 0x2,}, + {P_ENCP_DVI_VSO_END_ODD, 0x0,}, + {P_ENCP_DE_H_BEGIN, 0x106,}, + {P_ENCP_DE_H_END, 0x606,}, + {P_ENCP_DE_V_BEGIN_EVEN, 0x19,}, + {P_ENCP_DE_V_END_EVEN, 0x5D7,}, + {P_ENCP_DE_V_BEGIN_ODD, 0x0,}, + {P_ENCP_DE_V_END_ODD, 0x0,}, + + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +static const struct reg_s tvregs_3dfp_720p60[] = { + {P_ENCP_VIDEO_EN, 0}, + {P_ENCI_VIDEO_EN, 0}, + + {P_ENCP_VIDEO_MODE, 0x4040,}, + {P_ENCP_VIDEO_MODE_ADV, 0x18,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0x671,}, + {P_ENCP_VIDEO_MAX_LNCNT, 0x5DB,}, + {P_ENCP_VIDEO_HAVON_BEGIN, 0x104,}, + {P_ENCP_VIDEO_HAVON_END, 0x603,}, + {P_ENCP_VIDEO_VAVON_BLINE, 0x19,}, + {P_ENCP_VIDEO_VAVON_ELINE, 0x5D6,}, + {P_ENCP_VIDEO_HSO_BEGIN, 0x0,}, + {P_ENCP_VIDEO_HSO_END, 0x28,}, + {P_ENCP_VIDEO_VSO_BEGIN, 0x1E,}, + {P_ENCP_VIDEO_VSO_END, 0x32,}, + {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, + {P_ENCP_VIDEO_VSO_ELINE, 0x5,}, + {P_ENCP_DVI_HSO_BEGIN, 0x2,}, + {P_ENCP_DVI_HSO_END, 0x2A,}, + {P_ENCP_DVI_VSO_BLINE_EVN, 0x0,}, + {P_ENCP_DVI_VSO_BLINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_ELINE_EVN, 0x5,}, + {P_ENCP_DVI_VSO_ELINE_ODD, 0x0,}, + {P_ENCP_DVI_VSO_BEGIN_EVN, 0x2,}, + {P_ENCP_DVI_VSO_BEGIN_ODD, 0x0,}, + {P_ENCP_DVI_VSO_END_EVN, 0x2,}, + {P_ENCP_DVI_VSO_END_ODD, 0x0,}, + {P_ENCP_DE_H_BEGIN, 0x106,}, + {P_ENCP_DE_H_END, 0x606,}, + {P_ENCP_DE_V_BEGIN_EVEN, 0x19,}, + {P_ENCP_DE_V_END_EVEN, 0x5D7,}, + {P_ENCP_DE_V_BEGIN_ODD, 0x0,}, + {P_ENCP_DE_V_END_ODD, 0x0,}, + + {P_ENCI_VIDEO_EN, 0}, + {P_ENCP_VIDEO_EN, 1}, + {MREG_END_MARKER, 0}, +}; + +/* Using HDMI VIC as index */ +static struct vic_tvregs_set tvregsTab_3dfp[] = { + {HDMI_1920x1080p60_16x9, tvregs_3dfp_1080p60}, + {HDMI_1920x1080p30_16x9, tvregs_3dfp_1080p60}, + {HDMI_1920x1080p50_16x9, tvregs_3dfp_1080p50}, + {HDMI_1920x1080p25_16x9, tvregs_3dfp_1080p50}, + {HDMI_1920x1080p24_16x9, tvregs_3dfp_1080p24}, + {HDMI_1280x720p60_16x9, tvregs_3dfp_720p60}, + {HDMI_1280x720p50_16x9, tvregs_3dfp_720p50}, +}; + +static const struct reg_s *tvregs_3dfp_setting_mode(enum hdmi_vic vic) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(tvregsTab_3dfp); i++) { + if (vic == tvregsTab_3dfp[i].vic) + return tvregsTab_3dfp[i].reg_setting; + } + return NULL; +} + +void set_vmode_3dfp_enc_hw(enum hdmi_vic vic) +{ + const struct reg_s *s = tvregs_3dfp_setting_mode(vic); + + if (s) { + pr_info("hdmitx: set 3dfp enc for VIC: %d\n", vic); + while (s->reg != MREG_END_MARKER) + setreg(s++); + } else + pr_info("hdmitx: not find VIC: %d\n", vic); +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h new file mode 100644 index 000000000000..5fe69afde3a1 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h @@ -0,0 +1,45 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcp.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef HDCP_H_ +#define HDCP_H_ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +enum hdcp_status_t { + HDCP_IDLE = 0, + HDCP_KSV_LIST_READY, + HDCP_ERR_KSV_LIST_NOT_VALID, + HDCP_KSV_LIST_ERR_DEPTH_EXCEEDED, + HDCP_KSV_LIST_ERR_MEM_ACCESS, + HDCP_ENGAGED, + HDCP_FAILED +}; + +/* HDCP Interrupt bit fields */ +#define INT_KSV_ACCESS (0) +#define INT_KSV_SHA1 (1) +#define INT_HDCP_FAIL (6) +#define INT_HDCP_ENGAGED (7) + +#endif /* HDCP_H_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c new file mode 100644 index 000000000000..ebe66fd8f70d --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c @@ -0,0 +1,600 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "hdcpVerify.h" + +#define SIZE (160/8) +#define KSIZE (1024/8) + +void sha_Reset(struct sha_t *sha) +{ + size_t i = 0; + + sha->mIndex = 0; + sha->mComputed = FALSE; + sha->mCorrupted = FALSE; + for (i = 0; i < sizeof(sha->mLength); i++) + sha->mLength[i] = 0; + sha->mDigest[0] = 0x67452301; + sha->mDigest[1] = 0xEFCDAB89; + sha->mDigest[2] = 0x98BADCFE; + sha->mDigest[3] = 0x10325476; + sha->mDigest[4] = 0xC3D2E1F0; +} + +int sha_Result(struct sha_t *sha) +{ + if (sha->mCorrupted == TRUE) + return FALSE; + if (sha->mComputed == FALSE) { + sha_PadMessage(sha); + sha->mComputed = TRUE; + } + return TRUE; +} + +void sha_Input(struct sha_t *sha, const uint8_t *data, size_t size) +{ + int i = 0; + unsigned int j = 0; + int rc = TRUE; + + if (data == 0 || size == 0) { + pr_info("invalid input data"); + return; + } + if (sha->mComputed == TRUE || sha->mCorrupted == TRUE) { + sha->mCorrupted = TRUE; + return; + } + while (size-- && sha->mCorrupted == FALSE) { + sha->mBlock[sha->mIndex++] = *data; + + for (i = 0; i < 8; i++) { + rc = TRUE; + for (j = 0; j < sizeof(sha->mLength); j++) { + sha->mLength[j]++; + if (sha->mLength[j] != 0) { + rc = FALSE; + break; + } + } + sha->mCorrupted = (sha->mCorrupted == TRUE || + rc == TRUE) ? TRUE : FALSE; + } + /* if corrupted then message is too long */ + if (sha->mIndex == 64) + sha_ProcessBlock(sha); + data++; + } +} + +void sha_ProcessBlock(struct sha_t *sha) +{ +#define shaCircularShift(bits, word) \ + ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits)))) + + const unsigned int K[] = { + /* constants defined in SHA-1 */ + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; + unsigned int W[80]; /* word sequence */ + unsigned int A, B, C, D, E; /* word buffers */ + unsigned int temp = 0; + int t = 0; + + /* Initialize the first 16 words in the array W */ + for (t = 0; t < 80; t++) { + if (t < 16) { + W[t] = ((unsigned int) sha->mBlock[t * 4 + 0]) << 24; + W[t] |= ((unsigned int) sha->mBlock[t * 4 + 1]) << 16; + W[t] |= ((unsigned int) sha->mBlock[t * 4 + 2]) << 8; + W[t] |= ((unsigned int) sha->mBlock[t * 4 + 3]) << 0; + } else + W[t] = shaCircularShift(1, + W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = sha->mDigest[0]; + B = sha->mDigest[1]; + C = sha->mDigest[2]; + D = sha->mDigest[3]; + E = sha->mDigest[4]; + + for (t = 0; t < 80; t++) { + temp = shaCircularShift(5, A); + if (t < 20) + temp += ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + else if (t < 40) + temp += (B ^ C ^ D) + E + W[t] + K[1]; + else if (t < 60) + temp += ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + else + temp += (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = shaCircularShift(30, B); + B = A; + A = (temp & 0xFFFFFFFF); + } + + sha->mDigest[0] = (sha->mDigest[0] + A) & 0xFFFFFFFF; + sha->mDigest[1] = (sha->mDigest[1] + B) & 0xFFFFFFFF; + sha->mDigest[2] = (sha->mDigest[2] + C) & 0xFFFFFFFF; + sha->mDigest[3] = (sha->mDigest[3] + D) & 0xFFFFFFFF; + sha->mDigest[4] = (sha->mDigest[4] + E) & 0xFFFFFFFF; + + sha->mIndex = 0; +} + +void sha_PadMessage(struct sha_t *sha) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (sha->mIndex > 55) { + sha->mBlock[sha->mIndex++] = 0x80; + while (sha->mIndex < 64) + sha->mBlock[sha->mIndex++] = 0; + sha_ProcessBlock(sha); + while (sha->mIndex < 56) + sha->mBlock[sha->mIndex++] = 0; + } else { + sha->mBlock[sha->mIndex++] = 0x80; + while (sha->mIndex < 56) + sha->mBlock[sha->mIndex++] = 0; + } + + /* Store the message length as the last 8 octets */ + sha->mBlock[56] = sha->mLength[7]; + sha->mBlock[57] = sha->mLength[6]; + sha->mBlock[58] = sha->mLength[5]; + sha->mBlock[59] = sha->mLength[4]; + sha->mBlock[60] = sha->mLength[3]; + sha->mBlock[61] = sha->mLength[2]; + sha->mBlock[62] = sha->mLength[1]; + sha->mBlock[63] = sha->mLength[0]; + + sha_ProcessBlock(sha); +} + +int hdcpVerify_DSA(const uint8_t *M, size_t n, const uint8_t *r, + const uint8_t *s) +{ + int i = 0; + struct sha_t sha; + static const uint8_t q[] = { + 0xE7, 0x08, 0xC7, 0xF9, 0x4D, 0x3F, 0xEF, 0x97, + 0xE2, 0x14, 0x6D, 0xCD, 0x6A, 0xB5, 0x6D, 0x5E, + 0xCE, 0xF2, 0x8A, 0xEE }; + static const uint8_t p[] = { + 0x27, 0x75, 0x28, 0xF3, 0x2B, 0x80, 0x59, 0x8C, + 0x11, 0xC2, 0xED, 0x46, 0x1C, 0x95, 0x39, 0x2A, + 0x54, 0x19, 0x89, 0x96, 0xFD, 0x49, 0x8A, 0x02, + 0x3B, 0x73, 0x75, 0x32, 0x14, 0x9C, 0x7B, 0x5C, + 0x49, 0x20, 0x98, 0xB9, 0x07, 0x32, 0x3F, 0xA7, + 0x30, 0x15, 0x72, 0xB3, 0x09, 0x55, 0x71, 0x10, + 0x3A, 0x4C, 0x97, 0xD1, 0xBC, 0xA0, 0x04, 0xF4, + 0x35, 0xCF, 0x47, 0x54, 0x0E, 0xA7, 0x2B, 0xE5, + 0x83, 0xB9, 0xC6, 0xD4, 0x47, 0xC7, 0x44, 0xB8, + 0x67, 0x76, 0x7C, 0xAE, 0x0C, 0xDC, 0x34, 0x4F, + 0x4B, 0x9E, 0x96, 0x1D, 0x82, 0x84, 0xD2, 0xA0, + 0xDC, 0xE0, 0x00, 0xF5, 0x64, 0xA1, 0x7F, 0x8E, + 0xFF, 0x58, 0x70, 0x6A, 0xC3, 0x4F, 0xA2, 0xA1, + 0xB8, 0xC7, 0x52, 0x5A, 0x35, 0x5B, 0x39, 0x17, + 0x6B, 0x78, 0x43, 0x93, 0xF7, 0x75, 0x8D, 0x01, + 0xB7, 0x61, 0x17, 0xFD, 0xB2, 0xF5, 0xC3, 0xD3 }; + static const uint8_t g[] = { + 0xD9, 0x0B, 0xBA, 0xC2, 0x42, 0x24, 0x46, 0x69, + 0x5B, 0x40, 0x67, 0x2F, 0x5B, 0x18, 0x3F, 0xB9, + 0xE8, 0x6F, 0x21, 0x29, 0xAC, 0x7D, 0xFA, 0x51, + 0xC2, 0x9D, 0x4A, 0xAB, 0x8A, 0x9B, 0x8E, 0xC9, + 0x42, 0x42, 0xA5, 0x1D, 0xB2, 0x69, 0xAB, 0xC8, + 0xE3, 0xA5, 0xC8, 0x81, 0xBE, 0xB6, 0xA0, 0xB1, + 0x7F, 0xBA, 0x21, 0x2C, 0x64, 0x35, 0xC8, 0xF7, + 0x5F, 0x58, 0x78, 0xF7, 0x45, 0x29, 0xDD, 0x92, + 0x9E, 0x79, 0x3D, 0xA0, 0x0C, 0xCD, 0x29, 0x0E, + 0xA9, 0xE1, 0x37, 0xEB, 0xBF, 0xC6, 0xED, 0x8E, + 0xA8, 0xFF, 0x3E, 0xA8, 0x7D, 0x97, 0x62, 0x51, + 0xD2, 0xA9, 0xEC, 0xBD, 0x4A, 0xB1, 0x5D, 0x8F, + 0x11, 0x86, 0x27, 0xCD, 0x66, 0xD7, 0x56, 0x5D, + 0x31, 0xD7, 0xBE, 0xA9, 0xAC, 0xDE, 0xAF, 0x02, + 0xB5, 0x1A, 0xDE, 0x45, 0x24, 0x3E, 0xE4, 0x1A, + 0x13, 0x52, 0x4D, 0x6A, 0x1B, 0x5D, 0xF8, 0x92 }; + static const uint8_t y[] = { + 0x99, 0x37, 0xE5, 0x36, 0xFA, 0xF7, 0xA9, 0x62, + 0x83, 0xFB, 0xB3, 0xE9, 0xF7, 0x9D, 0x8F, 0xD8, + 0xCB, 0x62, 0xF6, 0x66, 0x8D, 0xDC, 0xC8, 0x95, + 0x10, 0x24, 0x6C, 0x88, 0xBD, 0xFF, 0xB7, 0x7B, + 0xE2, 0x06, 0x52, 0xFD, 0xF7, 0x5F, 0x43, 0x62, + 0xE6, 0x53, 0x65, 0xB1, 0x38, 0x90, 0x25, 0x87, + 0x8D, 0xA4, 0x9E, 0xFE, 0x56, 0x08, 0xA7, 0xA2, + 0x0D, 0x4E, 0xD8, 0x43, 0x3C, 0x97, 0xBA, 0x27, + 0x6C, 0x56, 0xC4, 0x17, 0xA4, 0xB2, 0x5C, 0x8D, + 0xDB, 0x04, 0x17, 0x03, 0x4F, 0xE1, 0x22, 0xDB, + 0x74, 0x18, 0x54, 0x1B, 0xDE, 0x04, 0x68, 0xE1, + 0xBD, 0x0B, 0x4F, 0x65, 0x48, 0x0E, 0x95, 0x56, + 0x8D, 0xA7, 0x5B, 0xF1, 0x55, 0x47, 0x65, 0xE7, + 0xA8, 0x54, 0x17, 0x8A, 0x65, 0x76, 0x0D, 0x4F, + 0x0D, 0xFF, 0xAC, 0xA3, 0xE0, 0xFB, 0x80, 0x3A, + 0x86, 0xB0, 0xA0, 0x6B, 0x52, 0x00, 0x06, 0xC7 }; + uint8_t w[SIZE]; + uint8_t z[SIZE]; + uint8_t u1[SIZE]; + uint8_t u2[SIZE]; + uint8_t gu1[KSIZE]; + uint8_t yu2[KSIZE]; + uint8_t pro[KSIZE]; + uint8_t v[SIZE]; + + /* adapt to the expected format by arithmetic functions */ + uint8_t r1[SIZE]; + uint8_t s1[SIZE]; + + sha_Reset(&sha); + hdcpVerify_ArrayCPY(r1, r, sizeof(r1)); + hdcpVerify_ArrayCPY(s1, s, sizeof(s1)); + hdcpVerify_ArraySWP(r1, sizeof(r1)); + hdcpVerify_ArraySWP(s1, sizeof(s1)); + + hdcpVerify_ComputeINV(w, s1, q, sizeof(w)); + sha_Input(&sha, M, n); + if (sha_Result(&sha) == TRUE) { + for (i = 0; i < 5; i++) { + z[i * 4 + 0] = sha.mDigest[i] >> 24; + z[i * 4 + 1] = sha.mDigest[i] >> 16; + z[i * 4 + 2] = sha.mDigest[i] >> 8; + z[i * 4 + 3] = sha.mDigest[i] >> 0; + } + hdcpVerify_ArraySWP(z, sizeof(z)); + } else { + pr_info("cannot digest message"); + return FALSE; + } + if (hdcpVerify_ComputeMUL(u1, z, w, q, sizeof(u1)) == FALSE) + return FALSE; + if (hdcpVerify_ComputeMUL(u2, r1, w, q, sizeof(u2)) == FALSE) + return FALSE; + if (hdcpVerify_ComputeEXP(gu1, g, u1, p, sizeof(gu1), sizeof(u1)) + == FALSE) + return FALSE; + if (hdcpVerify_ComputeEXP(yu2, y, u2, p, sizeof(yu2), sizeof(u2)) + == FALSE) + return FALSE; + if (hdcpVerify_ComputeMUL(pro, gu1, yu2, p, sizeof(pro)) == FALSE) + return FALSE; + if (hdcpVerify_ComputeMOD(v, pro, q, sizeof(v)) == FALSE) + return FALSE; + return hdcpVerify_ArrayCMP(v, r1, sizeof(v)) == 0; +} + +int hdcpVerify_ArrayADD(uint8_t *r, const uint8_t *a, const uint8_t *b, + size_t n) +{ + uint8_t c = 0; + size_t i = 0; + + for (i = 0; i < n; i++) { + u16 s = a[i] + b[i] + c; + + c = (uint8_t) (s >> 8); + r[i] = (uint8_t) s; + } + return c; +} + +int hdcpVerify_ArrayCMP(const uint8_t *a, const uint8_t *b, size_t n) +{ + int i = 0; + + for (i = n; i > 0; i--) { + if (a[i - 1] > b[i - 1]) + return 1; + else if (a[i - 1] < b[i - 1]) + return -1; + } + return 0; +} + +void hdcpVerify_ArrayCPY(uint8_t *dst, const uint8_t *src, size_t n) +{ + size_t i = 0; + + for (i = 0; i < n; i++) + dst[i] = src[i]; +} + +int hdcpVerify_ArrayDIV(uint8_t *r, const uint8_t *D, const uint8_t *d, + size_t n) +{ + int i = 0; + + if (r == D || r == d || (!hdcpVerify_ArrayTST(d, 0, n)) == TRUE) { + pr_info("invalid input data"); + return FALSE; + } + hdcpVerify_ArraySET(&r[n], 0, n); + hdcpVerify_ArrayCPY(r, D, n); + for (i = n; i > 0; i--) { + r[i - 1 + n] = 0; + while (hdcpVerify_ArrayCMP(&r[i - 1], d, n) >= 0) { + hdcpVerify_ArraySUB(&r[i - 1], &r[i - 1], d, n); + r[i - 1 + n] += 1; + } + } + return TRUE; +} + +int hdcpVerify_ArrayMAC(uint8_t *r, const uint8_t *M, const uint8_t m, size_t n) +{ + u16 c = 0; + size_t i = 0; + + for (i = 0; i < n; i++) { + u16 p = (M[i] * m) + c + r[i]; + + c = p >> 8; + r[i] = (uint8_t) p; + } + return (uint8_t) c; +} + +int hdcpVerify_ArrayMUL(uint8_t *r, const uint8_t *M, const uint8_t *m, + size_t n) +{ + size_t i = 0; + + if (r == M || r == m) { + pr_info("invalid input data"); + return FALSE; + } + hdcpVerify_ArraySET(r, 0, n); + for (i = 0; i < n; i++) { + if (m[i] == 0) + continue; + else if (m[i] == 1) + hdcpVerify_ArrayADD(&r[i], &r[i], M, n - i); + else + hdcpVerify_ArrayMAC(&r[i], M, m[i], n - i); + } + return TRUE; +} + +void hdcpVerify_ArraySET(uint8_t *dst, const uint8_t src, size_t n) +{ + size_t i = 0; + + for (i = 0; i < n; i++) + dst[i] = src; +} + +int hdcpVerify_ArraySUB(uint8_t *r, const uint8_t *a, const uint8_t *b, + size_t n) +{ + uint8_t c = 1; + size_t i = 0; + + for (i = 0; i < n; i++) { + u16 s = ((uint8_t) a[i] + (uint8_t) (~b[i])) + c; + + c = (uint8_t) (s >> 8); + r[i] = (uint8_t) s; + } + return c; +} + +void hdcpVerify_ArraySWP(uint8_t *r, size_t n) +{ + size_t i = 0; + + for (i = 0; i < (n / 2); i++) { + uint8_t tmp = r[i]; + + r[i] = r[n - 1 - i]; + r[n - 1 - i] = tmp; + } +} + +int hdcpVerify_ArrayTST(const uint8_t *a, const uint8_t b, size_t n) +{ + size_t i = 0; + + for (i = 0; i < n; i++) { + if (a[i] != b) + return FALSE; + } + return TRUE; +} + +int hdcpVerify_ComputeEXP(uint8_t *c, const uint8_t *M, const uint8_t *e, + const uint8_t *p, size_t n, size_t nE) +{ + int i = 8 * nE - 1; + int rc = TRUE; + + /* LR Binary Method */ + if ((e[i / 8] & (1 << (i % 8))) != 0) + hdcpVerify_ArrayCPY(c, M, n); + else { + hdcpVerify_ArraySET(c, 0, n); + c[0] = 1; + } + for (i -= 1; i >= 0; i--) { + rc |= hdcpVerify_ComputeMUL(c, c, c, p, n); + if ((e[i / 8] & (1 << (i % 8))) != 0) + rc &= hdcpVerify_ComputeMUL(c, c, M, p, n); + } + return rc; +} + +int hdcpVerify_ComputeINV(uint8_t *out, const uint8_t *z, const uint8_t *a, + size_t n) +{ + uint8_t w[2][SIZE]; + uint8_t x[2][SIZE]; + uint8_t y[2][SIZE]; + uint8_t r[2*SIZE]; + uint8_t *i, *j, *q, *t; + uint8_t *x1, *x2; + uint8_t *y1, *y2; + + if ((n > SIZE) || (hdcpVerify_ArrayTST(z, 0, n) == TRUE) + || (hdcpVerify_ArrayTST(a, 0, n) == TRUE) + || (hdcpVerify_ArrayCMP(z, a, n) >= 0)) { + pr_info("invalid input data"); + return FALSE; + } + + hdcpVerify_ArrayCPY(w[0], a, n); + hdcpVerify_ArrayCPY(w[1], z, n); + i = w[0]; + j = w[1]; + + hdcpVerify_ArraySET(x[1], 0, n); + x[1][0] = 1; + hdcpVerify_ArraySET(x[0], 0, n); + x2 = x[1]; + x1 = x[0]; + + hdcpVerify_ArraySET(y[1], 0, n); + hdcpVerify_ArraySET(y[0], 0, n); + y[0][0] = 1; + y2 = y[1]; + y1 = y[0]; + + do { + hdcpVerify_ArrayDIV(r, i, j, n); + hdcpVerify_ArrayCPY(i, r, n); + q = &r[n]; + t = i; /* swap i <-> j */ + i = j; + j = t; + + hdcpVerify_ArrayMUL(r, x1, q, n); + hdcpVerify_ArraySUB(x2, x2, r, n); + t = x2; /* swap x1 <-> x2 */ + x2 = x1; + x1 = t; + + hdcpVerify_ArrayMUL(r, y1, q, n); + hdcpVerify_ArraySUB(y2, y2, r, n); + t = y2; /* swap y1 <-> y2 */ + y2 = y1; + y1 = t; + + } while (hdcpVerify_ArrayTST(j, 0, n) == FALSE); + + j[0] = 1; + if (hdcpVerify_ArrayCMP(i, j, n) != 0) { + pr_info("i != 1"); + return FALSE; + } + hdcpVerify_ArrayCPY(out, y2, n); + return TRUE; +} + +int hdcpVerify_ComputeMOD(uint8_t *dst, const uint8_t *src, const uint8_t *p, + size_t n) +{ + uint8_t aux[KSIZE]; + uint8_t ext[SIZE + 1]; + uint8_t tmp[2 * (KSIZE + 1)]; + int i = 0; + + if (n > SIZE) { + pr_info("invalid input data"); + return FALSE; + } + hdcpVerify_ArrayCPY(aux, src, sizeof(aux)); + /* TODO: remove extension */ + hdcpVerify_ArrayCPY(ext, p, n); + ext[n] = 0; + for (i = sizeof(aux)-n-1; i >= 0; i--) { + hdcpVerify_ArrayDIV(tmp, &aux[i], ext, n+1); + hdcpVerify_ArrayCPY(&aux[i], tmp, n+1); + } + hdcpVerify_ArrayCPY(dst, aux, n); + return TRUE; +} + +int hdcpVerify_ComputeMUL(uint8_t *p, const uint8_t *a, const uint8_t *b, + const uint8_t *m, size_t n) +{ + uint8_t aux[2 * KSIZE + 1]; + uint8_t ext[KSIZE + 1]; + uint8_t tmp[2 * (KSIZE + 1)]; + size_t i = 0; + int j = 0; + + if (n > KSIZE) { + pr_info("invalid input data"); + return FALSE; + } + hdcpVerify_ArraySET(aux, 0, sizeof(aux)); + for (i = 0; i < n; i++) { + /* TODO: extension was faster */ + aux[n+i] = hdcpVerify_ArrayMAC(&aux[i], a, b[i], n); + } + /* TODO: reuse ComputeMOD */ + hdcpVerify_ArrayCPY(ext, m, n); + ext[n] = 0; + for (j = n; j >= 0; j--) { + hdcpVerify_ArrayDIV(tmp, &aux[j], ext, n+1); + hdcpVerify_ArrayCPY(&aux[j], tmp, n+1); + } + hdcpVerify_ArrayCPY(p, aux, n); + return TRUE; +} + +int hdcpVerify_KSV(const uint8_t *data, size_t size) +{ + size_t i = 0; + struct sha_t sha; + + if (data == 0 || size < (HEADER + SHAMAX)) { + pr_info("invalid input data"); + return FALSE; + } + sha_Reset(&sha); + sha_Input(&sha, data, size - SHAMAX); + if (sha_Result(&sha) == FALSE) { + pr_info("cannot process SHA digest"); + return FALSE; + } + for (i = 0; i < SHAMAX; i++) { + if (data[size - SHAMAX + i] != (uint8_t) (sha.mDigest[i / 4] + >> ((i % 4) * 8))) { + pr_info("SHA digest does not match"); + return FALSE; + } + } + return TRUE; +} + +int hdcpVerify_SRM(const uint8_t *data, size_t size) +{ + if (data == 0 || size < (VRL_HEADER + VRL_NUMBER + 2 * DSAMAX)) { + pr_info("invalid input data"); + return FALSE; + } + /* M, n, r, s */ + return hdcpVerify_DSA(data, size - 2 * DSAMAX, &data[size - 2 * DSAMAX], + &data[size - DSAMAX]); +} + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h new file mode 100644 index 000000000000..404074b1c3e3 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h @@ -0,0 +1,97 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdcpVerify.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef HDCPVERIFY_H_ +#define HDCPVERIFY_H_ + +#include +#include +#include "hdcp.h" + +struct sha_t { + uint8_t mLength[8]; + uint8_t mBlock[64]; + int mIndex; + int mComputed; + int mCorrupted; + unsigned int mDigest[5]; +}; + +#define KSV_LEN 5 +#define KSV_MSK 0x7F +#define VRL_LENGTH 0x05 +#define VRL_HEADER 5 +#define VRL_NUMBER 3 +#define HEADER 10 +#define SHAMAX 20 +#define DSAMAX 20 + +void sha_Reset(struct sha_t *sha); + +int sha_Result(struct sha_t *sha); + +void sha_Input(struct sha_t *sha, const uint8_t *data, size_t size); + +void sha_ProcessBlock(struct sha_t *sha); + +void sha_PadMessage(struct sha_t *sha); + +int hdcpVerify_DSA(const uint8_t *M, size_t n, const uint8_t *r, + const uint8_t *s); + +int hdcpVerify_ArrayADD(uint8_t *r, const uint8_t *a, const uint8_t *b, + size_t n); + +int hdcpVerify_ArrayCMP(const uint8_t *a, const uint8_t *b, size_t n); + +void hdcpVerify_ArrayCPY(uint8_t *dst, const uint8_t *src, size_t n); + +int hdcpVerify_ArrayDIV(uint8_t *r, const uint8_t *D, const uint8_t *d, + size_t n); + +int hdcpVerify_ArrayMAC(uint8_t *r, const uint8_t *M, const uint8_t m, + size_t n); + +int hdcpVerify_ArrayMUL(uint8_t *r, const uint8_t *M, const uint8_t *m, + size_t n); + +void hdcpVerify_ArraySET(uint8_t *dst, const uint8_t src, size_t n); + +int hdcpVerify_ArraySUB(uint8_t *r, const uint8_t *a, const uint8_t *b, + size_t n); + +void hdcpVerify_ArraySWP(uint8_t *r, size_t n); + +int hdcpVerify_ArrayTST(const uint8_t *a, const uint8_t b, size_t n); + +int hdcpVerify_ComputeEXP(uint8_t *c, const uint8_t *M, const uint8_t *e, + const uint8_t *p, size_t n, size_t nE); + +int hdcpVerify_ComputeINV(uint8_t *out, const uint8_t *z, const uint8_t *a, + size_t n); + +int hdcpVerify_ComputeMOD(uint8_t *dst, const uint8_t *src, const uint8_t *p, + size_t n); + +int hdcpVerify_ComputeMUL(uint8_t *p, const uint8_t *a, const uint8_t *b, + const uint8_t *m, size_t n); + +int hdcpVerify_KSV(const uint8_t *data, size_t size); + +int hdcpVerify_SRM(const uint8_t *data, size_t size); + +#endif /* HDCPVERIFY_H_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c new file mode 100644 index 000000000000..63da890c520a --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c @@ -0,0 +1,205 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_ddc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hdmi_tx_reg.h" + +static uint32_t ddc_write_1byte(uint8_t slave, uint8_t offset_addr, + uint8_t data) +{ + uint32_t st = 0; + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, slave); + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, offset_addr); + hdmitx_wr_reg(HDMITX_DWC_I2CM_DATAO, data); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 4); + mdelay(2); + if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) { + st = 0; + pr_info("hdmitx: ddc w1b error 0x%02x 0x%02x 0x%02x\n", + slave, offset_addr, data); + } else + st = 1; + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7); + + return st; +} + +static uint32_t ddc_readext_8byte(uint8_t slave, uint8_t offset_addr, + uint8_t *data) +{ + uint32_t st = 0; + int32_t i; + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, slave); + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, offset_addr); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR, EDIDSEG_ADR); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, 0x00); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 3); + mdelay(2); + if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) { + st = 0; + pr_info("hdmitx: ddc rdext8b error 0x%02x 0x%02x\n", + slave, offset_addr); + } else + st = 1; + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7); + for (i = 0; i < 8; i++) + data[i] = hdmitx_rd_reg(HDMITX_DWC_I2CM_READ_BUFF0 + i); + return st; +} + +static uint32_t ddc_read_8byte(uint8_t slave, uint8_t offset_addr, + uint8_t *data) +{ + uint32_t st = 0; + int32_t i; + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, slave); + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, offset_addr); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 2); + mdelay(2); + if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) { + st = 0; + pr_info("hdmitx: ddc rd8b error 0x%02x 0x%02x 0x%02x\n", + slave, offset_addr, *data); + } else + st = 1; + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7); + for (i = 0; i < 8; i++) + data[i] = hdmitx_rd_reg(HDMITX_DWC_I2CM_READ_BUFF0 + i); + return st; +} + +static uint32_t ddc_readext_1byte(uint8_t slave, uint8_t address, uint8_t *data) +{ + uint32_t st = 0; + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, slave); + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, address); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR, EDIDSEG_ADR); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, 0x00); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 1); + mdelay(2); + if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) { + st = 0; + pr_info("hdmitx: ddc rd8b error 0x%02x 0x%02x\n", + slave, address); + } else + st = 1; + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7); + *data = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI); + return st; +} + +static uint32_t ddc_read_1byte(uint8_t slave, uint8_t offset_addr, + uint8_t *data) +{ + uint32_t st = 0; + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, slave); + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, offset_addr); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 0); + mdelay(2); + if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) { + st = 0; + pr_info("hdmitx: ddc rd8b error 0x%02x 0x%02x\n", + slave, offset_addr); + } else + st = 1; + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7); + *data = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI); + return st; +} + +static uint32_t hdcp_rd_bksv(uint8_t *data) +{ + if (0) + ddc_readext_8byte(HDCP_SLAVE, HDCP14_BKSV, data); + + return ddc_read_8byte(HDCP_SLAVE, HDCP14_BKSV, data); +} + +void scdc_rd_sink(uint8_t adr, uint8_t *val) +{ + hdmitx_ddc_hw_op(DDC_MUX_DDC); + + if (0) + ddc_readext_1byte(SCDC_SLAVE, adr, val); + + ddc_read_1byte(SCDC_SLAVE, adr, val); +} + +void scdc_wr_sink(uint8_t adr, uint8_t val) +{ + hdmitx_ddc_hw_op(DDC_MUX_DDC); + ddc_write_1byte(SCDC_SLAVE, adr, val); +} + +uint32_t hdcp_rd_hdcp14_ver(void) +{ + int ret = 0; + uint8_t bksv[8] = {0}; + + hdmitx_ddc_hw_op(DDC_MUX_DDC); + ret = hdcp_rd_bksv(&bksv[0]); + if (ret) + return 1; + ret = hdcp_rd_bksv(&bksv[0]); + if (ret) + return 1; + + return 0; +} + +uint32_t hdcp_rd_hdcp22_ver(void) +{ + uint32_t ret; + uint8_t ver; + + hdmitx_ddc_hw_op(DDC_MUX_DDC); + ret = ddc_read_1byte(HDCP_SLAVE, HDCP2_VERSION, &ver); + if (ret) + return ver == 0x04; + ret = ddc_read_1byte(HDCP_SLAVE, HDCP2_VERSION, &ver); + if (ret) + return ver == 0x04; + + return 0; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c new file mode 100644 index 000000000000..39e45b28c629 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -0,0 +1,4628 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mach_reg.h" +#include "hdmi_tx_reg.h" + +#if 0 /* todo */ +#include "../hdmi_tx_hdcp.h" +#include "../hdmi_tx_compliance.h" +#endif +#include "tvenc_conf.h" +#include "common.h" +#include "hdcpVerify.h" +#include "hw_clk.h" + +#define EDID_RAM_ADDR_SIZE (8) + +static void hdmi_audio_init(unsigned int spdif_flag); +static void hdmitx_dump_tvenc_reg(int cur_VIC, int pr_info_flag); + +static void mode420_half_horizontal_para(void); +static void hdmi_phy_suspend(void); +static void hdmi_phy_wakeup(struct hdmitx_dev *hdev); +static void hdmitx_set_phy(struct hdmitx_dev *hdev); +static void hdmitx_set_hw(struct hdmitx_dev *hdev); +static void set_hdmi_audio_source(unsigned int src); +static void hdmitx_csc_config(unsigned char input_color_format, + unsigned char output_color_format, unsigned char color_depth); +static int hdmitx_hdmi_dvi_config(struct hdmitx_dev *hdev, + unsigned int dvi_mode); +static void hdmitx_set_avi_colorimetry(struct hdmi_format_para *para); + +unsigned char hdmi_pll_mode; /* 1, use external clk as hdmi pll source */ + +/* HSYNC polarity: active high */ +#define HSYNC_POLARITY 1 +/* VSYNC polarity: active high */ +#define VSYNC_POLARITY 1 +/* Pixel format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. */ +#define TX_INPUT_COLOR_FORMAT COLORSPACE_YUV444 +/* Pixel range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. */ +#define TX_INPUT_COLOR_RANGE 0 +/* Pixel bit width: 4=24-bit; 5=30-bit; 6=36-bit; 7=48-bit. */ +#define TX_COLOR_DEPTH COLORDEPTH_24B +/* Pixel format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420. */ +#define TX_OUTPUT_COLOR_FORMAT COLORSPACE_YUV444 +#define TX_OUTPUT_COLOR_RANGE 0 + +#if 1 +/* 0=I2S 2-channel; 1=I2S 4 x 2-channel. */ +#define TX_I2S_8_CHANNEL 0 +#endif + +static unsigned int tx_aud_src; /* 0: SPDIF 1: I2S */ + +/* store downstream ksv lists */ +static char *rptx_ksvs; +static char rptx_ksv_prbuf[1271]; /* 127 * 5 * 2 + 1 */ +MODULE_PARM_DESC(rptx_ksvs, "\n downstream ksvs\n"); +module_param(rptx_ksvs, charp, 0444); +static int rptx_ksv_no; +static int rptx_ksvlist_retry; +static char rptx_ksv_buf[635]; + +/* static struct tasklet_struct EDID_tasklet; */ +static unsigned int delay_flag; +static unsigned long serial_reg_val = 0x1; +static unsigned char i2s_to_spdif_flag = 1; +static unsigned long color_depth_f; +static unsigned long COLORSPACE_f; +static unsigned char new_reset_sequence_flag = 1; +static unsigned char power_mode = 1; +static unsigned char power_off_vdac_flag; +/* 0, do not use fixed tvenc val for all mode; + * 1, use fixed tvenc val mode for 480i; + * 2, use fixed tvenc val mode for all modes + */ +static unsigned char use_tvenc_conf_flag = 1; + +static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB); +static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, + unsigned char *CHAN_STAT_BUF); +static int hdmitx_set_dispmode(struct hdmitx_dev *hdev); +static int hdmitx_set_audmode(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param); +static void hdmitx_setupirq(struct hdmitx_dev *hdev); +static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf); +static void hdmitx_uninit(struct hdmitx_dev *hdev); +static int hdmitx_cntl(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv); +static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned long argv); +static int hdmitx_get_state(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv); +static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv); +static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv); +static void digital_clk_on(unsigned char flag); +static void digital_clk_off(unsigned char flag); + +static int hdmitx_hpd_hw_op(enum hpd_op cmd) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + return hdmitx_hpd_hw_op_gxbb(cmd); + case MESON_CPU_MAJOR_ID_GXTVBB: + return hdmitx_hpd_hw_op_gxtvbb(cmd); + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + return hdmitx_hpd_hw_op_gxl(cmd); + default: + break; + } + return 0; +} + +int read_hpd_gpio(void) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + return read_hpd_gpio_gxbb(); + case MESON_CPU_MAJOR_ID_GXTVBB: + return read_hpd_gpio_gxtvbb(); + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + return read_hpd_gpio_gxl(); + default: + break; + } + return 0; +} +EXPORT_SYMBOL(read_hpd_gpio); + +int hdmitx_ddc_hw_op(enum ddc_op cmd) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + return hdmitx_ddc_hw_op_gxbb(cmd); + case MESON_CPU_MAJOR_ID_GXTVBB: + return hdmitx_ddc_hw_op_gxtvbb(cmd); + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + return hdmitx_ddc_hw_op_gxl(cmd); + default: + break; + } + return 0; +} + +int hdmitx_hdcp_opr(unsigned int val) +{ + if (val == 1) { /* HDCP14_ENABLE */ + register long x0 asm("x0") = 0x82000010; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 2) { /* HDCP14_RESULT */ + register long x0 asm("x0") = 0x82000011; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : "+r"(x0) + ); + return (unsigned int)(x0&0xffffffff); + } + if (val == 0) { /* HDCP14_INIT */ + register long x0 asm("x0") = 0x82000012; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 3) { /* HDCP14_EN_ENCRYPT */ + register long x0 asm("x0") = 0x82000013; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 4) { /* HDCP14_OFF */ + register long x0 asm("x0") = 0x82000014; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 5) { /* HDCP_MUX_22 */ + register long x0 asm("x0") = 0x82000015; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 6) { /* HDCP_MUX_14 */ + register long x0 asm("x0") = 0x82000016; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : : "r"(x0) + ); + } + if (val == 7) { /* HDCP22_RESULT */ + register long x0 asm("x0") = 0x82000017; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : "+r"(x0) + ); + return (unsigned int)(x0&0xffffffff); + } + if (val == 0xa) { /* HDCP14_KEY_LSTORE */ + register long x0 asm("x0") = 0x8200001a; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : "+r"(x0) + ); + return (unsigned int)(x0&0xffffffff); + } + if (val == 0xb) { /* HDCP22_KEY_LSTORE */ + register long x0 asm("x0") = 0x8200001b; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : "+r"(x0) + ); + return (unsigned int)(x0&0xffffffff); + } + if (val == 0xc) { /* HDCP22_KEY_SET_DUK */ + register long x0 asm("x0") = 0x8200001c; + asm volatile( + __asmeq("%0", "x0") + "smc #0\n" + : "+r"(x0) + ); + return (unsigned int)(x0&0xffffffff); + } + return -1; +} + +static void config_avmute(unsigned int val) +{ + pr_info("avmute set to %d\n", val); + switch (val) { + case SET_AVMUTE: + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 1, 1, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 0, 0, 1); + break; + case CLR_AVMUTE: + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 0, 1, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 1, 0, 1); + break; + case OFF_AVMUTE: + default: + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 0, 1, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_GCP, 0, 0, 1); + break; + } +} + +static void config_video_mapping(enum hdmi_color_space cs, + enum hdmi_color_depth cd) +{ + unsigned int val = 0; + + pr_info("hdmitx: config: cs = %d cd = %d\n", cs, cd); + switch (cs) { + case COLORSPACE_RGB444: + switch (cd) { + case COLORDEPTH_24B: + val = 0x1; + break; + case COLORDEPTH_30B: + val = 0x3; + break; + case COLORDEPTH_36B: + val = 0x5; + break; + case COLORDEPTH_48B: + val = 0x7; + break; + default: + break; + } + break; + case COLORSPACE_YUV444: + case COLORSPACE_YUV420: + switch (cd) { + case COLORDEPTH_24B: + val = 0x9; + break; + case COLORDEPTH_30B: + val = 0xb; + break; + case COLORDEPTH_36B: + val = 0xd; + break; + case COLORDEPTH_48B: + val = 0xf; + break; + default: + break; + } + break; + case COLORSPACE_YUV422: + switch (cd) { + case COLORDEPTH_24B: + val = 0x16; + break; + case COLORDEPTH_30B: + val = 0x14; + break; + case COLORDEPTH_36B: + val = 0x12; + break; + case COLORDEPTH_48B: + pr_info("hdmitx: y422 no 48bits mode\n"); + break; + default: + break; + } + break; + default: + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_TX_INVID0, val, 0, 4); + + switch (cd) { + case COLORDEPTH_24B: + val = 0x4; + break; + case COLORDEPTH_30B: + val = 0x5; + break; + case COLORDEPTH_36B: + val = 0x6; + break; + case COLORDEPTH_48B: + val = 0x7; + break; + default: + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_VP_PR_CD, val, 4, 4); + + switch (cd) { + case COLORDEPTH_30B: + case COLORDEPTH_36B: + case COLORDEPTH_48B: + hdmitx_set_reg_bits(HDMITX_DWC_VP_CONF, 0, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_VP_CONF, 1, 5, 1); + hdmitx_set_reg_bits(HDMITX_DWC_VP_CONF, 1, 2, 1); + hdmitx_set_reg_bits(HDMITX_DWC_VP_CONF, 0, 0, 2); + break; + case COLORDEPTH_24B: + break; + default: + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_VP_PR_CD, val, 4, 4); +} + +/* record HDMITX current format, matched with uboot */ +/* ISA_DEBUG_REG0 0x2600 + * bit[11]: Y420 + * bit[10:8]: HDMI VIC + * bit[7:0]: CEA VIC + */ +static unsigned int get_hdmitx_format(void) +{ + return hd_read_reg(P_ISA_DEBUG_REG0); +} + +static int hdmitx_uboot_already_display(void) +{ + if ((hd_read_reg(P_HHI_HDMI_CLK_CNTL) & (1 << 8)) + && (hd_read_reg(P_HHI_HDMI_PLL_CNTL) & (1 << 31)) + && (get_hdmitx_format())) { + pr_info("hdmitx: alread display in uboot 0x%x\n", + get_hdmitx_format()); + return 1; + } else + return 0; +} + +/* for 30bits colordepth */ +static void set_vmode_clk(struct hdmitx_dev *hdev) +{ + hdmitx_set_clk(hdev); +} + +static void hdmi_hwp_init(struct hdmitx_dev *hdev) +{ + /* Enable clocks and bring out of reset */ + + /* Enable hdmitx_sys_clk */ + /* .clk0 ( cts_oscin_clk ), */ + /* .clk1 ( fclk_div4 ), */ + /* .clk2 ( fclk_div3 ), */ + /* .clk3 ( fclk_div5 ), */ +/* [10: 9] clk_sel. select cts_oscin_clk=24MHz */ +/* [ 8] clk_en. Enable gated clock */ +/* [ 6: 0] clk_div. Divide by 1. = 24/1 = 24 MHz */ + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0x100, 0, 16); + +/* Enable clk81_hdmitx_pclk */ + hd_set_reg_bits(P_HHI_GCLK_MPEG2, 1, 4, 1); + /* wire wr_enable = control[3]; */ + /* wire fifo_enable = control[2]; */ + /* assign phy_clk_en = control[1]; */ +/* Bring HDMITX MEM output of power down */ + hd_set_reg_bits(P_HHI_MEM_PD_REG0, 0, 8, 8); + if (hdmitx_uboot_already_display()) + return; + /* reset HDMITX APB & TX & PHY */ + hd_set_reg_bits(P_RESET0_REGISTER, 1, 19, 1); + hd_set_reg_bits(P_RESET2_REGISTER, 1, 15, 1); + hd_set_reg_bits(P_RESET2_REGISTER, 1, 2, 1); + /* Enable APB3 fail on error */ + hd_set_reg_bits(P_HDMITX_CTRL_PORT, 1, 15, 1); + hd_set_reg_bits((P_HDMITX_CTRL_PORT + 0x10), 1, 15, 1); + /* Bring out of reset */ + hdmitx_wr_reg(HDMITX_TOP_SW_RESET, 0); + udelay(200); + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 3, 0, 2); + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 3, 4, 2); + hdmitx_wr_reg(HDMITX_DWC_MC_LOCKONCLOCK, 0xff); + hdmitx_wr_reg(HDMITX_TOP_INTR_MASKN, 0x1f); +} + +static void hdmi_hwi_init(struct hdmitx_dev *hdev) +{ + unsigned int data32 = 0; + + hdmitx_hpd_hw_op(HPD_INIT_DISABLE_PULLUP); + hdmitx_hpd_hw_op(HPD_INIT_SET_FILTER); + hdmitx_ddc_hw_op(DDC_INIT_DISABLE_PULL_UP_DN); + hdmitx_ddc_hw_op(DDC_MUX_DDC); + +/* Configure E-DDC interface */ + data32 = 0; + data32 |= (0 << 6); /* [ 6] read_req_mask */ + data32 |= (0 << 2); /* [ 2] done_mask */ + hdmitx_wr_reg(HDMITX_DWC_I2CM_INT, data32); + + data32 = 0; + data32 |= (0 << 6); /* [ 6] nack_mask */ + data32 |= (0 << 2); /* [ 2] arbitration_error_mask */ + hdmitx_wr_reg(HDMITX_DWC_I2CM_CTLINT, data32); + +/* [ 3] i2c_fast_mode: 0=standard mode; 1=fast mode. */ + data32 = 0; + data32 |= (0 << 3); + hdmitx_wr_reg(HDMITX_DWC_I2CM_DIV, data32); + + hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_1, 0); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_0, 0x67); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_LCNT_1, 0); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_LCNT_0, 0x78); + hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_HCNT_1, 0); + hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_HCNT_0, 0x0f); + hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_LCNT_1, 0); + hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_LCNT_0, 0x20); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SDA_HOLD, 0x08); + + data32 = 0; + data32 |= (0 << 5); /* [ 5] updt_rd_vsyncpoll_en */ + data32 |= (0 << 4); /* [ 4] read_request_en // scdc */ + data32 |= (0 << 0); /* [ 0] read_update */ + hdmitx_wr_reg(HDMITX_DWC_I2CM_SCDC_UPDATE, data32); +} + +void HDMITX_Meson_Init(struct hdmitx_dev *hdev) +{ + hdev->HWOp.SetPacket = hdmitx_set_packet; + hdev->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; + hdev->HWOp.SetDispMode = hdmitx_set_dispmode; + hdev->HWOp.SetAudMode = hdmitx_set_audmode; + hdev->HWOp.SetupIRQ = hdmitx_setupirq; + hdev->HWOp.DebugFun = hdmitx_debug; + hdev->HWOp.UnInit = hdmitx_uninit; + hdev->HWOp.Cntl = hdmitx_cntl; /* todo */ + hdev->HWOp.CntlDDC = hdmitx_cntl_ddc; + hdev->HWOp.GetState = hdmitx_get_state; + hdev->HWOp.CntlPacket = hdmitx_cntl; + hdev->HWOp.CntlConfig = hdmitx_cntl_config; + hdev->HWOp.CntlMisc = hdmitx_cntl_misc; + init_reg_map(); + digital_clk_on(0xff); + hdmi_hwp_init(hdev); + hdmi_hwi_init(hdev); + config_avmute(CLR_AVMUTE); + hdmitx_set_audmode(NULL, NULL); + rptx_ksvs = &rptx_ksv_prbuf[0]; +} + +static irqreturn_t intr_handler(int irq, void *dev) +{ + unsigned int data32 = 0; + struct hdmitx_dev *hdev = (struct hdmitx_dev *)dev; + /* get interrupt status */ + data32 = hdmitx_rd_reg(HDMITX_TOP_INTR_STAT); + hdmi_print(IMP, SYS "irq %x\n", data32); + if (hdev->hpd_lock == 1) { + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0xf); + hdmi_print(IMP, HPD "HDMI hpd locked\n"); + goto next; + } + /* check HPD status */ + if ((data32 & (1 << 1)) && (data32 & (1 << 2))) { + if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO)) + data32 &= ~(1 << 2); + else + data32 &= ~(1 << 1); + } + /* HPD rising */ + if (data32 & (1 << 1)) { + hdev->hdmitx_event |= HDMI_TX_HPD_PLUGIN; + hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; + queue_delayed_work(hdev->hdmi_wq, + &hdev->work_hpd_plugin, HZ / 3); + } + /* HPD falling */ + if (data32 & (1 << 2)) { + hdev->hdmitx_event |= HDMI_TX_HPD_PLUGOUT; + hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN; + queue_delayed_work(hdev->hdmi_wq, + &hdev->work_hpd_plugout, 0); + } +next: + /* internal interrupt */ + if (data32 & (1 << 0)) { + hdev->hdmitx_event |= HDMI_TX_INTERNAL_INTR; + queue_work(hdev->hdmi_wq, &hdev->work_internal_intr); + } + if (data32 & (1 << 3)) { + unsigned int rd_nonce_mode = + hdmitx_rd_reg(HDMITX_TOP_SKP_CNTL_STAT) & 0x1; + pr_info("hdcp22: Nonce %s Vld: %d\n", + rd_nonce_mode ? "HW" : "SW", + ((hdmitx_rd_reg(HDMITX_TOP_SKP_CNTL_STAT) >> 31) & 1)); + if (rd_nonce_mode) + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, (1 << 3)); + else { + hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x32107654); + hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xba98fedc); + hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0xcdef89ab); + hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x45670123); + hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x76543210); + hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xfedcba98); + hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0x89abcdef); + hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x01234567); + } + } + if (data32 & (1 << 30)) { + pr_info("hdcp22: reg stat: 0x%x\n", + hdmitx_rd_reg(HDMITX_DWC_HDCP22REG_STAT)); + hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff); + } + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, data32 | 0x6); + return IRQ_HANDLED; +} + +static unsigned long modulo(unsigned long a, unsigned long b) +{ + if (a >= b) + return a - b; + else + return a; +} + +static signed int to_signed(unsigned int a) +{ + if (a <= 7) + return a; + else + return a - 16; +} + +static void delay_us(int us) +{ + /* udelay(us); */ + if (delay_flag&0x1) + mdelay((us+999)/1000); +} /* delay_us */ + +/* + * mode: 1 means Progressive; 0 means interlaced + */ +static void enc_vpu_bridge_reset(int mode) +{ + unsigned int wr_clk = 0; + + wr_clk = (hd_read_reg(P_VPU_HDMI_SETTING) & 0xf00) >> 8; + if (mode) { + hd_write_reg(P_ENCP_VIDEO_EN, 0); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 0, 2); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 8, 4); + mdelay(1); + hd_write_reg(P_ENCP_VIDEO_EN, 1); + mdelay(1); + hd_set_reg_bits(P_VPU_HDMI_SETTING, wr_clk, 8, 4); + mdelay(1); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 2, 0, 2); + } else { + hd_write_reg(P_ENCI_VIDEO_EN, 0); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 0, 2); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 8, 4); + mdelay(1); + hd_write_reg(P_ENCI_VIDEO_EN, 1); + mdelay(1); + hd_set_reg_bits(P_VPU_HDMI_SETTING, wr_clk, 8, 4); + mdelay(1); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 0, 2); + } +} + +static void hdmi_tvenc1080i_set(struct hdmitx_vidpara *param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; + unsigned long TOTAL_PIXELS = 0, PIXEL_REPEAT_HDMI = 0, + PIXEL_REPEAT_VENC = 0, ACTIVE_PIXELS = 0; + unsigned int FRONT_PORCH = 88, HSYNC_PIXELS = 0, ACTIVE_LINES = 0, + INTERLACE_MODE = 0, TOTAL_LINES = 0, SOF_LINES = 0, + VSYNC_LINES = 0; + unsigned int LINES_F0 = 0, LINES_F1 = 563, BACK_PORCH = 0, + EOF_LINES = 2, TOTAL_FRAMES = 0; + + unsigned long total_pixels_venc = 0; + unsigned long active_pixels_venc = 0; + unsigned long front_porch_venc = 0; + unsigned long hsync_pixels_venc = 0; + + unsigned long de_h_begin = 0, de_h_end = 0; + unsigned long de_v_begin_even = 0, de_v_end_even = 0, + de_v_begin_odd = 0, de_v_end_odd = 0; + unsigned long hs_begin = 0, hs_end = 0; + unsigned long vs_adjust = 0; + unsigned long vs_bline_evn = 0, vs_eline_evn = 0, + vs_bline_odd = 0, vs_eline_odd = 0; + unsigned long vso_begin_evn = 0, vso_begin_odd = 0; + + if (param->VIC == HDMI_1080i60) { + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); + LINES_F0 = 562; + LINES_F1 = 563; + FRONT_PORCH = 88; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 2; + VSYNC_LINES = 5; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + } else if (param->VIC == HDMI_1080i50) { + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); + LINES_F0 = 562; + LINES_F1 = 563; + FRONT_PORCH = 528; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 2; + VSYNC_LINES = 5; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + } + TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); + TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + active_pixels_venc = (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + hsync_pixels_venc = + (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); + + hd_write_reg(P_ENCP_VIDEO_MODE, hd_read_reg(P_ENCP_VIDEO_MODE)|(1<<14)); + + /* Program DE timing */ + de_h_begin = modulo(hd_read_reg(P_ENCP_VIDEO_HAVON_BEGIN) + + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DE_H_BEGIN, de_h_begin); + hd_write_reg(P_ENCP_DE_H_END, de_h_end); + /* Program DE timing for even field */ + de_v_begin_even = hd_read_reg(P_ENCP_VIDEO_VAVON_BLINE); + de_v_end_even = de_v_begin_even + ACTIVE_LINES; + hd_write_reg(P_ENCP_DE_V_BEGIN_EVEN, de_v_begin_even); + hd_write_reg(P_ENCP_DE_V_END_EVEN, de_v_end_even); + /* Program DE timing for odd field if needed */ + if (INTERLACE_MODE) { + de_v_begin_odd = to_signed(( + hd_read_reg(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + + de_v_begin_even + (TOTAL_LINES-1)/2; + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; + hd_write_reg(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd);/* 583 */ + hd_write_reg(P_ENCP_DE_V_END_ODD, de_v_end_odd); /* 1123 */ + } + + /* Program Hsync timing */ + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DVI_HSO_BEGIN, hs_begin); + hd_write_reg(P_ENCP_DVI_HSO_END, hs_end); + + /* Program Vsync timing for even field */ + if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) + vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES + - (1-vs_adjust); + else + vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES + - VSYNC_LINES - (1-vs_adjust); + + vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); /* 0 */ + hd_write_reg(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); /* 5 */ + vso_begin_evn = hs_begin; /* 2 */ + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); /* 2 */ + hd_write_reg(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); /* 2 */ + /* Program Vsync timing for odd field if needed */ + if (INTERLACE_MODE) { + vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; + vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), + total_pixels_venc); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); + hd_write_reg(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); + hd_write_reg(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); + } + + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (4 << 5) | + (1 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + +} + +static void hdmi_tvenc4k2k_set(struct hdmitx_vidpara *param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; + unsigned long TOTAL_PIXELS = 4400, PIXEL_REPEAT_HDMI = 0, + PIXEL_REPEAT_VENC = 0, ACTIVE_PIXELS = 3840; + unsigned int FRONT_PORCH = 1020, HSYNC_PIXELS = 0, ACTIVE_LINES = 2160, + INTERLACE_MODE = 0, TOTAL_LINES = 0, SOF_LINES = 0, + VSYNC_LINES = 0; + unsigned int LINES_F0 = 2250, LINES_F1 = 2250, BACK_PORCH = 0, + EOF_LINES = 8, TOTAL_FRAMES = 0; + + unsigned long total_pixels_venc = 0; + unsigned long active_pixels_venc = 0; + unsigned long front_porch_venc = 0; + unsigned long hsync_pixels_venc = 0; + + unsigned long de_h_begin = 0, de_h_end = 0; + unsigned long de_v_begin_even = 0, de_v_end_even = 0, + de_v_begin_odd = 0, de_v_end_odd = 0; + unsigned long hs_begin = 0, hs_end = 0; + unsigned long vs_adjust = 0; + unsigned long vs_bline_evn = 0, vs_eline_evn = 0, vs_bline_odd = 0, + vs_eline_odd = 0; + unsigned long vso_begin_evn = 0, vso_begin_odd = 0; + + switch (param->VIC) { + case HDMI_4k2k_30: + case HDMI_3840x2160p60_16x9: + case HDMI_3840x2160p60_16x9_Y420: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (3840*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 176; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 8 + 1; + VSYNC_LINES = 10; + SOF_LINES = 72 + 1; + TOTAL_FRAMES = 3; + break; + case HDMI_4k2k_25: + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p50_16x9_Y420: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (3840*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 1056; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 8 + 1; + VSYNC_LINES = 10; + SOF_LINES = 72 + 1; + TOTAL_FRAMES = 3; + break; + case HDMI_4k2k_24: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (3840*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 1276; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 8 + 1; + VSYNC_LINES = 10; + SOF_LINES = 72 + 1; + TOTAL_FRAMES = 3; + break; + case HDMI_4k2k_smpte_24: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (4096*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 1020; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 8 + 1; + VSYNC_LINES = 10; + SOF_LINES = 72 + 1; + TOTAL_FRAMES = 3; + break; + case HDMI_4096x2160p25_256x135: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p50_256x135_Y420: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (4096*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 968; + HSYNC_PIXELS = 88; + BACK_PORCH = 128; + EOF_LINES = 8; + VSYNC_LINES = 10; + SOF_LINES = 72; + TOTAL_FRAMES = 3; + break; + case HDMI_4096x2160p30_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_4096x2160p60_256x135_Y420: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (4096*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (2160/(1+INTERLACE_MODE)); + LINES_F0 = 2250; + LINES_F1 = 2250; + FRONT_PORCH = 88; + HSYNC_PIXELS = 88; + BACK_PORCH = 128; + EOF_LINES = 8; + VSYNC_LINES = 10; + SOF_LINES = 72; + TOTAL_FRAMES = 3; + break; + default: + pr_info("hdmitx20: no setting for VIC = %d\n", param->VIC); + break; + } + + TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); + TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + active_pixels_venc = (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + + de_h_begin = modulo(hd_read_reg(P_ENCP_VIDEO_HAVON_BEGIN) + + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DE_H_BEGIN, de_h_begin); + hd_write_reg(P_ENCP_DE_H_END, de_h_end); + /* Program DE timing for even field */ + de_v_begin_even = hd_read_reg(P_ENCP_VIDEO_VAVON_BLINE); + de_v_end_even = modulo(de_v_begin_even + ACTIVE_LINES, TOTAL_LINES); + hd_write_reg(P_ENCP_DE_V_BEGIN_EVEN, de_v_begin_even); + hd_write_reg(P_ENCP_DE_V_END_EVEN, de_v_end_even); + /* Program DE timing for odd field if needed */ + if (INTERLACE_MODE) { + de_v_begin_odd = to_signed( + (hd_read_reg(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + + de_v_begin_even + (TOTAL_LINES-1)/2; + de_v_end_odd = modulo(de_v_begin_odd + ACTIVE_LINES, + TOTAL_LINES); + hd_write_reg(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd); + hd_write_reg(P_ENCP_DE_V_END_ODD, de_v_end_odd); + } + + /* Program Hsync timing */ + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; + vs_adjust = 1; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DVI_HSO_BEGIN, hs_begin); + hd_write_reg(P_ENCP_DVI_HSO_END, hs_end); + + /* Program Vsync timing for even field */ + if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) + vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES + - (1-vs_adjust); + else + vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES + - VSYNC_LINES - (1-vs_adjust); + vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); + hd_write_reg(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); + vso_begin_evn = hs_begin; + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); + hd_write_reg(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); + /* Program Vsync timing for odd field if needed */ + if (INTERLACE_MODE) { + vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; + vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), + total_pixels_venc); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); + hd_write_reg(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); + hd_write_reg(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); + } + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (4 << 5) | + (0 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + hd_write_reg(P_ENCP_VIDEO_EN, 1); +} + +static void hdmi_tvenc480i_set(struct hdmitx_vidpara *param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 1; + unsigned long TOTAL_PIXELS = 0, PIXEL_REPEAT_HDMI = 0, + PIXEL_REPEAT_VENC = 0, ACTIVE_PIXELS = 0; + unsigned int FRONT_PORCH = 38, HSYNC_PIXELS = 124, ACTIVE_LINES = 0, + INTERLACE_MODE = 0, TOTAL_LINES = 0, SOF_LINES = 0, + VSYNC_LINES = 0; + unsigned int LINES_F0 = 262, LINES_F1 = 263, BACK_PORCH = 114, + EOF_LINES = 2, TOTAL_FRAMES = 0; + + unsigned long total_pixels_venc = 0; + unsigned long active_pixels_venc = 0; + unsigned long front_porch_venc = 0; + unsigned long hsync_pixels_venc = 0; + + unsigned long de_h_begin = 0, de_h_end = 0; + unsigned long de_v_begin_even = 0, de_v_end_even = 0, + de_v_begin_odd = 0, de_v_end_odd = 0; + unsigned long hs_begin = 0, hs_end = 0; + unsigned long vs_adjust = 0; + unsigned long vs_bline_evn = 0, vs_eline_evn = 0, + vs_bline_odd = 0, vs_eline_odd = 0; + unsigned long vso_begin_evn = 0, vso_begin_odd = 0; + + hd_set_reg_bits(P_HHI_GCLK_OTHER, 1, 8, 1); + switch (param->VIC) { + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_480i60_16x9_rpt: + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 1; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (480/(1+INTERLACE_MODE)); + LINES_F0 = 262; + LINES_F1 = 263; + FRONT_PORCH = 38; + HSYNC_PIXELS = 124; + BACK_PORCH = 114; + EOF_LINES = 4; + VSYNC_LINES = 3; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + break; + case HDMI_576i50: + case HDMI_576i50_16x9: + case HDMI_576i50_16x9_rpt: + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 1; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (576/(1+INTERLACE_MODE)); + LINES_F0 = 312; + LINES_F1 = 313; + FRONT_PORCH = 24; + HSYNC_PIXELS = 126; + BACK_PORCH = 138; + EOF_LINES = 2; + VSYNC_LINES = 3; + SOF_LINES = 19; + TOTAL_FRAMES = 4; + break; + default: + break; + } + + TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); + TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); /* 1716 / 2 * 2 = 1716 */ + active_pixels_venc = (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); /* 38 / 2 * 2 = 38 */ + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); /* 124 / 2 * 2 = 124 */ + + de_h_begin = modulo(hd_read_reg(P_ENCI_VFIFO2VD_PIXEL_START) + + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCI_DE_H_BEGIN, de_h_begin); /* 235 */ + hd_write_reg(P_ENCI_DE_H_END, de_h_end); /* 1675 */ + + de_v_begin_even = hd_read_reg(P_ENCI_VFIFO2VD_LINE_TOP_START); + de_v_end_even = de_v_begin_even + ACTIVE_LINES; + de_v_begin_odd = hd_read_reg(P_ENCI_VFIFO2VD_LINE_BOT_START); + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; + hd_write_reg(P_ENCI_DE_V_BEGIN_EVEN, de_v_begin_even); + hd_write_reg(P_ENCI_DE_V_END_EVEN, de_v_end_even); + hd_write_reg(P_ENCI_DE_V_BEGIN_ODD, de_v_begin_odd); + hd_write_reg(P_ENCI_DE_V_END_ODD, de_v_end_odd); + + /* Program Hsync timing */ + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCI_DVI_HSO_BEGIN, hs_begin); /* 1713 */ + hd_write_reg(P_ENCI_DVI_HSO_END, hs_end); /* 121 */ + + /* Program Vsync timing for even field */ + if (de_v_end_odd-1 + EOF_LINES + vs_adjust >= LINES_F1) { + vs_bline_evn = de_v_end_odd-1 + EOF_LINES + vs_adjust + - LINES_F1; + vs_eline_evn = vs_bline_evn + VSYNC_LINES; + hd_write_reg(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); + /* vso_bline_evn_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); + /* vso_eline_evn_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_BEGIN_EVN, hs_begin); + hd_write_reg(P_ENCI_DVI_VSO_END_EVN, hs_begin); + } else { + vs_bline_odd = de_v_end_odd-1 + EOF_LINES + vs_adjust; + hd_write_reg(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); + /* vso_bline_odd_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_BEGIN_ODD, hs_begin); + if (vs_bline_odd + VSYNC_LINES >= LINES_F1) { + vs_eline_evn = vs_bline_odd + VSYNC_LINES - LINES_F1; + hd_write_reg(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); + /* vso_eline_evn_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_END_EVN, hs_begin); + } else { + vs_eline_odd = vs_bline_odd + VSYNC_LINES; + hd_write_reg(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); + /* vso_eline_odd_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_END_ODD, hs_begin); + } + } + /* Program Vsync timing for odd field */ + if (de_v_end_even-1 + EOF_LINES + 1 >= LINES_F0) { + vs_bline_odd = de_v_end_even-1 + EOF_LINES + 1 - LINES_F0; + vs_eline_odd = vs_bline_odd + VSYNC_LINES; + hd_write_reg(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); + /* vso_bline_odd_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); + /* vso_eline_odd_reg_wr_cnt ++; */ + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), + total_pixels_venc); + hd_write_reg(P_ENCI_DVI_VSO_BEGIN_ODD, vso_begin_odd); + hd_write_reg(P_ENCI_DVI_VSO_END_ODD, vso_begin_odd); + } else { + vs_bline_evn = de_v_end_even-1 + EOF_LINES + 1; + hd_write_reg(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); /* 261 */ + /* vso_bline_evn_reg_wr_cnt ++; */ + vso_begin_evn = modulo(hs_begin + (total_pixels_venc>>1), + total_pixels_venc); + hd_write_reg(P_ENCI_DVI_VSO_BEGIN_EVN, vso_begin_evn); + if (vs_bline_evn + VSYNC_LINES >= LINES_F0) { + vs_eline_odd = vs_bline_evn + VSYNC_LINES - LINES_F0; + hd_write_reg(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); + /* vso_eline_odd_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_END_ODD, vso_begin_evn); + } else { + vs_eline_evn = vs_bline_evn + VSYNC_LINES; + hd_write_reg(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); + /* vso_eline_evn_reg_wr_cnt ++; */ + hd_write_reg(P_ENCI_DVI_VSO_END_EVN, vso_begin_evn); + } + } + + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (0 << 2) | + (0 << 3) | + (0 << 4) | + (4 << 5) | + (1 << 8) | + (1 << 12) + ); + if ((param->VIC == HDMI_480i60_16x9_rpt) || + (param->VIC == HDMI_576i50_16x9_rpt)) + hd_set_reg_bits(P_VPU_HDMI_SETTING, 3, 12, 4); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 0, 1); +} + +static void hdmi_tvenc_set(struct hdmitx_vidpara *param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; + unsigned long TOTAL_PIXELS = 0, PIXEL_REPEAT_HDMI = 0, + PIXEL_REPEAT_VENC = 0, ACTIVE_PIXELS = 0; + unsigned int FRONT_PORCH = 0, HSYNC_PIXELS = 0, ACTIVE_LINES = 0, + INTERLACE_MODE = 0, TOTAL_LINES = 0, SOF_LINES = 0, + VSYNC_LINES = 0; + unsigned int LINES_F0 = 0, LINES_F1 = 0, BACK_PORCH = 0, + EOF_LINES = 0, TOTAL_FRAMES = 0; + + unsigned long total_pixels_venc = 0; + unsigned long active_pixels_venc = 0; + unsigned long front_porch_venc = 0; + unsigned long hsync_pixels_venc = 0; + + unsigned long de_h_begin = 0, de_h_end = 0; + unsigned long de_v_begin_even = 0, de_v_end_even = 0, + de_v_begin_odd = 0, de_v_end_odd = 0; + unsigned long hs_begin = 0, hs_end = 0; + unsigned long vs_adjust = 0; + unsigned long vs_bline_evn = 0, vs_eline_evn = 0, + vs_bline_odd = 0, vs_eline_odd = 0; + unsigned long vso_begin_evn = 0, vso_begin_odd = 0; + + switch (param->VIC) { + case HDMI_3840x1080p120hz: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = 3840; + ACTIVE_LINES = 1080; + LINES_F0 = 1125; + LINES_F1 = 1125; + FRONT_PORCH = 176; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 4; + VSYNC_LINES = 5; + SOF_LINES = 36; + TOTAL_FRAMES = 0; + break; + case HDMI_3840x1080p100hz: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = 3840; + ACTIVE_LINES = 1080; + LINES_F0 = 1125; + LINES_F1 = 1125; + FRONT_PORCH = 1056; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 4; + VSYNC_LINES = 5; + SOF_LINES = 36; + TOTAL_FRAMES = 0; + break; + case HDMI_3840x540p240hz: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = 3840; + ACTIVE_LINES = 1080; + LINES_F0 = 562; + LINES_F1 = 562; + FRONT_PORCH = 176; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 2; + VSYNC_LINES = 2; + SOF_LINES = 18; + TOTAL_FRAMES = 0; + break; + case HDMI_3840x540p200hz: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = 3840; + ACTIVE_LINES = 1080; + LINES_F0 = 562; + LINES_F1 = 562; + FRONT_PORCH = 1056; + HSYNC_PIXELS = 88; + BACK_PORCH = 296; + EOF_LINES = 2; + VSYNC_LINES = 2; + SOF_LINES = 18; + TOTAL_FRAMES = 0; + break; + case HDMI_480p60: + case HDMI_480p60_16x9: + case HDMI_480p60_16x9_rpt: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (480/(1+INTERLACE_MODE)); + LINES_F0 = 525; + LINES_F1 = 525; + FRONT_PORCH = 16; + HSYNC_PIXELS = 62; + BACK_PORCH = 60; + EOF_LINES = 9; + VSYNC_LINES = 6; + SOF_LINES = 30; + TOTAL_FRAMES = 4; + break; + case HDMI_576p50: + case HDMI_576p50_16x9: + case HDMI_576p50_16x9_rpt: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (576/(1+INTERLACE_MODE)); + LINES_F0 = 625; + LINES_F1 = 625; + FRONT_PORCH = 12; + HSYNC_PIXELS = 64; + BACK_PORCH = 68; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 39; + TOTAL_FRAMES = 4; + break; + case HDMI_720p60: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (720/(1+INTERLACE_MODE)); + LINES_F0 = 750; + LINES_F1 = 750; + FRONT_PORCH = 110; + HSYNC_PIXELS = 40; + BACK_PORCH = 220; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 20; + TOTAL_FRAMES = 4; + break; + case HDMI_720p50: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (720/(1+INTERLACE_MODE)); + LINES_F0 = 750; + LINES_F1 = 750; + FRONT_PORCH = 440; + HSYNC_PIXELS = 40; + BACK_PORCH = 220; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 20; + TOTAL_FRAMES = 4; + break; + case HDMI_1080p50: + case HDMI_1080p25: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); + LINES_F0 = 1125; + LINES_F1 = 1125; + FRONT_PORCH = 528; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 4; + VSYNC_LINES = 5; + SOF_LINES = 36; + TOTAL_FRAMES = 4; + break; + case HDMI_1080p24: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); + LINES_F0 = 1125; + LINES_F1 = 1125; + FRONT_PORCH = 638; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 4; + VSYNC_LINES = 5; + SOF_LINES = 36; + TOTAL_FRAMES = 4; + break; + case HDMI_1080p60: + case HDMI_1080p30: + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 0; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); + LINES_F0 = 1125; + LINES_F1 = 1125; + FRONT_PORCH = 88; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 4; + VSYNC_LINES = 5; + SOF_LINES = 36; + TOTAL_FRAMES = 4; + break; + default: + break; + } + + TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); + TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + active_pixels_venc = (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * + (1+PIXEL_REPEAT_VENC); + + hd_write_reg(P_ENCP_VIDEO_MODE, hd_read_reg(P_ENCP_VIDEO_MODE)|(1<<14)); + /* Program DE timing */ + de_h_begin = modulo(hd_read_reg(P_ENCP_VIDEO_HAVON_BEGIN) + + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DE_H_BEGIN, de_h_begin); /* 220 */ + hd_write_reg(P_ENCP_DE_H_END, de_h_end); /* 1660 */ + /* Program DE timing for even field */ + de_v_begin_even = hd_read_reg(P_ENCP_VIDEO_VAVON_BLINE); + de_v_end_even = de_v_begin_even + ACTIVE_LINES; + hd_write_reg(P_ENCP_DE_V_BEGIN_EVEN, de_v_begin_even); + hd_write_reg(P_ENCP_DE_V_END_EVEN, de_v_end_even); /* 522 */ + /* Program DE timing for odd field if needed */ + if (INTERLACE_MODE) { + de_v_begin_odd = to_signed( + (hd_read_reg(P_ENCP_VIDEO_OFLD_VOAV_OFST) + & 0xf0)>>4) + de_v_begin_even + (TOTAL_LINES-1)/2; + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; + hd_write_reg(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd); + hd_write_reg(P_ENCP_DE_V_END_ODD, de_v_end_odd); + } + + /* Program Hsync timing */ + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); + hd_write_reg(P_ENCP_DVI_HSO_BEGIN, hs_begin); + hd_write_reg(P_ENCP_DVI_HSO_END, hs_end); + + /* Program Vsync timing for even field */ + if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) + vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES - + (1-vs_adjust); + else + vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES - + VSYNC_LINES - (1-vs_adjust); + vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); /* 5 */ + hd_write_reg(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); /* 11 */ + vso_begin_evn = hs_begin; /* 1692 */ + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); /* 1692 */ + hd_write_reg(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); /* 1692 */ + /* Program Vsync timing for odd field if needed */ + if (INTERLACE_MODE) { + vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; + vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), + total_pixels_venc); + hd_write_reg(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); + hd_write_reg(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); + hd_write_reg(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); + hd_write_reg(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); + } + if ((param->VIC == HDMI_3840x540p240hz) || + (param->VIC == HDMI_3840x540p200hz)) + hd_write_reg(P_ENCP_DE_V_END_EVEN, 0x230); + switch (param->VIC) { + case HDMI_3840x1080p120hz: + case HDMI_3840x1080p100hz: + case HDMI_3840x540p240hz: + case HDMI_3840x540p200hz: + hd_write_reg(P_VPU_HDMI_SETTING, 0x8e); + break; + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + case HDMI_480i60_16x9_rpt: + case HDMI_576i50_16x9_rpt: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (0 << 2) | + (0 << 3) | + (0 << 4) | + (4 << 5) | + (1 << 8) | + (1 << 12) + ); + if ((param->VIC == HDMI_480i60_16x9_rpt) || + (param->VIC == HDMI_576i50_16x9_rpt)) + hd_set_reg_bits(P_VPU_HDMI_SETTING, 3, 12, 4); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 0, 1); + break; + case HDMI_1080i60: + case HDMI_1080i50: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (0 << 5) | + (1 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + break; + case HDMI_4k2k_30: + case HDMI_4k2k_25: + case HDMI_4k2k_24: + case HDMI_4k2k_smpte_24: + case HDMI_4096x2160p25_256x135: + case HDMI_4096x2160p30_256x135: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (4 << 5) | + (0 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + hd_write_reg(P_ENCP_VIDEO_EN, 1); /* Enable VENC */ + break; + case HDMI_480p60_16x9_rpt: + case HDMI_576p50_16x9_rpt: + case HDMI_480p60: + case HDMI_480p60_16x9: + case HDMI_576p50: + case HDMI_576p50_16x9: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (0 << 2) | + (0 << 3) | + (0 << 4) | + (4 << 5) | + (1 << 8) | + (0 << 12) + ); + if ((param->VIC == HDMI_480p60_16x9_rpt) || + (param->VIC == HDMI_576p50_16x9_rpt)) + hd_set_reg_bits(P_VPU_HDMI_SETTING, 3, 12, 4); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + break; + case HDMI_720p60: + case HDMI_720p50: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (4 << 5) | + (1 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + break; + default: + hd_write_reg(P_VPU_HDMI_SETTING, (0 << 0) | + (0 << 1) | /* [ 1] src_sel_encp */ + (HSYNC_POLARITY << 2) | + (VSYNC_POLARITY << 3) | + (0 << 4) | + (4 << 5) | + (0 << 8) | + (0 << 12) + ); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); + } + if ((param->VIC == HDMI_480p60_16x9_rpt) || + (param->VIC == HDMI_576p50_16x9_rpt)) + hd_set_reg_bits(P_VPU_HDMI_SETTING, 3, 12, 4); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); +} + +static void digital_clk_off(unsigned char flag) +{ + /* TODO */ +} + +static void digital_clk_on(unsigned char flag) +{ +/* clk81_set(); */ + if (flag&4) { + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 3); + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); + } + if (flag&2) { + /* on hdmi pixel clock */ + hd_write_reg(P_HHI_GCLK_MPEG2, + hd_read_reg(P_HHI_GCLK_MPEG2) | (1<<4)); + hd_write_reg(P_HHI_GCLK_OTHER, + hd_read_reg(P_HHI_GCLK_OTHER)|(1<<17)); + } +} + +void phy_pll_off(void) +{ + hdmi_phy_suspend(); +} + +static void hdmi_audio_init(unsigned int spdif_flag) +{ + return; + /* TODO */ +} + +/************************************ + * hdmitx hardware level interface + *************************************/ + +static void hdmitx_dump_tvenc_reg(int cur_VIC, int pr_info_flag) +{ +} + +static void hdmitx_config_tvenc_reg(int vic, unsigned int reg, + unsigned int val) +{ +} + +static void hdmitx_set_pll(struct hdmitx_dev *hdev) +{ + hdmi_print(IMP, SYS "set pll\n"); + hdmi_print(IMP, SYS "param->VIC:%d\n", hdev->cur_video_param->VIC); + + set_vmode_clk(hdev); +} + +static void set_phy_by_mode(unsigned int mode) +{ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + switch (mode) { + case 1: /* 5.94Gbps, 3.7125Gbsp */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x333d3282); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2136315b); + break; + case 2: /* 2.97Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33303382); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2036315b); + break; + case 3: /* 1.485Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33303042); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2016315b); + break; + default: /* 742.5Mbps, and below */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33604132); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x0016315b); + break; + } + return; + } + + /* other than GXL */ + switch (mode) { + case 1: /* 5.94Gbps, 3.7125Gbsp */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33353245); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2100115b); + break; + case 2: /* 2.97Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33634283); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0xb000115b); + break; + case 3: /* 1.485Gbps, and below */ + default: + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33632122); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2000115b); + break; + } +} + +static void hdmitx_set_phy(struct hdmitx_dev *hdev) +{ + if (!hdev) + return; + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x0); +#if 1 +/* P_HHI_HDMI_PHY_CNTL1 bit[1]: enable clock bit[0]: soft reset */ +#define RESET_HDMI_PHY() \ +do { \ + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0xf, 0, 4); \ + mdelay(2); \ + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0xe, 0, 4); \ + mdelay(2); \ +} while (0) + + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0390, 16, 16); + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x1, 17, 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 17, 1); + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 0, 4); + msleep(100); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); +#undef RESET_HDMI_PHY +#endif + switch (hdev->cur_VIC) { + case HDMI_4k2k_24: + case HDMI_4k2k_25: + case HDMI_4k2k_30: + case HDMI_4k2k_smpte_24: + case HDMI_4096x2160p25_256x135: + case HDMI_4096x2160p30_256x135: + if ((hdev->para->cs == COLORSPACE_YUV422) + || (hdev->para->cd == COLORDEPTH_24B)) + set_phy_by_mode(2); + else + set_phy_by_mode(1); + break; + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + if (hdev->para->cs == COLORSPACE_YUV420) + set_phy_by_mode(2); + else + set_phy_by_mode(1); + break; + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + if (hdev->para->cd == COLORDEPTH_24B) + set_phy_by_mode(2); + else + set_phy_by_mode(1); + break; + case HDMI_1080p60: + case HDMI_1080p50: + if (hdev->flag_3dfp) + set_phy_by_mode(2); + else + set_phy_by_mode(3); + break; + default: + if (hdev->flag_3dfp) + set_phy_by_mode(3); + else + set_phy_by_mode(4); + break; + } + hdmi_print(IMP, SYS "PHY Setting Done\n"); +} + +static void set_tmds_clk_div40(unsigned int div40) +{ + pr_info("hdmitx div40: %d\n", div40); + if (div40) { + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_01, 0); + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_23, 0x03ff03ff); + } else { + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f); + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f); + } + hdmitx_set_reg_bits(HDMITX_DWC_FC_SCRAMBLER_CTRL, !!div40, 0, 1); + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1); + msleep(20); + hdmitx_wr_reg(HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2); +} + +static int hdmitx_set_dispmode(struct hdmitx_dev *hdev) +{ + unsigned char rx_ver = 0; + + if (hdev->cur_video_param == NULL) /* disable HDMI */ + return 0; + if (!hdmitx_edid_VIC_support(hdev->cur_video_param->VIC)) + return -1; + hdev->cur_VIC = hdev->cur_video_param->VIC; + if (hdev->RXCap.scdc_present) + pr_info("hdmitx: rx has SCDC present indicator\n"); + else + pr_info("hdmitx: rx no SCDC present indicator\n"); + + scdc_rd_sink(SINK_VER, &rx_ver); + if (rx_ver != 1) + scdc_rd_sink(SINK_VER, &rx_ver); /* Recheck */ + pr_info("hdmirx version is %s\n", + (rx_ver == 1) ? "2.0" : "1.4 or below"); + + switch (hdev->cur_VIC) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + if ((hdev->para->cs == COLORSPACE_YUV420) + && (hdev->para->cd == COLORDEPTH_24B)) + hdev->para->tmds_clk_div40 = 0; + else + hdev->para->tmds_clk_div40 = 1; + break; + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + case HDMI_3840x2160p50_64x27_Y420: + case HDMI_3840x2160p60_64x27_Y420: + if (hdev->para->cd == COLORDEPTH_24B) + hdev->para->tmds_clk_div40 = 0; + else + hdev->para->tmds_clk_div40 = 1; + break; + case HDMI_3840x2160p24_16x9: + case HDMI_3840x2160p24_64x27: + case HDMI_3840x2160p25_16x9: + case HDMI_3840x2160p25_64x27: + case HDMI_3840x2160p30_16x9: + case HDMI_3840x2160p30_64x27: + if ((hdev->para->cs == COLORSPACE_YUV422) + || (hdev->para->cd == COLORDEPTH_24B)) + hdev->para->tmds_clk_div40 = 0; + else + hdev->para->tmds_clk_div40 = 1; + break; + default: + hdev->para->tmds_clk_div40 = 0; + break; + } + set_tmds_clk_div40(hdev->para->tmds_clk_div40); + scdc_config(hdev); + + if (color_depth_f == 24) + hdev->cur_video_param->color_depth = COLORDEPTH_24B; + else if (color_depth_f == 30) + hdev->cur_video_param->color_depth = COLORDEPTH_30B; + else if (color_depth_f == 36) + hdev->cur_video_param->color_depth = COLORDEPTH_36B; + else if (color_depth_f == 48) + hdev->cur_video_param->color_depth = COLORDEPTH_48B; + hdmi_print(INF, SYS "set mode VIC %d (cd%d,cs%d,pm%d,vd%d,%x)\n", + hdev->cur_video_param->VIC, color_depth_f, COLORSPACE_f, + power_mode, power_off_vdac_flag, serial_reg_val); + if (COLORSPACE_f != 0) + hdev->cur_video_param->color = COLORSPACE_f; + hdmitx_set_pll(hdev); + /*hdmitx_set_phy(hdev);*/ + if (hdev->flag_3dfp) + set_vmode_3dfp_enc_hw(hdev->cur_video_param->VIC); + else + set_vmode_enc_hw(hdev->cur_video_param->VIC); + if (hdev->flag_3dfp) { + hd_write_reg(P_VPU_HDMI_SETTING, 0x8e); + goto next; + } + switch (hdev->cur_video_param->VIC) { + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + case HDMI_480i60_16x9_rpt: + case HDMI_576i50_16x9_rpt: + hdmi_tvenc480i_set(hdev->cur_video_param); + break; + case HDMI_1080i60: + case HDMI_1080i50: + hdmi_tvenc1080i_set(hdev->cur_video_param); + break; + case HDMI_4k2k_30: + case HDMI_4k2k_25: + case HDMI_4k2k_24: + case HDMI_4k2k_smpte_24: + case HDMI_4096x2160p25_256x135: + case HDMI_4096x2160p30_256x135: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + hdmi_tvenc4k2k_set(hdev->cur_video_param); + break; + default: + hdmi_tvenc_set(hdev->cur_video_param); + } +next: +/* [ 3: 2] chroma_dnsmp. 0=use pixel 0; 1=use pixel 1; 2=use average. */ +/* [ 5] hdmi_dith_md: random noise selector. */ + hd_write_reg(P_VPU_HDMI_FMT_CTRL, (((TX_INPUT_COLOR_FORMAT == + COLORSPACE_YUV420) ? 2 : 0) << 0) | (2 << 2) | + (0 << 4) | /* [4]dith_en: disable dithering */ + (0 << 5) | + (0 << 6)); /* [ 9: 6] hdmi_dith10_cntl. */ + if (hdev->para->cs == COLORSPACE_YUV420) { + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 2, 0, 2); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 4, 4); + hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 8, 1); + } + switch (hdev->para->cd) { + case COLORDEPTH_30B: + case COLORDEPTH_36B: + case COLORDEPTH_48B: + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) { + unsigned int hs_flag = 0; + /* 12-10 dithering on */ + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 1, 4, 1); + /* hsync/vsync not invert */ + hs_flag = (hd_read_reg(P_VPU_HDMI_SETTING) >> 2) & 0x3; + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 2, 2); + /* 12-10 rounding off */ + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 10, 1); + /* 10-8 dithering off (2x2 old dither) */ + hd_set_reg_bits(P_VPU_HDMI_DITH_CNTL, 0, 4, 1); + /* set hsync/vsync */ + hd_set_reg_bits(P_VPU_HDMI_DITH_CNTL, hs_flag, 2, 2); + } else { + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 4, 1); + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 10, 1); + } + break; + default: + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) { + /* 12-10 dithering off */ + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 4, 1); + /* 12-10 rounding on */ + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 1, 10, 1); + /* 10-8 dithering on (2x2 old dither) */ + hd_set_reg_bits(P_VPU_HDMI_DITH_CNTL, 1, 4, 1); + /* set hsync/vsync as default 0 */ + hd_set_reg_bits(P_VPU_HDMI_DITH_CNTL, 0, 2, 2); + } else { + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 4, 1); + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 1, 10, 1); + } + break; + } + + hdmitx_set_hw(hdev); + + /* move hdmitx_set_pll() to the end of this function. */ + /* hdmitx_set_pll(param); */ + hdev->cur_VIC = hdev->cur_video_param->VIC; + if ((!hdev->flag_3dfp) && (!hdev->flag_3dtb) && (!hdev->flag_3dss)) + hdmitx_set_phy(hdev); + switch (hdev->cur_video_param->VIC) { + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + case HDMI_480i60_16x9_rpt: + case HDMI_576i50_16x9_rpt: + enc_vpu_bridge_reset(0); + break; + default: + enc_vpu_bridge_reset(1); + break; + } + + if (hdev->para->cs == COLORSPACE_YUV420) { + /* change AVI packet */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, 0x3, 0, 2); + mode420_half_horizontal_para(); + } else { + /* change AVI packet */ + unsigned int indicator = 0; + unsigned int data32 = 0x0; + + switch (hdev->para->cs) { + case COLORSPACE_RGB444: + indicator = 0x0; + break; + case COLORSPACE_YUV422: + indicator = 0x1; + break; + case COLORSPACE_YUV444: + default: + indicator = 0x2; + break; + case COLORSPACE_YUV420: + indicator = 0x3; + break; + } + data32 = (0x40 | ((indicator&0x4)<<5) | (indicator&0x3)); + hdmitx_wr_reg(HDMITX_DWC_FC_AVICONF0, data32); + } + + hdmitx_set_reg_bits(HDMITX_DWC_FC_INVIDCONF, 0, 3, 1); + mdelay(1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_INVIDCONF, 1, 3, 1); + + return 0; +} + +static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) +{ + int i; + int pkt_data_len = 0; + + switch (type) { + case HDMI_PACKET_AVI: + break; + case HDMI_PACKET_VEND: + if ((!DB) || (!HB)) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); + return; + } + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, DB[1]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0, DB[3]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, HB[2]); + if (DB[3] == 0x20) { /* set HDMI VIC */ + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); + } + if (DB[3] == 0x40) { /* 3D VSI */ + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD2, DB[5]); + if ((DB[4] >> 4) == T3D_FRAME_PACKING) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 5); + else + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 6); + } + /* Enable VSI packet */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO2, 0x10); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 4, 1); + break; + case HDMI_PACKET_DRM: + pkt_data_len = 26; + if ((!DB) || (!HB)) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 0, 6, 1); + hdmitx_set_reg_bits( + HDMITX_DWC_FC_PACKET_TX_EN, 0, 7, 1); + return; + } + /* Ignore HB[0] */ + hdmitx_wr_reg(HDMITX_DWC_FC_DRM_HB01, HB[1]); + hdmitx_wr_reg(HDMITX_DWC_FC_DRM_HB02, HB[2]); + for (i = 0; i < pkt_data_len; i++) + hdmitx_wr_reg(HDMITX_DWC_FC_DRM_PB00 + i, DB[i]); + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 1, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 7, 1); + break; + case HDMI_AUDIO_INFO: + pkt_data_len = 9; + break; + case HDMI_SOURCE_DESCRIPTION: + pkt_data_len = 25; + for (i = 0; i < 25; i++) + hdmitx_wr_reg(HDMITX_DWC_FC_SPDVENDORNAME0 + i, DB[i]); + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 4, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO2, 0x1, 4, 4); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 4, 1); + break; + default: + break; + } +} + + +static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, + unsigned char *CHAN_STAT_BUF) +{ +} + + +/* set_hdmi_audio_source(unsigned int src) */ +/* Description: */ +/* Select HDMI audio clock source, and I2S input data source. */ +/* Parameters: */ +/* src -- 0=no audio clock to HDMI; 1=pcmout to HDMI; 2=Aiu I2S out to HDMI. */ +static void set_hdmi_audio_source(unsigned int src) +{ + unsigned long data32; + + /* Disable HDMI audio clock input and its I2S input */ + data32 = 0; + data32 |= (0 << 4); + data32 |= (0 << 0); + hd_write_reg(P_AIU_HDMI_CLK_DATA_CTRL, data32); + + /* Enable HDMI I2S input from the selected source */ + data32 = 0; + data32 |= (src << 4); + data32 |= (src << 0); + hd_write_reg(P_AIU_HDMI_CLK_DATA_CTRL, data32); +} /* set_hdmi_audio_source */ + +/* 60958-3 bit 27-24 */ +static unsigned char aud_csb_sampfreq[FS_MAX + 1] = { + [FS_REFER_TO_STREAM] = 0x1, /* not indicated */ + [FS_32K] = 0x3, /* FS_32K */ + [FS_44K1] = 0x0, /* FS_44K1 */ + [FS_48K] = 0x2, /* FS_48K */ + [FS_88K2] = 0x8, /* FS_88K2 */ + [FS_96K] = 0xa, /* FS_96K */ + [FS_176K4] = 0xc, /* FS_176K4 */ + [FS_192K] = 0xe, /* FS_192K */ + [FS_768K] = 0x9, /* FS_768K */ +}; + +/* 60958-3 bit 39:36 */ +static unsigned char aud_csb_ori_sampfreq[FS_MAX + 1] = { + [FS_REFER_TO_STREAM] = 0x0, /* not indicated */ + [FS_32K] = 0xc, /* FS_32K */ + [FS_44K1] = 0xf, /* FS_44K1 */ + [FS_48K] = 0xd, /* FS_48K */ + [FS_88K2] = 0x7, /* FS_88K2 */ + [FS_96K] = 0xa, /* FS_96K */ + [FS_176K4] = 0x3, /* FS_176K4 */ + [FS_192K] = 0x1, /* FS_192K */ +}; + +static void set_aud_chnls(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param) +{ + int i; + + pr_info("hdmitx set channel status\n"); + for (i = 0; i < 9; i++) + /* First, set all status to 0 */ + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS0+i, 0x00); + /* set default 48k 2ch pcm */ + if ((audio_param->type == CT_PCM) && + (audio_param->channel_num == (2 - 1))) { + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSV, 0x11); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS7, 0x02); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS8, 0xd2); + } else { + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSV, 0xff); + } + switch (audio_param->type) { + case CT_AC_3: + case CT_DOLBY_D: + case CT_DST: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS3, 0x01); /* CSB 20 */ + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS5, 0x02); /* CSB 21 */ + break; + default: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS3, 0x00); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS5, 0x00); + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCHNLS7, + aud_csb_sampfreq[audio_param->sample_rate], 0, 4); /*CSB 27:24*/ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCHNLS7, 0x0, 6, 2); /*CSB 31:30*/ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCHNLS7, 0x0, 4, 2); /*CSB 29:28*/ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCHNLS8, 0x2, 0, 4); /*CSB 35:32*/ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCHNLS8, /* CSB 39:36 */ + aud_csb_ori_sampfreq[audio_param->sample_rate], 4, 4); +} + +#define GET_OUTCHN_NO(a) (((a) >> 4) & 0xf) +#define GET_OUTCHN_MSK(a) ((a) & 0xf) + +static void set_aud_info_pkt(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param) +{ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, 0, 0, 4); /* CT */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, audio_param->channel_num, + 4, 3); /* CC */ + if (GET_OUTCHN_NO(hdev->aud_output_ch)) + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, + GET_OUTCHN_NO(hdev->aud_output_ch) - 1, 4, 3); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF1, 0, 0, 3); /* SF */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF1, 0, 4, 2); /* SS */ + switch (audio_param->type) { + case CT_MAT: + case CT_DTS_HD_MA: + /* CC: 8ch */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, 7, 4, 3); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x13); + break; + case CT_PCM: + if (!hdev->aud_output_ch) + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, + audio_param->channel_num, 4, 3); + if ((audio_param->channel_num == 0x7) && (!hdev->aud_output_ch)) + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x13); + else + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x00); + /* Refer to CEA861-D P90 */ + switch (GET_OUTCHN_NO(hdev->aud_output_ch)) { + case 2: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x00); + break; + case 4: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x03); + break; + case 6: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x0b); + break; + case 8: + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x13); + break; + default: + break; + } + break; + case CT_DTS: + case CT_DTS_HD: + default: + /* CC: 2ch */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDICONF0, 1, 4, 3); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x0); + break; + } + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF3, 0); +} + +static void set_aud_acr_pkt(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param) +{ + unsigned int data32; + unsigned int aud_n_para; + unsigned int char_rate; + + /* audio packetizer config */ + hdmitx_wr_reg(HDMITX_DWC_AUD_INPUTCLKFS, tx_aud_src ? 4 : 0); + + if ((audio_param->type == CT_MAT) + || (audio_param->type == CT_DTS_HD_MA)) + hdmitx_wr_reg(HDMITX_DWC_AUD_INPUTCLKFS, 2); + + if ((hdev->frac_rate_policy) && (hdev->para->timing.frac_freq)) + char_rate = hdev->para->timing.frac_freq; + else + char_rate = hdev->para->timing.pixel_freq; + if (hdev->para->cs == COLORSPACE_YUV422) + aud_n_para = hdmi_get_aud_n_paras(audio_param->sample_rate, + COLORDEPTH_24B, char_rate); + else + aud_n_para = hdmi_get_aud_n_paras(audio_param->sample_rate, + hdev->para->cd, char_rate); + /* N must mutiples 4 for DD+ */ + switch (audio_param->type) { + case CT_DOLBY_D: + aud_n_para *= 4; + break; + default: + break; + } + pr_info("hdmitx aud_n_para = %d\n", aud_n_para); + + /* ACR packet configuration */ + data32 = 0; + data32 |= (1 << 7); /* [ 7] ncts_atomic_write */ + data32 |= (0 << 0); /* [3:0] AudN[19:16] */ + hdmitx_wr_reg(HDMITX_DWC_AUD_N3, data32); + + data32 = 0; + data32 |= (0 << 7); /* [7:5] N_shift */ + data32 |= (0 << 4); /* [ 4] CTS_manual */ + data32 |= (0 << 0); /* [3:0] manual AudCTS[19:16] */ + hdmitx_wr_reg(HDMITX_DWC_AUD_CTS3, data32); + + hdmitx_wr_reg(HDMITX_DWC_AUD_CTS2, 0); /* manual AudCTS[15:8] */ + hdmitx_wr_reg(HDMITX_DWC_AUD_CTS1, 0); /* manual AudCTS[7:0] */ + + data32 = 0; + data32 |= (1 << 7); /* [ 7] ncts_atomic_write */ + data32 |= (((aud_n_para>>16)&0xf) << 0); /* [3:0] AudN[19:16] */ + hdmitx_wr_reg(HDMITX_DWC_AUD_N3, data32); + hdmitx_wr_reg(HDMITX_DWC_AUD_N2, (aud_n_para>>8)&0xff); /* AudN[15:8] */ + hdmitx_wr_reg(HDMITX_DWC_AUD_N1, aud_n_para&0xff); /* AudN[7:0] */ +} + +static void set_aud_fifo_rst(void) +{ + /* reset audio fifo */ + hdmitx_set_reg_bits(HDMITX_DWC_AUD_CONF0, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_CONF0, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF0, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF0, 0, 7, 1); + hdmitx_wr_reg(HDMITX_DWC_MC_SWRSTZREQ, 0xe7); + /* need reset again */ + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF0, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF0, 0, 7, 1); +} + +static void set_aud_samp_pkt(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param) +{ + switch (audio_param->type) { + case CT_MAT: /* HBR */ + case CT_DTS_HD_MA: + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 1, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 24, 0, 5); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 1, 0, 1); + break; + case CT_PCM: /* AudSamp */ + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 0, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 24, 0, 5); + if ((audio_param->channel_num == 0x7) && (!hdev->aud_output_ch)) + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 1, 0, 1); + else + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 0, 0, 1); + switch (GET_OUTCHN_NO(hdev->aud_output_ch)) { + case 2: + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 0, 0, 1); + break; + case 4: + case 6: + case 8: + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 1, 0, 1); + break; + default: + break; + } + break; + case CT_AC_3: + case CT_DOLBY_D: + case CT_DTS: + case CT_DTS_HD: + default: + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 0, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_AUD_SPDIF1, 24, 0, 5); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AUDSCONF, 0, 0, 1); + break; + } +} + +static void audio_mute_op(bool flag) +{ + if (flag == 0) { + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 0, 2, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 0, 0, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 0, 3, 1); + } else { + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 3, 2, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 0, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 3, 1); + } +} + +static int hdmitx_set_audmode(struct hdmitx_dev *hdev, + struct hdmitx_audpara *audio_param) +{ + unsigned int data32; + + if (!hdev) + return 0; + if (!audio_param) + return 0; + pr_info("hdmtix: set audio\n"); + audio_mute_op(hdev->tx_aud_cfg); + /* PCM & 8 ch */ + if ((audio_param->type == CT_PCM) && + (audio_param->channel_num == (8 - 1))) + tx_aud_src = 1; + else + tx_aud_src = 0; + + /* if hdev->aud_output_ch is true, select I2S as 8ch in, 2ch out */ + if (hdev->aud_output_ch) + tx_aud_src = 1; + + pr_info("hdmitx tx_aud_src = %d\n", tx_aud_src); + + /* set_hdmi_audio_source(tx_aud_src ? 1 : 2); */ + set_hdmi_audio_source(2); + +/* config IP */ +/* Configure audio */ + /* I2S Sampler config */ + data32 = 0; +/* [ 3] fifo_empty_mask: 0=enable int; 1=mask int. */ + data32 |= (1 << 3); +/* [ 2] fifo_full_mask: 0=enable int; 1=mask int. */ + data32 |= (1 << 2); + hdmitx_wr_reg(HDMITX_DWC_AUD_INT, data32); + + data32 = 0; +/* [ 4] fifo_overrun_mask: 0=enable int; 1=mask int. + * Enable it later when audio starts. + */ + data32 |= (1 << 4); + hdmitx_wr_reg(HDMITX_DWC_AUD_INT1, data32); +/* [ 5] 0=select SPDIF; 1=select I2S. */ + data32 = 0; + data32 |= (0 << 7); /* [ 7] sw_audio_fifo_rst */ + data32 |= (tx_aud_src << 5); + data32 |= (0 << 0); /* [3:0] i2s_in_en: enable it later in test.c */ +/* if enable it now, fifo_overrun will happen, because packet don't get sent + * out until initial DE detected. + */ + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF0, data32); + + data32 = 0; + data32 |= (0 << 5); /* [7:5] i2s_mode: 0=standard I2S mode */ + data32 |= (24 << 0); /* [4:0] i2s_width */ + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF1, data32); + + data32 = 0; + data32 |= (0 << 1); /* [ 1] NLPCM */ + data32 |= (0 << 0); /* [ 0] HBR */ + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF2, data32); + + /* spdif sampler config */ +/* [ 2] SPDIF fifo_full_mask: 0=enable int; 1=mask int. */ +/* [ 3] SPDIF fifo_empty_mask: 0=enable int; 1=mask int. */ + data32 = 0; + data32 |= (1 << 3); + data32 |= (1 << 2); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIFINT, data32); + /* [ 4] SPDIF fifo_overrun_mask: 0=enable int; 1=mask int. */ + data32 = 0; + data32 |= (0 << 4); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIFINT1, data32); + + data32 = 0; + data32 |= (0 << 7); /* [ 7] sw_audio_fifo_rst */ + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIF0, data32); + + set_aud_info_pkt(hdev, audio_param); + set_aud_acr_pkt(hdev, audio_param); + set_aud_samp_pkt(hdev, audio_param); + + set_aud_chnls(hdev, audio_param); + + hdmitx_set_reg_bits(HDMITX_DWC_AUD_CONF0, tx_aud_src, 5, 1); + if (tx_aud_src == 1) { + if (GET_OUTCHN_MSK(hdev->aud_output_ch)) + hdmitx_set_reg_bits(HDMITX_DWC_AUD_CONF0, + GET_OUTCHN_MSK(hdev->aud_output_ch), 0, 4); + else + hdmitx_set_reg_bits(HDMITX_DWC_AUD_CONF0, 0xf, 0, 4); + /* Enable audi2s_fifo_overrun interrupt */ + hdmitx_wr_reg(HDMITX_DWC_AUD_INT1, + hdmitx_rd_reg(HDMITX_DWC_AUD_INT1) & (~(1<<4))); + /* Wait for 40 us for TX I2S decoder to settle */ + msleep(20); + } + set_aud_fifo_rst(); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_AUD_N1, hdmitx_rd_reg(HDMITX_DWC_AUD_N1)); + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 1, 0, 1); + + return 1; +} + +static void hdmitx_setupirq(struct hdmitx_dev *phdev) +{ + int r; + + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0x7); + r = request_irq(phdev->irq_hpd, &intr_handler, + IRQF_SHARED, "hdmitx", + (void *)phdev); +} + +static void hdmitx_uninit(struct hdmitx_dev *phdev) +{ + free_irq(phdev->irq_hpd, (void *)phdev); + hdmi_print(1, "power off hdmi, unmux hpd\n"); + + phy_pll_off(); + digital_clk_off(7); /* off sys clk */ + hdmitx_hpd_hw_op(HPD_UNMUX_HPD); +} + +static void hw_reset_dbg(void) +{ + uint32_t val1 = hdmitx_rd_reg(HDMITX_DWC_MC_CLKDIS); + uint32_t val2 = hdmitx_rd_reg(HDMITX_DWC_FC_INVIDCONF); + uint32_t val3 = hdmitx_rd_reg(HDMITX_DWC_FC_VSYNCINWIDTH); + + hdmitx_wr_reg(HDMITX_DWC_MC_CLKDIS, 0xff); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_MC_CLKDIS, val1); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_MC_SWRSTZREQ, 0); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_FC_INVIDCONF, 0); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_FC_INVIDCONF, val2); + udelay(10); + hdmitx_wr_reg(HDMITX_DWC_FC_VSYNCINWIDTH, val3); +} + +static int hdmitx_cntl(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv) +{ + if (cmd == HDMITX_AVMUTE_CNTL) { + return 0; + } else if (cmd == HDMITX_EARLY_SUSPEND_RESUME_CNTL) { + if (argv == HDMITX_EARLY_SUSPEND) { + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0, 30, 1); + hdmi_phy_suspend(); + } + if (argv == HDMITX_LATE_RESUME) { + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 1, 30, 1); + hw_reset_dbg(); + pr_info("hdmitx: swrstzreq\n"); + } + return 0; + } else if (cmd == HDMITX_HDCP_MONITOR) { + /* TODO */ + return 0; + } else if (cmd == HDMITX_IP_SW_RST) { + return 0; /* TODO */ + } else if (cmd == HDMITX_CBUS_RST) { + return 0;/* todo */ + hd_set_reg_bits(P_RESET2_REGISTER, 1, 15, 1); + return 0; + } else if (cmd == HDMITX_INTR_MASKN_CNTL) + /* TODO */ + return 0; + else if (cmd == HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH) { + /* turnon digital module if gpio is high */ + if (hdmitx_hpd_hw_op(HPD_IS_HPD_MUXED) == 0) { + if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO)) { + msleep(500); + if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO)) { + hdmi_print(IMP, HPD "mux hpd\n"); + digital_clk_on(4); + delay_us(1000*100); + hdmitx_hpd_hw_op(HPD_MUX_HPD); + } + } + } + } else if (cmd == HDMITX_HWCMD_MUX_HPD) + hdmitx_hpd_hw_op(HPD_MUX_HPD); +/* For test only. */ + else if (cmd == HDMITX_HWCMD_TURNOFF_HDMIHW) { + int unmux_hpd_flag = argv; + + if (unmux_hpd_flag) { + hdmi_print(IMP, SYS "power off hdmi, unmux hpd\n"); + phy_pll_off(); + digital_clk_off(4); /* off sys clk */ + hdmitx_hpd_hw_op(HPD_UNMUX_HPD); + } else { + hdmi_print(IMP, SYS "power off hdmi\n"); + digital_clk_on(6); + phy_pll_off(); + digital_clk_off(3); /* do not off sys clk */ + } + } + return 0; +} + +static void hdmitx_print_info(struct hdmitx_dev *hdev, int pr_info_flag) +{ + hdmi_print(INF, "------------------\nHdmitx driver version: "); + hdmi_print(INF, "%s\nSerial %x\nColor Depth %d\n", HDMITX_VER, + serial_reg_val, color_depth_f); + hdmi_print(INF, "reset sequence %d\n", new_reset_sequence_flag); + hdmi_print(INF, "power mode %d\n", power_mode); + hdmi_print(INF, "%spowerdown when unplug\n", + hdev->unplug_powerdown?"":"do not "); + hdmi_print(INF, "use_tvenc_conf_flag=%d\n", use_tvenc_conf_flag); + hdmi_print(INF, "vdac %s\n", power_off_vdac_flag?"off":"on"); + hdmi_print(INF, "hdmi audio %s\n", hdmi_audio_off_flag?"off":"on"); + if (!hdmi_audio_off_flag) + hdmi_print(INF, "audio out type %s\n", + i2s_to_spdif_flag?"spdif":"i2s"); + hdmi_print(INF, "delay flag %d\n", delay_flag); + hdmi_print(INF, "------------------\n"); +} + +struct aud_cts_log { + unsigned int val:20; +}; + +static inline unsigned int get_msr_cts(void) +{ + unsigned int ret = 0; + + ret = hdmitx_rd_reg(HDMITX_DWC_AUD_CTS1); + ret += (hdmitx_rd_reg(HDMITX_DWC_AUD_CTS2) << 8); + ret += ((hdmitx_rd_reg(HDMITX_DWC_AUD_CTS3) & 0xf) << 16); + + return ret; +} + +#define AUD_CTS_LOG_NUM 1000 +struct aud_cts_log cts_buf[AUD_CTS_LOG_NUM]; +static void cts_test(struct hdmitx_dev *hdev) +{ + int i; + unsigned int min = 0, max = 0, total = 0; + + pr_info("\nhdmitx: audio: cts test\n"); + memset(cts_buf, 0, sizeof(cts_buf)); + for (i = 0; i < AUD_CTS_LOG_NUM; i++) { + cts_buf[i].val = get_msr_cts(); + mdelay(1); + } + + pr_info("\ncts change:\n"); + for (i = 1; i < AUD_CTS_LOG_NUM; i++) { + if (cts_buf[i].val > cts_buf[i-1].val) + pr_info("dis: +%d [%d] %d [%d] %d\n", + cts_buf[i].val - cts_buf[i-1].val, i, + cts_buf[i].val, i - 1, cts_buf[i - 1].val); + if (cts_buf[i].val < cts_buf[i-1].val) + pr_info("dis: %d [%d] %d [%d] %d\n", + cts_buf[i].val - cts_buf[i-1].val, i, + cts_buf[i].val, i - 1, cts_buf[i - 1].val); + } + + for (i = 0; i < AUD_CTS_LOG_NUM; i++) { + total += cts_buf[i].val; + if (min > cts_buf[i].val) + min = cts_buf[i].val; + if (max < cts_buf[i].val) + max = cts_buf[i].val; + } + pr_info("\nCTS Min: %d Max: %d Avg: %d/1000\n\n", min, max, total); +} + +void hdmitx_dump_inter_timing(void) +{ + unsigned int tmp = 0; +#define CONNECT2REG(reg) ((hdmitx_rd_reg(reg)) + (hdmitx_rd_reg(reg + 1) << 8)) + tmp = CONNECT2REG(HDMITX_DWC_FC_INHACTV0); + pr_info("Hactive = %d\n", tmp); + + tmp = CONNECT2REG(HDMITX_DWC_FC_INHBLANK0); + pr_info("Hblank = %d\n", tmp); + + tmp = CONNECT2REG(HDMITX_DWC_FC_INVACTV0); + pr_info("Vactive = %d\n", tmp); + + tmp = hdmitx_rd_reg(HDMITX_DWC_FC_INVBLANK); + pr_info("Vblank = %d\n", tmp); + + tmp = CONNECT2REG(HDMITX_DWC_FC_HSYNCINDELAY0); + pr_info("Hfront = %d\n", tmp); + + tmp = CONNECT2REG(HDMITX_DWC_FC_HSYNCINWIDTH0); + pr_info("Hsync = %d\n", tmp); + + tmp = hdmitx_rd_reg(HDMITX_DWC_FC_VSYNCINDELAY); + pr_info("Vfront = %d\n", tmp); + + tmp = hdmitx_rd_reg(HDMITX_DWC_FC_VSYNCINWIDTH); + pr_info("Vsync = %d\n", tmp); + + /* HDMITX_DWC_FC_INFREQ0 ??? */ +} + +#define DUMP_CVREG_SECTION(start, end) \ +do { \ + if (start > end) { \ + pr_info("Error start = 0x%x > end = 0x%x\n", \ + ((start & 0xffff) >> 2), ((end & 0xffff) >> 2)); \ + break; \ + } \ + pr_info("Start = 0x%x[0x%x] End = 0x%x[0x%x]\n", \ + start, ((start & 0xffff) >> 2), end, ((end & 0xffff) >> 2)); \ + for (addr = start; addr < end + 1; addr += 4) { \ + val = hd_read_reg(addr); \ + if (val) \ + pr_info("0x%08x[0x%04x]: 0x%08x\n", addr, \ + ((addr & 0xffff) >> 2), val); \ + } \ +} while (0) + +static void hdmitx_dump_all_cvregs(void) +{ +#if 0 + unsigned int addr = 0, val = 0; + + DUMP_CVREG_SECTION(P_STB_TOP_CONFIG, P_CIPLUS_ENDIAN); + DUMP_CVREG_SECTION(P_PREG_CTLREG0_ADDR, P_AHB_BRIDGE_CNTL_REG2); + DUMP_CVREG_SECTION(P_BT_CTRL, P_BT656_ADDR_END); + DUMP_CVREG_SECTION(P_VERSION_CTRL, P_RESET7_LEVEL); + DUMP_CVREG_SECTION(P_SCR_HIU, P_HHI_HDMIRX_AUD_PLL_CNTL6); + DUMP_CVREG_SECTION(P_PARSER_CONTROL, P_PARSER_AV2_WRAP_COUNT); + DUMP_CVREG_SECTION(P_DVIN_FRONT_END_CTRL, P_DVIN_CTRL_STAT); + DUMP_CVREG_SECTION(P_AIU_958_BPF, P_AIU_I2S_CBUS_DDR_ADDR); + DUMP_CVREG_SECTION(P_GE2D_GEN_CTRL0, P_GE2D_GEN_CTRL4); + DUMP_CVREG_SECTION(P_AUDIO_COP_CTL2, P_EE_ASSIST_MBOX3_FIQ_SEL); + DUMP_CVREG_SECTION(P_AUDIN_SPDIF_MODE, P_AUDIN_ADDR_END); + DUMP_CVREG_SECTION(P_VDIN_SCALE_COEF_IDX, P_VDIN0_SCALE_COEF_IDX); + DUMP_CVREG_SECTION(P_VDIN0_SCALE_COEF, P_VDIN1_ASFIFO_CTRL3); + DUMP_CVREG_SECTION(P_L_GAMMA_CNTL_PORT, P_MLVDS_RESET_CONFIG_LO); + DUMP_CVREG_SECTION(P_VPP2_DUMMY_DATA, P_DI_CHAN2_URGENT_CTRL); + DUMP_CVREG_SECTION(P_DI_PRE_CTRL, P_DI_CANVAS_URGENT2); + DUMP_CVREG_SECTION(P_ENCP_VFIFO2VD_CTL, P_VIU2_VD1_FMT_W); + DUMP_CVREG_SECTION(P_VPU_OSD1_MMC_CTRL, P_VPU_PROT3_REQ_ONOFF); + DUMP_CVREG_SECTION(P_D2D3_GLB_CTRL, P_D2D3_RESEV_STATUS2); + DUMP_CVREG_SECTION(P_VI_HIST_CTRL, P_DEMO_CRTL); + DUMP_CVREG_SECTION(P_AO_RTI_STATUS_REG0, P_AO_SAR_ADC_REG12); + DUMP_CVREG_SECTION(P_STB_VERSION, P_DEMUX_SECTION_RESET_3); +#endif +} + +#define DUMP_HDMITXREG_SECTION(start, end) \ +do { \ + if (start > end) { \ + pr_info("Error start = 0x%lx > end = 0x%lx\n", start, end); \ + break; \ + } \ + pr_info("Start = 0x%lx End = 0x%lx\n", start, end); \ + for (addr = start; addr < end + 1; addr++) { \ + val = hdmitx_rd_reg(addr); \ + if (val) \ + pr_info("[0x%08x]: 0x%08x\n", addr, val); \ + } \ +} while (0) + +static void hdmitx_dump_intr(void) +{ + unsigned int addr = 0, val = 0; + + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_FC_STAT0, HDMITX_DWC_IH_MUTE); +} + +static void mode420_half_horizontal_para(void) +{ + unsigned int hactive = 0; + unsigned int hblank = 0; + unsigned int hfront = 0; + unsigned int hsync = 0; + + hactive = hdmitx_rd_reg(HDMITX_DWC_FC_INHACTV0); + hactive += (hdmitx_rd_reg(HDMITX_DWC_FC_INHACTV1) & 0x3f) << 8; + hblank = hdmitx_rd_reg(HDMITX_DWC_FC_INHBLANK0); + hblank += (hdmitx_rd_reg(HDMITX_DWC_FC_INHBLANK1) & 0x1f) << 8; + hfront = hdmitx_rd_reg(HDMITX_DWC_FC_HSYNCINDELAY0); + hfront += (hdmitx_rd_reg(HDMITX_DWC_FC_HSYNCINDELAY1) & 0x1f) << 8; + hsync = hdmitx_rd_reg(HDMITX_DWC_FC_HSYNCINWIDTH0); + hsync += (hdmitx_rd_reg(HDMITX_DWC_FC_HSYNCINWIDTH1) & 0x3) << 8; + + hactive = hactive / 2; + hblank = hblank / 2; + hfront = hfront / 2; + hsync = hsync / 2; + + hdmitx_wr_reg(HDMITX_DWC_FC_INHACTV0, (hactive & 0xff)); + hdmitx_wr_reg(HDMITX_DWC_FC_INHACTV1, ((hactive >> 8) & 0x3f)); + hdmitx_wr_reg(HDMITX_DWC_FC_INHBLANK0, (hblank & 0xff)); + hdmitx_wr_reg(HDMITX_DWC_FC_INHBLANK1, ((hblank >> 8) & 0x1f)); + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINDELAY0, (hfront & 0xff)); + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINDELAY1, ((hfront >> 8) & 0x1f)); + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINWIDTH0, (hsync & 0xff)); + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINWIDTH1, ((hsync >> 8) & 0x3)); +} + +static void hdmitx_set_fake_vic(struct hdmitx_dev *hdev) +{ + hdev->para->cs = COLORSPACE_YUV444; + hdev->cur_VIC = HDMI_VIC_FAKE; + set_vmode_clk(hdev); +} + +static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) +{ + char tmpbuf[128]; + int i = 0; + int ret; + unsigned long adr = 0; + unsigned long value = 0; + + while ((buf[i]) && (buf[i] != ',') && (buf[i] != ' ')) { + tmpbuf[i] = buf[i]; + i++; + } + tmpbuf[i] = 0; + + if ((strncmp(tmpbuf, "dumpreg", 7) == 0) || + (strncmp(tmpbuf, "dumptvencreg", 12) == 0)) { + hdmitx_dump_tvenc_reg(hdev->cur_VIC, 1); + return; + } else if (strncmp(tmpbuf, "testhpll", 8) == 0) { + ret = kstrtoul(tmpbuf + 8, 10, &value); + hdev->cur_VIC = value; + set_vmode_clk(hdev); + return; + } else if (strncmp(tmpbuf, "testpll", 7) == 0) + return; + else if (strncmp(tmpbuf, "testedid", 8) == 0) { + dd(); + hdev->HWOp.CntlDDC(hdev, DDC_RESET_EDID, 0); + hdev->HWOp.CntlDDC(hdev, DDC_EDID_READ_DATA, 0); + return; + } else if (strncmp(tmpbuf, "bist", 4) == 0) { + if (strncmp(tmpbuf + 4, "off", 3) == 0) { + hd_set_reg_bits(P_ENCP_VIDEO_MODE_ADV, 1, 3, 1); + hd_write_reg(P_VENC_VIDEO_TST_EN, 0); + return; + } + hd_set_reg_bits(P_HHI_GCLK_OTHER, 1, 3, 1); + hd_set_reg_bits(P_ENCP_VIDEO_MODE_ADV, 0, 3, 1); + hd_write_reg(P_VENC_VIDEO_TST_EN, 1); + if (strncmp(tmpbuf+4, "line", 4) == 0) { + hd_write_reg(P_VENC_VIDEO_TST_MDSEL, 2); + return; + } + if (strncmp(tmpbuf+4, "dot", 3) == 0) { + hd_write_reg(P_VENC_VIDEO_TST_MDSEL, 3); + return; + } + if (strncmp(tmpbuf+4, "start", 5) == 0) { + ret = kstrtoul(tmpbuf + 9, 10, &value); + hd_write_reg(P_VENC_VIDEO_TST_CLRBAR_STRT, value); + return; + } + if (strncmp(tmpbuf+4, "shift", 5) == 0) { + ret = kstrtoul(tmpbuf + 9, 10, &value); + hd_write_reg(P_VENC_VIDEO_TST_VDCNT_STSET, value); + return; + } + hd_write_reg(P_VENC_VIDEO_TST_MDSEL, 1); + value = 1920; + ret = kstrtoul(tmpbuf + 4, 10, &value); + hd_write_reg(P_VENC_VIDEO_TST_CLRBAR_WIDTH, value / 8); + return; + } else if (strncmp(tmpbuf, "dumptiming", 10) == 0) { + hdmitx_dump_inter_timing(); + return; + } else if (strncmp(tmpbuf, "testaudio", 9) == 0) { + hdmitx_set_audmode(hdev, NULL); + } else if (strncmp(tmpbuf, "dumpintr", 8) == 0) { + hdmitx_dump_intr(); + } else if (strncmp(tmpbuf, "testhdcp", 8) == 0) { + int i; + + i = tmpbuf[8] - '0'; + if (i == 2) + pr_info("hdcp rslt = %d", hdmitx_hdcp_opr(2)); + if (i == 1) + hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_ON); + return; + } else if (strncmp(tmpbuf, "dumpallregs", 11) == 0) { + hdmitx_dump_all_cvregs(); + return; + } else if (strncmp(tmpbuf, "chkfmt", 6) == 0) { + check_detail_fmt(); + return; + } else if (strncmp(tmpbuf, "testcts", 7) == 0) { + cts_test(hdev); + return; + } else if (strncmp(tmpbuf, "ss", 2) == 0) { + pr_info("hdev->output_blank_flag: 0x%x\n", + hdev->output_blank_flag); + pr_info("hdev->hpd_state: 0x%x\n", hdev->hpd_state); + pr_info("hdev->cur_VIC: 0x%x\n", hdev->cur_VIC); + } else if (strncmp(tmpbuf, "hpd_lock", 8) == 0) { + if (tmpbuf[8] == '1') { + hdev->hpd_lock = 1; + hdmi_print(INF, HPD "hdmitx: lock hpd\n"); + } else { + hdev->hpd_lock = 0; + hdmi_print(INF, HPD "hdmitx: unlock hpd\n"); + } + return; + } else if (strncmp(tmpbuf, "hpd_stick", 9) == 0) { + if (tmpbuf[9] == '1') + hdev->hdcp_hpd_stick = 1; + else + hdev->hdcp_hpd_stick = 0; + pr_info("hdmitx: %sstick hpd\n", + (hdev->hdcp_hpd_stick) ? "" : "un"); + } else if (strncmp(tmpbuf, "vic", 3) == 0) { + pr_info("hdmi vic count = %d\n", hdev->vic_count); + if ((tmpbuf[3] >= '0') && (tmpbuf[3] <= '9')) { + hdev->vic_count = tmpbuf[3] - '0'; + hdmi_print(INF, SYS "set hdmi vic count = %d\n", + hdev->vic_count); + } + } else if (strncmp(tmpbuf, "cec", 3) == 0) + return; + else if (strncmp(tmpbuf, "dumphdmireg", 11) == 0) { + unsigned char reg_val = 0; + unsigned int reg_adr = 0; + +#define DUMP_HDMITX_SECTION(a, b) \ + for (reg_adr = a; reg_adr < b+1; reg_adr++) { \ + reg_val = hdmitx_rd_reg(reg_adr); \ + if (reg_val) \ + pr_info("[0x%x]: 0x%x\n", reg_adr, reg_val); \ + } + +#define DUMP_HDMITX_HDCP_SECTION(a, b) \ + for (reg_adr = a; reg_adr < b+1; reg_adr++) { \ + hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x1); \ + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); \ + reg_val = hdmitx_rd_reg(reg_adr); \ + if (reg_val) \ + pr_info("[0x%x]: 0x%x\n", reg_adr, reg_val); \ + } + + DUMP_HDMITX_SECTION(HDMITX_TOP_SW_RESET, + HDMITX_TOP_DONT_TOUCH1); + DUMP_HDMITX_SECTION(HDMITX_TOP_SKP_CNTL_STAT, + HDMITX_TOP_SEC_SCRATCH); + DUMP_HDMITX_SECTION(HDMITX_DWC_DESIGN_ID, + HDMITX_DWC_A_KSVMEMCTRL); + DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCP_BSTATUS_0, + HDMITX_DWC_HDCPREG_BKSV0 - 1); + DUMP_HDMITX_SECTION(HDMITX_DWC_HDCPREG_ANCONF, + HDMITX_DWC_HDCP22REG_MUTE); + DUMP_HDMITX_SECTION(HDMITX_DWC_A_HDCPCFG0, + HDMITX_DWC_A_HDCPCFG1); + DUMP_HDMITX_SECTION(HDMITX_DWC_HDCPREG_SEED0, + HDMITX_DWC_HDCPREG_DPK6); + DUMP_HDMITX_SECTION(HDMITX_DWC_HDCP22REG_CTRL, + HDMITX_DWC_HDCP22REG_CTRL); + return; + } else if (strncmp(tmpbuf, "dumpcecreg", 10) == 0) { + unsigned char cec_val = 0; + unsigned int cec_adr = 0; + /* HDMI CEC Regs address range:0xc000~0xc01c;0xc080~0xc094 */ + for (cec_adr = 0xc000; cec_adr < 0xc01d; cec_adr++) { + cec_val = hdmitx_rd_reg(cec_adr); + hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n", + cec_adr, cec_val); + } + for (cec_adr = 0xc080; cec_adr < 0xc095; cec_adr++) { + cec_val = hdmitx_rd_reg(cec_adr); + hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n", + cec_adr, cec_val); + } + return; + } else if (strncmp(tmpbuf, "dumpcbusreg", 11) == 0) { + unsigned int i, val; + + for (i = 0; i < 0x3000; i++) { + val = hd_read_reg(CBUS_REG_ADDR(i)); + if (val) + pr_info("CBUS[0x%x]: 0x%x\n", i, val); + } + return; + } else if (strncmp(tmpbuf, "dumpvcbusreg", 12) == 0) { + unsigned int i, val; + + for (i = 0; i < 0x3000; i++) { + val = hd_read_reg(VCBUS_REG_ADDR(i)); + if (val) + pr_info("VCBUS[0x%x]: 0x%x\n", i, val); + } + return; + } else if (strncmp(tmpbuf, "log", 3) == 0) { + if (strncmp(tmpbuf+3, "hdcp", 4) == 0) { + static unsigned int i = 1; + + if (i & 1) + hdev->log |= HDMI_LOG_HDCP; + else + hdev->log &= ~HDMI_LOG_HDCP; + i++; + } + return; + } else if (strncmp(tmpbuf, "pllcalc", 7) == 0) { + /* TODO clk_measure(0xff); */ + return; + } else if (strncmp(tmpbuf, "hdmiaudio", 9) == 0) { + ret = kstrtoul(tmpbuf+9, 16, &value); + if (value == 1) { + hdmi_audio_off_flag = 0; + hdmi_audio_init(i2s_to_spdif_flag); + } else if (value == 0) + ; + return; + } else if (strncmp(tmpbuf, "cfgreg", 6) == 0) { + ret = kstrtoul(tmpbuf+6, 16, &adr); + ret = kstrtoul(buf+i+1, 16, &value); + hdmitx_config_tvenc_reg(hdev->cur_VIC, adr, value); + return; + } else if (strncmp(tmpbuf, "tvenc_flag", 10) == 0) { + use_tvenc_conf_flag = tmpbuf[10]-'0'; + hdmi_print(INF, "set use_tvenc_conf_flag = %d\n", + use_tvenc_conf_flag); + } else if (strncmp(tmpbuf, "reset", 5) == 0) { + if (tmpbuf[5] == '0') + new_reset_sequence_flag = 0; + else + new_reset_sequence_flag = 1; + return; + } else if (strncmp(tmpbuf, "delay_flag", 10) == 0) + delay_flag = tmpbuf[10]-'0'; + else if (tmpbuf[0] == 'v') { + hdmitx_print_info(hdev, 1); + return; + } else if (tmpbuf[0] == 's') { + ret = kstrtoul(tmpbuf+1, 16, &serial_reg_val); + return; + } else if (tmpbuf[0] == 'c') { + if (tmpbuf[1] == 'd') { + ret = kstrtoul(tmpbuf+2, 10, &color_depth_f); + if ((color_depth_f != 24) && (color_depth_f != 30) && + (color_depth_f != 36)) { + pr_info("Color depth %lu is not supported\n", + color_depth_f); + color_depth_f = 0; + } + return; + } else if (tmpbuf[1] == 's') { + ret = kstrtoul(tmpbuf+2, 10, &COLORSPACE_f); + if (COLORSPACE_f > 2) { + pr_info("Color space %lu is not supported\n", + COLORSPACE_f); + COLORSPACE_f = 0; + } + } + } else if (strncmp(tmpbuf, "i2s", 2) == 0) { + if (strncmp(tmpbuf+3, "off", 3) == 0) + i2s_to_spdif_flag = 1; + else + i2s_to_spdif_flag = 0; + } else if (strncmp(tmpbuf, "pattern_on", 10) == 0) { + /* turn_on_shift_pattern(); */ + hdmi_print(INF, "Shift Pattern On\n"); + return; + } else if (strncmp(tmpbuf, "pattern_off", 11) == 0) { + hdmi_print(INF, "Shift Pattern Off\n"); + return; + } else if (strncmp(tmpbuf, "prbs", 4) == 0) + /* int prbs_mode =kstrtoul(tmpbuf+4, NULL, 10); */ + return; + else if (tmpbuf[0] == 'w') { + unsigned int read_back = 0; + + ret = kstrtoul(tmpbuf+2, 16, &adr); + ret = kstrtoul(buf+i+1, 16, &value); + if (buf[1] == 'h') { + hdmitx_wr_reg((unsigned int)adr, (unsigned int)value); + read_back = hdmitx_rd_reg(adr); + } + if (buf[1] == 'c') { + hdcp22_wr_reg((uint32_t)adr, (uint32_t)value); + read_back = hdcp22_rd_reg((uint32_t)adr); + } + hdmi_print(INF, "write %x to %s reg[%x]\n", value, "HDMI", adr); +/* Add read back function in order to judge writing is OK or NG. */ + hdmi_print(INF, "Read Back %s reg[%x]=%x\n", "HDMI", + adr, read_back); + } else if (tmpbuf[0] == 'r') { + ret = kstrtoul(tmpbuf+2, 16, &adr); + if (buf[1] == 'h') + value = hdmitx_rd_reg(adr); + if (buf[1] == 'c') + value = hdcp22_rd_reg((uint32_t)adr); + hdmi_print(INF, "%s reg[%x]=%x\n", "HDMI", adr, value); + } +} + + +static void hdmitx_getediddata(unsigned char *des, unsigned char *src) +{ + int i = 0; + unsigned int blk = src[126] + 1; + + if (blk > 4) + blk = 4; + + for (i = 0; i < 128 * blk; i++) + des[i] = src[i]; +} + +/* + * Note: read 8 Bytes of EDID data every time + */ +static void hdmitx_read_edid(unsigned char *rx_edid) +{ + unsigned int timeout = 0; + unsigned int i; + unsigned int byte_num = 0; + unsigned char blk_no = 1; + + /* Program SLAVE/ADDR */ + hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, 0x50); + /* Read complete EDID data sequentially */ + while (byte_num < 128 * blk_no) { + hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, byte_num&0xff); + if (((byte_num == 256) || (byte_num == 384)) && (blk_no > 2)) { + /* Program SEGMENT/SEGPTR */ + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR, 0x30); + hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, 0x1); + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1<<3); + } else + hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1<<2); + /* Wait until I2C done */ + timeout = 0; + while ((!(hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 1))) + && (timeout < 5)) { + mdelay(1); + timeout++; + } + if (timeout == 5) + pr_info("hdmitx: ddc timeout\n"); + mdelay(1); + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 1 << 1); + /* Read back 8 bytes */ + for (i = 0; i < 8; i++) { + rx_edid[byte_num] = + hdmitx_rd_reg(HDMITX_DWC_I2CM_READ_BUFF0 + i); + if (byte_num == 126) { + blk_no = rx_edid[126] + 1; + if (blk_no > 4) { + pr_info("edid extension block number:"); + pr_info(" %d, reset to MAX 3\n", + blk_no - 1); + blk_no = 4; /* Max extended block */ + } + } + byte_num++; + } + } +} /* hdmi20_tx_read_edid */ + +static unsigned char tmp_edid_buf[128*EDID_MAX_BLOCK] = { 0 }; + +#define HDCP_NMOOFDEVICES 127 + +static int get_hdcp_depth(void) +{ + int ret; + + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + ret = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1) & 0x7; + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + + return ret; +} + +static bool get_hdcp_max_cascade(void) +{ + bool ret; + + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + ret = (hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1) >> 3) & 0x1; + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + + return ret; +} + +static bool get_hdcp_max_devs(void) +{ + bool ret; + + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + ret = (hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) >> 7) & 0x1; + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + + return ret; +} + +static int get_hdcp_device_count(void) +{ + int ret; + + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + ret = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) & 0x7f; + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + + return ret; +} + +static void get_hdcp_bstatus(void) +{ + int ret1 = 0; + int ret2 = 0; + + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + ret1 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0); + ret2 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1); + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + pr_info("BSTATUS0 = 0x%x BSTATUS1 = 0x%x\n", ret1, ret2); +} + +static void hdcp_ksv_store(unsigned char *dat, int no) +{ + int i; + + for (i = 0; i < no; i++) { + rptx_ksv_buf[rptx_ksv_no] = dat[i]; + rptx_ksv_no++; + } +} + +static void hdcp_ksv_print(void) +{ + unsigned int i, pos; + unsigned char *tmp_buf = NULL; + + tmp_buf = kmalloc(2000, GFP_KERNEL); + if (!tmp_buf) + return; + + pos = 0; + memset(tmp_buf, 0, sizeof(2000)); + pos += sprintf(tmp_buf + pos, "Dump ksv test START\n"); + for (i = 0; (i < rptx_ksv_no) && (i < 635); i++) { + pos += sprintf(tmp_buf + pos, "%02x", rptx_ksv_buf[i]); + if (((i+1) % 40) == 0) /* print 40bytes a line */ + pos += sprintf(tmp_buf + pos, "\n"); + } + pos += sprintf(tmp_buf + pos, "\n"); + pos += sprintf(tmp_buf + pos, "Dump ksv test END\n"); + pr_info("%s\n", tmp_buf); + kfree(tmp_buf); +} + +static uint8_t *hdcp_mKsvListBuf; +static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev) +{ + size_t list = 0; + size_t size = 0; + size_t i = 0; + int valid = HDCP_IDLE; + unsigned char ksvs[635] = {0}; /* Max 127 * 5 */ + int j = 0; + + /* 0x165e: Page 95 */ + hdcp_mKsvListBuf = kmalloc(0x1660, GFP_KERNEL); + if (hdcp_mKsvListBuf) { + /* KSV_LEN; */ + list = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) & KSV_MSK; + if (list <= HDCP_NMOOFDEVICES) { + size = (list * KSV_LEN) + HEADER + SHAMAX; + for (i = 0; i < size; i++) { + if (i < HEADER) { /* BSTATUS & M0 */ + hdcp_mKsvListBuf[(list * KSV_LEN) + i] + = hdmitx_rd_reg( + HDMITX_DWC_HDCP_BSTATUS_0 + i); + } else if (i < (HEADER + (list * KSV_LEN))) { + /* KSV list */ + hdcp_mKsvListBuf[i - HEADER] = + hdmitx_rd_reg( + HDMITX_DWC_HDCP_BSTATUS_0 + i); + ksvs[j] = hdcp_mKsvListBuf[i - HEADER]; + j++; + } else { /* SHA */ + hdcp_mKsvListBuf[i] = hdmitx_rd_reg( + HDMITX_DWC_HDCP_BSTATUS_0 + i); + } + } + valid = hdcpVerify_KSV(hdcp_mKsvListBuf, size) + == TRUE ? HDCP_KSV_LIST_READY : + HDCP_ERR_KSV_LIST_NOT_VALID; + } + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1); + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, + (valid == HDCP_KSV_LIST_READY) ? 0 : 1, 3, 1); + if (valid == HDCP_KSV_LIST_READY) + hdcp_ksv_store(ksvs, j); + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 2, 1); + hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 2, 1); + kfree(hdcp_mKsvListBuf); + } else + pr_info("hdcptx14: KSV List memory not valid\n"); +} + +static void hdcptx_events_handle(unsigned long arg) +{ + struct hdmitx_dev *hdev = (struct hdmitx_dev *)arg; + unsigned char ksv[5] = {0}; + int pos, i; + unsigned int bcaps_6_rp; + static unsigned int st_flag = -1; + + bcaps_6_rp = !!(hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3) & (1 << 6)); + if (st_flag != hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT)) { + st_flag = hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT); + pr_info("hdcp14: instat: 0x%x\n", st_flag); + } + if (st_flag & (1 << 7)) { + hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 1 << 7); + hdmitx_hdcp_opr(3); + for (i = 0; i < 5; i++) + ksv[i] = (unsigned char) + hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + i); + hdcp_ksv_store(ksv, 5); + get_hdcp_bstatus(); + rx_set_receive_hdcp(rptx_ksv_buf, (rptx_ksv_no + 1) / 5, + (bcaps_6_rp ? get_hdcp_depth() : 0) + 1, + bcaps_6_rp ? get_hdcp_max_cascade() : 0, + bcaps_6_rp ? get_hdcp_max_devs() : 0); + pr_info("%s[%d] ksvs Num = %d device_count = %d\n", + __func__, __LINE__, + (rptx_ksv_no + 1) / 5, + bcaps_6_rp ? get_hdcp_device_count() : 0); + memset(rptx_ksv_prbuf, 0, sizeof(rptx_ksv_prbuf)); + for (pos = 0, i = 0; i < rptx_ksv_no; i++) + pos += sprintf(rptx_ksv_prbuf + pos, "%02x", + rptx_ksv_buf[i]); + rptx_ksv_prbuf[pos + 1] = '\0'; + if (1) + hdcp_ksv_print(); + } + if (st_flag & (1 << 1)) { + rptx_ksvlist_retry++; + hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, (1 << 1)); + hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x1); + hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ); + if (hdmitx_rd_reg(HDMITX_DWC_A_KSVMEMCTRL) & (1 << 1)) + hdcp_ksv_sha1_calc(hdev); + else { + pr_info("hdcptx14: KSV List memory access denied\n"); + return; + } + hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x4); + if (rptx_ksvlist_retry % 4 == 0) { + for (i = 0; i < 5; i++) + ksv[i] = (unsigned char) + hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + + i); + hdcp_ksv_store(ksv, 5); + rx_set_receive_hdcp(&ksv[0], 1, 127, 1, 1); + } + + } + if ((bcaps_6_rp) && (get_hdcp_max_devs() || get_hdcp_max_cascade())) { + for (i = 0; i < 5; i++) + ksv[i] = (unsigned char) + hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + i); + hdcp_ksv_store(ksv, 5); + rx_set_receive_hdcp(&ksv[0], 1, 127, 1, 1); + } + if (hdev->hdcp_try_times) + mod_timer(&hdev->hdcp_timer, jiffies + HZ / 100); + else + return; + hdev->hdcp_try_times--; +} + +static void hdcp_start_timer(struct hdmitx_dev *hdev) +{ + static int init_flag; + + if (!init_flag) { + init_flag = 1; + init_timer(&hdev->hdcp_timer); + hdev->hdcp_timer.data = (ulong)hdev; + hdev->hdcp_timer.function = hdcptx_events_handle; + hdev->hdcp_timer.expires = jiffies + HZ / 100; + add_timer(&hdev->hdcp_timer); + hdev->hdcp_try_times = 500; + return; + } + hdev->hdcp_try_times = 500; + hdev->hdcp_timer.expires = jiffies + HZ / 100; + mod_timer(&hdev->hdcp_timer, jiffies + HZ / 100); +} + +static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned long argv) +{ + int i = 0; + unsigned char *tmp_char = NULL; + + if (!(cmd & CMD_DDC_OFFSET)) + hdmi_print(ERR, "ddc: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "ddc: cmd 0x%x\n", cmd); + + switch (cmd) { + case DDC_RESET_EDID: + hdmitx_wr_reg(HDMITX_DWC_I2CM_SOFTRSTZ, 0); + memset(tmp_edid_buf, 0, ARRAY_SIZE(tmp_edid_buf)); + break; + case DDC_IS_EDID_DATA_READY: + + break; + case DDC_EDID_READ_DATA: + hdmitx_read_edid(tmp_edid_buf); + break; + case DDC_EDID_GET_DATA: + if (argv == 0) + hdmitx_getediddata(&hdev->EDID_buf[0], tmp_edid_buf); + else + hdmitx_getediddata(&hdev->EDID_buf1[0], tmp_edid_buf); + break; + case DDC_PIN_MUX_OP: + if (argv == PIN_MUX) + hdmitx_ddc_hw_op(DDC_MUX_DDC); + if (argv == PIN_UNMUX) + hdmitx_ddc_hw_op(DDC_UNMUX_DDC); + break; + case DDC_EDID_CLEAR_RAM: + for (i = 0; i < EDID_RAM_ADDR_SIZE; i++) + hdmitx_wr_reg(HDMITX_DWC_I2CM_READ_BUFF0 + i, 0); + break; + case DDC_RESET_HDCP: + + break; + case DDC_HDCP_MUX_INIT: + if (argv == 2) + hdmitx_ddc_hw_op(DDC_MUX_DDC); + if (argv == 1) + hdmitx_hdcp_opr(6); + break; + case DDC_HDCP_OP: + if (argv == HDCP14_ON) { + rptx_ksvlist_retry = 0; + rptx_ksv_no = 0; + memset(rptx_ksv_buf, 0, sizeof(rptx_ksv_buf)); + hdmitx_ddc_hw_op(DDC_MUX_DDC); + hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 0, 6, 1); + hdmitx_hdcp_opr(6); + hdmitx_hdcp_opr(1); + hdcp_start_timer(hdev); + } + if (argv == HDCP14_OFF) { + rptx_ksvlist_retry = 0; + hdmitx_hdcp_opr(4); + } + if (argv == HDCP22_ON) { + hdmitx_ddc_hw_op(DDC_MUX_DDC); + hdmitx_hdcp_opr(5); + /* wait for start hdcp22app */ + } + if (argv == HDCP22_OFF) + hdmitx_hdcp_opr(6); + break; + case DDC_IS_HDCP_ON: +/* argv = !!((hdmitx_rd_reg(TX_HDCP_MODE)) & (1 << 7)); */ + break; + case DDC_HDCP_GET_BKSV: + tmp_char = (unsigned char *) argv; + for (i = 0; i < 5; i++) + tmp_char[i] = (unsigned char) + hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + 4 - i); + break; + case DDC_HDCP_GET_AUTH: + if (hdev->hdcp_mode == 1) + return hdmitx_hdcp_opr(2); + if (hdev->hdcp_mode == 2) + return hdmitx_hdcp_opr(7); + else + return 0; + break; + case DDC_HDCP_14_LSTORE: + return hdmitx_hdcp_opr(0xa); + case DDC_HDCP_22_LSTORE: + return hdmitx_hdcp_opr(0xb); + case DDC_HDCP_BYP: + hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1); + break; + case DDC_SCDC_DIV40_SCRAMB: + if (argv == 1) { + scdc_wr_sink(TMDS_CFG, 0x3); /* TMDS 1/40 & Scramble */ + scdc_wr_sink(TMDS_CFG, 0x3); /* TMDS 1/40 & Scramble */ + hdmitx_wr_reg(HDMITX_DWC_FC_SCRAMBLER_CTRL, 1); + } else { + scdc_wr_sink(TMDS_CFG, 0x0); /* TMDS 1/40 & Scramble */ + scdc_wr_sink(TMDS_CFG, 0x0); /* TMDS 1/40 & Scramble */ + hdmitx_wr_reg(HDMITX_DWC_FC_SCRAMBLER_CTRL, 0); + } + break; + default: + hdmi_print(INF, "ddc: unknown cmd: 0x%x\n", cmd); + break; + } + return 1; +} + +static int hdmitx_hdmi_dvi_config(struct hdmitx_dev *hdev, + unsigned int dvi_mode) +{ + if (dvi_mode == 1) { + hdmitx_csc_config(TX_INPUT_COLOR_FORMAT, + COLORSPACE_RGB444, TX_COLOR_DEPTH); + + /* set dvi flag */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_INVIDCONF, 0, 3, 1); + + } else { + /* set hdmi flag */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_INVIDCONF, 1, 3, 1); + } + + return 0; +} + +static int hdmitx_get_hdmi_dvi_config(struct hdmitx_dev *hdev) +{ + int value = hdmitx_rd_reg(HDMITX_DWC_FC_INVIDCONF) & 0x8; + + return (value == 0)?DVI_MODE:HDMI_MODE; +} + +static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv) +{ + int ret = 0; + + if (!(cmd & CMD_CONF_OFFSET)) + hdmi_print(ERR, "config: hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "config: hdmitx: conf cmd 0x%x\n", cmd); + + switch (cmd) { + case CONF_HDMI_DVI_MODE: + hdmitx_hdmi_dvi_config(hdev, (argv == DVI_MODE)?1:0); + break; + case CONF_GET_HDMI_DVI_MODE: + ret = hdmitx_get_hdmi_dvi_config(hdev); + break; + case CONF_SYSTEM_ST: + break; + case CONF_AUDIO_MUTE_OP: + audio_mute_op(argv == AUDIO_MUTE ? 0 : 1); + break; + case CONF_VIDEO_BLANK_OP: + return 1; /* TODO */ + if (argv == VIDEO_BLANK) { + /* set blank CrYCb as 0x200 0x0 0x200 */ + hd_write_reg(P_VPU_HDMI_DATA_OVR, + (0x200 << 20) | (0x0 << 10) | (0x200 << 0)); + /* Output data map: CrYCb */ + hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 5, 3); + /* Enable HDMI data override */ + hd_set_reg_bits(P_VPU_HDMI_DATA_OVR, 1, 31, 1); + } + if (argv == VIDEO_UNBLANK) + /* Disable HDMI data override */ + hd_write_reg(P_VPU_HDMI_DATA_OVR, 0); + break; + case CONF_CLR_AVI_PACKET: + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, 0); + if (hdmitx_rd_reg(HDMITX_DWC_FC_VSDPAYLOAD0) == 0x20) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, 0); + hd_write_reg(P_ISA_DEBUG_REG0, 0); + break; + case CONF_CLR_VSDB_PACKET: + if (hdmitx_rd_reg(HDMITX_DWC_FC_VSDPAYLOAD0) == 0x20) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, 0); + break; + case CONF_VIDEO_MAPPING: + config_video_mapping(hdev->para->cs, hdev->para->cd); + break; + case CONF_CLR_AUDINFO_PACKET: + break; + case CONF_AVI_BT2020: + if (argv == SET_AVI_BT2020) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 3, 6, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 6, 4, 3); + } + if (argv == CLR_AVI_BT2020) + hdmitx_set_avi_colorimetry(hdev->para); + break; + case CONF_AVI_RGBYCC_INDIC: + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, argv, 0, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, 0, 7, 1); + break; + case CONF_AVI_Q01: + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, argv, 2, 2); + break; + case CONF_AVI_YQ01: + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv, 2, 2); + break; + default: + hdmi_print(ERR, "config: hdmitx: unknown cmd: 0x%x\n", cmd); + } + + return ret; +} + +static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv) +{ + if (!(cmd & CMD_MISC_OFFSET)) + hdmi_print(ERR, "misc: hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "misc: hdmitx: misc cmd 0x%x\n", cmd); + + switch (cmd) { + case MISC_HPD_MUX_OP: + if (argv == PIN_MUX) + argv = HPD_MUX_HPD; + else + argv = HPD_UNMUX_HPD; + return hdmitx_hpd_hw_op(argv); + case MISC_HPD_GPI_ST: + return hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO); + case MISC_HPLL_OP: + if (argv == HPLL_ENABLE) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 1, 30, 1); + if (argv == HPLL_DISABLE) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0, 30, 1); + break; + case MISC_HPLL_FAKE: + hdmitx_set_fake_vic(hdev); + break; + case MISC_TMDS_PHY_OP: + if (argv == TMDS_PHY_ENABLE) + hdmi_phy_wakeup(hdev); /* TODO */ + if (argv == TMDS_PHY_DISABLE) + hdmi_phy_suspend(); + break; + case MISC_ESM_RESET: + if (hdev->hdcp_hpd_stick == 1) { + pr_info("hdcp: stick mode\n"); + break; + } + hdmitx_hdcp_opr(6); + break; + case MISC_VIID_IS_USING: + break; + case MISC_TMDS_CLK_DIV40: + set_tmds_clk_div40(argv); + break; + case MISC_AVMUTE_OP: + config_avmute(argv); + break; + case MISC_HDCP_CLKDIS: + hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, argv, 6, 1); + break; + default: + hdmi_print(ERR, "misc: hdmitx: unknown cmd: 0x%x\n", cmd); + } + return 1; +} + +static enum hdmi_vic get_vic_from_pkt(void) +{ + enum hdmi_vic vic = HDMI_Unknown; + unsigned int rgb_ycc = hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF0); + + vic = hdmitx_rd_reg(HDMITX_DWC_FC_AVIVID); + if (vic == HDMI_Unknown) { + vic = (enum hdmi_vic)hdmitx_rd_reg(HDMITX_DWC_FC_VSDPAYLOAD1); + if (vic == 1) + vic = HDMI_3840x2160p30_16x9; + else if (vic == 2) + vic = HDMI_3840x2160p25_16x9; + else if (vic == 3) + vic = HDMI_3840x2160p24_16x9; + else if (vic == 4) + vic = HDMI_4096x2160p24_256x135; + else + vic = hd_read_reg(P_ISA_DEBUG_REG0); + } + + rgb_ycc &= 0x3; + switch (vic) { + case HDMI_3840x2160p50_16x9: + if (rgb_ycc == 0x3) + vic = HDMI_3840x2160p50_16x9_Y420; + break; + case HDMI_4096x2160p50_256x135: + if (rgb_ycc == 0x3) + vic = HDMI_4096x2160p50_256x135_Y420; + break; + case HDMI_3840x2160p60_16x9: + if (rgb_ycc == 0x3) + vic = HDMI_3840x2160p60_16x9_Y420; + break; + case HDMI_4096x2160p60_256x135: + if (rgb_ycc == 0x3) + vic = HDMI_4096x2160p60_256x135_Y420; + break; + break; + default: + break; + } + + return vic; +} + +static int hdmitx_get_state(struct hdmitx_dev *hdev, unsigned int cmd, + unsigned int argv) +{ + if (!(cmd & CMD_STAT_OFFSET)) + hdmi_print(ERR, "stat: hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "stat: hdmitx: misc cmd 0x%x\n", cmd); + + switch (cmd) { + case STAT_VIDEO_VIC: + return (int)get_vic_from_pkt(); + case STAT_VIDEO_CLK: + break; + default: + break; + } + return 0; +} + +static void hdmi_phy_suspend(void) +{ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x0); +} + +static void hdmi_phy_wakeup(struct hdmitx_dev *hdev) +{ + hdmitx_set_phy(hdev); + /* hdmi_print(INF, SYS "phy wakeup\n"); */ +} + +/* CRT_VIDEO SETTING FUNCTIONS + * input : + * vIdx: 0:V1; 1:V2; there have 2 parallel set clock generator: V1 and V2 + * inSel : 0:vid_pll_clk; 1:fclk_div4; 2:flck_div3; 3:fclk_div5; + * 4:vid_pll2_clk; 5:fclk_div7; 6:vid_pll2_clk; + * DivN : clock divider for enci_clk/encp_clk/encl_clk/vda_clk + * /hdmi_tx_pixel_clk; + */ +void set_crt_video_enc(uint32_t vIdx, uint32_t inSel, uint32_t DivN) +{ + if (vIdx == 0) { + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 0, 19, 1); + + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, inSel, 16, 3); + hd_set_reg_bits(P_HHI_VID_CLK_DIV, (DivN-1), 0, 8); + + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 1, 19, 1); + + } else { /* V2 */ + hd_set_reg_bits(P_HHI_VIID_CLK_CNTL, 0, 19, 1); + + hd_set_reg_bits(P_HHI_VIID_CLK_CNTL, inSel, 16, 3); + hd_set_reg_bits(P_HHI_VIID_CLK_DIV, (DivN-1), 0, 8); + + hd_set_reg_bits(P_HHI_VIID_CLK_CNTL, 1, 19, 1); + } +} + +void hdmitx_set_avi_colorimetry(struct hdmi_format_para *para) +{ + if (!para) + return; + + /* set Colorimetry in AVIInfo */ + switch (para->vic) { + case HDMI_640x480p60_4x3: + case HDMI_720x480p60_4x3: + case HDMI_720x480p60_16x9: + case HDMI_720x480i60_4x3: + case HDMI_720x480i60_16x9: + case HDMI_720x240p60_4x3: + case HDMI_720x240p60_16x9: + case HDMI_2880x480i60_4x3: + case HDMI_2880x480i60_16x9: + case HDMI_2880x240p60_4x3: + case HDMI_2880x240p60_16x9: + case HDMI_1440x480p60_4x3: + case HDMI_1440x480p60_16x9: + case HDMI_720x576p50_4x3: + case HDMI_720x576p50_16x9: + case HDMI_720x576i50_4x3: + case HDMI_720x576i50_16x9: + case HDMI_720x288p_4x3: + case HDMI_720x288p_16x9: + case HDMI_2880x576i50_4x3: + case HDMI_2880x576i50_16x9: + case HDMI_2880x288p50_4x3: + case HDMI_2880x288p50_16x9: + case HDMI_1440x576p_4x3: + case HDMI_1440x576p_16x9: + case HDMI_2880x480p60_4x3: + case HDMI_2880x480p60_16x9: + case HDMI_2880x576p50_4x3: + case HDMI_2880x576p50_16x9: + case HDMI_720x576p100_4x3: + case HDMI_720x576p100_16x9: + case HDMI_720x576i100_4x3: + case HDMI_720x576i100_16x9: + case HDMI_720x480p120_4x3: + case HDMI_720x480p120_16x9: + case HDMI_720x480i120_4x3: + case HDMI_720x480i120_16x9: + case HDMI_720x576p200_4x3: + case HDMI_720x576p200_16x9: + case HDMI_720x576i200_4x3: + case HDMI_720x576i200_16x9: + case HDMI_720x480p240_4x3: + case HDMI_720x480p240_16x9: + case HDMI_720x480i240_4x3: + case HDMI_720x480i240_16x9: + /* C1C0 601 */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 1, 6, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 0, 4, 3); + break; + default: + /* C1C0 709 */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 2, 6, 2); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 0, 4, 3); + break; + } +} + +/* + * color_depth: Pixel bit width: 4=24-bit; 5=30-bit; 6=36-bit; 7=48-bit. + * input_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420. + * input_color_range: 0=limited; 1=full. + * output_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420 + */ +static void config_hdmi20_tx(enum hdmi_vic vic, + struct hdmitx_dev *hdev, + unsigned char color_depth, + unsigned char input_color_format, + unsigned char output_color_format) +{ + struct hdmi_format_para *para = hdev->para; + struct hdmi_cea_timing *t = ¶->timing; + unsigned long data32; + unsigned char vid_map; + unsigned char csc_en; + unsigned char default_phase = 0; + unsigned int tmp = 0; + +#define GET_TIMING(name) (t->name) + + /* Enable clocks and bring out of reset */ + + /* Enable hdmitx_sys_clk */ + /* .clk0 ( cts_oscin_clk ), */ + /* .clk1 ( fclk_div4 ), */ + /* .clk2 ( fclk_div3 ), */ + /* .clk3 ( fclk_div5 ), */ + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0x0100, 0, 16); + + /* Enable clk81_hdmitx_pclk */ + hd_set_reg_bits(P_HHI_GCLK_MPEG2, 1, 4, 1); + + /* wire wr_enable = control[3]; */ + /* wire fifo_enable = control[2]; */ + /* assign phy_clk_en = control[1]; */ + /* Enable tmds_clk */ + /* Bring HDMITX MEM output of power down */ + hd_set_reg_bits(P_HHI_MEM_PD_REG0, 0, 8, 8); + + /* Bring out of reset */ + hdmitx_wr_reg(HDMITX_TOP_SW_RESET, 0); + + /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 3, 0, 2); + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 3, 4, 2); + hdmitx_wr_reg(HDMITX_DWC_MC_LOCKONCLOCK, 0xff); + +/* But keep spdif_clk and i2s_clk disable + * until later enable by test.c + */ + data32 = 0; + data32 |= (0 << 6); + data32 |= (0 << 5); + data32 |= (0 << 4); + data32 |= (0 << 3); + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_MC_CLKDIS, data32); + + /* Enable normal output to PHY */ + + data32 = 0; + data32 |= (1 << 12); + data32 |= (0 << 8); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_TOP_BIST_CNTL, data32); + + /* Configure video */ + + vid_map = (input_color_format == COLORSPACE_RGB444) ? + ((color_depth == COLORDEPTH_24B) ? 0x01 : + (color_depth == COLORDEPTH_30B) ? 0x03 : + (color_depth == COLORDEPTH_36B) ? 0x05 : + 0x07) : + ((input_color_format == COLORSPACE_YUV444) || + (input_color_format == COLORSPACE_YUV420)) ? + ((color_depth == COLORDEPTH_24B) ? 0x09 : + (color_depth == COLORDEPTH_30B) ? 0x0b : + (color_depth == COLORDEPTH_36B) ? 0x0d : + 0x0f) : + ((color_depth == COLORDEPTH_24B) ? 0x16 : + (color_depth == COLORDEPTH_30B) ? 0x14 : + 0x12); + + data32 = 0; + data32 |= (0 << 7); + data32 |= (vid_map << 0); + hdmitx_wr_reg(HDMITX_DWC_TX_INVID0, data32); + + data32 = 0; + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_TX_INSTUFFING, data32); + hdmitx_wr_reg(HDMITX_DWC_TX_GYDATA0, 0x00); + hdmitx_wr_reg(HDMITX_DWC_TX_GYDATA1, 0x00); + hdmitx_wr_reg(HDMITX_DWC_TX_RCRDATA0, 0x00); + hdmitx_wr_reg(HDMITX_DWC_TX_RCRDATA1, 0x00); + hdmitx_wr_reg(HDMITX_DWC_TX_BCBDATA0, 0x00); + hdmitx_wr_reg(HDMITX_DWC_TX_BCBDATA1, 0x00); + + /* Configure Color Space Converter */ + + csc_en = (input_color_format != output_color_format) ? 1 : 0; + + data32 = 0; + data32 |= (csc_en << 0); + hdmitx_wr_reg(HDMITX_DWC_MC_FLOWCTRL, data32); + + data32 = 0; + data32 |= ((((input_color_format == COLORSPACE_YUV422) && + (output_color_format != COLORSPACE_YUV422)) ? 2 : 0) << 4); + data32 |= ((((input_color_format != COLORSPACE_YUV422) && + (output_color_format == COLORSPACE_YUV422)) ? 1 : 0) << 0); + hdmitx_wr_reg(HDMITX_DWC_CSC_CFG, data32); + hdmitx_csc_config(input_color_format, output_color_format, color_depth); + + /* Configure video packetizer */ + + /* Video Packet color depth and pixel repetition */ + data32 = 0; + data32 |= (((output_color_format == COLORSPACE_YUV422) ? + COLORDEPTH_24B : color_depth) << 4); + data32 |= (0 << 0); + if ((data32 & 0xf0) == 0x40) + data32 &= ~(0xf << 4); + hdmitx_wr_reg(HDMITX_DWC_VP_PR_CD, data32); + if (output_color_format == COLORSPACE_YUV422) { + if (color_depth == COLORDEPTH_24B) + hdmitx_set_reg_bits(HDMITX_DWC_VP_PR_CD, 0x4, 4, 4); + else + hdmitx_set_reg_bits(HDMITX_DWC_VP_PR_CD, 0, 4, 4); + } + + /* Video Packet Stuffing */ + data32 = 0; + data32 |= (default_phase << 5); + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_VP_STUFF, data32); + + /* Video Packet YCC color remapping */ + data32 = 0; + data32 |= (((color_depth == COLORDEPTH_30B) ? 1 : + (color_depth == COLORDEPTH_36B) ? 2 : 0) << 0); + hdmitx_wr_reg(HDMITX_DWC_VP_REMAP, data32); + if (output_color_format == COLORSPACE_YUV422) { + switch (color_depth) { + case COLORDEPTH_36B: + tmp = 2; + break; + case COLORDEPTH_30B: + tmp = 1; + break; + case COLORDEPTH_24B: + tmp = 0; + break; + } + } + /* [1:0] ycc422_size */ + hdmitx_set_reg_bits(HDMITX_DWC_VP_REMAP, tmp, 0, 2); + + /* Video Packet configuration */ + data32 = 0; + data32 |= ((((output_color_format != COLORSPACE_YUV422) && + (color_depth == COLORDEPTH_24B)) ? 1 : 0) << 6); + data32 |= ((((output_color_format == COLORSPACE_YUV422) || + (color_depth == COLORDEPTH_24B)) ? 0 : 1) << 5); + data32 |= (0 << 4); + data32 |= (((output_color_format == COLORSPACE_YUV422) ? 1 : 0) + << 3); + data32 |= (1 << 2); + data32 |= (((output_color_format == COLORSPACE_YUV422) ? 1 : + (color_depth == COLORDEPTH_24B) ? 2 : 0) << 0); + hdmitx_wr_reg(HDMITX_DWC_VP_CONF, data32); + + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_VP_MASK, data32); + + /* Configure audio */ + /* I2S Sampler config */ + + data32 = 0; + data32 |= (1 << 3); + data32 |= (1 << 2); + hdmitx_wr_reg(HDMITX_DWC_AUD_INT, data32); + + data32 = 0; + data32 |= (1 << 4); + hdmitx_wr_reg(HDMITX_DWC_AUD_INT1, data32); + + hdmitx_wr_reg(HDMITX_DWC_FC_MULTISTREAM_CTRL, 0); + +/* if enable it now, fifo_overrun will happen, because packet don't get + * sent out until initial DE detected. + */ + data32 = 0; + data32 |= (0 << 7); + data32 |= (tx_aud_src << 5); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF0, data32); + + data32 = 0; + data32 |= (0 << 5); + data32 |= (24 << 0); + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF1, data32); + + data32 = 0; + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_AUD_CONF2, data32); + + /* spdif sampler config */ + + data32 = 0; + data32 |= (1 << 3); + data32 |= (1 << 2); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIFINT, data32); + + data32 = 0; + data32 |= (0 << 4); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIFINT1, data32); + + data32 = 0; + data32 |= (0 << 7); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIF0, data32); + + data32 = 0; + data32 |= (0 << 7); + data32 |= (0 << 6); + data32 |= (24 << 0); + hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIF1, data32); + + /* Frame Composer configuration */ + + /* Video definitions, as per output video(for packet gen/schedulling) */ + + data32 = 0; + data32 |= (1 << 7); + data32 |= (GET_TIMING(vsync_polarity) << 6); + data32 |= (GET_TIMING(hsync_polarity) << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (!(para->progress_mode) << 1); + data32 |= (!(para->progress_mode) << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_INVIDCONF, data32); + + data32 = GET_TIMING(h_active)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_INHACTV0, data32); + data32 = (GET_TIMING(h_active)>>8) & 0x3f; + hdmitx_wr_reg(HDMITX_DWC_FC_INHACTV1, data32); + + data32 = GET_TIMING(h_blank) & 0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_INHBLANK0, data32); + data32 = (GET_TIMING(h_blank)>>8)&0x1f; + hdmitx_wr_reg(HDMITX_DWC_FC_INHBLANK1, data32); + + if (hdev->flag_3dfp) { + data32 = (((GET_TIMING(v_active)) * 2) + (GET_TIMING(v_blank))); + hdmitx_wr_reg(HDMITX_DWC_FC_INVACTV0, data32 & 0xff); + hdmitx_wr_reg(HDMITX_DWC_FC_INVACTV1, (data32 >> 8) & 0x1f); + } else { + data32 = GET_TIMING(v_active) & 0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_INVACTV0, data32); + data32 = (GET_TIMING(v_active) >> 8) & 0x1f; + hdmitx_wr_reg(HDMITX_DWC_FC_INVACTV1, data32); + } + data32 = GET_TIMING(v_blank)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_INVBLANK, data32); + + data32 = GET_TIMING(h_front)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINDELAY0, data32); + data32 = (GET_TIMING(h_front)>>8)&0x1f; + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINDELAY1, data32); + + data32 = GET_TIMING(h_sync)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINWIDTH0, data32); + data32 = (GET_TIMING(h_sync)>>8)&0x3; + hdmitx_wr_reg(HDMITX_DWC_FC_HSYNCINWIDTH1, data32); + + data32 = GET_TIMING(v_front)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_VSYNCINDELAY, data32); + + data32 = GET_TIMING(v_sync)&0x3f; + hdmitx_wr_reg(HDMITX_DWC_FC_VSYNCINWIDTH, data32); + + /* control period duration (typ 12 tmds periods) */ + hdmitx_wr_reg(HDMITX_DWC_FC_CTRLDUR, 12); + /* extended control period duration (typ 32 tmds periods) */ + hdmitx_wr_reg(HDMITX_DWC_FC_EXCTRLDUR, 32); + /* max interval betwen extended control period duration (typ 50) */ + hdmitx_wr_reg(HDMITX_DWC_FC_EXCTRLSPAC, 1); + /* preamble filler */ + hdmitx_wr_reg(HDMITX_DWC_FC_CH0PREAM, 0x0b); + hdmitx_wr_reg(HDMITX_DWC_FC_CH1PREAM, 0x16); + hdmitx_wr_reg(HDMITX_DWC_FC_CH2PREAM, 0x21); + + /* write GCP packet configuration */ + data32 = 0; + data32 |= (default_phase << 2); + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_GCP, data32); + + /* write AVI Infoframe packet configuration */ + + data32 = 0; + data32 |= (((output_color_format>>2)&0x1) << 7); + data32 |= (1 << 6); + data32 |= (0 << 4); + data32 |= (0 << 2); + data32 |= (0x2 << 0); /* FIXED YCBCR 444 */ + hdmitx_wr_reg(HDMITX_DWC_FC_AVICONF0, data32); + switch (output_color_format) { + case COLORSPACE_RGB444: + tmp = 0; + break; + case COLORSPACE_YUV422: + tmp = 1; + break; + case COLORSPACE_YUV420: + tmp = 3; + break; + case COLORSPACE_YUV444: + default: + tmp = 2; + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, tmp, 0, 2); + + hdmitx_wr_reg(HDMITX_DWC_FC_AVICONF1, 0x8); + hdmitx_wr_reg(HDMITX_DWC_FC_AVICONF2, 0); + + /* set Aspect Ratio in AVIInfo */ + switch (para->vic) { + case HDMI_640x480p60_4x3: + case HDMI_720x480p60_4x3: + case HDMI_720x480i60_4x3: + case HDMI_720x240p60_4x3: + case HDMI_2880x480i60_4x3: + case HDMI_2880x240p60_4x3: + case HDMI_1440x480p60_4x3: + case HDMI_720x576p50_4x3: + case HDMI_720x576i50_4x3: + case HDMI_720x288p_4x3: + case HDMI_2880x576i50_4x3: + case HDMI_2880x288p50_4x3: + case HDMI_1440x576p_4x3: + case HDMI_2880x480p60_4x3: + case HDMI_2880x576p50_4x3: + case HDMI_720x576p100_4x3: + case HDMI_720x576i100_4x3: + case HDMI_720x480p120_4x3: + case HDMI_720x480i120_4x3: + case HDMI_720x576p200_4x3: + case HDMI_720x576i200_4x3: + case HDMI_720x480p240_4x3: + case HDMI_720x480i240_4x3: + /* Picture Aspect Ratio M1/M0 4:3 */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 0x1, 4, 2); + break; + default: + /* Picture Aspect Ratio M1/M0 16:9 */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 0x2, 4, 2); + break; + } + /* Active Format Aspect Ratio R3~R0 Same as picture aspect ratio */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF1, 0x8, 0, 4); + + hdmitx_set_avi_colorimetry(para); + if (hdev->hdr_src_feature) + hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, SET_AVI_BT2020); + + data32 = 0; + data32 |= (((0 == COLORRANGE_FUL) ? 1 : 0) << 2); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AVICONF3, data32); + + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, (para->vic & HDMITX_VIC_MASK)); + + /* write Audio Infoframe packet configuration */ + + data32 = 0; + data32 |= (1 << 4); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF0, data32); + + data32 = 0; + data32 |= (3 << 4); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF1, data32); + + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF2, 0x00); + + data32 = 0; + data32 |= (1 << 5); + data32 |= (0 << 4); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF3, data32); + + /* write audio packet configuration */ + data32 = 0; + data32 |= (0 << 4); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCONF, data32); + +/* the audio setting bellow are only used for I2S audio IEC60958-3 frame + * insertion + */ + data32 = 0; + data32 |= (0 << 7); + data32 |= (0 << 6); + data32 |= (0 << 5); + data32 |= (1 << 4); + data32 |= (0 << 3); + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSV, data32); + + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSU, 0); + + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS0, 0x01); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS1, 0x23); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS2, 0x45); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS3, 0x67); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS4, 0x89); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS5, 0xab); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS6, 0xcd); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS7, 0x2f); + hdmitx_wr_reg(HDMITX_DWC_FC_AUDSCHNLS8, 0xf0); + + /* packet queue priority (auto mode) */ + hdmitx_wr_reg(HDMITX_DWC_FC_CTRLQHIGH, 15); + hdmitx_wr_reg(HDMITX_DWC_FC_CTRLQLOW, 3); + + /* packet scheduller configuration for SPD, VSD, ISRC1/2, ACP. */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 0, 3); + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 4, 4); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_DATMAN, 0); + + /* packet scheduller configuration for AVI, GCP, AUDI, ACR. */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 0xe, 0, 6); + /* If RX not support HDR, then disable HDR send out */ + if (!hdev->RXCap.hdr_sup_eotf_smpte_st_2084) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 0, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 0, 7, 1); + } else { + /* If RX support HDR, and feature is HDR, + * then enable HDR send out + */ + if (hdev->hdr_src_feature) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 1, 6, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, + 1, 7, 1); + } + } + + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB0, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB2, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB3, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB4, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB5, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB6, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB7, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB8, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB9, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB10, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_RDRB11, 0); + + /* Packet transmission enable */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 1, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 2, 1); + + /* For 3D video */ + data32 = 0; + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_ACTSPC_HDLR_CFG, data32); + + data32 = GET_TIMING(v_active)&0xff; + hdmitx_wr_reg(HDMITX_DWC_FC_INVACT_2D_0, data32); + data32 = (GET_TIMING(v_active)>>8)&0xf; + hdmitx_wr_reg(HDMITX_DWC_FC_INVACT_2D_1, data32); + + /* Do not enable these interrupt below, we can check them at RX side. */ + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 5); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_MASK0, data32); + + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_MASK1, data32); + + data32 = 0; + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_MASK2, data32); + + /* Pixel repetition ratio the input and output video */ + data32 = 0; + data32 |= ((para->pixel_repetition_factor+1) << 4); + data32 |= (para->pixel_repetition_factor << 0); + hdmitx_wr_reg(HDMITX_DWC_FC_PRCONF, data32); + + /* Configure HDCP */ + data32 = 0; + data32 |= (0 << 7); + data32 |= (0 << 6); + data32 |= (0 << 4); + data32 |= (0 << 3); + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_A_APIINTMSK, data32); + + data32 = 0; + data32 |= (0 << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 1); + hdmitx_wr_reg(HDMITX_DWC_A_VIDPOLCFG, data32); + + hdmitx_wr_reg(HDMITX_DWC_A_OESSWCFG, 0x40); + if (hdmitx_hdcp_opr(0xa)) + hdmitx_hdcp_opr(0); + /* Interrupts */ + /* Clear interrupts */ + hdmitx_wr_reg(HDMITX_DWC_IH_FC_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_FC_STAT1, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_FC_STAT2, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_AS_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_PHY_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_CEC_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_VP_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_IH_I2CMPHY_STAT0, 0xff); + hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 0xff); + hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff); + + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0x0000001f); + + /* Selectively enable/mute interrupt sources */ + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_FC_STAT0, data32); + + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 5); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_FC_STAT1, data32); + + data32 = 0; + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_FC_STAT2, data32); + + data32 = 0; + data32 |= (0 << 4); + data32 |= (0 << 3); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_AS_STAT0, data32); + + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_PHY_STAT0, 0x3f); + + data32 = 0; + data32 |= (0 << 2); + data32 |= (1 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_I2CM_STAT0, data32); + + data32 = 0; + data32 |= (0 << 6); + data32 |= (0 << 5); + data32 |= (0 << 4); + data32 |= (0 << 3); + data32 |= (0 << 2); + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_CEC_STAT0, data32); + + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_VP_STAT0, 0xff); + + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0, 0x03); + + data32 = 0; + data32 |= (0 << 1); + data32 |= (0 << 0); + hdmitx_wr_reg(HDMITX_DWC_IH_MUTE, data32); + + data32 = 0; + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 2); + data32 |= (1 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_TOP_INTR_MASKN, data32); + + /* Reset pulse */ + hdmitx_rd_check_reg(HDMITX_DWC_MC_LOCKONCLOCK, 0xff, 0x9f); + hdmitx_wr_reg(HDMITX_DWC_MC_SWRSTZREQ, 0); + mdelay(10); + + data32 = 0; + data32 |= (1 << 7); + data32 |= (1 << 6); + data32 |= (1 << 4); + data32 |= (1 << 3); + data32 |= (1 << 2); + data32 |= (0 << 1); + data32 |= (1 << 0); + hdmitx_wr_reg(HDMITX_DWC_MC_SWRSTZREQ, data32); + hdmitx_wr_reg(HDMITX_DWC_FC_VSYNCINWIDTH, + hdmitx_rd_reg(HDMITX_DWC_FC_VSYNCINWIDTH)); +} /* config_hdmi20_tx */ + +/* TODO */ +static void hdmitx_csc_config(unsigned char input_color_format, + unsigned char output_color_format, + unsigned char color_depth) +{ + unsigned char conv_en; + unsigned char csc_scale; + unsigned char rgb_ycc_indicator; + unsigned long csc_coeff_a1, csc_coeff_a2, csc_coeff_a3, csc_coeff_a4; + unsigned long csc_coeff_b1, csc_coeff_b2, csc_coeff_b3, csc_coeff_b4; + unsigned long csc_coeff_c1, csc_coeff_c2, csc_coeff_c3, csc_coeff_c4; + unsigned long data32; + + conv_en = (((input_color_format == COLORSPACE_RGB444) || + (output_color_format == COLORSPACE_RGB444)) && + (input_color_format != output_color_format)) ? 1 : 0; + + if (conv_en) { + if (output_color_format == COLORSPACE_RGB444) { + csc_coeff_a1 = 0x2000; + csc_coeff_a2 = 0x6926; + csc_coeff_a3 = 0x74fd; + csc_coeff_a4 = (color_depth == COLORDEPTH_24B) ? + 0x010e : + (color_depth == COLORDEPTH_30B) ? 0x043b : + (color_depth == COLORDEPTH_36B) ? 0x10ee : + (color_depth == COLORDEPTH_48B) ? 0x10ee : 0x010e; + csc_coeff_b1 = 0x2000; + csc_coeff_b2 = 0x2cdd; + csc_coeff_b3 = 0x0000; + csc_coeff_b4 = (color_depth == COLORDEPTH_24B) ? 0x7e9a : + (color_depth == COLORDEPTH_30B) ? 0x7a65 : + (color_depth == COLORDEPTH_36B) ? 0x6992 : + (color_depth == COLORDEPTH_48B) ? 0x6992 : 0x7e9a; + csc_coeff_c1 = 0x2000; + csc_coeff_c2 = 0x0000; + csc_coeff_c3 = 0x38b4; + csc_coeff_c4 = (color_depth == COLORDEPTH_24B) ? 0x7e3b : + (color_depth == COLORDEPTH_30B) ? 0x78ea : + (color_depth == COLORDEPTH_36B) ? 0x63a6 : + (color_depth == COLORDEPTH_48B) ? 0x63a6 : 0x7e3b; + csc_scale = 1; + } else { /* input_color_format == COLORSPACE_RGB444 */ + csc_coeff_a1 = 0x2591; + csc_coeff_a2 = 0x1322; + csc_coeff_a3 = 0x074b; + csc_coeff_a4 = 0x0000; + csc_coeff_b1 = 0x6535; + csc_coeff_b2 = 0x2000; + csc_coeff_b3 = 0x7acc; + csc_coeff_b4 = (color_depth == COLORDEPTH_24B) ? 0x0200 : + (color_depth == COLORDEPTH_30B) ? 0x0800 : + (color_depth == COLORDEPTH_36B) ? 0x2000 : + (color_depth == COLORDEPTH_48B) ? 0x2000 : 0x0200; + csc_coeff_c1 = 0x6acd; + csc_coeff_c2 = 0x7534; + csc_coeff_c3 = 0x2000; + csc_coeff_c4 = (color_depth == COLORDEPTH_24B) ? 0x0200 : + (color_depth == COLORDEPTH_30B) ? 0x0800 : + (color_depth == COLORDEPTH_36B) ? 0x2000 : + (color_depth == COLORDEPTH_48B) ? 0x2000 : 0x0200; + csc_scale = 0; + } + } else { + csc_coeff_a1 = 0x2000; + csc_coeff_a2 = 0x0000; + csc_coeff_a3 = 0x0000; + csc_coeff_a4 = 0x0000; + csc_coeff_b1 = 0x0000; + csc_coeff_b2 = 0x2000; + csc_coeff_b3 = 0x0000; + csc_coeff_b4 = 0x0000; + csc_coeff_c1 = 0x0000; + csc_coeff_c2 = 0x0000; + csc_coeff_c3 = 0x2000; + csc_coeff_c4 = 0x0000; + csc_scale = 1; + } + + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A1_MSB, (csc_coeff_a1>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A1_LSB, csc_coeff_a1&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A2_MSB, (csc_coeff_a2>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A2_LSB, csc_coeff_a2&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A3_MSB, (csc_coeff_a3>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A3_LSB, csc_coeff_a3&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A4_MSB, (csc_coeff_a4>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_A4_LSB, csc_coeff_a4&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B1_MSB, (csc_coeff_b1>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B1_LSB, csc_coeff_b1&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B2_MSB, (csc_coeff_b2>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B2_LSB, csc_coeff_b2&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B3_MSB, (csc_coeff_b3>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B3_LSB, csc_coeff_b3&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B4_MSB, (csc_coeff_b4>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_B4_LSB, csc_coeff_b4&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C1_MSB, (csc_coeff_c1>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C1_LSB, csc_coeff_c1&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C2_MSB, (csc_coeff_c2>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C2_LSB, csc_coeff_c2&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C3_MSB, (csc_coeff_c3>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C3_LSB, csc_coeff_c3&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C4_MSB, (csc_coeff_c4>>8)&0xff); + hdmitx_wr_reg(HDMITX_DWC_CSC_COEF_C4_LSB, csc_coeff_c4&0xff); + + data32 = 0; + data32 |= (color_depth << 4); /* [7:4] csc_color_depth */ + data32 |= (csc_scale << 0); /* [1:0] cscscale */ + hdmitx_wr_reg(HDMITX_DWC_CSC_SCALE, data32); + + /* set csc in video path */ + hdmitx_wr_reg(HDMITX_DWC_MC_FLOWCTRL, (conv_en == 1)?0x1:0x0); + + /* set rgb_ycc indicator */ + switch (output_color_format) { + case COLORSPACE_RGB444: + rgb_ycc_indicator = 0x0; + break; + case COLORSPACE_YUV422: + rgb_ycc_indicator = 0x1; + break; + case COLORSPACE_YUV420: + rgb_ycc_indicator = 0x3; + break; + case COLORSPACE_YUV444: + default: + rgb_ycc_indicator = 0x2; + break; + } + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, + ((rgb_ycc_indicator & 0x4) >> 2), 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF0, + (rgb_ycc_indicator & 0x3), 0, 2); +} /* hdmitx_csc_config */ + +static void hdmitx_set_hw(struct hdmitx_dev *hdev) +{ + enum hdmi_vic vic = HDMI_Unknown; + struct hdmi_format_para *para = NULL; + + if (hdev->cur_video_param == NULL) { + pr_info("error at null vidpara!\n"); + return; + } + + vic = (enum hdmi_vic)hdev->cur_video_param->VIC; + para = hdmi_get_fmt_paras(vic); + if (para == NULL) { + pr_info("error at %s[%d] vic = %d\n", __func__, __LINE__, vic); + return; + } + + pr_info("%s[%d] set VIC = %d\n", __func__, __LINE__, para->vic); + config_hdmi20_tx(vic, hdev, + hdev->para->cd, + TX_INPUT_COLOR_FORMAT, + hdev->para->cs); +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h new file mode 100644 index 000000000000..516661fa78e0 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h @@ -0,0 +1,1059 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _HDMI_TX_REG_H +#define _HDMI_TX_REG_H + +/* Use the following functions to access the on-chip HDMITX modules + * by default + */ +void hdmitx_wr_reg(unsigned int addr, unsigned int data); +void hdmitx_poll_reg(unsigned int addr, unsigned int val, + unsigned long timeout); +void hdmitx_set_reg_bits(unsigned int addr, unsigned int value, + unsigned int offset, unsigned int len); +unsigned int hdmitx_rd_reg(unsigned int addr); +void hdmitx_rd_check_reg(unsigned int addr, unsigned int exp_data, + unsigned int mask); +unsigned long aocec_rd_reg(unsigned long addr); +void aocec_wr_reg(unsigned long addr, unsigned long data); +void hdcp22_wr_reg(uint32_t addr, uint32_t data); +uint32_t hdcp22_rd_reg(uint32_t addr); +int hdmitx_hdcp_opr(unsigned int val); + +/* TOP-level wrapper registers addresses + * bit24: 1 means secure access + * bit28: 1 means DWC, 0 means TOP + */ +#define SEC_OFFSET (0x1UL << 24) +#define TOP_OFFSET_MASK (0x0UL << 24) +#define TOP_SEC_OFFSET_MASK ((TOP_OFFSET_MASK) | (SEC_OFFSET)) +#define DWC_OFFSET_MASK (0x10UL << 24) +#define DWC_SEC_OFFSET_MASK ((DWC_OFFSET_MASK) | (SEC_OFFSET)) + +/* Bit 7 RW Reserved. Default 1. + * Bit 6 RW Reserved. Default 1. + * Bit 5 RW Reserved. Default 1. + * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset. + * Default 1. + * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset; + * 0=Release from reset. Default 1. + * Bit 2 RW sw_reset_mem: KSV/REVOC mem. 1=Apply reset; 0=Release from reset. + * Default 1. + * Bit 1 RW sw_reset_rnd: random number interface to HDCP. 1=Apply reset; + * 0=Release from reset. Default 1. + * Bit 0 RW sw_reset_core: connects to IP's ~irstz. 1=Apply reset; + * 0=Release from reset. Default 1. + */ +#define HDMITX_TOP_SW_RESET (TOP_OFFSET_MASK + 0x000) + +/* Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0. */ +/* Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0. */ +/* Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0. */ +/* Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0. */ +/* Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0. */ +/* Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. */ +/* Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0. */ +/* Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0. */ +/* Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0. */ +/* Bit 0 RW pixel_clk_en: 1=enable pixel_clk; 0=disable. Default 0. */ +#define HDMITX_TOP_CLK_CNTL (TOP_OFFSET_MASK + 0x001) + +/* Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0. */ +/* Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0. */ +#define HDMITX_TOP_HPD_FILTER (TOP_OFFSET_MASK + 0x002) + +/* intr_maskn: MASK_N, one bit per interrupt source. + * 1=Enable interrupt source; 0=Disable interrupt source. Default 0. + * [ 4] hdcp22_rndnum_err + * [ 3] nonce_rfrsh_rise + * [ 2] hpd_fall_intr + * [ 1] hpd_rise_intr + * [ 0] core_intr + */ +#define HDMITX_TOP_INTR_MASKN (TOP_OFFSET_MASK + 0x003) + +/* Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt + * bit, read back the interrupt status. + * Bit 31 R IP interrupt status + * Bit 2 RW hpd_fall + * Bit 1 RW hpd_rise + * Bit 0 RW IP interrupt + */ +#define HDMITX_TOP_INTR_STAT (TOP_OFFSET_MASK + 0x004) + +/* [4] hdcp22_rndnum_err */ +/* [3] nonce_rfrsh_rise */ +/* [2] hpd_fall */ +/* [1] hpd_rise */ +/* [0] core_intr_rise */ +#define HDMITX_TOP_INTR_STAT_CLR (TOP_OFFSET_MASK + 0x005) + +/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data; + * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0. + * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern + * every 2 clk cycles; ...; 7=New pattern every 8 clk cycles. Default 0. + * Bit 8 RW shift_pttn_en: 1= Eanble shift pattern generator; 0=Disable. + * Default 0. + * Bit 4: 3 RW prbs_pttn_mode: 0=PRBS11; 1=PRBS15; 2=PRBS7; 3=PRBS31. Default 0. + * Bit 2: 1 RW prbs_pttn_width: 0=idle; 1=output 8-bit pattern; + * 2=Output 1-bit pattern; 3=output 10-bit pattern. Default 0. + * Bit 0 RW prbs_pttn_en: 1=Enable PRBS generator; 0=Disable. Default 0. + */ +#define HDMITX_TOP_BIST_CNTL (TOP_OFFSET_MASK + 0x006) + +/* Bit 29:20 RW shift_pttn_data[59:50]. Default 0. */ +/* Bit 19:10 RW shift_pttn_data[69:60]. Default 0. */ +/* Bit 9: 0 RW shift_pttn_data[79:70]. Default 0. */ +#define HDMITX_TOP_SHIFT_PTTN_012 (TOP_OFFSET_MASK + 0x007) + +/* Bit 29:20 RW shift_pttn_data[29:20]. Default 0. */ +/* Bit 19:10 RW shift_pttn_data[39:30]. Default 0. */ +/* Bit 9: 0 RW shift_pttn_data[49:40]. Default 0. */ +#define HDMITX_TOP_SHIFT_PTTN_345 (TOP_OFFSET_MASK + 0x008) + +/* Bit 19:10 RW shift_pttn_data[ 9: 0]. Default 0. */ +/* Bit 9: 0 RW shift_pttn_data[19:10]. Default 0. */ +#define HDMITX_TOP_SHIFT_PTTN_67 (TOP_OFFSET_MASK + 0x009) + +/* Bit 25:16 RW tmds_clk_pttn[19:10]. Default 0. */ +/* Bit 9: 0 RW tmds_clk_pttn[ 9: 0]. Default 0. */ +#define HDMITX_TOP_TMDS_CLK_PTTN_01 (TOP_OFFSET_MASK + 0x00A) + +/* Bit 25:16 RW tmds_clk_pttn[39:30]. Default 0. */ +/* Bit 9: 0 RW tmds_clk_pttn[29:20]. Default 0. */ +#define HDMITX_TOP_TMDS_CLK_PTTN_23 (TOP_OFFSET_MASK + 0x00B) + +/* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern, + * used when TMDS CLK rate = TMDS character rate /4. Default 0. + * Bit 0 R Reserved. Default 0. + */ +/* [ 1] shift_tmds_clk_pttn */ +/* [ 0] load_tmds_clk_pttn */ +#define HDMITX_TOP_TMDS_CLK_PTTN_CNTL (TOP_OFFSET_MASK + 0x00C) + +/* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM + * failure, write 1 to clear the failure flag. Default 0. + */ +#define HDMITX_TOP_REVOCMEM_STAT (TOP_OFFSET_MASK + 0x00D) + +/* Bit 0 R filtered HPD status. */ +#define HDMITX_TOP_STAT0 (TOP_OFFSET_MASK + 0x00E) +#define HDMITX_TOP_SKP_CNTL_STAT (TOP_SEC_OFFSET_MASK + 0x010) +#define HDMITX_TOP_NONCE_0 (TOP_SEC_OFFSET_MASK + 0x011) +#define HDMITX_TOP_NONCE_1 (TOP_SEC_OFFSET_MASK + 0x012) +#define HDMITX_TOP_NONCE_2 (TOP_SEC_OFFSET_MASK + 0x013) +#define HDMITX_TOP_NONCE_3 (TOP_SEC_OFFSET_MASK + 0x014) +#define HDMITX_TOP_PKF_0 (TOP_SEC_OFFSET_MASK + 0x015) +#define HDMITX_TOP_PKF_1 (TOP_SEC_OFFSET_MASK + 0x016) +#define HDMITX_TOP_PKF_2 (TOP_SEC_OFFSET_MASK + 0x017) +#define HDMITX_TOP_PKF_3 (TOP_SEC_OFFSET_MASK + 0x018) +#define HDMITX_TOP_DUK_0 (TOP_SEC_OFFSET_MASK + 0x019) +#define HDMITX_TOP_DUK_1 (TOP_SEC_OFFSET_MASK + 0x01A) +#define HDMITX_TOP_DUK_2 (TOP_SEC_OFFSET_MASK + 0x01B) +#define HDMITX_TOP_DUK_3 (TOP_SEC_OFFSET_MASK + 0x01C) +/* [26:24] infilter_ddc_intern_clk_divide */ +/* [23:16] infilter_ddc_sample_clk_divide */ +/* [10: 8] infilter_cec_intern_clk_divide */ +/* [ 7: 0] infilter_cec_sample_clk_divide */ +#define HDMITX_TOP_INFILTER (TOP_OFFSET_MASK + 0x01D) +#define HDMITX_TOP_NSEC_SCRATCH (TOP_OFFSET_MASK + 0x01E) +#define HDMITX_TOP_SEC_SCRATCH (TOP_SEC_OFFSET_MASK + 0x01F) + +#define HDMITX_TOP_DONT_TOUCH0 (TOP_OFFSET_MASK + 0x0FE) +#define HDMITX_TOP_DONT_TOUCH1 (TOP_OFFSET_MASK + 0x0FF) + +/* DWC_HDMI_TX Controller registers addresses */ + +/* Identification Registers */ +#define HDMITX_DWC_DESIGN_ID (DWC_OFFSET_MASK + 0x0000) +#define HDMITX_DWC_REVISION_ID (DWC_OFFSET_MASK + 0x0001) +#define HDMITX_DWC_PRODUCT_ID0 (DWC_OFFSET_MASK + 0x0002) +#define HDMITX_DWC_PRODUCT_ID1 (DWC_OFFSET_MASK + 0x0003) +#define HDMITX_DWC_CONFIG0_ID (DWC_OFFSET_MASK + 0x0004) +#define HDMITX_DWC_CONFIG1_ID (DWC_OFFSET_MASK + 0x0005) +#define HDMITX_DWC_CONFIG2_ID (DWC_OFFSET_MASK + 0x0006) +#define HDMITX_DWC_CONFIG3_ID (DWC_OFFSET_MASK + 0x0007) + +/* Interrupt Registers */ +#define HDMITX_DWC_IH_FC_STAT0 (DWC_OFFSET_MASK + 0x0100) +#define HDMITX_DWC_IH_FC_STAT1 (DWC_OFFSET_MASK + 0x0101) +#define HDMITX_DWC_IH_FC_STAT2 (DWC_OFFSET_MASK + 0x0102) +#define HDMITX_DWC_IH_AS_STAT0 (DWC_OFFSET_MASK + 0x0103) +#define HDMITX_DWC_IH_PHY_STAT0 (DWC_OFFSET_MASK + 0x0104) +#define HDMITX_DWC_IH_I2CM_STAT0 (DWC_OFFSET_MASK + 0x0105) +#define HDMITX_DWC_IH_CEC_STAT0 (DWC_OFFSET_MASK + 0x0106) +#define HDMITX_DWC_IH_VP_STAT0 (DWC_OFFSET_MASK + 0x0107) +#define HDMITX_DWC_IH_I2CMPHY_STAT0 (DWC_OFFSET_MASK + 0x0108) +#define HDMITX_DWC_IH_DECODE (DWC_OFFSET_MASK + 0x0170) +/* [ 7] mute_AUDI */ +/* [ 6] mute_ACP */ +/* [ 5] mute_HBR */ +/* [ 4] mute_MAS */ +/* [ 3] mute_NVBI */ +/* [ 2] mute_AUDS */ +/* [ 1] mute_ACR */ +/* [ 0] mute_NULL */ +#define HDMITX_DWC_IH_MUTE_FC_STAT0 (DWC_OFFSET_MASK + 0x0180) +/* [ 7] mute_GMD */ +/* [ 6] mute_ISRC1 */ +/* [ 5] mute_ISRC2 */ +/* [ 4] mute_VSD */ +/* [ 3] mute_SPD */ +/* [ 2] mute_AMP */ +/* [ 1] mute_AVI */ +/* [ 0] mute_GCP */ +#define HDMITX_DWC_IH_MUTE_FC_STAT1 (DWC_OFFSET_MASK + 0x0181) +/* [ 1] mute_LowPriority_fifo_full */ +/* [ 0] mute_HighPriority_fifo_full */ +#define HDMITX_DWC_IH_MUTE_FC_STAT2 (DWC_OFFSET_MASK + 0x0182) +/* [ 4] mute_aud_fifo_underrun */ +/* [ 3] mute_aud_fifo_overrun */ +/* [ 2] mute_aud_fifo_empty_thr. oififoemptythr tied to 0. */ +/* [ 1] mute_aud_fifo_empty */ +/* [ 0] mute_aud_fifo_full */ +#define HDMITX_DWC_IH_MUTE_AS_STAT0 (DWC_OFFSET_MASK + 0x0183) +#define HDMITX_DWC_IH_MUTE_PHY_STAT0 (DWC_OFFSET_MASK + 0x0184) +/* [ 2] mute_scdc_readreq */ +/* [ 1] mute_edid_i2c_master_done */ +/* [ 0] mute_edid_i2c_master_error */ +#define HDMITX_DWC_IH_MUTE_I2CM_STAT0 (DWC_OFFSET_MASK + 0x0185) +/* [ 6] cec_wakeup */ +/* [ 5] cec_error_follower */ +/* [ 4] cec_error_initiator */ +/* [ 3] cec_arb_lost */ +/* [ 2] cec_nack */ +/* [ 1] cec_eom */ +/* [ 0] cec_done */ +#define HDMITX_DWC_IH_MUTE_CEC_STAT0 (DWC_OFFSET_MASK + 0x0186) +#define HDMITX_DWC_IH_MUTE_VP_STAT0 (DWC_OFFSET_MASK + 0x0187) +#define HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0 (DWC_OFFSET_MASK + 0x0188) +/* [ 1] mute_wakeup_interrupt */ +/* [ 0] mute_all_interrupt */ +#define HDMITX_DWC_IH_MUTE (DWC_OFFSET_MASK + 0x01FF) + +/* Video Sampler Registers */ +/* [ 7] internal_de_generator */ +/* [4:0] video_mapping */ +#define HDMITX_DWC_TX_INVID0 (DWC_OFFSET_MASK + 0x0200) +/* [ 2] bcbdata_stuffing */ +/* [ 1] rcrdata_stuffing */ +/* [ 0] gydata_stuffing */ +#define HDMITX_DWC_TX_INSTUFFING (DWC_OFFSET_MASK + 0x0201) +#define HDMITX_DWC_TX_GYDATA0 (DWC_OFFSET_MASK + 0x0202) +#define HDMITX_DWC_TX_GYDATA1 (DWC_OFFSET_MASK + 0x0203) +#define HDMITX_DWC_TX_RCRDATA0 (DWC_OFFSET_MASK + 0x0204) +#define HDMITX_DWC_TX_RCRDATA1 (DWC_OFFSET_MASK + 0x0205) +#define HDMITX_DWC_TX_BCBDATA0 (DWC_OFFSET_MASK + 0x0206) +#define HDMITX_DWC_TX_BCBDATA1 (DWC_OFFSET_MASK + 0x0207) + +/* Video Packetizer Registers */ +#define HDMITX_DWC_VP_STATUS (DWC_OFFSET_MASK + 0x0800) +/* [3:0] desired_pr_factor */ +#define HDMITX_DWC_VP_PR_CD (DWC_OFFSET_MASK + 0x0801) +/* [ 5] default_phase */ +/* [ 2] ycc422_stuffing */ +/* [ 1] pp_stuffing */ +/* [ 0] pr_stuffing */ +#define HDMITX_DWC_VP_STUFF (DWC_OFFSET_MASK + 0x0802) +#define HDMITX_DWC_VP_REMAP (DWC_OFFSET_MASK + 0x0803) +#define HDMITX_DWC_VP_CONF (DWC_OFFSET_MASK + 0x0804) +/* [ 7] mask_int_full_prpt */ +/* [ 6] mask_int_empty_prpt */ +/* [ 5] mask_int_full_ppack */ +/* [ 4] mask_int_empty_ppack */ +/* [ 3] mask_int_full_remap */ +/* [ 2] mask_int_empty_remap */ +/* [ 1] mask_int_full_byp */ +/* [ 0] mask_int_empty_byp */ +#define HDMITX_DWC_VP_MASK (DWC_OFFSET_MASK + 0x0807) + +/* Frmae Composer Registers */ +/* [ 7] HDCP_keepout */ +/* [ 6] vs_in_pol: 0=active low; 1=active high. */ +/* [ 5] hs_in_pol: 0=active low; 1=active high. */ +/* [ 4] de_in_pol: 0=active low; 1=active high. */ +/* [ 3] dvi_modez: 0=dvi; 1=hdmi. */ +/* [ 1] r_v_blank_in_osc */ +/* [ 0] in_I_P: 0=progressive; 1=interlaced. */ +#define HDMITX_DWC_FC_INVIDCONF (DWC_OFFSET_MASK + 0x1000) +/* [7:0] H_in_active[7:0] */ +#define HDMITX_DWC_FC_INHACTV0 (DWC_OFFSET_MASK + 0x1001) +/* [5:0] H_in_active[13:8] */ +#define HDMITX_DWC_FC_INHACTV1 (DWC_OFFSET_MASK + 0x1002) +/* [7:0] H_in_blank[7:0] */ +#define HDMITX_DWC_FC_INHBLANK0 (DWC_OFFSET_MASK + 0x1003) +/* [4:0] H_in_blank[12:8] */ +#define HDMITX_DWC_FC_INHBLANK1 (DWC_OFFSET_MASK + 0x1004) +/* [7:0] V_in_active[7:0] */ +#define HDMITX_DWC_FC_INVACTV0 (DWC_OFFSET_MASK + 0x1005) +/* [4:0] V_in_active[12:8] */ +#define HDMITX_DWC_FC_INVACTV1 (DWC_OFFSET_MASK + 0x1006) +/* [7:0] V_in_blank */ +#define HDMITX_DWC_FC_INVBLANK (DWC_OFFSET_MASK + 0x1007) +/* [7:0] H_in_delay[7:0] */ +#define HDMITX_DWC_FC_HSYNCINDELAY0 (DWC_OFFSET_MASK + 0x1008) +/* [4:0] H_in_delay[12:8] */ +#define HDMITX_DWC_FC_HSYNCINDELAY1 (DWC_OFFSET_MASK + 0x1009) +/* [7:0] H_in_width[7:0] */ +#define HDMITX_DWC_FC_HSYNCINWIDTH0 (DWC_OFFSET_MASK + 0x100A) +/* [1:0] H_in_width[9:8] */ +#define HDMITX_DWC_FC_HSYNCINWIDTH1 (DWC_OFFSET_MASK + 0x100B) +/* [7:0] V_in_delay */ +#define HDMITX_DWC_FC_VSYNCINDELAY (DWC_OFFSET_MASK + 0x100C) +/* [5:0] V_in_width */ +#define HDMITX_DWC_FC_VSYNCINWIDTH (DWC_OFFSET_MASK + 0x100D) +#define HDMITX_DWC_FC_INFREQ0 (DWC_OFFSET_MASK + 0x100E) +#define HDMITX_DWC_FC_INFREQ1 (DWC_OFFSET_MASK + 0x100F) +#define HDMITX_DWC_FC_INFREQ2 (DWC_OFFSET_MASK + 0x1010) +#define HDMITX_DWC_FC_CTRLDUR (DWC_OFFSET_MASK + 0x1011) +#define HDMITX_DWC_FC_EXCTRLDUR (DWC_OFFSET_MASK + 0x1012) +#define HDMITX_DWC_FC_EXCTRLSPAC (DWC_OFFSET_MASK + 0x1013) +#define HDMITX_DWC_FC_CH0PREAM (DWC_OFFSET_MASK + 0x1014) +#define HDMITX_DWC_FC_CH1PREAM (DWC_OFFSET_MASK + 0x1015) +#define HDMITX_DWC_FC_CH2PREAM (DWC_OFFSET_MASK + 0x1016) +/* [3:2] YQ */ +/* [1:0] CN */ +#define HDMITX_DWC_FC_AVICONF3 (DWC_OFFSET_MASK + 0x1017) +/* [ 2] default_phase */ +/* [ 1] set_avmute */ +/* [ 0] clear_avmute */ +#define HDMITX_DWC_FC_GCP (DWC_OFFSET_MASK + 0x1018) +/* [ 7] rgb_ycc_indication[2] */ +/* [ 6] active_format_present */ +/* [5:4] scan_information */ +/* [3:2] bar_information */ +/* [1:0] rgb_ycc_indication[1:0] */ +#define HDMITX_DWC_FC_AVICONF0 (DWC_OFFSET_MASK + 0x1019) +/* [7:6] colorimetry */ +/* [5:4] picture_aspect_ratio */ +/* [3:0] active_aspect_ratio */ +#define HDMITX_DWC_FC_AVICONF1 (DWC_OFFSET_MASK + 0x101A) +/* [ 7] IT_content */ +/* [6:4] extended_colorimetry */ +/* [3:2] quantization_range */ +/* [1:0] non_uniform_picture_scaling */ +#define HDMITX_DWC_FC_AVICONF2 (DWC_OFFSET_MASK + 0x101B) +#define HDMITX_DWC_FC_AVIVID (DWC_OFFSET_MASK + 0x101C) +#define HDMITX_DWC_FC_AVIETB0 (DWC_OFFSET_MASK + 0x101D) +#define HDMITX_DWC_FC_AVIETB1 (DWC_OFFSET_MASK + 0x101E) +#define HDMITX_DWC_FC_AVISBB0 (DWC_OFFSET_MASK + 0x101F) +#define HDMITX_DWC_FC_AVISBB1 (DWC_OFFSET_MASK + 0x1020) +#define HDMITX_DWC_FC_AVIELB0 (DWC_OFFSET_MASK + 0x1021) +#define HDMITX_DWC_FC_AVIELB1 (DWC_OFFSET_MASK + 0x1022) +#define HDMITX_DWC_FC_AVISRB0 (DWC_OFFSET_MASK + 0x1023) +#define HDMITX_DWC_FC_AVISRB1 (DWC_OFFSET_MASK + 0x1024) +/* [3:0] CT: coding type */ +#define HDMITX_DWC_FC_AUDICONF0 (DWC_OFFSET_MASK + 0x1025) +/* [5:4] SS: sampling size */ +/* [2:0] SF: sampling frequency */ +#define HDMITX_DWC_FC_AUDICONF1 (DWC_OFFSET_MASK + 0x1026) +/* CA: channel allocation */ +#define HDMITX_DWC_FC_AUDICONF2 (DWC_OFFSET_MASK + 0x1027) +/* [6:5] LFEPBL: LFE playback info */ +/* [ 4] DM_INH: down mix enable */ +/* [3:0] LSv: Level shift value */ +#define HDMITX_DWC_FC_AUDICONF3 (DWC_OFFSET_MASK + 0x1028) +#define HDMITX_DWC_FC_VSDIEEEID0 (DWC_OFFSET_MASK + 0x1029) +#define HDMITX_DWC_FC_VSDSIZE (DWC_OFFSET_MASK + 0x102A) +#define HDMITX_DWC_FC_VSDIEEEID1 (DWC_OFFSET_MASK + 0x1030) +#define HDMITX_DWC_FC_VSDIEEEID2 (DWC_OFFSET_MASK + 0x1031) +#define HDMITX_DWC_FC_VSDPAYLOAD0 (DWC_OFFSET_MASK + 0x1032) +#define HDMITX_DWC_FC_VSDPAYLOAD1 (DWC_OFFSET_MASK + 0x1033) +#define HDMITX_DWC_FC_VSDPAYLOAD2 (DWC_OFFSET_MASK + 0x1034) +#define HDMITX_DWC_FC_VSDPAYLOAD3 (DWC_OFFSET_MASK + 0x1035) +#define HDMITX_DWC_FC_VSDPAYLOAD4 (DWC_OFFSET_MASK + 0x1036) +#define HDMITX_DWC_FC_VSDPAYLOAD5 (DWC_OFFSET_MASK + 0x1037) +#define HDMITX_DWC_FC_VSDPAYLOAD6 (DWC_OFFSET_MASK + 0x1038) +#define HDMITX_DWC_FC_VSDPAYLOAD7 (DWC_OFFSET_MASK + 0x1039) +#define HDMITX_DWC_FC_VSDPAYLOAD8 (DWC_OFFSET_MASK + 0x103A) +#define HDMITX_DWC_FC_VSDPAYLOAD9 (DWC_OFFSET_MASK + 0x103B) +#define HDMITX_DWC_FC_VSDPAYLOAD10 (DWC_OFFSET_MASK + 0x103C) +#define HDMITX_DWC_FC_VSDPAYLOAD11 (DWC_OFFSET_MASK + 0x103D) +#define HDMITX_DWC_FC_VSDPAYLOAD12 (DWC_OFFSET_MASK + 0x103E) +#define HDMITX_DWC_FC_VSDPAYLOAD13 (DWC_OFFSET_MASK + 0x103F) +#define HDMITX_DWC_FC_VSDPAYLOAD14 (DWC_OFFSET_MASK + 0x1040) +#define HDMITX_DWC_FC_VSDPAYLOAD15 (DWC_OFFSET_MASK + 0x1041) +#define HDMITX_DWC_FC_VSDPAYLOAD16 (DWC_OFFSET_MASK + 0x1042) +#define HDMITX_DWC_FC_VSDPAYLOAD17 (DWC_OFFSET_MASK + 0x1043) +#define HDMITX_DWC_FC_VSDPAYLOAD18 (DWC_OFFSET_MASK + 0x1044) +#define HDMITX_DWC_FC_VSDPAYLOAD19 (DWC_OFFSET_MASK + 0x1045) +#define HDMITX_DWC_FC_VSDPAYLOAD20 (DWC_OFFSET_MASK + 0x1046) +#define HDMITX_DWC_FC_VSDPAYLOAD21 (DWC_OFFSET_MASK + 0x1047) +#define HDMITX_DWC_FC_VSDPAYLOAD22 (DWC_OFFSET_MASK + 0x1048) +#define HDMITX_DWC_FC_VSDPAYLOAD23 (DWC_OFFSET_MASK + 0x1049) +#define HDMITX_DWC_FC_SPDVENDORNAME0 (DWC_OFFSET_MASK + 0x104A) +#define HDMITX_DWC_FC_SPDVENDORNAME1 (DWC_OFFSET_MASK + 0x104B) +#define HDMITX_DWC_FC_SPDVENDORNAME2 (DWC_OFFSET_MASK + 0x104C) +#define HDMITX_DWC_FC_SPDVENDORNAME3 (DWC_OFFSET_MASK + 0x104D) +#define HDMITX_DWC_FC_SPDVENDORNAME4 (DWC_OFFSET_MASK + 0x104E) +#define HDMITX_DWC_FC_SPDVENDORNAME5 (DWC_OFFSET_MASK + 0x104F) +#define HDMITX_DWC_FC_SPDVENDORNAME6 (DWC_OFFSET_MASK + 0x1050) +#define HDMITX_DWC_FC_SPDVENDORNAME7 (DWC_OFFSET_MASK + 0x1051) +#define HDMITX_DWC_FC_SDPPRODUCTNAME0 (DWC_OFFSET_MASK + 0x1052) +#define HDMITX_DWC_FC_SDPPRODUCTNAME1 (DWC_OFFSET_MASK + 0x1053) +#define HDMITX_DWC_FC_SDPPRODUCTNAME2 (DWC_OFFSET_MASK + 0x1054) +#define HDMITX_DWC_FC_SDPPRODUCTNAME3 (DWC_OFFSET_MASK + 0x1055) +#define HDMITX_DWC_FC_SDPPRODUCTNAME4 (DWC_OFFSET_MASK + 0x1056) +#define HDMITX_DWC_FC_SDPPRODUCTNAME5 (DWC_OFFSET_MASK + 0x1057) +#define HDMITX_DWC_FC_SDPPRODUCTNAME6 (DWC_OFFSET_MASK + 0x1058) +#define HDMITX_DWC_FC_SDPPRODUCTNAME7 (DWC_OFFSET_MASK + 0x1059) +#define HDMITX_DWC_FC_SDPPRODUCTNAME8 (DWC_OFFSET_MASK + 0x105A) +#define HDMITX_DWC_FC_SDPPRODUCTNAME9 (DWC_OFFSET_MASK + 0x105B) +#define HDMITX_DWC_FC_SDPPRODUCTNAME10 (DWC_OFFSET_MASK + 0x105C) +#define HDMITX_DWC_FC_SDPPRODUCTNAME11 (DWC_OFFSET_MASK + 0x105D) +#define HDMITX_DWC_FC_SDPPRODUCTNAME12 (DWC_OFFSET_MASK + 0x105E) +#define HDMITX_DWC_FC_SDPPRODUCTNAME13 (DWC_OFFSET_MASK + 0x105F) +#define HDMITX_DWC_FC_SDPPRODUCTNAME14 (DWC_OFFSET_MASK + 0x1060) +#define HDMITX_DWC_FC_SPDPRODUCTNAME15 (DWC_OFFSET_MASK + 0x1061) +#define HDMITX_DWC_FC_SPDDEVICEINF (DWC_OFFSET_MASK + 0x1062) +/* [7:4] aud_packet_sampflat */ +/* [ 0] aud_packet_layout */ +#define HDMITX_DWC_FC_AUDSCONF (DWC_OFFSET_MASK + 0x1063) +#define HDMITX_DWC_FC_AUDSSTAT (DWC_OFFSET_MASK + 0x1064) +/* [ 7] V3r */ +/* [ 6] V2r */ +/* [ 5] V1r */ +/* [ 4] V0r */ +/* [ 3] V3l */ +/* [ 2] V2l */ +/* [ 1] V1l */ +/* [ 0] V0l */ +#define HDMITX_DWC_FC_AUDSV (DWC_OFFSET_MASK + 0x1065) +#define HDMITX_DWC_FC_AUDSU (DWC_OFFSET_MASK + 0x1066) +/* bit5:4 CSB 41:40 */ +/* bit0 CSB 2 */ +#define HDMITX_DWC_FC_AUDSCHNLS0 (DWC_OFFSET_MASK + 0x1067) +/* bit7:0 CSB 15:8 */ +#define HDMITX_DWC_FC_AUDSCHNLS1 (DWC_OFFSET_MASK + 0x1068) +/* bit6:4 CSB 5:3 */ +/* bit3:0 CSB 17:16 */ +#define HDMITX_DWC_FC_AUDSCHNLS2 (DWC_OFFSET_MASK + 0x1069) +/* bit7:4 CSB 22:21 2nd right sub */ +/* bit3:0 CSB 22:21 1st right sub */ +#define HDMITX_DWC_FC_AUDSCHNLS3 (DWC_OFFSET_MASK + 0x106A) +/* bit?? CSB 22:21 4th right sub */ +/* bit?? CSB 22:21 3rd right sub */ +#define HDMITX_DWC_FC_AUDSCHNLS4 (DWC_OFFSET_MASK + 0x106B) +/* bit7:4 CSB 22:21 2nd left sub */ +/* bit3:0 CSB 22:21 1st left sub */ +#define HDMITX_DWC_FC_AUDSCHNLS5 (DWC_OFFSET_MASK + 0x106C) +/* bit?? CSB 22:21 4th left sub */ +/* bit?? CSB 22:21 3rd left sub */ +#define HDMITX_DWC_FC_AUDSCHNLS6 (DWC_OFFSET_MASK + 0x106D) +#define HDMITX_DWC_FC_AUDSCHNLS7 (DWC_OFFSET_MASK + 0x106E) +#define HDMITX_DWC_FC_AUDSCHNLS8 (DWC_OFFSET_MASK + 0x106F) +#define HDMITX_DWC_FC_DATACH0FILL (DWC_OFFSET_MASK + 0x1070) +#define HDMITX_DWC_FC_DATACH1FILL (DWC_OFFSET_MASK + 0x1071) +#define HDMITX_DWC_FC_DATACH2FILL (DWC_OFFSET_MASK + 0x1072) +#define HDMITX_DWC_FC_CTRLQHIGH (DWC_OFFSET_MASK + 0x1073) +#define HDMITX_DWC_FC_CTRLQLOW (DWC_OFFSET_MASK + 0x1074) +#define HDMITX_DWC_FC_ACP0 (DWC_OFFSET_MASK + 0x1075) +#define HDMITX_DWC_FC_ACP16 (DWC_OFFSET_MASK + 0x1082) +#define HDMITX_DWC_FC_ACP15 (DWC_OFFSET_MASK + 0x1083) +#define HDMITX_DWC_FC_ACP14 (DWC_OFFSET_MASK + 0x1084) +#define HDMITX_DWC_FC_ACP13 (DWC_OFFSET_MASK + 0x1085) +#define HDMITX_DWC_FC_ACP12 (DWC_OFFSET_MASK + 0x1086) +#define HDMITX_DWC_FC_ACP11 (DWC_OFFSET_MASK + 0x1087) +#define HDMITX_DWC_FC_ACP10 (DWC_OFFSET_MASK + 0x1088) +#define HDMITX_DWC_FC_ACP9 (DWC_OFFSET_MASK + 0x1089) +#define HDMITX_DWC_FC_ACP8 (DWC_OFFSET_MASK + 0x108A) +#define HDMITX_DWC_FC_ACP7 (DWC_OFFSET_MASK + 0x108B) +#define HDMITX_DWC_FC_ACP6 (DWC_OFFSET_MASK + 0x108C) +#define HDMITX_DWC_FC_ACP5 (DWC_OFFSET_MASK + 0x108D) +#define HDMITX_DWC_FC_ACP4 (DWC_OFFSET_MASK + 0x108E) +#define HDMITX_DWC_FC_ACP3 (DWC_OFFSET_MASK + 0x108F) +#define HDMITX_DWC_FC_ACP2 (DWC_OFFSET_MASK + 0x1090) +#define HDMITX_DWC_FC_ACP1 (DWC_OFFSET_MASK + 0x1091) +#define HDMITX_DWC_FC_ISCR1_0 (DWC_OFFSET_MASK + 0x1092) +#define HDMITX_DWC_FC_ISCR1_16 (DWC_OFFSET_MASK + 0x1093) +#define HDMITX_DWC_FC_ISCR1_15 (DWC_OFFSET_MASK + 0x1094) +#define HDMITX_DWC_FC_ISCR1_14 (DWC_OFFSET_MASK + 0x1095) +#define HDMITX_DWC_FC_ISCR1_13 (DWC_OFFSET_MASK + 0x1096) +#define HDMITX_DWC_FC_ISCR1_12 (DWC_OFFSET_MASK + 0x1097) +#define HDMITX_DWC_FC_ISCR1_11 (DWC_OFFSET_MASK + 0x1098) +#define HDMITX_DWC_FC_ISCR1_10 (DWC_OFFSET_MASK + 0x1099) +#define HDMITX_DWC_FC_ISCR1_9 (DWC_OFFSET_MASK + 0x109A) +#define HDMITX_DWC_FC_ISCR1_8 (DWC_OFFSET_MASK + 0x109B) +#define HDMITX_DWC_FC_ISCR1_7 (DWC_OFFSET_MASK + 0x109C) +#define HDMITX_DWC_FC_ISCR1_6 (DWC_OFFSET_MASK + 0x109D) +#define HDMITX_DWC_FC_ISCR1_5 (DWC_OFFSET_MASK + 0x109E) +#define HDMITX_DWC_FC_ISCR1_4 (DWC_OFFSET_MASK + 0x109F) +#define HDMITX_DWC_FC_ISCR1_3 (DWC_OFFSET_MASK + 0x10A0) +#define HDMITX_DWC_FC_ISCR1_2 (DWC_OFFSET_MASK + 0x10A1) +#define HDMITX_DWC_FC_ISCR1_1 (DWC_OFFSET_MASK + 0x10A2) +#define HDMITX_DWC_FC_ISCR0_15 (DWC_OFFSET_MASK + 0x10A3) +#define HDMITX_DWC_FC_ISCR0_14 (DWC_OFFSET_MASK + 0x10A4) +#define HDMITX_DWC_FC_ISCR0_13 (DWC_OFFSET_MASK + 0x10A5) +#define HDMITX_DWC_FC_ISCR0_12 (DWC_OFFSET_MASK + 0x10A6) +#define HDMITX_DWC_FC_ISCR0_11 (DWC_OFFSET_MASK + 0x10A7) +#define HDMITX_DWC_FC_ISCR0_10 (DWC_OFFSET_MASK + 0x10A8) +#define HDMITX_DWC_FC_ISCR0_9 (DWC_OFFSET_MASK + 0x10A9) +#define HDMITX_DWC_FC_ISCR0_8 (DWC_OFFSET_MASK + 0x10AA) +#define HDMITX_DWC_FC_ISCR0_7 (DWC_OFFSET_MASK + 0x10AB) +#define HDMITX_DWC_FC_ISCR0_6 (DWC_OFFSET_MASK + 0x10AC) +#define HDMITX_DWC_FC_ISCR0_5 (DWC_OFFSET_MASK + 0x10AD) +#define HDMITX_DWC_FC_ISCR0_4 (DWC_OFFSET_MASK + 0x10AE) +#define HDMITX_DWC_FC_ISCR0_3 (DWC_OFFSET_MASK + 0x10AF) +#define HDMITX_DWC_FC_ISCR0_2 (DWC_OFFSET_MASK + 0x10B0) +#define HDMITX_DWC_FC_ISCR0_1 (DWC_OFFSET_MASK + 0x10B1) +#define HDMITX_DWC_FC_ISCR0_0 (DWC_OFFSET_MASK + 0x10B2) +/* [ 4] spd_auto */ +/* [ 3] vsd_auto */ +/* [ 2] isrc2_auto */ +/* [ 1] isrc1_auto */ +/* [ 0] acp_auto */ +#define HDMITX_DWC_FC_DATAUTO0 (DWC_OFFSET_MASK + 0x10B3) +#define HDMITX_DWC_FC_DATAUTO1 (DWC_OFFSET_MASK + 0x10B4) +#define HDMITX_DWC_FC_DATAUTO2 (DWC_OFFSET_MASK + 0x10B5) +#define HDMITX_DWC_FC_DATMAN (DWC_OFFSET_MASK + 0x10B6) +/* [ 6] drm_auto: instert on Vsync */ +/* [ 5] nvbi_auto: insert on Vsync */ +/* [ 4] amp_auto: insert on Vsync */ +/* [ 3] avi_auto: insert on Vsync */ +/* [ 2] gcp_auto: insert on Vsync */ +/* [ 1] audi_auto: insert on Vsync */ +/* [ 0] acr_auto: insert on CTS update. Assert this bit later to avoid + * initial packets with false CTS value + */ +#define HDMITX_DWC_FC_DATAUTO3 (DWC_OFFSET_MASK + 0x10B7) +#define HDMITX_DWC_FC_RDRB0 (DWC_OFFSET_MASK + 0x10B8) +#define HDMITX_DWC_FC_RDRB1 (DWC_OFFSET_MASK + 0x10B9) +#define HDMITX_DWC_FC_RDRB2 (DWC_OFFSET_MASK + 0x10BA) +#define HDMITX_DWC_FC_RDRB3 (DWC_OFFSET_MASK + 0x10BB) +#define HDMITX_DWC_FC_RDRB4 (DWC_OFFSET_MASK + 0x10BC) +#define HDMITX_DWC_FC_RDRB5 (DWC_OFFSET_MASK + 0x10BD) +#define HDMITX_DWC_FC_RDRB6 (DWC_OFFSET_MASK + 0x10BE) +#define HDMITX_DWC_FC_RDRB7 (DWC_OFFSET_MASK + 0x10BF) +#define HDMITX_DWC_FC_RDRB8 (DWC_OFFSET_MASK + 0x10C0) +#define HDMITX_DWC_FC_RDRB9 (DWC_OFFSET_MASK + 0x10C1) +#define HDMITX_DWC_FC_RDRB10 (DWC_OFFSET_MASK + 0x10C2) +#define HDMITX_DWC_FC_RDRB11 (DWC_OFFSET_MASK + 0x10C3) +/* [ 7] AUDI_int_mask */ +/* [ 6] ACP_int_mask */ +/* [ 5] HBR_int_mask */ +/* [ 2] AUDS_int_mask */ +/* [ 1] ACR_int_mask */ +/* [ 0] NULL_int_mask */ +#define HDMITX_DWC_FC_MASK0 (DWC_OFFSET_MASK + 0x10D2) +/* [ 7] GMD_int_mask */ +/* [ 6] ISRC1_int_mask */ +/* [ 5] ISRC2_int_mask */ +/* [ 4] VSD_int_mask */ +/* [ 3] SPD_int_mask */ +/* [ 1] AVI_int_mask */ +/* [ 0] GCP_int_mask */ +#define HDMITX_DWC_FC_MASK1 (DWC_OFFSET_MASK + 0x10D6) +/* [ 2] Mask bit for FC_INT2.DRM interrupt bit */ +/* [ 1] LowPriority_fifo_full */ +/* [ 0] HighPriority_fifo_full */ +#define HDMITX_DWC_FC_MASK2 (DWC_OFFSET_MASK + 0x10DA) +/* [7:4] incoming_pr_factor */ +/* [3:0] output_pr_factor */ +#define HDMITX_DWC_FC_PRCONF (DWC_OFFSET_MASK + 0x10E0) +/* [ 4] scrambler_ucp_line */ +/* [ 0] scrambler_en. Only update this bit once we've sent SCDC message*/ +#define HDMITX_DWC_FC_SCRAMBLER_CTRL (DWC_OFFSET_MASK + 0x10E1) +#define HDMITX_DWC_FC_MULTISTREAM_CTRL (DWC_OFFSET_MASK + 0x10E2) +/* [ 7] drm_tx_en */ +/* [ 6] nvbi_tx_en */ +/* [ 5] amp_tx_en */ +/* [ 4] aut_tx_en */ +/* [ 3] audi_tx_en */ +/* [ 2] avi_tx_en */ +/* [ 1] gcp_tx_en */ +/* [ 0] acr_tx_en */ +#define HDMITX_DWC_FC_PACKET_TX_EN (DWC_OFFSET_MASK + 0x10E3) +/* [ 1] actspc_hdlr_tgl */ +/* [ 0] actspc_hdlr_en */ +#define HDMITX_DWC_FC_ACTSPC_HDLR_CFG (DWC_OFFSET_MASK + 0x10E8) +#define HDMITX_DWC_FC_INVACT_2D_0 (DWC_OFFSET_MASK + 0x10E9) +/* [3:0] fc_invact_2d_0[11:8] */ +/* [7:0] fc_invact_2d_0[7:0] */ +#define HDMITX_DWC_FC_INVACT_2D_1 (DWC_OFFSET_MASK + 0x10EA) + +#define HDMITX_DWC_FC_GMD_STAT (DWC_OFFSET_MASK + 0x1100) +#define HDMITX_DWC_FC_GMD_EN (DWC_OFFSET_MASK + 0x1101) +#define HDMITX_DWC_FC_GMD_UP (DWC_OFFSET_MASK + 0x1102) +#define HDMITX_DWC_FC_GMD_CONF (DWC_OFFSET_MASK + 0x1103) +#define HDMITX_DWC_FC_GMD_HB (DWC_OFFSET_MASK + 0x1104) +#define HDMITX_DWC_FC_GMD_PB0 (DWC_OFFSET_MASK + 0x1105) +#define HDMITX_DWC_FC_GMD_PB1 (DWC_OFFSET_MASK + 0x1106) +#define HDMITX_DWC_FC_GMD_PB2 (DWC_OFFSET_MASK + 0x1107) +#define HDMITX_DWC_FC_GMD_PB3 (DWC_OFFSET_MASK + 0x1108) +#define HDMITX_DWC_FC_GMD_PB4 (DWC_OFFSET_MASK + 0x1109) +#define HDMITX_DWC_FC_GMD_PB5 (DWC_OFFSET_MASK + 0x110A) +#define HDMITX_DWC_FC_GMD_PB6 (DWC_OFFSET_MASK + 0x110B) +#define HDMITX_DWC_FC_GMD_PB7 (DWC_OFFSET_MASK + 0x110C) +#define HDMITX_DWC_FC_GMD_PB8 (DWC_OFFSET_MASK + 0x110D) +#define HDMITX_DWC_FC_GMD_PB9 (DWC_OFFSET_MASK + 0x110E) +#define HDMITX_DWC_FC_GMD_PB10 (DWC_OFFSET_MASK + 0x110F) +#define HDMITX_DWC_FC_GMD_PB11 (DWC_OFFSET_MASK + 0x1110) +#define HDMITX_DWC_FC_GMD_PB12 (DWC_OFFSET_MASK + 0x1111) +#define HDMITX_DWC_FC_GMD_PB13 (DWC_OFFSET_MASK + 0x1112) +#define HDMITX_DWC_FC_GMD_PB14 (DWC_OFFSET_MASK + 0x1113) +#define HDMITX_DWC_FC_GMD_PB15 (DWC_OFFSET_MASK + 0x1114) +#define HDMITX_DWC_FC_GMD_PB16 (DWC_OFFSET_MASK + 0x1115) +#define HDMITX_DWC_FC_GMD_PB17 (DWC_OFFSET_MASK + 0x1116) +#define HDMITX_DWC_FC_GMD_PB18 (DWC_OFFSET_MASK + 0x1117) +#define HDMITX_DWC_FC_GMD_PB19 (DWC_OFFSET_MASK + 0x1118) +#define HDMITX_DWC_FC_GMD_PB20 (DWC_OFFSET_MASK + 0x1119) +#define HDMITX_DWC_FC_GMD_PB21 (DWC_OFFSET_MASK + 0x111A) +#define HDMITX_DWC_FC_GMD_PB22 (DWC_OFFSET_MASK + 0x111B) +#define HDMITX_DWC_FC_GMD_PB23 (DWC_OFFSET_MASK + 0x111C) +#define HDMITX_DWC_FC_GMD_PB24 (DWC_OFFSET_MASK + 0x111D) +#define HDMITX_DWC_FC_GMD_PB25 (DWC_OFFSET_MASK + 0x111E) +#define HDMITX_DWC_FC_GMD_PB26 (DWC_OFFSET_MASK + 0x111F) +#define HDMITX_DWC_FC_GMD_PB27 (DWC_OFFSET_MASK + 0x1120) + +/* Audio Metadata Packet Registers */ +#define HDMITX_DWC_FC_AMP_HB01 (DWC_OFFSET_MASK + 0x1128) +#define HDMITX_DWC_FC_AMP_HB02 (DWC_OFFSET_MASK + 0x1129) +#define HDMITX_DWC_FC_AMP_PB00 (DWC_OFFSET_MASK + 0x112A) +#define HDMITX_DWC_FC_AMP_PB01 (DWC_OFFSET_MASK + 0x112B) +#define HDMITX_DWC_FC_AMP_PB02 (DWC_OFFSET_MASK + 0x112C) +#define HDMITX_DWC_FC_AMP_PB03 (DWC_OFFSET_MASK + 0x112D) +#define HDMITX_DWC_FC_AMP_PB04 (DWC_OFFSET_MASK + 0x112E) +#define HDMITX_DWC_FC_AMP_PB05 (DWC_OFFSET_MASK + 0x112F) +#define HDMITX_DWC_FC_AMP_PB06 (DWC_OFFSET_MASK + 0x1130) +#define HDMITX_DWC_FC_AMP_PB07 (DWC_OFFSET_MASK + 0x1131) +#define HDMITX_DWC_FC_AMP_PB08 (DWC_OFFSET_MASK + 0x1132) +#define HDMITX_DWC_FC_AMP_PB09 (DWC_OFFSET_MASK + 0x1133) +#define HDMITX_DWC_FC_AMP_PB10 (DWC_OFFSET_MASK + 0x1134) +#define HDMITX_DWC_FC_AMP_PB11 (DWC_OFFSET_MASK + 0x1135) +#define HDMITX_DWC_FC_AMP_PB12 (DWC_OFFSET_MASK + 0x1136) +#define HDMITX_DWC_FC_AMP_PB13 (DWC_OFFSET_MASK + 0x1137) +#define HDMITX_DWC_FC_AMP_PB14 (DWC_OFFSET_MASK + 0x1138) +#define HDMITX_DWC_FC_AMP_PB15 (DWC_OFFSET_MASK + 0x1139) +#define HDMITX_DWC_FC_AMP_PB16 (DWC_OFFSET_MASK + 0x113A) +#define HDMITX_DWC_FC_AMP_PB17 (DWC_OFFSET_MASK + 0x113B) +#define HDMITX_DWC_FC_AMP_PB18 (DWC_OFFSET_MASK + 0x113C) +#define HDMITX_DWC_FC_AMP_PB19 (DWC_OFFSET_MASK + 0x113D) +#define HDMITX_DWC_FC_AMP_PB20 (DWC_OFFSET_MASK + 0x113E) +#define HDMITX_DWC_FC_AMP_PB21 (DWC_OFFSET_MASK + 0x113F) +#define HDMITX_DWC_FC_AMP_PB22 (DWC_OFFSET_MASK + 0x1140) +#define HDMITX_DWC_FC_AMP_PB23 (DWC_OFFSET_MASK + 0x1141) +#define HDMITX_DWC_FC_AMP_PB24 (DWC_OFFSET_MASK + 0x1142) +#define HDMITX_DWC_FC_AMP_PB25 (DWC_OFFSET_MASK + 0x1143) +#define HDMITX_DWC_FC_AMP_PB26 (DWC_OFFSET_MASK + 0x1144) +#define HDMITX_DWC_FC_AMP_PB27 (DWC_OFFSET_MASK + 0x1145) + +/* NTSC VBI Packet Registers */ +#define HDMITX_DWC_FC_NVBI_HB01 (DWC_OFFSET_MASK + 0x1148) +#define HDMITX_DWC_FC_NVBI_HB02 (DWC_OFFSET_MASK + 0x1149) +#define HDMITX_DWC_FC_NVBI_PB01 (DWC_OFFSET_MASK + 0x114A) +#define HDMITX_DWC_FC_NVBI_PB02 (DWC_OFFSET_MASK + 0x114B) +#define HDMITX_DWC_FC_NVBI_PB03 (DWC_OFFSET_MASK + 0x114C) +#define HDMITX_DWC_FC_NVBI_PB04 (DWC_OFFSET_MASK + 0x114D) +#define HDMITX_DWC_FC_NVBI_PB05 (DWC_OFFSET_MASK + 0x114E) +#define HDMITX_DWC_FC_NVBI_PB06 (DWC_OFFSET_MASK + 0x114F) +#define HDMITX_DWC_FC_NVBI_PB07 (DWC_OFFSET_MASK + 0x1150) +#define HDMITX_DWC_FC_NVBI_PB08 (DWC_OFFSET_MASK + 0x1151) +#define HDMITX_DWC_FC_NVBI_PB09 (DWC_OFFSET_MASK + 0x1152) +#define HDMITX_DWC_FC_NVBI_PB10 (DWC_OFFSET_MASK + 0x1153) +#define HDMITX_DWC_FC_NVBI_PB11 (DWC_OFFSET_MASK + 0x1154) +#define HDMITX_DWC_FC_NVBI_PB12 (DWC_OFFSET_MASK + 0x1155) +#define HDMITX_DWC_FC_NVBI_PB13 (DWC_OFFSET_MASK + 0x1156) +#define HDMITX_DWC_FC_NVBI_PB14 (DWC_OFFSET_MASK + 0x1157) +#define HDMITX_DWC_FC_NVBI_PB15 (DWC_OFFSET_MASK + 0x1158) +#define HDMITX_DWC_FC_NVBI_PB16 (DWC_OFFSET_MASK + 0x1159) +#define HDMITX_DWC_FC_NVBI_PB17 (DWC_OFFSET_MASK + 0x115A) +#define HDMITX_DWC_FC_NVBI_PB18 (DWC_OFFSET_MASK + 0x115B) +#define HDMITX_DWC_FC_NVBI_PB19 (DWC_OFFSET_MASK + 0x115C) +#define HDMITX_DWC_FC_NVBI_PB20 (DWC_OFFSET_MASK + 0x115D) +#define HDMITX_DWC_FC_NVBI_PB21 (DWC_OFFSET_MASK + 0x115E) +#define HDMITX_DWC_FC_NVBI_PB22 (DWC_OFFSET_MASK + 0x115F) +#define HDMITX_DWC_FC_NVBI_PB23 (DWC_OFFSET_MASK + 0x1160) +#define HDMITX_DWC_FC_NVBI_PB24 (DWC_OFFSET_MASK + 0x1161) +#define HDMITX_DWC_FC_NVBI_PB25 (DWC_OFFSET_MASK + 0x1162) +#define HDMITX_DWC_FC_NVBI_PB26 (DWC_OFFSET_MASK + 0x1163) +#define HDMITX_DWC_FC_NVBI_PB27 (DWC_OFFSET_MASK + 0x1164) +#define HDMITX_DWC_FC_DRM_HB01 (DWC_OFFSET_MASK + 0x1168) +#define HDMITX_DWC_FC_DRM_HB02 (DWC_OFFSET_MASK + 0x1169) +#define HDMITX_DWC_FC_DRM_PB00 (DWC_OFFSET_MASK + 0x116A) +#define HDMITX_DWC_FC_DRM_PB01 (DWC_OFFSET_MASK + 0x116B) +#define HDMITX_DWC_FC_DRM_PB02 (DWC_OFFSET_MASK + 0x116C) +#define HDMITX_DWC_FC_DRM_PB03 (DWC_OFFSET_MASK + 0x116D) +#define HDMITX_DWC_FC_DRM_PB04 (DWC_OFFSET_MASK + 0x116E) +#define HDMITX_DWC_FC_DRM_PB05 (DWC_OFFSET_MASK + 0x116F) +#define HDMITX_DWC_FC_DRM_PB06 (DWC_OFFSET_MASK + 0x1170) +#define HDMITX_DWC_FC_DRM_PB07 (DWC_OFFSET_MASK + 0x1171) +#define HDMITX_DWC_FC_DRM_PB08 (DWC_OFFSET_MASK + 0x1172) +#define HDMITX_DWC_FC_DRM_PB09 (DWC_OFFSET_MASK + 0x1173) +#define HDMITX_DWC_FC_DRM_PB10 (DWC_OFFSET_MASK + 0x1174) +#define HDMITX_DWC_FC_DRM_PB11 (DWC_OFFSET_MASK + 0x1175) +#define HDMITX_DWC_FC_DRM_PB12 (DWC_OFFSET_MASK + 0x1176) +#define HDMITX_DWC_FC_DRM_PB13 (DWC_OFFSET_MASK + 0x1177) +#define HDMITX_DWC_FC_DRM_PB14 (DWC_OFFSET_MASK + 0x1178) +#define HDMITX_DWC_FC_DRM_PB15 (DWC_OFFSET_MASK + 0x1179) +#define HDMITX_DWC_FC_DRM_PB16 (DWC_OFFSET_MASK + 0x117A) +#define HDMITX_DWC_FC_DRM_PB17 (DWC_OFFSET_MASK + 0x117B) +#define HDMITX_DWC_FC_DRM_PB18 (DWC_OFFSET_MASK + 0x117C) +#define HDMITX_DWC_FC_DRM_PB19 (DWC_OFFSET_MASK + 0x117D) +#define HDMITX_DWC_FC_DRM_PB20 (DWC_OFFSET_MASK + 0x117E) +#define HDMITX_DWC_FC_DRM_PB21 (DWC_OFFSET_MASK + 0x117F) +#define HDMITX_DWC_FC_DRM_PB22 (DWC_OFFSET_MASK + 0x1180) +#define HDMITX_DWC_FC_DRM_PB23 (DWC_OFFSET_MASK + 0x1181) +#define HDMITX_DWC_FC_DRM_PB24 (DWC_OFFSET_MASK + 0x1182) +#define HDMITX_DWC_FC_DRM_PB25 (DWC_OFFSET_MASK + 0x1183) +#define HDMITX_DWC_FC_DRM_PB26 (DWC_OFFSET_MASK + 0x1184) + +#define HDMITX_DWC_FC_DBGFORCE (DWC_OFFSET_MASK + 0x1200) +#define HDMITX_DWC_FC_DBGAUD0CH0 (DWC_OFFSET_MASK + 0x1201) +#define HDMITX_DWC_FC_DBGAUD1CH0 (DWC_OFFSET_MASK + 0x1202) +#define HDMITX_DWC_FC_DBGAUD2CH0 (DWC_OFFSET_MASK + 0x1203) +#define HDMITX_DWC_FC_DBGAUD0CH1 (DWC_OFFSET_MASK + 0x1204) +#define HDMITX_DWC_FC_DBGAUD1CH1 (DWC_OFFSET_MASK + 0x1205) +#define HDMITX_DWC_FC_DBGAUD2CH1 (DWC_OFFSET_MASK + 0x1206) +#define HDMITX_DWC_FC_DBGAUD0CH2 (DWC_OFFSET_MASK + 0x1207) +#define HDMITX_DWC_FC_DBGAUD1CH2 (DWC_OFFSET_MASK + 0x1208) +#define HDMITX_DWC_FC_DBGAUD2CH2 (DWC_OFFSET_MASK + 0x1209) +#define HDMITX_DWC_FC_DBGAUD0CH3 (DWC_OFFSET_MASK + 0x120A) +#define HDMITX_DWC_FC_DBGAUD1CH3 (DWC_OFFSET_MASK + 0x120B) +#define HDMITX_DWC_FC_DBGAUD2CH3 (DWC_OFFSET_MASK + 0x120C) +#define HDMITX_DWC_FC_DBGAUD0CH4 (DWC_OFFSET_MASK + 0x120D) +#define HDMITX_DWC_FC_DBGAUD1CH4 (DWC_OFFSET_MASK + 0x120E) +#define HDMITX_DWC_FC_DBGAUD2CH4 (DWC_OFFSET_MASK + 0x120F) +#define HDMITX_DWC_FC_DBGAUD0CH5 (DWC_OFFSET_MASK + 0x1210) +#define HDMITX_DWC_FC_DBGAUD1CH5 (DWC_OFFSET_MASK + 0x1211) +#define HDMITX_DWC_FC_DBGAUD2CH5 (DWC_OFFSET_MASK + 0x1212) +#define HDMITX_DWC_FC_DBGAUD0CH6 (DWC_OFFSET_MASK + 0x1213) +#define HDMITX_DWC_FC_DBGAUD1CH6 (DWC_OFFSET_MASK + 0x1214) +#define HDMITX_DWC_FC_DBGAUD2CH6 (DWC_OFFSET_MASK + 0x1215) +#define HDMITX_DWC_FC_DBGAUD0CH7 (DWC_OFFSET_MASK + 0x1216) +#define HDMITX_DWC_FC_DBGAUD1CH7 (DWC_OFFSET_MASK + 0x1217) +#define HDMITX_DWC_FC_DBGAUD2CH7 (DWC_OFFSET_MASK + 0x1218) +#define HDMITX_DWC_FC_DBGTMDS0 (DWC_OFFSET_MASK + 0x1219) +#define HDMITX_DWC_FC_DBGTMDS1 (DWC_OFFSET_MASK + 0x121A) +#define HDMITX_DWC_FC_DBGTMDS2 (DWC_OFFSET_MASK + 0x121B) + +/* HDMI Source PHY Registers */ +#define HDMITX_DWC_PHY_CONF0 (DWC_OFFSET_MASK + 0x3000) +#define HDMITX_DWC_PHY_TST0 (DWC_OFFSET_MASK + 0x3001) +#define HDMITX_DWC_PHY_TST1 (DWC_OFFSET_MASK + 0x3002) +#define HDMITX_DWC_PHY_TST2 (DWC_OFFSET_MASK + 0x3003) +#define HDMITX_DWC_PHY_STAT0 (DWC_OFFSET_MASK + 0x3004) +#define HDMITX_DWC_PHY_INT0 (DWC_OFFSET_MASK + 0x3005) +#define HDMITX_DWC_PHY_MASK0 (DWC_OFFSET_MASK + 0x3006) +#define HDMITX_DWC_PHY_POL0 (DWC_OFFSET_MASK + 0x3007) + +/* I2C Master PHY Registers */ +#define HDMITX_DWC_I2CM_PHY_SLAVE (DWC_OFFSET_MASK + 0x3020) +#define HDMITX_DWC_I2CM_PHY_ADDRESS (DWC_OFFSET_MASK + 0x3021) +#define HDMITX_DWC_I2CM_PHY_DATAO_1 (DWC_OFFSET_MASK + 0x3022) +#define HDMITX_DWC_I2CM_PHY_DATAO_0 (DWC_OFFSET_MASK + 0x3023) +#define HDMITX_DWC_I2CM_PHY_DATAI_1 (DWC_OFFSET_MASK + 0x3024) +#define HDMITX_DWC_I2CM_PHY_DATAI_0 (DWC_OFFSET_MASK + 0x3025) +#define HDMITX_DWC_I2CM_PHY_OPERATION (DWC_OFFSET_MASK + 0x3026) +#define HDMITX_DWC_I2CM_PHY_INT (DWC_OFFSET_MASK + 0x3027) +#define HDMITX_DWC_I2CM_PHY_CTLINT (DWC_OFFSET_MASK + 0x3028) +#define HDMITX_DWC_I2CM_PHY_DIV (DWC_OFFSET_MASK + 0x3029) +#define HDMITX_DWC_I2CM_PHY_SOFTRSTZ (DWC_OFFSET_MASK + 0x302A) +#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x302B) +#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x302C) +#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x302D) +#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x302E) +#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x302F) +#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x3030) +#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x3031) +#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x3032) +#define HDMITX_DWC_I2CM_PHY_SDA_HOLD (DWC_OFFSET_MASK + 0x3033) + +/* Audio Sampler Registers */ + + /* [ 7] sw_audio_fifo_rst */ + /* [ 5] 0=select SPDIF; 1=select I2S. */ + /* [3:0] i2s_in_en: enable it later in test.c */ +#define HDMITX_DWC_AUD_CONF0 (DWC_OFFSET_MASK + 0x3100) +/* [4:0] i2s_width */ +/* [7:5] i2s_mode: 0=standard I2S mode */ +#define HDMITX_DWC_AUD_CONF1 (DWC_OFFSET_MASK + 0x3101) +/* [ 3] fifo_empty_mask: 0=enable int; 1=mask int. */ +/* [ 2] fifo_full_mask: 0=enable int; 1=mask int. */ +#define HDMITX_DWC_AUD_INT (DWC_OFFSET_MASK + 0x3102) + /* [ 1] NLPCM */ +#define HDMITX_DWC_AUD_CONF2 (DWC_OFFSET_MASK + 0x3103) + +/* [ 4] fifo_overrun_mask: 0=enable int; 1=mask int. + * Enable it later when audio starts. + */ +#define HDMITX_DWC_AUD_INT1 (DWC_OFFSET_MASK + 0x3104) + +#define HDMITX_DWC_AUD_N1 (DWC_OFFSET_MASK + 0x3200) +#define HDMITX_DWC_AUD_N2 (DWC_OFFSET_MASK + 0x3201) +#define HDMITX_DWC_AUD_N3 (DWC_OFFSET_MASK + 0x3202) +#define HDMITX_DWC_AUD_CTS1 (DWC_OFFSET_MASK + 0x3203) +#define HDMITX_DWC_AUD_CTS2 (DWC_OFFSET_MASK + 0x3204) +#define HDMITX_DWC_AUD_CTS3 (DWC_OFFSET_MASK + 0x3205) +#define HDMITX_DWC_AUD_INPUTCLKFS (DWC_OFFSET_MASK + 0x3206) +/* [ 7] sw_audio_fifo_rst */ +#define HDMITX_DWC_AUD_SPDIF0 (DWC_OFFSET_MASK + 0x3300) +/* [4:0] spdif_width */ +/* [ 7] setnlpcm */ +#define HDMITX_DWC_AUD_SPDIF1 (DWC_OFFSET_MASK + 0x3301) +/* [ 3] SPDIF fifo_empty_mask: 0=enable int; 1=mask int. */ +/* [ 2] SPDIF fifo_full_mask: 0=enable int; 1=mask int. */ +#define HDMITX_DWC_AUD_SPDIFINT (DWC_OFFSET_MASK + 0x3302) +/* [ 4] SPDIF fifo_overrun_mask: 0=enable int; 1=mask int. */ +#define HDMITX_DWC_AUD_SPDIFINT1 (DWC_OFFSET_MASK + 0x3303) + +/* Generic Parallel Audio Interface Registers (DWC_OFFSET_MASK + 0x3500) */ +/* Audio DMA Registers (DWC_OFFSET_MASK + 0x3600) */ + +/* Main Controller Registers */ +/* [ 6] hdcpclk_disable */ +/* [ 5] cecclk_disable */ +/* [ 4] cscclk_disable */ +/* [ 3] audclk_disable */ +/* [ 2] prepclk_disable */ +/* [ 1] tmdsclk_disable */ +/* [ 0] pixelclk_disable */ +#define HDMITX_DWC_MC_CLKDIS (DWC_OFFSET_MASK + 0x4001) +/* + * [ 7] gpaswrst_req: 0=generate reset pulse; 1=no reset. + * [ 6] cecswrst_req: 0=generate reset pulse; 1=no reset. + * [ 4] spdifswrst_req: 0=generate reset pulse; 1=no reset. + * [ 3] i2sswrst_req: 0=generate reset pulse; 1=no reset. + * [ 2] prepswrst_req: 0=generate reset pulse; 1=no reset. + * [ 1] tmdsswrst_req: 0=generate reset pulse; 1=no reset. + * [ 0] pixelswrst_req: 0=generate reset pulse; 1=no reset. + */ +#define HDMITX_DWC_MC_SWRSTZREQ (DWC_OFFSET_MASK + 0x4002) +#define HDMITX_DWC_MC_OPCTRL (DWC_OFFSET_MASK + 0x4003) +/* [ 0] CSC enable */ +#define HDMITX_DWC_MC_FLOWCTRL (DWC_OFFSET_MASK + 0x4004) +#define HDMITX_DWC_MC_PHYRSTZ (DWC_OFFSET_MASK + 0x4005) +#define HDMITX_DWC_MC_LOCKONCLOCK (DWC_OFFSET_MASK + 0x4006) + +/* Color Space Converter Registers */ +/* [ 7] csc_limit */ +#define HDMITX_DWC_CSC_CFG (DWC_OFFSET_MASK + 0x4100) +#define HDMITX_DWC_CSC_SCALE (DWC_OFFSET_MASK + 0x4101) +#define HDMITX_DWC_CSC_COEF_A1_MSB (DWC_OFFSET_MASK + 0x4102) +#define HDMITX_DWC_CSC_COEF_A1_LSB (DWC_OFFSET_MASK + 0x4103) +#define HDMITX_DWC_CSC_COEF_A2_MSB (DWC_OFFSET_MASK + 0x4104) +#define HDMITX_DWC_CSC_COEF_A2_LSB (DWC_OFFSET_MASK + 0x4105) +#define HDMITX_DWC_CSC_COEF_A3_MSB (DWC_OFFSET_MASK + 0x4106) +#define HDMITX_DWC_CSC_COEF_A3_LSB (DWC_OFFSET_MASK + 0x4107) +#define HDMITX_DWC_CSC_COEF_A4_MSB (DWC_OFFSET_MASK + 0x4108) +#define HDMITX_DWC_CSC_COEF_A4_LSB (DWC_OFFSET_MASK + 0x4109) +#define HDMITX_DWC_CSC_COEF_B1_MSB (DWC_OFFSET_MASK + 0x410A) +#define HDMITX_DWC_CSC_COEF_B1_LSB (DWC_OFFSET_MASK + 0x410B) +#define HDMITX_DWC_CSC_COEF_B2_MSB (DWC_OFFSET_MASK + 0x410C) +#define HDMITX_DWC_CSC_COEF_B2_LSB (DWC_OFFSET_MASK + 0x410D) +#define HDMITX_DWC_CSC_COEF_B3_MSB (DWC_OFFSET_MASK + 0x410E) +#define HDMITX_DWC_CSC_COEF_B3_LSB (DWC_OFFSET_MASK + 0x410F) +#define HDMITX_DWC_CSC_COEF_B4_MSB (DWC_OFFSET_MASK + 0x4110) +#define HDMITX_DWC_CSC_COEF_B4_LSB (DWC_OFFSET_MASK + 0x4111) +#define HDMITX_DWC_CSC_COEF_C1_MSB (DWC_OFFSET_MASK + 0x4112) +#define HDMITX_DWC_CSC_COEF_C1_LSB (DWC_OFFSET_MASK + 0x4113) +#define HDMITX_DWC_CSC_COEF_C2_MSB (DWC_OFFSET_MASK + 0x4114) +#define HDMITX_DWC_CSC_COEF_C2_LSB (DWC_OFFSET_MASK + 0x4115) +#define HDMITX_DWC_CSC_COEF_C3_MSB (DWC_OFFSET_MASK + 0x4116) +#define HDMITX_DWC_CSC_COEF_C3_LSB (DWC_OFFSET_MASK + 0x4117) +#define HDMITX_DWC_CSC_COEF_C4_MSB (DWC_OFFSET_MASK + 0x4118) +#define HDMITX_DWC_CSC_COEF_C4_LSB (DWC_OFFSET_MASK + 0x4119) +#define HDMITX_DWC_CSC_LIMIT_UP_MSB (DWC_OFFSET_MASK + 0x411A) +#define HDMITX_DWC_CSC_LIMIT_UP_LSB (DWC_OFFSET_MASK + 0x411B) +#define HDMITX_DWC_CSC_LIMIT_DN_MSB (DWC_OFFSET_MASK + 0x411C) +#define HDMITX_DWC_CSC_LIMIT_DN_LSB (DWC_OFFSET_MASK + 0x411D) + +/* HDCP Encryption Engine Registers */ +#define HDMITX_DWC_A_HDCPCFG0 (DWC_SEC_OFFSET_MASK + 0x5000) +/* [ 4] hdcp_lock */ +/* [ 3] dissha1check */ +/* [ 2] ph2upshiftenc */ +/* [ 1] encryptiondisable */ +/* [ 0] swresetn. Write 0 to activate, self-clear to 1. */ +#define HDMITX_DWC_A_HDCPCFG1 (DWC_SEC_OFFSET_MASK + 0x5001) +#define HDMITX_DWC_A_HDCPOBS0 (DWC_OFFSET_MASK + 0x5002) +#define HDMITX_DWC_A_HDCPOBS1 (DWC_OFFSET_MASK + 0x5003) +#define HDMITX_DWC_A_HDCPOBS2 (DWC_OFFSET_MASK + 0x5004) +#define HDMITX_DWC_A_HDCPOBS3 (DWC_OFFSET_MASK + 0x5005) +#define HDMITX_DWC_A_APIINTCLR (DWC_OFFSET_MASK + 0x5006) +#define HDMITX_DWC_A_APIINTSTAT (DWC_OFFSET_MASK + 0x5007) +/* [ 7] hdcp_engaged_int_mask */ +/* [ 6] hdcp_failed_int_mask */ +/* [ 4] i2c_nack_int_mask */ +/* [ 3] lost_arbitration_int_mask */ +/* [ 2] keepout_error_int_mask */ +/* [ 1] ksv_sha1_calc_int_mask */ +/* [ 0] ksv_access_int_mask */ +#define HDMITX_DWC_A_APIINTMSK (DWC_OFFSET_MASK + 0x5008) +/* [6:5] unencryptconf */ +/* [ 4] dataenpol */ +/* [ 3] vsyncpol */ +/* [ 1] hsyncpol */ +#define HDMITX_DWC_A_VIDPOLCFG (DWC_OFFSET_MASK + 0x5009) +#define HDMITX_DWC_A_OESSWCFG (DWC_OFFSET_MASK + 0x500A) +#define HDMITX_DWC_A_COREVERLSB (DWC_OFFSET_MASK + 0x5014) +#define HDMITX_DWC_A_COREVERMSB (DWC_OFFSET_MASK + 0x5015) +/* [ 3] sha1_fail */ +/* [ 2] ksv_ctrl_update */ +/* [ 1] Rsvd for read-only ksv_mem_access */ +/* [ 0] ksv_mem_request */ +#define HDMITX_DWC_A_KSVMEMCTRL (DWC_OFFSET_MASK + 0x5016) + +#define HDMITX_DWC_HDCP_BSTATUS_0 (DWC_OFFSET_MASK + 0x5020) +#define HDMITX_DWC_HDCP_BSTATUS_1 (DWC_OFFSET_MASK + 0x5021) +#define HDMITX_DWC_HDCP_M0_0 (DWC_OFFSET_MASK + 0x5022) +#define HDMITX_DWC_HDCP_M0_1 (DWC_OFFSET_MASK + 0x5023) +#define HDMITX_DWC_HDCP_M0_2 (DWC_OFFSET_MASK + 0x5024) +#define HDMITX_DWC_HDCP_M0_3 (DWC_OFFSET_MASK + 0x5025) +#define HDMITX_DWC_HDCP_M0_4 (DWC_OFFSET_MASK + 0x5026) +#define HDMITX_DWC_HDCP_M0_5 (DWC_OFFSET_MASK + 0x5027) +#define HDMITX_DWC_HDCP_M0_6 (DWC_OFFSET_MASK + 0x5028) +#define HDMITX_DWC_HDCP_M0_7 (DWC_OFFSET_MASK + 0x5029) +#define HDMITX_DWC_HDCP_KSV (DWC_OFFSET_MASK + 0x502A) +#define HDMITX_DWC_HDCP_VH (DWC_OFFSET_MASK + 0x52A5) +#define HDMITX_DWC_HDCP_REVOC_SIZE_0 (DWC_OFFSET_MASK + 0x52B9) +#define HDMITX_DWC_HDCP_REVOC_SIZE_1 (DWC_OFFSET_MASK + 0x52BA) +#define HDMITX_DWC_HDCP_REVOC_LIST (DWC_OFFSET_MASK + 0x52BB) +#define HDMITX_DWC_HDCP_REVOC_LIST_END (DWC_OFFSET_MASK + 0x667E) + +/* HDCP BKSV Registers */ +#define HDMITX_DWC_HDCPREG_BKSV0 (DWC_OFFSET_MASK + 0x7800) +#define HDMITX_DWC_HDCPREG_BKSV1 (DWC_OFFSET_MASK + 0x7801) +#define HDMITX_DWC_HDCPREG_BKSV2 (DWC_OFFSET_MASK + 0x7802) +#define HDMITX_DWC_HDCPREG_BKSV3 (DWC_OFFSET_MASK + 0x7803) +#define HDMITX_DWC_HDCPREG_BKSV4 (DWC_OFFSET_MASK + 0x7804) + +/* HDCP AN Registers */ +#define HDMITX_DWC_HDCPREG_ANCONF (DWC_OFFSET_MASK + 0x7805) +#define HDMITX_DWC_HDCPREG_AN0 (DWC_OFFSET_MASK + 0x7806) +#define HDMITX_DWC_HDCPREG_AN1 (DWC_OFFSET_MASK + 0x7807) +#define HDMITX_DWC_HDCPREG_AN2 (DWC_OFFSET_MASK + 0x7808) +#define HDMITX_DWC_HDCPREG_AN3 (DWC_OFFSET_MASK + 0x7809) +#define HDMITX_DWC_HDCPREG_AN4 (DWC_OFFSET_MASK + 0x780A) +#define HDMITX_DWC_HDCPREG_AN5 (DWC_OFFSET_MASK + 0x780B) +#define HDMITX_DWC_HDCPREG_AN6 (DWC_OFFSET_MASK + 0x780C) +#define HDMITX_DWC_HDCPREG_AN7 (DWC_OFFSET_MASK + 0x780D) +#define HDMITX_DWC_HDCPREG_RMLCTL (DWC_OFFSET_MASK + 0x780E) + +/* Encrypted DPK Embedded Storage Registers */ +#define HDMITX_DWC_HDCPREG_RMLSTS (DWC_OFFSET_MASK + 0x780F) +#define HDMITX_DWC_HDCPREG_SEED0 (DWC_SEC_OFFSET_MASK + 0x7810) +#define HDMITX_DWC_HDCPREG_SEED1 (DWC_SEC_OFFSET_MASK + 0x7811) +#define HDMITX_DWC_HDCPREG_DPK0 (DWC_SEC_OFFSET_MASK + 0x7812) +#define HDMITX_DWC_HDCPREG_DPK1 (DWC_SEC_OFFSET_MASK + 0x7813) +#define HDMITX_DWC_HDCPREG_DPK2 (DWC_SEC_OFFSET_MASK + 0x7814) +#define HDMITX_DWC_HDCPREG_DPK3 (DWC_SEC_OFFSET_MASK + 0x7815) +#define HDMITX_DWC_HDCPREG_DPK4 (DWC_SEC_OFFSET_MASK + 0x7816) +#define HDMITX_DWC_HDCPREG_DPK5 (DWC_SEC_OFFSET_MASK + 0x7817) +#define HDMITX_DWC_HDCPREG_DPK6 (DWC_SEC_OFFSET_MASK + 0x7818) + +/* HDCP22 Registers */ +#define HDMITX_DWC_HDCP22REG_ID (DWC_OFFSET_MASK + 0x7900) +#define HDMITX_DWC_HDCP22REG_CTRL (DWC_SEC_OFFSET_MASK + 0x7904) +#define HDMITX_DWC_HDCP22REG_CTRL1 (DWC_OFFSET_MASK + 0x7905) +#define HDMITX_DWC_HDCP22REG_STS (DWC_OFFSET_MASK + 0x7908) +#define HDMITX_DWC_HDCP22REG_MASK (DWC_OFFSET_MASK + 0x790C) +#define HDMITX_DWC_HDCP22REG_STAT (DWC_OFFSET_MASK + 0x790D) +#define HDMITX_DWC_HDCP22REG_MUTE (DWC_OFFSET_MASK + 0x790E) + + +/* ********** CEC related ********** */ + +/* CEC 2.0 Engine Registers */ +#define HDMITX_DWC_CEC_CTRL (DWC_OFFSET_MASK + 0x7D00) +#define HDMITX_DWC_CEC_INTR_MASK (DWC_OFFSET_MASK + 0x7D02) +#define HDMITX_DWC_CEC_LADD_LOW (DWC_OFFSET_MASK + 0x7D05) +#define HDMITX_DWC_CEC_LADD_HIGH (DWC_OFFSET_MASK + 0x7D06) +#define HDMITX_DWC_CEC_TX_CNT (DWC_OFFSET_MASK + 0x7D07) +#define HDMITX_DWC_CEC_RX_CNT (DWC_OFFSET_MASK + 0x7D08) +#define HDMITX_DWC_CEC_TX_DATA00 (DWC_OFFSET_MASK + 0x7D10) +#define HDMITX_DWC_CEC_TX_DATA01 (DWC_OFFSET_MASK + 0x7D11) +#define HDMITX_DWC_CEC_TX_DATA02 (DWC_OFFSET_MASK + 0x7D12) +#define HDMITX_DWC_CEC_TX_DATA03 (DWC_OFFSET_MASK + 0x7D13) +#define HDMITX_DWC_CEC_TX_DATA04 (DWC_OFFSET_MASK + 0x7D14) +#define HDMITX_DWC_CEC_TX_DATA05 (DWC_OFFSET_MASK + 0x7D15) +#define HDMITX_DWC_CEC_TX_DATA06 (DWC_OFFSET_MASK + 0x7D16) +#define HDMITX_DWC_CEC_TX_DATA07 (DWC_OFFSET_MASK + 0x7D17) +#define HDMITX_DWC_CEC_TX_DATA08 (DWC_OFFSET_MASK + 0x7D18) +#define HDMITX_DWC_CEC_TX_DATA09 (DWC_OFFSET_MASK + 0x7D19) +#define HDMITX_DWC_CEC_TX_DATA10 (DWC_OFFSET_MASK + 0x7D1A) +#define HDMITX_DWC_CEC_TX_DATA11 (DWC_OFFSET_MASK + 0x7D1B) +#define HDMITX_DWC_CEC_TX_DATA12 (DWC_OFFSET_MASK + 0x7D1C) +#define HDMITX_DWC_CEC_TX_DATA13 (DWC_OFFSET_MASK + 0x7D1D) +#define HDMITX_DWC_CEC_TX_DATA14 (DWC_OFFSET_MASK + 0x7D1E) +#define HDMITX_DWC_CEC_TX_DATA15 (DWC_OFFSET_MASK + 0x7D1F) +#define HDMITX_DWC_CEC_RX_DATA00 (DWC_OFFSET_MASK + 0x7D20) +#define HDMITX_DWC_CEC_RX_DATA01 (DWC_OFFSET_MASK + 0x7D21) +#define HDMITX_DWC_CEC_RX_DATA02 (DWC_OFFSET_MASK + 0x7D22) +#define HDMITX_DWC_CEC_RX_DATA03 (DWC_OFFSET_MASK + 0x7D23) +#define HDMITX_DWC_CEC_RX_DATA04 (DWC_OFFSET_MASK + 0x7D24) +#define HDMITX_DWC_CEC_RX_DATA05 (DWC_OFFSET_MASK + 0x7D25) +#define HDMITX_DWC_CEC_RX_DATA06 (DWC_OFFSET_MASK + 0x7D26) +#define HDMITX_DWC_CEC_RX_DATA07 (DWC_OFFSET_MASK + 0x7D27) +#define HDMITX_DWC_CEC_RX_DATA08 (DWC_OFFSET_MASK + 0x7D28) +#define HDMITX_DWC_CEC_RX_DATA09 (DWC_OFFSET_MASK + 0x7D29) +#define HDMITX_DWC_CEC_RX_DATA10 (DWC_OFFSET_MASK + 0x7D2A) +#define HDMITX_DWC_CEC_RX_DATA11 (DWC_OFFSET_MASK + 0x7D2B) +#define HDMITX_DWC_CEC_RX_DATA12 (DWC_OFFSET_MASK + 0x7D2C) +#define HDMITX_DWC_CEC_RX_DATA13 (DWC_OFFSET_MASK + 0x7D2D) +#define HDMITX_DWC_CEC_RX_DATA14 (DWC_OFFSET_MASK + 0x7D2E) +#define HDMITX_DWC_CEC_RX_DATA15 (DWC_OFFSET_MASK + 0x7D2F) +#define HDMITX_DWC_CEC_LOCK_BUF (DWC_OFFSET_MASK + 0x7D30) +#define HDMITX_DWC_CEC_WAKEUPCTRL (DWC_OFFSET_MASK + 0x7D31) + +/* I2C Master Registers(E-DDC/SCDC) */ +#define HDMITX_DWC_I2CM_SLAVE (DWC_OFFSET_MASK + 0x7E00) +#define HDMITX_DWC_I2CM_ADDRESS (DWC_OFFSET_MASK + 0x7E01) +#define HDMITX_DWC_I2CM_DATAO (DWC_OFFSET_MASK + 0x7E02) +#define HDMITX_DWC_I2CM_DATAI (DWC_OFFSET_MASK + 0x7E03) +#define HDMITX_DWC_I2CM_OPERATION (DWC_OFFSET_MASK + 0x7E04) +/* [ 2] done_mask */ +/* [ 6] read_req_mask */ +#define HDMITX_DWC_I2CM_INT (DWC_OFFSET_MASK + 0x7E05) +/* [ 6] nack_mask */ +/* [ 2] arbitration_error_mask */ +#define HDMITX_DWC_I2CM_CTLINT (DWC_OFFSET_MASK + 0x7E06) +/* [ 3] i2c_fast_mode: 0=standard mode; 1=fast mode. */ +#define HDMITX_DWC_I2CM_DIV (DWC_OFFSET_MASK + 0x7E07) +#define HDMITX_DWC_I2CM_SEGADDR (DWC_OFFSET_MASK + 0x7E08) +#define HDMITX_DWC_I2CM_SOFTRSTZ (DWC_OFFSET_MASK + 0x7E09) +#define HDMITX_DWC_I2CM_SEGPTR (DWC_OFFSET_MASK + 0x7E0A) +/* I2CM_SS_SCL_HCNT = RndUp(min_ss_scl_htime*Freq(sfrclkInMHz)/1000) */ +/* I2CM_SS_SCL_LCNT = RndUp(min_ss_scl_ltime*Freq(sfrclkInMHz)/1000) */ +/* I2CM_FS_SCL_HCNT = RndUp(min_fs_scl_htime*Freq(sfrclkInMHz)/1000) */ +/* I2CM_FS_SCL_LCNT = RndUp(min_fs_scl_ltime*Freq(sfrclkInMHz)/1000) */ +/* Where Freq(sfrclkInMHz)=24; */ +#define HDMITX_DWC_I2CM_SS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x7E0B) +#define HDMITX_DWC_I2CM_SS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x7E0C) +#define HDMITX_DWC_I2CM_SS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x7E0D) +#define HDMITX_DWC_I2CM_SS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x7E0E) +#define HDMITX_DWC_I2CM_FS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x7E0F) +#define HDMITX_DWC_I2CM_FS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x7E10) +#define HDMITX_DWC_I2CM_FS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x7E11) +#define HDMITX_DWC_I2CM_FS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x7E12) +#define HDMITX_DWC_I2CM_SDA_HOLD (DWC_OFFSET_MASK + 0x7E13) +/* [ 5] updt_rd_vsyncpoll_en */ +/* [ 4] read_request_en */ +/* [ 0] read_update */ +#define HDMITX_DWC_I2CM_SCDC_UPDATE (DWC_OFFSET_MASK + 0x7E14) +#define HDMITX_DWC_I2CM_READ_BUFF0 (DWC_OFFSET_MASK + 0x7E20) +#define HDMITX_DWC_I2CM_READ_BUFF1 (DWC_OFFSET_MASK + 0x7E21) +#define HDMITX_DWC_I2CM_READ_BUFF2 (DWC_OFFSET_MASK + 0x7E22) +#define HDMITX_DWC_I2CM_READ_BUFF3 (DWC_OFFSET_MASK + 0x7E23) +#define HDMITX_DWC_I2CM_READ_BUFF4 (DWC_OFFSET_MASK + 0x7E24) +#define HDMITX_DWC_I2CM_READ_BUFF5 (DWC_OFFSET_MASK + 0x7E25) +#define HDMITX_DWC_I2CM_READ_BUFF6 (DWC_OFFSET_MASK + 0x7E26) +#define HDMITX_DWC_I2CM_READ_BUFF7 (DWC_OFFSET_MASK + 0x7E27) +#define HDMITX_DWC_I2CM_SCDC_UPDATE0 (DWC_OFFSET_MASK + 0x7E30) +#define HDMITX_DWC_I2CM_SCDC_UPDATE1 (DWC_OFFSET_MASK + 0x7E31) + +#endif /* __HDMI_TX_REG_H_ */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c new file mode 100644 index 000000000000..882c40a76dca --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c @@ -0,0 +1,879 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include "common.h" +#include "mach_reg.h" +#include "hw_clk.h" + +static uint32_t frac_rate; +static int sspll_en = 1; + +/* + * HDMITX Clock configuration + */ + +static inline int check_div(unsigned int div) +{ + if (div == -1) + return -1; + switch (div) { + case 1: + div = 0; + break; + case 2: + div = 1; + break; + case 4: + div = 2; + break; + case 6: + div = 3; + break; + case 12: + div = 4; + break; + default: + break; + } + return div; +} + +static void set_hdmitx_sys_clk(void) +{ + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 3); + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); +} + +static void set_gxb_hpll_clk_out(unsigned int clk) +{ + switch (clk) { + case 5940000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800027b); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x135c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4a05, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4c00, 0, 16); + break; + case 5405400: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000270); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x135c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4800, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x49cd, 0, 16); + break; + case 4455000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800025c); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x135c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4b84, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4d00, 0, 16); + break; + case 3712500: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800024d); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4443, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4580, 0, 16); + break; + case 3450000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000247); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4300, 0, 16); + break; + case 3243240: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000243); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4300, 0, 16); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4800, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4914, 0, 16); + break; + case 2970000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800023d); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4d03, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4e00, 0, 16); + break; + case 4324320: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800025a); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00000000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00000e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4171, 0, 16); + break; + default: + pr_info("error hpll clk: %d\n", clk); + break; + } +} + +static void set_gxtvbb_hpll_clk_out(unsigned int clk) +{ + switch (clk) { + case 5940000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800027b); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4281, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4300, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x12dc5081); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 5405400: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000270); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4200, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4273, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x12dc5081); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 4455000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800025c); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x42e1, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4340, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x12dc5081); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3712500: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800024d); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4111, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4160, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3450000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000247); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4300, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3243240: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x58000243); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4200, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4245, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 2970000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800023d); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4341, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4380, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4e00, 0, 16); + break; + case 4324320: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800025a); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00000000); + if (frac_rate) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x0, 0, 16); + else + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x405c, 0, 16); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x801da72c); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x71486980); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x00002e55); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + default: + pr_info("error hpll clk: %d\n", clk); + break; + } +} + +static void set_hpll_clk_out(unsigned int clk) +{ + pr_info("config HPLL = %d\n", clk); + + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + set_gxb_hpll_clk_out(clk); + break; + case MESON_CPU_MAJOR_ID_GXTVBB: + set_gxtvbb_hpll_clk_out(clk); + break; + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + default: + set_gxl_hpll_clk_out(frac_rate, clk); + break; + } + + pr_info("config HPLL done\n"); +} + +static void set_hpll_sspll(enum hdmi_vic vic) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + break; + case MESON_CPU_MAJOR_ID_GXTVBB: + break; + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + set_hpll_sspll_gxl(vic); + break; + default: + break; + } +} + +static void set_hpll_od1(unsigned int div) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + case MESON_CPU_MAJOR_ID_GXTVBB: + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 16, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 16, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 16, 2); + break; + case 8: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 3, 16, 2); + break; + default: + break; + } + break; + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + default: + set_hpll_od1_gxl(div); + break; + } +} + +static void set_hpll_od2(unsigned int div) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + case MESON_CPU_MAJOR_ID_GXTVBB: + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 22, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 22, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 22, 2); + break; + case 8: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 3, 22, 2); + break; + default: + break; + } + break; + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + default: + set_hpll_od2_gxl(div); + break; + } +} + +static void set_hpll_od3(unsigned int div) +{ + switch (get_cpu_type()) { + case MESON_CPU_MAJOR_ID_GXBB: + case MESON_CPU_MAJOR_ID_GXTVBB: + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 18, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 18, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 18, 2); + break; + case 8: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 3, 18, 2); + break; + default: + break; + } + break; + case MESON_CPU_MAJOR_ID_GXL: + case MESON_CPU_MAJOR_ID_GXM: + default: + set_hpll_od3_gxl(div); + break; + } +} + +/* -------------------------------------------------- + * clocks_set_vid_clk_div + * -------------------------------------------------- + * wire clk_final_en = control[19]; + * wire clk_div1 = control[18]; + * wire [1:0] clk_sel = control[17:16]; + * wire set_preset = control[15]; + * wire [14:0] shift_preset = control[14:0]; + */ +static void set_hpll_od3_clk_div(int div_sel) +{ + int shift_val = 0; + int shift_sel = 0; + + pr_info("%s[%d] div = %d\n", __func__, __LINE__, div_sel); + /* Disable the output clock */ + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 18, 2); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 15, 1); + + switch (div_sel) { + case VID_PLL_DIV_1: + shift_val = 0xFFFF; + shift_sel = 0; + break; + case VID_PLL_DIV_2: + shift_val = 0x0aaa; + shift_sel = 0; + break; + case VID_PLL_DIV_3: + shift_val = 0x0db6; + shift_sel = 0; + break; + case VID_PLL_DIV_3p5: + shift_val = 0x36cc; + shift_sel = 1; + break; + case VID_PLL_DIV_3p75: + shift_val = 0x6666; + shift_sel = 2; + break; + case VID_PLL_DIV_4: + shift_val = 0x0ccc; + shift_sel = 0; + break; + case VID_PLL_DIV_5: + shift_val = 0x739c; + shift_sel = 2; + break; + case VID_PLL_DIV_6: + shift_val = 0x0e38; + shift_sel = 0; + break; + case VID_PLL_DIV_6p25: + shift_val = 0x0000; + shift_sel = 3; + break; + case VID_PLL_DIV_7: + shift_val = 0x3c78; + shift_sel = 1; + break; + case VID_PLL_DIV_7p5: + shift_val = 0x78f0; + shift_sel = 2; + break; + case VID_PLL_DIV_12: + shift_val = 0x0fc0; + shift_sel = 0; + break; + case VID_PLL_DIV_14: + shift_val = 0x3f80; + shift_sel = 1; + break; + case VID_PLL_DIV_15: + shift_val = 0x7f80; + shift_sel = 2; + break; + case VID_PLL_DIV_2p5: + shift_val = 0x5294; + shift_sel = 2; + break; + default: + pr_info("Error: clocks_set_vid_clk_div: Invalid parameter\n"); + break; + } + + if (shift_val == 0xffff) /* if divide by 1 */ + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 1, 18, 1); + else { + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 18, 1); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 16, 2); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 15, 1); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 0, 14); + + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, shift_sel, 16, 2); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 1, 15, 1); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, shift_val, 0, 14); + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 0, 15, 1); + } + /* Enable the final output clock */ + hd_set_reg_bits(P_HHI_VID_PLL_CLK_DIV, 1, 19, 1); +} + +static void set_vid_clk_div(unsigned int div) +{ + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 0, 16, 3); + hd_set_reg_bits(P_HHI_VID_CLK_DIV, div-1, 0, 8); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 7, 0, 3); +} + +static void set_hdmi_tx_pixel_div(unsigned int div) +{ + div = check_div(div); + if (div == -1) + return; + hd_set_reg_bits(P_HHI_HDMI_CLK_CNTL, div, 16, 4); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 5, 1); +} +static void set_encp_div(unsigned int div) +{ + div = check_div(div); + if (div == -1) + return; + hd_set_reg_bits(P_HHI_VID_CLK_DIV, div, 24, 4); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 2, 1); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 1, 19, 1); +} + +static void set_enci_div(unsigned int div) +{ + div = check_div(div); + if (div == -1) + return; + hd_set_reg_bits(P_HHI_VID_CLK_DIV, div, 28, 4); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 0, 1); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 1, 19, 1); +} + +/* mode hpll_clk_out od1 od2(PHY) od3 + * vid_pll_div vid_clk_div hdmi_tx_pixel_div encp_div enci_div + */ +static struct hw_enc_clk_val_group setting_enc_clk_val_24[] = { + {{HDMI_720x480i60_16x9, + HDMI_720x576i50_16x9, + HDMI_VIC_END}, + 4324320, 4, 4, 1, VID_PLL_DIV_5, 1, 2, -1, 2}, + {{HDMI_720x576p50_16x9, + HDMI_720x480p60_16x9, + HDMI_VIC_END}, + 4324320, 4, 4, 1, VID_PLL_DIV_5, 1, 2, 1, -1}, + {{HDMI_1280x720p50_16x9, + HDMI_1280x720p60_16x9, + HDMI_VIC_END}, + 2970000, 4, 1, 1, VID_PLL_DIV_5, 1, 2, 1, -1}, + {{HDMI_1920x1080i60_16x9, + HDMI_1920x1080i50_16x9, + HDMI_VIC_END}, + 2970000, 4, 1, 1, VID_PLL_DIV_5, 1, 2, 1, -1}, + {{HDMI_1920x1080p60_16x9, + HDMI_1920x1080p50_16x9, + HDMI_VIC_END}, + 2970000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, + {{HDMI_1920x1080p30_16x9, + HDMI_1920x1080p24_16x9, + HDMI_1920x1080p25_16x9, + HDMI_VIC_END}, + 2970000, 2, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, + {{HDMI_3840x2160p30_16x9, + HDMI_3840x2160p25_16x9, + HDMI_3840x2160p24_16x9, + HDMI_4096x2160p24_256x135, + HDMI_4096x2160p25_256x135, + HDMI_4096x2160p30_256x135, + HDMI_VIC_END}, + 5940000, 2, 1, 1, VID_PLL_DIV_5, 2, 1, 1, -1}, + {{HDMI_3840x2160p60_16x9, + HDMI_3840x2160p50_16x9, + HDMI_4096x2160p60_256x135, + HDMI_4096x2160p50_256x135, + HDMI_VIC_END}, + 5940000, 1, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, + {{HDMI_4096x2160p60_256x135_Y420, + HDMI_4096x2160p50_256x135_Y420, + HDMI_3840x2160p60_16x9_Y420, + HDMI_3840x2160p50_16x9_Y420, + HDMI_VIC_END}, + 5940000, 2, 1, 1, VID_PLL_DIV_5, 1, 2, 1, -1}, + {{HDMI_VIC_FAKE, + HDMI_VIC_END}, + 3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, +}; + +/* mode hpll_clk_out od1 od2(PHY) od3 + * vid_pll_div vid_clk_div hdmi_tx_pixel_div encp_div enci_div + */ +static struct hw_enc_clk_val_group setting_enc_clk_val_30[] = { + {{HDMI_720x480i60_16x9, + HDMI_720x576i50_16x9, + HDMI_VIC_END}, + 5405400, 4, 4, 1, VID_PLL_DIV_6p25, 1, 2, -1, 2}, + {{HDMI_720x576p50_16x9, + HDMI_720x480p60_16x9, + HDMI_VIC_END}, + 5405400, 4, 4, 1, VID_PLL_DIV_6p25, 1, 2, 1, -1}, + {{HDMI_1280x720p50_16x9, + HDMI_1280x720p60_16x9, + HDMI_VIC_END}, + 3712500, 4, 1, 1, VID_PLL_DIV_6p25, 1, 2, 1, -1}, + {{HDMI_1920x1080i60_16x9, + HDMI_1920x1080i50_16x9, + HDMI_VIC_END}, + 3712500, 4, 1, 1, VID_PLL_DIV_6p25, 1, 2, 1, -1}, + {{HDMI_1920x1080p60_16x9, + HDMI_1920x1080p50_16x9, + HDMI_VIC_END}, + 3712500, 1, 2, 2, VID_PLL_DIV_6p25, 1, 1, 1, -1}, + {{HDMI_1920x1080p30_16x9, + HDMI_1920x1080p24_16x9, + HDMI_1920x1080p25_16x9, + HDMI_VIC_END}, + 3712500, 2, 2, 2, VID_PLL_DIV_6p25, 1, 1, 1, -1}, + {{HDMI_4096x2160p60_256x135_Y420, + HDMI_4096x2160p50_256x135_Y420, + HDMI_3840x2160p60_16x9_Y420, + HDMI_3840x2160p50_16x9_Y420, + HDMI_VIC_END}, + 3712500, 1, 1, 1, VID_PLL_DIV_6p25, 1, 2, 1, -1}, + {{HDMI_3840x2160p24_16x9, + HDMI_3840x2160p25_16x9, + HDMI_3840x2160p30_16x9, + HDMI_4096x2160p24_256x135, + HDMI_4096x2160p25_256x135, + HDMI_4096x2160p30_256x135, + HDMI_VIC_END}, + 3712500, 1, 1, 1, VID_PLL_DIV_6p25, 1, 2, 2, -1}, + {{HDMI_VIC_FAKE, + HDMI_VIC_END}, + 3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, +}; + +static struct hw_enc_clk_val_group setting_enc_clk_val_36[] = { + {{HDMI_720x480i60_16x9, + HDMI_720x576i50_16x9, + HDMI_VIC_END}, + 3243240, 2, 4, 1, VID_PLL_DIV_7p5, 1, 2, -1, 2}, + {{HDMI_720x576p50_16x9, + HDMI_720x480p60_16x9, + HDMI_VIC_END}, + 3243240, 2, 4, 1, VID_PLL_DIV_7p5, 1, 2, 1, -1}, + {{HDMI_1280x720p50_16x9, + HDMI_1280x720p60_16x9, + HDMI_VIC_END}, + 4455000, 4, 1, 1, VID_PLL_DIV_7p5, 1, 2, 1, -1}, + {{HDMI_1920x1080i60_16x9, + HDMI_1920x1080i50_16x9, + HDMI_VIC_END}, + 4455000, 4, 1, 1, VID_PLL_DIV_7p5, 1, 2, 1, -1}, + {{HDMI_1920x1080p60_16x9, + HDMI_1920x1080p50_16x9, + HDMI_VIC_END}, + 4455000, 1, 2, 2, VID_PLL_DIV_7p5, 1, 1, 1, -1}, + {{HDMI_1920x1080p30_16x9, + HDMI_1920x1080p24_16x9, + HDMI_1920x1080p25_16x9, + HDMI_VIC_END}, + 4455000, 2, 2, 2, VID_PLL_DIV_7p5, 1, 1, 1, -1}, + {{HDMI_4096x2160p60_256x135_Y420, + HDMI_4096x2160p50_256x135_Y420, + HDMI_3840x2160p60_16x9_Y420, + HDMI_3840x2160p50_16x9_Y420, + HDMI_VIC_END}, + 4455000, 1, 1, 1, VID_PLL_DIV_7p5, 1, 2, 1, -1}, + {{HDMI_3840x2160p24_16x9, + HDMI_3840x2160p25_16x9, + HDMI_3840x2160p30_16x9, + HDMI_4096x2160p24_256x135, + HDMI_4096x2160p25_256x135, + HDMI_4096x2160p30_256x135, + HDMI_VIC_END}, + 4455000, 1, 1, 1, VID_PLL_DIV_7p5, 1, 2, 2, -1}, + {{HDMI_VIC_FAKE, + HDMI_VIC_END}, + 3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, +}; +static struct hw_enc_clk_val_group setting_3dfp_enc_clk_val[] = { + {{HDMI_1920x1080p60_16x9, + HDMI_1920x1080p50_16x9, + HDMI_VIC_END}, + 2970000, 1, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, + {{HDMI_1280x720p50_16x9, + HDMI_1280x720p60_16x9, + HDMI_1920x1080p30_16x9, + HDMI_1920x1080p24_16x9, + HDMI_1920x1080p25_16x9, + HDMI_VIC_END}, + 2970000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, + {{HDMI_VIC_FAKE, + HDMI_VIC_END}, + 3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, +}; +static void hdmitx_set_clk_(enum hdmi_vic vic, enum hdmi_color_depth cd) +{ + int i = 0; + int j = 0; + struct hw_enc_clk_val_group *p_enc = NULL; + + if (cd == COLORDEPTH_24B) { + p_enc = &setting_enc_clk_val_24[0]; + for (j = 0; j < sizeof(setting_enc_clk_val_24) + / sizeof(struct hw_enc_clk_val_group); j++) { + for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i] + != HDMI_VIC_END)); i++) { + if (vic == p_enc[j].group[i]) + goto next; + } + } + if (j == sizeof(setting_enc_clk_val_24) + / sizeof(struct hw_enc_clk_val_group)) { + pr_info("Not find VIC = %d for hpll setting\n", vic); + return; + } + } else if (cd == COLORDEPTH_30B) { + p_enc = &setting_enc_clk_val_30[0]; + for (j = 0; j < sizeof(setting_enc_clk_val_30) + / sizeof(struct hw_enc_clk_val_group); j++) { + for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i] + != HDMI_VIC_END)); i++) { + if (vic == p_enc[j].group[i]) + goto next; + } + } + if (j == sizeof(setting_enc_clk_val_30) / + sizeof(struct hw_enc_clk_val_group)) { + pr_info("Not find VIC = %d for hpll setting\n", vic); + return; + } + } else if (cd == COLORDEPTH_36B) { + p_enc = &setting_enc_clk_val_36[0]; + for (j = 0; j < sizeof(setting_enc_clk_val_36) + / sizeof(struct hw_enc_clk_val_group); j++) { + for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i] + != HDMI_VIC_END)); i++) { + if (vic == p_enc[j].group[i]) + goto next; + } + } + if (j == sizeof(setting_enc_clk_val_36) / + sizeof(struct hw_enc_clk_val_group)) { + pr_info("Not find VIC = %d for hpll setting\n", vic); + return; + } + } else { + pr_info("not support colordepth 48bits\n"); + return; + } +next: + set_hdmitx_sys_clk(); + set_hpll_clk_out(p_enc[j].hpll_clk_out); + if ((cd == COLORDEPTH_24B) && sspll_en) + set_hpll_sspll(vic); + set_hpll_od1(p_enc[j].od1); + set_hpll_od2(p_enc[j].od2); + set_hpll_od3(p_enc[j].od3); + set_hpll_od3_clk_div(p_enc[j].vid_pll_div); + pr_info("j = %d vid_clk_div = %d\n", j, p_enc[j].vid_clk_div); + set_vid_clk_div(p_enc[j].vid_clk_div); + set_hdmi_tx_pixel_div(p_enc[j].hdmi_tx_pixel_div); + set_encp_div(p_enc[j].encp_div); + set_enci_div(p_enc[j].enci_div); +} +static void hdmitx_set_3dfp_clk(enum hdmi_vic vic) +{ + int i = 0; + int j = 0; + struct hw_enc_clk_val_group *p_enc = NULL; + + p_enc = &setting_3dfp_enc_clk_val[0]; + for (j = 0; j < sizeof(setting_3dfp_enc_clk_val) + / sizeof(struct hw_enc_clk_val_group); j++) { + for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i] + != HDMI_VIC_END)); i++) { + if (vic == p_enc[j].group[i]) + goto next; + } + } + if (j == sizeof(setting_3dfp_enc_clk_val) + / sizeof(struct hw_enc_clk_val_group)) { + pr_info("Not find VIC = %d for hpll setting\n", vic); + return; + } +next: + set_hdmitx_sys_clk(); + set_hpll_clk_out(p_enc[j].hpll_clk_out); + set_hpll_sspll(vic); + set_hpll_od1(p_enc[j].od1); + set_hpll_od2(p_enc[j].od2); + set_hpll_od3(p_enc[j].od3); + set_hpll_od3_clk_div(p_enc[j].vid_pll_div); + pr_info("j = %d vid_clk_div = %d\n", j, p_enc[j].vid_clk_div); + set_vid_clk_div(p_enc[j].vid_clk_div); + set_hdmi_tx_pixel_div(p_enc[j].hdmi_tx_pixel_div); + set_encp_div(p_enc[j].encp_div); + set_enci_div(p_enc[j].enci_div); +} + +static int likely_frac_rate_mode(char *m) +{ + if (strstr(m, "24hz") || strstr(m, "30hz") || strstr(m, "60hz") + || strstr(m, "120hz") || strstr(m, "240hz")) + return 1; + else + return 0; + } +void hdmitx_set_clk(struct hdmitx_dev *hdev) +{ + enum hdmi_vic vic = hdev->cur_VIC; + struct hdmi_format_para *para = NULL; + + frac_rate = hdev->frac_rate_policy; + pr_info("hdmitx: set clk: VIC = %d cd = %d frac_rate = %d\n", vic, + hdev->para->cd, frac_rate); + para = hdmi_get_fmt_paras(vic); + if (para && (para->name) && likely_frac_rate_mode(para->name)) + ; + else { + pr_info("hdmitx: %s doesn't have frac_rate\n", para->name); + frac_rate = 0; + } + + if (hdev->flag_3dfp) { + hdmitx_set_3dfp_clk(vic); + return; + } + if (hdev->para->cs != COLORSPACE_YUV422) + hdmitx_set_clk_(vic, hdev->para->cd); + + + else + hdmitx_set_clk_(vic, COLORDEPTH_24B); + } + +MODULE_PARM_DESC(sspll_en, "\n hdmitx sspll_en\n"); +module_param(sspll_en, int, 0664); + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h new file mode 100644 index 000000000000..43083b1cadb0 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h @@ -0,0 +1,58 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HW_ENC_CLK_CONFIG_H__ +#define __HW_ENC_CLK_CONFIG_H__ + +#include +#include +#include + +#define VID_PLL_DIV_1 0 +#define VID_PLL_DIV_2 1 +#define VID_PLL_DIV_3 2 +#define VID_PLL_DIV_3p5 3 +#define VID_PLL_DIV_3p75 4 +#define VID_PLL_DIV_4 5 +#define VID_PLL_DIV_5 6 +#define VID_PLL_DIV_6 7 +#define VID_PLL_DIV_6p25 8 +#define VID_PLL_DIV_7 9 +#define VID_PLL_DIV_7p5 10 +#define VID_PLL_DIV_12 11 +#define VID_PLL_DIV_14 12 +#define VID_PLL_DIV_15 13 +#define VID_PLL_DIV_2p5 14 + +#define GROUP_MAX 8 +struct hw_enc_clk_val_group { + enum hdmi_vic group[GROUP_MAX]; + unsigned int hpll_clk_out; /* Unit: kHz */ + unsigned int od1; + unsigned int od2; /* HDMI_CLK_TODIG */ + unsigned int od3; + unsigned int vid_pll_div; + unsigned int vid_clk_div; + unsigned int hdmi_tx_pixel_div; + unsigned int encp_div; + unsigned int enci_div; +}; + +void hdmitx_set_clk(struct hdmitx_dev *hdev); + +#endif + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c new file mode 100644 index 000000000000..f5ea69911547 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c @@ -0,0 +1,92 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxbb.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include "common.h" +#include "mach_reg.h" + +/* + * NAME PAD PINMUX GPIO + * HPD GPIOH_0 reg1[26] GPIO1[16] + * SCL GPIOH_2 reg1[24] GPIO1[18[ + * SDA GPIOH_1 reg7[25] GPIO1[17] + */ + +int hdmitx_hpd_hw_op_gxbb(enum hpd_op cmd) +{ + int ret = 0; + + switch (cmd) { + case HPD_INIT_DISABLE_PULLUP: + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 20, 1); + break; + case HPD_INIT_SET_FILTER: + hdmitx_wr_reg(HDMITX_TOP_HPD_FILTER, + ((0xa << 12) | (0xa0 << 0))); + break; + case HPD_IS_HPD_MUXED: + ret = !!(hd_read_reg(P_PERIPHS_PIN_MUX_1) & (1 << 26)); + break; + case HPD_MUX_HPD: +/* GPIOH_5 input */ + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 21, 1); +/* clear other pinmux */ + hd_set_reg_bits(P_PERIPHS_PIN_MUX_1, 0, 19, 1); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_1, 1, 26, 1); + break; + case HPD_UNMUX_HPD: + hd_set_reg_bits(P_PERIPHS_PIN_MUX_1, 0, 26, 1); +/* GPIOH_5 input */ + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 21, 1); + break; + case HPD_READ_HPD_GPIO: + ret = !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 20)); + break; + default: + pr_info("error hpd cmd %d\n", cmd); + break; + } + return ret; +} + +int read_hpd_gpio_gxbb(void) +{ + return !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 20)); +} + +int hdmitx_ddc_hw_op_gxbb(enum ddc_op cmd) +{ + int ret = 0; + + switch (cmd) { + case DDC_INIT_DISABLE_PULL_UP_DN: + hd_set_reg_bits(P_PAD_PULL_UP_EN_REG1, 0, 21, 2); + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 21, 2); + break; + case DDC_MUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 21, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_1, 3, 24, 2); + break; + case DDC_UNMUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 21, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_1, 0, 24, 2); + break; + default: + pr_info("error ddc cmd %d\n", cmd); + } + return ret; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c new file mode 100644 index 000000000000..6cb0f9c21241 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c @@ -0,0 +1,330 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxl.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include "common.h" +#include "mach_reg.h" + +/* + * From GXL chips, registers names changes. + * Added new HHI_HDMI_PLL_CNTL1 but addessed as 0xc9. + * It's different with HHI_HDMI_PLL_CNTL2 0xc9 in previouse chips. + */ +#ifdef P_HHI_HDMI_PLL_CNTL2 +#undef P_HHI_HDMI_PLL_CNTL2 +#endif +#ifdef P_HHI_HDMI_PLL_CNTL3 +#undef P_HHI_HDMI_PLL_CNTL3 +#endif +#ifdef P_HHI_HDMI_PLL_CNTL4 +#undef P_HHI_HDMI_PLL_CNTL4 +#endif +#ifdef P_HHI_HDMI_PLL_CNTL5 +#undef P_HHI_HDMI_PLL_CNTL5 +#endif +#ifdef P_HHI_HDMI_PLL_CNTL6 +#undef P_HHI_HDMI_PLL_CNTL6 +#endif + +#define P_HHI_HDMI_PLL_CNTL1 (0xc883c000 + (0xc9 << 2)) +#define P_HHI_HDMI_PLL_CNTL2 (0xc883c000 + (0xca << 2)) +#define P_HHI_HDMI_PLL_CNTL3 (0xc883c000 + (0xcb << 2)) +#define P_HHI_HDMI_PLL_CNTL4 (0xc883c000 + (0xcc << 2)) +#define P_HHI_HDMI_PLL_CNTL5 (0xc883c000 + (0xcd << 2)) + +/* + * NAME PAD PINMUX GPIO + * HPD GPIOH_0 reg6[31] GPIO1[20] + * SCL GPIOH_2 reg6[29] GPIO1[22[ + * SDA GPIOH_1 reg6[30] GPIO1[21] + */ + +int hdmitx_hpd_hw_op_gxl(enum hpd_op cmd) +{ + int ret = 0; + + switch (cmd) { + case HPD_INIT_DISABLE_PULLUP: + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 25, 1); + break; + case HPD_INIT_SET_FILTER: + hdmitx_wr_reg(HDMITX_TOP_HPD_FILTER, + ((0xa << 12) | (0xa0 << 0))); + break; + case HPD_IS_HPD_MUXED: + ret = !!(hd_read_reg(P_PERIPHS_PIN_MUX_6) & (1 << 31)); + break; + case HPD_MUX_HPD: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 20, 1); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_6, 1, 31, 1); + break; + case HPD_UNMUX_HPD: + hd_set_reg_bits(P_PERIPHS_PIN_MUX_6, 0, 31, 1); + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 20, 1); + break; + case HPD_READ_HPD_GPIO: + ret = !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 20)); + break; + default: + pr_info("error hpd cmd %d\n", cmd); + break; + } + return ret; +} + +int read_hpd_gpio_gxl(void) +{ + return !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 20)); +} + +int hdmitx_ddc_hw_op_gxl(enum ddc_op cmd) +{ + int ret = 0; + + switch (cmd) { + case DDC_INIT_DISABLE_PULL_UP_DN: + hd_set_reg_bits(P_PAD_PULL_UP_EN_REG1, 0, 23, 2); + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 23, 2); + break; + case DDC_MUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 21, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_6, 3, 29, 2); + break; + case DDC_UNMUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 21, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_6, 0, 29, 2); + break; + default: + pr_info("error ddc cmd %d\n", cmd); + } + return ret; +} + +void set_gxl_hpll_clk_out(unsigned int frac_rate, unsigned int clk) +{ + switch (clk) { + case 5940000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x4000027b); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb281); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb300); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0xc60f30e0); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 5405400: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x400002e1); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb000); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb0e6); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 4455000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x400002b9); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb1c2); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb280); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3712500: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x4000029a); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb222); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb2c0); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3450000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x4000028f); + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb300); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 3243240: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x40000287); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb000); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb08a); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 2970000: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x4000027b); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb281); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb300); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + case 4324320: + hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x400002b4); + if (frac_rate) + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb000); + else + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x800cb0b8); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x860f30c4); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0c8e0000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x001fa729); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x01a31500); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x1, 28, 1); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x0, 28, 1); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); + break; + default: + pr_info("error hpll clk: %d\n", clk); + break; + } +} + +void set_hpll_sspll_gxl(enum hdmi_vic vic) +{ + switch (vic) { + case HDMI_1920x1080p60_16x9: + case HDMI_1920x1080p50_16x9: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x68b48c4, 0, 30); + break; + case HDMI_1280x720p60_16x9: + case HDMI_1280x720p50_16x9: + case HDMI_1920x1080i60_16x9: + case HDMI_1920x1080i50_16x9: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x64348c4, 0, 30); + break; + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + break; + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + case HDMI_3840x2160p30_16x9: + case HDMI_3840x2160p25_16x9: + case HDMI_3840x2160p24_16x9: + case HDMI_4096x2160p30_256x135: + case HDMI_4096x2160p25_256x135: + case HDMI_4096x2160p24_256x135: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x62b44c4, 0, 30); + break; + default: + break; + } +} + +void set_hpll_od1_gxl(unsigned int div) +{ + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 21, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 21, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 21, 2); + break; + default: + pr_info("Err %s[%d]\n", __func__, __LINE__); + break; + } +} + +void set_hpll_od2_gxl(unsigned int div) +{ + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 23, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 23, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 23, 2); + break; + default: + pr_info("Err %s[%d]\n", __func__, __LINE__); + break; + } +} + +void set_hpll_od3_gxl(unsigned int div) +{ + switch (div) { + case 1: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0, 19, 2); + break; + case 2: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 19, 2); + break; + case 4: + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 19, 2); + break; + default: + pr_info("Err %s[%d]\n", __func__, __LINE__); + break; + } +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c new file mode 100644 index 000000000000..967fc82521fe --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c @@ -0,0 +1,90 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_gxtvbb.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include "common.h" +#include "mach_reg.h" + +/* + * NAME PAD PINMUX GPIO + * HPD GPIOH_5 reg7[21] GPIO1[25] + * SCL GPIOH_4 reg7[20] GPIO1[24[ + * SDA GPIOH_3 reg7[19] GPIO1[23] + */ + +int hdmitx_hpd_hw_op_gxtvbb(enum hpd_op cmd) +{ + int ret = 0; + + switch (cmd) { + case HPD_INIT_DISABLE_PULLUP: + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 25, 1); + break; + case HPD_INIT_SET_FILTER: + hdmitx_wr_reg(HDMITX_TOP_HPD_FILTER, + ((0xa << 12) | (0xa0 << 0))); + break; + case HPD_IS_HPD_MUXED: + ret = !!(hd_read_reg(P_PERIPHS_PIN_MUX_7) & (1 << 21)); + break; + case HPD_MUX_HPD: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 25, 1); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_7, 0, 23, 1); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_7, 1, 21, 1); + break; + case HPD_UNMUX_HPD: + hd_set_reg_bits(P_PERIPHS_PIN_MUX_7, 0, 21, 1); + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 1, 25, 1); + break; + case HPD_READ_HPD_GPIO: + ret = !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 25)); + break; + default: + pr_info("error hpd cmd %d\n", cmd); + break; + } + return ret; +} + +int read_hpd_gpio_gxtvbb(void) +{ + return !!(hd_read_reg(P_PREG_PAD_GPIO1_I) & (1 << 25)); +} + +int hdmitx_ddc_hw_op_gxtvbb(enum ddc_op cmd) +{ + int ret = 0; + + switch (cmd) { + case DDC_INIT_DISABLE_PULL_UP_DN: + hd_set_reg_bits(P_PAD_PULL_UP_EN_REG1, 0, 23, 2); + hd_set_reg_bits(P_PAD_PULL_UP_REG1, 0, 23, 2); + break; + case DDC_MUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 24, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_7, 3, 19, 2); + break; + case DDC_UNMUX_DDC: + hd_set_reg_bits(P_PREG_PAD_GPIO1_EN_N, 3, 24, 2); + hd_set_reg_bits(P_PERIPHS_PIN_MUX_7, 0, 19, 2); + break; + default: + pr_info("error ddc cmd %d\n", cmd); + } + return ret; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h new file mode 100644 index 000000000000..3836e22df28c --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h @@ -0,0 +1,834 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MACH_REG_H__ +#define __MACH_REG_H__ +#include +#include + +struct reg_s { + unsigned int reg; + unsigned int val; +}; + +#define OFFSET 24 +#define CBUS_REG_ADDR(reg) ((IO_CBUS_BASE << OFFSET) + (reg << 2)) +#define nCBUS_REG_ADDR(reg) (0xc8834400 + (reg << 2)) +#define VCBUS_REG_ADDR(reg) (0xd0100000 + (reg << 2)) +#define AOBUS_REG_ADDR(reg) ((IO_AOBUS_BASE << OFFSET) + reg) +#define APB_REG_ADDR(reg) ((IO_APB_BUS_BASE << OFFSET) + reg) + +unsigned int hd_read_reg(unsigned int addr); +void hd_write_reg(unsigned int addr, unsigned int val); +void hd_set_reg_bits(unsigned int addr, unsigned int value, unsigned int offset, + unsigned int len); +void sec_reg_write(unsigned int *addr, unsigned int value); +unsigned int sec_reg_read(unsigned int *addr); +void init_reg_map(void); + +#define WAIT_FOR_PLL_LOCKED(reg) \ + do { \ + unsigned int st = 0, cnt = 10; \ + while (cnt--) { \ + udelay(5); \ + st = !!(hd_read_reg(reg) & (1 << 31)); \ + if (st) \ + break; \ + else { \ + /* reset hpll */ \ + hd_set_reg_bits(reg, 1, 28, 1); \ + hd_set_reg_bits(reg, 0, 28, 1); \ + } \ + } \ + if (cnt < 9) \ + pr_info("pll[0x%x] reset %d times\n", reg, 9 - cnt);\ + } while (0) + +#define P_PREG_PAD_GPIO6_EN_N nCBUS_REG_ADDR(0x08) +#define P_PREG_PAD_GPIO6_O nCBUS_REG_ADDR(0x09) +#define P_PREG_PAD_GPIO6_I nCBUS_REG_ADDR(0x0a) +#define P_PREG_JTAG_GPIO_ADDR nCBUS_REG_ADDR(0x0b) +#define P_PREG_PAD_GPIO0_EN_N nCBUS_REG_ADDR(0x0c) +#define P_PREG_PAD_GPIO0_O nCBUS_REG_ADDR(0x0d) +#define P_PREG_PAD_GPIO0_I nCBUS_REG_ADDR(0x0e) +#define P_PREG_PAD_GPIO1_EN_N nCBUS_REG_ADDR(0x0f) +#define P_PREG_PAD_GPIO1_O nCBUS_REG_ADDR(0x10) +#define P_PREG_PAD_GPIO1_I nCBUS_REG_ADDR(0x11) +#define P_PREG_PAD_GPIO2_EN_N nCBUS_REG_ADDR(0x12) +#define P_PREG_PAD_GPIO2_O nCBUS_REG_ADDR(0x13) +#define P_PREG_PAD_GPIO2_I nCBUS_REG_ADDR(0x14) +#define P_PREG_PAD_GPIO3_EN_N nCBUS_REG_ADDR(0x15) +#define P_PREG_PAD_GPIO3_O nCBUS_REG_ADDR(0x16) +#define P_PREG_PAD_GPIO3_I nCBUS_REG_ADDR(0x17) +#define P_PREG_PAD_GPIO4_EN_N nCBUS_REG_ADDR(0x18) +#define P_PREG_PAD_GPIO4_O nCBUS_REG_ADDR(0x19) +#define P_PREG_PAD_GPIO4_I nCBUS_REG_ADDR(0x1a) +#define P_PREG_PAD_GPIO5_EN_N nCBUS_REG_ADDR(0x1b) +#define P_PREG_PAD_GPIO5_O nCBUS_REG_ADDR(0x1c) +#define P_PREG_PAD_GPIO5_I nCBUS_REG_ADDR(0x1d) +#define PERIPHS_PIN_MUX_0 0x2c /* register.h:419 */ +#define P_PERIPHS_PIN_MUX_0 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_0) +#define PERIPHS_PIN_MUX_1 0x2d /* register.h:420 */ +#define P_PERIPHS_PIN_MUX_1 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_1) +#define PERIPHS_PIN_MUX_2 0x2e /* register.h:421 */ +#define P_PERIPHS_PIN_MUX_2 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_2) +#define PERIPHS_PIN_MUX_3 0x2f /* register.h:422 */ +#define P_PERIPHS_PIN_MUX_3 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_3) +#define PERIPHS_PIN_MUX_4 0x30 /* register.h:423 */ +#define P_PERIPHS_PIN_MUX_4 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_4) +#define PERIPHS_PIN_MUX_5 0x31 /* register.h:424 */ +#define P_PERIPHS_PIN_MUX_5 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_5) +#define PERIPHS_PIN_MUX_6 0x32 /* register.h:425 */ +#define P_PERIPHS_PIN_MUX_6 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_6) +#define PERIPHS_PIN_MUX_7 0x33 /* register.h:426 */ +#define P_PERIPHS_PIN_MUX_7 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_7) +#define PERIPHS_PIN_MUX_8 0x34 /* register.h:427 */ +#define P_PERIPHS_PIN_MUX_8 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_8) +#define PERIPHS_PIN_MUX_9 0x35 /* register.h:428 */ +#define P_PERIPHS_PIN_MUX_9 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_9) +#define PERIPHS_PIN_MUX_10 0x36 /* register.h:429 */ +#define P_PERIPHS_PIN_MUX_10 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_10) +#define PERIPHS_PIN_MUX_11 0x37 /* register.h:430 */ +#define P_PERIPHS_PIN_MUX_11 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_11) +#define PERIPHS_PIN_MUX_12 0x38 /* register.h:431 */ +#define P_PERIPHS_PIN_MUX_12 nCBUS_REG_ADDR(PERIPHS_PIN_MUX_12) + +#define PAD_PULL_UP_REG0 0x3a +#define P_PAD_PULL_UP_REG0 nCBUS_REG_ADDR(PAD_PULL_UP_REG0) +#define PAD_PULL_UP_REG1 0x3d +#define P_PAD_PULL_UP_REG1 nCBUS_REG_ADDR(PAD_PULL_UP_REG1) +#define PAD_PULL_UP_REG2 0x3c +#define P_PAD_PULL_UP_REG2 nCBUS_REG_ADDR(PAD_PULL_UP_REG2) +#define PAD_PULL_UP_REG3 0x3d +#define P_PAD_PULL_UP_REG3 nCBUS_REG_ADDR(PAD_PULL_UP_REG3) +#define PAD_PULL_UP_REG4 0x3d +#define P_PAD_PULL_UP_REG4 nCBUS_REG_ADDR(PAD_PULL_UP_REG4) +#define PAD_PULL_UP_EN_REG0 0x48 +#define P_PAD_PULL_UP_EN_REG0 nCBUS_REG_ADDR(PAD_PULL_UP_EN_REG0) +#define PAD_PULL_UP_EN_REG1 0x49 +#define P_PAD_PULL_UP_EN_REG1 nCBUS_REG_ADDR(PAD_PULL_UP_EN_REG1) +#define PAD_PULL_UP_EN_REG2 0x4a +#define P_PAD_PULL_UP_EN_REG2 nCBUS_REG_ADDR(PAD_PULL_UP_EN_REG2) +#define PAD_PULL_UP_EN_REG3 0x4b +#define P_PAD_PULL_UP_EN_REG3 nCBUS_REG_ADDR(PAD_PULL_UP_EN_REG3) +#define PAD_PULL_UP_EN_REG4 0x4c +#define P_PAD_PULL_UP_EN_REG4 nCBUS_REG_ADDR(PAD_PULL_UP_EN_REG4) + +#define P_HHI_MEM_PD_REG0 (0xc883c000 + (0x40 << 2)) +#define P_HHI_VPU_MEM_PD_REG0 (0xc883c000 + (0x41 << 2)) +#define P_HHI_VPU_MEM_PD_REG1 (0xc883c000 + (0x42 << 2)) +#define P_HHI_AUD_DAC_CTRL (0xc883c000 + (0x44 << 2)) +#define P_HHI_VIID_CLK_DIV (0xc883c000 + (0x4a << 2)) +/* [19] -enable clk_div0 */ +/* [18:16] - cntl_clk_in_sel */ +#define P_HHI_VIID_CLK_CNTL (0xc883c000 + (0x4b << 2)) +#define P_HHI_VIID_DIVIDER_CNTL (0xc883c000 + (0x4c << 2)) + +/* + *======================================================================== + * Global Control Registers (12'h000 - 12'h0ff) + * + *======================================================================== + * ----------------------------------------------- + * CBUS_BASE: RESET_CBUS_BASE = 0x11 + * ----------------------------------------------- + */ +#define P_VERSION_CTRL ((0x00 << 2) + 0xc1104400) +#define P_RESET0_REGISTER ((0x01 << 2) + 0xc1104400) +#define P_RESET1_REGISTER ((0x02 << 2) + 0xc1104400) +#define P_RESET2_REGISTER ((0x03 << 2) + 0xc1104400) +#define P_RESET3_REGISTER ((0x04 << 2) + 0xc1104400) +#define P_RESET4_REGISTER ((0x05 << 2) + 0xc1104400) +#define P_RESET5_REGISTER ((0x06 << 2) + 0xc1104400) +#define P_RESET6_REGISTER ((0x07 << 2) + 0xc1104400) +#define P_RESET7_REGISTER ((0x08 << 2) + 0xc1104400) +#define P_RESET0_MASK ((0x10 << 2) + 0xc1104400) +#define P_RESET1_MASK ((0x11 << 2) + 0xc1104400) +#define P_RESET2_MASK ((0x12 << 2) + 0xc1104400) +#define P_RESET3_MASK ((0x13 << 2) + 0xc1104400) +#define P_RESET4_MASK ((0x14 << 2) + 0xc1104400) +#define P_RESET5_MASK ((0x15 << 2) + 0xc1104400) +#define P_RESET6_MASK ((0x16 << 2) + 0xc1104400) + +/* Gated clock enables. + * There are 64 enables for the MPEG clocks and 32 enables for other + * clock domains. + */ +#define P_HHI_GCLK_MPEG0 (0xc883c000 + (0x50 << 2)) +#define P_HHI_GCLK_MPEG1 (0xc883c000 + (0x51 << 2)) +#define P_HHI_GCLK_MPEG2 (0xc883c000 + (0x52 << 2)) +#define P_HHI_GCLK_OTHER (0xc883c000 + (0x54 << 2)) +#define P_HHI_GCLK_AO (0xc883c000 + (0x55 << 2)) +#define P_HHI_SYS_OSCIN_CNTL (0xc883c000 + (0x56 << 2)) +#define P_HHI_SYS_CPU_CLK_CNTL1 (0xc883c000 + (0x57 << 2)) +#define P_HHI_SYS_CPU_RESET_CNTL (0xc883c000 + (0x58 << 2)) +/* [7:0] - cntl_xd0 */ +#define P_HHI_VID_CLK_DIV (0xc883c000 + (0x59 << 2)) +#define P_HHI_MPEG_CLK_CNTL (0xc883c000 + (0x5d << 2)) +#define P_HHI_AUD_CLK_CNTL (0xc883c000 + (0x5e << 2)) +/* [18:16] - cntl_clk_in_sel */ +#define P_HHI_VID_CLK_CNTL (0xc883c000 + (0x5f << 2)) +#define P_HHI_WIFI_CLK_CNTL (0xc883c000 + (0x60 << 2)) +#define P_HHI_WIFI_PLL_CNTL (0xc883c000 + (0x61 << 2)) +#define P_HHI_WIFI_PLL_CNTL2 (0xc883c000 + (0x62 << 2)) +#define P_HHI_WIFI_PLL_CNTL3 (0xc883c000 + (0x63 << 2)) +#define P_HHI_AUD_CLK_CNTL2 (0xc883c000 + (0x64 << 2)) +#define P_HHI_VID_CLK_CNTL2 (0xc883c000 + (0x65 << 2)) +#define P_HHI_VID_DIVIDER_CNTL (0xc883c000 + (0x66 << 2)) +#define P_HHI_SYS_CPU_CLK_CNTL (0xc883c000 + (0x67 << 2)) +#define P_HHI_VID_PLL_CLK_DIV (0xc883c000 + (0x68 << 2)) +#define P_HHI_AUD_CLK_CNTL3 (0xc883c000 + (0x69 << 2)) +#define P_HHI_MALI_CLK_CNTL (0xc883c000 + (0x6c << 2)) +#define P_HHI_MIPI_PHY_CLK_CNTL (0xc883c000 + (0x6e << 2)) +#define P_HHI_VPU_CLK_CNTL (0xc883c000 + (0x6f << 2)) +#define P_HHI_OTHER_PLL_CNTL (0xc883c000 + (0x70 << 2)) +#define P_HHI_OTHER_PLL_CNTL2 (0xc883c000 + (0x71 << 2)) +#define P_HHI_OTHER_PLL_CNTL3 (0xc883c000 + (0x72 << 2)) +#define P_HHI_HDMI_CLK_CNTL (0xc883c000 + (0x73 << 2)) +#define P_HHI_DEMOD_CLK_CNTL (0xc883c000 + (0x74 << 2)) +#define P_HHI_SATA_CLK_CNTL (0xc883c000 + (0x75 << 2)) +#define P_HHI_ETH_CLK_CNTL (0xc883c000 + (0x76 << 2)) +#define P_HHI_CLK_DOUBLE_CNTL (0xc883c000 + (0x77 << 2)) +#define P_HHI_VDEC_CLK_CNTL (0xc883c000 + (0x78 << 2)) +#define P_HHI_VDEC2_CLK_CNTL (0xc883c000 + (0x79 << 2)) +#define P_HHI_VDEC3_CLK_CNTL (0xc883c000 + (0x7a << 2)) +#define P_HHI_VDEC4_CLK_CNTL (0xc883c000 + (0x7b << 2)) +#define P_HHI_HDCP22_CLK_CNTL (0xc883c000 + (0x7c << 2)) +#define P_HHI_VAPBCLK_CNTL (0xc883c000 + (0x7d << 2)) +#define P_HHI_VP9DEC_CLK_CNTL (0xc883c000 + (0x7e << 2)) +#define P_HHI_HDMI_AFC_CNTL (0xc883c000 + (0x7f << 2)) +#define P_HHI_HDMIRX_CLK_CNTL (0xc883c000 + (0x80 << 2)) +#define P_HHI_HDMIRX_AUD_CLK_CNTL (0xc883c000 + (0x81 << 2)) +#define P_HHI_EDP_APB_CLK_CNTL (0xc883c000 + (0x82 << 2)) +#define P_HHI_VPU_CLKB_CNTL (0xc883c000 + (0x83 << 2)) +#define P_HHI_VID_PLL_MOD_CNTL0 (0xc883c000 + (0x84 << 2)) +#define P_HHI_VID_PLL_MOD_LOW_TCNT (0xc883c000 + (0x85 << 2)) +#define P_HHI_VID_PLL_MOD_HIGH_TCNT (0xc883c000 + (0x86 << 2)) +#define P_HHI_VID_PLL_MOD_NOM_TCNT (0xc883c000 + (0x87 << 2)) +#define P_HHI_USB_CLK_CNTL (0xc883c000 + (0x88 << 2)) +#define P_HHI_32K_CLK_CNTL (0xc883c000 + (0x89 << 2)) +#define P_HHI_GEN_CLK_CNTL (0xc883c000 + (0x8a << 2)) +#define P_HHI_GEN_CLK_CNTL2 (0xc883c000 + (0x8b << 2)) +#define P_HHI_JTAG_CONFIG (0xc883c000 + (0x8e << 2)) +#define P_HHI_VAFE_CLKXTALIN_CNTL (0xc883c000 + (0x8f << 2)) +#define P_HHI_VAFE_CLKOSCIN_CNTL (0xc883c000 + (0x90 << 2)) +#define P_HHI_VAFE_CLKIN_CNTL (0xc883c000 + (0x91 << 2)) +#define P_HHI_TVFE_AUTOMODE_CLK_CNTL (0xc883c000 + (0x92 << 2)) +#define P_HHI_VAFE_CLKPI_CNTL (0xc883c000 + (0x93 << 2)) +#define P_HHI_VDIN_MEAS_CLK_CNTL (0xc883c000 + (0x94 << 2)) +#define P_HHI_PCM_CLK_CNTL (0xc883c000 + (0x96 << 2)) +#define P_HHI_NAND_CLK_CNTL (0xc883c000 + (0x97 << 2)) +#define P_HHI_ISP_LED_CLK_CNTL (0xc883c000 + (0x98 << 2)) +#define P_HHI_SD_EMMC_CLK_CNTL (0xc883c000 + (0x99 << 2)) +#define P_HHI_EDP_TX_PHY_CNTL0 (0xc883c000 + (0x9c << 2)) +#define P_HHI_EDP_TX_PHY_CNTL1 (0xc883c000 + (0x9d << 2)) +#define P_HHI_MPLL_CNTL (0xc883c000 + (0xa0 << 2)) +#define P_HHI_MPLL_CNTL2 (0xc883c000 + (0xa1 << 2)) +#define P_HHI_MPLL_CNTL3 (0xc883c000 + (0xa2 << 2)) +#define P_HHI_MPLL_CNTL4 (0xc883c000 + (0xa3 << 2)) +#define P_HHI_MPLL_CNTL5 (0xc883c000 + (0xa4 << 2)) +#define P_HHI_MPLL_CNTL6 (0xc883c000 + (0xa5 << 2)) +#define P_HHI_MPLL_CNTL7 (0xc883c000 + (0xa6 << 2)) +#define P_HHI_MPLL_CNTL8 (0xc883c000 + (0xa7 << 2)) +#define P_HHI_MPLL_CNTL9 (0xc883c000 + (0xa8 << 2)) +#define P_HHI_MPLL_CNTL10 (0xc883c000 + (0xa9 << 2)) +#define P_HHI_ADC_PLL_CNTL (0xc883c000 + (0xaa << 2)) +#define P_HHI_ADC_PLL_CNTL2 (0xc883c000 + (0xab << 2)) +#define P_HHI_ADC_PLL_CNTL3 (0xc883c000 + (0xac << 2)) +#define P_HHI_ADC_PLL_CNTL4 (0xc883c000 + (0xad << 2)) +#define P_HHI_ADC_PLL_CNTL_I (0xc883c000 + (0xae << 2)) +#define P_HHI_AUDCLK_PLL_CNTL (0xc883c000 + (0xb0 << 2)) +#define P_HHI_AUDCLK_PLL_CNTL2 (0xc883c000 + (0xb1 << 2)) +#define P_HHI_AUDCLK_PLL_CNTL3 (0xc883c000 + (0xb2 << 2)) +#define P_HHI_AUDCLK_PLL_CNTL4 (0xc883c000 + (0xb3 << 2)) +#define P_HHI_AUDCLK_PLL_CNTL5 (0xc883c000 + (0xb4 << 2)) +#define P_HHI_AUDCLK_PLL_CNTL6 (0xc883c000 + (0xb5 << 2)) +#define P_HHI_L2_DDR_CLK_CNTL (0xc883c000 + (0xb6 << 2)) +#define P_HHI_MPLL3_CNTL0 (0xc883c000 + (0xb8 << 2)) +#define P_HHI_MPLL3_CNTL1 (0xc883c000 + (0xb9 << 2)) +#define P_HHI_VDAC_CNTL0 (0xc883c000 + (0xbd << 2)) +#define P_HHI_VDAC_CNTL1 (0xc883c000 + (0xbe << 2)) +#define P_HHI_SYS_PLL_CNTL (0xc883c000 + (0xc0 << 2)) +#define P_HHI_SYS_PLL_CNTL2 (0xc883c000 + (0xc1 << 2)) +#define P_HHI_SYS_PLL_CNTL3 (0xc883c000 + (0xc2 << 2)) +#define P_HHI_SYS_PLL_CNTL4 (0xc883c000 + (0xc3 << 2)) +#define P_HHI_SYS_PLL_CNTL5 (0xc883c000 + (0xc4 << 2)) +#define P_HHI_DPLL_TOP_I (0xc883c000 + (0xc6 << 2)) +#define P_HHI_DPLL_TOP2_I (0xc883c000 + (0xc7 << 2)) +#define P_HHI_HDMI_PLL_CNTL (0xc883c000 + (0xc8 << 2)) +#define P_HHI_HDMI_PLL_CNTL2 (0xc883c000 + (0xc9 << 2)) +#define P_HHI_HDMI_PLL_CNTL3 (0xc883c000 + (0xca << 2)) +#define P_HHI_HDMI_PLL_CNTL4 (0xc883c000 + (0xcb << 2)) +#define P_HHI_HDMI_PLL_CNTL5 (0xc883c000 + (0xcc << 2)) +#define P_HHI_HDMI_PLL_CNTL6 (0xc883c000 + (0xcd << 2)) +#define P_HHI_HDMI_PLL_CNTL_I (0xc883c000 + (0xce << 2)) +#define P_HHI_HDMI_PLL_CNTL7 (0xc883c000 + (0xcf << 2)) +#define P_HHI_DSI_LVDS_EDP_CNTL0 (0xc883c000 + (0xd1 << 2)) +#define P_HHI_DSI_LVDS_EDP_CNTL1 (0xc883c000 + (0xd2 << 2)) +#define P_HHI_CSI_PHY_CNTL0 (0xc883c000 + (0xd3 << 2)) +#define P_HHI_CSI_PHY_CNTL1 (0xc883c000 + (0xd4 << 2)) +#define P_HHI_CSI_PHY_CNTL2 (0xc883c000 + (0xd5 << 2)) +#define P_HHI_CSI_PHY_CNTL3 (0xc883c000 + (0xd6 << 2)) +#define P_HHI_CSI_PHY_CNTL4 (0xc883c000 + (0xd7 << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL0 (0xc883c000 + (0xd8 << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL1 (0xc883c000 + (0xd9 << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL2 (0xc883c000 + (0xda << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL3 (0xc883c000 + (0xdb << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL4 (0xc883c000 + (0xdc << 2)) +#define P_HHI_DIF_CSI_PHY_CNTL5 (0xc883c000 + (0xdd << 2)) +#define P_HHI_LVDS_TX_PHY_CNTL0 (0xc883c000 + (0xde << 2)) +#define P_HHI_LVDS_TX_PHY_CNTL1 (0xc883c000 + (0xdf << 2)) +#define P_HHI_VID2_PLL_CNTL (0xc883c000 + (0xe0 << 2)) +#define P_HHI_VID2_PLL_CNTL2 (0xc883c000 + (0xe1 << 2)) +#define P_HHI_VID2_PLL_CNTL3 (0xc883c000 + (0xe2 << 2)) +#define P_HHI_VID2_PLL_CNTL4 (0xc883c000 + (0xe3 << 2)) +#define P_HHI_VID2_PLL_CNTL5 (0xc883c000 + (0xe4 << 2)) +#define P_HHI_VID2_PLL_CNTL_I (0xc883c000 + (0xe5 << 2)) +#define P_HHI_HDMI_PHY_CNTL0 (0xc883c000 + (0xe8 << 2)) +#define P_HHI_HDMI_PHY_CNTL1 (0xc883c000 + (0xe9 << 2)) +#define P_HHI_HDMI_PHY_CNTL2 (0xc883c000 + (0xea << 2)) +#define P_HHI_HDMI_PHY_CNTL3 (0xc883c000 + (0xeb << 2)) +#define P_HHI_VID_LOCK_CLK_CNTL (0xc883c000 + (0xf2 << 2)) +#define P_HHI_ATV_DMD_SYS_CLK_CNTL (0xc883c000 + (0xf3 << 2)) +#define P_HHI_BT656_CLK_CNTL (0xc883c000 + (0xf5 << 2)) +#define P_HHI_SAR_CLK_CNTL (0xc883c000 + (0xf6 << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL (0xc883c000 + (0xf8 << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL2 (0xc883c000 + (0xf9 << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL3 (0xc883c000 + (0xfa << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL4 (0xc883c000 + (0xfb << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL5 (0xc883c000 + (0xfc << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL6 (0xc883c000 + (0xfd << 2)) +#define P_HHI_HDMIRX_AUD_PLL_CNTL_I (0xc883c000 + (0xfe << 2)) + +#define AIU_HDMI_CLK_DATA_CTRL 0x152a /* register.h:2466 */ +#define P_AIU_HDMI_CLK_DATA_CTRL CBUS_REG_ADDR(AIU_HDMI_CLK_DATA_CTRL) + +#define ISA_DEBUG_REG0 0x2600 +#define P_ISA_DEBUG_REG0 CBUS_REG_ADDR(ISA_DEBUG_REG0) + +#define VENC_DVI_SETTING 0x1b62 /* register.h:8014 */ +#define P_VENC_DVI_SETTING VCBUS_REG_ADDR(VENC_DVI_SETTING) + +#define VENC_VIDEO_TST_EN 0x1b70 +#define P_VENC_VIDEO_TST_EN VCBUS_REG_ADDR(VENC_VIDEO_TST_EN) +#define VENC_VIDEO_TST_MDSEL 0x1b71 +#define P_VENC_VIDEO_TST_MDSEL VCBUS_REG_ADDR(VENC_VIDEO_TST_MDSEL) +#define VENC_VIDEO_TST_Y 0x1b72 +#define P_VENC_VIDEO_TST_Y VCBUS_REG_ADDR(VENC_VIDEO_TST_Y) +#define VENC_VIDEO_TST_CB 0x1b73 +#define P_VENC_VIDEO_TST_CB VCBUS_REG_ADDR(VENC_VIDEO_TST_CB) +#define VENC_VIDEO_TST_CR 0x1b74 +#define P_VENC_VIDEO_TST_CR VCBUS_REG_ADDR(VENC_VIDEO_TST_CR) +#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75 +#define P_VENC_VIDEO_TST_CLRBAR_STRT VCBUS_REG_ADDR(VENC_VIDEO_TST_CLRBAR_STRT) +#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76 +#define P_VENC_VIDEO_TST_CLRBAR_WIDTH \ + VCBUS_REG_ADDR(VENC_VIDEO_TST_CLRBAR_WIDTH) +#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77 +#define P_VENC_VIDEO_TST_VDCNT_STSET VCBUS_REG_ADDR(VENC_VIDEO_TST_VDCNT_STSET) +#define VENC_VDAC_SETTING 0x1b7e +#define P_VENC_VDAC_SETTING VCBUS_REG_ADDR(VENC_VDAC_SETTING) +#define ENCP_VIDEO_EN 0x1b80 /* register.h:8078 */ +#define P_ENCP_VIDEO_EN VCBUS_REG_ADDR(ENCP_VIDEO_EN) +#define ENCP_VIDEO_SYNC_MODE 0x1b81 /* register.h:8079 */ +#define P_ENCP_VIDEO_SYNC_MODE VCBUS_REG_ADDR(ENCP_VIDEO_SYNC_MODE) +#define ENCP_MACV_EN 0x1b82 /* register.h:8080 */ +#define P_ENCP_MACV_EN VCBUS_REG_ADDR(ENCP_MACV_EN) +#define ENCP_VIDEO_Y_SCL 0x1b83 /* register.h:8081 */ +#define P_ENCP_VIDEO_Y_SCL VCBUS_REG_ADDR(ENCP_VIDEO_Y_SCL) +#define ENCP_VIDEO_PB_SCL 0x1b84 /* register.h:8082 */ +#define P_ENCP_VIDEO_PB_SCL VCBUS_REG_ADDR(ENCP_VIDEO_PB_SCL) +#define ENCP_VIDEO_PR_SCL 0x1b85 /* register.h:8083 */ +#define P_ENCP_VIDEO_PR_SCL VCBUS_REG_ADDR(ENCP_VIDEO_PR_SCL) +#define ENCP_VIDEO_SYNC_SCL 0x1b86 /* register.h:8084 */ +#define P_ENCP_VIDEO_SYNC_SCL VCBUS_REG_ADDR(ENCP_VIDEO_SYNC_SCL) +#define ENCP_VIDEO_MACV_SCL 0x1b87 /* register.h:8085 */ +#define P_ENCP_VIDEO_MACV_SCL VCBUS_REG_ADDR(ENCP_VIDEO_MACV_SCL) +#define ENCP_VIDEO_Y_OFFST 0x1b88 /* register.h:8086 */ +#define P_ENCP_VIDEO_Y_OFFST VCBUS_REG_ADDR(ENCP_VIDEO_Y_OFFST) +#define ENCP_VIDEO_PB_OFFST 0x1b89 /* register.h:8087 */ +#define P_ENCP_VIDEO_PB_OFFST VCBUS_REG_ADDR(ENCP_VIDEO_PB_OFFST) +#define ENCP_VIDEO_PR_OFFST 0x1b8a /* register.h:8088 */ +#define P_ENCP_VIDEO_PR_OFFST VCBUS_REG_ADDR(ENCP_VIDEO_PR_OFFST) +#define ENCP_VIDEO_SYNC_OFFST 0x1b8b /* register.h:8089 */ +#define P_ENCP_VIDEO_SYNC_OFFST VCBUS_REG_ADDR(ENCP_VIDEO_SYNC_OFFST) +#define ENCP_VIDEO_MACV_OFFST 0x1b8c /* register.h:8090 */ +#define P_ENCP_VIDEO_MACV_OFFST VCBUS_REG_ADDR(ENCP_VIDEO_MACV_OFFST) +#define ENCP_VIDEO_MODE 0x1b8d /* register.h:8092 */ +#define P_ENCP_VIDEO_MODE VCBUS_REG_ADDR(ENCP_VIDEO_MODE) +#define ENCP_VIDEO_MODE_ADV 0x1b8e /* register.h:8093 */ +#define P_ENCP_VIDEO_MODE_ADV VCBUS_REG_ADDR(ENCP_VIDEO_MODE_ADV) +#define ENCP_DBG_PX_RST 0x1b90 /* register.h:8095 */ +#define P_ENCP_DBG_PX_RST VCBUS_REG_ADDR(ENCP_DBG_PX_RST) +#define ENCP_DBG_LN_RST 0x1b91 /* register.h:8096 */ +#define P_ENCP_DBG_LN_RST VCBUS_REG_ADDR(ENCP_DBG_LN_RST) +#define ENCP_DBG_PX_INT 0x1b92 /* register.h:8097 */ +#define P_ENCP_DBG_PX_INT VCBUS_REG_ADDR(ENCP_DBG_PX_INT) +#define ENCP_DBG_LN_INT 0x1b93 /* register.h:8098 */ +#define P_ENCP_DBG_LN_INT VCBUS_REG_ADDR(ENCP_DBG_LN_INT) +#define ENCP_VIDEO_YFP1_HTIME 0x1b94 /* register.h:8100 */ +#define P_ENCP_VIDEO_YFP1_HTIME VCBUS_REG_ADDR(ENCP_VIDEO_YFP1_HTIME) +#define ENCP_VIDEO_YFP2_HTIME 0x1b95 /* register.h:8101 */ +#define P_ENCP_VIDEO_YFP2_HTIME VCBUS_REG_ADDR(ENCP_VIDEO_YFP2_HTIME) +#define ENCP_VIDEO_YC_DLY 0x1b96 /* register.h:8102 */ +#define P_ENCP_VIDEO_YC_DLY VCBUS_REG_ADDR(ENCP_VIDEO_YC_DLY) +#define ENCP_VIDEO_MAX_PXCNT 0x1b97 /* register.h:8103 */ +#define P_ENCP_VIDEO_MAX_PXCNT VCBUS_REG_ADDR(ENCP_VIDEO_MAX_PXCNT) +#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98 /* register.h:8104 */ +#define P_ENCP_VIDEO_HSPULS_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_HSPULS_BEGIN) +#define ENCP_VIDEO_HSPULS_END 0x1b99 /* register.h:8105 */ +#define P_ENCP_VIDEO_HSPULS_END VCBUS_REG_ADDR(ENCP_VIDEO_HSPULS_END) +#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a /* register.h:8106 */ +#define P_ENCP_VIDEO_HSPULS_SWITCH VCBUS_REG_ADDR(ENCP_VIDEO_HSPULS_SWITCH) +#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b /* register.h:8107 */ +#define P_ENCP_VIDEO_VSPULS_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_VSPULS_BEGIN) +#define ENCP_VIDEO_VSPULS_END 0x1b9c /* register.h:8108 */ +#define P_ENCP_VIDEO_VSPULS_END VCBUS_REG_ADDR(ENCP_VIDEO_VSPULS_END) +#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d /* register.h:8109 */ +#define P_ENCP_VIDEO_VSPULS_BLINE VCBUS_REG_ADDR(ENCP_VIDEO_VSPULS_BLINE) +#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e /* register.h:8110 */ +#define P_ENCP_VIDEO_VSPULS_ELINE VCBUS_REG_ADDR(ENCP_VIDEO_VSPULS_ELINE) +#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f /* register.h:8111 */ +#define P_ENCP_VIDEO_EQPULS_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_EQPULS_BEGIN) +#define ENCP_VIDEO_EQPULS_END 0x1ba0 /* register.h:8112 */ +#define P_ENCP_VIDEO_EQPULS_END VCBUS_REG_ADDR(ENCP_VIDEO_EQPULS_END) +#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1 /* register.h:8113 */ +#define P_ENCP_VIDEO_EQPULS_BLINE VCBUS_REG_ADDR(ENCP_VIDEO_EQPULS_BLINE) +#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2 /* register.h:8114 */ +#define P_ENCP_VIDEO_EQPULS_ELINE VCBUS_REG_ADDR(ENCP_VIDEO_EQPULS_ELINE) +#define ENCP_VIDEO_HAVON_END 0x1ba3 /* register.h:8115 */ +#define P_ENCP_VIDEO_HAVON_END VCBUS_REG_ADDR(ENCP_VIDEO_HAVON_END) +#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4 /* register.h:8116 */ +#define P_ENCP_VIDEO_HAVON_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_HAVON_BEGIN) +#define ENCP_VIDEO_VAVON_ELINE 0x1baf /* register.h:8117 */ +#define P_ENCP_VIDEO_VAVON_ELINE VCBUS_REG_ADDR(ENCP_VIDEO_VAVON_ELINE) +#define ENCP_VIDEO_VAVON_BLINE 0x1ba6 /* register.h:8118 */ +#define P_ENCP_VIDEO_VAVON_BLINE VCBUS_REG_ADDR(ENCP_VIDEO_VAVON_BLINE) +#define ENCP_VIDEO_HSO_BEGIN 0x1ba7 /* register.h:8119 */ +#define P_ENCP_VIDEO_HSO_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_HSO_BEGIN) +#define ENCP_VIDEO_HSO_END 0x1ba8 /* register.h:8120 */ +#define P_ENCP_VIDEO_HSO_END VCBUS_REG_ADDR(ENCP_VIDEO_HSO_END) +#define ENCP_VIDEO_VSO_BEGIN 0x1ba9 /* register.h:8121 */ +#define P_ENCP_VIDEO_VSO_BEGIN VCBUS_REG_ADDR(ENCP_VIDEO_VSO_BEGIN) +#define ENCP_VIDEO_VSO_END 0x1baa /* register.h:8122 */ +#define P_ENCP_VIDEO_VSO_END VCBUS_REG_ADDR(ENCP_VIDEO_VSO_END) +#define ENCP_VIDEO_VSO_BLINE 0x1bab /* register.h:8123 */ +#define P_ENCP_VIDEO_VSO_BLINE VCBUS_REG_ADDR(ENCP_VIDEO_VSO_BLINE) +#define ENCP_VIDEO_VSO_ELINE 0x1bac /* register.h:8124 */ +#define P_ENCP_VIDEO_VSO_ELINE VCBUS_REG_ADDR(ENCP_VIDEO_VSO_ELINE) +#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad /* register.h:8125 */ +#define P_ENCP_VIDEO_SYNC_WAVE_CURVE VCBUS_REG_ADDR(ENCP_VIDEO_SYNC_WAVE_CURVE) +#define ENCP_VIDEO_MAX_LNCNT 0x1bae /* register.h:8126 */ +#define P_ENCP_VIDEO_MAX_LNCNT VCBUS_REG_ADDR(ENCP_VIDEO_MAX_LNCNT) +#define ENCP_VIDEO_SY_VAL 0x1bb0 /* register.h:8127 */ +#define P_ENCP_VIDEO_SY_VAL VCBUS_REG_ADDR(ENCP_VIDEO_SY_VAL) +#define ENCP_VIDEO_SY2_VAL 0x1bb1 /* register.h:8128 */ +#define P_ENCP_VIDEO_SY2_VAL VCBUS_REG_ADDR(ENCP_VIDEO_SY2_VAL) +#define ENCP_VIDEO_BLANKY_VAL 0x1bb2 /* register.h:8129 */ +#define P_ENCP_VIDEO_BLANKY_VAL VCBUS_REG_ADDR(ENCP_VIDEO_BLANKY_VAL) +#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3 /* register.h:8130 */ +#define P_ENCP_VIDEO_BLANKPB_VAL VCBUS_REG_ADDR(ENCP_VIDEO_BLANKPB_VAL) +#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4 /* register.h:8131 */ +#define P_ENCP_VIDEO_BLANKPR_VAL VCBUS_REG_ADDR(ENCP_VIDEO_BLANKPR_VAL) +#define ENCP_VIDEO_HOFFST 0x1bb5 /* register.h:8132 */ +#define P_ENCP_VIDEO_HOFFST VCBUS_REG_ADDR(ENCP_VIDEO_HOFFST) +#define ENCP_VIDEO_VOFFST 0x1bb6 /* register.h:8133 */ +#define P_ENCP_VIDEO_VOFFST VCBUS_REG_ADDR(ENCP_VIDEO_VOFFST) +#define ENCP_VIDEO_RGB_CTRL 0x1bb7 /* register.h:8134 */ +#define P_ENCP_VIDEO_RGB_CTRL VCBUS_REG_ADDR(ENCP_VIDEO_RGB_CTRL) +#define ENCP_VIDEO_FILT_CTRL 0x1bb8 /* register.h:8135 */ +#define P_ENCP_VIDEO_FILT_CTRL VCBUS_REG_ADDR(ENCP_VIDEO_FILT_CTRL) +#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9 /* register.h:8136 */ +#define P_ENCP_VIDEO_OFLD_VPEQ_OFST VCBUS_REG_ADDR(ENCP_VIDEO_OFLD_VPEQ_OFST) +#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba /* register.h:8137 */ +#define P_ENCP_VIDEO_OFLD_VOAV_OFST VCBUS_REG_ADDR(ENCP_VIDEO_OFLD_VOAV_OFST) +#define ENCP_VIDEO_MATRIX_CB 0x1bbb /* register.h:8138 */ +#define P_ENCP_VIDEO_MATRIX_CB VCBUS_REG_ADDR(ENCP_VIDEO_MATRIX_CB) +#define ENCP_VIDEO_MATRIX_CR 0x1bbc /* register.h:8139 */ +#define P_ENCP_VIDEO_MATRIX_CR VCBUS_REG_ADDR(ENCP_VIDEO_MATRIX_CR) +#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd /* register.h:8140 */ +#define P_ENCP_VIDEO_RGBIN_CTRL VCBUS_REG_ADDR(ENCP_VIDEO_RGBIN_CTRL) +#define ENCP_MACV_BLANKY_VAL 0x1bc0 /* register.h:8142 */ +#define P_ENCP_MACV_BLANKY_VAL VCBUS_REG_ADDR(ENCP_MACV_BLANKY_VAL) +#define ENCP_MACV_MAXY_VAL 0x1bc1 /* register.h:8143 */ +#define P_ENCP_MACV_MAXY_VAL VCBUS_REG_ADDR(ENCP_MACV_MAXY_VAL) +#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2 /* register.h:8144 */ +#define P_ENCP_MACV_1ST_PSSYNC_STRT VCBUS_REG_ADDR(ENCP_MACV_1ST_PSSYNC_STRT) +#define ENCP_MACV_PSSYNC_STRT 0x1bc3 /* register.h:8145 */ +#define P_ENCP_MACV_PSSYNC_STRT VCBUS_REG_ADDR(ENCP_MACV_PSSYNC_STRT) +#define ENCP_MACV_AGC_STRT 0x1bc4 /* register.h:8146 */ +#define P_ENCP_MACV_AGC_STRT VCBUS_REG_ADDR(ENCP_MACV_AGC_STRT) +#define ENCP_MACV_AGC_END 0x1bc5 /* register.h:8147 */ +#define P_ENCP_MACV_AGC_END VCBUS_REG_ADDR(ENCP_MACV_AGC_END) +#define ENCP_MACV_WAVE_END 0x1bc6 /* register.h:8148 */ +#define P_ENCP_MACV_WAVE_END VCBUS_REG_ADDR(ENCP_MACV_WAVE_END) +#define ENCP_MACV_STRTLINE 0x1bc7 /* register.h:8149 */ +#define P_ENCP_MACV_STRTLINE VCBUS_REG_ADDR(ENCP_MACV_STRTLINE) +#define ENCP_MACV_ENDLINE 0x1bc8 /* register.h:8150 */ +#define P_ENCP_MACV_ENDLINE VCBUS_REG_ADDR(ENCP_MACV_ENDLINE) +#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9 /* register.h:8151 */ +#define P_ENCP_MACV_TS_CNT_MAX_L VCBUS_REG_ADDR(ENCP_MACV_TS_CNT_MAX_L) +#define ENCP_MACV_TS_CNT_MAX_H 0x1bca /* register.h:8152 */ +#define P_ENCP_MACV_TS_CNT_MAX_H VCBUS_REG_ADDR(ENCP_MACV_TS_CNT_MAX_H) +#define ENCP_MACV_TIME_DOWN 0x1bcb /* register.h:8153 */ +#define P_ENCP_MACV_TIME_DOWN VCBUS_REG_ADDR(ENCP_MACV_TIME_DOWN) +#define ENCP_MACV_TIME_LO 0x1bcc /* register.h:8154 */ +#define P_ENCP_MACV_TIME_LO VCBUS_REG_ADDR(ENCP_MACV_TIME_LO) +#define ENCP_MACV_TIME_UP 0x1bcd /* register.h:8155 */ +#define P_ENCP_MACV_TIME_UP VCBUS_REG_ADDR(ENCP_MACV_TIME_UP) +#define ENCP_MACV_TIME_RST 0x1bce /* register.h:8156 */ +#define P_ENCP_MACV_TIME_RST VCBUS_REG_ADDR(ENCP_MACV_TIME_RST) +#define ENCP_VBI_CTRL 0x1bd0 /* register.h:8158 */ +#define P_ENCP_VBI_CTRL VCBUS_REG_ADDR(ENCP_VBI_CTRL) +#define ENCP_VBI_SETTING 0x1bd1 /* register.h:8159 */ +#define P_ENCP_VBI_SETTING VCBUS_REG_ADDR(ENCP_VBI_SETTING) +#define ENCP_VBI_BEGIN 0x1bd2 /* register.h:8160 */ +#define P_ENCP_VBI_BEGIN VCBUS_REG_ADDR(ENCP_VBI_BEGIN) +#define ENCP_VBI_WIDTH 0x1bd3 /* register.h:8161 */ +#define P_ENCP_VBI_WIDTH VCBUS_REG_ADDR(ENCP_VBI_WIDTH) +#define ENCP_VBI_HVAL 0x1bd4 /* register.h:8162 */ +#define P_ENCP_VBI_HVAL VCBUS_REG_ADDR(ENCP_VBI_HVAL) +#define ENCP_VBI_DATA0 0x1bd5 /* register.h:8163 */ +#define P_ENCP_VBI_DATA0 VCBUS_REG_ADDR(ENCP_VBI_DATA0) +#define ENCP_VBI_DATA1 0x1bd6 /* register.h:8164 */ +#define P_ENCP_VBI_DATA1 VCBUS_REG_ADDR(ENCP_VBI_DATA1) + +#define ENCI_VIDEO_MODE 0x1b00 /* register.h:8185 */ +#define P_ENCI_VIDEO_MODE VCBUS_REG_ADDR(ENCI_VIDEO_MODE) +#define ENCI_VIDEO_MODE_ADV 0x1b01 /* register.h:8186 */ +#define P_ENCI_VIDEO_MODE_ADV VCBUS_REG_ADDR(ENCI_VIDEO_MODE_ADV) +#define ENCI_VIDEO_FSC_ADJ 0x1b02 /* register.h:8187 */ +#define P_ENCI_VIDEO_FSC_ADJ VCBUS_REG_ADDR(ENCI_VIDEO_FSC_ADJ) +#define ENCI_VIDEO_BRIGHT 0x1b03 /* register.h:8188 */ +#define P_ENCI_VIDEO_BRIGHT VCBUS_REG_ADDR(ENCI_VIDEO_BRIGHT) +#define ENCI_VIDEO_CONT 0x1b04 /* register.h:8189 */ +#define P_ENCI_VIDEO_CONT VCBUS_REG_ADDR(ENCI_VIDEO_CONT) +#define ENCI_VIDEO_SAT 0x1b05 /* register.h:8190 */ +#define P_ENCI_VIDEO_SAT VCBUS_REG_ADDR(ENCI_VIDEO_SAT) +#define ENCI_VIDEO_HUE 0x1b06 /* register.h:8191 */ +#define P_ENCI_VIDEO_HUE VCBUS_REG_ADDR(ENCI_VIDEO_HUE) +#define ENCI_VIDEO_SCH 0x1b07 /* register.h:8192 */ +#define P_ENCI_VIDEO_SCH VCBUS_REG_ADDR(ENCI_VIDEO_SCH) +#define ENCI_SYNC_MODE 0x1b08 /* register.h:8193 */ +#define P_ENCI_SYNC_MODE VCBUS_REG_ADDR(ENCI_SYNC_MODE) +#define ENCI_SYNC_CTRL 0x1b09 /* register.h:8194 */ +#define P_ENCI_SYNC_CTRL VCBUS_REG_ADDR(ENCI_SYNC_CTRL) +#define ENCI_SYNC_HSO_BEGIN 0x1b0a /* register.h:8195 */ +#define P_ENCI_SYNC_HSO_BEGIN VCBUS_REG_ADDR(ENCI_SYNC_HSO_BEGIN) +#define ENCI_SYNC_HSO_END 0x1b0b /* register.h:8196 */ +#define P_ENCI_SYNC_HSO_END VCBUS_REG_ADDR(ENCI_SYNC_HSO_END) +#define ENCI_SYNC_VSO_EVN 0x1b0c /* register.h:8197 */ +#define P_ENCI_SYNC_VSO_EVN VCBUS_REG_ADDR(ENCI_SYNC_VSO_EVN) +#define ENCI_SYNC_VSO_ODD 0x1b0d /* register.h:8198 */ +#define P_ENCI_SYNC_VSO_ODD VCBUS_REG_ADDR(ENCI_SYNC_VSO_ODD) +#define ENCI_SYNC_VSO_EVNLN 0x1b0e /* register.h:8199 */ +#define P_ENCI_SYNC_VSO_EVNLN VCBUS_REG_ADDR(ENCI_SYNC_VSO_EVNLN) +#define ENCI_SYNC_VSO_ODDLN 0x1b0f /* register.h:8200 */ +#define P_ENCI_SYNC_VSO_ODDLN VCBUS_REG_ADDR(ENCI_SYNC_VSO_ODDLN) +#define ENCI_SYNC_HOFFST 0x1b10 /* register.h:8201 */ +#define P_ENCI_SYNC_HOFFST VCBUS_REG_ADDR(ENCI_SYNC_HOFFST) +#define ENCI_SYNC_VOFFST 0x1b11 /* register.h:8202 */ +#define P_ENCI_SYNC_VOFFST VCBUS_REG_ADDR(ENCI_SYNC_VOFFST) +#define ENCI_SYNC_ADJ 0x1b12 /* register.h:8203 */ +#define P_ENCI_SYNC_ADJ VCBUS_REG_ADDR(ENCI_SYNC_ADJ) +#define ENCI_RGB_SETTING 0x1b13 /* register.h:8204 */ +#define P_ENCI_RGB_SETTING VCBUS_REG_ADDR(ENCI_RGB_SETTING) +#define ENCI_DE_H_BEGIN 0x1b16 /* register.h:8207 */ +#define P_ENCI_DE_H_BEGIN VCBUS_REG_ADDR(ENCI_DE_H_BEGIN) +#define ENCI_DE_H_END 0x1b17 /* register.h:8208 */ +#define P_ENCI_DE_H_END VCBUS_REG_ADDR(ENCI_DE_H_END) +#define ENCI_DE_V_BEGIN_EVEN 0x1b18 /* register.h:8209 */ +#define P_ENCI_DE_V_BEGIN_EVEN VCBUS_REG_ADDR(ENCI_DE_V_BEGIN_EVEN) +#define ENCI_DE_V_END_EVEN 0x1b19 /* register.h:8210 */ +#define P_ENCI_DE_V_END_EVEN VCBUS_REG_ADDR(ENCI_DE_V_END_EVEN) +#define ENCI_DE_V_BEGIN_ODD 0x1b1a /* register.h:8211 */ +#define P_ENCI_DE_V_BEGIN_ODD VCBUS_REG_ADDR(ENCI_DE_V_BEGIN_ODD) +#define ENCI_DE_V_END_ODD 0x1b1b /* register.h:8212 */ +#define P_ENCI_DE_V_END_ODD VCBUS_REG_ADDR(ENCI_DE_V_END_ODD) +#define ENCI_VBI_SETTING 0x1b20 /* register.h:8213 */ +#define P_ENCI_VBI_SETTING VCBUS_REG_ADDR(ENCI_VBI_SETTING) +#define ENCI_VBI_CCDT_EVN 0x1b21 /* register.h:8214 */ +#define P_ENCI_VBI_CCDT_EVN VCBUS_REG_ADDR(ENCI_VBI_CCDT_EVN) +#define ENCI_VBI_CCDT_ODD 0x1b22 /* register.h:8215 */ +#define P_ENCI_VBI_CCDT_ODD VCBUS_REG_ADDR(ENCI_VBI_CCDT_ODD) +#define ENCI_VBI_CC525_LN 0x1b23 /* register.h:8216 */ +#define P_ENCI_VBI_CC525_LN VCBUS_REG_ADDR(ENCI_VBI_CC525_LN) +#define ENCI_VBI_CC625_LN 0x1b24 /* register.h:8217 */ +#define P_ENCI_VBI_CC625_LN VCBUS_REG_ADDR(ENCI_VBI_CC625_LN) +#define ENCI_VBI_WSSDT 0x1b25 /* register.h:8218 */ +#define P_ENCI_VBI_WSSDT VCBUS_REG_ADDR(ENCI_VBI_WSSDT) +#define ENCI_VBI_WSS_LN 0x1b26 /* register.h:8219 */ +#define P_ENCI_VBI_WSS_LN VCBUS_REG_ADDR(ENCI_VBI_WSS_LN) +#define ENCI_VBI_CGMSDT_L 0x1b27 /* register.h:8220 */ +#define P_ENCI_VBI_CGMSDT_L VCBUS_REG_ADDR(ENCI_VBI_CGMSDT_L) +#define ENCI_VBI_CGMSDT_H 0x1b28 /* register.h:8221 */ +#define P_ENCI_VBI_CGMSDT_H VCBUS_REG_ADDR(ENCI_VBI_CGMSDT_H) +#define ENCI_VBI_CGMS_LN 0x1b29 /* register.h:8222 */ +#define P_ENCI_VBI_CGMS_LN VCBUS_REG_ADDR(ENCI_VBI_CGMS_LN) +#define ENCI_VBI_TTX_HTIME 0x1b2a /* register.h:8223 */ +#define P_ENCI_VBI_TTX_HTIME VCBUS_REG_ADDR(ENCI_VBI_TTX_HTIME) +#define ENCI_VBI_TTX_LN 0x1b2b /* register.h:8224 */ +#define P_ENCI_VBI_TTX_LN VCBUS_REG_ADDR(ENCI_VBI_TTX_LN) +#define ENCI_VBI_TTXDT0 0x1b2c /* register.h:8225 */ +#define P_ENCI_VBI_TTXDT0 VCBUS_REG_ADDR(ENCI_VBI_TTXDT0) +#define ENCI_VBI_TTXDT1 0x1b2d /* register.h:8226 */ +#define P_ENCI_VBI_TTXDT1 VCBUS_REG_ADDR(ENCI_VBI_TTXDT1) +#define ENCI_VBI_TTXDT2 0x1b2e /* register.h:8227 */ +#define P_ENCI_VBI_TTXDT2 VCBUS_REG_ADDR(ENCI_VBI_TTXDT2) +#define ENCI_VBI_TTXDT3 0x1b2f /* register.h:8228 */ +#define P_ENCI_VBI_TTXDT3 VCBUS_REG_ADDR(ENCI_VBI_TTXDT3) +#define ENCI_MACV_N0 0x1b30 /* register.h:8229 */ +#define P_ENCI_MACV_N0 VCBUS_REG_ADDR(ENCI_MACV_N0) +#define ENCI_MACV_N1 0x1b31 /* register.h:8230 */ +#define P_ENCI_MACV_N1 VCBUS_REG_ADDR(ENCI_MACV_N1) +#define ENCI_MACV_N2 0x1b32 /* register.h:8231 */ +#define P_ENCI_MACV_N2 VCBUS_REG_ADDR(ENCI_MACV_N2) +#define ENCI_MACV_N3 0x1b33 /* register.h:8232 */ +#define P_ENCI_MACV_N3 VCBUS_REG_ADDR(ENCI_MACV_N3) +#define ENCI_MACV_N4 0x1b34 /* register.h:8233 */ +#define P_ENCI_MACV_N4 VCBUS_REG_ADDR(ENCI_MACV_N4) +#define ENCI_MACV_N5 0x1b35 /* register.h:8234 */ +#define P_ENCI_MACV_N5 VCBUS_REG_ADDR(ENCI_MACV_N5) +#define ENCI_MACV_N6 0x1b36 /* register.h:8235 */ +#define P_ENCI_MACV_N6 VCBUS_REG_ADDR(ENCI_MACV_N6) +#define ENCI_MACV_N7 0x1b37 /* register.h:8236 */ +#define P_ENCI_MACV_N7 VCBUS_REG_ADDR(ENCI_MACV_N7) +#define ENCI_MACV_N8 0x1b38 /* register.h:8237 */ +#define P_ENCI_MACV_N8 VCBUS_REG_ADDR(ENCI_MACV_N8) +#define ENCI_MACV_N9 0x1b39 /* register.h:8238 */ +#define P_ENCI_MACV_N9 VCBUS_REG_ADDR(ENCI_MACV_N9) +#define ENCI_MACV_N10 0x1b3a /* register.h:8239 */ +#define P_ENCI_MACV_N10 VCBUS_REG_ADDR(ENCI_MACV_N10) +#define ENCI_MACV_N11 0x1b3b /* register.h:8240 */ +#define P_ENCI_MACV_N11 VCBUS_REG_ADDR(ENCI_MACV_N11) +#define ENCI_MACV_N12 0x1b3c /* register.h:8241 */ +#define P_ENCI_MACV_N12 VCBUS_REG_ADDR(ENCI_MACV_N12) +#define ENCI_MACV_N13 0x1b3d /* register.h:8242 */ +#define P_ENCI_MACV_N13 VCBUS_REG_ADDR(ENCI_MACV_N13) +#define ENCI_MACV_N14 0x1b3e /* register.h:8243 */ +#define P_ENCI_MACV_N14 VCBUS_REG_ADDR(ENCI_MACV_N14) +#define ENCI_MACV_N15 0x1b3f /* register.h:8244 */ +#define P_ENCI_MACV_N15 VCBUS_REG_ADDR(ENCI_MACV_N15) +#define ENCI_MACV_N16 0x1b40 /* register.h:8245 */ +#define P_ENCI_MACV_N16 VCBUS_REG_ADDR(ENCI_MACV_N16) +#define ENCI_MACV_N17 0x1b41 /* register.h:8246 */ +#define P_ENCI_MACV_N17 VCBUS_REG_ADDR(ENCI_MACV_N17) +#define ENCI_MACV_N18 0x1b42 /* register.h:8247 */ +#define P_ENCI_MACV_N18 VCBUS_REG_ADDR(ENCI_MACV_N18) +#define ENCI_MACV_N19 0x1b43 /* register.h:8248 */ +#define P_ENCI_MACV_N19 VCBUS_REG_ADDR(ENCI_MACV_N19) +#define ENCI_MACV_N20 0x1b44 /* register.h:8249 */ +#define P_ENCI_MACV_N20 VCBUS_REG_ADDR(ENCI_MACV_N20) +#define ENCI_MACV_N21 0x1b45 /* register.h:8250 */ +#define P_ENCI_MACV_N21 VCBUS_REG_ADDR(ENCI_MACV_N21) +#define ENCI_MACV_N22 0x1b46 /* register.h:8251 */ +#define P_ENCI_MACV_N22 VCBUS_REG_ADDR(ENCI_MACV_N22) +#define ENCI_DBG_PX_RST 0x1b48 /* register.h:8253 */ +#define P_ENCI_DBG_PX_RST VCBUS_REG_ADDR(ENCI_DBG_PX_RST) +#define ENCI_DBG_FLDLN_RST 0x1b49 /* register.h:8254 */ +#define P_ENCI_DBG_FLDLN_RST VCBUS_REG_ADDR(ENCI_DBG_FLDLN_RST) +#define ENCI_DBG_PX_INT 0x1b4a /* register.h:8255 */ +#define P_ENCI_DBG_PX_INT VCBUS_REG_ADDR(ENCI_DBG_PX_INT) +#define ENCI_DBG_FLDLN_INT 0x1b4b /* register.h:8256 */ +#define P_ENCI_DBG_FLDLN_INT VCBUS_REG_ADDR(ENCI_DBG_FLDLN_INT) +#define ENCI_DBG_MAXPX 0x1b4c /* register.h:8257 */ +#define P_ENCI_DBG_MAXPX VCBUS_REG_ADDR(ENCI_DBG_MAXPX) +#define ENCI_DBG_MAXLN 0x1b4d /* register.h:8258 */ +#define P_ENCI_DBG_MAXLN VCBUS_REG_ADDR(ENCI_DBG_MAXLN) +#define ENCI_MACV_MAX_AMP 0x1b50 /* register.h:8259 */ +#define P_ENCI_MACV_MAX_AMP VCBUS_REG_ADDR(ENCI_MACV_MAX_AMP) +#define ENCI_MACV_PULSE_LO 0x1b51 /* register.h:8260 */ +#define P_ENCI_MACV_PULSE_LO VCBUS_REG_ADDR(ENCI_MACV_PULSE_LO) +#define ENCI_MACV_PULSE_HI 0x1b52 /* register.h:8261 */ +#define P_ENCI_MACV_PULSE_HI VCBUS_REG_ADDR(ENCI_MACV_PULSE_HI) +#define ENCI_MACV_BKP_MAX 0x1b53 /* register.h:8262 */ +#define P_ENCI_MACV_BKP_MAX VCBUS_REG_ADDR(ENCI_MACV_BKP_MAX) +#define ENCI_CFILT_CTRL 0x1b54 /* register.h:8263 */ +#define P_ENCI_CFILT_CTRL VCBUS_REG_ADDR(ENCI_CFILT_CTRL) +#define ENCI_CFILT7 0x1b55 /* register.h:8264 */ +#define P_ENCI_CFILT7 VCBUS_REG_ADDR(ENCI_CFILT7) +#define ENCI_YC_DELAY 0x1b56 /* register.h:8265 */ +#define P_ENCI_YC_DELAY VCBUS_REG_ADDR(ENCI_YC_DELAY) +#define ENCI_VIDEO_EN 0x1b57 /* register.h:8266 */ +#define P_ENCI_VIDEO_EN VCBUS_REG_ADDR(ENCI_VIDEO_EN) +#define VENC_VIDEO_PROG_MODE 0x1b68 /* /../ucode/register.h:8023 */ +#define P_VENC_VIDEO_PROG_MODE VCBUS_REG_ADDR(VENC_VIDEO_PROG_MODE) + +#define ENCI_DVI_HSO_BEGIN 0x1c00 /* register.h:8280 */ +#define P_ENCI_DVI_HSO_BEGIN VCBUS_REG_ADDR(ENCI_DVI_HSO_BEGIN) +#define ENCI_DVI_HSO_END 0x1c01 /* register.h:8281 */ +#define P_ENCI_DVI_HSO_END VCBUS_REG_ADDR(ENCI_DVI_HSO_END) +#define ENCI_DVI_VSO_BLINE_EVN 0x1c02 /* register.h:8282 */ +#define P_ENCI_DVI_VSO_BLINE_EVN VCBUS_REG_ADDR(ENCI_DVI_VSO_BLINE_EVN) +#define ENCI_DVI_VSO_BLINE_ODD 0x1c03 /* register.h:8283 */ +#define P_ENCI_DVI_VSO_BLINE_ODD VCBUS_REG_ADDR(ENCI_DVI_VSO_BLINE_ODD) +#define ENCI_DVI_VSO_ELINE_EVN 0x1c04 /* register.h:8284 */ +#define P_ENCI_DVI_VSO_ELINE_EVN VCBUS_REG_ADDR(ENCI_DVI_VSO_ELINE_EVN) +#define ENCI_DVI_VSO_ELINE_ODD 0x1c05 /* register.h:8285 */ +#define P_ENCI_DVI_VSO_ELINE_ODD VCBUS_REG_ADDR(ENCI_DVI_VSO_ELINE_ODD) +#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06 /* register.h:8286 */ +#define P_ENCI_DVI_VSO_BEGIN_EVN VCBUS_REG_ADDR(ENCI_DVI_VSO_BEGIN_EVN) +#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07 /* register.h:8287 */ +#define P_ENCI_DVI_VSO_BEGIN_ODD VCBUS_REG_ADDR(ENCI_DVI_VSO_BEGIN_ODD) +#define ENCI_DVI_VSO_END_EVN 0x1c08 /* register.h:8288 */ +#define P_ENCI_DVI_VSO_END_EVN VCBUS_REG_ADDR(ENCI_DVI_VSO_END_EVN) +#define ENCI_DVI_VSO_END_ODD 0x1c09 /* register.h:8289 */ +#define P_ENCI_DVI_VSO_END_ODD VCBUS_REG_ADDR(ENCI_DVI_VSO_END_ODD) +#define ENCI_CFILT_CTRL2 0x1c0a /* register.h:8295 */ +#define P_ENCI_CFILT_CTRL2 VCBUS_REG_ADDR(ENCI_CFILT_CTRL2) +#define ENCI_DACSEL_0 0x1c0b /* register.h:8296 */ +#define P_ENCI_DACSEL_0 VCBUS_REG_ADDR(ENCI_DACSEL_0) +#define ENCI_DACSEL_1 0x1c0c /* register.h:8297 */ +#define P_ENCI_DACSEL_1 VCBUS_REG_ADDR(ENCI_DACSEL_1) +#define ENCP_DACSEL_0 0x1c0d /* register.h:8298 */ +#define P_ENCP_DACSEL_0 VCBUS_REG_ADDR(ENCP_DACSEL_0) +#define ENCP_DACSEL_1 0x1c0e /* register.h:8299 */ +#define P_ENCP_DACSEL_1 VCBUS_REG_ADDR(ENCP_DACSEL_1) +#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f /* register.h:8300 */ +#define P_ENCP_MAX_LINE_SWITCH_POINT VCBUS_REG_ADDR(ENCP_MAX_LINE_SWITCH_POINT) +#define ENCI_TST_EN 0x1c10 /* register.h:8301 */ +#define P_ENCI_TST_EN VCBUS_REG_ADDR(ENCI_TST_EN) +#define ENCI_TST_MDSEL 0x1c11 /* register.h:8302 */ +#define P_ENCI_TST_MDSEL VCBUS_REG_ADDR(ENCI_TST_MDSEL) +#define ENCI_TST_Y 0x1c12 /* register.h:8303 */ +#define P_ENCI_TST_Y VCBUS_REG_ADDR(ENCI_TST_Y) +#define ENCI_TST_CB 0x1c13 /* register.h:8304 */ +#define P_ENCI_TST_CB VCBUS_REG_ADDR(ENCI_TST_CB) +#define ENCI_TST_CR 0x1c14 /* register.h:8305 */ +#define P_ENCI_TST_CR VCBUS_REG_ADDR(ENCI_TST_CR) +#define ENCI_TST_CLRBAR_STRT 0x1c15 /* register.h:8306 */ +#define P_ENCI_TST_CLRBAR_STRT VCBUS_REG_ADDR(ENCI_TST_CLRBAR_STRT) +#define ENCI_TST_CLRBAR_WIDTH 0x1c16 /* register.h:8307 */ +#define P_ENCI_TST_CLRBAR_WIDTH VCBUS_REG_ADDR(ENCI_TST_CLRBAR_WIDTH) +#define ENCI_TST_VDCNT_STSET 0x1c17 /* register.h:8308 */ +#define P_ENCI_TST_VDCNT_STSET VCBUS_REG_ADDR(ENCI_TST_VDCNT_STSET) +#define ENCI_VFIFO2VD_CTL 0x1c18 /* register.h:8313 */ +#define P_ENCI_VFIFO2VD_CTL VCBUS_REG_ADDR(ENCI_VFIFO2VD_CTL) +#define ENCI_VFIFO2VD_PIXEL_START 0x1c19 /* register.h:8315 */ +#define P_ENCI_VFIFO2VD_PIXEL_START \ + VCBUS_REG_ADDR(ENCI_VFIFO2VD_PIXEL_START) +#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a /* register.h:8317 */ +#define P_ENCI_VFIFO2VD_PIXEL_END VCBUS_REG_ADDR(ENCI_VFIFO2VD_PIXEL_END) +#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b /* register.h:8319 */ +#define P_ENCI_VFIFO2VD_LINE_TOP_START \ + VCBUS_REG_ADDR(ENCI_VFIFO2VD_LINE_TOP_START) +#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c /* register.h:8321 */ +#define P_ENCI_VFIFO2VD_LINE_TOP_END \ + VCBUS_REG_ADDR(ENCI_VFIFO2VD_LINE_TOP_END) +#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d /* register.h:8323 */ +#define P_ENCI_VFIFO2VD_LINE_BOT_START \ + VCBUS_REG_ADDR(ENCI_VFIFO2VD_LINE_BOT_START) +#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e /* register.h:8325 */ +#define P_ENCI_VFIFO2VD_LINE_BOT_END \ + VCBUS_REG_ADDR(ENCI_VFIFO2VD_LINE_BOT_END) +#define ENCI_VFIFO2VD_CTL2 0x1c1f /* register.h:8326 */ +#define P_ENCI_VFIFO2VD_CTL2 VCBUS_REG_ADDR(ENCI_VFIFO2VD_CTL2) + +#define ENCP_DVI_HSO_BEGIN 0x1c30 /* register.h:8354 */ +#define P_ENCP_DVI_HSO_BEGIN VCBUS_REG_ADDR(ENCP_DVI_HSO_BEGIN) +#define ENCP_DVI_HSO_END 0x1c31 /* register.h:8355 */ +#define P_ENCP_DVI_HSO_END VCBUS_REG_ADDR(ENCP_DVI_HSO_END) +#define ENCP_DVI_VSO_BLINE_EVN 0x1c32 /* register.h:8356 */ +#define P_ENCP_DVI_VSO_BLINE_EVN VCBUS_REG_ADDR(ENCP_DVI_VSO_BLINE_EVN) +#define ENCP_DVI_VSO_BLINE_ODD 0x1c33 /* register.h:8357 */ +#define P_ENCP_DVI_VSO_BLINE_ODD VCBUS_REG_ADDR(ENCP_DVI_VSO_BLINE_ODD) +#define ENCP_DVI_VSO_ELINE_EVN 0x1c34 /* register.h:8358 */ +#define P_ENCP_DVI_VSO_ELINE_EVN VCBUS_REG_ADDR(ENCP_DVI_VSO_ELINE_EVN) +#define ENCP_DVI_VSO_ELINE_ODD 0x1c35 /* register.h:8359 */ +#define P_ENCP_DVI_VSO_ELINE_ODD VCBUS_REG_ADDR(ENCP_DVI_VSO_ELINE_ODD) +#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36 /* register.h:8360 */ +#define P_ENCP_DVI_VSO_BEGIN_EVN VCBUS_REG_ADDR(ENCP_DVI_VSO_BEGIN_EVN) +#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37 /* register.h:8361 */ +#define P_ENCP_DVI_VSO_BEGIN_ODD VCBUS_REG_ADDR(ENCP_DVI_VSO_BEGIN_ODD) +#define ENCP_DVI_VSO_END_EVN 0x1c38 /* register.h:8362 */ +#define P_ENCP_DVI_VSO_END_EVN VCBUS_REG_ADDR(ENCP_DVI_VSO_END_EVN) +#define ENCP_DVI_VSO_END_ODD 0x1c39 /* register.h:8363 */ +#define P_ENCP_DVI_VSO_END_ODD VCBUS_REG_ADDR(ENCP_DVI_VSO_END_ODD) +#define ENCP_DE_H_BEGIN 0x1c3a /* register.h:8364 */ +#define P_ENCP_DE_H_BEGIN VCBUS_REG_ADDR(ENCP_DE_H_BEGIN) +#define ENCP_DE_H_END 0x1c3b /* register.h:8365 */ +#define P_ENCP_DE_H_END VCBUS_REG_ADDR(ENCP_DE_H_END) +#define ENCP_DE_V_BEGIN_EVEN 0x1c3c /* register.h:8366 */ +#define P_ENCP_DE_V_BEGIN_EVEN VCBUS_REG_ADDR(ENCP_DE_V_BEGIN_EVEN) +#define ENCP_DE_V_END_EVEN 0x1c3d /* register.h:8367 */ +#define P_ENCP_DE_V_END_EVEN VCBUS_REG_ADDR(ENCP_DE_V_END_EVEN) +#define ENCP_DE_V_BEGIN_ODD 0x1c3e /* register.h:8368 */ +#define P_ENCP_DE_V_BEGIN_ODD VCBUS_REG_ADDR(ENCP_DE_V_BEGIN_ODD) +#define ENCP_DE_V_END_ODD 0x1c3f /* register.h:8369 */ +#define P_ENCP_DE_V_END_ODD VCBUS_REG_ADDR(ENCP_DE_V_END_ODD) +#define ENCI_SYNC_LINE_LENGTH 0x1c40 /* register.h:8372 */ +#define P_ENCI_SYNC_LINE_LENGTH VCBUS_REG_ADDR(ENCI_SYNC_LINE_LENGTH) +#define ENCI_SYNC_PIXEL_EN 0x1c41 /* register.h:8375 */ +#define P_ENCI_SYNC_PIXEL_EN VCBUS_REG_ADDR(ENCI_SYNC_PIXEL_EN) +#define ENCI_SYNC_TO_LINE_EN 0x1c42 /* register.h:8382 */ +#define P_ENCI_SYNC_TO_LINE_EN VCBUS_REG_ADDR(ENCI_SYNC_TO_LINE_EN) +#define ENCI_SYNC_TO_PIXEL 0x1c43 /* register.h:8384 */ +#define P_ENCI_SYNC_TO_PIXEL VCBUS_REG_ADDR(ENCI_SYNC_TO_PIXEL) +#define ENCP_SYNC_LINE_LENGTH 0x1c44 /* register.h:8387 */ +#define P_ENCP_SYNC_LINE_LENGTH VCBUS_REG_ADDR(ENCP_SYNC_LINE_LENGTH) +#define ENCP_SYNC_PIXEL_EN 0x1c45 /* register.h:8390 */ +#define P_ENCP_SYNC_PIXEL_EN VCBUS_REG_ADDR(ENCP_SYNC_PIXEL_EN) +#define ENCP_SYNC_TO_LINE_EN 0x1c46 /* register.h:8397 */ +#define P_ENCP_SYNC_TO_LINE_EN VCBUS_REG_ADDR(ENCP_SYNC_TO_LINE_EN) +#define ENCP_SYNC_TO_PIXEL 0x1c47 /* register.h:8399 */ +#define P_ENCP_SYNC_TO_PIXEL VCBUS_REG_ADDR(ENCP_SYNC_TO_PIXEL) + +/* [3:2] cntl_viu2_sel_venc: 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. */ +/* [1:0] cntl_viu1_sel_venc: 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. */ +#define VPU_VIU_VENC_MUX_CTRL 0x271a /* register.h:9214 */ +#define P_VPU_VIU_VENC_MUX_CTRL VCBUS_REG_ADDR(VPU_VIU_VENC_MUX_CTRL) +#define VPU_HDMI_SETTING 0x271b /* register.h:9229 */ +#define P_VPU_HDMI_SETTING VCBUS_REG_ADDR(VPU_HDMI_SETTING) + +#define VPU_HDMI_DATA_OVR 0x2727 /* register.h:9270 */ +#define P_VPU_HDMI_DATA_OVR VCBUS_REG_ADDR(VPU_HDMI_DATA_OVR) +#define VPU_HDMI_FMT_CTRL 0x2743 +#define P_VPU_HDMI_FMT_CTRL VCBUS_REG_ADDR(VPU_HDMI_FMT_CTRL) +/* For GXM and later */ +#define VPU_HDMI_DITH_CNTL 0x27fc +#define P_VPU_HDMI_DITH_CNTL VCBUS_REG_ADDR(VPU_HDMI_DITH_CNTL) + +/* c_always_on_pointer.h:71 */ +#define AO_RTI_PULL_UP_REG ((0x00 << 10) | (0x0B << 2)) +#define P_AO_RTI_PULL_UP_REG AOBUS_REG_ADDR(AO_RTI_PULL_UP_REG) +#define AO_RTI_PIN_MUX_REG ((0x00 << 10) | (0x05 << 2)) +#define P_AO_RTI_PIN_MUX_REG AOBUS_REG_ADDR(AO_RTI_PIN_MUX_REG) +#define AO_RTI_PIN_MUX_REG2 ((0x00 << 10) | (0x06 << 2)) +#define P_AO_RTI_PIN_MUX_REG2 AOBUS_REG_ADDR(AO_RTI_PIN_MUX_REG2) +#define AO_CRT_CLK_CNTL1 ((0x00 << 10) | (0x1A << 2)) +#define P_AO_CRT_CLK_CNTL1 AOBUS_REG_ADDR(AO_CRT_CLK_CNTL1) +#define AO_DEBUG_REG0 ((0x00 << 10) | (0x28 << 2)) +#define P_AO_DEBUG_REG0 AOBUS_REG_ADDR(AO_DEBUG_REG0) +#define AO_DEBUG_REG1 ((0x00 << 10) | (0x29 << 2)) +#define P_AO_DEBUG_REG1 AOBUS_REG_ADDR(AO_DEBUG_REG1) +#define AO_DEBUG_REG2 ((0x00 << 10) | (0x2a << 2)) +#define P_AO_DEBUG_REG2 AOBUS_REG_ADDR(AO_DEBUG_REG2) +#define AO_DEBUG_REG3 ((0x00 << 10) | (0x2b << 2)) +#define P_AO_DEBUG_REG3 AOBUS_REG_ADDR(AO_DEBUG_REG3) + +#define P_AO_RTI_GEN_PWR_SLEEP0 (0xc8100000 + (0x3a << 2)) + +#define P_HDMITX_ADDR_PORT_SEC 0xda83a000 +#define P_HDMITX_DATA_PORT_SEC 0xda83a004 +#define P_HDMITX_CTRL_PORT_SEC 0xda83a008 +/* secure address P_HDMITX_ADDR_PORT 0xda83a000 */ +#define P_HDMITX_ADDR_PORT 0xc883a000 +#define P_HDMITX_DATA_PORT 0xc883a004 +#define P_HDMITX_CTRL_PORT 0xc883a008 + +#define P_ELP_ESM_HPI_REG_BASE 0xd0044000 +#endif diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c new file mode 100644 index 000000000000..6a0bf5f58f5d --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c @@ -0,0 +1,305 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mach_reg.h" +#include "hdmi_tx_reg.h" + +static int dbg_en; + +/* + * RePacket HDMI related registers rd/wr + */ +struct reg_map { + unsigned int phy_addr; + unsigned int size; + void __iomem *p; + int flag; +}; + +static struct reg_map reg_maps[] = { + { /* CBUS */ + .phy_addr = 0xc0800000, + .size = 0xa00000, + }, + { /* RESET */ + .phy_addr = 0xc1104400, + .size = 0x100, + }, + { /* RTI */ + .phy_addr = 0xc8100000, + .size = 0x100000, + }, + { /* PERIPHS */ + .phy_addr = 0xc8834000, + .size = 0x2000, + }, + { /* HDMITX NON-SECURE*/ + .phy_addr = 0xc883a000, + .size = 0x2000, + }, + { /* HIU */ + .phy_addr = 0xc883c000, + .size = 0x2000, + }, + { /* VPU */ + .phy_addr = 0xd0100000, + .size = 0x40000, + }, + { /* HDMITX SECURE */ + .phy_addr = 0xda83a000, + .size = 0x2000, + }, +}; + +static int in_reg_maps_idx(unsigned int addr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_maps); i++) { + if ((addr >= reg_maps[i].phy_addr) && + (addr < (reg_maps[i].phy_addr + reg_maps[i].size))) { + return i; + } + } + + return -1; +} + +static int check_map_flag(unsigned int addr) +{ + int idx; + + idx = in_reg_maps_idx(addr); + if ((idx != -1) && (reg_maps[idx].flag)) + return 1; + return 0; +} + +void init_reg_map(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_maps); i++) { + reg_maps[i].p = ioremap(reg_maps[i].phy_addr, reg_maps[i].size); + if (!reg_maps[i].p) { + pr_info("hdmitx20: failed Mapped PHY: 0x%x\n", + reg_maps[i].phy_addr); + } else { + reg_maps[i].flag = 1; + pr_info("hdmitx20: Mapped PHY: 0x%x\n", + reg_maps[i].phy_addr); + } + } +} + +unsigned int hd_read_reg(unsigned int addr) +{ + int ret = 0; + int idx = in_reg_maps_idx(addr); + unsigned int val = 0; + unsigned int type = (addr >> OFFSET); + unsigned int reg = addr & ((1 << OFFSET) - 1); + + if ((idx != -1) && check_map_flag(addr)) { + val = readl(reg_maps[idx].p + (addr - reg_maps[idx].phy_addr)); + goto end; + } + + ret = aml_reg_read(type, reg, &val); + + if (ret < 0) { + pr_info("Rd[0x%x] Error\n", addr); + return val; + } +end: + if (dbg_en) + pr_info("Rd[0x%x] 0x%x\n", addr, val); + return val; +} + +void hd_write_reg(unsigned int addr, unsigned int val) +{ + int ret = 0; + int idx = in_reg_maps_idx(addr); + unsigned int type = (addr >> OFFSET); + unsigned int reg = addr & ((1 << OFFSET) - 1); + + if ((idx != -1) && check_map_flag(addr)) { + writel(val, reg_maps[idx].p + (addr - reg_maps[idx].phy_addr)); + goto end; + } + + ret = aml_reg_write(type, reg, val); + + if (ret < 0) { + pr_info("Wr[0x%x] 0x%x Error\n", addr, val); + return; + } + +end: + if (dbg_en) + pr_info("Wr[0x%x] 0x%x\n", addr, val); +} + +void hd_set_reg_bits(unsigned int addr, unsigned int value, + unsigned int offset, unsigned int len) +{ + unsigned int data32 = 0; + + data32 = hd_read_reg(addr); + data32 &= ~(((1 << len) - 1) << offset); + data32 |= (value & ((1 << len) - 1)) << offset; + hd_write_reg(addr, data32); +} + +static DEFINE_SPINLOCK(reg_lock); +unsigned int hdmitx_rd_reg(unsigned int addr) +{ + unsigned int data = 0; + unsigned long offset = (addr & DWC_OFFSET_MASK) >> 24; + unsigned long flags, fiq_flag; + + if (addr & SEC_OFFSET) { + addr = addr & 0xffff; + sec_reg_write((unsigned int *)(unsigned long) + (P_HDMITX_ADDR_PORT_SEC + offset), addr); + sec_reg_write((unsigned int *)(unsigned long) + (P_HDMITX_ADDR_PORT_SEC + offset), addr); + data = sec_reg_read((unsigned int *)(unsigned long) + (P_HDMITX_DATA_PORT_SEC + offset)); + } else { + addr = addr & 0xffff; + spin_lock_irqsave(®_lock, flags); + raw_local_save_flags(fiq_flag); + local_fiq_disable(); + +/* + * If addr is located at 0x5020 ~ 0x667e in DWC, + * then should operate twice + */ + hd_write_reg(P_HDMITX_ADDR_PORT + offset, addr); + hd_write_reg(P_HDMITX_ADDR_PORT + offset, addr); + data = hd_read_reg(P_HDMITX_DATA_PORT + offset); + data = hd_read_reg(P_HDMITX_DATA_PORT + offset); + + raw_local_irq_restore(fiq_flag); + spin_unlock_irqrestore(®_lock, flags); + } + if (dbg_en) + pr_info("%s rd[0x%x] 0x%x\n", offset ? "DWC" : "TOP", + addr, data); + return data; +} + +void hdmitx_wr_reg(unsigned int addr, unsigned int data) +{ + unsigned long flags, fiq_flag; + unsigned long offset = (addr & DWC_OFFSET_MASK) >> 24; + + if (addr & SEC_OFFSET) { + addr = addr & 0xffff; + sec_reg_write((unsigned int *)(unsigned long) + (P_HDMITX_ADDR_PORT_SEC + offset), addr); + sec_reg_write((unsigned int *)(unsigned long) + (P_HDMITX_ADDR_PORT_SEC + offset), addr); + sec_reg_write((unsigned int *)(unsigned long) + (P_HDMITX_DATA_PORT_SEC + offset), data); + } else { + addr = addr & 0xffff; + spin_lock_irqsave(®_lock, flags); + raw_local_save_flags(fiq_flag); + local_fiq_disable(); + + hd_write_reg(P_HDMITX_ADDR_PORT + offset, addr); + hd_write_reg(P_HDMITX_ADDR_PORT + offset, addr); + hd_write_reg(P_HDMITX_DATA_PORT + offset, data); + raw_local_irq_restore(fiq_flag); + spin_unlock_irqrestore(®_lock, flags); + } + if (dbg_en) + pr_info("%s wr[0x%x] 0x%x\n", offset ? "DWC" : "TOP", + addr, data); +} + +void hdmitx_set_reg_bits(unsigned int addr, unsigned int value, + unsigned int offset, unsigned int len) +{ + unsigned int data32 = 0; + + data32 = hdmitx_rd_reg(addr); + data32 &= ~(((1 << len) - 1) << offset); + data32 |= (value & ((1 << len) - 1)) << offset; + hdmitx_wr_reg(addr, data32); +} + +void hdmitx_poll_reg(unsigned int addr, unsigned int val, unsigned long timeout) +{ + unsigned long time = 0; + + time = jiffies; + while ((!(hdmitx_rd_reg(addr) & val)) && + time_before(jiffies, time + timeout)) { + mdelay(2); + } + if (time_after(jiffies, time + timeout)) + pr_info("hdmitx poll:0x%x val:0x%x T1=%lu t=%lu T2=%lu timeout\n", + addr, val, time, timeout, jiffies); +} + +void hdmitx_rd_check_reg(unsigned int addr, unsigned int exp_data, + unsigned int mask) +{ + unsigned long rd_data; + + rd_data = hdmitx_rd_reg(addr); + if ((rd_data | mask) != (exp_data | mask)) { + pr_info("HDMITX-DWC addr=0x%04x rd_data=0x%02x\n", + (unsigned int)addr, (unsigned int)rd_data); + pr_info("Error: HDMITX-DWC exp_data=0x%02x mask=0x%02x\n", + (unsigned int)exp_data, (unsigned int)mask); + } +} + +void hdcp22_wr_reg(uint32_t addr, uint32_t data) +{ + sec_reg_write((unsigned int *)(unsigned long) + (P_ELP_ESM_HPI_REG_BASE + addr), data); +} + +uint32_t hdcp22_rd_reg(uint32_t addr) +{ + return (uint32_t)sec_reg_read((unsigned int *)(unsigned long) + (P_ELP_ESM_HPI_REG_BASE + addr)); +} + +MODULE_PARM_DESC(dbg_en, "\n debug_level\n"); +module_param(dbg_en, int, 0664); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c new file mode 100644 index 000000000000..7c15f5ced2b3 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c @@ -0,0 +1,60 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/sec_ops.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mach_reg.h" + +#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" + +void sec_reg_write(unsigned int *addr, unsigned int value) +{ + register long x0 asm("x0") = 0x82000019; + register long x1 asm("x1") = (unsigned long)addr; + register long x2 asm("x2") = value; + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + "smc #0\n" + : : "r"(x0), "r"(x1), "r"(x2) + ); +} + +unsigned int sec_reg_read(unsigned int *addr) +{ + register long x0 asm("x0") = 0x82000018; + register long x1 asm("x1") = (unsigned long)addr; + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + "smc #0\n" + : "+r"(x0) : "r"(x1) + ); + return (unsigned int)(x0&0xffffffff); +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h new file mode 100644 index 000000000000..a02bc53f7bb7 --- /dev/null +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h @@ -0,0 +1,21 @@ +/* + * drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/tvenc_conf.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include + +void set_vmode_enc_hw(enum hdmi_vic vic); +void set_vmode_3dfp_enc_hw(enum hdmi_vic vic); /* For 3D Frame Packing */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/enc_clk_config.h b/include/linux/amlogic/media/vout/hdmi_tx/enc_clk_config.h new file mode 100644 index 000000000000..9cbe50bdfc41 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/enc_clk_config.h @@ -0,0 +1,50 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/enc_clk_config.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __ENC_CLK_CONFIG_H__ +#define __ENC_CLK_CONFIG_H__ + +enum Viu_Type { + VIU_ENCL = 0, VIU_ENCI, VIU_ENCP, VIU_ENCT, +}; + +extern int set_viu_path(unsigned int viu_channel_sel, + enum Viu_Type viu_type_sel); +extern void set_enci_clk(unsigned int clk); +extern void set_encp_clk(unsigned int clk); +/* extern void set_vmode_clk(vmode_t mode); */ + +struct enc_clk_val { + enum vmode_e mode; + unsigned int hpll_clk_out; + unsigned int hpll_hdmi_od; + unsigned int hpll_lvds_od; + unsigned int viu_path; + enum Viu_Type viu_type; + unsigned int vid_pll_div; + unsigned int clk_final_div; + unsigned int hdmi_tx_pixel_div; + unsigned int encp_div; + unsigned int enci_div; + unsigned int enct_div; + unsigned int encl_div; + unsigned int vdac0_div; + unsigned int vdac1_div; + unsigned int unused; /* prevent compile error */ +}; + +#endif diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h new file mode 100644 index 000000000000..1cbd2059c003 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h @@ -0,0 +1,578 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMI_COMMON_H__ +#define __HDMI_COMMON_H__ + +#include + +/* HDMI VIC definitions */ + +/* HDMITX_VIC420_OFFSET and HDMITX_VIC_MASK are associated with + * VIC_MAX_VALID_MODE and VIC_MAX_NUM in hdmi_tx_module.h + */ +#define HDMITX_VIC420_OFFSET 0x100 +#define HDMITX_VIC420_FAKE_OFFSET 0x200 + +#define HDMITX_VIC_MASK 0xff + +enum hdmi_vic { + /* Refer to CEA 861-D */ + HDMI_Unknown = 0, + HDMI_640x480p60_4x3 = 1, + HDMI_720x480p60_4x3 = 2, + HDMI_720x480p60_16x9 = 3, + HDMI_1280x720p60_16x9 = 4, + HDMI_1920x1080i60_16x9 = 5, + HDMI_720x480i60_4x3 = 6, + HDMI_720x480i60_16x9 = 7, + HDMI_720x240p60_4x3 = 8, + HDMI_720x240p60_16x9 = 9, + HDMI_2880x480i60_4x3 = 10, + HDMI_2880x480i60_16x9 = 11, + HDMI_2880x240p60_4x3 = 12, + HDMI_2880x240p60_16x9 = 13, + HDMI_1440x480p60_4x3 = 14, + HDMI_1440x480p60_16x9 = 15, + HDMI_1920x1080p60_16x9 = 16, + HDMI_720x576p50_4x3 = 17, + HDMI_720x576p50_16x9 = 18, + HDMI_1280x720p50_16x9 = 19, + HDMI_1920x1080i50_16x9 = 20, + HDMI_720x576i50_4x3 = 21, + HDMI_720x576i50_16x9 = 22, + HDMI_720x288p_4x3 = 23, + HDMI_720x288p_16x9 = 24, + HDMI_2880x576i50_4x3 = 25, + HDMI_2880x576i50_16x9 = 26, + HDMI_2880x288p50_4x3 = 27, + HDMI_2880x288p50_16x9 = 28, + HDMI_1440x576p_4x3 = 29, + HDMI_1440x576p_16x9 = 30, + HDMI_1920x1080p50_16x9 = 31, + HDMI_1920x1080p24_16x9 = 32, + HDMI_1920x1080p25_16x9 = 33, + HDMI_1920x1080p30_16x9 = 34, + HDMI_2880x480p60_4x3 = 35, + HDMI_2880x480p60_16x9 = 36, + HDMI_2880x576p50_4x3 = 37, + HDMI_2880x576p50_16x9 = 38, + HDMI_1920x1080i_t1250_50_16x9 = 39, + HDMI_1920x1080i100_16x9 = 40, + HDMI_1280x720p100_16x9 = 41, + HDMI_720x576p100_4x3 = 42, + HDMI_720x576p100_16x9 = 43, + HDMI_720x576i100_4x3 = 44, + HDMI_720x576i100_16x9 = 45, + HDMI_1920x1080i120_16x9 = 46, + HDMI_1280x720p120_16x9 = 47, + HDMI_720x480p120_4x3 = 48, + HDMI_720x480p120_16x9 = 49, + HDMI_720x480i120_4x3 = 50, + HDMI_720x480i120_16x9 = 51, + HDMI_720x576p200_4x3 = 52, + HDMI_720x576p200_16x9 = 53, + HDMI_720x576i200_4x3 = 54, + HDMI_720x576i200_16x9 = 55, + HDMI_720x480p240_4x3 = 56, + HDMI_720x480p240_16x9 = 57, + HDMI_720x480i240_4x3 = 58, + HDMI_720x480i240_16x9 = 59, + /* Refet to CEA 861-F */ + HDMI_1280x720p24_16x9 = 60, + HDMI_1280x720p25_16x9 = 61, + HDMI_1280x720p30_16x9 = 62, + HDMI_1920x1080p120_16x9 = 63, + HDMI_1920x1080p100_16x9 = 64, + HDMI_1280x720p24_64x27 = 65, + HDMI_1280x720p25_64x27 = 66, + HDMI_1280x720p30_64x27 = 67, + HDMI_1280x720p50_64x27 = 68, + HDMI_1280x720p60_64x27 = 69, + HDMI_1280x720p100_64x27 = 70, + HDMI_1280x720p120_64x27 = 71, + HDMI_1920x1080p24_64x27 = 72, + HDMI_1920x1080p25_64x27 = 73, + HDMI_1920x1080p30_64x27 = 74, + HDMI_1920x1080p50_64x27 = 75, + HDMI_1920x1080p60_64x27 = 76, + HDMI_1920x1080p100_64x27 = 77, + HDMI_1920x1080p120_64x27 = 78, + HDMI_1680x720p24_64x27 = 79, + HDMI_1680x720p25_64x27 = 80, + HDMI_1680x720p30_64x27 = 81, + HDMI_1680x720p50_64x27 = 82, + HDMI_1680x720p60_64x27 = 83, + HDMI_1680x720p100_64x27 = 84, + HDMI_1680x720p120_64x27 = 85, + HDMI_2560x1080p24_64x27 = 86, + HDMI_2560x1080p25_64x27 = 87, + HDMI_2560x1080p30_64x27 = 88, + HDMI_2560x1080p50_64x27 = 89, + HDMI_2560x1080p60_64x27 = 90, + HDMI_2560x1080p100_64x27 = 91, + HDMI_2560x1080p120_64x27 = 92, + HDMI_3840x2160p24_16x9 = 93, + HDMI_3840x2160p25_16x9 = 94, + HDMI_3840x2160p30_16x9 = 95, + HDMI_3840x2160p50_16x9 = 96, + HDMI_3840x2160p60_16x9 = 97, + HDMI_4096x2160p24_256x135 = 98, + HDMI_4096x2160p25_256x135 = 99, + HDMI_4096x2160p30_256x135 = 100, + HDMI_4096x2160p50_256x135 = 101, + HDMI_4096x2160p60_256x135 = 102, + HDMI_3840x2160p24_64x27 = 103, + HDMI_3840x2160p25_64x27 = 104, + HDMI_3840x2160p30_64x27 = 105, + HDMI_3840x2160p50_64x27 = 106, + HDMI_3840x2160p60_64x27 = 107, + HDMI_RESERVED = 108, + HDMI_3840x1080p120hz = 109, + HDMI_3840x1080p100hz, + HDMI_3840x540p240hz, + HDMI_3840x540p200hz, + + /* + * the following vic is for those y420 mode + * they are all beyond OFFSET_HDMITX_VIC420(0x1000) + * and they has same vic with normal vic in the lower bytes. + */ + HDMI_VIC_Y420 = + HDMITX_VIC420_OFFSET, + HDMI_3840x2160p50_16x9_Y420 = + HDMITX_VIC420_OFFSET + HDMI_3840x2160p50_16x9, + HDMI_3840x2160p60_16x9_Y420 = + HDMITX_VIC420_OFFSET + HDMI_3840x2160p60_16x9, + HDMI_4096x2160p50_256x135_Y420 = + HDMITX_VIC420_OFFSET + HDMI_4096x2160p50_256x135, + HDMI_4096x2160p60_256x135_Y420 = + HDMITX_VIC420_OFFSET + HDMI_4096x2160p60_256x135, + HDMI_3840x2160p50_64x27_Y420 = + HDMITX_VIC420_OFFSET + HDMI_3840x2160p50_64x27, + HDMI_3840x2160p60_64x27_Y420 = + HDMITX_VIC420_OFFSET + HDMI_3840x2160p60_64x27, + HDMI_VIC_Y420_MAX, + + HDMI_VIC_FAKE = HDMITX_VIC420_FAKE_OFFSET, + HDMI_VIC_END, +}; + +/* Compliance with old definitions */ +#define HDMI_640x480p60 HDMI_640x480p60_4x3 +#define HDMI_480p60 HDMI_720x480p60_4x3 +#define HDMI_480p60_16x9 HDMI_720x480p60_16x9 +#define HDMI_720p60 HDMI_1280x720p60_16x9 +#define HDMI_1080i60 HDMI_1920x1080i60_16x9 +#define HDMI_480i60 HDMI_720x480i60_4x3 +#define HDMI_480i60_16x9 HDMI_720x480i60_16x9 +#define HDMI_480i60_16x9_rpt HDMI_2880x480i60_16x9 +#define HDMI_1440x480p60 HDMI_1440x480p60_4x3 +#define HDMI_1440x480p60_16x9 HDMI_1440x480p60_16x9 +#define HDMI_1080p60 HDMI_1920x1080p60_16x9 +#define HDMI_576p50 HDMI_720x576p50_4x3 +#define HDMI_576p50_16x9 HDMI_720x576p50_16x9 +#define HDMI_720p50 HDMI_1280x720p50_16x9 +#define HDMI_1080i50 HDMI_1920x1080i50_16x9 +#define HDMI_576i50 HDMI_720x576i50_4x3 +#define HDMI_576i50_16x9 HDMI_720x576i50_16x9 +#define HDMI_576i50_16x9_rpt HDMI_2880x576i50_16x9 +#define HDMI_1080p50 HDMI_1920x1080p50_16x9 +#define HDMI_1080p24 HDMI_1920x1080p24_16x9 +#define HDMI_1080p25 HDMI_1920x1080p25_16x9 +#define HDMI_1080p30 HDMI_1920x1080p30_16x9 +#define HDMI_480p60_16x9_rpt HDMI_2880x480p60_16x9 +#define HDMI_576p50_16x9_rpt HDMI_2880x576p50_16x9 +#define HDMI_4k2k_24 HDMI_3840x2160p24_16x9 +#define HDMI_4k2k_25 HDMI_3840x2160p25_16x9 +#define HDMI_4k2k_30 HDMI_3840x2160p30_16x9 +#define HDMI_4k2k_50 HDMI_3840x2160p50_16x9 +#define HDMI_4k2k_60 HDMI_3840x2160p60_16x9 +#define HDMI_4k2k_smpte_24 HDMI_4096x2160p24_256x135 +#define HDMI_4k2k_smpte_50 HDMI_4096x2160p50_256x135 +#define HDMI_4k2k_smpte_60 HDMI_4096x2160p60_256x135 + +/* for Y420 modes*/ +#define HDMI_4k2k_50_y420 HDMI_3840x2160p50_16x9_Y420 +#define HDMI_4k2k_60_y420 HDMI_3840x2160p60_16x9_Y420 +#define HDMI_4k2k_smpte_50_y420 HDMI_4096x2160p50_256x135_Y420 +#define HDMI_4k2k_smpte_60_y420 HDMI_4096x2160p60_256x135_Y420 + +enum hdmi_audio_fs; +struct dtd; + +/* CEA TIMING STRUCT DEFINITION */ +struct hdmi_cea_timing { + unsigned int pixel_freq; /* Unit: 1000 */ + unsigned int frac_freq; /* 1.001 shift */ + unsigned int h_freq; /* Unit: Hz */ + unsigned int v_freq; /* Unit: 0.001 Hz */ + unsigned int vsync_polarity:1; + unsigned int hsync_polarity:1; + unsigned short h_active; + unsigned short h_total; + unsigned short h_blank; + unsigned short h_front; + unsigned short h_sync; + unsigned short h_back; + unsigned short v_active; + unsigned short v_total; + unsigned short v_blank; + unsigned short v_front; + unsigned short v_sync; + unsigned short v_back; + unsigned short v_sync_ln; +}; + +enum hdmi_color_depth { + COLORDEPTH_24B = 4, + COLORDEPTH_30B = 5, + COLORDEPTH_36B = 6, + COLORDEPTH_48B = 7, +}; + +enum hdmi_color_space { + COLORSPACE_RGB444 = 0, + COLORSPACE_YUV422 = 1, + COLORSPACE_YUV444 = 2, + COLORSPACE_YUV420 = 3, + COLORSPACE_RESERVED, +}; + +enum hdmi_color_range { + COLORRANGE_LIM, + COLORRANGE_FUL, +}; + +enum hdmi_3d_type { + T3D_FRAME_PACKING = 0, + T3D_FIELD_ALTER = 1, + T3D_LINE_ALTER = 2, + T3D_SBS_FULL = 3, + T3D_L_DEPTH = 4, + T3D_L_DEPTH_GRAPHICS = 5, + T3D_TAB = 6, /* Top and Buttom */ + T3D_RSVD = 7, + T3D_SBS_HALF = 8, + T3D_DISABLE, +}; + +/* get hdmi cea timing */ +/* t: struct hdmi_cea_timing * */ +#define GET_TIMING(name) (t->name) + +struct hdmi_format_para { + enum hdmi_vic vic; + unsigned char *name; + unsigned char *sname; + char ext_name[32]; + enum hdmi_color_depth cd; /* cd8, cd10 or cd12 */ + enum hdmi_color_space cs; /* rgb, y444, y422, y420 */ + enum hdmi_color_range cr; /* limit, full */ + unsigned int pixel_repetition_factor; + unsigned int progress_mode:1; + unsigned int scrambler_en:1; + unsigned int tmds_clk_div40:1; + unsigned int tmds_clk; /* Unit: 1000 */ + struct hdmi_cea_timing timing; + struct vinfo_s hdmitx_vinfo; +}; + +/* HDMI Packet Type Definitions */ +#define PT_NULL_PKT 0x00 +#define PT_AUD_CLK_REGENERATION 0x01 +#define PT_AUD_SAMPLE 0x02 +#define PT_GENERAL_CONTROL 0x03 +#define PT_ACP 0x04 +#define PT_ISRC1 0x05 +#define PT_ISRC2 0x06 +#define PT_ONE_BIT_AUD_SAMPLE 0x07 +#define PT_DST_AUD 0x08 +#define PT_HBR_AUD_STREAM 0x09 +#define PT_GAMUT_METADATA 0x0A +#define PT_3D_AUD_SAMPLE 0x0B +#define PT_ONE_BIT_3D_AUD_SAMPLE 0x0C +#define PT_AUD_METADATA 0x0D +#define PT_MULTI_SREAM_AUD_SAMPLE 0x0E +#define PT_ONE_BIT_MULTI_SREAM_AUD_SAMPLE 0x0F +/* Infoframe Packet */ +#define PT_IF_VENDOR_SEPCIFIC 0x81 +#define PT_IF_AVI 0x82 +#define PT_IF_SPD 0x83 +#define PT_IF_AUD 0x84 +#define PT_IF_MPEG_SOURCE 0x85 + +/* Old definitions */ +#define TYPE_AVI_INFOFRAMES 0x82 +#define AVI_INFOFRAMES_VERSION 0x02 +#define AVI_INFOFRAMES_LENGTH 0x0D + +struct hdmi_csc_coef_table { + unsigned char input_format; + unsigned char output_format; + unsigned char color_depth; + unsigned char color_format; /* 0 for ITU601, 1 for ITU709 */ + unsigned char coef_length; + unsigned char *coef; +}; + +enum hdmi_audio_packet { + hdmi_audio_packet_SMP = 0x02, + hdmi_audio_packet_1BT = 0x07, + hdmi_audio_packet_DST = 0x08, + hdmi_audio_packet_HBR = 0x09, +}; + +enum hdmi_aspect_ratio { + ASPECT_RATIO_SAME_AS_SOURCE = 0x8, + TV_ASPECT_RATIO_4_3 = 0x9, + TV_ASPECT_RATIO_16_9 = 0xA, + TV_ASPECT_RATIO_14_9 = 0xB, + TV_ASPECT_RATIO_MAX +}; + +struct hdmi_format_para *hdmi_get_fmt_paras(enum hdmi_vic vic); +struct hdmi_format_para *hdmi_match_dtd_paras(struct dtd *t); +void check_detail_fmt(void); +unsigned int hdmi_get_csc_coef( + unsigned int input_format, unsigned int output_format, + unsigned int color_depth, unsigned int color_format, + unsigned char **coef_array, unsigned int *coef_length); +struct hdmi_format_para *hdmi_get_fmt_name(char const *name, char const *attr); +struct vinfo_s *hdmi_get_valid_vinfo(char *mode); +const char *hdmi_get_str_cd(struct hdmi_format_para *para); +const char *hdmi_get_str_cs(struct hdmi_format_para *para); +const char *hdmi_get_str_cr(struct hdmi_format_para *para); +unsigned int hdmi_get_aud_n_paras(enum hdmi_audio_fs fs, + enum hdmi_color_depth cd, unsigned int tmds_clk); + +/* HDMI Audio Parmeters */ +/* Refer to CEA-861-D Page 88 */ +#define DTS_HD_TYPE_MASK 0xff00 +#define DTS_HD_MA (0X1 << 8) +enum hdmi_audio_type { + CT_REFER_TO_STREAM = 0, + CT_PCM, + CT_AC_3, /* DD */ + CT_MPEG1, + CT_MP3, + CT_MPEG2, + CT_AAC, + CT_DTS, + CT_ATRAC, + CT_ONE_BIT_AUDIO, + CT_DOLBY_D, /* DDP or DD+ */ + CT_DTS_HD, + CT_MAT, /* TrueHD */ + CT_DST, + CT_WMA, + CT_DTS_HD_MA = CT_DTS_HD + (DTS_HD_MA), + CT_MAX, +}; + +enum hdmi_audio_chnnum { + CC_REFER_TO_STREAM = 0, + CC_2CH, + CC_3CH, + CC_4CH, + CC_5CH, + CC_6CH, + CC_7CH, + CC_8CH, + CC_MAX_CH +}; + +enum hdmi_audio_format { + AF_SPDIF = 0, AF_I2S, AF_DSD, AF_HBR, AT_MAX +}; + +enum hdmi_audio_sampsize { + SS_REFER_TO_STREAM = 0, SS_16BITS, SS_20BITS, SS_24BITS, SS_MAX +}; + +struct size_map { + unsigned int sample_bits; + enum hdmi_audio_sampsize ss; +}; + +/* FL-- Front Left */ +/* FC --Front Center */ +/* FR --Front Right */ +/* FLC-- Front Left Center */ +/* FRC-- Front RiQhtCenter */ +/* RL-- Rear Left */ +/* RC --Rear Center */ +/* RR-- Rear Right */ +/* RLC-- Rear Left Center */ +/* RRC --Rear RiQhtCenter */ +/* LFE-- Low Frequency Effect */ +enum hdmi_speak_location { + CA_FR_FL = 0, + CA_LFE_FR_FL, + CA_FC_FR_FL, + CA_FC_LFE_FR_FL, + + CA_RC_FR_FL, + CA_RC_LFE_FR_FL, + CA_RC_FC_FR_FL, + CA_RC_FC_LFE_FR_FL, + + CA_RR_RL_FR_FL, + CA_RR_RL_LFE_FR_FL, + CA_RR_RL_FC_FR_FL, + CA_RR_RL_FC_LFE_FR_FL, + + CA_RC_RR_RL_FR_FL, + CA_RC_RR_RL_LFE_FR_FL, + CA_RC_RR_RL_FC_FR_FL, + CA_RC_RR_RL_FC_LFE_FR_FL, + + CA_RRC_RC_RR_RL_FR_FL, + CA_RRC_RC_RR_RL_LFE_FR_FL, + CA_RRC_RC_RR_RL_FC_FR_FL, + CA_RRC_RC_RR_RL_FC_LFE_FR_FL, + + CA_FRC_RLC_FR_FL, + CA_FRC_RLC_LFE_FR_FL, + CA_FRC_RLC_FC_FR_FL, + CA_FRC_RLC_FC_LFE_FR_FL, + + CA_FRC_RLC_RC_FR_FL, + CA_FRC_RLC_RC_LFE_FR_FL, + CA_FRC_RLC_RC_FC_FR_FL, + CA_FRC_RLC_RC_FC_LFE_FR_FL, + + CA_FRC_RLC_RR_RL_FR_FL, + CA_FRC_RLC_RR_RL_LFE_FR_FL, + CA_FRC_RLC_RR_RL_FC_FR_FL, + CA_FRC_RLC_RR_RL_FC_LFE_FR_FL, +}; + +enum hdmi_audio_downmix { + LSV_0DB = 0, + LSV_1DB, + LSV_2DB, + LSV_3DB, + LSV_4DB, + LSV_5DB, + LSV_6DB, + LSV_7DB, + LSV_8DB, + LSV_9DB, + LSV_10DB, + LSV_11DB, + LSV_12DB, + LSV_13DB, + LSV_14DB, + LSV_15DB, +}; + +enum hdmi_rx_audio_state { + STATE_AUDIO__MUTED = 0, + STATE_AUDIO__REQUEST_AUDIO = 1, + STATE_AUDIO__AUDIO_READY = 2, + STATE_AUDIO__ON = 3, +}; + +/* Sampling Freq Fs: + * 0 - Refer to Stream Header; + * 1 - 32KHz; + * 2 - 44.1KHz; + * 3 - 48KHz; + * 4 - 88.2KHz... + */ +enum hdmi_audio_fs { + FS_REFER_TO_STREAM = 0, + FS_32K = 1, + FS_44K1 = 2, + FS_48K = 3, + FS_88K2 = 4, + FS_96K = 5, + FS_176K4 = 6, + FS_192K = 7, + FS_768K = 8, + FS_MAX, +}; + +struct rate_map_fs { + unsigned int rate; + enum hdmi_audio_fs fs; +}; + +struct hdmi_rx_audioinfo { + /* !< Signal decoding type -- TvAudioType */ + enum hdmi_audio_type type; + enum hdmi_audio_format format; + /* !< active audio channels bit mask. */ + enum hdmi_audio_chnnum channels; + enum hdmi_audio_fs fs; /* !< Signal sample rate in Hz */ + enum hdmi_audio_sampsize ss; + enum hdmi_speak_location speak_loc; + enum hdmi_audio_downmix lsv; + unsigned int N_value; + unsigned int CTS; +}; + +#define AUDIO_PARA_MAX_NUM 14 +struct hdmi_audio_fs_ncts { + struct { + unsigned int tmds_clk; + unsigned int n; /* 24 or 30 bit */ + unsigned int cts; /* 24 or 30 bit */ + unsigned int n_36bit; + unsigned int cts_36bit; + unsigned int n_48bit; + unsigned int cts_48bit; + } array[AUDIO_PARA_MAX_NUM]; + unsigned int def_n; +}; + +struct parse_cd { + enum hdmi_color_depth cd; + const char *name; +}; + +struct parse_cs { + enum hdmi_color_space cs; + const char *name; +}; + +struct parse_cr { + enum hdmi_color_range cr; + const char *name; +}; + +/* Refer CEA861-D Page 116 Table 55 */ +struct dtd { + unsigned short pixel_clock; + unsigned short h_active; + unsigned short h_blank; + unsigned short v_active; + unsigned short v_blank; + unsigned short h_sync_offset; + unsigned short h_sync; + unsigned short v_sync_offset; + unsigned short v_sync; + unsigned char h_image_size; + unsigned char v_image_size; + unsigned char h_border; + unsigned char v_border; + unsigned char flags; + enum hdmi_vic vic; +}; + +#endif diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_config.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_config.h new file mode 100644 index 000000000000..722049cef156 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_config.h @@ -0,0 +1,78 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_config.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __PLAT_MESON_HDMI_CONFIG_H +#define __PLAT_MESON_HDMI_CONFIG_H + +struct hdmi_phy_set_data { + unsigned long freq; + unsigned long addr; + unsigned long data; +}; + +struct vendor_info_data { + unsigned char *vendor_name; /* Max Chars: 8 */ + /* vendor_id, 3 Bytes, Refer to + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + unsigned char *product_desc; /* Max Chars: 16 */ + unsigned char *cec_osd_string; /* Max Chars: 14 */ + unsigned int cec_config; /* 4 bytes: use to control cec switch on/off */ + unsigned int vendor_id; +}; + +enum pwr_type { + NONE = 0, CPU_GPO = 1, PMU, +}; + +struct pwr_cpu_gpo { + unsigned int pin; + unsigned int val; +}; + +struct pwr_pmu { + unsigned int pin; + unsigned int val; +}; + +struct pwr_ctl_var { + enum pwr_type type; + union { + struct pwr_cpu_gpo gpo; + struct pwr_pmu pmu; + } var; +}; + +struct hdmi_pwr_ctl { + struct pwr_ctl_var pwr_5v_on; + struct pwr_ctl_var pwr_5v_off; + struct pwr_ctl_var pwr_3v3_on; + struct pwr_ctl_var pwr_3v3_off; + struct pwr_ctl_var pwr_hpll_vdd_on; + struct pwr_ctl_var pwr_hpll_vdd_off; + int pwr_level; +}; + +struct hdmi_config_platform_data { + void (*hdmi_sspll_ctrl)(unsigned int level); /* SSPLL control level */ + /* For some boards, HDMI PHY setting may diff from ref board. */ + struct hdmi_phy_set_data *phy_data; + struct vendor_info_data *vend_data; + struct hdmi_pwr_ctl *pwr_ctl; +}; + +#endif /* __PLAT_MESON_HDMI_CONFIG_H */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_info_global.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_info_global.h new file mode 100644 index 000000000000..ec4e1ecc05d8 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_info_global.h @@ -0,0 +1,339 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_info_global.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _HDMI_INFO_GLOBAL_H +#define _HDMI_INFO_GLOBAL_H + +#include "hdmi_common.h" + +/* old definitions move to hdmi_common.h */ + +enum hdmi_rx_video_state { + STATE_VIDEO__POWERDOWN = 0, + STATE_VIDEO__MUTED = 1, + STATE_VIDEO__UNMUTE = 2, + STATE_VIDEO__ON = 3, +}; + +struct pixel_num { + short H; /* Number of horizontal pixels */ + short V; /* Number of vertical pixels */ +}; + +enum hdmi_pixel_repeat { + NO_REPEAT = 0, + HDMI_2_TIMES_REPEAT, + HDMI_3_TIMES_REPEAT, + HDMI_4_TIMES_REPEAT, + HDMI_5_TIMES_REPEAT, + HDMI_6_TIMES_REPEAT, + HDMI_7_TIMES_REPEAT, + HDMI_8_TIMES_REPEAT, + HDMI_9_TIMES_REPEAT, + HDMI_10_TIMES_REPEAT, + MAX_TIMES_REPEAT, +}; + +enum hdmi_scan { + SS_NO_DATA = 0, + /* where some active pixelsand lines at the edges are not displayed. */ + SS_SCAN_OVER, + /* where all active pixels&lines are displayed, + * with or withouta border. + */ + SS_SCAN_UNDER, + SS_RSV +}; + +enum hdmi_barinfo { + B_UNVALID = 0, B_BAR_VERT, /* Vert. Bar Infovalid */ + B_BAR_HORIZ, /* Horiz. Bar Infovalid */ + B_BAR_VERT_HORIZ, +/* Vert.and Horiz. Bar Info valid */ +}; + +enum hdmi_colorimetry { + CC_NO_DATA = 0, CC_ITU601, CC_ITU709, CC_XVYCC601, CC_XVYCC709, +}; + +enum hdmi_slacing { + SC_NO_UINFORM = 0, + /* Picture has been scaled horizontally */ + SC_SCALE_HORIZ, + SC_SCALE_VERT, /* Picture has been scaled verticallv */ + SC_SCALE_HORIZ_VERT, +/* Picture has been scaled horizontally & SC_SCALE_H_V */ +}; + +struct hdmi_videoinfo { + enum hdmi_vic VIC; + enum hdmi_color_space color; + enum hdmi_color_depth color_depth; + enum hdmi_barinfo bar_info; + enum hdmi_pixel_repeat repeat_time; + enum hdmi_aspect_ratio aspect_ratio; + enum hdmi_colorimetry cc; + enum hdmi_scan ss; + enum hdmi_slacing sc; +}; +/* -------------------HDMI VIDEO END---------------------------- */ + +/* -------------------HDMI AUDIO-------------------------------- */ +#define TYPE_AUDIO_INFOFRAMES 0x84 +#define AUDIO_INFOFRAMES_VERSION 0x01 +#define AUDIO_INFOFRAMES_LENGTH 0x0A + +#define HDMI_E_NONE 0x0 +/* HPD Event & Status */ +#define E_HPD_PULG_IN 0x1 +#define E_HPD_PLUG_OUT 0x2 +#define S_HPD_PLUG_IN 0x1 +#define S_HPD_PLUG_OUT 0x0 + +#define E_HDCP_CHK_BKSV 0x1 + +/* -------------------HDMI AUDIO END---------------------- */ + +/* -------------------HDCP-------------------------------- */ +/* HDCP keys from Efuse are encrypted by default, in this test HDCP keys + * are written by CPU with encryption manually added + */ +#define ENCRYPT_KEY 0xbe + +enum hdcp_authstate { + HDCP_NO_AUTH = 0, + HDCP_NO_DEVICE_WITH_SLAVE_ADDR, + HDCP_BCAP_ERROR, + HDCP_BKSV_ERROR, + HDCP_R0S_ARE_MISSMATCH, + HDCP_RIS_ARE_MISSMATCH, + HDCP_REAUTHENTATION_REQ, + HDCP_REQ_AUTHENTICATION, + HDCP_NO_ACK_FROM_DEV, + HDCP_NO_RSEN, + HDCP_AUTHENTICATED, + HDCP_REPEATER_AUTH_REQ, + HDCP_REQ_SHA_CALC, + HDCP_REQ_SHA_HW_CALC, + HDCP_FAILED_ViERROR, + HDCP_MAX +}; + +/* -----------------------HDCP END---------------------------------------- */ + +/* -----------------------HDMI TX---------------------------------- */ +enum hdmitx_disptype { + CABLE_UNPLUG = 0, + CABLE_PLUGIN_CHECK_EDID_I2C_ERROR, + CABLE_PLUGIN_CHECK_EDID_HEAD_ERROR, + CABLE_PLUGIN_CHECK_EDID_CHECKSUM_ERROR, + CABLE_PLUGIN_DVI_OUT, + CABLE_PLUGIN_HDMI_OUT, + CABLE_MAX +}; + +struct hdmitx_supstatus { + int hpd_state:1; + int support_480i:1; + int support_576i:1; + int support_480p:1; + int support_576p:1; + int support_720p_60hz:1; + int support_720p_50hz:1; + int support_1080i_60hz:1; + int support_1080i_50hz:1; + int support_1080p_60hz:1; + int support_1080p_50hz:1; + int support_1080p_24hz:1; + int support_1080p_25hz:1; + int support_1080p_30hz:1; +}; + +struct hdmitx_suplpcminfo { + int support_flag:1; + int max_channel_num:3; + int _192k:1; + int _176k:1; + int _96k:1; + int _88k:1; + int _48k:1; + int _44k:1; + int _32k:1; + int _24bit:1; + int _20bit:1; + int _16bit:1; +}; + +struct hdmitx_supcompressedinfo { + int support_flag:1; + int max_channel_num:3; + int _192k:1; + int _176k:1; + int _96k:1; + int _88k:1; + int _48k:1; + int _44k:1; + int _32k:1; + int _max_bit:10; +}; + +struct hdmitx_supspeakerformat { + int rlc_rrc:1; + int flc_frc:1; + int rc:1; + int rl_rr:1; + int fc:1; + int lfe:1; + int fl_fr:1; +}; + +struct hdmitx_vidpara { + unsigned int VIC; + enum hdmi_color_space color_prefer; + enum hdmi_color_space color; + enum hdmi_color_depth color_depth; + enum hdmi_barinfo bar_info; + enum hdmi_pixel_repeat repeat_time; + enum hdmi_aspect_ratio aspect_ratio; + enum hdmi_colorimetry cc; + enum hdmi_scan ss; + enum hdmi_slacing sc; +}; + +struct hdmitx_audpara { + enum hdmi_audio_type type; + enum hdmi_audio_chnnum channel_num; + enum hdmi_audio_fs sample_rate; + enum hdmi_audio_sampsize sample_size; +}; + +struct hdmitx_supaudinfo { + struct hdmitx_suplpcminfo _60958_PCM; + struct hdmitx_supcompressedinfo _AC3; + struct hdmitx_supcompressedinfo _MPEG1; + struct hdmitx_supcompressedinfo _MP3; + struct hdmitx_supcompressedinfo _MPEG2; + struct hdmitx_supcompressedinfo _AAC; + struct hdmitx_supcompressedinfo _DTS; + struct hdmitx_supcompressedinfo _ATRAC; + struct hdmitx_supcompressedinfo _One_Bit_Audio; + struct hdmitx_supcompressedinfo _Dolby; + struct hdmitx_supcompressedinfo _DTS_HD; + struct hdmitx_supcompressedinfo _MAT; + struct hdmitx_supcompressedinfo _DST; + struct hdmitx_supcompressedinfo _WMA; + struct hdmitx_supspeakerformat speaker_allocation; +}; + +/* ACR packet CTS parameters have 3 types: */ +/* 1. HW auto calculated */ +/* 2. Fixed values defined by Spec */ +/* 3. Calculated by clock meter */ +enum hdmitx_audcts { + AUD_CTS_AUTO = 0, AUD_CTS_FIXED, AUD_CTS_CALC, +}; + +struct dispmode_vic { + const char *disp_mode; + enum hdmi_vic VIC; +}; + +struct hdmitx_audinfo { + /* !< Signal decoding type -- TvAudioType */ + enum hdmi_audio_type type; + enum hdmi_audio_format format; + /* !< active audio channels bit mask. */ + enum hdmi_audio_chnnum channels; + enum hdmi_audio_fs fs; /* !< Signal sample rate in Hz */ + enum hdmi_audio_sampsize ss; +}; + +/* -----------------Source Physical Address--------------- */ +struct vsdb_phyaddr { + unsigned char a:4; + unsigned char b:4; + unsigned char c:4; + unsigned char d:4; + unsigned char valid; +}; + +struct hdmitx_clk { + enum hdmi_vic vic; + uint64_t clk_sys; + uint64_t clk_phy; + uint64_t clk_vid; + uint64_t clk_encp; + uint64_t clk_enci; + uint64_t clk_pixel; +}; + +#define Y420CMDB_MAX 32 +struct hdmitx_info { + struct hdmi_rx_audioinfo audio_info; + struct hdmitx_supaudinfo tv_audio_info; + /* Hdmi_tx_video_info_t video_info; */ + enum hdcp_authstate auth_state; + enum hdmitx_disptype output_state; + /* -----------------Source Physical Address--------------- */ + struct vsdb_phyaddr vsdb_phy_addr; + /* ------------------------------------------------------- */ + unsigned video_out_changing_flag:1; + unsigned support_underscan_flag:1; + unsigned support_ycbcr444_flag:1; + unsigned support_ycbcr422_flag:1; + unsigned tx_video_input_stable_flag:1; + unsigned auto_hdcp_ri_flag:1; + unsigned hw_sha_calculator_flag:1; + unsigned need_sup_cec:1; + + /* ------------------------------------------------------- */ + unsigned audio_out_changing_flag:1; + unsigned audio_flag:1; + unsigned support_basic_audio_flag:1; + unsigned audio_fifo_overflow:1; + unsigned audio_fifo_underflow:1; + unsigned audio_cts_status_err_flag:1; + unsigned support_ai_flag:1; + unsigned hdmi_sup_480i:1; + + /* ------------------------------------------------------- */ + unsigned hdmi_sup_576i:1; + unsigned hdmi_sup_480p:1; + unsigned hdmi_sup_576p:1; + unsigned hdmi_sup_720p_60hz:1; + unsigned hdmi_sup_720p_50hz:1; + unsigned hdmi_sup_1080i_60hz:1; + unsigned hdmi_sup_1080i_50hz:1; + unsigned hdmi_sup_1080p_60hz:1; + + /* ------------------------------------------------------- */ + unsigned hdmi_sup_1080p_50hz:1; + unsigned hdmi_sup_1080p_24hz:1; + unsigned hdmi_sup_1080p_25hz:1; + unsigned hdmi_sup_1080p_30hz:1; + + /* ------------------------------------------------------- */ + /* for total = 32*8 = 256 VICs */ + /* for Y420CMDB bitmap */ + unsigned char bitmap_valid; + unsigned char bitmap_length; + unsigned char y420_all_vic; + unsigned char y420cmdb_bitmap[Y420CMDB_MAX]; + /* ------------------------------------------------------- */ +}; + +#endif /* _HDMI_RX_GLOBAL_H */ 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 new file mode 100644 index 000000000000..5e5abb17c708 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h @@ -0,0 +1,329 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _TX_CEC_H_ +#define _TX_CEC_H_ + +#include +#include +#include "hdmi_info_global.h" +#include "hdmi_tx_module.h" + +#define CEC0_LOG_ADDR 4 /* MBX logical address */ +#define TV_CEC_INTERVAL (HZ*3) + +#define CEC_VERSION "v1.3" +#define _RX_DATA_BUF_SIZE_ 16 + +#define AO_CEC /* for switch between aocec and hdmi cec2.0 */ + +#define MAX_MSG 16 +#define MAX_NUM_OF_DEV 16 + +enum _cec_log_dev_addr_e { + CEC_TV_ADDR = 0x00, + CEC_RECORDING_DEVICE_1_ADDR, + CEC_RECORDING_DEVICE_2_ADDR, + CEC_TUNER_1_ADDR, + CEC_PLAYBACK_DEVICE_1_ADDR, + CEC_AUDIO_SYSTEM_ADDR, + CEC_TUNER_2_ADDR, + CEC_TUNER_3_ADDR, + CEC_PLAYBACK_DEVICE_2_ADDR, + CEC_RECORDING_DEVICE_3_ADDR, + CEC_TUNER_4_ADDR, + CEC_PLAYBACK_DEVICE_3_ADDR, + CEC_RESERVED_1_ADDR, + CEC_RESERVED_2_ADDR, + CEC_FREE_USE_ADDR, + CEC_UNREGISTERED_ADDR +}; + +#define CEC_BROADCAST_ADDR CEC_UNREGISTERED_ADDR + +#define CEC_TV (1 << CEC_TV_ADDR) +#define CEC_RECORDING_DEVICE_1 (1 << CEC_RECORDING_DEVICE_1_ADDR) +#define CEC_RECORDING_DEVICE_2 (1 << CEC_RECORDING_DEVICE_2_ADDR) +#define CEC_TUNER_1 (1 << CEC_TUNER_1_ADDR) +#define CEC_PLAYBACK_DEVICE_1 (1 << CEC_PLAYBACK_DEVICE_1_ADDR) +#define CEC_AUDIO_SYSTEM (1 << CEC_AUDIO_SYSTEM_ADDR) +#define CEC_TUNER_2 (1 << CEC_TUNER_2_ADDR) +#define CEC_TUNER_3 (1 << CEC_TUNER_3_ADDR) +#define CEC_PLAYBACK_DEVICE_2 (1 << CEC_PLAYBACK_DEVICE_2_ADDR) +#define CEC_RECORDING_DEVICE_3 (1 << CEC_RECORDING_DEVICE_3_ADDR) +#define CEC_TUNER_4 (1 << CEC_TUNER_4_ADDR) +#define CEC_PLAYBACK_DEVICE_3 (1 << CEC_PLAYBACK_DEVICE_3_ADDR) +#define CEC_RESERVED_1 (1 << CEC_RESERVED_1_ADDR) +#define CEC_RESERVED_2 (1 << CEC_RESERVED_2_ADDR) +#define CEC_FREE_USE (1 << CEC_FREE_USE_ADDR) +#define CEC_UNREGISTERED (1 << CEC_UNREGISTERED_ADDR) + +#define CEC_DISPLAY_DEVICE (CEC_TV | CEC_FREE_USE) +#define CEC_RECORDING_DEVICE (CEC_RECORDING_DEVICE_1 \ + | CEC_RECORDING_DEVICE_2 | CEC_RECORDING_DEVICE_3) +#define CEC_PLAYBACK_DEVICE (CEC_PLAYBACK_DEVICE_1 \ + | CEC_PLAYBACK_DEVICE_2 | CEC_PLAYBACK_DEVICE_3) +#define CEC_TUNER_DEVICE (CEC_TUNER_1 | CEC_TUNER_2 \ + | CEC_TUNER_3 | CEC_TUNER_4) +#define CEC_AUDIO_SYSTEM_DEVICE (CEC_AUDIO_SYSTEM) + +#define CEC_IOC_MAGIC 'C' +#define CEC_IOC_GET_PHYSICAL_ADDR _IOR(CEC_IOC_MAGIC, 0x00, uint16_t) +#define CEC_IOC_GET_VERSION _IOR(CEC_IOC_MAGIC, 0x01, int) +#define CEC_IOC_GET_VENDOR_ID _IOR(CEC_IOC_MAGIC, 0x02, uint32_t) +#define CEC_IOC_GET_PORT_INFO _IOR(CEC_IOC_MAGIC, 0x03, int) +#define CEC_IOC_GET_PORT_NUM _IOR(CEC_IOC_MAGIC, 0x04, int) +#define CEC_IOC_GET_SEND_FAIL_REASON _IOR(CEC_IOC_MAGIC, 0x05, uint32_t) +#define CEC_IOC_SET_OPTION_WAKEUP _IOW(CEC_IOC_MAGIC, 0x06, uint32_t) +#define CEC_IOC_SET_OPTION_ENALBE_CEC _IOW(CEC_IOC_MAGIC, 0x07, uint32_t) +#define CEC_IOC_SET_OPTION_SYS_CTRL _IOW(CEC_IOC_MAGIC, 0x08, uint32_t) +#define CEC_IOC_SET_OPTION_SET_LANG _IOW(CEC_IOC_MAGIC, 0x09, uint32_t) +#define CEC_IOC_GET_CONNECT_STATUS _IOR(CEC_IOC_MAGIC, 0x0A, uint32_t) +#define CEC_IOC_ADD_LOGICAL_ADDR _IOW(CEC_IOC_MAGIC, 0x0B, uint32_t) +#define CEC_IOC_CLR_LOGICAL_ADDR _IOW(CEC_IOC_MAGIC, 0x0C, uint32_t) +#define CEC_IOC_SET_DEV_TYPE _IOW(CEC_IOC_MAGIC, 0x0D, uint32_t) +#define CEC_IOC_SET_ARC_ENABLE _IOW(CEC_IOC_MAGIC, 0x0E, uint32_t) +#define CEC_IOC_SET_AUTO_DEVICE_OFF _IOW(CEC_IOC_MAGIC, 0x0F, uint32_t) + +#define CEC_FAIL_NONE 0 +#define CEC_FAIL_NACK 1 +#define CEC_FAIL_BUSY 2 +#define CEC_FAIL_OTHER 3 + +enum hdmi_port_type { + HDMI_INPUT = 0, + HDMI_OUTPUT = 1 +}; + +struct hdmi_port_info { + int type; + /* Port ID should start from 1 which corresponds to HDMI "port 1". */ + int port_id; + int cec_supported; + int arc_supported; + uint16_t physical_address; +}; + +enum cec_dev_type_addr { + CEC_DISPLAY_DEVICE_TYPE = 0x0, + CEC_RECORDING_DEVICE_TYPE, + CEC_RESERVED_DEVICE_TYPE, + CEC_TUNER_DEVICE_TYPE, + CEC_PLAYBACK_DEVICE_TYPE, + CEC_AUDIO_SYSTEM_DEVICE_TYPE, + CEC_UNREGISTERED_DEVICE_TYPE, +}; + +enum cec_feature_abort_e { + CEC_UNRECONIZED_OPCODE = 0x0, + CEC_NOT_CORRECT_MODE_TO_RESPOND, + CEC_CANNOT_PROVIDE_SOURCE, + CEC_INVALID_OPERAND, + CEC_REFUSED, + CEC_UNABLE_TO_DETERMINE, +}; + +/* + * CEC OPCODES + */ +#define CEC_OC_ABORT_MESSAGE 0xFF +#define CEC_OC_ACTIVE_SOURCE 0x82 +#define CEC_OC_CEC_VERSION 0x9E +#define CEC_OC_CLEAR_ANALOGUE_TIMER 0x33 +#define CEC_OC_CLEAR_DIGITAL_TIMER 0x99 +#define CEC_OC_CLEAR_EXTERNAL_TIMER 0xA1 +#define CEC_OC_DECK_CONTROL 0x42 +#define CEC_OC_DECK_STATUS 0x1B +#define CEC_OC_DEVICE_VENDOR_ID 0x87 +#define CEC_OC_FEATURE_ABORT 0x00 +#define CEC_OC_GET_CEC_VERSION 0x9F +#define CEC_OC_GET_MENU_LANGUAGE 0x91 +#define CEC_OC_GIVE_AUDIO_STATUS 0x71 +#define CEC_OC_GIVE_DECK_STATUS 0x1A +#define CEC_OC_GIVE_DEVICE_POWER_STATUS 0x8F +#define CEC_OC_GIVE_DEVICE_VENDOR_ID 0x8C +#define CEC_OC_GIVE_OSD_NAME 0x46 +#define CEC_OC_GIVE_PHYSICAL_ADDRESS 0x83 +#define CEC_OC_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7D +#define CEC_OC_GIVE_TUNER_DEVICE_STATUS 0x08 +#define CEC_OC_IMAGE_VIEW_ON 0x04 +#define CEC_OC_INACTIVE_SOURCE 0x9D +#define CEC_OC_MENU_REQUEST 0x8D +#define CEC_OC_MENU_STATUS 0x8E +#define CEC_OC_PLAY 0x41 +#define CEC_OC_POLLING_MESSAGE 0xFC +#define CEC_OC_RECORD_OFF 0x0B +#define CEC_OC_RECORD_ON 0x09 +#define CEC_OC_RECORD_STATUS 0x0A +#define CEC_OC_RECORD_TV_SCREEN 0x0F +#define CEC_OC_REPORT_AUDIO_STATUS 0x7A +#define CEC_OC_REPORT_PHYSICAL_ADDRESS 0x84 +#define CEC_OC_REPORT_POWER_STATUS 0x90 +#define CEC_OC_REQUEST_ACTIVE_SOURCE 0x85 +#define CEC_OC_ROUTING_CHANGE 0x80 +#define CEC_OC_ROUTING_INFORMATION 0x81 +#define CEC_OC_SELECT_ANALOGUE_SERVICE 0x92 +#define CEC_OC_SELECT_DIGITAL_SERVICE 0x93 +#define CEC_OC_SET_ANALOGUE_TIMER 0x34 +#define CEC_OC_SET_AUDIO_RATE 0x9A +#define CEC_OC_SET_DIGITAL_TIMER 0x97 +#define CEC_OC_SET_EXTERNAL_TIMER 0xA2 +#define CEC_OC_SET_MENU_LANGUAGE 0x32 +#define CEC_OC_SET_OSD_NAME 0x47 +#define CEC_OC_SET_OSD_STRING 0x64 +#define CEC_OC_SET_STREAM_PATH 0x86 +#define CEC_OC_SET_SYSTEM_AUDIO_MODE 0x72 +#define CEC_OC_SET_TIMER_PROGRAM_TITLE 0x67 +#define CEC_OC_STANDBY 0x36 +#define CEC_OC_SYSTEM_AUDIO_MODE_REQUEST 0x70 +#define CEC_OC_SYSTEM_AUDIO_MODE_STATUS 0x7E +#define CEC_OC_TEXT_VIEW_ON 0x0D +#define CEC_OC_TIMER_CLEARED_STATUS 0x43 +#define CEC_OC_TIMER_STATUS 0x35 +#define CEC_OC_TUNER_DEVICE_STATUS 0x07 +#define CEC_OC_TUNER_STEP_DECREMENT 0x06 +#define CEC_OC_TUNER_STEP_INCREMENT 0x05 +#define CEC_OC_USER_CONTROL_PRESSED 0x44 +#define CEC_OC_USER_CONTROL_RELEASED 0x45 +#define CEC_OC_VENDOR_COMMAND 0x89 +#define CEC_OC_VENDOR_COMMAND_WITH_ID 0xA0 +#define CEC_OC_VENDOR_REMOTE_BUTTON_DOWN 0x8A +#define CEC_OC_VENDOR_REMOTE_BUTTON_UP 0x8B + +/* cec global struct */ + +enum cec_node_status_e { + STATE_UNKNOWN = 0x00, + STATE_START, + STATE_STOP +}; + +enum cec_power_status_e { + POWER_ON = 0x00, + POWER_STANDBY, + TRANS_STANDBY_TO_ON, + TRANS_ON_TO_STANDBY, +}; + +enum status_req_mode_e { + STATUS_REQ_ON = 1, + STATUS_REQ_OFF, + STATUS_REQ_ONCE, +}; + +enum deck_info_e { + DECK_UNKNOWN_STATUS = 0, + DECK_PLAY = 0X11, + DECK_RECORD, + DECK_PLAY_REVERSE, + DECK_STILL, + DECK_SLOW, + DECK_SLOW_REVERSE, + DECK_FAST_FORWARD, + DECK_FAST_REVERSE, + DECK_NO_MEDIA, + DECK_STOP, + DECK_SKIP_FORWARD_WIND, + DECK_SKIP_REVERSE_REWIND, + DECK_INDEX_SEARCH_FORWARD, + DECK_INDEX_SEARCH_REVERSE, + DECK_OTHER_STATUS, +}; + +enum deck_cnt_mode_e { + DECK_CNT_SKIP_FORWARD_WIND = 1, + DECK_CNT_SKIP_REVERSE_REWIND, + DECK_CNT_STOP, + DECK_CNT_EJECT, +}; + +enum play_mode_e { + PLAY_FORWARD = 0X24, + PLAY_REVERSE = 0X20, + PLAY_STILL = 0X25, + FAST_FORWARD_MIN_SPEED = 0X05, + FAST_FORWARD_MEDIUM_SPEED = 0X06, + FAST_FORWARD_MAX_SPEED = 0X07, + FAST_REVERSE_MIN_SPEED = 0X09, + FAST_REVERSE_MEDIUM_SPEED = 0X0A, + FAST_REVERSE_MAX_SPEED = 0X0B, + SLOW_FORWARD_MIN_SPEED = 0X15, + SLOW_FORWARD_MEDIUM_SPEED = 0X16, + SLOW_FORWARD_MAX_SPEED = 0X17, + SLOW_REVERSE_MIN_SPEED = 0X19, + SLOW_REVERSE_MEDIUM_SPEED = 0X1A, + SLOW_REVERSE_MAX_SPEED = 0X1B, +}; + +enum cec_version_e { + CEC_VERSION_11 = 0, + CEC_VERSION_12, + CEC_VERSION_12A, + CEC_VERSION_13, + CEC_VERSION_13A, + CEC_VERSION_14A, +}; + +#define INFO_MASK_CEC_VERSION (1<<0) +#define INFO_MASK_VENDOR_ID (1<<1) +#define INFO_MASK_DEVICE_TYPE (1<<2) +#define INFO_MASK_POWER_STATUS (1<<3) +#define INFO_MASK_PHYSICAL_ADDRESS (1<<4) +#define INFO_MASK_LOGIC_ADDRESS (1<<5) +#define INFO_MASK_OSD_NAME (1<<6) +#define INFO_MASK_MENU_STATE (1<<7) +#define INFO_MASK_MENU_LANGUAGE (1<<8) +#define INFO_MASK_DECK_INfO (1<<9) +#define INFO_MASK_PLAY_MODE (1<<10) + +/*CEC UI MASK*/ +#define CEC_FUNC_MSAK 0 +#define ONE_TOUCH_PLAY_MASK 1 +#define ONE_TOUCH_STANDBY_MASK 2 +#define AUTO_POWER_ON_MASK 3 + + +struct cec_node_info_t { +}; + +/* + * only for 1 tx device + */ +struct cec_global_info_t { + dev_t dev_no; + unsigned int open_count; + unsigned int hal_ctl; /* message controlled by hal */ + unsigned int vendor_id:24; + unsigned int menu_lang; + unsigned char cec_version; + unsigned char power_status; + unsigned char log_addr; + unsigned char menu_status; + unsigned char osd_name[16]; + struct input_dev *remote_cec_dev; /* cec input device */ + struct hdmitx_dev *hdmitx_device; +}; + +enum cec_device_menu_state_e { + DEVICE_MENU_ACTIVE = 0, + DEVICE_MENU_INACTIVE, +}; + +int cec_ll_tx(const unsigned char *msg, unsigned char len); +int cec_ll_rx(unsigned char *msg, unsigned char *len); +#endif + diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_compliance.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_compliance.h new file mode 100644 index 000000000000..609e3a663d8c --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_compliance.h @@ -0,0 +1,28 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_compliance.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMI_TX_COMPLIANCE_H +#define __HDMI_TX_COMPLIANCE_H + +#include "hdmi_info_global.h" +#include "hdmi_tx_module.h" + +void hdmitx_special_handler_video(struct hdmitx_dev *hdmitx_device); +void hdmitx_special_handler_audio(struct hdmitx_dev *hdmitx_device); + +#endif + diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h new file mode 100644 index 000000000000..2a13f18f00b9 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h @@ -0,0 +1,93 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMI_TX_DDC_H__ +#define __HDMI_TX_DDC_H__ + +#include + +#define EDID_SLAVE 0x50 + #define EDIDSEG_ADR 0x30 +#define HDCP_SLAVE 0x3a +#define SCDC_SLAVE 0x54 + +/* Little-Endian format */ +enum scdc_addr { + SINK_VER = 0x01, + SOURCE_VER, /* RW */ + UPDATE_0 = 0x10, /* RW */ + UPDATE_1, /* RW */ + TMDS_CFG = 0x20, /* RW */ + SCRAMBLER_ST, + CONFIG_0 = 0x30, /* RW */ + STATUS_FLAGS_0 = 0x40, + STATUS_FLAGS_1, + ERR_DET_0_L = 0x50, + ERR_DET_0_H, + ERR_DET_1_L, + ERR_DET_1_H, + ERR_DET_2_L, + ERR_DET_2_H, + ERR_DET_CHKSUM, + TEST_CONFIG_0 = 0xC0, /* RW */ + MANUFACT_IEEE_OUI_2 = 0xD0, + MANUFACT_IEEE_OUI_1, + MANUFACT_IEEE_OUI_0, + DEVICE_ID = 0xD3, /* 0xD3 ~ 0xDD */ + /* RW 0xDE ~ 0xFF */ + MANUFACT_SPECIFIC = 0xDE, +}; + +enum hdcp_addr { + HDCP14_BKSV = 0x00, + HDCP14_RI_ = 0x08, + HDCP14_PJ_ = 0x0a, + HDCP14_AKSV = 0x10, + HDCP14_AINFO = 0x15, + HDCP14_AN = 0x18, + HDCP14_V_H0 = 0x20, + HDCP14_V_H1 = 0x24, + HDCP14_V_H2 = 0x28, + HDCP14_V_H3 = 0x2C, + HDCP14_V_H4 = 0x30, + HDCP14_BCAPS = 0x40, + HDCP14_BSTATUS = 0x41, + HDCP14_KSV_FIFO = 0x43, + HDCP2_VERSION = 0x50, + HDCP2_WR_MSG = 0x60, + HDCP2_RXSTATUS = 0x70, + HDCP2_RD_MSG = 0x80, + HDCP2_DBG = 0xC0, +}; + +/* + * HDMITX DDC HW related operations + */ +enum ddc_op { + DDC_INIT_DISABLE_PULL_UP_DN, + DDC_MUX_DDC, + DDC_UNMUX_DDC, +}; +int hdmitx_ddc_hw_op(enum ddc_op cmd); + +void scdc_rd_sink(uint8_t adr, uint8_t *val); +void scdc_wr_sink(uint8_t adr, uint8_t val); +uint32_t hdcp_rd_hdcp14_ver(void); +uint32_t hdcp_rd_hdcp22_ver(void); +void scdc_config(void *hdev); + +#endif /* __HDMI_TX_SCDC_H__ */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h new file mode 100644 index 000000000000..3657e8489fb8 --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h @@ -0,0 +1,24 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMI_TX_EXT_H__ +#define __HDMI_TX_EXT_H__ + +void direct_hdcptx14_start(void); +void direct_hdcptx14_stop(void); + +#endif diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h new file mode 100644 index 000000000000..c28dc5811c0a --- /dev/null +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -0,0 +1,592 @@ +/* + * include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _HDMI_TX_MODULE_H +#define _HDMI_TX_MODULE_H +#include "hdmi_info_global.h" +#include "hdmi_config.h" +#include +#include +#include +#include +#include +/* #include */ + +/***************************** + * hdmitx attr management + ******************************/ + +/************************************ + * hdmitx device structure + *************************************/ +/* VIC_MAX_VALID_MODE and VIC_MAX_NUM are associated with + * HDMITX_VIC420_OFFSET and HDMITX_VIC_MASK in hdmi_common.h + */ +#define VIC_MAX_VALID_MODE 256 /* consider 4k2k */ +/* half for valid vic, half for vic with y420*/ +#define VIC_MAX_NUM 512 +#define AUD_MAX_NUM 60 +struct rx_audiocap { + unsigned char audio_format_code; + unsigned char channel_num_max; + unsigned char freq_cc; + unsigned char cc3; +}; + +enum hd_ctrl { + VID_EN, VID_DIS, AUD_EN, AUD_DIS, EDID_EN, EDID_DIS, HDCP_EN, HDCP_DIS, +}; + +struct rx_cap { + unsigned int native_Mode; + /*video*/ + unsigned int VIC[VIC_MAX_NUM]; + unsigned int VIC_count; + unsigned int native_VIC; + /*audio*/ + struct rx_audiocap RxAudioCap[AUD_MAX_NUM]; + unsigned char AUD_count; + unsigned char RxSpeakerAllocation; + /*vendor*/ + unsigned int IEEEOUI; + unsigned int Max_TMDS_Clock1; /* HDMI1.4b TMDS_CLK */ + unsigned int HF_IEEEOUI; /* For HDMI Forum */ + unsigned int Max_TMDS_Clock2; /* HDMI2.0 TMDS_CLK */ + /* CEA861-F, Table 56, Colorimetry Data Block */ + unsigned int colorimetry_data; + unsigned int scdc_present:1; + unsigned int scdc_rr_capable:1; /* SCDC read request */ + unsigned int lte_340mcsc_scramble:1; + unsigned int dc_y444:1; + unsigned int dc_30bit:1; + unsigned int dc_36bit:1; + unsigned int dc_48bit:1; + unsigned int dc_30bit_420:1; + unsigned int dc_36bit_420:1; + unsigned int dc_48bit_420:1; + unsigned int hdr_sup_eotf_sdr:1; + unsigned int hdr_sup_eotf_hdr:1; + unsigned int hdr_sup_eotf_smpte_st_2084:1; + unsigned int hdr_sup_eotf_future:1; + unsigned int hdr_sup_SMD_type1:1; + unsigned char hdr_lum_max; + unsigned char hdr_lum_avg; + unsigned char hdr_lum_min; + unsigned char ReceiverBrandName[4]; + unsigned char ReceiverProductName[16]; + unsigned char manufacture_week; + unsigned char manufacture_year; + unsigned char edid_version; + unsigned char edid_revision; + unsigned int ColorDeepSupport; + unsigned int Video_Latency; + unsigned int Audio_Latency; + unsigned int Interlaced_Video_Latency; + unsigned int Interlaced_Audio_Latency; + unsigned int threeD_present; + unsigned int threeD_Multi_present; + unsigned int hdmi_vic_LEN; + unsigned int HDMI_3D_LEN; + unsigned int threeD_Structure_ALL_15_0; + unsigned int threeD_MASK_15_0; + struct { + unsigned char frame_packing; + unsigned char top_and_bottom; + unsigned char side_by_side; + } support_3d_format[VIC_MAX_NUM]; + struct dv_info dv_info; + enum hdmi_vic preferred_mode; + struct dtd dtd[16]; + unsigned char dtd_idx; + unsigned char flag_vfpdb; + unsigned char number_of_dtd; + /*blk0 check sum*/ + unsigned char blk0_chksum; +}; + +struct cts_conftab { + unsigned int fixed_n; + unsigned int tmds_clk; + unsigned int fixed_cts; +}; + +struct vic_attrmap { + enum hdmi_vic VIC; + unsigned int tmds_clk; +}; + +enum hdmi_event_t { + HDMI_TX_NONE = 0, + HDMI_TX_HPD_PLUGIN = 1, + HDMI_TX_HPD_PLUGOUT = 2, + HDMI_TX_INTERNAL_INTR = 4, +}; + +struct hdmi_phy_t { + unsigned long reg; + unsigned long val_sleep; + unsigned long val_save; +}; + +struct audcts_log { + unsigned int val:20; + unsigned int stable:1; +}; + +struct frac_rate_table { + char *hz; + u32 sync_num_int; + u32 sync_den_int; + u32 sync_num_dec; + u32 sync_den_dec; +}; +#define EDID_MAX_BLOCK 4 +#define HDMI_TMP_BUF_SIZE 1024 +struct hdmitx_dev { + struct cdev cdev; /* The cdev structure */ + struct proc_dir_entry *proc_file; + struct task_struct *task; + struct task_struct *task_monitor; + struct task_struct *task_hdcp; + struct task_struct *task_cec; + struct notifier_block nb; + struct workqueue_struct *hdmi_wq; + struct device *hdtx_dev; + struct delayed_work work_hpd_plugin; + struct delayed_work work_hpd_plugout; + struct work_struct work_internal_intr; + struct work_struct work_hdr; + struct timer_list hdcp_timer; + const char *hpd_pin; + const char *ddc_pin; + int hdcp_try_times; + /* -1, no hdcp; 0, NULL; 1, 1.4; 2, 2.2 */ + int hdcp_mode; + int ready; /* 1, hdmi stable output, others are 0 */ + int hdcp_hpd_stick; /* 1 not init & reset at plugout */ + struct { + void (*SetPacket)(int type, unsigned char *DB, + unsigned char *HB); + void (*SetAudioInfoFrame)(unsigned char *AUD_DB, + unsigned char *CHAN_STAT_BUF); + int (*SetDispMode)(struct hdmitx_dev *hdmitx_device); + int (*SetAudMode)(struct hdmitx_dev *hdmitx_device, + struct hdmitx_audpara *audio_param); + void (*SetupIRQ)(struct hdmitx_dev *hdmitx_device); + void (*DebugFun)(struct hdmitx_dev *hdmitx_device, + const char *buf); + void (*UnInit)(struct hdmitx_dev *hdmitx_device); + int (*CntlPower)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, unsigned int arg); /* Power control */ + /* edid/hdcp control */ + int (*CntlDDC)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, unsigned long arg); + /* Audio/Video/System Status */ + int (*GetState)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, unsigned int arg); + int (*CntlPacket)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, + unsigned int arg); /* Packet control */ + int (*CntlConfig)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, + unsigned int arg); /* Configure control */ + int (*CntlMisc)(struct hdmitx_dev *hdmitx_device, + unsigned int cmd, unsigned int arg); /* Other control */ + int (*Cntl)(struct hdmitx_dev *hdmitx_device, unsigned int cmd, + unsigned int arg); /* Other control */ + } HWOp; + struct { + unsigned int hdcp14_en; + unsigned int hdcp14_rslt; + } hdcpop; + struct hdmi_config_platform_data config_data; + enum hdmi_event_t hdmitx_event; + unsigned int irq_hpd; + unsigned int irq_cec; + /* wait_queue_head_t wait_queue;*/ + /*EDID*/ + unsigned int cur_edid_block; + unsigned int cur_phy_block_ptr; + unsigned char EDID_buf[EDID_MAX_BLOCK * 128]; + unsigned char EDID_buf1[EDID_MAX_BLOCK*128]; /* for second read */ + unsigned char *edid_ptr; + unsigned int edid_parsing; /* Indicator that RX edid data integrated */ + unsigned char EDID_hash[20]; + struct rx_cap RXCap; + struct hdmitx_vidpara *cur_video_param; + int vic_count; + /*audio*/ + struct hdmitx_audpara cur_audio_param; + int audio_param_update_flag; + /*status*/ +#define DISP_SWITCH_FORCE 0 +#define DISP_SWITCH_EDID 1 + unsigned char disp_switch_config; /* 0, force; 1,edid */ + unsigned int cur_VIC; + unsigned char unplug_powerdown; + /**/ + unsigned char hpd_event; /* 1, plugin; 2, plugout */ + unsigned char hpd_state; /* 1, connect; 0, disconnect */ + unsigned char force_audio_flag; + unsigned char mux_hpd_if_pin_high_flag; + unsigned char cec_func_flag; + int auth_process_timer; + struct hdmitx_info hdmi_info; + unsigned char tmp_buf[HDMI_TMP_BUF_SIZE]; + unsigned int log; + unsigned int cec_func_config; + unsigned int cec_init_ready; + unsigned int tv_cec_support; + unsigned int tx_aud_cfg; /* 0, off; 1, on */ + /* For some un-well-known TVs, no edid at all */ + unsigned int tv_no_edid; + unsigned int hpd_lock; + struct hdmi_format_para *para; + /* 0: RGB444 1: Y444 2: Y422 3: Y420 */ + /* 4: 24bit 5: 30bit 6: 36bit 7: 48bit */ + /* if equals to 1, means current video & audio output are blank */ + unsigned int output_blank_flag; + unsigned int audio_notify_flag; + unsigned int audio_step; + unsigned int frac_rate_policy; + /* configure for I2S: 8ch in, 2ch out */ + /* 0: default setting 1:ch0/1 2:ch2/3 3:ch4/5 4:ch6/7 */ + unsigned int aud_output_ch; + unsigned int hdr_src_feature; + unsigned int flag_3dfp:1; + unsigned int flag_3dtb:1; + unsigned int flag_3dss:1; +}; + +#define CMD_DDC_OFFSET (0x10 << 24) +#define CMD_STATUS_OFFSET (0x11 << 24) +#define CMD_PACKET_OFFSET (0x12 << 24) +#define CMD_MISC_OFFSET (0x13 << 24) +#define CMD_CONF_OFFSET (0x14 << 24) +#define CMD_STAT_OFFSET (0x15 << 24) + +/*********************************************************************** + * DDC CONTROL //CntlDDC + **********************************************************************/ +#define DDC_RESET_EDID (CMD_DDC_OFFSET + 0x00) +#define DDC_RESET_HDCP (CMD_DDC_OFFSET + 0x01) +#define DDC_HDCP_OP (CMD_DDC_OFFSET + 0x02) + #define HDCP14_ON 0x1 + #define HDCP14_OFF 0x2 + #define HDCP22_ON 0x3 + #define HDCP22_OFF 0x4 +#define DDC_HDCP_BYP (CMD_DDC_OFFSET + 0x03) +#define DDC_IS_HDCP_ON (CMD_DDC_OFFSET + 0x04) +#define DDC_HDCP_GET_AKSV (CMD_DDC_OFFSET + 0x05) +#define DDC_HDCP_GET_BKSV (CMD_DDC_OFFSET + 0x06) +#define DDC_HDCP_GET_AUTH (CMD_DDC_OFFSET + 0x07) +#define DDC_PIN_MUX_OP (CMD_DDC_OFFSET + 0x08) +#define PIN_MUX 0x1 +#define PIN_UNMUX 0x2 +#define DDC_EDID_READ_DATA (CMD_DDC_OFFSET + 0x0a) +#define DDC_IS_EDID_DATA_READY (CMD_DDC_OFFSET + 0x0b) +#define DDC_EDID_GET_DATA (CMD_DDC_OFFSET + 0x0c) +#define DDC_EDID_CLEAR_RAM (CMD_DDC_OFFSET + 0x0d) +#define DDC_HDCP_MUX_INIT (CMD_DDC_OFFSET + 0x0e) +#define DDC_HDCP_14_LSTORE (CMD_DDC_OFFSET + 0x0f) +#define DDC_HDCP_22_LSTORE (CMD_DDC_OFFSET + 0x10) +#define DDC_SCDC_DIV40_SCRAMB (CMD_DDC_OFFSET + 0x20) + +/*********************************************************************** + * CONFIG CONTROL //CntlConfig + **********************************************************************/ +/* Video part */ +#define CONF_VIDEO_BLANK_OP (CMD_CONF_OFFSET + 0x00) +#define VIDEO_BLANK 0x1 +#define VIDEO_UNBLANK 0x2 +#define CONF_HDMI_DVI_MODE (CMD_CONF_OFFSET + 0x02) +#define HDMI_MODE 0x1 +#define DVI_MODE 0x2 +#define CONF_SYSTEM_ST (CMD_CONF_OFFSET + 0x03) +/* Audio part */ +#define CONF_CLR_AVI_PACKET (CMD_CONF_OFFSET + 0x04) +#define CONF_CLR_VSDB_PACKET (CMD_CONF_OFFSET + 0x05) +#define CONF_VIDEO_MAPPING (CMD_CONF_OFFSET + 0x06) +#define CONF_GET_HDMI_DVI_MODE (CMD_CONF_OFFSET + 0x07) + +#define CONF_AUDIO_MUTE_OP (CMD_CONF_OFFSET + 0x1000 + 0x00) +#define AUDIO_MUTE 0x1 +#define AUDIO_UNMUTE 0x2 +#define CONF_CLR_AUDINFO_PACKET (CMD_CONF_OFFSET + 0x1000 + 0x01) +#define CONF_AVI_BT2020 (CMD_CONF_OFFSET + 0X2000 + 0x00) + #define CLR_AVI_BT2020 0x0 + #define SET_AVI_BT2020 0x1 +/* set value as COLORSPACE_RGB444, YUV422, YUV444, YUV420 */ +#define CONF_AVI_RGBYCC_INDIC (CMD_CONF_OFFSET + 0X2000 + 0x01) +#define CONF_AVI_Q01 (CMD_CONF_OFFSET + 0X2000 + 0x02) + #define RGB_RANGE_DEFAULT 0 + #define RGB_RANGE_LIM 1 + #define RGB_RANGE_FUL 2 + #define RGB_RANGE_RSVD 3 +#define CONF_AVI_YQ01 (CMD_CONF_OFFSET + 0X2000 + 0x03) + #define YCC_RANGE_LIM 0 + #define YCC_RANGE_FUL 1 + #define YCC_RANGE_RSVD 2 + +/*********************************************************************** + * MISC control, hpd, hpll //CntlMisc + **********************************************************************/ +#define MISC_HPD_MUX_OP (CMD_MISC_OFFSET + 0x00) +#define MISC_HPD_GPI_ST (CMD_MISC_OFFSET + 0x02) +#define MISC_HPLL_OP (CMD_MISC_OFFSET + 0x03) +#define HPLL_ENABLE 0x1 +#define HPLL_DISABLE 0x2 +#define HPLL_SET 0x3 +#define MISC_TMDS_PHY_OP (CMD_MISC_OFFSET + 0x04) +#define TMDS_PHY_ENABLE 0x1 +#define TMDS_PHY_DISABLE 0x2 +#define MISC_VIID_IS_USING (CMD_MISC_OFFSET + 0x05) +#define MISC_TMDS_CLK_DIV40 (CMD_MISC_OFFSET + 0x07) +#define MISC_COMP_HPLL (CMD_MISC_OFFSET + 0x08) +#define COMP_HPLL_SET_OPTIMISE_HPLL1 0x1 +#define COMP_HPLL_SET_OPTIMISE_HPLL2 0x2 +#define MISC_COMP_AUDIO (CMD_MISC_OFFSET + 0x09) +#define COMP_AUDIO_SET_N_6144x2 0x1 +#define COMP_AUDIO_SET_N_6144x3 0x2 +#define MISC_AVMUTE_OP (CMD_MISC_OFFSET + 0x0a) +#define MISC_FINE_TUNE_HPLL (CMD_MISC_OFFSET + 0x0b) + #define OFF_AVMUTE 0x0 + #define CLR_AVMUTE 0x1 + #define SET_AVMUTE 0x2 +#define MISC_HPLL_FAKE (CMD_MISC_OFFSET + 0x0c) +#define MISC_ESM_RESET (CMD_MISC_OFFSET + 0x0d) +#define MISC_HDCP_CLKDIS (CMD_MISC_OFFSET + 0x0e) + +/*********************************************************************** + * Get State //GetState + **********************************************************************/ +#define STAT_VIDEO_VIC (CMD_STAT_OFFSET + 0x00) +#define STAT_VIDEO_CLK (CMD_STAT_OFFSET + 0x01) +#define STAT_AUDIO_FORMAT (CMD_STAT_OFFSET + 0x10) +#define STAT_AUDIO_CHANNEL (CMD_STAT_OFFSET + 0x11) +#define STAT_AUDIO_CLK_STABLE (CMD_STAT_OFFSET + 0x12) +#define STAT_AUDIO_PACK (CMD_STAT_OFFSET + 0x13) + +/* HDMI LOG */ +#define HDMI_LOG_HDCP (1 << 0) + +#define HDMI_SOURCE_DESCRIPTION 0 +#define HDMI_PACKET_VEND 1 +#define HDMI_MPEG_SOURCE_INFO 2 +#define HDMI_PACKET_AVI 3 +#define HDMI_AUDIO_INFO 4 +#define HDMI_AUDIO_CONTENT_PROTECTION 5 +#define HDMI_PACKET_HBR 6 +#define HDMI_PACKET_DRM 0x86 + +#define HDMI_PROCESS_DELAY msleep(10) +/* reduce a little time, previous setting is 4000/10 */ +#define AUTH_PROCESS_TIME (1000/100) + +#define HDMITX_VER "2014May6" + +/*********************************************************************** + * hdmitx protocol level interface + **********************************************************************/ +extern void hdmitx_init_parameters(struct hdmitx_info *info); +extern enum hdmi_vic hdmitx_edid_vic_tab_map_vic(const char *disp_mode); + +extern int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device); +extern int check_dvi_hdmi_edid_valid(unsigned char *buf); + +enum hdmi_vic hdmitx_edid_get_VIC(struct hdmitx_dev *hdmitx_device, + const char *disp_mode, char force_flag); + +extern int hdmitx_edid_VIC_support(enum hdmi_vic vic); + +extern int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, + int buffer_len); +bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, + struct hdmi_format_para *para); +extern const char *hdmitx_edid_vic_to_string(enum hdmi_vic vic); +extern void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device); + +extern void hdmitx_edid_ram_buffer_clear(struct hdmitx_dev *hdmitx_device); + +extern void hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device); + +extern const char *hdmitx_edid_get_native_VIC(struct hdmitx_dev *hdmitx_device); + +/* + * HDMI Repeater TX I/F + * RX downstream Information from rptx to rprx + */ +/* send part raw edid from TX to RX */ +extern void rx_repeat_hpd_state(unsigned int st); +/* prevent compile error in no HDMIRX case */ +void __attribute__((weak))rx_repeat_hpd_state(unsigned int st) +{ +} + +extern void rx_edid_physical_addr(unsigned char a, unsigned char b, + unsigned char c, unsigned char d); +void __attribute__((weak))rx_edid_physical_addr(unsigned char a, + unsigned char b, unsigned char c, unsigned char d) +{ +} + +extern void rx_set_repeater_support(bool enable); +void __attribute__((weak))rx_set_repeater_support(bool enable) +{ +} + +extern void rx_set_receiver_edid(unsigned char *data, int len); +void __attribute__((weak))rx_set_receiver_edid(unsigned char *data, int len) +{ +} + +/* + * ver = 22 means downstream supports HDCP22 + * ver = 14 means support HDCP14 + * ver = 0 means support NO HDCP + */ +extern void rx_repeat_hdcp_ver(unsigned int ver); +void __attribute__((weak))rx_repeat_hdcp_ver(unsigned int ver) +{ +} + +extern void rx_set_receive_hdcp(unsigned char *data, int len, int depth, + bool max_cascade, bool max_devs); +void __attribute__((weak))rx_set_receive_hdcp(unsigned char *data, int len, + int depth, bool max_cascade, bool max_devs) +{ +} + +extern int hdmitx_set_display(struct hdmitx_dev *hdmitx_device, + enum hdmi_vic VideoCode); + +extern int hdmi_set_3d(struct hdmitx_dev *hdmitx_device, int type, + unsigned int param); + +extern int hdmitx_set_audio(struct hdmitx_dev *hdmitx_device, + struct hdmitx_audpara *audio_param, int hdmi_ch); + +#ifdef CONFIG_AMLOGIC_HDMITX +extern struct hdmitx_dev *get_hdmitx_device(void); +#else +static inline struct hdmitx_dev *get_hdmitx_device(void) +{ + return NULL; +} +#endif + +extern int hdmi_print_buf(char *buf, int len); + +extern void hdmi_set_audio_para(int para); + +extern void hdmitx_output_rgb(void); + +extern int get_cur_vout_index(void); +extern struct vinfo_s *hdmi_get_current_vinfo(void); +void phy_pll_off(void); + + +extern int get_hpd_state(void); + + +/*********************************************************************** + * hdmitx hardware level interface + ***********************************************************************/ +/* #define DOUBLE_CLK_720P_1080I */ +extern unsigned char hdmi_pll_mode; /* 1, use external clk as hdmi pll source */ + +extern void HDMITX_Meson_Init(struct hdmitx_dev *hdmitx_device); + +extern unsigned char hdmi_audio_off_flag; +/* + * hdmitx_audio_mute_op() is used by external driver call + * flag: 0: audio off 1: audio_on + * 2: for EDID auto mode + */ +extern void hdmitx_audio_mute_op(unsigned int flag); + +#define HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH 0x3 +#define HDMITX_HWCMD_TURNOFF_HDMIHW 0x4 +#define HDMITX_HWCMD_MUX_HPD 0x5 +#define HDMITX_HWCMD_PLL_MODE 0x6 +#define HDMITX_HWCMD_TURN_ON_PRBS 0x7 +#define HDMITX_FORCE_480P_CLK 0x8 +#define HDMITX_GET_AUTHENTICATE_STATE 0xa +#define HDMITX_SW_INTERNAL_HPD_TRIG 0xb +#define HDMITX_HWCMD_OSD_ENABLE 0xf + +#define HDMITX_HDCP_MONITOR 0x11 +#define HDMITX_IP_INTR_MASN_RST 0x12 +#define HDMITX_EARLY_SUSPEND_RESUME_CNTL 0x14 +#define HDMITX_EARLY_SUSPEND 0x1 +#define HDMITX_LATE_RESUME 0x2 +/* Refer to HDMI_OTHER_CTRL0 in hdmi_tx_reg.h */ +#define HDMITX_IP_SW_RST 0x15 +#define TX_CREG_SW_RST (1<<5) +#define TX_SYS_SW_RST (1<<4) +#define CEC_CREG_SW_RST (1<<3) +#define CEC_SYS_SW_RST (1<<2) +#define HDMITX_AVMUTE_CNTL 0x19 +#define AVMUTE_SET 0 /* set AVMUTE to 1 */ +#define AVMUTE_CLEAR 1 /* set AVunMUTE to 1 */ +#define AVMUTE_OFF 2 /* set both AVMUTE and AVunMUTE to 0 */ +#define HDMITX_CBUS_RST 0x1A +#define HDMITX_INTR_MASKN_CNTL 0x1B +#define INTR_MASKN_ENABLE 0 +#define INTR_MASKN_DISABLE 1 +#define INTR_CLEAR 2 + +#define HDMI_HDCP_DELAYTIME_AFTER_DISPLAY 20 /* unit: ms */ + +#define HDMITX_HDCP_MONITOR_BUF_SIZE 1024 +struct Hdcp_Sub { + char *hdcp_sub_name; + unsigned int hdcp_sub_addr_start; + unsigned int hdcp_sub_len; +}; + +/*********************************************************************** + * hdmi debug printk + * level: 0 ~ 4 Default is 2 + * 0: ERRor 1: IMPortant 2: INFormative 3: DETtal 4: LOW + * hdmi_print(ERR, EDID "edid bad\"); + * hdmi_print(IMP, AUD "set audio format: AC-3\n"); + * hdmi_print(DET) + **********************************************************************/ +#define HD "hdmitx: " +#define VID HD "video: " +#define AUD HD "audio: " +#define CEC HD "cec: " +#define EDID HD "edid: " +#define HDCP HD "hdcp: " +#define SYS HD "system: " +#define HPD HD "hpd: " + +#define ERR 1 +#define IMP 2 +#define INF 3 +#define LOW 4 +#define DET (5, "%s[%d]", __func__, __LINE__) + +extern void hdmi_print(int level, const char *fmt, ...); + +#define dd() +#ifndef dd +#error delete debug information +#endif +#endif + diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index 9b6a8bbdd0b0..9275929bb4d3 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -49,6 +49,56 @@ struct master_display_info_s { u32 primaries[3][2]; /* normalized 50000 in G,B,R order */ u32 white_point[2]; /* normalized 50000 */ u32 luminance[2]; /* max/min lumin, normalized 10000 */ + u32 max_content; /* Maximum Content Light Level */ + u32 max_frame_average; /* Maximum Frame-average Light Level */ +}; +struct hdr_info { + u32 hdr_support; /* RX EDID hdr support types */ + u32 lumi_max; /* RX EDID Lumi Max value */ + u32 lumi_avg; /* RX EDID Lumi Avg value */ + u32 lumi_min; /* RX EDID Lumi Min value */ +}; +enum eotf_type { + EOTF_T_NULL = 0, + EOTF_T_DOLBYVISION, + EOTF_T_HDR10, + EOTF_T_SDR, + EOTF_T_MAX, +}; +struct dv_info { + uint32_t ieeeoui; + uint8_t ver; /* 0 or 1 */ + uint8_t sup_yuv422_12bit:1; /* if as 0, then support RGB tunnel mode */ + uint8_t sup_2160p60hz:1; /* if as 0, then support 2160p30hz */ + uint8_t sup_global_dimming:1; + uint8_t colorimetry:1; + union { + struct { + uint16_t chrom_red_primary_x; + uint16_t chrom_red_primary_y; + uint16_t chrom_green_primary_x; + uint16_t chrom_green_primary_y; + uint16_t chrom_blue_primary_x; + uint16_t chrom_blue_primary_y; + uint16_t chrom_white_primary_x; + uint16_t chrom_white_primary_y; + uint16_t target_min_pq; + uint16_t target_max_pq; + uint8_t dm_major_ver; + uint8_t dm_minor_ver; + } ver0; + struct { + uint8_t dm_version; + uint8_t target_max_lum; + uint8_t target_min_lum; + uint8_t chrom_red_primary_x; + uint8_t chrom_red_primary_y; + uint8_t chrom_green_primary_x; + uint8_t chrom_green_primary_y; + uint8_t chrom_blue_primary_x; + uint8_t chrom_blue_primary_y; + } ver1; + } vers; }; struct vinfo_s { @@ -68,6 +118,10 @@ struct vinfo_s { enum color_fmt_e viu_color_fmt; enum viu_mux_e viu_mux; struct master_display_info_s master_display_info; + struct hdr_info hdr_info; + const struct dv_info *dv_info; + void (*fresh_tx_hdr_pkt)(struct master_display_info_s *data); + void (*fresh_tx_vsif_pkt)(enum eotf_type type, uint8_t tunnel_mode); void *vout_device; }; diff --git a/include/linux/amlogic/media/vout/vout_notify.h b/include/linux/amlogic/media/vout/vout_notify.h index 3aa93ed94de3..f791ba4b554e 100644 --- a/include/linux/amlogic/media/vout/vout_notify.h +++ b/include/linux/amlogic/media/vout/vout_notify.h @@ -1,7 +1,7 @@ /* * include/linux/amlogic/media/vout/vout_notify.h * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by