From: Wojciech Dubowik <[email protected]>

The chip supports output lvds lanes in two orders, default <1 2 3 4>
and <4 3 2 1>. Add parsing of an optional output lvds data-lanes
property so we can inform chip that the lanes have been reversed.

Signed-off-by: Wojciech Dubowik <[email protected]>
---
Changes in v2:
- Parse existing data-lanes property instead of ading new DT
  bindings
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 50 +++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 42b451432bbb..4945d4c960c4 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -148,6 +148,18 @@ enum sn65dsi83_lvds_term {
        OHM_200
 };
 
+enum {
+       NORMAL_LANE_MAPPING,
+       REVERSE_LANE_MAPPING,
+};
+
+#define DATA_LANES_COUNT       4
+
+static const int supported_data_lane_mapping[][DATA_LANES_COUNT] = {
+       [NORMAL_LANE_MAPPING] = { 1, 2, 3, 4 },
+       [REVERSE_LANE_MAPPING] = { 4, 3, 2, 1},
+};
+
 enum sn65dsi83_model {
        MODEL_SN65DSI83,
        MODEL_SN65DSI84,
@@ -163,6 +175,7 @@ struct sn65dsi83 {
        struct regulator                *vcc;
        bool                            lvds_dual_link;
        bool                            lvds_dual_link_even_odd_swap;
+       bool                            lvds_reverse_lanes_conf[2];
        int                             lvds_vod_swing_conf[2];
        int                             lvds_term_conf[2];
        int                             irq;
@@ -644,6 +657,10 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge 
*bridge,
        regmap_write(ctx->regmap, REG_LVDS_LANE,
                     (ctx->lvds_dual_link_even_odd_swap ?
                      REG_LVDS_LANE_EVEN_ODD_SWAP : 0) |
+                    (ctx->lvds_reverse_lanes_conf[CHANNEL_A] ?
+                     REG_LVDS_LANE_CHA_REVERSE_LVDS : 0) |
+                    (ctx->lvds_reverse_lanes_conf[CHANNEL_B] ?
+                     REG_LVDS_LANE_CHB_REVERSE_LVDS : 0) |
                     (ctx->lvds_term_conf[CHANNEL_A] ?
                          REG_LVDS_LANE_CHA_LVDS_TERM : 0) |
                     (ctx->lvds_term_conf[CHANNEL_B] ?
@@ -832,10 +849,12 @@ static int sn65dsi83_parse_lvds_endpoint(struct sn65dsi83 
*ctx, int channel)
        u32 lvds_vod_swing_clk[2] = { 0, 1000000 };
        /* Set default near end terminataion to 200 Ohm */
        u32 lvds_term = 200;
+       u32 data_lanes[DATA_LANES_COUNT];
        int lvds_vod_swing_conf;
        int ret = 0;
        int ret_data;
        int ret_clock;
+       int i, j;
 
        if (channel == CHANNEL_A)
                endpoint_reg = 2;
@@ -854,6 +873,37 @@ static int sn65dsi83_parse_lvds_endpoint(struct sn65dsi83 
*ctx, int channel)
                goto exit;
        }
 
+       ret_data = of_property_read_u32_array(endpoint, "data-lanes", 
data_lanes,
+                       ARRAY_SIZE(data_lanes));
+       if (ret_data != 0 && ret_data != -EINVAL) {
+               ret = ret_data;
+               goto exit;
+       }
+
+       if (!ret_data) {
+               for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) {
+                       for (j = 0; j < DATA_LANES_COUNT; j++) {
+                               if (data_lanes[j] != 
supported_data_lane_mapping[i][j])
+                                       break;
+                       }
+
+                       if (j == DATA_LANES_COUNT)
+                               break;
+               }
+
+               switch (i) {
+               case NORMAL_LANE_MAPPING:
+                       break;
+               case REVERSE_LANE_MAPPING:
+                       ctx->lvds_reverse_lanes_conf[channel] = true;
+                       break;
+               default:
+                       dev_err(dev, "invalid data lanes mapping\n");
+                       ret = -EINVAL;
+                       goto exit;
+               }
+       }
+
        ret_data = of_property_read_u32_array(endpoint, 
"ti,lvds-vod-swing-data-microvolt",
                                        lvds_vod_swing_data, 
ARRAY_SIZE(lvds_vod_swing_data));
        if (ret_data != 0 && ret_data != -EINVAL) {
-- 
2.47.3

Reply via email to