diff --git a/patches/HDR-for-LSPCON.patch b/patches/HDR-for-LSPCON.patch new file mode 100644 index 0000000..42ef2e4 --- /dev/null +++ b/patches/HDR-for-LSPCON.patch @@ -0,0 +1,312 @@ +diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h +index 8358152e403e..573ab6ea1a6e 100644 +--- a/drivers/gpu/drm/i915/display/intel_display_types.h ++++ b/drivers/gpu/drm/i915/display/intel_display_types.h +@@ -1274,6 +1274,7 @@ struct intel_lspcon { + bool active; + enum drm_lspcon_mode mode; + enum lspcon_vendor vendor; ++ bool hdr_supported; + }; + + struct intel_digital_port { +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c +index f8f1308643a9..a1d0127b7f57 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.c ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.c +@@ -35,6 +35,8 @@ + #define LSPCON_VENDOR_PARADE_OUI 0x001CF8 + #define LSPCON_VENDOR_MCA_OUI 0x0060AD + ++#define DPCD_MCA_LSPCON_HDR_STATUS 0x70003 ++ + /* AUX addresses to write MCA AVI IF */ + #define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0 + #define LSPCON_MCA_AVI_IF_CTRL 0x5DF +@@ -104,6 +106,31 @@ static bool lspcon_detect_vendor(struct intel_lspcon *lspcon) + return true; + } + ++static bool lspcon_detect_hdr_capability(struct intel_lspcon *lspcon) ++{ ++ struct intel_dp *dp = lspcon_to_intel_dp(lspcon); ++ u8 hdr_caps; ++ int ret; ++ ++ /* Enable HDR for MCA based LSPCON devices */ ++ if (lspcon->vendor == LSPCON_VENDOR_MCA) ++ ret = drm_dp_dpcd_read(&dp->aux, DPCD_MCA_LSPCON_HDR_STATUS, ++ &hdr_caps, 1); ++ else ++ return false; ++ ++ if (ret < 0) { ++ DRM_DEBUG_KMS("hdr capability detection failed\n"); ++ lspcon->hdr_supported = false; ++ return false; ++ } else if (hdr_caps & 0x1) { ++ DRM_DEBUG_KMS("lspcon capable of HDR\n"); ++ lspcon->hdr_supported = true; ++ } ++ ++ return true; ++} ++ + static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) + { + enum drm_lspcon_mode current_mode; +@@ -581,6 +608,11 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) + return false; + } + ++ if (!lspcon_detect_hdr_capability(lspcon)) { ++ DRM_ERROR("LSPCON hdr detection failed\n"); ++ return false; ++ } ++ + connector->ycbcr_420_allowed = true; + lspcon->active = true; + DRM_DEBUG_KMS("Success: LSPCON init\n"); +-- +diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c +index b54ccbb5aad5..051e30ad80e7 100644 +--- a/drivers/gpu/drm/i915/display/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/display/intel_hdmi.c +@@ -576,6 +576,16 @@ static u32 hsw_infoframes_enabled(struct intel_encoder *encoder, + return val & mask; + } + ++void lspcon_drm_write_infoframe(struct intel_encoder *encoder, ++ const struct intel_crtc_state *crtc_state, ++ unsigned int type, ++ const void *frame, ssize_t len) ++{ ++ DRM_DEBUG_KMS("Update HDR metadata for lspcon\n"); ++ /* It uses the legacy hsw implementation for the same */ ++ hsw_write_infoframe(encoder, crtc_state, type, frame, len); ++} ++ + static const u8 infoframe_type_to_idx[] = { + HDMI_PACKET_TYPE_GENERAL_CONTROL, + HDMI_PACKET_TYPE_GAMUT_METADATA, +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c +index a1d0127b7f57..51ad5f02e700 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.c ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.c +@@ -460,27 +460,41 @@ void lspcon_write_infoframe(struct intel_encoder *encoder, + unsigned int type, + const void *frame, ssize_t len) + { +- bool ret; ++ bool ret = true; + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base); + +- /* LSPCON only needs AVI IF */ +- if (type != HDMI_INFOFRAME_TYPE_AVI) ++ if (!(type == HDMI_INFOFRAME_TYPE_AVI || ++ type == HDMI_PACKET_TYPE_GAMUT_METADATA)) + return; + +- if (lspcon->vendor == LSPCON_VENDOR_MCA) +- ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux, +- frame, len); +- else +- ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, +- frame, len); ++ /* ++ * Supporting HDR on MCA LSPCON ++ * Todo: Add support for Parade later ++ */ ++ if (type == HDMI_PACKET_TYPE_GAMUT_METADATA && ++ lspcon->vendor != LSPCON_VENDOR_MCA) ++ return; ++ ++ if (lspcon->vendor == LSPCON_VENDOR_MCA) { ++ if (type == HDMI_INFOFRAME_TYPE_AVI) ++ ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux, ++ frame, len); ++ else if (type == HDMI_PACKET_TYPE_GAMUT_METADATA) ++ lspcon_drm_write_infoframe(encoder, crtc_state, ++ HDMI_PACKET_TYPE_GAMUT_METADATA, ++ frame, VIDEO_DIP_DATA_SIZE); ++ } else { ++ ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, frame, ++ len); ++ } + + if (!ret) { +- DRM_ERROR("Failed to write AVI infoframes\n"); ++ DRM_ERROR("Failed to write infoframes\n"); + return; + } + +- DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n"); ++ DRM_DEBUG_DRIVER("Infoframes updated successfully\n"); + } + + void lspcon_read_infoframe(struct intel_encoder *encoder, +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h +index 37cfddf8a9c5..65878904f672 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.h ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.h +@@ -35,4 +35,8 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, + void lspcon_ycbcr420_config(struct drm_connector *connector, + struct intel_crtc_state *crtc_state); + ++void lspcon_drm_write_infoframe(struct intel_encoder *encoder, ++ const struct intel_crtc_state *crtc_state, ++ unsigned int type, ++ const void *frame, ssize_t len); + #endif /* __INTEL_LSPCON_H__ */ +-- +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c +index 51ad5f02e700..c32452360eeb 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.c ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.c +@@ -627,6 +627,11 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) + return false; + } + ++ if (lspcon->vendor == LSPCON_VENDOR_MCA && lspcon->hdr_supported) ++ drm_object_attach_property(&connector->base, ++ connector->dev->mode_config.hdr_output_metadata_property, ++ 0); ++ + connector->ycbcr_420_allowed = true; + lspcon->active = true; + DRM_DEBUG_KMS("Success: LSPCON init\n"); +-- +diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c +index d0a937fb0c56..e78b3a1626fd 100644 +--- a/drivers/gpu/drm/drm_atomic_state_helper.c ++++ b/drivers/gpu/drm/drm_atomic_state_helper.c +@@ -416,6 +416,7 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, + + if (state->hdr_output_metadata) + drm_property_blob_get(state->hdr_output_metadata); ++ state->hdr_metadata_changed = false; + + /* Don't copy over a writeback job, they are used only once */ + state->writeback_job = NULL; +diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c +index 0d466d3b0809..5beabcd42d30 100644 +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -734,6 +734,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, + val, + sizeof(struct hdr_output_metadata), -1, + &replaced); ++ state->hdr_metadata_changed |= replaced; + return ret; + } else if (property == config->aspect_ratio_property) { + state->picture_aspect_ratio = val; +diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c +index 9ba794cb9b4f..dee3a593564c 100644 +--- a/drivers/gpu/drm/i915/display/intel_ddi.c ++++ b/drivers/gpu/drm/i915/display/intel_ddi.c +@@ -3851,6 +3851,8 @@ static void intel_enable_ddi_dp(struct intel_encoder *encoder, + { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); ++ struct intel_lspcon *lspcon = ++ enc_to_intel_lspcon(&encoder->base); + enum port port = encoder->port; + + if (port == PORT_A && INTEL_GEN(dev_priv) < 9) +@@ -3860,6 +3862,12 @@ static void intel_enable_ddi_dp(struct intel_encoder *encoder, + intel_psr_enable(intel_dp, crtc_state); + intel_dp_vsc_enable(intel_dp, crtc_state, conn_state); + intel_dp_hdr_metadata_enable(intel_dp, crtc_state, conn_state); ++ ++ /* Set the infoframe for NON modeset cases as well */ ++ if (lspcon->active && lspcon->hdr_supported && ++ conn_state->hdr_metadata_changed) ++ intel_dp_setup_hdr_metadata_infoframe_sdp(intel_dp, crtc_state, ++ conn_state); + intel_edp_drrs_enable(intel_dp, crtc_state); + + if (crtc_state->has_audio) +diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c +index 5eeafa45831a..cc616fd31d8b 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp.c +@@ -4651,7 +4651,7 @@ intel_dp_setup_vsc_sdp(struct intel_dp *intel_dp, + crtc_state, DP_SDP_VSC, &vsc_sdp, sizeof(vsc_sdp)); + } + +-static void ++void + intel_dp_setup_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h +index 65878904f672..3404cff8c337 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.h ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.h +@@ -14,6 +14,7 @@ struct intel_crtc_state; + struct intel_digital_port; + struct intel_encoder; + struct intel_lspcon; ++struct intel_dp; + + bool lspcon_init(struct intel_digital_port *intel_dig_port); + void lspcon_resume(struct intel_lspcon *lspcon); +@@ -39,4 +40,7 @@ void lspcon_drm_write_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + unsigned int type, + const void *frame, ssize_t len); ++void intel_dp_setup_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state, ++ const struct drm_connector_state *conn_state); + #endif /* __INTEL_LSPCON_H__ */ +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index 5f8c3389d46f..1f0b4fcf0bd3 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -661,6 +661,7 @@ struct drm_connector_state { + * DRM blob property for HDR output metadata + */ + struct drm_property_blob *hdr_output_metadata; ++ u8 hdr_metadata_changed : 1; + }; + + /** +-- +diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c +index c32452360eeb..8565bf73c4cd 100644 +--- a/drivers/gpu/drm/i915/display/intel_lspcon.c ++++ b/drivers/gpu/drm/i915/display/intel_lspcon.c +@@ -505,6 +505,11 @@ void lspcon_read_infoframe(struct intel_encoder *encoder, + /* FIXME implement this */ + } + ++/* HDMI HDR Colorspace Spec Definitions */ ++#define NORMAL_COLORIMETRY_MASK 0x3 ++#define EXTENDED_COLORIMETRY_MASK 0x7 ++#define HDMI_COLORIMETRY_BT2020_YCC ((3 << 0) | (6 << 2) | (0 << 5)) ++ + void lspcon_set_infoframes(struct intel_encoder *encoder, + bool enable, + const struct intel_crtc_state *crtc_state, +@@ -549,6 +554,19 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL); + ++ /* ++ * Set BT2020 colorspace if driving HDR data ++ * ToDo: Make this generic and expose all colorspaces for lspcon ++ */ ++ if (lspcon->active && conn_state->hdr_metadata_changed) { ++ frame.avi.colorimetry = ++ HDMI_COLORIMETRY_BT2020_YCC & ++ NORMAL_COLORIMETRY_MASK; ++ frame.avi.extended_colorimetry = ++ (HDMI_COLORIMETRY_BT2020_YCC >> 2) & ++ EXTENDED_COLORIMETRY_MASK; ++ } ++ + ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf)); + if (ret < 0) { + DRM_ERROR("Failed to pack AVI IF\n"); +-- diff --git a/patches/UHD-10Bit.patch b/patches/UHD-10Bit.patch new file mode 100644 index 0000000..79dfeeb --- /dev/null +++ b/patches/UHD-10Bit.patch @@ -0,0 +1,38 @@ +diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c +index cc616fd31d8b..f2d1d7bd87d3 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp.c +@@ -616,8 +616,10 @@ intel_dp_mode_valid(struct drm_connector *connector, + { + struct intel_dp *intel_dp = intel_attached_dp(connector); + struct intel_connector *intel_connector = to_intel_connector(connector); ++ struct intel_encoder *intel_encoder = intel_attached_encoder(connector); + struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; + struct drm_i915_private *dev_priv = to_i915(connector->dev); ++ struct intel_lspcon *lspcon = enc_to_intel_lspcon(&intel_encoder->base); + int target_clock = mode->clock; + int max_rate, mode_rate, max_lanes, max_link_clock; + int max_dotclk; +@@ -639,6 +641,21 @@ intel_dp_mode_valid(struct drm_connector *connector, + target_clock = fixed_mode->clock; + } + ++ /* ++ * Reducing Blanking to incorporate DP and HDMI timing/link bandwidth ++ * limitations for CEA modes (4k@60 at 10 bpp). DP can drive 17.28Gbs ++ * while 4k modes (VIC97 etc) at 10 bpp required 17.8 Gbps. This will ++ * cause mode to blank out. Reduced Htotal by shortening the back porch ++ * and front porch within permissible limits. ++ */ ++ if (lspcon->active && lspcon->hdr_supported && ++ mode->clock > 570000) { ++ mode->clock = 570000; ++ mode->htotal -= 180; ++ mode->hsync_start -= 72; ++ mode->hsync_end -= 72; ++ } ++ + max_link_clock = intel_dp_max_link_rate(intel_dp); + max_lanes = intel_dp_max_lane_count(intel_dp); + +-- diff --git a/skindesigner_patch.txt b/patches/skindesigner_patch.txt similarity index 100% rename from skindesigner_patch.txt rename to patches/skindesigner_patch.txt