Merge "drm/msm: update CSC matrix during HDR playback"
This commit is contained in:
commit
6949010ef3
8 changed files with 180 additions and 5 deletions
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue