Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +132 −1 Original line number Diff line number Diff line Loading @@ -1970,6 +1970,123 @@ enable_packet_control: hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control); } static void sde_hdmi_update_colorimetry(struct sde_hdmi *display, bool use_bt2020) { struct hdmi *hdmi; struct drm_connector *connector; bool mode_is_yuv = false; struct drm_display_mode *mode; u32 mode_fmt_flags = 0; u8 checksum; u32 avi_info0 = 0; u32 avi_info1 = 0; u8 avi_iframe[HDMI_AVI_INFOFRAME_BUFFER_SIZE] = {0}; u8 *avi_frame = &avi_iframe[HDMI_INFOFRAME_HEADER_SIZE]; struct hdmi_avi_infoframe info; if (!display) { SDE_ERROR("invalid input\n"); return; } hdmi = display->ctrl.ctrl; if (!hdmi) { SDE_ERROR("invalid input\n"); return; } connector = display->ctrl.ctrl->connector; if (!connector) { SDE_ERROR("invalid input\n"); return; } if (!connector->hdr_supported) { SDE_DEBUG("HDR is not supported\n"); return; } /* If sink doesn't support BT2020, just return */ if (!(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_YCC) || !(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_RGB)) { SDE_DEBUG("BT2020 colorimetry is not supported\n"); return; } /* If there is no change in colorimetry, just return */ if (use_bt2020 && display->bt2020_colorimetry) return; else if (!use_bt2020 && !display->bt2020_colorimetry) return; mode = &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; drm_hdmi_avi_infoframe_from_display_mode(&info, mode); /* Restore the format flags */ mode->flags = mode_fmt_flags; /* Mode should only support YUV and not both to set the flag */ if ((mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) && !(mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_RGB444)) { mode_is_yuv = true; } if (!display->bt2020_colorimetry && use_bt2020) { /** * 1. Update colorimetry to use extended * 2. Change extended to use BT2020 * 3. Change colorspace based on mode * 4. Use limited as BT2020 is always limited */ info.colorimetry = SDE_HDMI_USE_EXTENDED_COLORIMETRY; info.extended_colorimetry = SDE_HDMI_BT2020_COLORIMETRY; if (mode_is_yuv) info.colorspace = HDMI_COLORSPACE_YUV420; if (connector->yuv_qs) info.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; } else if (display->bt2020_colorimetry && !use_bt2020) { /** * 1. Update colorimetry to non-extended * 2. Change colorspace based on mode * 3. Restore quantization to full if QS * is enabled */ info.colorimetry = SDE_HDMI_DEFAULT_COLORIMETRY; if (mode_is_yuv) info.colorspace = HDMI_COLORSPACE_YUV420; 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]; avi_info0 = checksum | LEFT_SHIFT_BYTE(avi_frame[0]) | LEFT_SHIFT_WORD(avi_frame[1]) | LEFT_SHIFT_24BITS(avi_frame[2]); avi_info1 = avi_frame[3] | LEFT_SHIFT_BYTE(avi_frame[4]) | LEFT_SHIFT_WORD(avi_frame[5]) | LEFT_SHIFT_24BITS(avi_frame[6]); hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), avi_info0); hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), avi_info1); display->bt2020_colorimetry = use_bt2020; } static void sde_hdmi_clear_hdr_infoframe(struct sde_hdmi *display) { struct hdmi *hdmi; Loading Loading @@ -2340,14 +2457,22 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector, { struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display; struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl; struct drm_msm_ext_panel_hdr_metadata *hdr_meta; u8 hdr_op; if (!connector || !display || !params) { if (!connector || !display || !params || !params->hdr_ctrl) { pr_err("Invalid params\n"); return -EINVAL; } hdr_ctrl = params->hdr_ctrl; hdr_meta = &hdr_ctrl->hdr_meta; if (!hdr_meta) { SDE_ERROR("Invalid params\n"); return -EINVAL; } hdr_op = sde_hdmi_hdr_get_ops(hdmi_display->curr_hdr_state, hdr_ctrl->hdr_state); Loading @@ -2356,6 +2481,12 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector, if (connector->hdr_supported) sde_hdmi_panel_set_hdr_infoframe(display, &hdr_ctrl->hdr_meta); if (hdr_meta->eotf) sde_hdmi_update_colorimetry(hdmi_display, true); else sde_hdmi_update_colorimetry(hdmi_display, false); } else if (hdr_op == HDR_CLEAR_INFO) sde_hdmi_clear_hdr_infoframe(display); Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +10 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,7 @@ struct sde_hdmi { bool pll_update_enable; bool dc_enable; bool dc_feature_supported; bool bt2020_colorimetry; struct delayed_work hdcp_cb_work; struct dss_io_data io[HDMI_TX_MAX_IO]; Loading Loading @@ -201,6 +202,15 @@ enum hdmi_tx_scdc_access_type { #define HDMI_GEN_PKT_CTRL_CLR_MASK 0x7 /* for AVI program */ #define HDMI_AVI_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE) #define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6) #define LEFT_SHIFT_BYTE(x) ((x) << 8) #define LEFT_SHIFT_WORD(x) ((x) << 16) #define LEFT_SHIFT_24BITS(x) ((x) << 24) /* Maximum pixel clock rates for hdmi tx */ #define HDMI_DEFAULT_MAX_PCLK_RATE 148500 #define HDMI_TX_3_MAX_PCLK_RATE 297000 Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +0 −7 Original line number Diff line number Diff line Loading @@ -99,17 +99,10 @@ struct sde_hdmi_bridge { #define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200 /* for AVI program */ #define HDMI_AVI_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE) #define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6) #define HDMI_SPD_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE) #define HDMI_DEFAULT_VENDOR_NAME "unknown" #define HDMI_DEFAULT_PRODUCT_NAME "msm" #define LEFT_SHIFT_BYTE(x) ((x) << 8) #define LEFT_SHIFT_WORD(x) ((x) << 16) #define LEFT_SHIFT_24BITS(x) ((x) << 24) #define HDMI_AVI_IFRAME_LINE_NUMBER 1 #define HDMI_VENDOR_IFRAME_LINE_NUMBER 3 Loading drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h +6 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,12 @@ #define HDMI_GET_LSB(x)(x & 0xff) #define SDE_HDMI_VIC_640x480 0x1 #define SDE_HDMI_YCC_QUANT_MASK (0x3 << 14) #define SDE_HDMI_COLORIMETRY_MASK (0x3 << 22) #define SDE_HDMI_DEFAULT_COLORIMETRY 0x0 #define SDE_HDMI_USE_EXTENDED_COLORIMETRY 0x3 #define SDE_HDMI_BT2020_COLORIMETRY 0x6 /* * Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be Loading Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +132 −1 Original line number Diff line number Diff line Loading @@ -1970,6 +1970,123 @@ enable_packet_control: hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control); } static void sde_hdmi_update_colorimetry(struct sde_hdmi *display, bool use_bt2020) { struct hdmi *hdmi; struct drm_connector *connector; bool mode_is_yuv = false; struct drm_display_mode *mode; u32 mode_fmt_flags = 0; u8 checksum; u32 avi_info0 = 0; u32 avi_info1 = 0; u8 avi_iframe[HDMI_AVI_INFOFRAME_BUFFER_SIZE] = {0}; u8 *avi_frame = &avi_iframe[HDMI_INFOFRAME_HEADER_SIZE]; struct hdmi_avi_infoframe info; if (!display) { SDE_ERROR("invalid input\n"); return; } hdmi = display->ctrl.ctrl; if (!hdmi) { SDE_ERROR("invalid input\n"); return; } connector = display->ctrl.ctrl->connector; if (!connector) { SDE_ERROR("invalid input\n"); return; } if (!connector->hdr_supported) { SDE_DEBUG("HDR is not supported\n"); return; } /* If sink doesn't support BT2020, just return */ if (!(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_YCC) || !(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_RGB)) { SDE_DEBUG("BT2020 colorimetry is not supported\n"); return; } /* If there is no change in colorimetry, just return */ if (use_bt2020 && display->bt2020_colorimetry) return; else if (!use_bt2020 && !display->bt2020_colorimetry) return; mode = &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; drm_hdmi_avi_infoframe_from_display_mode(&info, mode); /* Restore the format flags */ mode->flags = mode_fmt_flags; /* Mode should only support YUV and not both to set the flag */ if ((mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) && !(mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_RGB444)) { mode_is_yuv = true; } if (!display->bt2020_colorimetry && use_bt2020) { /** * 1. Update colorimetry to use extended * 2. Change extended to use BT2020 * 3. Change colorspace based on mode * 4. Use limited as BT2020 is always limited */ info.colorimetry = SDE_HDMI_USE_EXTENDED_COLORIMETRY; info.extended_colorimetry = SDE_HDMI_BT2020_COLORIMETRY; if (mode_is_yuv) info.colorspace = HDMI_COLORSPACE_YUV420; if (connector->yuv_qs) info.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; } else if (display->bt2020_colorimetry && !use_bt2020) { /** * 1. Update colorimetry to non-extended * 2. Change colorspace based on mode * 3. Restore quantization to full if QS * is enabled */ info.colorimetry = SDE_HDMI_DEFAULT_COLORIMETRY; if (mode_is_yuv) info.colorspace = HDMI_COLORSPACE_YUV420; 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]; avi_info0 = checksum | LEFT_SHIFT_BYTE(avi_frame[0]) | LEFT_SHIFT_WORD(avi_frame[1]) | LEFT_SHIFT_24BITS(avi_frame[2]); avi_info1 = avi_frame[3] | LEFT_SHIFT_BYTE(avi_frame[4]) | LEFT_SHIFT_WORD(avi_frame[5]) | LEFT_SHIFT_24BITS(avi_frame[6]); hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), avi_info0); hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), avi_info1); display->bt2020_colorimetry = use_bt2020; } static void sde_hdmi_clear_hdr_infoframe(struct sde_hdmi *display) { struct hdmi *hdmi; Loading Loading @@ -2340,14 +2457,22 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector, { struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display; struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl; struct drm_msm_ext_panel_hdr_metadata *hdr_meta; u8 hdr_op; if (!connector || !display || !params) { if (!connector || !display || !params || !params->hdr_ctrl) { pr_err("Invalid params\n"); return -EINVAL; } hdr_ctrl = params->hdr_ctrl; hdr_meta = &hdr_ctrl->hdr_meta; if (!hdr_meta) { SDE_ERROR("Invalid params\n"); return -EINVAL; } hdr_op = sde_hdmi_hdr_get_ops(hdmi_display->curr_hdr_state, hdr_ctrl->hdr_state); Loading @@ -2356,6 +2481,12 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector, if (connector->hdr_supported) sde_hdmi_panel_set_hdr_infoframe(display, &hdr_ctrl->hdr_meta); if (hdr_meta->eotf) sde_hdmi_update_colorimetry(hdmi_display, true); else sde_hdmi_update_colorimetry(hdmi_display, false); } else if (hdr_op == HDR_CLEAR_INFO) sde_hdmi_clear_hdr_infoframe(display); Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +10 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,7 @@ struct sde_hdmi { bool pll_update_enable; bool dc_enable; bool dc_feature_supported; bool bt2020_colorimetry; struct delayed_work hdcp_cb_work; struct dss_io_data io[HDMI_TX_MAX_IO]; Loading Loading @@ -201,6 +202,15 @@ enum hdmi_tx_scdc_access_type { #define HDMI_GEN_PKT_CTRL_CLR_MASK 0x7 /* for AVI program */ #define HDMI_AVI_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE) #define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6) #define LEFT_SHIFT_BYTE(x) ((x) << 8) #define LEFT_SHIFT_WORD(x) ((x) << 16) #define LEFT_SHIFT_24BITS(x) ((x) << 24) /* Maximum pixel clock rates for hdmi tx */ #define HDMI_DEFAULT_MAX_PCLK_RATE 148500 #define HDMI_TX_3_MAX_PCLK_RATE 297000 Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +0 −7 Original line number Diff line number Diff line Loading @@ -99,17 +99,10 @@ struct sde_hdmi_bridge { #define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200 /* for AVI program */ #define HDMI_AVI_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE) #define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6) #define HDMI_SPD_INFOFRAME_BUFFER_SIZE \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE) #define HDMI_DEFAULT_VENDOR_NAME "unknown" #define HDMI_DEFAULT_PRODUCT_NAME "msm" #define LEFT_SHIFT_BYTE(x) ((x) << 8) #define LEFT_SHIFT_WORD(x) ((x) << 16) #define LEFT_SHIFT_24BITS(x) ((x) << 24) #define HDMI_AVI_IFRAME_LINE_NUMBER 1 #define HDMI_VENDOR_IFRAME_LINE_NUMBER 3 Loading
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h +6 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,12 @@ #define HDMI_GET_LSB(x)(x & 0xff) #define SDE_HDMI_VIC_640x480 0x1 #define SDE_HDMI_YCC_QUANT_MASK (0x3 << 14) #define SDE_HDMI_COLORIMETRY_MASK (0x3 << 22) #define SDE_HDMI_DEFAULT_COLORIMETRY 0x0 #define SDE_HDMI_USE_EXTENDED_COLORIMETRY 0x3 #define SDE_HDMI_BT2020_COLORIMETRY 0x6 /* * Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be Loading