lcd_mipid.c (13006B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * LCD driver for MIPI DBI-C / DCS compatible LCDs 4 * 5 * Copyright (C) 2006 Nokia Corporation 6 * Author: Imre Deak <imre.deak@nokia.com> 7 */ 8#include <linux/device.h> 9#include <linux/delay.h> 10#include <linux/slab.h> 11#include <linux/workqueue.h> 12#include <linux/spi/spi.h> 13#include <linux/module.h> 14 15#include <linux/platform_data/lcd-mipid.h> 16 17#include "omapfb.h" 18 19#define MIPID_MODULE_NAME "lcd_mipid" 20 21#define MIPID_CMD_READ_DISP_ID 0x04 22#define MIPID_CMD_READ_RED 0x06 23#define MIPID_CMD_READ_GREEN 0x07 24#define MIPID_CMD_READ_BLUE 0x08 25#define MIPID_CMD_READ_DISP_STATUS 0x09 26#define MIPID_CMD_RDDSDR 0x0F 27#define MIPID_CMD_SLEEP_IN 0x10 28#define MIPID_CMD_SLEEP_OUT 0x11 29#define MIPID_CMD_DISP_OFF 0x28 30#define MIPID_CMD_DISP_ON 0x29 31 32#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000) 33 34#define to_mipid_device(p) container_of(p, struct mipid_device, \ 35 panel) 36struct mipid_device { 37 int enabled; 38 int revision; 39 unsigned int saved_bklight_level; 40 unsigned long hw_guard_end; /* next value of jiffies 41 when we can issue the 42 next sleep in/out command */ 43 unsigned long hw_guard_wait; /* max guard time in jiffies */ 44 45 struct omapfb_device *fbdev; 46 struct spi_device *spi; 47 struct mutex mutex; 48 struct lcd_panel panel; 49 50 struct delayed_work esd_work; 51 void (*esd_check)(struct mipid_device *m); 52}; 53 54static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf, 55 int wlen, u8 *rbuf, int rlen) 56{ 57 struct spi_message m; 58 struct spi_transfer *x, xfer[4]; 59 u16 w; 60 int r; 61 62 BUG_ON(md->spi == NULL); 63 64 spi_message_init(&m); 65 66 memset(xfer, 0, sizeof(xfer)); 67 x = &xfer[0]; 68 69 cmd &= 0xff; 70 x->tx_buf = &cmd; 71 x->bits_per_word = 9; 72 x->len = 2; 73 spi_message_add_tail(x, &m); 74 75 if (wlen) { 76 x++; 77 x->tx_buf = wbuf; 78 x->len = wlen; 79 x->bits_per_word = 9; 80 spi_message_add_tail(x, &m); 81 } 82 83 if (rlen) { 84 x++; 85 x->rx_buf = &w; 86 x->len = 1; 87 spi_message_add_tail(x, &m); 88 89 if (rlen > 1) { 90 /* Arrange for the extra clock before the first 91 * data bit. 92 */ 93 x->bits_per_word = 9; 94 x->len = 2; 95 96 x++; 97 x->rx_buf = &rbuf[1]; 98 x->len = rlen - 1; 99 spi_message_add_tail(x, &m); 100 } 101 } 102 103 r = spi_sync(md->spi, &m); 104 if (r < 0) 105 dev_dbg(&md->spi->dev, "spi_sync %d\n", r); 106 107 if (rlen) 108 rbuf[0] = w & 0xff; 109} 110 111static inline void mipid_cmd(struct mipid_device *md, int cmd) 112{ 113 mipid_transfer(md, cmd, NULL, 0, NULL, 0); 114} 115 116static inline void mipid_write(struct mipid_device *md, 117 int reg, const u8 *buf, int len) 118{ 119 mipid_transfer(md, reg, buf, len, NULL, 0); 120} 121 122static inline void mipid_read(struct mipid_device *md, 123 int reg, u8 *buf, int len) 124{ 125 mipid_transfer(md, reg, NULL, 0, buf, len); 126} 127 128static void set_data_lines(struct mipid_device *md, int data_lines) 129{ 130 u16 par; 131 132 switch (data_lines) { 133 case 16: 134 par = 0x150; 135 break; 136 case 18: 137 par = 0x160; 138 break; 139 case 24: 140 par = 0x170; 141 break; 142 } 143 mipid_write(md, 0x3a, (u8 *)&par, 2); 144} 145 146static void send_init_string(struct mipid_device *md) 147{ 148 u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; 149 150 mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar)); 151 set_data_lines(md, md->panel.data_lines); 152} 153 154static void hw_guard_start(struct mipid_device *md, int guard_msec) 155{ 156 md->hw_guard_wait = msecs_to_jiffies(guard_msec); 157 md->hw_guard_end = jiffies + md->hw_guard_wait; 158} 159 160static void hw_guard_wait(struct mipid_device *md) 161{ 162 unsigned long wait = md->hw_guard_end - jiffies; 163 164 if ((long)wait > 0 && time_before_eq(wait, md->hw_guard_wait)) { 165 set_current_state(TASK_UNINTERRUPTIBLE); 166 schedule_timeout(wait); 167 } 168} 169 170static void set_sleep_mode(struct mipid_device *md, int on) 171{ 172 int cmd, sleep_time = 50; 173 174 if (on) 175 cmd = MIPID_CMD_SLEEP_IN; 176 else 177 cmd = MIPID_CMD_SLEEP_OUT; 178 hw_guard_wait(md); 179 mipid_cmd(md, cmd); 180 hw_guard_start(md, 120); 181 /* 182 * When we enable the panel, it seems we _have_ to sleep 183 * 120 ms before sending the init string. When disabling the 184 * panel we'll sleep for the duration of 2 frames, so that the 185 * controller can still provide the PCLK,HS,VS signals. 186 */ 187 if (!on) 188 sleep_time = 120; 189 msleep(sleep_time); 190} 191 192static void set_display_state(struct mipid_device *md, int enabled) 193{ 194 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; 195 196 mipid_cmd(md, cmd); 197} 198 199static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level) 200{ 201 struct mipid_device *md = to_mipid_device(panel); 202 struct mipid_platform_data *pd = md->spi->dev.platform_data; 203 204 if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL) 205 return -ENODEV; 206 if (level > pd->get_bklight_max(pd)) 207 return -EINVAL; 208 if (!md->enabled) { 209 md->saved_bklight_level = level; 210 return 0; 211 } 212 pd->set_bklight_level(pd, level); 213 214 return 0; 215} 216 217static unsigned int mipid_get_bklight_level(struct lcd_panel *panel) 218{ 219 struct mipid_device *md = to_mipid_device(panel); 220 struct mipid_platform_data *pd = md->spi->dev.platform_data; 221 222 if (pd->get_bklight_level == NULL) 223 return -ENODEV; 224 return pd->get_bklight_level(pd); 225} 226 227static unsigned int mipid_get_bklight_max(struct lcd_panel *panel) 228{ 229 struct mipid_device *md = to_mipid_device(panel); 230 struct mipid_platform_data *pd = md->spi->dev.platform_data; 231 232 if (pd->get_bklight_max == NULL) 233 return -ENODEV; 234 235 return pd->get_bklight_max(pd); 236} 237 238static unsigned long mipid_get_caps(struct lcd_panel *panel) 239{ 240 return OMAPFB_CAPS_SET_BACKLIGHT; 241} 242 243static u16 read_first_pixel(struct mipid_device *md) 244{ 245 u16 pixel; 246 u8 red, green, blue; 247 248 mutex_lock(&md->mutex); 249 mipid_read(md, MIPID_CMD_READ_RED, &red, 1); 250 mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1); 251 mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1); 252 mutex_unlock(&md->mutex); 253 254 switch (md->panel.data_lines) { 255 case 16: 256 pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1); 257 break; 258 case 24: 259 /* 24 bit -> 16 bit */ 260 pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | 261 (blue >> 3); 262 break; 263 default: 264 pixel = 0; 265 BUG(); 266 } 267 268 return pixel; 269} 270 271static int mipid_run_test(struct lcd_panel *panel, int test_num) 272{ 273 struct mipid_device *md = to_mipid_device(panel); 274 static const u16 test_values[4] = { 275 0x0000, 0xffff, 0xaaaa, 0x5555, 276 }; 277 int i; 278 279 if (test_num != MIPID_TEST_RGB_LINES) 280 return MIPID_TEST_INVALID; 281 282 for (i = 0; i < ARRAY_SIZE(test_values); i++) { 283 int delay; 284 unsigned long tmo; 285 286 omapfb_write_first_pixel(md->fbdev, test_values[i]); 287 tmo = jiffies + msecs_to_jiffies(100); 288 delay = 25; 289 while (1) { 290 u16 pixel; 291 292 msleep(delay); 293 pixel = read_first_pixel(md); 294 if (pixel == test_values[i]) 295 break; 296 if (time_after(jiffies, tmo)) { 297 dev_err(&md->spi->dev, 298 "MIPI LCD RGB I/F test failed: " 299 "expecting %04x, got %04x\n", 300 test_values[i], pixel); 301 return MIPID_TEST_FAILED; 302 } 303 delay = 10; 304 } 305 } 306 307 return 0; 308} 309 310static void ls041y3_esd_recover(struct mipid_device *md) 311{ 312 dev_err(&md->spi->dev, "performing LCD ESD recovery\n"); 313 set_sleep_mode(md, 1); 314 set_sleep_mode(md, 0); 315} 316 317static void ls041y3_esd_check_mode1(struct mipid_device *md) 318{ 319 u8 state1, state2; 320 321 mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1); 322 set_sleep_mode(md, 0); 323 mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1); 324 dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n", 325 state1, state2); 326 /* Each sleep out command will trigger a self diagnostic and flip 327 * Bit6 if the test passes. 328 */ 329 if (!((state1 ^ state2) & (1 << 6))) 330 ls041y3_esd_recover(md); 331} 332 333static void ls041y3_esd_check_mode2(struct mipid_device *md) 334{ 335 int i; 336 u8 rbuf[2]; 337 static const struct { 338 int cmd; 339 int wlen; 340 u16 wbuf[3]; 341 } *rd, rd_ctrl[7] = { 342 { 0xb0, 4, { 0x0101, 0x01fe, } }, 343 { 0xb1, 4, { 0x01de, 0x0121, } }, 344 { 0xc2, 4, { 0x0100, 0x0100, } }, 345 { 0xbd, 2, { 0x0100, } }, 346 { 0xc2, 4, { 0x01fc, 0x0103, } }, 347 { 0xb4, 0, }, 348 { 0x00, 0, }, 349 }; 350 351 rd = rd_ctrl; 352 for (i = 0; i < 3; i++, rd++) 353 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); 354 355 udelay(10); 356 mipid_read(md, rd->cmd, rbuf, 2); 357 rd++; 358 359 for (i = 0; i < 3; i++, rd++) { 360 udelay(10); 361 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); 362 } 363 364 dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]); 365 if (rbuf[1] == 0x00) 366 ls041y3_esd_recover(md); 367} 368 369static void ls041y3_esd_check(struct mipid_device *md) 370{ 371 ls041y3_esd_check_mode1(md); 372 if (md->revision >= 0x88) 373 ls041y3_esd_check_mode2(md); 374} 375 376static void mipid_esd_start_check(struct mipid_device *md) 377{ 378 if (md->esd_check != NULL) 379 schedule_delayed_work(&md->esd_work, 380 MIPID_ESD_CHECK_PERIOD); 381} 382 383static void mipid_esd_stop_check(struct mipid_device *md) 384{ 385 if (md->esd_check != NULL) 386 cancel_delayed_work_sync(&md->esd_work); 387} 388 389static void mipid_esd_work(struct work_struct *work) 390{ 391 struct mipid_device *md = container_of(work, struct mipid_device, 392 esd_work.work); 393 394 mutex_lock(&md->mutex); 395 md->esd_check(md); 396 mutex_unlock(&md->mutex); 397 mipid_esd_start_check(md); 398} 399 400static int mipid_enable(struct lcd_panel *panel) 401{ 402 struct mipid_device *md = to_mipid_device(panel); 403 404 mutex_lock(&md->mutex); 405 406 if (md->enabled) { 407 mutex_unlock(&md->mutex); 408 return 0; 409 } 410 set_sleep_mode(md, 0); 411 md->enabled = 1; 412 send_init_string(md); 413 set_display_state(md, 1); 414 mipid_set_bklight_level(panel, md->saved_bklight_level); 415 mipid_esd_start_check(md); 416 417 mutex_unlock(&md->mutex); 418 return 0; 419} 420 421static void mipid_disable(struct lcd_panel *panel) 422{ 423 struct mipid_device *md = to_mipid_device(panel); 424 425 /* 426 * A final ESD work might be called before returning, 427 * so do this without holding the lock. 428 */ 429 mipid_esd_stop_check(md); 430 mutex_lock(&md->mutex); 431 432 if (!md->enabled) { 433 mutex_unlock(&md->mutex); 434 return; 435 } 436 md->saved_bklight_level = mipid_get_bklight_level(panel); 437 mipid_set_bklight_level(panel, 0); 438 set_display_state(md, 0); 439 set_sleep_mode(md, 1); 440 md->enabled = 0; 441 442 mutex_unlock(&md->mutex); 443} 444 445static int panel_enabled(struct mipid_device *md) 446{ 447 u32 disp_status; 448 int enabled; 449 450 mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4); 451 disp_status = __be32_to_cpu(disp_status); 452 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); 453 dev_dbg(&md->spi->dev, 454 "LCD panel %senabled by bootloader (status 0x%04x)\n", 455 enabled ? "" : "not ", disp_status); 456 return enabled; 457} 458 459static int mipid_init(struct lcd_panel *panel, 460 struct omapfb_device *fbdev) 461{ 462 struct mipid_device *md = to_mipid_device(panel); 463 464 md->fbdev = fbdev; 465 INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work); 466 mutex_init(&md->mutex); 467 468 md->enabled = panel_enabled(md); 469 470 if (md->enabled) 471 mipid_esd_start_check(md); 472 else 473 md->saved_bklight_level = mipid_get_bklight_level(panel); 474 475 return 0; 476} 477 478static void mipid_cleanup(struct lcd_panel *panel) 479{ 480 struct mipid_device *md = to_mipid_device(panel); 481 482 if (md->enabled) 483 mipid_esd_stop_check(md); 484} 485 486static const struct lcd_panel mipid_panel = { 487 .config = OMAP_LCDC_PANEL_TFT, 488 489 .bpp = 16, 490 .x_res = 800, 491 .y_res = 480, 492 .pixel_clock = 21940, 493 .hsw = 50, 494 .hfp = 20, 495 .hbp = 15, 496 .vsw = 2, 497 .vfp = 1, 498 .vbp = 3, 499 500 .init = mipid_init, 501 .cleanup = mipid_cleanup, 502 .enable = mipid_enable, 503 .disable = mipid_disable, 504 .get_caps = mipid_get_caps, 505 .set_bklight_level = mipid_set_bklight_level, 506 .get_bklight_level = mipid_get_bklight_level, 507 .get_bklight_max = mipid_get_bklight_max, 508 .run_test = mipid_run_test, 509}; 510 511static int mipid_detect(struct mipid_device *md) 512{ 513 struct mipid_platform_data *pdata; 514 u8 display_id[3]; 515 516 pdata = md->spi->dev.platform_data; 517 if (pdata == NULL) { 518 dev_err(&md->spi->dev, "missing platform data\n"); 519 return -ENOENT; 520 } 521 522 mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3); 523 dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n", 524 display_id[0], display_id[1], display_id[2]); 525 526 switch (display_id[0]) { 527 case 0x45: 528 md->panel.name = "lph8923"; 529 break; 530 case 0x83: 531 md->panel.name = "ls041y3"; 532 md->esd_check = ls041y3_esd_check; 533 break; 534 default: 535 md->panel.name = "unknown"; 536 dev_err(&md->spi->dev, "invalid display ID\n"); 537 return -ENODEV; 538 } 539 540 md->revision = display_id[1]; 541 md->panel.data_lines = pdata->data_lines; 542 pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n", 543 md->panel.name, md->revision, md->panel.data_lines); 544 545 return 0; 546} 547 548static int mipid_spi_probe(struct spi_device *spi) 549{ 550 struct mipid_device *md; 551 int r; 552 553 md = kzalloc(sizeof(*md), GFP_KERNEL); 554 if (md == NULL) { 555 dev_err(&spi->dev, "out of memory\n"); 556 return -ENOMEM; 557 } 558 559 spi->mode = SPI_MODE_0; 560 md->spi = spi; 561 dev_set_drvdata(&spi->dev, md); 562 md->panel = mipid_panel; 563 564 r = mipid_detect(md); 565 if (r < 0) 566 return r; 567 568 omapfb_register_panel(&md->panel); 569 570 return 0; 571} 572 573static void mipid_spi_remove(struct spi_device *spi) 574{ 575 struct mipid_device *md = dev_get_drvdata(&spi->dev); 576 577 mipid_disable(&md->panel); 578 kfree(md); 579} 580 581static struct spi_driver mipid_spi_driver = { 582 .driver = { 583 .name = MIPID_MODULE_NAME, 584 }, 585 .probe = mipid_spi_probe, 586 .remove = mipid_spi_remove, 587}; 588 589module_spi_driver(mipid_spi_driver); 590 591MODULE_DESCRIPTION("MIPI display driver"); 592MODULE_LICENSE("GPL");