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