mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
313 lines
11 KiB
Diff
313 lines
11 KiB
Diff
|
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");
|
||
|
--
|