Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/connector: hdmi: Add custom hook to filter TMDS character rate

Most of the HDMI controllers have an upper TMDS character rate limit
they can't exceed. On "embedded"-grade display controllers, it will
typically be lower than what high-grade monitors can provide these days,
so drivers will filter the TMDS character rate based on the controller
capabilities.

To make that easier to handle for drivers, let's provide an optional
hook to be implemented by drivers so they can tell the HDMI controller
helpers if a given TMDS character rate is reachable for them or not.

This will then be useful to figure out the best format and bpc count for
a given mode.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240527-kms-hdmi-connector-state-v15-13-c5af16c3aae2@kernel.org
Signed-off-by: Maxime Ripard <mripard@kernel.org>

+62
+9
drivers/gpu/drm/display/drm_hdmi_state_helper.c
··· 53 53 const struct drm_display_mode *mode, 54 54 unsigned long long clock) 55 55 { 56 + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 56 57 const struct drm_display_info *info = &connector->display_info; 57 58 58 59 if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) 59 60 return MODE_CLOCK_HIGH; 61 + 62 + if (funcs && funcs->tmds_char_rate_valid) { 63 + enum drm_mode_status status; 64 + 65 + status = funcs->tmds_char_rate_valid(connector, mode, clock); 66 + if (status != MODE_OK) 67 + return status; 68 + } 60 69 61 70 return MODE_OK; 62 71 }
+4
drivers/gpu/drm/drm_connector.c
··· 457 457 * @dev: DRM device 458 458 * @connector: A pointer to the HDMI connector to init 459 459 * @funcs: callbacks for this connector 460 + * @hdmi_funcs: HDMI-related callbacks for this connector 460 461 * @connector_type: user visible type of the connector 461 462 * @ddc: optional pointer to the associated ddc adapter 462 463 * @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats ··· 477 476 int drmm_connector_hdmi_init(struct drm_device *dev, 478 477 struct drm_connector *connector, 479 478 const struct drm_connector_funcs *funcs, 479 + const struct drm_connector_hdmi_funcs *hdmi_funcs, 480 480 int connector_type, 481 481 struct i2c_adapter *ddc, 482 482 unsigned long supported_formats, ··· 513 511 514 512 if (max_bpc > 8) 515 513 drm_connector_attach_hdr_output_metadata_property(connector); 514 + 515 + connector->hdmi.funcs = hdmi_funcs; 516 516 517 517 return 0; 518 518 }
+14
drivers/gpu/drm/tests/drm_connector_test.c
··· 24 24 struct i2c_adapter ddc; 25 25 }; 26 26 27 + static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = { 28 + }; 29 + 27 30 static const struct drm_connector_funcs dummy_funcs = { 28 31 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 29 32 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ··· 192 189 193 190 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 194 191 &dummy_funcs, 192 + &dummy_hdmi_funcs, 195 193 DRM_MODE_CONNECTOR_HDMIA, 196 194 &priv->ddc, 197 195 BIT(HDMI_COLORSPACE_RGB), ··· 211 207 212 208 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 213 209 &dummy_funcs, 210 + &dummy_hdmi_funcs, 214 211 DRM_MODE_CONNECTOR_HDMIA, 215 212 NULL, 216 213 BIT(HDMI_COLORSPACE_RGB), ··· 230 225 231 226 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 232 227 &dummy_funcs, 228 + &dummy_hdmi_funcs, 233 229 DRM_MODE_CONNECTOR_HDMIA, 234 230 &priv->ddc, 235 231 BIT(HDMI_COLORSPACE_RGB), ··· 249 243 250 244 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 251 245 &dummy_funcs, 246 + &dummy_hdmi_funcs, 252 247 DRM_MODE_CONNECTOR_HDMIA, 253 248 &priv->ddc, 254 249 BIT(HDMI_COLORSPACE_RGB), ··· 273 266 274 267 ret = drmm_connector_hdmi_init(&priv->drm, connector, 275 268 &dummy_funcs, 269 + &dummy_hdmi_funcs, 276 270 DRM_MODE_CONNECTOR_HDMIA, 277 271 &priv->ddc, 278 272 BIT(HDMI_COLORSPACE_RGB), ··· 313 305 314 306 ret = drmm_connector_hdmi_init(&priv->drm, connector, 315 307 &dummy_funcs, 308 + &dummy_hdmi_funcs, 316 309 DRM_MODE_CONNECTOR_HDMIA, 317 310 &priv->ddc, 318 311 BIT(HDMI_COLORSPACE_RGB), ··· 353 344 354 345 ret = drmm_connector_hdmi_init(&priv->drm, connector, 355 346 &dummy_funcs, 347 + &dummy_hdmi_funcs, 356 348 DRM_MODE_CONNECTOR_HDMIA, 357 349 &priv->ddc, 358 350 BIT(HDMI_COLORSPACE_RGB), ··· 388 378 389 379 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 390 380 &dummy_funcs, 381 + &dummy_hdmi_funcs, 391 382 DRM_MODE_CONNECTOR_HDMIA, 392 383 &priv->ddc, 393 384 0, ··· 407 396 408 397 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 409 398 &dummy_funcs, 399 + &dummy_hdmi_funcs, 410 400 DRM_MODE_CONNECTOR_HDMIA, 411 401 &priv->ddc, 412 402 BIT(HDMI_COLORSPACE_YUV422), ··· 427 415 428 416 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 429 417 &dummy_funcs, 418 + &dummy_hdmi_funcs, 430 419 connector_type, 431 420 &priv->ddc, 432 421 BIT(HDMI_COLORSPACE_RGB), ··· 461 448 462 449 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 463 450 &dummy_funcs, 451 + &dummy_hdmi_funcs, 464 452 connector_type, 465 453 &priv->ddc, 466 454 BIT(HDMI_COLORSPACE_RGB),
+4
drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
··· 112 112 return 0; 113 113 } 114 114 115 + static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = { 116 + }; 117 + 115 118 static int dummy_connector_get_modes(struct drm_connector *connector) 116 119 { 117 120 struct drm_atomic_helper_connector_hdmi_priv *priv = ··· 197 194 conn = &priv->connector; 198 195 ret = drmm_connector_hdmi_init(drm, conn, 199 196 &dummy_connector_funcs, 197 + &dummy_connector_hdmi_funcs, 200 198 DRM_MODE_CONNECTOR_HDMIA, 201 199 NULL, 202 200 formats,
+31
include/drm/drm_connector.h
··· 38 38 struct drm_modeset_acquire_ctx; 39 39 struct drm_device; 40 40 struct drm_crtc; 41 + struct drm_display_mode; 41 42 struct drm_encoder; 42 43 struct drm_panel; 43 44 struct drm_property; ··· 1059 1058 }; 1060 1059 1061 1060 /** 1061 + * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions 1062 + */ 1063 + struct drm_connector_hdmi_funcs { 1064 + /** 1065 + * @tmds_char_rate_valid: 1066 + * 1067 + * This callback is invoked at atomic_check time to figure out 1068 + * whether a particular TMDS character rate is supported by the 1069 + * driver. 1070 + * 1071 + * The @tmds_char_rate_valid callback is optional. 1072 + * 1073 + * Returns: 1074 + * 1075 + * Either &drm_mode_status.MODE_OK or one of the failure reasons 1076 + * in &enum drm_mode_status. 1077 + */ 1078 + enum drm_mode_status 1079 + (*tmds_char_rate_valid)(const struct drm_connector *connector, 1080 + const struct drm_display_mode *mode, 1081 + unsigned long long tmds_rate); 1082 + }; 1083 + 1084 + /** 1062 1085 * struct drm_connector_funcs - control connectors on a given device 1063 1086 * 1064 1087 * Each CRTC may have one or more connectors attached to it. The functions ··· 1954 1929 * supported by the controller. 1955 1930 */ 1956 1931 unsigned long supported_formats; 1932 + 1933 + /** 1934 + * @funcs: HDMI connector Control Functions 1935 + */ 1936 + const struct drm_connector_hdmi_funcs *funcs; 1957 1937 } hdmi; 1958 1938 }; 1959 1939 ··· 1981 1951 int drmm_connector_hdmi_init(struct drm_device *dev, 1982 1952 struct drm_connector *connector, 1983 1953 const struct drm_connector_funcs *funcs, 1954 + const struct drm_connector_hdmi_funcs *hdmi_funcs, 1984 1955 int connector_type, 1985 1956 struct i2c_adapter *ddc, 1986 1957 unsigned long supported_formats,