0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/gpio/consumer.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/regulator/consumer.h>
0012
0013 #include <video/mipi_display.h>
0014
0015 #include <drm/drm_crtc.h>
0016 #include <drm/drm_device.h>
0017 #include <drm/drm_mipi_dsi.h>
0018 #include <drm/drm_modes.h>
0019 #include <drm/drm_panel.h>
0020
0021 struct khadas_ts050_panel {
0022 struct drm_panel base;
0023 struct mipi_dsi_device *link;
0024
0025 struct regulator *supply;
0026 struct gpio_desc *reset_gpio;
0027 struct gpio_desc *enable_gpio;
0028
0029 bool prepared;
0030 bool enabled;
0031 };
0032
0033 struct khadas_ts050_panel_cmd {
0034 u8 cmd;
0035 u8 data;
0036 };
0037
0038
0039 static const struct khadas_ts050_panel_cmd init_code[] = {
0040
0041 {0xff, 0xee},
0042
0043 {0xfb, 0x01},
0044 {0x1f, 0x45},
0045 {0x24, 0x4f},
0046 {0x38, 0xc8},
0047 {0x39, 0x27},
0048 {0x1e, 0x77},
0049 {0x1d, 0x0f},
0050 {0x7e, 0x71},
0051 {0x7c, 0x03},
0052 {0xff, 0x00},
0053 {0xfb, 0x01},
0054 {0x35, 0x01},
0055
0056 {0xff, 0x01},
0057
0058 {0xfb, 0x01},
0059 {0x00, 0x01},
0060 {0x01, 0x55},
0061 {0x02, 0x40},
0062 {0x05, 0x40},
0063 {0x06, 0x4a},
0064 {0x07, 0x24},
0065 {0x08, 0x0c},
0066 {0x0b, 0x7d},
0067 {0x0c, 0x7d},
0068 {0x0e, 0xb0},
0069 {0x0f, 0xae},
0070 {0x11, 0x10},
0071 {0x12, 0x10},
0072 {0x13, 0x03},
0073 {0x14, 0x4a},
0074 {0x15, 0x12},
0075 {0x16, 0x12},
0076 {0x18, 0x00},
0077 {0x19, 0x77},
0078 {0x1a, 0x55},
0079 {0x1b, 0x13},
0080 {0x1c, 0x00},
0081 {0x1d, 0x00},
0082 {0x1e, 0x13},
0083 {0x1f, 0x00},
0084 {0x23, 0x00},
0085 {0x24, 0x00},
0086 {0x25, 0x00},
0087 {0x26, 0x00},
0088 {0x27, 0x00},
0089 {0x28, 0x00},
0090 {0x35, 0x00},
0091 {0x66, 0x00},
0092 {0x58, 0x82},
0093 {0x59, 0x02},
0094 {0x5a, 0x02},
0095 {0x5b, 0x02},
0096 {0x5c, 0x82},
0097 {0x5d, 0x82},
0098 {0x5e, 0x02},
0099 {0x5f, 0x02},
0100 {0x72, 0x31},
0101
0102 {0xff, 0x05},
0103
0104 {0xfb, 0x01},
0105 {0x00, 0x01},
0106 {0x01, 0x0b},
0107 {0x02, 0x0c},
0108 {0x03, 0x09},
0109 {0x04, 0x0a},
0110 {0x05, 0x00},
0111 {0x06, 0x0f},
0112 {0x07, 0x10},
0113 {0x08, 0x00},
0114 {0x09, 0x00},
0115 {0x0a, 0x00},
0116 {0x0b, 0x00},
0117 {0x0c, 0x00},
0118 {0x0d, 0x13},
0119 {0x0e, 0x15},
0120 {0x0f, 0x17},
0121 {0x10, 0x01},
0122 {0x11, 0x0b},
0123 {0x12, 0x0c},
0124 {0x13, 0x09},
0125 {0x14, 0x0a},
0126 {0x15, 0x00},
0127 {0x16, 0x0f},
0128 {0x17, 0x10},
0129 {0x18, 0x00},
0130 {0x19, 0x00},
0131 {0x1a, 0x00},
0132 {0x1b, 0x00},
0133 {0x1c, 0x00},
0134 {0x1d, 0x13},
0135 {0x1e, 0x15},
0136 {0x1f, 0x17},
0137 {0x20, 0x00},
0138 {0x21, 0x03},
0139 {0x22, 0x01},
0140 {0x23, 0x40},
0141 {0x24, 0x40},
0142 {0x25, 0xed},
0143 {0x29, 0x58},
0144 {0x2a, 0x12},
0145 {0x2b, 0x01},
0146 {0x4b, 0x06},
0147 {0x4c, 0x11},
0148 {0x4d, 0x20},
0149 {0x4e, 0x02},
0150 {0x4f, 0x02},
0151 {0x50, 0x20},
0152 {0x51, 0x61},
0153 {0x52, 0x01},
0154 {0x53, 0x63},
0155 {0x54, 0x77},
0156 {0x55, 0xed},
0157 {0x5b, 0x00},
0158 {0x5c, 0x00},
0159 {0x5d, 0x00},
0160 {0x5e, 0x00},
0161 {0x5f, 0x15},
0162 {0x60, 0x75},
0163 {0x61, 0x00},
0164 {0x62, 0x00},
0165 {0x63, 0x00},
0166 {0x64, 0x00},
0167 {0x65, 0x00},
0168 {0x66, 0x00},
0169 {0x67, 0x00},
0170 {0x68, 0x04},
0171 {0x69, 0x00},
0172 {0x6a, 0x00},
0173 {0x6c, 0x40},
0174 {0x75, 0x01},
0175 {0x76, 0x01},
0176 {0x7a, 0x80},
0177 {0x7b, 0xa3},
0178 {0x7c, 0xd8},
0179 {0x7d, 0x60},
0180 {0x7f, 0x15},
0181 {0x80, 0x81},
0182 {0x83, 0x05},
0183 {0x93, 0x08},
0184 {0x94, 0x10},
0185 {0x8a, 0x00},
0186 {0x9b, 0x0f},
0187 {0xea, 0xff},
0188 {0xec, 0x00},
0189
0190 {0xff, 0x01},
0191
0192 {0xfb, 0x01},
0193 {0x75, 0x00},
0194 {0x76, 0xdf},
0195 {0x77, 0x00},
0196 {0x78, 0xe4},
0197 {0x79, 0x00},
0198 {0x7a, 0xed},
0199 {0x7b, 0x00},
0200 {0x7c, 0xf6},
0201 {0x7d, 0x00},
0202 {0x7e, 0xff},
0203 {0x7f, 0x01},
0204 {0x80, 0x07},
0205 {0x81, 0x01},
0206 {0x82, 0x10},
0207 {0x83, 0x01},
0208 {0x84, 0x18},
0209 {0x85, 0x01},
0210 {0x86, 0x20},
0211 {0x87, 0x01},
0212 {0x88, 0x3d},
0213 {0x89, 0x01},
0214 {0x8a, 0x56},
0215 {0x8b, 0x01},
0216 {0x8c, 0x84},
0217 {0x8d, 0x01},
0218 {0x8e, 0xab},
0219 {0x8f, 0x01},
0220 {0x90, 0xec},
0221 {0x91, 0x02},
0222 {0x92, 0x22},
0223 {0x93, 0x02},
0224 {0x94, 0x23},
0225 {0x95, 0x02},
0226 {0x96, 0x55},
0227 {0x97, 0x02},
0228 {0x98, 0x8b},
0229 {0x99, 0x02},
0230 {0x9a, 0xaf},
0231 {0x9b, 0x02},
0232 {0x9c, 0xdf},
0233 {0x9d, 0x03},
0234 {0x9e, 0x01},
0235 {0x9f, 0x03},
0236 {0xa0, 0x2c},
0237 {0xa2, 0x03},
0238 {0xa3, 0x39},
0239 {0xa4, 0x03},
0240 {0xa5, 0x47},
0241 {0xa6, 0x03},
0242 {0xa7, 0x56},
0243 {0xa9, 0x03},
0244 {0xaa, 0x66},
0245 {0xab, 0x03},
0246 {0xac, 0x76},
0247 {0xad, 0x03},
0248 {0xae, 0x85},
0249 {0xaf, 0x03},
0250 {0xb0, 0x90},
0251 {0xb1, 0x03},
0252 {0xb2, 0xcb},
0253 {0xb3, 0x00},
0254 {0xb4, 0xdf},
0255 {0xb5, 0x00},
0256 {0xb6, 0xe4},
0257 {0xb7, 0x00},
0258 {0xb8, 0xed},
0259 {0xb9, 0x00},
0260 {0xba, 0xf6},
0261 {0xbb, 0x00},
0262 {0xbc, 0xff},
0263 {0xbd, 0x01},
0264 {0xbe, 0x07},
0265 {0xbf, 0x01},
0266 {0xc0, 0x10},
0267 {0xc1, 0x01},
0268 {0xc2, 0x18},
0269 {0xc3, 0x01},
0270 {0xc4, 0x20},
0271 {0xc5, 0x01},
0272 {0xc6, 0x3d},
0273 {0xc7, 0x01},
0274 {0xc8, 0x56},
0275 {0xc9, 0x01},
0276 {0xca, 0x84},
0277 {0xcb, 0x01},
0278 {0xcc, 0xab},
0279 {0xcd, 0x01},
0280 {0xce, 0xec},
0281 {0xcf, 0x02},
0282 {0xd0, 0x22},
0283 {0xd1, 0x02},
0284 {0xd2, 0x23},
0285 {0xd3, 0x02},
0286 {0xd4, 0x55},
0287 {0xd5, 0x02},
0288 {0xd6, 0x8b},
0289 {0xd7, 0x02},
0290 {0xd8, 0xaf},
0291 {0xd9, 0x02},
0292 {0xda, 0xdf},
0293 {0xdb, 0x03},
0294 {0xdc, 0x01},
0295 {0xdd, 0x03},
0296 {0xde, 0x2c},
0297 {0xdf, 0x03},
0298 {0xe0, 0x39},
0299 {0xe1, 0x03},
0300 {0xe2, 0x47},
0301 {0xe3, 0x03},
0302 {0xe4, 0x56},
0303 {0xe5, 0x03},
0304 {0xe6, 0x66},
0305 {0xe7, 0x03},
0306 {0xe8, 0x76},
0307 {0xe9, 0x03},
0308 {0xea, 0x85},
0309 {0xeb, 0x03},
0310 {0xec, 0x90},
0311 {0xed, 0x03},
0312 {0xee, 0xcb},
0313 {0xef, 0x00},
0314 {0xf0, 0xbb},
0315 {0xf1, 0x00},
0316 {0xf2, 0xc0},
0317 {0xf3, 0x00},
0318 {0xf4, 0xcc},
0319 {0xf5, 0x00},
0320 {0xf6, 0xd6},
0321 {0xf7, 0x00},
0322 {0xf8, 0xe1},
0323 {0xf9, 0x00},
0324 {0xfa, 0xea},
0325
0326 {0xff, 0x02},
0327
0328 {0xfb, 0x01},
0329 {0x00, 0x00},
0330 {0x01, 0xf4},
0331 {0x02, 0x00},
0332 {0x03, 0xef},
0333 {0x04, 0x01},
0334 {0x05, 0x07},
0335 {0x06, 0x01},
0336 {0x07, 0x28},
0337 {0x08, 0x01},
0338 {0x09, 0x44},
0339 {0x0a, 0x01},
0340 {0x0b, 0x76},
0341 {0x0c, 0x01},
0342 {0x0d, 0xa0},
0343 {0x0e, 0x01},
0344 {0x0f, 0xe7},
0345 {0x10, 0x02},
0346 {0x11, 0x1f},
0347 {0x12, 0x02},
0348 {0x13, 0x22},
0349 {0x14, 0x02},
0350 {0x15, 0x54},
0351 {0x16, 0x02},
0352 {0x17, 0x8b},
0353 {0x18, 0x02},
0354 {0x19, 0xaf},
0355 {0x1a, 0x02},
0356 {0x1b, 0xe0},
0357 {0x1c, 0x03},
0358 {0x1d, 0x01},
0359 {0x1e, 0x03},
0360 {0x1f, 0x2d},
0361 {0x20, 0x03},
0362 {0x21, 0x39},
0363 {0x22, 0x03},
0364 {0x23, 0x47},
0365 {0x24, 0x03},
0366 {0x25, 0x57},
0367 {0x26, 0x03},
0368 {0x27, 0x65},
0369 {0x28, 0x03},
0370 {0x29, 0x77},
0371 {0x2a, 0x03},
0372 {0x2b, 0x85},
0373 {0x2d, 0x03},
0374 {0x2f, 0x8f},
0375 {0x30, 0x03},
0376 {0x31, 0xcb},
0377 {0x32, 0x00},
0378 {0x33, 0xbb},
0379 {0x34, 0x00},
0380 {0x35, 0xc0},
0381 {0x36, 0x00},
0382 {0x37, 0xcc},
0383 {0x38, 0x00},
0384 {0x39, 0xd6},
0385 {0x3a, 0x00},
0386 {0x3b, 0xe1},
0387 {0x3d, 0x00},
0388 {0x3f, 0xea},
0389 {0x40, 0x00},
0390 {0x41, 0xf4},
0391 {0x42, 0x00},
0392 {0x43, 0xfe},
0393 {0x44, 0x01},
0394 {0x45, 0x07},
0395 {0x46, 0x01},
0396 {0x47, 0x28},
0397 {0x48, 0x01},
0398 {0x49, 0x44},
0399 {0x4a, 0x01},
0400 {0x4b, 0x76},
0401 {0x4c, 0x01},
0402 {0x4d, 0xa0},
0403 {0x4e, 0x01},
0404 {0x4f, 0xe7},
0405 {0x50, 0x02},
0406 {0x51, 0x1f},
0407 {0x52, 0x02},
0408 {0x53, 0x22},
0409 {0x54, 0x02},
0410 {0x55, 0x54},
0411 {0x56, 0x02},
0412 {0x58, 0x8b},
0413 {0x59, 0x02},
0414 {0x5a, 0xaf},
0415 {0x5b, 0x02},
0416 {0x5c, 0xe0},
0417 {0x5d, 0x03},
0418 {0x5e, 0x01},
0419 {0x5f, 0x03},
0420 {0x60, 0x2d},
0421 {0x61, 0x03},
0422 {0x62, 0x39},
0423 {0x63, 0x03},
0424 {0x64, 0x47},
0425 {0x65, 0x03},
0426 {0x66, 0x57},
0427 {0x67, 0x03},
0428 {0x68, 0x65},
0429 {0x69, 0x03},
0430 {0x6a, 0x77},
0431 {0x6b, 0x03},
0432 {0x6c, 0x85},
0433 {0x6d, 0x03},
0434 {0x6e, 0x8f},
0435 {0x6f, 0x03},
0436 {0x70, 0xcb},
0437 {0x71, 0x00},
0438 {0x72, 0x00},
0439 {0x73, 0x00},
0440 {0x74, 0x21},
0441 {0x75, 0x00},
0442 {0x76, 0x4c},
0443 {0x77, 0x00},
0444 {0x78, 0x6b},
0445 {0x79, 0x00},
0446 {0x7a, 0x85},
0447 {0x7b, 0x00},
0448 {0x7c, 0x9a},
0449 {0x7d, 0x00},
0450 {0x7e, 0xad},
0451 {0x7f, 0x00},
0452 {0x80, 0xbe},
0453 {0x81, 0x00},
0454 {0x82, 0xcd},
0455 {0x83, 0x01},
0456 {0x84, 0x01},
0457 {0x85, 0x01},
0458 {0x86, 0x29},
0459 {0x87, 0x01},
0460 {0x88, 0x68},
0461 {0x89, 0x01},
0462 {0x8a, 0x98},
0463 {0x8b, 0x01},
0464 {0x8c, 0xe5},
0465 {0x8d, 0x02},
0466 {0x8e, 0x1e},
0467 {0x8f, 0x02},
0468 {0x90, 0x30},
0469 {0x91, 0x02},
0470 {0x92, 0x52},
0471 {0x93, 0x02},
0472 {0x94, 0x88},
0473 {0x95, 0x02},
0474 {0x96, 0xaa},
0475 {0x97, 0x02},
0476 {0x98, 0xd7},
0477 {0x99, 0x02},
0478 {0x9a, 0xf7},
0479 {0x9b, 0x03},
0480 {0x9c, 0x21},
0481 {0x9d, 0x03},
0482 {0x9e, 0x2e},
0483 {0x9f, 0x03},
0484 {0xa0, 0x3d},
0485 {0xa2, 0x03},
0486 {0xa3, 0x4c},
0487 {0xa4, 0x03},
0488 {0xa5, 0x5e},
0489 {0xa6, 0x03},
0490 {0xa7, 0x71},
0491 {0xa9, 0x03},
0492 {0xaa, 0x86},
0493 {0xab, 0x03},
0494 {0xac, 0x94},
0495 {0xad, 0x03},
0496 {0xae, 0xfa},
0497 {0xaf, 0x00},
0498 {0xb0, 0x00},
0499 {0xb1, 0x00},
0500 {0xb2, 0x21},
0501 {0xb3, 0x00},
0502 {0xb4, 0x4c},
0503 {0xb5, 0x00},
0504 {0xb6, 0x6b},
0505 {0xb7, 0x00},
0506 {0xb8, 0x85},
0507 {0xb9, 0x00},
0508 {0xba, 0x9a},
0509 {0xbb, 0x00},
0510 {0xbc, 0xad},
0511 {0xbd, 0x00},
0512 {0xbe, 0xbe},
0513 {0xbf, 0x00},
0514 {0xc0, 0xcd},
0515 {0xc1, 0x01},
0516 {0xc2, 0x01},
0517 {0xc3, 0x01},
0518 {0xc4, 0x29},
0519 {0xc5, 0x01},
0520 {0xc6, 0x68},
0521 {0xc7, 0x01},
0522 {0xc8, 0x98},
0523 {0xc9, 0x01},
0524 {0xca, 0xe5},
0525 {0xcb, 0x02},
0526 {0xcc, 0x1e},
0527 {0xcd, 0x02},
0528 {0xce, 0x20},
0529 {0xcf, 0x02},
0530 {0xd0, 0x52},
0531 {0xd1, 0x02},
0532 {0xd2, 0x88},
0533 {0xd3, 0x02},
0534 {0xd4, 0xaa},
0535 {0xd5, 0x02},
0536 {0xd6, 0xd7},
0537 {0xd7, 0x02},
0538 {0xd8, 0xf7},
0539 {0xd9, 0x03},
0540 {0xda, 0x21},
0541 {0xdb, 0x03},
0542 {0xdc, 0x2e},
0543 {0xdd, 0x03},
0544 {0xde, 0x3d},
0545 {0xdf, 0x03},
0546 {0xe0, 0x4c},
0547 {0xe1, 0x03},
0548 {0xe2, 0x5e},
0549 {0xe3, 0x03},
0550 {0xe4, 0x71},
0551 {0xe5, 0x03},
0552 {0xe6, 0x86},
0553 {0xe7, 0x03},
0554 {0xe8, 0x94},
0555 {0xe9, 0x03},
0556 {0xea, 0xfa},
0557
0558 {0xff, 0x01},
0559
0560 {0xfb, 0x01},
0561
0562 {0xff, 0x02},
0563
0564 {0xfb, 0x01},
0565
0566 {0xff, 0x04},
0567
0568 {0xfb, 0x01},
0569
0570 {0xff, 0x00},
0571 {0xd3, 0x05},
0572 {0xd4, 0x04},
0573 };
0574
0575 static inline
0576 struct khadas_ts050_panel *to_khadas_ts050_panel(struct drm_panel *panel)
0577 {
0578 return container_of(panel, struct khadas_ts050_panel, base);
0579 }
0580
0581 static int khadas_ts050_panel_prepare(struct drm_panel *panel)
0582 {
0583 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
0584 unsigned int i;
0585 int err;
0586
0587 if (khadas_ts050->prepared)
0588 return 0;
0589
0590 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
0591
0592 err = regulator_enable(khadas_ts050->supply);
0593 if (err < 0)
0594 return err;
0595
0596 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 1);
0597
0598 msleep(60);
0599
0600 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
0601
0602 usleep_range(10000, 11000);
0603
0604 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 0);
0605
0606
0607 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x05 }, 1);
0608
0609
0610 mipi_dsi_dcs_write(khadas_ts050->link, 0xfb, (u8[]){ 0x01 }, 1);
0611
0612 mipi_dsi_dcs_write(khadas_ts050->link, 0xc5, (u8[]){ 0x01 }, 1);
0613
0614 msleep(100);
0615
0616 for (i = 0; i < ARRAY_SIZE(init_code); i++) {
0617 err = mipi_dsi_dcs_write(khadas_ts050->link,
0618 init_code[i].cmd,
0619 &init_code[i].data, 1);
0620 if (err < 0) {
0621 dev_err(panel->dev, "failed write cmds: %d\n", err);
0622 goto poweroff;
0623 }
0624 }
0625
0626 err = mipi_dsi_dcs_exit_sleep_mode(khadas_ts050->link);
0627 if (err < 0) {
0628 dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
0629 goto poweroff;
0630 }
0631
0632 msleep(120);
0633
0634
0635 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x00 }, 1);
0636
0637 err = mipi_dsi_dcs_set_tear_on(khadas_ts050->link,
0638 MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0639 if (err < 0) {
0640 dev_err(panel->dev, "failed to set tear on: %d\n", err);
0641 goto poweroff;
0642 }
0643
0644 err = mipi_dsi_dcs_set_display_on(khadas_ts050->link);
0645 if (err < 0) {
0646 dev_err(panel->dev, "failed to set display on: %d\n", err);
0647 goto poweroff;
0648 }
0649
0650 usleep_range(10000, 11000);
0651
0652 khadas_ts050->prepared = true;
0653
0654 return 0;
0655
0656 poweroff:
0657 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
0658 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
0659
0660 regulator_disable(khadas_ts050->supply);
0661
0662 return err;
0663 }
0664
0665 static int khadas_ts050_panel_unprepare(struct drm_panel *panel)
0666 {
0667 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
0668 int err;
0669
0670 if (!khadas_ts050->prepared)
0671 return 0;
0672
0673 khadas_ts050->prepared = false;
0674
0675 err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link);
0676 if (err < 0)
0677 dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
0678
0679 msleep(150);
0680
0681 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
0682 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
0683
0684 err = regulator_disable(khadas_ts050->supply);
0685 if (err < 0)
0686 return err;
0687
0688 return 0;
0689 }
0690
0691 static int khadas_ts050_panel_enable(struct drm_panel *panel)
0692 {
0693 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
0694
0695 khadas_ts050->enabled = true;
0696
0697 return 0;
0698 }
0699
0700 static int khadas_ts050_panel_disable(struct drm_panel *panel)
0701 {
0702 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
0703 int err;
0704
0705 if (!khadas_ts050->enabled)
0706 return 0;
0707
0708 err = mipi_dsi_dcs_set_display_off(khadas_ts050->link);
0709 if (err < 0)
0710 dev_err(panel->dev, "failed to set display off: %d\n", err);
0711
0712 usleep_range(10000, 11000);
0713
0714 khadas_ts050->enabled = false;
0715
0716 return 0;
0717 }
0718
0719 static const struct drm_display_mode default_mode = {
0720 .clock = 120000,
0721 .hdisplay = 1088,
0722 .hsync_start = 1088 + 104,
0723 .hsync_end = 1088 + 104 + 4,
0724 .htotal = 1088 + 104 + 4 + 127,
0725 .vdisplay = 1920,
0726 .vsync_start = 1920 + 4,
0727 .vsync_end = 1920 + 4 + 2,
0728 .vtotal = 1920 + 4 + 2 + 3,
0729 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0730 };
0731
0732 static int khadas_ts050_panel_get_modes(struct drm_panel *panel,
0733 struct drm_connector *connector)
0734 {
0735 struct drm_display_mode *mode;
0736
0737 mode = drm_mode_duplicate(connector->dev, &default_mode);
0738 if (!mode) {
0739 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0740 default_mode.hdisplay, default_mode.vdisplay,
0741 drm_mode_vrefresh(&default_mode));
0742 return -ENOMEM;
0743 }
0744
0745 drm_mode_set_name(mode);
0746
0747 drm_mode_probed_add(connector, mode);
0748
0749 connector->display_info.width_mm = 64;
0750 connector->display_info.height_mm = 118;
0751 connector->display_info.bpc = 8;
0752
0753 return 1;
0754 }
0755
0756 static const struct drm_panel_funcs khadas_ts050_panel_funcs = {
0757 .prepare = khadas_ts050_panel_prepare,
0758 .unprepare = khadas_ts050_panel_unprepare,
0759 .enable = khadas_ts050_panel_enable,
0760 .disable = khadas_ts050_panel_disable,
0761 .get_modes = khadas_ts050_panel_get_modes,
0762 };
0763
0764 static const struct of_device_id khadas_ts050_of_match[] = {
0765 { .compatible = "khadas,ts050", },
0766 { }
0767 };
0768 MODULE_DEVICE_TABLE(of, khadas_ts050_of_match);
0769
0770 static int khadas_ts050_panel_add(struct khadas_ts050_panel *khadas_ts050)
0771 {
0772 struct device *dev = &khadas_ts050->link->dev;
0773 int err;
0774
0775 khadas_ts050->supply = devm_regulator_get(dev, "power");
0776 if (IS_ERR(khadas_ts050->supply))
0777 return dev_err_probe(dev, PTR_ERR(khadas_ts050->supply),
0778 "failed to get power supply");
0779
0780 khadas_ts050->reset_gpio = devm_gpiod_get(dev, "reset",
0781 GPIOD_OUT_LOW);
0782 if (IS_ERR(khadas_ts050->reset_gpio))
0783 return dev_err_probe(dev, PTR_ERR(khadas_ts050->reset_gpio),
0784 "failed to get reset gpio");
0785
0786 khadas_ts050->enable_gpio = devm_gpiod_get(dev, "enable",
0787 GPIOD_OUT_HIGH);
0788 if (IS_ERR(khadas_ts050->enable_gpio))
0789 return dev_err_probe(dev, PTR_ERR(khadas_ts050->enable_gpio),
0790 "failed to get enable gpio");
0791
0792 drm_panel_init(&khadas_ts050->base, &khadas_ts050->link->dev,
0793 &khadas_ts050_panel_funcs, DRM_MODE_CONNECTOR_DSI);
0794
0795 err = drm_panel_of_backlight(&khadas_ts050->base);
0796 if (err)
0797 return err;
0798
0799 drm_panel_add(&khadas_ts050->base);
0800
0801 return 0;
0802 }
0803
0804 static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
0805 {
0806 struct khadas_ts050_panel *khadas_ts050;
0807 int err;
0808
0809 dsi->lanes = 4;
0810 dsi->format = MIPI_DSI_FMT_RGB888;
0811 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
0812 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
0813
0814 khadas_ts050 = devm_kzalloc(&dsi->dev, sizeof(*khadas_ts050),
0815 GFP_KERNEL);
0816 if (!khadas_ts050)
0817 return -ENOMEM;
0818
0819 mipi_dsi_set_drvdata(dsi, khadas_ts050);
0820 khadas_ts050->link = dsi;
0821
0822 err = khadas_ts050_panel_add(khadas_ts050);
0823 if (err < 0)
0824 return err;
0825
0826 err = mipi_dsi_attach(dsi);
0827 if (err)
0828 drm_panel_remove(&khadas_ts050->base);
0829
0830 return err;
0831 }
0832
0833 static int khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
0834 {
0835 struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
0836 int err;
0837
0838 err = mipi_dsi_detach(dsi);
0839 if (err < 0)
0840 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
0841
0842 drm_panel_remove(&khadas_ts050->base);
0843 drm_panel_disable(&khadas_ts050->base);
0844 drm_panel_unprepare(&khadas_ts050->base);
0845
0846 return 0;
0847 }
0848
0849 static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi)
0850 {
0851 struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
0852
0853 drm_panel_disable(&khadas_ts050->base);
0854 drm_panel_unprepare(&khadas_ts050->base);
0855 }
0856
0857 static struct mipi_dsi_driver khadas_ts050_panel_driver = {
0858 .driver = {
0859 .name = "panel-khadas-ts050",
0860 .of_match_table = khadas_ts050_of_match,
0861 },
0862 .probe = khadas_ts050_panel_probe,
0863 .remove = khadas_ts050_panel_remove,
0864 .shutdown = khadas_ts050_panel_shutdown,
0865 };
0866 module_mipi_dsi_driver(khadas_ts050_panel_driver);
0867
0868 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0869 MODULE_DESCRIPTION("Khadas TS050 panel driver");
0870 MODULE_LICENSE("GPL v2");