1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 3 4 #include <linux/delay.h> 5 #include <linux/gpio/consumer.h> 6 #include <linux/module.h> 7 #include <linux/of.h> 8 #include <linux/regulator/consumer.h> 9 10 #include <drm/drm_mipi_dsi.h> 11 #include <drm/drm_modes.h> 12 #include <drm/drm_panel.h> 13 14 #include <video/mipi_display.h> 15 16 static const char * const regulator_names[] = { 17 "vddi", 18 "avdd", 19 "avee", 20 }; 21 22 static const unsigned long regulator_enable_loads[] = { 23 62000, 24 100000, 25 100000, 26 }; 27 28 struct panel_desc { 29 const struct drm_display_mode *display_mode; 30 u32 width_mm; 31 u32 height_mm; 32 unsigned long mode_flags; 33 enum mipi_dsi_pixel_format format; 34 unsigned int lanes; 35 const char *panel_name; 36 void (*init_sequence)(struct mipi_dsi_multi_context *ctx); 37 }; 38 39 struct nt36672e_panel { 40 struct drm_panel panel; 41 struct mipi_dsi_device *dsi; 42 struct gpio_desc *reset_gpio; 43 struct regulator_bulk_data supplies[3]; 44 const struct panel_desc *desc; 45 }; 46 47 #define NT36672E_DCS_SWITCH_PAGE 0xff 48 49 #define nt36672e_switch_page(ctx, page) \ 50 mipi_dsi_dcs_write_seq_multi(ctx, NT36672E_DCS_SWITCH_PAGE, (page)) 51 52 static void nt36672e_enable_reload_cmds(struct mipi_dsi_multi_context *ctx) 53 { 54 mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); 55 } 56 57 static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel) 58 { 59 return container_of(panel, struct nt36672e_panel, panel); 60 } 61 62 static void nt36672e_1080x2408_60hz_init(struct mipi_dsi_multi_context *ctx) 63 { 64 nt36672e_switch_page(ctx, 0x10); 65 nt36672e_enable_reload_cmds(ctx); 66 mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00); 67 mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00); 68 mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02, 69 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7); 70 mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x1b, 0xa0); 71 72 nt36672e_switch_page(ctx, 0x20); 73 nt36672e_enable_reload_cmds(ctx); 74 mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x66); 75 mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x40); 76 mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x38); 77 mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x83); 78 mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x91); 79 mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0xd1); 80 mipi_dsi_dcs_write_seq_multi(ctx, 0x96, 0xd1); 81 mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x64); 82 mipi_dsi_dcs_write_seq_multi(ctx, 0xf3, 0x54); 83 mipi_dsi_dcs_write_seq_multi(ctx, 0xf4, 0x64); 84 mipi_dsi_dcs_write_seq_multi(ctx, 0xf5, 0x54); 85 mipi_dsi_dcs_write_seq_multi(ctx, 0xf6, 0x64); 86 mipi_dsi_dcs_write_seq_multi(ctx, 0xf7, 0x54); 87 mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x64); 88 mipi_dsi_dcs_write_seq_multi(ctx, 0xf9, 0x54); 89 90 nt36672e_switch_page(ctx, 0x24); 91 nt36672e_enable_reload_cmds(ctx); 92 mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x0f); 93 mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x0c); 94 mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x1d); 95 mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x2f); 96 mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x2e); 97 mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x2d); 98 mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x2c); 99 mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x17); 100 mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x13); 101 mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x15); 102 mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x14); 103 mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x16); 104 mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x18); 105 mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x01); 106 mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x1d); 107 mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x2f); 108 mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x2e); 109 mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x2d); 110 mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x2c); 111 mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x17); 112 mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0x13); 113 mipi_dsi_dcs_write_seq_multi(ctx, 0x2b, 0x15); 114 mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x14); 115 mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x16); 116 mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x18); 117 mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x04); 118 mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0x10); 119 mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x1f); 120 mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x1f); 121 mipi_dsi_dcs_write_seq_multi(ctx, 0x4d, 0x14); 122 mipi_dsi_dcs_write_seq_multi(ctx, 0x4e, 0x36); 123 mipi_dsi_dcs_write_seq_multi(ctx, 0x4f, 0x36); 124 mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x36); 125 mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x30); 126 mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x11); 127 mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x82); 128 mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x8f); 129 mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x04); 130 mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x04); 131 mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x04); 132 mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x13); 133 mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x31); 134 mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x00); 135 mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x00); 136 mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x00); 137 mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x13); 138 mipi_dsi_dcs_write_seq_multi(ctx, 0x92, 0x31); 139 mipi_dsi_dcs_write_seq_multi(ctx, 0x93, 0x00); 140 mipi_dsi_dcs_write_seq_multi(ctx, 0x94, 0x00); 141 mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0x00); 142 mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0xf4); 143 mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x01); 144 mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x0f); 145 mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x0f); 146 mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x02); 147 mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x04); 148 mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x04); 149 mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0xc0); 150 mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x00); 151 mipi_dsi_dcs_write_seq_multi(ctx, 0xd9, 0x80); 152 mipi_dsi_dcs_write_seq_multi(ctx, 0xe9, 0x02); 153 154 nt36672e_switch_page(ctx, 0x25); 155 nt36672e_enable_reload_cmds(ctx); 156 mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x22); 157 mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0xe4); 158 mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x40); 159 mipi_dsi_dcs_write_seq_multi(ctx, 0x66, 0xd8); 160 mipi_dsi_dcs_write_seq_multi(ctx, 0x68, 0x50); 161 mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x10); 162 mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x00); 163 mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x0d); 164 mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x48); 165 mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x41); 166 mipi_dsi_dcs_write_seq_multi(ctx, 0x73, 0x4a); 167 mipi_dsi_dcs_write_seq_multi(ctx, 0x74, 0xd0); 168 mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x62); 169 mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x7e); 170 mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x03); 171 mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x15); 172 mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0x00); 173 mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x4d); 174 mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x80); 175 mipi_dsi_dcs_write_seq_multi(ctx, 0xd6, 0x80); 176 mipi_dsi_dcs_write_seq_multi(ctx, 0xd7, 0x80); 177 mipi_dsi_dcs_write_seq_multi(ctx, 0xef, 0x20); 178 mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x84); 179 180 nt36672e_switch_page(ctx, 0x26); 181 nt36672e_enable_reload_cmds(ctx); 182 mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x0f); 183 mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x01); 184 mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x03); 185 mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x01); 186 mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x03); 187 mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x01); 188 mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x05); 189 mipi_dsi_dcs_write_seq_multi(ctx, 0x8a, 0x1a); 190 mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x11); 191 mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x24); 192 mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x42); 193 mipi_dsi_dcs_write_seq_multi(ctx, 0x8f, 0x11); 194 mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x11); 195 mipi_dsi_dcs_write_seq_multi(ctx, 0x91, 0x11); 196 mipi_dsi_dcs_write_seq_multi(ctx, 0x9a, 0x80); 197 mipi_dsi_dcs_write_seq_multi(ctx, 0x9b, 0x04); 198 mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0x00); 199 mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x00); 200 mipi_dsi_dcs_write_seq_multi(ctx, 0x9e, 0x00); 201 202 nt36672e_switch_page(ctx, 0x27); 203 nt36672e_enable_reload_cmds(ctx); 204 mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x68); 205 mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x81); 206 mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x6a); 207 mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x81); 208 mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x94); 209 mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x00); 210 mipi_dsi_dcs_write_seq_multi(ctx, 0x6f, 0x00); 211 mipi_dsi_dcs_write_seq_multi(ctx, 0x70, 0x00); 212 mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x00); 213 mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x00); 214 mipi_dsi_dcs_write_seq_multi(ctx, 0x75, 0x00); 215 mipi_dsi_dcs_write_seq_multi(ctx, 0x76, 0x00); 216 mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x00); 217 mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x09); 218 mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x67); 219 mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x23); 220 mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x09); 221 mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x67); 222 mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x01); 223 mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x10); 224 mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x10); 225 mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x23); 226 mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x01); 227 mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x40); 228 mipi_dsi_dcs_write_seq_multi(ctx, 0xe5, 0x02); 229 mipi_dsi_dcs_write_seq_multi(ctx, 0xe6, 0xd3); 230 mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x03); 231 mipi_dsi_dcs_write_seq_multi(ctx, 0xec, 0x28); 232 233 nt36672e_switch_page(ctx, 0x2a); 234 nt36672e_enable_reload_cmds(ctx); 235 mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x91); 236 mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x20); 237 mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x50); 238 mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x70); 239 mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x04); 240 mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x40); 241 mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x01); 242 mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0xe0); 243 mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x0f); 244 mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0xa4); 245 mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x0f); 246 mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x78); 247 mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x23); 248 mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x36); 249 mipi_dsi_dcs_write_seq_multi(ctx, 0x1e, 0x3e); 250 mipi_dsi_dcs_write_seq_multi(ctx, 0x1f, 0x3e); 251 mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x3e); 252 mipi_dsi_dcs_write_seq_multi(ctx, 0x28, 0xfd); 253 mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x12); 254 mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0xe1); 255 mipi_dsi_dcs_write_seq_multi(ctx, 0x2d, 0x0a); 256 mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x49); 257 mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x96); 258 mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xff); 259 mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x40); 260 mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0xde); 261 mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0xf9); 262 mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x45); 263 mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0xd9); 264 mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x49); 265 mipi_dsi_dcs_write_seq_multi(ctx, 0x4a, 0xf0); 266 mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x09); 267 mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x40); 268 mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0xf0); 269 mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x0f); 270 mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0xa4); 271 mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x0f); 272 mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x78); 273 mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x23); 274 mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x36); 275 mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x7d); 276 mipi_dsi_dcs_write_seq_multi(ctx, 0x8d, 0x7d); 277 mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x7d); 278 279 nt36672e_switch_page(ctx, 0x20); 280 nt36672e_enable_reload_cmds(ctx); 281 mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, 282 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); 283 mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, 284 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); 285 mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, 286 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); 287 mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, 288 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 289 mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, 290 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); 291 mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, 292 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); 293 mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, 294 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); 295 mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, 296 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 297 mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, 298 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); 299 mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, 300 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); 301 mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, 302 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); 303 mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, 304 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 305 306 nt36672e_switch_page(ctx, 0x21); 307 nt36672e_enable_reload_cmds(ctx); 308 mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, 309 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); 310 mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, 311 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); 312 mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, 313 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); 314 mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, 315 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 316 mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, 317 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); 318 mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, 319 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); 320 mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, 321 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); 322 mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, 323 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 324 mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, 325 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); 326 mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, 327 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); 328 mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, 329 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); 330 mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, 331 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); 332 333 nt36672e_switch_page(ctx, 0x2c); 334 nt36672e_enable_reload_cmds(ctx); 335 mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x1f); 336 mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x1f); 337 mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x03); 338 mipi_dsi_dcs_write_seq_multi(ctx, 0x6a, 0x14); 339 mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x36); 340 mipi_dsi_dcs_write_seq_multi(ctx, 0x6c, 0x36); 341 mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x36); 342 mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x04); 343 mipi_dsi_dcs_write_seq_multi(ctx, 0x54, 0x04); 344 mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x04); 345 mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x0f); 346 mipi_dsi_dcs_write_seq_multi(ctx, 0x58, 0x0f); 347 mipi_dsi_dcs_write_seq_multi(ctx, 0x59, 0x0f); 348 349 nt36672e_switch_page(ctx, 0xf0); 350 nt36672e_enable_reload_cmds(ctx); 351 mipi_dsi_dcs_write_seq_multi(ctx, 0x5a, 0x00); 352 353 nt36672e_switch_page(ctx, 0x10); 354 nt36672e_enable_reload_cmds(ctx); 355 mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0xff); 356 mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x24); 357 mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x01); 358 } 359 360 static int nt36672e_power_on(struct nt36672e_panel *ctx) 361 { 362 struct mipi_dsi_device *dsi = ctx->dsi; 363 int ret; 364 365 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 366 if (ret < 0) { 367 dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret); 368 return ret; 369 } 370 371 /* 372 * Reset sequence of nt36672e panel requires the panel to be out of reset 373 * for 10ms, followed by being held in reset for 10ms and then out again. 374 */ 375 gpiod_set_value(ctx->reset_gpio, 1); 376 usleep_range(10000, 20000); 377 gpiod_set_value(ctx->reset_gpio, 0); 378 usleep_range(10000, 20000); 379 gpiod_set_value(ctx->reset_gpio, 1); 380 usleep_range(10000, 20000); 381 382 return 0; 383 } 384 385 static int nt36672e_power_off(struct nt36672e_panel *ctx) 386 { 387 struct mipi_dsi_device *dsi = ctx->dsi; 388 int ret = 0; 389 390 gpiod_set_value(ctx->reset_gpio, 0); 391 392 ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 393 if (ret) 394 dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret); 395 396 return ret; 397 } 398 399 static int nt36672e_on(struct nt36672e_panel *nt36672e) 400 { 401 struct mipi_dsi_multi_context ctx = { .dsi = nt36672e->dsi }; 402 const struct panel_desc *desc = nt36672e->desc; 403 404 nt36672e->dsi->mode_flags |= MIPI_DSI_MODE_LPM; 405 406 if (desc->init_sequence) 407 desc->init_sequence(&ctx); 408 409 mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); 410 mipi_dsi_msleep(&ctx, 120); 411 412 mipi_dsi_dcs_set_display_on_multi(&ctx); 413 414 mipi_dsi_msleep(&ctx, 100); 415 416 return ctx.accum_err; 417 } 418 419 static int nt36672e_off(struct nt36672e_panel *panel) 420 { 421 struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi }; 422 423 panel->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 424 425 mipi_dsi_dcs_set_display_off_multi(&ctx); 426 mipi_dsi_msleep(&ctx, 20); 427 428 mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 429 mipi_dsi_msleep(&ctx, 60); 430 431 return ctx.accum_err; 432 } 433 434 static int nt36672e_panel_prepare(struct drm_panel *panel) 435 { 436 struct nt36672e_panel *ctx = to_nt36672e_panel(panel); 437 struct mipi_dsi_device *dsi = ctx->dsi; 438 int ret; 439 440 ret = nt36672e_power_on(ctx); 441 if (ret < 0) 442 return ret; 443 444 ret = nt36672e_on(ctx); 445 if (ret < 0) { 446 if (nt36672e_power_off(ctx)) 447 dev_err(&dsi->dev, "power off failed\n"); 448 return ret; 449 } 450 451 return 0; 452 } 453 454 static int nt36672e_panel_unprepare(struct drm_panel *panel) 455 { 456 struct nt36672e_panel *ctx = to_nt36672e_panel(panel); 457 struct mipi_dsi_device *dsi = ctx->dsi; 458 int ret; 459 460 nt36672e_off(ctx); 461 462 ret = nt36672e_power_off(ctx); 463 if (ret < 0) 464 dev_err(&dsi->dev, "power off failed: %d\n", ret); 465 466 return 0; 467 } 468 469 static const struct drm_display_mode nt36672e_1080x2408_60hz = { 470 .name = "1080x2408", 471 .clock = 181690, 472 .hdisplay = 1080, 473 .hsync_start = 1080 + 76, 474 .hsync_end = 1080 + 76 + 12, 475 .htotal = 1080 + 76 + 12 + 56, 476 .vdisplay = 2408, 477 .vsync_start = 2408 + 46, 478 .vsync_end = 2408 + 46 + 10, 479 .vtotal = 2408 + 46 + 10 + 10, 480 .flags = 0, 481 }; 482 483 static const struct panel_desc nt36672e_panel_desc = { 484 .display_mode = &nt36672e_1080x2408_60hz, 485 .width_mm = 74, 486 .height_mm = 131, 487 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, 488 .format = MIPI_DSI_FMT_RGB888, 489 .lanes = 4, 490 .panel_name = "nt36672e fhd plus panel", 491 .init_sequence = nt36672e_1080x2408_60hz_init, 492 }; 493 494 static int nt36672e_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector) 495 { 496 struct nt36672e_panel *ctx = to_nt36672e_panel(panel); 497 struct drm_display_mode *mode; 498 499 mode = drm_mode_duplicate(connector->dev, ctx->desc->display_mode); 500 if (!mode) 501 return -ENOMEM; 502 503 drm_mode_set_name(mode); 504 505 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 506 connector->display_info.width_mm = ctx->desc->width_mm; 507 connector->display_info.height_mm = ctx->desc->height_mm; 508 drm_mode_probed_add(connector, mode); 509 510 return 1; 511 } 512 513 static const struct drm_panel_funcs nt36672e_drm_funcs = { 514 .prepare = nt36672e_panel_prepare, 515 .unprepare = nt36672e_panel_unprepare, 516 .get_modes = nt36672e_panel_get_modes, 517 }; 518 519 static int nt36672e_panel_probe(struct mipi_dsi_device *dsi) 520 { 521 struct device *dev = &dsi->dev; 522 struct nt36672e_panel *ctx; 523 int i, ret = 0; 524 525 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 526 if (!ctx) 527 return -ENOMEM; 528 529 ctx->desc = of_device_get_match_data(dev); 530 if (!ctx->desc) { 531 dev_err(dev, "missing device configuration\n"); 532 return -ENODEV; 533 } 534 535 for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 536 ctx->supplies[i].supply = regulator_names[i]; 537 ctx->supplies[i].init_load_uA = regulator_enable_loads[i]; 538 } 539 540 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 541 ctx->supplies); 542 if (ret < 0) 543 return ret; 544 545 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 546 if (IS_ERR(ctx->reset_gpio)) 547 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n"); 548 549 ctx->dsi = dsi; 550 mipi_dsi_set_drvdata(dsi, ctx); 551 552 dsi->lanes = ctx->desc->lanes; 553 dsi->format = ctx->desc->format; 554 dsi->mode_flags = ctx->desc->mode_flags; 555 556 drm_panel_init(&ctx->panel, dev, &nt36672e_drm_funcs, DRM_MODE_CONNECTOR_DSI); 557 558 ret = drm_panel_of_backlight(&ctx->panel); 559 if (ret) 560 return dev_err_probe(dev, ret, "Failed to get backlight\n"); 561 562 ctx->panel.prepare_prev_first = true; 563 564 drm_panel_add(&ctx->panel); 565 566 ret = mipi_dsi_attach(dsi); 567 if (ret < 0) { 568 dev_err(dev, "Failed to attach to DSI host: %d\n", ret); 569 goto err_dsi_attach; 570 } 571 572 return 0; 573 574 err_dsi_attach: 575 drm_panel_remove(&ctx->panel); 576 return ret; 577 } 578 579 static void nt36672e_panel_remove(struct mipi_dsi_device *dsi) 580 { 581 struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi); 582 583 mipi_dsi_detach(ctx->dsi); 584 drm_panel_remove(&ctx->panel); 585 } 586 587 static const struct of_device_id nt36672e_of_match[] = { 588 { 589 .compatible = "novatek,nt36672e", 590 .data = &nt36672e_panel_desc, 591 }, 592 { } 593 }; 594 MODULE_DEVICE_TABLE(of, nt36672e_of_match); 595 596 static struct mipi_dsi_driver nt36672e_panel_driver = { 597 .driver = { 598 .name = "panel-novatek-nt36672e", 599 .of_match_table = nt36672e_of_match, 600 }, 601 .probe = nt36672e_panel_probe, 602 .remove = nt36672e_panel_remove, 603 }; 604 module_mipi_dsi_driver(nt36672e_panel_driver); 605 606 MODULE_AUTHOR("Ritesh Kumar <quic_riteshk@quicinc.com>"); 607 MODULE_DESCRIPTION("Novatek NT36672E DSI Panel Driver"); 608 MODULE_LICENSE("GPL"); 609