0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/backlight.h>
0026 #include <linux/bitops.h>
0027 #include <linux/gpio/consumer.h>
0028 #include <linux/module.h>
0029 #include <linux/of_device.h>
0030 #include <linux/regmap.h>
0031 #include <linux/regulator/consumer.h>
0032
0033 #include <video/mipi_display.h>
0034
0035 #include <drm/drm_mipi_dsi.h>
0036 #include <drm/drm_modes.h>
0037 #include <drm/drm_panel.h>
0038
0039 #define MCS_CMD_MAUCCTR 0xF0
0040 #define MCS_CMD_READ_ID1 0xDA
0041 #define MCS_CMD_READ_ID2 0xDB
0042 #define MCS_CMD_READ_ID3 0xDC
0043 #define MCS_CMD_MTP_READ_SETTING 0xF8
0044 #define MCS_CMD_MTP_READ_PARAM 0xFF
0045
0046
0047
0048
0049
0050 #define NT35510_P0_DOPCTR 0xB1
0051 #define NT35510_P0_SDHDTCTR 0xB6
0052 #define NT35510_P0_GSEQCTR 0xB7
0053 #define NT35510_P0_SDEQCTR 0xB8
0054 #define NT35510_P0_SDVPCTR 0xBA
0055 #define NT35510_P0_DPFRCTR1 0xBD
0056 #define NT35510_P0_DPFRCTR2 0xBE
0057 #define NT35510_P0_DPFRCTR3 0xBF
0058 #define NT35510_P0_DPMCTR12 0xCC
0059
0060 #define NT35510_P0_DOPCTR_LEN 2
0061 #define NT35510_P0_GSEQCTR_LEN 2
0062 #define NT35510_P0_SDEQCTR_LEN 4
0063 #define NT35510_P0_SDVPCTR_LEN 1
0064 #define NT35510_P0_DPFRCTR1_LEN 5
0065 #define NT35510_P0_DPFRCTR2_LEN 5
0066 #define NT35510_P0_DPFRCTR3_LEN 5
0067 #define NT35510_P0_DPMCTR12_LEN 3
0068
0069 #define NT35510_DOPCTR_0_RAMKP BIT(7)
0070 #define NT35510_DOPCTR_0_DSITE BIT(6)
0071 #define NT35510_DOPCTR_0_DSIG BIT(5)
0072 #define NT35510_DOPCTR_0_DSIM BIT(4)
0073 #define NT35510_DOPCTR_0_EOTP BIT(3)
0074 #define NT35510_DOPCTR_0_N565 BIT(2)
0075 #define NT35510_DOPCTR_1_TW_PWR_SEL BIT(4)
0076 #define NT35510_DOPCTR_1_CRGB BIT(3)
0077 #define NT35510_DOPCTR_1_CTB BIT(2)
0078 #define NT35510_DOPCTR_1_CRL BIT(1)
0079 #define NT35510_P0_SDVPCTR_PRG BIT(2)
0080 #define NT35510_P0_SDVPCTR_AVDD 0
0081 #define NT35510_P0_SDVPCTR_OFFCOL 1
0082 #define NT35510_P0_SDVPCTR_AVSS 2
0083 #define NT35510_P0_SDVPCTR_HI_Z 3
0084
0085
0086
0087
0088
0089 #define NT35510_P1_SETAVDD 0xB0
0090 #define NT35510_P1_SETAVEE 0xB1
0091 #define NT35510_P1_SETVCL 0xB2
0092 #define NT35510_P1_SETVGH 0xB3
0093 #define NT35510_P1_SETVRGH 0xB4
0094 #define NT35510_P1_SETVGL 0xB5
0095 #define NT35510_P1_BT1CTR 0xB6
0096 #define NT35510_P1_BT2CTR 0xB7
0097 #define NT35510_P1_BT3CTR 0xB8
0098 #define NT35510_P1_BT4CTR 0xB9
0099 #define NT35510_P1_BT5CTR 0xBA
0100 #define NT35510_P1_PFMCTR 0xBB
0101 #define NT35510_P1_SETVGP 0xBC
0102 #define NT35510_P1_SETVGN 0xBD
0103 #define NT35510_P1_SETVCMOFF 0xBE
0104 #define NT35510_P1_VGHCTR 0xBF
0105 #define NT35510_P1_SET_GAMMA_RED_POS 0xD1
0106 #define NT35510_P1_SET_GAMMA_GREEN_POS 0xD2
0107 #define NT35510_P1_SET_GAMMA_BLUE_POS 0xD3
0108 #define NT35510_P1_SET_GAMMA_RED_NEG 0xD4
0109 #define NT35510_P1_SET_GAMMA_GREEN_NEG 0xD5
0110 #define NT35510_P1_SET_GAMMA_BLUE_NEG 0xD6
0111
0112
0113 #define NT35510_P1_AVDD_LEN 3
0114 #define NT35510_P1_AVEE_LEN 3
0115 #define NT35510_P1_VGH_LEN 3
0116 #define NT35510_P1_VGL_LEN 3
0117 #define NT35510_P1_VGP_LEN 3
0118 #define NT35510_P1_VGN_LEN 3
0119
0120 #define NT35510_P1_BT1CTR_LEN 3
0121 #define NT35510_P1_BT2CTR_LEN 3
0122 #define NT35510_P1_BT4CTR_LEN 3
0123 #define NT35510_P1_BT5CTR_LEN 3
0124
0125 #define NT35510_P1_GAMMA_LEN 52
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 struct nt35510_config {
0160
0161
0162
0163 u32 width_mm;
0164
0165
0166
0167 u32 height_mm;
0168
0169
0170
0171
0172
0173 const struct drm_display_mode mode;
0174
0175
0176
0177
0178 u8 avdd[NT35510_P1_AVDD_LEN];
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 u8 bt1ctr[NT35510_P1_BT1CTR_LEN];
0203
0204
0205
0206
0207 u8 avee[NT35510_P1_AVEE_LEN];
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 u8 bt2ctr[NT35510_P1_BT2CTR_LEN];
0223
0224
0225
0226
0227 u8 vgh[NT35510_P1_VGH_LEN];
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 u8 bt4ctr[NT35510_P1_BT4CTR_LEN];
0242
0243
0244
0245
0246 u8 vgl[NT35510_P1_VGL_LEN];
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 u8 bt5ctr[NT35510_P1_BT5CTR_LEN];
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 u8 vgp[NT35510_P1_VGP_LEN];
0271
0272
0273
0274
0275 u8 vgn[NT35510_P1_VGN_LEN];
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 u8 sdeqctr[NT35510_P0_SDEQCTR_LEN];
0286
0287
0288
0289 u8 sdvpctr;
0290
0291
0292
0293
0294
0295 u16 t1;
0296
0297
0298
0299
0300
0301 u8 vbp;
0302
0303
0304
0305 u8 vfp;
0306
0307
0308
0309 u8 psel;
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321 u8 dpmctr12[NT35510_P0_DPMCTR12_LEN];
0322
0323
0324
0325 u8 gamma_corr_pos_r[NT35510_P1_GAMMA_LEN];
0326
0327
0328
0329 u8 gamma_corr_pos_g[NT35510_P1_GAMMA_LEN];
0330
0331
0332
0333 u8 gamma_corr_pos_b[NT35510_P1_GAMMA_LEN];
0334
0335
0336
0337 u8 gamma_corr_neg_r[NT35510_P1_GAMMA_LEN];
0338
0339
0340
0341 u8 gamma_corr_neg_g[NT35510_P1_GAMMA_LEN];
0342
0343
0344
0345 u8 gamma_corr_neg_b[NT35510_P1_GAMMA_LEN];
0346 };
0347
0348
0349
0350
0351 struct nt35510 {
0352
0353
0354
0355 struct device *dev;
0356
0357
0358
0359
0360
0361
0362 const struct nt35510_config *conf;
0363
0364
0365
0366 struct drm_panel panel;
0367
0368
0369
0370 struct regulator_bulk_data supplies[2];
0371
0372
0373
0374 struct gpio_desc *reset_gpio;
0375 };
0376
0377
0378 static const u8 nt35510_mauc_mtp_read_param[] = { 0xAA, 0x55, 0x25, 0x01 };
0379 static const u8 nt35510_mauc_mtp_read_setting[] = { 0x01, 0x02, 0x00, 0x20,
0380 0x33, 0x13, 0x00, 0x40,
0381 0x00, 0x00, 0x23, 0x02 };
0382 static const u8 nt35510_mauc_select_page_0[] = { 0x55, 0xAA, 0x52, 0x08, 0x00 };
0383 static const u8 nt35510_mauc_select_page_1[] = { 0x55, 0xAA, 0x52, 0x08, 0x01 };
0384 static const u8 nt35510_vgh_on[] = { 0x01 };
0385
0386 static inline struct nt35510 *panel_to_nt35510(struct drm_panel *panel)
0387 {
0388 return container_of(panel, struct nt35510, panel);
0389 }
0390
0391 #define NT35510_ROTATE_0_SETTING 0x02
0392 #define NT35510_ROTATE_180_SETTING 0x00
0393
0394 static int nt35510_send_long(struct nt35510 *nt, struct mipi_dsi_device *dsi,
0395 u8 cmd, u8 cmdlen, const u8 *seq)
0396 {
0397 const u8 *seqp = seq;
0398 int cmdwritten = 0;
0399 int chunk = cmdlen;
0400 int ret;
0401
0402 if (chunk > 15)
0403 chunk = 15;
0404 ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk);
0405 if (ret < 0) {
0406 dev_err(nt->dev, "error sending DCS command seq cmd %02x\n", cmd);
0407 return ret;
0408 }
0409 cmdwritten += chunk;
0410 seqp += chunk;
0411
0412 while (cmdwritten < cmdlen) {
0413 chunk = cmdlen - cmdwritten;
0414 if (chunk > 15)
0415 chunk = 15;
0416 ret = mipi_dsi_generic_write(dsi, seqp, chunk);
0417 if (ret < 0) {
0418 dev_err(nt->dev, "error sending generic write seq %02x\n", cmd);
0419 return ret;
0420 }
0421 cmdwritten += chunk;
0422 seqp += chunk;
0423 }
0424 dev_dbg(nt->dev, "sent command %02x %02x bytes\n", cmd, cmdlen);
0425 return 0;
0426 }
0427
0428 static int nt35510_read_id(struct nt35510 *nt)
0429 {
0430 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0431 u8 id1, id2, id3;
0432 int ret;
0433
0434 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID1, &id1, 1);
0435 if (ret < 0) {
0436 dev_err(nt->dev, "could not read MTP ID1\n");
0437 return ret;
0438 }
0439 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID2, &id2, 1);
0440 if (ret < 0) {
0441 dev_err(nt->dev, "could not read MTP ID2\n");
0442 return ret;
0443 }
0444 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID3, &id3, 1);
0445 if (ret < 0) {
0446 dev_err(nt->dev, "could not read MTP ID3\n");
0447 return ret;
0448 }
0449
0450
0451
0452
0453
0454
0455 dev_info(nt->dev, "MTP ID manufacturer: %02x version: %02x driver: %02x\n", id1, id2, id3);
0456
0457 return 0;
0458 }
0459
0460
0461
0462
0463
0464 static int nt35510_setup_power(struct nt35510 *nt)
0465 {
0466 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0467 int ret;
0468
0469 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVDD,
0470 NT35510_P1_AVDD_LEN,
0471 nt->conf->avdd);
0472 if (ret)
0473 return ret;
0474 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT1CTR,
0475 NT35510_P1_BT1CTR_LEN,
0476 nt->conf->bt1ctr);
0477 if (ret)
0478 return ret;
0479 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVEE,
0480 NT35510_P1_AVEE_LEN,
0481 nt->conf->avee);
0482 if (ret)
0483 return ret;
0484 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT2CTR,
0485 NT35510_P1_BT2CTR_LEN,
0486 nt->conf->bt2ctr);
0487 if (ret)
0488 return ret;
0489 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGH,
0490 NT35510_P1_VGH_LEN,
0491 nt->conf->vgh);
0492 if (ret)
0493 return ret;
0494 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT4CTR,
0495 NT35510_P1_BT4CTR_LEN,
0496 nt->conf->bt4ctr);
0497 if (ret)
0498 return ret;
0499 ret = nt35510_send_long(nt, dsi, NT35510_P1_VGHCTR,
0500 ARRAY_SIZE(nt35510_vgh_on),
0501 nt35510_vgh_on);
0502 if (ret)
0503 return ret;
0504 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGL,
0505 NT35510_P1_VGL_LEN,
0506 nt->conf->vgl);
0507 if (ret)
0508 return ret;
0509 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT5CTR,
0510 NT35510_P1_BT5CTR_LEN,
0511 nt->conf->bt5ctr);
0512 if (ret)
0513 return ret;
0514 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGP,
0515 NT35510_P1_VGP_LEN,
0516 nt->conf->vgp);
0517 if (ret)
0518 return ret;
0519 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGN,
0520 NT35510_P1_VGN_LEN,
0521 nt->conf->vgn);
0522 if (ret)
0523 return ret;
0524
0525
0526 usleep_range(10000, 20000);
0527
0528 return 0;
0529 }
0530
0531
0532
0533
0534
0535 static int nt35510_setup_display(struct nt35510 *nt)
0536 {
0537 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0538 const struct nt35510_config *conf = nt->conf;
0539 u8 dopctr[NT35510_P0_DOPCTR_LEN];
0540 u8 gseqctr[NT35510_P0_GSEQCTR_LEN];
0541 u8 dpfrctr[NT35510_P0_DPFRCTR1_LEN];
0542
0543 u8 addr_mode = NT35510_ROTATE_0_SETTING;
0544 u8 val;
0545 int ret;
0546
0547
0548 dopctr[0] = NT35510_DOPCTR_0_DSITE | NT35510_DOPCTR_0_EOTP |
0549 NT35510_DOPCTR_0_N565;
0550 dopctr[1] = NT35510_DOPCTR_1_CTB;
0551 ret = nt35510_send_long(nt, dsi, NT35510_P0_DOPCTR,
0552 NT35510_P0_DOPCTR_LEN,
0553 dopctr);
0554 if (ret)
0555 return ret;
0556
0557 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &addr_mode,
0558 sizeof(addr_mode));
0559 if (ret < 0)
0560 return ret;
0561
0562
0563
0564
0565
0566
0567 val = 0x0A;
0568 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDHDTCTR, &val,
0569 sizeof(val));
0570 if (ret < 0)
0571 return ret;
0572
0573
0574 gseqctr[0] = 0x00;
0575 gseqctr[1] = 0x00;
0576 ret = nt35510_send_long(nt, dsi, NT35510_P0_GSEQCTR,
0577 NT35510_P0_GSEQCTR_LEN,
0578 gseqctr);
0579 if (ret)
0580 return ret;
0581
0582 ret = nt35510_send_long(nt, dsi, NT35510_P0_SDEQCTR,
0583 NT35510_P0_SDEQCTR_LEN,
0584 conf->sdeqctr);
0585 if (ret)
0586 return ret;
0587
0588 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDVPCTR,
0589 &conf->sdvpctr, 1);
0590 if (ret < 0)
0591 return ret;
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609 dpfrctr[0] = (conf->t1 >> 8) & 0xFF;
0610 dpfrctr[1] = conf->t1 & 0xFF;
0611
0612 dpfrctr[2] = conf->vbp;
0613
0614 dpfrctr[3] = conf->vfp;
0615 dpfrctr[4] = conf->psel;
0616 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR1,
0617 NT35510_P0_DPFRCTR1_LEN,
0618 dpfrctr);
0619 if (ret)
0620 return ret;
0621
0622 dpfrctr[3]--;
0623 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR2,
0624 NT35510_P0_DPFRCTR2_LEN,
0625 dpfrctr);
0626 if (ret)
0627 return ret;
0628 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR3,
0629 NT35510_P0_DPFRCTR3_LEN,
0630 dpfrctr);
0631 if (ret)
0632 return ret;
0633
0634
0635 ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0636 if (ret)
0637 return ret;
0638
0639
0640 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPMCTR12,
0641 NT35510_P0_DPMCTR12_LEN,
0642 conf->dpmctr12);
0643 if (ret)
0644 return ret;
0645
0646 return 0;
0647 }
0648
0649 static int nt35510_set_brightness(struct backlight_device *bl)
0650 {
0651 struct nt35510 *nt = bl_get_data(bl);
0652 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0653 u8 brightness = bl->props.brightness;
0654 int ret;
0655
0656 dev_dbg(nt->dev, "set brightness %d\n", brightness);
0657 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
0658 &brightness,
0659 sizeof(brightness));
0660 if (ret < 0)
0661 return ret;
0662
0663 return 0;
0664 }
0665
0666 static const struct backlight_ops nt35510_bl_ops = {
0667 .update_status = nt35510_set_brightness,
0668 };
0669
0670
0671
0672
0673 static int nt35510_power_on(struct nt35510 *nt)
0674 {
0675 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0676 int ret;
0677
0678 ret = regulator_bulk_enable(ARRAY_SIZE(nt->supplies), nt->supplies);
0679 if (ret < 0) {
0680 dev_err(nt->dev, "unable to enable regulators\n");
0681 return ret;
0682 }
0683
0684
0685 if (nt->reset_gpio) {
0686 gpiod_set_value(nt->reset_gpio, 1);
0687
0688 usleep_range(20, 1000);
0689 gpiod_set_value(nt->reset_gpio, 0);
0690
0691
0692
0693
0694 usleep_range(120000, 140000);
0695 }
0696
0697 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_PARAM,
0698 ARRAY_SIZE(nt35510_mauc_mtp_read_param),
0699 nt35510_mauc_mtp_read_param);
0700 if (ret)
0701 return ret;
0702
0703 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_SETTING,
0704 ARRAY_SIZE(nt35510_mauc_mtp_read_setting),
0705 nt35510_mauc_mtp_read_setting);
0706 if (ret)
0707 return ret;
0708
0709 nt35510_read_id(nt);
0710
0711
0712 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
0713 ARRAY_SIZE(nt35510_mauc_select_page_1),
0714 nt35510_mauc_select_page_1);
0715 if (ret)
0716 return ret;
0717
0718 ret = nt35510_setup_power(nt);
0719 if (ret)
0720 return ret;
0721
0722 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,
0723 NT35510_P1_GAMMA_LEN,
0724 nt->conf->gamma_corr_pos_r);
0725 if (ret)
0726 return ret;
0727 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,
0728 NT35510_P1_GAMMA_LEN,
0729 nt->conf->gamma_corr_pos_g);
0730 if (ret)
0731 return ret;
0732 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,
0733 NT35510_P1_GAMMA_LEN,
0734 nt->conf->gamma_corr_pos_b);
0735 if (ret)
0736 return ret;
0737 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,
0738 NT35510_P1_GAMMA_LEN,
0739 nt->conf->gamma_corr_neg_r);
0740 if (ret)
0741 return ret;
0742 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,
0743 NT35510_P1_GAMMA_LEN,
0744 nt->conf->gamma_corr_neg_g);
0745 if (ret)
0746 return ret;
0747 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,
0748 NT35510_P1_GAMMA_LEN,
0749 nt->conf->gamma_corr_neg_b);
0750 if (ret)
0751 return ret;
0752
0753
0754 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
0755 ARRAY_SIZE(nt35510_mauc_select_page_0),
0756 nt35510_mauc_select_page_0);
0757 if (ret)
0758 return ret;
0759
0760 ret = nt35510_setup_display(nt);
0761 if (ret)
0762 return ret;
0763
0764 return 0;
0765 }
0766
0767 static int nt35510_power_off(struct nt35510 *nt)
0768 {
0769 int ret;
0770
0771 ret = regulator_bulk_disable(ARRAY_SIZE(nt->supplies), nt->supplies);
0772 if (ret)
0773 return ret;
0774
0775 if (nt->reset_gpio)
0776 gpiod_set_value(nt->reset_gpio, 1);
0777
0778 return 0;
0779 }
0780
0781 static int nt35510_unprepare(struct drm_panel *panel)
0782 {
0783 struct nt35510 *nt = panel_to_nt35510(panel);
0784 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0785 int ret;
0786
0787 ret = mipi_dsi_dcs_set_display_off(dsi);
0788 if (ret) {
0789 dev_err(nt->dev, "failed to turn display off (%d)\n", ret);
0790 return ret;
0791 }
0792 usleep_range(10000, 20000);
0793
0794
0795 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0796 if (ret) {
0797 dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);
0798 return ret;
0799 }
0800
0801
0802 usleep_range(5000, 10000);
0803
0804 ret = nt35510_power_off(nt);
0805 if (ret)
0806 return ret;
0807
0808 return 0;
0809 }
0810
0811 static int nt35510_prepare(struct drm_panel *panel)
0812 {
0813 struct nt35510 *nt = panel_to_nt35510(panel);
0814 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
0815 int ret;
0816
0817 ret = nt35510_power_on(nt);
0818 if (ret)
0819 return ret;
0820
0821
0822 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0823 if (ret) {
0824 dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);
0825 return ret;
0826 }
0827
0828 usleep_range(120000, 150000);
0829
0830 ret = mipi_dsi_dcs_set_display_on(dsi);
0831 if (ret) {
0832 dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
0833 return ret;
0834 }
0835
0836 usleep_range(10000, 20000);
0837
0838 return 0;
0839 }
0840
0841 static int nt35510_get_modes(struct drm_panel *panel,
0842 struct drm_connector *connector)
0843 {
0844 struct nt35510 *nt = panel_to_nt35510(panel);
0845 struct drm_display_mode *mode;
0846 struct drm_display_info *info;
0847
0848 info = &connector->display_info;
0849 info->width_mm = nt->conf->width_mm;
0850 info->height_mm = nt->conf->height_mm;
0851 mode = drm_mode_duplicate(connector->dev, &nt->conf->mode);
0852 if (!mode) {
0853 dev_err(panel->dev, "bad mode or failed to add mode\n");
0854 return -EINVAL;
0855 }
0856 drm_mode_set_name(mode);
0857 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0858
0859 mode->width_mm = nt->conf->width_mm;
0860 mode->height_mm = nt->conf->height_mm;
0861 drm_mode_probed_add(connector, mode);
0862
0863 return 1;
0864 }
0865
0866 static const struct drm_panel_funcs nt35510_drm_funcs = {
0867 .unprepare = nt35510_unprepare,
0868 .prepare = nt35510_prepare,
0869 .get_modes = nt35510_get_modes,
0870 };
0871
0872 static int nt35510_probe(struct mipi_dsi_device *dsi)
0873 {
0874 struct device *dev = &dsi->dev;
0875 struct nt35510 *nt;
0876 int ret;
0877
0878 nt = devm_kzalloc(dev, sizeof(struct nt35510), GFP_KERNEL);
0879 if (!nt)
0880 return -ENOMEM;
0881 mipi_dsi_set_drvdata(dsi, nt);
0882 nt->dev = dev;
0883
0884 dsi->lanes = 2;
0885 dsi->format = MIPI_DSI_FMT_RGB888;
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897 dsi->hs_rate = 349440000;
0898 dsi->lp_rate = 9600000;
0899 dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
0900
0901
0902
0903
0904
0905 nt->conf = of_device_get_match_data(dev);
0906 if (!nt->conf) {
0907 dev_err(dev, "missing device configuration\n");
0908 return -ENODEV;
0909 }
0910
0911 nt->supplies[0].supply = "vdd";
0912 nt->supplies[1].supply = "vddi";
0913 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->supplies),
0914 nt->supplies);
0915 if (ret < 0)
0916 return ret;
0917 ret = regulator_set_voltage(nt->supplies[0].consumer,
0918 2300000, 4800000);
0919 if (ret)
0920 return ret;
0921 ret = regulator_set_voltage(nt->supplies[1].consumer,
0922 1650000, 3300000);
0923 if (ret)
0924 return ret;
0925
0926 nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
0927 if (IS_ERR(nt->reset_gpio)) {
0928 dev_err(dev, "error getting RESET GPIO\n");
0929 return PTR_ERR(nt->reset_gpio);
0930 }
0931
0932 drm_panel_init(&nt->panel, dev, &nt35510_drm_funcs,
0933 DRM_MODE_CONNECTOR_DSI);
0934
0935
0936
0937
0938
0939
0940 ret = drm_panel_of_backlight(&nt->panel);
0941 if (ret) {
0942 dev_err(dev, "error getting external backlight %d\n", ret);
0943 return ret;
0944 }
0945 if (!nt->panel.backlight) {
0946 struct backlight_device *bl;
0947
0948 bl = devm_backlight_device_register(dev, "nt35510", dev, nt,
0949 &nt35510_bl_ops, NULL);
0950 if (IS_ERR(bl)) {
0951 dev_err(dev, "failed to register backlight device\n");
0952 return PTR_ERR(bl);
0953 }
0954 bl->props.max_brightness = 255;
0955 bl->props.brightness = 255;
0956 bl->props.power = FB_BLANK_POWERDOWN;
0957 nt->panel.backlight = bl;
0958 }
0959
0960 drm_panel_add(&nt->panel);
0961
0962 ret = mipi_dsi_attach(dsi);
0963 if (ret < 0)
0964 drm_panel_remove(&nt->panel);
0965
0966 return 0;
0967 }
0968
0969 static int nt35510_remove(struct mipi_dsi_device *dsi)
0970 {
0971 struct nt35510 *nt = mipi_dsi_get_drvdata(dsi);
0972 int ret;
0973
0974 mipi_dsi_detach(dsi);
0975
0976 ret = nt35510_power_off(nt);
0977 drm_panel_remove(&nt->panel);
0978
0979 return ret;
0980 }
0981
0982
0983
0984
0985
0986
0987
0988
0989 #define NT35510_GAMMA_POS_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
0990 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
0991 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
0992 0x83, 0x02, 0x78, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
0993 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
0994 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
0995
0996 #define NT35510_GAMMA_NEG_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
0997 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
0998 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
0999 0x43, 0x02, 0x50, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
1000 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
1001 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
1002
1003
1004
1005
1006 static const struct nt35510_config nt35510_hydis_hva40wv1 = {
1007 .width_mm = 52,
1008 .height_mm = 86,
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 .mode = {
1020
1021 .clock = 20000,
1022 .hdisplay = 480,
1023 .hsync_start = 480 + 2,
1024 .hsync_end = 480 + 2 + 0,
1025 .htotal = 480 + 2 + 0 + 5,
1026 .vdisplay = 800,
1027 .vsync_start = 800 + 2,
1028 .vsync_end = 800 + 2 + 0,
1029 .vtotal = 800 + 2 + 0 + 5,
1030 .flags = 0,
1031 },
1032
1033 .avdd = { 0x09, 0x09, 0x09 },
1034
1035 .bt1ctr = { 0x34, 0x34, 0x34 },
1036
1037 .avee = { 0x09, 0x09, 0x09 },
1038
1039 .bt2ctr = { 0x24, 0x24, 0x24 },
1040
1041 .vgh = { 0x05, 0x05, 0x05 },
1042
1043 .bt4ctr = { 0x24, 0x24, 0x24 },
1044
1045 .vgl = { 0x0B, 0x0B, 0x0B },
1046
1047 .bt5ctr = { 0x24, 0x24, 0x24 },
1048
1049 .vgp = { 0x00, 0xA3, 0x00 },
1050
1051 .vgn = { 0x00, 0xA3, 0x00 },
1052
1053 .sdeqctr = { 0x01, 0x05, 0x05, 0x05 },
1054
1055 .sdvpctr = 0x01,
1056
1057 .t1 = 0x0184,
1058
1059 .vbp = 7,
1060
1061 .vfp = 50,
1062
1063 .psel = 0,
1064
1065 .dpmctr12 = { 0x03, 0x00, 0x00, },
1066
1067 .gamma_corr_pos_r = { NT35510_GAMMA_POS_DEFAULT },
1068 .gamma_corr_pos_g = { NT35510_GAMMA_POS_DEFAULT },
1069 .gamma_corr_pos_b = { NT35510_GAMMA_POS_DEFAULT },
1070 .gamma_corr_neg_r = { NT35510_GAMMA_NEG_DEFAULT },
1071 .gamma_corr_neg_g = { NT35510_GAMMA_NEG_DEFAULT },
1072 .gamma_corr_neg_b = { NT35510_GAMMA_NEG_DEFAULT },
1073 };
1074
1075 static const struct of_device_id nt35510_of_match[] = {
1076 {
1077 .compatible = "hydis,hva40wv1",
1078 .data = &nt35510_hydis_hva40wv1,
1079 },
1080 { }
1081 };
1082 MODULE_DEVICE_TABLE(of, nt35510_of_match);
1083
1084 static struct mipi_dsi_driver nt35510_driver = {
1085 .probe = nt35510_probe,
1086 .remove = nt35510_remove,
1087 .driver = {
1088 .name = "panel-novatek-nt35510",
1089 .of_match_table = nt35510_of_match,
1090 },
1091 };
1092 module_mipi_dsi_driver(nt35510_driver);
1093
1094 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
1095 MODULE_DESCRIPTION("NT35510-based panel driver");
1096 MODULE_LICENSE("GPL v2");