brintos

brintos / linux-shallow public Read only

0
0
Text · 22.6 KiB · 266a087 Raw
700 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Panels based on the Ilitek ILI9882T display controller.4 */5#include <linux/delay.h>6#include <linux/gpio/consumer.h>7#include <linux/module.h>8#include <linux/of.h>9#include <linux/regulator/consumer.h>10 11#include <drm/drm_connector.h>12#include <drm/drm_crtc.h>13#include <drm/drm_mipi_dsi.h>14#include <drm/drm_panel.h>15 16#include <video/mipi_display.h>17 18struct ili9882t;19 20/*21 * Use this descriptor struct to describe different panels using the22 * Ilitek ILI9882T display controller.23 */24struct panel_desc {25	const struct drm_display_mode *modes;26	unsigned int bpc;27 28	/**29	 * @width_mm: width of the panel's active display area30	 * @height_mm: height of the panel's active display area31	 */32	struct {33		unsigned int width_mm;34		unsigned int height_mm;35	} size;36 37	unsigned long mode_flags;38	enum mipi_dsi_pixel_format format;39	int (*init)(struct ili9882t *boe);40	unsigned int lanes;41};42 43struct ili9882t {44	struct drm_panel base;45	struct mipi_dsi_device *dsi;46 47	const struct panel_desc *desc;48 49	enum drm_panel_orientation orientation;50	struct regulator *pp3300;51	struct regulator *pp1800;52	struct regulator *avee;53	struct regulator *avdd;54	struct gpio_desc *enable_gpio;55};56 57/* ILI9882-specific commands, add new commands as you decode them */58#define ILI9882T_DCS_SWITCH_PAGE	0xFF59 60#define ili9882t_switch_page(ctx, page) \61	mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \62				     0x98, 0x82, (page))63 64static int starry_ili9882t_init(struct ili9882t *ili)65{66	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };67 68	usleep_range(5000, 5100);69 70	ili9882t_switch_page(&ctx, 0x01);71	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42);72	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11);73	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00);74	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00);75 76	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01);77	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11);78	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00);79	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);80 81	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80);82	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81);83	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71);84	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00);85 86	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00);87	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a);88 89	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);90	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);91	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00);92	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);93 94	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4);95	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40);96 97	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11);98 99	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32);100	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30);101 102	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);103 104	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01);105	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93);106	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00);107	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80);108 109	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07);110	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07);111	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07);112	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07);113	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07);114	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01);115	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00);116	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28);117	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29);118	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11);119	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13);120	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15);121	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17);122	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09);123	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d);124	mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02);125	mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02);126	mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02);127	mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02);128	mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02);129	mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02);130	mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02);131 132	mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07);133	mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07);134	mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07);135	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07);136	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07);137	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01);138	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00);139	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28);140	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29);141	mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10);142	mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);143	mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14);144	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16);145	mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08);146	mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c);147	mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02);148	mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02);149	mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02);150	mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02);151	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02);152	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);153	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02);154 155	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07);156	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07);157	mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07);158	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07);159	mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07);160	mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01);161	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00);162	mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28);163	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29);164	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);165	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14);166	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12);167	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10);168	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c);169	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08);170	mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02);171	mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02);172	mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02);173	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02);174	mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02);175	mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02);176	mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02);177 178	mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07);179	mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07);180	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07);181	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07);182	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07);183	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01);184	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);185	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28);186	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29);187	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17);188	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15);189	mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13);190	mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11);191	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d);192	mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09);193	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02);194	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07);195	mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07);196	mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07);197	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07);198	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07);199	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07);200 201	ili9882t_switch_page(&ctx, 0x02);202	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a);203	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b);204 205	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01);206	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01);207	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c);208	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44);209 210	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);211	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11);212	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00);213	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c);214	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44);215 216	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f);217	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);218	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00);219 220	ili9882t_switch_page(&ctx, 0x03);221	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);222	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c);223	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa);224 225	ili9882t_switch_page(&ctx, 0x0a);226	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01);227	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01);228	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91);229	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c);230	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);231	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa);232 233	ili9882t_switch_page(&ctx, 0x12);234	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c);235 236	ili9882t_switch_page(&ctx, 0x05);237	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5);238	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b);239	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4);240	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54);241	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97);242	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97);243	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f);244	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda);245	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1);246	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01);247	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f);248	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90);249	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);250 251	ili9882t_switch_page(&ctx, 0x06);252	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80);253	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07);254	mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58);255	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02);256	mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58);257	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02);258	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60);259	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00);260	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);261	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08);262	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);263	mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38);264 265	ili9882t_switch_page(&ctx, 0x08);266	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,267				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,268				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);269	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,270				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,271				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);272 273	ili9882t_switch_page(&ctx, 0x04);274	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81);275 276	ili9882t_switch_page(&ctx, 0x0c);277	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02);278	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);279	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);280	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01);281	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03);282	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02);283	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);284	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03);285	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03);286	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04);287	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04);288	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05);289	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04);290	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06);291	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05);292	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07);293	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04);294	mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);295	mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05);296	mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09);297	mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05);298	mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a);299	mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06);300	mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b);301	mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05);302	mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c);303	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06);304	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);305	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06);306	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e);307	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07);308	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);309	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06);310	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10);311	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07);312	mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11);313	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07);314	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12);315	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);316	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13);317	mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07);318	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14);319	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08);320	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15);321	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08);322	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16);323	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09);324	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17);325	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08);326	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18);327	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09);328	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19);329	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09);330	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a);331	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a);332	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b);333	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a);334	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c);335	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a);336	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d);337	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);338	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e);339	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a);340	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f);341 342	ili9882t_switch_page(&ctx, 0x04);343	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01);344 345	ili9882t_switch_page(&ctx, 0x0e);346	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c);347	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10);348	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16);349	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0);350	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);351	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71);352	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46);353	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f);354	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7);355	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02);356	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf);357	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a);358	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0);359	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a);360	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0);361	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65);362	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e);363	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0);364	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);365	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc);366	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12);367	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc);368	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc);369	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc);370	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc);371	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc);372	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc);373	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc);374	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc);375	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);376	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81);377	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02);378	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00);379	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21);380	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10);381 382	ili9882t_switch_page(&ctx, 0x1e);383	mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);384	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00);385	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00);386 387	ili9882t_switch_page(&ctx, 0x0b);388	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44);389	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6);390	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03);391	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03);392	mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51);393	mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51);394	mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04);395	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92);396	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1);397 398	ili9882t_switch_page(&ctx, 0x05);399	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);400 401	ili9882t_switch_page(&ctx, 0x06);402	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);403 404	ili9882t_switch_page(&ctx, 0x00);405	mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);406 407	mipi_dsi_msleep(&ctx, 120);408 409	mipi_dsi_dcs_set_display_on_multi(&ctx);410 411	mipi_dsi_msleep(&ctx, 20);412 413	return ctx.accum_err;414};415 416static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)417{418	return container_of(panel, struct ili9882t, base);419}420 421static int ili9882t_disable(struct drm_panel *panel)422{423	struct ili9882t *ili = to_ili9882t(panel);424	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };425 426	ili9882t_switch_page(&ctx, 0x00);427 428	ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;429 430	mipi_dsi_dcs_set_display_off_multi(&ctx);431	mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);432 433	mipi_dsi_msleep(&ctx, 150);434 435	return ctx.accum_err;436}437 438static int ili9882t_unprepare(struct drm_panel *panel)439{440	struct ili9882t *ili = to_ili9882t(panel);441 442	gpiod_set_value(ili->enable_gpio, 0);443	usleep_range(1000, 2000);444	regulator_disable(ili->avee);445	regulator_disable(ili->avdd);446	usleep_range(5000, 7000);447	regulator_disable(ili->pp1800);448	regulator_disable(ili->pp3300);449 450	return 0;451}452 453static int ili9882t_prepare(struct drm_panel *panel)454{455	struct ili9882t *ili = to_ili9882t(panel);456	int ret;457 458	gpiod_set_value(ili->enable_gpio, 0);459	usleep_range(1000, 1500);460 461	ret = regulator_enable(ili->pp3300);462	if (ret < 0)463		return ret;464 465	ret = regulator_enable(ili->pp1800);466	if (ret < 0)467		return ret;468 469	usleep_range(3000, 5000);470 471	ret = regulator_enable(ili->avdd);472	if (ret < 0)473		goto poweroff1v8;474	ret = regulator_enable(ili->avee);475	if (ret < 0)476		goto poweroffavdd;477 478	usleep_range(10000, 11000);479 480	// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high481	ret = mipi_dsi_dcs_nop(ili->dsi);482	if (ret < 0) {483		dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);484		goto poweroff;485	}486	usleep_range(1000, 2000);487 488	gpiod_set_value(ili->enable_gpio, 1);489	usleep_range(1000, 2000);490	gpiod_set_value(ili->enable_gpio, 0);491	msleep(50);492	gpiod_set_value(ili->enable_gpio, 1);493	usleep_range(6000, 10000);494 495	ret = ili->desc->init(ili);496	if (ret < 0)497		goto poweroff;498 499	return 0;500 501poweroff:502	gpiod_set_value(ili->enable_gpio, 0);503	regulator_disable(ili->avee);504poweroffavdd:505	regulator_disable(ili->avdd);506poweroff1v8:507	usleep_range(5000, 7000);508	regulator_disable(ili->pp1800);509 510	return ret;511}512 513static int ili9882t_enable(struct drm_panel *panel)514{515	msleep(130);516	return 0;517}518 519static const struct drm_display_mode starry_ili9882t_default_mode = {520	.clock = 165280,521	.hdisplay = 1200,522	.hsync_start = 1200 + 72,523	.hsync_end = 1200 + 72 + 30,524	.htotal = 1200 + 72 + 30 + 72,525	.vdisplay = 1920,526	.vsync_start = 1920 + 68,527	.vsync_end = 1920 + 68 + 2,528	.vtotal = 1920 + 68 + 2 + 10,529	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,530};531 532static const struct panel_desc starry_ili9882t_desc = {533	.modes = &starry_ili9882t_default_mode,534	.bpc = 8,535	.size = {536		.width_mm = 141,537		.height_mm = 226,538	},539	.lanes = 4,540	.format = MIPI_DSI_FMT_RGB888,541	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |542		      MIPI_DSI_MODE_LPM,543	.init = starry_ili9882t_init,544};545 546static int ili9882t_get_modes(struct drm_panel *panel,547			      struct drm_connector *connector)548{549	struct ili9882t *ili = to_ili9882t(panel);550	const struct drm_display_mode *m = ili->desc->modes;551	struct drm_display_mode *mode;552 553	mode = drm_mode_duplicate(connector->dev, m);554	if (!mode) {555		dev_err(panel->dev, "failed to add mode %ux%u@%u\n",556			m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));557		return -ENOMEM;558	}559 560	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;561	drm_mode_set_name(mode);562	drm_mode_probed_add(connector, mode);563 564	connector->display_info.width_mm = ili->desc->size.width_mm;565	connector->display_info.height_mm = ili->desc->size.height_mm;566	connector->display_info.bpc = ili->desc->bpc;567 568	return 1;569}570 571static enum drm_panel_orientation ili9882t_get_orientation(struct drm_panel *panel)572{573	struct ili9882t *ili = to_ili9882t(panel);574 575	return ili->orientation;576}577 578static const struct drm_panel_funcs ili9882t_funcs = {579	.disable = ili9882t_disable,580	.unprepare = ili9882t_unprepare,581	.prepare = ili9882t_prepare,582	.enable = ili9882t_enable,583	.get_modes = ili9882t_get_modes,584	.get_orientation = ili9882t_get_orientation,585};586 587static int ili9882t_add(struct ili9882t *ili)588{589	struct device *dev = &ili->dsi->dev;590	int err;591 592	ili->avdd = devm_regulator_get(dev, "avdd");593	if (IS_ERR(ili->avdd))594		return PTR_ERR(ili->avdd);595 596	ili->avee = devm_regulator_get(dev, "avee");597	if (IS_ERR(ili->avee))598		return PTR_ERR(ili->avee);599 600	ili->pp3300 = devm_regulator_get(dev, "pp3300");601	if (IS_ERR(ili->pp3300))602		return PTR_ERR(ili->pp3300);603 604	ili->pp1800 = devm_regulator_get(dev, "pp1800");605	if (IS_ERR(ili->pp1800))606		return PTR_ERR(ili->pp1800);607 608	ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);609	if (IS_ERR(ili->enable_gpio)) {610		dev_err(dev, "cannot get reset-gpios %ld\n",611			PTR_ERR(ili->enable_gpio));612		return PTR_ERR(ili->enable_gpio);613	}614 615	gpiod_set_value(ili->enable_gpio, 0);616 617	drm_panel_init(&ili->base, dev, &ili9882t_funcs,618		       DRM_MODE_CONNECTOR_DSI);619	err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation);620	if (err < 0) {621		dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);622		return err;623	}624 625	err = drm_panel_of_backlight(&ili->base);626	if (err)627		return err;628 629	ili->base.funcs = &ili9882t_funcs;630	ili->base.dev = &ili->dsi->dev;631 632	drm_panel_add(&ili->base);633 634	return 0;635}636 637static int ili9882t_probe(struct mipi_dsi_device *dsi)638{639	struct ili9882t *ili;640	int ret;641	const struct panel_desc *desc;642 643	ili = devm_kzalloc(&dsi->dev, sizeof(*ili), GFP_KERNEL);644	if (!ili)645		return -ENOMEM;646 647	desc = of_device_get_match_data(&dsi->dev);648	dsi->lanes = desc->lanes;649	dsi->format = desc->format;650	dsi->mode_flags = desc->mode_flags;651	ili->desc = desc;652	ili->dsi = dsi;653	ret = ili9882t_add(ili);654	if (ret < 0)655		return ret;656 657	mipi_dsi_set_drvdata(dsi, ili);658 659	ret = mipi_dsi_attach(dsi);660	if (ret)661		drm_panel_remove(&ili->base);662 663	return ret;664}665 666static void ili9882t_remove(struct mipi_dsi_device *dsi)667{668	struct ili9882t *ili = mipi_dsi_get_drvdata(dsi);669	int ret;670 671	ret = mipi_dsi_detach(dsi);672	if (ret < 0)673		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);674 675	if (ili->base.dev)676		drm_panel_remove(&ili->base);677}678 679static const struct of_device_id ili9882t_of_match[] = {680	{ .compatible = "starry,ili9882t",681	  .data = &starry_ili9882t_desc682	},683	{ /* sentinel */ }684};685MODULE_DEVICE_TABLE(of, ili9882t_of_match);686 687static struct mipi_dsi_driver ili9882t_driver = {688	.driver = {689		.name = "panel-ili9882t",690		.of_match_table = ili9882t_of_match,691	},692	.probe = ili9882t_probe,693	.remove = ili9882t_remove,694};695module_mipi_dsi_driver(ili9882t_driver);696 697MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");698MODULE_DESCRIPTION("Ilitek ILI9882T-based panels driver");699MODULE_LICENSE("GPL");700