^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Ilitek ILI9322 TFT LCD drm_panel driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This panel can be configured to support:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * - 8-bit serial RGB interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * - 24-bit parallel RGB interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - 8-bit ITU-R BT.601 interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - 8-bit ITU-R BT.656 interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * - Up to 320RGBx240 dots resolution TFT LCD displays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * - Scaling, brightness and contrast
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * The scaling means that the display accepts a 640x480 or 720x480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * input and rescales it to fit to the 320x240 display. So what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * present to the system is something else than what comes out on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * actual display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Derived from drivers/drm/gpu/panel/panel-samsung-ld9040.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <video/mipi_display.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <video/of_videomode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <video/videomode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <drm/drm_modes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <drm/drm_panel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ILI9322_CHIP_ID 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define ILI9322_CHIP_ID_MAGIC 0x96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Voltage on the communication interface, from 0.7 (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * to 1.32 (0x1f) times the VREG1OUT voltage in 2% increments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * 1.00 (0x0f) is the default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define ILI9322_VCOM_AMP 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * High voltage on the communication signals, from 0.37 (0x00) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * 1.0 (0x3f) times the VREGOUT1 voltage in 1% increments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * 0.83 (0x2e) is the default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ILI9322_VCOM_HIGH 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * VREG1 voltage regulator from 3.6V (0x00) to 6.0V (0x18) in 0.1V
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * increments. 5.4V (0x12) is the default. This is the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * voltage for the VCOM levels and the greyscale level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ILI9322_VREG1_VOLTAGE 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Describes the incoming signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ILI9322_ENTRY 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* 0 = right-to-left, 1 = left-to-right (default), horizontal flip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ILI9322_ENTRY_HDIR BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* 0 = down-to-up, 1 = up-to-down (default), vertical flip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ILI9322_ENTRY_VDIR BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* NTSC, PAL or autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define ILI9322_ENTRY_NTSC (0 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define ILI9322_ENTRY_PAL (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define ILI9322_ENTRY_AUTODETECT (3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Input format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ILI9322_ENTRY_SERIAL_RGB_THROUGH (0 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define ILI9322_ENTRY_SERIAL_RGB_ALIGNED (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_320X240 (2 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_360X240 (3 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define ILI9322_ENTRY_DISABLE_1 (4 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ILI9322_ENTRY_PARALLEL_RGB_THROUGH (5 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ILI9322_ENTRY_PARALLEL_RGB_ALIGNED (6 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ILI9322_ENTRY_YUV_640Y_320CBCR_25_54_MHZ (7 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ILI9322_ENTRY_YUV_720Y_360CBCR_27_MHZ (8 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ILI9322_ENTRY_DISABLE_2 (9 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define ILI9322_ENTRY_ITU_R_BT_656_720X360 (10 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define ILI9322_ENTRY_ITU_R_BT_656_640X320 (11 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Power control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define ILI9322_POW_CTRL 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define ILI9322_POW_CTRL_STB BIT(0) /* 0 = standby, 1 = normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define ILI9322_POW_CTRL_VGL BIT(1) /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define ILI9322_POW_CTRL_VGH BIT(2) /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define ILI9322_POW_CTRL_DDVDH BIT(3) /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define ILI9322_POW_CTRL_VCOM BIT(4) /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define ILI9322_POW_CTRL_VCL BIT(5) /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define ILI9322_POW_CTRL_AUTO BIT(6) /* 0 = interactive, 1 = auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define ILI9322_POW_CTRL_STANDBY (ILI9322_POW_CTRL_VGL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ILI9322_POW_CTRL_VGH | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ILI9322_POW_CTRL_DDVDH | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ILI9322_POW_CTRL_VCL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ILI9322_POW_CTRL_AUTO | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) BIT(7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define ILI9322_POW_CTRL_DEFAULT (ILI9322_POW_CTRL_STANDBY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ILI9322_POW_CTRL_STB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Vertical back porch bits 0..5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define ILI9322_VBP 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Horizontal back porch, 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define ILI9322_HBP 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Polarity settings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * 1 = positive polarity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * 0 = negative polarity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define ILI9322_POL 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define ILI9322_POL_DCLK BIT(0) /* 1 default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define ILI9322_POL_HSYNC BIT(1) /* 0 default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define ILI9322_POL_VSYNC BIT(2) /* 0 default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define ILI9322_POL_DE BIT(3) /* 1 default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * 0 means YCBCR are ordered Cb0,Y0,Cr0,Y1,Cb2,Y2,Cr2,Y3 (default)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * in RGB mode this means RGB comes in RGBRGB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * 1 means YCBCR are ordered Cr0,Y0,Cb0,Y1,Cr2,Y2,Cb2,Y3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * in RGB mode this means RGB comes in BGRBGR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define ILI9322_POL_YCBCR_MODE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Formula A for YCbCR->RGB = 0, Formula B = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define ILI9322_POL_FORMULA BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Reverse polarity: 0 = 0..255, 1 = 255..0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define ILI9322_POL_REV BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define ILI9322_IF_CTRL 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define ILI9322_IF_CTRL_HSYNC_VSYNC 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define ILI9322_IF_CTRL_HSYNC_VSYNC_DE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define ILI9322_IF_CTRL_DE_ONLY BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define ILI9322_IF_CTRL_SYNC_DISABLED (BIT(2) | BIT(3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define ILI9322_IF_CTRL_LINE_INVERSION BIT(0) /* Not set means frame inv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define ILI9322_GLOBAL_RESET 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define ILI9322_GLOBAL_RESET_ASSERT 0x00 /* bit 0 = 0 -> reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * 4+4 bits of negative and positive gamma correction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Upper nybble, bits 4-7 are negative gamma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Lower nybble, bits 0-3 are positive gamma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define ILI9322_GAMMA_1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define ILI9322_GAMMA_2 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define ILI9322_GAMMA_3 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define ILI9322_GAMMA_4 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define ILI9322_GAMMA_5 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define ILI9322_GAMMA_6 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define ILI9322_GAMMA_7 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define ILI9322_GAMMA_8 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * enum ili9322_input - the format of the incoming signal to the panel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * The panel can be connected to various input streams and four of them can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * be selected by electronic straps on the display. However it is possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * to select another mode or override the electronic default with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) enum ili9322_input {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ILI9322_INPUT_SRGB_THROUGH = 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ILI9322_INPUT_SRGB_ALIGNED = 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ILI9322_INPUT_SRGB_DUMMY_320X240 = 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ILI9322_INPUT_SRGB_DUMMY_360X240 = 0x3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ILI9322_INPUT_DISABLED_1 = 0x4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ILI9322_INPUT_PRGB_THROUGH = 0x5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ILI9322_INPUT_PRGB_ALIGNED = 0x6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ILI9322_INPUT_YUV_640X320_YCBCR = 0x7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ILI9322_INPUT_YUV_720X360_YCBCR = 0x8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ILI9322_INPUT_DISABLED_2 = 0x9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR = 0xa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR = 0xb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ILI9322_INPUT_UNKNOWN = 0xc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static const char * const ili9322_inputs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) "8 bit serial RGB through",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) "8 bit serial RGB aligned",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) "8 bit serial RGB dummy 320x240",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) "8 bit serial RGB dummy 360x240",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) "disabled 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "24 bit parallel RGB through",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) "24 bit parallel RGB aligned",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) "24 bit YUV 640Y 320CbCr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) "24 bit YUV 720Y 360CbCr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) "disabled 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) "8 bit ITU-R BT.656 720Y 360CbCr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) "8 bit ITU-R BT.656 640Y 320CbCr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * struct ili9322_config - the system specific ILI9322 configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @width_mm: physical panel width [mm]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @height_mm: physical panel height [mm]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @flip_horizontal: flip the image horizontally (right-to-left scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * (only in RGB and YUV modes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @flip_vertical: flip the image vertically (down-to-up scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * (only in RGB and YUV modes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @input: the input/entry type used in this system, if this is set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * ILI9322_INPUT_UNKNOWN the driver will try to figure it out by probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * @vreg1out_mv: the output in microvolts for the VREGOUT1 regulator used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * to drive the physical display. Valid ranges are 3600 thru 6000 in 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * microvolt increments. If not specified, hardware defaults will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * used (4.5V).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @vcom_high_percent: the percentage of VREGOUT1 used for the peak
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * voltage on the communications link. Valid ranges are 37 thru 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * percent. If not specified, hardware defaults will be used (91%).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @vcom_amplitude_percent: the percentage of VREGOUT1 used for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * peak-to-peak amplitude of the communcation signals to the physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * display. Valid ranges are 70 thru 132 percent in increments if two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * percent. Odd percentages will be truncated. If not specified, hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * defaults will be used (114%).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @dclk_active_high: data/pixel clock active high, data will be clocked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * in on the rising edge of the DCLK (this is usually the case).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @syncmode: The synchronization mode, what sync signals are emitted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * See the enum for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @de_active_high: DE (data entry) is active high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @hsync_active_high: HSYNC is active high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @vsync_active_high: VSYNC is active high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @gamma_corr_pos: a set of 8 nybbles describing positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * gamma correction for voltages V1 thru V8. Valid range 0..15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * @gamma_corr_neg: a set of 8 nybbles describing negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * gamma correction for voltages V1 thru V8. Valid range 0..15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * These adjust what grayscale voltage will be output for input data V1 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * V2 = 16, V3 = 48, V4 = 96, V5 = 160, V6 = 208, V7 = 240 and V8 = 255.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * The curve is shaped like this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * | V8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * | V7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * | V6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * | V5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * | V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * | V3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * | V2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * | V1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * +----------------------------------------------------------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * 0 16 48 96 160 208 240 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * The negative and postive gamma values adjust the V1 thru V8 up/down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * according to the datasheet specifications. This is a property of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * physical display connected to the display controller and may vary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * If defined, both arrays must be supplied in full. If the properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * are not supplied, hardware defaults will be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct ili9322_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 width_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 height_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bool flip_horizontal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) bool flip_vertical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) enum ili9322_input input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 vreg1out_mv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u32 vcom_high_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u32 vcom_amplitude_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) bool dclk_active_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) bool de_active_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) bool hsync_active_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bool vsync_active_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u8 syncmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 gamma_corr_pos[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u8 gamma_corr_neg[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct ili9322 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct ili9322_config *conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct drm_panel panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct regulator_bulk_data supplies[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) enum ili9322_input input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct videomode vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 gamma[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u8 vreg1out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u8 vcom_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u8 vcom_amplitude;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static inline struct ili9322 *panel_to_ili9322(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return container_of(panel, struct ili9322, panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int ili9322_regmap_spi_write(void *context, const void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct device *dev = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct spi_device *spi = to_spi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* Clear bit 7 to write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) memcpy(buf, data, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) buf[0] &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_dbg(dev, "WRITE: %02x %02x\n", buf[0], buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return spi_write_then_read(spi, buf, 2, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int ili9322_regmap_spi_read(void *context, const void *reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) size_t reg_size, void *val, size_t val_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct device *dev = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct spi_device *spi = to_spi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* Set bit 7 to 1 to read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) memcpy(buf, reg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev_dbg(dev, "READ: %02x reg size = %zu, val size = %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) buf[0], reg_size, val_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) buf[0] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return spi_write_then_read(spi, buf, 1, val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct regmap_bus ili9322_regmap_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .write = ili9322_regmap_spi_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .read = ili9322_regmap_spi_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .reg_format_endian_default = REGMAP_ENDIAN_BIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .val_format_endian_default = REGMAP_ENDIAN_BIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static bool ili9322_volatile_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static bool ili9322_writeable_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Just register 0 is read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (reg == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static const struct regmap_config ili9322_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .max_register = 0x44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .volatile_reg = ili9322_volatile_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .writeable_reg = ili9322_writeable_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* Reset display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ret = regmap_write(ili->regmap, ILI9322_GLOBAL_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ILI9322_GLOBAL_RESET_ASSERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) dev_err(ili->dev, "can't issue GRESET (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Set up the main voltage regulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (ili->vreg1out != U8_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ret = regmap_write(ili->regmap, ILI9322_VREG1_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ili->vreg1out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(ili->dev, "can't set up VREG1OUT (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (ili->vcom_amplitude != U8_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ret = regmap_write(ili->regmap, ILI9322_VCOM_AMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ili->vcom_amplitude);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_err(ili->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) "can't set up VCOM amplitude (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (ili->vcom_high != U8_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = regmap_write(ili->regmap, ILI9322_VCOM_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ili->vcom_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_err(ili->dev, "can't set up VCOM high (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* Set up gamma correction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = regmap_write(ili->regmap, ILI9322_GAMMA_1 + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ili->gamma[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) dev_err(ili->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) "can't write gamma V%d to 0x%02x (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) i + 1, ILI9322_GAMMA_1 + i, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * Polarity and inverted color order for RGB input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * None of this applies in the BT.656 mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ili->conf->dclk_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) reg = ILI9322_POL_DCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ili->conf->de_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) reg |= ILI9322_POL_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (ili->conf->hsync_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) reg |= ILI9322_POL_HSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ili->conf->vsync_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) reg |= ILI9322_POL_VSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = regmap_write(ili->regmap, ILI9322_POL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) dev_err(ili->dev, "can't write POL register (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * Set up interface control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * This is not used in the BT.656 mode (no H/Vsync or DE signals).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) reg = ili->conf->syncmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) reg |= ILI9322_IF_CTRL_LINE_INVERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = regmap_write(ili->regmap, ILI9322_IF_CTRL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) dev_err(ili->dev, "can't write IF CTRL register (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Set up the input mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) reg = (ili->input << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* These are inverted, setting to 1 is the default, clearing flips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (!ili->conf->flip_horizontal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) reg |= ILI9322_ENTRY_HDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!ili->conf->flip_vertical)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) reg |= ILI9322_ENTRY_VDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) reg |= ILI9322_ENTRY_AUTODETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ret = regmap_write(ili->regmap, ILI9322_ENTRY, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dev_err(ili->dev, "can't write ENTRY reg (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dev_info(ili->dev, "display is in %s mode, syncmode %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ili9322_inputs[ili->input],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ili->conf->syncmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev_info(ili->dev, "initialized display\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * This power-on sequence if from the datasheet, page 57.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int ili9322_power_on(struct ili9322 *ili)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* Assert RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) gpiod_set_value(ili->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies), ili->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dev_err(ili->dev, "unable to enable regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* De-assert RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) gpiod_set_value(ili->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int ili9322_power_off(struct ili9322 *ili)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int ili9322_disable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct ili9322 *ili = panel_to_ili9322(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ILI9322_POW_CTRL_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dev_err(ili->dev, "unable to go to standby mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int ili9322_unprepare(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct ili9322 *ili = panel_to_ili9322(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return ili9322_power_off(ili);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static int ili9322_prepare(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) struct ili9322 *ili = panel_to_ili9322(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ret = ili9322_power_on(ili);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = ili9322_init(panel, ili);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ili9322_unprepare(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int ili9322_enable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct ili9322 *ili = panel_to_ili9322(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ILI9322_POW_CTRL_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_err(ili->dev, "unable to enable panel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Serial RGB modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static const struct drm_display_mode srgb_320x240_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .clock = 24535,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .hdisplay = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) .hsync_start = 320 + 359,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) .hsync_end = 320 + 359 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) .htotal = 320 + 359 + 1 + 241,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .vdisplay = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .vsync_start = 240 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .vsync_end = 240 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .vtotal = 262,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static const struct drm_display_mode srgb_360x240_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .clock = 27000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .hdisplay = 360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .hsync_start = 360 + 35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .hsync_end = 360 + 35 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) .htotal = 360 + 35 + 1 + 241,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .vdisplay = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .vsync_start = 240 + 21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .vsync_end = 240 + 21 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .vtotal = 262,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* This is the only mode listed for parallel RGB in the datasheet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static const struct drm_display_mode prgb_320x240_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .clock = 64000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .hdisplay = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) .hsync_start = 320 + 38,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .hsync_end = 320 + 38 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .htotal = 320 + 38 + 1 + 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .vdisplay = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .vsync_start = 240 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .vsync_end = 240 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .vtotal = 262,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* YUV modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static const struct drm_display_mode yuv_640x320_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) .clock = 24540,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .hdisplay = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .hsync_start = 640 + 252,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .hsync_end = 640 + 252 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .htotal = 640 + 252 + 1 + 28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .vdisplay = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .vsync_start = 320 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .vsync_end = 320 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .vtotal = 320 + 4 + 1 + 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static const struct drm_display_mode yuv_720x360_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .clock = 27000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) .hdisplay = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .hsync_start = 720 + 252,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) .hsync_end = 720 + 252 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .htotal = 720 + 252 + 1 + 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) .vdisplay = 360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) .vsync_start = 360 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .vsync_end = 360 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .vtotal = 360 + 4 + 1 + 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* BT.656 VGA mode, 640x480 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static const struct drm_display_mode itu_r_bt_656_640_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) .clock = 24540,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) .hdisplay = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) .hsync_start = 640 + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .hsync_end = 640 + 3 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .htotal = 640 + 3 + 1 + 272,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) .vdisplay = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) .vsync_start = 480 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) .vsync_end = 480 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) .vtotal = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* BT.656 D1 mode 720x480 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static const struct drm_display_mode itu_r_bt_656_720_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) .clock = 27000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) .hdisplay = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .hsync_start = 720 + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) .hsync_end = 720 + 3 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) .htotal = 720 + 3 + 1 + 272,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) .vdisplay = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) .vsync_start = 480 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .vsync_end = 480 + 4 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) .vtotal = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int ili9322_get_modes(struct drm_panel *panel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct ili9322 *ili = panel_to_ili9322(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct drm_device *drm = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct drm_display_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) info->width_mm = ili->conf->width_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) info->height_mm = ili->conf->height_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (ili->conf->dclk_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (ili->conf->de_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) switch (ili->input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) case ILI9322_INPUT_SRGB_DUMMY_320X240:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) mode = drm_mode_duplicate(drm, &srgb_320x240_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case ILI9322_INPUT_SRGB_DUMMY_360X240:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) mode = drm_mode_duplicate(drm, &srgb_360x240_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) case ILI9322_INPUT_PRGB_THROUGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case ILI9322_INPUT_PRGB_ALIGNED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) mode = drm_mode_duplicate(drm, &prgb_320x240_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) case ILI9322_INPUT_YUV_640X320_YCBCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) mode = drm_mode_duplicate(drm, &yuv_640x320_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) case ILI9322_INPUT_YUV_720X360_YCBCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mode = drm_mode_duplicate(drm, &yuv_720x360_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) mode = drm_mode_duplicate(drm, &itu_r_bt_656_720_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) case ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) mode = drm_mode_duplicate(drm, &itu_r_bt_656_640_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) mode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (!mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dev_err(panel->dev, "bad mode or failed to add mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * This is the preferred mode because most people are going
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * to want to use the display with VGA type graphics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* Set up the polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (ili->conf->hsync_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) mode->flags |= DRM_MODE_FLAG_PHSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mode->flags |= DRM_MODE_FLAG_NHSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (ili->conf->vsync_active_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) mode->flags |= DRM_MODE_FLAG_PVSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) mode->flags |= DRM_MODE_FLAG_NVSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mode->width_mm = ili->conf->width_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) mode->height_mm = ili->conf->height_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 1; /* Number of modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static const struct drm_panel_funcs ili9322_drm_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .disable = ili9322_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .unprepare = ili9322_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .prepare = ili9322_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .enable = ili9322_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .get_modes = ili9322_get_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int ili9322_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct device *dev = &spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct ili9322 *ili;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) const struct regmap_config *regmap_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) u8 gamma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) ili = devm_kzalloc(dev, sizeof(struct ili9322), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (!ili)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) spi_set_drvdata(spi, ili);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ili->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * Every new incarnation of this display must have a unique
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * data entry for the system in this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ili->conf = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (!ili->conf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_err(dev, "missing device configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) val = ili->conf->vreg1out_mv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* Default HW value, do not touch (should be 4.5V) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ili->vreg1out = U8_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (val < 3600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dev_err(dev, "too low VREG1OUT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (val > 6000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dev_err(dev, "too high VREG1OUT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if ((val % 100) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dev_err(dev, "VREG1OUT is no even 100 microvolt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) val -= 3600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) val /= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) dev_dbg(dev, "VREG1OUT = 0x%02x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ili->vreg1out = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) val = ili->conf->vcom_high_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* Default HW value, do not touch (should be 91%) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ili->vcom_high = U8_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (val < 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) dev_err(dev, "too low VCOM high\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (val > 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) dev_err(dev, "too high VCOM high\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) val -= 37;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dev_dbg(dev, "VCOM high = 0x%02x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ili->vcom_high = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) val = ili->conf->vcom_amplitude_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* Default HW value, do not touch (should be 114%) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) ili->vcom_high = U8_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (val < 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) dev_err(dev, "too low VCOM amplitude\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (val > 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dev_err(dev, "too high VCOM amplitude\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) val -= 70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) val >>= 1; /* Increments of 2% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) dev_dbg(dev, "VCOM amplitude = 0x%02x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) ili->vcom_amplitude = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) val = ili->conf->gamma_corr_neg[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (val > 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dev_err(dev, "negative gamma %u > 15, capping\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) val = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) gamma = val << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) val = ili->conf->gamma_corr_pos[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (val > 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) dev_err(dev, "positive gamma %u > 15, capping\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) val = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) gamma |= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ili->gamma[i] = gamma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) dev_dbg(dev, "gamma V%d: 0x%02x\n", i + 1, gamma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ili->supplies[0].supply = "vcc"; /* 2.7-3.6 V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ili->supplies[1].supply = "iovcc"; /* 1.65-3.6V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) ili->supplies[2].supply = "vci"; /* 2.7-3.6V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ili->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = regulator_set_voltage(ili->supplies[0].consumer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 2700000, 3600000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ret = regulator_set_voltage(ili->supplies[1].consumer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 1650000, 3600000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ret = regulator_set_voltage(ili->supplies[2].consumer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 2700000, 3600000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ili->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (IS_ERR(ili->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) dev_err(dev, "failed to get RESET GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return PTR_ERR(ili->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) spi->bits_per_word = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = spi_setup(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) dev_err(dev, "spi setup failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) regmap_config = &ili9322_regmap_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ili->regmap = devm_regmap_init(dev, &ili9322_regmap_bus, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (IS_ERR(ili->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dev_err(dev, "failed to allocate register map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return PTR_ERR(ili->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ret = regmap_read(ili->regmap, ILI9322_CHIP_ID, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) dev_err(dev, "can't get chip ID (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (val != ILI9322_CHIP_ID_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) dev_err(dev, "chip ID 0x%0x2, expected 0x%02x\n", val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) ILI9322_CHIP_ID_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Probe the system to find the display setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (ili->conf->input == ILI9322_INPUT_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ret = regmap_read(ili->regmap, ILI9322_ENTRY, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dev_err(dev, "can't get entry setting (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* Input enum corresponds to HW setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ili->input = (val >> 4) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (ili->input >= ILI9322_INPUT_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ili->input = ILI9322_INPUT_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) ili->input = ili->conf->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) DRM_MODE_CONNECTOR_DPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) drm_panel_add(&ili->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static int ili9322_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct ili9322 *ili = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ili9322_power_off(ili);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) drm_panel_remove(&ili->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * The D-Link DIR-685 panel is marked LM918A01-1A SY-B4-091116-E0199
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static const struct ili9322_config ili9322_dir_685 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .width_mm = 65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .height_mm = 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .input = ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .vreg1out_mv = 4600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .vcom_high_percent = 91,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .vcom_amplitude_percent = 114,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .syncmode = ILI9322_IF_CTRL_SYNC_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .dclk_active_high = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .gamma_corr_neg = { 0xa, 0x5, 0x7, 0x7, 0x7, 0x5, 0x1, 0x6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .gamma_corr_pos = { 0x7, 0x7, 0x3, 0x2, 0x3, 0x5, 0x7, 0x2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static const struct of_device_id ili9322_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .compatible = "dlink,dir-685-panel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .data = &ili9322_dir_685,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .compatible = "ilitek,ili9322",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .data = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) MODULE_DEVICE_TABLE(of, ili9322_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static struct spi_driver ili9322_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .probe = ili9322_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .remove = ili9322_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .name = "panel-ilitek-ili9322",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .of_match_table = ili9322_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) module_spi_driver(ili9322_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) MODULE_DESCRIPTION("ILI9322 LCD panel driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) MODULE_LICENSE("GPL v2");