diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 7f38d9c4fb91..a8fb7fd56a28 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -114,9 +114,11 @@ struct rockchip_hdmi { struct drm_property *hdmi_output_property; struct drm_property *colordepth_capacity; struct drm_property *outputmode_capacity; + struct drm_property *colorimetry_property; struct drm_property *quant_range; unsigned int colordepth; + unsigned int colorimetry; unsigned int hdmi_quant_range; unsigned int phy_bus_width; enum drm_hdmi_output_type hdmi_output; @@ -569,9 +571,11 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, *eotf = hdr_metadata->eotf; } - if (*eotf > TRADITIONAL_GAMMA_HDR && - conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & - BIT(*eotf)) + if ((*eotf > TRADITIONAL_GAMMA_HDR && + conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & + BIT(*eotf)) || (hdmi->colorimetry == + HDMI_EXTENDED_COLORIMETRY_BT2020 && info->hdmi.colorimetry & + (BIT(6) | BIT(7)))) *enc_out_encoding = V4L2_YCBCR_ENC_BT2020; else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) || (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) @@ -580,8 +584,9 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, *enc_out_encoding = V4L2_YCBCR_ENC_709; if (*enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { - /* According to ITU.BT2020, color depth is at lest 10bit */ + /* BT2020 require color depth at lest 10bit */ *color_depth = 10; + /* We prefer use YCbCr422 to send 10bit */ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) *color_format = DRM_HDMI_OUTPUT_YCBCR422; } @@ -709,6 +714,14 @@ dw_hdmi_rockchip_get_output_bus_format(void *data) return hdmi->output_bus_format; } +static unsigned long +dw_hdmi_rockchip_get_enc_in_encoding(void *data) +{ + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + + return hdmi->enc_out_encoding; +} + static unsigned long dw_hdmi_rockchip_get_enc_out_encoding(void *data) { @@ -747,6 +760,12 @@ static const struct drm_prop_enum_list quant_range_enum_list[] = { { HDMI_QUANTIZATION_RANGE_FULL, "full" }, }; +static const struct drm_prop_enum_list colorimetry_enum_list[] = { + { HDMI_COLORIMETRY_NONE, "None" }, + { HDMI_COLORIMETRY_EXTENDED + HDMI_EXTENDED_COLORIMETRY_BT2020, + "ITU_2020" }, +}; + static void dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, unsigned int color, int version, @@ -810,6 +829,15 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, drm_object_attach_property(&connector->base, prop, 0); } + prop = drm_property_create_enum(connector->dev, 0, + "hdmi_output_colorimetry", + colorimetry_enum_list, + ARRAY_SIZE(colorimetry_enum_list)); + if (prop) { + hdmi->colorimetry_property = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + prop = drm_property_create_range(connector->dev, 0, "hdmi_color_depth_capacity", 0, 0xff); @@ -878,6 +906,12 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, hdmi->quant_range); hdmi->quant_range = NULL; } + + if (hdmi->colorimetry_property) { + drm_property_destroy(connector->dev, + hdmi->colorimetry_property); + hdmi->colordepth_capacity = NULL; + } } static int @@ -901,6 +935,9 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, return 0; } else if (property == config->hdr_output_metadata_property) { return 0; + } else if (property == hdmi->colorimetry_property) { + hdmi->colorimetry = val; + return 0; } DRM_ERROR("failed to set rockchip hdmi connector property\n"); @@ -959,6 +996,9 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector, *val = state->hdr_output_metadata ? state->hdr_output_metadata->base.id : 0; return 0; + } else if (property == hdmi->colorimetry_property) { + *val = hdmi->colorimetry; + return 0; } DRM_ERROR("failed to get rockchip hdmi connector property\n"); @@ -1197,6 +1237,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, dw_hdmi_rockchip_get_input_bus_format; plat_data->get_output_bus_format = dw_hdmi_rockchip_get_output_bus_format; + plat_data->get_enc_in_encoding = + dw_hdmi_rockchip_get_enc_in_encoding; plat_data->get_enc_out_encoding = dw_hdmi_rockchip_get_enc_out_encoding; plat_data->get_quant_range =