[PATCH v2 2/2] drm/panel: add Raydium RM67200 panel driver
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Tue Feb 25 03:37:43 UTC 2025
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 at quicinc.com>
> Reviewed-by: Andy Yan <andyshrk at 163.com>
> Signed-off-by: Sebastian Reichel <sebastian.reichel at 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
More information about the dri-devel
mailing list