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>
This commit is contained in:
Chirag Khurana 2019-11-20 18:27:03 +05:30 • committed by Gerrit - the friendly Code Review server
commit ce2aa51732
6 changed files with 91 additions and 6 deletions

View file

@ -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 @@ struct dp_display {
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_ */

View file

@ -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 @@ int dp_connector_get_info(struct msm_display_info *info, void *data)
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)

View file

@ -724,6 +724,28 @@ int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
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;

View file

@ -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
@ -183,6 +183,14 @@ struct sde_connector_ops {
void *display,
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
@ -702,6 +710,14 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector)
return (c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL);
}
/**
* 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

View file

@ -5171,6 +5171,7 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
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 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
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,

View file

@ -1318,6 +1318,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.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,