On Thu, Jul 16, 2026 at 02:56:02PM +0200, Krzysztof Kozlowski wrote:
> On 16/07/2026 13:31, [email protected] wrote:
> > From: Sunyun Yang <[email protected]>
> > 
> > LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port
> > mipi dsi and output hdmi, differences in hardware features:
> > - LT9611C: supports 1-port mipi dsi to hdmi 1.4
> > - LT9611EX: supports 2-port mipi dsi to hdmi 1.4
> > - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0
> > 
> > Signed-off-by: Sunyun Yang <[email protected]>
> > Co-developed-by: Mohit Dsor <[email protected]>
> > Signed-off-by: Mohit Dsor <[email protected]>
> > ---
> >  MAINTAINERS                              |    7 +
> >  drivers/gpu/drm/bridge/Kconfig           |   18 +
> >  drivers/gpu/drm/bridge/Makefile          |    1 +
> >  drivers/gpu/drm/bridge/lontium-lt9611c.c | 1293 
> > ++++++++++++++++++++++++++++++
> >  4 files changed, 1319 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 6dea93a41962..30be2eaf2bec 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -15184,6 +15184,13 @@ S: Maintained
> >  F: Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
> >  F: drivers/gpu/drm/bridge/lontium-lt8912b.c
> >  
> > +LONTIUM LT9611C MIPI DSI TO HDMI BRIDGE
> > +M: Sunyun Yang <[email protected]>
> > +M: Mohit Dsor <[email protected]>
> > +S: Maintained
> > +F: Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml
> > +F: drivers/gpu/drm/bridge/lontium-lt9611c.c
> > +
> >  LOONGARCH
> >  M: Huacai Chen <[email protected]>
> >  R: WANG Xuerui <[email protected]>
> > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> > index 4a57d49b4c6d..b8959b8e2ad0 100644
> > --- a/drivers/gpu/drm/bridge/Kconfig
> > +++ b/drivers/gpu/drm/bridge/Kconfig
> > @@ -177,6 +177,24 @@ config DRM_LONTIUM_LT9611
> >       HDMI signals
> >       Please say Y if you have such hardware.
> >  
> > +config DRM_LONTIUM_LT9611C
> > +   tristate "Lontium LT9611C DSI/HDMI bridge"
> > +   select SND_SOC_HDMI_CODEC if SND_SOC
> > +   depends on OF
> > +   select CRC8
> > +   select FW_LOADER
> > +   select DRM_PANEL_BRIDGE
> > +   select DRM_KMS_HELPER
> > +   select DRM_MIPI_DSI
> > +   select DRM_DISPLAY_HELPER
> > +   select DRM_DISPLAY_HDMI_STATE_HELPER
> > +   select REGMAP_I2C
> > +   help
> > +     Driver for Lontium DSI to HDMI bridge
> > +     chip driver that converts dual DSI and I2S to
> > +     HDMI signals
> > +     Please say Y if you have such hardware.
> 
> Please wrap the code to appropriate limits.
I checked the others in Kconfigs they appear to be similar,
still i will try to fix it.
> 
> ...
> 
> > +
> > +static void lt9611c_reset(struct lt9611c *lt9611c)
> > +{
> > +   gpiod_set_value_cansleep(lt9611c->reset_gpio, 1);
> > +   usleep_range(10000, 12000);
> > +
> > +   gpiod_set_value_cansleep(lt9611c->reset_gpio, 0);
> > +   msleep(400);
> > +
> > +   dev_dbg(lt9611c->dev, "lt9611c reset");
> 
> Same comment as before.
will remove all debug comments.
> 
> > +}
> > +
> 
> > +static int lt9611c_upgrade_result(struct lt9611c *lt9611c, u8 fw_crc)
> > +{
> > +   struct device *dev = lt9611c->dev;
> > +   unsigned int crc_result;
> > +
> > +   regmap_write(lt9611c->regmap, 0xe0ee, 0x01);
> > +   regmap_read(lt9611c->regmap, 0xe021, &crc_result);
> > +
> > +   if (crc_result != fw_crc) {
> > +           dev_err(dev, "lt9611c fw upgrade failed, expected crc=0x%02x, 
> > read crc=0x%02x\n",
> > +                   fw_crc, crc_result);
> > +           return -1;
> > +   }
> > +
> > +   dev_dbg(dev, "lt9611c firmware upgrade success, crc=0x%02x\n", 
> > crc_result);
> > +   return 0;
> > +}
> 
> ...
> 
> > +
> > +static ssize_t lt9611c_firmware_show(struct device *dev, struct 
> > device_attribute *attr, char *buf)
> > +{
> > +   struct lt9611c *lt9611c = dev_get_drvdata(dev);
> > +
> > +   return sysfs_emit(buf, "0x%04x\n", lt9611c->fw_version);
> > +}
> > +
> > +static DEVICE_ATTR_RW(lt9611c_firmware);
> 
> Where is this ABI documented?
Will have its ABI documentation.
> 
> > +
> > +static struct attribute *lt9611c_attrs[] = {
> > +   &dev_attr_lt9611c_firmware.attr,
> > +   NULL,
> > +};
> > +
> > +static const struct attribute_group lt9611c_attr_group = {
> > +   .attrs = lt9611c_attrs,
> > +};
> > +
> > +static const struct attribute_group *lt9611c_attr_groups[] = {
> > +   &lt9611c_attr_group,
> > +   NULL,
> > +};
> > +
> > +static int lt9611c_probe(struct i2c_client *client)
> > +{
> > +   struct lt9611c *lt9611c;
> > +   struct device *dev = &client->dev;
> > +   bool fw_updated = false;
> > +   int ret;
> > +
> > +   crc8_populate_msb(lt9611c_crc8_table, LT9611C_CRC_POLYNOMIAL);
> > +
> > +   if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> > +           return dev_err_probe(dev, -ENODEV, "device doesn't support 
> > I2C\n");
> > +
> > +   lt9611c = devm_drm_bridge_alloc(dev, struct lt9611c, bridge, 
> > &lt9611c_bridge_funcs);
> > +   if (IS_ERR(lt9611c))
> > +           return dev_err_probe(dev, PTR_ERR(lt9611c), "drm bridge alloc 
> > failed.\n");
> > +
> > +   lt9611c->dev = dev;
> > +   lt9611c->client = client;
> > +   lt9611c->chip_type = (uintptr_t)i2c_get_match_data(client);
> 
> uintptr_t is not for kernel, use unsigned long.
I will fix this.
> 
> 
> > +
> > +   ret = devm_mutex_init(dev, &lt9611c->ocm_lock);
> > +   if (ret)
> > +           return dev_err_probe(dev, ret, "failed to init mutex\n");
> > +
> > +   lt9611c->regmap = devm_regmap_init_i2c(client, &lt9611c_regmap_config);
> > +   if (IS_ERR(lt9611c->regmap))
> > +           return dev_err_probe(dev, PTR_ERR(lt9611c->regmap), "regmap i2c 
> > init failed\n");
> > +
> > +   ret = lt9611c_parse_dt(dev, lt9611c);
> > +   if (ret)
> > +           return dev_err_probe(dev, ret, "failed to parse device tree\n");
> > +
> > +   ret = lt9611c_gpio_init(lt9611c);
> > +   if (ret < 0)
> > +           goto err_of_put;
> > +
> > +   ret = lt9611c_regulator_init(lt9611c);
> > +   if (ret < 0)
> > +           goto err_of_put;
> > +
> > +   ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), 
> > lt9611c->supplies);
> > +   if (ret)
> > +           goto err_of_put;
> > +
> > +   lt9611c_reset(lt9611c);
> > +
> > +   lt9611c_lock(lt9611c);
> > +
> > +   ret = lt9611c_read_chipid(lt9611c);
> > +   if (ret < 0) {
> > +           dev_err(dev, "failed to read chip id.\n");
> > +           lt9611c_unlock(lt9611c);
> > +           goto err_disable_regulators;
> > +   }
> > +
> > +retry:
> > +   lt9611c->fw_version = lt9611c_read_version(lt9611c);
> > +   if (lt9611c->fw_version < 0) {
> > +           dev_err(dev, "failed to read fw version\n");
> > +           ret = -EOPNOTSUPP;
> > +           lt9611c_unlock(lt9611c);
> > +           goto err_disable_regulators;
> > +
> > +   } else if (lt9611c->fw_version == 0) {
> > +           if (!fw_updated) {
> > +                   fw_updated = true;
> > +                   ret = lt9611c_firmware_upgrade(lt9611c);
> > +                   if (ret < 0) {
> > +                           lt9611c_unlock(lt9611c);
> > +                           goto err_disable_regulators;
> > +                   }
> > +
> > +                   goto retry;
> > +
> > +           } else {
> > +                   dev_err(dev, "fw version 0x%04x, update failed\n", 
> > lt9611c->fw_version);
> > +                   ret = -EOPNOTSUPP;
> > +                   lt9611c_unlock(lt9611c);
> > +                   goto err_disable_regulators;
> > +           }
> > +   }
> > +
> > +   lt9611c_unlock(lt9611c);
> > +   dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version);
> > +
> > +   INIT_WORK(&lt9611c->work, lt9611c_hpd_work);
> > +
> > +   ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
> > +                                   lt9611c_irq_thread_handler,
> > +                                   IRQF_TRIGGER_FALLING |
> > +                                   IRQF_ONESHOT |
> > +                                   IRQF_NO_AUTOEN,
> > +                                   "lt9611c", lt9611c);
> > +   if (ret) {
> > +           dev_err(dev, "failed to request irq\n");
> > +           goto err_disable_regulators;
> > +   }
> > +
> > +   lt9611c->bridge.of_node = client->dev.of_node;
> > +   lt9611c->bridge.ops = DRM_BRIDGE_OP_DETECT |
> > +                   DRM_BRIDGE_OP_EDID |
> > +                   DRM_BRIDGE_OP_HPD |
> > +                   DRM_BRIDGE_OP_HDMI |
> > +                   DRM_BRIDGE_OP_HDMI_AUDIO;
> > +   lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > +
> > +   lt9611c->bridge.vendor = "Lontium";
> > +   lt9611c->bridge.product = "LT9611C";
> > +
> > +   lt9611c->bridge.hdmi_audio_dev = dev;
> > +   lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8;
> > +   lt9611c->bridge.hdmi_audio_dai_port = 2;
> > +
> > +   devm_drm_bridge_add(dev, &lt9611c->bridge);
> > +
> > +   /* Attach primary DSI */
> > +   lt9611c->dsi0 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi0_node);
> > +   if (IS_ERR(lt9611c->dsi0)) {
> > +           ret = PTR_ERR(lt9611c->dsi0);
> > +           goto err_remove_bridge;
> > +   }
> > +
> > +   /* Attach secondary DSI, if specified */
> > +   if (lt9611c->dsi1_node) {
> > +           lt9611c->dsi1 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi1_node);
> > +           if (IS_ERR(lt9611c->dsi1)) {
> > +                   ret = PTR_ERR(lt9611c->dsi1);
> > +                   goto err_remove_bridge;
> > +           }
> > +   }
> > +
> > +   lt9611c->hdmi_connected = false;
> > +   i2c_set_clientdata(client, lt9611c);
> > +   enable_irq(client->irq);
> > +
> > +   lt9611c_reset(lt9611c);
> > +   return 0;
> > +
> > +err_remove_bridge:
> > +   cancel_work_sync(&lt9611c->work);
> > +
> > +err_disable_regulators:
> > +   regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), 
> > lt9611c->supplies);
> > +
> > +err_of_put:
> > +   of_node_put(lt9611c->dsi1_node);
> > +   of_node_put(lt9611c->dsi0_node);
> > +
> > +   return ret;
> > +}
> > +
> > +static void lt9611c_remove(struct i2c_client *client)
> > +{
> > +   struct lt9611c *lt9611c = i2c_get_clientdata(client);
> > +
> > +   cancel_work_sync(&lt9611c->work);
> > +   regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), 
> > lt9611c->supplies);
> > +   of_node_put(lt9611c->dsi1_node);
> > +   of_node_put(lt9611c->dsi0_node);
> > +}
> > +
> > +static int lt9611c_bridge_suspend(struct device *dev)
> > +{
> > +   struct lt9611c *lt9611c = dev_get_drvdata(dev);
> > +   int ret;
> > +
> > +   dev_dbg(lt9611c->dev, "suspend\n");
> 
> Same comments.
Will remove these debug prints.
> 
> 
> This does not look like useful printk message. Drivers should be silent
> on success:
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/coding-style.rst#L913
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/debugging/driver_development_debugging_guide.rst#L79
> 
> Best regards,
> Krzysztof

Reply via email to