drm/msm: change CSC matrix selection logic for CDM block
CDM block is always using a limited quantization range
matrix.
This can be overridden to use a full range matrix if
the sink supports override capability or the mode is a
non-CEA mode.
Adjust the matrix selection logic to accommodate full
range quantization as well.
Change-Id: I708412a923fb0d47e798f35ebe14b4c2f1a72fc9
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Signed-off-by: Chirag Khurana <ckhurana@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 266de5f..4da21d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,4 +50,5 @@
int dp_display_get_num_of_displays(void);
int dp_display_get_displays(void **displays, int count);
+bool dp_connector_mode_needs_full_range(void *display);
#endif /* _DP_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 7c817d3..5b78218 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -356,6 +356,34 @@
return 0;
}
+bool dp_connector_mode_needs_full_range(void *data)
+{
+ struct dp_display *display = data;
+ struct dp_bridge *bridge;
+ struct dp_display_mode *mode;
+ struct dp_panel_info *timing;
+
+ if (!display) {
+ pr_err("invalid input\n");
+ return false;
+ }
+
+ bridge = display->bridge;
+ if (!bridge) {
+ pr_err("invalid bridge data\n");
+ return false;
+ }
+
+ mode = &bridge->dp_mode;
+ timing = &mode->timing;
+
+ if (timing->h_active == 640 &&
+ timing->v_active == 480)
+ return true;
+
+ return false;
+}
+
enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
bool force,
void *display)
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 96df60f..9fba20f 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -724,6 +724,28 @@
return rc;
}
+bool sde_connector_mode_needs_full_range(struct drm_connector *connector)
+{
+ struct sde_connector *c_conn;
+
+ if (!connector) {
+ SDE_ERROR("invalid argument\n");
+ return false;
+ }
+
+ c_conn = to_sde_connector(connector);
+
+ if (!c_conn->display) {
+ SDE_ERROR("invalid argument\n");
+ return false;
+ }
+
+ if (!c_conn->ops.mode_needs_full_range)
+ return false;
+
+ return c_conn->ops.mode_needs_full_range(c_conn->display);
+}
+
static void sde_connector_destroy(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 0ae6a91..87c2ee2 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -184,6 +184,14 @@
struct msm_display_kickoff_params *params);
/**
+ * mode_needs_full_range - does the mode need full range
+ * quantization
+ * @display: Pointer to private display structure
+ * Returns: true or false based on whether full range is needed
+ */
+ bool (*mode_needs_full_range)(void *display);
+
+ /**
* clk_ctrl - perform clk enable/disable on the connector
* @handle: Pointer to clk handle
* @type: Type of clks
@@ -703,6 +711,14 @@
}
/**
+ * sde_connector_mode_needs_full_range - query quantization type
+ * for the connector mode
+ * @connector: Pointer to drm connector object
+ * Returns: true OR false based on connector mode
+ */
+bool sde_connector_mode_needs_full_range(struct drm_connector *connector);
+
+/**
* sde_connector_get_dither_cfg - get dither property data
* @conn: Pointer to drm_connector struct
* @state: Pointer to drm_connector_state struct
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 21c883a..8594f54 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -5171,6 +5171,7 @@
struct sde_encoder_virt *sde_enc = NULL;
struct sde_hw_cdm *hw_cdm = phys_enc->hw_cdm;
struct sde_hw_cdm_cfg *cdm_cfg = &phys_enc->cdm_cfg;
+ struct drm_connector *connector = phys_enc->connector;
int ret;
u32 csc_type = 0;
@@ -5230,10 +5231,26 @@
cdm_cfg->h_cdwn_type,
cdm_cfg->v_cdwn_type);
- if (output_type == CDM_CDWN_OUTPUT_HDMI)
- csc_type = SDE_CSC_RGB2YUV_601FR;
- else if (output_type == CDM_CDWN_OUTPUT_WB)
+ /**
+ * Choose CSC matrix based on following rules:
+ * 1. If connector supports quantization select,
+ * pick Full-Range for better quality.
+ * 2. If non-CEA mode, then pick Full-Range as per CEA spec
+ * 3. Otherwise, pick Limited-Range as all other CEA modes
+ * need a limited range
+ */
+
+ if (output_type == CDM_CDWN_OUTPUT_HDMI) {
+ if (connector && connector->yuv_qs)
+ csc_type = SDE_CSC_RGB2YUV_601FR;
+ else if (connector &&
+ sde_connector_mode_needs_full_range(connector))
+ csc_type = SDE_CSC_RGB2YUV_601FR;
+ else
+ csc_type = SDE_CSC_RGB2YUV_601L;
+ } else if (output_type == CDM_CDWN_OUTPUT_WB) {
csc_type = SDE_CSC_RGB2YUV_601L;
+ }
if (hw_cdm && hw_cdm->ops.setup_csc_data) {
ret = hw_cdm->ops.setup_csc_data(hw_cdm,
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 88af0c0..68c3ca0 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1318,6 +1318,7 @@
.cmd_transfer = NULL,
.cont_splash_config = NULL,
.get_panel_vfp = NULL,
+ .mode_needs_full_range = dp_connector_mode_needs_full_range,
};
static const struct sde_connector_ops ext_bridge_ops = {
.set_info_blob = dsi_conn_set_info_blob,