1/* 2 * Sony ACX565AKM LCD Panel driver 3 * 4 * Copyright (C) 2010 Nokia Corporation 5 * 6 * Original Driver Author: Imre Deak <imre.deak@nokia.com> 7 * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com> 8 * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com> 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published by 12 * the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 * more details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23#include <linux/kernel.h> 24#include <linux/module.h> 25#include <linux/platform_device.h> 26#include <linux/delay.h> 27#include <linux/spi/spi.h> 28#include <linux/jiffies.h> 29#include <linux/sched.h> 30#include <linux/backlight.h> 31#include <linux/fb.h> 32#include <linux/gpio.h> 33#include <linux/of.h> 34#include <linux/of_gpio.h> 35 36#include <video/omapdss.h> 37#include <video/omap-panel-data.h> 38 39#define MIPID_CMD_READ_DISP_ID 0x04 40#define MIPID_CMD_READ_RED 0x06 41#define MIPID_CMD_READ_GREEN 0x07 42#define MIPID_CMD_READ_BLUE 0x08 43#define MIPID_CMD_READ_DISP_STATUS 0x09 44#define MIPID_CMD_RDDSDR 0x0F 45#define MIPID_CMD_SLEEP_IN 0x10 46#define MIPID_CMD_SLEEP_OUT 0x11 47#define MIPID_CMD_DISP_OFF 0x28 48#define MIPID_CMD_DISP_ON 0x29 49#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51 50#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52 51#define MIPID_CMD_WRITE_CTRL_DISP 0x53 52 53#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5) 54#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4) 55#define CTRL_DISP_BACKLIGHT_ON (1 << 2) 56#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1) 57 58#define MIPID_CMD_READ_CTRL_DISP 0x54 59#define MIPID_CMD_WRITE_CABC 0x55 60#define MIPID_CMD_READ_CABC 0x56 61 62#define MIPID_VER_LPH8923 3 63#define MIPID_VER_LS041Y3 4 64#define MIPID_VER_L4F00311 8 65#define MIPID_VER_ACX565AKM 9 66 67struct panel_drv_data { 68 struct omap_dss_device dssdev; 69 struct omap_dss_device *in; 70 71 int reset_gpio; 72 int datapairs; 73 74 struct omap_video_timings videomode; 75 76 char *name; 77 int enabled; 78 int model; 79 int revision; 80 u8 display_id[3]; 81 unsigned has_bc:1; 82 unsigned has_cabc:1; 83 unsigned cabc_mode; 84 unsigned long hw_guard_end; /* next value of jiffies 85 when we can issue the 86 next sleep in/out command */ 87 unsigned long hw_guard_wait; /* max guard time in jiffies */ 88 89 struct spi_device *spi; 90 struct mutex mutex; 91 92 struct backlight_device *bl_dev; 93}; 94 95static const struct omap_video_timings acx565akm_panel_timings = { 96 .x_res = 800, 97 .y_res = 480, 98 .pixelclock = 24000000, 99 .hfp = 28, 100 .hsw = 4, 101 .hbp = 24, 102 .vfp = 3, 103 .vsw = 3, 104 .vbp = 4, 105 106 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, 107 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, 108 109 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, 110 .de_level = OMAPDSS_SIG_ACTIVE_HIGH, 111 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, 112}; 113 114#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) 115 116static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd, 117 const u8 *wbuf, int wlen, u8 *rbuf, int rlen) 118{ 119 struct spi_message m; 120 struct spi_transfer *x, xfer[5]; 121 int r; 122 123 BUG_ON(ddata->spi == NULL); 124 125 spi_message_init(&m); 126 127 memset(xfer, 0, sizeof(xfer)); 128 x = &xfer[0]; 129 130 cmd &= 0xff; 131 x->tx_buf = &cmd; 132 x->bits_per_word = 9; 133 x->len = 2; 134 135 if (rlen > 1 && wlen == 0) { 136 /* 137 * Between the command and the response data there is a 138 * dummy clock cycle. Add an extra bit after the command 139 * word to account for this. 140 */ 141 x->bits_per_word = 10; 142 cmd <<= 1; 143 } 144 spi_message_add_tail(x, &m); 145 146 if (wlen) { 147 x++; 148 x->tx_buf = wbuf; 149 x->len = wlen; 150 x->bits_per_word = 9; 151 spi_message_add_tail(x, &m); 152 } 153 154 if (rlen) { 155 x++; 156 x->rx_buf = rbuf; 157 x->len = rlen; 158 spi_message_add_tail(x, &m); 159 } 160 161 r = spi_sync(ddata->spi, &m); 162 if (r < 0) 163 dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r); 164} 165 166static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd) 167{ 168 acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0); 169} 170 171static inline void acx565akm_write(struct panel_drv_data *ddata, 172 int reg, const u8 *buf, int len) 173{ 174 acx565akm_transfer(ddata, reg, buf, len, NULL, 0); 175} 176 177static inline void acx565akm_read(struct panel_drv_data *ddata, 178 int reg, u8 *buf, int len) 179{ 180 acx565akm_transfer(ddata, reg, NULL, 0, buf, len); 181} 182 183static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec) 184{ 185 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec); 186 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait; 187} 188 189static void hw_guard_wait(struct panel_drv_data *ddata) 190{ 191 unsigned long wait = ddata->hw_guard_end - jiffies; 192 193 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) { 194 set_current_state(TASK_UNINTERRUPTIBLE); 195 schedule_timeout(wait); 196 } 197} 198 199static void set_sleep_mode(struct panel_drv_data *ddata, int on) 200{ 201 int cmd; 202 203 if (on) 204 cmd = MIPID_CMD_SLEEP_IN; 205 else 206 cmd = MIPID_CMD_SLEEP_OUT; 207 /* 208 * We have to keep 120msec between sleep in/out commands. 209 * (8.2.15, 8.2.16). 210 */ 211 hw_guard_wait(ddata); 212 acx565akm_cmd(ddata, cmd); 213 hw_guard_start(ddata, 120); 214} 215 216static void set_display_state(struct panel_drv_data *ddata, int enabled) 217{ 218 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; 219 220 acx565akm_cmd(ddata, cmd); 221} 222 223static int panel_enabled(struct panel_drv_data *ddata) 224{ 225 u32 disp_status; 226 int enabled; 227 228 acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS, 229 (u8 *)&disp_status, 4); 230 disp_status = __be32_to_cpu(disp_status); 231 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); 232 dev_dbg(&ddata->spi->dev, 233 "LCD panel %senabled by bootloader (status 0x%04x)\n", 234 enabled ? "" : "not ", disp_status); 235 return enabled; 236} 237 238static int panel_detect(struct panel_drv_data *ddata) 239{ 240 acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3); 241 dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n", 242 ddata->display_id[0], 243 ddata->display_id[1], 244 ddata->display_id[2]); 245 246 switch (ddata->display_id[0]) { 247 case 0x10: 248 ddata->model = MIPID_VER_ACX565AKM; 249 ddata->name = "acx565akm"; 250 ddata->has_bc = 1; 251 ddata->has_cabc = 1; 252 break; 253 case 0x29: 254 ddata->model = MIPID_VER_L4F00311; 255 ddata->name = "l4f00311"; 256 break; 257 case 0x45: 258 ddata->model = MIPID_VER_LPH8923; 259 ddata->name = "lph8923"; 260 break; 261 case 0x83: 262 ddata->model = MIPID_VER_LS041Y3; 263 ddata->name = "ls041y3"; 264 break; 265 default: 266 ddata->name = "unknown"; 267 dev_err(&ddata->spi->dev, "invalid display ID\n"); 268 return -ENODEV; 269 } 270 271 ddata->revision = ddata->display_id[1]; 272 273 dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n", 274 ddata->name, ddata->revision); 275 276 return 0; 277} 278 279/*----------------------Backlight Control-------------------------*/ 280 281static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable) 282{ 283 u16 ctrl; 284 285 acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1); 286 if (enable) { 287 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON | 288 CTRL_DISP_BACKLIGHT_ON; 289 } else { 290 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON | 291 CTRL_DISP_BACKLIGHT_ON); 292 } 293 294 ctrl |= 1 << 8; 295 acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2); 296} 297 298static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode) 299{ 300 u16 cabc_ctrl; 301 302 ddata->cabc_mode = mode; 303 if (!ddata->enabled) 304 return; 305 cabc_ctrl = 0; 306 acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1); 307 cabc_ctrl &= ~3; 308 cabc_ctrl |= (1 << 8) | (mode & 3); 309 acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2); 310} 311 312static unsigned get_cabc_mode(struct panel_drv_data *ddata) 313{ 314 return ddata->cabc_mode; 315} 316 317static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata) 318{ 319 u8 cabc_ctrl; 320 321 acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1); 322 return cabc_ctrl & 3; 323} 324 325static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level) 326{ 327 int bv; 328 329 bv = level | (1 << 8); 330 acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2); 331 332 if (level) 333 enable_backlight_ctrl(ddata, 1); 334 else 335 enable_backlight_ctrl(ddata, 0); 336} 337 338static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata) 339{ 340 u8 bv; 341 342 acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1); 343 344 return bv; 345} 346 347 348static int acx565akm_bl_update_status(struct backlight_device *dev) 349{ 350 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); 351 int level; 352 353 dev_dbg(&ddata->spi->dev, "%s\n", __func__); 354 355 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 356 dev->props.power == FB_BLANK_UNBLANK) 357 level = dev->props.brightness; 358 else 359 level = 0; 360 361 if (ddata->has_bc) 362 acx565akm_set_brightness(ddata, level); 363 else 364 return -ENODEV; 365 366 return 0; 367} 368 369static int acx565akm_bl_get_intensity(struct backlight_device *dev) 370{ 371 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); 372 373 dev_dbg(&dev->dev, "%s\n", __func__); 374 375 if (!ddata->has_bc) 376 return -ENODEV; 377 378 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 379 dev->props.power == FB_BLANK_UNBLANK) { 380 if (ddata->has_bc) 381 return acx565akm_get_actual_brightness(ddata); 382 else 383 return dev->props.brightness; 384 } 385 386 return 0; 387} 388 389static int acx565akm_bl_update_status_locked(struct backlight_device *dev) 390{ 391 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); 392 int r; 393 394 mutex_lock(&ddata->mutex); 395 r = acx565akm_bl_update_status(dev); 396 mutex_unlock(&ddata->mutex); 397 398 return r; 399} 400 401static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev) 402{ 403 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); 404 int r; 405 406 mutex_lock(&ddata->mutex); 407 r = acx565akm_bl_get_intensity(dev); 408 mutex_unlock(&ddata->mutex); 409 410 return r; 411} 412 413static const struct backlight_ops acx565akm_bl_ops = { 414 .get_brightness = acx565akm_bl_get_intensity_locked, 415 .update_status = acx565akm_bl_update_status_locked, 416}; 417 418/*--------------------Auto Brightness control via Sysfs---------------------*/ 419 420static const char * const cabc_modes[] = { 421 "off", /* always used when CABC is not supported */ 422 "ui", 423 "still-image", 424 "moving-image", 425}; 426 427static ssize_t show_cabc_mode(struct device *dev, 428 struct device_attribute *attr, 429 char *buf) 430{ 431 struct panel_drv_data *ddata = dev_get_drvdata(dev); 432 const char *mode_str; 433 int mode; 434 int len; 435 436 if (!ddata->has_cabc) 437 mode = 0; 438 else 439 mode = get_cabc_mode(ddata); 440 mode_str = "unknown"; 441 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) 442 mode_str = cabc_modes[mode]; 443 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); 444 445 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; 446} 447 448static ssize_t store_cabc_mode(struct device *dev, 449 struct device_attribute *attr, 450 const char *buf, size_t count) 451{ 452 struct panel_drv_data *ddata = dev_get_drvdata(dev); 453 int i; 454 455 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { 456 const char *mode_str = cabc_modes[i]; 457 int cmp_len = strlen(mode_str); 458 459 if (count > 0 && buf[count - 1] == '\n') 460 count--; 461 if (count != cmp_len) 462 continue; 463 464 if (strncmp(buf, mode_str, cmp_len) == 0) 465 break; 466 } 467 468 if (i == ARRAY_SIZE(cabc_modes)) 469 return -EINVAL; 470 471 if (!ddata->has_cabc && i != 0) 472 return -EINVAL; 473 474 mutex_lock(&ddata->mutex); 475 set_cabc_mode(ddata, i); 476 mutex_unlock(&ddata->mutex); 477 478 return count; 479} 480 481static ssize_t show_cabc_available_modes(struct device *dev, 482 struct device_attribute *attr, 483 char *buf) 484{ 485 struct panel_drv_data *ddata = dev_get_drvdata(dev); 486 int len; 487 int i; 488 489 if (!ddata->has_cabc) 490 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]); 491 492 for (i = 0, len = 0; 493 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) 494 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", 495 i ? " " : "", cabc_modes[i], 496 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); 497 498 return len < PAGE_SIZE ? len : PAGE_SIZE - 1; 499} 500 501static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, 502 show_cabc_mode, store_cabc_mode); 503static DEVICE_ATTR(cabc_available_modes, S_IRUGO, 504 show_cabc_available_modes, NULL); 505 506static struct attribute *bldev_attrs[] = { 507 &dev_attr_cabc_mode.attr, 508 &dev_attr_cabc_available_modes.attr, 509 NULL, 510}; 511 512static struct attribute_group bldev_attr_group = { 513 .attrs = bldev_attrs, 514}; 515 516static int acx565akm_connect(struct omap_dss_device *dssdev) 517{ 518 struct panel_drv_data *ddata = to_panel_data(dssdev); 519 struct omap_dss_device *in = ddata->in; 520 int r; 521 522 if (omapdss_device_is_connected(dssdev)) 523 return 0; 524 525 r = in->ops.sdi->connect(in, dssdev); 526 if (r) 527 return r; 528 529 return 0; 530} 531 532static void acx565akm_disconnect(struct omap_dss_device *dssdev) 533{ 534 struct panel_drv_data *ddata = to_panel_data(dssdev); 535 struct omap_dss_device *in = ddata->in; 536 537 if (!omapdss_device_is_connected(dssdev)) 538 return; 539 540 in->ops.sdi->disconnect(in, dssdev); 541} 542 543static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) 544{ 545 struct panel_drv_data *ddata = to_panel_data(dssdev); 546 struct omap_dss_device *in = ddata->in; 547 int r; 548 549 dev_dbg(&ddata->spi->dev, "%s\n", __func__); 550 551 in->ops.sdi->set_timings(in, &ddata->videomode); 552 553 if (ddata->datapairs > 0) 554 in->ops.sdi->set_datapairs(in, ddata->datapairs); 555 556 r = in->ops.sdi->enable(in); 557 if (r) { 558 pr_err("%s sdi enable failed\n", __func__); 559 return r; 560 } 561 562 /*FIXME tweak me */ 563 msleep(50); 564 565 if (gpio_is_valid(ddata->reset_gpio)) 566 gpio_set_value(ddata->reset_gpio, 1); 567 568 if (ddata->enabled) { 569 dev_dbg(&ddata->spi->dev, "panel already enabled\n"); 570 return 0; 571 } 572 573 /* 574 * We have to meet all the following delay requirements: 575 * 1. tRW: reset pulse width 10usec (7.12.1) 576 * 2. tRT: reset cancel time 5msec (7.12.1) 577 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst 578 * case (7.6.2) 579 * 4. 120msec before the sleep out command (7.12.1) 580 */ 581 msleep(120); 582 583 set_sleep_mode(ddata, 0); 584 ddata->enabled = 1; 585 586 /* 5msec between sleep out and the next command. (8.2.16) */ 587 usleep_range(5000, 10000); 588 set_display_state(ddata, 1); 589 set_cabc_mode(ddata, ddata->cabc_mode); 590 591 return acx565akm_bl_update_status(ddata->bl_dev); 592} 593 594static void acx565akm_panel_power_off(struct omap_dss_device *dssdev) 595{ 596 struct panel_drv_data *ddata = to_panel_data(dssdev); 597 struct omap_dss_device *in = ddata->in; 598 599 dev_dbg(dssdev->dev, "%s\n", __func__); 600 601 if (!ddata->enabled) 602 return; 603 604 set_display_state(ddata, 0); 605 set_sleep_mode(ddata, 1); 606 ddata->enabled = 0; 607 /* 608 * We have to provide PCLK,HS,VS signals for 2 frames (worst case 609 * ~50msec) after sending the sleep in command and asserting the 610 * reset signal. We probably could assert the reset w/o the delay 611 * but we still delay to avoid possible artifacts. (7.6.1) 612 */ 613 msleep(50); 614 615 if (gpio_is_valid(ddata->reset_gpio)) 616 gpio_set_value(ddata->reset_gpio, 0); 617 618 /* FIXME need to tweak this delay */ 619 msleep(100); 620 621 in->ops.sdi->disable(in); 622} 623 624static int acx565akm_enable(struct omap_dss_device *dssdev) 625{ 626 struct panel_drv_data *ddata = to_panel_data(dssdev); 627 int r; 628 629 dev_dbg(dssdev->dev, "%s\n", __func__); 630 631 if (!omapdss_device_is_connected(dssdev)) 632 return -ENODEV; 633 634 if (omapdss_device_is_enabled(dssdev)) 635 return 0; 636 637 mutex_lock(&ddata->mutex); 638 r = acx565akm_panel_power_on(dssdev); 639 mutex_unlock(&ddata->mutex); 640 if (r) 641 return r; 642 643 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 644 645 return 0; 646} 647 648static void acx565akm_disable(struct omap_dss_device *dssdev) 649{ 650 struct panel_drv_data *ddata = to_panel_data(dssdev); 651 652 dev_dbg(dssdev->dev, "%s\n", __func__); 653 654 if (!omapdss_device_is_enabled(dssdev)) 655 return; 656 657 mutex_lock(&ddata->mutex); 658 acx565akm_panel_power_off(dssdev); 659 mutex_unlock(&ddata->mutex); 660 661 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 662} 663 664static void acx565akm_set_timings(struct omap_dss_device *dssdev, 665 struct omap_video_timings *timings) 666{ 667 struct panel_drv_data *ddata = to_panel_data(dssdev); 668 struct omap_dss_device *in = ddata->in; 669 670 ddata->videomode = *timings; 671 dssdev->panel.timings = *timings; 672 673 in->ops.sdi->set_timings(in, timings); 674} 675 676static void acx565akm_get_timings(struct omap_dss_device *dssdev, 677 struct omap_video_timings *timings) 678{ 679 struct panel_drv_data *ddata = to_panel_data(dssdev); 680 681 *timings = ddata->videomode; 682} 683 684static int acx565akm_check_timings(struct omap_dss_device *dssdev, 685 struct omap_video_timings *timings) 686{ 687 struct panel_drv_data *ddata = to_panel_data(dssdev); 688 struct omap_dss_device *in = ddata->in; 689 690 return in->ops.sdi->check_timings(in, timings); 691} 692 693static struct omap_dss_driver acx565akm_ops = { 694 .connect = acx565akm_connect, 695 .disconnect = acx565akm_disconnect, 696 697 .enable = acx565akm_enable, 698 .disable = acx565akm_disable, 699 700 .set_timings = acx565akm_set_timings, 701 .get_timings = acx565akm_get_timings, 702 .check_timings = acx565akm_check_timings, 703 704 .get_resolution = omapdss_default_get_resolution, 705}; 706 707static int acx565akm_probe_pdata(struct spi_device *spi) 708{ 709 const struct panel_acx565akm_platform_data *pdata; 710 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 711 struct omap_dss_device *dssdev, *in; 712 713 pdata = dev_get_platdata(&spi->dev); 714 715 ddata->reset_gpio = pdata->reset_gpio; 716 717 in = omap_dss_find_output(pdata->source); 718 if (in == NULL) { 719 dev_err(&spi->dev, "failed to find video source '%s'\n", 720 pdata->source); 721 return -EPROBE_DEFER; 722 } 723 ddata->in = in; 724 725 ddata->datapairs = pdata->datapairs; 726 727 dssdev = &ddata->dssdev; 728 dssdev->name = pdata->name; 729 730 return 0; 731} 732 733static int acx565akm_probe_of(struct spi_device *spi) 734{ 735 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 736 struct device_node *np = spi->dev.of_node; 737 738 ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); 739 740 ddata->in = omapdss_of_find_source_for_first_ep(np); 741 if (IS_ERR(ddata->in)) { 742 dev_err(&spi->dev, "failed to find video source\n"); 743 return PTR_ERR(ddata->in); 744 } 745 746 return 0; 747} 748 749static int acx565akm_probe(struct spi_device *spi) 750{ 751 struct panel_drv_data *ddata; 752 struct omap_dss_device *dssdev; 753 struct backlight_device *bldev; 754 int max_brightness, brightness; 755 struct backlight_properties props; 756 int r; 757 758 dev_dbg(&spi->dev, "%s\n", __func__); 759 760 spi->mode = SPI_MODE_3; 761 762 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 763 if (ddata == NULL) 764 return -ENOMEM; 765 766 dev_set_drvdata(&spi->dev, ddata); 767 768 ddata->spi = spi; 769 770 mutex_init(&ddata->mutex); 771 772 if (dev_get_platdata(&spi->dev)) { 773 r = acx565akm_probe_pdata(spi); 774 if (r) 775 return r; 776 } else if (spi->dev.of_node) { 777 r = acx565akm_probe_of(spi); 778 if (r) 779 return r; 780 } else { 781 dev_err(&spi->dev, "platform data missing!\n"); 782 return -ENODEV; 783 } 784 785 if (gpio_is_valid(ddata->reset_gpio)) { 786 r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio, 787 GPIOF_OUT_INIT_LOW, "lcd reset"); 788 if (r) 789 goto err_gpio; 790 } 791 792 if (gpio_is_valid(ddata->reset_gpio)) 793 gpio_set_value(ddata->reset_gpio, 1); 794 795 /* 796 * After reset we have to wait 5 msec before the first 797 * command can be sent. 798 */ 799 usleep_range(5000, 10000); 800 801 ddata->enabled = panel_enabled(ddata); 802 803 r = panel_detect(ddata); 804 805 if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio)) 806 gpio_set_value(ddata->reset_gpio, 0); 807 808 if (r) { 809 dev_err(&spi->dev, "%s panel detect error\n", __func__); 810 goto err_detect; 811 } 812 813 memset(&props, 0, sizeof(props)); 814 props.fb_blank = FB_BLANK_UNBLANK; 815 props.power = FB_BLANK_UNBLANK; 816 props.type = BACKLIGHT_RAW; 817 818 bldev = backlight_device_register("acx565akm", &ddata->spi->dev, 819 ddata, &acx565akm_bl_ops, &props); 820 if (IS_ERR(bldev)) { 821 r = PTR_ERR(bldev); 822 goto err_reg_bl; 823 } 824 ddata->bl_dev = bldev; 825 if (ddata->has_cabc) { 826 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group); 827 if (r) { 828 dev_err(&bldev->dev, 829 "%s failed to create sysfs files\n", __func__); 830 goto err_sysfs; 831 } 832 ddata->cabc_mode = get_hw_cabc_mode(ddata); 833 } 834 835 max_brightness = 255; 836 837 if (ddata->has_bc) 838 brightness = acx565akm_get_actual_brightness(ddata); 839 else 840 brightness = 0; 841 842 bldev->props.max_brightness = max_brightness; 843 bldev->props.brightness = brightness; 844 845 acx565akm_bl_update_status(bldev); 846 847 848 ddata->videomode = acx565akm_panel_timings; 849 850 dssdev = &ddata->dssdev; 851 dssdev->dev = &spi->dev; 852 dssdev->driver = &acx565akm_ops; 853 dssdev->type = OMAP_DISPLAY_TYPE_SDI; 854 dssdev->owner = THIS_MODULE; 855 dssdev->panel.timings = ddata->videomode; 856 857 r = omapdss_register_display(dssdev); 858 if (r) { 859 dev_err(&spi->dev, "Failed to register panel\n"); 860 goto err_reg; 861 } 862 863 return 0; 864 865err_reg: 866 sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group); 867err_sysfs: 868 backlight_device_unregister(bldev); 869err_reg_bl: 870err_detect: 871err_gpio: 872 omap_dss_put_device(ddata->in); 873 return r; 874} 875 876static int acx565akm_remove(struct spi_device *spi) 877{ 878 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 879 struct omap_dss_device *dssdev = &ddata->dssdev; 880 struct omap_dss_device *in = ddata->in; 881 882 dev_dbg(&ddata->spi->dev, "%s\n", __func__); 883 884 sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group); 885 backlight_device_unregister(ddata->bl_dev); 886 887 omapdss_unregister_display(dssdev); 888 889 acx565akm_disable(dssdev); 890 acx565akm_disconnect(dssdev); 891 892 omap_dss_put_device(in); 893 894 return 0; 895} 896 897static const struct of_device_id acx565akm_of_match[] = { 898 { .compatible = "omapdss,sony,acx565akm", }, 899 {}, 900}; 901 902static struct spi_driver acx565akm_driver = { 903 .driver = { 904 .name = "acx565akm", 905 .owner = THIS_MODULE, 906 .of_match_table = acx565akm_of_match, 907 .suppress_bind_attrs = true, 908 }, 909 .probe = acx565akm_probe, 910 .remove = acx565akm_remove, 911}; 912 913module_spi_driver(acx565akm_driver); 914 915MODULE_AUTHOR("Nokia Corporation"); 916MODULE_DESCRIPTION("acx565akm LCD Driver"); 917MODULE_LICENSE("GPL"); 918