172967d56SGuido Günther // SPDX-License-Identifier: GPL-2.0 272967d56SGuido Günther /* 372967d56SGuido Günther * Mantix MLAF057WE51 5.7" MIPI-DSI panel driver 472967d56SGuido Günther * 572967d56SGuido Günther * Copyright (C) Purism SPC 2020 672967d56SGuido Günther */ 772967d56SGuido Günther 872967d56SGuido Günther #include <linux/backlight.h> 972967d56SGuido Günther #include <linux/delay.h> 1072967d56SGuido Günther #include <linux/gpio/consumer.h> 1172967d56SGuido Günther #include <linux/module.h> 1272967d56SGuido Günther #include <linux/regulator/consumer.h> 1372967d56SGuido Günther 1472967d56SGuido Günther #include <video/mipi_display.h> 1572967d56SGuido Günther 1672967d56SGuido Günther #include <drm/drm_mipi_dsi.h> 1772967d56SGuido Günther #include <drm/drm_modes.h> 1872967d56SGuido Günther #include <drm/drm_panel.h> 1972967d56SGuido Günther 2072967d56SGuido Günther #define DRV_NAME "panel-mantix-mlaf057we51" 2172967d56SGuido Günther 2272967d56SGuido Günther /* Manufacturer specific Commands send via DSI */ 2372967d56SGuido Günther #define MANTIX_CMD_OTP_STOP_RELOAD_MIPI 0x41 2472967d56SGuido Günther #define MANTIX_CMD_INT_CANCEL 0x4C 2572967d56SGuido Günther 2672967d56SGuido Günther struct mantix { 2772967d56SGuido Günther struct device *dev; 2872967d56SGuido Günther struct drm_panel panel; 2972967d56SGuido Günther struct gpio_desc *reset_gpio; 3072967d56SGuido Günther 3172967d56SGuido Günther struct regulator *avdd; 3272967d56SGuido Günther struct regulator *avee; 3372967d56SGuido Günther struct regulator *vddi; 3472967d56SGuido Günther }; 3572967d56SGuido Günther 3672967d56SGuido Günther static inline struct mantix *panel_to_mantix(struct drm_panel *panel) 3772967d56SGuido Günther { 3872967d56SGuido Günther return container_of(panel, struct mantix, panel); 3972967d56SGuido Günther } 4072967d56SGuido Günther 4172967d56SGuido Günther #define dsi_generic_write_seq(dsi, seq...) do { \ 4272967d56SGuido Günther static const u8 d[] = { seq }; \ 4372967d56SGuido Günther int ret; \ 4472967d56SGuido Günther ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ 4572967d56SGuido Günther if (ret < 0) \ 4672967d56SGuido Günther return ret; \ 4772967d56SGuido Günther } while (0) 4872967d56SGuido Günther 4972967d56SGuido Günther static int mantix_init_sequence(struct mantix *ctx) 5072967d56SGuido Günther { 5172967d56SGuido Günther struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 5272967d56SGuido Günther struct device *dev = ctx->dev; 5372967d56SGuido Günther 5472967d56SGuido Günther /* 5572967d56SGuido Günther * Init sequence was supplied by the panel vendor. 5672967d56SGuido Günther */ 5772967d56SGuido Günther dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A); 5872967d56SGuido Günther 5972967d56SGuido Günther dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03); 6072967d56SGuido Günther dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03); 6172967d56SGuido Günther dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00); 6272967d56SGuido Günther 6372967d56SGuido Günther dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09); 6472967d56SGuido Günther dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00); 6572967d56SGuido Günther msleep(20); 6672967d56SGuido Günther 6772967d56SGuido Günther dev_dbg(dev, "Panel init sequence done\n"); 6872967d56SGuido Günther return 0; 6972967d56SGuido Günther } 7072967d56SGuido Günther 7172967d56SGuido Günther static int mantix_enable(struct drm_panel *panel) 7272967d56SGuido Günther { 7372967d56SGuido Günther struct mantix *ctx = panel_to_mantix(panel); 7472967d56SGuido Günther struct device *dev = ctx->dev; 7572967d56SGuido Günther struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 7672967d56SGuido Günther int ret; 7772967d56SGuido Günther 7872967d56SGuido Günther ret = mantix_init_sequence(ctx); 7972967d56SGuido Günther if (ret < 0) { 8072967d56SGuido Günther dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); 8172967d56SGuido Günther return ret; 8272967d56SGuido Günther } 8372967d56SGuido Günther 8472967d56SGuido Günther ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 8572967d56SGuido Günther if (ret < 0) { 8672967d56SGuido Günther dev_err(dev, "Failed to exit sleep mode\n"); 8772967d56SGuido Günther return ret; 8872967d56SGuido Günther } 8972967d56SGuido Günther msleep(20); 9072967d56SGuido Günther 9172967d56SGuido Günther ret = mipi_dsi_dcs_set_display_on(dsi); 9272967d56SGuido Günther if (ret) 9372967d56SGuido Günther return ret; 9472967d56SGuido Günther usleep_range(10000, 12000); 9572967d56SGuido Günther 9672967d56SGuido Günther ret = mipi_dsi_turn_on_peripheral(dsi); 9772967d56SGuido Günther if (ret < 0) { 9872967d56SGuido Günther dev_err(dev, "Failed to turn on peripheral\n"); 9972967d56SGuido Günther return ret; 10072967d56SGuido Günther } 10172967d56SGuido Günther 10272967d56SGuido Günther return 0; 10372967d56SGuido Günther } 10472967d56SGuido Günther 10572967d56SGuido Günther static int mantix_disable(struct drm_panel *panel) 10672967d56SGuido Günther { 10772967d56SGuido Günther struct mantix *ctx = panel_to_mantix(panel); 10872967d56SGuido Günther struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 10972967d56SGuido Günther int ret; 11072967d56SGuido Günther 11172967d56SGuido Günther ret = mipi_dsi_dcs_set_display_off(dsi); 11272967d56SGuido Günther if (ret < 0) 11372967d56SGuido Günther dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret); 11472967d56SGuido Günther 11572967d56SGuido Günther ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 11672967d56SGuido Günther if (ret < 0) 11772967d56SGuido Günther dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); 11872967d56SGuido Günther 11972967d56SGuido Günther 12072967d56SGuido Günther return 0; 12172967d56SGuido Günther } 12272967d56SGuido Günther 12372967d56SGuido Günther static int mantix_unprepare(struct drm_panel *panel) 12472967d56SGuido Günther { 12572967d56SGuido Günther struct mantix *ctx = panel_to_mantix(panel); 12672967d56SGuido Günther 12772967d56SGuido Günther regulator_disable(ctx->avee); 12872967d56SGuido Günther regulator_disable(ctx->avdd); 12972967d56SGuido Günther /* T11 */ 13072967d56SGuido Günther usleep_range(5000, 6000); 13172967d56SGuido Günther regulator_disable(ctx->vddi); 13272967d56SGuido Günther /* T14 */ 13372967d56SGuido Günther msleep(50); 13472967d56SGuido Günther 13572967d56SGuido Günther return 0; 13672967d56SGuido Günther } 13772967d56SGuido Günther 13872967d56SGuido Günther static int mantix_prepare(struct drm_panel *panel) 13972967d56SGuido Günther { 14072967d56SGuido Günther struct mantix *ctx = panel_to_mantix(panel); 14172967d56SGuido Günther int ret; 14272967d56SGuido Günther 14372967d56SGuido Günther /* Focaltech FT8006P, section 7.3.1 and 7.3.4 */ 14472967d56SGuido Günther dev_dbg(ctx->dev, "Resetting the panel\n"); 14572967d56SGuido Günther ret = regulator_enable(ctx->vddi); 14672967d56SGuido Günther if (ret < 0) { 14772967d56SGuido Günther dev_err(ctx->dev, "Failed to enable vddi supply: %d\n", ret); 14872967d56SGuido Günther return ret; 14972967d56SGuido Günther } 15072967d56SGuido Günther 15172967d56SGuido Günther /* T1 + T2 */ 15272967d56SGuido Günther usleep_range(8000, 10000); 15372967d56SGuido Günther 15472967d56SGuido Günther ret = regulator_enable(ctx->avdd); 15572967d56SGuido Günther if (ret < 0) { 15672967d56SGuido Günther dev_err(ctx->dev, "Failed to enable avdd supply: %d\n", ret); 15772967d56SGuido Günther return ret; 15872967d56SGuido Günther } 15972967d56SGuido Günther 16072967d56SGuido Günther /* T2d */ 16172967d56SGuido Günther usleep_range(3500, 4000); 16272967d56SGuido Günther ret = regulator_enable(ctx->avee); 16372967d56SGuido Günther if (ret < 0) { 16472967d56SGuido Günther dev_err(ctx->dev, "Failed to enable avee supply: %d\n", ret); 16572967d56SGuido Günther return ret; 16672967d56SGuido Günther } 16772967d56SGuido Günther 16872967d56SGuido Günther /* T3+T5 */ 16972967d56SGuido Günther usleep_range(10000, 12000); 17072967d56SGuido Günther 17172967d56SGuido Günther gpiod_set_value_cansleep(ctx->reset_gpio, 1); 17272967d56SGuido Günther usleep_range(5150, 7000); 17372967d56SGuido Günther 17472967d56SGuido Günther gpiod_set_value_cansleep(ctx->reset_gpio, 0); 17572967d56SGuido Günther 17672967d56SGuido Günther /* T6 */ 17772967d56SGuido Günther msleep(50); 17872967d56SGuido Günther 17972967d56SGuido Günther return 0; 18072967d56SGuido Günther } 18172967d56SGuido Günther 18272967d56SGuido Günther static const struct drm_display_mode default_mode = { 18372967d56SGuido Günther .hdisplay = 720, 18472967d56SGuido Günther .hsync_start = 720 + 45, 18572967d56SGuido Günther .hsync_end = 720 + 45 + 14, 18672967d56SGuido Günther .htotal = 720 + 45 + 14 + 25, 18772967d56SGuido Günther .vdisplay = 1440, 18872967d56SGuido Günther .vsync_start = 1440 + 130, 18972967d56SGuido Günther .vsync_end = 1440 + 130 + 8, 19072967d56SGuido Günther .vtotal = 1440 + 130 + 8 + 106, 19172967d56SGuido Günther .clock = 85298, 19272967d56SGuido Günther .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 19372967d56SGuido Günther .width_mm = 65, 19472967d56SGuido Günther .height_mm = 130, 19572967d56SGuido Günther }; 19672967d56SGuido Günther 19772967d56SGuido Günther static int mantix_get_modes(struct drm_panel *panel, 19872967d56SGuido Günther struct drm_connector *connector) 19972967d56SGuido Günther { 20072967d56SGuido Günther struct mantix *ctx = panel_to_mantix(panel); 20172967d56SGuido Günther struct drm_display_mode *mode; 20272967d56SGuido Günther 20372967d56SGuido Günther mode = drm_mode_duplicate(connector->dev, &default_mode); 20472967d56SGuido Günther if (!mode) { 20572967d56SGuido Günther dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", 20672967d56SGuido Günther default_mode.hdisplay, default_mode.vdisplay, 20772967d56SGuido Günther drm_mode_vrefresh(mode)); 20872967d56SGuido Günther return -ENOMEM; 20972967d56SGuido Günther } 21072967d56SGuido Günther 21172967d56SGuido Günther drm_mode_set_name(mode); 21272967d56SGuido Günther 21372967d56SGuido Günther mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 21472967d56SGuido Günther connector->display_info.width_mm = mode->width_mm; 21572967d56SGuido Günther connector->display_info.height_mm = mode->height_mm; 21672967d56SGuido Günther drm_mode_probed_add(connector, mode); 21772967d56SGuido Günther 21872967d56SGuido Günther return 1; 21972967d56SGuido Günther } 22072967d56SGuido Günther 22172967d56SGuido Günther static const struct drm_panel_funcs mantix_drm_funcs = { 22272967d56SGuido Günther .disable = mantix_disable, 22372967d56SGuido Günther .unprepare = mantix_unprepare, 22472967d56SGuido Günther .prepare = mantix_prepare, 22572967d56SGuido Günther .enable = mantix_enable, 22672967d56SGuido Günther .get_modes = mantix_get_modes, 22772967d56SGuido Günther }; 22872967d56SGuido Günther 22972967d56SGuido Günther static int mantix_probe(struct mipi_dsi_device *dsi) 23072967d56SGuido Günther { 23172967d56SGuido Günther struct device *dev = &dsi->dev; 23272967d56SGuido Günther struct mantix *ctx; 23372967d56SGuido Günther int ret; 23472967d56SGuido Günther 23572967d56SGuido Günther ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 23672967d56SGuido Günther if (!ctx) 23772967d56SGuido Günther return -ENOMEM; 23872967d56SGuido Günther 23972967d56SGuido Günther ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 24072967d56SGuido Günther if (IS_ERR(ctx->reset_gpio)) { 24172967d56SGuido Günther dev_err(dev, "cannot get reset gpio\n"); 24272967d56SGuido Günther return PTR_ERR(ctx->reset_gpio); 24372967d56SGuido Günther } 24472967d56SGuido Günther 24572967d56SGuido Günther mipi_dsi_set_drvdata(dsi, ctx); 24672967d56SGuido Günther ctx->dev = dev; 24772967d56SGuido Günther 24872967d56SGuido Günther dsi->lanes = 4; 24972967d56SGuido Günther dsi->format = MIPI_DSI_FMT_RGB888; 25072967d56SGuido Günther dsi->mode_flags = MIPI_DSI_MODE_VIDEO | 25172967d56SGuido Günther MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; 25272967d56SGuido Günther 25372967d56SGuido Günther ctx->avdd = devm_regulator_get(dev, "avdd"); 25472967d56SGuido Günther if (IS_ERR(ctx->avdd)) 25572967d56SGuido Günther return dev_err_probe(dev, PTR_ERR(ctx->avdd), "Failed to request avdd regulator\n"); 25672967d56SGuido Günther 25772967d56SGuido Günther ctx->avee = devm_regulator_get(dev, "avee"); 25872967d56SGuido Günther if (IS_ERR(ctx->avee)) 25972967d56SGuido Günther return dev_err_probe(dev, PTR_ERR(ctx->avee), "Failed to request avee regulator\n"); 26072967d56SGuido Günther 26172967d56SGuido Günther ctx->vddi = devm_regulator_get(dev, "vddi"); 26272967d56SGuido Günther if (IS_ERR(ctx->vddi)) 26372967d56SGuido Günther return dev_err_probe(dev, PTR_ERR(ctx->vddi), "Failed to request vddi regulator\n"); 26472967d56SGuido Günther 26572967d56SGuido Günther drm_panel_init(&ctx->panel, dev, &mantix_drm_funcs, 26672967d56SGuido Günther DRM_MODE_CONNECTOR_DSI); 26772967d56SGuido Günther 26872967d56SGuido Günther ret = drm_panel_of_backlight(&ctx->panel); 26972967d56SGuido Günther if (ret) 27072967d56SGuido Günther return ret; 27172967d56SGuido Günther 27272967d56SGuido Günther drm_panel_add(&ctx->panel); 27372967d56SGuido Günther 27472967d56SGuido Günther ret = mipi_dsi_attach(dsi); 27572967d56SGuido Günther if (ret < 0) { 27672967d56SGuido Günther dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret); 27772967d56SGuido Günther drm_panel_remove(&ctx->panel); 27872967d56SGuido Günther return ret; 27972967d56SGuido Günther } 28072967d56SGuido Günther 28172967d56SGuido Günther dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", 28272967d56SGuido Günther default_mode.hdisplay, default_mode.vdisplay, 28372967d56SGuido Günther drm_mode_vrefresh(&default_mode), 28472967d56SGuido Günther mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); 28572967d56SGuido Günther 28672967d56SGuido Günther return 0; 28772967d56SGuido Günther } 28872967d56SGuido Günther 28972967d56SGuido Günther static void mantix_shutdown(struct mipi_dsi_device *dsi) 29072967d56SGuido Günther { 29172967d56SGuido Günther struct mantix *ctx = mipi_dsi_get_drvdata(dsi); 29272967d56SGuido Günther 29372967d56SGuido Günther drm_panel_unprepare(&ctx->panel); 29472967d56SGuido Günther drm_panel_disable(&ctx->panel); 29572967d56SGuido Günther } 29672967d56SGuido Günther 29772967d56SGuido Günther static int mantix_remove(struct mipi_dsi_device *dsi) 29872967d56SGuido Günther { 29972967d56SGuido Günther struct mantix *ctx = mipi_dsi_get_drvdata(dsi); 30072967d56SGuido Günther 30172967d56SGuido Günther mantix_shutdown(dsi); 30272967d56SGuido Günther 30372967d56SGuido Günther mipi_dsi_detach(dsi); 30472967d56SGuido Günther drm_panel_remove(&ctx->panel); 30572967d56SGuido Günther 30672967d56SGuido Günther return 0; 30772967d56SGuido Günther } 30872967d56SGuido Günther 30972967d56SGuido Günther static const struct of_device_id mantix_of_match[] = { 31072967d56SGuido Günther { .compatible = "mantix,mlaf057we51-x" }, 31172967d56SGuido Günther { /* sentinel */ } 31272967d56SGuido Günther }; 31372967d56SGuido Günther MODULE_DEVICE_TABLE(of, mantix_of_match); 31472967d56SGuido Günther 31572967d56SGuido Günther static struct mipi_dsi_driver mantix_driver = { 31672967d56SGuido Günther .probe = mantix_probe, 31772967d56SGuido Günther .remove = mantix_remove, 31872967d56SGuido Günther .shutdown = mantix_shutdown, 31972967d56SGuido Günther .driver = { 32072967d56SGuido Günther .name = DRV_NAME, 32172967d56SGuido Günther .of_match_table = mantix_of_match, 32272967d56SGuido Günther }, 32372967d56SGuido Günther }; 32472967d56SGuido Günther module_mipi_dsi_driver(mantix_driver); 32572967d56SGuido Günther 32672967d56SGuido Günther MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); 32772967d56SGuido Günther MODULE_DESCRIPTION("DRM driver for Mantix MLAF057WE51-X MIPI DSI panel"); 32872967d56SGuido Günther MODULE_LICENSE("GPL v2"); 329