Loading Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt +14 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,15 @@ Optional properties: - qcom,mdss-dsi-te-using-wd: Boolean entry enables the watchdog timer support to generate the vsync signal for command mode panel. By default, panel TE will be used to generate the vsync. - qcom,mdss-dsi-te-using-te-pin: Boolean to specify whether using hardware vsync. - qcom,mdss-dsi-qsync-min-refresh-rate: A u32 entry to specify minimum refresh rate supported by the panel to enable qsync feature. - qcom,mdss-dsi-qsync-on-commands: String that specifies the commands to enable qsync feature. - qcom,mdss-dsi-qsync-on-commands-state: String that specifies the ctrl state for sending qsync on commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode - qcom,mdss-dsi-qsync-off-commands: String that specifies the commands to disable qsync feature. - qcom,mdss-dsi-qsync-off-commands-state: String that specifies the ctrl state for sending qsync off commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode - qcom,mdss-dsi-te-pin-select: Specifies TE operating mode. 0 = TE through embedded dcs command 1 = TE through TE gpio pin. (default) Loading Loading @@ -599,6 +608,7 @@ Example: qcom,mdss-dsi-te-check-enable; qcom,mdss-dsi-te-using-wd; qcom,mdss-dsi-te-using-te-pin; qcom,mdss-dsi-qsync-min-refresh-rate = <30>; qcom,mdss-dsi-te-dcs-command = <1>; qcom,mdss-dsi-wr-mem-continue = <0x3c>; qcom,mdss-dsi-wr-mem-start = <0x2c>; Loading Loading @@ -712,6 +722,10 @@ Example: 29 00 00 00 00 00 02 B0 04 29 00 00 00 00 00 02 F1 00]; qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode"; qcom,mdss-dsi-qsync-on-commands = [15 01 00 00 00 00 02 51 00]; qcom,mdss-dsi-qsync-on-commands-state = "dsi_hs_mode"; qcom,mdss-dsi-qsync-off-commands = [15 01 00 00 00 00 02 51 00]; qcom,mdss-dsi-qsync-off-commands-state = "dsi_hs_mode"; qcom,mdss-dsc-slice-height = <16>; qcom,mdss-dsc-slice-width = <360>; Loading arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ }; &mdss_mdp { connectors = <&sde_wb &sde_dp &sde_dsi>; connectors = <&sde_rscc &sde_wb &sde_dp &sde_dsi>; }; /* PHY TIMINGS REVISION P */ Loading arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi +0 −17 Original line number Diff line number Diff line Loading @@ -79,8 +79,6 @@ reg-names = "pll_base", "phy_base", "ln_tx0_base", "ln_tx1_base", "gdsc_base"; gdsc-supply = <&mdss_core_gdsc>; clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_rpmh RPMH_CXO_CLK>, <&clock_gcc GCC_DISP_AHB_CLK>, Loading @@ -89,21 +87,6 @@ clock-names = "iface_clk", "ref_clk_src", "gcc_iface", "ref_clk", "pipe_clk"; clock-rate = <0>; qcom,platform-supply-entries { #address-cells = <1>; #size-cells = <0>; qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "gdsc"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; qcom,supply-disable-load = <0>; }; }; }; }; arch/arm64/boot/dts/qcom/sm8150-sde.dtsi +10 −33 Original line number Diff line number Diff line Loading @@ -24,15 +24,19 @@ clocks = <&clock_gcc GCC_DISP_AHB_CLK>, <&clock_gcc GCC_DISP_HF_AXI_CLK>, <&clock_gcc GCC_DISP_SF_AXI_CLK>, <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>; clock-names = "gcc_iface", "gcc_bus", "iface_clk", "core_clk", "vsync_clk"; clock-rate = <0 0 0 300000000 19200000>; clock-max-rate = <0 0 0 460000000 19200000>; <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>, <&clock_dispcc DISP_CC_MDSS_ROT_CLK>; clock-names = "gcc_iface", "gcc_bus", "gcc_nrt_bus", "iface_clk", "core_clk", "vsync_clk", "rot_clk"; clock-rate = <0 0 0 0 300000000 19200000 0>; clock-max-rate = <0 0 0 0 460000000 19200000 0>; sde-vdd-supply = <&mdss_core_gdsc>; mmcx-supply = <&VDD_MMCX_LEVEL>; /* interrupt config */ interrupts = <0 83 0>; Loading Loading @@ -193,12 +197,7 @@ qcom,sde-qos-cpu-mask = <0x3>; qcom,sde-qos-cpu-dma-latency = <300>; qcom,sde-inline-rotator = <&mdss_rotator 0>; qcom,sde-inline-rot-xin = <10 11>; qcom,sde-inline-rot-xin-type = "sspp", "wb"; /* offsets are relative to "mdp_phys + qcom,sde-off */ qcom,sde-inline-rot-clk-ctrl = <0x2bc 0x8>, <0x2bc 0xc>; qcom,sde-reg-dma-off = <0>; qcom,sde-reg-dma-version = <0x00010001>; Loading Loading @@ -248,7 +247,7 @@ qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "sde-vdd"; qcom,supply-name = "mmcx"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; Loading Loading @@ -311,7 +310,6 @@ <0xaf30000 0x3fd4>; reg-names = "drv", "wrapper"; qcom,sde-rsc-version = <2>; status = "disabled"; vdd-supply = <&mdss_core_gdsc>; clocks = <&clock_dispcc DISP_CC_MDSS_RSCC_VSYNC_CLK>, Loading Loading @@ -358,20 +356,6 @@ <20000 20512 0 6400000>, <20000 20512 0 6400000>; }; qcom,platform-supply-entries { #address-cells = <1>; #size-cells = <0>; qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "mmcx"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; qcom,supply-disable-load = <0>; }; }; }; mdss_rotator: qcom,mdss_rotator@ae00000 { Loading Loading @@ -419,13 +403,6 @@ qcom,mdss-rot-danger-lut = <0x0 0x0>; qcom,mdss-rot-safe-lut = <0x0000ffff 0x0000ffff>; /* Inline rotator QoS Setting */ /* setting default register values for RD - qos/danger/safe */ qcom,mdss-inline-rot-qos-lut = <0x44556677 0x00112233 0x44556677 0x00112233>; qcom,mdss-inline-rot-danger-lut = <0x0055aaff 0x0000ffff>; qcom,mdss-inline-rot-safe-lut = <0x0000f000 0x0000f000>; qcom,mdss-default-ot-rd-limit = <32>; qcom,mdss-default-ot-wr-limit = <32>; Loading drivers/gpu/drm/drm_edid.c +195 −1 Original line number Diff line number Diff line Loading @@ -2787,7 +2787,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, return closure.modes; } #define VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK 0x0 #define AUDIO_BLOCK 0x01 #define VIDEO_BLOCK 0x02 #define VENDOR_BLOCK 0x03 Loading Loading @@ -3846,6 +3846,161 @@ add_YCbCr420VDB_modes(struct drm_connector *connector, struct edid *edid) return modes; } /* * drm_extract_vcdb_info - Parse the HDMI Video Capability Data Block * @connector: connector corresponding to the HDMI sink * @db: start of the CEA vendor specific block * * Parses the HDMI VCDB to extract sink info for @connector. */ static void drm_extract_vcdb_info(struct drm_connector *connector, const u8 *db) { /* * Check if the sink specifies underscan * support for: * BIT 5: preferred video format * BIT 3: IT video format * BIT 1: CE video format */ connector->pt_scan_info = (db[2] & (BIT(4) | BIT(5))) >> 4; connector->it_scan_info = (db[2] & (BIT(3) | BIT(2))) >> 2; connector->ce_scan_info = db[2] & (BIT(1) | BIT(0)); DRM_DEBUG_KMS("Scan Info (pt|it|ce): (%d|%d|%d)", (int) connector->pt_scan_info, (int) connector->it_scan_info, (int) connector->ce_scan_info); } static bool drm_edid_is_luminance_value_present( u32 block_length, enum luminance_value value) { return block_length > NO_LUMINANCE_DATA && value <= block_length; } /* * drm_extract_hdr_db - Parse the HDMI HDR extended block * @connector: connector corresponding to the HDMI sink * @db: start of the HDMI HDR extended block * * Parses the HDMI HDR extended block to extract sink info for @connector. */ static void drm_extract_hdr_db(struct drm_connector *connector, const u8 *db) { u8 len = 0; if (!db) return; len = db[0] & 0x1f; /* Byte 3: Electro-Optical Transfer Functions */ connector->hdr_eotf = db[2] & 0x3F; /* Byte 4: Static Metadata Descriptor Type 1 */ connector->hdr_metadata_type_one = (db[3] & BIT(0)); /* Byte 5: Desired Content Maximum Luminance */ if (drm_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) connector->hdr_max_luminance = db[MAXIMUM_LUMINANCE]; /* Byte 6: Desired Content Max Frame-average Luminance */ if (drm_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE)) connector->hdr_avg_luminance = db[FRAME_AVERAGE_LUMINANCE]; /* Byte 7: Desired Content Min Luminance */ if (drm_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE)) connector->hdr_min_luminance = db[MINIMUM_LUMINANCE]; connector->hdr_supported = true; DRM_DEBUG_KMS("HDR electro-optical %d\n", connector->hdr_eotf); DRM_DEBUG_KMS("metadata desc 1 %d\n", connector->hdr_metadata_type_one); DRM_DEBUG_KMS("max luminance %d\n", connector->hdr_max_luminance); DRM_DEBUG_KMS("avg luminance %d\n", connector->hdr_avg_luminance); DRM_DEBUG_KMS("min luminance %d\n", connector->hdr_min_luminance); } /* * drm_hdmi_extract_extended_blk_info - Parse the HDMI extended tag blocks * @connector: connector corresponding to the HDMI sink * @edid: handle to the EDID structure * Parses the all extended tag blocks extract sink info for @connector. */ static void drm_hdmi_extract_extended_blk_info(struct drm_connector *connector, struct edid *edid) { const u8 *cea = drm_find_cea_extension(edid); const u8 *db = NULL; if (cea && cea_revision(cea) >= 3) { int i, start, end; if (cea_db_offsets(cea, &start, &end)) return; for_each_cea_db(cea, i, start, end) { db = &cea[i]; if (cea_db_tag(db) == USE_EXTENDED_TAG) { DRM_DEBUG_KMS("found extended tag block = %d\n", db[1]); switch (db[1]) { case VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK: drm_extract_vcdb_info(connector, db); break; case HDR_STATIC_METADATA_EXTENDED_DATA_BLOCK: drm_extract_hdr_db(connector, db); break; default: break; } } } } } static void parse_hdmi_hf_vsdb(struct drm_connector *connector, const u8 *db) { u8 len = cea_db_payload_len(db); if (len < 7) return; if (db[4] != 1) return; /* invalid version */ connector->max_tmds_char = db[5] * 5; connector->scdc_present = db[6] & (1 << 7); connector->rr_capable = db[6] & (1 << 6); connector->flags_3d = db[6] & 0x7; connector->supports_scramble = connector->scdc_present && (db[6] & (1 << 3)); DRM_DEBUG_KMS("HDMI v2: max TMDS char %d, " "scdc %s, " "rr %s, " "3D flags 0x%x, " "scramble %s\n", connector->max_tmds_char, connector->scdc_present ? "available" : "not available", connector->rr_capable ? "capable" : "not capable", connector->flags_3d, connector->supports_scramble ? "supported" : "not supported"); } static void monitor_name(struct detailed_timing *t, void *data) { Loading Loading @@ -3972,6 +4127,9 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) /* HDMI Vendor-Specific Data Block */ if (cea_db_is_hdmi_vsdb(db)) drm_parse_hdmi_vsdb_audio(connector, db); /* HDMI Forum Vendor-Specific Data Block */ else if (cea_db_is_hdmi_forum_vsdb(db)) parse_hdmi_hf_vsdb(connector, db); break; default: break; Loading Loading @@ -4461,6 +4619,37 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } } static void drm_hdmi_extract_vsdbs_info(struct drm_connector *connector, struct edid *edid) { const u8 *cea = drm_find_cea_extension(edid); const u8 *db = NULL; if (cea && cea_revision(cea) >= 3) { int i, start, end; if (cea_db_offsets(cea, &start, &end)) return; for_each_cea_db(cea, i, start, end) { db = &cea[i]; if (cea_db_tag(db) == VENDOR_BLOCK) { /* HDMI Vendor-Specific Data Block */ if (cea_db_is_hdmi_vsdb(db)) { drm_parse_hdmi_vsdb_video( connector, db); drm_parse_hdmi_vsdb_audio( connector, db); } /* HDMI Forum Vendor-Specific Data Block */ else if (cea_db_is_hdmi_forum_vsdb(db)) parse_hdmi_hf_vsdb(connector, db); } } } } static void drm_add_display_info(struct drm_connector *connector, struct edid *edid) { Loading Loading @@ -4498,6 +4687,11 @@ static void drm_add_display_info(struct drm_connector *connector, connector->name, info->bpc); } /* Extract audio and video latency fields for the sink */ drm_hdmi_extract_vsdbs_info(connector, edid); /* Extract info from extended tag blocks */ drm_hdmi_extract_extended_blk_info(connector, edid); /* Only defined for 1.4 with digital displays */ if (edid->revision < 4) return; Loading Loading
Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt +14 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,15 @@ Optional properties: - qcom,mdss-dsi-te-using-wd: Boolean entry enables the watchdog timer support to generate the vsync signal for command mode panel. By default, panel TE will be used to generate the vsync. - qcom,mdss-dsi-te-using-te-pin: Boolean to specify whether using hardware vsync. - qcom,mdss-dsi-qsync-min-refresh-rate: A u32 entry to specify minimum refresh rate supported by the panel to enable qsync feature. - qcom,mdss-dsi-qsync-on-commands: String that specifies the commands to enable qsync feature. - qcom,mdss-dsi-qsync-on-commands-state: String that specifies the ctrl state for sending qsync on commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode - qcom,mdss-dsi-qsync-off-commands: String that specifies the commands to disable qsync feature. - qcom,mdss-dsi-qsync-off-commands-state: String that specifies the ctrl state for sending qsync off commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode - qcom,mdss-dsi-te-pin-select: Specifies TE operating mode. 0 = TE through embedded dcs command 1 = TE through TE gpio pin. (default) Loading Loading @@ -599,6 +608,7 @@ Example: qcom,mdss-dsi-te-check-enable; qcom,mdss-dsi-te-using-wd; qcom,mdss-dsi-te-using-te-pin; qcom,mdss-dsi-qsync-min-refresh-rate = <30>; qcom,mdss-dsi-te-dcs-command = <1>; qcom,mdss-dsi-wr-mem-continue = <0x3c>; qcom,mdss-dsi-wr-mem-start = <0x2c>; Loading Loading @@ -712,6 +722,10 @@ Example: 29 00 00 00 00 00 02 B0 04 29 00 00 00 00 00 02 F1 00]; qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode"; qcom,mdss-dsi-qsync-on-commands = [15 01 00 00 00 00 02 51 00]; qcom,mdss-dsi-qsync-on-commands-state = "dsi_hs_mode"; qcom,mdss-dsi-qsync-off-commands = [15 01 00 00 00 00 02 51 00]; qcom,mdss-dsi-qsync-off-commands-state = "dsi_hs_mode"; qcom,mdss-dsc-slice-height = <16>; qcom,mdss-dsc-slice-width = <360>; Loading
arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ }; &mdss_mdp { connectors = <&sde_wb &sde_dp &sde_dsi>; connectors = <&sde_rscc &sde_wb &sde_dp &sde_dsi>; }; /* PHY TIMINGS REVISION P */ Loading
arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi +0 −17 Original line number Diff line number Diff line Loading @@ -79,8 +79,6 @@ reg-names = "pll_base", "phy_base", "ln_tx0_base", "ln_tx1_base", "gdsc_base"; gdsc-supply = <&mdss_core_gdsc>; clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_rpmh RPMH_CXO_CLK>, <&clock_gcc GCC_DISP_AHB_CLK>, Loading @@ -89,21 +87,6 @@ clock-names = "iface_clk", "ref_clk_src", "gcc_iface", "ref_clk", "pipe_clk"; clock-rate = <0>; qcom,platform-supply-entries { #address-cells = <1>; #size-cells = <0>; qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "gdsc"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; qcom,supply-disable-load = <0>; }; }; }; };
arch/arm64/boot/dts/qcom/sm8150-sde.dtsi +10 −33 Original line number Diff line number Diff line Loading @@ -24,15 +24,19 @@ clocks = <&clock_gcc GCC_DISP_AHB_CLK>, <&clock_gcc GCC_DISP_HF_AXI_CLK>, <&clock_gcc GCC_DISP_SF_AXI_CLK>, <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>; clock-names = "gcc_iface", "gcc_bus", "iface_clk", "core_clk", "vsync_clk"; clock-rate = <0 0 0 300000000 19200000>; clock-max-rate = <0 0 0 460000000 19200000>; <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>, <&clock_dispcc DISP_CC_MDSS_ROT_CLK>; clock-names = "gcc_iface", "gcc_bus", "gcc_nrt_bus", "iface_clk", "core_clk", "vsync_clk", "rot_clk"; clock-rate = <0 0 0 0 300000000 19200000 0>; clock-max-rate = <0 0 0 0 460000000 19200000 0>; sde-vdd-supply = <&mdss_core_gdsc>; mmcx-supply = <&VDD_MMCX_LEVEL>; /* interrupt config */ interrupts = <0 83 0>; Loading Loading @@ -193,12 +197,7 @@ qcom,sde-qos-cpu-mask = <0x3>; qcom,sde-qos-cpu-dma-latency = <300>; qcom,sde-inline-rotator = <&mdss_rotator 0>; qcom,sde-inline-rot-xin = <10 11>; qcom,sde-inline-rot-xin-type = "sspp", "wb"; /* offsets are relative to "mdp_phys + qcom,sde-off */ qcom,sde-inline-rot-clk-ctrl = <0x2bc 0x8>, <0x2bc 0xc>; qcom,sde-reg-dma-off = <0>; qcom,sde-reg-dma-version = <0x00010001>; Loading Loading @@ -248,7 +247,7 @@ qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "sde-vdd"; qcom,supply-name = "mmcx"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; Loading Loading @@ -311,7 +310,6 @@ <0xaf30000 0x3fd4>; reg-names = "drv", "wrapper"; qcom,sde-rsc-version = <2>; status = "disabled"; vdd-supply = <&mdss_core_gdsc>; clocks = <&clock_dispcc DISP_CC_MDSS_RSCC_VSYNC_CLK>, Loading Loading @@ -358,20 +356,6 @@ <20000 20512 0 6400000>, <20000 20512 0 6400000>; }; qcom,platform-supply-entries { #address-cells = <1>; #size-cells = <0>; qcom,platform-supply-entry@0 { reg = <0>; qcom,supply-name = "mmcx"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; qcom,supply-disable-load = <0>; }; }; }; mdss_rotator: qcom,mdss_rotator@ae00000 { Loading Loading @@ -419,13 +403,6 @@ qcom,mdss-rot-danger-lut = <0x0 0x0>; qcom,mdss-rot-safe-lut = <0x0000ffff 0x0000ffff>; /* Inline rotator QoS Setting */ /* setting default register values for RD - qos/danger/safe */ qcom,mdss-inline-rot-qos-lut = <0x44556677 0x00112233 0x44556677 0x00112233>; qcom,mdss-inline-rot-danger-lut = <0x0055aaff 0x0000ffff>; qcom,mdss-inline-rot-safe-lut = <0x0000f000 0x0000f000>; qcom,mdss-default-ot-rd-limit = <32>; qcom,mdss-default-ot-wr-limit = <32>; Loading
drivers/gpu/drm/drm_edid.c +195 −1 Original line number Diff line number Diff line Loading @@ -2787,7 +2787,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, return closure.modes; } #define VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK 0x0 #define AUDIO_BLOCK 0x01 #define VIDEO_BLOCK 0x02 #define VENDOR_BLOCK 0x03 Loading Loading @@ -3846,6 +3846,161 @@ add_YCbCr420VDB_modes(struct drm_connector *connector, struct edid *edid) return modes; } /* * drm_extract_vcdb_info - Parse the HDMI Video Capability Data Block * @connector: connector corresponding to the HDMI sink * @db: start of the CEA vendor specific block * * Parses the HDMI VCDB to extract sink info for @connector. */ static void drm_extract_vcdb_info(struct drm_connector *connector, const u8 *db) { /* * Check if the sink specifies underscan * support for: * BIT 5: preferred video format * BIT 3: IT video format * BIT 1: CE video format */ connector->pt_scan_info = (db[2] & (BIT(4) | BIT(5))) >> 4; connector->it_scan_info = (db[2] & (BIT(3) | BIT(2))) >> 2; connector->ce_scan_info = db[2] & (BIT(1) | BIT(0)); DRM_DEBUG_KMS("Scan Info (pt|it|ce): (%d|%d|%d)", (int) connector->pt_scan_info, (int) connector->it_scan_info, (int) connector->ce_scan_info); } static bool drm_edid_is_luminance_value_present( u32 block_length, enum luminance_value value) { return block_length > NO_LUMINANCE_DATA && value <= block_length; } /* * drm_extract_hdr_db - Parse the HDMI HDR extended block * @connector: connector corresponding to the HDMI sink * @db: start of the HDMI HDR extended block * * Parses the HDMI HDR extended block to extract sink info for @connector. */ static void drm_extract_hdr_db(struct drm_connector *connector, const u8 *db) { u8 len = 0; if (!db) return; len = db[0] & 0x1f; /* Byte 3: Electro-Optical Transfer Functions */ connector->hdr_eotf = db[2] & 0x3F; /* Byte 4: Static Metadata Descriptor Type 1 */ connector->hdr_metadata_type_one = (db[3] & BIT(0)); /* Byte 5: Desired Content Maximum Luminance */ if (drm_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) connector->hdr_max_luminance = db[MAXIMUM_LUMINANCE]; /* Byte 6: Desired Content Max Frame-average Luminance */ if (drm_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE)) connector->hdr_avg_luminance = db[FRAME_AVERAGE_LUMINANCE]; /* Byte 7: Desired Content Min Luminance */ if (drm_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE)) connector->hdr_min_luminance = db[MINIMUM_LUMINANCE]; connector->hdr_supported = true; DRM_DEBUG_KMS("HDR electro-optical %d\n", connector->hdr_eotf); DRM_DEBUG_KMS("metadata desc 1 %d\n", connector->hdr_metadata_type_one); DRM_DEBUG_KMS("max luminance %d\n", connector->hdr_max_luminance); DRM_DEBUG_KMS("avg luminance %d\n", connector->hdr_avg_luminance); DRM_DEBUG_KMS("min luminance %d\n", connector->hdr_min_luminance); } /* * drm_hdmi_extract_extended_blk_info - Parse the HDMI extended tag blocks * @connector: connector corresponding to the HDMI sink * @edid: handle to the EDID structure * Parses the all extended tag blocks extract sink info for @connector. */ static void drm_hdmi_extract_extended_blk_info(struct drm_connector *connector, struct edid *edid) { const u8 *cea = drm_find_cea_extension(edid); const u8 *db = NULL; if (cea && cea_revision(cea) >= 3) { int i, start, end; if (cea_db_offsets(cea, &start, &end)) return; for_each_cea_db(cea, i, start, end) { db = &cea[i]; if (cea_db_tag(db) == USE_EXTENDED_TAG) { DRM_DEBUG_KMS("found extended tag block = %d\n", db[1]); switch (db[1]) { case VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK: drm_extract_vcdb_info(connector, db); break; case HDR_STATIC_METADATA_EXTENDED_DATA_BLOCK: drm_extract_hdr_db(connector, db); break; default: break; } } } } } static void parse_hdmi_hf_vsdb(struct drm_connector *connector, const u8 *db) { u8 len = cea_db_payload_len(db); if (len < 7) return; if (db[4] != 1) return; /* invalid version */ connector->max_tmds_char = db[5] * 5; connector->scdc_present = db[6] & (1 << 7); connector->rr_capable = db[6] & (1 << 6); connector->flags_3d = db[6] & 0x7; connector->supports_scramble = connector->scdc_present && (db[6] & (1 << 3)); DRM_DEBUG_KMS("HDMI v2: max TMDS char %d, " "scdc %s, " "rr %s, " "3D flags 0x%x, " "scramble %s\n", connector->max_tmds_char, connector->scdc_present ? "available" : "not available", connector->rr_capable ? "capable" : "not capable", connector->flags_3d, connector->supports_scramble ? "supported" : "not supported"); } static void monitor_name(struct detailed_timing *t, void *data) { Loading Loading @@ -3972,6 +4127,9 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) /* HDMI Vendor-Specific Data Block */ if (cea_db_is_hdmi_vsdb(db)) drm_parse_hdmi_vsdb_audio(connector, db); /* HDMI Forum Vendor-Specific Data Block */ else if (cea_db_is_hdmi_forum_vsdb(db)) parse_hdmi_hf_vsdb(connector, db); break; default: break; Loading Loading @@ -4461,6 +4619,37 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } } static void drm_hdmi_extract_vsdbs_info(struct drm_connector *connector, struct edid *edid) { const u8 *cea = drm_find_cea_extension(edid); const u8 *db = NULL; if (cea && cea_revision(cea) >= 3) { int i, start, end; if (cea_db_offsets(cea, &start, &end)) return; for_each_cea_db(cea, i, start, end) { db = &cea[i]; if (cea_db_tag(db) == VENDOR_BLOCK) { /* HDMI Vendor-Specific Data Block */ if (cea_db_is_hdmi_vsdb(db)) { drm_parse_hdmi_vsdb_video( connector, db); drm_parse_hdmi_vsdb_audio( connector, db); } /* HDMI Forum Vendor-Specific Data Block */ else if (cea_db_is_hdmi_forum_vsdb(db)) parse_hdmi_hf_vsdb(connector, db); } } } } static void drm_add_display_info(struct drm_connector *connector, struct edid *edid) { Loading Loading @@ -4498,6 +4687,11 @@ static void drm_add_display_info(struct drm_connector *connector, connector->name, info->bpc); } /* Extract audio and video latency fields for the sink */ drm_hdmi_extract_vsdbs_info(connector, edid); /* Extract info from extended tag blocks */ drm_hdmi_extract_extended_blk_info(connector, edid); /* Only defined for 1.4 with digital displays */ if (edid->revision < 4) return; Loading