diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 908147e3df81..e03838ca73ad 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2584,6 +2584,7 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); struct drm_display_mode *mode = NULL; + void *data = hdmi->plat_data->phy_data; if (!hdmi->hpd_state || !conn_state->crtc) return; @@ -2595,6 +2596,19 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, * drm_display_mode and set phy status to enabled. */ if (!hdmi->hdmi_data.video_mode.mpixelclock) { + if (hdmi->plat_data->get_enc_in_encoding) + hdmi->hdmi_data.enc_in_encoding = + hdmi->plat_data->get_enc_in_encoding(data); + if (hdmi->plat_data->get_enc_out_encoding) + hdmi->hdmi_data.enc_out_encoding = + hdmi->plat_data->get_enc_out_encoding(data); + if (hdmi->plat_data->get_input_bus_format) + hdmi->hdmi_data.enc_in_bus_format = + hdmi->plat_data->get_input_bus_format(data); + if (hdmi->plat_data->get_output_bus_format) + hdmi->hdmi_data.enc_out_bus_format = + hdmi->plat_data->get_output_bus_format(data); + mode = &conn_state->crtc->mode; memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); hdmi->hdmi_data.video_mode.mpixelclock = mode->clock; @@ -2949,12 +2963,53 @@ static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = { static void dw_hdmi_attatch_properties(struct dw_hdmi *hdmi) { + unsigned int color = MEDIA_BUS_FMT_RGB888_1X24; + int video_mapping, colorspace; + enum drm_connector_status connect_status = + hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; + if (connect_status == connector_status_connected) { + video_mapping = (hdmi_readb(hdmi, HDMI_TX_INVID0) & + HDMI_TX_INVID0_VIDEO_MAPPING_MASK); + colorspace = (hdmi_readb(hdmi, HDMI_FC_AVICONF0) & + HDMI_FC_AVICONF0_PIX_FMT_MASK); + switch (video_mapping) { + case 0x01: + color = MEDIA_BUS_FMT_RGB888_1X24; + break; + case 0x03: + color = MEDIA_BUS_FMT_RGB101010_1X30; + break; + case 0x09: + if (colorspace == HDMI_COLORSPACE_YUV420) + color = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + else + color = MEDIA_BUS_FMT_YUV8_1X24; + break; + case 0x0b: + if (colorspace == HDMI_COLORSPACE_YUV420) + color = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + else + color = MEDIA_BUS_FMT_YUV10_1X30; + break; + case 0x14: + color = MEDIA_BUS_FMT_UYVY10_1X20; + break; + case 0x16: + color = MEDIA_BUS_FMT_UYVY8_1X16; + break; + default: + color = MEDIA_BUS_FMT_RGB888_1X24; + dev_err(hdmi->dev, "unexpected mapping: 0x%x\n", + video_mapping); + } + } + if (ops && ops->attatch_properties) return ops->attatch_properties(&hdmi->connector, - hdmi->version, + color, hdmi->version, hdmi->plat_data->phy_data); } diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index dbd6c303e0f3..0f818338e20f 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -865,11 +865,46 @@ static const struct drm_prop_enum_list colorimetry_enum_list[] = { static void dw_hdmi_rockchip_attatch_properties(struct drm_connector *connector, - int version, void *data) + unsigned int color, int version, + void *data) { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; struct drm_property *prop; + switch (color) { + case MEDIA_BUS_FMT_RGB101010_1X30: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB; + hdmi->colordepth = 10; + break; + case MEDIA_BUS_FMT_YUV8_1X24: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444; + hdmi->colordepth = 8; + break; + case MEDIA_BUS_FMT_YUV10_1X30: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444; + hdmi->colordepth = 10; + break; + case MEDIA_BUS_FMT_UYVY10_1X20: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422; + hdmi->colordepth = 10; + break; + case MEDIA_BUS_FMT_UYVY8_1X16: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422; + hdmi->colordepth = 8; + break; + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420; + hdmi->colordepth = 8; + break; + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420; + hdmi->colordepth = 10; + break; + default: + hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB; + hdmi->colordepth = 8; + } + /* RK3368 does not support deep color mode */ if (!hdmi->color_depth_property && hdmi->dev_type != RK3368_HDMI) { prop = drm_property_create_enum(connector->dev, 0, diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index e6cf3da43aa8..29c7c832cb9b 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -139,7 +139,7 @@ struct dw_hdmi_phy_ops { struct dw_hdmi_property_ops { void (*attatch_properties)(struct drm_connector *connector, - int version, + unsigned int color, int version, void *data); void (*destroy_properties)(struct drm_connector *connector, void *data);