Le mer. 26 août 2026 à 23:22, David Lechner <[email protected]> a écrit :
>
> Add a driver for the Startek KD070FHFID078 7" DSI panel. This panel is
> used on the MediaTek Genio 360 EVK board.
>
> The display mode and DSI mode flags follow the upstream Linux driver
> panel-himax-hx8279.c, which is what the "himax,hx8279" fallback
> compatible in the device tree binds to.
>
> Signed-off-by: David Lechner <[email protected]>
> ---
> Add a driver for the Startek KD070FHFID078 7" DSI panel.
>
> This depends on the mipi_dsi {generic,dcs}_write_seq helper macros series
> for mipi_dsi_generic_write_seq().
>
> Note: no defconfig enables this driver yet, since there is no MediaTek DSI
> host driver in U-Boot at this point. It will be enabled together with the
> display pipeline support.
> ---
> Changes in v2:
> - Added missing BACKLIGHT and DM_REGULATOR Kconfig dependencies.
> - Use the display mode and MIPI_DSI_CLOCK_NON_CONTINUOUS flag from the
>   upstream Linux panel-himax-hx8279.c driver instead of the MediaTek
>   downstream driver.
> - enable-gpios is now optional, matching the binding.
> - A missing backlight is now an error instead of a warning.
> - Do not request reset/enable GPIOs as active, so they are not asserted
>   before the regulators are enabled.
> - Use mipi_dsi_dcs_exit_sleep_mode()/mipi_dsi_dcs_set_display_on() instead
>   of raw DCS opcodes and check their return values.
> - Dropped stale InforceComputing/Linaro copyright and author lines.
> - Dropped the unused dev field and the unreachable mode check.
> - Link to v1: 
> https://patch.msgid.link/20260814-mtk-video-panel-startek-078-v1-1-5f84a5724...@baylibre.com
> ---
>  MAINTAINERS                                 |   6 +
>  drivers/video/Kconfig                       |  10 +
>  drivers/video/Makefile                      |   1 +
>  drivers/video/panel-startek-kd070fhfid078.c | 283 
> ++++++++++++++++++++++++++++
>  4 files changed, 300 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fabcb8b2968..b3bf5b1f8c7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1723,6 +1723,12 @@ R:       GSS_MTK_Uboot_upstream 
> <[email protected]>
>  S:     Maintained
>  F:     drivers/video/panel-startek-kd070fhfid015.c
>
> +STARTEK KD070FHFID078 PANEL
> +M:     David Lechner <[email protected]>
> +R:     GSS_MTK_Uboot_upstream <[email protected]>
> +S:     Maintained
> +F:     drivers/video/panel-startek-kd070fhfid078.c
> +
>  TARGET_BCMNS3
>  M:     Rayagonda Kokatanur <[email protected]>
>  S:     Maintained
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 37ab17f0ab2..495e4382a22 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -330,6 +330,16 @@ config PANEL_STARTEK_KD070FHFID015
>           1200 x 1920 pixels. It provides a MIPI DSI interface to the host, a
>           built-in LED backlight and touch controller.
>
> +config PANEL_STARTEK_KD070FHFID078
> +       bool "STARTEK KD070FHFID078 panel"
> +       depends on PANEL && BACKLIGHT && DM_GPIO && DM_REGULATOR
> +       select VIDEO_MIPI_DSI
> +       help
> +         Say Y here if you want to enable support for STARTEK KD070FHFID078 
> DSI panel.
> +         The panel is a 7-inch TFT LCD display with a resolution of 1200 x 
> 1920
> +         pixels. It provides a MIPI DSI interface to the host, a built-in LED
> +         backlight and touch controller.

This looks like a copy/paste from PANEL_STARTEK_KD070FHFID015. The
built-in LED backlight is wrong for this panel. drop it.

> +
>  config VIDEO_BOCHS
>         bool "Enable Bochs video emulation for QEMU"
>         help
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index 7a54f1f290d..7a7b54e6b53 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -23,6 +23,7 @@ obj-$(CONFIG_$(PHASE_)VIDEO) += video_bmp.o
>  obj-$(CONFIG_$(PHASE_)PANEL) += panel-uclass.o
>  obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o
>  obj-$(CONFIG_PANEL_STARTEK_KD070FHFID015) += panel-startek-kd070fhfid015.o
> +obj-$(CONFIG_PANEL_STARTEK_KD070FHFID078) += panel-startek-kd070fhfid078.o
>  obj-$(CONFIG_$(PHASE_)SIMPLE_PANEL) += simple_panel.o
>
>  obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.bmp.o
> diff --git a/drivers/video/panel-startek-kd070fhfid078.c 
> b/drivers/video/panel-startek-kd070fhfid078.c
> new file mode 100644
> index 00000000000..dd5cac46267
> --- /dev/null
> +++ b/drivers/video/panel-startek-kd070fhfid078.c
> @@ -0,0 +1,283 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2025 MediaTek Inc.
> + * Copyright (C) 2026 BayLibre, SAS
> + *
> + * Authors:
> + * - Guillaume La Roque <[email protected]>
> + * - Jitao Shi <[email protected]>
> + * - David Lechner <[email protected]>
> + */
> +
> +#include <asm-generic/gpio.h>
> +#include <backlight.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <errno.h>
> +#include <linux/delay.h>
> +#include <mipi_dsi.h>
> +#include <panel.h>
> +#include <power/regulator.h>
> +
> +struct stk078_panel {
> +       struct gpio_desc *enable_gpio;
> +       struct gpio_desc *reset_gpio;
> +       struct mipi_dsi_device *dsi;
> +       struct udevice *iovcc;
> +       struct udevice *vdd;
> +       struct udevice *backlight;
> +};
> +
> +static const struct drm_display_mode default_mode = {
> +       .clock = 156458,
> +       .hdisplay = 1200,
> +       .hsync_start = 1200 + 50,
> +       .hsync_end = 1200 + 50 + 24,
> +       .htotal = 1200 + 50 + 24 + 66,
> +       .vdisplay = 1920,
> +       .vsync_start = 1920 + 14,
> +       .vsync_end = 1920 + 14 + 2,
> +       .vtotal = 1920 + 14 + 2 + 10,
> +};
> +
> +static int stk078_panel_init(struct stk078_panel *stk)
> +{
> +       struct mipi_dsi_device *dsi = stk->dsi;
> +       int ret;
> +
> +       mipi_dsi_generic_write_seq(dsi, 0xB0, 0x05);
> +       mipi_dsi_generic_write_seq(dsi, 0xB3, 0x52);
> +       mipi_dsi_generic_write_seq(dsi, 0xB8, 0x7F);
> +       mipi_dsi_generic_write_seq(dsi, 0xBC, 0x20);
> +       mipi_dsi_generic_write_seq(dsi, 0xD6, 0x7F);
> +       mipi_dsi_generic_write_seq(dsi, 0xB0, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xC0, 0x0D);
> +       mipi_dsi_generic_write_seq(dsi, 0xC1, 0x0D);
> +       mipi_dsi_generic_write_seq(dsi, 0xC2, 0x06);
> +       mipi_dsi_generic_write_seq(dsi, 0xC3, 0x06);
> +       mipi_dsi_generic_write_seq(dsi, 0xC4, 0x08);
> +       mipi_dsi_generic_write_seq(dsi, 0xC5, 0x08);
> +       mipi_dsi_generic_write_seq(dsi, 0xC6, 0x0A);
> +       mipi_dsi_generic_write_seq(dsi, 0xC7, 0x0A);
> +       mipi_dsi_generic_write_seq(dsi, 0xC8, 0x0C);
> +       mipi_dsi_generic_write_seq(dsi, 0xC9, 0x0C);
> +       mipi_dsi_generic_write_seq(dsi, 0xCA, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xCB, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xCC, 0x0E);
> +       mipi_dsi_generic_write_seq(dsi, 0xCD, 0x0E);
> +       mipi_dsi_generic_write_seq(dsi, 0xCE, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xCF, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xD0, 0x04);
> +       mipi_dsi_generic_write_seq(dsi, 0xD1, 0x04);
> +       mipi_dsi_generic_write_seq(dsi, 0xD2, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xD3, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xD4, 0x0D);
> +       mipi_dsi_generic_write_seq(dsi, 0xD5, 0x0D);
> +       mipi_dsi_generic_write_seq(dsi, 0xD6, 0x05);
> +       mipi_dsi_generic_write_seq(dsi, 0xD7, 0x05);
> +       mipi_dsi_generic_write_seq(dsi, 0xD8, 0x07);
> +       mipi_dsi_generic_write_seq(dsi, 0xD9, 0x07);
> +       mipi_dsi_generic_write_seq(dsi, 0xDA, 0x09);
> +       mipi_dsi_generic_write_seq(dsi, 0xDB, 0x09);
> +       mipi_dsi_generic_write_seq(dsi, 0xDC, 0x0B);
> +       mipi_dsi_generic_write_seq(dsi, 0xDD, 0x0B);
> +       mipi_dsi_generic_write_seq(dsi, 0xDE, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xDF, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xE0, 0x0E);
> +       mipi_dsi_generic_write_seq(dsi, 0xE1, 0x0E);
> +       mipi_dsi_generic_write_seq(dsi, 0xE2, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xE3, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xE4, 0x03);
> +       mipi_dsi_generic_write_seq(dsi, 0xE5, 0x03);
> +       mipi_dsi_generic_write_seq(dsi, 0xE6, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xE7, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xB0, 0x03);
> +       mipi_dsi_generic_write_seq(dsi, 0xBA, 0xF0);
> +       mipi_dsi_generic_write_seq(dsi, 0xC8, 0x07);
> +       mipi_dsi_generic_write_seq(dsi, 0xC9, 0x03);
> +       mipi_dsi_generic_write_seq(dsi, 0xCA, 0x41);
> +       mipi_dsi_generic_write_seq(dsi, 0xD2, 0x01);
> +       mipi_dsi_generic_write_seq(dsi, 0xD3, 0x05);
> +       mipi_dsi_generic_write_seq(dsi, 0xD4, 0x05);
> +       mipi_dsi_generic_write_seq(dsi, 0xD5, 0x8A);
> +       mipi_dsi_generic_write_seq(dsi, 0xE4, 0xC0);
> +       mipi_dsi_generic_write_seq(dsi, 0xE5, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xB0, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xBF, 0x1F);
> +       mipi_dsi_generic_write_seq(dsi, 0xC0, 0x12);
> +       mipi_dsi_generic_write_seq(dsi, 0xC2, 0x1E);
> +       mipi_dsi_generic_write_seq(dsi, 0xC4, 0x1E);
> +       mipi_dsi_generic_write_seq(dsi, 0xB0, 0x06);
> +       mipi_dsi_generic_write_seq(dsi, 0xB8, 0xA5);
> +       mipi_dsi_generic_write_seq(dsi, 0xC0, 0xA5);
> +       mipi_dsi_generic_write_seq(dsi, 0xBC, 0x11);
> +       mipi_dsi_generic_write_seq(dsi, 0xD5, 0x48);
> +       mipi_dsi_generic_write_seq(dsi, 0xB8, 0x00);
> +       mipi_dsi_generic_write_seq(dsi, 0xC0, 0x00);
> +
> +       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
> +       if (ret < 0)
> +               return ret;
> +
> +       mdelay(120);
> +
> +       ret = mipi_dsi_dcs_set_display_on(dsi);
> +       if (ret < 0)
> +               return ret;
> +
> +       mdelay(20);
> +
> +       return 0;
> +}
> +
> +static int stk078_panel_enable_backlight(struct udevice *dev)
> +{
> +       struct stk078_panel *stk = dev_get_priv(dev);
> +       struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
> +       struct mipi_dsi_device *dsi = plat->device;
> +       int ret;
> +
> +       stk->dsi = dsi;
> +       ret = mipi_dsi_attach(dsi);
> +       if (ret < 0) {
> +               dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       dm_gpio_set_value(stk->reset_gpio, 0);
> +       if (stk->enable_gpio)
> +               dm_gpio_set_value(stk->enable_gpio, 0);
> +       mdelay(10);
> +
> +       ret = regulator_enable(stk->vdd);
> +       if (ret < 0) {
> +               dev_err(dev, "enable vdd failed: %d\n", ret);
> +               goto out_gpio;
> +       }
> +
> +       ret = regulator_enable(stk->iovcc);
> +       if (ret < 0) {
> +               dev_err(dev, "enable iovcc failed: %d\n", ret);
> +               goto out_vdd;
> +       }
> +
> +       mdelay(15);
> +       if (stk->enable_gpio)
> +               dm_gpio_set_value(stk->enable_gpio, 1);
> +       mdelay(10);
> +       dm_gpio_set_value(stk->reset_gpio, 1);
> +       mdelay(140);
> +
> +       ret = stk078_panel_init(stk);
> +       if (ret < 0) {
> +               dev_err(dev, "panel init sequence failed: %d\n", ret);
> +               goto out_power;
> +       }
> +
> +       ret = backlight_enable(stk->backlight);
> +       if (ret < 0) {
> +               dev_err(dev, "enable backlight failed: %d\n", ret);
> +               goto out_power;
> +       }
> +
> +       return 0;
> +
> +out_power:
> +       regulator_disable(stk->iovcc);
> +out_vdd:
> +       regulator_disable(stk->vdd);
> +out_gpio:
> +       dm_gpio_set_value(stk->reset_gpio, 0);
> +       if (stk->enable_gpio)
> +               dm_gpio_set_value(stk->enable_gpio, 0);
> +
> +       return ret;

I think we are missing mipi_dsi_detach() call at the end

> +}
> +
> +static int stk078_panel_add(struct udevice *dev)
> +{
> +       struct stk078_panel *stk = dev_get_priv(dev);
> +       int ret;
> +
> +       ret = device_get_supply_regulator(dev, "iovcc-supply", &stk->iovcc);
> +       if (ret) {
> +               dev_err(dev, "Failed to get iovcc regulator: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = device_get_supply_regulator(dev, "vdd-supply", &stk->vdd);
> +       if (ret) {
> +               dev_err(dev, "Failed to get vdd regulator: %d\n", ret);
> +               return ret;
> +       }
> +
> +       stk->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_IS_OUT);
> +       if (IS_ERR(stk->reset_gpio)) {
> +               ret = PTR_ERR(stk->reset_gpio);
> +               dev_err(dev, "cannot get reset-gpios %d\n", ret);
> +               return ret;
> +       }
> +
> +       stk->enable_gpio = devm_gpiod_get_optional(dev, "enable", 
> GPIOD_IS_OUT);
> +       if (IS_ERR(stk->enable_gpio)) {
> +               ret = PTR_ERR(stk->enable_gpio);
> +               dev_err(dev, "cannot get enable-gpios %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
> +                                          "backlight", &stk->backlight);
> +       if (ret) {
> +               dev_err(dev, "failed to get backlight: %d\n", ret);
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int stk078_panel_probe(struct udevice *dev)
> +{
> +       struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
> +       int ret;
> +
> +       plat->lanes = 4;
> +       plat->format = MIPI_DSI_FMT_RGB888;
> +       plat->mode_flags = MIPI_DSI_MODE_VIDEO |
> +                          MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
> +                          MIPI_DSI_MODE_LPM |
> +                          MIPI_DSI_CLOCK_NON_CONTINUOUS;
> +
> +       ret = stk078_panel_add(dev);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;

can be simplified:  return stk078_panel_add(dev);

> +}
> +
> +static int stk078_panel_get_modes(struct udevice *dev,
> +                                 const struct drm_display_mode **modes)
> +{
> +       *modes = &default_mode;
> +
> +       return 1;
> +}
> +
> +static const struct panel_ops stk078_panel_ops = {
> +       .enable_backlight = stk078_panel_enable_backlight,
> +       .get_modes = stk078_panel_get_modes,
> +};
> +
> +static const struct udevice_id stk078_of_match[] = {
> +       { .compatible = "startek,kd070fhfid078" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(stk078_panel_driver) = {
> +       .name           = "panel-startek-kd070fhfid078",
> +       .id             = UCLASS_PANEL,
> +       .of_match       = stk078_of_match,
> +       .ops            = &stk078_panel_ops,
> +       .probe          = stk078_panel_probe,
> +       .plat_auto      = sizeof(struct mipi_dsi_panel_plat),
> +       .priv_auto      = sizeof(struct stk078_panel),
> +};
>
> ---
> base-commit: f252d228be2b2d180737ad0a851f91749273cbd9
> change-id: 20260814-mtk-video-panel-startek-078-1a9ab38e89f7
> prerequisite-message-id: 
> <20260806-add_mipi_dsi_write_seq_helper_macros-v1-0-6b533788d...@baylibre.com>
> prerequisite-patch-id: cf35ac4802976971af68bd0ce1dc0ab872fdb661
> prerequisite-patch-id: 9f6aca2bfde84a5d84329b77b3b9af8898b18e4a
> prerequisite-patch-id: e7bb7ee54b88b6d6e00f74fe84b1c81d00957051
> prerequisite-patch-id: d4a530120b1a93d68e4b17c6e1fcf2878e784454
> prerequisite-patch-id: 18b1bbeab6808decceaf5117b3e999baf4495e1d
> prerequisite-patch-id: d50e7e28a399c303226ff08c78e60749930a7243
>
> Best regards,
> --
> David Lechner <[email protected]>
>

Reply via email to