Commit 03ea01c0 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Robert Foss

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarRobert Foss <robert.foss@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210621125518.13715-5-laurent.pinchart@ideasonboard.com
parent a6ea7d26
...@@ -147,8 +147,6 @@ struct sn65dsi83 { ...@@ -147,8 +147,6 @@ struct sn65dsi83 {
int dsi_lanes; int dsi_lanes;
bool lvds_dual_link; bool lvds_dual_link;
bool lvds_dual_link_even_odd_swap; bool lvds_dual_link_even_odd_swap;
bool lvds_format_24bpp;
bool lvds_format_jeida;
}; };
static const struct regmap_range sn65dsi83_readable_ranges[] = { static const struct regmap_range sn65dsi83_readable_ranges[] = {
...@@ -371,11 +369,45 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, ...@@ -371,11 +369,45 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state) struct drm_bridge_state *old_bridge_state)
{ {
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
struct drm_atomic_state *state = old_bridge_state->base.state;
const struct drm_bridge_state *bridge_state;
bool lvds_format_24bpp;
bool lvds_format_jeida;
unsigned int pval; unsigned int pval;
__le16 le16val; __le16 le16val;
u16 val; u16 val;
int ret; int ret;
/* Get the LVDS format from the bridge state. */
bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
switch (bridge_state->output_bus_cfg.format) {
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
lvds_format_24bpp = false;
lvds_format_jeida = true;
break;
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
lvds_format_24bpp = true;
lvds_format_jeida = true;
break;
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
lvds_format_24bpp = true;
lvds_format_jeida = false;
break;
default:
/*
* Some bridges still don't set the correct
* LVDS bus pixel format, use SPWG24 default
* format until those are fixed.
*/
lvds_format_24bpp = true;
lvds_format_jeida = false;
dev_warn(ctx->dev,
"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",
bridge_state->output_bus_cfg.format);
break;
}
/* Clear reset, disable PLL */ /* Clear reset, disable PLL */
regmap_write(ctx->regmap, REG_RC_RESET, 0x00); regmap_write(ctx->regmap, REG_RC_RESET, 0x00);
regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
...@@ -405,14 +437,14 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, ...@@ -405,14 +437,14 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
REG_LVDS_FMT_VS_NEG_POLARITY : 0); REG_LVDS_FMT_VS_NEG_POLARITY : 0);
/* Set up bits-per-pixel, 18bpp or 24bpp. */ /* Set up bits-per-pixel, 18bpp or 24bpp. */
if (ctx->lvds_format_24bpp) { if (lvds_format_24bpp) {
val |= REG_LVDS_FMT_CHA_24BPP_MODE; val |= REG_LVDS_FMT_CHA_24BPP_MODE;
if (ctx->lvds_dual_link) if (ctx->lvds_dual_link)
val |= REG_LVDS_FMT_CHB_24BPP_MODE; val |= REG_LVDS_FMT_CHB_24BPP_MODE;
} }
/* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */ /* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */
if (ctx->lvds_format_jeida) { if (lvds_format_jeida) {
val |= REG_LVDS_FMT_CHA_24BPP_FORMAT1; val |= REG_LVDS_FMT_CHA_24BPP_FORMAT1;
if (ctx->lvds_dual_link) if (ctx->lvds_dual_link)
val |= REG_LVDS_FMT_CHB_24BPP_FORMAT1; val |= REG_LVDS_FMT_CHB_24BPP_FORMAT1;
...@@ -515,41 +547,8 @@ static void sn65dsi83_mode_set(struct drm_bridge *bridge, ...@@ -515,41 +547,8 @@ static void sn65dsi83_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *adj) const struct drm_display_mode *adj)
{ {
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
struct drm_encoder *encoder = bridge->encoder;
struct drm_device *ddev = encoder->dev;
struct drm_connector *connector;
ctx->mode = *adj; ctx->mode = *adj;
/* The DSI format is always RGB888_1X24 */
list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
switch (connector->display_info.bus_formats[0]) {
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
ctx->lvds_format_24bpp = false;
ctx->lvds_format_jeida = true;
break;
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
ctx->lvds_format_24bpp = true;
ctx->lvds_format_jeida = true;
break;
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
ctx->lvds_format_24bpp = true;
ctx->lvds_format_jeida = false;
break;
default:
/*
* Some bridges still don't set the correct
* LVDS bus pixel format, use SPWG24 default
* format until those are fixed.
*/
ctx->lvds_format_24bpp = true;
ctx->lvds_format_jeida = false;
dev_warn(ctx->dev,
"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",
connector->display_info.bus_formats[0]);
break;
}
}
} }
#define MAX_INPUT_SEL_FORMATS 1 #define MAX_INPUT_SEL_FORMATS 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment