summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-08-11 16:23:51 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-08-11 16:23:51 -0700
commit6949010ef3f740d5a3d7bdc18baf67975c6fcd19 (patch)
treeae1759da51b8246414b6184f7b2f72425a0cb8bc
parentde1f4ef405e0aa572c27d2bf699e96707ec45ce7 (diff)
parent5920f5fe3c882ff942416df34589434251ab8dc6 (diff)
Merge "drm/msm: update CSC matrix during HDR playback"
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c34
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h15
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c22
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h19
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c87
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdss.h3
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c3
8 files changed, 180 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 0949b55a6d87..ab8e7a0ed6a5 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -2394,6 +2394,40 @@ bool sde_hdmi_mode_needs_full_range(void *display)
return true;
}
+enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
+ void *display)
+{
+ struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
+ struct sde_connector_state *c_state;
+ struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
+ struct drm_msm_ext_panel_hdr_metadata *hdr_meta;
+
+ if (!hdmi_display || !conn) {
+ SDE_ERROR("invalid input\n");
+ goto error;
+ }
+
+ c_state = to_sde_connector_state(conn->state);
+
+ if (!c_state) {
+ SDE_ERROR("invalid input\n");
+ goto error;
+ }
+
+ hdr_ctrl = &c_state->hdr_ctrl;
+ hdr_meta = &hdr_ctrl->hdr_meta;
+
+ if ((hdr_ctrl->hdr_state == HDR_ENABLE)
+ && (hdr_meta->eotf != 0))
+ return SDE_CSC_RGB2YUV_2020L;
+ else if (sde_hdmi_mode_needs_full_range(hdmi_display)
+ || conn->yuv_qs)
+ return SDE_CSC_RGB2YUV_601FR;
+
+error:
+ return SDE_CSC_RGB2YUV_601L;
+}
+
int sde_hdmi_connector_get_modes(struct drm_connector *connector, void *display)
{
struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index 441bb3a6dfe8..e80fc66a6244 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -490,6 +490,15 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
*/
bool sde_hdmi_mode_needs_full_range(void *display);
+/*
+ * sde_hdmi_get_csc_type - returns the CSC type to be
+ * used based on state of HDR playback
+ * @conn: Pointer to DRM connector
+ * @display: Pointer to private display structure
+ * Returns: true or false based on mode
+ */
+enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
+ void *display);
#else /*#ifdef CONFIG_DRM_SDE_HDMI*/
static inline u32 sde_hdmi_get_num_of_displays(void)
@@ -609,5 +618,11 @@ static inline bool sde_hdmi_mode_needs_full_range(void *display)
return false;
}
+enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
+ void *display)
+{
+ return 0;
+}
+
#endif /*#else of CONFIG_DRM_SDE_HDMI*/
#endif /* _SDE_HDMI_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index d79361bbe265..5fa4c21060f9 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -90,6 +90,28 @@ int sde_connector_pre_kickoff(struct drm_connector *connector)
return rc;
}
+enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn)
+{
+ struct sde_connector *c_conn;
+
+ if (!conn) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ c_conn = to_sde_connector(conn);
+
+ if (!c_conn->display) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ if (!c_conn->ops.get_csc_type)
+ return SDE_CSC_RGB2YUV_601L;
+
+ return c_conn->ops.get_csc_type(conn, c_conn->display);
+}
+
bool sde_connector_mode_needs_full_range(struct drm_connector *connector)
{
struct sde_connector *c_conn;
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 73a20133a944..b76ce0aaf577 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -143,6 +143,16 @@ struct sde_connector_ops {
* Returns: true or false based on whether full range is needed
*/
bool (*mode_needs_full_range)(void *display);
+
+ /**
+ * get_csc_type - returns the CSC type to be used
+ * by the CDM block based on HDR state
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display structure
+ * Returns: type of CSC matrix to be used
+ */
+ enum sde_csc_type (*get_csc_type)(struct drm_connector *connector,
+ void *display);
};
/**
@@ -342,5 +352,14 @@ int sde_connector_pre_kickoff(struct drm_connector *connector);
* Returns: true OR false based on connector mode
*/
bool sde_connector_mode_needs_full_range(struct drm_connector *connector);
+
+/**
+ * sde_connector_get_csc_type - query csc type
+ * to be used for the connector
+ * @connector: Pointer to drm connector object
+ * Returns: csc type based on connector HDR state
+ */
+enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn);
+
#endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index baf0d0bf1f0b..23fb79241d84 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -80,6 +80,42 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = {
{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
},
+
+ [SDE_CSC_RGB2YUV_709L] = {
+ {
+ TO_S15D16(0x005d), TO_S15D16(0x013a), TO_S15D16(0x0020),
+ TO_S15D16(0xffcc), TO_S15D16(0xff53), TO_S15D16(0x00e1),
+ TO_S15D16(0x00e1), TO_S15D16(0xff34), TO_S15D16(0xffeb),
+ },
+ { 0x0, 0x0, 0x0,},
+ { 0x0040, 0x0200, 0x0200,},
+ { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+ { 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
+ },
+
+ [SDE_CSC_RGB2YUV_2020L] = {
+ {
+ TO_S15D16(0x0073), TO_S15D16(0x0129), TO_S15D16(0x001a),
+ TO_S15D16(0xffc1), TO_S15D16(0xff5e), TO_S15D16(0x00e0),
+ TO_S15D16(0x00e0), TO_S15D16(0xff32), TO_S15D16(0xffee),
+ },
+ { 0x0, 0x0, 0x0,},
+ { 0x0040, 0x0200, 0x0200,},
+ { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+ { 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
+ },
+
+ [SDE_CSC_RGB2YUV_2020FR] = {
+ {
+ TO_S15D16(0x0086), TO_S15D16(0x015b), TO_S15D16(0x001e),
+ TO_S15D16(0xffb9), TO_S15D16(0xff47), TO_S15D16(0x0100),
+ TO_S15D16(0x0100), TO_S15D16(0xff15), TO_S15D16(0xffeb),
+ },
+ { 0x0, 0x0, 0x0,},
+ { 0x0, 0x0200, 0x0200,},
+ { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+ { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+ },
};
/**
@@ -826,7 +862,12 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
{
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys;
+ struct drm_connector *conn_mas = NULL;
unsigned int i;
+ enum sde_csc_type conn_csc;
+ struct drm_display_mode *mode;
+ struct sde_hw_cdm *hw_cdm;
+ int mode_is_yuv = 0;
int rc;
if (!drm_enc) {
@@ -846,11 +887,46 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
}
if (sde_enc->cur_master && sde_enc->cur_master->connector) {
- rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
+ conn_mas = sde_enc->cur_master->connector;
+ rc = sde_connector_pre_kickoff(conn_mas);
if (rc)
- SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
- sde_enc->cur_master->connector->base.id,
- rc);
+ SDE_ERROR_ENC(sde_enc,
+ "kickoff conn%d failed rc %d\n",
+ conn_mas->base.id,
+ rc);
+
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ phys = sde_enc->phys_encs[i];
+ if (phys) {
+ mode = &phys->cached_mode;
+ mode_is_yuv = (mode->private_flags &
+ MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420);
+ }
+ /**
+ * Check the CSC matrix type to which the
+ * CDM CSC matrix should be updated to based
+ * on the connector HDR state
+ */
+ conn_csc = sde_connector_get_csc_type(conn_mas);
+ if (phys && mode_is_yuv) {
+ if (phys->enc_cdm_csc != conn_csc) {
+ hw_cdm = phys->hw_cdm;
+ rc = hw_cdm->ops.setup_csc_data(hw_cdm,
+ &sde_csc_10bit_convert[conn_csc]);
+
+ if (rc)
+ SDE_ERROR_ENC(sde_enc,
+ "CSC setup failed rc %d\n",
+ rc);
+ SDE_DEBUG_ENC(sde_enc,
+ "updating CSC %d to %d\n",
+ phys->enc_cdm_csc,
+ conn_csc);
+ phys->enc_cdm_csc = conn_csc;
+
+ }
+ }
+ }
}
}
@@ -1507,6 +1583,9 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
}
}
+ /* Cache the CSC default matrix type */
+ phys_enc->enc_cdm_csc = csc_type;
+
if (hw_cdm && hw_cdm->ops.setup_cdwn) {
ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index 20f125155de3..aec844d640bd 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -174,6 +174,7 @@ enum sde_intr_idx {
* @split_role: Role to play in a split-panel configuration
* @intf_mode: Interface mode
* @intf_idx: Interface index on sde hardware
+ * @enc_cdm_csc: Cached CSC type of CDM block
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
* @enable_state: Enable state tracking
* @vblank_refcount: Reference count of vblank request
@@ -201,6 +202,7 @@ struct sde_encoder_phys {
enum sde_enc_split_role split_role;
enum sde_intf_mode intf_mode;
enum sde_intf intf_idx;
+ enum sde_csc_type enc_cdm_csc;
spinlock_t *enc_spinlock;
enum sde_enc_enable_state enable_state;
atomic_t vblank_refcount;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
index 1edeff6a7aec..92dd829eee3e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
@@ -344,6 +344,9 @@ enum sde_3d_blend_mode {
enum sde_csc_type {
SDE_CSC_RGB2YUV_601L,
SDE_CSC_RGB2YUV_601FR,
+ SDE_CSC_RGB2YUV_709L,
+ SDE_CSC_RGB2YUV_2020L,
+ SDE_CSC_RGB2YUV_2020FR,
SDE_MAX_CSC
};
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index eaa1eca8fc8e..cdf67c0aa864 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -594,7 +594,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.set_property = sde_hdmi_set_property,
.get_property = sde_hdmi_get_property,
.pre_kickoff = sde_hdmi_pre_kickoff,
- .mode_needs_full_range = sde_hdmi_mode_needs_full_range
+ .mode_needs_full_range = sde_hdmi_mode_needs_full_range,
+ .get_csc_type = sde_hdmi_get_csc_type
};
struct msm_display_info info = {0};
struct drm_encoder *encoder;