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_jessz...@quicinc.com>
> Reviewed-by: Andy Yan <andys...@163.com>
> Signed-off-by: Sebastian Reichel <sebastian.reic...@collabora.com>
> ---
>  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

Reply via email to