1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020 BayLibre, SAS 4 * Author: Neil Armstrong <narmstrong@baylibre.com> 5 */ 6 7 #include <linux/delay.h> 8 #include <linux/gpio/consumer.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/regulator/consumer.h> 12 13 #include <video/mipi_display.h> 14 15 #include <drm/drm_crtc.h> 16 #include <drm/drm_device.h> 17 #include <drm/drm_mipi_dsi.h> 18 #include <drm/drm_modes.h> 19 #include <drm/drm_panel.h> 20 21 struct khadas_ts050_panel { 22 struct drm_panel base; 23 struct mipi_dsi_device *link; 24 25 struct regulator *supply; 26 struct gpio_desc *reset_gpio; 27 struct gpio_desc *enable_gpio; 28 struct khadas_ts050_panel_data *panel_data; 29 30 bool prepared; 31 bool enabled; 32 }; 33 34 struct khadas_ts050_panel_cmd { 35 u8 cmd; 36 u8 data[55]; 37 u8 size; 38 }; 39 40 struct khadas_ts050_panel_data { 41 struct khadas_ts050_panel_cmd *init_code; 42 int len; 43 }; 44 45 static const struct khadas_ts050_panel_cmd ts050v2_init_code[] = { 46 {0xB9, {0xFF, 0x83, 0x99}, 0x03}, 47 {0xBA, {0x63, 0x23, 0x68, 0xCF}, 0x04}, 48 {0xD2, {0x55}, 0x01}, 49 {0xB1, {0x02, 0x04, 0x70, 0x90, 0x01, 0x32, 0x33, 50 0x11, 0x11, 0x4D, 0x57, 0x56, 0x73, 0x02, 0x02}, 0x0f}, 51 {0xB2, {0x00, 0x80, 0x80, 0xAE, 0x0A, 0x0E, 0x75, 0x11, 0x00, 0x00, 0x00}, 0x0b}, 52 {0xB4, {0x00, 0xFF, 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 53 0x00, 0x24, 0x02, 0x04, 0x0A, 0x21, 0x03, 0x00, 0x00, 0x08, 0xA6, 0x88, 54 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, 55 0x02, 0x04, 0x0A, 0x00, 0x00, 0x08, 0xA6, 0x00, 0x08, 0x11}, 0x2e}, 56 {0xD3, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 57 0x18, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32, 58 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0A, 60 0x40}, 0x21}, 61 {0xD5, {0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x19, 0x19, 0x19, 62 0x19, 0x18, 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2F, 0x2F, 63 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, 64 {0xD6, {0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 0x19, 0x19, 0x18, 0x18, 0x19, 65 0x19, 0x18, 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2F, 0x2F, 66 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, 67 {0xD8, {0x0A, 0xBE, 0xFA, 0xA0, 0x0A, 0xBE, 0xFA, 0xA0}, 0x08}, 68 {0xBD, {0x01}, 0x01}, 69 {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, 70 {0xBD, {0x02}, 0x01}, 71 {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, 72 {0xBD, {0x00}, 0x01}, 73 {0xE0, {0x01, 0x35, 0x41, 0x3B, 0x79, 0x81, 0x8C, 0x85, 0x8E, 74 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 0xB3, 0xB7, 0xC5, 0xBD, 0xC5, 75 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 0x73, 0x01, 0x35, 0x41, 0x3B, 76 0x79, 0x81, 0x8C, 0x85, 0x8E, 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 77 0xB3, 0xB7, 0xB5, 0xBD, 0xC5, 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 78 0x73}, 0x36}, 79 {0xB6, {0x97, 0x97}, 0x02}, 80 {0xCC, {0xC8}, 0x02}, 81 {0xBF, {0x40, 0x41, 0x50, 0x19}, 0x04}, 82 {0xC6, {0xFF, 0xF9}, 0x02}, 83 {0xC0, {0x25, 0x5A}, 0x02}, 84 }; 85 86 /* Only the CMD1 User Command set is documented */ 87 static const struct khadas_ts050_panel_cmd ts050_init_code[] = { 88 /* Select Unknown CMD Page (Undocumented) */ 89 {0xff, {0xee}, 0x01}, 90 /* Reload CMD1: Don't reload default value to register */ 91 {0xfb, {0x01}, 0x01}, 92 {0x1f, {0x45}, 0x01}, 93 {0x24, {0x4f}, 0x01}, 94 {0x38, {0xc8}, 0x01}, 95 {0x39, {0x27}, 0x01}, 96 {0x1e, {0x77}, 0x01}, 97 {0x1d, {0x0f}, 0x01}, 98 {0x7e, {0x71}, 0x01}, 99 {0x7c, {0x03}, 0x01}, 100 {0xff, {0x00}, 0x01}, 101 {0xfb, {0x01}, 0x01}, 102 {0x35, {0x01}, 0x01}, 103 /* Select CMD2 Page0 (Undocumented) */ 104 {0xff, {0x01}, 0x01}, 105 /* Reload CMD1: Don't reload default value to register */ 106 {0xfb, {0x01}, 0x01}, 107 {0x00, {0x01}, 0x01}, 108 {0x01, {0x55}, 0x01}, 109 {0x02, {0x40}, 0x01}, 110 {0x05, {0x40}, 0x01}, 111 {0x06, {0x4a}, 0x01}, 112 {0x07, {0x24}, 0x01}, 113 {0x08, {0x0c}, 0x01}, 114 {0x0b, {0x7d}, 0x01}, 115 {0x0c, {0x7d}, 0x01}, 116 {0x0e, {0xb0}, 0x01}, 117 {0x0f, {0xae}, 0x01}, 118 {0x11, {0x10}, 0x01}, 119 {0x12, {0x10}, 0x01}, 120 {0x13, {0x03}, 0x01}, 121 {0x14, {0x4a}, 0x01}, 122 {0x15, {0x12}, 0x01}, 123 {0x16, {0x12}, 0x01}, 124 {0x18, {0x00}, 0x01}, 125 {0x19, {0x77}, 0x01}, 126 {0x1a, {0x55}, 0x01}, 127 {0x1b, {0x13}, 0x01}, 128 {0x1c, {0x00}, 0x01}, 129 {0x1d, {0x00}, 0x01}, 130 {0x1e, {0x13}, 0x01}, 131 {0x1f, {0x00}, 0x01}, 132 {0x23, {0x00}, 0x01}, 133 {0x24, {0x00}, 0x01}, 134 {0x25, {0x00}, 0x01}, 135 {0x26, {0x00}, 0x01}, 136 {0x27, {0x00}, 0x01}, 137 {0x28, {0x00}, 0x01}, 138 {0x35, {0x00}, 0x01}, 139 {0x66, {0x00}, 0x01}, 140 {0x58, {0x82}, 0x01}, 141 {0x59, {0x02}, 0x01}, 142 {0x5a, {0x02}, 0x01}, 143 {0x5b, {0x02}, 0x01}, 144 {0x5c, {0x82}, 0x01}, 145 {0x5d, {0x82}, 0x01}, 146 {0x5e, {0x02}, 0x01}, 147 {0x5f, {0x02}, 0x01}, 148 {0x72, {0x31}, 0x01}, 149 /* Select CMD2 Page4 (Undocumented) */ 150 {0xff, {0x05}, 0x01}, 151 /* Reload CMD1: Don't reload default value to register */ 152 {0xfb, {0x01}, 0x01}, 153 {0x00, {0x01}, 0x01}, 154 {0x01, {0x0b}, 0x01}, 155 {0x02, {0x0c}, 0x01}, 156 {0x03, {0x09}, 0x01}, 157 {0x04, {0x0a}, 0x01}, 158 {0x05, {0x00}, 0x01}, 159 {0x06, {0x0f}, 0x01}, 160 {0x07, {0x10}, 0x01}, 161 {0x08, {0x00}, 0x01}, 162 {0x09, {0x00}, 0x01}, 163 {0x0a, {0x00}, 0x01}, 164 {0x0b, {0x00}, 0x01}, 165 {0x0c, {0x00}, 0x01}, 166 {0x0d, {0x13}, 0x01}, 167 {0x0e, {0x15}, 0x01}, 168 {0x0f, {0x17}, 0x01}, 169 {0x10, {0x01}, 0x01}, 170 {0x11, {0x0b}, 0x01}, 171 {0x12, {0x0c}, 0x01}, 172 {0x13, {0x09}, 0x01}, 173 {0x14, {0x0a}, 0x01}, 174 {0x15, {0x00}, 0x01}, 175 {0x16, {0x0f}, 0x01}, 176 {0x17, {0x10}, 0x01}, 177 {0x18, {0x00}, 0x01}, 178 {0x19, {0x00}, 0x01}, 179 {0x1a, {0x00}, 0x01}, 180 {0x1b, {0x00}, 0x01}, 181 {0x1c, {0x00}, 0x01}, 182 {0x1d, {0x13}, 0x01}, 183 {0x1e, {0x15}, 0x01}, 184 {0x1f, {0x17}, 0x01}, 185 {0x20, {0x00}, 0x01}, 186 {0x21, {0x03}, 0x01}, 187 {0x22, {0x01}, 0x01}, 188 {0x23, {0x40}, 0x01}, 189 {0x24, {0x40}, 0x01}, 190 {0x25, {0xed}, 0x01}, 191 {0x29, {0x58}, 0x01}, 192 {0x2a, {0x12}, 0x01}, 193 {0x2b, {0x01}, 0x01}, 194 {0x4b, {0x06}, 0x01}, 195 {0x4c, {0x11}, 0x01}, 196 {0x4d, {0x20}, 0x01}, 197 {0x4e, {0x02}, 0x01}, 198 {0x4f, {0x02}, 0x01}, 199 {0x50, {0x20}, 0x01}, 200 {0x51, {0x61}, 0x01}, 201 {0x52, {0x01}, 0x01}, 202 {0x53, {0x63}, 0x01}, 203 {0x54, {0x77}, 0x01}, 204 {0x55, {0xed}, 0x01}, 205 {0x5b, {0x00}, 0x01}, 206 {0x5c, {0x00}, 0x01}, 207 {0x5d, {0x00}, 0x01}, 208 {0x5e, {0x00}, 0x01}, 209 {0x5f, {0x15}, 0x01}, 210 {0x60, {0x75}, 0x01}, 211 {0x61, {0x00}, 0x01}, 212 {0x62, {0x00}, 0x01}, 213 {0x63, {0x00}, 0x01}, 214 {0x64, {0x00}, 0x01}, 215 {0x65, {0x00}, 0x01}, 216 {0x66, {0x00}, 0x01}, 217 {0x67, {0x00}, 0x01}, 218 {0x68, {0x04}, 0x01}, 219 {0x69, {0x00}, 0x01}, 220 {0x6a, {0x00}, 0x01}, 221 {0x6c, {0x40}, 0x01}, 222 {0x75, {0x01}, 0x01}, 223 {0x76, {0x01}, 0x01}, 224 {0x7a, {0x80}, 0x01}, 225 {0x7b, {0xa3}, 0x01}, 226 {0x7c, {0xd8}, 0x01}, 227 {0x7d, {0x60}, 0x01}, 228 {0x7f, {0x15}, 0x01}, 229 {0x80, {0x81}, 0x01}, 230 {0x83, {0x05}, 0x01}, 231 {0x93, {0x08}, 0x01}, 232 {0x94, {0x10}, 0x01}, 233 {0x8a, {0x00}, 0x01}, 234 {0x9b, {0x0f}, 0x01}, 235 {0xea, {0xff}, 0x01}, 236 {0xec, {0x00}, 0x01}, 237 /* Select CMD2 Page0 (Undocumented) */ 238 {0xff, {0x01}, 0x01}, 239 /* Reload CMD1: Don't reload default value to register */ 240 {0xfb, {0x01}, 0x01}, 241 {0x75, {0x00}, 0x01}, 242 {0x76, {0xdf}, 0x01}, 243 {0x77, {0x00}, 0x01}, 244 {0x78, {0xe4}, 0x01}, 245 {0x79, {0x00}, 0x01}, 246 {0x7a, {0xed}, 0x01}, 247 {0x7b, {0x00}, 0x01}, 248 {0x7c, {0xf6}, 0x01}, 249 {0x7d, {0x00}, 0x01}, 250 {0x7e, {0xff}, 0x01}, 251 {0x7f, {0x01}, 0x01}, 252 {0x80, {0x07}, 0x01}, 253 {0x81, {0x01}, 0x01}, 254 {0x82, {0x10}, 0x01}, 255 {0x83, {0x01}, 0x01}, 256 {0x84, {0x18}, 0x01}, 257 {0x85, {0x01}, 0x01}, 258 {0x86, {0x20}, 0x01}, 259 {0x87, {0x01}, 0x01}, 260 {0x88, {0x3d}, 0x01}, 261 {0x89, {0x01}, 0x01}, 262 {0x8a, {0x56}, 0x01}, 263 {0x8b, {0x01}, 0x01}, 264 {0x8c, {0x84}, 0x01}, 265 {0x8d, {0x01}, 0x01}, 266 {0x8e, {0xab}, 0x01}, 267 {0x8f, {0x01}, 0x01}, 268 {0x90, {0xec}, 0x01}, 269 {0x91, {0x02}, 0x01}, 270 {0x92, {0x22}, 0x01}, 271 {0x93, {0x02}, 0x01}, 272 {0x94, {0x23}, 0x01}, 273 {0x95, {0x02}, 0x01}, 274 {0x96, {0x55}, 0x01}, 275 {0x97, {0x02}, 0x01}, 276 {0x98, {0x8b}, 0x01}, 277 {0x99, {0x02}, 0x01}, 278 {0x9a, {0xaf}, 0x01}, 279 {0x9b, {0x02}, 0x01}, 280 {0x9c, {0xdf}, 0x01}, 281 {0x9d, {0x03}, 0x01}, 282 {0x9e, {0x01}, 0x01}, 283 {0x9f, {0x03}, 0x01}, 284 {0xa0, {0x2c}, 0x01}, 285 {0xa2, {0x03}, 0x01}, 286 {0xa3, {0x39}, 0x01}, 287 {0xa4, {0x03}, 0x01}, 288 {0xa5, {0x47}, 0x01}, 289 {0xa6, {0x03}, 0x01}, 290 {0xa7, {0x56}, 0x01}, 291 {0xa9, {0x03}, 0x01}, 292 {0xaa, {0x66}, 0x01}, 293 {0xab, {0x03}, 0x01}, 294 {0xac, {0x76}, 0x01}, 295 {0xad, {0x03}, 0x01}, 296 {0xae, {0x85}, 0x01}, 297 {0xaf, {0x03}, 0x01}, 298 {0xb0, {0x90}, 0x01}, 299 {0xb1, {0x03}, 0x01}, 300 {0xb2, {0xcb}, 0x01}, 301 {0xb3, {0x00}, 0x01}, 302 {0xb4, {0xdf}, 0x01}, 303 {0xb5, {0x00}, 0x01}, 304 {0xb6, {0xe4}, 0x01}, 305 {0xb7, {0x00}, 0x01}, 306 {0xb8, {0xed}, 0x01}, 307 {0xb9, {0x00}, 0x01}, 308 {0xba, {0xf6}, 0x01}, 309 {0xbb, {0x00}, 0x01}, 310 {0xbc, {0xff}, 0x01}, 311 {0xbd, {0x01}, 0x01}, 312 {0xbe, {0x07}, 0x01}, 313 {0xbf, {0x01}, 0x01}, 314 {0xc0, {0x10}, 0x01}, 315 {0xc1, {0x01}, 0x01}, 316 {0xc2, {0x18}, 0x01}, 317 {0xc3, {0x01}, 0x01}, 318 {0xc4, {0x20}, 0x01}, 319 {0xc5, {0x01}, 0x01}, 320 {0xc6, {0x3d}, 0x01}, 321 {0xc7, {0x01}, 0x01}, 322 {0xc8, {0x56}, 0x01}, 323 {0xc9, {0x01}, 0x01}, 324 {0xca, {0x84}, 0x01}, 325 {0xcb, {0x01}, 0x01}, 326 {0xcc, {0xab}, 0x01}, 327 {0xcd, {0x01}, 0x01}, 328 {0xce, {0xec}, 0x01}, 329 {0xcf, {0x02}, 0x01}, 330 {0xd0, {0x22}, 0x01}, 331 {0xd1, {0x02}, 0x01}, 332 {0xd2, {0x23}, 0x01}, 333 {0xd3, {0x02}, 0x01}, 334 {0xd4, {0x55}, 0x01}, 335 {0xd5, {0x02}, 0x01}, 336 {0xd6, {0x8b}, 0x01}, 337 {0xd7, {0x02}, 0x01}, 338 {0xd8, {0xaf}, 0x01}, 339 {0xd9, {0x02}, 0x01}, 340 {0xda, {0xdf}, 0x01}, 341 {0xdb, {0x03}, 0x01}, 342 {0xdc, {0x01}, 0x01}, 343 {0xdd, {0x03}, 0x01}, 344 {0xde, {0x2c}, 0x01}, 345 {0xdf, {0x03}, 0x01}, 346 {0xe0, {0x39}, 0x01}, 347 {0xe1, {0x03}, 0x01}, 348 {0xe2, {0x47}, 0x01}, 349 {0xe3, {0x03}, 0x01}, 350 {0xe4, {0x56}, 0x01}, 351 {0xe5, {0x03}, 0x01}, 352 {0xe6, {0x66}, 0x01}, 353 {0xe7, {0x03}, 0x01}, 354 {0xe8, {0x76}, 0x01}, 355 {0xe9, {0x03}, 0x01}, 356 {0xea, {0x85}, 0x01}, 357 {0xeb, {0x03}, 0x01}, 358 {0xec, {0x90}, 0x01}, 359 {0xed, {0x03}, 0x01}, 360 {0xee, {0xcb}, 0x01}, 361 {0xef, {0x00}, 0x01}, 362 {0xf0, {0xbb}, 0x01}, 363 {0xf1, {0x00}, 0x01}, 364 {0xf2, {0xc0}, 0x01}, 365 {0xf3, {0x00}, 0x01}, 366 {0xf4, {0xcc}, 0x01}, 367 {0xf5, {0x00}, 0x01}, 368 {0xf6, {0xd6}, 0x01}, 369 {0xf7, {0x00}, 0x01}, 370 {0xf8, {0xe1}, 0x01}, 371 {0xf9, {0x00}, 0x01}, 372 {0xfa, {0xea}, 0x01}, 373 /* Select CMD2 Page2 (Undocumented) */ 374 {0xff, {0x02}, 0x01}, 375 /* Reload CMD1: Don't reload default value to register */ 376 {0xfb, {0x01}, 0x01}, 377 {0x00, {0x00}, 0x01}, 378 {0x01, {0xf4}, 0x01}, 379 {0x02, {0x00}, 0x01}, 380 {0x03, {0xef}, 0x01}, 381 {0x04, {0x01}, 0x01}, 382 {0x05, {0x07}, 0x01}, 383 {0x06, {0x01}, 0x01}, 384 {0x07, {0x28}, 0x01}, 385 {0x08, {0x01}, 0x01}, 386 {0x09, {0x44}, 0x01}, 387 {0x0a, {0x01}, 0x01}, 388 {0x0b, {0x76}, 0x01}, 389 {0x0c, {0x01}, 0x01}, 390 {0x0d, {0xa0}, 0x01}, 391 {0x0e, {0x01}, 0x01}, 392 {0x0f, {0xe7}, 0x01}, 393 {0x10, {0x02}, 0x01}, 394 {0x11, {0x1f}, 0x01}, 395 {0x12, {0x02}, 0x01}, 396 {0x13, {0x22}, 0x01}, 397 {0x14, {0x02}, 0x01}, 398 {0x15, {0x54}, 0x01}, 399 {0x16, {0x02}, 0x01}, 400 {0x17, {0x8b}, 0x01}, 401 {0x18, {0x02}, 0x01}, 402 {0x19, {0xaf}, 0x01}, 403 {0x1a, {0x02}, 0x01}, 404 {0x1b, {0xe0}, 0x01}, 405 {0x1c, {0x03}, 0x01}, 406 {0x1d, {0x01}, 0x01}, 407 {0x1e, {0x03}, 0x01}, 408 {0x1f, {0x2d}, 0x01}, 409 {0x20, {0x03}, 0x01}, 410 {0x21, {0x39}, 0x01}, 411 {0x22, {0x03}, 0x01}, 412 {0x23, {0x47}, 0x01}, 413 {0x24, {0x03}, 0x01}, 414 {0x25, {0x57}, 0x01}, 415 {0x26, {0x03}, 0x01}, 416 {0x27, {0x65}, 0x01}, 417 {0x28, {0x03}, 0x01}, 418 {0x29, {0x77}, 0x01}, 419 {0x2a, {0x03}, 0x01}, 420 {0x2b, {0x85}, 0x01}, 421 {0x2d, {0x03}, 0x01}, 422 {0x2f, {0x8f}, 0x01}, 423 {0x30, {0x03}, 0x01}, 424 {0x31, {0xcb}, 0x01}, 425 {0x32, {0x00}, 0x01}, 426 {0x33, {0xbb}, 0x01}, 427 {0x34, {0x00}, 0x01}, 428 {0x35, {0xc0}, 0x01}, 429 {0x36, {0x00}, 0x01}, 430 {0x37, {0xcc}, 0x01}, 431 {0x38, {0x00}, 0x01}, 432 {0x39, {0xd6}, 0x01}, 433 {0x3a, {0x00}, 0x01}, 434 {0x3b, {0xe1}, 0x01}, 435 {0x3d, {0x00}, 0x01}, 436 {0x3f, {0xea}, 0x01}, 437 {0x40, {0x00}, 0x01}, 438 {0x41, {0xf4}, 0x01}, 439 {0x42, {0x00}, 0x01}, 440 {0x43, {0xfe}, 0x01}, 441 {0x44, {0x01}, 0x01}, 442 {0x45, {0x07}, 0x01}, 443 {0x46, {0x01}, 0x01}, 444 {0x47, {0x28}, 0x01}, 445 {0x48, {0x01}, 0x01}, 446 {0x49, {0x44}, 0x01}, 447 {0x4a, {0x01}, 0x01}, 448 {0x4b, {0x76}, 0x01}, 449 {0x4c, {0x01}, 0x01}, 450 {0x4d, {0xa0}, 0x01}, 451 {0x4e, {0x01}, 0x01}, 452 {0x4f, {0xe7}, 0x01}, 453 {0x50, {0x02}, 0x01}, 454 {0x51, {0x1f}, 0x01}, 455 {0x52, {0x02}, 0x01}, 456 {0x53, {0x22}, 0x01}, 457 {0x54, {0x02}, 0x01}, 458 {0x55, {0x54}, 0x01}, 459 {0x56, {0x02}, 0x01}, 460 {0x58, {0x8b}, 0x01}, 461 {0x59, {0x02}, 0x01}, 462 {0x5a, {0xaf}, 0x01}, 463 {0x5b, {0x02}, 0x01}, 464 {0x5c, {0xe0}, 0x01}, 465 {0x5d, {0x03}, 0x01}, 466 {0x5e, {0x01}, 0x01}, 467 {0x5f, {0x03}, 0x01}, 468 {0x60, {0x2d}, 0x01}, 469 {0x61, {0x03}, 0x01}, 470 {0x62, {0x39}, 0x01}, 471 {0x63, {0x03}, 0x01}, 472 {0x64, {0x47}, 0x01}, 473 {0x65, {0x03}, 0x01}, 474 {0x66, {0x57}, 0x01}, 475 {0x67, {0x03}, 0x01}, 476 {0x68, {0x65}, 0x01}, 477 {0x69, {0x03}, 0x01}, 478 {0x6a, {0x77}, 0x01}, 479 {0x6b, {0x03}, 0x01}, 480 {0x6c, {0x85}, 0x01}, 481 {0x6d, {0x03}, 0x01}, 482 {0x6e, {0x8f}, 0x01}, 483 {0x6f, {0x03}, 0x01}, 484 {0x70, {0xcb}, 0x01}, 485 {0x71, {0x00}, 0x01}, 486 {0x72, {0x00}, 0x01}, 487 {0x73, {0x00}, 0x01}, 488 {0x74, {0x21}, 0x01}, 489 {0x75, {0x00}, 0x01}, 490 {0x76, {0x4c}, 0x01}, 491 {0x77, {0x00}, 0x01}, 492 {0x78, {0x6b}, 0x01}, 493 {0x79, {0x00}, 0x01}, 494 {0x7a, {0x85}, 0x01}, 495 {0x7b, {0x00}, 0x01}, 496 {0x7c, {0x9a}, 0x01}, 497 {0x7d, {0x00}, 0x01}, 498 {0x7e, {0xad}, 0x01}, 499 {0x7f, {0x00}, 0x01}, 500 {0x80, {0xbe}, 0x01}, 501 {0x81, {0x00}, 0x01}, 502 {0x82, {0xcd}, 0x01}, 503 {0x83, {0x01}, 0x01}, 504 {0x84, {0x01}, 0x01}, 505 {0x85, {0x01}, 0x01}, 506 {0x86, {0x29}, 0x01}, 507 {0x87, {0x01}, 0x01}, 508 {0x88, {0x68}, 0x01}, 509 {0x89, {0x01}, 0x01}, 510 {0x8a, {0x98}, 0x01}, 511 {0x8b, {0x01}, 0x01}, 512 {0x8c, {0xe5}, 0x01}, 513 {0x8d, {0x02}, 0x01}, 514 {0x8e, {0x1e}, 0x01}, 515 {0x8f, {0x02}, 0x01}, 516 {0x90, {0x30}, 0x01}, 517 {0x91, {0x02}, 0x01}, 518 {0x92, {0x52}, 0x01}, 519 {0x93, {0x02}, 0x01}, 520 {0x94, {0x88}, 0x01}, 521 {0x95, {0x02}, 0x01}, 522 {0x96, {0xaa}, 0x01}, 523 {0x97, {0x02}, 0x01}, 524 {0x98, {0xd7}, 0x01}, 525 {0x99, {0x02}, 0x01}, 526 {0x9a, {0xf7}, 0x01}, 527 {0x9b, {0x03}, 0x01}, 528 {0x9c, {0x21}, 0x01}, 529 {0x9d, {0x03}, 0x01}, 530 {0x9e, {0x2e}, 0x01}, 531 {0x9f, {0x03}, 0x01}, 532 {0xa0, {0x3d}, 0x01}, 533 {0xa2, {0x03}, 0x01}, 534 {0xa3, {0x4c}, 0x01}, 535 {0xa4, {0x03}, 0x01}, 536 {0xa5, {0x5e}, 0x01}, 537 {0xa6, {0x03}, 0x01}, 538 {0xa7, {0x71}, 0x01}, 539 {0xa9, {0x03}, 0x01}, 540 {0xaa, {0x86}, 0x01}, 541 {0xab, {0x03}, 0x01}, 542 {0xac, {0x94}, 0x01}, 543 {0xad, {0x03}, 0x01}, 544 {0xae, {0xfa}, 0x01}, 545 {0xaf, {0x00}, 0x01}, 546 {0xb0, {0x00}, 0x01}, 547 {0xb1, {0x00}, 0x01}, 548 {0xb2, {0x21}, 0x01}, 549 {0xb3, {0x00}, 0x01}, 550 {0xb4, {0x4c}, 0x01}, 551 {0xb5, {0x00}, 0x01}, 552 {0xb6, {0x6b}, 0x01}, 553 {0xb7, {0x00}, 0x01}, 554 {0xb8, {0x85}, 0x01}, 555 {0xb9, {0x00}, 0x01}, 556 {0xba, {0x9a}, 0x01}, 557 {0xbb, {0x00}, 0x01}, 558 {0xbc, {0xad}, 0x01}, 559 {0xbd, {0x00}, 0x01}, 560 {0xbe, {0xbe}, 0x01}, 561 {0xbf, {0x00}, 0x01}, 562 {0xc0, {0xcd}, 0x01}, 563 {0xc1, {0x01}, 0x01}, 564 {0xc2, {0x01}, 0x01}, 565 {0xc3, {0x01}, 0x01}, 566 {0xc4, {0x29}, 0x01}, 567 {0xc5, {0x01}, 0x01}, 568 {0xc6, {0x68}, 0x01}, 569 {0xc7, {0x01}, 0x01}, 570 {0xc8, {0x98}, 0x01}, 571 {0xc9, {0x01}, 0x01}, 572 {0xca, {0xe5}, 0x01}, 573 {0xcb, {0x02}, 0x01}, 574 {0xcc, {0x1e}, 0x01}, 575 {0xcd, {0x02}, 0x01}, 576 {0xce, {0x20}, 0x01}, 577 {0xcf, {0x02}, 0x01}, 578 {0xd0, {0x52}, 0x01}, 579 {0xd1, {0x02}, 0x01}, 580 {0xd2, {0x88}, 0x01}, 581 {0xd3, {0x02}, 0x01}, 582 {0xd4, {0xaa}, 0x01}, 583 {0xd5, {0x02}, 0x01}, 584 {0xd6, {0xd7}, 0x01}, 585 {0xd7, {0x02}, 0x01}, 586 {0xd8, {0xf7}, 0x01}, 587 {0xd9, {0x03}, 0x01}, 588 {0xda, {0x21}, 0x01}, 589 {0xdb, {0x03}, 0x01}, 590 {0xdc, {0x2e}, 0x01}, 591 {0xdd, {0x03}, 0x01}, 592 {0xde, {0x3d}, 0x01}, 593 {0xdf, {0x03}, 0x01}, 594 {0xe0, {0x4c}, 0x01}, 595 {0xe1, {0x03}, 0x01}, 596 {0xe2, {0x5e}, 0x01}, 597 {0xe3, {0x03}, 0x01}, 598 {0xe4, {0x71}, 0x01}, 599 {0xe5, {0x03}, 0x01}, 600 {0xe6, {0x86}, 0x01}, 601 {0xe7, {0x03}, 0x01}, 602 {0xe8, {0x94}, 0x01}, 603 {0xe9, {0x03}, 0x01}, 604 {0xea, {0xfa}, 0x01}, 605 /* Select CMD2 Page0 (Undocumented) */ 606 {0xff, {0x01}, 0x01}, 607 /* Reload CMD1: Don't reload default value to register */ 608 {0xfb, {0x01}, 0x01}, 609 /* Select CMD2 Page1 (Undocumented) */ 610 {0xff, {0x02}, 0x01}, 611 /* Reload CMD1: Don't reload default value to register */ 612 {0xfb, {0x01}, 0x01}, 613 /* Select CMD2 Page3 (Undocumented) */ 614 {0xff, {0x04}, 0x01}, 615 /* Reload CMD1: Don't reload default value to register */ 616 {0xfb, {0x01}, 0x01}, 617 /* Select CMD1 */ 618 {0xff, {0x00}, 0x01}, 619 {0xd3, {0x22}, 0x01}, /* RGBMIPICTRL: VSYNC back porch = 34 */ 620 {0xd4, {0x04}, 0x01}, /* RGBMIPICTRL: VSYNC front porch = 4 */ 621 }; 622 623 struct khadas_ts050_panel_data ts050_panel_data = { 624 .init_code = (struct khadas_ts050_panel_cmd *)ts050_init_code, 625 .len = ARRAY_SIZE(ts050_init_code) 626 }; 627 628 struct khadas_ts050_panel_data ts050v2_panel_data = { 629 .init_code = (struct khadas_ts050_panel_cmd *)ts050v2_init_code, 630 .len = ARRAY_SIZE(ts050v2_init_code) 631 }; 632 633 static inline 634 struct khadas_ts050_panel *to_khadas_ts050_panel(struct drm_panel *panel) 635 { 636 return container_of(panel, struct khadas_ts050_panel, base); 637 } 638 639 static int khadas_ts050_panel_prepare(struct drm_panel *panel) 640 { 641 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); 642 unsigned int i; 643 int err; 644 645 if (khadas_ts050->prepared) 646 return 0; 647 648 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0); 649 650 err = regulator_enable(khadas_ts050->supply); 651 if (err < 0) 652 return err; 653 654 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 1); 655 656 msleep(60); 657 658 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1); 659 660 usleep_range(10000, 11000); 661 662 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 0); 663 664 /* Select CMD2 page 4 (Undocumented) */ 665 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x05 }, 1); 666 667 /* Reload CMD1: Don't reload default value to register */ 668 mipi_dsi_dcs_write(khadas_ts050->link, 0xfb, (u8[]){ 0x01 }, 1); 669 670 mipi_dsi_dcs_write(khadas_ts050->link, 0xc5, (u8[]){ 0x01 }, 1); 671 672 msleep(100); 673 674 for (i = 0; i < khadas_ts050->panel_data->len; i++) { 675 err = mipi_dsi_dcs_write(khadas_ts050->link, 676 khadas_ts050->panel_data->init_code[i].cmd, 677 &khadas_ts050->panel_data->init_code[i].data, 678 khadas_ts050->panel_data->init_code[i].size); 679 if (err < 0) { 680 dev_err(panel->dev, "failed write cmds: %d\n", err); 681 goto poweroff; 682 } 683 } 684 685 err = mipi_dsi_dcs_exit_sleep_mode(khadas_ts050->link); 686 if (err < 0) { 687 dev_err(panel->dev, "failed to exit sleep mode: %d\n", err); 688 goto poweroff; 689 } 690 691 msleep(120); 692 693 /* Select CMD1 */ 694 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x00 }, 1); 695 696 err = mipi_dsi_dcs_set_tear_on(khadas_ts050->link, 697 MIPI_DSI_DCS_TEAR_MODE_VBLANK); 698 if (err < 0) { 699 dev_err(panel->dev, "failed to set tear on: %d\n", err); 700 goto poweroff; 701 } 702 703 err = mipi_dsi_dcs_set_display_on(khadas_ts050->link); 704 if (err < 0) { 705 dev_err(panel->dev, "failed to set display on: %d\n", err); 706 goto poweroff; 707 } 708 709 usleep_range(10000, 11000); 710 711 khadas_ts050->prepared = true; 712 713 return 0; 714 715 poweroff: 716 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0); 717 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1); 718 719 regulator_disable(khadas_ts050->supply); 720 721 return err; 722 } 723 724 static int khadas_ts050_panel_unprepare(struct drm_panel *panel) 725 { 726 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); 727 int err; 728 729 if (!khadas_ts050->prepared) 730 return 0; 731 732 khadas_ts050->prepared = false; 733 734 err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link); 735 if (err < 0) 736 dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); 737 738 msleep(150); 739 740 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0); 741 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1); 742 743 err = regulator_disable(khadas_ts050->supply); 744 if (err < 0) 745 return err; 746 747 return 0; 748 } 749 750 static int khadas_ts050_panel_enable(struct drm_panel *panel) 751 { 752 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); 753 754 khadas_ts050->enabled = true; 755 756 return 0; 757 } 758 759 static int khadas_ts050_panel_disable(struct drm_panel *panel) 760 { 761 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); 762 int err; 763 764 if (!khadas_ts050->enabled) 765 return 0; 766 767 err = mipi_dsi_dcs_set_display_off(khadas_ts050->link); 768 if (err < 0) 769 dev_err(panel->dev, "failed to set display off: %d\n", err); 770 771 usleep_range(10000, 11000); 772 773 khadas_ts050->enabled = false; 774 775 return 0; 776 } 777 778 static const struct drm_display_mode default_mode = { 779 .clock = 160000, 780 .hdisplay = 1080, 781 .hsync_start = 1080 + 117, 782 .hsync_end = 1080 + 117 + 5, 783 .htotal = 1080 + 117 + 5 + 160, 784 .vdisplay = 1920, 785 .vsync_start = 1920 + 4, 786 .vsync_end = 1920 + 4 + 3, 787 .vtotal = 1920 + 4 + 3 + 31, 788 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 789 }; 790 791 static int khadas_ts050_panel_get_modes(struct drm_panel *panel, 792 struct drm_connector *connector) 793 { 794 struct drm_display_mode *mode; 795 796 mode = drm_mode_duplicate(connector->dev, &default_mode); 797 if (!mode) { 798 dev_err(panel->dev, "failed to add mode %ux%u@%u\n", 799 default_mode.hdisplay, default_mode.vdisplay, 800 drm_mode_vrefresh(&default_mode)); 801 return -ENOMEM; 802 } 803 804 drm_mode_set_name(mode); 805 806 drm_mode_probed_add(connector, mode); 807 808 connector->display_info.width_mm = 64; 809 connector->display_info.height_mm = 118; 810 connector->display_info.bpc = 8; 811 812 return 1; 813 } 814 815 static const struct drm_panel_funcs khadas_ts050_panel_funcs = { 816 .prepare = khadas_ts050_panel_prepare, 817 .unprepare = khadas_ts050_panel_unprepare, 818 .enable = khadas_ts050_panel_enable, 819 .disable = khadas_ts050_panel_disable, 820 .get_modes = khadas_ts050_panel_get_modes, 821 }; 822 823 static const struct of_device_id khadas_ts050_of_match[] = { 824 { .compatible = "khadas,ts050", .data = &ts050_panel_data, }, 825 { .compatible = "khadas,ts050v2", .data = &ts050v2_panel_data, }, 826 { /* sentinel */ } 827 }; 828 MODULE_DEVICE_TABLE(of, khadas_ts050_of_match); 829 830 static int khadas_ts050_panel_add(struct khadas_ts050_panel *khadas_ts050) 831 { 832 struct device *dev = &khadas_ts050->link->dev; 833 int err; 834 835 khadas_ts050->supply = devm_regulator_get(dev, "power"); 836 if (IS_ERR(khadas_ts050->supply)) 837 return dev_err_probe(dev, PTR_ERR(khadas_ts050->supply), 838 "failed to get power supply"); 839 840 khadas_ts050->reset_gpio = devm_gpiod_get(dev, "reset", 841 GPIOD_OUT_LOW); 842 if (IS_ERR(khadas_ts050->reset_gpio)) 843 return dev_err_probe(dev, PTR_ERR(khadas_ts050->reset_gpio), 844 "failed to get reset gpio"); 845 846 khadas_ts050->enable_gpio = devm_gpiod_get(dev, "enable", 847 GPIOD_OUT_HIGH); 848 if (IS_ERR(khadas_ts050->enable_gpio)) 849 return dev_err_probe(dev, PTR_ERR(khadas_ts050->enable_gpio), 850 "failed to get enable gpio"); 851 852 drm_panel_init(&khadas_ts050->base, &khadas_ts050->link->dev, 853 &khadas_ts050_panel_funcs, DRM_MODE_CONNECTOR_DSI); 854 855 err = drm_panel_of_backlight(&khadas_ts050->base); 856 if (err) 857 return err; 858 859 drm_panel_add(&khadas_ts050->base); 860 861 return 0; 862 } 863 864 static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi) 865 { 866 struct khadas_ts050_panel *khadas_ts050; 867 int err; 868 869 const void *data = of_device_get_match_data(&dsi->dev); 870 871 if (!data) { 872 dev_err(&dsi->dev, "No matching data\n"); 873 return -ENODEV; 874 } 875 876 dsi->lanes = 4; 877 dsi->format = MIPI_DSI_FMT_RGB888; 878 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 879 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; 880 881 khadas_ts050 = devm_kzalloc(&dsi->dev, sizeof(*khadas_ts050), 882 GFP_KERNEL); 883 if (!khadas_ts050) 884 return -ENOMEM; 885 886 khadas_ts050->panel_data = (struct khadas_ts050_panel_data *)data; 887 mipi_dsi_set_drvdata(dsi, khadas_ts050); 888 khadas_ts050->link = dsi; 889 890 err = khadas_ts050_panel_add(khadas_ts050); 891 if (err < 0) 892 return err; 893 894 err = mipi_dsi_attach(dsi); 895 if (err) 896 drm_panel_remove(&khadas_ts050->base); 897 898 return err; 899 } 900 901 static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi) 902 { 903 struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi); 904 int err; 905 906 err = mipi_dsi_detach(dsi); 907 if (err < 0) 908 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); 909 910 drm_panel_remove(&khadas_ts050->base); 911 drm_panel_disable(&khadas_ts050->base); 912 drm_panel_unprepare(&khadas_ts050->base); 913 } 914 915 static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi) 916 { 917 struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi); 918 919 drm_panel_disable(&khadas_ts050->base); 920 drm_panel_unprepare(&khadas_ts050->base); 921 } 922 923 static struct mipi_dsi_driver khadas_ts050_panel_driver = { 924 .driver = { 925 .name = "panel-khadas-ts050", 926 .of_match_table = khadas_ts050_of_match, 927 }, 928 .probe = khadas_ts050_panel_probe, 929 .remove = khadas_ts050_panel_remove, 930 .shutdown = khadas_ts050_panel_shutdown, 931 }; 932 module_mipi_dsi_driver(khadas_ts050_panel_driver); 933 934 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 935 MODULE_DESCRIPTION("Khadas TS050 panel driver"); 936 MODULE_LICENSE("GPL v2"); 937