Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

OMAPDSS: Add N800 panel driver

This is a driver for N800's display, ported from the old omapfb. This is
a slightly lighter version of the driver as not all features of the old
driver can be ported without big changes to DSS2, and also because some
of the HW features used in the old driver are unclear (e.g. the power
management part).

That said, the new driver works fine for basic use.

Architecturally the driver is not as neat as it could be. N800's display
HW consists of a display buffer chip and a panel, and ideally they would
be represented by separate, independent drivers. This is not currently
possible, and this driver contains both buffer chip and panel driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

+770
+7
drivers/video/omap2/displays/Kconfig
··· 62 62 select BACKLIGHT_CLASS_DEVICE 63 63 help 64 64 This is the LCD panel used on Nokia N900 65 + 66 + config PANEL_N8X0 67 + tristate "N8X0 Panel" 68 + depends on OMAP2_DSS_RFBI && SPI 69 + select BACKLIGHT_CLASS_DEVICE 70 + help 71 + This is the LCD panel used on Nokia N8x0 65 72 endmenu
+1
drivers/video/omap2/displays/Makefile
··· 8 8 obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o 9 9 obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 10 10 obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 11 + obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
+747
drivers/video/omap2/displays/panel-n8x0.c
··· 1 + /* #define DEBUG */ 2 + 3 + #include <linux/module.h> 4 + #include <linux/delay.h> 5 + #include <linux/slab.h> 6 + #include <linux/gpio.h> 7 + #include <linux/spi/spi.h> 8 + #include <linux/backlight.h> 9 + #include <linux/fb.h> 10 + 11 + #include <video/omapdss.h> 12 + #include <video/omap-panel-n8x0.h> 13 + 14 + #define BLIZZARD_REV_CODE 0x00 15 + #define BLIZZARD_CONFIG 0x02 16 + #define BLIZZARD_PLL_DIV 0x04 17 + #define BLIZZARD_PLL_LOCK_RANGE 0x06 18 + #define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 19 + #define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a 20 + #define BLIZZARD_PLL_MODE 0x0c 21 + #define BLIZZARD_CLK_SRC 0x0e 22 + #define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 23 + #define BLIZZARD_MEM_BANK0_STATUS 0x14 24 + #define BLIZZARD_PANEL_CONFIGURATION 0x28 25 + #define BLIZZARD_HDISP 0x2a 26 + #define BLIZZARD_HNDP 0x2c 27 + #define BLIZZARD_VDISP0 0x2e 28 + #define BLIZZARD_VDISP1 0x30 29 + #define BLIZZARD_VNDP 0x32 30 + #define BLIZZARD_HSW 0x34 31 + #define BLIZZARD_VSW 0x38 32 + #define BLIZZARD_DISPLAY_MODE 0x68 33 + #define BLIZZARD_INPUT_WIN_X_START_0 0x6c 34 + #define BLIZZARD_DATA_SOURCE_SELECT 0x8e 35 + #define BLIZZARD_DISP_MEM_DATA_PORT 0x90 36 + #define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 37 + #define BLIZZARD_POWER_SAVE 0xE6 38 + #define BLIZZARD_NDISP_CTRL_STATUS 0xE8 39 + 40 + /* Data source select */ 41 + /* For S1D13745 */ 42 + #define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 43 + #define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 44 + #define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 45 + #define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 46 + /* For S1D13744 */ 47 + #define BLIZZARD_SRC_WRITE_LCD 0x00 48 + #define BLIZZARD_SRC_BLT_LCD 0x06 49 + 50 + #define BLIZZARD_COLOR_RGB565 0x01 51 + #define BLIZZARD_COLOR_YUV420 0x09 52 + 53 + #define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ 54 + #define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ 55 + 56 + #define MIPID_CMD_READ_DISP_ID 0x04 57 + #define MIPID_CMD_READ_RED 0x06 58 + #define MIPID_CMD_READ_GREEN 0x07 59 + #define MIPID_CMD_READ_BLUE 0x08 60 + #define MIPID_CMD_READ_DISP_STATUS 0x09 61 + #define MIPID_CMD_RDDSDR 0x0F 62 + #define MIPID_CMD_SLEEP_IN 0x10 63 + #define MIPID_CMD_SLEEP_OUT 0x11 64 + #define MIPID_CMD_DISP_OFF 0x28 65 + #define MIPID_CMD_DISP_ON 0x29 66 + 67 + static struct panel_drv_data { 68 + struct mutex lock; 69 + 70 + struct omap_dss_device *dssdev; 71 + struct spi_device *spidev; 72 + struct backlight_device *bldev; 73 + 74 + int blizzard_ver; 75 + } s_drv_data; 76 + 77 + 78 + static inline 79 + struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev) 80 + { 81 + return dssdev->data; 82 + } 83 + 84 + static inline 85 + struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev) 86 + { 87 + return &s_drv_data; 88 + } 89 + 90 + 91 + static inline void blizzard_cmd(u8 cmd) 92 + { 93 + omap_rfbi_write_command(&cmd, 1); 94 + } 95 + 96 + static inline void blizzard_write(u8 cmd, const u8 *buf, int len) 97 + { 98 + omap_rfbi_write_command(&cmd, 1); 99 + omap_rfbi_write_data(buf, len); 100 + } 101 + 102 + static inline void blizzard_read(u8 cmd, u8 *buf, int len) 103 + { 104 + omap_rfbi_write_command(&cmd, 1); 105 + omap_rfbi_read_data(buf, len); 106 + } 107 + 108 + static u8 blizzard_read_reg(u8 cmd) 109 + { 110 + u8 data; 111 + blizzard_read(cmd, &data, 1); 112 + return data; 113 + } 114 + 115 + static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, 116 + int x, int y, int w, int h) 117 + { 118 + struct panel_drv_data *ddata = get_drv_data(dssdev); 119 + u8 tmp[18]; 120 + int x_end, y_end; 121 + 122 + x_end = x + w - 1; 123 + y_end = y + h - 1; 124 + 125 + tmp[0] = x; 126 + tmp[1] = x >> 8; 127 + tmp[2] = y; 128 + tmp[3] = y >> 8; 129 + tmp[4] = x_end; 130 + tmp[5] = x_end >> 8; 131 + tmp[6] = y_end; 132 + tmp[7] = y_end >> 8; 133 + 134 + /* scaling? */ 135 + tmp[8] = x; 136 + tmp[9] = x >> 8; 137 + tmp[10] = y; 138 + tmp[11] = y >> 8; 139 + tmp[12] = x_end; 140 + tmp[13] = x_end >> 8; 141 + tmp[14] = y_end; 142 + tmp[15] = y_end >> 8; 143 + 144 + tmp[16] = BLIZZARD_COLOR_RGB565; 145 + 146 + if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745) 147 + tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; 148 + else 149 + tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ? 150 + BLIZZARD_SRC_WRITE_LCD : 151 + BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; 152 + 153 + omap_rfbi_configure(dssdev, 16, 8); 154 + 155 + blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); 156 + 157 + omap_rfbi_configure(dssdev, 16, 16); 158 + } 159 + 160 + static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, 161 + int wlen, u8 *rbuf, int rlen) 162 + { 163 + struct spi_message m; 164 + struct spi_transfer *x, xfer[4]; 165 + u16 w; 166 + int r; 167 + 168 + spi_message_init(&m); 169 + 170 + memset(xfer, 0, sizeof(xfer)); 171 + x = &xfer[0]; 172 + 173 + cmd &= 0xff; 174 + x->tx_buf = &cmd; 175 + x->bits_per_word = 9; 176 + x->len = 2; 177 + spi_message_add_tail(x, &m); 178 + 179 + if (wlen) { 180 + x++; 181 + x->tx_buf = wbuf; 182 + x->len = wlen; 183 + x->bits_per_word = 9; 184 + spi_message_add_tail(x, &m); 185 + } 186 + 187 + if (rlen) { 188 + x++; 189 + x->rx_buf = &w; 190 + x->len = 1; 191 + spi_message_add_tail(x, &m); 192 + 193 + if (rlen > 1) { 194 + /* Arrange for the extra clock before the first 195 + * data bit. 196 + */ 197 + x->bits_per_word = 9; 198 + x->len = 2; 199 + 200 + x++; 201 + x->rx_buf = &rbuf[1]; 202 + x->len = rlen - 1; 203 + spi_message_add_tail(x, &m); 204 + } 205 + } 206 + 207 + r = spi_sync(spi, &m); 208 + if (r < 0) 209 + dev_dbg(&spi->dev, "spi_sync %d\n", r); 210 + 211 + if (rlen) 212 + rbuf[0] = w & 0xff; 213 + } 214 + 215 + static inline void mipid_cmd(struct spi_device *spi, int cmd) 216 + { 217 + mipid_transfer(spi, cmd, NULL, 0, NULL, 0); 218 + } 219 + 220 + static inline void mipid_write(struct spi_device *spi, 221 + int reg, const u8 *buf, int len) 222 + { 223 + mipid_transfer(spi, reg, buf, len, NULL, 0); 224 + } 225 + 226 + static inline void mipid_read(struct spi_device *spi, 227 + int reg, u8 *buf, int len) 228 + { 229 + mipid_transfer(spi, reg, NULL, 0, buf, len); 230 + } 231 + 232 + static void set_data_lines(struct spi_device *spi, int data_lines) 233 + { 234 + u16 par; 235 + 236 + switch (data_lines) { 237 + case 16: 238 + par = 0x150; 239 + break; 240 + case 18: 241 + par = 0x160; 242 + break; 243 + case 24: 244 + par = 0x170; 245 + break; 246 + } 247 + 248 + mipid_write(spi, 0x3a, (u8 *)&par, 2); 249 + } 250 + 251 + static void send_init_string(struct spi_device *spi) 252 + { 253 + u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; 254 + mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar)); 255 + } 256 + 257 + static void send_display_on(struct spi_device *spi) 258 + { 259 + mipid_cmd(spi, MIPID_CMD_DISP_ON); 260 + } 261 + 262 + static void send_display_off(struct spi_device *spi) 263 + { 264 + mipid_cmd(spi, MIPID_CMD_DISP_OFF); 265 + } 266 + 267 + static void send_sleep_out(struct spi_device *spi) 268 + { 269 + mipid_cmd(spi, MIPID_CMD_SLEEP_OUT); 270 + msleep(120); 271 + } 272 + 273 + static void send_sleep_in(struct spi_device *spi) 274 + { 275 + mipid_cmd(spi, MIPID_CMD_SLEEP_IN); 276 + msleep(50); 277 + } 278 + 279 + static int n8x0_panel_power_on(struct omap_dss_device *dssdev) 280 + { 281 + int r; 282 + struct panel_n8x0_data *bdata = get_board_data(dssdev); 283 + struct panel_drv_data *ddata = get_drv_data(dssdev); 284 + struct spi_device *spi = ddata->spidev; 285 + u8 rev, conf; 286 + u8 display_id[3]; 287 + const char *panel_name; 288 + 289 + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 290 + return 0; 291 + 292 + gpio_direction_output(bdata->ctrl_pwrdown, 1); 293 + 294 + if (bdata->platform_enable) { 295 + r = bdata->platform_enable(dssdev); 296 + if (r) 297 + goto err_plat_en; 298 + } 299 + 300 + r = omapdss_rfbi_display_enable(dssdev); 301 + if (r) 302 + goto err_rfbi_en; 303 + 304 + rev = blizzard_read_reg(BLIZZARD_REV_CODE); 305 + conf = blizzard_read_reg(BLIZZARD_CONFIG); 306 + 307 + switch (rev & 0xfc) { 308 + case 0x9c: 309 + ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744; 310 + dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d " 311 + "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); 312 + break; 313 + case 0xa4: 314 + ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745; 315 + dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d " 316 + "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); 317 + break; 318 + default: 319 + dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev); 320 + r = -ENODEV; 321 + goto err_inv_chip; 322 + } 323 + 324 + /* panel */ 325 + 326 + gpio_direction_output(bdata->panel_reset, 1); 327 + 328 + mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3); 329 + dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n", 330 + display_id[0], display_id[1], display_id[2]); 331 + 332 + switch (display_id[0]) { 333 + case 0x45: 334 + panel_name = "lph8923"; 335 + break; 336 + case 0x83: 337 + panel_name = "ls041y3"; 338 + break; 339 + default: 340 + dev_err(&dssdev->dev, "invalid display ID 0x%x\n", 341 + display_id[0]); 342 + r = -ENODEV; 343 + goto err_inv_panel; 344 + } 345 + 346 + dev_info(&dssdev->dev, "%s rev %02x LCD detected\n", 347 + panel_name, display_id[1]); 348 + 349 + send_sleep_out(spi); 350 + send_init_string(spi); 351 + set_data_lines(spi, 24); 352 + send_display_on(spi); 353 + 354 + return 0; 355 + 356 + err_inv_panel: 357 + /* 358 + * HACK: we should turn off the panel here, but there is some problem 359 + * with the initialization sequence, and we fail to init the panel if we 360 + * have turned it off 361 + */ 362 + /* gpio_direction_output(bdata->panel_reset, 0); */ 363 + err_inv_chip: 364 + omapdss_rfbi_display_disable(dssdev); 365 + err_rfbi_en: 366 + if (bdata->platform_disable) 367 + bdata->platform_disable(dssdev); 368 + err_plat_en: 369 + gpio_direction_output(bdata->ctrl_pwrdown, 0); 370 + return r; 371 + } 372 + 373 + static void n8x0_panel_power_off(struct omap_dss_device *dssdev) 374 + { 375 + struct panel_n8x0_data *bdata = get_board_data(dssdev); 376 + struct panel_drv_data *ddata = get_drv_data(dssdev); 377 + struct spi_device *spi = ddata->spidev; 378 + 379 + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 380 + return; 381 + 382 + send_display_off(spi); 383 + send_sleep_in(spi); 384 + 385 + if (bdata->platform_disable) 386 + bdata->platform_disable(dssdev); 387 + 388 + /* 389 + * HACK: we should turn off the panel here, but there is some problem 390 + * with the initialization sequence, and we fail to init the panel if we 391 + * have turned it off 392 + */ 393 + /* gpio_direction_output(bdata->panel_reset, 0); */ 394 + gpio_direction_output(bdata->ctrl_pwrdown, 0); 395 + omapdss_rfbi_display_disable(dssdev); 396 + } 397 + 398 + static const struct rfbi_timings n8x0_panel_timings = { 399 + .cs_on_time = 0, 400 + 401 + .we_on_time = 9000, 402 + .we_off_time = 18000, 403 + .we_cycle_time = 36000, 404 + 405 + .re_on_time = 9000, 406 + .re_off_time = 27000, 407 + .re_cycle_time = 36000, 408 + 409 + .access_time = 27000, 410 + .cs_off_time = 36000, 411 + 412 + .cs_pulse_width = 0, 413 + }; 414 + 415 + static int n8x0_bl_update_status(struct backlight_device *dev) 416 + { 417 + struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 418 + struct panel_n8x0_data *bdata = get_board_data(dssdev); 419 + struct panel_drv_data *ddata = get_drv_data(dssdev); 420 + int r; 421 + int level; 422 + 423 + mutex_lock(&ddata->lock); 424 + 425 + if (dev->props.fb_blank == FB_BLANK_UNBLANK && 426 + dev->props.power == FB_BLANK_UNBLANK) 427 + level = dev->props.brightness; 428 + else 429 + level = 0; 430 + 431 + dev_dbg(&dssdev->dev, "update brightness to %d\n", level); 432 + 433 + if (!bdata->set_backlight) 434 + r = -EINVAL; 435 + else 436 + r = bdata->set_backlight(dssdev, level); 437 + 438 + mutex_unlock(&ddata->lock); 439 + 440 + return r; 441 + } 442 + 443 + static int n8x0_bl_get_intensity(struct backlight_device *dev) 444 + { 445 + if (dev->props.fb_blank == FB_BLANK_UNBLANK && 446 + dev->props.power == FB_BLANK_UNBLANK) 447 + return dev->props.brightness; 448 + 449 + return 0; 450 + } 451 + 452 + static const struct backlight_ops n8x0_bl_ops = { 453 + .get_brightness = n8x0_bl_get_intensity, 454 + .update_status = n8x0_bl_update_status, 455 + }; 456 + 457 + static int n8x0_panel_probe(struct omap_dss_device *dssdev) 458 + { 459 + struct panel_n8x0_data *bdata = get_board_data(dssdev); 460 + struct panel_drv_data *ddata; 461 + struct backlight_device *bldev; 462 + struct backlight_properties props; 463 + int r; 464 + 465 + dev_dbg(&dssdev->dev, "probe\n"); 466 + 467 + if (!bdata) 468 + return -EINVAL; 469 + 470 + s_drv_data.dssdev = dssdev; 471 + 472 + ddata = &s_drv_data; 473 + 474 + mutex_init(&ddata->lock); 475 + 476 + dssdev->panel.config = OMAP_DSS_LCD_TFT; 477 + dssdev->panel.timings.x_res = 800; 478 + dssdev->panel.timings.y_res = 480; 479 + dssdev->ctrl.pixel_size = 16; 480 + dssdev->ctrl.rfbi_timings = n8x0_panel_timings; 481 + 482 + memset(&props, 0, sizeof(props)); 483 + props.max_brightness = 127; 484 + props.type = BACKLIGHT_PLATFORM; 485 + bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, 486 + dssdev, &n8x0_bl_ops, &props); 487 + if (IS_ERR(bldev)) { 488 + r = PTR_ERR(bldev); 489 + dev_err(&dssdev->dev, "register backlight failed\n"); 490 + return r; 491 + } 492 + 493 + ddata->bldev = bldev; 494 + 495 + bldev->props.fb_blank = FB_BLANK_UNBLANK; 496 + bldev->props.power = FB_BLANK_UNBLANK; 497 + bldev->props.brightness = 127; 498 + 499 + n8x0_bl_update_status(bldev); 500 + 501 + return 0; 502 + } 503 + 504 + static void n8x0_panel_remove(struct omap_dss_device *dssdev) 505 + { 506 + struct panel_drv_data *ddata = get_drv_data(dssdev); 507 + struct backlight_device *bldev; 508 + 509 + dev_dbg(&dssdev->dev, "remove\n"); 510 + 511 + bldev = ddata->bldev; 512 + bldev->props.power = FB_BLANK_POWERDOWN; 513 + n8x0_bl_update_status(bldev); 514 + backlight_device_unregister(bldev); 515 + 516 + dev_set_drvdata(&dssdev->dev, NULL); 517 + } 518 + 519 + static int n8x0_panel_enable(struct omap_dss_device *dssdev) 520 + { 521 + struct panel_drv_data *ddata = get_drv_data(dssdev); 522 + int r; 523 + 524 + dev_dbg(&dssdev->dev, "enable\n"); 525 + 526 + mutex_lock(&ddata->lock); 527 + 528 + rfbi_bus_lock(); 529 + 530 + r = n8x0_panel_power_on(dssdev); 531 + 532 + rfbi_bus_unlock(); 533 + 534 + if (r) { 535 + mutex_unlock(&ddata->lock); 536 + return r; 537 + } 538 + 539 + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 540 + 541 + mutex_unlock(&ddata->lock); 542 + 543 + return 0; 544 + } 545 + 546 + static void n8x0_panel_disable(struct omap_dss_device *dssdev) 547 + { 548 + struct panel_drv_data *ddata = get_drv_data(dssdev); 549 + 550 + dev_dbg(&dssdev->dev, "disable\n"); 551 + 552 + mutex_lock(&ddata->lock); 553 + 554 + rfbi_bus_lock(); 555 + 556 + n8x0_panel_power_off(dssdev); 557 + 558 + rfbi_bus_unlock(); 559 + 560 + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 561 + 562 + mutex_unlock(&ddata->lock); 563 + } 564 + 565 + static int n8x0_panel_suspend(struct omap_dss_device *dssdev) 566 + { 567 + struct panel_drv_data *ddata = get_drv_data(dssdev); 568 + 569 + dev_dbg(&dssdev->dev, "suspend\n"); 570 + 571 + mutex_lock(&ddata->lock); 572 + 573 + rfbi_bus_lock(); 574 + 575 + n8x0_panel_power_off(dssdev); 576 + 577 + rfbi_bus_unlock(); 578 + 579 + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 580 + 581 + mutex_unlock(&ddata->lock); 582 + 583 + return 0; 584 + } 585 + 586 + static int n8x0_panel_resume(struct omap_dss_device *dssdev) 587 + { 588 + struct panel_drv_data *ddata = get_drv_data(dssdev); 589 + int r; 590 + 591 + dev_dbg(&dssdev->dev, "resume\n"); 592 + 593 + mutex_lock(&ddata->lock); 594 + 595 + rfbi_bus_lock(); 596 + 597 + r = n8x0_panel_power_on(dssdev); 598 + 599 + rfbi_bus_unlock(); 600 + 601 + if (r) { 602 + mutex_unlock(&ddata->lock); 603 + return r; 604 + } 605 + 606 + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 607 + 608 + mutex_unlock(&ddata->lock); 609 + 610 + return 0; 611 + } 612 + 613 + static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, 614 + struct omap_video_timings *timings) 615 + { 616 + *timings = dssdev->panel.timings; 617 + } 618 + 619 + static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, 620 + u16 *xres, u16 *yres) 621 + { 622 + *xres = dssdev->panel.timings.x_res; 623 + *yres = dssdev->panel.timings.y_res; 624 + } 625 + 626 + static void update_done(void *data) 627 + { 628 + rfbi_bus_unlock(); 629 + } 630 + 631 + static int n8x0_panel_update(struct omap_dss_device *dssdev, 632 + u16 x, u16 y, u16 w, u16 h) 633 + { 634 + struct panel_drv_data *ddata = get_drv_data(dssdev); 635 + 636 + dev_dbg(&dssdev->dev, "update\n"); 637 + 638 + mutex_lock(&ddata->lock); 639 + rfbi_bus_lock(); 640 + 641 + omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h); 642 + 643 + blizzard_ctrl_setup_update(dssdev, x, y, w, h); 644 + 645 + omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); 646 + 647 + mutex_unlock(&ddata->lock); 648 + 649 + return 0; 650 + } 651 + 652 + static int n8x0_panel_sync(struct omap_dss_device *dssdev) 653 + { 654 + struct panel_drv_data *ddata = get_drv_data(dssdev); 655 + 656 + dev_dbg(&dssdev->dev, "sync\n"); 657 + 658 + mutex_lock(&ddata->lock); 659 + rfbi_bus_lock(); 660 + rfbi_bus_unlock(); 661 + mutex_unlock(&ddata->lock); 662 + 663 + return 0; 664 + } 665 + 666 + static struct omap_dss_driver n8x0_panel_driver = { 667 + .probe = n8x0_panel_probe, 668 + .remove = n8x0_panel_remove, 669 + 670 + .enable = n8x0_panel_enable, 671 + .disable = n8x0_panel_disable, 672 + .suspend = n8x0_panel_suspend, 673 + .resume = n8x0_panel_resume, 674 + 675 + .update = n8x0_panel_update, 676 + .sync = n8x0_panel_sync, 677 + 678 + .get_resolution = n8x0_panel_get_resolution, 679 + .get_recommended_bpp = omapdss_default_get_recommended_bpp, 680 + 681 + .get_timings = n8x0_panel_get_timings, 682 + 683 + .driver = { 684 + .name = "n8x0_panel", 685 + .owner = THIS_MODULE, 686 + }, 687 + }; 688 + 689 + /* PANEL */ 690 + 691 + static int mipid_spi_probe(struct spi_device *spi) 692 + { 693 + dev_dbg(&spi->dev, "mipid_spi_probe\n"); 694 + 695 + spi->mode = SPI_MODE_0; 696 + 697 + s_drv_data.spidev = spi; 698 + 699 + return 0; 700 + } 701 + 702 + static int mipid_spi_remove(struct spi_device *spi) 703 + { 704 + dev_dbg(&spi->dev, "mipid_spi_remove\n"); 705 + return 0; 706 + } 707 + 708 + static struct spi_driver mipid_spi_driver = { 709 + .driver = { 710 + .name = "lcd_mipid", 711 + .bus = &spi_bus_type, 712 + .owner = THIS_MODULE, 713 + }, 714 + .probe = mipid_spi_probe, 715 + .remove = __devexit_p(mipid_spi_remove), 716 + }; 717 + 718 + static int __init n8x0_panel_drv_init(void) 719 + { 720 + int r; 721 + 722 + r = spi_register_driver(&mipid_spi_driver); 723 + if (r) { 724 + pr_err("n8x0_panel: spi driver registration failed\n"); 725 + return r; 726 + } 727 + 728 + r = omap_dss_register_driver(&n8x0_panel_driver); 729 + if (r) { 730 + pr_err("n8x0_panel: dss driver registration failed\n"); 731 + spi_unregister_driver(&mipid_spi_driver); 732 + return r; 733 + } 734 + 735 + return 0; 736 + } 737 + 738 + static void __exit n8x0_panel_drv_exit(void) 739 + { 740 + spi_unregister_driver(&mipid_spi_driver); 741 + 742 + omap_dss_unregister_driver(&n8x0_panel_driver); 743 + } 744 + 745 + module_init(n8x0_panel_drv_init); 746 + module_exit(n8x0_panel_drv_exit); 747 + MODULE_LICENSE("GPL");
+15
include/video/omap-panel-n8x0.h
··· 1 + #ifndef __OMAP_PANEL_N8X0_H 2 + #define __OMAP_PANEL_N8X0_H 3 + 4 + struct omap_dss_device; 5 + 6 + struct panel_n8x0_data { 7 + int (*platform_enable)(struct omap_dss_device *dssdev); 8 + void (*platform_disable)(struct omap_dss_device *dssdev); 9 + int panel_reset; 10 + int ctrl_pwrdown; 11 + 12 + int (*set_backlight)(struct omap_dss_device *dssdev, int level); 13 + }; 14 + 15 + #endif