From d8cf628954e132f7e65b5778a8bcefd6bb6919d5 Mon Sep 17 00:00:00 2001 From: Haaland Chen Date: Fri, 1 Dec 2023 17:55:39 +0800 Subject: [PATCH] drm: panel: Add Orise Technology ota7290b dsi panel Signed-off-by: Haaland Chen (cherry picked from commit 93bec7933ce8df4093ccb9e99070b25ddc68fa85) Signed-off-by: Jaehoon Chung --- drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-orisetech-ota7290b.c | 258 ++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-orisetech-ota7290b.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 2ca5f4b6d81b..152cc1ef836a 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -241,6 +241,15 @@ config DRM_PANEL_OLIMEX_LCD_OLINUXINO Say Y here if you want to enable support for Olimex Ltd. LCD-OLinuXino panel. +config DRM_PANEL_ORISETECH_OTA7290B + tristate "Orise Technology ota7290b dsi panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Orise Technology + ota7290b dsi panel. + config DRM_PANEL_ORISETECH_OTM8009A tristate "Orise Technology otm8009a 480x800 dsi 2dl panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 1ca5576d6d70..9a2a75695e78 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o +obj-$(CONFIG_DRM_PANEL_ORISETECH_OTA7290B) += panel-orisetech-ota7290b.o obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o diff --git a/drivers/gpu/drm/panel/panel-orisetech-ota7290b.c b/drivers/gpu/drm/panel/panel-orisetech-ota7290b.c new file mode 100644 index 000000000000..78fb8644334c --- /dev/null +++ b/drivers/gpu/drm/panel/panel-orisetech-ota7290b.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Radxa Limited + * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. + * + * Author: + * - Jagan Teki + * - Stephen Chen + * + * This file based on panel-jadard-jd9365da-h3.c + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct orisetech_panel_desc { + const struct drm_display_mode mode; + unsigned int lanes; + enum mipi_dsi_pixel_format format; +}; + +struct orisetech { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + const struct orisetech_panel_desc *desc; + + struct regulator *vdd; + struct regulator *vccio; + struct gpio_desc *reset; +}; + +static inline struct orisetech *panel_to_orisetech(struct drm_panel *panel) +{ + return container_of(panel, struct orisetech, panel); +} + +static int orisetech_enable(struct drm_panel *panel) +{ + struct device *dev = panel->dev; + struct orisetech *orisetech = panel_to_orisetech(panel); + struct mipi_dsi_device *dsi = orisetech->dsi; + int err; + + msleep(10); + + err = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (err < 0) + DRM_DEV_ERROR(dev, "failed to exit sleep mode ret = %d\n", err); + + err = mipi_dsi_dcs_set_display_on(dsi); + if (err < 0) + DRM_DEV_ERROR(dev, "failed to set display on ret = %d\n", err); + + return 0; +} + +static int orisetech_disable(struct drm_panel *panel) +{ + struct device *dev = panel->dev; + struct orisetech *orisetech = panel_to_orisetech(panel); + int ret; + + ret = mipi_dsi_dcs_set_display_off(orisetech->dsi); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to set display off: %d\n", ret); + + ret = mipi_dsi_dcs_enter_sleep_mode(orisetech->dsi); + if (ret < 0) + DRM_DEV_ERROR(dev, "failed to enter sleep mode: %d\n", ret); + + return 0; +} + +static int orisetech_prepare(struct drm_panel *panel) +{ + struct orisetech *orisetech = panel_to_orisetech(panel); + int ret; + + ret = regulator_enable(orisetech->vccio); + if (ret) + return ret; + + ret = regulator_enable(orisetech->vdd); + if (ret) + return ret; + + gpiod_set_value(orisetech->reset, 1); + msleep(5); + + gpiod_set_value(orisetech->reset, 0); + msleep(120); + + gpiod_set_value(orisetech->reset, 1); + msleep(120); + + return 0; +} + +static int orisetech_unprepare(struct drm_panel *panel) +{ + struct orisetech *orisetech = panel_to_orisetech(panel); + + gpiod_set_value(orisetech->reset, 1); + msleep(120); + + regulator_disable(orisetech->vdd); + regulator_disable(orisetech->vccio); + + return 0; +} + +static int orisetech_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct orisetech *orisetech = panel_to_orisetech(panel); + const struct drm_display_mode *desc_mode = &orisetech->desc->mode; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, desc_mode); + if (!mode) { + DRM_DEV_ERROR(&orisetech->dsi->dev, "failed to add mode %ux%ux@%u\n", + desc_mode->hdisplay, desc_mode->vdisplay, + drm_mode_vrefresh(desc_mode)); + return -ENOMEM; + } + + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + + return 1; +} + +static const struct drm_panel_funcs orisetech_funcs = { + .disable = orisetech_disable, + .unprepare = orisetech_unprepare, + .prepare = orisetech_prepare, + .enable = orisetech_enable, + .get_modes = orisetech_get_modes, +}; + +static const struct orisetech_panel_desc radxa_display_10fhd_ad003_desc = { + .mode = { + .clock = 160000, + + .hdisplay = 1200, + .hsync_start = 1200 + 80, + .hsync_end = 1200 + 80 + 60, + .htotal = 1200 + 80 + 60 + 4, + + .vdisplay = 1920, + .vsync_start = 1920 + 35, + .vsync_end = 1920 + 35 + 25, + .vtotal = 1920 + 35 + 25 + 4, + + .width_mm = 135, + .height_mm = 217, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + }, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, +}; + +static int orisetech_dsi_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct orisetech_panel_desc *desc; + struct orisetech *orisetech; + int ret; + + orisetech = devm_kzalloc(&dsi->dev, sizeof(*orisetech), GFP_KERNEL); + if (!orisetech) + return -ENOMEM; + + desc = of_device_get_match_data(dev); + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_EOT_PACKET; + dsi->format = desc->format; + dsi->lanes = desc->lanes; + + orisetech->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(orisetech->reset)) { + DRM_DEV_ERROR(&dsi->dev, "failed to get our reset GPIO\n"); + return PTR_ERR(orisetech->reset); + } + + orisetech->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(orisetech->vdd)) { + DRM_DEV_ERROR(&dsi->dev, "failed to get vdd regulator\n"); + return PTR_ERR(orisetech->vdd); + } + + orisetech->vccio = devm_regulator_get(dev, "vccio"); + if (IS_ERR(orisetech->vccio)) { + DRM_DEV_ERROR(&dsi->dev, "failed to get vccio regulator\n"); + return PTR_ERR(orisetech->vccio); + } + + drm_panel_init(&orisetech->panel, dev, &orisetech_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = drm_panel_of_backlight(&orisetech->panel); + if (ret) + return ret; + + drm_panel_add(&orisetech->panel); + + mipi_dsi_set_drvdata(dsi, orisetech); + orisetech->dsi = dsi; + orisetech->desc = desc; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + drm_panel_remove(&orisetech->panel); + + return ret; +} + +static int orisetech_dsi_remove(struct mipi_dsi_device *dsi) +{ + struct orisetech *orisetech = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&orisetech->panel); + + return 0; +} + +static const struct of_device_id orisetech_of_match[] = { + { .compatible = "radxa,display-10fhd-ad003", .data = &radxa_display_10fhd_ad003_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, orisetech_of_match); + +static struct mipi_dsi_driver orisetech_driver = { + .probe = orisetech_dsi_probe, + .remove = orisetech_dsi_remove, + .driver = { + .name = "orisetech-ota7290b", + .of_match_table = orisetech_of_match, + }, +}; +module_mipi_dsi_driver(orisetech_driver); + +MODULE_AUTHOR("Haaland Chen "); +MODULE_DESCRIPTION("Orise Tech OTA7290B TFT-LCD panel"); +MODULE_LICENSE("GPL"); -- 2.34.1