* [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels
@ 2025-10-09 16:22 Kaustabh Chakraborty
2025-10-09 16:22 ` [PATCH RESEND v5 1/2] dt-bindings: display: panel: document Synaptics TDDI panel Kaustabh Chakraborty
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Kaustabh Chakraborty @ 2025-10-09 16:22 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jessica Zhang
Cc: dri-devel, devicetree, linux-kernel, Kaustabh Chakraborty,
Krzysztof Kozlowski
Synaptics' Touch and Display Driver Integration (TDDI) technology [1]
employs a single chip for both touchscreen and display capabilities.
Such designs reportedly help reducing costs and power consumption.
Although the touchscreens, which are powered by Synaptics'
Register-Mapped Interface 4 (RMI4) touch protocol via I2C or SPI have
driver support in the kernel, the MIPI DSI display panels don't.
This series introduces a rudimentary driver for controlling said display
panels, which supports TD4101 and TD4300 panels.
[1] https://www.synaptics.com/technology/display-integration
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
Changes in v5:
- added missing Reviewed-by tag from Krzysztof in [v3 1/2]
- Link to v4: https://lore.kernel.org/r/20250819-panel-synaptics-tddi-v4-0-448f466d16a6@disroot.org
Changes in v4:
- utilized drm_connector_helper_get_modes_fixed() (dmitry.baryshkov)
- constified backlight properties (dmitry.baryshkov)
- Link to v3: https://lore.kernel.org/r/20250720-panel-synaptics-tddi-v3-0-43a5957f4b24@disroot.org
Changes in v3:
- fixed various dt_binding_check errors (robh's bot)
- adjusted commit description of [v2 1/2] (robh)
- utilized devm_drm_panel_alloc() and devm_regulator_bulk_get_const()
- Link to v2: https://lore.kernel.org/r/20250625-panel-synaptics-tddi-v2-0-7a62ab1d13c7@disroot.org
Changes in v2:
- fixed various dt_binding_check errors (conor)
- did s/tddi_update_brightness/tddi_update_status
- added check for panel enable in tddi_update_status()
- used backlight_get_brightness() in appropriate places
- Link to v1: https://lore.kernel.org/r/20250612-panel-synaptics-tddi-v1-0-dfb8a425f76c@disroot.org
---
Kaustabh Chakraborty (2):
dt-bindings: display: panel: document Synaptics TDDI panel
drm: panel: add support for Synaptics TDDI series DSI panels
.../display/panel/synaptics,td4300-panel.yaml | 89 +++++++
drivers/gpu/drm/panel/Kconfig | 11 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-synaptics-tddi.c | 276 +++++++++++++++++++++
4 files changed, 377 insertions(+)
---
base-commit: 5303936d609e09665deda94eaedf26a0e5c3a087
change-id: 20250523-panel-synaptics-tddi-0b0b3f07f814
Best regards,
--
Kaustabh Chakraborty <kauschluss@disroot.org>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH RESEND v5 1/2] dt-bindings: display: panel: document Synaptics TDDI panel 2025-10-09 16:22 [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty @ 2025-10-09 16:22 ` Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels Kaustabh Chakraborty ` (2 subsequent siblings) 3 siblings, 0 replies; 6+ messages in thread From: Kaustabh Chakraborty @ 2025-10-09 16:22 UTC (permalink / raw) To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jessica Zhang Cc: dri-devel, devicetree, linux-kernel, Kaustabh Chakraborty, Krzysztof Kozlowski Document the Synaptics TDDI (Touch/Display Integration) panel hardware. Along with the MIPI-DSI panel, these devices also have an in-built LED backlight device and a touchscreen, all packed together in a single chip. Also, add compatibles for supported panels - TD4101 and TD4300. Both have the '-panel' suffix so as to remove any ambiguity between the panel and touchscreen chips. Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org> --- .../display/panel/synaptics,td4300-panel.yaml | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,td4300-panel.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,td4300-panel.yaml new file mode 100644 index 0000000000000000000000000000000000000000..152d94367130e9d80a885fe87a2da53db88e3393 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/synaptics,td4300-panel.yaml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/synaptics,td4300-panel.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synaptics TDDI Display Panel Controller + +maintainers: + - Kaustabh Chakraborty <kauschluss@disroot.org> + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + enum: + - syna,td4101-panel + - syna,td4300-panel + + reg: + maxItems: 1 + + vio-supply: + description: core I/O voltage supply + + vsn-supply: + description: negative voltage supply for analog circuits + + vsp-supply: + description: positive voltage supply for analog circuits + + backlight-gpios: + maxItems: 1 + description: backlight enable GPIO + + reset-gpios: true + width-mm: true + height-mm: true + panel-timing: true + +required: + - compatible + - reg + - width-mm + - height-mm + - panel-timing + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "syna,td4300-panel"; + reg = <0>; + + vio-supply = <&panel_vio_reg>; + vsn-supply = <&panel_vsn_reg>; + vsp-supply = <&panel_vsp_reg>; + + backlight-gpios = <&gpd3 5 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpd3 4 GPIO_ACTIVE_LOW>; + + width-mm = <68>; + height-mm = <121>; + + panel-timing { + clock-frequency = <144389520>; + + hactive = <1080>; + hsync-len = <4>; + hfront-porch = <120>; + hback-porch = <32>; + + vactive = <1920>; + vsync-len = <2>; + vfront-porch = <21>; + vback-porch = <4>; + }; + }; + }; + +... -- 2.51.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels 2025-10-09 16:22 [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 1/2] dt-bindings: display: panel: document Synaptics TDDI panel Kaustabh Chakraborty @ 2025-10-09 16:22 ` Kaustabh Chakraborty 2025-10-29 21:00 ` Neil Armstrong 2025-10-24 16:29 ` [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty 2025-10-29 21:05 ` Neil Armstrong 3 siblings, 1 reply; 6+ messages in thread From: Kaustabh Chakraborty @ 2025-10-09 16:22 UTC (permalink / raw) To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jessica Zhang Cc: dri-devel, devicetree, linux-kernel, Kaustabh Chakraborty Synaptics TDDI (Touch/Display Integration) panels utilize a single chip for display and touch controllers. Implement a simple device driver for such panels, along with its built-in LED backlight controller, and add support for TD4101 and TD4300 panels in the driver. Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org> --- drivers/gpu/drm/panel/Kconfig | 11 ++ drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-synaptics-tddi.c | 276 +++++++++++++++++++++++++++ 3 files changed, 288 insertions(+) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 407c5f6a268b2ec66e5d0eddae26b3368e4cb2cb..98708979ab45281628620bbe803fe8b597eb812d 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -1045,6 +1045,17 @@ config DRM_PANEL_SYNAPTICS_R63353 Say Y if you want to enable support for panels based on the Synaptics R63353 controller. +config DRM_PANEL_SYNAPTICS_TDDI + tristate "Synaptics TDDI display panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for the Synaptics TDDI display + panels. There are multiple MIPI DSI panels manufactured under the TDDI + namesake, with varying resolutions and data lanes. They also have a + built-in LED backlight and a touch controller. + config DRM_PANEL_TDO_TL070WSH30 tristate "TDO TL070WSH30 DSI panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 3615a761b44f9de0b4a653be157d8e0bcbc8f6b7..2535e1c9df76451d1c66d7d211ac9bfbf18dc80e 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o obj-$(CONFIG_DRM_PANEL_SUMMIT) += panel-summit.o obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o +obj-$(CONFIG_DRM_PANEL_SYNAPTICS_TDDI) += panel-synaptics-tddi.o obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o obj-$(CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521) += panel-sony-tulip-truly-nt35521.o diff --git a/drivers/gpu/drm/panel/panel-synaptics-tddi.c b/drivers/gpu/drm/panel/panel-synaptics-tddi.c new file mode 100644 index 0000000000000000000000000000000000000000..a4b3cbdebb6ca4062c02c6e7ac184f3ec245926a --- /dev/null +++ b/drivers/gpu/drm/panel/panel-synaptics-tddi.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Synaptics TDDI display panel driver. + * + * Copyright (C) 2025 Kaustabh Chakraborty <kauschluss@disroot.org> + */ + +#include <linux/backlight.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> + +#include <video/mipi_display.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + +struct tddi_panel_data { + u8 lanes; + /* wait timings for panel enable */ + u8 delay_ms_sleep_exit; + u8 delay_ms_display_on; + /* wait timings for panel disable */ + u8 delay_ms_display_off; + u8 delay_ms_sleep_enter; +}; + +struct tddi_ctx { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct drm_display_mode mode; + struct backlight_device *backlight; + const struct tddi_panel_data *data; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; + struct gpio_desc *backlight_gpio; +}; + +static const struct regulator_bulk_data tddi_supplies[] = { + { .supply = "vio" }, + { .supply = "vsn" }, + { .supply = "vsp" }, +}; + +static inline struct tddi_ctx *to_tddi_ctx(struct drm_panel *panel) +{ + return container_of(panel, struct tddi_ctx, panel); +} + +static int tddi_update_status(struct backlight_device *backlight) +{ + struct tddi_ctx *ctx = bl_get_data(backlight); + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; + u8 brightness = backlight_get_brightness(backlight); + + if (!ctx->panel.enabled) + return 0; + + mipi_dsi_dcs_set_display_brightness_multi(&dsi, brightness); + + return dsi.accum_err; +} + +static int tddi_prepare(struct drm_panel *panel) +{ + struct tddi_ctx *ctx = to_tddi_ctx(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(tddi_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); + + gpiod_set_value_cansleep(ctx->backlight_gpio, 0); + usleep_range(5000, 6000); + + return 0; +} + +static int tddi_unprepare(struct drm_panel *panel) +{ + struct tddi_ctx *ctx = to_tddi_ctx(panel); + + gpiod_set_value_cansleep(ctx->backlight_gpio, 1); + usleep_range(5000, 6000); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(5000, 6000); + + regulator_bulk_disable(ARRAY_SIZE(tddi_supplies), ctx->supplies); + + return 0; +} + +static int tddi_enable(struct drm_panel *panel) +{ + struct tddi_ctx *ctx = to_tddi_ctx(panel); + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; + u8 brightness = ctx->backlight->props.brightness; + + mipi_dsi_dcs_write_seq_multi(&dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x0c); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi); + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_sleep_exit); + + /* sync the panel with the backlight's brightness level */ + mipi_dsi_dcs_set_display_brightness_multi(&dsi, brightness); + + mipi_dsi_dcs_set_display_on_multi(&dsi); + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_display_on); + + return dsi.accum_err; +}; + +static int tddi_disable(struct drm_panel *panel) +{ + struct tddi_ctx *ctx = to_tddi_ctx(panel); + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; + + mipi_dsi_dcs_set_display_off_multi(&dsi); + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_display_off); + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi); + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_sleep_enter); + + return dsi.accum_err; +} + +static int tddi_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct tddi_ctx *ctx = to_tddi_ctx(panel); + + return drm_connector_helper_get_modes_fixed(connector, &ctx->mode); +} + +static const struct backlight_ops tddi_bl_ops = { + .update_status = tddi_update_status, +}; + +static const struct backlight_properties tddi_bl_props = { + .type = BACKLIGHT_PLATFORM, + .brightness = 255, + .max_brightness = 255, +}; + +static const struct drm_panel_funcs tddi_drm_panel_funcs = { + .prepare = tddi_prepare, + .unprepare = tddi_unprepare, + .enable = tddi_enable, + .disable = tddi_disable, + .get_modes = tddi_get_modes, +}; + +static int tddi_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct tddi_ctx *ctx; + int ret; + + ctx = devm_drm_panel_alloc(dev, struct tddi_ctx, panel, + &tddi_drm_panel_funcs, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ctx->data = of_device_get_match_data(dev); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(tddi_supplies), + tddi_supplies, &ctx->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + ctx->backlight_gpio = devm_gpiod_get_optional(dev, "backlight", GPIOD_ASIS); + if (IS_ERR(ctx->backlight_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->backlight_gpio), + "failed to get backlight-gpios\n"); + + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "failed to get reset-gpios\n"); + + ret = of_get_drm_panel_display_mode(dev->of_node, &ctx->mode, NULL); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get panel timings\n"); + + ctx->backlight = devm_backlight_device_register(dev, dev_name(dev), dev, + ctx, &tddi_bl_ops, + &tddi_bl_props); + if (IS_ERR(ctx->backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->backlight), + "failed to register backlight device"); + + dsi->lanes = ctx->data->lanes; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_NO_HFP; + + ctx->panel.prepare_prev_first = true; + drm_panel_add(&ctx->panel); + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "failed to attach to DSI host\n"); + } + + return 0; +} + +static void tddi_remove(struct mipi_dsi_device *dsi) +{ + struct tddi_ctx *ctx = mipi_dsi_get_drvdata(dsi); + + drm_panel_remove(&ctx->panel); +} + +static const struct tddi_panel_data td4101_panel_data = { + .lanes = 2, + /* wait timings for panel enable */ + .delay_ms_sleep_exit = 100, + .delay_ms_display_on = 0, + /* wait timings for panel disable */ + .delay_ms_display_off = 20, + .delay_ms_sleep_enter = 90, +}; + +static const struct tddi_panel_data td4300_panel_data = { + .lanes = 4, + /* wait timings for panel enable */ + .delay_ms_sleep_exit = 100, + .delay_ms_display_on = 0, + /* wait timings for panel disable */ + .delay_ms_display_off = 0, + .delay_ms_sleep_enter = 0, +}; + +static const struct of_device_id tddi_of_device_id[] = { + { + .compatible = "syna,td4101-panel", + .data = &td4101_panel_data, + }, { + .compatible = "syna,td4300-panel", + .data = &td4300_panel_data, + }, { } +}; +MODULE_DEVICE_TABLE(of, tddi_of_device_id); + +static struct mipi_dsi_driver tddi_dsi_driver = { + .probe = tddi_probe, + .remove = tddi_remove, + .driver = { + .name = "panel-synaptics-tddi", + .of_match_table = tddi_of_device_id, + }, +}; +module_mipi_dsi_driver(tddi_dsi_driver); + +MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>"); +MODULE_DESCRIPTION("Synaptics TDDI Display Panel Driver"); +MODULE_LICENSE("GPL"); -- 2.51.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels 2025-10-09 16:22 ` [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels Kaustabh Chakraborty @ 2025-10-29 21:00 ` Neil Armstrong 0 siblings, 0 replies; 6+ messages in thread From: Neil Armstrong @ 2025-10-29 21:00 UTC (permalink / raw) To: Kaustabh Chakraborty, Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jessica Zhang Cc: dri-devel, devicetree, linux-kernel On 10/9/25 18:22, Kaustabh Chakraborty wrote: > Synaptics TDDI (Touch/Display Integration) panels utilize a single chip > for display and touch controllers. Implement a simple device driver for > such panels, along with its built-in LED backlight controller, and add > support for TD4101 and TD4300 panels in the driver. > > Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org> > --- > drivers/gpu/drm/panel/Kconfig | 11 ++ > drivers/gpu/drm/panel/Makefile | 1 + > drivers/gpu/drm/panel/panel-synaptics-tddi.c | 276 +++++++++++++++++++++++++++ > 3 files changed, 288 insertions(+) > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig > index 407c5f6a268b2ec66e5d0eddae26b3368e4cb2cb..98708979ab45281628620bbe803fe8b597eb812d 100644 > --- a/drivers/gpu/drm/panel/Kconfig > +++ b/drivers/gpu/drm/panel/Kconfig > @@ -1045,6 +1045,17 @@ config DRM_PANEL_SYNAPTICS_R63353 > Say Y if you want to enable support for panels based on the > Synaptics R63353 controller. > > +config DRM_PANEL_SYNAPTICS_TDDI > + tristate "Synaptics TDDI display panels" > + depends on OF > + depends on DRM_MIPI_DSI > + depends on BACKLIGHT_CLASS_DEVICE > + help > + Say Y if you want to enable support for the Synaptics TDDI display > + panels. There are multiple MIPI DSI panels manufactured under the TDDI > + namesake, with varying resolutions and data lanes. They also have a > + built-in LED backlight and a touch controller. > + > config DRM_PANEL_TDO_TL070WSH30 > tristate "TDO TL070WSH30 DSI panel" > depends on OF > diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile > index 3615a761b44f9de0b4a653be157d8e0bcbc8f6b7..2535e1c9df76451d1c66d7d211ac9bfbf18dc80e 100644 > --- a/drivers/gpu/drm/panel/Makefile > +++ b/drivers/gpu/drm/panel/Makefile > @@ -100,6 +100,7 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o > obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o > obj-$(CONFIG_DRM_PANEL_SUMMIT) += panel-summit.o > obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o > +obj-$(CONFIG_DRM_PANEL_SYNAPTICS_TDDI) += panel-synaptics-tddi.o > obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o > obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o > obj-$(CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521) += panel-sony-tulip-truly-nt35521.o > diff --git a/drivers/gpu/drm/panel/panel-synaptics-tddi.c b/drivers/gpu/drm/panel/panel-synaptics-tddi.c > new file mode 100644 > index 0000000000000000000000000000000000000000..a4b3cbdebb6ca4062c02c6e7ac184f3ec245926a > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-synaptics-tddi.c > @@ -0,0 +1,276 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Synaptics TDDI display panel driver. > + * > + * Copyright (C) 2025 Kaustabh Chakraborty <kauschluss@disroot.org> > + */ > + > +#include <linux/backlight.h> > +#include <linux/gpio/consumer.h> > +#include <linux/module.h> > +#include <linux/of.h> > + > +#include <video/mipi_display.h> > + > +#include <drm/drm_mipi_dsi.h> > +#include <drm/drm_modes.h> > +#include <drm/drm_panel.h> > +#include <drm/drm_probe_helper.h> > + > +struct tddi_panel_data { > + u8 lanes; > + /* wait timings for panel enable */ > + u8 delay_ms_sleep_exit; > + u8 delay_ms_display_on; > + /* wait timings for panel disable */ > + u8 delay_ms_display_off; > + u8 delay_ms_sleep_enter; > +}; > + > +struct tddi_ctx { > + struct drm_panel panel; > + struct mipi_dsi_device *dsi; > + struct drm_display_mode mode; > + struct backlight_device *backlight; > + const struct tddi_panel_data *data; > + struct regulator_bulk_data *supplies; > + struct gpio_desc *reset_gpio; > + struct gpio_desc *backlight_gpio; > +}; > + > +static const struct regulator_bulk_data tddi_supplies[] = { > + { .supply = "vio" }, > + { .supply = "vsn" }, > + { .supply = "vsp" }, > +}; > + > +static inline struct tddi_ctx *to_tddi_ctx(struct drm_panel *panel) > +{ > + return container_of(panel, struct tddi_ctx, panel); > +} > + > +static int tddi_update_status(struct backlight_device *backlight) > +{ > + struct tddi_ctx *ctx = bl_get_data(backlight); > + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; > + u8 brightness = backlight_get_brightness(backlight); > + > + if (!ctx->panel.enabled) > + return 0; > + > + mipi_dsi_dcs_set_display_brightness_multi(&dsi, brightness); > + > + return dsi.accum_err; > +} > + > +static int tddi_prepare(struct drm_panel *panel) > +{ > + struct tddi_ctx *ctx = to_tddi_ctx(panel); > + struct device *dev = &ctx->dsi->dev; > + int ret; > + > + ret = regulator_bulk_enable(ARRAY_SIZE(tddi_supplies), ctx->supplies); > + if (ret < 0) { > + dev_err(dev, "failed to enable regulators: %d\n", ret); > + return ret; > + } > + > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + usleep_range(5000, 6000); > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + usleep_range(5000, 6000); > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + usleep_range(10000, 11000); > + > + gpiod_set_value_cansleep(ctx->backlight_gpio, 0); > + usleep_range(5000, 6000); > + > + return 0; > +} > + > +static int tddi_unprepare(struct drm_panel *panel) > +{ > + struct tddi_ctx *ctx = to_tddi_ctx(panel); > + > + gpiod_set_value_cansleep(ctx->backlight_gpio, 1); > + usleep_range(5000, 6000); > + > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + usleep_range(5000, 6000); > + > + regulator_bulk_disable(ARRAY_SIZE(tddi_supplies), ctx->supplies); > + > + return 0; > +} > + > +static int tddi_enable(struct drm_panel *panel) > +{ > + struct tddi_ctx *ctx = to_tddi_ctx(panel); > + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; > + u8 brightness = ctx->backlight->props.brightness; > + > + mipi_dsi_dcs_write_seq_multi(&dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); > + mipi_dsi_dcs_write_seq_multi(&dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x0c); > + > + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi); > + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_sleep_exit); > + > + /* sync the panel with the backlight's brightness level */ > + mipi_dsi_dcs_set_display_brightness_multi(&dsi, brightness); > + > + mipi_dsi_dcs_set_display_on_multi(&dsi); > + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_display_on); > + > + return dsi.accum_err; > +}; > + > +static int tddi_disable(struct drm_panel *panel) > +{ > + struct tddi_ctx *ctx = to_tddi_ctx(panel); > + struct mipi_dsi_multi_context dsi = { .dsi = ctx->dsi }; > + > + mipi_dsi_dcs_set_display_off_multi(&dsi); > + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_display_off); > + > + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi); > + mipi_dsi_msleep(&dsi, ctx->data->delay_ms_sleep_enter); > + > + return dsi.accum_err; > +} > + > +static int tddi_get_modes(struct drm_panel *panel, > + struct drm_connector *connector) > +{ > + struct tddi_ctx *ctx = to_tddi_ctx(panel); > + > + return drm_connector_helper_get_modes_fixed(connector, &ctx->mode); > +} > + > +static const struct backlight_ops tddi_bl_ops = { > + .update_status = tddi_update_status, > +}; > + > +static const struct backlight_properties tddi_bl_props = { > + .type = BACKLIGHT_PLATFORM, > + .brightness = 255, > + .max_brightness = 255, > +}; > + > +static const struct drm_panel_funcs tddi_drm_panel_funcs = { > + .prepare = tddi_prepare, > + .unprepare = tddi_unprepare, > + .enable = tddi_enable, > + .disable = tddi_disable, > + .get_modes = tddi_get_modes, > +}; > + > +static int tddi_probe(struct mipi_dsi_device *dsi) > +{ > + struct device *dev = &dsi->dev; > + struct tddi_ctx *ctx; > + int ret; > + > + ctx = devm_drm_panel_alloc(dev, struct tddi_ctx, panel, > + &tddi_drm_panel_funcs, DRM_MODE_CONNECTOR_DSI); > + if (IS_ERR(ctx)) > + return PTR_ERR(ctx); > + > + ctx->data = of_device_get_match_data(dev); > + > + ctx->dsi = dsi; > + mipi_dsi_set_drvdata(dsi, ctx); > + > + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(tddi_supplies), > + tddi_supplies, &ctx->supplies); > + if (ret < 0) > + return dev_err_probe(dev, ret, "failed to get regulators\n"); > + > + ctx->backlight_gpio = devm_gpiod_get_optional(dev, "backlight", GPIOD_ASIS); > + if (IS_ERR(ctx->backlight_gpio)) > + return dev_err_probe(dev, PTR_ERR(ctx->backlight_gpio), > + "failed to get backlight-gpios\n"); > + > + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS); > + if (IS_ERR(ctx->reset_gpio)) > + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), > + "failed to get reset-gpios\n"); > + > + ret = of_get_drm_panel_display_mode(dev->of_node, &ctx->mode, NULL); > + if (ret < 0) > + return dev_err_probe(dev, ret, "failed to get panel timings\n"); > + > + ctx->backlight = devm_backlight_device_register(dev, dev_name(dev), dev, > + ctx, &tddi_bl_ops, > + &tddi_bl_props); > + if (IS_ERR(ctx->backlight)) > + return dev_err_probe(dev, PTR_ERR(ctx->backlight), > + "failed to register backlight device"); > + > + dsi->lanes = ctx->data->lanes; > + dsi->format = MIPI_DSI_FMT_RGB888; > + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | > + MIPI_DSI_MODE_VIDEO_NO_HFP; > + > + ctx->panel.prepare_prev_first = true; > + drm_panel_add(&ctx->panel); > + > + ret = devm_mipi_dsi_attach(dev, dsi); > + if (ret < 0) { > + drm_panel_remove(&ctx->panel); > + return dev_err_probe(dev, ret, "failed to attach to DSI host\n"); > + } > + > + return 0; > +} > + > +static void tddi_remove(struct mipi_dsi_device *dsi) > +{ > + struct tddi_ctx *ctx = mipi_dsi_get_drvdata(dsi); > + > + drm_panel_remove(&ctx->panel); > +} > + > +static const struct tddi_panel_data td4101_panel_data = { > + .lanes = 2, > + /* wait timings for panel enable */ > + .delay_ms_sleep_exit = 100, > + .delay_ms_display_on = 0, > + /* wait timings for panel disable */ > + .delay_ms_display_off = 20, > + .delay_ms_sleep_enter = 90, > +}; > + > +static const struct tddi_panel_data td4300_panel_data = { > + .lanes = 4, > + /* wait timings for panel enable */ > + .delay_ms_sleep_exit = 100, > + .delay_ms_display_on = 0, > + /* wait timings for panel disable */ > + .delay_ms_display_off = 0, > + .delay_ms_sleep_enter = 0, > +}; > + > +static const struct of_device_id tddi_of_device_id[] = { > + { > + .compatible = "syna,td4101-panel", > + .data = &td4101_panel_data, > + }, { > + .compatible = "syna,td4300-panel", > + .data = &td4300_panel_data, > + }, { } > +}; > +MODULE_DEVICE_TABLE(of, tddi_of_device_id); > + > +static struct mipi_dsi_driver tddi_dsi_driver = { > + .probe = tddi_probe, > + .remove = tddi_remove, > + .driver = { > + .name = "panel-synaptics-tddi", > + .of_match_table = tddi_of_device_id, > + }, > +}; > +module_mipi_dsi_driver(tddi_dsi_driver); > + > +MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>"); > +MODULE_DESCRIPTION("Synaptics TDDI Display Panel Driver"); > +MODULE_LICENSE("GPL"); > Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels 2025-10-09 16:22 [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 1/2] dt-bindings: display: panel: document Synaptics TDDI panel Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels Kaustabh Chakraborty @ 2025-10-24 16:29 ` Kaustabh Chakraborty 2025-10-29 21:05 ` Neil Armstrong 3 siblings, 0 replies; 6+ messages in thread From: Kaustabh Chakraborty @ 2025-10-24 16:29 UTC (permalink / raw) To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jessica Zhang Cc: dri-devel, devicetree, linux-kernel, Krzysztof Kozlowski Hi, I've been trying to get this driver accepted. If panel maintainers have haven't looked into it yet, this is a gentle reminder. Thank you. On 2025-10-09 16:22, Kaustabh Chakraborty wrote: > Synaptics' Touch and Display Driver Integration (TDDI) technology [1] > employs a single chip for both touchscreen and display capabilities. > Such designs reportedly help reducing costs and power consumption. > > Although the touchscreens, which are powered by Synaptics' > Register-Mapped Interface 4 (RMI4) touch protocol via I2C or SPI have > driver support in the kernel, the MIPI DSI display panels don't. > > This series introduces a rudimentary driver for controlling said display > panels, which supports TD4101 and TD4300 panels. > > [1] https://www.synaptics.com/technology/display-integration > > Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org> > --- > Changes in v5: > - added missing Reviewed-by tag from Krzysztof in [v3 1/2] > - Link to v4: https://lore.kernel.org/r/20250819-panel-synaptics-tddi-v4-0-448f466d16a6@disroot.org > > Changes in v4: > - utilized drm_connector_helper_get_modes_fixed() (dmitry.baryshkov) > - constified backlight properties (dmitry.baryshkov) > - Link to v3: https://lore.kernel.org/r/20250720-panel-synaptics-tddi-v3-0-43a5957f4b24@disroot.org > > Changes in v3: > - fixed various dt_binding_check errors (robh's bot) > - adjusted commit description of [v2 1/2] (robh) > - utilized devm_drm_panel_alloc() and devm_regulator_bulk_get_const() > - Link to v2: https://lore.kernel.org/r/20250625-panel-synaptics-tddi-v2-0-7a62ab1d13c7@disroot.org > > Changes in v2: > - fixed various dt_binding_check errors (conor) > - did s/tddi_update_brightness/tddi_update_status > - added check for panel enable in tddi_update_status() > - used backlight_get_brightness() in appropriate places > - Link to v1: https://lore.kernel.org/r/20250612-panel-synaptics-tddi-v1-0-dfb8a425f76c@disroot.org > > --- > Kaustabh Chakraborty (2): > dt-bindings: display: panel: document Synaptics TDDI panel > drm: panel: add support for Synaptics TDDI series DSI panels > > .../display/panel/synaptics,td4300-panel.yaml | 89 +++++++ > drivers/gpu/drm/panel/Kconfig | 11 + > drivers/gpu/drm/panel/Makefile | 1 + > drivers/gpu/drm/panel/panel-synaptics-tddi.c | 276 +++++++++++++++++++++ > 4 files changed, 377 insertions(+) > --- > base-commit: 5303936d609e09665deda94eaedf26a0e5c3a087 > change-id: 20250523-panel-synaptics-tddi-0b0b3f07f814 > > Best regards, > -- > Kaustabh Chakraborty <kauschluss@disroot.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels 2025-10-09 16:22 [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty ` (2 preceding siblings ...) 2025-10-24 16:29 ` [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty @ 2025-10-29 21:05 ` Neil Armstrong 3 siblings, 0 replies; 6+ messages in thread From: Neil Armstrong @ 2025-10-29 21:05 UTC (permalink / raw) To: Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jessica Zhang, Kaustabh Chakraborty Cc: dri-devel, devicetree, linux-kernel, Krzysztof Kozlowski Hi, On Thu, 09 Oct 2025 21:52:09 +0530, Kaustabh Chakraborty wrote: > Synaptics' Touch and Display Driver Integration (TDDI) technology [1] > employs a single chip for both touchscreen and display capabilities. > Such designs reportedly help reducing costs and power consumption. > > Although the touchscreens, which are powered by Synaptics' > Register-Mapped Interface 4 (RMI4) touch protocol via I2C or SPI have > driver support in the kernel, the MIPI DSI display panels don't. > > [...] Thanks, Applied to https://gitlab.freedesktop.org/drm/misc/kernel.git (drm-misc-next) [1/2] dt-bindings: display: panel: document Synaptics TDDI panel https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/5c42579b0705ea372ed7e6f158c880618850b409 [2/2] drm: panel: add support for Synaptics TDDI series DSI panels https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/3eae82503f4fb24e36fc06f6827b8360678c2555 -- Neil ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-10-29 21:05 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-10-09 16:22 [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 1/2] dt-bindings: display: panel: document Synaptics TDDI panel Kaustabh Chakraborty 2025-10-09 16:22 ` [PATCH RESEND v5 2/2] drm: panel: add support for Synaptics TDDI series DSI panels Kaustabh Chakraborty 2025-10-29 21:00 ` Neil Armstrong 2025-10-24 16:29 ` [PATCH RESEND v5 0/2] Support for Synaptics TDDI series panels Kaustabh Chakraborty 2025-10-29 21:05 ` Neil Armstrong
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®