0001
0002
0003
0004
0005
0006 #include <linux/delay.h>
0007 #include <linux/device.h>
0008 #include <linux/err.h>
0009 #include <linux/errno.h>
0010 #include <linux/fb.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/of_device.h>
0014
0015 #include <linux/gpio/consumer.h>
0016 #include <linux/regulator/consumer.h>
0017
0018 #include <drm/drm_mipi_dsi.h>
0019 #include <drm/drm_modes.h>
0020 #include <drm/drm_panel.h>
0021
0022 #include <video/mipi_display.h>
0023
0024 enum ili9881c_op {
0025 ILI9881C_SWITCH_PAGE,
0026 ILI9881C_COMMAND,
0027 };
0028
0029 struct ili9881c_instr {
0030 enum ili9881c_op op;
0031
0032 union arg {
0033 struct cmd {
0034 u8 cmd;
0035 u8 data;
0036 } cmd;
0037 u8 page;
0038 } arg;
0039 };
0040
0041 struct ili9881c_desc {
0042 const struct ili9881c_instr *init;
0043 const size_t init_length;
0044 const struct drm_display_mode *mode;
0045 const unsigned long mode_flags;
0046 };
0047
0048 struct ili9881c {
0049 struct drm_panel panel;
0050 struct mipi_dsi_device *dsi;
0051 const struct ili9881c_desc *desc;
0052
0053 struct regulator *power;
0054 struct gpio_desc *reset;
0055
0056 enum drm_panel_orientation orientation;
0057 };
0058
0059 #define ILI9881C_SWITCH_PAGE_INSTR(_page) \
0060 { \
0061 .op = ILI9881C_SWITCH_PAGE, \
0062 .arg = { \
0063 .page = (_page), \
0064 }, \
0065 }
0066
0067 #define ILI9881C_COMMAND_INSTR(_cmd, _data) \
0068 { \
0069 .op = ILI9881C_COMMAND, \
0070 .arg = { \
0071 .cmd = { \
0072 .cmd = (_cmd), \
0073 .data = (_data), \
0074 }, \
0075 }, \
0076 }
0077
0078 static const struct ili9881c_instr lhr050h41_init[] = {
0079 ILI9881C_SWITCH_PAGE_INSTR(3),
0080 ILI9881C_COMMAND_INSTR(0x01, 0x00),
0081 ILI9881C_COMMAND_INSTR(0x02, 0x00),
0082 ILI9881C_COMMAND_INSTR(0x03, 0x73),
0083 ILI9881C_COMMAND_INSTR(0x04, 0x03),
0084 ILI9881C_COMMAND_INSTR(0x05, 0x00),
0085 ILI9881C_COMMAND_INSTR(0x06, 0x06),
0086 ILI9881C_COMMAND_INSTR(0x07, 0x06),
0087 ILI9881C_COMMAND_INSTR(0x08, 0x00),
0088 ILI9881C_COMMAND_INSTR(0x09, 0x18),
0089 ILI9881C_COMMAND_INSTR(0x0a, 0x04),
0090 ILI9881C_COMMAND_INSTR(0x0b, 0x00),
0091 ILI9881C_COMMAND_INSTR(0x0c, 0x02),
0092 ILI9881C_COMMAND_INSTR(0x0d, 0x03),
0093 ILI9881C_COMMAND_INSTR(0x0e, 0x00),
0094 ILI9881C_COMMAND_INSTR(0x0f, 0x25),
0095 ILI9881C_COMMAND_INSTR(0x10, 0x25),
0096 ILI9881C_COMMAND_INSTR(0x11, 0x00),
0097 ILI9881C_COMMAND_INSTR(0x12, 0x00),
0098 ILI9881C_COMMAND_INSTR(0x13, 0x00),
0099 ILI9881C_COMMAND_INSTR(0x14, 0x00),
0100 ILI9881C_COMMAND_INSTR(0x15, 0x00),
0101 ILI9881C_COMMAND_INSTR(0x16, 0x0C),
0102 ILI9881C_COMMAND_INSTR(0x17, 0x00),
0103 ILI9881C_COMMAND_INSTR(0x18, 0x00),
0104 ILI9881C_COMMAND_INSTR(0x19, 0x00),
0105 ILI9881C_COMMAND_INSTR(0x1a, 0x00),
0106 ILI9881C_COMMAND_INSTR(0x1b, 0x00),
0107 ILI9881C_COMMAND_INSTR(0x1c, 0x00),
0108 ILI9881C_COMMAND_INSTR(0x1d, 0x00),
0109 ILI9881C_COMMAND_INSTR(0x1e, 0xC0),
0110 ILI9881C_COMMAND_INSTR(0x1f, 0x80),
0111 ILI9881C_COMMAND_INSTR(0x20, 0x04),
0112 ILI9881C_COMMAND_INSTR(0x21, 0x01),
0113 ILI9881C_COMMAND_INSTR(0x22, 0x00),
0114 ILI9881C_COMMAND_INSTR(0x23, 0x00),
0115 ILI9881C_COMMAND_INSTR(0x24, 0x00),
0116 ILI9881C_COMMAND_INSTR(0x25, 0x00),
0117 ILI9881C_COMMAND_INSTR(0x26, 0x00),
0118 ILI9881C_COMMAND_INSTR(0x27, 0x00),
0119 ILI9881C_COMMAND_INSTR(0x28, 0x33),
0120 ILI9881C_COMMAND_INSTR(0x29, 0x03),
0121 ILI9881C_COMMAND_INSTR(0x2a, 0x00),
0122 ILI9881C_COMMAND_INSTR(0x2b, 0x00),
0123 ILI9881C_COMMAND_INSTR(0x2c, 0x00),
0124 ILI9881C_COMMAND_INSTR(0x2d, 0x00),
0125 ILI9881C_COMMAND_INSTR(0x2e, 0x00),
0126 ILI9881C_COMMAND_INSTR(0x2f, 0x00),
0127 ILI9881C_COMMAND_INSTR(0x30, 0x00),
0128 ILI9881C_COMMAND_INSTR(0x31, 0x00),
0129 ILI9881C_COMMAND_INSTR(0x32, 0x00),
0130 ILI9881C_COMMAND_INSTR(0x33, 0x00),
0131 ILI9881C_COMMAND_INSTR(0x34, 0x04),
0132 ILI9881C_COMMAND_INSTR(0x35, 0x00),
0133 ILI9881C_COMMAND_INSTR(0x36, 0x00),
0134 ILI9881C_COMMAND_INSTR(0x37, 0x00),
0135 ILI9881C_COMMAND_INSTR(0x38, 0x3C),
0136 ILI9881C_COMMAND_INSTR(0x39, 0x00),
0137 ILI9881C_COMMAND_INSTR(0x3a, 0x00),
0138 ILI9881C_COMMAND_INSTR(0x3b, 0x00),
0139 ILI9881C_COMMAND_INSTR(0x3c, 0x00),
0140 ILI9881C_COMMAND_INSTR(0x3d, 0x00),
0141 ILI9881C_COMMAND_INSTR(0x3e, 0x00),
0142 ILI9881C_COMMAND_INSTR(0x3f, 0x00),
0143 ILI9881C_COMMAND_INSTR(0x40, 0x00),
0144 ILI9881C_COMMAND_INSTR(0x41, 0x00),
0145 ILI9881C_COMMAND_INSTR(0x42, 0x00),
0146 ILI9881C_COMMAND_INSTR(0x43, 0x00),
0147 ILI9881C_COMMAND_INSTR(0x44, 0x00),
0148 ILI9881C_COMMAND_INSTR(0x50, 0x01),
0149 ILI9881C_COMMAND_INSTR(0x51, 0x23),
0150 ILI9881C_COMMAND_INSTR(0x52, 0x45),
0151 ILI9881C_COMMAND_INSTR(0x53, 0x67),
0152 ILI9881C_COMMAND_INSTR(0x54, 0x89),
0153 ILI9881C_COMMAND_INSTR(0x55, 0xab),
0154 ILI9881C_COMMAND_INSTR(0x56, 0x01),
0155 ILI9881C_COMMAND_INSTR(0x57, 0x23),
0156 ILI9881C_COMMAND_INSTR(0x58, 0x45),
0157 ILI9881C_COMMAND_INSTR(0x59, 0x67),
0158 ILI9881C_COMMAND_INSTR(0x5a, 0x89),
0159 ILI9881C_COMMAND_INSTR(0x5b, 0xab),
0160 ILI9881C_COMMAND_INSTR(0x5c, 0xcd),
0161 ILI9881C_COMMAND_INSTR(0x5d, 0xef),
0162 ILI9881C_COMMAND_INSTR(0x5e, 0x11),
0163 ILI9881C_COMMAND_INSTR(0x5f, 0x02),
0164 ILI9881C_COMMAND_INSTR(0x60, 0x02),
0165 ILI9881C_COMMAND_INSTR(0x61, 0x02),
0166 ILI9881C_COMMAND_INSTR(0x62, 0x02),
0167 ILI9881C_COMMAND_INSTR(0x63, 0x02),
0168 ILI9881C_COMMAND_INSTR(0x64, 0x02),
0169 ILI9881C_COMMAND_INSTR(0x65, 0x02),
0170 ILI9881C_COMMAND_INSTR(0x66, 0x02),
0171 ILI9881C_COMMAND_INSTR(0x67, 0x02),
0172 ILI9881C_COMMAND_INSTR(0x68, 0x02),
0173 ILI9881C_COMMAND_INSTR(0x69, 0x02),
0174 ILI9881C_COMMAND_INSTR(0x6a, 0x0C),
0175 ILI9881C_COMMAND_INSTR(0x6b, 0x02),
0176 ILI9881C_COMMAND_INSTR(0x6c, 0x0F),
0177 ILI9881C_COMMAND_INSTR(0x6d, 0x0E),
0178 ILI9881C_COMMAND_INSTR(0x6e, 0x0D),
0179 ILI9881C_COMMAND_INSTR(0x6f, 0x06),
0180 ILI9881C_COMMAND_INSTR(0x70, 0x07),
0181 ILI9881C_COMMAND_INSTR(0x71, 0x02),
0182 ILI9881C_COMMAND_INSTR(0x72, 0x02),
0183 ILI9881C_COMMAND_INSTR(0x73, 0x02),
0184 ILI9881C_COMMAND_INSTR(0x74, 0x02),
0185 ILI9881C_COMMAND_INSTR(0x75, 0x02),
0186 ILI9881C_COMMAND_INSTR(0x76, 0x02),
0187 ILI9881C_COMMAND_INSTR(0x77, 0x02),
0188 ILI9881C_COMMAND_INSTR(0x78, 0x02),
0189 ILI9881C_COMMAND_INSTR(0x79, 0x02),
0190 ILI9881C_COMMAND_INSTR(0x7a, 0x02),
0191 ILI9881C_COMMAND_INSTR(0x7b, 0x02),
0192 ILI9881C_COMMAND_INSTR(0x7c, 0x02),
0193 ILI9881C_COMMAND_INSTR(0x7d, 0x02),
0194 ILI9881C_COMMAND_INSTR(0x7e, 0x02),
0195 ILI9881C_COMMAND_INSTR(0x7f, 0x02),
0196 ILI9881C_COMMAND_INSTR(0x80, 0x0C),
0197 ILI9881C_COMMAND_INSTR(0x81, 0x02),
0198 ILI9881C_COMMAND_INSTR(0x82, 0x0F),
0199 ILI9881C_COMMAND_INSTR(0x83, 0x0E),
0200 ILI9881C_COMMAND_INSTR(0x84, 0x0D),
0201 ILI9881C_COMMAND_INSTR(0x85, 0x06),
0202 ILI9881C_COMMAND_INSTR(0x86, 0x07),
0203 ILI9881C_COMMAND_INSTR(0x87, 0x02),
0204 ILI9881C_COMMAND_INSTR(0x88, 0x02),
0205 ILI9881C_COMMAND_INSTR(0x89, 0x02),
0206 ILI9881C_COMMAND_INSTR(0x8A, 0x02),
0207 ILI9881C_SWITCH_PAGE_INSTR(4),
0208 ILI9881C_COMMAND_INSTR(0x6C, 0x15),
0209 ILI9881C_COMMAND_INSTR(0x6E, 0x22),
0210 ILI9881C_COMMAND_INSTR(0x6F, 0x33),
0211 ILI9881C_COMMAND_INSTR(0x3A, 0xA4),
0212 ILI9881C_COMMAND_INSTR(0x8D, 0x0D),
0213 ILI9881C_COMMAND_INSTR(0x87, 0xBA),
0214 ILI9881C_COMMAND_INSTR(0x26, 0x76),
0215 ILI9881C_COMMAND_INSTR(0xB2, 0xD1),
0216 ILI9881C_SWITCH_PAGE_INSTR(1),
0217 ILI9881C_COMMAND_INSTR(0x22, 0x0A),
0218 ILI9881C_COMMAND_INSTR(0x53, 0xDC),
0219 ILI9881C_COMMAND_INSTR(0x55, 0xA7),
0220 ILI9881C_COMMAND_INSTR(0x50, 0x78),
0221 ILI9881C_COMMAND_INSTR(0x51, 0x78),
0222 ILI9881C_COMMAND_INSTR(0x31, 0x02),
0223 ILI9881C_COMMAND_INSTR(0x60, 0x14),
0224 ILI9881C_COMMAND_INSTR(0xA0, 0x2A),
0225 ILI9881C_COMMAND_INSTR(0xA1, 0x39),
0226 ILI9881C_COMMAND_INSTR(0xA2, 0x46),
0227 ILI9881C_COMMAND_INSTR(0xA3, 0x0e),
0228 ILI9881C_COMMAND_INSTR(0xA4, 0x12),
0229 ILI9881C_COMMAND_INSTR(0xA5, 0x25),
0230 ILI9881C_COMMAND_INSTR(0xA6, 0x19),
0231 ILI9881C_COMMAND_INSTR(0xA7, 0x1d),
0232 ILI9881C_COMMAND_INSTR(0xA8, 0xa6),
0233 ILI9881C_COMMAND_INSTR(0xA9, 0x1C),
0234 ILI9881C_COMMAND_INSTR(0xAA, 0x29),
0235 ILI9881C_COMMAND_INSTR(0xAB, 0x85),
0236 ILI9881C_COMMAND_INSTR(0xAC, 0x1C),
0237 ILI9881C_COMMAND_INSTR(0xAD, 0x1B),
0238 ILI9881C_COMMAND_INSTR(0xAE, 0x51),
0239 ILI9881C_COMMAND_INSTR(0xAF, 0x22),
0240 ILI9881C_COMMAND_INSTR(0xB0, 0x2d),
0241 ILI9881C_COMMAND_INSTR(0xB1, 0x4f),
0242 ILI9881C_COMMAND_INSTR(0xB2, 0x59),
0243 ILI9881C_COMMAND_INSTR(0xB3, 0x3F),
0244 ILI9881C_COMMAND_INSTR(0xC0, 0x2A),
0245 ILI9881C_COMMAND_INSTR(0xC1, 0x3a),
0246 ILI9881C_COMMAND_INSTR(0xC2, 0x45),
0247 ILI9881C_COMMAND_INSTR(0xC3, 0x0e),
0248 ILI9881C_COMMAND_INSTR(0xC4, 0x11),
0249 ILI9881C_COMMAND_INSTR(0xC5, 0x24),
0250 ILI9881C_COMMAND_INSTR(0xC6, 0x1a),
0251 ILI9881C_COMMAND_INSTR(0xC7, 0x1c),
0252 ILI9881C_COMMAND_INSTR(0xC8, 0xaa),
0253 ILI9881C_COMMAND_INSTR(0xC9, 0x1C),
0254 ILI9881C_COMMAND_INSTR(0xCA, 0x29),
0255 ILI9881C_COMMAND_INSTR(0xCB, 0x96),
0256 ILI9881C_COMMAND_INSTR(0xCC, 0x1C),
0257 ILI9881C_COMMAND_INSTR(0xCD, 0x1B),
0258 ILI9881C_COMMAND_INSTR(0xCE, 0x51),
0259 ILI9881C_COMMAND_INSTR(0xCF, 0x22),
0260 ILI9881C_COMMAND_INSTR(0xD0, 0x2b),
0261 ILI9881C_COMMAND_INSTR(0xD1, 0x4b),
0262 ILI9881C_COMMAND_INSTR(0xD2, 0x59),
0263 ILI9881C_COMMAND_INSTR(0xD3, 0x3F),
0264 };
0265
0266 static const struct ili9881c_instr k101_im2byl02_init[] = {
0267 ILI9881C_SWITCH_PAGE_INSTR(3),
0268 ILI9881C_COMMAND_INSTR(0x01, 0x00),
0269 ILI9881C_COMMAND_INSTR(0x02, 0x00),
0270 ILI9881C_COMMAND_INSTR(0x03, 0x73),
0271 ILI9881C_COMMAND_INSTR(0x04, 0x00),
0272 ILI9881C_COMMAND_INSTR(0x05, 0x00),
0273 ILI9881C_COMMAND_INSTR(0x06, 0x08),
0274 ILI9881C_COMMAND_INSTR(0x07, 0x00),
0275 ILI9881C_COMMAND_INSTR(0x08, 0x00),
0276 ILI9881C_COMMAND_INSTR(0x09, 0x00),
0277 ILI9881C_COMMAND_INSTR(0x0A, 0x01),
0278 ILI9881C_COMMAND_INSTR(0x0B, 0x01),
0279 ILI9881C_COMMAND_INSTR(0x0C, 0x00),
0280 ILI9881C_COMMAND_INSTR(0x0D, 0x01),
0281 ILI9881C_COMMAND_INSTR(0x0E, 0x01),
0282 ILI9881C_COMMAND_INSTR(0x0F, 0x00),
0283 ILI9881C_COMMAND_INSTR(0x10, 0x00),
0284 ILI9881C_COMMAND_INSTR(0x11, 0x00),
0285 ILI9881C_COMMAND_INSTR(0x12, 0x00),
0286 ILI9881C_COMMAND_INSTR(0x13, 0x00),
0287 ILI9881C_COMMAND_INSTR(0x14, 0x00),
0288 ILI9881C_COMMAND_INSTR(0x15, 0x00),
0289 ILI9881C_COMMAND_INSTR(0x16, 0x00),
0290 ILI9881C_COMMAND_INSTR(0x17, 0x00),
0291 ILI9881C_COMMAND_INSTR(0x18, 0x00),
0292 ILI9881C_COMMAND_INSTR(0x19, 0x00),
0293 ILI9881C_COMMAND_INSTR(0x1A, 0x00),
0294 ILI9881C_COMMAND_INSTR(0x1B, 0x00),
0295 ILI9881C_COMMAND_INSTR(0x1C, 0x00),
0296 ILI9881C_COMMAND_INSTR(0x1D, 0x00),
0297 ILI9881C_COMMAND_INSTR(0x1E, 0x40),
0298 ILI9881C_COMMAND_INSTR(0x1F, 0xC0),
0299 ILI9881C_COMMAND_INSTR(0x20, 0x06),
0300 ILI9881C_COMMAND_INSTR(0x21, 0x01),
0301 ILI9881C_COMMAND_INSTR(0x22, 0x06),
0302 ILI9881C_COMMAND_INSTR(0x23, 0x01),
0303 ILI9881C_COMMAND_INSTR(0x24, 0x88),
0304 ILI9881C_COMMAND_INSTR(0x25, 0x88),
0305 ILI9881C_COMMAND_INSTR(0x26, 0x00),
0306 ILI9881C_COMMAND_INSTR(0x27, 0x00),
0307 ILI9881C_COMMAND_INSTR(0x28, 0x3B),
0308 ILI9881C_COMMAND_INSTR(0x29, 0x03),
0309 ILI9881C_COMMAND_INSTR(0x2A, 0x00),
0310 ILI9881C_COMMAND_INSTR(0x2B, 0x00),
0311 ILI9881C_COMMAND_INSTR(0x2C, 0x00),
0312 ILI9881C_COMMAND_INSTR(0x2D, 0x00),
0313 ILI9881C_COMMAND_INSTR(0x2E, 0x00),
0314 ILI9881C_COMMAND_INSTR(0x2F, 0x00),
0315 ILI9881C_COMMAND_INSTR(0x30, 0x00),
0316 ILI9881C_COMMAND_INSTR(0x31, 0x00),
0317 ILI9881C_COMMAND_INSTR(0x32, 0x00),
0318 ILI9881C_COMMAND_INSTR(0x33, 0x00),
0319 ILI9881C_COMMAND_INSTR(0x34, 0x00),
0320 ILI9881C_COMMAND_INSTR(0x35, 0x00),
0321 ILI9881C_COMMAND_INSTR(0x36, 0x00),
0322 ILI9881C_COMMAND_INSTR(0x37, 0x00),
0323 ILI9881C_COMMAND_INSTR(0x38, 0x00),
0324 ILI9881C_COMMAND_INSTR(0x39, 0x00),
0325 ILI9881C_COMMAND_INSTR(0x3A, 0x00),
0326 ILI9881C_COMMAND_INSTR(0x3B, 0x00),
0327 ILI9881C_COMMAND_INSTR(0x3C, 0x00),
0328 ILI9881C_COMMAND_INSTR(0x3D, 0x00),
0329 ILI9881C_COMMAND_INSTR(0x3E, 0x00),
0330 ILI9881C_COMMAND_INSTR(0x3F, 0x00),
0331 ILI9881C_COMMAND_INSTR(0x40, 0x00),
0332 ILI9881C_COMMAND_INSTR(0x41, 0x00),
0333 ILI9881C_COMMAND_INSTR(0x42, 0x00),
0334 ILI9881C_COMMAND_INSTR(0x43, 0x00),
0335 ILI9881C_COMMAND_INSTR(0x44, 0x00),
0336 ILI9881C_COMMAND_INSTR(0x50, 0x01),
0337 ILI9881C_COMMAND_INSTR(0x51, 0x23),
0338 ILI9881C_COMMAND_INSTR(0x52, 0x45),
0339 ILI9881C_COMMAND_INSTR(0x53, 0x67),
0340 ILI9881C_COMMAND_INSTR(0x54, 0x89),
0341 ILI9881C_COMMAND_INSTR(0x55, 0xAB),
0342 ILI9881C_COMMAND_INSTR(0x56, 0x01),
0343 ILI9881C_COMMAND_INSTR(0x57, 0x23),
0344 ILI9881C_COMMAND_INSTR(0x58, 0x45),
0345 ILI9881C_COMMAND_INSTR(0x59, 0x67),
0346 ILI9881C_COMMAND_INSTR(0x5A, 0x89),
0347 ILI9881C_COMMAND_INSTR(0x5B, 0xAB),
0348 ILI9881C_COMMAND_INSTR(0x5C, 0xCD),
0349 ILI9881C_COMMAND_INSTR(0x5D, 0xEF),
0350 ILI9881C_COMMAND_INSTR(0x5E, 0x00),
0351 ILI9881C_COMMAND_INSTR(0x5F, 0x01),
0352 ILI9881C_COMMAND_INSTR(0x60, 0x01),
0353 ILI9881C_COMMAND_INSTR(0x61, 0x06),
0354 ILI9881C_COMMAND_INSTR(0x62, 0x06),
0355 ILI9881C_COMMAND_INSTR(0x63, 0x07),
0356 ILI9881C_COMMAND_INSTR(0x64, 0x07),
0357 ILI9881C_COMMAND_INSTR(0x65, 0x00),
0358 ILI9881C_COMMAND_INSTR(0x66, 0x00),
0359 ILI9881C_COMMAND_INSTR(0x67, 0x02),
0360 ILI9881C_COMMAND_INSTR(0x68, 0x02),
0361 ILI9881C_COMMAND_INSTR(0x69, 0x05),
0362 ILI9881C_COMMAND_INSTR(0x6A, 0x05),
0363 ILI9881C_COMMAND_INSTR(0x6B, 0x02),
0364 ILI9881C_COMMAND_INSTR(0x6C, 0x0D),
0365 ILI9881C_COMMAND_INSTR(0x6D, 0x0D),
0366 ILI9881C_COMMAND_INSTR(0x6E, 0x0C),
0367 ILI9881C_COMMAND_INSTR(0x6F, 0x0C),
0368 ILI9881C_COMMAND_INSTR(0x70, 0x0F),
0369 ILI9881C_COMMAND_INSTR(0x71, 0x0F),
0370 ILI9881C_COMMAND_INSTR(0x72, 0x0E),
0371 ILI9881C_COMMAND_INSTR(0x73, 0x0E),
0372 ILI9881C_COMMAND_INSTR(0x74, 0x02),
0373 ILI9881C_COMMAND_INSTR(0x75, 0x01),
0374 ILI9881C_COMMAND_INSTR(0x76, 0x01),
0375 ILI9881C_COMMAND_INSTR(0x77, 0x06),
0376 ILI9881C_COMMAND_INSTR(0x78, 0x06),
0377 ILI9881C_COMMAND_INSTR(0x79, 0x07),
0378 ILI9881C_COMMAND_INSTR(0x7A, 0x07),
0379 ILI9881C_COMMAND_INSTR(0x7B, 0x00),
0380 ILI9881C_COMMAND_INSTR(0x7C, 0x00),
0381 ILI9881C_COMMAND_INSTR(0x7D, 0x02),
0382 ILI9881C_COMMAND_INSTR(0x7E, 0x02),
0383 ILI9881C_COMMAND_INSTR(0x7F, 0x05),
0384 ILI9881C_COMMAND_INSTR(0x80, 0x05),
0385 ILI9881C_COMMAND_INSTR(0x81, 0x02),
0386 ILI9881C_COMMAND_INSTR(0x82, 0x0D),
0387 ILI9881C_COMMAND_INSTR(0x83, 0x0D),
0388 ILI9881C_COMMAND_INSTR(0x84, 0x0C),
0389 ILI9881C_COMMAND_INSTR(0x85, 0x0C),
0390 ILI9881C_COMMAND_INSTR(0x86, 0x0F),
0391 ILI9881C_COMMAND_INSTR(0x87, 0x0F),
0392 ILI9881C_COMMAND_INSTR(0x88, 0x0E),
0393 ILI9881C_COMMAND_INSTR(0x89, 0x0E),
0394 ILI9881C_COMMAND_INSTR(0x8A, 0x02),
0395 ILI9881C_SWITCH_PAGE_INSTR(4),
0396 ILI9881C_COMMAND_INSTR(0x3B, 0xC0),
0397 ILI9881C_COMMAND_INSTR(0x6C, 0x15),
0398 ILI9881C_COMMAND_INSTR(0x6E, 0x2A),
0399 ILI9881C_COMMAND_INSTR(0x6F, 0x33),
0400 ILI9881C_COMMAND_INSTR(0x8D, 0x1B),
0401 ILI9881C_COMMAND_INSTR(0x87, 0xBA),
0402 ILI9881C_COMMAND_INSTR(0x3A, 0x24),
0403 ILI9881C_COMMAND_INSTR(0x26, 0x76),
0404 ILI9881C_COMMAND_INSTR(0xB2, 0xD1),
0405 ILI9881C_SWITCH_PAGE_INSTR(1),
0406 ILI9881C_COMMAND_INSTR(0x22, 0x0A),
0407 ILI9881C_COMMAND_INSTR(0x31, 0x00),
0408 ILI9881C_COMMAND_INSTR(0x40, 0x53),
0409 ILI9881C_COMMAND_INSTR(0x43, 0x66),
0410 ILI9881C_COMMAND_INSTR(0x53, 0x4C),
0411 ILI9881C_COMMAND_INSTR(0x50, 0x87),
0412 ILI9881C_COMMAND_INSTR(0x51, 0x82),
0413 ILI9881C_COMMAND_INSTR(0x60, 0x15),
0414 ILI9881C_COMMAND_INSTR(0x61, 0x01),
0415 ILI9881C_COMMAND_INSTR(0x62, 0x0C),
0416 ILI9881C_COMMAND_INSTR(0x63, 0x00),
0417 ILI9881C_COMMAND_INSTR(0xA0, 0x00),
0418 ILI9881C_COMMAND_INSTR(0xA1, 0x13),
0419 ILI9881C_COMMAND_INSTR(0xA2, 0x23),
0420 ILI9881C_COMMAND_INSTR(0xA3, 0x14),
0421 ILI9881C_COMMAND_INSTR(0xA4, 0x16),
0422 ILI9881C_COMMAND_INSTR(0xA5, 0x29),
0423 ILI9881C_COMMAND_INSTR(0xA6, 0x1E),
0424 ILI9881C_COMMAND_INSTR(0xA7, 0x1D),
0425 ILI9881C_COMMAND_INSTR(0xA8, 0x86),
0426 ILI9881C_COMMAND_INSTR(0xA9, 0x1E),
0427 ILI9881C_COMMAND_INSTR(0xAA, 0x29),
0428 ILI9881C_COMMAND_INSTR(0xAB, 0x74),
0429 ILI9881C_COMMAND_INSTR(0xAC, 0x19),
0430 ILI9881C_COMMAND_INSTR(0xAD, 0x17),
0431 ILI9881C_COMMAND_INSTR(0xAE, 0x4B),
0432 ILI9881C_COMMAND_INSTR(0xAF, 0x20),
0433 ILI9881C_COMMAND_INSTR(0xB0, 0x26),
0434 ILI9881C_COMMAND_INSTR(0xB1, 0x4C),
0435 ILI9881C_COMMAND_INSTR(0xB2, 0x5D),
0436 ILI9881C_COMMAND_INSTR(0xB3, 0x3F),
0437 ILI9881C_COMMAND_INSTR(0xC0, 0x00),
0438 ILI9881C_COMMAND_INSTR(0xC1, 0x13),
0439 ILI9881C_COMMAND_INSTR(0xC2, 0x23),
0440 ILI9881C_COMMAND_INSTR(0xC3, 0x14),
0441 ILI9881C_COMMAND_INSTR(0xC4, 0x16),
0442 ILI9881C_COMMAND_INSTR(0xC5, 0x29),
0443 ILI9881C_COMMAND_INSTR(0xC6, 0x1E),
0444 ILI9881C_COMMAND_INSTR(0xC7, 0x1D),
0445 ILI9881C_COMMAND_INSTR(0xC8, 0x86),
0446 ILI9881C_COMMAND_INSTR(0xC9, 0x1E),
0447 ILI9881C_COMMAND_INSTR(0xCA, 0x29),
0448 ILI9881C_COMMAND_INSTR(0xCB, 0x74),
0449 ILI9881C_COMMAND_INSTR(0xCC, 0x19),
0450 ILI9881C_COMMAND_INSTR(0xCD, 0x17),
0451 ILI9881C_COMMAND_INSTR(0xCE, 0x4B),
0452 ILI9881C_COMMAND_INSTR(0xCF, 0x20),
0453 ILI9881C_COMMAND_INSTR(0xD0, 0x26),
0454 ILI9881C_COMMAND_INSTR(0xD1, 0x4C),
0455 ILI9881C_COMMAND_INSTR(0xD2, 0x5D),
0456 ILI9881C_COMMAND_INSTR(0xD3, 0x3F),
0457 };
0458
0459 static const struct ili9881c_instr w552946ab_init[] = {
0460 ILI9881C_SWITCH_PAGE_INSTR(3),
0461 ILI9881C_COMMAND_INSTR(0x01, 0x00),
0462 ILI9881C_COMMAND_INSTR(0x02, 0x00),
0463 ILI9881C_COMMAND_INSTR(0x03, 0x53),
0464 ILI9881C_COMMAND_INSTR(0x04, 0x53),
0465 ILI9881C_COMMAND_INSTR(0x05, 0x13),
0466 ILI9881C_COMMAND_INSTR(0x06, 0x04),
0467 ILI9881C_COMMAND_INSTR(0x07, 0x02),
0468 ILI9881C_COMMAND_INSTR(0x08, 0x02),
0469 ILI9881C_COMMAND_INSTR(0x09, 0x00),
0470 ILI9881C_COMMAND_INSTR(0x0A, 0x00),
0471 ILI9881C_COMMAND_INSTR(0x0B, 0x00),
0472 ILI9881C_COMMAND_INSTR(0x0C, 0x00),
0473 ILI9881C_COMMAND_INSTR(0x0D, 0x00),
0474 ILI9881C_COMMAND_INSTR(0x0E, 0x00),
0475 ILI9881C_COMMAND_INSTR(0x0F, 0x00),
0476
0477 ILI9881C_COMMAND_INSTR(0x10, 0x00),
0478 ILI9881C_COMMAND_INSTR(0x11, 0x00),
0479 ILI9881C_COMMAND_INSTR(0x12, 0x00),
0480 ILI9881C_COMMAND_INSTR(0x13, 0x00),
0481 ILI9881C_COMMAND_INSTR(0x14, 0x00),
0482 ILI9881C_COMMAND_INSTR(0x15, 0x08),
0483 ILI9881C_COMMAND_INSTR(0x16, 0x10),
0484 ILI9881C_COMMAND_INSTR(0x17, 0x00),
0485 ILI9881C_COMMAND_INSTR(0x18, 0x08),
0486 ILI9881C_COMMAND_INSTR(0x19, 0x00),
0487 ILI9881C_COMMAND_INSTR(0x1A, 0x00),
0488 ILI9881C_COMMAND_INSTR(0x1B, 0x00),
0489 ILI9881C_COMMAND_INSTR(0x1C, 0x00),
0490 ILI9881C_COMMAND_INSTR(0x1D, 0x00),
0491 ILI9881C_COMMAND_INSTR(0x1E, 0xC0),
0492 ILI9881C_COMMAND_INSTR(0x1F, 0x80),
0493
0494 ILI9881C_COMMAND_INSTR(0x20, 0x02),
0495 ILI9881C_COMMAND_INSTR(0x21, 0x09),
0496 ILI9881C_COMMAND_INSTR(0x22, 0x00),
0497 ILI9881C_COMMAND_INSTR(0x23, 0x00),
0498 ILI9881C_COMMAND_INSTR(0x24, 0x00),
0499 ILI9881C_COMMAND_INSTR(0x25, 0x00),
0500 ILI9881C_COMMAND_INSTR(0x26, 0x00),
0501 ILI9881C_COMMAND_INSTR(0x27, 0x00),
0502 ILI9881C_COMMAND_INSTR(0x28, 0x55),
0503 ILI9881C_COMMAND_INSTR(0x29, 0x03),
0504 ILI9881C_COMMAND_INSTR(0x2A, 0x00),
0505 ILI9881C_COMMAND_INSTR(0x2B, 0x00),
0506 ILI9881C_COMMAND_INSTR(0x2C, 0x00),
0507 ILI9881C_COMMAND_INSTR(0x2D, 0x00),
0508 ILI9881C_COMMAND_INSTR(0x2E, 0x00),
0509 ILI9881C_COMMAND_INSTR(0x2F, 0x00),
0510
0511 ILI9881C_COMMAND_INSTR(0x30, 0x00),
0512 ILI9881C_COMMAND_INSTR(0x31, 0x00),
0513 ILI9881C_COMMAND_INSTR(0x32, 0x00),
0514 ILI9881C_COMMAND_INSTR(0x33, 0x00),
0515 ILI9881C_COMMAND_INSTR(0x34, 0x04),
0516 ILI9881C_COMMAND_INSTR(0x35, 0x05),
0517 ILI9881C_COMMAND_INSTR(0x36, 0x05),
0518 ILI9881C_COMMAND_INSTR(0x37, 0x00),
0519 ILI9881C_COMMAND_INSTR(0x38, 0x3C),
0520 ILI9881C_COMMAND_INSTR(0x39, 0x35),
0521 ILI9881C_COMMAND_INSTR(0x3A, 0x00),
0522 ILI9881C_COMMAND_INSTR(0x3B, 0x40),
0523 ILI9881C_COMMAND_INSTR(0x3C, 0x00),
0524 ILI9881C_COMMAND_INSTR(0x3D, 0x00),
0525 ILI9881C_COMMAND_INSTR(0x3E, 0x00),
0526 ILI9881C_COMMAND_INSTR(0x3F, 0x00),
0527
0528 ILI9881C_COMMAND_INSTR(0x40, 0x00),
0529 ILI9881C_COMMAND_INSTR(0x41, 0x88),
0530 ILI9881C_COMMAND_INSTR(0x42, 0x00),
0531 ILI9881C_COMMAND_INSTR(0x43, 0x00),
0532 ILI9881C_COMMAND_INSTR(0x44, 0x1F),
0533
0534 ILI9881C_COMMAND_INSTR(0x50, 0x01),
0535 ILI9881C_COMMAND_INSTR(0x51, 0x23),
0536 ILI9881C_COMMAND_INSTR(0x52, 0x45),
0537 ILI9881C_COMMAND_INSTR(0x53, 0x67),
0538 ILI9881C_COMMAND_INSTR(0x54, 0x89),
0539 ILI9881C_COMMAND_INSTR(0x55, 0xaB),
0540 ILI9881C_COMMAND_INSTR(0x56, 0x01),
0541 ILI9881C_COMMAND_INSTR(0x57, 0x23),
0542 ILI9881C_COMMAND_INSTR(0x58, 0x45),
0543 ILI9881C_COMMAND_INSTR(0x59, 0x67),
0544 ILI9881C_COMMAND_INSTR(0x5A, 0x89),
0545 ILI9881C_COMMAND_INSTR(0x5B, 0xAB),
0546 ILI9881C_COMMAND_INSTR(0x5C, 0xCD),
0547 ILI9881C_COMMAND_INSTR(0x5D, 0xEF),
0548 ILI9881C_COMMAND_INSTR(0x5E, 0x03),
0549 ILI9881C_COMMAND_INSTR(0x5F, 0x14),
0550
0551 ILI9881C_COMMAND_INSTR(0x60, 0x15),
0552 ILI9881C_COMMAND_INSTR(0x61, 0x0C),
0553 ILI9881C_COMMAND_INSTR(0x62, 0x0D),
0554 ILI9881C_COMMAND_INSTR(0x63, 0x0E),
0555 ILI9881C_COMMAND_INSTR(0x64, 0x0F),
0556 ILI9881C_COMMAND_INSTR(0x65, 0x10),
0557 ILI9881C_COMMAND_INSTR(0x66, 0x11),
0558 ILI9881C_COMMAND_INSTR(0x67, 0x08),
0559 ILI9881C_COMMAND_INSTR(0x68, 0x02),
0560 ILI9881C_COMMAND_INSTR(0x69, 0x0A),
0561 ILI9881C_COMMAND_INSTR(0x6A, 0x02),
0562 ILI9881C_COMMAND_INSTR(0x6B, 0x02),
0563 ILI9881C_COMMAND_INSTR(0x6C, 0x02),
0564 ILI9881C_COMMAND_INSTR(0x6D, 0x02),
0565 ILI9881C_COMMAND_INSTR(0x6E, 0x02),
0566 ILI9881C_COMMAND_INSTR(0x6F, 0x02),
0567
0568 ILI9881C_COMMAND_INSTR(0x70, 0x02),
0569 ILI9881C_COMMAND_INSTR(0x71, 0x02),
0570 ILI9881C_COMMAND_INSTR(0x72, 0x06),
0571 ILI9881C_COMMAND_INSTR(0x73, 0x02),
0572 ILI9881C_COMMAND_INSTR(0x74, 0x02),
0573 ILI9881C_COMMAND_INSTR(0x75, 0x14),
0574 ILI9881C_COMMAND_INSTR(0x76, 0x15),
0575 ILI9881C_COMMAND_INSTR(0x77, 0x0F),
0576 ILI9881C_COMMAND_INSTR(0x78, 0x0E),
0577 ILI9881C_COMMAND_INSTR(0x79, 0x0D),
0578 ILI9881C_COMMAND_INSTR(0x7A, 0x0C),
0579 ILI9881C_COMMAND_INSTR(0x7B, 0x11),
0580 ILI9881C_COMMAND_INSTR(0x7C, 0x10),
0581 ILI9881C_COMMAND_INSTR(0x7D, 0x06),
0582 ILI9881C_COMMAND_INSTR(0x7E, 0x02),
0583 ILI9881C_COMMAND_INSTR(0x7F, 0x0A),
0584
0585 ILI9881C_COMMAND_INSTR(0x80, 0x02),
0586 ILI9881C_COMMAND_INSTR(0x81, 0x02),
0587 ILI9881C_COMMAND_INSTR(0x82, 0x02),
0588 ILI9881C_COMMAND_INSTR(0x83, 0x02),
0589 ILI9881C_COMMAND_INSTR(0x84, 0x02),
0590 ILI9881C_COMMAND_INSTR(0x85, 0x02),
0591 ILI9881C_COMMAND_INSTR(0x86, 0x02),
0592 ILI9881C_COMMAND_INSTR(0x87, 0x02),
0593 ILI9881C_COMMAND_INSTR(0x88, 0x08),
0594 ILI9881C_COMMAND_INSTR(0x89, 0x02),
0595 ILI9881C_COMMAND_INSTR(0x8A, 0x02),
0596
0597 ILI9881C_SWITCH_PAGE_INSTR(4),
0598 ILI9881C_COMMAND_INSTR(0x00, 0x80),
0599 ILI9881C_COMMAND_INSTR(0x70, 0x00),
0600 ILI9881C_COMMAND_INSTR(0x71, 0x00),
0601 ILI9881C_COMMAND_INSTR(0x66, 0xFE),
0602 ILI9881C_COMMAND_INSTR(0x82, 0x15),
0603 ILI9881C_COMMAND_INSTR(0x84, 0x15),
0604 ILI9881C_COMMAND_INSTR(0x85, 0x15),
0605 ILI9881C_COMMAND_INSTR(0x3a, 0x24),
0606 ILI9881C_COMMAND_INSTR(0x32, 0xAC),
0607 ILI9881C_COMMAND_INSTR(0x8C, 0x80),
0608 ILI9881C_COMMAND_INSTR(0x3C, 0xF5),
0609 ILI9881C_COMMAND_INSTR(0x88, 0x33),
0610
0611 ILI9881C_SWITCH_PAGE_INSTR(1),
0612 ILI9881C_COMMAND_INSTR(0x22, 0x0A),
0613 ILI9881C_COMMAND_INSTR(0x31, 0x00),
0614 ILI9881C_COMMAND_INSTR(0x53, 0x78),
0615 ILI9881C_COMMAND_INSTR(0x50, 0x5B),
0616 ILI9881C_COMMAND_INSTR(0x51, 0x5B),
0617 ILI9881C_COMMAND_INSTR(0x60, 0x20),
0618 ILI9881C_COMMAND_INSTR(0x61, 0x00),
0619 ILI9881C_COMMAND_INSTR(0x62, 0x0D),
0620 ILI9881C_COMMAND_INSTR(0x63, 0x00),
0621
0622 ILI9881C_COMMAND_INSTR(0xA0, 0x00),
0623 ILI9881C_COMMAND_INSTR(0xA1, 0x10),
0624 ILI9881C_COMMAND_INSTR(0xA2, 0x1C),
0625 ILI9881C_COMMAND_INSTR(0xA3, 0x13),
0626 ILI9881C_COMMAND_INSTR(0xA4, 0x15),
0627 ILI9881C_COMMAND_INSTR(0xA5, 0x26),
0628 ILI9881C_COMMAND_INSTR(0xA6, 0x1A),
0629 ILI9881C_COMMAND_INSTR(0xA7, 0x1D),
0630 ILI9881C_COMMAND_INSTR(0xA8, 0x67),
0631 ILI9881C_COMMAND_INSTR(0xA9, 0x1C),
0632 ILI9881C_COMMAND_INSTR(0xAA, 0x29),
0633 ILI9881C_COMMAND_INSTR(0xAB, 0x5B),
0634 ILI9881C_COMMAND_INSTR(0xAC, 0x26),
0635 ILI9881C_COMMAND_INSTR(0xAD, 0x28),
0636 ILI9881C_COMMAND_INSTR(0xAE, 0x5C),
0637 ILI9881C_COMMAND_INSTR(0xAF, 0x30),
0638 ILI9881C_COMMAND_INSTR(0xB0, 0x31),
0639 ILI9881C_COMMAND_INSTR(0xB1, 0x2E),
0640 ILI9881C_COMMAND_INSTR(0xB2, 0x32),
0641 ILI9881C_COMMAND_INSTR(0xB3, 0x00),
0642
0643 ILI9881C_COMMAND_INSTR(0xC0, 0x00),
0644 ILI9881C_COMMAND_INSTR(0xC1, 0x10),
0645 ILI9881C_COMMAND_INSTR(0xC2, 0x1C),
0646 ILI9881C_COMMAND_INSTR(0xC3, 0x13),
0647 ILI9881C_COMMAND_INSTR(0xC4, 0x15),
0648 ILI9881C_COMMAND_INSTR(0xC5, 0x26),
0649 ILI9881C_COMMAND_INSTR(0xC6, 0x1A),
0650 ILI9881C_COMMAND_INSTR(0xC7, 0x1D),
0651 ILI9881C_COMMAND_INSTR(0xC8, 0x67),
0652 ILI9881C_COMMAND_INSTR(0xC9, 0x1C),
0653 ILI9881C_COMMAND_INSTR(0xCA, 0x29),
0654 ILI9881C_COMMAND_INSTR(0xCB, 0x5B),
0655 ILI9881C_COMMAND_INSTR(0xCC, 0x26),
0656 ILI9881C_COMMAND_INSTR(0xCD, 0x28),
0657 ILI9881C_COMMAND_INSTR(0xCE, 0x5C),
0658 ILI9881C_COMMAND_INSTR(0xCF, 0x30),
0659 ILI9881C_COMMAND_INSTR(0xD0, 0x31),
0660 ILI9881C_COMMAND_INSTR(0xD1, 0x2E),
0661 ILI9881C_COMMAND_INSTR(0xD2, 0x32),
0662 ILI9881C_COMMAND_INSTR(0xD3, 0x00),
0663 ILI9881C_SWITCH_PAGE_INSTR(0),
0664 };
0665
0666 static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel)
0667 {
0668 return container_of(panel, struct ili9881c, panel);
0669 }
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682 static int ili9881c_switch_page(struct ili9881c *ctx, u8 page)
0683 {
0684 u8 buf[4] = { 0xff, 0x98, 0x81, page };
0685 int ret;
0686
0687 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, buf, sizeof(buf));
0688 if (ret < 0)
0689 return ret;
0690
0691 return 0;
0692 }
0693
0694 static int ili9881c_send_cmd_data(struct ili9881c *ctx, u8 cmd, u8 data)
0695 {
0696 u8 buf[2] = { cmd, data };
0697 int ret;
0698
0699 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, buf, sizeof(buf));
0700 if (ret < 0)
0701 return ret;
0702
0703 return 0;
0704 }
0705
0706 static int ili9881c_prepare(struct drm_panel *panel)
0707 {
0708 struct ili9881c *ctx = panel_to_ili9881c(panel);
0709 unsigned int i;
0710 int ret;
0711
0712
0713 ret = regulator_enable(ctx->power);
0714 if (ret)
0715 return ret;
0716 msleep(5);
0717
0718
0719 gpiod_set_value(ctx->reset, 1);
0720 msleep(20);
0721
0722 gpiod_set_value(ctx->reset, 0);
0723 msleep(20);
0724
0725 for (i = 0; i < ctx->desc->init_length; i++) {
0726 const struct ili9881c_instr *instr = &ctx->desc->init[i];
0727
0728 if (instr->op == ILI9881C_SWITCH_PAGE)
0729 ret = ili9881c_switch_page(ctx, instr->arg.page);
0730 else if (instr->op == ILI9881C_COMMAND)
0731 ret = ili9881c_send_cmd_data(ctx, instr->arg.cmd.cmd,
0732 instr->arg.cmd.data);
0733
0734 if (ret)
0735 return ret;
0736 }
0737
0738 ret = ili9881c_switch_page(ctx, 0);
0739 if (ret)
0740 return ret;
0741
0742 ret = mipi_dsi_dcs_set_tear_on(ctx->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0743 if (ret)
0744 return ret;
0745
0746 ret = mipi_dsi_dcs_exit_sleep_mode(ctx->dsi);
0747 if (ret)
0748 return ret;
0749
0750 return 0;
0751 }
0752
0753 static int ili9881c_enable(struct drm_panel *panel)
0754 {
0755 struct ili9881c *ctx = panel_to_ili9881c(panel);
0756
0757 msleep(120);
0758
0759 mipi_dsi_dcs_set_display_on(ctx->dsi);
0760
0761 return 0;
0762 }
0763
0764 static int ili9881c_disable(struct drm_panel *panel)
0765 {
0766 struct ili9881c *ctx = panel_to_ili9881c(panel);
0767
0768 return mipi_dsi_dcs_set_display_off(ctx->dsi);
0769 }
0770
0771 static int ili9881c_unprepare(struct drm_panel *panel)
0772 {
0773 struct ili9881c *ctx = panel_to_ili9881c(panel);
0774
0775 mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
0776 regulator_disable(ctx->power);
0777 gpiod_set_value(ctx->reset, 1);
0778
0779 return 0;
0780 }
0781
0782 static const struct drm_display_mode lhr050h41_default_mode = {
0783 .clock = 62000,
0784
0785 .hdisplay = 720,
0786 .hsync_start = 720 + 10,
0787 .hsync_end = 720 + 10 + 20,
0788 .htotal = 720 + 10 + 20 + 30,
0789
0790 .vdisplay = 1280,
0791 .vsync_start = 1280 + 10,
0792 .vsync_end = 1280 + 10 + 10,
0793 .vtotal = 1280 + 10 + 10 + 20,
0794
0795 .width_mm = 62,
0796 .height_mm = 110,
0797 };
0798
0799 static const struct drm_display_mode k101_im2byl02_default_mode = {
0800 .clock = 69700,
0801
0802 .hdisplay = 800,
0803 .hsync_start = 800 + 52,
0804 .hsync_end = 800 + 52 + 8,
0805 .htotal = 800 + 52 + 8 + 48,
0806
0807 .vdisplay = 1280,
0808 .vsync_start = 1280 + 16,
0809 .vsync_end = 1280 + 16 + 6,
0810 .vtotal = 1280 + 16 + 6 + 15,
0811
0812 .width_mm = 135,
0813 .height_mm = 217,
0814 };
0815
0816 static const struct drm_display_mode w552946aba_default_mode = {
0817 .clock = 64000,
0818
0819 .hdisplay = 720,
0820 .hsync_start = 720 + 40,
0821 .hsync_end = 720 + 40 + 10,
0822 .htotal = 720 + 40 + 10 + 40,
0823
0824 .vdisplay = 1280,
0825 .vsync_start = 1280 + 22,
0826 .vsync_end = 1280 + 22 + 4,
0827 .vtotal = 1280 + 22 + 4 + 11,
0828
0829 .width_mm = 68,
0830 .height_mm = 121,
0831 };
0832
0833 static int ili9881c_get_modes(struct drm_panel *panel,
0834 struct drm_connector *connector)
0835 {
0836 struct ili9881c *ctx = panel_to_ili9881c(panel);
0837 struct drm_display_mode *mode;
0838
0839 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
0840 if (!mode) {
0841 dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n",
0842 ctx->desc->mode->hdisplay,
0843 ctx->desc->mode->vdisplay,
0844 drm_mode_vrefresh(ctx->desc->mode));
0845 return -ENOMEM;
0846 }
0847
0848 drm_mode_set_name(mode);
0849
0850 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0851 drm_mode_probed_add(connector, mode);
0852
0853 connector->display_info.width_mm = mode->width_mm;
0854 connector->display_info.height_mm = mode->height_mm;
0855
0856
0857
0858
0859
0860 drm_connector_set_panel_orientation(connector, ctx->orientation);
0861
0862 return 1;
0863 }
0864
0865 static enum drm_panel_orientation ili9881c_get_orientation(struct drm_panel *panel)
0866 {
0867 struct ili9881c *ctx = panel_to_ili9881c(panel);
0868
0869 return ctx->orientation;
0870 }
0871
0872 static const struct drm_panel_funcs ili9881c_funcs = {
0873 .prepare = ili9881c_prepare,
0874 .unprepare = ili9881c_unprepare,
0875 .enable = ili9881c_enable,
0876 .disable = ili9881c_disable,
0877 .get_modes = ili9881c_get_modes,
0878 .get_orientation = ili9881c_get_orientation,
0879 };
0880
0881 static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi)
0882 {
0883 struct ili9881c *ctx;
0884 int ret;
0885
0886 ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
0887 if (!ctx)
0888 return -ENOMEM;
0889 mipi_dsi_set_drvdata(dsi, ctx);
0890 ctx->dsi = dsi;
0891 ctx->desc = of_device_get_match_data(&dsi->dev);
0892
0893 drm_panel_init(&ctx->panel, &dsi->dev, &ili9881c_funcs,
0894 DRM_MODE_CONNECTOR_DSI);
0895
0896 ctx->power = devm_regulator_get(&dsi->dev, "power");
0897 if (IS_ERR(ctx->power))
0898 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->power),
0899 "Couldn't get our power regulator\n");
0900
0901 ctx->reset = devm_gpiod_get_optional(&dsi->dev, "reset", GPIOD_OUT_LOW);
0902 if (IS_ERR(ctx->reset))
0903 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset),
0904 "Couldn't get our reset GPIO\n");
0905
0906 ret = of_drm_get_panel_orientation(dsi->dev.of_node, &ctx->orientation);
0907 if (ret) {
0908 dev_err(&dsi->dev, "%pOF: failed to get orientation: %d\n",
0909 dsi->dev.of_node, ret);
0910 return ret;
0911 }
0912
0913 ret = drm_panel_of_backlight(&ctx->panel);
0914 if (ret)
0915 return ret;
0916
0917 drm_panel_add(&ctx->panel);
0918
0919 dsi->mode_flags = ctx->desc->mode_flags;
0920 dsi->format = MIPI_DSI_FMT_RGB888;
0921 dsi->lanes = 4;
0922
0923 return mipi_dsi_attach(dsi);
0924 }
0925
0926 static int ili9881c_dsi_remove(struct mipi_dsi_device *dsi)
0927 {
0928 struct ili9881c *ctx = mipi_dsi_get_drvdata(dsi);
0929
0930 mipi_dsi_detach(dsi);
0931 drm_panel_remove(&ctx->panel);
0932
0933 return 0;
0934 }
0935
0936 static const struct ili9881c_desc lhr050h41_desc = {
0937 .init = lhr050h41_init,
0938 .init_length = ARRAY_SIZE(lhr050h41_init),
0939 .mode = &lhr050h41_default_mode,
0940 .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
0941 };
0942
0943 static const struct ili9881c_desc k101_im2byl02_desc = {
0944 .init = k101_im2byl02_init,
0945 .init_length = ARRAY_SIZE(k101_im2byl02_init),
0946 .mode = &k101_im2byl02_default_mode,
0947 .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
0948 };
0949
0950 static const struct ili9881c_desc w552946aba_desc = {
0951 .init = w552946ab_init,
0952 .init_length = ARRAY_SIZE(w552946ab_init),
0953 .mode = &w552946aba_default_mode,
0954 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
0955 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET,
0956 };
0957
0958 static const struct of_device_id ili9881c_of_match[] = {
0959 { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc },
0960 { .compatible = "feixin,k101-im2byl02", .data = &k101_im2byl02_desc },
0961 { .compatible = "wanchanglong,w552946aba", .data = &w552946aba_desc },
0962 { }
0963 };
0964 MODULE_DEVICE_TABLE(of, ili9881c_of_match);
0965
0966 static struct mipi_dsi_driver ili9881c_dsi_driver = {
0967 .probe = ili9881c_dsi_probe,
0968 .remove = ili9881c_dsi_remove,
0969 .driver = {
0970 .name = "ili9881c-dsi",
0971 .of_match_table = ili9881c_of_match,
0972 },
0973 };
0974 module_mipi_dsi_driver(ili9881c_dsi_driver);
0975
0976 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
0977 MODULE_DESCRIPTION("Ilitek ILI9881C Controller Driver");
0978 MODULE_LICENSE("GPL v2");