Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +15 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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_ */ drivers/gpu/drm/msm/sde/sde_connector.c +22 −0 Original line number Diff line number Diff line Loading @@ -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; Loading drivers/gpu/drm/msm/sde/sde_connector.h +19 −0 Original line number Diff line number Diff line Loading @@ -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); }; /** Loading Loading @@ -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_ */ drivers/gpu/drm/msm/sde/sde_encoder.c +83 −4 Original line number Diff line number Diff line Loading @@ -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,}, }, }; /** Loading Loading @@ -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) { Loading @@ -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", 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, "kickoff conn%d failed rc %d\n", sde_enc->cur_master->connector->base.id, 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; } } } } } Loading Loading @@ -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) { Loading Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +15 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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_ */
drivers/gpu/drm/msm/sde/sde_connector.c +22 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
drivers/gpu/drm/msm/sde/sde_connector.h +19 −0 Original line number Diff line number Diff line Loading @@ -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); }; /** Loading Loading @@ -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_ */
drivers/gpu/drm/msm/sde/sde_encoder.c +83 −4 Original line number Diff line number Diff line Loading @@ -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,}, }, }; /** Loading Loading @@ -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) { Loading @@ -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", 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, "kickoff conn%d failed rc %d\n", sde_enc->cur_master->connector->base.id, 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; } } } } } Loading Loading @@ -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) { Loading