1
0
mirror of https://github.com/jojo61/vdr-plugin-softhdcuvid.git synced 2023-10-10 13:37:41 +02:00
vdr-plugin-softhdcuvid/patches/HDR-for-LSPCON.patch

313 lines
11 KiB
Diff
Raw Permalink Normal View History

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");
--