diff options
author | Jan200101 <sentrycraft123@gmail.com> | 2021-01-15 00:10:49 +0100 |
---|---|---|
committer | Jan200101 <sentrycraft123@gmail.com> | 2021-01-15 00:10:49 +0100 |
commit | 3814de27892f88d7bee46f434d386ada761fd4ba (patch) | |
tree | 0470c6d559ec46201e695664cfaef60ea541f4df /SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch | |
parent | d6cbdaa78bfe1ecf6aa6a95e743bcba390a2ae93 (diff) | |
download | kernel-fsync-3814de27892f88d7bee46f434d386ada761fd4ba.tar.gz kernel-fsync-3814de27892f88d7bee46f434d386ada761fd4ba.zip |
kernel 5.10.6
Diffstat (limited to 'SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch')
-rw-r--r-- | SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch | 948 |
1 files changed, 0 insertions, 948 deletions
diff --git a/SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch b/SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch deleted file mode 100644 index d78bf56..0000000 --- a/SOURCES/0001-drm-panel-rocktech-jh057n00900-Rename-the-driver-to-.patch +++ /dev/null @@ -1,948 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman <megous@megous.com> -Date: Fri, 26 Jun 2020 02:55:52 +0200 -Subject: [PATCH] drm/panel: rocktech-jh057n00900: Rename the driver to st7703 - -This rename is done so that the driver matches the name of the -display controller and in preparation for adding support for more -panels to the driver. - -This is just a basic file rename, with no code changes. - -Signed-off-by: Ondrej Jirman <megous@megous.com> ---- - drivers/gpu/drm/panel/Kconfig | 26 +- - drivers/gpu/drm/panel/Makefile | 2 +- - .../drm/panel/panel-rocktech-jh057n00900.c | 424 ------------------ - drivers/gpu/drm/panel/panel-sitronix-st7703.c | 424 ++++++++++++++++++ - 4 files changed, 438 insertions(+), 438 deletions(-) - delete mode 100644 drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c - create mode 100644 drivers/gpu/drm/panel/panel-sitronix-st7703.c - -diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig -index 39055c1f0e2f..de2f2a452be5 100644 ---- a/drivers/gpu/drm/panel/Kconfig -+++ b/drivers/gpu/drm/panel/Kconfig -@@ -283,19 +283,6 @@ config DRM_PANEL_RAYDIUM_RM68200 - Say Y here if you want to enable support for Raydium RM68200 - 720x1280 DSI video mode panel. - --config DRM_PANEL_ROCKTECH_JH057N00900 -- tristate "Rocktech JH057N00900 MIPI touchscreen 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 Rocktech JH057N00900 -- MIPI DSI panel as e.g. used in the Librem 5 devkit. It has a -- resolution of 720x1440 pixels, a built in backlight and touch -- controller. -- Touch input support is provided by the goodix driver and needs to be -- selected separately. -- - config DRM_PANEL_RONBO_RB070D30 - tristate "Ronbo Electronics RB070D30 panel" - depends on OF -@@ -395,6 +382,19 @@ config DRM_PANEL_SITRONIX_ST7701 - ST7701 controller for 480X864 LCD panels with MIPI/RGB/SPI - system interfaces. - -+config DRM_PANEL_SITRONIX_ST7703 -+ tristate "Sitronix ST7703 based MIPI touchscreen panels" -+ depends on OF -+ depends on DRM_MIPI_DSI -+ depends on BACKLIGHT_CLASS_DEVICE -+ help -+ Say Y here if you want to enable support for Sitronix ST7703 based -+ panels, souch as Rocktech JH057N00900 MIPI DSI panel as e.g. used in -+ the Librem 5 devkit. It has a resolution of 720x1440 pixels, a built -+ in backlight and touch controller. -+ Touch input support is provided by the goodix driver and needs to be -+ selected separately. -+ - config DRM_PANEL_SITRONIX_ST7789V - tristate "Sitronix ST7789V panel" - depends on OF && SPI -diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile -index de74f282c433..e45ceac6286f 100644 ---- a/drivers/gpu/drm/panel/Makefile -+++ b/drivers/gpu/drm/panel/Makefile -@@ -27,7 +27,6 @@ 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_RM68200) += panel-raydium-rm68200.o --obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o - obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o - obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o - obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o -@@ -41,6 +40,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o - obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o - obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o - obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o -+obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o - obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o - obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o - obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o -diff --git a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c b/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c -deleted file mode 100644 -index 38ff742bc120..000000000000 ---- a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c -+++ /dev/null -@@ -1,424 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Rockteck jh057n00900 5.5" MIPI-DSI panel driver -- * -- * Copyright (C) Purism SPC 2019 -- */ -- --#include <linux/debugfs.h> --#include <linux/delay.h> --#include <linux/gpio/consumer.h> --#include <linux/media-bus-format.h> --#include <linux/mod_devicetable.h> --#include <linux/module.h> --#include <linux/regulator/consumer.h> -- --#include <video/display_timing.h> --#include <video/mipi_display.h> -- --#include <drm/drm_mipi_dsi.h> --#include <drm/drm_modes.h> --#include <drm/drm_panel.h> --#include <drm/drm_print.h> -- --#define DRV_NAME "panel-rocktech-jh057n00900" -- --/* Manufacturer specific Commands send via DSI */ --#define ST7703_CMD_ALL_PIXEL_OFF 0x22 --#define ST7703_CMD_ALL_PIXEL_ON 0x23 --#define ST7703_CMD_SETDISP 0xB2 --#define ST7703_CMD_SETRGBIF 0xB3 --#define ST7703_CMD_SETCYC 0xB4 --#define ST7703_CMD_SETBGP 0xB5 --#define ST7703_CMD_SETVCOM 0xB6 --#define ST7703_CMD_SETOTP 0xB7 --#define ST7703_CMD_SETPOWER_EXT 0xB8 --#define ST7703_CMD_SETEXTC 0xB9 --#define ST7703_CMD_SETMIPI 0xBA --#define ST7703_CMD_SETVDC 0xBC --#define ST7703_CMD_UNKNOWN0 0xBF --#define ST7703_CMD_SETSCR 0xC0 --#define ST7703_CMD_SETPOWER 0xC1 --#define ST7703_CMD_SETPANEL 0xCC --#define ST7703_CMD_SETGAMMA 0xE0 --#define ST7703_CMD_SETEQ 0xE3 --#define ST7703_CMD_SETGIP1 0xE9 --#define ST7703_CMD_SETGIP2 0xEA -- --struct jh057n { -- struct device *dev; -- struct drm_panel panel; -- struct gpio_desc *reset_gpio; -- struct regulator *vcc; -- struct regulator *iovcc; -- bool prepared; -- -- struct dentry *debugfs; --}; -- --static inline struct jh057n *panel_to_jh057n(struct drm_panel *panel) --{ -- return container_of(panel, struct jh057n, panel); --} -- --#define dsi_generic_write_seq(dsi, seq...) do { \ -- static const u8 d[] = { seq }; \ -- int ret; \ -- ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ -- if (ret < 0) \ -- return ret; \ -- } while (0) -- --static int jh057n_init_sequence(struct jh057n *ctx) --{ -- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -- struct device *dev = ctx->dev; -- int ret; -- -- /* -- * Init sequence was supplied by the panel vendor. Most of the commands -- * resemble the ST7703 but the number of parameters often don't match -- * so it's likely a clone. -- */ -- dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC, -- 0xF1, 0x12, 0x83); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF, -- 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, -- 0x00, 0x00); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR, -- 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, -- 0x00); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ, -- 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, -- 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08); -- msleep(20); -- -- dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F); -- dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN0, 0x02, 0x11, 0x00); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1, -- 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, -- 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, -- 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, -- 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, -- 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, -- 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -- 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2, -- 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -- 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, -- 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, -- 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -- 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, -- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, -- 0xA5, 0x00, 0x00, 0x00, 0x00); -- dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA, -- 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, -- 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, -- 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, -- 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, -- 0x11, 0x18); -- msleep(20); -- -- ret = mipi_dsi_dcs_exit_sleep_mode(dsi); -- if (ret < 0) { -- DRM_DEV_ERROR(dev, "Failed to exit sleep mode: %d\n", ret); -- return ret; -- } -- /* Panel is operational 120 msec after reset */ -- msleep(60); -- ret = mipi_dsi_dcs_set_display_on(dsi); -- if (ret) -- return ret; -- -- DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n"); -- return 0; --} -- --static int jh057n_enable(struct drm_panel *panel) --{ -- struct jh057n *ctx = panel_to_jh057n(panel); -- int ret; -- -- ret = jh057n_init_sequence(ctx); -- if (ret < 0) { -- DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", -- ret); -- return ret; -- } -- -- return 0; --} -- --static int jh057n_disable(struct drm_panel *panel) --{ -- struct jh057n *ctx = panel_to_jh057n(panel); -- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -- -- return mipi_dsi_dcs_set_display_off(dsi); --} -- --static int jh057n_unprepare(struct drm_panel *panel) --{ -- struct jh057n *ctx = panel_to_jh057n(panel); -- -- if (!ctx->prepared) -- return 0; -- -- regulator_disable(ctx->iovcc); -- regulator_disable(ctx->vcc); -- ctx->prepared = false; -- -- return 0; --} -- --static int jh057n_prepare(struct drm_panel *panel) --{ -- struct jh057n *ctx = panel_to_jh057n(panel); -- int ret; -- -- if (ctx->prepared) -- return 0; -- -- DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); -- ret = regulator_enable(ctx->vcc); -- if (ret < 0) { -- DRM_DEV_ERROR(ctx->dev, -- "Failed to enable vcc supply: %d\n", ret); -- return ret; -- } -- ret = regulator_enable(ctx->iovcc); -- if (ret < 0) { -- DRM_DEV_ERROR(ctx->dev, -- "Failed to enable iovcc supply: %d\n", ret); -- goto disable_vcc; -- } -- -- gpiod_set_value_cansleep(ctx->reset_gpio, 1); -- usleep_range(20, 40); -- gpiod_set_value_cansleep(ctx->reset_gpio, 0); -- msleep(20); -- -- ctx->prepared = true; -- -- return 0; -- --disable_vcc: -- regulator_disable(ctx->vcc); -- return ret; --} -- --static const struct drm_display_mode default_mode = { -- .hdisplay = 720, -- .hsync_start = 720 + 90, -- .hsync_end = 720 + 90 + 20, -- .htotal = 720 + 90 + 20 + 20, -- .vdisplay = 1440, -- .vsync_start = 1440 + 20, -- .vsync_end = 1440 + 20 + 4, -- .vtotal = 1440 + 20 + 4 + 12, -- .vrefresh = 60, -- .clock = 75276, -- .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, -- .width_mm = 65, -- .height_mm = 130, --}; -- --static int jh057n_get_modes(struct drm_panel *panel, -- struct drm_connector *connector) --{ -- struct jh057n *ctx = panel_to_jh057n(panel); -- struct drm_display_mode *mode; -- -- mode = drm_mode_duplicate(connector->dev, &default_mode); -- if (!mode) { -- DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n", -- default_mode.hdisplay, default_mode.vdisplay, -- default_mode.vrefresh); -- return -ENOMEM; -- } -- -- drm_mode_set_name(mode); -- -- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; -- connector->display_info.width_mm = mode->width_mm; -- connector->display_info.height_mm = mode->height_mm; -- drm_mode_probed_add(connector, mode); -- -- return 1; --} -- --static const struct drm_panel_funcs jh057n_drm_funcs = { -- .disable = jh057n_disable, -- .unprepare = jh057n_unprepare, -- .prepare = jh057n_prepare, -- .enable = jh057n_enable, -- .get_modes = jh057n_get_modes, --}; -- --static int allpixelson_set(void *data, u64 val) --{ -- struct jh057n *ctx = data; -- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -- -- DRM_DEV_DEBUG_DRIVER(ctx->dev, "Setting all pixels on\n"); -- dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); -- msleep(val * 1000); -- /* Reset the panel to get video back */ -- drm_panel_disable(&ctx->panel); -- drm_panel_unprepare(&ctx->panel); -- drm_panel_prepare(&ctx->panel); -- drm_panel_enable(&ctx->panel); -- -- return 0; --} -- --DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL, -- allpixelson_set, "%llu\n"); -- --static void jh057n_debugfs_init(struct jh057n *ctx) --{ -- ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL); -- -- debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx, -- &allpixelson_fops); --} -- --static void jh057n_debugfs_remove(struct jh057n *ctx) --{ -- debugfs_remove_recursive(ctx->debugfs); -- ctx->debugfs = NULL; --} -- --static int jh057n_probe(struct mipi_dsi_device *dsi) --{ -- struct device *dev = &dsi->dev; -- struct jh057n *ctx; -- int ret; -- -- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); -- if (!ctx) -- return -ENOMEM; -- -- ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); -- if (IS_ERR(ctx->reset_gpio)) { -- DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); -- return PTR_ERR(ctx->reset_gpio); -- } -- -- mipi_dsi_set_drvdata(dsi, ctx); -- -- ctx->dev = dev; -- -- dsi->lanes = 4; -- dsi->format = MIPI_DSI_FMT_RGB888; -- dsi->mode_flags = MIPI_DSI_MODE_VIDEO | -- MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; -- -- ctx->vcc = devm_regulator_get(dev, "vcc"); -- if (IS_ERR(ctx->vcc)) { -- ret = PTR_ERR(ctx->vcc); -- if (ret != -EPROBE_DEFER) -- DRM_DEV_ERROR(dev, -- "Failed to request vcc regulator: %d\n", -- ret); -- return ret; -- } -- ctx->iovcc = devm_regulator_get(dev, "iovcc"); -- if (IS_ERR(ctx->iovcc)) { -- ret = PTR_ERR(ctx->iovcc); -- if (ret != -EPROBE_DEFER) -- DRM_DEV_ERROR(dev, -- "Failed to request iovcc regulator: %d\n", -- ret); -- return ret; -- } -- -- drm_panel_init(&ctx->panel, dev, &jh057n_drm_funcs, -- DRM_MODE_CONNECTOR_DSI); -- -- ret = drm_panel_of_backlight(&ctx->panel); -- if (ret) -- return ret; -- -- drm_panel_add(&ctx->panel); -- -- ret = mipi_dsi_attach(dsi); -- if (ret < 0) { -- DRM_DEV_ERROR(dev, -- "mipi_dsi_attach failed (%d). Is host ready?\n", -- ret); -- drm_panel_remove(&ctx->panel); -- return ret; -- } -- -- DRM_DEV_INFO(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", -- default_mode.hdisplay, default_mode.vdisplay, -- default_mode.vrefresh, -- mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); -- -- jh057n_debugfs_init(ctx); -- return 0; --} -- --static void jh057n_shutdown(struct mipi_dsi_device *dsi) --{ -- struct jh057n *ctx = mipi_dsi_get_drvdata(dsi); -- int ret; -- -- ret = drm_panel_unprepare(&ctx->panel); -- if (ret < 0) -- DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", -- ret); -- -- ret = drm_panel_disable(&ctx->panel); -- if (ret < 0) -- DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", -- ret); --} -- --static int jh057n_remove(struct mipi_dsi_device *dsi) --{ -- struct jh057n *ctx = mipi_dsi_get_drvdata(dsi); -- int ret; -- -- jh057n_shutdown(dsi); -- -- ret = mipi_dsi_detach(dsi); -- if (ret < 0) -- DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", -- ret); -- -- drm_panel_remove(&ctx->panel); -- -- jh057n_debugfs_remove(ctx); -- -- return 0; --} -- --static const struct of_device_id jh057n_of_match[] = { -- { .compatible = "rocktech,jh057n00900" }, -- { /* sentinel */ } --}; --MODULE_DEVICE_TABLE(of, jh057n_of_match); -- --static struct mipi_dsi_driver jh057n_driver = { -- .probe = jh057n_probe, -- .remove = jh057n_remove, -- .shutdown = jh057n_shutdown, -- .driver = { -- .name = DRV_NAME, -- .of_match_table = jh057n_of_match, -- }, --}; --module_mipi_dsi_driver(jh057n_driver); -- --MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); --MODULE_DESCRIPTION("DRM driver for Rocktech JH057N00900 MIPI DSI panel"); --MODULE_LICENSE("GPL v2"); -diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c -new file mode 100644 -index 000000000000..38ff742bc120 ---- /dev/null -+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c -@@ -0,0 +1,424 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Rockteck jh057n00900 5.5" MIPI-DSI panel driver -+ * -+ * Copyright (C) Purism SPC 2019 -+ */ -+ -+#include <linux/debugfs.h> -+#include <linux/delay.h> -+#include <linux/gpio/consumer.h> -+#include <linux/media-bus-format.h> -+#include <linux/mod_devicetable.h> -+#include <linux/module.h> -+#include <linux/regulator/consumer.h> -+ -+#include <video/display_timing.h> -+#include <video/mipi_display.h> -+ -+#include <drm/drm_mipi_dsi.h> -+#include <drm/drm_modes.h> -+#include <drm/drm_panel.h> -+#include <drm/drm_print.h> -+ -+#define DRV_NAME "panel-rocktech-jh057n00900" -+ -+/* Manufacturer specific Commands send via DSI */ -+#define ST7703_CMD_ALL_PIXEL_OFF 0x22 -+#define ST7703_CMD_ALL_PIXEL_ON 0x23 -+#define ST7703_CMD_SETDISP 0xB2 -+#define ST7703_CMD_SETRGBIF 0xB3 -+#define ST7703_CMD_SETCYC 0xB4 -+#define ST7703_CMD_SETBGP 0xB5 -+#define ST7703_CMD_SETVCOM 0xB6 -+#define ST7703_CMD_SETOTP 0xB7 -+#define ST7703_CMD_SETPOWER_EXT 0xB8 -+#define ST7703_CMD_SETEXTC 0xB9 -+#define ST7703_CMD_SETMIPI 0xBA -+#define ST7703_CMD_SETVDC 0xBC -+#define ST7703_CMD_UNKNOWN0 0xBF -+#define ST7703_CMD_SETSCR 0xC0 -+#define ST7703_CMD_SETPOWER 0xC1 -+#define ST7703_CMD_SETPANEL 0xCC -+#define ST7703_CMD_SETGAMMA 0xE0 -+#define ST7703_CMD_SETEQ 0xE3 -+#define ST7703_CMD_SETGIP1 0xE9 -+#define ST7703_CMD_SETGIP2 0xEA -+ -+struct jh057n { -+ struct device *dev; -+ struct drm_panel panel; -+ struct gpio_desc *reset_gpio; -+ struct regulator *vcc; -+ struct regulator *iovcc; -+ bool prepared; -+ -+ struct dentry *debugfs; -+}; -+ -+static inline struct jh057n *panel_to_jh057n(struct drm_panel *panel) -+{ -+ return container_of(panel, struct jh057n, panel); -+} -+ -+#define dsi_generic_write_seq(dsi, seq...) do { \ -+ static const u8 d[] = { seq }; \ -+ int ret; \ -+ ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ -+ if (ret < 0) \ -+ return ret; \ -+ } while (0) -+ -+static int jh057n_init_sequence(struct jh057n *ctx) -+{ -+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -+ struct device *dev = ctx->dev; -+ int ret; -+ -+ /* -+ * Init sequence was supplied by the panel vendor. Most of the commands -+ * resemble the ST7703 but the number of parameters often don't match -+ * so it's likely a clone. -+ */ -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC, -+ 0xF1, 0x12, 0x83); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF, -+ 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, -+ 0x00, 0x00); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR, -+ 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, -+ 0x00); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ, -+ 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, -+ 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08); -+ msleep(20); -+ -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F); -+ dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN0, 0x02, 0x11, 0x00); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1, -+ 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, -+ 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, -+ 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, -+ 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, -+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, -+ 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -+ 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2, -+ 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, -+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, -+ 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -+ 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, -+ 0xA5, 0x00, 0x00, 0x00, 0x00); -+ dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA, -+ 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, -+ 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, -+ 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, -+ 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, -+ 0x11, 0x18); -+ msleep(20); -+ -+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); -+ if (ret < 0) { -+ DRM_DEV_ERROR(dev, "Failed to exit sleep mode: %d\n", ret); -+ return ret; -+ } -+ /* Panel is operational 120 msec after reset */ -+ msleep(60); -+ ret = mipi_dsi_dcs_set_display_on(dsi); -+ if (ret) -+ return ret; -+ -+ DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n"); -+ return 0; -+} -+ -+static int jh057n_enable(struct drm_panel *panel) -+{ -+ struct jh057n *ctx = panel_to_jh057n(panel); -+ int ret; -+ -+ ret = jh057n_init_sequence(ctx); -+ if (ret < 0) { -+ DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", -+ ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int jh057n_disable(struct drm_panel *panel) -+{ -+ struct jh057n *ctx = panel_to_jh057n(panel); -+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -+ -+ return mipi_dsi_dcs_set_display_off(dsi); -+} -+ -+static int jh057n_unprepare(struct drm_panel *panel) -+{ -+ struct jh057n *ctx = panel_to_jh057n(panel); -+ -+ if (!ctx->prepared) -+ return 0; -+ -+ regulator_disable(ctx->iovcc); -+ regulator_disable(ctx->vcc); -+ ctx->prepared = false; -+ -+ return 0; -+} -+ -+static int jh057n_prepare(struct drm_panel *panel) -+{ -+ struct jh057n *ctx = panel_to_jh057n(panel); -+ int ret; -+ -+ if (ctx->prepared) -+ return 0; -+ -+ DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); -+ ret = regulator_enable(ctx->vcc); -+ if (ret < 0) { -+ DRM_DEV_ERROR(ctx->dev, -+ "Failed to enable vcc supply: %d\n", ret); -+ return ret; -+ } -+ ret = regulator_enable(ctx->iovcc); -+ if (ret < 0) { -+ DRM_DEV_ERROR(ctx->dev, -+ "Failed to enable iovcc supply: %d\n", ret); -+ goto disable_vcc; -+ } -+ -+ gpiod_set_value_cansleep(ctx->reset_gpio, 1); -+ usleep_range(20, 40); -+ gpiod_set_value_cansleep(ctx->reset_gpio, 0); -+ msleep(20); -+ -+ ctx->prepared = true; -+ -+ return 0; -+ -+disable_vcc: -+ regulator_disable(ctx->vcc); -+ return ret; -+} -+ -+static const struct drm_display_mode default_mode = { -+ .hdisplay = 720, -+ .hsync_start = 720 + 90, -+ .hsync_end = 720 + 90 + 20, -+ .htotal = 720 + 90 + 20 + 20, -+ .vdisplay = 1440, -+ .vsync_start = 1440 + 20, -+ .vsync_end = 1440 + 20 + 4, -+ .vtotal = 1440 + 20 + 4 + 12, -+ .vrefresh = 60, -+ .clock = 75276, -+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, -+ .width_mm = 65, -+ .height_mm = 130, -+}; -+ -+static int jh057n_get_modes(struct drm_panel *panel, -+ struct drm_connector *connector) -+{ -+ struct jh057n *ctx = panel_to_jh057n(panel); -+ struct drm_display_mode *mode; -+ -+ mode = drm_mode_duplicate(connector->dev, &default_mode); -+ if (!mode) { -+ DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n", -+ default_mode.hdisplay, default_mode.vdisplay, -+ default_mode.vrefresh); -+ return -ENOMEM; -+ } -+ -+ drm_mode_set_name(mode); -+ -+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; -+ connector->display_info.width_mm = mode->width_mm; -+ connector->display_info.height_mm = mode->height_mm; -+ drm_mode_probed_add(connector, mode); -+ -+ return 1; -+} -+ -+static const struct drm_panel_funcs jh057n_drm_funcs = { -+ .disable = jh057n_disable, -+ .unprepare = jh057n_unprepare, -+ .prepare = jh057n_prepare, -+ .enable = jh057n_enable, -+ .get_modes = jh057n_get_modes, -+}; -+ -+static int allpixelson_set(void *data, u64 val) -+{ -+ struct jh057n *ctx = data; -+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -+ -+ DRM_DEV_DEBUG_DRIVER(ctx->dev, "Setting all pixels on\n"); -+ dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); -+ msleep(val * 1000); -+ /* Reset the panel to get video back */ -+ drm_panel_disable(&ctx->panel); -+ drm_panel_unprepare(&ctx->panel); -+ drm_panel_prepare(&ctx->panel); -+ drm_panel_enable(&ctx->panel); -+ -+ return 0; -+} -+ -+DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL, -+ allpixelson_set, "%llu\n"); -+ -+static void jh057n_debugfs_init(struct jh057n *ctx) -+{ -+ ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL); -+ -+ debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx, -+ &allpixelson_fops); -+} -+ -+static void jh057n_debugfs_remove(struct jh057n *ctx) -+{ -+ debugfs_remove_recursive(ctx->debugfs); -+ ctx->debugfs = NULL; -+} -+ -+static int jh057n_probe(struct mipi_dsi_device *dsi) -+{ -+ struct device *dev = &dsi->dev; -+ struct jh057n *ctx; -+ int ret; -+ -+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); -+ if (!ctx) -+ return -ENOMEM; -+ -+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); -+ if (IS_ERR(ctx->reset_gpio)) { -+ DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); -+ return PTR_ERR(ctx->reset_gpio); -+ } -+ -+ mipi_dsi_set_drvdata(dsi, ctx); -+ -+ ctx->dev = dev; -+ -+ dsi->lanes = 4; -+ dsi->format = MIPI_DSI_FMT_RGB888; -+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | -+ MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; -+ -+ ctx->vcc = devm_regulator_get(dev, "vcc"); -+ if (IS_ERR(ctx->vcc)) { -+ ret = PTR_ERR(ctx->vcc); -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(dev, -+ "Failed to request vcc regulator: %d\n", -+ ret); -+ return ret; -+ } -+ ctx->iovcc = devm_regulator_get(dev, "iovcc"); -+ if (IS_ERR(ctx->iovcc)) { -+ ret = PTR_ERR(ctx->iovcc); -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(dev, -+ "Failed to request iovcc regulator: %d\n", -+ ret); -+ return ret; -+ } -+ -+ drm_panel_init(&ctx->panel, dev, &jh057n_drm_funcs, -+ DRM_MODE_CONNECTOR_DSI); -+ -+ ret = drm_panel_of_backlight(&ctx->panel); -+ if (ret) -+ return ret; -+ -+ drm_panel_add(&ctx->panel); -+ -+ ret = mipi_dsi_attach(dsi); -+ if (ret < 0) { -+ DRM_DEV_ERROR(dev, -+ "mipi_dsi_attach failed (%d). Is host ready?\n", -+ ret); -+ drm_panel_remove(&ctx->panel); -+ return ret; -+ } -+ -+ DRM_DEV_INFO(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", -+ default_mode.hdisplay, default_mode.vdisplay, -+ default_mode.vrefresh, -+ mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); -+ -+ jh057n_debugfs_init(ctx); -+ return 0; -+} -+ -+static void jh057n_shutdown(struct mipi_dsi_device *dsi) -+{ -+ struct jh057n *ctx = mipi_dsi_get_drvdata(dsi); -+ int ret; -+ -+ ret = drm_panel_unprepare(&ctx->panel); -+ if (ret < 0) -+ DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", -+ ret); -+ -+ ret = drm_panel_disable(&ctx->panel); -+ if (ret < 0) -+ DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", -+ ret); -+} -+ -+static int jh057n_remove(struct mipi_dsi_device *dsi) -+{ -+ struct jh057n *ctx = mipi_dsi_get_drvdata(dsi); -+ int ret; -+ -+ jh057n_shutdown(dsi); -+ -+ ret = mipi_dsi_detach(dsi); -+ if (ret < 0) -+ DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", -+ ret); -+ -+ drm_panel_remove(&ctx->panel); -+ -+ jh057n_debugfs_remove(ctx); -+ -+ return 0; -+} -+ -+static const struct of_device_id jh057n_of_match[] = { -+ { .compatible = "rocktech,jh057n00900" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, jh057n_of_match); -+ -+static struct mipi_dsi_driver jh057n_driver = { -+ .probe = jh057n_probe, -+ .remove = jh057n_remove, -+ .shutdown = jh057n_shutdown, -+ .driver = { -+ .name = DRV_NAME, -+ .of_match_table = jh057n_of_match, -+ }, -+}; -+module_mipi_dsi_driver(jh057n_driver); -+ -+MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); -+MODULE_DESCRIPTION("DRM driver for Rocktech JH057N00900 MIPI DSI panel"); -+MODULE_LICENSE("GPL v2"); --- -2.26.2 - |