Merge "drm/msm: change CSC matrix selection logic for CDM block"

This commit is contained in:
Linux Build Service Account 2017-08-11 16:23:51 -07:00 committed by Gerrit - the friendly Code Review server
commit de1f4ef405
8 changed files with 136 additions and 5 deletions

View file

@ -2364,6 +2364,36 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
return 0;
}
bool sde_hdmi_mode_needs_full_range(void *display)
{
struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
struct drm_display_mode *mode;
u32 mode_fmt_flags = 0;
u32 cea_mode;
if (!hdmi_display) {
SDE_ERROR("invalid input\n");
return false;
}
mode = &hdmi_display->mode;
/* Cache the format flags before clearing */
mode_fmt_flags = mode->flags;
/**
* Clear the RGB/YUV format flags before calling upstream API
* as the API also compares the flags and then returns a mode
*/
mode->flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK;
cea_mode = drm_match_cea_mode(mode);
/* Restore the format flags */
mode->flags = mode_fmt_flags;
if (cea_mode > SDE_HDMI_VIC_640x480)
return false;
return true;
}
int sde_hdmi_connector_get_modes(struct drm_connector *connector, void *display)
{
struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;

View file

@ -482,6 +482,14 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
void *display,
struct msm_display_kickoff_params *params);
/*
* sde_hdmi_mode_needs_full_range - does mode need full range
* quantization
* @display: Pointer to private display structure
* Returns: true or false based on mode
*/
bool sde_hdmi_mode_needs_full_range(void *display);
#else /*#ifdef CONFIG_DRM_SDE_HDMI*/
static inline u32 sde_hdmi_get_num_of_displays(void)
@ -596,5 +604,10 @@ static inline int sde_hdmi_set_property(struct drm_connector *connector,
return 0;
}
static inline bool sde_hdmi_mode_needs_full_range(void *display)
{
return false;
}
#endif /*#else of CONFIG_DRM_SDE_HDMI*/
#endif /* _SDE_HDMI_H_ */

View file

@ -582,18 +582,49 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
}
static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,
const struct drm_display_mode *mode)
struct drm_display_mode *mode)
{
u8 avi_iframe[HDMI_AVI_INFOFRAME_BUFFER_SIZE] = {0};
u8 *avi_frame = &avi_iframe[HDMI_INFOFRAME_HEADER_SIZE];
u8 checksum;
u32 reg_val;
u32 mode_fmt_flags = 0;
struct hdmi_avi_infoframe info;
struct drm_connector *connector;
if (!hdmi || !mode) {
SDE_ERROR("invalid input\n");
return;
}
connector = hdmi->connector;
if (!connector) {
SDE_ERROR("invalid input\n");
return;
}
/* Cache the format flags before clearing */
mode_fmt_flags = mode->flags;
/**
* Clear the RGB/YUV format flags before calling upstream API
* as the API also compares the flags and then returns a mode
*/
mode->flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK;
drm_hdmi_avi_infoframe_from_display_mode(&info, mode);
/* Restore the format flags */
mode->flags = mode_fmt_flags;
if (mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)
if (mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) {
info.colorspace = HDMI_COLORSPACE_YUV420;
/**
* If sink supports quantization select,
* override to full range
*/
if (connector->yuv_qs)
info.ycc_quantization_range =
HDMI_YCC_QUANTIZATION_RANGE_FULL;
}
hdmi_avi_infoframe_pack(&info, avi_iframe, sizeof(avi_iframe));
checksum = avi_iframe[HDMI_INFOFRAME_HEADER_SIZE - 1];

View file

@ -97,6 +97,8 @@
#define HDMI_GET_MSB(x)(x >> 8)
#define HDMI_GET_LSB(x)(x & 0xff)
#define SDE_HDMI_VIC_640x480 0x1
/*
* Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be
* read by the hardware

View file

@ -90,6 +90,28 @@ int sde_connector_pre_kickoff(struct drm_connector *connector)
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

@ -135,6 +135,14 @@ struct sde_connector_ops {
int (*pre_kickoff)(struct drm_connector *connector,
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);
};
/**
@ -327,5 +335,12 @@ int sde_connector_get_info(struct drm_connector *connector,
*/
int sde_connector_pre_kickoff(struct drm_connector *connector);
/**
* 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);
#endif /* _SDE_CONNECTOR_H_ */

View file

@ -1417,6 +1417,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;
@ -1476,10 +1477,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

@ -594,6 +594,7 @@ 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
};
struct msm_display_info info = {0};
struct drm_encoder *encoder;