Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");