/* * hdmi2.0.h: hdmi2.0 driver. * * Copyright (c) 2014-2018, NVIDIA CORPORATION, All rights reserved. * Author: Animesh Kishore * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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 __DRIVERS_VIDEO_TEGRA_DC_HDMI2_0_H__ #define __DRIVERS_VIDEO_TEGRA_DC_HDMI2_0_H__ #include #define HDMI_HPD_DEBOUNCE_DELAY_MS (100) #define HDMI_SCDC_MONITOR_TIMEOUT_MS (5000) #define HDMI_EDID_MAX_LENGTH (4 * EDID_BYTES_PER_BLOCK) #define HDMI_HDR_INFOFRAME_STOP_TIMEOUT_MS (2000) #define HDMI_HPD_DEBOUNCE_WAR_DELAY_MS (4000) /* SCDC block */ #define HDMI_SCDC_TMDS_CONFIG_OFFSET (0x20) #define HDMI_SCDC_TMDS_CONFIG_SCRAMBLING_EN (1) #define HDMI_SCDC_TMDS_CONFIG_SCRAMBLING_DIS (1) #define HDMI_SCDC_TMDS_CONFIG_BIT_CLK_RATIO_10 (0 << 1) #define HDMI_SCDC_TMDS_CONFIG_BIT_CLK_RATIO_40 (1 << 1) #define HDMI_SCDC_STATUS_FLAGS (0x21) #define HDMI_SCDC_STATUS_FLAGS_SCRAMBLING_EN (1) #define HDMI_SCDC_STATUS_FLAGS_SCRAMBLING_DIS (0) enum { HDMI_INFOFRAME_TYPE_VENDOR = 0x81, HDMI_INFOFRAME_TYPE_AVI = 0x82, HDMI_INFOFRAME_TYPE_SPD = 0x83, HDMI_INFOFRAME_TYPE_AUDIO = 0x84, HDMI_INFOFRAME_TYPE_MPEG_SRC = 0x85, HDMI_INFOFRAME_TYPE_HDR = 0x87, }; enum { HDMI_INFOFRAME_VS_VENDOR = 0x1, HDMI_INFOFRAME_VS_AVI = 0x2, HDMI_INFOFRAME_VS_SPD = 0x1, HDMI_INFOFRAME_VS_AUDIO = 0x1, HDMI_INFOFRAME_VS_MPEG_SRC = 0x1, HDMI_INFOFRAME_VS_HDR = 0x1, }; /* excluding checksum and header bytes */ enum { HDMI_INFOFRAME_LEN_VENDOR, /* vendor specific */ HDMI_INFOFRAME_LEN_AVI = 13, HDMI_INFOFRAME_LEN_SPD = 25, HDMI_INFOFRAME_LEN_AUDIO = 10, HDMI_INFOFRAME_LEN_MPEG_SRC = 10, HDMI_INFOFRAME_LEN_HDR = 26, }; enum { HDMI_AVI_SCAN_NO_INFO = 0x0, HDMI_AVI_OVERSCAN = 0x1, HDMI_AVI_UNDERSCAN = 0x2, }; enum { HDMI_AVI_BAR_INVALID = 0x0, HDMI_AVI_VERT_BAR_VALID = 0x1, HDMI_AVI_HOR_BAR_VALID = 0x2, HDMI_AVI_VERT_HOR_BAR_VALID = 0x3, }; enum { HDMI_AVI_ACTIVE_FORMAT_INVALID = 0x0, HDMI_AVI_ACTIVE_FORMAT_VALID = 0x1, }; enum { HDMI_AVI_RGB = 0x0, HDMI_AVI_YCC_422 = 0x1, HDMI_AVI_YCC_444 = 0x2, HDMI_AVI_YCC_420 = 0x3, }; enum { HDMI_AVI_ACTIVE_FORMAT_SAME = 0x8, HDMI_AVI_ACTIVE_FORMAT_4_3_CENTER = 0x9, HDMI_AVI_ACTIVE_FORMAT_16_9_CENTER = 0xa, HDMI_AVI_ACTIVE_FORMAT_14_9_CENTER = 0xb, }; enum { HDMI_AVI_ASPECT_RATIO_NO_DATA = 0x0, HDMI_AVI_ASPECT_RATIO_4_3 = 0x1, HDMI_AVI_ASPECT_RATIO_16_9 = 0x2, }; enum { HDMI_AVI_COLORIMETRY_DEFAULT = 0x0, HDMI_AVI_COLORIMETRY_SMPTE170M_ITU601 = 0x1, HDMI_AVI_COLORIMETRY_ITU709 = 0x2, HDMI_AVI_COLORIMETRY_EXTENDED_VALID = 0x3, }; enum { HDMI_AVI_SCALING_UNKNOWN = 0x0, HDMI_AVI_SCALING_HOR = 0x1, HDMI_AVI_SCALING_VERT = 0x2, HDMI_AVI_SCALING_VERT_HOR = 0x3, }; enum { HDMI_AVI_RGB_QUANT_DEFAULT = 0x0, HDMI_AVI_RGB_QUANT_LIMITED = 0x1, HDMI_AVI_RGB_QUANT_FULL = 0x2, }; enum { HDMI_AVI_EXT_COLORIMETRY_INVALID = 0x0, HDMI_AVI_EXT_COLORIMETRY_xvYCC601 = 0x0, HDMI_AVI_EXT_COLORIMETRY_xvYCC709 = 0x1, HDMI_AVI_EXT_COLORIMETRY_sYCC601 = 0x2, HDMI_AVI_EXT_COLORIMETRY_ADOBE_YCC601 = 0x3, HDMI_AVI_EXT_COLORIMETRY_ADOBE_RGB = 0x4, HDMI_AVI_EXT_COLORIMETRY_BT2020_CYCC = 0x5, HDMI_AVI_EXT_COLORIMETRY_BT2020_YCC_RGB = 0x6, }; enum { HDMI_AVI_IT_CONTENT_FALSE = 0x0, HDMI_AVI_IT_CONTENT_TRUE = 0x0, }; enum { HDMI_AVI_NO_PIX_REPEAT = 0x0, }; enum { HDMI_AVI_IT_CONTENT_NONE = 0x0, HDMI_AVI_IT_CONTENT_GRAPHICS = 0x0, HDMI_AVI_IT_CONTENT_PHOTO = 0x1, HDMI_AVI_IT_CONTENT_CINEMA = 0x2, HDMI_AVI_IT_CONTENT_GAME = 0x3, }; enum { HDMI_AVI_YCC_QUANT_NONE = 0x0, HDMI_AVI_YCC_QUANT_LIMITED = 0x0, HDMI_AVI_YCC_QUANT_FULL = 0x1, }; /* all fields little endian */ struct hdmi_avi_infoframe { /* PB0 */ u32 csum:8; /* checksum */ /* PB1 */ u32 scan:2; /* scan information */ u32 bar_valid:2; /* bar info data valid */ u32 act_fmt_valid:1; /* active info present */ u32 rgb_ycc:2; /* RGB or YCbCr */ u32 res1:1; /* reserved */ /* PB2 */ u32 act_format:4; /* active format aspect ratio */ u32 aspect_ratio:2; /* picture aspect ratio */ u32 colorimetry:2; /* colorimetry */ /* PB3 */ u32 scaling:2; /* non-uniform picture scaling */ u32 rgb_quant:2; /* rgb quantization range */ u32 ext_colorimetry:3; /* extended colorimetry */ u32 it_content:1; /* it content */ /* PB4 */ u32 video_format:7; /* video format id code */ u32 res4:1; /* reserved */ /* PB5 */ u32 pix_rep:4; /* pixel repetition factor */ u32 it_content_type:2; /* it content type */ u32 ycc_quant:2; /* YCbCr quantization range */ /* PB6-7 */ u32 top_bar_end_line_low_byte:8; u32 reg_hole1:8; u32 top_bar_end_line_high_byte:8; /* PB8-9 */ u32 bot_bar_start_line_low_byte:8; u32 bot_bar_start_line_high_byte:8; /* PB10-11 */ u32 left_bar_end_pixel_low_byte:8; u32 left_bar_end_pixel_high_byte:8; /* PB12-13 */ u32 right_bar_start_pixel_low_byte:8; u32 right_bar_start_pixel_high_byte:8; u32 reg_hole2:8; } __packed; struct hdmi_hdr_infoframe { /* PB0 */ u32 csum:8; /* checksum */ /* PB1 */ u32 eotf:3; /* The EOTF requested by the source */ u32 res1:5; /* reserved */ /* PB2 */ u32 static_metadata_id:3; /* The id of the following static metadata */ u32 res2:5; /* reserved */ /* PB3-14 : Group 1 : Static Metadata*/ u32 display_primaries_x_0_lsb:8; u32 display_primaries_x_0_msb:8; u32 display_primaries_y_0_lsb:8; u32 display_primaries_y_0_msb:8; u32 reg_hole1:8; u32 display_primaries_x_1_lsb:8; u32 display_primaries_x_1_msb:8; u32 display_primaries_y_1_lsb:8; u32 display_primaries_y_1_msb:8; u32 display_primaries_x_2_lsb:8; u32 display_primaries_x_2_msb:8; u32 display_primaries_y_2_lsb:8; u32 reg_hole2:8; u32 display_primaries_y_2_msb:8; /* PB15-18 : Group 2 : Static Metadata*/ u32 white_point_x_lsb:8; u32 white_point_x_msb:8; u32 white_point_y_lsb:8; u32 white_point_y_msb:8; /* PB19-20 : Group 3 : Static Metadata*/ u32 max_display_mastering_luminance_lsb:8; u32 max_display_mastering_luminance_msb:8; u32 reg_hole3:8; /* PB21-22 : Group 4 : Static Metadata*/ u32 min_display_mastering_luminance_lsb:8; u32 min_display_mastering_luminance_msb:8; /* PB23-24 : Group 5 : Static Metadata*/ u32 max_content_light_level_lsb:8; u32 max_content_light_level_msb:8; /* PB25-26 : Group 6 : Static Metadata*/ u32 max_frame_avg_light_level_lsb:8; u32 min_frame_avg_light_level_msb:8; } __packed; enum { HDMI_SPD_SI_UNKNOWN = 0x0, HDMI_SPD_SI_DIGITAL_STB = 0x1, HDMI_SPD_SI_DVD_PLAYER = 0x2, HDMI_SPD_SI_DVHS = 0x3, HDMI_SPD_SI_HDD_VIDEORECORDER = 0x4, HDMI_SPD_SI_DVD = 0x5, HDMI_SPD_SI_DSC = 0x6, HDMI_SPD_SI_VIDEO_CD = 0x7, HDMI_SPD_SI_GAME = 0x8, HDMI_SPD_SI_PC_GENERAL = 0x9, HDMI_SPD_SI_BLUERAY_DISC = 0xa, HDMI_SPD_SI_SUPER_AUDIO_CD = 0xb, HDMI_SPD_SI_HD_DVD = 0xc, HDMI_SPD_SI_PMP = 0xd, HDMI_SPD_SI_RESERVED = 0xFF, }; #define SPD_DEFAULT_VENDOR_NAME "NVIDIA" #define SPD_DEFAULT_PRODUCT_DESC "Tegra Family" #define SPD_DEFAULT_SOURCE_INFO HDMI_SPD_SI_DIGITAL_STB struct hdmi_spd_infoframe { /* PB0 */ u32 csum:8; /* checksum */ /* PB1-8 : Vendor Name */ u32 vendor_name_char_1:8; u32 vendor_name_char_2:8; u32 vendor_name_char_3:8; u32 vendor_name_char_4:8; u32 vendor_name_char_5:8; u32 vendor_name_char_6:8; u32 reg_hole1:8; u32 vendor_name_char_7:8; u32 vendor_name_char_8:8; /* PB9-24 : Product Description */ u32 prod_desc_char_1:8; u32 prod_desc_char_2:8; u32 prod_desc_char_3:8; u32 prod_desc_char_4:8; u32 prod_desc_char_5:8; u32 reg_hole2:8; u32 prod_desc_char_6:8; u32 prod_desc_char_7:8; u32 prod_desc_char_8:8; u32 prod_desc_char_9:8; u32 prod_desc_char_10:8; u32 prod_desc_char_11:8; u32 prod_desc_char_12:8; u32 reg_hole3:8; u32 prod_desc_char_13:8; u32 prod_desc_char_14:8; u32 prod_desc_char_15:8; u32 prod_desc_char_16:8; /* PB25 : Source Information */ u32 source_information:8; } __packed; enum { HDMI_AUDIO_CHANNEL_CNT_STREAM, /* refer to audio stream header */ HDMI_AUDIO_CHANNEL_CNT_2, HDMI_AUDIO_CHANNEL_CNT_3, HDMI_AUDIO_CHANNEL_CNT_4, HDMI_AUDIO_CHANNEL_CNT_5, HDMI_AUDIO_CHANNEL_CNT_6, HDMI_AUDIO_CHANNEL_CNT_7, HDMI_AUDIO_CHANNEL_CNT_8, }; /* all fields little endian */ struct hdmi_audio_infoframe { /* PB0 */ u32 csum:8; /* checksum */ /* PB1 */ u32 channel_cnt:3; u32 res1:1; /* reserved */ u32 coding_type:4; /* coding type */ /* PB2 */ u32 sample_size:2; u32 sample_freq:3; u32 res2:3; /* reserved */ /* PB3 */ u32 res3:8; /* reserved */ /* PB4 */ u32 channel_alloc:8; /* channel/speaker allocation */ /* PB5 */ u32 low_freq_effect_level:2; /* low freq effect playback level */ u32 res4:1; /* reserved */ u32 level_sft_val:4; /* level shift value */ u32 downmix_inhibit:1; u32 reg_hole1:16; } __packed; #define HDMI_LICENSING_LLC_OUI (0x000c03) enum { HDMI_VENDOR_VIDEO_FORMAT_NONE, HDMI_VENDOR_VIDEO_FORMAT_EXTENDED, HDMI_VENDOR_VIDEO_FORMAT_3D, }; /* all fields little endian */ struct hdmi_vendor_infoframe { /* PB0 */ u32 csum:8; /* PB1, PB2, PB3 */ u32 oui:24; /* organizationally unique identifier */ /* PB4 */ u32 res1:5; u32 video_format:3; /* PB5 */ union { u32 extended_vic:8; u32 res2:4; u32 format_3d:4; } __packed; /* PB6 */ u32 res3:4; u32 ext_data_3d:4; } __packed; enum { TEGRA_HDMI_SAFE_CLK = 1, TEGRA_HDMI_BRICK_CLK = 2, }; struct tmds_prod_pair { int clk; /* upper freq of a range. 0:end of the array */ const char *name; /* prod-setting node name */ }; struct tegra_hdmi { /* * The following "dpaux" and "sor" fields need to stay at the top of * this struct. The placement of these fields needs to align with the * tegra_dc_dp_data struct definition in order to support dynamic SOR * re-assignment with fakeDP. This is something that needs to be fixed, * though. */ struct tegra_dc_dpaux_data *dpaux; struct tegra_dc_sor_data *sor; void *hda_handle; struct tegra_dc *dc; struct tegra_hdmi_out *pdata; struct hdmi_avi_infoframe avi; struct hdmi_hdr_infoframe hdr; struct hdmi_spd_infoframe spd; bool enabled; atomic_t clock_refcount; bool dvi; u32 clk_type; struct tegra_edid_hdmi_eld eld; bool eld_valid; u8 edid_src; struct fb_monspecs mon_spec; bool mon_spec_valid; u8 avi_colorimetry; struct tegra_edid *edid; struct i2c_client *ddc_i2c_client; struct i2c_client *scdc_i2c_client; struct delayed_work scdc_work; struct i2c_client *ddcci_i2c_client; struct hdmi_audio_infoframe audio; #ifdef CONFIG_SWITCH struct switch_dev hpd_switch; struct switch_dev audio_switch; #endif char *hpd_switch_name; char *audio_switch_name; struct hdmi_vendor_infoframe vsi; struct tegra_nvhdcp *nvhdcp; struct delayed_work hpd_worker; struct mutex hpd_lock; #ifdef CONFIG_DEBUG_FS struct dentry *debugdir; #endif int ddc_i2c_original_rate; int irq; struct tegra_prod *prod_list; struct tmds_prod_pair *tmds_range; int ddc_refcount; struct mutex ddc_refcount_lock; bool device_shutdown; int plug_state; atomic_t suspended; struct delayed_work hdr_worker; struct tegra_hdmi_out_ops *out_ops; void *out_data; /* HDMI to GMSL bridge, HDMI to DSI bridge, etc. */ }; struct tegra_hdmi_out_ops { /* initialize output. dsi clocks are not on at this point */ int (*init)(struct tegra_hdmi *); /* destroy output. dsi clocks are not on at this point */ void (*destroy)(struct tegra_hdmi *); /* enable output. dsi clocks are on at this point */ void (*enable)(struct tegra_hdmi *); /* disable output. dsi clocks are on at this point */ void (*disable)(struct tegra_hdmi *dc); /* suspend output. dsi clocks are on at this point */ void (*suspend)(struct tegra_hdmi *); /* resume output. dsi clocks are on at this point */ void (*resume)(struct tegra_hdmi *); }; #define HDMI_ELD_BUF 96 /* eld field indexes */ enum { HDMI_ELD_VER = 0, HDMI_ELD_BASELINE_ELD_LEN = 2, HDMI_ELD_CEA_EDID_VER_MNL = 4, HDMI_ELD_SAD_CNT_CON_TYPE_S_AI_S_HDCP = 5, HDMI_ELD_AUDIO_SYNC_DELAY = 6, HDMI_ELD_RLRC_FLRC_RC_RLR_FC_LFE_FLR = 7, HDMI_ELD_PORT_ID = 8, /* 8 bytes */ HDMI_ELD_MANUFACTURER_NAME = 16, /* 2 bytes */ HDMI_ELD_PRODUCT_CODE = 18, /* 2 bytes */ HDMI_ELD_MONITOR_NAME_STR = 20, /* MNL bytes */ HDMI_ELD_CEA_SAD, /* SAD_CNT * 3 bytes, index depends on MNL */ }; /* bpp without alpha */ enum { TEGRA_HDMI_BPP_UNKNOWN = 0, TEGRA_HDMI_BPP_24 = 4, TEGRA_HDMI_BPP_30 = 5, TEGRA_HDMI_BPP_36 = 6, TEGRA_HDMI_BPP_48 = 7, }; void tegra_hdmi_get(struct tegra_dc *dc); void tegra_hdmi_put(struct tegra_dc *dc); void tegra_hdmi_infoframe_pkt_write(struct tegra_hdmi *hdmi, u32 header_reg, u8 pkt_type, u8 pkt_vs, u8 pkt_len, void *reg_payload, u32 reg_payload_len, bool sw_checksum); u32 tegra_hdmi_get_cea_modedb_size(struct tegra_hdmi *hdmi); #endif int tegra_hdmi_get_hotplug_state(struct tegra_hdmi *hdmi); void tegra_hdmi_set_hotplug_state(struct tegra_hdmi *hdmi, int new_hpd_state); static inline void *tegra_hdmi_get_outdata(struct tegra_hdmi *hdmi) { return hdmi->out_data; } static inline void tegra_hdmi_set_outdata(struct tegra_hdmi *hdmi, void *data) { hdmi->out_data = data; }