Some board designs connect only DSI port B, or both DSI ports A and B, to the LT9611C. Add support for a 'lontium,port-select' DT property that allows the board DTS to specify which DSI port(s) the chip should use:
0 = PORT_SELECT_A (default, single DSI port A) 1 = PORT_SELECT_B (single DSI port B) 2 = PORT_SELECT_AB (dual DSI ports A+B) When the property is absent the driver defaults to PORT_SELECT_A (0), preserving backward compatibility with existing DTS files. The selected port is programmed into the chip via lt9611c_select_port() during probe, after the chip ID has been verified. Signed-off-by: Mohit Dsor <[email protected]> --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index fe51f4978546..5d67bb7391fb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -41,6 +41,12 @@ enum lt9611_chip_type { CHIP_LT9611UXD, }; +enum lt9611c_PORT_SELECT { + PORT_SELECT_A = 0, + PORT_SELECT_B = 1, + PORT_SELECT_AB = 2, +}; + struct lt9611c { struct device *dev; struct i2c_client *client; @@ -60,6 +66,8 @@ struct lt9611c { enum lt9611_chip_type chip_type; /* HDMI cable connection status */ bool hdmi_connected; + /* Selected DSI port configuration */ + int selected_port; }; DECLARE_CRC8_TABLE(lt9611c_crc8_table); @@ -115,6 +123,34 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, return_count); } +static int lt9611c_select_port(struct lt9611c *lt9611c, int port_select) +{ + int ret; + u8 set_port_select_cmd[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0xc0}; + u8 set_port_select_ret[5]; + + if (port_select == PORT_SELECT_B) { + set_port_select_cmd[5] = 0x40; + } else if (port_select == PORT_SELECT_AB) { + set_port_select_cmd[4] = 0x02; + set_port_select_cmd[5] = 0xd0; + } else if (port_select != PORT_SELECT_A) { + return -EINVAL; + } + + /* MCU must be running (0xe0ee=0x00) for lt9611c_read_write_flow */ + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, set_port_select_cmd, + ARRAY_SIZE(set_port_select_cmd), + set_port_select_ret, + ARRAY_SIZE(set_port_select_ret)); + if (ret < 0 || set_port_select_ret[4] == 0) + return ret < 0 ? ret : -EIO; + + return 0; +} + static void lt9611c_config_parameters(struct lt9611c *lt9611c) { const struct reg_sequence seq_write_paras[] = { @@ -924,6 +960,10 @@ static int lt9611c_parse_dt(struct device *dev, lt9611c->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + if (of_property_read_u32(dev->of_node, "lontium,port-select", + <9611c->selected_port)) + lt9611c->selected_port = 0; + return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); } @@ -1070,6 +1110,10 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c_reset(lt9611c); + ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); + if (ret < 0) + dev_err(lt9611c->dev, "failed to select port %d\n", lt9611c->selected_port); + lt9611c_lock(lt9611c); ret = lt9611c_read_chipid(lt9611c); -- 2.34.1
