Hi, just some random remarks, not a complete review.
On Wed Mar 11, 2026 at 4:55 PM CET, Bartholomäus Steinmayr wrote: > Add Densitron DMT050WVNMCMI-1A to ILI9806E DSI > Add i2c-frag to allow probe deferral until Goodix touchpanel chip in the > display is initialized. Make reset-gpios optional to allow delegation of > reset to Goodix driver. > > Signed-off-by: Bart Steinmayr <[email protected]> > --- > drivers/gpu/drm/panel/panel-ilitek-ili9806e.c | 202 +++++++++++++++++- > 1 file changed, 201 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c > b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c > index 18aa6222b0c5..ce77ee7cbc10 100644 > --- a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c > +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c > @@ -10,6 +10,9 @@ > #include <linux/module.h> > #include <linux/property.h> > #include <linux/regulator/consumer.h> > +#include <linux/of.h> > + > +#include <linux/i2c.h> > > #include <drm/drm_mipi_dsi.h> > #include <drm/drm_modes.h> > @@ -166,6 +169,22 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device > *dsi) > struct ili9806e_panel *ctx; > int i, ret; > > + struct device_node *i2c_frag = of_parse_phandle(dev->of_node, > "i2c-frag", 0); > + > + if (i2c_frag) { > + void *i2c_driver_data = NULL; > + > + struct i2c_client *i2c_frag_client = > of_find_i2c_device_by_node(i2c_frag); > + > + of_node_put(i2c_frag); > + if (i2c_frag_client) { > + i2c_driver_data = > dev_get_drvdata(&i2c_frag_client->dev); > + put_device(&i2c_frag_client->dev); > + } > + if (!i2c_driver_data) > + return dev_err_probe(dev, -EPROBE_DEFER, "failed to get > i2c-frag\n"); > + } > + > ctx = devm_drm_panel_alloc(dev, struct ili9806e_panel, panel, > &ili9806e_funcs, > DRM_MODE_CONNECTOR_DSI); > if (IS_ERR(ctx)) > @@ -181,7 +200,7 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi) > if (ret < 0) > return ret; > > - ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); > + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); As mentioned in my previous reply. I'm not really sure this will work. Do you have a regulator attached and described in the device tree? First, that will still be disabled and not having a reset then is bad. Also I guess the init sequeuce will still be run if the panel is turned off and on again. And then there will be no reset to defaults. > if (IS_ERR(ctx->reset_gpio)) > return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), > "Failed to get reset-gpios\n"); > @@ -542,8 +561,188 @@ static const struct panel_desc dmt028vghmcmi_1d_desc = { > .lanes = 2, > }; > > +static u8 dsi_read(struct mipi_dsi_multi_context *ctx, u8 command) > +{ > + struct mipi_dsi_device *dsi = ctx->dsi; > + > + u8 len = 1; > + u8 result_data = 0xFF; Use lower case, as you've already did below. > + > + mipi_dsi_set_maximum_return_packet_size(dsi, 1); > + mipi_dsi_dcs_read(dsi, command, &result_data, len); > + > + return result_data; > +} > + > +static void dmt050wvnmcmi_1a_init(struct mipi_dsi_multi_context *ctx) > +{ > + // Try to read pixel format to check display connection Use C comments /* */ > + u8 pixel_format = dsi_read(ctx, 0x0c); Also this is just used once. You could just use the two commands here. "dsi_read" is a pretty common name which might cause aliasing issues in the future. > + > + if (pixel_format != 0x70) > + dev_err(&ctx->dsi->dev, "Read pixel format failed: %d\n", > pixel_format); So? No return? Just an error message? Also if you happen to know what 0x70 is, please either add a define or a comment. > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x10); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x16); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x41, 0x33); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x42, 0x03); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x43, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x44, 0x06); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x50, 0x88); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0x88); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x52, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x49); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x49); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x60, 0x07); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x07); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x63, 0x00); > + > + //Positive Gamma > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA0, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA1, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA2, 0x11); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA3, 0x0B); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA4, 0x05); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA5, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA6, 0x06); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA7, 0x04); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA8, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xA9, 0x0C); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAA, 0x15); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAB, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAC, 0x0F); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAD, 0x12); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAE, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xAF, 0x00); > + > + //Negative Gamma > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC0, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC1, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC2, 0x10); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC3, 0x0C); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC4, 0x05); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC5, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC6, 0x06); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC7, 0x04); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC8, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xC9, 0x0C); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCA, 0x14); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCB, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCC, 0x0F); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCD, 0x11); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCE, 0x09); > + mipi_dsi_dcs_write_seq_multi(ctx, 0xCF, 0x00); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x6); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x20); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x0A); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x02, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x04, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x98); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x06); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x80); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0A, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0B, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0C, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0D, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0E, 0x05); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x0F, 0x00); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x10, 0xF0); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0xF4); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x14, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0xC0); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x08); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x1A, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x1B, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x1C, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x1D, 0x00); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x23); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x45); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x67); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x24, 0x01); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x23); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x45); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x27, 0x67); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x11); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x11); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x00); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0xEE); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xFF); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0xBB); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0xAA); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0xDD); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0xCC); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0x66); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3A, 0x77); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3B, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3C, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3D, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3E, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3F, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x22); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x22); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x02, 0x77); > + mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0xB2); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00); > + > + mipi_dsi_dcs_write_seq_multi(ctx, 0x3A, 0x70); //Data format RGB24 For all the numbers above, please use lower case to match the style of this file. -michael > +}; > + > +static const struct drm_display_mode dmt050wvnmcmi_1a_default_mode = { > + .clock = 41666, > + > + .hdisplay = 480, > + .hsync_start = 480 + 100, > + .hsync_end = 480 + 100 + 10, > + .htotal = 480 + 100 + 10 + 50, > + > + .vdisplay = 854, > + .vsync_start = 854 + 20, > + .vsync_end = 854 + 20 + 4, > + .vtotal = 854 + 20 + 4 + 20, > + > + .width_mm = 61, > + .height_mm = 109, > + > + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, > + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, > +}; > + > +static const struct panel_desc dmt050wvnmcmi_1a_desc = { > + .init_sequence = dmt050wvnmcmi_1a_init, > + .display_mode = &dmt050wvnmcmi_1a_default_mode, > + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | > + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, > + .format = MIPI_DSI_FMT_RGB888, > + .lanes = 2, > +}; > + > static const struct of_device_id ili9806e_of_match[] = { > { .compatible = "densitron,dmt028vghmcmi-1d", .data = > &dmt028vghmcmi_1d_desc }, > + { .compatible = "densitron,dmt050wvnmcmi-1a", .data = > &dmt050wvnmcmi_1a_desc }, > { .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc > }, > { } > }; > @@ -561,5 +760,6 @@ module_mipi_dsi_driver(ili9806e_dsi_driver); > > MODULE_AUTHOR("Gunnar Dibbern <[email protected]>"); > MODULE_AUTHOR("Michael Walle <[email protected]>"); > +MODULE_AUTHOR("Bart Steinmayr <[email protected]>"); > MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver"); > MODULE_LICENSE("GPL");
signature.asc
Description: PGP signature
