Loading drivers/gpu/drm/msm/dp/dp_display.h +3 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, 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 Loading Loading @@ -51,4 +51,6 @@ 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); enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, void *data); #endif /* _DP_DISPLAY_H_ */ drivers/gpu/drm/msm/dp/dp_drm.c +38 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, 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 Loading @@ -26,6 +26,11 @@ #define to_dp_bridge(x) container_of((x), struct dp_bridge, base) enum dp_connector_hdr_state { HDR_DISABLE, HDR_ENABLE }; static void convert_to_dp_mode(const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode, struct dp_display *dp) { Loading Loading @@ -384,6 +389,38 @@ bool dp_connector_mode_needs_full_range(void *data) return false; } enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, void *data) { struct dp_display *display = data; struct sde_connector_state *c_state; struct drm_msm_ext_hdr_metadata *hdr_meta; if (!display || !conn) { pr_err("invalid input\n"); goto error; } c_state = to_sde_connector_state(conn->state); if (!c_state) { pr_err("invalid input\n"); goto error; } hdr_meta = &c_state->hdr_meta; if ((hdr_meta->hdr_state == HDR_ENABLE) && (hdr_meta->eotf != 0)) return SDE_CSC_RGB2YUV_2020L; else if (dp_connector_mode_needs_full_range(data) || conn->yuv_qs) return SDE_CSC_RGB2YUV_601FR; error: return SDE_CSC_RGB2YUV_601L; } enum drm_connector_status dp_connector_detect(struct drm_connector *conn, bool force, void *display) Loading drivers/gpu/drm/msm/sde/sde_connector.c +23 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, 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 Loading Loading @@ -724,6 +724,28 @@ int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable) 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 +18 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, 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 Loading Loading @@ -198,6 +198,15 @@ struct sde_connector_ops { * @enable: State of clks */ int (*clk_ctrl)(void *handle, u32 type, u32 state); /** * 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); /** * set_power - update dpms setting Loading Loading @@ -718,6 +727,14 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector) */ 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); /** * sde_connector_get_dither_cfg - get dither property data * @conn: Pointer to drm_connector struct Loading drivers/gpu/drm/msm/sde/sde_encoder.c +84 −5 Original line number Diff line number Diff line /* * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading Loading @@ -186,6 +186,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 @@ -4058,10 +4094,15 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_phys *phys; struct sde_kms *sde_kms = NULL; struct msm_drm_private *priv = NULL; struct drm_connector *conn_mas = NULL; struct drm_display_mode *mode; struct sde_hw_cdm *hw_cdm; enum sde_csc_type conn_csc; bool needs_hw_reset = false; uint32_t ln_cnt1, ln_cnt2; unsigned int i; int rc, ret = 0; int mode_is_yuv = 0; if (!drm_enc || !params || !drm_enc->dev || !drm_enc->dev->dev_private) { Loading Loading @@ -4131,13 +4172,48 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, _sde_encoder_update_roi(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, SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n", conn_mas->base.id, rc); ret = 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; } } } } if (_sde_encoder_is_dsc_enabled(drm_enc) && Loading Loading @@ -5261,6 +5337,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/dp/dp_display.h +3 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, 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 Loading Loading @@ -51,4 +51,6 @@ 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); enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, void *data); #endif /* _DP_DISPLAY_H_ */
drivers/gpu/drm/msm/dp/dp_drm.c +38 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, 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 Loading @@ -26,6 +26,11 @@ #define to_dp_bridge(x) container_of((x), struct dp_bridge, base) enum dp_connector_hdr_state { HDR_DISABLE, HDR_ENABLE }; static void convert_to_dp_mode(const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode, struct dp_display *dp) { Loading Loading @@ -384,6 +389,38 @@ bool dp_connector_mode_needs_full_range(void *data) return false; } enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, void *data) { struct dp_display *display = data; struct sde_connector_state *c_state; struct drm_msm_ext_hdr_metadata *hdr_meta; if (!display || !conn) { pr_err("invalid input\n"); goto error; } c_state = to_sde_connector_state(conn->state); if (!c_state) { pr_err("invalid input\n"); goto error; } hdr_meta = &c_state->hdr_meta; if ((hdr_meta->hdr_state == HDR_ENABLE) && (hdr_meta->eotf != 0)) return SDE_CSC_RGB2YUV_2020L; else if (dp_connector_mode_needs_full_range(data) || conn->yuv_qs) return SDE_CSC_RGB2YUV_601FR; error: return SDE_CSC_RGB2YUV_601L; } enum drm_connector_status dp_connector_detect(struct drm_connector *conn, bool force, void *display) Loading
drivers/gpu/drm/msm/sde/sde_connector.c +23 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, 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 Loading Loading @@ -724,6 +724,28 @@ int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable) 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 +18 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, 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 Loading Loading @@ -198,6 +198,15 @@ struct sde_connector_ops { * @enable: State of clks */ int (*clk_ctrl)(void *handle, u32 type, u32 state); /** * 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); /** * set_power - update dpms setting Loading Loading @@ -718,6 +727,14 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector) */ 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); /** * sde_connector_get_dither_cfg - get dither property data * @conn: Pointer to drm_connector struct Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +84 −5 Original line number Diff line number Diff line /* * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading Loading @@ -186,6 +186,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 @@ -4058,10 +4094,15 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_phys *phys; struct sde_kms *sde_kms = NULL; struct msm_drm_private *priv = NULL; struct drm_connector *conn_mas = NULL; struct drm_display_mode *mode; struct sde_hw_cdm *hw_cdm; enum sde_csc_type conn_csc; bool needs_hw_reset = false; uint32_t ln_cnt1, ln_cnt2; unsigned int i; int rc, ret = 0; int mode_is_yuv = 0; if (!drm_enc || !params || !drm_enc->dev || !drm_enc->dev->dev_private) { Loading Loading @@ -4131,13 +4172,48 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, _sde_encoder_update_roi(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, SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n", conn_mas->base.id, rc); ret = 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; } } } } if (_sde_encoder_is_dsc_enabled(drm_enc) && Loading Loading @@ -5261,6 +5337,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