brintos

brintos / linux-shallow public Read only

0
0
Text · 41.7 KiB · 5768634 Raw
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