1408 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Novatek NT35510 panel driver4 * Copyright (C) 2020 Linus Walleij <linus.walleij@linaro.org>5 * Based on code by Robert Teather (C) 2012 Samsung6 *7 * This display driver (and I refer to the physical component NT35510,8 * not this Linux kernel software driver) can handle:9 * 480x864, 480x854, 480x800, 480x720 and 480x640 pixel displays.10 * It has 480x840x24bit SRAM embedded for storing a frame.11 * When powered on the display is by default in 480x800 mode.12 *13 * The actual panels using this component have different names, but14 * the code needed to set up and configure the panel will be similar,15 * so they should all use the NT35510 driver with appropriate configuration16 * per-panel, e.g. for physical size.17 *18 * This driver is for the DSI interface to panels using the NT35510.19 *20 * The NT35510 can also use an RGB (DPI) interface combined with an21 * I2C or SPI interface for setting up the NT35510. If this is needed22 * this panel driver should be refactored to also support that use23 * case.24 */25#include <linux/backlight.h>26#include <linux/bitops.h>27#include <linux/gpio/consumer.h>28#include <linux/module.h>29#include <linux/of.h>30#include <linux/regmap.h>31#include <linux/regulator/consumer.h>32 33#include <video/mipi_display.h>34 35#include <drm/drm_mipi_dsi.h>36#include <drm/drm_modes.h>37#include <drm/drm_panel.h>38 39#define NT35510_CMD_CORRECT_GAMMA BIT(0)40#define NT35510_CMD_CONTROL_DISPLAY BIT(1)41 42#define MCS_CMD_MAUCCTR 0xF0 /* Manufacturer command enable */43#define MCS_CMD_READ_ID1 0xDA44#define MCS_CMD_READ_ID2 0xDB45#define MCS_CMD_READ_ID3 0xDC46#define MCS_CMD_MTP_READ_SETTING 0xF8 /* Uncertain about name */47#define MCS_CMD_MTP_READ_PARAM 0xFF /* Uncertain about name */48 49/*50 * These manufacturer commands are available after we enable manufacturer51 * command set (MCS) for page 0.52 */53#define NT35510_P0_DOPCTR 0xB154#define NT35510_P0_SDHDTCTR 0xB655#define NT35510_P0_GSEQCTR 0xB756#define NT35510_P0_SDEQCTR 0xB857#define NT35510_P0_SDVPCTR 0xBA58#define NT35510_P0_DPFRCTR1 0xBD59#define NT35510_P0_DPFRCTR2 0xBE60#define NT35510_P0_DPFRCTR3 0xBF61#define NT35510_P0_DPMCTR12 0xCC62 63#define NT35510_P0_DOPCTR_LEN 264#define NT35510_P0_GSEQCTR_LEN 265#define NT35510_P0_SDEQCTR_LEN 466#define NT35510_P0_SDVPCTR_LEN 167#define NT35510_P0_DPFRCTR1_LEN 568#define NT35510_P0_DPFRCTR2_LEN 569#define NT35510_P0_DPFRCTR3_LEN 570#define NT35510_P0_DPMCTR12_LEN 371 72#define NT35510_DOPCTR_0_RAMKP BIT(7) /* Contents kept in sleep */73#define NT35510_DOPCTR_0_DSITE BIT(6) /* Enable TE signal */74#define NT35510_DOPCTR_0_DSIG BIT(5) /* Enable generic read/write */75#define NT35510_DOPCTR_0_DSIM BIT(4) /* Enable video mode on DSI */76#define NT35510_DOPCTR_0_EOTP BIT(3) /* Support EoTP */77#define NT35510_DOPCTR_0_N565 BIT(2) /* RGB or BGR pixel format */78#define NT35510_DOPCTR_1_TW_PWR_SEL BIT(4) /* TE power selector */79#define NT35510_DOPCTR_1_CRGB BIT(3) /* RGB or BGR byte order */80#define NT35510_DOPCTR_1_CTB BIT(2) /* Vertical scanning direction */81#define NT35510_DOPCTR_1_CRL BIT(1) /* Source driver data shift */82#define NT35510_P0_SDVPCTR_PRG BIT(2) /* 0 = normal operation, 1 = VGLO */83#define NT35510_P0_SDVPCTR_AVDD 0 /* source driver output = AVDD */84#define NT35510_P0_SDVPCTR_OFFCOL 1 /* source driver output = off color */85#define NT35510_P0_SDVPCTR_AVSS 2 /* source driver output = AVSS */86#define NT35510_P0_SDVPCTR_HI_Z 3 /* source driver output = High impedance */87 88/*89 * These manufacturer commands are available after we enable manufacturer90 * command set (MCS) for page 1.91 */92#define NT35510_P1_SETAVDD 0xB093#define NT35510_P1_SETAVEE 0xB194#define NT35510_P1_SETVCL 0xB295#define NT35510_P1_SETVGH 0xB396#define NT35510_P1_SETVRGH 0xB497#define NT35510_P1_SETVGL 0xB598#define NT35510_P1_BT1CTR 0xB699#define NT35510_P1_BT2CTR 0xB7100#define NT35510_P1_BT3CTR 0xB8101#define NT35510_P1_BT4CTR 0xB9 /* VGH boosting times/freq */102#define NT35510_P1_BT5CTR 0xBA103#define NT35510_P1_PFMCTR 0xBB104#define NT35510_P1_SETVGP 0xBC105#define NT35510_P1_SETVGN 0xBD106#define NT35510_P1_SETVCMOFF 0xBE107#define NT35510_P1_VGHCTR 0xBF /* VGH output ctrl */108#define NT35510_P1_SET_GAMMA_RED_POS 0xD1109#define NT35510_P1_SET_GAMMA_GREEN_POS 0xD2110#define NT35510_P1_SET_GAMMA_BLUE_POS 0xD3111#define NT35510_P1_SET_GAMMA_RED_NEG 0xD4112#define NT35510_P1_SET_GAMMA_GREEN_NEG 0xD5113#define NT35510_P1_SET_GAMMA_BLUE_NEG 0xD6114 115/* AVDD and AVEE setting 3 bytes */116#define NT35510_P1_AVDD_LEN 3117#define NT35510_P1_AVEE_LEN 3118#define NT35510_P1_VCL_LEN 3119#define NT35510_P1_VGH_LEN 3120#define NT35510_P1_VGL_LEN 3121#define NT35510_P1_VGP_LEN 3122#define NT35510_P1_VGN_LEN 3123#define NT35510_P1_VCMOFF_LEN 2124/* BT1CTR thru BT5CTR setting 3 bytes */125#define NT35510_P1_BT1CTR_LEN 3126#define NT35510_P1_BT2CTR_LEN 3127#define NT35510_P1_BT3CTR_LEN 3128#define NT35510_P1_BT4CTR_LEN 3129#define NT35510_P1_BT5CTR_LEN 3130/* 52 gamma parameters times two per color: positive and negative */131#define NT35510_P1_GAMMA_LEN 52132 133#define NT35510_WRCTRLD_BCTRL BIT(5)134#define NT35510_WRCTRLD_A BIT(4)135#define NT35510_WRCTRLD_DD BIT(3)136#define NT35510_WRCTRLD_BL BIT(2)137#define NT35510_WRCTRLD_DB BIT(1)138#define NT35510_WRCTRLD_G BIT(0)139 140#define NT35510_WRCABC_OFF 0141#define NT35510_WRCABC_UI_MODE 1142#define NT35510_WRCABC_STILL_MODE 2143#define NT35510_WRCABC_MOVING_MODE 3144 145/**146 * struct nt35510_config - the display-specific NT35510 configuration147 *148 * Some of the settings provide an array of bytes, A, B C which mean:149 * A = normal / idle off mode150 * B = idle on mode151 * C = partial / idle off mode152 *153 * Gamma correction arrays are 10bit numbers, two consecutive bytes154 * makes out one point on the gamma correction curve. The points are155 * not linearly placed along the X axis, we get points 0, 1, 3, 5156 * 7, 11, 15, 23, 31, 47, 63, 95, 127, 128, 160, 192, 208, 224, 232,157 * 240, 244, 248, 250, 252, 254, 255. The voltages tuples form158 * V0, V1, V3 ... V255, with 0x0000 being the lowest voltage and159 * 0x03FF being the highest voltage.160 *161 * Each value must be strictly higher than the previous value forming162 * a rising curve like this:163 *164 * ^165 * | V255166 * | V254167 * | ....168 * | V5169 * | V3170 * | V1171 * | V0172 * +------------------------------------------->173 *174 * The details about all settings can be found in the NT35510 Application175 * Note.176 */177struct nt35510_config {178 /**179 * @width_mm: physical panel width [mm]180 */181 u32 width_mm;182 /**183 * @height_mm: physical panel height [mm]184 */185 u32 height_mm;186 /**187 * @mode: the display mode. This is only relevant outside the panel188 * in video mode: in command mode this is configuring the internal189 * timing in the display controller.190 */191 const struct drm_display_mode mode;192 /**193 * @mode_flags: DSI operation mode related flags194 */195 unsigned long mode_flags;196 /**197 * @cmds: enable DSI commands198 */199 u32 cmds;200 /**201 * @avdd: setting for AVDD ranging from 0x00 = 6.5V to 0x14 = 4.5V202 * in 0.1V steps the default is 0x05 which means 6.0V203 */204 u8 avdd[NT35510_P1_AVDD_LEN];205 /**206 * @bt1ctr: setting for boost power control for the AVDD step-up207 * circuit (1)208 * bits 0..2 in the lower nibble controls PCK, the booster clock209 * frequency for the step-up circuit:210 * 0 = Hsync/32211 * 1 = Hsync/16212 * 2 = Hsync/8213 * 3 = Hsync/4214 * 4 = Hsync/2215 * 5 = Hsync216 * 6 = Hsync x 2217 * 7 = Hsync x 4218 * bits 4..6 in the upper nibble controls BTP, the boosting219 * amplification for the step-up circuit:220 * 0 = Disable221 * 1 = 1.5 x VDDB222 * 2 = 1.66 x VDDB223 * 3 = 2 x VDDB224 * 4 = 2.5 x VDDB225 * 5 = 3 x VDDB226 * The defaults are 4 and 4 yielding 0x44227 */228 u8 bt1ctr[NT35510_P1_BT1CTR_LEN];229 /**230 * @avee: setting for AVEE ranging from 0x00 = -6.5V to 0x14 = -4.5V231 * in 0.1V steps the default is 0x05 which means -6.0V232 */233 u8 avee[NT35510_P1_AVEE_LEN];234 /**235 * @bt2ctr: setting for boost power control for the AVEE step-up236 * circuit (2)237 * bits 0..2 in the lower nibble controls NCK, the booster clock238 * frequency, the values are the same as for PCK in @bt1ctr.239 * bits 4..5 in the upper nibble controls BTN, the boosting240 * amplification for the step-up circuit.241 * 0 = Disable242 * 1 = -1.5 x VDDB243 * 2 = -2 x VDDB244 * 3 = -2.5 x VDDB245 * 4 = -3 x VDDB246 * The defaults are 4 and 3 yielding 0x34247 */248 u8 bt2ctr[NT35510_P1_BT2CTR_LEN];249 /**250 * @vcl: setting for VCL ranging from 0x00 = -2.5V to 0x11 = -4.0V251 * in 1V steps, the default is 0x00 which means -2.5V252 */253 u8 vcl[NT35510_P1_VCL_LEN];254 /**255 * @bt3ctr: setting for boost power control for the VCL step-up256 * circuit (3)257 * bits 0..2 in the lower nibble controls CLCK, the booster clock258 * frequency, the values are the same as for PCK in @bt1ctr.259 * bits 4..5 in the upper nibble controls BTCL, the boosting260 * amplification for the step-up circuit.261 * 0 = Disable262 * 1 = -0.5 x VDDB263 * 2 = -1 x VDDB264 * 3 = -2 x VDDB265 * The defaults are 4 and 2 yielding 0x24266 */267 u8 bt3ctr[NT35510_P1_BT3CTR_LEN];268 /**269 * @vgh: setting for VGH ranging from 0x00 = 7.0V to 0x0B = 18.0V270 * in 1V steps, the default is 0x08 which means 15V271 */272 u8 vgh[NT35510_P1_VGH_LEN];273 /**274 * @bt4ctr: setting for boost power control for the VGH step-up275 * circuit (4)276 * bits 0..2 in the lower nibble controls HCK, the booster clock277 * frequency, the values are the same as for PCK in @bt1ctr.278 * bits 4..5 in the upper nibble controls BTH, the boosting279 * amplification for the step-up circuit.280 * 0 = AVDD + VDDB281 * 1 = AVDD - AVEE282 * 2 = AVDD - AVEE + VDDB283 * 3 = AVDD x 2 - AVEE284 * The defaults are 4 and 3 yielding 0x34285 */286 u8 bt4ctr[NT35510_P1_BT4CTR_LEN];287 /**288 * @vgl: setting for VGL ranging from 0x00 = -2V to 0x0f = -15V in289 * 1V steps, the default is 0x08 which means -10V290 */291 u8 vgl[NT35510_P1_VGL_LEN];292 /**293 * @bt5ctr: setting for boost power control for the VGL step-up294 * circuit (5)295 * bits 0..2 in the lower nibble controls LCK, the booster clock296 * frequency, the values are the same as for PCK in @bt1ctr.297 * bits 4..5 in the upper nibble controls BTL, the boosting298 * amplification for the step-up circuit.299 * 0 = AVEE + VCL300 * 1 = AVEE - AVDD301 * 2 = AVEE + VCL - AVDD302 * 3 = AVEE x 2 - AVDD303 * The defaults are 3 and 2 yielding 0x32304 */305 u8 bt5ctr[NT35510_P1_BT5CTR_LEN];306 /**307 * @vgp: setting for VGP, the positive gamma divider voltages308 * VGMP the high voltage and VGSP the low voltage.309 * The first byte contains bit 8 of VGMP and VGSP in bits 4 and 0310 * The second byte contains bit 0..7 of VGMP311 * The third byte contains bit 0..7 of VGSP312 * VGMP 0x00 = 3.0V .. 0x108 = 6.3V in steps of 12.5mV313 * VGSP 0x00 = 0V .. 0x111 = 3.7V in steps of 12.5mV314 */315 u8 vgp[NT35510_P1_VGP_LEN];316 /**317 * @vgn: setting for VGN, the negative gamma divider voltages,318 * same layout of bytes as @vgp.319 */320 u8 vgn[NT35510_P1_VGN_LEN];321 /**322 * @vcmoff: setting the DC VCOM offset voltage323 * The first byte contains bit 8 of VCM in bit 0 and VCMOFFSEL in bit 4.324 * The second byte contains bits 0..7 of VCM.325 * VCMOFFSEL the common voltage offset mode.326 * VCMOFFSEL 0x00 = VCOM .. 0x01 Gamma.327 * The default is 0x00.328 * VCM the VCOM output voltage (VCMOFFSEL = 0) or the internal register329 * offset for gamma voltage (VCMOFFSEL = 1).330 * VCM 0x00 = 0V/0 .. 0x118 = 3.5V/280 in steps of 12.5mV/1step331 * The default is 0x00 = 0V/0.332 */333 u8 vcmoff[NT35510_P1_VCMOFF_LEN];334 /**335 * @dopctr: setting optional control for display336 * ERR bits 0..1 in the first byte is the ERR pin output signal setting.337 * 0 = Disable, ERR pin output low338 * 1 = ERR pin output CRC error only339 * 2 = ERR pin output ECC error only340 * 3 = ERR pin output CRC and ECC error341 * The default is 0.342 * N565 bit 2 in the first byte is the 16-bit/pixel format selection.343 * 0 = R[4:0] + G[5:3] & G[2:0] + B[4:0]344 * 1 = G[2:0] + R[4:0] & B[4:0] + G[5:3]345 * The default is 0.346 * DIS_EoTP_HS bit 3 in the first byte is "DSI protocol violation" error347 * reporting.348 * 0 = reporting when error349 * 1 = not reporting when error350 * DSIM bit 4 in the first byte is the video mode data type enable351 * 0 = Video mode data type disable352 * 1 = Video mode data type enable353 * The default is 0.354 * DSIG bit 5 int the first byte is the generic r/w data type enable355 * 0 = Generic r/w disable356 * 1 = Generic r/w enable357 * The default is 0.358 * DSITE bit 6 in the first byte is TE line enable359 * 0 = TE line is disabled360 * 1 = TE line is enabled361 * The default is 0.362 * RAMKP bit 7 in the first byte is the frame memory keep/loss in363 * sleep-in mode364 * 0 = contents loss in sleep-in365 * 1 = contents keep in sleep-in366 * The default is 0.367 * CRL bit 1 in the second byte is the source driver data shift368 * direction selection. This bit is XOR operation with bit RSMX369 * of 3600h command.370 * 0 (RMSX = 0) = S1 -> S1440371 * 0 (RMSX = 1) = S1440 -> S1372 * 1 (RMSX = 0) = S1440 -> S1373 * 1 (RMSX = 1) = S1 -> S1440374 * The default is 0.375 * CTB bit 2 in the second byte is the vertical scanning direction376 * selection for gate control signals. This bit is XOR operation377 * with bit ML of 3600h command.378 * 0 (ML = 0) = Forward (top -> bottom)379 * 0 (ML = 1) = Reverse (bottom -> top)380 * 1 (ML = 0) = Reverse (bottom -> top)381 * 1 (ML = 1) = Forward (top -> bottom)382 * The default is 0.383 * CRGB bit 3 in the second byte is RGB-BGR order selection. This384 * bit is XOR operation with bit RGB of 3600h command.385 * 0 (RGB = 0) = RGB/Normal386 * 0 (RGB = 1) = BGR/RB swap387 * 1 (RGB = 0) = BGR/RB swap388 * 1 (RGB = 1) = RGB/Normal389 * The default is 0.390 * TE_PWR_SEL bit 4 in the second byte is the TE output voltage391 * level selection (only valid when DSTB_SEL = 0 or DSTB_SEL = 1,392 * VSEL = High and VDDI = 1.665~3.3V).393 * 0 = TE output voltage level is VDDI394 * 1 = TE output voltage level is VDDA395 * The default is 0.396 */397 u8 dopctr[NT35510_P0_DOPCTR_LEN];398 /**399 * @madctl: Memory data access control400 * RSMY bit 0 is flip vertical. Flips the display image top to down.401 * RSMX bit 1 is flip horizontal. Flips the display image left to right.402 * MH bit 2 is the horizontal refresh order.403 * RGB bit 3 is the RGB-BGR order.404 * 0 = RGB color sequence405 * 1 = BGR color sequence406 * ML bit 4 is the vertical refresh order.407 * MV bit 5 is the row/column exchange.408 * MX bit 6 is the column address order.409 * MY bit 7 is the row address order.410 */411 u8 madctl;412 /**413 * @sdhdtctr: source output data hold time414 * 0x00..0x3F = 0..31.5us in steps of 0.5us415 * The default is 0x05 = 2.5us.416 */417 u8 sdhdtctr;418 /**419 * @gseqctr: EQ control for gate signals420 * GFEQ_XX[3:0]: time setting of EQ step for falling edge in steps421 * of 0.5us.422 * The default is 0x07 = 3.5us423 * GREQ_XX[7:4]: time setting of EQ step for rising edge in steps424 * of 0.5us.425 * The default is 0x07 = 3.5us426 */427 u8 gseqctr[NT35510_P0_GSEQCTR_LEN];428 /**429 * @sdeqctr: Source driver control settings, first byte is430 * 0 for mode 1 and 1 for mode 2. Mode 1 uses two steps and431 * mode 2 uses three steps meaning EQS3 is not used in mode432 * 1. Mode 2 is default. The last three parameters are EQS1, EQS2433 * and EQS3, setting the rise time for each equalizer step:434 * 0x00 = 0.0 us to 0x0f = 7.5 us in steps of 0.5us. The default435 * is 0x07 = 3.5 us.436 */437 u8 sdeqctr[NT35510_P0_SDEQCTR_LEN];438 /**439 * @sdvpctr: power/voltage behaviour during vertical porch time440 */441 u8 sdvpctr;442 /**443 * @t1: the number of pixel clocks on one scanline, range444 * 0x100 (258 ticks) .. 0x3FF (1024 ticks) so the value + 1445 * clock ticks.446 */447 u16 t1;448 /**449 * @vbp: vertical back porch toward the PANEL note: not toward450 * the DSI host; these are separate interfaces, in from DSI host451 * and out to the panel.452 */453 u8 vbp;454 /**455 * @vfp: vertical front porch toward the PANEL.456 */457 u8 vfp;458 /**459 * @psel: pixel clock divisor: 0 = 1, 1 = 2, 2 = 4, 3 = 8.460 */461 u8 psel;462 /**463 * @dpmctr12: Display timing control 12464 * Byte 1 bit 4 selects LVGL voltage level: 0 = VGLX, 1 = VGL_REG465 * Byte 1 bit 1 selects gate signal mode: 0 = non-overlap, 1 = overlap466 * Byte 1 bit 0 selects output signal control R/L swap, 0 = normal467 * 1 = swap all O->E, L->R468 * Byte 2 is CLW delay clock for CK O/E and CKB O/E signals:469 * 0x00 = 0us .. 0xFF = 12.75us in 0.05us steps470 * Byte 3 is FTI_H0 delay time for STP O/E signals:471 * 0x00 = 0us .. 0xFF = 12.75us in 0.05us steps472 */473 u8 dpmctr12[NT35510_P0_DPMCTR12_LEN];474 /**475 * @gamma_corr_pos_r: Red gamma correction parameters, positive476 */477 u8 gamma_corr_pos_r[NT35510_P1_GAMMA_LEN];478 /**479 * @gamma_corr_pos_g: Green gamma correction parameters, positive480 */481 u8 gamma_corr_pos_g[NT35510_P1_GAMMA_LEN];482 /**483 * @gamma_corr_pos_b: Blue gamma correction parameters, positive484 */485 u8 gamma_corr_pos_b[NT35510_P1_GAMMA_LEN];486 /**487 * @gamma_corr_neg_r: Red gamma correction parameters, negative488 */489 u8 gamma_corr_neg_r[NT35510_P1_GAMMA_LEN];490 /**491 * @gamma_corr_neg_g: Green gamma correction parameters, negative492 */493 u8 gamma_corr_neg_g[NT35510_P1_GAMMA_LEN];494 /**495 * @gamma_corr_neg_b: Blue gamma correction parameters, negative496 */497 u8 gamma_corr_neg_b[NT35510_P1_GAMMA_LEN];498 /**499 * @wrdisbv: write display brightness500 * 0x00 value means the lowest brightness and 0xff value means501 * the highest brightness.502 * The default is 0x00.503 */504 u8 wrdisbv;505 /**506 * @wrctrld: write control display507 * G bit 0 selects gamma curve: 0 = Manual, 1 = Automatic508 * DB bit 1 selects display brightness: 0 = Manual, 1 = Automatic509 * BL bit 2 controls backlight control: 0 = Off, 1 = On510 * DD bit 3 controls display dimming: 0 = Off, 1 = On511 * A bit 4 controls LABC block: 0 = Off, 1 = On512 * BCTRL bit 5 controls brightness block: 0 = Off, 1 = On513 */514 u8 wrctrld;515 /**516 * @wrcabc: write content adaptive brightness control517 * There is possible to use 4 different modes for content adaptive518 * image functionality:519 * 0: Off520 * 1: User Interface Image (UI-Mode)521 * 2: Still Picture Image (Still-Mode)522 * 3: Moving Picture Image (Moving-Mode)523 * The default is 0524 */525 u8 wrcabc;526 /**527 * @wrcabcmb: write CABC minimum brightness528 * Set the minimum brightness value of the display for CABC529 * function.530 * 0x00 value means the lowest brightness for CABC and 0xff531 * value means the highest brightness for CABC.532 * The default is 0x00.533 */534 u8 wrcabcmb;535};536 537/**538 * struct nt35510 - state container for the NT35510 panel539 */540struct nt35510 {541 /**542 * @dev: the container device543 */544 struct device *dev;545 /**546 * @conf: the specific panel configuration, as the NT35510547 * can be combined with many physical panels, they can have548 * different physical dimensions and gamma correction etc,549 * so this is stored in the config.550 */551 const struct nt35510_config *conf;552 /**553 * @panel: the DRM panel object for the instance554 */555 struct drm_panel panel;556 /**557 * @supplies: regulators supplying the panel558 */559 struct regulator_bulk_data supplies[2];560 /**561 * @reset_gpio: the reset line562 */563 struct gpio_desc *reset_gpio;564};565 566/* Manufacturer command has strictly this byte sequence */567static const u8 nt35510_mauc_mtp_read_param[] = { 0xAA, 0x55, 0x25, 0x01 };568static const u8 nt35510_mauc_mtp_read_setting[] = { 0x01, 0x02, 0x00, 0x20,569 0x33, 0x13, 0x00, 0x40,570 0x00, 0x00, 0x23, 0x02 };571static const u8 nt35510_mauc_select_page_0[] = { 0x55, 0xAA, 0x52, 0x08, 0x00 };572static const u8 nt35510_mauc_select_page_1[] = { 0x55, 0xAA, 0x52, 0x08, 0x01 };573static const u8 nt35510_vgh_on[] = { 0x01 };574 575static inline struct nt35510 *panel_to_nt35510(struct drm_panel *panel)576{577 return container_of(panel, struct nt35510, panel);578}579 580#define NT35510_ROTATE_0_SETTING 0x02581#define NT35510_ROTATE_180_SETTING 0x00582 583static int nt35510_send_long(struct nt35510 *nt, struct mipi_dsi_device *dsi,584 u8 cmd, u8 cmdlen, const u8 *seq)585{586 const u8 *seqp = seq;587 int cmdwritten = 0;588 int chunk = cmdlen;589 int ret;590 591 if (chunk > 15)592 chunk = 15;593 ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk);594 if (ret < 0) {595 dev_err(nt->dev, "error sending DCS command seq cmd %02x\n", cmd);596 return ret;597 }598 cmdwritten += chunk;599 seqp += chunk;600 601 while (cmdwritten < cmdlen) {602 chunk = cmdlen - cmdwritten;603 if (chunk > 15)604 chunk = 15;605 ret = mipi_dsi_generic_write(dsi, seqp, chunk);606 if (ret < 0) {607 dev_err(nt->dev, "error sending generic write seq %02x\n", cmd);608 return ret;609 }610 cmdwritten += chunk;611 seqp += chunk;612 }613 dev_dbg(nt->dev, "sent command %02x %02x bytes\n", cmd, cmdlen);614 return 0;615}616 617static int nt35510_read_id(struct nt35510 *nt)618{619 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);620 u8 id1, id2, id3;621 int ret;622 623 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID1, &id1, 1);624 if (ret < 0) {625 dev_err(nt->dev, "could not read MTP ID1\n");626 return ret;627 }628 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID2, &id2, 1);629 if (ret < 0) {630 dev_err(nt->dev, "could not read MTP ID2\n");631 return ret;632 }633 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID3, &id3, 1);634 if (ret < 0) {635 dev_err(nt->dev, "could not read MTP ID3\n");636 return ret;637 }638 639 /*640 * Multi-Time Programmable (?) memory contains manufacturer641 * ID (e.g. Hydis 0x55), driver ID (e.g. NT35510 0xc0) and642 * version.643 */644 dev_info(nt->dev, "MTP ID manufacturer: %02x version: %02x driver: %02x\n", id1, id2, id3);645 646 return 0;647}648 649/**650 * nt35510_setup_power() - set up power config in page 1651 * @nt: the display instance to set up652 */653static int nt35510_setup_power(struct nt35510 *nt)654{655 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);656 int ret;657 658 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVDD,659 NT35510_P1_AVDD_LEN,660 nt->conf->avdd);661 if (ret)662 return ret;663 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT1CTR,664 NT35510_P1_BT1CTR_LEN,665 nt->conf->bt1ctr);666 if (ret)667 return ret;668 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVEE,669 NT35510_P1_AVEE_LEN,670 nt->conf->avee);671 if (ret)672 return ret;673 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT2CTR,674 NT35510_P1_BT2CTR_LEN,675 nt->conf->bt2ctr);676 if (ret)677 return ret;678 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCL,679 NT35510_P1_VCL_LEN,680 nt->conf->vcl);681 if (ret)682 return ret;683 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT3CTR,684 NT35510_P1_BT3CTR_LEN,685 nt->conf->bt3ctr);686 if (ret)687 return ret;688 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGH,689 NT35510_P1_VGH_LEN,690 nt->conf->vgh);691 if (ret)692 return ret;693 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT4CTR,694 NT35510_P1_BT4CTR_LEN,695 nt->conf->bt4ctr);696 if (ret)697 return ret;698 ret = nt35510_send_long(nt, dsi, NT35510_P1_VGHCTR,699 ARRAY_SIZE(nt35510_vgh_on),700 nt35510_vgh_on);701 if (ret)702 return ret;703 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGL,704 NT35510_P1_VGL_LEN,705 nt->conf->vgl);706 if (ret)707 return ret;708 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT5CTR,709 NT35510_P1_BT5CTR_LEN,710 nt->conf->bt5ctr);711 if (ret)712 return ret;713 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGP,714 NT35510_P1_VGP_LEN,715 nt->conf->vgp);716 if (ret)717 return ret;718 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGN,719 NT35510_P1_VGN_LEN,720 nt->conf->vgn);721 if (ret)722 return ret;723 724 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCMOFF,725 NT35510_P1_VCMOFF_LEN,726 nt->conf->vcmoff);727 if (ret)728 return ret;729 730 /* Typically 10 ms */731 usleep_range(10000, 20000);732 733 return 0;734}735 736/**737 * nt35510_setup_display() - set up display config in page 0738 * @nt: the display instance to set up739 */740static int nt35510_setup_display(struct nt35510 *nt)741{742 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);743 const struct nt35510_config *conf = nt->conf;744 u8 dpfrctr[NT35510_P0_DPFRCTR1_LEN];745 int ret;746 747 ret = nt35510_send_long(nt, dsi, NT35510_P0_DOPCTR,748 NT35510_P0_DOPCTR_LEN,749 conf->dopctr);750 if (ret)751 return ret;752 753 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &conf->madctl,754 sizeof(conf->madctl));755 if (ret < 0)756 return ret;757 758 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDHDTCTR, &conf->sdhdtctr,759 sizeof(conf->sdhdtctr));760 if (ret < 0)761 return ret;762 763 ret = nt35510_send_long(nt, dsi, NT35510_P0_GSEQCTR,764 NT35510_P0_GSEQCTR_LEN,765 conf->gseqctr);766 if (ret)767 return ret;768 769 ret = nt35510_send_long(nt, dsi, NT35510_P0_SDEQCTR,770 NT35510_P0_SDEQCTR_LEN,771 conf->sdeqctr);772 if (ret)773 return ret;774 775 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDVPCTR,776 &conf->sdvpctr, 1);777 if (ret < 0)778 return ret;779 780 /*781 * Display timing control for active and idle off mode:782 * the first byte contains783 * the two high bits of T1A and second byte the low 8 bits, and784 * the valid range is 0x100 (257) to 0x3ff (1023) representing785 * 258..1024 (+1) pixel clock ticks for one scanline. At 20MHz pixel786 * clock this covers the range of 12.90us .. 51.20us in steps of787 * 0.05us, the default is 0x184 (388) representing 389 ticks.788 * The third byte is VBPDA, vertical back porch display active789 * and the fourth VFPDA, vertical front porch display active,790 * both given in number of scanlines in the range 0x02..0xff791 * for 2..255 scanlines. The fifth byte is 2 bits selecting792 * PSEL for active and idle off mode, how much the 20MHz clock793 * is divided by 0..3. This needs to be adjusted to get the right794 * frame rate.795 */796 dpfrctr[0] = (conf->t1 >> 8) & 0xFF;797 dpfrctr[1] = conf->t1 & 0xFF;798 /* Vertical back porch */799 dpfrctr[2] = conf->vbp;800 /* Vertical front porch */801 dpfrctr[3] = conf->vfp;802 dpfrctr[4] = conf->psel;803 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR1,804 NT35510_P0_DPFRCTR1_LEN,805 dpfrctr);806 if (ret)807 return ret;808 /* For idle and partial idle off mode we decrease front porch by one */809 dpfrctr[3]--;810 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR2,811 NT35510_P0_DPFRCTR2_LEN,812 dpfrctr);813 if (ret)814 return ret;815 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR3,816 NT35510_P0_DPFRCTR3_LEN,817 dpfrctr);818 if (ret)819 return ret;820 821 /* Enable TE on vblank */822 ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);823 if (ret)824 return ret;825 826 /* Turn on the pads? */827 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPMCTR12,828 NT35510_P0_DPMCTR12_LEN,829 conf->dpmctr12);830 if (ret)831 return ret;832 833 return 0;834}835 836static int nt35510_set_brightness(struct backlight_device *bl)837{838 struct nt35510 *nt = bl_get_data(bl);839 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);840 u8 brightness = bl->props.brightness;841 int ret;842 843 dev_dbg(nt->dev, "set brightness %d\n", brightness);844 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,845 &brightness,846 sizeof(brightness));847 if (ret < 0)848 return ret;849 850 return 0;851}852 853static const struct backlight_ops nt35510_bl_ops = {854 .update_status = nt35510_set_brightness,855};856 857/*858 * This power-on sequence859 */860static int nt35510_power_on(struct nt35510 *nt)861{862 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);863 int ret;864 865 ret = regulator_bulk_enable(ARRAY_SIZE(nt->supplies), nt->supplies);866 if (ret < 0) {867 dev_err(nt->dev, "unable to enable regulators\n");868 return ret;869 }870 871 /* Toggle RESET in accordance with datasheet page 370 */872 if (nt->reset_gpio) {873 gpiod_set_value(nt->reset_gpio, 1);874 /* Active min 10 us according to datasheet, let's say 20 */875 usleep_range(20, 1000);876 gpiod_set_value(nt->reset_gpio, 0);877 /*878 * 5 ms during sleep mode, 120 ms during sleep out mode879 * according to datasheet, let's use 120-140 ms.880 */881 usleep_range(120000, 140000);882 }883 884 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_PARAM,885 ARRAY_SIZE(nt35510_mauc_mtp_read_param),886 nt35510_mauc_mtp_read_param);887 if (ret)888 return ret;889 890 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_SETTING,891 ARRAY_SIZE(nt35510_mauc_mtp_read_setting),892 nt35510_mauc_mtp_read_setting);893 if (ret)894 return ret;895 896 nt35510_read_id(nt);897 898 /* Set up stuff in manufacturer control, page 1 */899 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,900 ARRAY_SIZE(nt35510_mauc_select_page_1),901 nt35510_mauc_select_page_1);902 if (ret)903 return ret;904 905 ret = nt35510_setup_power(nt);906 if (ret)907 return ret;908 909 if (nt->conf->cmds & NT35510_CMD_CORRECT_GAMMA) {910 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,911 NT35510_P1_GAMMA_LEN,912 nt->conf->gamma_corr_pos_r);913 if (ret)914 return ret;915 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,916 NT35510_P1_GAMMA_LEN,917 nt->conf->gamma_corr_pos_g);918 if (ret)919 return ret;920 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,921 NT35510_P1_GAMMA_LEN,922 nt->conf->gamma_corr_pos_b);923 if (ret)924 return ret;925 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,926 NT35510_P1_GAMMA_LEN,927 nt->conf->gamma_corr_neg_r);928 if (ret)929 return ret;930 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,931 NT35510_P1_GAMMA_LEN,932 nt->conf->gamma_corr_neg_g);933 if (ret)934 return ret;935 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,936 NT35510_P1_GAMMA_LEN,937 nt->conf->gamma_corr_neg_b);938 if (ret)939 return ret;940 }941 942 /* Set up stuff in manufacturer control, page 0 */943 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,944 ARRAY_SIZE(nt35510_mauc_select_page_0),945 nt35510_mauc_select_page_0);946 if (ret)947 return ret;948 949 ret = nt35510_setup_display(nt);950 if (ret)951 return ret;952 953 return 0;954}955 956static int nt35510_power_off(struct nt35510 *nt)957{958 int ret;959 960 ret = regulator_bulk_disable(ARRAY_SIZE(nt->supplies), nt->supplies);961 if (ret)962 return ret;963 964 if (nt->reset_gpio)965 gpiod_set_value(nt->reset_gpio, 1);966 967 return 0;968}969 970static int nt35510_unprepare(struct drm_panel *panel)971{972 struct nt35510 *nt = panel_to_nt35510(panel);973 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);974 int ret;975 976 ret = mipi_dsi_dcs_set_display_off(dsi);977 if (ret) {978 dev_err(nt->dev, "failed to turn display off (%d)\n", ret);979 return ret;980 }981 usleep_range(10000, 20000);982 983 /* Enter sleep mode */984 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);985 if (ret) {986 dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);987 return ret;988 }989 990 /* Wait 4 frames, how much is that 5ms in the vendor driver */991 usleep_range(5000, 10000);992 993 ret = nt35510_power_off(nt);994 if (ret)995 return ret;996 997 return 0;998}999 1000static int nt35510_prepare(struct drm_panel *panel)1001{1002 struct nt35510 *nt = panel_to_nt35510(panel);1003 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);1004 int ret;1005 1006 ret = nt35510_power_on(nt);1007 if (ret)1008 return ret;1009 1010 /* Exit sleep mode */1011 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);1012 if (ret) {1013 dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);1014 return ret;1015 }1016 /* Up to 120 ms */1017 usleep_range(120000, 150000);1018 1019 if (nt->conf->cmds & NT35510_CMD_CONTROL_DISPLAY) {1020 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,1021 &nt->conf->wrctrld,1022 sizeof(nt->conf->wrctrld));1023 if (ret < 0)1024 return ret;1025 1026 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,1027 &nt->conf->wrcabc,1028 sizeof(nt->conf->wrcabc));1029 if (ret < 0)1030 return ret;1031 1032 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS,1033 &nt->conf->wrcabcmb,1034 sizeof(nt->conf->wrcabcmb));1035 if (ret < 0)1036 return ret;1037 }1038 1039 ret = mipi_dsi_dcs_set_display_on(dsi);1040 if (ret) {1041 dev_err(nt->dev, "failed to turn display on (%d)\n", ret);1042 return ret;1043 }1044 /* Some 10 ms */1045 usleep_range(10000, 20000);1046 1047 return 0;1048}1049 1050static int nt35510_get_modes(struct drm_panel *panel,1051 struct drm_connector *connector)1052{1053 struct nt35510 *nt = panel_to_nt35510(panel);1054 struct drm_display_mode *mode;1055 struct drm_display_info *info;1056 1057 info = &connector->display_info;1058 info->width_mm = nt->conf->width_mm;1059 info->height_mm = nt->conf->height_mm;1060 mode = drm_mode_duplicate(connector->dev, &nt->conf->mode);1061 if (!mode) {1062 dev_err(panel->dev, "bad mode or failed to add mode\n");1063 return -EINVAL;1064 }1065 drm_mode_set_name(mode);1066 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;1067 1068 mode->width_mm = nt->conf->width_mm;1069 mode->height_mm = nt->conf->height_mm;1070 drm_mode_probed_add(connector, mode);1071 1072 return 1; /* Number of modes */1073}1074 1075static const struct drm_panel_funcs nt35510_drm_funcs = {1076 .unprepare = nt35510_unprepare,1077 .prepare = nt35510_prepare,1078 .get_modes = nt35510_get_modes,1079};1080 1081static int nt35510_probe(struct mipi_dsi_device *dsi)1082{1083 struct device *dev = &dsi->dev;1084 struct nt35510 *nt;1085 int ret;1086 1087 nt = devm_kzalloc(dev, sizeof(struct nt35510), GFP_KERNEL);1088 if (!nt)1089 return -ENOMEM;1090 mipi_dsi_set_drvdata(dsi, nt);1091 nt->dev = dev;1092 1093 dsi->lanes = 2;1094 dsi->format = MIPI_DSI_FMT_RGB888;1095 /*1096 * Datasheet suggests max HS rate for NT35510 is 250 MHz1097 * (period time 4ns, see figure 7.6.4 page 365) and max LP rate is1098 * 20 MHz (period time 50ns, see figure 7.6.6. page 366).1099 * However these frequencies appear in source code for the Hydis1100 * HVA40WV1 panel and setting up the LP frequency makes the panel1101 * not work.1102 *1103 * TODO: if other panels prove to be closer to the datasheet,1104 * maybe make this a per-panel config in struct nt35510_config?1105 */1106 dsi->hs_rate = 349440000;1107 dsi->lp_rate = 9600000;1108 1109 /*1110 * Every new incarnation of this display must have a unique1111 * data entry for the system in this driver.1112 */1113 nt->conf = of_device_get_match_data(dev);1114 if (!nt->conf) {1115 dev_err(dev, "missing device configuration\n");1116 return -ENODEV;1117 }1118 1119 dsi->mode_flags = nt->conf->mode_flags;1120 1121 nt->supplies[0].supply = "vdd"; /* 2.3-4.8 V */1122 nt->supplies[1].supply = "vddi"; /* 1.65-3.3V */1123 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->supplies),1124 nt->supplies);1125 if (ret < 0)1126 return ret;1127 ret = regulator_set_voltage(nt->supplies[0].consumer,1128 2300000, 4800000);1129 if (ret)1130 return ret;1131 ret = regulator_set_voltage(nt->supplies[1].consumer,1132 1650000, 3300000);1133 if (ret)1134 return ret;1135 1136 nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);1137 if (IS_ERR(nt->reset_gpio)) {1138 dev_err(dev, "error getting RESET GPIO\n");1139 return PTR_ERR(nt->reset_gpio);1140 }1141 1142 drm_panel_init(&nt->panel, dev, &nt35510_drm_funcs,1143 DRM_MODE_CONNECTOR_DSI);1144 1145 /*1146 * First, try to locate an external backlight (such as on GPIO)1147 * if this fails, assume we will want to use the internal backlight1148 * control.1149 */1150 ret = drm_panel_of_backlight(&nt->panel);1151 if (ret) {1152 dev_err(dev, "error getting external backlight %d\n", ret);1153 return ret;1154 }1155 if (!nt->panel.backlight) {1156 struct backlight_device *bl;1157 1158 bl = devm_backlight_device_register(dev, "nt35510", dev, nt,1159 &nt35510_bl_ops, NULL);1160 if (IS_ERR(bl)) {1161 dev_err(dev, "failed to register backlight device\n");1162 return PTR_ERR(bl);1163 }1164 bl->props.max_brightness = 255;1165 if (nt->conf->cmds & NT35510_CMD_CONTROL_DISPLAY)1166 bl->props.brightness = nt->conf->wrdisbv;1167 else1168 bl->props.brightness = 255;1169 bl->props.power = BACKLIGHT_POWER_OFF;1170 nt->panel.backlight = bl;1171 }1172 1173 drm_panel_add(&nt->panel);1174 1175 ret = mipi_dsi_attach(dsi);1176 if (ret < 0)1177 drm_panel_remove(&nt->panel);1178 1179 return 0;1180}1181 1182static void nt35510_remove(struct mipi_dsi_device *dsi)1183{1184 struct nt35510 *nt = mipi_dsi_get_drvdata(dsi);1185 int ret;1186 1187 mipi_dsi_detach(dsi);1188 /* Power off */1189 ret = nt35510_power_off(nt);1190 if (ret)1191 dev_err(&dsi->dev, "Failed to power off\n");1192 1193 drm_panel_remove(&nt->panel);1194}1195 1196/*1197 * These gamma correction values are 10bit tuples, so only bits 0 and 1 is1198 * ever used in the first byte. They form a positive and negative gamma1199 * correction curve for each color, values must be strictly higher for each1200 * step on the curve. As can be seen these default curves goes from 0x00011201 * to 0x03FE.1202 */1203#define NT35510_GAMMA_POS_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \1204 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \1205 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \1206 0x83, 0x02, 0x78, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \1207 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \1208 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE1209 1210#define NT35510_GAMMA_NEG_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \1211 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \1212 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \1213 0x43, 0x02, 0x50, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \1214 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \1215 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE1216 1217/*1218 * The Hydis HVA40WV1 panel1219 */1220static const struct nt35510_config nt35510_hydis_hva40wv1 = {1221 .width_mm = 52,1222 .height_mm = 86,1223 /**1224 * As the Hydis panel is used in command mode, the porches etc1225 * are settings programmed internally into the NT35510 controller1226 * and generated toward the physical display. As the panel is not1227 * used in video mode, these are not really exposed to the DSI1228 * host.1229 *1230 * Display frame rate control:1231 * Frame rate = (20 MHz / 1) / (389 * (7 + 50 + 800)) ~= 60 Hz1232 */1233 .mode = {1234 /* The internal pixel clock of the NT35510 is 20 MHz */1235 .clock = 20000,1236 .hdisplay = 480,1237 .hsync_start = 480 + 2, /* HFP = 2 */1238 .hsync_end = 480 + 2 + 0, /* HSync = 0 */1239 .htotal = 480 + 2 + 0 + 5, /* HBP = 5 */1240 .vdisplay = 800,1241 .vsync_start = 800 + 2, /* VFP = 2 */1242 .vsync_end = 800 + 2 + 0, /* VSync = 0 */1243 .vtotal = 800 + 2 + 0 + 5, /* VBP = 5 */1244 .flags = 0,1245 },1246 .mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS,1247 .cmds = NT35510_CMD_CORRECT_GAMMA,1248 /* 0x09: AVDD = 5.6V */1249 .avdd = { 0x09, 0x09, 0x09 },1250 /* 0x34: PCK = Hsync/2, BTP = 2 x VDDB */1251 .bt1ctr = { 0x34, 0x34, 0x34 },1252 /* 0x09: AVEE = -5.6V */1253 .avee = { 0x09, 0x09, 0x09 },1254 /* 0x24: NCK = Hsync/2, BTN = -2 x VDDB */1255 .bt2ctr = { 0x24, 0x24, 0x24 },1256 /* VBCLA: -2.5V, VBCLB: -2.5V, VBCLC: -2.5V */1257 .vcl = { 0x00, 0x00, 0x00 },1258 /* 0x24: CLCK = Hsync/2, BTN = -1 x VDDB */1259 .bt3ctr = { 0x24, 0x24, 0x24 },1260 /* 0x05 = 12V */1261 .vgh = { 0x05, 0x05, 0x05 },1262 /* 0x24: NCKA = Hsync/2, VGH = 2 x AVDD - AVEE */1263 .bt4ctr = { 0x24, 0x24, 0x24 },1264 /* 0x0B = -13V */1265 .vgl = { 0x0B, 0x0B, 0x0B },1266 /* 0x24: LCKA = Hsync, VGL = AVDD + VCL - AVDD */1267 .bt5ctr = { 0x24, 0x24, 0x24 },1268 /* VGMP: 0x0A3 = 5.0375V, VGSP = 0V */1269 .vgp = { 0x00, 0xA3, 0x00 },1270 /* VGMP: 0x0A3 = 5.0375V, VGSP = 0V */1271 .vgn = { 0x00, 0xA3, 0x00 },1272 /* VCMOFFSEL = VCOM voltage offset mode, VCM = 0V */1273 .vcmoff = { 0x00, 0x00 },1274 /* Enable TE, EoTP and RGB pixel format */1275 .dopctr = { NT35510_DOPCTR_0_DSITE | NT35510_DOPCTR_0_EOTP |1276 NT35510_DOPCTR_0_N565, NT35510_DOPCTR_1_CTB },1277 .madctl = NT35510_ROTATE_0_SETTING,1278 /* 0x0A: SDT = 5 us */1279 .sdhdtctr = 0x0A,1280 /* EQ control for gate signals, 0x00 = 0 us */1281 .gseqctr = { 0x00, 0x00 },1282 /* SDEQCTR: source driver EQ mode 2, 2.5 us rise time on each step */1283 .sdeqctr = { 0x01, 0x05, 0x05, 0x05 },1284 /* SDVPCTR: Normal operation off color during v porch */1285 .sdvpctr = 0x01,1286 /* T1: number of pixel clocks on one scanline: 0x184 = 389 clocks */1287 .t1 = 0x0184,1288 /* VBP: vertical back porch toward the panel */1289 .vbp = 7,1290 /* VFP: vertical front porch toward the panel */1291 .vfp = 50,1292 /* PSEL: divide pixel clock 20MHz with 1 (no clock downscaling) */1293 .psel = 0,1294 /* DPTMCTR12: 0x03: LVGL = VGLX, overlap mode, swap R->L O->E */1295 .dpmctr12 = { 0x03, 0x00, 0x00, },1296 /* Default gamma correction values */1297 .gamma_corr_pos_r = { NT35510_GAMMA_POS_DEFAULT },1298 .gamma_corr_pos_g = { NT35510_GAMMA_POS_DEFAULT },1299 .gamma_corr_pos_b = { NT35510_GAMMA_POS_DEFAULT },1300 .gamma_corr_neg_r = { NT35510_GAMMA_NEG_DEFAULT },1301 .gamma_corr_neg_g = { NT35510_GAMMA_NEG_DEFAULT },1302 .gamma_corr_neg_b = { NT35510_GAMMA_NEG_DEFAULT },1303};1304 1305static const struct nt35510_config nt35510_frida_frd400b25025 = {1306 .width_mm = 52,1307 .height_mm = 86,1308 .mode = {1309 .clock = 23000,1310 .hdisplay = 480,1311 .hsync_start = 480 + 34, /* HFP = 34 */1312 .hsync_end = 480 + 34 + 2, /* HSync = 2 */1313 .htotal = 480 + 34 + 2 + 34, /* HBP = 34 */1314 .vdisplay = 800,1315 .vsync_start = 800 + 15, /* VFP = 15 */1316 .vsync_end = 800 + 15 + 12, /* VSync = 12 */1317 .vtotal = 800 + 15 + 12 + 15, /* VBP = 15 */1318 .flags = 0,1319 },1320 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |1321 MIPI_DSI_MODE_LPM,1322 .cmds = NT35510_CMD_CONTROL_DISPLAY,1323 /* 0x03: AVDD = 6.2V */1324 .avdd = { 0x03, 0x03, 0x03 },1325 /* 0x46: PCK = 2 x Hsync, BTP = 2.5 x VDDB */1326 .bt1ctr = { 0x46, 0x46, 0x46 },1327 /* 0x03: AVEE = -6.2V */1328 .avee = { 0x03, 0x03, 0x03 },1329 /* 0x36: PCK = 2 x Hsync, BTP = 2 x VDDB */1330 .bt2ctr = { 0x36, 0x36, 0x36 },1331 /* VBCLA: -2.5V, VBCLB: -2.5V, VBCLC: -3.5V */1332 .vcl = { 0x00, 0x00, 0x02 },1333 /* 0x26: CLCK = 2 x Hsync, BTN = -1 x VDDB */1334 .bt3ctr = { 0x26, 0x26, 0x26 },1335 /* 0x09 = 16V */1336 .vgh = { 0x09, 0x09, 0x09 },1337 /* 0x36: HCK = 2 x Hsync, VGH = 2 x AVDD - AVEE */1338 .bt4ctr = { 0x36, 0x36, 0x36 },1339 /* 0x08 = -10V */1340 .vgl = { 0x08, 0x08, 0x08 },1341 /* 0x26: LCK = 2 x Hsync, VGL = AVDD + VCL - AVDD */1342 .bt5ctr = { 0x26, 0x26, 0x26 },1343 /* VGMP: 0x080 = 4.6V, VGSP = 0V */1344 .vgp = { 0x00, 0x80, 0x00 },1345 /* VGMP: 0x080 = 4.6V, VGSP = 0V */1346 .vgn = { 0x00, 0x80, 0x00 },1347 /* VCMOFFSEL = VCOM voltage offset mode, VCM = -1V */1348 .vcmoff = { 0x00, 0x50 },1349 .dopctr = { NT35510_DOPCTR_0_RAMKP | NT35510_DOPCTR_0_DSITE |1350 NT35510_DOPCTR_0_DSIG | NT35510_DOPCTR_0_DSIM |1351 NT35510_DOPCTR_0_EOTP | NT35510_DOPCTR_0_N565, 0 },1352 .madctl = NT35510_ROTATE_180_SETTING,1353 /* 0x03: SDT = 1.5 us */1354 .sdhdtctr = 0x03,1355 /* EQ control for gate signals, 0x00 = 0 us */1356 .gseqctr = { 0x00, 0x00 },1357 /* SDEQCTR: source driver EQ mode 2, 1 us rise time on each step */1358 .sdeqctr = { 0x01, 0x02, 0x02, 0x02 },1359 /* SDVPCTR: Normal operation off color during v porch */1360 .sdvpctr = 0x01,1361 /* T1: number of pixel clocks on one scanline: 0x184 = 389 clocks */1362 .t1 = 0x0184,1363 /* VBP: vertical back porch toward the panel */1364 .vbp = 0x1C,1365 /* VFP: vertical front porch toward the panel */1366 .vfp = 0x1C,1367 /* PSEL: divide pixel clock 23MHz with 1 (no clock downscaling) */1368 .psel = 0,1369 /* DPTMCTR12: 0x03: LVGL = VGLX, overlap mode, swap R->L O->E */1370 .dpmctr12 = { 0x03, 0x00, 0x00, },1371 /* write display brightness */1372 .wrdisbv = 0x7f,1373 /* write control display */1374 .wrctrld = NT35510_WRCTRLD_BCTRL | NT35510_WRCTRLD_DD |1375 NT35510_WRCTRLD_BL,1376 /* write content adaptive brightness control */1377 .wrcabc = NT35510_WRCABC_STILL_MODE,1378 /* write CABC minimum brightness */1379 .wrcabcmb = 0xff,1380};1381 1382static const struct of_device_id nt35510_of_match[] = {1383 {1384 .compatible = "frida,frd400b25025",1385 .data = &nt35510_frida_frd400b25025,1386 },1387 {1388 .compatible = "hydis,hva40wv1",1389 .data = &nt35510_hydis_hva40wv1,1390 },1391 { }1392};1393MODULE_DEVICE_TABLE(of, nt35510_of_match);1394 1395static struct mipi_dsi_driver nt35510_driver = {1396 .probe = nt35510_probe,1397 .remove = nt35510_remove,1398 .driver = {1399 .name = "panel-novatek-nt35510",1400 .of_match_table = nt35510_of_match,1401 },1402};1403module_mipi_dsi_driver(nt35510_driver);1404 1405MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");1406MODULE_DESCRIPTION("NT35510-based panel driver");1407MODULE_LICENSE("GPL v2");1408