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

drm: bridge: ti-sn65dsi83: Retrieve output format from bridge state

The driver currently iterates over all connectors to get the bus format,
used to configure the LVDS output format. This causes several issues:

- If other connectors than the LVDS output are present, the format used
by the driver may end up belonging to an entirely different output.

- The code can crash if some connectors are not connected, as bus_format
may then be NULL.

- There's no guarantee that the bus format on the connector at the
output of the pipeline matches the output of the sn65dsi83, as there
may be other bridges in the pipeline.

Solve this by retrieving the format from the bridge state instead, which
provides the format corresponding to the output of the bridge.

The struct sn65dsi83 lvds_format_24bpp and lvds_format_jeida fields are
moved to local variables in sn65dsi83_atomic_enable() as they're now
used in that function only.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Robert Foss <robert.foss@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210621125518.13715-5-laurent.pinchart@ideasonboard.com

authored by

Laurent Pinchart and committed by
Robert Foss
03ea01c0 a6ea7d26

+36 -37
+36 -37
drivers/gpu/drm/bridge/ti-sn65dsi83.c
··· 147 147 int dsi_lanes; 148 148 bool lvds_dual_link; 149 149 bool lvds_dual_link_even_odd_swap; 150 - bool lvds_format_24bpp; 151 - bool lvds_format_jeida; 152 150 }; 153 151 154 152 static const struct regmap_range sn65dsi83_readable_ranges[] = { ··· 369 371 struct drm_bridge_state *old_bridge_state) 370 372 { 371 373 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); 374 + struct drm_atomic_state *state = old_bridge_state->base.state; 375 + const struct drm_bridge_state *bridge_state; 376 + bool lvds_format_24bpp; 377 + bool lvds_format_jeida; 372 378 unsigned int pval; 373 379 __le16 le16val; 374 380 u16 val; 375 381 int ret; 382 + 383 + /* Get the LVDS format from the bridge state. */ 384 + bridge_state = drm_atomic_get_new_bridge_state(state, bridge); 385 + 386 + switch (bridge_state->output_bus_cfg.format) { 387 + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 388 + lvds_format_24bpp = false; 389 + lvds_format_jeida = true; 390 + break; 391 + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 392 + lvds_format_24bpp = true; 393 + lvds_format_jeida = true; 394 + break; 395 + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 396 + lvds_format_24bpp = true; 397 + lvds_format_jeida = false; 398 + break; 399 + default: 400 + /* 401 + * Some bridges still don't set the correct 402 + * LVDS bus pixel format, use SPWG24 default 403 + * format until those are fixed. 404 + */ 405 + lvds_format_24bpp = true; 406 + lvds_format_jeida = false; 407 + dev_warn(ctx->dev, 408 + "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", 409 + bridge_state->output_bus_cfg.format); 410 + break; 411 + } 376 412 377 413 /* Clear reset, disable PLL */ 378 414 regmap_write(ctx->regmap, REG_RC_RESET, 0x00); ··· 437 405 REG_LVDS_FMT_VS_NEG_POLARITY : 0); 438 406 439 407 /* Set up bits-per-pixel, 18bpp or 24bpp. */ 440 - if (ctx->lvds_format_24bpp) { 408 + if (lvds_format_24bpp) { 441 409 val |= REG_LVDS_FMT_CHA_24BPP_MODE; 442 410 if (ctx->lvds_dual_link) 443 411 val |= REG_LVDS_FMT_CHB_24BPP_MODE; 444 412 } 445 413 446 414 /* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */ 447 - if (ctx->lvds_format_jeida) { 415 + if (lvds_format_jeida) { 448 416 val |= REG_LVDS_FMT_CHA_24BPP_FORMAT1; 449 417 if (ctx->lvds_dual_link) 450 418 val |= REG_LVDS_FMT_CHB_24BPP_FORMAT1; ··· 547 515 const struct drm_display_mode *adj) 548 516 { 549 517 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); 550 - struct drm_encoder *encoder = bridge->encoder; 551 - struct drm_device *ddev = encoder->dev; 552 - struct drm_connector *connector; 553 518 554 519 ctx->mode = *adj; 555 - 556 - /* The DSI format is always RGB888_1X24 */ 557 - list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { 558 - switch (connector->display_info.bus_formats[0]) { 559 - case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 560 - ctx->lvds_format_24bpp = false; 561 - ctx->lvds_format_jeida = true; 562 - break; 563 - case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 564 - ctx->lvds_format_24bpp = true; 565 - ctx->lvds_format_jeida = true; 566 - break; 567 - case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 568 - ctx->lvds_format_24bpp = true; 569 - ctx->lvds_format_jeida = false; 570 - break; 571 - default: 572 - /* 573 - * Some bridges still don't set the correct 574 - * LVDS bus pixel format, use SPWG24 default 575 - * format until those are fixed. 576 - */ 577 - ctx->lvds_format_24bpp = true; 578 - ctx->lvds_format_jeida = false; 579 - dev_warn(ctx->dev, 580 - "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", 581 - connector->display_info.bus_formats[0]); 582 - break; 583 - } 584 - } 585 520 } 586 521 587 522 #define MAX_INPUT_SEL_FORMATS 1