diff options
Diffstat (limited to 'drivers/gpu/drm/panel')
-rw-r--r-- | drivers/gpu/drm/panel/Kconfig | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-abt-y030xx067a.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 743 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-edp.c | 1896 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 85 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-samsung-s6d27a1.c | 320 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-simple.c | 1098 |
9 files changed, 3075 insertions, 1113 deletions
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index beb581b96ecd..2cb8eba76af8 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -77,14 +77,26 @@ config DRM_PANEL_LVDS backlight handling if the panel is attached to a backlight controller. config DRM_PANEL_SIMPLE - tristate "support for simple panels" + tristate "support for simple panels (other than eDP ones)" + depends on OF + depends on BACKLIGHT_CLASS_DEVICE + depends on PM + select VIDEOMODE_HELPERS + help + DRM panel driver for dumb non-eDP panels that need at most a regulator + and a GPIO to be powered up. Optionally a backlight can be attached so + that it can be automatically turned off when the panel goes into a + low power state. + +config DRM_PANEL_EDP + tristate "support for simple Embedded DisplayPort panels" depends on OF depends on BACKLIGHT_CLASS_DEVICE depends on PM select VIDEOMODE_HELPERS select DRM_DP_AUX_BUS help - DRM panel driver for dumb panels that need at most a regulator and + DRM panel driver for dumb eDP panels that need at most a regulator and a GPIO to be powered up. Optionally a backlight can be attached so that it can be automatically turned off when the panel goes into a low power state. @@ -295,6 +307,7 @@ config DRM_PANEL_OLIMEX_LCD_OLINUXINO depends on OF depends on I2C depends on BACKLIGHT_CLASS_DEVICE + select CRC32 help The panel is used with different sizes LCDs, from 480x272 to 1280x800, and 24 bit per pixel. @@ -392,6 +405,17 @@ config DRM_PANEL_SAMSUNG_S6D16D0 depends on DRM_MIPI_DSI select VIDEOMODE_HELPERS +config DRM_PANEL_SAMSUNG_S6D27A1 + tristate "Samsung S6D27A1 DPI panel driver" + depends on OF && SPI && GPIOLIB + select DRM_MIPI_DBI + help + Say Y here if you want to enable support for the Samsung + S6D27A1 DPI 480x800 panel. + + This panel can be found in Samsung Galaxy Ace 2 + GT-I8160 mobile phone. + config DRM_PANEL_SAMSUNG_S6E3HA2 tristate "Samsung S6E3HA2 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index c8132050bcec..6e30640b9099 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +obj-$(CONFIG_DRM_PANEL_EDP) += panel-edp.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 @@ -39,6 +40,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index 2d8794d495d0..3d8a9ab47cae 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -146,8 +146,8 @@ static const struct reg_sequence y030xx067a_init_sequence[] = { { 0x09, REG09_SUB_BRIGHT_R(0x20) }, { 0x0a, REG0A_SUB_BRIGHT_B(0x20) }, { 0x0b, REG0B_HD_FREERUN | REG0B_VD_FREERUN }, - { 0x0c, REG0C_CONTRAST_R(0x10) }, - { 0x0d, REG0D_CONTRAST_G(0x10) }, + { 0x0c, REG0C_CONTRAST_R(0x00) }, + { 0x0d, REG0D_CONTRAST_G(0x00) }, { 0x0e, REG0E_CONTRAST_B(0x10) }, { 0x0f, 0 }, { 0x10, REG10_BRIGHT(0x7f) }, diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index db9d0b86d542..529561b4fbbc 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -45,6 +45,7 @@ struct boe_panel { const struct panel_desc *desc; enum drm_panel_orientation orientation; + struct regulator *pp3300; struct regulator *pp1800; struct regulator *avee; struct regulator *avdd; @@ -74,6 +75,670 @@ struct panel_init_cmd { .len = sizeof((char[]){__VA_ARGS__}), \ .data = (char[]){__VA_ARGS__} } +static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { + _INIT_DCS_CMD(0xFF, 0x20), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x05, 0xD9), + _INIT_DCS_CMD(0x07, 0x78), + _INIT_DCS_CMD(0x08, 0x5A), + _INIT_DCS_CMD(0x0D, 0x63), + _INIT_DCS_CMD(0x0E, 0x91), + _INIT_DCS_CMD(0x0F, 0x73), + _INIT_DCS_CMD(0x95, 0xEB), + _INIT_DCS_CMD(0x96, 0xEB), + _INIT_DCS_CMD(0x30, 0x11), + _INIT_DCS_CMD(0x6D, 0x66), + _INIT_DCS_CMD(0x75, 0xA2), + _INIT_DCS_CMD(0x77, 0x3B), + + _INIT_DCS_CMD(0xB0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), + _INIT_DCS_CMD(0xB1, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), + _INIT_DCS_CMD(0xB2, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), + _INIT_DCS_CMD(0xB3, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), + + _INIT_DCS_CMD(0xB4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), + _INIT_DCS_CMD(0xB5, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), + _INIT_DCS_CMD(0xB6, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), + _INIT_DCS_CMD(0xB7, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), + _INIT_DCS_CMD(0xB8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), + _INIT_DCS_CMD(0xB9, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), + _INIT_DCS_CMD(0xBA, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), + _INIT_DCS_CMD(0xBB, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), + + _INIT_DCS_CMD(0xFF, 0x21), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), + _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), + _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), + _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + + _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), + _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), + _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), + _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + + _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), + _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), + _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), + _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + + _INIT_DCS_CMD(0xFF, 0x24), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x00, 0x00), + _INIT_DCS_CMD(0x01, 0x00), + + _INIT_DCS_CMD(0x02, 0x1C), + _INIT_DCS_CMD(0x03, 0x1C), + + _INIT_DCS_CMD(0x04, 0x1D), + _INIT_DCS_CMD(0x05, 0x1D), + + _INIT_DCS_CMD(0x06, 0x04), + _INIT_DCS_CMD(0x07, 0x04), + + _INIT_DCS_CMD(0x08, 0x0F), + _INIT_DCS_CMD(0x09, 0x0F), + + _INIT_DCS_CMD(0x0A, 0x0E), + _INIT_DCS_CMD(0x0B, 0x0E), + + _INIT_DCS_CMD(0x0C, 0x0D), + _INIT_DCS_CMD(0x0D, 0x0D), + + _INIT_DCS_CMD(0x0E, 0x0C), + _INIT_DCS_CMD(0x0F, 0x0C), + + _INIT_DCS_CMD(0x10, 0x08), + _INIT_DCS_CMD(0x11, 0x08), + + _INIT_DCS_CMD(0x12, 0x00), + _INIT_DCS_CMD(0x13, 0x00), + _INIT_DCS_CMD(0x14, 0x00), + _INIT_DCS_CMD(0x15, 0x00), + + _INIT_DCS_CMD(0x16, 0x00), + _INIT_DCS_CMD(0x17, 0x00), + + _INIT_DCS_CMD(0x18, 0x1C), + _INIT_DCS_CMD(0x19, 0x1C), + + _INIT_DCS_CMD(0x1A, 0x1D), + _INIT_DCS_CMD(0x1B, 0x1D), + + _INIT_DCS_CMD(0x1C, 0x04), + _INIT_DCS_CMD(0x1D, 0x04), + + _INIT_DCS_CMD(0x1E, 0x0F), + _INIT_DCS_CMD(0x1F, 0x0F), + + _INIT_DCS_CMD(0x20, 0x0E), + _INIT_DCS_CMD(0x21, 0x0E), + + _INIT_DCS_CMD(0x22, 0x0D), + _INIT_DCS_CMD(0x23, 0x0D), + + _INIT_DCS_CMD(0x24, 0x0C), + _INIT_DCS_CMD(0x25, 0x0C), + + _INIT_DCS_CMD(0x26, 0x08), + _INIT_DCS_CMD(0x27, 0x08), + + _INIT_DCS_CMD(0x28, 0x00), + _INIT_DCS_CMD(0x29, 0x00), + _INIT_DCS_CMD(0x2A, 0x00), + _INIT_DCS_CMD(0x2B, 0x00), + + _INIT_DCS_CMD(0x2D, 0x20), + _INIT_DCS_CMD(0x2F, 0x0A), + _INIT_DCS_CMD(0x30, 0x44), + _INIT_DCS_CMD(0x33, 0x0C), + _INIT_DCS_CMD(0x34, 0x32), + + _INIT_DCS_CMD(0x37, 0x44), + _INIT_DCS_CMD(0x38, 0x40), + _INIT_DCS_CMD(0x39, 0x00), + _INIT_DCS_CMD(0x3A, 0x5D), + _INIT_DCS_CMD(0x3B, 0x60), + _INIT_DCS_CMD(0x3D, 0x42), + _INIT_DCS_CMD(0x3F, 0x06), + _INIT_DCS_CMD(0x43, 0x06), + _INIT_DCS_CMD(0x47, 0x66), + _INIT_DCS_CMD(0x4A, 0x5D), + _INIT_DCS_CMD(0x4B, 0x60), + _INIT_DCS_CMD(0x4C, 0x91), + _INIT_DCS_CMD(0x4D, 0x21), + _INIT_DCS_CMD(0x4E, 0x43), + _INIT_DCS_CMD(0x51, 0x12), + _INIT_DCS_CMD(0x52, 0x34), + _INIT_DCS_CMD(0x55, 0x82, 0x02), + _INIT_DCS_CMD(0x56, 0x04), + _INIT_DCS_CMD(0x58, 0x21), + _INIT_DCS_CMD(0x59, 0x30), + _INIT_DCS_CMD(0x5A, 0x60), + _INIT_DCS_CMD(0x5B, 0x50), + _INIT_DCS_CMD(0x5E, 0x00, 0x06), + _INIT_DCS_CMD(0x5F, 0x00), + _INIT_DCS_CMD(0x65, 0x82), + _INIT_DCS_CMD(0x7E, 0x20), + _INIT_DCS_CMD(0x7F, 0x3C), + _INIT_DCS_CMD(0x82, 0x04), + _INIT_DCS_CMD(0x97, 0xC0), + _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00), + _INIT_DCS_CMD(0x91, 0x44), + _INIT_DCS_CMD(0x92, 0xA9), + _INIT_DCS_CMD(0x93, 0x1A), + _INIT_DCS_CMD(0x94, 0x96), + _INIT_DCS_CMD(0xD7, 0x55), + _INIT_DCS_CMD(0xDA, 0x0A), + _INIT_DCS_CMD(0xDE, 0x08), + _INIT_DCS_CMD(0xDB, 0x05), + _INIT_DCS_CMD(0xDC, 0xA9), + _INIT_DCS_CMD(0xDD, 0x22), + + _INIT_DCS_CMD(0xDF, 0x05), + _INIT_DCS_CMD(0xE0, 0xA9), + _INIT_DCS_CMD(0xE1, 0x05), + _INIT_DCS_CMD(0xE2, 0xA9), + _INIT_DCS_CMD(0xE3, 0x05), + _INIT_DCS_CMD(0xE4, 0xA9), + _INIT_DCS_CMD(0xE5, 0x05), + _INIT_DCS_CMD(0xE6, 0xA9), + _INIT_DCS_CMD(0x5C, 0x00), + _INIT_DCS_CMD(0x5D, 0x00), + _INIT_DCS_CMD(0x8D, 0x00), + _INIT_DCS_CMD(0x8E, 0x00), + _INIT_DCS_CMD(0xB5, 0x90), + _INIT_DCS_CMD(0xFF, 0x25), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x05, 0x00), + _INIT_DCS_CMD(0x19, 0x07), + _INIT_DCS_CMD(0x1F, 0x60), + _INIT_DCS_CMD(0x20, 0x50), + _INIT_DCS_CMD(0x26, 0x60), + _INIT_DCS_CMD(0x27, 0x50), + _INIT_DCS_CMD(0x33, 0x60), + _INIT_DCS_CMD(0x34, 0x50), + _INIT_DCS_CMD(0x3F, 0xE0), + _INIT_DCS_CMD(0x40, 0x00), + _INIT_DCS_CMD(0x44, 0x00), + _INIT_DCS_CMD(0x45, 0x40), + _INIT_DCS_CMD(0x48, 0x60), + _INIT_DCS_CMD(0x49, 0x50), + _INIT_DCS_CMD(0x5B, 0x00), + _INIT_DCS_CMD(0x5C, 0x00), + _INIT_DCS_CMD(0x5D, 0x00), + _INIT_DCS_CMD(0x5E, 0xD0), + _INIT_DCS_CMD(0x61, 0x60), + _INIT_DCS_CMD(0x62, 0x50), + _INIT_DCS_CMD(0xF1, 0x10), + _INIT_DCS_CMD(0xFF, 0x2A), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x64, 0x16), + _INIT_DCS_CMD(0x67, 0x16), + _INIT_DCS_CMD(0x6A, 0x16), + + _INIT_DCS_CMD(0x70, 0x30), + + _INIT_DCS_CMD(0xA2, 0xF3), + _INIT_DCS_CMD(0xA3, 0xFF), + _INIT_DCS_CMD(0xA4, 0xFF), + _INIT_DCS_CMD(0xA5, 0xFF), + + _INIT_DCS_CMD(0xD6, 0x08), + + _INIT_DCS_CMD(0xFF, 0x26), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x00, 0xA1), + + _INIT_DCS_CMD(0x02, 0x31), + _INIT_DCS_CMD(0x04, 0x28), + _INIT_DCS_CMD(0x06, 0x30), + _INIT_DCS_CMD(0x0C, 0x16), + _INIT_DCS_CMD(0x0D, 0x0D), + _INIT_DCS_CMD(0x0F, 0x00), + _INIT_DCS_CMD(0x11, 0x00), + _INIT_DCS_CMD(0x12, 0x50), + _INIT_DCS_CMD(0x13, 0x56), + _INIT_DCS_CMD(0x14, 0x57), + _INIT_DCS_CMD(0x15, 0x00), + _INIT_DCS_CMD(0x16, 0x10), + _INIT_DCS_CMD(0x17, 0xA0), + _INIT_DCS_CMD(0x18, 0x86), + _INIT_DCS_CMD(0x19, 0x0D), + _INIT_DCS_CMD(0x1A, 0x7F), + _INIT_DCS_CMD(0x1B, 0x0C), + _INIT_DCS_CMD(0x1C, 0xBF), + _INIT_DCS_CMD(0x22, 0x00), + _INIT_DCS_CMD(0x23, 0x00), + _INIT_DCS_CMD(0x2A, 0x0D), + _INIT_DCS_CMD(0x2B, 0x7F), + + _INIT_DCS_CMD(0x1D, 0x00), + _INIT_DCS_CMD(0x1E, 0x65), + _INIT_DCS_CMD(0x1F, 0x65), + _INIT_DCS_CMD(0x24, 0x00), + _INIT_DCS_CMD(0x25, 0x65), + _INIT_DCS_CMD(0x2F, 0x05), + _INIT_DCS_CMD(0x30, 0x65), + _INIT_DCS_CMD(0x31, 0x05), + _INIT_DCS_CMD(0x32, 0x7D), + _INIT_DCS_CMD(0x39, 0x00), + _INIT_DCS_CMD(0x3A, 0x65), + _INIT_DCS_CMD(0x20, 0x01), + _INIT_DCS_CMD(0x33, 0x11), + _INIT_DCS_CMD(0x34, 0x78), + _INIT_DCS_CMD(0x35, 0x16), + _INIT_DCS_CMD(0xC8, 0x04), + _INIT_DCS_CMD(0xC9, 0x80), + _INIT_DCS_CMD(0xCA, 0x4E), + _INIT_DCS_CMD(0xCB, 0x00), + _INIT_DCS_CMD(0xA9, 0x4C), + _INIT_DCS_CMD(0xAA, 0x47), + + _INIT_DCS_CMD(0xFF, 0x27), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x56, 0x06), + _INIT_DCS_CMD(0x58, 0x80), + _INIT_DCS_CMD(0x59, 0x75), + _INIT_DCS_CMD(0x5A, 0x00), + _INIT_DCS_CMD(0x5B, 0x02), + _INIT_DCS_CMD(0x5C, 0x00), + _INIT_DCS_CMD(0x5D, 0x00), + _INIT_DCS_CMD(0x5E, 0x20), + _INIT_DCS_CMD(0x5F, 0x10), + _INIT_DCS_CMD(0x60, 0x00), + _INIT_DCS_CMD(0x61, 0x2E), + _INIT_DCS_CMD(0x62, 0x00), + _INIT_DCS_CMD(0x63, 0x01), + _INIT_DCS_CMD(0x64, 0x43), + _INIT_DCS_CMD(0x65, 0x2D), + _INIT_DCS_CMD(0x66, 0x00), + _INIT_DCS_CMD(0x67, 0x01), + _INIT_DCS_CMD(0x68, 0x44), + + _INIT_DCS_CMD(0x00, 0x00), + _INIT_DCS_CMD(0x78, 0x00), + _INIT_DCS_CMD(0xC3, 0x00), + + _INIT_DCS_CMD(0xFF, 0x2A), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x22, 0x2F), + _INIT_DCS_CMD(0x23, 0x08), + + _INIT_DCS_CMD(0x24, 0x00), + _INIT_DCS_CMD(0x25, 0x65), + _INIT_DCS_CMD(0x26, 0xF8), + _INIT_DCS_CMD(0x27, 0x00), + _INIT_DCS_CMD(0x28, 0x1A), + _INIT_DCS_CMD(0x29, 0x00), + _INIT_DCS_CMD(0x2A, 0x1A), + _INIT_DCS_CMD(0x2B, 0x00), + _INIT_DCS_CMD(0x2D, 0x1A), + + _INIT_DCS_CMD(0xFF, 0x23), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x00, 0x80), + _INIT_DCS_CMD(0x07, 0x00), + + _INIT_DCS_CMD(0xFF, 0xE0), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x14, 0x60), + _INIT_DCS_CMD(0x16, 0xC0), + + _INIT_DCS_CMD(0xFF, 0xF0), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x3A, 0x08), + + _INIT_DCS_CMD(0xFF, 0x10), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0xB9, 0x01), + _INIT_DCS_CMD(0xFF, 0x20), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x18, 0x40), + + _INIT_DCS_CMD(0xFF, 0x10), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0xB9, 0x02), + _INIT_DCS_CMD(0x35, 0x00), + _INIT_DCS_CMD(0x51, 0x00, 0xFF), + _INIT_DCS_CMD(0x53, 0x24), + _INIT_DCS_CMD(0x55, 0x00), + _INIT_DCS_CMD(0xBB, 0x13), + _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04), + _INIT_DELAY_CMD(100), + _INIT_DCS_CMD(0x11), + _INIT_DELAY_CMD(200), + _INIT_DCS_CMD(0x29), + _INIT_DELAY_CMD(100), + {}, +}; + +static const struct panel_init_cmd inx_init_cmd[] = { + _INIT_DCS_CMD(0xFF, 0x20), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x05, 0xD1), + _INIT_DCS_CMD(0x0D, 0x63), + _INIT_DCS_CMD(0x07, 0x8C), + _INIT_DCS_CMD(0x08, 0x4B), + _INIT_DCS_CMD(0x0E, 0x91), + _INIT_DCS_CMD(0x0F, 0x69), + _INIT_DCS_CMD(0x95, 0xFF), + _INIT_DCS_CMD(0x96, 0xFF), + _INIT_DCS_CMD(0x9D, 0x0A), + _INIT_DCS_CMD(0x9E, 0x0A), + _INIT_DCS_CMD(0x69, 0x98), + _INIT_DCS_CMD(0x75, 0xA2), + _INIT_DCS_CMD(0x77, 0xB3), + _INIT_DCS_CMD(0xFF, 0x24), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x91, 0x44), + _INIT_DCS_CMD(0x92, 0x7A), + _INIT_DCS_CMD(0x93, 0x1A), + _INIT_DCS_CMD(0x94, 0x40), + _INIT_DCS_CMD(0x9A, 0x08), + _INIT_DCS_CMD(0x60, 0x96), + _INIT_DCS_CMD(0x61, 0xD0), + _INIT_DCS_CMD(0x63, 0x70), + _INIT_DCS_CMD(0xC2, 0xCF), + _INIT_DCS_CMD(0x9B, 0x0F), + _INIT_DCS_CMD(0x9A, 0x08), + _INIT_DCS_CMD(0x00, 0x03), + _INIT_DCS_CMD(0x01, 0x03), + _INIT_DCS_CMD(0x02, 0x03), + _INIT_DCS_CMD(0x03, 0x03), + _INIT_DCS_CMD(0x04, 0x03), + _INIT_DCS_CMD(0x05, 0x03), + _INIT_DCS_CMD(0x06, 0x22), + _INIT_DCS_CMD(0x07, 0x06), + _INIT_DCS_CMD(0x08, 0x00), + _INIT_DCS_CMD(0x09, 0x1D), + _INIT_DCS_CMD(0x0A, 0x1C), + _INIT_DCS_CMD(0x0B, 0x13), + _INIT_DCS_CMD(0x0C, 0x12), + _INIT_DCS_CMD(0x0D, 0x11), + _INIT_DCS_CMD(0x0E, 0x10), + _INIT_DCS_CMD(0x0F, 0x0F), + _INIT_DCS_CMD(0x10, 0x0E), + _INIT_DCS_CMD(0x11, 0x0D), + _INIT_DCS_CMD(0x12, 0x0C), + _INIT_DCS_CMD(0x13, 0x04), + _INIT_DCS_CMD(0x14, 0x03), + _INIT_DCS_CMD(0x15, 0x03), + _INIT_DCS_CMD(0x16, 0x03), + _INIT_DCS_CMD(0x17, 0x03), + _INIT_DCS_CMD(0x18, 0x03), + _INIT_DCS_CMD(0x19, 0x03), + _INIT_DCS_CMD(0x1A, 0x03), + _INIT_DCS_CMD(0x1B, 0x03), + _INIT_DCS_CMD(0x1C, 0x22), + _INIT_DCS_CMD(0x1D, 0x06), + _INIT_DCS_CMD(0x1E, 0x00), + _INIT_DCS_CMD(0x1F, 0x1D), + _INIT_DCS_CMD(0x20, 0x1C), + _INIT_DCS_CMD(0x21, 0x13), + _INIT_DCS_CMD(0x22, 0x12), + _INIT_DCS_CMD(0x23, 0x11), + _INIT_DCS_CMD(0x24, 0x10), + _INIT_DCS_CMD(0x25, 0x0F), + _INIT_DCS_CMD(0x26, 0x0E), + _INIT_DCS_CMD(0x27, 0x0D), + _INIT_DCS_CMD(0x28, 0x0C), + _INIT_DCS_CMD(0x29, 0x04), + _INIT_DCS_CMD(0x2A, 0x03), + _INIT_DCS_CMD(0x2B, 0x03), + + _INIT_DCS_CMD(0x2F, 0x06), + _INIT_DCS_CMD(0x30, 0x32), + _INIT_DCS_CMD(0x31, 0x43), + _INIT_DCS_CMD(0x33, 0x06), + _INIT_DCS_CMD(0x34, 0x32), + _INIT_DCS_CMD(0x35, 0x43), + _INIT_DCS_CMD(0x37, 0x44), + _INIT_DCS_CMD(0x38, 0x40), + _INIT_DCS_CMD(0x39, 0x00), + _INIT_DCS_CMD(0x3A, 0x01), + _INIT_DCS_CMD(0x3B, 0x48), + _INIT_DCS_CMD(0x3D, 0x93), + _INIT_DCS_CMD(0xAB, 0x44), + _INIT_DCS_CMD(0xAC, 0x40), + + _INIT_DCS_CMD(0x4D, 0x21), + _INIT_DCS_CMD(0x4E, 0x43), + _INIT_DCS_CMD(0x4F, 0x65), + _INIT_DCS_CMD(0x50, 0x87), + _INIT_DCS_CMD(0x51, 0x78), + _INIT_DCS_CMD(0x52, 0x56), + _INIT_DCS_CMD(0x53, 0x34), + _INIT_DCS_CMD(0x54, 0x21), + _INIT_DCS_CMD(0x55, 0x83), + _INIT_DCS_CMD(0x56, 0x08), + _INIT_DCS_CMD(0x58, 0x21), + _INIT_DCS_CMD(0x59, 0x40), + _INIT_DCS_CMD(0x5A, 0x09), + _INIT_DCS_CMD(0x5B, 0x48), + _INIT_DCS_CMD(0x5E, 0x00, 0x10), + _INIT_DCS_CMD(0x5F, 0x00), + + _INIT_DCS_CMD(0x7A, 0x00), + _INIT_DCS_CMD(0x7B, 0x00), + _INIT_DCS_CMD(0x7C, 0x00), + _INIT_DCS_CMD(0x7D, 0x00), + _INIT_DCS_CMD(0x7E, 0x20), + _INIT_DCS_CMD(0x7F, 0x3C), + _INIT_DCS_CMD(0x80, 0x00), + _INIT_DCS_CMD(0x81, 0x00), + _INIT_DCS_CMD(0x82, 0x08), + _INIT_DCS_CMD(0x97, 0x02), + _INIT_DCS_CMD(0xC5, 0x10), + _INIT_DCS_CMD(0xDA, 0x05), + _INIT_DCS_CMD(0xDB, 0x01), + _INIT_DCS_CMD(0xDC, 0x7A), + _INIT_DCS_CMD(0xDD, 0x55), + _INIT_DCS_CMD(0xDE, 0x27), + _INIT_DCS_CMD(0xDF, 0x01), + _INIT_DCS_CMD(0xE0, 0x7A), + _INIT_DCS_CMD(0xE1, 0x01), + _INIT_DCS_CMD(0xE2, 0x7A), + _INIT_DCS_CMD(0xE3, 0x01), + _INIT_DCS_CMD(0xE4, 0x7A), + _INIT_DCS_CMD(0xE5, 0x01), + _INIT_DCS_CMD(0xE6, 0x7A), + _INIT_DCS_CMD(0xE7, 0x00), + _INIT_DCS_CMD(0xE8, 0x00), + _INIT_DCS_CMD(0xE9, 0x01), + _INIT_DCS_CMD(0xEA, 0x7A), + _INIT_DCS_CMD(0xEB, 0x01), + _INIT_DCS_CMD(0xEE, 0x7A), + _INIT_DCS_CMD(0xEF, 0x01), + _INIT_DCS_CMD(0xF0, 0x7A), + + _INIT_DCS_CMD(0xFF, 0x25), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x05, 0x00), + + _INIT_DCS_CMD(0xF1, 0x10), + _INIT_DCS_CMD(0x1E, 0x00), + _INIT_DCS_CMD(0x1F, 0x09), + _INIT_DCS_CMD(0x20, 0x46), + _INIT_DCS_CMD(0x25, 0x00), + _INIT_DCS_CMD(0x26, 0x09), + _INIT_DCS_CMD(0x27, 0x46), + _INIT_DCS_CMD(0x3F, 0x80), + _INIT_DCS_CMD(0x40, 0x00), + _INIT_DCS_CMD(0x43, 0x00), + + _INIT_DCS_CMD(0x44, 0x09), + _INIT_DCS_CMD(0x45, 0x46), + + _INIT_DCS_CMD(0x48, 0x09), + _INIT_DCS_CMD(0x49, 0x46), + _INIT_DCS_CMD(0x5B, 0x80), + _INIT_DCS_CMD(0x5C, 0x00), + _INIT_DCS_CMD(0x5D, 0x01), + _INIT_DCS_CMD(0x5E, 0x46), + _INIT_DCS_CMD(0x61, 0x01), + _INIT_DCS_CMD(0x62, 0x46), + _INIT_DCS_CMD(0x68, 0x10), + _INIT_DCS_CMD(0xFF, 0x26), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x00, 0xA1), + _INIT_DCS_CMD(0x02, 0x31), + _INIT_DCS_CMD(0x0A, 0xF2), + _INIT_DCS_CMD(0x04, 0x28), + _INIT_DCS_CMD(0x06, 0x30), + _INIT_DCS_CMD(0x0C, 0x16), + _INIT_DCS_CMD(0x0D, 0x0D), + _INIT_DCS_CMD(0x0F, 0x00), + _INIT_DCS_CMD(0x11, 0x00), + _INIT_DCS_CMD(0x12, 0x50), + _INIT_DCS_CMD(0x13, 0x56), + _INIT_DCS_CMD(0x14, 0x57), + _INIT_DCS_CMD(0x15, 0x00), + _INIT_DCS_CMD(0x16, 0x10), + _INIT_DCS_CMD(0x17, 0xA0), + _INIT_DCS_CMD(0x18, 0x86), + _INIT_DCS_CMD(0x22, 0x00), + _INIT_DCS_CMD(0x23, 0x00), + _INIT_DCS_CMD(0x19, 0x0D), + _INIT_DCS_CMD(0x1A, 0x7F), + _INIT_DCS_CMD(0x1B, 0x0C), + _INIT_DCS_CMD(0x1C, 0xBF), + _INIT_DCS_CMD(0x2A, 0x0D), + _INIT_DCS_CMD(0x2B, 0x7F), + _INIT_DCS_CMD(0x20, 0x00), + + _INIT_DCS_CMD(0x1D, 0x00), + _INIT_DCS_CMD(0x1E, 0x78), + _INIT_DCS_CMD(0x1F, 0x78), + + _INIT_DCS_CMD(0x2F, 0x03), + _INIT_DCS_CMD(0x30, 0x78), + _INIT_DCS_CMD(0x33, 0x78), + _INIT_DCS_CMD(0x34, 0x66), + _INIT_DCS_CMD(0x35, 0x11), + + _INIT_DCS_CMD(0x39, 0x10), + _INIT_DCS_CMD(0x3A, 0x78), + _INIT_DCS_CMD(0x3B, 0x06), + + _INIT_DCS_CMD(0xC8, 0x04), + _INIT_DCS_CMD(0xC9, 0x84), + _INIT_DCS_CMD(0xCA, 0x4E), + _INIT_DCS_CMD(0xCB, 0x00), + + _INIT_DCS_CMD(0xA9, 0x50), + _INIT_DCS_CMD(0xAA, 0x4F), + _INIT_DCS_CMD(0xAB, 0x4D), + _INIT_DCS_CMD(0xAC, 0x4A), + _INIT_DCS_CMD(0xAD, 0x48), + _INIT_DCS_CMD(0xAE, 0x46), + _INIT_DCS_CMD(0xFF, 0x27), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0xC0, 0x18), + _INIT_DCS_CMD(0xC1, 0x00), + _INIT_DCS_CMD(0xC2, 0x00), + _INIT_DCS_CMD(0x56, 0x06), + _INIT_DCS_CMD(0x58, 0x80), + _INIT_DCS_CMD(0x59, 0x75), + _INIT_DCS_CMD(0x5A, 0x00), + _INIT_DCS_CMD(0x5B, 0x02), + _INIT_DCS_CMD(0x5C, 0x00), + _INIT_DCS_CMD(0x5D, 0x00), + _INIT_DCS_CMD(0x5E, 0x20), + _INIT_DCS_CMD(0x5F, 0x10), + _INIT_DCS_CMD(0x60, 0x00), + _INIT_DCS_CMD(0x61, 0x2E), + _INIT_DCS_CMD(0x62, 0x00), + _INIT_DCS_CMD(0x63, 0x01), + _INIT_DCS_CMD(0x64, 0x43), + _INIT_DCS_CMD(0x65, 0x2D), + _INIT_DCS_CMD(0x66, 0x00), + _INIT_DCS_CMD(0x67, 0x01), + _INIT_DCS_CMD(0x68, 0x43), + _INIT_DCS_CMD(0x98, 0x01), + _INIT_DCS_CMD(0xB4, 0x03), + _INIT_DCS_CMD(0x9B, 0xBD), + _INIT_DCS_CMD(0xA0, 0x90), + _INIT_DCS_CMD(0xAB, 0x1B), + _INIT_DCS_CMD(0xBC, 0x0C), + _INIT_DCS_CMD(0xBD, 0x28), + + _INIT_DCS_CMD(0xFF, 0x2A), + _INIT_DCS_CMD(0xFB, 0x01), + + _INIT_DCS_CMD(0x22, 0x2F), + _INIT_DCS_CMD(0x23, 0x08), + + _INIT_DCS_CMD(0x24, 0x00), + _INIT_DCS_CMD(0x25, 0x65), + _INIT_DCS_CMD(0x26, 0xF8), + _INIT_DCS_CMD(0x27, 0x00), + _INIT_DCS_CMD(0x28, 0x1A), + _INIT_DCS_CMD(0x29, 0x00), + _INIT_DCS_CMD(0x2A, 0x1A), + _INIT_DCS_CMD(0x2B, 0x00), + _INIT_DCS_CMD(0x2D, 0x1A), + + _INIT_DCS_CMD(0x64, 0x96), + _INIT_DCS_CMD(0x65, 0x00), + _INIT_DCS_CMD(0x66, 0x00), + _INIT_DCS_CMD(0x6A, 0x96), + _INIT_DCS_CMD(0x6B, 0x00), + _INIT_DCS_CMD(0x6C, 0x00), + _INIT_DCS_CMD(0x70, 0x92), + _INIT_DCS_CMD(0x71, 0x00), + _INIT_DCS_CMD(0x72, 0x00), + _INIT_DCS_CMD(0xA2, 0x33), + _INIT_DCS_CMD(0xA3, 0x30), + _INIT_DCS_CMD(0xA4, 0xC0), + _INIT_DCS_CMD(0xE8, 0x00), + _INIT_DCS_CMD(0xFF, 0xF0), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x3A, 0x08), + _INIT_DCS_CMD(0xFF, 0xD0), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x00, 0x33), + _INIT_DCS_CMD(0x02, 0x77), + _INIT_DCS_CMD(0x08, 0x01), + _INIT_DCS_CMD(0x09, 0xBF), + _INIT_DCS_CMD(0x28, 0x30), + _INIT_DCS_CMD(0x2F, 0x33), + _INIT_DCS_CMD(0xFF, 0x23), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x00, 0x80), + _INIT_DCS_CMD(0x07, 0x00), + _INIT_DCS_CMD(0xFF, 0x20), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0x30, 0x00), + _INIT_DCS_CMD(0xFF, 0x10), + _INIT_DCS_CMD(0xB9, 0x01), + _INIT_DCS_CMD(0xFF, 0x20), + _INIT_DCS_CMD(0x18, 0x40), + _INIT_DCS_CMD(0xFF, 0x10), + _INIT_DCS_CMD(0xB9, 0x02), + _INIT_DCS_CMD(0xFF, 0x10), + _INIT_DCS_CMD(0xFB, 0x01), + _INIT_DCS_CMD(0xBB, 0x13), + _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04), + _INIT_DCS_CMD(0x35, 0x00), + _INIT_DCS_CMD(0x51, 0x0F, 0xFF), + _INIT_DCS_CMD(0x53, 0x24), + _INIT_DELAY_CMD(100), + _INIT_DCS_CMD(0x11), + _INIT_DELAY_CMD(200), + _INIT_DCS_CMD(0x29), + _INIT_DELAY_CMD(100), + {}, +}; + static const struct panel_init_cmd boe_init_cmd[] = { _INIT_DELAY_CMD(24), _INIT_DCS_CMD(0xB0, 0x05), @@ -511,13 +1176,15 @@ static int boe_panel_unprepare(struct drm_panel *panel) gpiod_set_value(boe->enable_gpio, 0); usleep_range(5000, 7000); regulator_disable(boe->pp1800); + regulator_disable(boe->pp3300); } else { gpiod_set_value(boe->enable_gpio, 0); - usleep_range(500, 1000); + usleep_range(1000, 2000); regulator_disable(boe->avee); regulator_disable(boe->avdd); usleep_range(5000, 7000); regulator_disable(boe->pp1800); + regulator_disable(boe->pp3300); } boe->prepared = false; @@ -536,6 +1203,10 @@ static int boe_panel_prepare(struct drm_panel *panel) gpiod_set_value(boe->enable_gpio, 0); usleep_range(1000, 1500); + ret = regulator_enable(boe->pp3300); + if (ret < 0) + return ret; + ret = regulator_enable(boe->pp1800); if (ret < 0) return ret; @@ -549,7 +1220,7 @@ static int boe_panel_prepare(struct drm_panel *panel) if (ret < 0) goto poweroffavdd; - usleep_range(5000, 10000); + usleep_range(10000, 11000); gpiod_set_value(boe->enable_gpio, 1); usleep_range(1000, 2000); @@ -586,6 +1257,64 @@ static int boe_panel_enable(struct drm_panel *panel) return 0; } +static const struct drm_display_mode boe_tv110c9m_default_mode = { + .clock = 166594, + .hdisplay = 1200, + .hsync_start = 1200 + 40, + .hsync_end = 1200 + 40 + 8, + .htotal = 1200 + 40 + 8 + 28, + .vdisplay = 2000, + .vsync_start = 2000 + 26, + .vsync_end = 2000 + 26 + 2, + .vtotal = 2000 + 26 + 2 + 148, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct panel_desc boe_tv110c9m_desc = { + .modes = &boe_tv110c9m_default_mode, + .bpc = 8, + .size = { + .width_mm = 143, + .height_mm = 238, + }, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO + | MIPI_DSI_MODE_VIDEO_HSE + | MIPI_DSI_CLOCK_NON_CONTINUOUS + | MIPI_DSI_MODE_VIDEO_BURST, + .init_cmds = boe_tv110c9m_init_cmd, +}; + +static const struct drm_display_mode inx_hj110iz_default_mode = { + .clock = 166594, + .hdisplay = 1200, + .hsync_start = 1200 + 40, + .hsync_end = 1200 + 40 + 8, + .htotal = 1200 + 40 + 8 + 28, + .vdisplay = 2000, + .vsync_start = 2000 + 26, + .vsync_end = 2000 + 26 + 1, + .vtotal = 2000 + 26 + 1 + 149, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct panel_desc inx_hj110iz_desc = { + .modes = &inx_hj110iz_default_mode, + .bpc = 8, + .size = { + .width_mm = 143, + .height_mm = 238, + }, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO + | MIPI_DSI_MODE_VIDEO_HSE + | MIPI_DSI_CLOCK_NON_CONTINUOUS + | MIPI_DSI_MODE_VIDEO_BURST, + .init_cmds = inx_init_cmd, +}; + static const struct drm_display_mode boe_tv101wum_nl6_default_mode = { .clock = 159425, .hdisplay = 1200, @@ -767,6 +1496,10 @@ static int boe_panel_add(struct boe_panel *boe) if (IS_ERR(boe->avee)) return PTR_ERR(boe->avee); + boe->pp3300 = devm_regulator_get(dev, "pp3300"); + if (IS_ERR(boe->pp3300)) + return PTR_ERR(boe->pp3300); + boe->pp1800 = devm_regulator_get(dev, "pp1800"); if (IS_ERR(boe->pp1800)) return PTR_ERR(boe->pp1800); @@ -870,6 +1603,12 @@ static const struct of_device_id boe_of_match[] = { { .compatible = "boe,tv105wum-nw0", .data = &boe_tv105wum_nw0_desc }, + { .compatible = "boe,tv110c9m-ll3", + .data = &boe_tv110c9m_desc + }, + { .compatible = "innolux,hj110iz-01a", + .data = &inx_hj110iz_desc + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, boe_of_match); diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c new file mode 100644 index 000000000000..fc03046de134 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -0,0 +1,1896 @@ +/* + * Copyright (C) 2013, NVIDIA Corporation. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> + +#include <video/display_timing.h> +#include <video/of_display_timing.h> +#include <video/videomode.h> + +#include <drm/drm_crtc.h> +#include <drm/drm_device.h> +#include <drm/drm_dp_aux_bus.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_panel.h> + +/** + * struct panel_delay - Describes delays for a simple panel. + */ +struct panel_delay { + /** + * @hpd_reliable: Time for HPD to be reliable + * + * The time (in milliseconds) that it takes after powering the panel + * before the HPD signal is reliable. Ideally this is 0 but some panels, + * board designs, or bad pulldown configs can cause a glitch here. + * + * NOTE: on some old panel data this number appers to be much too big. + * Presumably some old panels simply didn't have HPD hooked up and put + * the hpd_absent here because this field predates the + * hpd_absent. While that works, it's non-ideal. + */ + unsigned int hpd_reliable; + + /** + * @hpd_absent: Time to wait if HPD isn't hooked up. + * + * Add this to the prepare delay if we know Hot Plug Detect isn't used. + * + * This is T3-max on eDP timing diagrams or the delay from power on + * until HPD is guaranteed to be asserted. + */ + unsigned int hpd_absent; + + /** + * @prepare_to_enable: Time between prepare and enable. + * + * The minimum time, in milliseconds, that needs to have passed + * between when prepare finished and enable may begin. If at + * enable time less time has passed since prepare finished, + * the driver waits for the remaining time. + * + * If a fixed enable delay is also specified, we'll start + * counting before delaying for the fixed delay. + * + * If a fixed prepare delay is also specified, we won't start + * counting until after the fixed delay. We can't overlap this + * fixed delay with the min time because the fixed delay + * doesn't happen at the end of the function if a HPD GPIO was + * specified. + * + * In other words: + * prepare() + * ... + * // do fixed prepare delay + * // wait for HPD GPIO if applicable + * // start counting for prepare_to_enable + * + * enable() + * // do fixed enable delay + * // enforce prepare_to_enable min time + * + * This is not specified in a standard way on eDP timing diagrams. + * It is effectively the time from HPD going high till you can + * turn on the backlight. + */ + unsigned int prepare_to_enable; + + /** + * @enable: Time for the panel to display a valid frame. + * + * The time (in milliseconds) that it takes for the panel to + * display the first valid frame after starting to receive + * video data. + * + * This is (T6-min + max(T7-max, T8-min)) on eDP timing diagrams or + * the delay after link training finishes until we can turn the + * backlight on and see valid data. + */ + unsigned int enable; + + /** + * @disable: Time for the panel to turn the display off. + * + * The time (in milliseconds) that it takes for the panel to + * turn the display off (no content is visible). + * + * This is T9-min (delay from backlight off to end of valid video + * data) on eDP timing diagrams. It is not common to set. + */ + unsigned int disable; + + /** + * @unprepare: Time to power down completely. + * + * The time (in milliseconds) that it takes for the panel + * to power itself down completely. + * + * This time is used to prevent a future "prepare" from + * starting until at least this many milliseconds has passed. + * If at prepare time less time has passed since unprepare + * finished, the driver waits for the remaining time. + * + * This is T12-min on eDP timing diagrams. + */ + unsigned int unprepare; +}; + +/** + * struct panel_desc - Describes a simple panel. + */ +struct panel_desc { + /** + * @modes: Pointer to array of fixed modes appropriate for this panel. + * + * If only one mode then this can just be the address of the mode. + * NOTE: cannot be used with "timings" and also if this is specified + * then you cannot override the mode in the device tree. + */ + const struct drm_display_mode *modes; + + /** @num_modes: Number of elements in modes array. */ + unsigned int num_modes; + + /** + * @timings: Pointer to array of display timings + * + * NOTE: cannot be used with "modes" and also these will be used to + * validate a device tree override if one is present. + */ + const struct display_timing *timings; + + /** @num_timings: Number of elements in timings array. */ + unsigned int num_timings; + + /** @bpc: Bits per color. */ + unsigned int bpc; + + /** @size: Structure containing the physical size of this panel. */ + struct { + /** + * @size.width: Width (in mm) of the active display area. + */ + unsigned int width; + + /** + * @size.height: Height (in mm) of the active display area. + */ + unsigned int height; + } size; + + /** @delay: Structure containing various delay values for this panel. */ + struct panel_delay delay; +}; + +/** + * struct edp_panel_entry - Maps panel ID to delay / panel name. + */ +struct edp_panel_entry { + /** @panel_id: 32-bit ID for panel, encoded with drm_edid_encode_panel_id(). */ + u32 panel_id; + + /* @delay: The power sequencing delays needed for this panel. */ + const struct panel_delay *delay; + + /* @name: Name of this panel (for printing to logs). */ + const char *name; +}; + +struct panel_edp { + struct drm_panel base; + bool enabled; + bool no_hpd; + + bool prepared; + + ktime_t prepared_time; + ktime_t unprepared_time; + + const struct panel_desc *desc; + + struct regulator *supply; + struct i2c_adapter *ddc; + struct drm_dp_aux *aux; + + struct gpio_desc *enable_gpio; + struct gpio_desc *hpd_gpio; + + struct edid *edid; + + struct drm_display_mode override_mode; + + enum drm_panel_orientation orientation; +}; + +static inline struct panel_edp *to_panel_edp(struct drm_panel *panel) +{ + return container_of(panel, struct panel_edp, base); +} + +static unsigned int panel_edp_get_timings_modes(struct panel_edp *panel, + struct drm_connector *connector) +{ + struct drm_display_mode *mode; + unsigned int i, num = 0; + + for (i = 0; i < panel->desc->num_timings; i++) { + const struct display_timing *dt = &panel->desc->timings[i]; + struct videomode vm; + + videomode_from_timing(dt, &vm); + mode = drm_mode_create(connector->dev); + if (!mode) { + dev_err(panel->base.dev, "failed to add mode %ux%u\n", + dt->hactive.typ, dt->vactive.typ); + continue; + } + + drm_display_mode_from_videomode(&vm, mode); + + mode->type |= DRM_MODE_TYPE_DRIVER; + + if (panel->desc->num_timings == 1) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + num++; + } + + return num; +} + +static unsigned int panel_edp_get_display_modes(struct panel_edp *panel, + struct drm_connector *connector) +{ + struct drm_display_mode *mode; + unsigned int i, num = 0; + + for (i = 0; i < panel->desc->num_modes; i++) { + const struct drm_display_mode *m = &panel->desc->modes[i]; + + mode = drm_mode_duplicate(connector->dev, m); + if (!mode) { + dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n", + m->hdisplay, m->vdisplay, + drm_mode_vrefresh(m)); + continue; + } + + mode->type |= DRM_MODE_TYPE_DRIVER; + + if (panel->desc->num_modes == 1) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_set_name(mode); + + drm_mode_probed_add(connector, mode); + num++; + } + + return num; +} + +static int panel_edp_get_non_edid_modes(struct panel_edp *panel, + struct drm_connector *connector) +{ + struct drm_display_mode *mode; + bool has_override = panel->override_mode.type; + unsigned int num = 0; + + if (!panel->desc) + return 0; + + if (has_override) { + mode = drm_mode_duplicate(connector->dev, + &panel->override_mode); + if (mode) { + drm_mode_probed_add(connector, mode); + num = 1; + } else { + dev_err(panel->base.dev, "failed to add override mode\n"); + } + } + + /* Only add timings if override was not there or failed to validate */ + if (num == 0 && panel->desc->num_timings) + num = panel_edp_get_timings_modes(panel, connector); + + /* + * Only add fixed modes if timings/override added no mode. + * + * We should only ever have either the display timings specified + * or a fixed mode. Anything else is rather bogus. + */ + WARN_ON(panel->desc->num_timings && panel->desc->num_modes); + if (num == 0) + num = panel_edp_get_display_modes(panel, connector); + + connector->display_info.bpc = panel->desc->bpc; + connector->display_info.width_mm = panel->desc->size.width; + connector->display_info.height_mm = panel->desc->size.height; + + return num; +} + +static void panel_edp_wait(ktime_t start_ktime, unsigned int min_ms) +{ + ktime_t now_ktime, min_ktime; + + if (!min_ms) + return; + + min_ktime = ktime_add(start_ktime, ms_to_ktime(min_ms)); + now_ktime = ktime_get(); + + if (ktime_before(now_ktime, min_ktime)) + msleep(ktime_to_ms(ktime_sub(min_ktime, now_ktime)) + 1); +} + +static int panel_edp_disable(struct drm_panel *panel) +{ + struct panel_edp *p = to_panel_edp(panel); + + if (!p->enabled) + return 0; + + if (p->desc->delay.disable) + msleep(p->desc->delay.disable); + + p->enabled = false; + + return 0; +} + +static int panel_edp_suspend(struct device *dev) +{ + struct panel_edp *p = dev_get_drvdata(dev); + + gpiod_set_value_cansleep(p->enable_gpio, 0); + regulator_disable(p->supply); + p->unprepared_time = ktime_get(); + + return 0; +} + +static int panel_edp_unprepare(struct drm_panel *panel) +{ + struct panel_edp *p = to_panel_edp(panel); + int ret; + + /* Unpreparing when already unprepared is a no-op */ + if (!p->prepared) + return 0; + + pm_runtime_mark_last_busy(panel->dev); + ret = pm_runtime_put_autosuspend(panel->dev); + if (ret < 0) + return ret; + p->prepared = false; + + return 0; +} + +static int panel_edp_get_hpd_gpio(struct device *dev, struct panel_edp *p) +{ + int err; + + p->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); + if (IS_ERR(p->hpd_gpio)) { + err = PTR_ERR(p->hpd_gpio); + + if (err != -EPROBE_DEFER) + dev_err(dev, "failed to get 'hpd' GPIO: %d\n", err); + + return err; + } + + return 0; +} + +static int panel_edp_prepare_once(struct panel_edp *p) +{ + struct device *dev = p->base.dev; + unsigned int delay; + int err; + int hpd_asserted; + unsigned long hpd_wait_us; + + panel_edp_wait(p->unprepared_time, p->desc->delay.unprepare); + + err = regulator_enable(p->supply); + if (err < 0) { + dev_err(dev, "failed to enable supply: %d\n", err); + return err; + } + + gpiod_set_value_cansleep(p->enable_gpio, 1); + + delay = p->desc->delay.hpd_reliable; + if (p->no_hpd) + delay = max(delay, p->desc->delay.hpd_absent); + if (delay) + msleep(delay); + + if (p->hpd_gpio) { + if (p->desc->delay.hpd_absent) + hpd_wait_us = p->desc->delay.hpd_absent * 1000UL; + else + hpd_wait_us = 2000000; + + err = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio, + hpd_asserted, hpd_asserted, + 1000, hpd_wait_us); + if (hpd_asserted < 0) + err = hpd_asserted; + + if (err) { + if (err != -ETIMEDOUT) + dev_err(dev, + "error waiting for hpd GPIO: %d\n", err); + goto error; + } + } + + p->prepared_time = ktime_get(); + + return 0; + +error: + gpiod_set_value_cansleep(p->enable_gpio, 0); + regulator_disable(p->supply); + p->unprepared_time = ktime_get(); + + return err; +} + +/* + * Some panels simply don't always come up and need to be power cycled to + * work properly. We'll allow for a handful of retries. + */ +#define MAX_PANEL_PREPARE_TRIES 5 + +static int panel_edp_resume(struct device *dev) +{ + struct panel_edp *p = dev_get_drvdata(dev); + int ret; + int try; + + for (try = 0; try < MAX_PANEL_PREPARE_TRIES; try++) { + ret = panel_edp_prepare_once(p); + if (ret != -ETIMEDOUT) + break; + } + + if (ret == -ETIMEDOUT) + dev_err(dev, "Prepare timeout after %d tries\n", try); + else if (try) + dev_warn(dev, "Prepare needed %d retries\n", try); + + return ret; +} + +static int panel_edp_prepare(struct drm_panel *panel) +{ + struct panel_edp *p = to_panel_edp(panel); + int ret; + + /* Preparing when already prepared is a no-op */ + if (p->prepared) + return 0; + + ret = pm_runtime_get_sync(panel->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(panel->dev); + return ret; + } + + p->prepared = true; + + return 0; +} + +static int panel_edp_enable(struct drm_panel *panel) +{ + struct panel_edp *p = to_panel_edp(panel); + unsigned int delay; + + if (p->enabled) + return 0; + + delay = p->desc->delay.enable; + + /* + * If there is a "prepare_to_enable" delay then that's supposed to be + * the delay from HPD going high until we can turn the backlight on. + * However, we can only count this if HPD is handled by the panel + * driver, not if it goes to a dedicated pin on the controller. + * If we aren't handling the HPD pin ourselves then the best we + * can do is assume that HPD went high immediately before we were + * called (and link training took zero time). + * + * NOTE: if we ever end up in this "if" statement then we're + * guaranteed that the panel_edp_wait() call below will do no delay. + * It already handles that case, though, so we don't need any special + * code for it. + */ + if (p->desc->delay.prepare_to_enable && !p->hpd_gpio && !p->no_hpd) + delay = max(delay, p->desc->delay.prepare_to_enable); + + if (delay) + msleep(delay); + + panel_edp_wait(p->prepared_time, p->desc->delay.prepare_to_enable); + + p->enabled = true; + + return 0; +} + +static int panel_edp_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct panel_edp *p = to_panel_edp(panel); + int num = 0; + + /* probe EDID if a DDC bus is available */ + if (p->ddc) { + pm_runtime_get_sync(panel->dev); + + if (!p->edid) + p->edid = drm_get_edid(connector, p->ddc); + + if (p->edid) + num += drm_add_edid_modes(connector, p->edid); + + pm_runtime_mark_last_busy(panel->dev); + pm_runtime_put_autosuspend(panel->dev); + } + + /* + * Add hard-coded panel modes. Don't call this if there are no timings + * and no modes (the generic edp-panel case) because it will clobber + * the display_info that was already set by drm_add_edid_modes(). + */ + if (p->desc->num_timings || p->desc->num_modes) + num += panel_edp_get_non_edid_modes(p, connector); + else if (!num) + dev_warn(p->base.dev, "No display modes\n"); + + /* set up connector's "panel orientation" property */ + drm_connector_set_panel_orientation(connector, p->orientation); + + return num; +} + +static int panel_edp_get_timings(struct drm_panel *panel, + unsigned int num_timings, + struct display_timing *timings) +{ + struct panel_edp *p = to_panel_edp(panel); + unsigned int i; + + if (p->desc->num_timings < num_timings) + num_timings = p->desc->num_timings; + + if (timings) + for (i = 0; i < num_timings; i++) + timings[i] = p->desc->timings[i]; + + return p->desc->num_timings; +} + +static const struct drm_panel_funcs panel_edp_funcs = { + .disable = panel_edp_disable, + .unprepare = panel_edp_unprepare, + .prepare = panel_edp_prepare, + .enable = panel_edp_enable, + .get_modes = panel_edp_get_modes, + .get_timings = panel_edp_get_timings, +}; + +#define PANEL_EDP_BOUNDS_CHECK(to_check, bounds, field) \ + (to_check->field.typ >= bounds->field.min && \ + to_check->field.typ <= bounds->field.max) +static void panel_edp_parse_panel_timing_node(struct device *dev, + struct panel_edp *panel, + const struct display_timing *ot) +{ + const struct panel_desc *desc = panel->desc; + struct videomode vm; + unsigned int i; + + if (WARN_ON(desc->num_modes)) { + dev_err(dev, "Reject override mode: panel has a fixed mode\n"); + return; + } + if (WARN_ON(!desc->num_timings)) { + dev_err(dev, "Reject override mode: no timings specified\n"); + return; + } + + for (i = 0; i < panel->desc->num_timings; i++) { + const struct display_timing *dt = &panel->desc->timings[i]; + + if (!PANEL_EDP_BOUNDS_CHECK(ot, dt, hactive) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, hfront_porch) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, hback_porch) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, hsync_len) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, vactive) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, vfront_porch) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, vback_porch) || + !PANEL_EDP_BOUNDS_CHECK(ot, dt, vsync_len)) + continue; + + if (ot->flags != dt->flags) + continue; + + videomode_from_timing(ot, &vm); + drm_display_mode_from_videomode(&vm, &panel->override_mode); + panel->override_mode.type |= DRM_MODE_TYPE_DRIVER | + DRM_MODE_TYPE_PREFERRED; + break; + } + + if (WARN_ON(!panel->override_mode.type)) + dev_err(dev, "Reject override mode: No display_timing found\n"); +} + +static const struct edp_panel_entry *find_edp_panel(u32 panel_id); + +static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) +{ + const struct edp_panel_entry *edp_panel; + struct panel_desc *desc; + u32 panel_id; + char vend[4]; + u16 product_id; + u32 reliable_ms = 0; + u32 absent_ms = 0; + int ret; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + panel->desc = desc; + + /* + * Read the dts properties for the initial probe. These are used by + * the runtime resume code which will get called by the + * pm_runtime_get_sync() call below. + */ + of_property_read_u32(dev->of_node, "hpd-reliable-delay-ms", &reliable_ms); + desc->delay.hpd_reliable = reliable_ms; + of_property_read_u32(dev->of_node, "hpd-absent-delay-ms", &absent_ms); + desc->delay.hpd_reliable = absent_ms; + + /* Power the panel on so we can read the EDID */ + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "Couldn't power on panel to read EDID: %d\n", ret); + goto exit; + } + + panel_id = drm_edid_get_panel_id(panel->ddc); + if (!panel_id) { + dev_err(dev, "Couldn't identify panel via EDID\n"); + ret = -EIO; + goto exit; + } + drm_edid_decode_panel_id(panel_id, vend, &product_id); + + edp_panel = find_edp_panel(panel_id); + + /* + * We're using non-optimized timings and want it really obvious that + * someone needs to add an entry to the table, so we'll do a WARN_ON + * splat. + */ + if (WARN_ON(!edp_panel)) { + dev_warn(dev, + "Unknown panel %s %#06x, using conservative timings\n", + vend, product_id); + + /* + * It's highly likely that the panel will work if we use very + * conservative timings, so let's do that. We already know that + * the HPD-related delays must have worked since we got this + * far, so we really just need the "unprepare" / "enable" + * delays. We don't need "prepare_to_enable" since that + * overlaps the "enable" delay anyway. + * + * Nearly all panels have a "unprepare" delay of 500 ms though + * there are a few with 1000. Let's stick 2000 in just to be + * super conservative. + * + * An "enable" delay of 80 ms seems the most common, but we'll + * throw in 200 ms to be safe. + */ + desc->delay.unprepare = 2000; + desc->delay.enable = 200; + } else { + dev_info(dev, "Detected %s %s (%#06x)\n", + vend, edp_panel->name, product_id); + + /* Update the delay; everything else comes from EDID */ + desc->delay = *edp_panel->delay; + } + + ret = 0; +exit: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static int panel_edp_probe(struct device *dev, const struct panel_desc *desc, + struct drm_dp_aux *aux) +{ + struct panel_edp *panel; + struct display_timing dt; + struct device_node *ddc; + int err; + + panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + panel->enabled = false; + panel->prepared_time = 0; + panel->desc = desc; + panel->aux = aux; + + panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd"); + if (!panel->no_hpd) { + err = panel_edp_get_hpd_gpio(dev, panel); + if (err) + return err; + } + + panel->supply = devm_regulator_get(dev, "power"); + if (IS_ERR(panel->supply)) + return PTR_ERR(panel->supply); + + panel->enable_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(panel->enable_gpio)) { + err = PTR_ERR(panel->enable_gpio); + if (err != -EPROBE_DEFER) + dev_err(dev, "failed to request GPIO: %d\n", err); + return err; + } + + err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation); + if (err) { + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err); + return err; + } + + ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); + if (ddc) { + panel->ddc = of_find_i2c_adapter_by_node(ddc); + of_node_put(ddc); + + if (!panel->ddc) + return -EPROBE_DEFER; + } else if (aux) { + panel->ddc = &aux->ddc; + } + + if (!of_get_display_timing(dev->of_node, "panel-timing", &dt)) + panel_edp_parse_panel_timing_node(dev, panel, &dt); + + 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; + + /* + * We use runtime PM for prepare / unprepare since those power the panel + * on and off and those can be very slow operations. This is important + * to optimize powering the panel on briefly to read the EDID before + * fully enabling the panel. + */ + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + + if (of_device_is_compatible(dev->of_node, "edp-panel")) { + err = generic_edp_panel_probe(dev, panel); + if (err) { + dev_err_probe(dev, err, + "Couldn't detect panel nor find a fallback\n"); + goto err_finished_pm_runtime; + } + /* generic_edp_panel_probe() replaces desc in the panel */ + desc = panel->desc; + } else if (desc->bpc != 6 && desc->bpc != 8 && desc->bpc != 10) { + dev_warn(dev, "Expected bpc in {6,8,10} but got: %u\n", desc->bpc); + } + + if (!panel->base.backlight && panel->aux) { + pm_runtime_get_sync(dev); + err = drm_panel_dp_aux_backlight(&panel->base, panel->aux); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (err) + goto err_finished_pm_runtime; + } + + drm_panel_add(&panel->base); + + return 0; + +err_finished_pm_runtime: + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); +err_finished_ddc_init: + if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) + put_device(&panel->ddc->dev); + + return err; +} + +static int panel_edp_remove(struct device *dev) +{ + struct panel_edp *panel = dev_get_drvdata(dev); + + drm_panel_remove(&panel->base); + drm_panel_disable(&panel->base); + drm_panel_unprepare(&panel->base); + + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) + put_device(&panel->ddc->dev); + + kfree(panel->edid); + panel->edid = NULL; + + return 0; +} + +static void panel_edp_shutdown(struct device *dev) +{ + struct panel_edp *panel = dev_get_drvdata(dev); + + drm_panel_disable(&panel->base); + drm_panel_unprepare(&panel->base); +} + +static const struct display_timing auo_b101ean01_timing = { + .pixelclock = { 65300000, 72500000, 75000000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 18, 119, 119 }, + .hback_porch = { 21, 21, 21 }, + .hsync_len = { 32, 32, 32 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 8, 8, 8 }, + .vsync_len = { 18, 20, 20 }, +}; + +static const struct panel_desc auo_b101ean01 = { + .timings = &auo_b101ean01_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 217, + .height = 136, + }, +}; + +static const struct drm_display_mode auo_b116xak01_mode = { + .clock = 69300, + .hdisplay = 1366, + .hsync_start = 1366 + 48, + .hsync_end = 1366 + 48 + 32, + .htotal = 1366 + 48 + 32 + 10, + .vdisplay = 768, + .vsync_start = 768 + 4, + .vsync_end = 768 + 4 + 6, + .vtotal = 768 + 4 + 6 + 15, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc auo_b116xak01 = { + .modes = &auo_b116xak01_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .hpd_absent = 200, + }, +}; + +static const struct drm_display_mode auo_b116xw03_mode = { + .clock = 70589, + .hdisplay = 1366, + .hsync_start = 1366 + 40, + .hsync_end = 1366 + 40 + 40, + .htotal = 1366 + 40 + 40 + 32, + .vdisplay = 768, + .vsync_start = 768 + 10, + .vsync_end = 768 + 10 + 12, + .vtotal = 768 + 10 + 12 + 6, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc auo_b116xw03 = { + .modes = &auo_b116xw03_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .enable = 400, + }, +}; + +static const struct drm_display_mode auo_b133han05_mode = { + .clock = 142600, + .hdisplay = 1920, + .hsync_start = 1920 + 58, + .hsync_end = 1920 + 58 + 42, + .htotal = 1920 + 58 + 42 + 60, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 5, + .vtotal = 1080 + 3 + 5 + 54, +}; + +static const struct panel_desc auo_b133han05 = { + .modes = &auo_b133han05_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 293, + .height = 165, + }, + .delay = { + .hpd_reliable = 100, + .enable = 20, + .unprepare = 50, + }, +}; + +static const struct drm_display_mode auo_b133htn01_mode = { + .clock = 150660, + .hdisplay = 1920, + .hsync_start = 1920 + 172, + .hsync_end = 1920 + 172 + 80, + .htotal = 1920 + 172 + 80 + 60, + .vdisplay = 1080, + .vsync_start = 1080 + 25, + .vsync_end = 1080 + 25 + 10, + .vtotal = 1080 + 25 + 10 + 10, +}; + +static const struct panel_desc auo_b133htn01 = { + .modes = &auo_b133htn01_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 293, + .height = 165, + }, + .delay = { + .hpd_reliable = 105, + .enable = 20, + .unprepare = 50, + }, +}; + +static const struct drm_display_mode auo_b133xtn01_mode = { + .clock = 69500, + .hdisplay = 1366, + .hsync_start = 1366 + 48, + .hsync_end = 1366 + 48 + 32, + .htotal = 1366 + 48 + 32 + 20, + .vdisplay = 768, + .vsync_start = 768 + 3, + .vsync_end = 768 + 3 + 6, + .vtotal = 768 + 3 + 6 + 13, +}; + +static const struct panel_desc auo_b133xtn01 = { + .modes = &auo_b133xtn01_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 293, + .height = 165, + }, +}; + +static const struct drm_display_mode auo_b140han06_mode = { + .clock = 141000, + .hdisplay = 1920, + .hsync_start = 1920 + 16, + .hsync_end = 1920 + 16 + 16, + .htotal = 1920 + 16 + 16 + 152, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 14, + .vtotal = 1080 + 3 + 14 + 19, +}; + +static const struct panel_desc auo_b140han06 = { + .modes = &auo_b140han06_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 309, + .height = 174, + }, + .delay = { + .hpd_reliable = 100, + .enable = 20, + .unprepare = 50, + }, +}; + +static const struct drm_display_mode boe_nv101wxmn51_modes[] = { + { + .clock = 71900, + .hdisplay = 1280, + .hsync_start = 1280 + 48, + .hsync_end = 1280 + 48 + 32, + .htotal = 1280 + 48 + 32 + 80, + .vdisplay = 800, + .vsync_start = 800 + 3, + .vsync_end = 800 + 3 + 5, + .vtotal = 800 + 3 + 5 + 24, + }, + { + .clock = 57500, + .hdisplay = 1280, + .hsync_start = 1280 + 48, + .hsync_end = 1280 + 48 + 32, + .htotal = 1280 + 48 + 32 + 80, + .vdisplay = 800, + .vsync_start = 800 + 3, + .vsync_end = 800 + 3 + 5, + .vtotal = 800 + 3 + 5 + 24, + }, +}; + +static const struct panel_desc boe_nv101wxmn51 = { + .modes = boe_nv101wxmn51_modes, + .num_modes = ARRAY_SIZE(boe_nv101wxmn51_modes), + .bpc = 8, + .size = { + .width = 217, + .height = 136, + }, + .delay = { + /* TODO: should be hpd-absent and no-hpd should be set? */ + .hpd_reliable = 210, + .enable = 50, + .unprepare = 160, + }, +}; + +static const struct drm_display_mode boe_nv110wtm_n61_modes[] = { + { + .clock = 207800, + .hdisplay = 2160, + .hsync_start = 2160 + 48, + .hsync_end = 2160 + 48 + 32, + .htotal = 2160 + 48 + 32 + 100, + .vdisplay = 1440, + .vsync_start = 1440 + 3, + .vsync_end = 1440 + 3 + 6, + .vtotal = 1440 + 3 + 6 + 31, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, + }, + { + .clock = 138500, + .hdisplay = 2160, + .hsync_start = 2160 + 48, + .hsync_end = 2160 + 48 + 32, + .htotal = 2160 + 48 + 32 + 100, + .vdisplay = 1440, + .vsync_start = 1440 + 3, + .vsync_end = 1440 + 3 + 6, + .vtotal = 1440 + 3 + 6 + 31, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, + }, +}; + +static const struct panel_desc boe_nv110wtm_n61 = { + .modes = boe_nv110wtm_n61_modes, + .num_modes = ARRAY_SIZE(boe_nv110wtm_n61_modes), + .bpc = 8, + .size = { + .width = 233, + .height = 155, + }, + .delay = { + .hpd_absent = 200, + .prepare_to_enable = 80, + .enable = 50, + .unprepare = 500, + }, +}; + +/* Also used for boe_nv133fhm_n62 */ +static const struct drm_display_mode boe_nv133fhm_n61_modes = { + .clock = 147840, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 1920 + 48 + 32 + 200, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 6, + .vtotal = 1080 + 3 + 6 + 31, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +/* Also used for boe_nv133fhm_n62 */ +static const struct panel_desc boe_nv133fhm_n61 = { + .modes = &boe_nv133fhm_n61_modes, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 294, + .height = 165, + }, + .delay = { + /* + * When power is first given to the panel there's a short + * spike on the HPD line. It was explained that this spike + * was until the TCON data download was complete. On + * one system this was measured at 8 ms. We'll put 15 ms + * in the prepare delay just to be safe. That means: + * - If HPD isn't hooked up you still have 200 ms delay. + * - If HPD is hooked up we won't try to look at it for the + * first 15 ms. + */ + .hpd_reliable = 15, + .hpd_absent = 200, + + .unprepare = 500, + }, +}; + +static const struct drm_display_mode boe_nv140fhmn49_modes[] = { + { + .clock = 148500, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 2200, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 5, + .vtotal = 1125, + }, +}; + +static const struct panel_desc boe_nv140fhmn49 = { + .modes = boe_nv140fhmn49_modes, + .num_modes = ARRAY_SIZE(boe_nv140fhmn49_modes), + .bpc = 6, + .size = { + .width = 309, + .height = 174, + }, + .delay = { + /* TODO: should be hpd-absent and no-hpd should be set? */ + .hpd_reliable = 210, + .enable = 50, + .unprepare = 160, + }, +}; + +static const struct drm_display_mode innolux_n116bca_ea1_mode = { + .clock = 76420, + .hdisplay = 1366, + .hsync_start = 1366 + 136, + .hsync_end = 1366 + 136 + 30, + .htotal = 1366 + 136 + 30 + 60, + .vdisplay = 768, + .vsync_start = 768 + 8, + .vsync_end = 768 + 8 + 12, + .vtotal = 768 + 8 + 12 + 12, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +static const struct panel_desc innolux_n116bca_ea1 = { + .modes = &innolux_n116bca_ea1_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .hpd_absent = 200, + .prepare_to_enable = 80, + .unprepare = 500, + }, +}; + +/* + * Datasheet specifies that at 60 Hz refresh rate: + * - total horizontal time: { 1506, 1592, 1716 } + * - total vertical time: { 788, 800, 868 } + * + * ...but doesn't go into exactly how that should be split into a front + * porch, back porch, or sync length. For now we'll leave a single setting + * here which allows a bit of tweaking of the pixel clock at the expense of + * refresh rate. + */ +static const struct display_timing innolux_n116bge_timing = { + .pixelclock = { 72600000, 76420000, 80240000 }, + .hactive = { 1366, 1366, 1366 }, + .hfront_porch = { 136, 136, 136 }, + .hback_porch = { 60, 60, 60 }, + .hsync_len = { 30, 30, 30 }, + .vactive = { 768, 768, 768 }, + .vfront_porch = { 8, 8, 8 }, + .vback_porch = { 12, 12, 12 }, + .vsync_len = { 12, 12, 12 }, + .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW, +}; + +static const struct panel_desc innolux_n116bge = { + .timings = &innolux_n116bge_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, +}; + +static const struct drm_display_mode innolux_n125hce_gn1_mode = { + .clock = 162000, + .hdisplay = 1920, + .hsync_start = 1920 + 40, + .hsync_end = 1920 + 40 + 40, + .htotal = 1920 + 40 + 40 + 80, + .vdisplay = 1080, + .vsync_start = 1080 + 4, + .vsync_end = 1080 + 4 + 4, + .vtotal = 1080 + 4 + 4 + 24, +}; + +static const struct panel_desc innolux_n125hce_gn1 = { + .modes = &innolux_n125hce_gn1_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 276, + .height = 155, + }, +}; + +static const struct drm_display_mode innolux_p120zdg_bf1_mode = { + .clock = 206016, + .hdisplay = 2160, + .hsync_start = 2160 + 48, + .hsync_end = 2160 + 48 + 32, + .htotal = 2160 + 48 + 32 + 80, + .vdisplay = 1440, + .vsync_start = 1440 + 3, + .vsync_end = 1440 + 3 + 10, + .vtotal = 1440 + 3 + 10 + 27, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc innolux_p120zdg_bf1 = { + .modes = &innolux_p120zdg_bf1_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 254, + .height = 169, + }, + .delay = { + .hpd_absent = 200, + .unprepare = 500, + }, +}; + +static const struct drm_display_mode ivo_m133nwf4_r0_mode = { + .clock = 138778, + .hdisplay = 1920, + .hsync_start = 1920 + 24, + .hsync_end = 1920 + 24 + 48, + .htotal = 1920 + 24 + 48 + 88, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 12, + .vtotal = 1080 + 3 + 12 + 17, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc ivo_m133nwf4_r0 = { + .modes = &ivo_m133nwf4_r0_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 294, + .height = 165, + }, + .delay = { + .hpd_absent = 200, + .unprepare = 500, + }, +}; + +static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = { + .clock = 81000, + .hdisplay = 1366, + .hsync_start = 1366 + 40, + .hsync_end = 1366 + 40 + 32, + .htotal = 1366 + 40 + 32 + 62, + .vdisplay = 768, + .vsync_start = 768 + 5, + .vsync_end = 768 + 5 + 5, + .vtotal = 768 + 5 + 5 + 122, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc kingdisplay_kd116n21_30nv_a010 = { + .modes = &kingdisplay_kd116n21_30nv_a010_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .hpd_absent = 200, + }, +}; + +static const struct drm_display_mode lg_lp079qx1_sp0v_mode = { + .clock = 200000, + .hdisplay = 1536, + .hsync_start = 1536 + 12, + .hsync_end = 1536 + 12 + 16, + .htotal = 1536 + 12 + 16 + 48, + .vdisplay = 2048, + .vsync_start = 2048 + 8, + .vsync_end = 2048 + 8 + 4, + .vtotal = 2048 + 8 + 4 + 8, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc lg_lp079qx1_sp0v = { + .modes = &lg_lp079qx1_sp0v_mode, + .num_modes = 1, + .size = { + .width = 129, + .height = 171, + }, +}; + +static const struct drm_display_mode lg_lp097qx1_spa1_mode = { + .clock = 205210, + .hdisplay = 2048, + .hsync_start = 2048 + 150, + .hsync_end = 2048 + 150 + 5, + .htotal = 2048 + 150 + 5 + 5, + .vdisplay = 1536, + .vsync_start = 1536 + 3, + .vsync_end = 1536 + 3 + 1, + .vtotal = 1536 + 3 + 1 + 9, +}; + +static const struct panel_desc lg_lp097qx1_spa1 = { + .modes = &lg_lp097qx1_spa1_mode, + .num_modes = 1, + .size = { + .width = 208, + .height = 147, + }, +}; + +static const struct drm_display_mode lg_lp120up1_mode = { + .clock = 162300, + .hdisplay = 1920, + .hsync_start = 1920 + 40, + .hsync_end = 1920 + 40 + 40, + .htotal = 1920 + 40 + 40 + 80, + .vdisplay = 1280, + .vsync_start = 1280 + 4, + .vsync_end = 1280 + 4 + 4, + .vtotal = 1280 + 4 + 4 + 12, +}; + +static const struct panel_desc lg_lp120up1 = { + .modes = &lg_lp120up1_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 267, + .height = 183, + }, +}; + +static const struct drm_display_mode lg_lp129qe_mode = { + .clock = 285250, + .hdisplay = 2560, + .hsync_start = 2560 + 48, + .hsync_end = 2560 + 48 + 32, + .htotal = 2560 + 48 + 32 + 80, + .vdisplay = 1700, + .vsync_start = 1700 + 3, + .vsync_end = 1700 + 3 + 10, + .vtotal = 1700 + 3 + 10 + 36, +}; + +static const struct panel_desc lg_lp129qe = { + .modes = &lg_lp129qe_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 272, + .height = 181, + }, +}; + +static const struct drm_display_mode neweast_wjfh116008a_modes[] = { + { + .clock = 138500, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 1920 + 48 + 32 + 80, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 5, + .vtotal = 1080 + 3 + 5 + 23, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, + }, { + .clock = 110920, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 1920 + 48 + 32 + 80, + .vdisplay = 1080, + .vsync_start = 1080 + 3, + .vsync_end = 1080 + 3 + 5, + .vtotal = 1080 + 3 + 5 + 23, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, + } +}; + +static const struct panel_desc neweast_wjfh116008a = { + .modes = neweast_wjfh116008a_modes, + .num_modes = 2, + .bpc = 6, + .size = { + .width = 260, + .height = 150, + }, + .delay = { + .hpd_reliable = 110, + .enable = 20, + .unprepare = 500, + }, +}; + +static const struct drm_display_mode samsung_lsn122dl01_c01_mode = { + .clock = 271560, + .hdisplay = 2560, + .hsync_start = 2560 + 48, + .hsync_end = 2560 + 48 + 32, + .htotal = 2560 + 48 + 32 + 80, + .vdisplay = 1600, + .vsync_start = 1600 + 2, + .vsync_end = 1600 + 2 + 5, + .vtotal = 1600 + 2 + 5 + 57, +}; + +static const struct panel_desc samsung_lsn122dl01_c01 = { + .modes = &samsung_lsn122dl01_c01_mode, + .num_modes = 1, + .size = { + .width = 263, + .height = 164, + }, +}; + +static const struct drm_display_mode samsung_ltn140at29_301_mode = { + .clock = 76300, + .hdisplay = 1366, + .hsync_start = 1366 + 64, + .hsync_end = 1366 + 64 + 48, + .htotal = 1366 + 64 + 48 + 128, + .vdisplay = 768, + .vsync_start = 768 + 2, + .vsync_end = 768 + 2 + 5, + .vtotal = 768 + 2 + 5 + 17, +}; + +static const struct panel_desc samsung_ltn140at29_301 = { + .modes = &samsung_ltn140at29_301_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 320, + .height = 187, + }, +}; + +static const struct drm_display_mode sharp_ld_d5116z01b_mode = { + .clock = 168480, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 1920 + 48 + 32 + 80, + .vdisplay = 1280, + .vsync_start = 1280 + 3, + .vsync_end = 1280 + 3 + 10, + .vtotal = 1280 + 3 + 10 + 57, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc sharp_ld_d5116z01b = { + .modes = &sharp_ld_d5116z01b_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 260, + .height = 120, + }, +}; + +static const struct display_timing sharp_lq123p1jx31_timing = { + .pixelclock = { 252750000, 252750000, 266604720 }, + .hactive = { 2400, 2400, 2400 }, + .hfront_porch = { 48, 48, 48 }, + .hback_porch = { 80, 80, 84 }, + .hsync_len = { 32, 32, 32 }, + .vactive = { 1600, 1600, 1600 }, + .vfront_porch = { 3, 3, 3 }, + .vback_porch = { 33, 33, 120 }, + .vsync_len = { 10, 10, 10 }, + .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW, +}; + +static const struct panel_desc sharp_lq123p1jx31 = { + .timings = &sharp_lq123p1jx31_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 259, + .height = 173, + }, + .delay = { + .hpd_reliable = 110, + .enable = 50, + .unprepare = 550, + }, +}; + +static const struct drm_display_mode starry_kr122ea0sra_mode = { + .clock = 147000, + .hdisplay = 1920, + .hsync_start = 1920 + 16, + .hsync_end = 1920 + 16 + 16, + .htotal = 1920 + 16 + 16 + 32, + .vdisplay = 1200, + .vsync_start = 1200 + 15, + .vsync_end = 1200 + 15 + 2, + .vtotal = 1200 + 15 + 2 + 18, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc starry_kr122ea0sra = { + .modes = &starry_kr122ea0sra_mode, + .num_modes = 1, + .size = { + .width = 263, + .height = 164, + }, + .delay = { + /* TODO: should be hpd-absent and no-hpd should be set? */ + .hpd_reliable = 10 + 200, + .enable = 50, + .unprepare = 10 + 500, + }, +}; + +static const struct of_device_id platform_of_match[] = { + { + /* Must be first */ + .compatible = "edp-panel", + }, { + .compatible = "auo,b101ean01", + .data = &auo_b101ean01, + }, { + .compatible = "auo,b116xa01", + .data = &auo_b116xak01, + }, { + .compatible = "auo,b116xw03", + .data = &auo_b116xw03, + }, { + .compatible = "auo,b133han05", + .data = &auo_b133han05, + }, { + .compatible = "auo,b133htn01", + .data = &auo_b133htn01, + }, { + .compatible = "auo,b133xtn01", + .data = &auo_b133xtn01, + }, { + .compatible = "auo,b140han06", + .data = &auo_b140han06, + }, { + .compatible = "boe,nv101wxmn51", + .data = &boe_nv101wxmn51, + }, { + .compatible = "boe,nv110wtm-n61", + .data = &boe_nv110wtm_n61, + }, { + .compatible = "boe,nv133fhm-n61", + .data = &boe_nv133fhm_n61, + }, { + .compatible = "boe,nv133fhm-n62", + .data = &boe_nv133fhm_n61, + }, { + .compatible = "boe,nv140fhmn49", + .data = &boe_nv140fhmn49, + }, { + .compatible = "innolux,n116bca-ea1", + .data = &innolux_n116bca_ea1, + }, { + .compatible = "innolux,n116bge", + .data = &innolux_n116bge, + }, { + .compatible = "innolux,n125hce-gn1", + .data = &innolux_n125hce_gn1, + }, { + .compatible = "innolux,p120zdg-bf1", + .data = &innolux_p120zdg_bf1, + }, { + .compatible = "ivo,m133nwf4-r0", + .data = &ivo_m133nwf4_r0, + }, { + .compatible = "kingdisplay,kd116n21-30nv-a010", + .data = &kingdisplay_kd116n21_30nv_a010, + }, { + .compatible = "lg,lp079qx1-sp0v", + .data = &lg_lp079qx1_sp0v, + }, { + .compatible = "lg,lp097qx1-spa1", + .data = &lg_lp097qx1_spa1, + }, { + .compatible = "lg,lp120up1", + .data = &lg_lp120up1, + }, { + .compatible = "lg,lp129qe", + .data = &lg_lp129qe, + }, { + .compatible = "neweast,wjfh116008a", + .data = &neweast_wjfh116008a, + }, { + .compatible = "samsung,lsn122dl01-c01", + .data = &samsung_lsn122dl01_c01, + }, { + .compatible = "samsung,ltn140at29-301", + .data = &samsung_ltn140at29_301, + }, { + .compatible = "sharp,ld-d5116z01b", + .data = &sharp_ld_d5116z01b, + }, { + .compatible = "sharp,lq123p1jx31", + .data = &sharp_lq123p1jx31, + }, { + .compatible = "starry,kr122ea0sra", + .data = &starry_kr122ea0sra, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, platform_of_match); + +static const struct panel_delay delay_200_500_p2e80 = { + .hpd_absent = 200, + .unprepare = 500, + .prepare_to_enable = 80, +}; + +static const struct panel_delay delay_200_500_p2e100 = { + .hpd_absent = 200, + .unprepare = 500, + .prepare_to_enable = 100, +}; + +static const struct panel_delay delay_200_500_e50 = { + .hpd_absent = 200, + .unprepare = 500, + .enable = 50, +}; + +#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ +{ \ + .name = _name, \ + .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \ + product_id), \ + .delay = _delay \ +} + +/* + * This table is used to figure out power sequencing delays for panels that + * are detected by EDID. Entries here may point to entries in the + * platform_of_match table (if a panel is listed in both places). + * + * Sort first by vendor, then by product ID. + */ +static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), + + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x082d, &boe_nv133fhm_n61.delay, "NV133FHM-N62"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"), + + EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"), + + EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), + + EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), + + { /* sentinal */ } +}; + +static const struct edp_panel_entry *find_edp_panel(u32 panel_id) +{ + const struct edp_panel_entry *panel; + + if (!panel_id) + return NULL; + + for (panel = edp_panels; panel->panel_id; panel++) + if (panel->panel_id == panel_id) + return panel; + + return NULL; +} + +static int panel_edp_platform_probe(struct platform_device *pdev) +{ + const struct of_device_id *id; + + /* Skip one since "edp-panel" is only supported on DP AUX bus */ + id = of_match_node(platform_of_match + 1, pdev->dev.of_node); + if (!id) + return -ENODEV; + + return panel_edp_probe(&pdev->dev, id->data, NULL); +} + +static int panel_edp_platform_remove(struct platform_device *pdev) +{ + return panel_edp_remove(&pdev->dev); +} + +static void panel_edp_platform_shutdown(struct platform_device *pdev) +{ + panel_edp_shutdown(&pdev->dev); +} + +static const struct dev_pm_ops panel_edp_pm_ops = { + SET_RUNTIME_PM_OPS(panel_edp_suspend, panel_edp_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver panel_edp_platform_driver = { + .driver = { + .name = "panel-edp", + .of_match_table = platform_of_match, + .pm = &panel_edp_pm_ops, + }, + .probe = panel_edp_platform_probe, + .remove = panel_edp_platform_remove, + .shutdown = panel_edp_platform_shutdown, +}; + +static int panel_edp_dp_aux_ep_probe(struct dp_aux_ep_device *aux_ep) +{ + const struct of_device_id *id; + + id = of_match_node(platform_of_match, aux_ep->dev.of_node); + if (!id) + return -ENODEV; + + return panel_edp_probe(&aux_ep->dev, id->data, aux_ep->aux); +} + +static void panel_edp_dp_aux_ep_remove(struct dp_aux_ep_device *aux_ep) +{ + panel_edp_remove(&aux_ep->dev); +} + +static void panel_edp_dp_aux_ep_shutdown(struct dp_aux_ep_device *aux_ep) +{ + panel_edp_shutdown(&aux_ep->dev); +} + +static struct dp_aux_ep_driver panel_edp_dp_aux_ep_driver = { + .driver = { + .name = "panel-simple-dp-aux", + .of_match_table = platform_of_match, /* Same as platform one! */ + .pm = &panel_edp_pm_ops, + }, + .probe = panel_edp_dp_aux_ep_probe, + .remove = panel_edp_dp_aux_ep_remove, + .shutdown = panel_edp_dp_aux_ep_shutdown, +}; + +static int __init panel_edp_init(void) +{ + int err; + + err = platform_driver_register(&panel_edp_platform_driver); + if (err < 0) + return err; + + err = dp_aux_dp_driver_register(&panel_edp_dp_aux_ep_driver); + if (err < 0) + goto err_did_platform_register; + + return 0; + +err_did_platform_register: + platform_driver_unregister(&panel_edp_platform_driver); + + return err; +} +module_init(panel_edp_init); + +static void __exit panel_edp_exit(void) +{ + dp_aux_dp_driver_unregister(&panel_edp_dp_aux_ep_driver); + platform_driver_unregister(&panel_edp_platform_driver); +} +module_exit(panel_edp_exit); + +MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); +MODULE_DESCRIPTION("DRM Driver for Simple eDP Panels"); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 0145129d7c66..534dd7414d42 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -590,14 +590,14 @@ static const struct drm_display_mode k101_im2byl02_default_mode = { .clock = 69700, .hdisplay = 800, - .hsync_start = 800 + 6, - .hsync_end = 800 + 6 + 15, - .htotal = 800 + 6 + 15 + 16, + .hsync_start = 800 + 52, + .hsync_end = 800 + 52 + 8, + .htotal = 800 + 52 + 8 + 48, .vdisplay = 1280, - .vsync_start = 1280 + 8, - .vsync_end = 1280 + 8 + 48, - .vtotal = 1280 + 8 + 48 + 52, + .vsync_start = 1280 + 16, + .vsync_end = 1280 + 16 + 6, + .vtotal = 1280 + 16 + 6 + 15, .width_mm = 135, .height_mm = 217, diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c index f80b44a8a700..dfb43b1374e7 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c @@ -60,6 +60,9 @@ #define MCS_CMD2_ENA1 0xFF00 /* Enable Access Command2 "CMD2" */ #define MCS_CMD2_ENA2 0xFF80 /* Enable Access Orise Command2 */ +#define OTM8009A_HDISPLAY 480 +#define OTM8009A_VDISPLAY 800 + struct otm8009a { struct device *dev; struct drm_panel panel; @@ -70,19 +73,35 @@ struct otm8009a { bool enabled; }; -static const struct drm_display_mode default_mode = { - .clock = 29700, - .hdisplay = 480, - .hsync_start = 480 + 98, - .hsync_end = 480 + 98 + 32, - .htotal = 480 + 98 + 32 + 98, - .vdisplay = 800, - .vsync_start = 800 + 15, - .vsync_end = 800 + 15 + 10, - .vtotal = 800 + 15 + 10 + 14, - .flags = 0, - .width_mm = 52, - .height_mm = 86, +static const struct drm_display_mode modes[] = { + { /* 50 Hz, preferred */ + .clock = 29700, + .hdisplay = 480, + .hsync_start = 480 + 98, + .hsync_end = 480 + 98 + 32, + .htotal = 480 + 98 + 32 + 98, + .vdisplay = 800, + .vsync_start = 800 + 15, + .vsync_end = 800 + 15 + 10, + .vtotal = 800 + 15 + 10 + 14, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + .width_mm = 52, + .height_mm = 86, + }, + { /* 60 Hz */ + .clock = 33000, + .hdisplay = 480, + .hsync_start = 480 + 70, + .hsync_end = 480 + 70 + 32, + .htotal = 480 + 70 + 32 + 72, + .vdisplay = 800, + .vsync_start = 800 + 15, + .vsync_end = 800 + 15 + 10, + .vtotal = 800 + 15 + 10 + 16, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + .width_mm = 52, + .height_mm = 86, + }, }; static inline struct otm8009a *panel_to_otm8009a(struct drm_panel *panel) @@ -208,12 +227,11 @@ static int otm8009a_init_sequence(struct otm8009a *ctx) /* Default portrait 480x800 rgb24 */ dcs_write_seq(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - ret = mipi_dsi_dcs_set_column_address(dsi, 0, - default_mode.hdisplay - 1); + ret = mipi_dsi_dcs_set_column_address(dsi, 0, OTM8009A_HDISPLAY - 1); if (ret) return ret; - ret = mipi_dsi_dcs_set_page_address(dsi, 0, default_mode.vdisplay - 1); + ret = mipi_dsi_dcs_set_page_address(dsi, 0, OTM8009A_VDISPLAY - 1); if (ret) return ret; @@ -337,24 +355,33 @@ static int otm8009a_get_modes(struct drm_panel *panel, struct drm_connector *connector) { struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->dev, &default_mode); - if (!mode) { - dev_err(panel->dev, "failed to add mode %ux%u@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); - return -ENOMEM; + unsigned int num_modes = ARRAY_SIZE(modes); + unsigned int i; + + for (i = 0; i < num_modes; i++) { + mode = drm_mode_duplicate(connector->dev, &modes[i]); + if (!mode) { + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + modes[i].hdisplay, + modes[i].vdisplay, + drm_mode_vrefresh(&modes[i])); + return -ENOMEM; + } + + mode->type = DRM_MODE_TYPE_DRIVER; + + /* Setting first mode as preferred */ + if (!i) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); } - drm_mode_set_name(mode); - - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, mode); - connector->display_info.width_mm = mode->width_mm; connector->display_info.height_mm = mode->height_mm; - return 1; + return num_modes; } static const struct drm_panel_funcs otm8009a_drm_funcs = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c new file mode 100644 index 000000000000..1696ceb36aa0 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Panel driver for the Samsung S6D27A1 480x800 DPI RGB panel. + * Found in the Samsung Galaxy Ace 2 GT-I8160 mobile phone. + */ + +#include <drm/drm_mipi_dbi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/media-bus-format.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#include <video/mipi_display.h> + +#define S6D27A1_PASSWD_L2 0xF0 /* Password Command for Level 2 Control */ +#define S6D27A1_RESCTL 0xB3 /* Resolution Select Control */ +#define S6D27A1_PANELCTL2 0xB4 /* ASG Signal Control */ +#define S6D27A1_READID1 0xDA /* Read panel ID 1 */ +#define S6D27A1_READID2 0xDB /* Read panel ID 2 */ +#define S6D27A1_READID3 0xDC /* Read panel ID 3 */ +#define S6D27A1_DISPCTL 0xF2 /* Display Control */ +#define S6D27A1_MANPWR 0xF3 /* Manual Control */ +#define S6D27A1_PWRCTL1 0xF4 /* Power Control */ +#define S6D27A1_SRCCTL 0xF6 /* Source Control */ +#define S6D27A1_PANELCTL 0xF7 /* Panel Control*/ + +static const u8 s6d27a1_dbi_read_commands[] = { + S6D27A1_READID1, + S6D27A1_READID2, + S6D27A1_READID3, + 0, /* sentinel */ +}; + +struct s6d27a1 { + struct device *dev; + struct mipi_dbi dbi; + struct drm_panel panel; + struct gpio_desc *reset; + struct regulator_bulk_data regulators[2]; +}; + +static const struct drm_display_mode s6d27a1_480_800_mode = { + /* + * The vendor driver states that the S6D27A1 panel + * has a pixel clock frequency of 49920000 Hz / 2 = 24960000 Hz. + */ + .clock = 24960, + .hdisplay = 480, + .hsync_start = 480 + 63, + .hsync_end = 480 + 63 + 2, + .htotal = 480 + 63 + 2 + 63, + .vdisplay = 800, + .vsync_start = 800 + 11, + .vsync_end = 800 + 11 + 2, + .vtotal = 800 + 11 + 2 + 10, + .width_mm = 50, + .height_mm = 84, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static inline struct s6d27a1 *to_s6d27a1(struct drm_panel *panel) +{ + return container_of(panel, struct s6d27a1, panel); +} + +static void s6d27a1_read_mtp_id(struct s6d27a1 *ctx) +{ + struct mipi_dbi *dbi = &ctx->dbi; + u8 id1, id2, id3; + int ret; + + ret = mipi_dbi_command_read(dbi, S6D27A1_READID1, &id1); + if (ret) { + dev_err(ctx->dev, "unable to read MTP ID 1\n"); + return; + } + ret = mipi_dbi_command_read(dbi, S6D27A1_READID2, &id2); + if (ret) { + dev_err(ctx->dev, "unable to read MTP ID 2\n"); + return; + } + ret = mipi_dbi_command_read(dbi, S6D27A1_READID3, &id3); + if (ret) { + dev_err(ctx->dev, "unable to read MTP ID 3\n"); + return; + } + dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3); +} + +static int s6d27a1_power_on(struct s6d27a1 *ctx) +{ + struct mipi_dbi *dbi = &ctx->dbi; + int ret; + + /* Power up */ + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->regulators), + ctx->regulators); + if (ret) { + dev_err(ctx->dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + msleep(20); + + /* Assert reset >=1 ms */ + gpiod_set_value_cansleep(ctx->reset, 1); + usleep_range(1000, 5000); + /* De-assert reset */ + gpiod_set_value_cansleep(ctx->reset, 0); + /* Wait >= 10 ms */ + msleep(20); + + /* + * Exit sleep mode and initialize display - some hammering is + * necessary. + */ + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); + msleep(120); + + /* Magic to unlock level 2 control of the display */ + mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0x5A, 0x5A); + + /* Configure resolution to 480RGBx800 */ + mipi_dbi_command(dbi, S6D27A1_RESCTL, 0x22); + + mipi_dbi_command(dbi, S6D27A1_PANELCTL2, 0x00, 0x02, 0x03, 0x04, 0x05, 0x08, 0x00, 0x0c); + + mipi_dbi_command(dbi, S6D27A1_MANPWR, 0x01, 0x00, 0x00, 0x08, 0x08, 0x02, 0x00); + + mipi_dbi_command(dbi, S6D27A1_DISPCTL, 0x19, 0x00, 0x08, 0x0D, 0x03, 0x41, 0x3F); + + mipi_dbi_command(dbi, S6D27A1_PWRCTL1, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x44, 0x05, 0x88, 0x4B, 0x50); + + mipi_dbi_command(dbi, S6D27A1_SRCCTL, 0x03, 0x09, 0x8A, 0x00, 0x01, 0x16); + + mipi_dbi_command(dbi, S6D27A1_PANELCTL, 0x00, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x09, 0x0D, 0x0A, 0x0E, + 0x0B, 0x0F, 0x0C, 0x10, 0x01, + 0x11, 0x12, 0x13, 0x14, 0x05, + 0x06, 0x07, 0x08, 0x01, 0x09, + 0x0D, 0x0A, 0x0E, 0x0B, 0x0F, + 0x0C, 0x10, 0x01, 0x11, 0x12, + 0x13, 0x14); + + /* lock the level 2 control */ + mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0xA5, 0xA5); + + s6d27a1_read_mtp_id(ctx); + + return 0; +} + +static int s6d27a1_power_off(struct s6d27a1 *ctx) +{ + /* Go into RESET and disable regulators */ + gpiod_set_value_cansleep(ctx->reset, 1); + return regulator_bulk_disable(ARRAY_SIZE(ctx->regulators), + ctx->regulators); +} + +static int s6d27a1_unprepare(struct drm_panel *panel) +{ + struct s6d27a1 *ctx = to_s6d27a1(panel); + struct mipi_dbi *dbi = &ctx->dbi; + + mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE); + msleep(120); + return s6d27a1_power_off(to_s6d27a1(panel)); +} + +static int s6d27a1_disable(struct drm_panel *panel) +{ + struct s6d27a1 *ctx = to_s6d27a1(panel); + struct mipi_dbi *dbi = &ctx->dbi; + + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); + msleep(25); + + return 0; +} + +static int s6d27a1_prepare(struct drm_panel *panel) +{ + return s6d27a1_power_on(to_s6d27a1(panel)); +} + +static int s6d27a1_enable(struct drm_panel *panel) +{ + struct s6d27a1 *ctx = to_s6d27a1(panel); + struct mipi_dbi *dbi = &ctx->dbi; + + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); + + return 0; +} + +static int s6d27a1_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct s6d27a1 *ctx = to_s6d27a1(panel); + struct drm_display_mode *mode; + static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; + + mode = drm_mode_duplicate(connector->dev, &s6d27a1_480_800_mode); + if (!mode) { + dev_err(ctx->dev, "failed to add mode\n"); + return -ENOMEM; + } + + connector->display_info.bpc = 8; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + connector->display_info.bus_flags = + DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; + drm_display_info_set_bus_formats(&connector->display_info, + &bus_format, 1); + + drm_mode_set_name(mode); + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + + return 1; +} + +static const struct drm_panel_funcs s6d27a1_drm_funcs = { + .disable = s6d27a1_disable, + .unprepare = s6d27a1_unprepare, + .prepare = s6d27a1_prepare, + .enable = s6d27a1_enable, + .get_modes = s6d27a1_get_modes, +}; + +static int s6d27a1_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct s6d27a1 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev = dev; + + /* + * VCI is the analog voltage supply + * VCCIO is the digital I/O voltage supply + */ + ctx->regulators[0].supply = "vci"; + ctx->regulators[1].supply = "vccio"; + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(ctx->regulators), + ctx->regulators); + if (ret) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + ctx->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset)) { + ret = PTR_ERR(ctx->reset); + return dev_err_probe(dev, ret, "no RESET GPIO\n"); + } + + ret = mipi_dbi_spi_init(spi, &ctx->dbi, NULL); + if (ret) + return dev_err_probe(dev, ret, "MIPI DBI init failed\n"); + + ctx->dbi.read_commands = s6d27a1_dbi_read_commands; + + drm_panel_init(&ctx->panel, dev, &s6d27a1_drm_funcs, + DRM_MODE_CONNECTOR_DPI); + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "failed to add backlight\n"); + + spi_set_drvdata(spi, ctx); + + drm_panel_add(&ctx->panel); + + return 0; +} + +static int s6d27a1_remove(struct spi_device *spi) +{ + struct s6d27a1 *ctx = spi_get_drvdata(spi); + + drm_panel_remove(&ctx->panel); + return 0; +} + +static const struct of_device_id s6d27a1_match[] = { + { .compatible = "samsung,s6d27a1", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, s6d27a1_match); + +static struct spi_driver s6d27a1_driver = { + .probe = s6d27a1_probe, + .remove = s6d27a1_remove, + .driver = { + .name = "s6d27a1-panel", + .of_match_table = s6d27a1_match, + }, +}; +module_spi_driver(s6d27a1_driver); + +MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>"); +MODULE_DESCRIPTION("Samsung S6D27A1 panel driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9b6c4e6c38a1..7f3e1b84b5f5 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -23,7 +23,6 @@ #include <linux/delay.h> #include <linux/gpio/consumer.h> -#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> @@ -36,8 +35,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_dp_aux_bus.h> -#include <drm/drm_dp_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> @@ -95,44 +92,6 @@ struct panel_desc { unsigned int prepare; /** - * @delay.hpd_absent_delay: Time to wait if HPD isn't hooked up. - * - * Add this to the prepare delay if we know Hot Plug Detect - * isn't used. - */ - unsigned int hpd_absent_delay; - - /** - * @delay.prepare_to_enable: Time between prepare and enable. - * - * The minimum time, in milliseconds, that needs to have passed - * between when prepare finished and enable may begin. If at - * enable time less time has passed since prepare finished, - * the driver waits for the remaining time. - * - * If a fixed enable delay is also specified, we'll start - * counting before delaying for the fixed delay. - * - * If a fixed prepare delay is also specified, we won't start - * counting until after the fixed delay. We can't overlap this - * fixed delay with the min time because the fixed delay - * doesn't happen at the end of the function if a HPD GPIO was - * specified. - * - * In other words: - * prepare() - * ... - * // do fixed prepare delay - * // wait for HPD GPIO if applicable - * // start counting for prepare_to_enable - * - * enable() - * // do fixed enable delay - * // enforce prepare_to_enable min time - */ - unsigned int prepare_to_enable; - - /** * @delay.enable: Time for the panel to display a valid frame. * * The time (in milliseconds) that it takes for the panel to @@ -176,7 +135,6 @@ struct panel_desc { struct panel_simple { struct drm_panel base; bool enabled; - bool no_hpd; bool prepared; @@ -187,10 +145,8 @@ struct panel_simple { struct regulator *supply; struct i2c_adapter *ddc; - struct drm_dp_aux *aux; struct gpio_desc *enable_gpio; - struct gpio_desc *hpd_gpio; struct edid *edid; @@ -374,30 +330,10 @@ static int panel_simple_unprepare(struct drm_panel *panel) return 0; } -static int panel_simple_get_hpd_gpio(struct device *dev, struct panel_simple *p) -{ - int err; - - p->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); - if (IS_ERR(p->hpd_gpio)) { - err = PTR_ERR(p->hpd_gpio); - - if (err != -EPROBE_DEFER) - dev_err(dev, "failed to get 'hpd' GPIO: %d\n", err); - - return err; - } - - return 0; -} - -static int panel_simple_prepare_once(struct panel_simple *p) +static int panel_simple_resume(struct device *dev) { - struct device *dev = p->base.dev; - unsigned int delay; + struct panel_simple *p = dev_get_drvdata(dev); int err; - int hpd_asserted; - unsigned long hpd_wait_us; panel_simple_wait(p->unprepared_time, p->desc->delay.unprepare); @@ -409,68 +345,12 @@ static int panel_simple_prepare_once(struct panel_simple *p) gpiod_set_value_cansleep(p->enable_gpio, 1); - delay = p->desc->delay.prepare; - if (p->no_hpd) - delay += p->desc->delay.hpd_absent_delay; - if (delay) - msleep(delay); - - if (p->hpd_gpio) { - if (p->desc->delay.hpd_absent_delay) - hpd_wait_us = p->desc->delay.hpd_absent_delay * 1000UL; - else - hpd_wait_us = 2000000; - - err = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio, - hpd_asserted, hpd_asserted, - 1000, hpd_wait_us); - if (hpd_asserted < 0) - err = hpd_asserted; - - if (err) { - if (err != -ETIMEDOUT) - dev_err(dev, - "error waiting for hpd GPIO: %d\n", err); - goto error; - } - } + if (p->desc->delay.prepare) + msleep(p->desc->delay.prepare); p->prepared_time = ktime_get(); return 0; - -error: - gpiod_set_value_cansleep(p->enable_gpio, 0); - regulator_disable(p->supply); - p->unprepared_time = ktime_get(); - - return err; -} - -/* - * Some panels simply don't always come up and need to be power cycled to - * work properly. We'll allow for a handful of retries. - */ -#define MAX_PANEL_PREPARE_TRIES 5 - -static int panel_simple_resume(struct device *dev) -{ - struct panel_simple *p = dev_get_drvdata(dev); - int ret; - int try; - - for (try = 0; try < MAX_PANEL_PREPARE_TRIES; try++) { - ret = panel_simple_prepare_once(p); - if (ret != -ETIMEDOUT) - break; - } - - if (ret == -ETIMEDOUT) - dev_err(dev, "Prepare timeout after %d tries\n", try); - else if (try) - dev_warn(dev, "Prepare needed %d retries\n", try); - - return ret; } static int panel_simple_prepare(struct drm_panel *panel) @@ -503,8 +383,6 @@ static int panel_simple_enable(struct drm_panel *panel) if (p->desc->delay.enable) msleep(p->desc->delay.enable); - panel_simple_wait(p->prepared_time, p->desc->delay.prepare_to_enable); - p->enabled = true; return 0; @@ -660,8 +538,7 @@ static void panel_simple_parse_panel_timing_node(struct device *dev, dev_err(dev, "Reject override mode: No display_timing found\n"); } -static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, - struct drm_dp_aux *aux) +static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) { struct panel_simple *panel; struct display_timing dt; @@ -677,14 +554,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, panel->enabled = false; panel->prepared_time = 0; panel->desc = desc; - panel->aux = aux; - - panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd"); - if (!panel->no_hpd) { - err = panel_simple_get_hpd_gpio(dev, panel); - if (err) - return err; - } panel->supply = devm_regulator_get(dev, "power"); if (IS_ERR(panel->supply)) @@ -712,8 +581,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, if (!panel->ddc) return -EPROBE_DEFER; - } else if (aux) { - panel->ddc = &aux->ddc; } if (desc == &panel_dpi) { @@ -749,9 +616,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, desc->bpc != 8); break; case DRM_MODE_CONNECTOR_eDP: - if (desc->bpc != 6 && desc->bpc != 8 && desc->bpc != 10) - dev_warn(dev, "Expected bpc in {6,8,10} but got: %u\n", desc->bpc); - break; + dev_warn(dev, "eDP panels moved to panel-edp\n"); + err = -EINVAL; + goto free_ddc; case DRM_MODE_CONNECTOR_DSI: if (desc->bpc != 6 && desc->bpc != 8) dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc); @@ -798,15 +665,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, if (err) goto disable_pm_runtime; - if (!panel->base.backlight && panel->aux) { - pm_runtime_get_sync(dev); - err = drm_panel_dp_aux_backlight(&panel->base, panel->aux); - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - if (err) - goto disable_pm_runtime; - } - drm_panel_add(&panel->base); return 0; @@ -815,7 +673,7 @@ disable_pm_runtime: pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); free_ddc: - if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) + if (panel->ddc) put_device(&panel->ddc->dev); return err; @@ -831,7 +689,7 @@ static int panel_simple_remove(struct device *dev) pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); - if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) + if (panel->ddc) put_device(&panel->ddc->dev); return 0; @@ -970,28 +828,6 @@ static const struct panel_desc auo_b101aw03 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct display_timing auo_b101ean01_timing = { - .pixelclock = { 65300000, 72500000, 75000000 }, - .hactive = { 1280, 1280, 1280 }, - .hfront_porch = { 18, 119, 119 }, - .hback_porch = { 21, 21, 21 }, - .hsync_len = { 32, 32, 32 }, - .vactive = { 800, 800, 800 }, - .vfront_porch = { 4, 4, 4 }, - .vback_porch = { 8, 8, 8 }, - .vsync_len = { 18, 20, 20 }, -}; - -static const struct panel_desc auo_b101ean01 = { - .timings = &auo_b101ean01_timing, - .num_timings = 1, - .bpc = 6, - .size = { - .width = 217, - .height = 136, - }, -}; - static const struct drm_display_mode auo_b101xtn01_mode = { .clock = 72000, .hdisplay = 1366, @@ -1015,172 +851,6 @@ static const struct panel_desc auo_b101xtn01 = { }, }; -static const struct drm_display_mode auo_b116xak01_mode = { - .clock = 69300, - .hdisplay = 1366, - .hsync_start = 1366 + 48, - .hsync_end = 1366 + 48 + 32, - .htotal = 1366 + 48 + 32 + 10, - .vdisplay = 768, - .vsync_start = 768 + 4, - .vsync_end = 768 + 4 + 6, - .vtotal = 768 + 4 + 6 + 15, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc auo_b116xak01 = { - .modes = &auo_b116xak01_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .delay = { - .hpd_absent_delay = 200, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode auo_b116xw03_mode = { - .clock = 70589, - .hdisplay = 1366, - .hsync_start = 1366 + 40, - .hsync_end = 1366 + 40 + 40, - .htotal = 1366 + 40 + 40 + 32, - .vdisplay = 768, - .vsync_start = 768 + 10, - .vsync_end = 768 + 10 + 12, - .vtotal = 768 + 10 + 12 + 6, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc auo_b116xw03 = { - .modes = &auo_b116xw03_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .delay = { - .enable = 400, - }, - .bus_flags = DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode auo_b133xtn01_mode = { - .clock = 69500, - .hdisplay = 1366, - .hsync_start = 1366 + 48, - .hsync_end = 1366 + 48 + 32, - .htotal = 1366 + 48 + 32 + 20, - .vdisplay = 768, - .vsync_start = 768 + 3, - .vsync_end = 768 + 3 + 6, - .vtotal = 768 + 3 + 6 + 13, -}; - -static const struct panel_desc auo_b133xtn01 = { - .modes = &auo_b133xtn01_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 293, - .height = 165, - }, -}; - -static const struct drm_display_mode auo_b133han05_mode = { - .clock = 142600, - .hdisplay = 1920, - .hsync_start = 1920 + 58, - .hsync_end = 1920 + 58 + 42, - .htotal = 1920 + 58 + 42 + 60, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 54, -}; - -static const struct panel_desc auo_b133han05 = { - .modes = &auo_b133han05_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 293, - .height = 165, - }, - .delay = { - .prepare = 100, - .enable = 20, - .unprepare = 50, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode auo_b133htn01_mode = { - .clock = 150660, - .hdisplay = 1920, - .hsync_start = 1920 + 172, - .hsync_end = 1920 + 172 + 80, - .htotal = 1920 + 172 + 80 + 60, - .vdisplay = 1080, - .vsync_start = 1080 + 25, - .vsync_end = 1080 + 25 + 10, - .vtotal = 1080 + 25 + 10 + 10, -}; - -static const struct panel_desc auo_b133htn01 = { - .modes = &auo_b133htn01_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 293, - .height = 165, - }, - .delay = { - .prepare = 105, - .enable = 20, - .unprepare = 50, - }, -}; - -static const struct drm_display_mode auo_b140han06_mode = { - .clock = 141000, - .hdisplay = 1920, - .hsync_start = 1920 + 16, - .hsync_end = 1920 + 16 + 16, - .htotal = 1920 + 16 + 16 + 152, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 14, - .vtotal = 1080 + 3 + 14 + 19, -}; - -static const struct panel_desc auo_b140han06 = { - .modes = &auo_b140han06_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 309, - .height = 174, - }, - .delay = { - .prepare = 100, - .enable = 20, - .unprepare = 50, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct display_timing auo_g070vvn01_timings = { .pixelclock = { 33300000, 34209000, 45000000 }, .hactive = { 800, 800, 800 }, @@ -1524,169 +1194,6 @@ static const struct panel_desc boe_hv070wsa = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode boe_nv101wxmn51_modes[] = { - { - .clock = 71900, - .hdisplay = 1280, - .hsync_start = 1280 + 48, - .hsync_end = 1280 + 48 + 32, - .htotal = 1280 + 48 + 32 + 80, - .vdisplay = 800, - .vsync_start = 800 + 3, - .vsync_end = 800 + 3 + 5, - .vtotal = 800 + 3 + 5 + 24, - }, - { - .clock = 57500, - .hdisplay = 1280, - .hsync_start = 1280 + 48, - .hsync_end = 1280 + 48 + 32, - .htotal = 1280 + 48 + 32 + 80, - .vdisplay = 800, - .vsync_start = 800 + 3, - .vsync_end = 800 + 3 + 5, - .vtotal = 800 + 3 + 5 + 24, - }, -}; - -static const struct panel_desc boe_nv101wxmn51 = { - .modes = boe_nv101wxmn51_modes, - .num_modes = ARRAY_SIZE(boe_nv101wxmn51_modes), - .bpc = 8, - .size = { - .width = 217, - .height = 136, - }, - .delay = { - .prepare = 210, - .enable = 50, - .unprepare = 160, - }, -}; - -static const struct drm_display_mode boe_nv110wtm_n61_modes[] = { - { - .clock = 207800, - .hdisplay = 2160, - .hsync_start = 2160 + 48, - .hsync_end = 2160 + 48 + 32, - .htotal = 2160 + 48 + 32 + 100, - .vdisplay = 1440, - .vsync_start = 1440 + 3, - .vsync_end = 1440 + 3 + 6, - .vtotal = 1440 + 3 + 6 + 31, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, - }, - { - .clock = 138500, - .hdisplay = 2160, - .hsync_start = 2160 + 48, - .hsync_end = 2160 + 48 + 32, - .htotal = 2160 + 48 + 32 + 100, - .vdisplay = 1440, - .vsync_start = 1440 + 3, - .vsync_end = 1440 + 3 + 6, - .vtotal = 1440 + 3 + 6 + 31, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, - }, -}; - -static const struct panel_desc boe_nv110wtm_n61 = { - .modes = boe_nv110wtm_n61_modes, - .num_modes = ARRAY_SIZE(boe_nv110wtm_n61_modes), - .bpc = 8, - .size = { - .width = 233, - .height = 155, - }, - .delay = { - .hpd_absent_delay = 200, - .prepare_to_enable = 80, - .enable = 50, - .unprepare = 500, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -/* Also used for boe_nv133fhm_n62 */ -static const struct drm_display_mode boe_nv133fhm_n61_modes = { - .clock = 147840, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 200, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 6, - .vtotal = 1080 + 3 + 6 + 31, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, -}; - -/* Also used for boe_nv133fhm_n62 */ -static const struct panel_desc boe_nv133fhm_n61 = { - .modes = &boe_nv133fhm_n61_modes, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 294, - .height = 165, - }, - .delay = { - /* - * When power is first given to the panel there's a short - * spike on the HPD line. It was explained that this spike - * was until the TCON data download was complete. On - * one system this was measured at 8 ms. We'll put 15 ms - * in the prepare delay just to be safe and take it away - * from the hpd_absent_delay (which would otherwise be 200 ms) - * to handle this. That means: - * - If HPD isn't hooked up you still have 200 ms delay. - * - If HPD is hooked up we won't try to look at it for the - * first 15 ms. - */ - .prepare = 15, - .hpd_absent_delay = 185, - - .unprepare = 500, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode boe_nv140fhmn49_modes[] = { - { - .clock = 148500, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 2200, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1125, - }, -}; - -static const struct panel_desc boe_nv140fhmn49 = { - .modes = boe_nv140fhmn49_modes, - .num_modes = ARRAY_SIZE(boe_nv140fhmn49_modes), - .bpc = 6, - .size = { - .width = 309, - .height = 174, - }, - .delay = { - .prepare = 210, - .enable = 50, - .unprepare = 160, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct drm_display_mode cdtech_s043wq26h_ct7_mode = { .clock = 9000, .hdisplay = 480, @@ -2609,96 +2116,6 @@ static const struct panel_desc innolux_g121x1_l03 = { }, }; -static const struct drm_display_mode innolux_n116bca_ea1_mode = { - .clock = 76420, - .hdisplay = 1366, - .hsync_start = 1366 + 136, - .hsync_end = 1366 + 136 + 30, - .htotal = 1366 + 136 + 30 + 60, - .vdisplay = 768, - .vsync_start = 768 + 8, - .vsync_end = 768 + 8 + 12, - .vtotal = 768 + 8 + 12 + 12, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, -}; - -static const struct panel_desc innolux_n116bca_ea1 = { - .modes = &innolux_n116bca_ea1_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .delay = { - .hpd_absent_delay = 200, - .prepare_to_enable = 80, - .unprepare = 500, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -/* - * Datasheet specifies that at 60 Hz refresh rate: - * - total horizontal time: { 1506, 1592, 1716 } - * - total vertical time: { 788, 800, 868 } - * - * ...but doesn't go into exactly how that should be split into a front - * porch, back porch, or sync length. For now we'll leave a single setting - * here which allows a bit of tweaking of the pixel clock at the expense of - * refresh rate. - */ -static const struct display_timing innolux_n116bge_timing = { - .pixelclock = { 72600000, 76420000, 80240000 }, - .hactive = { 1366, 1366, 1366 }, - .hfront_porch = { 136, 136, 136 }, - .hback_porch = { 60, 60, 60 }, - .hsync_len = { 30, 30, 30 }, - .vactive = { 768, 768, 768 }, - .vfront_porch = { 8, 8, 8 }, - .vback_porch = { 12, 12, 12 }, - .vsync_len = { 12, 12, 12 }, - .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW, -}; - -static const struct panel_desc innolux_n116bge = { - .timings = &innolux_n116bge_timing, - .num_timings = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode innolux_n125hce_gn1_mode = { - .clock = 162000, - .hdisplay = 1920, - .hsync_start = 1920 + 40, - .hsync_end = 1920 + 40 + 40, - .htotal = 1920 + 40 + 40 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 4, - .vsync_end = 1080 + 4 + 4, - .vtotal = 1080 + 4 + 4 + 24, -}; - -static const struct panel_desc innolux_n125hce_gn1 = { - .modes = &innolux_n125hce_gn1_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 276, - .height = 155, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct drm_display_mode innolux_n156bge_l21_mode = { .clock = 69300, .hdisplay = 1366, @@ -2724,33 +2141,6 @@ static const struct panel_desc innolux_n156bge_l21 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode innolux_p120zdg_bf1_mode = { - .clock = 206016, - .hdisplay = 2160, - .hsync_start = 2160 + 48, - .hsync_end = 2160 + 48 + 32, - .htotal = 2160 + 48 + 32 + 80, - .vdisplay = 1440, - .vsync_start = 1440 + 3, - .vsync_end = 1440 + 3 + 10, - .vtotal = 1440 + 3 + 10 + 27, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, -}; - -static const struct panel_desc innolux_p120zdg_bf1 = { - .modes = &innolux_p120zdg_bf1_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 254, - .height = 169, - }, - .delay = { - .hpd_absent_delay = 200, - .unprepare = 500, - }, -}; - static const struct drm_display_mode innolux_zj070na_01p_mode = { .clock = 51501, .hdisplay = 1024, @@ -2773,64 +2163,6 @@ static const struct panel_desc innolux_zj070na_01p = { }, }; -static const struct drm_display_mode ivo_m133nwf4_r0_mode = { - .clock = 138778, - .hdisplay = 1920, - .hsync_start = 1920 + 24, - .hsync_end = 1920 + 24 + 48, - .htotal = 1920 + 24 + 48 + 88, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 12, - .vtotal = 1080 + 3 + 12 + 17, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, -}; - -static const struct panel_desc ivo_m133nwf4_r0 = { - .modes = &ivo_m133nwf4_r0_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 294, - .height = 165, - }, - .delay = { - .hpd_absent_delay = 200, - .unprepare = 500, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = { - .clock = 81000, - .hdisplay = 1366, - .hsync_start = 1366 + 40, - .hsync_end = 1366 + 40 + 32, - .htotal = 1366 + 40 + 32 + 62, - .vdisplay = 768, - .vsync_start = 768 + 5, - .vsync_end = 768 + 5 + 5, - .vtotal = 768 + 5 + 5 + 122, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc kingdisplay_kd116n21_30nv_a010 = { - .modes = &kingdisplay_kd116n21_30nv_a010_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .delay = { - .hpd_absent_delay = 200, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct display_timing koe_tx14d24vm1bpa_timing = { .pixelclock = { 5580000, 5850000, 6200000 }, .hactive = { 320, 320, 320 }, @@ -2982,94 +2314,6 @@ static const struct panel_desc lg_lb070wv8 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode lg_lp079qx1_sp0v_mode = { - .clock = 200000, - .hdisplay = 1536, - .hsync_start = 1536 + 12, - .hsync_end = 1536 + 12 + 16, - .htotal = 1536 + 12 + 16 + 48, - .vdisplay = 2048, - .vsync_start = 2048 + 8, - .vsync_end = 2048 + 8 + 4, - .vtotal = 2048 + 8 + 4 + 8, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc lg_lp079qx1_sp0v = { - .modes = &lg_lp079qx1_sp0v_mode, - .num_modes = 1, - .size = { - .width = 129, - .height = 171, - }, -}; - -static const struct drm_display_mode lg_lp097qx1_spa1_mode = { - .clock = 205210, - .hdisplay = 2048, - .hsync_start = 2048 + 150, - .hsync_end = 2048 + 150 + 5, - .htotal = 2048 + 150 + 5 + 5, - .vdisplay = 1536, - .vsync_start = 1536 + 3, - .vsync_end = 1536 + 3 + 1, - .vtotal = 1536 + 3 + 1 + 9, -}; - -static const struct panel_desc lg_lp097qx1_spa1 = { - .modes = &lg_lp097qx1_spa1_mode, - .num_modes = 1, - .size = { - .width = 208, - .height = 147, - }, -}; - -static const struct drm_display_mode lg_lp120up1_mode = { - .clock = 162300, - .hdisplay = 1920, - .hsync_start = 1920 + 40, - .hsync_end = 1920 + 40 + 40, - .htotal = 1920 + 40 + 40+ 80, - .vdisplay = 1280, - .vsync_start = 1280 + 4, - .vsync_end = 1280 + 4 + 4, - .vtotal = 1280 + 4 + 4 + 12, -}; - -static const struct panel_desc lg_lp120up1 = { - .modes = &lg_lp120up1_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 267, - .height = 183, - }, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - -static const struct drm_display_mode lg_lp129qe_mode = { - .clock = 285250, - .hdisplay = 2560, - .hsync_start = 2560 + 48, - .hsync_end = 2560 + 48 + 32, - .htotal = 2560 + 48 + 32 + 80, - .vdisplay = 1700, - .vsync_start = 1700 + 3, - .vsync_end = 1700 + 3 + 10, - .vtotal = 1700 + 3 + 10 + 36, -}; - -static const struct panel_desc lg_lp129qe = { - .modes = &lg_lp129qe_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 272, - .height = 181, - }, -}; - static const struct display_timing logictechno_lt161010_2nh_timing = { .pixelclock = { 26400000, 33300000, 46800000 }, .hactive = { 800, 800, 800 }, @@ -3158,19 +2402,6 @@ static const struct panel_desc logictechno_lttd800480070_l6wh_rt = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; -static const struct drm_display_mode mitsubishi_aa070mc01_mode = { - .clock = 30400, - .hdisplay = 800, - .hsync_start = 800 + 0, - .hsync_end = 800 + 1, - .htotal = 800 + 0 + 1 + 160, - .vdisplay = 480, - .vsync_start = 480 + 0, - .vsync_end = 480 + 48 + 1, - .vtotal = 480 + 48 + 1 + 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, -}; - static const struct drm_display_mode logicpd_type_28_mode = { .clock = 9107, .hdisplay = 480, @@ -3205,6 +2436,19 @@ static const struct panel_desc logicpd_type_28 = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; +static const struct drm_display_mode mitsubishi_aa070mc01_mode = { + .clock = 30400, + .hdisplay = 800, + .hsync_start = 800 + 0, + .hsync_end = 800 + 1, + .htotal = 800 + 0 + 1 + 160, + .vdisplay = 480, + .vsync_start = 480 + 0, + .vsync_end = 480 + 48 + 1, + .vtotal = 480 + 48 + 1 + 0, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + static const struct panel_desc mitsubishi_aa070mc01 = { .modes = &mitsubishi_aa070mc01_mode, .num_modes = 1, @@ -3330,49 +2574,6 @@ static const struct panel_desc netron_dy_e231732 = { .bus_format = MEDIA_BUS_FMT_RGB666_1X18, }; -static const struct drm_display_mode neweast_wjfh116008a_modes[] = { - { - .clock = 138500, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 23, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, - }, { - .clock = 110920, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 23, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, - } -}; - -static const struct panel_desc neweast_wjfh116008a = { - .modes = neweast_wjfh116008a_modes, - .num_modes = 2, - .bpc = 6, - .size = { - .width = 260, - .height = 150, - }, - .delay = { - .prepare = 110, - .enable = 20, - .unprepare = 500, - }, - .bus_format = MEDIA_BUS_FMT_RGB666_1X18, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct drm_display_mode newhaven_nhd_43_480272ef_atxl_mode = { .clock = 9000, .hdisplay = 480, @@ -3783,27 +2984,6 @@ static const struct panel_desc rocktech_rk101ii01d_ct = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode samsung_lsn122dl01_c01_mode = { - .clock = 271560, - .hdisplay = 2560, - .hsync_start = 2560 + 48, - .hsync_end = 2560 + 48 + 32, - .htotal = 2560 + 48 + 32 + 80, - .vdisplay = 1600, - .vsync_start = 1600 + 2, - .vsync_end = 1600 + 2 + 5, - .vtotal = 1600 + 2 + 5 + 57, -}; - -static const struct panel_desc samsung_lsn122dl01_c01 = { - .modes = &samsung_lsn122dl01_c01_mode, - .num_modes = 1, - .size = { - .width = 263, - .height = 164, - }, -}; - static const struct drm_display_mode samsung_ltn101nt05_mode = { .clock = 54030, .hdisplay = 1024, @@ -3829,28 +3009,6 @@ static const struct panel_desc samsung_ltn101nt05 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode samsung_ltn140at29_301_mode = { - .clock = 76300, - .hdisplay = 1366, - .hsync_start = 1366 + 64, - .hsync_end = 1366 + 64 + 48, - .htotal = 1366 + 64 + 48 + 128, - .vdisplay = 768, - .vsync_start = 768 + 2, - .vsync_end = 768 + 2 + 5, - .vtotal = 768 + 2 + 5 + 17, -}; - -static const struct panel_desc samsung_ltn140at29_301 = { - .modes = &samsung_ltn140at29_301_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 320, - .height = 187, - }, -}; - static const struct display_timing satoz_sat050at40h12r2_timing = { .pixelclock = {33300000, 33300000, 50000000}, .hactive = {800, 800, 800}, @@ -3875,31 +3033,6 @@ static const struct panel_desc satoz_sat050at40h12r2 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode sharp_ld_d5116z01b_mode = { - .clock = 168480, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1280, - .vsync_start = 1280 + 3, - .vsync_end = 1280 + 3 + 10, - .vtotal = 1280 + 3 + 10 + 57, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, -}; - -static const struct panel_desc sharp_ld_d5116z01b = { - .modes = &sharp_ld_d5116z01b_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 260, - .height = 120, - }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, - .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, -}; - static const struct drm_display_mode sharp_lq070y3dg3b_mode = { .clock = 33260, .hdisplay = 800, @@ -3974,34 +3107,6 @@ static const struct panel_desc sharp_lq101k1ly04 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct display_timing sharp_lq123p1jx31_timing = { - .pixelclock = { 252750000, 252750000, 266604720 }, - .hactive = { 2400, 2400, 2400 }, - .hfront_porch = { 48, 48, 48 }, - .hback_porch = { 80, 80, 84 }, - .hsync_len = { 32, 32, 32 }, - .vactive = { 1600, 1600, 1600 }, - .vfront_porch = { 3, 3, 3 }, - .vback_porch = { 33, 33, 120 }, - .vsync_len = { 10, 10, 10 }, - .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW, -}; - -static const struct panel_desc sharp_lq123p1jx31 = { - .timings = &sharp_lq123p1jx31_timing, - .num_timings = 1, - .bpc = 8, - .size = { - .width = 259, - .height = 173, - }, - .delay = { - .prepare = 110, - .enable = 50, - .unprepare = 550, - }, -}; - static const struct drm_display_mode sharp_ls020b1dd01d_modes[] = { { /* 50 Hz */ .clock = 3000, @@ -4090,33 +3195,6 @@ static const struct panel_desc starry_kr070pe2t = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; -static const struct drm_display_mode starry_kr122ea0sra_mode = { - .clock = 147000, - .hdisplay = 1920, - .hsync_start = 1920 + 16, - .hsync_end = 1920 + 16 + 16, - .htotal = 1920 + 16 + 16 + 32, - .vdisplay = 1200, - .vsync_start = 1200 + 15, - .vsync_end = 1200 + 15 + 2, - .vtotal = 1200 + 15 + 2 + 18, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc starry_kr122ea0sra = { - .modes = &starry_kr122ea0sra_mode, - .num_modes = 1, - .size = { - .width = 263, - .height = 164, - }, - .delay = { - .prepare = 10 + 200, - .enable = 50, - .unprepare = 10 + 500, - }, -}; - static const struct drm_display_mode tfc_s9700rtwv43tr_01b_mode = { .clock = 30000, .hdisplay = 800, @@ -4484,30 +3562,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "auo,b101aw03", .data = &auo_b101aw03, }, { - .compatible = "auo,b101ean01", - .data = &auo_b101ean01, - }, { .compatible = "auo,b101xtn01", .data = &auo_b101xtn01, }, { - .compatible = "auo,b116xa01", - .data = &auo_b116xak01, - }, { - .compatible = "auo,b116xw03", - .data = &auo_b116xw03, - }, { - .compatible = "auo,b133han05", - .data = &auo_b133han05, - }, { - .compatible = "auo,b133htn01", - .data = &auo_b133htn01, - }, { - .compatible = "auo,b140han06", - .data = &auo_b140han06, - }, { - .compatible = "auo,b133xtn01", - .data = &auo_b133xtn01, - }, { .compatible = "auo,g070vvn01", .data = &auo_g070vvn01, }, { @@ -4547,21 +3604,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "boe,hv070wsa-100", .data = &boe_hv070wsa }, { - .compatible = "boe,nv101wxmn51", - .data = &boe_nv101wxmn51, - }, { - .compatible = "boe,nv110wtm-n61", - .data = &boe_nv110wtm_n61, - }, { - .compatible = "boe,nv133fhm-n61", - .data = &boe_nv133fhm_n61, - }, { - .compatible = "boe,nv133fhm-n62", - .data = &boe_nv133fhm_n61, - }, { - .compatible = "boe,nv140fhmn49", - .data = &boe_nv140fhmn49, - }, { .compatible = "cdtech,s043wq26h-ct7", .data = &cdtech_s043wq26h_ct7, }, { @@ -4673,30 +3715,12 @@ static const struct of_device_id platform_of_match[] = { .compatible = "innolux,g121x1-l03", .data = &innolux_g121x1_l03, }, { - .compatible = "innolux,n116bca-ea1", - .data = &innolux_n116bca_ea1, - }, { - .compatible = "innolux,n116bge", - .data = &innolux_n116bge, - }, { - .compatible = "innolux,n125hce-gn1", - .data = &innolux_n125hce_gn1, - }, { .compatible = "innolux,n156bge-l21", .data = &innolux_n156bge_l21, }, { - .compatible = "innolux,p120zdg-bf1", - .data = &innolux_p120zdg_bf1, - }, { .compatible = "innolux,zj070na-01p", .data = &innolux_zj070na_01p, }, { - .compatible = "ivo,m133nwf4-r0", - .data = &ivo_m133nwf4_r0, - }, { - .compatible = "kingdisplay,kd116n21-30nv-a010", - .data = &kingdisplay_kd116n21_30nv_a010, - }, { .compatible = "koe,tx14d24vm1bpa", .data = &koe_tx14d24vm1bpa, }, { @@ -4715,18 +3739,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "lg,lb070wv8", .data = &lg_lb070wv8, }, { - .compatible = "lg,lp079qx1-sp0v", - .data = &lg_lp079qx1_sp0v, - }, { - .compatible = "lg,lp097qx1-spa1", - .data = &lg_lp097qx1_spa1, - }, { - .compatible = "lg,lp120up1", - .data = &lg_lp120up1, - }, { - .compatible = "lg,lp129qe", - .data = &lg_lp129qe, - }, { .compatible = "logicpd,type28", .data = &logicpd_type_28, }, { @@ -4757,9 +3769,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "netron-dy,e231732", .data = &netron_dy_e231732, }, { - .compatible = "neweast,wjfh116008a", - .data = &neweast_wjfh116008a, - }, { .compatible = "newhaven,nhd-4.3-480272ef-atxl", .data = &newhaven_nhd_43_480272ef_atxl, }, { @@ -4808,21 +3817,12 @@ static const struct of_device_id platform_of_match[] = { .compatible = "rocktech,rk101ii01d-ct", .data = &rocktech_rk101ii01d_ct, }, { - .compatible = "samsung,lsn122dl01-c01", - .data = &samsung_lsn122dl01_c01, - }, { .compatible = "samsung,ltn101nt05", .data = &samsung_ltn101nt05, }, { - .compatible = "samsung,ltn140at29-301", - .data = &samsung_ltn140at29_301, - }, { .compatible = "satoz,sat050at40h12r2", .data = &satoz_sat050at40h12r2, }, { - .compatible = "sharp,ld-d5116z01b", - .data = &sharp_ld_d5116z01b, - }, { .compatible = "sharp,lq035q7db03", .data = &sharp_lq035q7db03, }, { @@ -4832,9 +3832,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "sharp,lq101k1ly04", .data = &sharp_lq101k1ly04, }, { - .compatible = "sharp,lq123p1jx31", - .data = &sharp_lq123p1jx31, - }, { .compatible = "sharp,ls020b1dd01d", .data = &sharp_ls020b1dd01d, }, { @@ -4844,9 +3841,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "starry,kr070pe2t", .data = &starry_kr070pe2t, }, { - .compatible = "starry,kr122ea0sra", - .data = &starry_kr122ea0sra, - }, { .compatible = "tfc,s9700rtwv43tr-01b", .data = &tfc_s9700rtwv43tr_01b, }, { @@ -4918,7 +3912,7 @@ static int panel_simple_platform_probe(struct platform_device *pdev) if (!id) return -ENODEV; - return panel_simple_probe(&pdev->dev, id->data, NULL); + return panel_simple_probe(&pdev->dev, id->data); } static int panel_simple_platform_remove(struct platform_device *pdev) @@ -5198,7 +4192,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) desc = id->data; - err = panel_simple_probe(&dsi->dev, &desc->desc, NULL); + err = panel_simple_probe(&dsi->dev, &desc->desc); if (err < 0) return err; @@ -5243,38 +4237,6 @@ static struct mipi_dsi_driver panel_simple_dsi_driver = { .shutdown = panel_simple_dsi_shutdown, }; -static int panel_simple_dp_aux_ep_probe(struct dp_aux_ep_device *aux_ep) -{ - const struct of_device_id *id; - - id = of_match_node(platform_of_match, aux_ep->dev.of_node); - if (!id) - return -ENODEV; - - return panel_simple_probe(&aux_ep->dev, id->data, aux_ep->aux); -} - -static void panel_simple_dp_aux_ep_remove(struct dp_aux_ep_device *aux_ep) -{ - panel_simple_remove(&aux_ep->dev); -} - -static void panel_simple_dp_aux_ep_shutdown(struct dp_aux_ep_device *aux_ep) -{ - panel_simple_shutdown(&aux_ep->dev); -} - -static struct dp_aux_ep_driver panel_simple_dp_aux_ep_driver = { - .driver = { - .name = "panel-simple-dp-aux", - .of_match_table = platform_of_match, /* Same as platform one! */ - .pm = &panel_simple_pm_ops, - }, - .probe = panel_simple_dp_aux_ep_probe, - .remove = panel_simple_dp_aux_ep_remove, - .shutdown = panel_simple_dp_aux_ep_shutdown, -}; - static int __init panel_simple_init(void) { int err; @@ -5283,21 +4245,14 @@ static int __init panel_simple_init(void) if (err < 0) return err; - err = dp_aux_dp_driver_register(&panel_simple_dp_aux_ep_driver); - if (err < 0) - goto err_did_platform_register; - if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) { err = mipi_dsi_driver_register(&panel_simple_dsi_driver); if (err < 0) - goto err_did_aux_ep_register; + goto err_did_platform_register; } return 0; -err_did_aux_ep_register: - dp_aux_dp_driver_unregister(&panel_simple_dp_aux_ep_driver); - err_did_platform_register: platform_driver_unregister(&panel_simple_platform_driver); @@ -5310,7 +4265,6 @@ static void __exit panel_simple_exit(void) if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) mipi_dsi_driver_unregister(&panel_simple_dsi_driver); - dp_aux_dp_driver_unregister(&panel_simple_dp_aux_ep_driver); platform_driver_unregister(&panel_simple_platform_driver); } module_exit(panel_simple_exit); |