On Fri, Feb 07, 2025 at 05:21:48PM +0100, Sebastian Reichel wrote: > The Rockchip W552793DBA-V10 display/touchscreen board contains a > Wanchanglong W552793BAA panel, which in turn is using a Raydium > RM67200 MIPI-DSI controller. Add a DSI panel driver for it. > > The W552793BAA panel init sequence has been taken from the RK3588 > EVB1 vendor kernel devicetree. > > Reviewed-by: Jessica Zhang <quic_jesszhan@xxxxxxxxxxx> > Reviewed-by: Andy Yan <andyshrk@xxxxxxx> > Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> > --- > drivers/gpu/drm/panel/Kconfig | 10 + > drivers/gpu/drm/panel/Makefile | 1 + > drivers/gpu/drm/panel/panel-raydium-rm67200.c | 503 ++++++++++++++++++++++++++ > 3 files changed, 514 insertions(+) > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig > index d7469c565d1db8b8e974dd6c45d03d9352d99d63..ab962c7d572827774dabd2cdf329367a102c43de 100644 > --- a/drivers/gpu/drm/panel/Kconfig > +++ b/drivers/gpu/drm/panel/Kconfig > @@ -573,6 +573,16 @@ config DRM_PANEL_RAYDIUM_RM67191 > Say Y here if you want to enable support for Raydium RM67191 FHD > (1080x1920) DSI panel. > > +config DRM_PANEL_RAYDIUM_RM67200 > + tristate "Raydium RM67200-based DSI panel" > + depends on OF > + depends on DRM_MIPI_DSI > + help > + Say Y here if you want to enable support for Raydium RM67200-based > + DSI video mode panels. This panel controller can be found in the > + Wanchanglong W552793BAA panel found on the Rockchip RK3588 EVB1 > + evaluation boards. > + > config DRM_PANEL_RAYDIUM_RM68200 > tristate "Raydium RM68200 720x1280 DSI video mode panel" > depends on OF > diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile > index 7dcf72646cacff11bab90c78e3b8b1f357e5f14a..f7b7cd1794927401cab1930402ef5c5df9e4c1c5 100644 > --- a/drivers/gpu/drm/panel/Makefile > +++ b/drivers/gpu/drm/panel/Makefile > @@ -58,6 +58,7 @@ obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o > obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o > obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o > obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o > +obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67200) += panel-raydium-rm67200.o > obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o > obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o > obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o > diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67200.c b/drivers/gpu/drm/panel/panel-raydium-rm67200.c > new file mode 100644 > index 0000000000000000000000000000000000000000..1a7201ce6c9825d3c91661f612723306be1c7981 > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-raydium-rm67200.c > @@ -0,0 +1,503 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +// Copyright (c) 2024 Collabora > + > +#include <linux/delay.h> > +#include <linux/gpio/consumer.h> > +#include <linux/module.h> > +#include <linux/mod_devicetable.h> > +#include <linux/property.h> > +#include <linux/regulator/consumer.h> > + > +#include <drm/drm_mipi_dsi.h> > +#include <drm/drm_probe_helper.h> > +#include <drm/drm_modes.h> > +#include <drm/drm_panel.h> > + > +struct raydium_rm67200_panel_info { > + struct drm_display_mode mode; > + const struct regulator_bulk_data *regulators; > + int num_regulators; > + void (*panel_setup)(struct mipi_dsi_multi_context *ctx); > +}; > + > +struct raydium_rm67200 { > + struct drm_panel panel; > + const struct raydium_rm67200_panel_info *panel_info; > + struct mipi_dsi_device *dsi; > + struct gpio_desc *reset_gpio; > + struct regulator_bulk_data *supplies; > + int num_supplies; > +}; > + > +static inline struct raydium_rm67200 *to_raydium_rm67200(struct drm_panel *panel) > +{ > + return container_of(panel, struct raydium_rm67200, panel); > +} > + > +static void raydium_rm67200_reset(struct raydium_rm67200 *ctx) > +{ > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + msleep(60); > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + msleep(60); > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + msleep(60); > +} > + > +static void raydium_rm67200_write(struct mipi_dsi_multi_context *ctx, > + u8 arg1, u8 arg2) > +{ > + u8 d[] = { arg1, arg2 }; > + > + mipi_dsi_generic_write_multi(ctx, d, ARRAY_SIZE(d)); > +} > + > +static void w552793baa_setup(struct mipi_dsi_multi_context *ctx) > +{ > + raydium_rm67200_write(ctx, 0xFE, 0x21); Nit: Lowercase hex, please. > + raydium_rm67200_write(ctx, 0x04, 0x00); > + raydium_rm67200_write(ctx, 0x00, 0x64); > + raydium_rm67200_write(ctx, 0x2A, 0x00); [...] > +} > + > +static int raydium_rm67200_prepare(struct drm_panel *panel) > +{ > + struct raydium_rm67200 *ctx = to_raydium_rm67200(panel); > + int ret; > + > + ret = regulator_bulk_enable(ctx->num_supplies, ctx->supplies); > + if (ret < 0) > + return ret; > + > + raydium_rm67200_reset(ctx); > + > + msleep(60); > + > + return 0; > +} > + > +static int raydium_rm67200_unprepare(struct drm_panel *panel) > +{ > + struct raydium_rm67200 *ctx = to_raydium_rm67200(panel); > + > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + regulator_bulk_disable(ctx->num_supplies, ctx->supplies); > + > + msleep(60); > + > + return 0; > +} > + > +static int raydium_rm67200_enable(struct drm_panel *panel) > +{ > + struct raydium_rm67200 *rm67200 = to_raydium_rm67200(panel); > + struct mipi_dsi_multi_context ctx = { .dsi = rm67200->dsi }; > + > + rm67200->panel_info->panel_setup(&ctx); > + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); > + mipi_dsi_msleep(&ctx, 120); > + mipi_dsi_dcs_set_display_on_multi(&ctx); > + mipi_dsi_msleep(&ctx, 30); > + > + msleep(60); So, this function will sleep for 30 msec and then for 60 more. Is that expected? Granted that the first line uses msi_dsi_multi() and the second one is just msleep() I can assume that this is some debugging lefrover or a rebase issues. > + > + return ctx.accum_err; > +} > + > +static int raydium_rm67200_disable(struct drm_panel *panel) > +{ > + struct raydium_rm67200 *rm67200 = to_raydium_rm67200(panel); > + struct mipi_dsi_multi_context ctx = { .dsi = rm67200->dsi }; > + > + mipi_dsi_dcs_set_display_off_multi(&ctx); > + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); > + > + msleep(60); > + > + return ctx.accum_err; > +} > + > +static int raydium_rm67200_get_modes(struct drm_panel *panel, > + struct drm_connector *connector) > +{ > + struct raydium_rm67200 *ctx = to_raydium_rm67200(panel); > + > + drm_connector_helper_get_modes_fixed(connector, &ctx->panel_info->mode); > + return 1; return drm_connector_helper_get_modes_fixed(). > +} > + -- With best wishes Dmitry