diff options
Diffstat (limited to 'drivers/gpu/drm/panel')
35 files changed, 5399 insertions, 2011 deletions
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index d7469c565d1d..721581d425b4 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -67,6 +67,15 @@ config DRM_PANEL_BOE_HIMAX8279D 24 bit RGB per pixel. It provides a MIPI DSI interface to the host and has a built-in LED backlight. +config DRM_PANEL_BOE_TD4320 + tristate "BOE TD4320 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 BOE TD4320 1080x2340 + video mode panel found in Xiaomi Redmi Note 7 smartphones. + config DRM_PANEL_BOE_TH101MB31UIG002_28A tristate "Boe TH101MB31UIG002-28A panel" depends on OF @@ -154,6 +163,17 @@ config DRM_PANEL_LVDS handling of power supplies or control signals. It implements automatic backlight handling if the panel is attached to a backlight controller. +config DRM_PANEL_HIMAX_HX8279 + tristate "Himax HX8279-based panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Himax HX8279 controller, such as the Startek KD070FHFID078 + 7.0" 1200x1920 IPS LCD panel that uses a MIPI-DSI interface + and others. + config DRM_PANEL_HIMAX_HX83102 tristate "Himax HX83102-based panels" depends on OF @@ -497,6 +517,16 @@ config DRM_PANEL_NOVATEK_NT36672E LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit RGB per pixel. +config DRM_PANEL_NOVATEK_NT37801 + tristate "Novatek NT37801/NT37810 AMOLED 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 Novatek NT37801 (or + NT37810) AMOLED DSI Video Mode LCD panel module with 1440x3200 + resolution. + config DRM_PANEL_NOVATEK_NT39016 tristate "Novatek NT39016 RGB/SPI panel" depends on OF && SPI @@ -573,6 +603,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 @@ -925,6 +965,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state. +config DRM_PANEL_SUMMIT + tristate "Apple Summit display panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for the "Summit" display panel + used as a touchbar on certain Apple laptops. + config DRM_PANEL_SYNAPTICS_R63353 tristate "Synaptics R63353-based panels" depends on OF @@ -977,6 +1026,15 @@ config DRM_PANEL_TRULY_NT35597_WQXGA Say Y here if you want to enable support for Truly NT35597 WQXGA Dual DSI Video Mode panel +config DRM_PANEL_VISIONOX_G2647FB105 + tristate "Visionox G2647FB105" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the Visionox + G2647FB105 (2340x1080@60Hz) AMOLED DSI cmd mode panel. + config DRM_PANEL_VISIONOX_R66451 tristate "Visionox R66451" depends on OF @@ -996,6 +1054,18 @@ config DRM_PANEL_VISIONOX_RM69299 Say Y here if you want to enable support for Visionox RM69299 DSI Video Mode panel. +config DRM_PANEL_VISIONOX_RM692E5 + tristate "Visionox RM692E5" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_DSC_HELPER + select DRM_DISPLAY_HELPER + help + Say Y here if you want to enable support for Visionox RM692E5 amoled + display panels, such as the one found in the Nothing Phone (1) + smartphone. + config DRM_PANEL_VISIONOX_VTDR6130 tristate "Visionox VTDR6130" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 7dcf72646cac..714cbac830e3 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596. obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.o obj-$(CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0) += panel-boe-bf060y8m-aj0.o obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o +obj-$(CONFIG_DRM_PANEL_BOE_TD4320) += panel-boe-td4320.o obj-$(CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A) += panel-boe-th101mb31ig002-28a.o obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_LL2) += panel-boe-tv101wum-ll2.o obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o @@ -16,6 +17,7 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o +obj-$(CONFIG_DRM_PANEL_HIMAX_HX8279) += panel-himax-hx8279.o obj-$(CONFIG_DRM_PANEL_HIMAX_HX83102) += panel-himax-hx83102.o obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112A) += panel-himax-hx83112a.o obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o @@ -49,6 +51,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o +obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.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 @@ -58,6 +61,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 @@ -89,6 +93,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.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_SUMMIT) += panel-summit.o obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o @@ -99,7 +104,9 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o +obj-$(CONFIG_DRM_PANEL_VISIONOX_G2647FB105) += panel-visionox-g2647fb105.o obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o +obj-$(CONFIG_DRM_PANEL_VISIONOX_RM692E5) += panel-visionox-rm692e5.o obj-$(CONFIG_DRM_PANEL_VISIONOX_VTDR6130) += panel-visionox-vtdr6130.o obj-$(CONFIG_DRM_PANEL_VISIONOX_R66451) += panel-visionox-r66451.o obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index 4692c36fe217..87fb0fd29658 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -279,9 +279,10 @@ static int y030xx067a_probe(struct spi_device *spi) struct y030xx067a *priv; int err; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_panel_alloc(dev, struct y030xx067a, panel, + &y030xx067a_funcs, DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(priv)) + return PTR_ERR(priv); priv->spi = spi; spi_set_drvdata(spi, priv); @@ -306,9 +307,6 @@ static int y030xx067a_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), "Failed to get reset GPIO\n"); - drm_panel_init(&priv->panel, dev, &y030xx067a_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&priv->panel); if (err) return err; diff --git a/drivers/gpu/drm/panel/panel-arm-versatile.c b/drivers/gpu/drm/panel/panel-arm-versatile.c index 503ecea72c5e..ea5119018df4 100644 --- a/drivers/gpu/drm/panel/panel-arm-versatile.c +++ b/drivers/gpu/drm/panel/panel-arm-versatile.c @@ -306,9 +306,11 @@ static int versatile_panel_probe(struct platform_device *pdev) return PTR_ERR(map); } - vpanel = devm_kzalloc(dev, sizeof(*vpanel), GFP_KERNEL); - if (!vpanel) - return -ENOMEM; + vpanel = devm_drm_panel_alloc(dev, struct versatile_panel, panel, + &versatile_panel_drm_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(vpanel)) + return PTR_ERR(vpanel); ret = regmap_read(map, SYS_CLCD, &val); if (ret) { @@ -348,9 +350,6 @@ static int versatile_panel_probe(struct platform_device *pdev) dev_info(dev, "panel mounted on IB2 daughterboard\n"); } - drm_panel_init(&vpanel->panel, dev, &versatile_panel_drm_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_panel_add(&vpanel->panel); return 0; diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c index b05a663c134c..db006576d704 100644 --- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c +++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c @@ -224,9 +224,11 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi) struct tm5p5_nt35596 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct tm5p5_nt35596, panel, + &tm5p5_nt35596_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->supplies[0].supply = "vdd"; ctx->supplies[1].supply = "vddio"; @@ -253,9 +255,6 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; - drm_panel_init(&ctx->panel, dev, &tm5p5_nt35596_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - ctx->panel.backlight = tm5p5_nt35596_create_backlight(dsi); if (IS_ERR(ctx->panel.backlight)) { ret = PTR_ERR(ctx->panel.backlight); diff --git a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c index 77604d6a4e72..6e52bf6830e1 100644 --- a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c +++ b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c @@ -200,9 +200,10 @@ static int a030jtn01_probe(struct spi_device *spi) spi->mode |= SPI_MODE_3 | SPI_3WIRE; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_panel_alloc(dev, struct a030jtn01, panel, + &a030jtn01_funcs, DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(priv)) + return PTR_ERR(priv); priv->spi = spi; spi_set_drvdata(spi, priv); @@ -223,9 +224,6 @@ static int a030jtn01_probe(struct spi_device *spi) if (IS_ERR(priv->reset_gpio)) return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), "Failed to get reset GPIO"); - drm_panel_init(&priv->panel, dev, &a030jtn01_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&priv->panel); if (err) return err; diff --git a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c index 7e66db4a88bb..84c21c62a43e 100644 --- a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c +++ b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c @@ -55,77 +55,56 @@ static void boe_bf060y8m_aj0_reset(struct boe_bf060y8m_aj0 *boe) static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe) { struct mipi_dsi_device *dsi = boe->dsi; - struct device *dev = &dsi->dev; - int ret; - - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE); - mipi_dsi_dcs_write_seq(dsi, 0xf8, - 0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(30); - - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc0, - 0x08, 0x48, 0x65, 0x33, 0x33, 0x33, - 0x2a, 0x31, 0x39, 0x20, 0x09); - mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f); - mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92, - 0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83, - 0x5c, 0x5c, 0x5c); - mipi_dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e); - - msleep(30); - - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } - msleep(50); - - return 0; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0xa5, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x00, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_3D_CONTROL, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf8, + 0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 30); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0xa5, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, + 0x08, 0x48, 0x65, 0x33, 0x33, 0x33, + 0x2a, 0x31, 0x39, 0x20, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92, + 0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83, + 0x5c, 0x5c, 0x5c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e); + + mipi_dsi_msleep(&dsi_ctx, 30); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); + + return dsi_ctx.accum_err; } -static int boe_bf060y8m_aj0_off(struct boe_bf060y8m_aj0 *boe) +static void boe_bf060y8m_aj0_off(struct boe_bf060y8m_aj0 *boe) { struct mipi_dsi_device *dsi = boe->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; /* OFF commands sent in HS mode */ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - usleep_range(1000, 2000); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 1000, 2000); dsi->mode_flags |= MIPI_DSI_MODE_LPM; - - return 0; } static int boe_bf060y8m_aj0_prepare(struct drm_panel *panel) { struct boe_bf060y8m_aj0 *boe = to_boe_bf060y8m_aj0(panel); - struct device *dev = &boe->dsi->dev; int ret; /* @@ -157,13 +136,14 @@ static int boe_bf060y8m_aj0_prepare(struct drm_panel *panel) ret = boe_bf060y8m_aj0_on(boe); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(boe->reset_gpio, 1); - return ret; + goto err_on; } return 0; +err_on: + regulator_disable(boe->vregs[BF060Y8M_VREG_VCI].consumer); err_vci: regulator_disable(boe->vregs[BF060Y8M_VREG_VDDIO].consumer); err_vddio: @@ -178,15 +158,11 @@ err_elvss: static int boe_bf060y8m_aj0_unprepare(struct drm_panel *panel) { struct boe_bf060y8m_aj0 *boe = to_boe_bf060y8m_aj0(panel); - struct device *dev = &boe->dsi->dev; - int ret; - ret = boe_bf060y8m_aj0_off(boe); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + boe_bf060y8m_aj0_off(boe); gpiod_set_value_cansleep(boe->reset_gpio, 1); - ret = regulator_bulk_disable(ARRAY_SIZE(boe->vregs), boe->vregs); + regulator_bulk_disable(ARRAY_SIZE(boe->vregs), boe->vregs); return 0; } @@ -234,13 +210,11 @@ static int boe_bf060y8m_aj0_bl_update_status(struct backlight_device *bl) { struct mipi_dsi_device *dsi = bl_get_data(bl); u16 brightness = backlight_get_brightness(bl); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); - if (ret < 0) - return ret; + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, brightness); - return 0; + return dsi_ctx.accum_err; } static int boe_bf060y8m_aj0_bl_get_brightness(struct backlight_device *bl) @@ -350,9 +324,11 @@ static int boe_bf060y8m_aj0_probe(struct mipi_dsi_device *dsi) struct boe_bf060y8m_aj0 *boe; int ret; - boe = devm_kzalloc(dev, sizeof(*boe), GFP_KERNEL); - if (!boe) - return -ENOMEM; + boe = devm_drm_panel_alloc(dev, struct boe_bf060y8m_aj0, panel, + &boe_bf060y8m_aj0_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(boe)) + return PTR_ERR(boe); ret = boe_bf060y8m_aj0_init_vregs(boe, dev); if (ret) @@ -374,9 +350,6 @@ static int boe_bf060y8m_aj0_probe(struct mipi_dsi_device *dsi) MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; - drm_panel_init(&boe->panel, dev, &boe_bf060y8m_aj0_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - boe->panel.prepare_prev_first = true; boe->panel.backlight = boe_bf060y8m_aj0_create_backlight(dsi); diff --git a/drivers/gpu/drm/panel/panel-boe-td4320.c b/drivers/gpu/drm/panel/panel-boe-td4320.c new file mode 100644 index 000000000000..1956daa2c71b --- /dev/null +++ b/drivers/gpu/drm/panel/panel-boe-td4320.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2024 Barnabas Czeman <barnabas.czeman@mainlining.org> +// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: +// Copyright (c) 2013, The Linux Foundation. All rights reserved. + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regulator/consumer.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_probe_helper.h> + +struct boe_td4320 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; +}; + +static const struct regulator_bulk_data boe_td4320_supplies[] = { + { .supply = "iovcc" }, + { .supply = "vsn" }, + { .supply = "vsp" }, +}; + +static inline struct boe_td4320 *to_boe_td4320(struct drm_panel *panel) +{ + return container_of(panel, struct boe_td4320, panel); +} + +static void boe_td4320_reset(struct boe_td4320 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(30); +} + +static int boe_td4320_on(struct boe_td4320 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, + 0x19, 0x55, 0x00, 0xbe, 0x00, 0x00, + 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, + 0x4d, 0x55, 0x05, 0xe6, 0x00, 0x02, + 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, + 0x9b, 0x5b, 0x07, 0xe6, 0x00, 0x13, + 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf9, + 0x44, 0x3f, 0x00, 0x8d, 0xbf); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x5d, 0x00, 0x0f, 0x1f, 0x2f, 0x3f, + 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, + 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, + 0x04, 0x00, 0x02, 0x02, 0x42, 0x01, + 0x69, 0x5a, 0x40, 0x40, 0x00, 0x00, + 0x04, 0xfa, 0x00); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00b8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, + 0x2c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x00); + mipi_dsi_msleep(&dsi_ctx, 96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int boe_td4320_off(struct boe_td4320 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + return dsi_ctx.accum_err; +} + +static int boe_td4320_prepare(struct drm_panel *panel) +{ + struct boe_td4320 *ctx = to_boe_td4320(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(boe_td4320_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + boe_td4320_reset(ctx); + + ret = boe_td4320_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(boe_td4320_supplies), ctx->supplies); + return ret; + } + + return 0; +} + +static int boe_td4320_unprepare(struct drm_panel *panel) +{ + struct boe_td4320 *ctx = to_boe_td4320(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = boe_td4320_off(ctx); + if (ret < 0) + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(boe_td4320_supplies), ctx->supplies); + + return 0; +} + +static const struct drm_display_mode boe_td4320_mode = { + .clock = (1080 + 86 + 2 + 100) * (2340 + 4 + 4 + 60) * 60 / 1000, + .hdisplay = 1080, + .hsync_start = 1080 + 86, + .hsync_end = 1080 + 86 + 2, + .htotal = 1080 + 86 + 2 + 100, + .vdisplay = 2340, + .vsync_start = 2340 + 4, + .vsync_end = 2340 + 4 + 4, + .vtotal = 2340 + 4 + 4 + 60, + .width_mm = 67, + .height_mm = 145, + .type = DRM_MODE_TYPE_DRIVER, +}; + +static int boe_td4320_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &boe_td4320_mode); +} + +static const struct drm_panel_funcs boe_td4320_panel_funcs = { + .prepare = boe_td4320_prepare, + .unprepare = boe_td4320_unprepare, + .get_modes = boe_td4320_get_modes, +}; + +static int boe_td4320_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct boe_td4320 *ctx; + int ret; + + ctx = devm_drm_panel_alloc(dev, struct boe_td4320, panel, + &boe_td4320_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(boe_td4320_supplies), + boe_td4320_supplies, + &ctx->supplies); + if (ret < 0) + return ret; + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_CLOCK_NON_CONTINUOUS; + + ctx->panel.prepare_prev_first = true; + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void boe_td4320_remove(struct mipi_dsi_device *dsi) +{ + struct boe_td4320 *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); + + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id boe_td4320_of_match[] = { + { .compatible = "boe,td4320" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, boe_td4320_of_match); + +static struct mipi_dsi_driver boe_td4320_driver = { + .probe = boe_td4320_probe, + .remove = boe_td4320_remove, + .driver = { + .name = "panel-boe-td4320", + .of_match_table = boe_td4320_of_match, + }, +}; +module_mipi_dsi_driver(boe_td4320_driver); + +MODULE_AUTHOR("Barnabas Czeman <barnabas.czeman@mainlining.org>"); +MODULE_DESCRIPTION("DRM driver for boe td4320 fhdplus video mode dsi panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c index 0b87f1e6ecae..f33d4f855929 100644 --- a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c +++ b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c @@ -349,9 +349,11 @@ static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi) const struct panel_desc *desc; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&dsi->dev, struct boe_th101mb31ig002, panel, + &boe_th101mb31ig002_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; @@ -383,9 +385,6 @@ static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi) return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n"); - drm_panel_init(&ctx->panel, &dsi->dev, &boe_th101mb31ig002_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-ll2.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-ll2.c index 50e4a5341bc6..20b6e11a7d84 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-ll2.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-ll2.c @@ -166,9 +166,11 @@ static int boe_tv101wum_ll2_probe(struct mipi_dsi_device *dsi) struct boe_tv101wum_ll2 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct boe_tv101wum_ll2, panel, + &boe_tv101wum_ll2_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ret = devm_regulator_bulk_get_const(&dsi->dev, ARRAY_SIZE(boe_tv101wum_ll2_supplies), @@ -190,8 +192,6 @@ static int boe_tv101wum_ll2_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE; - drm_panel_init(&ctx->panel, dev, &boe_tv101wum_ll2_panel_funcs, - DRM_MODE_CONNECTOR_DSI); ctx->panel.prepare_prev_first = true; ret = drm_panel_of_backlight(&ctx->panel); diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c b/drivers/gpu/drm/panel/panel-dsi-cm.c index 6b3f4d664d2a..ae6e9ffc46cb 100644 --- a/drivers/gpu/drm/panel/panel-dsi-cm.c +++ b/drivers/gpu/drm/panel/panel-dsi-cm.c @@ -511,9 +511,10 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) dev_dbg(dev, "probe\n"); - ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); - if (!ddata) - return -ENOMEM; + ddata = devm_drm_panel_alloc(dev, struct panel_drv_data, panel, + &dsicm_panel_funcs, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ddata)) + return PTR_ERR(ddata); mipi_dsi_set_drvdata(dsi, ddata); ddata->dsi = dsi; @@ -530,9 +531,6 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) dsicm_hw_reset(ddata); - drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - if (ddata->use_dsi_backlight) { struct backlight_properties props = { 0 }; props.max_brightness = 255; diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index e85d63a176d0..fb9f9f42be4f 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -57,65 +57,39 @@ static void ebbg_ft8719_reset(struct ebbg_ft8719 *ctx) static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff); - if (ret < 0) { - dev_err(dev, "Failed to set display brightness: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(90); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00ff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 90); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } static int ebbg_ft8719_off(struct ebbg_ft8719 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - usleep_range(10000, 11000); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(90); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 90); - return 0; + return dsi_ctx.accum_err; } static int ebbg_ft8719_prepare(struct drm_panel *panel) { struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -126,7 +100,6 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel) ret = ebbg_ft8719_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); return ret; } @@ -137,18 +110,10 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel) static int ebbg_ft8719_unprepare(struct drm_panel *panel) { struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - - ret = ebbg_ft8719_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + ebbg_ft8719_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 1); - - ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret) - dev_err(panel->dev, "Failed to disable regulators: %d\n", ret); + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return 0; } @@ -198,9 +163,11 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi) struct ebbg_ft8719 *ctx; int i, ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct ebbg_ft8719, panel, + &ebbg_ft8719_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) ctx->supplies[i].supply = regulator_names[i]; @@ -231,9 +198,6 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_CLOCK_NON_CONTINUOUS; - drm_panel_init(&ctx->panel, dev, &ebbg_ft8719_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return dev_err_probe(dev, ret, "Failed to get backlight\n"); diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index f8511fe5fb0d..90e8c154a978 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -839,9 +839,10 @@ static int panel_edp_probe(struct device *dev, const struct panel_desc *desc, struct device_node *ddc; int err; - panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); - if (!panel) - return -ENOMEM; + panel = devm_drm_panel_alloc(dev, struct panel_edp, base, + &panel_edp_funcs, DRM_MODE_CONNECTOR_eDP); + if (IS_ERR(panel)) + return PTR_ERR(panel); panel->prepared_time = 0; panel->desc = desc; @@ -886,8 +887,6 @@ static int panel_edp_probe(struct device *dev, const struct panel_desc *desc, dev_set_drvdata(dev, panel); - drm_panel_init(&panel->base, dev, &panel_edp_funcs, DRM_MODE_CONNECTOR_eDP); - err = drm_panel_of_backlight(&panel->base); if (err) goto err_finished_ddc_init; @@ -1763,6 +1762,13 @@ static const struct panel_delay delay_80_500_e50 = { .enable = 50, }; +static const struct panel_delay delay_80_500_e80_p2e200 = { + .hpd_absent = 80, + .unprepare = 500, + .enable = 80, + .prepare_to_enable = 200, +}; + static const struct panel_delay delay_100_500_e200 = { .hpd_absent = 100, .unprepare = 500, @@ -1808,6 +1814,20 @@ static const struct panel_delay delay_200_150_e50 = { .enable = 50, }; +static const struct panel_delay delay_200_500_e250 = { + .hpd_absent = 200, + .unprepare = 500, + .enable = 250, +}; + +static const struct panel_delay delay_50_500_e200_d200_po2e335 = { + .hpd_absent = 50, + .unprepare = 500, + .enable = 200, + .disable = 200, + .powered_on_to_enable = 335, +}; + #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ { \ .ident = { \ @@ -1862,7 +1882,9 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x73aa, &delay_200_500_e50, "B116XTN02.3"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xa199, &delay_200_500_e50, "B116XAN06.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0xa7b3, &delay_200_500_e50, "B140UAN04.4"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xc4b4, &delay_200_500_e50, "B116XAT04.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0xc9a8, &delay_200_500_e50, "B140QAN08.H"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xd497, &delay_200_500_e50, "B120XAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xf390, &delay_200_500_e50, "B140XTN07.7"), @@ -1914,6 +1936,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ae8, &delay_200_500_e50_p2e80, "NV140WUM-N41"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b09, &delay_200_500_e50_po2e200, "NV140FHM-NZ"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b34, &delay_200_500_e80, "NV122WUM-N41"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b43, &delay_200_500_e200, "NV140FHM-T09"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b56, &delay_200_500_e80, "NT140FHM-N47"), @@ -1922,6 +1945,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c93, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0cb6, &delay_200_500_e200, "NT116WHM-N44"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0cfa, &delay_200_500_e50, "NV116WHM-A4D"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0d73, &delay_200_500_e80, "NE140WUM-N6S"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x1130, &delay_200_500_e50, "N116BGE-EB2"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x1132, &delay_200_500_e80_d50, "N116BGE-EA2"), @@ -1951,9 +1975,15 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"), EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50_p2e200, "MNC207QS1-1"), + EDP_PANEL_ENTRY('C', 'S', 'O', 0x1413, &delay_200_500_e50_p2e200, "MNE007JA1-2"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1103, &delay_200_500_e80_d50, "MNB601LS1-3"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1104, &delay_200_500_e50, "MNB601LS1-4"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1448, &delay_200_500_e50, "MNE007QS3-7"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1457, &delay_80_500_e80_p2e200, "MNE007QS3-8"), + + EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "MB116AN01"), @@ -1993,6 +2023,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), EDP_PANEL_ENTRY('S', 'H', 'P', 0x1593, &delay_200_500_p2e100, "LQ134N1"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0009, &delay_200_500_e250, "116QHD024002"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), { /* sentinal */ } diff --git a/drivers/gpu/drm/panel/panel-himax-hx8279.c b/drivers/gpu/drm/panel/panel-himax-hx8279.c new file mode 100644 index 000000000000..fb302d1f91b9 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-himax-hx8279.c @@ -0,0 +1,1296 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Himax HX8279 DriverIC panels driver + * + * Copyright (c) 2025 Collabora Ltd. + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_graph.h> +#include <linux/regulator/consumer.h> + +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +/* Page selection */ +#define HX8279_REG_PAGE 0xb0 + #define HX8279_PAGE_SEL GENMASK(3, 0) + +/* Page 0 - Driver/Module Configuration */ +#define HX8279_P0_VGHS 0xbf +#define HX8279_P0_VGLS 0xc0 +#define HX8279_P0_VGPHS 0xc2 +#define HX8279_P0_VGNHS 0xc4 + #define HX8279_P0_VG_SEL GENMASK(4, 0) + #define HX8279_VGH_MIN_MV 8700 + #define HX8279_VGH_STEP_MV 300 + #define HX8279_VGL_MIN_MV 6700 + #define HX8279_VGL_STEP_MV 300 + #define HX8279_VGPNH_MIN_MV 4000 + #define HX8279_VGPNX_STEP_MV 50 + #define HX8279_VGH_VOLT_SEL(x) ((x - HX8279_VGH_MIN_MV) / HX8279_VGH_STEP_MV) + #define HX8279_VGL_VOLT_SEL(x) ((x - HX8279_VGL_MIN_MV) / HX8279_VGL_STEP_MV) + #define HX8279_VGPN_VOLT_SEL(x) ((x - HX8279_VGPNH_MIN_MV) / HX8279_VGPNX_STEP_MV) + +/* Page 1 - Gate driver On Array (GOA) Mux */ +#define HX8279_P1_REG_GOA_L 0xc0 +#define HX8279_P1_REG_GOUTL(x) (HX8279_P1_REG_GOA_L + (x)) +#define HX8279_P1_REG_GOA_R 0xd4 +#define HX8279_P1_REG_GOUTR(x) (HX8279_P1_REG_GOA_R + (x)) + #define HX8279_GOUT_STB GENMASK(7, 6) + #define HX8279_GOUT_SEL GENMASK(5, 0) + +/* Page 2 - Analog Gamma Configuration */ +#define HX8279_P2_REG_ANALOG_GAMMA 0xc0 + #define HX8279_P2_REG_GAMMA_T_PVP(x) (HX8279_P2_REG_ANALOG_GAMMA + (x)) /* 0..16 */ + #define HX8279_P2_REG_GAMMA_T_PVN(x) (HX8279_P2_REG_GAMMA_T_PVP(17) + (x)) /* 0..16 */ + +/* Page 3 - Gate driver On Array (GOA) Configuration */ +#define HX8279_P3_REG_UNKNOWN_BA 0xba +#define HX8279_P3_REG_GOA_CKV_FALL_PREC 0xbc +#define HX8279_P3_REG_GOA_TIMING_ODD 0xc2 + #define HX8279_P3_REG_GOA_TO(x) (HX8279_P3_REG_GOA_TIMING_ODD + x) /* GOA_T0..5 */ +#define HX8279_P3_REG_GOA_STVL 0xc8 + #define HX8279_P3_GOA_STV_LEAD GENMASK(4, 0) +#define HX8279_P3_REG_GOA_CKVL 0xc9 + #define HX8279_P3_GOA_CKV_LEAD GENMASK(4, 0) +#define HX8279_P3_REG_GOA_CKVD 0xca + #define HX8279_P3_GOA_CKV_NONOVERLAP BIT(7) + #define HX8279_P3_GOA_CKV_RESERVED BIT(6) + #define HX8279_P3_GOA_CKV_DUMMY GENMASK(5, 0) +#define HX8279_P3_REG_GOA_CKV_RISE_PREC 0xcb +#define HX8279_P3_REG_GOA_CLR1_W_ADJ 0xd2 +#define HX8279_P3_REG_GOA_CLR234_W_ADJ 0xd3 +#define HX8279_P3_REG_GOA_CLR1_CFG 0xd4 +#define HX8279_P3_REG_GOA_CLR_CFG(x) (HX8279_P3_REG_GOA_CLR1_CFG + (x)) /* CLR1..4 */ + #define HX8279_P3_GOA_CLR_CFG_POLARITY BIT(7) + #define HX8279_P3_GOA_CLR_CFG_STARTPOS GENMASK(6, 0) +#define HX8279_P3_REG_GOA_TIMING_EVEN 0xdd + #define HX8279_P3_REG_GOA_TE(x) (HX8279_P3_REG_GOA_TIMING_EVEN + x) +#define HX8279_P3_REG_UNKNOWN_E4 0xe4 +#define HX8279_P3_REG_UNKNOWN_E5 0xe5 + +/* Page 5 - MIPI */ +#define HX8279_P5_REG_TIMING 0xb3 + #define HX8279_P5_TIMING_THS_SETTLE GENMASK(7, 5) + #define HX8279_P5_TIMING_LHS_SETTLE BIT(4) + #define HX8279_P5_TIMING_TLPX GENMASK(3, 0) +#define HX8279_P5_REG_UNKNOWN_B8 0xb8 +#define HX8279_P5_REG_UNKNOWN_BC 0xbc +#define HX8279_P5_REG_UNKNOWN_D6 0xd6 + +/* Page 6 - Engineer */ +#define HX8279_P6_REG_ENGINEER_PWD 0xb8 +#define HX8279_P6_REG_INHOUSE_FUNC 0xc0 + #define HX8279_P6_ENG_UNLOCK_WORD 0xa5 +#define HX8279_P6_REG_GAMMA_CHOPPER 0xbc + #define HX8279_P6_GAMMA_POCGM_CTL GENMASK(6, 4) + #define HX8279_P6_GAMMA_POGCMD_CTL GENMASK(2, 0) +#define HX8279_P6_REG_VOLT_ADJ 0xc7 + /* For VCCIFS and VCCS - 0: 1450, 1: 1500, 2: 1550, 3: 1600 uV */ + #define HX8279_P6_VOLT_ADJ_VCCIFS GENMASK(3, 2) + #define HX8279_P6_VOLT_ADJ_VCCS GENMASK(1, 0) +#define HX8279_P6_REG_DLY_TIME_ADJ 0xd5 + +/* Page 7...12 - Digital Gamma Adjustment */ +#define HX8279_PG_DIGITAL_GAMMA 0xb1 +#define HX8279_DGAMMA_DGMA1_HI GENMASK(7, 6) +#define HX8279_DGAMMA_DGMA2_HI GENMASK(5, 4) +#define HX8279_DGAMMA_DGMA3_HI GENMASK(3, 2) +#define HX8279_DGAMMA_DGMA4_HI GENMASK(1, 0) +#define HX8279_PG_DGAMMA_NUM_LO_BYTES 24 +#define HX8279_PG_DGAMMA_NUM_HI_BYTES 6 + +struct hx8279 { + struct drm_panel panel; + struct mipi_dsi_device *dsi[2]; + struct regulator_bulk_data vregs[2]; + struct gpio_desc *enable_gpio; + struct gpio_desc *reset_gpio; + const struct hx8279_panel_desc *desc; + u8 last_page; + bool skip_voltage_config; + bool skip_goa_config; + bool skip_goa_timing; + bool skip_goa_even_timing; + bool skip_mipi_timing; +}; + +struct hx8279_panel_mode { + const struct drm_display_mode mode; + u8 bpc; + bool is_video_mode; +}; + +/** + * struct hx8279_goa_mux - Gate driver On Array Muxer + * @gout_l: Mux GOA signal to GOUT Left pin + * @gout_r: Mux GOA signal to GOUT Right pin + */ +struct hx8279_goa_mux { + u8 gout_l[20]; + u8 gout_r[20]; +}; + +/** + * struct hx8279_analog_gamma - Analog Gamma Adjustment + * @pos: Positive gamma op's input voltage, adjusted by VGP(H/L) + * @neg: Negative gamma op's input voltage, adjusted by VGN(H/L) + * + * Analog Gamma correction is performed with 17+17 reference voltages, + * changed with resistor streams, and defined with 17 register values + * for positive and 17 for negative. + * + * Each register holds resistance values, in 8.5ohms per unit, for the + * following gamma levels: + * 0, 8, 16, 28, 40, 56, 80, 128, 176, 200, 216, 228, 240, 248, 252, 255. + */ +struct hx8279_analog_gamma { + u8 pos[17]; + u8 neg[17]; +}; + +/** + * struct hx8279_digital_gamma - Digital Gamma Adjustment + * @r: Adjustment for red component + * @g: Adjustment for green component + * @b: Adjustment for blue component + * + * The layout of this structure follows the register layout to simplify + * both the handling and the declaration of those values in the driver. + * Gamma correction is internally done with a 24 segment piecewise + * linear interpolation; those segments are defined with 24 ten bits + * values of which: + * - The LOW eight bits for the first 24 registers start at the first + * register (at 0xb1) of the Digital Gamma Adjustment page; + * - The HIGH two bits for each of the 24 registers are contained + * in the last six registers; + * - The last six registers contain four groups of two-bits HI values + * for each of the first 24 registers, but in an inverted fashion, + * this means that the first two bits relate to the last register + * of a set of four. + * + * The 24 segments refer to the following gamma levels: + * 0, 1, 3, 7, 11, 15, 23, 31, 47, 63, 95, 127, 128, 160, + * 192, 208, 224, 232, 240, 244, 248, 252, 254, 255 + */ +struct hx8279_digital_gamma { + u8 r[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES]; + u8 g[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES]; + u8 b[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES]; +}; + +struct hx8279_panel_desc { + const struct mipi_dsi_device_info dsi_info; + const struct hx8279_panel_mode *mode_data; + u8 num_lanes; + u8 num_modes; + + /* Page 0 */ + unsigned int vgh_mv; + unsigned int vgl_mv; + unsigned int vgph_mv; + unsigned int vgnh_mv; + + /* Page 1 */ + const struct hx8279_goa_mux *gmux; + + /* Page 2 */ + const struct hx8279_analog_gamma *agamma; + + /* Page 3 */ + u8 goa_unk_ba; + u8 goa_odd_timing[6]; + u8 goa_even_timing[6]; + u8 goa_stv_lead_time_ck; + u8 goa_ckv_lead_time_ck; + u8 goa_ckv_dummy_vblank_num; + u8 goa_ckv_rise_precharge; + u8 goa_ckv_fall_precharge; + bool goa_ckv_non_overlap_ctl; + u8 goa_clr1_width_adj; + u8 goa_clr234_width_adj; + s8 goa_clr_polarity[4]; + int goa_clr_start_pos[4]; + u8 goa_unk_e4; + u8 goa_unk_e5; + + /* Page 5 */ + u8 bta_tlpx; + bool lhs_settle_time_by_osc25; + u8 ths_settle_time; + u8 timing_unk_b8; + u8 timing_unk_bc; + u8 timing_unk_d6; + + /* Page 6 */ + u8 gamma_ctl; + u8 volt_adj; + u8 src_delay_time_adj_ck; + + /* Page 7..12 */ + const struct hx8279_digital_gamma *dgamma; +}; + +static inline struct hx8279 *to_hx8279(struct drm_panel *panel) +{ + return container_of(panel, struct hx8279, panel); +} + +static void hx8279_set_page(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx, u8 page) +{ + const u8 cmd_set_page[] = { HX8279_REG_PAGE, page }; + + if (hx->last_page == page) + return; + + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_page, ARRAY_SIZE(cmd_set_page)); + if (!dsi_ctx->accum_err) + hx->last_page = page; +} + +static void hx8279_set_module_config(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_panel_desc *desc = hx->desc; + u8 cmd_set_voltage[2]; + + if (hx->skip_voltage_config) + return; + + /* Page 0 - Driver/Module Configuration */ + hx8279_set_page(hx, dsi_ctx, 0); + + if (desc->vgh_mv) { + cmd_set_voltage[0] = HX8279_P0_VGHS; + cmd_set_voltage[1] = HX8279_VGH_VOLT_SEL(desc->vgh_mv); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage, + ARRAY_SIZE(cmd_set_voltage)); + } + + if (desc->vgl_mv) { + cmd_set_voltage[0] = HX8279_P0_VGLS; + cmd_set_voltage[1] = HX8279_VGL_VOLT_SEL(desc->vgl_mv); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage, + ARRAY_SIZE(cmd_set_voltage)); + } + + if (desc->vgph_mv) { + cmd_set_voltage[0] = HX8279_P0_VGPHS; + cmd_set_voltage[1] = HX8279_VGPN_VOLT_SEL(desc->vgph_mv); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage, + ARRAY_SIZE(cmd_set_voltage)); + } + + if (desc->vgnh_mv) { + cmd_set_voltage[0] = HX8279_P0_VGNHS; + cmd_set_voltage[1] = HX8279_VGPN_VOLT_SEL(desc->vgnh_mv); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage, + ARRAY_SIZE(cmd_set_voltage)); + } +} + +static void hx8279_set_gmux(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_goa_mux *gmux = hx->desc->gmux; + u8 cmd_set_gmux[2]; + int i; + + if (!gmux) + return; + + hx8279_set_page(hx, dsi_ctx, 1); + + for (i = 0; i < ARRAY_SIZE(gmux->gout_l); i++) { + cmd_set_gmux[0] = HX8279_P1_REG_GOUTL(i); + cmd_set_gmux[1] = gmux->gout_l[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gmux, + ARRAY_SIZE(cmd_set_gmux)); + } + + for (i = 0; i < ARRAY_SIZE(gmux->gout_r); i++) { + cmd_set_gmux[0] = HX8279_P1_REG_GOUTR(i); + cmd_set_gmux[1] = gmux->gout_r[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gmux, + ARRAY_SIZE(cmd_set_gmux)); + } +} + +static void hx8279_set_analog_gamma(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_analog_gamma *agamma = hx->desc->agamma; + u8 cmd_set_ana_gamma[2]; + int i; + + if (!agamma) + return; + + hx8279_set_page(hx, dsi_ctx, 2); + + for (i = 0; i < ARRAY_SIZE(agamma->pos); i++) { + cmd_set_ana_gamma[0] = HX8279_P2_REG_GAMMA_T_PVP(i); + cmd_set_ana_gamma[1] = agamma->pos[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_ana_gamma, + ARRAY_SIZE(cmd_set_ana_gamma)); + } + + for (i = 0; i < ARRAY_SIZE(agamma->neg); i++) { + cmd_set_ana_gamma[0] = HX8279_P2_REG_GAMMA_T_PVN(i); + cmd_set_ana_gamma[1] = agamma->neg[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_ana_gamma, + ARRAY_SIZE(cmd_set_ana_gamma)); + } +} + +static void hx8279_set_goa_timing(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_panel_desc *desc = hx->desc; + u8 cmd_set_goa_t[2]; + int i; + + if (hx->skip_goa_timing) + return; + + hx8279_set_page(hx, dsi_ctx, 3); + + for (i = 0; i < ARRAY_SIZE(desc->goa_odd_timing); i++) { + cmd_set_goa_t[0] = HX8279_P3_REG_GOA_TO(i); + cmd_set_goa_t[1] = desc->goa_odd_timing[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa_t, + ARRAY_SIZE(cmd_set_goa_t)); + } + + for (i = 0; i < ARRAY_SIZE(desc->goa_even_timing); i++) { + cmd_set_goa_t[0] = HX8279_P3_REG_GOA_TE(i); + cmd_set_goa_t[1] = desc->goa_odd_timing[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa_t, + ARRAY_SIZE(cmd_set_goa_t)); + } +} + +static void hx8279_set_goa_cfg(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_panel_desc *desc = hx->desc; + u8 cmd_set_goa[2]; + int i; + + if (hx->skip_goa_config) + return; + + hx8279_set_page(hx, dsi_ctx, 3); + + if (desc->goa_unk_ba) { + cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_BA; + cmd_set_goa[1] = desc->goa_unk_ba; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_stv_lead_time_ck) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_STVL; + cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_STV_LEAD, + desc->goa_stv_lead_time_ck); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_ckv_lead_time_ck) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_CKVL; + cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CKV_DUMMY, + desc->goa_ckv_lead_time_ck); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_ckv_dummy_vblank_num) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_CKVD; + cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CKV_LEAD, + desc->goa_ckv_dummy_vblank_num); + cmd_set_goa[1] |= FIELD_PREP(HX8279_P3_GOA_CKV_NONOVERLAP, + desc->goa_ckv_non_overlap_ctl); + /* RESERVED must be always set */ + cmd_set_goa[1] |= HX8279_P3_GOA_CKV_RESERVED; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + /* + * One of the two being more than zero means that we want to write + * both of them. Anyway, the register default is zero in this case. + */ + if (desc->goa_ckv_rise_precharge || desc->goa_ckv_fall_precharge) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_CKV_RISE_PREC; + cmd_set_goa[1] = desc->goa_ckv_rise_precharge; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + + cmd_set_goa[0] = HX8279_P3_REG_GOA_CKV_FALL_PREC; + cmd_set_goa[1] = desc->goa_ckv_fall_precharge; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_clr1_width_adj) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR1_W_ADJ; + cmd_set_goa[1] = desc->goa_clr1_width_adj; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_clr234_width_adj) { + cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR234_W_ADJ; + cmd_set_goa[1] = desc->goa_clr234_width_adj; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + /* Polarity and Start Position arrays are of the same size */ + for (i = 0; i < ARRAY_SIZE(desc->goa_clr_polarity); i++) { + if (desc->goa_clr_polarity[i] < 0 || desc->goa_clr_start_pos[i] < 0) + continue; + + cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR_CFG(i); + cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CLR_CFG_STARTPOS, + desc->goa_clr_start_pos[i]); + cmd_set_goa[1] |= FIELD_PREP(HX8279_P3_GOA_CLR_CFG_POLARITY, + desc->goa_clr_polarity[i]); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + if (desc->goa_unk_e4) { + cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_E4; + cmd_set_goa[1] = desc->goa_unk_e4; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); + } + + cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_E5; + cmd_set_goa[1] = desc->goa_unk_e5; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa, + ARRAY_SIZE(cmd_set_goa)); +} + +static void hx8279_set_mipi_cfg(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_panel_desc *desc = hx->desc; + u8 cmd_set_mipi[2]; + + if (hx->skip_mipi_timing) + return; + + hx8279_set_page(hx, dsi_ctx, 5); + + if (desc->bta_tlpx || desc->ths_settle_time || desc->lhs_settle_time_by_osc25) { + cmd_set_mipi[0] = HX8279_P5_REG_TIMING; + cmd_set_mipi[1] = FIELD_PREP(HX8279_P5_TIMING_TLPX, desc->bta_tlpx); + cmd_set_mipi[1] |= FIELD_PREP(HX8279_P5_TIMING_THS_SETTLE, + desc->ths_settle_time); + cmd_set_mipi[1] |= FIELD_PREP(HX8279_P5_TIMING_LHS_SETTLE, + desc->lhs_settle_time_by_osc25); + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi, + ARRAY_SIZE(cmd_set_mipi)); + } + + if (desc->timing_unk_b8) { + cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_B8; + cmd_set_mipi[1] = desc->timing_unk_b8; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi, + ARRAY_SIZE(cmd_set_mipi)); + } + + if (desc->timing_unk_bc) { + cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_BC; + cmd_set_mipi[1] = desc->timing_unk_bc; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi, + ARRAY_SIZE(cmd_set_mipi)); + } + + if (desc->timing_unk_d6) { + cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_D6; + cmd_set_mipi[1] = desc->timing_unk_d6; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi, + ARRAY_SIZE(cmd_set_mipi)); + } +} + +static void hx8279_set_adv_cfg(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_panel_desc *desc = hx->desc; + const u8 cmd_set_dly[] = { HX8279_P6_REG_DLY_TIME_ADJ, desc->src_delay_time_adj_ck }; + const u8 cmd_set_gamma[] = { HX8279_P6_REG_GAMMA_CHOPPER, desc->gamma_ctl }; + const u8 cmd_set_volt_adj[] = { HX8279_P6_REG_VOLT_ADJ, desc->volt_adj }; + u8 cmd_set_eng[] = { HX8279_P6_REG_ENGINEER_PWD, HX8279_P6_ENG_UNLOCK_WORD }; + + if (!desc->gamma_ctl && !desc->src_delay_time_adj_ck && !desc->volt_adj) + return; + + hx8279_set_page(hx, dsi_ctx, 6); + + /* Unlock ENG settings: write same word to both ENGINEER_PWD and INHOUSE_FUNC */ + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng)); + + cmd_set_eng[0] = HX8279_P6_REG_INHOUSE_FUNC; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng)); + + /* Set Gamma Chopper and Gamma buffer Chopper control */ + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gamma, ARRAY_SIZE(cmd_set_gamma)); + + /* Set Source delay time adjustment (CKV falling to Source off) */ + if (desc->src_delay_time_adj_ck) + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dly, + ARRAY_SIZE(cmd_set_dly)); + + /* Set voltage adjustment */ + if (desc->volt_adj) + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_volt_adj, + ARRAY_SIZE(cmd_set_volt_adj)); + + /* Lock ENG settings again */ + cmd_set_eng[0] = HX8279_P6_REG_ENGINEER_PWD; + cmd_set_eng[1] = 0; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng)); + + cmd_set_eng[0] = HX8279_P6_REG_INHOUSE_FUNC; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng)); +} + +static void hx8279_set_digital_gamma(struct hx8279 *hx, + struct mipi_dsi_multi_context *dsi_ctx) +{ + const struct hx8279_digital_gamma *dgamma = hx->desc->dgamma; + u8 cmd_set_dig_gamma[2]; + int i; + + if (!dgamma) + return; + + /* + * Pages 7..9 are for RGB Positive, 10..12 are for RGB Negative: + * The first iteration sets all positive component registers, + * the second one sets all negatives. + */ + for (i = 0; i < 2; i++) { + u8 pg_neg = i * 3; + + hx8279_set_page(hx, dsi_ctx, 7 + pg_neg); + + for (i = 0; i < ARRAY_SIZE(dgamma->r); i++) { + cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i; + cmd_set_dig_gamma[1] = dgamma->r[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma, + ARRAY_SIZE(cmd_set_dig_gamma)); + } + + hx8279_set_page(hx, dsi_ctx, 8 + pg_neg); + + for (i = 0; i < ARRAY_SIZE(dgamma->g); i++) { + cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i; + cmd_set_dig_gamma[1] = dgamma->g[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma, + ARRAY_SIZE(cmd_set_dig_gamma)); + } + + hx8279_set_page(hx, dsi_ctx, 9 + pg_neg); + + for (i = 0; i < ARRAY_SIZE(dgamma->b); i++) { + cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i; + cmd_set_dig_gamma[1] = dgamma->b[i]; + mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma, + ARRAY_SIZE(cmd_set_dig_gamma)); + } + } +} + +static int hx8279_on(struct hx8279 *hx) +{ + struct mipi_dsi_device *dsi = hx->dsi[0]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + /* Page 5 */ + hx8279_set_mipi_cfg(hx, &dsi_ctx); + + /* Page 1 */ + hx8279_set_gmux(hx, &dsi_ctx); + + /* Page 2 */ + hx8279_set_analog_gamma(hx, &dsi_ctx); + + /* Page 3 */ + hx8279_set_goa_cfg(hx, &dsi_ctx); + hx8279_set_goa_timing(hx, &dsi_ctx); + + /* Page 0 - Driver/Module Configuration */ + hx8279_set_module_config(hx, &dsi_ctx); + + /* Page 6 */ + hx8279_set_adv_cfg(hx, &dsi_ctx); + + /* Pages 7..12 */ + hx8279_set_digital_gamma(hx, &dsi_ctx); + + return dsi_ctx.accum_err; +} + +static void hx8279_power_off(struct hx8279 *hx) +{ + gpiod_set_value_cansleep(hx->reset_gpio, 0); + usleep_range(100, 500); + gpiod_set_value_cansleep(hx->enable_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(hx->vregs), hx->vregs); +} + +static int hx8279_disable(struct drm_panel *panel) +{ + struct hx8279 *hx = to_hx8279(panel); + struct mipi_dsi_device *dsi = hx->dsi[0]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + + return 0; +} + +static int hx8279_enable(struct drm_panel *panel) +{ + struct hx8279 *hx = to_hx8279(panel); + struct mipi_dsi_device *dsi = hx->dsi[0]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + + return 0; +} + +static int hx8279_prepare(struct drm_panel *panel) +{ + struct hx8279 *hx = to_hx8279(panel); + struct mipi_dsi_device *dsi = hx->dsi[0]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(hx->vregs), hx->vregs); + if (ret) + return ret; + + gpiod_set_value_cansleep(hx->enable_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(hx->reset_gpio, 1); + usleep_range(6000, 7000); + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + if (hx->dsi[1]) + hx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM; + + ret = hx8279_on(hx); + if (ret) { + hx8279_power_off(hx); + return ret; + } + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 130); + + return dsi_ctx.accum_err; +} + +static int hx8279_unprepare(struct drm_panel *panel) +{ + struct hx8279 *hx = to_hx8279(panel); + struct mipi_dsi_device *dsi = hx->dsi[0]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 130); + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + if (hx->dsi[1]) + hx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; + + hx8279_power_off(hx); + + return dsi_ctx.accum_err; +} + +static int hx8279_get_modes(struct drm_panel *panel, struct drm_connector *connector) +{ + struct hx8279 *hx = to_hx8279(panel); + int i; + + for (i = 0; i < hx->desc->num_modes; i++) { + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &hx->desc->mode_data[i].mode); + if (!mode) + return -ENOMEM; + + drm_mode_set_name(mode); + + mode->type |= DRM_MODE_TYPE_DRIVER; + if (hx->desc->num_modes == 1) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + } + + connector->display_info.bpc = hx->desc->mode_data[0].bpc; + connector->display_info.height_mm = hx->desc->mode_data[0].mode.height_mm; + connector->display_info.width_mm = hx->desc->mode_data[0].mode.width_mm; + + return hx->desc->num_modes; +} + +static const struct drm_panel_funcs hx8279_panel_funcs = { + .disable = hx8279_disable, + .unprepare = hx8279_unprepare, + .prepare = hx8279_prepare, + .enable = hx8279_enable, + .get_modes = hx8279_get_modes, +}; + +static int hx8279_init_vregs(struct hx8279 *hx, struct device *dev) +{ + int ret; + + hx->vregs[0].supply = "vdd"; + hx->vregs[1].supply = "iovcc"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hx->vregs), + hx->vregs); + if (ret < 0) + return ret; + + ret = regulator_is_supported_voltage(hx->vregs[0].consumer, + 3000000, 5000000); + if (!ret) + return -EINVAL; + + ret = regulator_is_supported_voltage(hx->vregs[1].consumer, + 1700000, 1900000); + if (!ret) + return -EINVAL; + + return 0; +} + +static int hx8279_check_gmux_config(struct hx8279 *hx, struct device *dev) +{ + const struct hx8279_panel_desc *desc = hx->desc; + const struct hx8279_goa_mux *gmux = desc->gmux; + int i; + + /* No gmux defined means we simply skip the GOA mux configuration */ + if (!gmux) + return 0; + + for (i = 0; i < ARRAY_SIZE(gmux->gout_l); i++) { + if (gmux->gout_l[i] > (HX8279_GOUT_STB | HX8279_GOUT_SEL)) + return dev_err_probe(dev, -EINVAL, + "Invalid value found in gout_l[%d]\n", i); + } + + for (i = 0; i < ARRAY_SIZE(gmux->gout_r); i++) { + if (gmux->gout_r[i] > (HX8279_GOUT_STB | HX8279_GOUT_SEL)) + return dev_err_probe(dev, -EINVAL, + "Invalid value found in gout_r[%d]\n", i); + } + + return 0; +} + +static int hx8279_check_goa_config(struct hx8279 *hx, struct device *dev) +{ + const struct hx8279_panel_desc *desc = hx->desc; + bool goa_odd_valid, goa_even_valid; + int i, num_zero, num_clr = 0; + + /* Up to 4 zero values is a valid configuration. Check them all. */ + num_zero = 1; + for (i = 0; i < ARRAY_SIZE(desc->goa_odd_timing); i++) { + if (desc->goa_odd_timing[i]) + num_zero++; + } + + goa_odd_valid = (num_zero != ARRAY_SIZE(desc->goa_odd_timing)); + + /* Up to 3 zeroes is a valid config. Check them all. */ + num_zero = 1; + for (i = 0; i < ARRAY_SIZE(desc->goa_even_timing); i++) { + if (desc->goa_even_timing[i]) + num_zero++; + } + + goa_even_valid = (num_zero != ARRAY_SIZE(desc->goa_even_timing)); + + /* Programming one without the other would make no sense! */ + if (goa_odd_valid != goa_even_valid) + return -EINVAL; + + /* We know that both are either true or false now, check just one */ + if (!goa_odd_valid) + hx->skip_goa_timing = true; + + if (!desc->goa_unk_ba && !desc->goa_stv_lead_time_ck && + !desc->goa_ckv_lead_time_ck && !desc->goa_ckv_dummy_vblank_num && + !desc->goa_ckv_rise_precharge && !desc->goa_ckv_fall_precharge && + !desc->goa_clr1_width_adj && !desc->goa_clr234_width_adj && + !desc->goa_unk_e4 && !desc->goa_unk_e5) { + hx->skip_goa_config = true; + return 0; + } + + if ((desc->goa_stv_lead_time_ck > HX8279_P3_GOA_STV_LEAD) || + (desc->goa_ckv_lead_time_ck > HX8279_P3_GOA_CKV_LEAD) || + (desc->goa_ckv_dummy_vblank_num > HX8279_P3_GOA_CKV_DUMMY)) + return dev_err_probe(dev, -EINVAL, + "Invalid lead timings in GOA config\n"); + + /* + * Don't perform zero check for polarity and start position, as + * both pol=0 and start=0 are valid configuration values. + */ + for (i = 0; i < ARRAY_SIZE(desc->goa_clr_start_pos); i++) { + if (desc->goa_clr_start_pos[i] < 0) + continue; + else if (desc->goa_clr_start_pos[i] > HX8279_P3_GOA_CLR_CFG_STARTPOS) + return dev_err_probe(dev, -EINVAL, + "Invalid start position for CLR%d\n", i + 1); + else + num_clr++; + } + if (!num_clr) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(desc->goa_clr_polarity); i++) { + if (num_clr < 0) + return -EINVAL; + + if (desc->goa_clr_polarity[i] < 0) + continue; + else if (desc->goa_clr_polarity[i] > 1) + return dev_err_probe(dev, -EINVAL, + "Invalid polarity for CLR%d\n", i + 1); + else + num_clr--; + } + + return 0; +} + +static int hx8279_check_dig_gamma(struct hx8279 *hx, struct device *dev, const u8 *component) +{ + u8 gamma_high_bits[4]; + u16 prev_val = 0; + int i, j, k, x; + + /* + * The gamma values are 10 bits long and shall be incremental + * to form a digital gamma correction reference curve. + * + * As for the registers format: the first 24 bytes contain each the + * lowest 8 bits for each of the gamma level references, and the last + * 6 bytes contain the high two bits of 4 registers at a time, where + * the first two bits are relative to the last register, and the last + * two are relative to the first register. + * + * Another way of saying, those are the first four LOW values: + * DGMA1_LO = 0xb1, DGMA2_LO = 0xb2, DGMA3_LO = 0xb3, DGMA4_LO = 0xb4 + * + * The high values for those four are at DGMA1_4_HI = 0xc9; + * ...and DGMA1_4_HI's data contains the following bits: + * [1:0] = DGMA4_HI, [3:2] = DGMA3_HI, [5:4] = DGMA2_HI, [7:6] = DGMA1_HI + */ + for (i = 0; i < HX8279_PG_DGAMMA_NUM_HI_BYTES; i++) { + k = HX8279_PG_DGAMMA_NUM_LO_BYTES + i; + j = i * 4; + x = 0; + + gamma_high_bits[0] = FIELD_GET(HX8279_DGAMMA_DGMA1_HI, component[k]); + gamma_high_bits[1] = FIELD_GET(HX8279_DGAMMA_DGMA2_HI, component[k]); + gamma_high_bits[2] = FIELD_GET(HX8279_DGAMMA_DGMA3_HI, component[k]); + gamma_high_bits[3] = FIELD_GET(HX8279_DGAMMA_DGMA4_HI, component[k]); + + do { + u16 cur_val = component[j] | (gamma_high_bits[x] << 8); + + if (cur_val < prev_val) + return dev_err_probe(dev, -EINVAL, + "Invalid dgamma values: %u < %u!\n", + cur_val, prev_val); + prev_val = cur_val; + j++; + x++; + } while (x < 4); + }; + + return 0; +} + +static int hx8279_check_params(struct hx8279 *hx, struct device *dev) +{ + const struct hx8279_panel_desc *desc = hx->desc; + int ret; + + /* Voltages config validation */ + if (!desc->vgh_mv && !desc->vgl_mv && !desc->vgph_mv && !desc->vgnh_mv) + hx->skip_voltage_config = true; + else if ((desc->vgh_mv && desc->vgh_mv < HX8279_VGH_MIN_MV) || + (desc->vgl_mv && desc->vgl_mv < HX8279_VGL_MIN_MV) || + (desc->vgph_mv && desc->vgph_mv < HX8279_VGPNH_MIN_MV) || + (desc->vgnh_mv && desc->vgnh_mv < HX8279_VGPNH_MIN_MV)) + return -EINVAL; + + /* GOA Muxing validation */ + ret = hx8279_check_gmux_config(hx, dev); + if (ret) + return ret; + + /* GOA Configuration validation */ + ret = hx8279_check_goa_config(hx, dev); + if (ret) + return ret; + + /* MIPI Configuration validation */ + if (!desc->bta_tlpx && !desc->lhs_settle_time_by_osc25 && + !desc->ths_settle_time && !desc->timing_unk_b8 && + !desc->timing_unk_bc && !desc->timing_unk_d6) + hx->skip_mipi_timing = true; + + /* ENG/Gamma Configuration validation */ + if (desc->gamma_ctl > (HX8279_P6_GAMMA_POCGM_CTL | HX8279_P6_GAMMA_POGCMD_CTL)) + return -EINVAL; + + /* Digital Gamma values validation */ + if (desc->dgamma) { + ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->r); + if (ret) + return ret; + + ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->g); + if (ret) + return ret; + + ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->b); + if (ret) + return ret; + } + + return 0; +} + +static int hx8279_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct device_node *dsi_r; + struct hx8279 *hx; + int i, ret; + + hx = devm_drm_panel_alloc(dev, struct hx8279, panel, + &hx8279_panel_funcs, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(hx)) + return PTR_ERR(hx); + + ret = hx8279_init_vregs(hx, dev); + if (ret) + return ret; + + hx->desc = device_get_match_data(dev); + if (!hx->desc) + return -ENODEV; + + /* + * In some DriverICs some or all fields may be OTP: perform a + * basic configuration check before writing to help avoiding + * irreparable mistakes. + * + * Please note that this is not perfect and will only check if + * the values may be plausible; values that are wrong for a + * specific display, but still plausible for DrIC config will + * be accepted. + */ + ret = hx8279_check_params(hx, dev); + if (ret) + return dev_err_probe(dev, ret, "Invalid DriverIC configuration\n"); + + /* The enable line may be always tied to VCCIO, so this is optional */ + hx->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_ASIS); + if (IS_ERR(hx->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(hx->enable_gpio), + "Failed to get enable GPIO\n"); + + hx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); + if (IS_ERR(hx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(hx->reset_gpio), + "Failed to get reset GPIO\n"); + + /* If the panel is connected on two DSIs then DSI0 left, DSI1 right */ + dsi_r = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); + if (dsi_r) { + const struct mipi_dsi_device_info *info = &hx->desc->dsi_info; + struct mipi_dsi_host *dsi_r_host; + + dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r); + of_node_put(dsi_r); + if (!dsi_r_host) + return dev_err_probe(dev, -EPROBE_DEFER, + "Cannot get secondary DSI host\n"); + + hx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi_r_host, info); + if (IS_ERR(hx->dsi[1])) + return dev_err_probe(dev, PTR_ERR(hx->dsi[1]), + "Cannot get secondary DSI node\n"); + mipi_dsi_set_drvdata(hx->dsi[1], hx); + } + + hx->dsi[0] = dsi; + mipi_dsi_set_drvdata(dsi, hx); + + ret = drm_panel_of_backlight(&hx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&hx->panel); + + for (i = 0; i < 2; i++) { + if (!hx->dsi[i]) + continue; + + hx->dsi[i]->lanes = hx->desc->num_lanes; + hx->dsi[i]->format = MIPI_DSI_FMT_RGB888; + + hx->dsi[i]->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_LPM; + + if (hx->desc->mode_data[0].is_video_mode) + hx->dsi[i]->mode_flags |= MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + + ret = devm_mipi_dsi_attach(dev, hx->dsi[i]); + if (ret < 0) { + drm_panel_remove(&hx->panel); + return dev_err_probe(dev, ret, + "Cannot attach to DSI%d host.\n", i); + } + } + + return 0; +} + +static void hx8279_remove(struct mipi_dsi_device *dsi) +{ + struct hx8279 *hx = mipi_dsi_get_drvdata(dsi); + + drm_panel_remove(&hx->panel); +} + +static const struct hx8279_panel_mode aoly_sl101pm1794fog_v15_modes[] = { + { + .mode = { + .clock = 159420, + .hdisplay = 1200, + .hsync_start = 1200 + 80, + .hsync_end = 1200 + 80 + 60, + .htotal = 1200 + 80 + 60 + 24, + .vdisplay = 1920, + .vsync_start = 1920 + 10, + .vsync_end = 1920 + 10 + 14, + .vtotal = 1920 + 10 + 14 + 4, + .width_mm = 136, + .height_mm = 217, + .type = DRM_MODE_TYPE_DRIVER + }, + .bpc = 8, + .is_video_mode = true, + }, +}; + +static const struct hx8279_panel_mode startek_kd070fhfid078_modes[] = { + { + .mode = { + .clock = 156458, + .hdisplay = 1200, + .hsync_start = 1200 + 50, + .hsync_end = 1200 + 50 + 24, + .htotal = 1200 + 50 + 24 + 66, + .vdisplay = 1920, + .vsync_start = 1920 + 14, + .vsync_end = 1920 + 14 + 2, + .vtotal = 1920 + 14 + 2 + 10, + .width_mm = 95, + .height_mm = 151, + .type = DRM_MODE_TYPE_DRIVER + }, + .bpc = 8, + .is_video_mode = true, + }, +}; + +static const struct hx8279_goa_mux aoly_sl101pm1794fog_v15_gmux = { + .gout_l = { 0x5, 0x5, 0xb, 0xb, 0x9, 0x9, 0x16, 0x16, 0xe, 0xe, + 0x7, 0x7, 0x26, 0x26, 0x15, 0x15, 0x1, 0x1, 0x3, 0x3 }, + .gout_r = { 0x6, 0x6, 0xc, 0xc, 0xa, 0xa, 0x16, 0x16, 0xe, 0xe, + 0x8, 0x8, 0x26, 0x26, 0x15, 0x15, 0x2, 0x2, 0x4, 0x4 }, +}; + +static const struct hx8279_analog_gamma aoly_sl101pm1794fog_v15_ana_gamma = { + .pos = { 0x0, 0xd, 0x17, 0x26, 0x31, 0x1c, 0x2c, 0x33, 0x31, + 0x37, 0x37, 0x37, 0x39, 0x2e, 0x2f, 0x2f, 0x7 }, + .neg = { 0x0, 0xd, 0x17, 0x26, 0x31, 0x3f, 0x3f, 0x3f, 0x3f, + 0x37, 0x37, 0x37, 0x39, 0x2e, 0x2f, 0x2f, 0x7 }, +}; + +static const struct hx8279_digital_gamma aoly_sl101pm1794fog_v15_dig_gamma = { + .r = { 0x0, 0x5, 0x10, 0x22, 0x36, 0x4a, 0x6c, 0x9a, 0xd7, 0x17, + 0x92, 0x15, 0x18, 0x8c, 0x0, 0x3a, 0x72, 0x8c, 0xa5, 0xb1, + 0xbe, 0xca, 0xd1, 0xd4, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff }, + .g = { 0x4, 0x5, 0x11, 0x24, 0x39, 0x4e, 0x72, 0xa3, 0xe1, 0x25, + 0xa8, 0x2e, 0x32, 0xad, 0x28, 0x63, 0x9b, 0xb5, 0xcf, 0xdb, + 0xe8, 0xf5, 0xfa, 0xfc, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff }, + .b = { 0x4, 0x4, 0xf, 0x22, 0x37, 0x4d, 0x71, 0xa2, 0xe1, 0x26, + 0xa9, 0x2f, 0x33, 0xac, 0x24, 0x5d, 0x94, 0xac, 0xc5, 0xd1, + 0xdc, 0xe8, 0xed, 0xf0, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff }, +}; + +static const struct hx8279_panel_desc aoly_sl101pm1794fog_v15 = { + .dsi_info = { + .type = "L101PM1794FOG-V15", + .channel = 0, + .node = NULL, + }, + .mode_data = aoly_sl101pm1794fog_v15_modes, + .num_modes = ARRAY_SIZE(aoly_sl101pm1794fog_v15_modes), + .num_lanes = 4, + + /* Driver/Module Configuration: LC Matrix voltages */ + .vgh_mv = 16500, + .vgl_mv = 11200, + .vgph_mv = 4600, + .vgnh_mv = 4600, + + /* Analog Gamma correction */ + .agamma = &aoly_sl101pm1794fog_v15_ana_gamma, + + /* Gate driver On Array (GOA) Muxing */ + .gmux = &aoly_sl101pm1794fog_v15_gmux, + + /* Gate driver On Array (GOA) Mux Config */ + .goa_unk_ba = 0xf0, + .goa_odd_timing = { 0, 0, 0, 42, 0, 0 }, + .goa_even_timing = { 1, 42, 0, 0 }, + .goa_stv_lead_time_ck = 11, + .goa_ckv_lead_time_ck = 7, + .goa_ckv_dummy_vblank_num = 3, + .goa_ckv_rise_precharge = 1, + .goa_clr1_width_adj = 0, + .goa_clr234_width_adj = 0, + .goa_clr_polarity = { 1, 0, 0, 0 }, + .goa_clr_start_pos = { 8, 9, 3, 4 }, + .goa_unk_e4 = 0xc0, + .goa_unk_e5 = 0x0d, + + /* MIPI Configuration */ + .bta_tlpx = 2, + .lhs_settle_time_by_osc25 = true, + .ths_settle_time = 2, + .timing_unk_b8 = 0xa5, + .timing_unk_bc = 0x20, + .timing_unk_d6 = 0x7f, + + /* ENG/Gamma Configuration */ + .gamma_ctl = 0, + .volt_adj = FIELD_PREP_CONST(HX8279_P6_VOLT_ADJ_VCCIFS, 3) | + FIELD_PREP_CONST(HX8279_P6_VOLT_ADJ_VCCS, 3), + .src_delay_time_adj_ck = 50, + + /* Digital Gamma Adjustment */ + .dgamma = &aoly_sl101pm1794fog_v15_dig_gamma, +}; + +static const struct hx8279_goa_mux startek_kd070fhfid078_gmux = { + .gout_l = { 0xd, 0xd, 0x6, 0x6, 0x8, 0x8, 0xa, 0xa, 0xc, 0xc, + 0x0, 0x0, 0xe, 0xe, 0x1, 0x1, 0x4, 0x4, 0x0, 0x0 }, + .gout_r = { 0xd, 0xd, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xb, 0xb, + 0x0, 0x0, 0xe, 0xe, 0x1, 0x1, 0x3, 0x3, 0x0, 0x0 }, +}; + +static const struct hx8279_panel_desc startek_kd070fhfid078 = { + .dsi_info = { + .type = "KD070FHFID078", + .channel = 0, + .node = NULL, + }, + .mode_data = startek_kd070fhfid078_modes, + .num_modes = ARRAY_SIZE(startek_kd070fhfid078_modes), + .num_lanes = 4, + + /* Driver/Module Configuration: LC Matrix voltages */ + .vgh_mv = 18000, + .vgl_mv = 12100, + .vgph_mv = 5500, + .vgnh_mv = 5500, + + /* Gate driver On Array (GOA) Mux Config */ + .gmux = &startek_kd070fhfid078_gmux, + + /* Gate driver On Array (GOA) Configuration */ + .goa_unk_ba = 0xf0, + .goa_stv_lead_time_ck = 7, + .goa_ckv_lead_time_ck = 3, + .goa_ckv_dummy_vblank_num = 1, + .goa_ckv_rise_precharge = 0, + .goa_ckv_fall_precharge = 0, + .goa_clr1_width_adj = 1, + .goa_clr234_width_adj = 5, + .goa_clr_polarity = { 0, 1, -1, -1 }, + .goa_clr_start_pos = { 5, 10, -1, -1 }, + .goa_unk_e4 = 0xc0, + .goa_unk_e5 = 0x00, + + /* MIPI Configuration */ + .bta_tlpx = 2, + .lhs_settle_time_by_osc25 = true, + .ths_settle_time = 2, + .timing_unk_b8 = 0x7f, + .timing_unk_bc = 0x20, + .timing_unk_d6 = 0x7f, + + /* ENG/Gamma Configuration */ + .gamma_ctl = FIELD_PREP_CONST(HX8279_P6_GAMMA_POCGM_CTL, 1) | + FIELD_PREP_CONST(HX8279_P6_GAMMA_POGCMD_CTL, 1), + .src_delay_time_adj_ck = 72, +}; + +static const struct of_device_id hx8279_of_match[] = { + { .compatible = "aoly,sl101pm1794fog-v15", .data = &aoly_sl101pm1794fog_v15 }, + { .compatible = "startek,kd070fhfid078", .data = &startek_kd070fhfid078 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, hx8279_of_match); + +static struct mipi_dsi_driver hx8279_driver = { + .probe = hx8279_probe, + .remove = hx8279_remove, + .driver = { + .name = "panel-himax-hx8279", + .of_match_table = hx8279_of_match, + }, +}; +module_mipi_dsi_driver(hx8279_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); +MODULE_DESCRIPTION("Himax HX8279 DriverIC panels driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c index 3644a7544b93..66abfc44e424 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -24,6 +24,8 @@ #define HX83102_SETPOWER 0xb1 #define HX83102_SETDISP 0xb2 #define HX83102_SETCYC 0xb4 +#define HX83102_UNKNOWN_B6 0xb6 +#define HX83102_UNKNOWN_B8 0xb8 #define HX83102_SETEXTC 0xb9 #define HX83102_SETMIPI 0xba #define HX83102_SETVDC 0xbc @@ -43,6 +45,7 @@ #define HX83102_SETGIP1 0xd5 #define HX83102_SETGIP2 0xd6 #define HX83102_SETGIP3 0xd8 +#define HX83102_UNKNOWN_D9 0xd9 #define HX83102_SETGMA 0xe0 #define HX83102_UNKNOWN_E1 0xe1 #define HX83102_SETTP1 0xe7 @@ -291,6 +294,103 @@ static int boe_nv110wum_init(struct hx83102 *ctx) return dsi_ctx.accum_err; }; +static int csot_pna957qt1_1_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(60); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb3, 0xb3, 0x31, 0xf1, 0x33, + 0xe0, 0x54, 0x36, 0x36, 0x3a, 0x3a, 0x32, 0x8b, 0x11, 0xe5, + 0x98); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x8b, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x2c, + 0x80, 0x3c, 0x9f, 0x22, 0x20, 0x00, 0x00, 0x98, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x41, 0x41, 0x41, 0x41, 0x64, 0x64, + 0x40, 0x84, 0x64, 0x84, 0x01, 0x9d, 0x01, 0x02, 0x01, 0x00, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4, 0x80, 0x9c, 0x36, 0x00, + 0x0d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x32, 0x32, 0x22, 0x11, 0x22, 0xa0, + 0x31, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, + 0x36); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c, + 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x04, + 0x08, 0x04, 0x08, 0x37, 0x07, 0x44, 0x37, 0x2b, 0x2b, 0x03, + 0x03, 0x32, 0x10, 0x22, 0x00, 0x25, 0x32, 0x10, 0x29, 0x00, + 0x29, 0x32, 0x10, 0x08, 0x00, 0x08, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, + 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x18, 0x18, 0x25, 0x24, 0x25, 0x24, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1e, 0x1e, 0x1e, 0x1e, 0x20, 0x20, 0x20, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x0a, 0x0e, 0x1a, 0x21, 0x28, 0x46, + 0x5c, 0x61, 0x63, 0x5e, 0x78, 0x7d, 0x80, 0x8e, 0x89, 0x90, + 0x98, 0xaa, 0xa8, 0x52, 0x59, 0x60, 0x6f, 0x06, 0x0a, 0x16, + 0x1d, 0x24, 0x46, 0x5c, 0x61, 0x6b, 0x66, 0x7c, 0x7d, 0x80, + 0x8e, 0x89, 0x90, 0x98, 0xaa, 0xa8, 0x52, 0x59, 0x60, 0x6f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xe0, 0x10, 0x10, 0x0d, 0x1e, 0x9d, + 0x02, 0x52, 0x9d, 0x14, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x05, 0x15, 0x55, 0x45, + 0x55, 0x50, 0x05, 0x15, 0x55, 0x45, 0x55, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x24, 0x01, 0x7e, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0, + 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9d, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x66, 0x81); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x0f, 0x2a, 0xaa, 0x8a, + 0xaa, 0xf0, 0x0f, 0x2a, 0xaa, 0x8a, 0xaa, 0xf0, 0x0a, 0x2a, + 0xaa, 0x8a, 0xaa, 0xa0, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 60); + + return dsi_ctx.accum_err; +}; + static int ivo_t109nw41_init(struct hx83102 *ctx) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; @@ -396,6 +496,211 @@ static int ivo_t109nw41_init(struct hx83102 *ctx) return dsi_ctx.accum_err; }; +static int kingdisplay_kd110n11_51ie_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(50); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb3, 0xb3, 0x31, 0xf1, + 0x33, 0xe0, 0x54, 0x36, 0x36, 0x3a, 0x3a, 0x32, 0x8b, + 0x11, 0xe5, 0x98); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x8b, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x2c, + 0x80, 0x3c, 0x9f, 0x22, 0x20, 0x00, 0x00, 0x98, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x40, 0x84, 0x64, 0x84, 0x01, 0x9d, 0x01, 0x02, 0x01, 0x00, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4, 0x80, 0x9c, 0x36, 0x00, + 0x0d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x32, 0x32, 0x22, 0x11, 0x22, 0xa0, + 0x31, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, + 0x0f, 0x36); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, + 0x04, 0x2c, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x04, + 0x08, 0x04, 0x08, 0x37, 0x07, 0x44, 0x37, 0x2b, 0x2b, 0x03, + 0x03, 0x32, 0x10, 0x22, 0x00, 0x25, 0x32, 0x10, 0x29, 0x00, + 0x29, 0x32, 0x10, 0x08, 0x00, 0x08, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, + 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x18, 0x18, 0x25, 0x24, 0x25, 0x24, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1e, 0x1e, 0x1e, 0x1e, 0x20, 0x20, 0x20, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xe0, 0x10, 0x10, 0x0d, 0x1e, 0x9d, + 0x02, 0x52, 0x9d, 0x14, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x05, 0x15, 0x55, 0x45, + 0x55, 0x50, 0x05, 0x15, 0x55, 0x45, 0x55, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x24, 0x01, 0x7e, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0, + 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9d, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x66, 0x81); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x0f, 0x2a, 0xaa, 0x8a, + 0xaa, 0xf0, 0x0f, 0x2a, 0xaa, 0x8a, 0xaa, 0xf0, 0x0a, 0x2a, + 0xaa, 0x8a, 0xaa, 0xa0, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + return dsi_ctx.accum_err; +} + +static int starry_2082109qfh040022_50e_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(50); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1, 0x33, + 0xc3, 0x57, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, + 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x3c, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x22, + 0x70, 0x3c, 0xa1, 0x22, 0x00, 0x00, 0x00, 0x88, 0xf4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x14, 0x16, 0x14, 0x50, 0x14, 0x50, + 0x0d, 0x6a, 0x0d, 0x6a, 0x01, 0x9e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_B6, 0x34, 0x34, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_B8, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x38, 0x38, 0x22, 0x11, 0x33, 0xa0, + 0x61, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, + 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, + 0x2c, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3b, 0x03, 0x73, 0x3b, 0x21, 0x21, 0x03, + 0x03, 0x98, 0x10, 0x1d, 0x00, 0x1d, 0x32, 0x17, 0xa1, 0x07, + 0xa1, 0x43, 0x17, 0xa6, 0x07, 0xa6, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x40, 0x40, 0x18, 0x18, 0x18, 0x18, 0x2a, 0x2b, 0x1f, 0x1f, + 0x1e, 0x1e, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x20, 0x21, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x02, 0xaa, 0xea, 0xaa, 0xaa, 0x00, + 0x02, 0xaa, 0xea, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x2a, 0x32, 0x9f, + 0x01, 0x5a, 0x91, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x05, 0x02, 0x02, 0x10, 0x33, 0x02, 0x04, 0x18, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x00, 0x80, 0x80, 0x0c, + 0xa1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2d, 0x01, 0x7f, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x02, 0x00, 0x00, 0x10, 0x58); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x0a, 0x0a, 0x05, 0x03, 0x0a, + 0x0a, 0x01, 0x03, 0x01, 0x01, 0x05, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x03, 0x1f, 0xe0, 0x11, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xab, 0xff, 0xff, 0xff, 0xff, 0xa0, + 0xab, 0xff, 0xff, 0xff, 0xff, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9e, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xab, 0xea, 0xaa, 0xaa, 0xa0, + 0xaa, 0xab, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xbf, 0xff, 0xff, + 0xfe, 0xa0, 0xaa, 0xbf, 0xff, 0xff, 0xfe, 0xa0, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 110); + + return dsi_ctx.accum_err; +} + static const struct drm_display_mode starry_mode = { .clock = 162680, .hdisplay = 1200, @@ -440,6 +745,28 @@ static const struct hx83102_panel_desc boe_nv110wum_desc = { .init = boe_nv110wum_init, }; +static const struct drm_display_mode csot_pna957qt1_1_default_mode = { + .clock = 177958, + .hdisplay = 1200, + .hsync_start = 1200 + 124, + .hsync_end = 1200 + 124 + 80, + .htotal = 1200 + 124 + 80 + 40, + .vdisplay = 1920, + .vsync_start = 1920 + 88, + .vsync_end = 1920 + 88 + 8, + .vtotal = 1920 + 88 + 8 + 38, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc csot_pna957qt1_1_desc = { + .modes = &csot_pna957qt1_1_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = csot_pna957qt1_1_init, +}; + static const struct drm_display_mode ivo_t109nw41_default_mode = { .clock = 167700, .hdisplay = 1200, @@ -462,6 +789,50 @@ static const struct hx83102_panel_desc ivo_t109nw41_desc = { .init = ivo_t109nw41_init, }; +static const struct drm_display_mode kingdisplay_kd110n11_51ie_default_mode = { + .clock = 182750, + .hdisplay = 1200, + .hsync_start = 1200 + 124, + .hsync_end = 1200 + 124 + 80, + .htotal = 1200 + 124 + 80 + 80, + .vdisplay = 1920, + .vsync_start = 1920 + 88, + .vsync_end = 1920 + 88 + 8, + .vtotal = 1920 + 88 + 8 + 38, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc kingdisplay_kd110n11_51ie_desc = { + .modes = &kingdisplay_kd110n11_51ie_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = kingdisplay_kd110n11_51ie_init, +}; + +static const struct drm_display_mode starry_2082109qfh040022_50e_default_mode = { + .clock = 192050, + .hdisplay = 1200, + .hsync_start = 1200 + 160, + .hsync_end = 1200 + 160 + 66, + .htotal = 1200 + 160 + 66 + 120, + .vdisplay = 1920, + .vsync_start = 1920 + 115, + .vsync_end = 1920 + 115 + 8, + .vtotal = 1920 + 115 + 8 + 28, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc starry_2082109qfh040022_50e_desc = { + .modes = &starry_2082109qfh040022_50e_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = starry_2082109qfh040022_50e_init, +}; + static int hx83102_enable(struct drm_panel *panel) { msleep(130); @@ -683,9 +1054,18 @@ static const struct of_device_id hx83102_of_match[] = { { .compatible = "boe,nv110wum-l60", .data = &boe_nv110wum_desc }, + { .compatible = "csot,pna957qt1-1", + .data = &csot_pna957qt1_1_desc + }, { .compatible = "ivo,t109nw41", .data = &ivo_t109nw41_desc }, + { .compatible = "kingdisplay,kd110n11-51ie", + .data = &kingdisplay_kd110n11_51ie_desc + }, + { .compatible = "starry,2082109qfh040022-50e", + .data = &starry_2082109qfh040022_50e_desc + }, { .compatible = "starry,himax83102-j02", .data = &starry_desc }, diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c index 92b03a2f65a3..ff994bf0e3cc 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx8394.c +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -80,7 +80,7 @@ struct hx8394_panel_desc { unsigned int lanes; unsigned long mode_flags; enum mipi_dsi_pixel_format format; - int (*init_sequence)(struct hx8394 *ctx); + void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx); }; static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel) @@ -88,98 +88,94 @@ static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel) return container_of(panel, struct hx8394, panel); } -static int hsd060bhw4_init_sequence(struct hx8394 *ctx) +static void hsd060bhw4_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - /* 5.19.8 SETEXTC: Set extension command (B9h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, - 0xff, 0x83, 0x94); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC, + 0xff, 0x83, 0x94); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30); /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, - 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI, + 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); /* 5.19.3 SETDISP: Set display related register (B2h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, - 0x00, 0x80, 0x78, 0x0c, 0x07); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP, + 0x00, 0x80, 0x78, 0x0c, 0x07); /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, - 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55, - 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c, - 0x7c); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC, + 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55, + 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c, + 0x7c); /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10, - 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00, - 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00, - 0x00, 0x0c, 0x40); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10, + 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00, + 0x00, 0x0c, 0x40); /* 5.19.20 Set GIP Option1 (D5h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, - 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1, + 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); /* 5.19.21 Set GIP Option2 (D6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, - 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2, + 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, - 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f, - 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, - 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00, - 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31, - 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, - 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, - 0x4a, 0x4c, 0x4b, 0x7f); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA, + 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f, + 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, + 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00, + 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31, + 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, + 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, + 0x4a, 0x4c, 0x4b, 0x7f); /* 5.19.17 SETPANEL (CCh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, - 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL, + 0x0b); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, - 0x1f, 0x31); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1, + 0x1f, 0x31); /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, - 0x7d, 0x7d); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM, + 0x7d, 0x7d); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, - 0x02); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3, + 0x02); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x01); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x01); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x00); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x00); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, - 0xed); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3, + 0xed); } static const struct drm_display_mode hsd060bhw4_mode = { @@ -205,114 +201,110 @@ static const struct hx8394_panel_desc hsd060bhw4_desc = { .init_sequence = hsd060bhw4_init_sequence, }; -static int powkiddy_x55_init_sequence(struct hx8394 *ctx) +static void powkiddy_x55_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - /* 5.19.8 SETEXTC: Set extension command (B9h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, - 0xff, 0x83, 0x94); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC, + 0xff, 0x83, 0x94); /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, - 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI, + 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, 0x47); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, 0x47); /* 5.19.3 SETDISP: Set display related register (B2h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, - 0x00, 0x80, 0x64, 0x2c, 0x16, 0x2f); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP, + 0x00, 0x80, 0x64, 0x2c, 0x16, 0x2f); /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, - 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 0x86, 0x75, - 0x00, 0x3f, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, - 0x86); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC, + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 0x86, 0x75, + 0x00, 0x3f, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, + 0x86); /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, - 0x6e, 0x6e); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM, + 0x6e, 0x6e); /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, - 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0c, 0x00, 0x08, 0x10, - 0x08, 0x00, 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, 0x02, 0x15, - 0x06, 0x05, 0x06, 0x47, 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, - 0x07, 0x0c, 0x40); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0, + 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0c, 0x00, 0x08, 0x10, + 0x08, 0x00, 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, 0x02, 0x15, + 0x06, 0x05, 0x06, 0x47, 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, + 0x07, 0x0c, 0x40); /* 5.19.20 Set GIP Option1 (D5h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, - 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, 0x18, 0x18, - 0x26, 0x27, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21, - 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1, + 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, 0x18, 0x18, + 0x26, 0x27, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21, + 0x18, 0x18, 0x18, 0x18); /* 5.19.21 Set GIP Option2 (D6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, - 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, - 0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18, - 0x27, 0x26, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24, - 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2, + 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, + 0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18, + 0x27, 0x26, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24, + 0x18, 0x18, 0x18, 0x18); /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, - 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, - 0x65, 0x66, 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, 0x98, 0xa8, - 0xb9, 0x5d, 0x5c, 0x61, 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, - 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, 0x65, - 0x65, 0x6e, 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, 0xa8, 0xba, - 0x5d, 0x5d, 0x62, 0x67, 0x6b, 0x72, 0x7f, 0x7f); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA, + 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, + 0x65, 0x66, 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, 0x98, 0xa8, + 0xb9, 0x5d, 0x5c, 0x61, 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, + 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, 0x65, + 0x65, 0x6e, 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, 0xa8, 0xba, + 0x5d, 0x5d, 0x62, 0x67, 0x6b, 0x72, 0x7f, 0x7f); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, - 0x1f, 0x31); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1, + 0x1f, 0x31); /* 5.19.17 SETPANEL (CCh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, - 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL, + 0x0b); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, - 0x02); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3, + 0x02); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x02); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x02); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x00); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x01); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x01); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x00); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x00); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN5, - 0x40, 0x81, 0x50, 0x00, 0x1a, 0xfc, 0x01); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN5, + 0x40, 0x81, 0x50, 0x00, 0x1a, 0xfc, 0x01); /* Unknown command, not listed in the HX8394-F datasheet */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN2, - 0xed); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2, + 0xed); } static const struct drm_display_mode powkiddy_x55_mode = { @@ -339,131 +331,127 @@ static const struct hx8394_panel_desc powkiddy_x55_desc = { .init_sequence = powkiddy_x55_init_sequence, }; -static int mchp_ac40t08a_init_sequence(struct hx8394 *ctx) +static void mchp_ac40t08a_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - /* DCS commands do not seem to be sent correclty without this delay */ - msleep(20); + mipi_dsi_msleep(dsi_ctx, 20); /* 5.19.8 SETEXTC: Set extension command (B9h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, - 0xff, 0x83, 0x94); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC, + 0xff, 0x83, 0x94); /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, - 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI, + 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, - 0x71, 0x71, 0x57, 0x47); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, + 0x71, 0x71, 0x57, 0x47); /* 5.19.3 SETDISP: Set display related register (B2h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, - 0x00, 0x80, 0x64, 0x0c, 0x0d, 0x2f); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP, + 0x00, 0x80, 0x64, 0x0c, 0x0d, 0x2f); /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, - 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, - 0x01, 0x0c, 0x86, 0x75, 0x00, 0x3f, - 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, - 0x01, 0x0c, 0x86); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC, + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, + 0x01, 0x0c, 0x86, 0x75, 0x00, 0x3f, + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, + 0x01, 0x0c, 0x86); /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, - 0x6e, 0x6e); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM, + 0x6e, 0x6e); /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, - 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, - 0x0c, 0x00, 0x08, 0x10, 0x08, 0x00, - 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, - 0x02, 0x15, 0x06, 0x05, 0x06, 0x47, - 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, - 0x07, 0x0c, 0x40); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0, + 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, + 0x0c, 0x00, 0x08, 0x10, 0x08, 0x00, + 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, + 0x02, 0x15, 0x06, 0x05, 0x06, 0x47, + 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, + 0x07, 0x0c, 0x40); /* 5.19.20 Set GIP Option1 (D5h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, - 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, - 0x18, 0x18, 0x26, 0x27, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x20, 0x21, 0x18, 0x18, - 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1, + 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, + 0x18, 0x18, 0x26, 0x27, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x20, 0x21, 0x18, 0x18, + 0x18, 0x18); /* 5.19.21 Set GIP Option2 (D6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, - 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, - 0x18, 0x18, 0x27, 0x26, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x25, 0x24, 0x18, 0x18, - 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2, + 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, + 0x18, 0x18, 0x27, 0x26, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x25, 0x24, 0x18, 0x18, + 0x18, 0x18); /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, - 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, - 0x24, 0x22, 0x47, 0x56, 0x65, 0x66, - 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, - 0x98, 0xa8, 0xb9, 0x5d, 0x5c, 0x61, - 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, - 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, - 0x22, 0x47, 0x56, 0x65, 0x65, 0x6e, - 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, - 0xa8, 0xba, 0x5d, 0x5d, 0x62, 0x67, - 0x6b, 0x72, 0x7f, 0x7f); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA, + 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, + 0x24, 0x22, 0x47, 0x56, 0x65, 0x66, + 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, + 0x98, 0xa8, 0xb9, 0x5d, 0x5c, 0x61, + 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, + 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, + 0x22, 0x47, 0x56, 0x65, 0x65, 0x6e, + 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, + 0xa8, 0xba, 0x5d, 0x5d, 0x62, 0x67, + 0x6b, 0x72, 0x7f, 0x7f); /* Unknown command, not listed in the HX8394-F datasheet (C0H) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, - 0x1f, 0x73); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1, + 0x1f, 0x73); /* Set CABC control (C9h)*/ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCABC, - 0x76, 0x00, 0x30); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCABC, + 0x76, 0x00, 0x30); /* 5.19.17 SETPANEL (CCh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, - 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL, + 0x0b); /* Unknown command, not listed in the HX8394-F datasheet (D4h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, - 0x02); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3, + 0x02); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x02); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x02); /* 5.19.11 Set register bank (D8h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x00); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x01); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x01); /* 5.19.2 SETPOWER: Set power (B1h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER, + 0x00); /* 5.19.11 Set register bank (BDh) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, - 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK, + 0x00); /* Unknown command, not listed in the HX8394-F datasheet (C6h) */ - mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN2, - 0xed); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2, + 0xed); } static const struct drm_display_mode mchp_ac40t08a_mode = { @@ -493,35 +481,31 @@ static int hx8394_enable(struct drm_panel *panel) { struct hx8394 *ctx = panel_to_hx8394(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; int ret; - ret = ctx->desc->init_sequence(ctx); - if (ret) { - dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); - return ret; - } + ctx->desc->init_sequence(&dsi_ctx); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret) { - dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; /* Panel is operational 120 msec after reset */ msleep(120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret) { - dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + if (dsi_ctx.accum_err) goto sleep_in; - } return 0; sleep_in: + ret = dsi_ctx.accum_err; + dsi_ctx.accum_err = 0; + /* This will probably fail, but let's try orderly power off anyway. */ - if (!mipi_dsi_dcs_enter_sleep_mode(dsi)) - msleep(50); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); return ret; } @@ -530,17 +514,12 @@ static int hx8394_disable(struct drm_panel *panel) { struct hx8394 *ctx = panel_to_hx8394(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - int ret; - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret) { - dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - msleep(50); /* about 3 frames */ + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); /* about 3 frames */ - return 0; + return dsi_ctx.accum_err; } static int hx8394_unprepare(struct drm_panel *panel) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index 266a087fe14c..3c24a63b6be8 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -607,7 +607,7 @@ static int ili9882t_add(struct ili9882t *ili) ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ili->enable_gpio)) { - dev_err(dev, "cannot get reset-gpios %ld\n", + dev_err(dev, "cannot get enable-gpios %ld\n", PTR_ERR(ili->enable_gpio)); return PTR_ERR(ili->enable_gpio); } diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c index 7d68a8acfe2e..eb0f8373258c 100644 --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c @@ -129,11 +129,11 @@ static int jadard_unprepare(struct drm_panel *panel) { struct jadard *jadard = panel_to_jadard(panel); - gpiod_set_value(jadard->reset, 1); + gpiod_set_value(jadard->reset, 0); msleep(120); if (jadard->desc->reset_before_power_off_vcioo) { - gpiod_set_value(jadard->reset, 0); + gpiod_set_value(jadard->reset, 1); usleep_range(1000, 2000); } diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c index 5d115ecd5dd4..b6429795e8f5 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c @@ -413,15 +413,10 @@ static int panel_nv3051d_probe(struct mipi_dsi_device *dsi) static void panel_nv3051d_shutdown(struct mipi_dsi_device *dsi) { struct panel_nv3051d *ctx = mipi_dsi_get_drvdata(dsi); - int ret; - ret = drm_panel_unprepare(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); + drm_panel_unprepare(&ctx->panel); - ret = drm_panel_disable(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); + drm_panel_disable(&ctx->panel); } static void panel_nv3051d_remove(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36523.c b/drivers/gpu/drm/panel/panel-novatek-nt36523.c index 04f1d2676c78..116d67bfa114 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36523.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36523.c @@ -23,10 +23,12 @@ #define DSI_NUM_MIN 1 -#define mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, cmd, seq...) \ - do { \ - mipi_dsi_dcs_write_seq(dsi0, cmd, seq); \ - mipi_dsi_dcs_write_seq(dsi1, cmd, seq); \ +#define mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, cmd, seq...) \ + do { \ + dsi_ctx.dsi = dsi0; \ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, cmd, seq); \ + dsi_ctx.dsi = dsi1; \ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, cmd, seq); \ } while (0) struct panel_info { @@ -67,868 +69,829 @@ static int elish_boe_init_sequence(struct panel_info *pinfo) { struct mipi_dsi_device *dsi0 = pinfo->dsi[0]; struct mipi_dsi_device *dsi1 = pinfo->dsi[1]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = NULL }; /* No datasheet, so write magic init sequence directly */ - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x05); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x18, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x23); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x01, 0x84); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x05, 0x2d); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x06, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x07, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x08, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x09, 0x45); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x11, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x12, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x15, 0x83); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x16, 0x0c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29, 0x0a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x30, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x31, 0xfe); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x32, 0xfd); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x33, 0xfb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x34, 0xf8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x35, 0xf5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x36, 0xf3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x37, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x38, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x39, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3a, 0xef); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3b, 0xec); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3d, 0xe9); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3f, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x40, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x41, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2a, 0x13); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x45, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x46, 0xf4); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x47, 0xe7); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x48, 0xda); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x49, 0xcd); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4a, 0xc0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4b, 0xb3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4c, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4d, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4e, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4f, 0x99); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x50, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x68); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x52, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x53, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x54, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2b, 0x0e); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x58, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x59, 0xfb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5a, 0xf7); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5b, 0xf3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5c, 0xef); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5d, 0xe3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5e, 0xda); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5f, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x60, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x61, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x62, 0xcb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x63, 0xbf); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x64, 0xb3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x65, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x66, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x67, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x2a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x25, 0x47); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x30, 0x47); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x39, 0x47); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x26); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x19, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1a, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1b, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1c, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2a, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2b, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xf0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x84, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x85, 0x0c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x91, 0x1f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x92, 0x0f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x93, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x94, 0x18); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x95, 0x03); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x96, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb0, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x19, 0x1f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1b, 0x1b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x24); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb8, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x27); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd0, 0x31); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd1, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd2, 0x30); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd4, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xde, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xdf, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x26); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x81); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x01, 0xb0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x22); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9f, 0x50); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x6f, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x70, 0x11); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x73, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x74, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x76, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x77, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xa0, 0x3f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xa9, 0x50); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xaa, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xab, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xad, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb8, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xba, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbb, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbe, 0x04); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbf, 0x49); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc0, 0x04); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc1, 0x59); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc2, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc5, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc6, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc7, 0x48); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xca, 0x43); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xcb, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xce, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xcf, 0x43); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd0, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd3, 0x43); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd4, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd7, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xdc, 0x43); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xdd, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xe1, 0x43); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xe2, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xf2, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xf3, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xf4, 0x48); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x13, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x14, 0x23); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbc, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbd, 0x23); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x2a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x97, 0x3c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x98, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x99, 0x95); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9a, 0x03); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9b, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9c, 0x0b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9d, 0x0a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9e, 0x90); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x22); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9f, 0x50); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x23); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xa3, 0x50); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x14, 0x60); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x16, 0xc0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4f, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xf0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3a, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xd0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x02, 0xaf); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x09, 0xee); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1c, 0x99); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1d, 0x09); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x0f, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x53, 0x2c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x35, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbb, 0x13); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3b, 0x03, 0xac, 0x1a, 0x04, 0x04); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x11); - msleep(70); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29); - - return 0; + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x05); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x18, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x23); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x00, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x01, 0x84); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x05, 0x2d); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x06, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x07, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x08, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x09, 0x45); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x11, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x12, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x15, 0x83); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x16, 0x0c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x29, 0x0a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x30, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x31, 0xfe); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x32, 0xfd); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x33, 0xfb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x34, 0xf8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x35, 0xf5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x36, 0xf3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x37, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x38, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x39, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3a, 0xef); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3b, 0xec); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3d, 0xe9); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3f, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x40, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x41, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2a, 0x13); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x45, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x46, 0xf4); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x47, 0xe7); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x48, 0xda); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x49, 0xcd); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4a, 0xc0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4b, 0xb3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4c, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4d, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4e, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4f, 0x99); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x50, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x68); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x52, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x53, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x54, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2b, 0x0e); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x58, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x59, 0xfb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5a, 0xf7); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5b, 0xf3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5c, 0xef); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5d, 0xe3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5e, 0xda); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5f, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x60, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x61, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x62, 0xcb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x63, 0xbf); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x64, 0xb3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x65, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x66, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x67, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x2a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x25, 0x47); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x30, 0x47); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x39, 0x47); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x26); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x19, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1a, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1b, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1c, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2a, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2b, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xf0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x84, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x85, 0x0c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x91, 0x1f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x92, 0x0f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x93, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x94, 0x18); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x95, 0x03); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x96, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb0, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x19, 0x1f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1b, 0x1b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x24); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb8, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x27); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd0, 0x31); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd1, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd2, 0x30); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd4, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xde, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xdf, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x26); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x00, 0x81); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x01, 0xb0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x22); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9f, 0x50); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x6f, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x70, 0x11); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x73, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x74, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x76, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x77, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xa0, 0x3f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xa9, 0x50); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xaa, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xab, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xad, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb8, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xba, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbb, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbe, 0x04); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbf, 0x49); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc0, 0x04); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc1, 0x59); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc2, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc5, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc6, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc7, 0x48); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xca, 0x43); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xcb, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xce, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xcf, 0x43); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd0, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd3, 0x43); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd4, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd7, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xdc, 0x43); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xdd, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xe1, 0x43); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xe2, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xf2, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xf3, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xf4, 0x48); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x13, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x14, 0x23); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbc, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbd, 0x23); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x2a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x97, 0x3c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x98, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x99, 0x95); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9a, 0x03); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9b, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9c, 0x0b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9d, 0x0a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9e, 0x90); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x22); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9f, 0x50); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x23); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xa3, 0x50); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x14, 0x60); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x16, 0xc0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4f, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xf0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3a, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xd0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x02, 0xaf); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x09, 0xee); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1c, 0x99); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1d, 0x09); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x0f, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x53, 0x2c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x35, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbb, 0x13); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3b, 0x03, 0xac, 0x1a, 0x04, 0x04); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x11); + mipi_dsi_msleep(&dsi_ctx, 70); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x29); + + return dsi_ctx.accum_err; } static int elish_csot_init_sequence(struct panel_info *pinfo) { struct mipi_dsi_device *dsi0 = pinfo->dsi[0]; struct mipi_dsi_device *dsi1 = pinfo->dsi[1]; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = NULL }; /* No datasheet, so write magic init sequence directly */ - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x05); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x18, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xd0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x02, 0xaf); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x30); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x09, 0xee); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1c, 0x99); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1d, 0x09); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xf0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3a, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4f, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x58, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x35, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x23); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x01, 0x84); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x05, 0x2d); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x06, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x07, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x08, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x09, 0x45); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x11, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x12, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x15, 0x83); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x16, 0x0c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29, 0x0a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x30, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x31, 0xfe); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x32, 0xfd); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x33, 0xfb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x34, 0xf8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x35, 0xf5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x36, 0xf3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x37, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x38, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x39, 0xf2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3a, 0xef); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3b, 0xec); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3d, 0xe9); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3f, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x40, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x41, 0xe5); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2a, 0x13); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x45, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x46, 0xf4); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x47, 0xe7); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x48, 0xda); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x49, 0xcd); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4a, 0xc0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4b, 0xb3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4c, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4d, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4e, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x4f, 0x99); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x50, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x68); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x52, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x53, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x54, 0x66); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2b, 0x0e); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x58, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x59, 0xfb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5a, 0xf7); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5b, 0xf3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5c, 0xef); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5d, 0xe3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5e, 0xda); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x5f, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x60, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x61, 0xd8); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x62, 0xcb); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x63, 0xbf); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x64, 0xb3); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x65, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x66, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x67, 0xb2); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x0f, 0xff); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x53, 0x2c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x55, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbb, 0x13); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x3b, 0x03, 0xac, 0x1a, 0x04, 0x04); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x2a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x25, 0x46); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x30, 0x46); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x39, 0x46); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x26); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x01, 0xb0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x19, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1a, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1b, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1c, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2a, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x2b, 0xe0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0xf0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x84, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x85, 0x0c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x51, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x91, 0x1f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x92, 0x0f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x93, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x94, 0x18); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x95, 0x03); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x96, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb0, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x19, 0x1f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x1b, 0x1b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x24); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb8, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x27); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd0, 0x31); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd1, 0x20); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd4, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xde, 0x80); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xdf, 0x02); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x26); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x81); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x01, 0xb0); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x22); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x6f, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x70, 0x11); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x73, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x74, 0x4d); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xa0, 0x3f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xa9, 0x50); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xaa, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xab, 0x28); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xad, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb8, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x4b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xba, 0x96); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbb, 0x4b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbe, 0x07); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbf, 0x4b); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc0, 0x07); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc1, 0x5c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc2, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc5, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc6, 0x3f); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xc7, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xca, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xcb, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xce, 0x00); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xcf, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd0, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd3, 0x08); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xd4, 0x40); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x25); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbc, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xbd, 0x1c); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x2a); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x9a, 0x03); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x11); - msleep(70); - mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x29); - - return 0; + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x05); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x18, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xd0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x02, 0xaf); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x00, 0x30); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x09, 0xee); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1c, 0x99); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1d, 0x09); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xf0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3a, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4f, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x58, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x35, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x23); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x00, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x01, 0x84); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x05, 0x2d); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x06, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x07, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x08, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x09, 0x45); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x11, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x12, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x15, 0x83); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x16, 0x0c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x29, 0x0a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x30, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x31, 0xfe); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x32, 0xfd); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x33, 0xfb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x34, 0xf8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x35, 0xf5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x36, 0xf3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x37, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x38, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x39, 0xf2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3a, 0xef); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3b, 0xec); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3d, 0xe9); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3f, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x40, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x41, 0xe5); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2a, 0x13); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x45, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x46, 0xf4); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x47, 0xe7); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x48, 0xda); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x49, 0xcd); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4a, 0xc0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4b, 0xb3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4c, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4d, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4e, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x4f, 0x99); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x50, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x68); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x52, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x53, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x54, 0x66); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2b, 0x0e); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x58, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x59, 0xfb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5a, 0xf7); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5b, 0xf3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5c, 0xef); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5d, 0xe3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5e, 0xda); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x5f, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x60, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x61, 0xd8); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x62, 0xcb); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x63, 0xbf); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x64, 0xb3); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x65, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x66, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x67, 0xb2); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x0f, 0xff); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x53, 0x2c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x55, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbb, 0x13); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x3b, 0x03, 0xac, 0x1a, 0x04, 0x04); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x2a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x25, 0x46); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x30, 0x46); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x39, 0x46); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x26); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x01, 0xb0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x19, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1a, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1b, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1c, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2a, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x2b, 0xe0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0xf0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x84, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x85, 0x0c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x51, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x91, 0x1f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x92, 0x0f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x93, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x94, 0x18); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x95, 0x03); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x96, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb0, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x19, 0x1f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x1b, 0x1b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x24); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb8, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x27); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd0, 0x31); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd1, 0x20); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd4, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xde, 0x80); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xdf, 0x02); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x26); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x00, 0x81); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x01, 0xb0); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x22); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x6f, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x70, 0x11); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x73, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x74, 0x4d); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xa0, 0x3f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xa9, 0x50); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xaa, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xab, 0x28); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xad, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb8, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xb9, 0x4b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xba, 0x96); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbb, 0x4b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbe, 0x07); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbf, 0x4b); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc0, 0x07); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc1, 0x5c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc2, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc5, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc6, 0x3f); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xc7, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xca, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xcb, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xce, 0x00); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xcf, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd0, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd3, 0x08); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xd4, 0x40); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x25); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbc, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xbd, 0x1c); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x2a); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xfb, 0x01); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x9a, 0x03); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0xff, 0x10); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x11); + mipi_dsi_msleep(&dsi_ctx, 70); + mipi_dsi_dual_dcs_write_seq_multi(dsi_ctx, dsi0, dsi1, 0x29); + + return dsi_ctx.accum_err; } static int j606f_boe_init_sequence(struct panel_info *pinfo) { struct mipi_dsi_device *dsi = pinfo->dsi[0]; - struct device *dev = &dsi->dev; - int ret; - - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x05, 0xd9); - mipi_dsi_dcs_write_seq(dsi, 0x07, 0x78); - mipi_dsi_dcs_write_seq(dsi, 0x08, 0x5a); - mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x63); - mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x91); - mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x73); - mipi_dsi_dcs_write_seq(dsi, 0x95, 0xeb); - mipi_dsi_dcs_write_seq(dsi, 0x96, 0xeb); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x66); - mipi_dsi_dcs_write_seq(dsi, 0x75, 0xa2); - mipi_dsi_dcs_write_seq(dsi, 0x77, 0xb3); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, - 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); - mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, - 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, - 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); - mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, - 0xfd, 0x03, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, - 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); - mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, - 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, - 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); - mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, - 0xfd, 0x03, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, - 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, - 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, - 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, - 0xfd, 0x03, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, - 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); - mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, - 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, - 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); - mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, - 0xf5, 0x03, 0xf7); - mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, - 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); - mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, - 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, - 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); - mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, - 0xf5, 0x03, 0xf7); - mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, - 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, - 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); - mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, - 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, - 0xf5, 0x03, 0xf7); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x23); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0x07, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x11, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x12, 0x77); - mipi_dsi_dcs_write_seq(dsi, 0x15, 0x07); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0x07); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x01, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x02, 0x1c); - mipi_dsi_dcs_write_seq(dsi, 0x03, 0x1c); - mipi_dsi_dcs_write_seq(dsi, 0x04, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x06, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x07, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x08, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x09, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x0e); - mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x0e); - mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x0d); - mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0d); - mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x10, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x11, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x12, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x14, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x17, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x18, 0x1c); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0x1c); - mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x0e); - mipi_dsi_dcs_write_seq(dsi, 0x21, 0x0e); - mipi_dsi_dcs_write_seq(dsi, 0x22, 0x0d); - mipi_dsi_dcs_write_seq(dsi, 0x23, 0x0d); - mipi_dsi_dcs_write_seq(dsi, 0x24, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0x0c); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x27, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x28, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x0a); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x44); - mipi_dsi_dcs_write_seq(dsi, 0x33, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0x32); - mipi_dsi_dcs_write_seq(dsi, 0x37, 0x44); - mipi_dsi_dcs_write_seq(dsi, 0x38, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x9a); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0x3b, 0xa0); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x42); - mipi_dsi_dcs_write_seq(dsi, 0x3f, 0x06); - mipi_dsi_dcs_write_seq(dsi, 0x43, 0x06); - mipi_dsi_dcs_write_seq(dsi, 0x47, 0x66); - mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x9a); - mipi_dsi_dcs_write_seq(dsi, 0x4b, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x91); - mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x21); - mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x43); - - ret = mipi_dsi_dcs_set_display_brightness(dsi, 18); - if (ret < 0) { - dev_err(dev, "Failed to set display brightness: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0x52, 0x34); - mipi_dsi_dcs_write_seq(dsi, 0x55, 0x82, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0x56, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x58, 0x21); - mipi_dsi_dcs_write_seq(dsi, 0x59, 0x30); - mipi_dsi_dcs_write_seq(dsi, 0x5a, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x5b, 0xa0); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00, 0x06); - mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x65, 0x82); - mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x3c); - mipi_dsi_dcs_write_seq(dsi, 0x82, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x97, 0xc0); - mipi_dsi_dcs_write_seq(dsi, 0xb6, - 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x05, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x92, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0x93, 0x1a); - mipi_dsi_dcs_write_seq(dsi, 0x94, 0x5f); - mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x55); - mipi_dsi_dcs_write_seq(dsi, 0xda, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xde, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xdc, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe0, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe2, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xc4); - mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x88); - mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x88); - mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x90); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x05, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0x07); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0xa0); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x27, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0x33, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0x3f, 0xe0); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x44, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_GET_SCANLINE, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x48, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x49, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0xd0); - mipi_dsi_dcs_write_seq(dsi, 0x61, 0xba); - mipi_dsi_dcs_write_seq(dsi, 0x62, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0xf1, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x64, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0x67, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0x70, 0x30); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_START, 0xf3); - mipi_dsi_dcs_write_seq(dsi, 0xa3, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xa4, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xa5, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0xa1); - mipi_dsi_dcs_write_seq(dsi, 0x0a, 0xf2); - mipi_dsi_dcs_write_seq(dsi, 0x04, 0x28); - mipi_dsi_dcs_write_seq(dsi, 0x06, 0x30); - mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x11, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x12, 0x50); - mipi_dsi_dcs_write_seq(dsi, 0x13, 0x51); - mipi_dsi_dcs_write_seq(dsi, 0x14, 0x65); - mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0x17, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0x18, 0x86); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7b); - mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0x1c, 0xbb); - mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x23, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7b); - mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x1e, 0xc3); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xc3); - mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); - mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x05); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0xc3); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x32, 0xc3); - mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0xc3); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x33, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0x78); - mipi_dsi_dcs_write_seq(dsi, 0x35, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x82); - mipi_dsi_dcs_write_seq(dsi, 0xca, 0x4e); - mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_CONTINUE, 0x4c); - mipi_dsi_dcs_write_seq(dsi, 0xaa, 0x47); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x56, 0x06); - mipi_dsi_dcs_write_seq(dsi, 0x58, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0x59, 0x53); - mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x01); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0x60, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x62, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x63, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x64, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0x65, 0x1c); - mipi_dsi_dcs_write_seq(dsi, 0x66, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x67, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x68, 0x25); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x78, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x30); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2f); - mipi_dsi_dcs_write_seq(dsi, 0x23, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xf8); - mipi_dsi_dcs_write_seq(dsi, 0x27, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x28, 0x1a); - mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x1a); - mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x1a); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0xe0); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x14, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0xc0); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x08); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x5d); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x5d); - mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x91, 0x44); - mipi_dsi_dcs_write_seq(dsi, 0x92, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xdc, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe0, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x60); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x27, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x33, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x48, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x49, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x61, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x62, 0x60); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7f); - mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7f); - mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x75); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0x32, 0x8d); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x75); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x18, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x02); - - ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - if (ret < 0) { - dev_err(dev, "Failed to set tear on: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x03, 0x5f, 0x1a, 0x04, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); - usleep_range(10000, 11000); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - - ret = mipi_dsi_dcs_set_display_brightness(dsi, 0); - if (ret < 0) { - dev_err(dev, "Failed to set display brightness: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x68, 0x05, 0x01); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(100); - - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } - msleep(30); - - return 0; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x5a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x63); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x91); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x95, 0xeb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x96, 0xeb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x66); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xa2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xb3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x21); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x23); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x1d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x1d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x0d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x0d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x1d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x1d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x0d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x0d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_LUT, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00); + + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x9a); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_3D_CONTROL, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x66); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x9a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x91); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x21); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x43); + + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 18); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x82, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x21); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x82); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x3c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x97, 0xc0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, + 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x05, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x92, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x93, 0x1a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x94, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xda, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xde, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdb, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdc, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdd, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe5, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8d, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8e, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x90); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xe0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_VSYNC_TIMING, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_GET_SCANLINE, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_READ_PPS_START, 0xf3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa3, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa4, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa5, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd6, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x26); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0xa1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0xf2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x13); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x65); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0xbb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00); + + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0xc3); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc8, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc9, 0x82); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcb, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_READ_PPS_CONTINUE, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xaa, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x27); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x1d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd1, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x2f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0xc3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x1a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x1a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_LUT, 0x1a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xe0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0xc0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x08); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x5d); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x5d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x91, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x92, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdb, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdc, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdd, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe5, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8e, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x26); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x8d); + + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x75); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x02); + + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x13); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x03, 0x5f, 0x1a, 0x04, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x10); + mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, 0x01); + + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x05, 0x01); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 100); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 30); + + return dsi_ctx.accum_err; } static const struct drm_display_mode elish_boe_modes[] = { @@ -1063,18 +1026,18 @@ static int nt36523_prepare(struct drm_panel *panel) static int nt36523_disable(struct drm_panel *panel) { struct panel_info *pinfo = to_panel_info(panel); - int i, ret; + int i; for (i = 0; i < DSI_NUM_MIN + pinfo->desc->is_dual_dsi; i++) { - ret = mipi_dsi_dcs_set_display_off(pinfo->dsi[i]); - if (ret < 0) - dev_err(&pinfo->dsi[i]->dev, "failed to set display off: %d\n", ret); + struct mipi_dsi_multi_context dsi_ctx = { .dsi = pinfo->dsi[i]}; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); } for (i = 0; i < DSI_NUM_MIN + pinfo->desc->is_dual_dsi; i++) { - ret = mipi_dsi_dcs_enter_sleep_mode(pinfo->dsi[i]); - if (ret < 0) - dev_err(&pinfo->dsi[i]->dev, "failed to enter sleep mode: %d\n", ret); + struct mipi_dsi_multi_context dsi_ctx = { .dsi = pinfo->dsi[i]}; + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); } msleep(70); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt37801.c b/drivers/gpu/drm/panel/panel-novatek-nt37801.c new file mode 100644 index 000000000000..84d367eab058 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-novatek-nt37801.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2024 Linaro Limited + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> + +#include <drm/display/drm_dsc.h> +#include <drm/display/drm_dsc_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + +#include <video/mipi_display.h> + +struct novatek_nt37801 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct drm_dsc_config dsc; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data *supplies; +}; + +static const struct regulator_bulk_data novatek_nt37801_supplies[] = { + { .supply = "vddio" }, + { .supply = "vci" }, + { .supply = "vdd" }, +}; + +static inline struct novatek_nt37801 *to_novatek_nt37801(struct drm_panel *panel) +{ + return container_of(panel, struct novatek_nt37801, panel); +} + +static void novatek_nt37801_reset(struct novatek_nt37801 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 21000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(10000, 21000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 21000); +} + +#define NT37801_DCS_SWITCH_PAGE 0xf0 + +#define novatek_nt37801_switch_page(dsi_ctx, page) \ + mipi_dsi_dcs_write_seq_multi((dsi_ctx), NT37801_DCS_SWITCH_PAGE, \ + 0x55, 0xaa, 0x52, 0x08, (page)) + +static int novatek_nt37801_on(struct novatek_nt37801 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + novatek_nt37801_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc5, 0x0b, 0x0b, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf5, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x1b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf8, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x00); + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 0x059f); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 0x0c7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x03, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x91, + 0x89, 0x28, 0x00, 0x28, 0xc2, 0x00, 0x02, + 0x68, 0x04, 0x6c, 0x00, 0x0a, 0x02, 0x77, + 0x01, 0xe9, 0x10, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x23); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, + 0x00, 0x01, 0x00, 0x11, 0x33, 0x33, 0x33, + 0x55, 0x57, 0xd0, 0x00, 0x00, 0x44, 0x56, + 0x77, 0x78, 0x9a, 0xbc, 0xdd, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0xdc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x00); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x00, 0x18, 0x00, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, + 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, + 0x07, 0xff, 0x07, 0xff, 0x0f, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9c, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x00); + + novatek_nt37801_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x55, 0x01, 0xff, 0x03); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int novatek_nt37801_off(struct novatek_nt37801 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + return dsi_ctx.accum_err; +} + +static int novatek_nt37801_prepare(struct drm_panel *panel) +{ + struct novatek_nt37801 *ctx = to_novatek_nt37801(panel); + struct device *dev = &ctx->dsi->dev; + struct drm_dsc_picture_parameter_set pps; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(novatek_nt37801_supplies), + ctx->supplies); + if (ret < 0) + return ret; + + novatek_nt37801_reset(ctx); + + ret = novatek_nt37801_on(ctx); + if (ret < 0) + goto err; + + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); + + ret = mipi_dsi_picture_parameter_set(ctx->dsi, &pps); + if (ret < 0) { + dev_err(panel->dev, "failed to transmit PPS: %d\n", ret); + goto err; + } + + ret = mipi_dsi_compression_mode(ctx->dsi, true); + if (ret < 0) { + dev_err(dev, "failed to enable compression mode: %d\n", ret); + goto err; + } + + msleep(28); + + return 0; + +err: + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(novatek_nt37801_supplies), + ctx->supplies); + + return ret; +} + +static int novatek_nt37801_unprepare(struct drm_panel *panel) +{ + struct novatek_nt37801 *ctx = to_novatek_nt37801(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = novatek_nt37801_off(ctx); + if (ret < 0) + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + + regulator_bulk_disable(ARRAY_SIZE(novatek_nt37801_supplies), + ctx->supplies); + + return 0; +} + +static const struct drm_display_mode novatek_nt37801_mode = { + .clock = (1440 + 20 + 4 + 20) * (3200 + 20 + 2 + 18) * 120 / 1000, + .hdisplay = 1440, + .hsync_start = 1440 + 20, + .hsync_end = 1440 + 20 + 4, + .htotal = 1440 + 20 + 4 + 20, + .vdisplay = 3200, + .vsync_start = 3200 + 20, + .vsync_end = 3200 + 20 + 2, + .vtotal = 3200 + 20 + 2 + 18, + .type = DRM_MODE_TYPE_DRIVER, +}; + +static int novatek_nt37801_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, + &novatek_nt37801_mode); +} + +static const struct drm_panel_funcs novatek_nt37801_panel_funcs = { + .prepare = novatek_nt37801_prepare, + .unprepare = novatek_nt37801_unprepare, + .get_modes = novatek_nt37801_get_modes, +}; + +static int novatek_nt37801_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + return 0; +} + +static const struct backlight_ops novatek_nt37801_bl_ops = { + .update_status = novatek_nt37801_bl_update_status, +}; + +static struct backlight_device * +novatek_nt37801_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 4095, + .max_brightness = 4095, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &novatek_nt37801_bl_ops, &props); +} + +static int novatek_nt37801_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct novatek_nt37801 *ctx; + int ret; + + ctx = devm_drm_panel_alloc(dev, struct novatek_nt37801, panel, + &novatek_nt37801_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (!ctx) + return -ENOMEM; + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(novatek_nt37801_supplies), + novatek_nt37801_supplies, + &ctx->supplies); + if (ret < 0) + return ret; + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_CLOCK_NON_CONTINUOUS; + + ctx->panel.prepare_prev_first = true; + ctx->panel.backlight = novatek_nt37801_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "Failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + /* This panel only supports DSC; unconditionally enable it */ + dsi->dsc = &ctx->dsc; + ctx->dsc.dsc_version_major = 1; + ctx->dsc.dsc_version_minor = 1; + ctx->dsc.slice_height = 40; + ctx->dsc.slice_width = 720; + ctx->dsc.slice_count = 1440 / ctx->dsc.slice_width; + ctx->dsc.bits_per_component = 8; + ctx->dsc.bits_per_pixel = 8 << 4; /* 4 fractional bits */ + ctx->dsc.block_pred_enable = true; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void novatek_nt37801_remove(struct mipi_dsi_device *dsi) +{ + struct novatek_nt37801 *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); + + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id novatek_nt37801_of_match[] = { + { .compatible = "novatek,nt37801" }, + {} +}; +MODULE_DEVICE_TABLE(of, novatek_nt37801_of_match); + +static struct mipi_dsi_driver novatek_nt37801_driver = { + .probe = novatek_nt37801_probe, + .remove = novatek_nt37801_remove, + .driver = { + .name = "panel-novatek-nt37801", + .of_match_table = novatek_nt37801_of_match, + }, +}; +module_mipi_dsi_driver(novatek_nt37801_driver); + +MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>"); +MODULE_DESCRIPTION("Panel driver for the Novatek NT37801/NT37810 AMOLED DSI panel"); +MODULE_LICENSE("GPL"); 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 000000000000..64b685dc11f6 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-raydium-rm67200.c @@ -0,0 +1,499 @@ +// 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); + raydium_rm67200_write(ctx, 0x04, 0x00); + raydium_rm67200_write(ctx, 0x00, 0x64); + raydium_rm67200_write(ctx, 0x2a, 0x00); + raydium_rm67200_write(ctx, 0x26, 0x64); + raydium_rm67200_write(ctx, 0x54, 0x00); + raydium_rm67200_write(ctx, 0x50, 0x64); + raydium_rm67200_write(ctx, 0x7b, 0x00); + raydium_rm67200_write(ctx, 0x77, 0x64); + raydium_rm67200_write(ctx, 0xa2, 0x00); + raydium_rm67200_write(ctx, 0x9d, 0x64); + raydium_rm67200_write(ctx, 0xc9, 0x00); + raydium_rm67200_write(ctx, 0xc5, 0x64); + raydium_rm67200_write(ctx, 0x01, 0x71); + raydium_rm67200_write(ctx, 0x27, 0x71); + raydium_rm67200_write(ctx, 0x51, 0x71); + raydium_rm67200_write(ctx, 0x78, 0x71); + raydium_rm67200_write(ctx, 0x9e, 0x71); + raydium_rm67200_write(ctx, 0xc6, 0x71); + raydium_rm67200_write(ctx, 0x02, 0x89); + raydium_rm67200_write(ctx, 0x28, 0x89); + raydium_rm67200_write(ctx, 0x52, 0x89); + raydium_rm67200_write(ctx, 0x79, 0x89); + raydium_rm67200_write(ctx, 0x9f, 0x89); + raydium_rm67200_write(ctx, 0xc7, 0x89); + raydium_rm67200_write(ctx, 0x03, 0x9e); + raydium_rm67200_write(ctx, 0x29, 0x9e); + raydium_rm67200_write(ctx, 0x53, 0x9e); + raydium_rm67200_write(ctx, 0x7a, 0x9e); + raydium_rm67200_write(ctx, 0xa0, 0x9e); + raydium_rm67200_write(ctx, 0xc8, 0x9e); + raydium_rm67200_write(ctx, 0x09, 0x00); + raydium_rm67200_write(ctx, 0x05, 0xb0); + raydium_rm67200_write(ctx, 0x31, 0x00); + raydium_rm67200_write(ctx, 0x2b, 0xb0); + raydium_rm67200_write(ctx, 0x5a, 0x00); + raydium_rm67200_write(ctx, 0x55, 0xb0); + raydium_rm67200_write(ctx, 0x80, 0x00); + raydium_rm67200_write(ctx, 0x7c, 0xb0); + raydium_rm67200_write(ctx, 0xa7, 0x00); + raydium_rm67200_write(ctx, 0xa3, 0xb0); + raydium_rm67200_write(ctx, 0xce, 0x00); + raydium_rm67200_write(ctx, 0xca, 0xb0); + raydium_rm67200_write(ctx, 0x06, 0xc0); + raydium_rm67200_write(ctx, 0x2d, 0xc0); + raydium_rm67200_write(ctx, 0x56, 0xc0); + raydium_rm67200_write(ctx, 0x7d, 0xc0); + raydium_rm67200_write(ctx, 0xa4, 0xc0); + raydium_rm67200_write(ctx, 0xcb, 0xc0); + raydium_rm67200_write(ctx, 0x07, 0xcf); + raydium_rm67200_write(ctx, 0x2f, 0xcf); + raydium_rm67200_write(ctx, 0x58, 0xcf); + raydium_rm67200_write(ctx, 0x7e, 0xcf); + raydium_rm67200_write(ctx, 0xa5, 0xcf); + raydium_rm67200_write(ctx, 0xcc, 0xcf); + raydium_rm67200_write(ctx, 0x08, 0xdd); + raydium_rm67200_write(ctx, 0x30, 0xdd); + raydium_rm67200_write(ctx, 0x59, 0xdd); + raydium_rm67200_write(ctx, 0x7f, 0xdd); + raydium_rm67200_write(ctx, 0xa6, 0xdd); + raydium_rm67200_write(ctx, 0xcd, 0xdd); + raydium_rm67200_write(ctx, 0x0e, 0x15); + raydium_rm67200_write(ctx, 0x0a, 0xe9); + raydium_rm67200_write(ctx, 0x36, 0x15); + raydium_rm67200_write(ctx, 0x32, 0xe9); + raydium_rm67200_write(ctx, 0x5f, 0x15); + raydium_rm67200_write(ctx, 0x5b, 0xe9); + raydium_rm67200_write(ctx, 0x85, 0x15); + raydium_rm67200_write(ctx, 0x81, 0xe9); + raydium_rm67200_write(ctx, 0xad, 0x15); + raydium_rm67200_write(ctx, 0xa9, 0xe9); + raydium_rm67200_write(ctx, 0xd3, 0x15); + raydium_rm67200_write(ctx, 0xcf, 0xe9); + raydium_rm67200_write(ctx, 0x0b, 0x14); + raydium_rm67200_write(ctx, 0x33, 0x14); + raydium_rm67200_write(ctx, 0x5c, 0x14); + raydium_rm67200_write(ctx, 0x82, 0x14); + raydium_rm67200_write(ctx, 0xaa, 0x14); + raydium_rm67200_write(ctx, 0xd0, 0x14); + raydium_rm67200_write(ctx, 0x0c, 0x36); + raydium_rm67200_write(ctx, 0x34, 0x36); + raydium_rm67200_write(ctx, 0x5d, 0x36); + raydium_rm67200_write(ctx, 0x83, 0x36); + raydium_rm67200_write(ctx, 0xab, 0x36); + raydium_rm67200_write(ctx, 0xd1, 0x36); + raydium_rm67200_write(ctx, 0x0d, 0x6b); + raydium_rm67200_write(ctx, 0x35, 0x6b); + raydium_rm67200_write(ctx, 0x5e, 0x6b); + raydium_rm67200_write(ctx, 0x84, 0x6b); + raydium_rm67200_write(ctx, 0xac, 0x6b); + raydium_rm67200_write(ctx, 0xd2, 0x6b); + raydium_rm67200_write(ctx, 0x13, 0x5a); + raydium_rm67200_write(ctx, 0x0f, 0x94); + raydium_rm67200_write(ctx, 0x3b, 0x5a); + raydium_rm67200_write(ctx, 0x37, 0x94); + raydium_rm67200_write(ctx, 0x64, 0x5a); + raydium_rm67200_write(ctx, 0x60, 0x94); + raydium_rm67200_write(ctx, 0x8a, 0x5a); + raydium_rm67200_write(ctx, 0x86, 0x94); + raydium_rm67200_write(ctx, 0xb2, 0x5a); + raydium_rm67200_write(ctx, 0xae, 0x94); + raydium_rm67200_write(ctx, 0xd8, 0x5a); + raydium_rm67200_write(ctx, 0xd4, 0x94); + raydium_rm67200_write(ctx, 0x10, 0xd1); + raydium_rm67200_write(ctx, 0x38, 0xd1); + raydium_rm67200_write(ctx, 0x61, 0xd1); + raydium_rm67200_write(ctx, 0x87, 0xd1); + raydium_rm67200_write(ctx, 0xaf, 0xd1); + raydium_rm67200_write(ctx, 0xd5, 0xd1); + raydium_rm67200_write(ctx, 0x11, 0x04); + raydium_rm67200_write(ctx, 0x39, 0x04); + raydium_rm67200_write(ctx, 0x62, 0x04); + raydium_rm67200_write(ctx, 0x88, 0x04); + raydium_rm67200_write(ctx, 0xb0, 0x04); + raydium_rm67200_write(ctx, 0xd6, 0x04); + raydium_rm67200_write(ctx, 0x12, 0x05); + raydium_rm67200_write(ctx, 0x3a, 0x05); + raydium_rm67200_write(ctx, 0x63, 0x05); + raydium_rm67200_write(ctx, 0x89, 0x05); + raydium_rm67200_write(ctx, 0xb1, 0x05); + raydium_rm67200_write(ctx, 0xd7, 0x05); + raydium_rm67200_write(ctx, 0x18, 0xaa); + raydium_rm67200_write(ctx, 0x14, 0x36); + raydium_rm67200_write(ctx, 0x42, 0xaa); + raydium_rm67200_write(ctx, 0x3d, 0x36); + raydium_rm67200_write(ctx, 0x69, 0xaa); + raydium_rm67200_write(ctx, 0x65, 0x36); + raydium_rm67200_write(ctx, 0x8f, 0xaa); + raydium_rm67200_write(ctx, 0x8b, 0x36); + raydium_rm67200_write(ctx, 0xb7, 0xaa); + raydium_rm67200_write(ctx, 0xb3, 0x36); + raydium_rm67200_write(ctx, 0xdd, 0xaa); + raydium_rm67200_write(ctx, 0xd9, 0x36); + raydium_rm67200_write(ctx, 0x15, 0x74); + raydium_rm67200_write(ctx, 0x3f, 0x74); + raydium_rm67200_write(ctx, 0x66, 0x74); + raydium_rm67200_write(ctx, 0x8c, 0x74); + raydium_rm67200_write(ctx, 0xb4, 0x74); + raydium_rm67200_write(ctx, 0xda, 0x74); + raydium_rm67200_write(ctx, 0x16, 0x9f); + raydium_rm67200_write(ctx, 0x40, 0x9f); + raydium_rm67200_write(ctx, 0x67, 0x9f); + raydium_rm67200_write(ctx, 0x8d, 0x9f); + raydium_rm67200_write(ctx, 0xb5, 0x9f); + raydium_rm67200_write(ctx, 0xdb, 0x9f); + raydium_rm67200_write(ctx, 0x17, 0xdc); + raydium_rm67200_write(ctx, 0x41, 0xdc); + raydium_rm67200_write(ctx, 0x68, 0xdc); + raydium_rm67200_write(ctx, 0x8e, 0xdc); + raydium_rm67200_write(ctx, 0xb6, 0xdc); + raydium_rm67200_write(ctx, 0xdc, 0xdc); + raydium_rm67200_write(ctx, 0x1d, 0xff); + raydium_rm67200_write(ctx, 0x19, 0x03); + raydium_rm67200_write(ctx, 0x47, 0xff); + raydium_rm67200_write(ctx, 0x43, 0x03); + raydium_rm67200_write(ctx, 0x6e, 0xff); + raydium_rm67200_write(ctx, 0x6a, 0x03); + raydium_rm67200_write(ctx, 0x94, 0xff); + raydium_rm67200_write(ctx, 0x90, 0x03); + raydium_rm67200_write(ctx, 0xbc, 0xff); + raydium_rm67200_write(ctx, 0xb8, 0x03); + raydium_rm67200_write(ctx, 0xe2, 0xff); + raydium_rm67200_write(ctx, 0xde, 0x03); + raydium_rm67200_write(ctx, 0x1a, 0x35); + raydium_rm67200_write(ctx, 0x44, 0x35); + raydium_rm67200_write(ctx, 0x6b, 0x35); + raydium_rm67200_write(ctx, 0x91, 0x35); + raydium_rm67200_write(ctx, 0xb9, 0x35); + raydium_rm67200_write(ctx, 0xdf, 0x35); + raydium_rm67200_write(ctx, 0x1b, 0x45); + raydium_rm67200_write(ctx, 0x45, 0x45); + raydium_rm67200_write(ctx, 0x6c, 0x45); + raydium_rm67200_write(ctx, 0x92, 0x45); + raydium_rm67200_write(ctx, 0xba, 0x45); + raydium_rm67200_write(ctx, 0xe0, 0x45); + raydium_rm67200_write(ctx, 0x1c, 0x55); + raydium_rm67200_write(ctx, 0x46, 0x55); + raydium_rm67200_write(ctx, 0x6d, 0x55); + raydium_rm67200_write(ctx, 0x93, 0x55); + raydium_rm67200_write(ctx, 0xbb, 0x55); + raydium_rm67200_write(ctx, 0xe1, 0x55); + raydium_rm67200_write(ctx, 0x22, 0xff); + raydium_rm67200_write(ctx, 0x1e, 0x68); + raydium_rm67200_write(ctx, 0x4c, 0xff); + raydium_rm67200_write(ctx, 0x48, 0x68); + raydium_rm67200_write(ctx, 0x73, 0xff); + raydium_rm67200_write(ctx, 0x6f, 0x68); + raydium_rm67200_write(ctx, 0x99, 0xff); + raydium_rm67200_write(ctx, 0x95, 0x68); + raydium_rm67200_write(ctx, 0xc1, 0xff); + raydium_rm67200_write(ctx, 0xbd, 0x68); + raydium_rm67200_write(ctx, 0xe7, 0xff); + raydium_rm67200_write(ctx, 0xe3, 0x68); + raydium_rm67200_write(ctx, 0x1f, 0x7e); + raydium_rm67200_write(ctx, 0x49, 0x7e); + raydium_rm67200_write(ctx, 0x70, 0x7e); + raydium_rm67200_write(ctx, 0x96, 0x7e); + raydium_rm67200_write(ctx, 0xbe, 0x7e); + raydium_rm67200_write(ctx, 0xe4, 0x7e); + raydium_rm67200_write(ctx, 0x20, 0x97); + raydium_rm67200_write(ctx, 0x4a, 0x97); + raydium_rm67200_write(ctx, 0x71, 0x97); + raydium_rm67200_write(ctx, 0x97, 0x97); + raydium_rm67200_write(ctx, 0xbf, 0x97); + raydium_rm67200_write(ctx, 0xe5, 0x97); + raydium_rm67200_write(ctx, 0x21, 0xb5); + raydium_rm67200_write(ctx, 0x4b, 0xb5); + raydium_rm67200_write(ctx, 0x72, 0xb5); + raydium_rm67200_write(ctx, 0x98, 0xb5); + raydium_rm67200_write(ctx, 0xc0, 0xb5); + raydium_rm67200_write(ctx, 0xe6, 0xb5); + raydium_rm67200_write(ctx, 0x25, 0xf0); + raydium_rm67200_write(ctx, 0x23, 0xe8); + raydium_rm67200_write(ctx, 0x4f, 0xf0); + raydium_rm67200_write(ctx, 0x4d, 0xe8); + raydium_rm67200_write(ctx, 0x76, 0xf0); + raydium_rm67200_write(ctx, 0x74, 0xe8); + raydium_rm67200_write(ctx, 0x9c, 0xf0); + raydium_rm67200_write(ctx, 0x9a, 0xe8); + raydium_rm67200_write(ctx, 0xc4, 0xf0); + raydium_rm67200_write(ctx, 0xc2, 0xe8); + raydium_rm67200_write(ctx, 0xea, 0xf0); + raydium_rm67200_write(ctx, 0xe8, 0xe8); + raydium_rm67200_write(ctx, 0x24, 0xff); + raydium_rm67200_write(ctx, 0x4e, 0xff); + raydium_rm67200_write(ctx, 0x75, 0xff); + raydium_rm67200_write(ctx, 0x9b, 0xff); + raydium_rm67200_write(ctx, 0xc3, 0xff); + raydium_rm67200_write(ctx, 0xe9, 0xff); + raydium_rm67200_write(ctx, 0xfe, 0x3d); + raydium_rm67200_write(ctx, 0x00, 0x04); + raydium_rm67200_write(ctx, 0xfe, 0x23); + raydium_rm67200_write(ctx, 0x08, 0x82); + raydium_rm67200_write(ctx, 0x0a, 0x00); + raydium_rm67200_write(ctx, 0x0b, 0x00); + raydium_rm67200_write(ctx, 0x0c, 0x01); + raydium_rm67200_write(ctx, 0x16, 0x00); + raydium_rm67200_write(ctx, 0x18, 0x02); + raydium_rm67200_write(ctx, 0x1b, 0x04); + raydium_rm67200_write(ctx, 0x19, 0x04); + raydium_rm67200_write(ctx, 0x1c, 0x81); + raydium_rm67200_write(ctx, 0x1f, 0x00); + raydium_rm67200_write(ctx, 0x20, 0x03); + raydium_rm67200_write(ctx, 0x23, 0x04); + raydium_rm67200_write(ctx, 0x21, 0x01); + raydium_rm67200_write(ctx, 0x54, 0x63); + raydium_rm67200_write(ctx, 0x55, 0x54); + raydium_rm67200_write(ctx, 0x6e, 0x45); + raydium_rm67200_write(ctx, 0x6d, 0x36); + raydium_rm67200_write(ctx, 0xfe, 0x3d); + raydium_rm67200_write(ctx, 0x55, 0x78); + raydium_rm67200_write(ctx, 0xfe, 0x20); + raydium_rm67200_write(ctx, 0x26, 0x30); + raydium_rm67200_write(ctx, 0xfe, 0x3d); + raydium_rm67200_write(ctx, 0x20, 0x71); + raydium_rm67200_write(ctx, 0x50, 0x8f); + raydium_rm67200_write(ctx, 0x51, 0x8f); + raydium_rm67200_write(ctx, 0xfe, 0x00); + raydium_rm67200_write(ctx, 0x35, 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); + + 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); + mipi_dsi_msleep(&ctx, 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); + + return drm_connector_helper_get_modes_fixed(connector, &ctx->panel_info->mode); +} + +static const struct drm_panel_funcs raydium_rm67200_funcs = { + .prepare = raydium_rm67200_prepare, + .unprepare = raydium_rm67200_unprepare, + .get_modes = raydium_rm67200_get_modes, + .enable = raydium_rm67200_enable, + .disable = raydium_rm67200_disable, +}; + +static int raydium_rm67200_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct raydium_rm67200 *ctx; + int ret = 0; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->panel_info = device_get_match_data(dev); + if (!ctx->panel_info) + return -EINVAL; + + ctx->num_supplies = ctx->panel_info->num_regulators; + ret = devm_regulator_bulk_get_const(&dsi->dev, + ctx->panel_info->num_regulators, + ctx->panel_info->regulators, + &ctx->supplies); + if (ret < 0) + return ret; + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + ctx->panel.prepare_prev_first = true; + + drm_panel_init(&ctx->panel, dev, &raydium_rm67200_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) { + dev_err(dev, "Failed to attach to DSI host: %d\n", ret); + drm_panel_remove(&ctx->panel); + } + + return ret; +} + +static void raydium_rm67200_remove(struct mipi_dsi_device *dsi) +{ + struct raydium_rm67200 *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "Failed to detach DSI host: %d\n", ret); + + drm_panel_remove(&ctx->panel); +} + +static const struct regulator_bulk_data w552793baa_regulators[] = { + { .supply = "vdd", }, /* 2.8V */ + { .supply = "iovcc", }, /* 1.8V */ + { .supply = "vsp", }, /* +5.5V */ + { .supply = "vsn", }, /* -5.5V */ +}; + +static const struct raydium_rm67200_panel_info w552793baa_info = { + .mode = { + .clock = 132000, + .hdisplay = 1080, + .hsync_start = 1095, + .hsync_end = 1125, + .htotal = 1129, + .vdisplay = 1920, + .vsync_start = 1935, + .vsync_end = 1950, + .vtotal = 1952, + .width_mm = 68, /* 68.04mm */ + .height_mm = 121, /* 120.96mm */ + .type = DRM_MODE_TYPE_DRIVER, + }, + .regulators = w552793baa_regulators, + .num_regulators = ARRAY_SIZE(w552793baa_regulators), + .panel_setup = w552793baa_setup, +}; + +static const struct of_device_id raydium_rm67200_of_match[] = { + { .compatible = "wanchanglong,w552793baa", .data = &w552793baa_info }, + { /*sentinel*/ } +}; +MODULE_DEVICE_TABLE(of, raydium_rm67200_of_match); + +static struct mipi_dsi_driver raydium_rm67200_driver = { + .probe = raydium_rm67200_probe, + .remove = raydium_rm67200_remove, + .driver = { + .name = "panel-raydium-rm67200", + .of_match_table = raydium_rm67200_of_match, + }, +}; +module_mipi_dsi_driver(raydium_rm67200_driver); + +MODULE_AUTHOR("Sebastian Reichel <sebastian.reichel@collabora.com>"); +MODULE_DESCRIPTION("DRM driver for RM67200-equipped DSI panels"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c index f23d8832a1ad..93f11e2e9398 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c @@ -34,8 +34,8 @@ struct s6d7aa0 { struct s6d7aa0_panel_desc { unsigned int panel_type; - int (*init_func)(struct s6d7aa0 *ctx); - int (*off_func)(struct s6d7aa0 *ctx); + void (*init_func)(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx); + void (*off_func)(struct mipi_dsi_multi_context *dsi_ctx); const struct drm_display_mode *drm_mode; unsigned long mode_flags; u32 bus_flags; @@ -62,93 +62,61 @@ static void s6d7aa0_reset(struct s6d7aa0 *ctx) msleep(50); } -static int s6d7aa0_lock(struct s6d7aa0 *ctx, bool lock) +static void s6d7aa0_lock(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx, bool lock) { - struct mipi_dsi_device *dsi = ctx->dsi; - if (lock) { - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD1, 0xa5, 0xa5); - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD2, 0xa5, 0xa5); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD1, 0xa5, 0xa5); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD2, 0xa5, 0xa5); if (ctx->desc->use_passwd3) - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD3, 0x5a, 0x5a); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD3, 0x5a, 0x5a); } else { - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD1, 0x5a, 0x5a); - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD2, 0x5a, 0x5a); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD1, 0x5a, 0x5a); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD2, 0x5a, 0x5a); if (ctx->desc->use_passwd3) - mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD3, 0xa5, 0xa5); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD3, 0xa5, 0xa5); } - - return 0; } static int s6d7aa0_on(struct s6d7aa0 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = ctx->desc->init_func(ctx); - if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); - gpiod_set_value_cansleep(ctx->reset_gpio, 1); - return ret; - } + ctx->desc->init_func(ctx, &dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } -static int s6d7aa0_off(struct s6d7aa0 *ctx) +static void s6d7aa0_off(struct s6d7aa0 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = ctx->desc->off_func(ctx); - if (ret < 0) { - dev_err(dev, "Panel-specific off function failed: %d\n", ret); - return ret; - } + ctx->desc->off_func(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(64); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 64); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); - return 0; + mipi_dsi_msleep(&dsi_ctx, 120); } static int s6d7aa0_prepare(struct drm_panel *panel) { struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + if (ret < 0) return ret; - } s6d7aa0_reset(ctx); ret = s6d7aa0_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); return ret; } @@ -159,12 +127,8 @@ static int s6d7aa0_prepare(struct drm_panel *panel) static int s6d7aa0_disable(struct drm_panel *panel) { struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = s6d7aa0_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + s6d7aa0_off(ctx); return 0; } @@ -185,13 +149,11 @@ static int s6d7aa0_bl_update_status(struct backlight_device *bl) { struct mipi_dsi_device *dsi = bl_get_data(bl); u16 brightness = backlight_get_brightness(bl); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); - if (ret < 0) - return ret; + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, brightness); - return 0; + return dsi_ctx.accum_err; } static int s6d7aa0_bl_get_brightness(struct backlight_device *bl) @@ -228,65 +190,39 @@ s6d7aa0_create_backlight(struct mipi_dsi_device *dsi) /* Initialization code and structures for LSL080AL02 panel */ -static int s6d7aa0_lsl080al02_init(struct s6d7aa0 *ctx) +static void s6d7aa0_lsl080al02_init(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + mipi_dsi_usleep_range(dsi_ctx, 20000, 25000); - usleep_range(20000, 25000); + s6d7aa0_lock(ctx, dsi_ctx, false); - ret = s6d7aa0_lock(ctx, false); - if (ret < 0) { - dev_err(dev, "Failed to unlock registers: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, MCS_OTP_RELOAD, 0x00, 0x10); - usleep_range(1000, 1500); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_OTP_RELOAD, 0x00, 0x10); + mipi_dsi_usleep_range(dsi_ctx, 1000, 1500); /* SEQ_B6_PARAM_8_R01 */ - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x10); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb6, 0x10); /* BL_CTL_ON */ - mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x28); - - usleep_range(5000, 6000); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_BL_CTL, 0x40, 0x00, 0x28); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x04); + mipi_dsi_usleep_range(dsi_ctx, 5000, 6000); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x04); - msleep(120); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00); + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); - ret = s6d7aa0_lock(ctx, true); - if (ret < 0) { - dev_err(dev, "Failed to lock registers: %d\n", ret); - return ret; - } + mipi_dsi_msleep(dsi_ctx, 120); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + s6d7aa0_lock(ctx, dsi_ctx, true); - return 0; + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); } -static int s6d7aa0_lsl080al02_off(struct s6d7aa0 *ctx) +static void s6d7aa0_lsl080al02_off(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; - /* BL_CTL_OFF */ - mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x20); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_BL_CTL, 0x40, 0x00, 0x20); } static const struct drm_display_mode s6d7aa0_lsl080al02_mode = { @@ -317,79 +253,51 @@ static const struct s6d7aa0_panel_desc s6d7aa0_lsl080al02_desc = { /* Initialization code and structures for LSL080AL03 panel */ -static int s6d7aa0_lsl080al03_init(struct s6d7aa0 *ctx) +static void s6d7aa0_lsl080al03_init(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; - - usleep_range(20000, 25000); + mipi_dsi_usleep_range(dsi_ctx, 20000, 25000); - ret = s6d7aa0_lock(ctx, false); - if (ret < 0) { - dev_err(dev, "Failed to unlock registers: %d\n", ret); - return ret; - } + s6d7aa0_lock(ctx, dsi_ctx, false); if (ctx->desc->panel_type == S6D7AA0_PANEL_LSL080AL03) { - mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0xc7, 0x00, 0x29); - mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x01, 0x4e, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0xfd, 0x16, 0x10, 0x11, 0x23, - 0x09); - mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00, 0x02, 0x03, 0x21, - 0x80, 0x78); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_BL_CTL, 0xc7, 0x00, 0x29); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbc, 0x01, 0x4e, 0xa0); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfd, 0x16, 0x10, 0x11, 0x23, + 0x09); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfe, 0x00, 0x02, 0x03, 0x21, + 0x80, 0x78); } else if (ctx->desc->panel_type == S6D7AA0_PANEL_LTL101AT01) { - mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x01, 0x4e, 0x0b); - mipi_dsi_dcs_write_seq(dsi, 0xfd, 0x16, 0x10, 0x11, 0x23, - 0x09); - mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00, 0x02, 0x03, 0x21, - 0x80, 0x68); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_BL_CTL, 0x40, 0x00, 0x08); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbc, 0x01, 0x4e, 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfd, 0x16, 0x10, 0x11, 0x23, + 0x09); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfe, 0x00, 0x02, 0x03, 0x21, + 0x80, 0x68); } - mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x51); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x02, 0x08, 0x08); - - usleep_range(10000, 11000); - - mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x80, 0x80, 0x30); - mipi_dsi_dcs_write_seq(dsi, 0xcd, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e); - mipi_dsi_dcs_write_seq(dsi, 0xce, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x03); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb3, 0x51); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xf2, 0x02, 0x08, 0x08); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - - ret = s6d7aa0_lock(ctx, true); - if (ret < 0) { - dev_err(dev, "Failed to lock registers: %d\n", ret); - return ret; - } + mipi_dsi_usleep_range(dsi_ctx, 10000, 11000); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc0, 0x80, 0x80, 0x30); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xcd, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xce, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc1, 0x03); - return 0; + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); + s6d7aa0_lock(ctx, dsi_ctx, true); + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); } -static int s6d7aa0_lsl080al03_off(struct s6d7aa0 *ctx) +static void s6d7aa0_lsl080al03_off(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; - - mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x22, 0x00); } static const struct drm_display_mode s6d7aa0_lsl080al03_mode = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c index d2df227abbea..57b1a899bbdc 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c @@ -39,91 +39,66 @@ static void s6e88a0_ams452ef01_reset(struct s6e88a0_ams452ef01 *ctx) static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands - mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c); // set Pixel Clock Divider polarity - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); // set default brightness/gama - mipi_dsi_dcs_write_seq(dsi, 0xca, - 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, // V255 RR,GG,BB - 0x80, 0x80, 0x80, // V203 R,G,B - 0x80, 0x80, 0x80, // V151 R,G,B - 0x80, 0x80, 0x80, // V87 R,G,B - 0x80, 0x80, 0x80, // V51 R,G,B - 0x80, 0x80, 0x80, // V35 R,G,B - 0x80, 0x80, 0x80, // V23 R,G,B - 0x80, 0x80, 0x80, // V11 R,G,B - 0x6b, 0x68, 0x71, // V3 R,G,B - 0x00, 0x00, 0x00); // V1 R,G,B + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,// V255 RR,GG,BB + 0x80, 0x80, 0x80, // V203 R,G,B + 0x80, 0x80, 0x80, // V151 R,G,B + 0x80, 0x80, 0x80, // V87 R,G,B + 0x80, 0x80, 0x80, // V51 R,G,B + 0x80, 0x80, 0x80, // V35 R,G,B + 0x80, 0x80, 0x80, // V23 R,G,B + 0x80, 0x80, 0x80, // V11 R,G,B + 0x6b, 0x68, 0x71, // V3 R,G,B + 0x00, 0x00, 0x00); // V1 R,G,B // set default Amoled Off Ratio - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x2c, 0x0b); // set default elvss voltage + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03); // gamma/aor update + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } -static int s6e88a0_ams452ef01_off(struct s6e88a0_ams452ef01 *ctx) +static void s6e88a0_ams452ef01_off(struct s6e88a0_ams452ef01 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi}; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(35); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(120); - - return 0; + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 35); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); } static int s6e88a0_ams452ef01_prepare(struct drm_panel *panel) { struct s6e88a0_ams452ef01 *ctx = to_s6e88a0_ams452ef01(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + if (ret < 0) return ret; - } s6e88a0_ams452ef01_reset(ctx); ret = s6e88a0_ams452ef01_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -136,12 +111,8 @@ static int s6e88a0_ams452ef01_prepare(struct drm_panel *panel) static int s6e88a0_ams452ef01_unprepare(struct drm_panel *panel) { struct s6e88a0_ams452ef01 *ctx = to_s6e88a0_ams452ef01(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = s6e88a0_ams452ef01_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + s6e88a0_ams452ef01_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c index 04ce925b3d9d..210a25afe82b 100644 --- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c +++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c @@ -22,7 +22,6 @@ struct sofef00_panel { struct mipi_dsi_device *dsi; struct regulator *supply; struct gpio_desc *reset_gpio; - const struct drm_display_mode *mode; }; static inline @@ -44,66 +43,44 @@ static void sofef00_panel_reset(struct sofef00_panel *ctx) static int sofef00_panel_on(struct sofef00_panel *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - usleep_range(10000, 11000); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a); - ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - if (ret < 0) { - dev_err(dev, "Failed to set tear on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x12); - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } static int sofef00_panel_off(struct sofef00_panel *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(40); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 40); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(160); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 160); - return 0; + return dsi_ctx.accum_err; } static int sofef00_panel_prepare(struct drm_panel *panel) @@ -122,7 +99,6 @@ static int sofef00_panel_prepare(struct drm_panel *panel) ret = sofef00_panel_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); return ret; } @@ -133,13 +109,8 @@ static int sofef00_panel_prepare(struct drm_panel *panel) static int sofef00_panel_unprepare(struct drm_panel *panel) { struct sofef00_panel *ctx = to_sofef00_panel(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - - ret = sofef00_panel_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + sofef00_panel_off(ctx); regulator_disable(ctx->supply); return 0; @@ -159,26 +130,11 @@ static const struct drm_display_mode enchilada_panel_mode = { .height_mm = 145, }; -static const struct drm_display_mode fajita_panel_mode = { - .clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000, - .hdisplay = 1080, - .hsync_start = 1080 + 72, - .hsync_end = 1080 + 72 + 16, - .htotal = 1080 + 72 + 16 + 36, - .vdisplay = 2340, - .vsync_start = 2340 + 32, - .vsync_end = 2340 + 32 + 4, - .vtotal = 2340 + 32 + 4 + 18, - .width_mm = 68, - .height_mm = 145, -}; - static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector) { struct drm_display_mode *mode; - struct sofef00_panel *ctx = to_sofef00_panel(panel); - mode = drm_mode_duplicate(connector->dev, ctx->mode); + mode = drm_mode_duplicate(connector->dev, &enchilada_panel_mode); if (!mode) return -ENOMEM; @@ -239,13 +195,6 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi) if (!ctx) return -ENOMEM; - ctx->mode = of_device_get_match_data(dev); - - if (!ctx->mode) { - dev_err(dev, "Missing device mode\n"); - return -ENODEV; - } - ctx->supply = devm_regulator_get(dev, "vddio"); if (IS_ERR(ctx->supply)) return dev_err_probe(dev, PTR_ERR(ctx->supply), @@ -295,14 +244,7 @@ static void sofef00_panel_remove(struct mipi_dsi_device *dsi) } static const struct of_device_id sofef00_panel_of_match[] = { - { // OnePlus 6 / enchilada - .compatible = "samsung,sofef00", - .data = &enchilada_panel_mode, - }, - { // OnePlus 6T / fajita - .compatible = "samsung,s6e3fc2x01", - .data = &fajita_panel_mode, - }, + { .compatible = "samsung,sofef00" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sofef00_panel_of_match); diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index 729cbb0d8403..36abfa2e65e9 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c @@ -36,60 +36,49 @@ static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel) static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt) { struct mipi_dsi_device *dsi = sharp_nt->dsi; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) - return ret; + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); - msleep(120); + mipi_dsi_msleep(&dsi_ctx, 120); /* Novatek two-lane operation */ - ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1); - if (ret < 0) - return ret; + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xae, 0x03); /* Set both MCU and RGB I/F to 24bpp */ - ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT | - (MIPI_DCS_PIXEL_FMT_24BIT << 4)); - if (ret < 0) - return ret; + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, + MIPI_DCS_PIXEL_FMT_24BIT | + (MIPI_DCS_PIXEL_FMT_24BIT << 4)); - return 0; + return dsi_ctx.accum_err; } static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt) { struct mipi_dsi_device *dsi = sharp_nt->dsi; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) - return ret; + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt) { struct mipi_dsi_device *dsi = sharp_nt->dsi; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - return ret; + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) - return ret; + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } static int sharp_nt_panel_unprepare(struct drm_panel *panel) diff --git a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c index 74c760ee0c2d..0b4e0983639b 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c @@ -44,60 +44,39 @@ static void sharp_ls060_reset(struct sharp_ls060 *ctx) static int sharp_ls060_on(struct sharp_ls060 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x13); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } - msleep(50); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); - return 0; + return dsi_ctx.accum_err; } -static int sharp_ls060_off(struct sharp_ls060 *ctx) +static void sharp_ls060_off(struct sharp_ls060 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - usleep_range(2000, 3000); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(121); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 2000, 3000); - return 0; + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 121); } static int sharp_ls060_prepare(struct drm_panel *panel) { struct sharp_ls060 *ctx = to_sharp_ls060(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_enable(ctx->vddi_supply); @@ -125,10 +104,8 @@ static int sharp_ls060_prepare(struct drm_panel *panel) sharp_ls060_reset(ctx); ret = sharp_ls060_on(ctx); - if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); + if (ret < 0) goto err_on; - } return 0; @@ -154,12 +131,8 @@ err_avdd: static int sharp_ls060_unprepare(struct drm_panel *panel) { struct sharp_ls060 *ctx = to_sharp_ls060(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = sharp_ls060_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + sharp_ls060_off(ctx); regulator_disable(ctx->vddh_supply); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9b2f128fd309..82ee2f12b8d2 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -579,9 +579,10 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) u32 bus_flags; int err; - panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); - if (!panel) - return -ENOMEM; + panel = devm_drm_panel_alloc(dev, struct panel_simple, base, + &panel_simple_funcs, desc->connector_type); + if (IS_ERR(panel)) + return PTR_ERR(panel); panel->desc = desc; @@ -694,8 +695,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) pm_runtime_set_autosuspend_delay(dev, 1000); pm_runtime_use_autosuspend(dev); - drm_panel_init(&panel->base, dev, &panel_simple_funcs, connector_type); - err = drm_panel_of_backlight(&panel->base); if (err) { dev_err_probe(dev, err, "Could not find backlight\n"); @@ -1027,27 +1026,28 @@ static const struct panel_desc auo_g070vvn01 = { }, }; -static const struct drm_display_mode auo_g101evn010_mode = { - .clock = 68930, - .hdisplay = 1280, - .hsync_start = 1280 + 82, - .hsync_end = 1280 + 82 + 2, - .htotal = 1280 + 82 + 2 + 84, - .vdisplay = 800, - .vsync_start = 800 + 8, - .vsync_end = 800 + 8 + 2, - .vtotal = 800 + 8 + 2 + 6, +static const struct display_timing auo_g101evn010_timing = { + .pixelclock = { 64000000, 68930000, 85000000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 8, 64, 256 }, + .hback_porch = { 8, 64, 256 }, + .hsync_len = { 40, 168, 767 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 4, 8, 100 }, + .vback_porch = { 4, 8, 100 }, + .vsync_len = { 8, 16, 223 }, }; static const struct panel_desc auo_g101evn010 = { - .modes = &auo_g101evn010_mode, - .num_modes = 1, + .timings = &auo_g101evn010_timing, + .num_timings = 1, .bpc = 6, .size = { .width = 216, .height = 135, }, .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, .connector_type = DRM_MODE_CONNECTOR_LVDS, }; @@ -1374,6 +1374,64 @@ static const struct panel_desc bananapi_s070wv20_ct16 = { }, }; +static const struct display_timing boe_av101hdt_a10_timing = { + .pixelclock = { 74210000, 75330000, 76780000, }, + .hactive = { 1280, 1280, 1280, }, + .hfront_porch = { 10, 42, 33, }, + .hback_porch = { 10, 18, 33, }, + .hsync_len = { 30, 10, 30, }, + .vactive = { 720, 720, 720, }, + .vfront_porch = { 200, 183, 200, }, + .vback_porch = { 8, 8, 8, }, + .vsync_len = { 2, 19, 2, }, + .flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc boe_av101hdt_a10 = { + .timings = &boe_av101hdt_a10_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 224, + .height = 126, + }, + .delay = { + .enable = 50, + .disable = 50, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + +static const struct display_timing boe_av123z7m_n17_timing = { + .pixelclock = { 86600000, 88000000, 90800000, }, + .hactive = { 1920, 1920, 1920, }, + .hfront_porch = { 10, 10, 10, }, + .hback_porch = { 10, 10, 10, }, + .hsync_len = { 9, 12, 25, }, + .vactive = { 720, 720, 720, }, + .vfront_porch = { 7, 10, 13, }, + .vback_porch = { 7, 10, 13, }, + .vsync_len = { 7, 11, 14, }, + .flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc boe_av123z7m_n17 = { + .timings = &boe_av123z7m_n17_timing, + .bpc = 8, + .num_timings = 1, + .size = { + .width = 292, + .height = 110, + }, + .delay = { + .prepare = 50, + .disable = 50, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode boe_bp101wx1_100_mode = { .clock = 78945, .hdisplay = 1280, @@ -3469,6 +3527,30 @@ static const struct panel_desc newhaven_nhd_43_480272ef_atxl = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; +static const struct drm_display_mode nlt_nl13676bc25_03f_mode = { + .clock = 75400, + .hdisplay = 1366, + .hsync_start = 1366 + 14, + .hsync_end = 1366 + 14 + 56, + .htotal = 1366 + 14 + 56 + 64, + .vdisplay = 768, + .vsync_start = 768 + 1, + .vsync_end = 768 + 1 + 3, + .vtotal = 768 + 1 + 3 + 22, +}; + +static const struct panel_desc nlt_nl13676bc25_03f = { + .modes = &nlt_nl13676bc25_03f_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 363, + .height = 215, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct display_timing nlt_nl192108ac18_02d_timing = { .pixelclock = { 130000000, 148350000, 163000000 }, .hactive = { 1920, 1920, 1920 }, @@ -3738,6 +3820,32 @@ static const struct panel_desc pda_91_00156_a0 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct drm_display_mode powertip_ph128800t004_zza01_mode = { + .clock = 71150, + .hdisplay = 1280, + .hsync_start = 1280 + 48, + .hsync_end = 1280 + 48 + 32, + .htotal = 1280 + 48 + 32 + 80, + .vdisplay = 800, + .vsync_start = 800 + 9, + .vsync_end = 800 + 9 + 8, + .vtotal = 800 + 9 + 8 + 6, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc powertip_ph128800t004_zza01 = { + .modes = &powertip_ph128800t004_zza01_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 216, + .height = 135, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode powertip_ph128800t006_zhc01_mode = { .clock = 66500, .hdisplay = 1280, @@ -4335,10 +4443,10 @@ static const struct panel_desc tianma_tm070jvhg33 = { }; /* - * The datasheet computes total blanking as back porch + front porch, not - * including sync pulse width. This is for both H and V. To make the total - * blanking and period correct, subtract the pulse width from the front - * porch. + * The TM070JDHG34-00 datasheet computes total blanking as back porch + + * front porch, not including sync pulse width. This is for both H and + * V. To make the total blanking and period correct, subtract the pulse + * width from the front porch. * * This works well for the Min and Typ values, but for Max values the sync * pulse width is higher than back porch + front porch, so work around that @@ -4347,6 +4455,10 @@ static const struct panel_desc tianma_tm070jvhg33 = { * * Exact datasheet values are added as a comment where they differ from the * ones implemented for the above reason. + * + * The P0700WXF1MBAA datasheet is even less detailed, only listing period + * and total blanking time, however the resulting values are the same as + * the TM070JDHG34-00. */ static const struct display_timing tianma_tm070jdhg34_00_timing = { .pixelclock = { 68400000, 71900000, 78100000 }, @@ -4369,6 +4481,30 @@ static const struct panel_desc tianma_tm070jdhg34_00 = { .width = 150, /* 149.76 */ .height = 94, /* 93.60 */ }, + .delay = { + .prepare = 15, /* Tp1 */ + .enable = 150, /* Tp2 */ + .disable = 150, /* Tp4 */ + .unprepare = 120, /* Tp3 */ + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + +static const struct panel_desc tianma_p0700wxf1mbaa = { + .timings = &tianma_tm070jdhg34_00_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 150, /* 149.76 */ + .height = 94, /* 93.60 */ + }, + .delay = { + .prepare = 18, /* Tr + Tp1 */ + .enable = 152, /* Tp2 + Tp5 */ + .disable = 152, /* Tp6 + Tp4 */ + .unprepare = 120, /* Tp3 */ + }, .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, .connector_type = DRM_MODE_CONNECTOR_LVDS, }; @@ -4814,6 +4950,12 @@ static const struct of_device_id platform_of_match[] = { .compatible = "bananapi,s070wv20-ct16", .data = &bananapi_s070wv20_ct16, }, { + .compatible = "boe,av101hdt-a10", + .data = &boe_av101hdt_a10, + }, { + .compatible = "boe,av123z7m-n17", + .data = &boe_av123z7m_n17, + }, { .compatible = "boe,bp082wx1-100", .data = &boe_bp082wx1_100, }, { @@ -5057,6 +5199,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "newhaven,nhd-4.3-480272ef-atxl", .data = &newhaven_nhd_43_480272ef_atxl, }, { + .compatible = "nlt,nl13676bc25-03f", + .data = &nlt_nl13676bc25_03f, + }, { .compatible = "nlt,nl192108ac18-02d", .data = &nlt_nl192108ac18_02d, }, { @@ -5090,6 +5235,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "pda,91-00156-a0", .data = &pda_91_00156_a0, }, { + .compatible = "powertip,ph128800t004-zza01", + .data = &powertip_ph128800t004_zza01, + }, { .compatible = "powertip,ph128800t006-zhc01", .data = &powertip_ph128800t006_zhc01, }, { @@ -5150,6 +5298,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "tfc,s9700rtwv43tr-01b", .data = &tfc_s9700rtwv43tr_01b, }, { + .compatible = "tianma,p0700wxf1mbaa", + .data = &tianma_p0700wxf1mbaa, + }, { .compatible = "tianma,tm070jdhg30", .data = &tianma_tm070jdhg30, }, { diff --git a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c index 472195d4bbbe..97f4bb4e1029 100644 --- a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c +++ b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c @@ -47,93 +47,40 @@ static inline struct sony_td4353_jdi *to_sony_td4353_jdi(struct drm_panel *panel static int sony_td4353_jdi_on(struct sony_td4353_jdi *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 1080 - 1); - if (ret < 0) { - dev_err(dev, "Failed to set column address: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 2160 - 1); - if (ret < 0) { - dev_err(dev, "Failed to set page address: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0); - if (ret < 0) { - dev_err(dev, "Failed to set tear scanline: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - if (ret < 0) { - dev_err(dev, "Failed to set tear on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 1080 - 1); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 2160 - 1); + mipi_dsi_dcs_set_tear_scanline_multi(&dsi_ctx, 0); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, - 0x00, 0x00, 0x08, 0x6f); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(70); + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, + 0x00, 0x00, 0x08, 0x6f); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to turn display on: %d\n", ret); - return ret; - } - - return 0; + return dsi_ctx.accum_err; } -static int sony_td4353_jdi_off(struct sony_td4353_jdi *ctx) +static void sony_td4353_jdi_off(struct sony_td4353_jdi *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(22); - - ret = mipi_dsi_dcs_set_tear_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set tear off: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(80); - - return 0; + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 22); + mipi_dsi_dcs_set_tear_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 80); } static void sony_td4353_assert_reset_gpios(struct sony_td4353_jdi *ctx, int mode) @@ -146,14 +93,11 @@ static void sony_td4353_assert_reset_gpios(struct sony_td4353_jdi *ctx, int mode static int sony_td4353_jdi_prepare(struct drm_panel *panel) { struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + if (ret < 0) return ret; - } msleep(100); @@ -161,7 +105,6 @@ static int sony_td4353_jdi_prepare(struct drm_panel *panel) ret = sony_td4353_jdi_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to power on panel: %d\n", ret); sony_td4353_assert_reset_gpios(ctx, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return ret; @@ -173,12 +116,8 @@ static int sony_td4353_jdi_prepare(struct drm_panel *panel) static int sony_td4353_jdi_unprepare(struct drm_panel *panel) { struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = sony_td4353_jdi_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to power off panel: %d\n", ret); + sony_td4353_jdi_off(ctx); sony_td4353_assert_reset_gpios(ctx, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); diff --git a/drivers/gpu/drm/panel/panel-summit.c b/drivers/gpu/drm/panel/panel-summit.c new file mode 100644 index 000000000000..e780faee1857 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-summit.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/backlight.h> +#include <drm/drm_device.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_mode.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> +#include <video/mipi_display.h> + +struct summit_data { + struct mipi_dsi_device *dsi; + struct backlight_device *bl; + struct drm_panel panel; +}; + +static int summit_set_brightness(struct device *dev) +{ + struct summit_data *s_data = dev_get_drvdata(dev); + int level = backlight_get_brightness(s_data->bl); + + return mipi_dsi_dcs_set_display_brightness(s_data->dsi, level); +} + +static int summit_bl_update_status(struct backlight_device *dev) +{ + return summit_set_brightness(&dev->dev); +} + +static const struct backlight_ops summit_bl_ops = { + .update_status = summit_bl_update_status, +}; + +static struct drm_display_mode summit_mode = { + .vdisplay = 2008, + .hdisplay = 60, + .hsync_start = 60 + 8, + .hsync_end = 60 + 8 + 80, + .htotal = 60 + 8 + 80 + 40, + .vsync_start = 2008 + 1, + .vsync_end = 2008 + 1 + 15, + .vtotal = 2008 + 1 + 15 + 6, + .clock = ((60 + 8 + 80 + 40) * (2008 + 1 + 15 + 6) * 60) / 1000, + .type = DRM_MODE_TYPE_DRIVER, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +static int summit_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + connector->display_info.non_desktop = true; + drm_object_property_set_value(&connector->base, + connector->dev->mode_config.non_desktop_property, + connector->display_info.non_desktop); + + return drm_connector_helper_get_modes_fixed(connector, &summit_mode); +} + +static const struct drm_panel_funcs summit_panel_funcs = { + .get_modes = summit_get_modes, +}; + +static int summit_probe(struct mipi_dsi_device *dsi) +{ + struct backlight_properties props = { 0 }; + struct device *dev = &dsi->dev; + struct summit_data *s_data; + int ret; + + s_data = devm_kzalloc(dev, sizeof(*s_data), GFP_KERNEL); + if (!s_data) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, s_data); + s_data->dsi = dsi; + + ret = device_property_read_u32(dev, "max-brightness", &props.max_brightness); + if (ret) + return ret; + props.type = BACKLIGHT_RAW; + + s_data->bl = devm_backlight_device_register(dev, dev_name(dev), + dev, s_data, &summit_bl_ops, &props); + if (IS_ERR(s_data->bl)) + return PTR_ERR(s_data->bl); + + drm_panel_init(&s_data->panel, dev, &summit_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + drm_panel_add(&s_data->panel); + + return mipi_dsi_attach(dsi); +} + +static void summit_remove(struct mipi_dsi_device *dsi) +{ + struct summit_data *s_data = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&s_data->panel); +} + +static int summit_suspend(struct device *dev) +{ + struct summit_data *s_data = dev_get_drvdata(dev); + + return mipi_dsi_dcs_set_display_brightness(s_data->dsi, 0); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(summit_pm_ops, summit_suspend, + summit_set_brightness); + +static const struct of_device_id summit_of_match[] = { + { .compatible = "apple,summit" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, summit_of_match); + +static struct mipi_dsi_driver summit_driver = { + .probe = summit_probe, + .remove = summit_remove, + .driver = { + .name = "panel-summit", + .of_match_table = summit_of_match, + .pm = pm_sleep_ptr(&summit_pm_ops), + }, +}; +module_mipi_dsi_driver(summit_driver); + +MODULE_DESCRIPTION("Summit Display Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-synaptics-r63353.c b/drivers/gpu/drm/panel/panel-synaptics-r63353.c index 17349825543f..b148e6cba9bd 100644 --- a/drivers/gpu/drm/panel/panel-synaptics-r63353.c +++ b/drivers/gpu/drm/panel/panel-synaptics-r63353.c @@ -106,53 +106,34 @@ static int r63353_panel_power_off(struct r63353_panel *rpanel) static int r63353_panel_activate(struct r63353_panel *rpanel) { struct mipi_dsi_device *dsi = rpanel->dsi; - struct device *dev = &dsi->dev; - int i, ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + int i; - ret = mipi_dsi_dcs_soft_reset(dsi); - if (ret < 0) { - dev_err(dev, "Failed to do Software Reset (%d)\n", ret); - goto fail; - } + mipi_dsi_dcs_soft_reset_multi(&dsi_ctx); - usleep_range(15000, 17000); + mipi_dsi_usleep_range(&dsi_ctx, 15000, 17000); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode (%d)\n", ret); - goto fail; - } + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); for (i = 0; i < rpanel->pdata->init_length; i++) { const struct r63353_instr *instr = &rpanel->pdata->init[i]; - ret = mipi_dsi_dcs_write_buffer(dsi, instr->data, instr->len); - if (ret < 0) - goto fail; + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, instr->data, + instr->len); } - msleep(120); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode (%d)\n", ret); - goto fail; - } + mipi_dsi_msleep(&dsi_ctx, 120); - usleep_range(5000, 10000); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display ON (%d)\n", ret); - goto fail; - } + mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000); - return 0; + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); -fail: - gpiod_set_value(rpanel->reset_gpio, 0); + if (dsi_ctx.accum_err) + gpiod_set_value(rpanel->reset_gpio, 0); - return ret; + return dsi_ctx.accum_err; } static int r63353_panel_prepare(struct drm_panel *panel) @@ -178,27 +159,16 @@ static int r63353_panel_prepare(struct drm_panel *panel) return 0; } -static int r63353_panel_deactivate(struct r63353_panel *rpanel) +static void r63353_panel_deactivate(struct r63353_panel *rpanel) { struct mipi_dsi_device *dsi = rpanel->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display OFF (%d)\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); - usleep_range(5000, 10000); + mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode (%d)\n", ret); - return ret; - } - - return 0; + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); } static int r63353_panel_unprepare(struct drm_panel *panel) diff --git a/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c b/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c new file mode 100644 index 000000000000..413849f7b4de --- /dev/null +++ b/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2025, Alexander Baransky <sanyapilot496@gmail.com> + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +struct visionox_g2647fb105 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data *supplies; +}; + +static const struct regulator_bulk_data visionox_g2647fb105_supplies[] = { + { .supply = "vdd3p3" }, + { .supply = "vddio" }, + { .supply = "vsn" }, + { .supply = "vsp" }, +}; + +static inline +struct visionox_g2647fb105 *to_visionox_g2647fb105(struct drm_panel *panel) +{ + return container_of(panel, struct visionox_g2647fb105, panel); +} + +static void visionox_g2647fb105_reset(struct visionox_g2647fb105 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); +} + +static int visionox_g2647fb105_on(struct visionox_g2647fb105 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbe, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0xbb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0xdd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x00); + + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x0000); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 100); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + + return dsi_ctx.accum_err; +} + +static int visionox_g2647fb105_off(struct visionox_g2647fb105 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int visionox_g2647fb105_prepare(struct drm_panel *panel) +{ + struct visionox_g2647fb105 *ctx = to_visionox_g2647fb105(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(visionox_g2647fb105_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + visionox_g2647fb105_reset(ctx); + + ret = visionox_g2647fb105_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + return ret; + } + + return 0; +} + +static int visionox_g2647fb105_unprepare(struct drm_panel *panel) +{ + struct visionox_g2647fb105 *ctx = to_visionox_g2647fb105(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = visionox_g2647fb105_off(ctx); + if (ret < 0) + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(visionox_g2647fb105_supplies), ctx->supplies); + + return 0; +} + +static const struct drm_display_mode visionox_g2647fb105_mode = { + .clock = (1080 + 28 + 4 + 36) * (2340 + 8 + 4 + 4) * 60 / 1000, + .hdisplay = 1080, + .hsync_start = 1080 + 28, + .hsync_end = 1080 + 28 + 4, + .htotal = 1080 + 28 + 4 + 36, + .vdisplay = 2340, + .vsync_start = 2340 + 8, + .vsync_end = 2340 + 8 + 4, + .vtotal = 2340 + 8 + 4 + 4, + .width_mm = 69, + .height_mm = 149, +}; + +static int visionox_g2647fb105_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &visionox_g2647fb105_mode); + if (!mode) + 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 visionox_g2647fb105_panel_funcs = { + .prepare = visionox_g2647fb105_prepare, + .unprepare = visionox_g2647fb105_unprepare, + .get_modes = visionox_g2647fb105_get_modes, +}; + +static int visionox_g2647fb105_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + return 0; +} + +static const struct backlight_ops visionox_g2647fb105_bl_ops = { + .update_status = visionox_g2647fb105_bl_update_status, +}; + +static struct backlight_device * +visionox_g2647fb105_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 1023, + .max_brightness = 2047, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &visionox_g2647fb105_bl_ops, &props); +} + +static int visionox_g2647fb105_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct visionox_g2647fb105 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(visionox_g2647fb105_supplies), + visionox_g2647fb105_supplies, + &ctx->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; + + ctx->panel.prepare_prev_first = true; + + drm_panel_init(&ctx->panel, dev, &visionox_g2647fb105_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; + + ctx->panel.backlight = visionox_g2647fb105_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "Failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void visionox_g2647fb105_remove(struct mipi_dsi_device *dsi) +{ + struct visionox_g2647fb105 *ctx = mipi_dsi_get_drvdata(dsi); + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id visionox_g2647fb105_of_match[] = { + { .compatible = "visionox,g2647fb105" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, visionox_g2647fb105_of_match); + +static struct mipi_dsi_driver visionox_g2647fb105_driver = { + .probe = visionox_g2647fb105_probe, + .remove = visionox_g2647fb105_remove, + .driver = { + .name = "panel-visionox-g2647fb105", + .of_match_table = visionox_g2647fb105_of_match, + }, +}; +module_mipi_dsi_driver(visionox_g2647fb105_driver); + +MODULE_AUTHOR("Alexander Baransky <sanyapilot496@gmail.com>"); +MODULE_DESCRIPTION("DRM driver for Visionox G2647FB105 AMOLED DSI panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-visionox-r66451.c b/drivers/gpu/drm/panel/panel-visionox-r66451.c index 493f2a6076f8..3ea0a86f6e69 100644 --- a/drivers/gpu/drm/panel/panel-visionox-r66451.c +++ b/drivers/gpu/drm/panel/panel-visionox-r66451.c @@ -42,85 +42,84 @@ static void visionox_r66451_reset(struct visionox_r66451 *ctx) static int visionox_r66451_on(struct visionox_r66451 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc2, - 0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x09, 0x3c); - mipi_dsi_dcs_write_seq(dsi, 0xd7, - 0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, - 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xde, - 0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, - 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x00, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x00, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32); - mipi_dsi_dcs_write_seq(dsi, 0xcf, - 0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0xd3, - 0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07, - 0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0, - 0x3c, 0x9c); - mipi_dsi_dcs_write_seq(dsi, 0xd7, - 0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, - 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x32, 0x00, 0x0a, 0x00, 0x22); - mipi_dsi_dcs_write_seq(dsi, 0xdf, - 0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39, 0x04, 0x09, 0x34); - mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x00, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x19); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x42); - mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - mipi_dsi_dcs_set_column_address(dsi, 0, 1080 - 1); - mipi_dsi_dcs_set_page_address(dsi, 0, 2340 - 1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, + 0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x09, 0x3c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7, + 0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xde, + 0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, + 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe8, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x00, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcf, + 0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd3, + 0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07, + 0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0, + 0x3c, 0x9c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7, + 0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x32, 0x00, 0x0a, 0x00, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, + 0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39, + 0x04, 0x09, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x42); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0, 1080 - 1); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0, 2340 - 1); dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - return 0; + return dsi_ctx.accum_err; } -static int visionox_r66451_off(struct visionox_r66451 *ctx) +static void visionox_r66451_off(struct visionox_r66451 *ctx) { ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - return 0; } static int visionox_r66451_prepare(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), @@ -132,7 +131,6 @@ static int visionox_r66451_prepare(struct drm_panel *panel) ret = visionox_r66451_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return ret; @@ -146,12 +144,8 @@ static int visionox_r66451_prepare(struct drm_panel *panel) static int visionox_r66451_unprepare(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = visionox_r66451_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + visionox_r66451_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -179,7 +173,7 @@ static int visionox_r66451_enable(struct drm_panel *panel) struct visionox_r66451 *ctx = to_visionox_r66451(panel); struct mipi_dsi_device *dsi = ctx->dsi; struct drm_dsc_picture_parameter_set pps; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; if (!dsi->dsc) { dev_err(&dsi->dev, "DSC not attached to DSI\n"); @@ -187,51 +181,30 @@ static int visionox_r66451_enable(struct drm_panel *panel) } drm_dsc_pps_payload_pack(&pps, dsi->dsc); - ret = mipi_dsi_picture_parameter_set(dsi, &pps); - if (ret) { - dev_err(&dsi->dev, "Failed to set PPS\n"); - return ret; - } + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed on set display on: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); - return 0; + return dsi_ctx.accum_err; } static int visionox_r66451_disable(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - return 0; + return dsi_ctx.accum_err; } static int visionox_r66451_get_modes(struct drm_panel *panel, diff --git a/drivers/gpu/drm/panel/panel-visionox-rm692e5.c b/drivers/gpu/drm/panel/panel-visionox-rm692e5.c new file mode 100644 index 000000000000..4db7fa8d74c4 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-visionox-rm692e5.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2025, Eugene Lepshy <fekz115@gmail.com> + * Copyright (c) 2025, Danila Tikhonov <danila@jiaxyga.com> + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/display/drm_dsc.h> +#include <drm/display/drm_dsc_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + +struct visionox_rm692e5 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct drm_dsc_config dsc; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data *supplies; +}; + +static const struct regulator_bulk_data visionox_rm692e5_supplies[] = { + { .supply = "vddio" }, /* 1p8 */ + { .supply = "vdd" }, /* 3p3 */ +}; + +static inline +struct visionox_rm692e5 *to_visionox_rm692e5(struct drm_panel *panel) +{ + return container_of(panel, struct visionox_rm692e5, panel); +} + +static void visionox_rm692e5_reset(struct visionox_rm692e5 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(32); +} + +static int visionox_rm692e5_on(struct visionox_rm692e5 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbd, 0x07); + mipi_dsi_usleep_range(&dsi_ctx, 17000, 18000); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0xd2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x11); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00ab); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0xe8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x54); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x62); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x69); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x79); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x7d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x7e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x83, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x84, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x85, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x86, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x87, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x88, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x89, 0xbe); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8a, 0x3a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8b, 0xfc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8c, 0x3a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8d, 0xfa); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8e, 0x3a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x8f, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x3b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x91, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x92, 0x3b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x93, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x94, 0x3b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x95, 0xb6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x96, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x97, 0xf6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x98, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x99, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9a, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9b, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9c, 0x5c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9d, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9e, 0x8c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9f, 0xf4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_READ_PPS_START, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa3, 0x1c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa4, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa5, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa6, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa7, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_READ_PPS_CONTINUE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xaa, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xa0, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0xa1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x6b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xce, 0xbb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfe, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfa, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, 0x08); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x000d); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 1000, 2000); + + return dsi_ctx.accum_err; +} + +static int visionox_rm692e5_disable(struct drm_panel *panel) +{ + struct visionox_rm692e5 *ctx = to_visionox_rm692e5(panel); + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 1000, 2000); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 1000, 2000); + + return dsi_ctx.accum_err; +} + +static int visionox_rm692e5_prepare(struct drm_panel *panel) +{ + struct visionox_rm692e5 *ctx = to_visionox_rm692e5(panel); + struct drm_dsc_picture_parameter_set pps; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(visionox_rm692e5_supplies), + ctx->supplies); + if (ret < 0) + return ret; + + visionox_rm692e5_reset(ctx); + + ret = visionox_rm692e5_on(ctx); + if (ret < 0) { + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + goto err; + } + + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); + mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 0); + + mipi_dsi_msleep(&dsi_ctx, 28); + + if (dsi_ctx.accum_err < 0) { + ret = dsi_ctx.accum_err; + goto err; + } + + return dsi_ctx.accum_err; +err: + regulator_bulk_disable(ARRAY_SIZE(visionox_rm692e5_supplies), + ctx->supplies); + return ret; +} + +static int visionox_rm692e5_unprepare(struct drm_panel *panel) +{ + struct visionox_rm692e5 *ctx = to_visionox_rm692e5(panel); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(visionox_rm692e5_supplies), + ctx->supplies); + + return 0; +} + +static const struct drm_display_mode visionox_rm692e5_modes[] = { + /* Let's initialize the highest frequency first */ + { /* 120Hz mode */ + .clock = (1080 + 26 + 39 + 36) * (2400 + 16 + 21 + 16) * 120 / 1000, + .hdisplay = 1080, + .hsync_start = 1080 + 26, + .hsync_end = 1080 + 26 + 39, + .htotal = 1080 + 26 + 39 + 36, + .vdisplay = 2400, + .vsync_start = 2400 + 16, + .vsync_end = 2400 + 16 + 21, + .vtotal = 2400 + 16 + 21 + 16, + .width_mm = 68, + .height_mm = 152, + .type = DRM_MODE_TYPE_DRIVER, + }, + { /* 90Hz mode */ + .clock = (1080 + 26 + 39 + 36) * (2400 + 16 + 21 + 16) * 90 / 1000, + .hdisplay = 1080, + .hsync_start = 1080 + 26, + .hsync_end = 1080 + 26 + 39, + .htotal = 1080 + 26 + 39 + 36, + .vdisplay = 2400, + .vsync_start = 2400 + 16, + .vsync_end = 2400 + 16 + 21, + .vtotal = 2400 + 16 + 21 + 16, + .width_mm = 68, + .height_mm = 152, + .type = DRM_MODE_TYPE_DRIVER, + }, + { /* 60Hz mode */ + .clock = (1080 + 26 + 39 + 36) * (2400 + 16 + 21 + 16) * 60 / 1000, + .hdisplay = 1080, + .hsync_start = 1080 + 26, + .hsync_end = 1080 + 26 + 39, + .htotal = 1080 + 26 + 39 + 36, + .vdisplay = 2400, + .vsync_start = 2400 + 16, + .vsync_end = 2400 + 16 + 21, + .vtotal = 2400 + 16 + 21 + 16, + .width_mm = 68, + .height_mm = 152, + .type = DRM_MODE_TYPE_DRIVER, + }, +}; + +static int visionox_rm692e5_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + int count = 0; + + for (int i = 0; i < ARRAY_SIZE(visionox_rm692e5_modes); i++) + count += drm_connector_helper_get_modes_fixed(connector, + &visionox_rm692e5_modes[i]); + + return count; +} + +static const struct drm_panel_funcs visionox_rm692e5_panel_funcs = { + .prepare = visionox_rm692e5_prepare, + .unprepare = visionox_rm692e5_unprepare, + .disable = visionox_rm692e5_disable, + .get_modes = visionox_rm692e5_get_modes, +}; + +static int visionox_rm692e5_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + return 0; +} + +static int visionox_rm692e5_bl_get_brightness(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness; + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + return brightness; +} + +static const struct backlight_ops visionox_rm692e5_bl_ops = { + .update_status = visionox_rm692e5_bl_update_status, + .get_brightness = visionox_rm692e5_bl_get_brightness, +}; + +static struct backlight_device * +visionox_rm692e5_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 2047, + .max_brightness = 4095, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &visionox_rm692e5_bl_ops, &props); +} + +static int visionox_rm692e5_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct visionox_rm692e5 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ret = devm_regulator_bulk_get_const(&dsi->dev, + ARRAY_SIZE(visionox_rm692e5_supplies), + visionox_rm692e5_supplies, + &ctx->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS; + + drm_panel_init(&ctx->panel, dev, &visionox_rm692e5_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; + + ctx->panel.backlight = visionox_rm692e5_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "Failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + dsi->dsc = &ctx->dsc; + ctx->dsc.dsc_version_major = 1; + ctx->dsc.dsc_version_minor = 1; + ctx->dsc.slice_height = 20; + ctx->dsc.slice_width = 540; + ctx->dsc.slice_count = 1080 / ctx->dsc.slice_width; + ctx->dsc.bits_per_component = 10; + ctx->dsc.bits_per_pixel = 8 << 4; + ctx->dsc.block_pred_enable = true; + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void visionox_rm692e5_remove(struct mipi_dsi_device *dsi) +{ + struct visionox_rm692e5 *ctx = mipi_dsi_get_drvdata(dsi); + + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id visionox_rm692e5_of_match[] = { + { .compatible = "visionox,rm692e5" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, visionox_rm692e5_of_match); + +static struct mipi_dsi_driver visionox_rm692e5_driver = { + .probe = visionox_rm692e5_probe, + .remove = visionox_rm692e5_remove, + .driver = { + .name = "panel-visionox-rm692e5", + .of_match_table = visionox_rm692e5_of_match, + }, +}; +module_mipi_dsi_driver(visionox_rm692e5_driver); + +MODULE_AUTHOR("Eugene Lepshy <fekz115@gmail.com>"); +MODULE_AUTHOR("Danila Tikhonov <danila@jiaxyga.com>"); +MODULE_DESCRIPTION("DRM driver for Visionox RM692E5 cmd mode dsi panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 22a14006765e..2b91414c2829 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -59,91 +59,80 @@ static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel) return container_of(panel, struct xpp055c272, panel); } -static int xpp055c272_init_sequence(struct xpp055c272 *ctx) +static void xpp055c272_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - struct device *dev = ctx->dev; - /* * Init sequence was supplied by the panel vendor without much * documentation. */ - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETMIPI, - 0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, - 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01, - 0x00, 0x00, 0x37); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETRGBIF, - 0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00, - 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETSCR, - 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, - 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEQ, - 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER, - 0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd, - 0x67, 0x77, 0x33, 0x33); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff, - 0xff, 0x01, 0xff); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09); - msleep(20); - - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP1, - 0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12, - 0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42, - 0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58, - 0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88, - 0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP2, - 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35, - 0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f, - 0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88, - 0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05, - 0xa0, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGAMMA, - 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36, - 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11, - 0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, - 0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, - 0x11, 0x18); - - msleep(60); - - dev_dbg(dev, "Panel init sequence done\n"); - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETMIPI, + 0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, + 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01, + 0x00, 0x00, 0x37); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPOWER_EXT, 0x25); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETRGBIF, + 0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETSCR, + 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, + 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETVDC, 0x46); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPANEL, 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETCYC, 0x80); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETEQ, + 0x07, 0x07, 0x0b, 0x0b, 0x03, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xC0, 0x10); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPOWER, + 0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd, + 0x67, 0x77, 0x33, 0x33); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff, + 0xff, 0x01, 0xff); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETBGP, 0x09, 0x09); + mipi_dsi_msleep(dsi_ctx, 20); + + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETVCOM, 0x87, 0x95); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGIP1, + 0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12, + 0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42, + 0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58, + 0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88, + 0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGIP2, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35, + 0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f, + 0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88, + 0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05, + 0xa0, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGAMMA, + 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36, + 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11, + 0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, + 0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, + 0x11, 0x18); + + mipi_dsi_msleep(dsi_ctx, 60); } static int xpp055c272_unprepare(struct drm_panel *panel) { struct xpp055c272 *ctx = panel_to_xpp055c272(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - dev_err(ctx->dev, "failed to set display off: %d\n", ret); - - mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; regulator_disable(ctx->iovcc); regulator_disable(ctx->vci); @@ -155,17 +144,19 @@ static int xpp055c272_prepare(struct drm_panel *panel) { struct xpp055c272 *ctx = panel_to_xpp055c272(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dev_dbg(ctx->dev, "Resetting the panel\n"); - ret = regulator_enable(ctx->vci); - if (ret < 0) { - dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); - return ret; + dsi_ctx.accum_err = regulator_enable(ctx->vci); + if (dsi_ctx.accum_err) { + dev_err(ctx->dev, "Failed to enable vci supply: %d\n", + dsi_ctx.accum_err); + return dsi_ctx.accum_err; } - ret = regulator_enable(ctx->iovcc); - if (ret < 0) { - dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); + dsi_ctx.accum_err = regulator_enable(ctx->iovcc); + if (dsi_ctx.accum_err) { + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", + dsi_ctx.accum_err); goto disable_vci; } @@ -177,26 +168,17 @@ static int xpp055c272_prepare(struct drm_panel *panel) /* T8: 20ms */ msleep(20); - ret = xpp055c272_init_sequence(ctx); - if (ret < 0) { - dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); - goto disable_iovcc; - } - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); - goto disable_iovcc; - } + xpp055c272_init_sequence(&dsi_ctx); + if (!dsi_ctx.accum_err) + dev_dbg(ctx->dev, "Panel init sequence done\n"); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); /* T9: 120ms */ - msleep(120); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(ctx->dev, "Failed to set display on: %d\n", ret); + if (dsi_ctx.accum_err) goto disable_iovcc; - } msleep(50); @@ -206,7 +188,7 @@ disable_iovcc: regulator_disable(ctx->iovcc); disable_vci: regulator_disable(ctx->vci); - return ret; + return dsi_ctx.accum_err; } static const struct drm_display_mode default_mode = { |