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:
parent
d4921e03a9
commit
ce2aa51732
6 changed files with 91 additions and 6 deletions
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue