1/* 2 * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02 3 * 4 * Copyright 2008-2009 Analog Devices Inc. 5 * Licensed under the GPL-2 or later. 6 */ 7 8#define DRIVER_NAME "bfin-lq035q1" 9#define pr_fmt(fmt) DRIVER_NAME ": " fmt 10 11#include <linux/module.h> 12#include <linux/kernel.h> 13#include <linux/errno.h> 14#include <linux/string.h> 15#include <linux/fb.h> 16#include <linux/gpio.h> 17#include <linux/slab.h> 18#include <linux/init.h> 19#include <linux/types.h> 20#include <linux/interrupt.h> 21#include <linux/device.h> 22#include <linux/backlight.h> 23#include <linux/lcd.h> 24#include <linux/dma-mapping.h> 25#include <linux/platform_device.h> 26#include <linux/spi/spi.h> 27 28#include <asm/blackfin.h> 29#include <asm/irq.h> 30#include <asm/dma.h> 31#include <asm/portmux.h> 32#include <asm/gptimers.h> 33 34#include <asm/bfin-lq035q1.h> 35 36#if defined(BF533_FAMILY) || defined(BF538_FAMILY) 37#define TIMER_HSYNC_id TIMER1_id 38#define TIMER_HSYNCbit TIMER1bit 39#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN1 40#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1 41#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF1 42 43#define TIMER_VSYNC_id TIMER2_id 44#define TIMER_VSYNCbit TIMER2bit 45#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN2 46#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL2 47#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF2 48#else 49#define TIMER_HSYNC_id TIMER0_id 50#define TIMER_HSYNCbit TIMER0bit 51#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN0 52#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL0 53#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF0 54 55#define TIMER_VSYNC_id TIMER1_id 56#define TIMER_VSYNCbit TIMER1bit 57#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN1 58#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1 59#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF1 60#endif 61 62#define LCD_X_RES 320 /* Horizontal Resolution */ 63#define LCD_Y_RES 240 /* Vertical Resolution */ 64#define DMA_BUS_SIZE 16 65#define U_LINE 4 /* Blanking Lines */ 66 67 68/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD) 69 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165 70 */ 71 72 73#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 74 75#define PPI_TX_MODE 0x2 76#define PPI_XFER_TYPE_11 0xC 77#define PPI_PORT_CFG_01 0x10 78#define PPI_POLS_1 0x8000 79 80#define LQ035_INDEX 0x74 81#define LQ035_DATA 0x76 82 83#define LQ035_DRIVER_OUTPUT_CTL 0x1 84#define LQ035_SHUT_CTL 0x11 85 86#define LQ035_DRIVER_OUTPUT_MASK (LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV) 87#define LQ035_DRIVER_OUTPUT_DEFAULT (0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK) 88 89#define LQ035_SHUT (1 << 0) /* Shutdown */ 90#define LQ035_ON (0 << 0) /* Shutdown */ 91 92struct bfin_lq035q1fb_info { 93 struct fb_info *fb; 94 struct device *dev; 95 struct spi_driver spidrv; 96 struct bfin_lq035q1fb_disp_info *disp_info; 97 unsigned char *fb_buffer; /* RGB Buffer */ 98 dma_addr_t dma_handle; 99 int lq035_open_cnt; 100 int irq; 101 spinlock_t lock; /* lock */ 102 u32 pseudo_pal[16]; 103 104 u32 lcd_bpp; 105 u32 h_actpix; 106 u32 h_period; 107 u32 h_pulse; 108 u32 h_start; 109 u32 v_lines; 110 u32 v_pulse; 111 u32 v_period; 112}; 113 114static int nocursor; 115module_param(nocursor, int, 0644); 116MODULE_PARM_DESC(nocursor, "cursor enable/disable"); 117 118struct spi_control { 119 unsigned short mode; 120}; 121 122static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value) 123{ 124 int ret; 125 u8 regs[3] = { LQ035_INDEX, 0, 0 }; 126 u8 dat[3] = { LQ035_DATA, 0, 0 }; 127 128 if (!spi) 129 return -ENODEV; 130 131 regs[2] = reg; 132 dat[1] = value >> 8; 133 dat[2] = value & 0xFF; 134 135 ret = spi_write(spi, regs, ARRAY_SIZE(regs)); 136 ret |= spi_write(spi, dat, ARRAY_SIZE(dat)); 137 return ret; 138} 139 140static int lq035q1_spidev_probe(struct spi_device *spi) 141{ 142 int ret; 143 struct spi_control *ctl; 144 struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver, 145 struct bfin_lq035q1fb_info, 146 spidrv.driver); 147 148 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 149 150 if (!ctl) 151 return -ENOMEM; 152 153 ctl->mode = (info->disp_info->mode & 154 LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT; 155 156 ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); 157 ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); 158 if (ret) { 159 kfree(ctl); 160 return ret; 161 } 162 163 spi_set_drvdata(spi, ctl); 164 165 return 0; 166} 167 168static int lq035q1_spidev_remove(struct spi_device *spi) 169{ 170 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); 171} 172 173#ifdef CONFIG_PM_SLEEP 174static int lq035q1_spidev_suspend(struct device *dev) 175{ 176 struct spi_device *spi = to_spi_device(dev); 177 178 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); 179} 180 181static int lq035q1_spidev_resume(struct device *dev) 182{ 183 struct spi_device *spi = to_spi_device(dev); 184 struct spi_control *ctl = spi_get_drvdata(spi); 185 int ret; 186 187 ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); 188 if (ret) 189 return ret; 190 191 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); 192} 193 194static SIMPLE_DEV_PM_OPS(lq035q1_spidev_pm_ops, lq035q1_spidev_suspend, 195 lq035q1_spidev_resume); 196#define LQ035Q1_SPIDEV_PM_OPS (&lq035q1_spidev_pm_ops) 197 198#else 199#define LQ035Q1_SPIDEV_PM_OPS NULL 200#endif 201 202/* Power down all displays on reboot, poweroff or halt */ 203static void lq035q1_spidev_shutdown(struct spi_device *spi) 204{ 205 lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); 206} 207 208static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg) 209{ 210 if (info->disp_info->use_bl) 211 gpio_set_value(info->disp_info->gpio_bl, arg); 212 213 return 0; 214} 215 216static int bfin_lq035q1_calc_timing(struct bfin_lq035q1fb_info *fbi) 217{ 218 unsigned long clocks_per_pix, cpld_pipeline_delay_cor; 219 220 /* 221 * Interface 16/18-bit TFT over an 8-bit wide PPI using a small 222 * Programmable Logic Device (CPLD) 223 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165 224 */ 225 226 switch (fbi->disp_info->ppi_mode) { 227 case USE_RGB565_16_BIT_PPI: 228 fbi->lcd_bpp = 16; 229 clocks_per_pix = 1; 230 cpld_pipeline_delay_cor = 0; 231 break; 232 case USE_RGB565_8_BIT_PPI: 233 fbi->lcd_bpp = 16; 234 clocks_per_pix = 2; 235 cpld_pipeline_delay_cor = 3; 236 break; 237 case USE_RGB888_8_BIT_PPI: 238 fbi->lcd_bpp = 24; 239 clocks_per_pix = 3; 240 cpld_pipeline_delay_cor = 5; 241 break; 242 default: 243 return -EINVAL; 244 } 245 246 /* 247 * HS and VS timing parameters (all in number of PPI clk ticks) 248 */ 249 250 fbi->h_actpix = (LCD_X_RES * clocks_per_pix); /* active horizontal pixel */ 251 fbi->h_period = (336 * clocks_per_pix); /* HS period */ 252 fbi->h_pulse = (2 * clocks_per_pix); /* HS pulse width */ 253 fbi->h_start = (7 * clocks_per_pix + cpld_pipeline_delay_cor); /* first valid pixel */ 254 255 fbi->v_lines = (LCD_Y_RES + U_LINE); /* total vertical lines */ 256 fbi->v_pulse = (2 * clocks_per_pix); /* VS pulse width (1-5 H_PERIODs) */ 257 fbi->v_period = (fbi->h_period * fbi->v_lines); /* VS period */ 258 259 return 0; 260} 261 262static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi) 263{ 264 unsigned ppi_pmode; 265 266 if (fbi->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI) 267 ppi_pmode = DLEN_16; 268 else 269 ppi_pmode = (DLEN_8 | PACK_EN); 270 271 bfin_write_PPI_DELAY(fbi->h_start); 272 bfin_write_PPI_COUNT(fbi->h_actpix - 1); 273 bfin_write_PPI_FRAME(fbi->v_lines); 274 275 bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */ 276 PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */ 277 PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */ 278 ppi_pmode | /* 8/16 bit data length / PACK_EN? */ 279 PPI_POLS_1); /* faling edge syncs POLS */ 280} 281 282static inline void bfin_lq035q1_disable_ppi(void) 283{ 284 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); 285} 286 287static inline void bfin_lq035q1_enable_ppi(void) 288{ 289 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); 290} 291 292static void bfin_lq035q1_start_timers(void) 293{ 294 enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit); 295} 296 297static void bfin_lq035q1_stop_timers(void) 298{ 299 disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit); 300 301 set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN | 302 TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL | 303 TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF); 304 305} 306 307static void bfin_lq035q1_init_timers(struct bfin_lq035q1fb_info *fbi) 308{ 309 310 bfin_lq035q1_stop_timers(); 311 312 set_gptimer_period(TIMER_HSYNC_id, fbi->h_period); 313 set_gptimer_pwidth(TIMER_HSYNC_id, fbi->h_pulse); 314 set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | 315 TIMER_TIN_SEL | TIMER_CLK_SEL| 316 TIMER_EMU_RUN); 317 318 set_gptimer_period(TIMER_VSYNC_id, fbi->v_period); 319 set_gptimer_pwidth(TIMER_VSYNC_id, fbi->v_pulse); 320 set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | 321 TIMER_TIN_SEL | TIMER_CLK_SEL | 322 TIMER_EMU_RUN); 323 324} 325 326static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi) 327{ 328 329 330 set_dma_config(CH_PPI, 331 set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, 332 INTR_DISABLE, DIMENSION_2D, 333 DATA_SIZE_16, 334 DMA_NOSYNC_KEEP_DMA_BUF)); 335 set_dma_x_count(CH_PPI, (LCD_X_RES * fbi->lcd_bpp) / DMA_BUS_SIZE); 336 set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8); 337 set_dma_y_count(CH_PPI, fbi->v_lines); 338 339 set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8); 340 set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer); 341 342} 343 344static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 345 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, 346 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, 347 P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, 348 P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, 349 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, 350 P_PPI0_D15, 0}; 351 352static const u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 353 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, 354 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, 355 P_PPI0_D6, P_PPI0_D7, 0}; 356 357static inline void bfin_lq035q1_free_ports(unsigned ppi16) 358{ 359 if (ppi16) 360 peripheral_free_list(ppi0_req_16); 361 else 362 peripheral_free_list(ppi0_req_8); 363 364 if (ANOMALY_05000400) 365 gpio_free(P_IDENT(P_PPI0_FS3)); 366} 367 368static int bfin_lq035q1_request_ports(struct platform_device *pdev, 369 unsigned ppi16) 370{ 371 int ret; 372 /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode: 373 * Drive PPI_FS3 Low 374 */ 375 if (ANOMALY_05000400) { 376 int ret = gpio_request_one(P_IDENT(P_PPI0_FS3), 377 GPIOF_OUT_INIT_LOW, "PPI_FS3"); 378 if (ret) 379 return ret; 380 } 381 382 if (ppi16) 383 ret = peripheral_request_list(ppi0_req_16, DRIVER_NAME); 384 else 385 ret = peripheral_request_list(ppi0_req_8, DRIVER_NAME); 386 387 if (ret) { 388 dev_err(&pdev->dev, "requesting peripherals failed\n"); 389 return -EFAULT; 390 } 391 392 return 0; 393} 394 395static int bfin_lq035q1_fb_open(struct fb_info *info, int user) 396{ 397 struct bfin_lq035q1fb_info *fbi = info->par; 398 399 spin_lock(&fbi->lock); 400 fbi->lq035_open_cnt++; 401 402 if (fbi->lq035_open_cnt <= 1) { 403 404 bfin_lq035q1_disable_ppi(); 405 SSYNC(); 406 407 bfin_lq035q1_config_dma(fbi); 408 bfin_lq035q1_config_ppi(fbi); 409 bfin_lq035q1_init_timers(fbi); 410 411 /* start dma */ 412 enable_dma(CH_PPI); 413 bfin_lq035q1_enable_ppi(); 414 bfin_lq035q1_start_timers(); 415 lq035q1_backlight(fbi, 1); 416 } 417 418 spin_unlock(&fbi->lock); 419 420 return 0; 421} 422 423static int bfin_lq035q1_fb_release(struct fb_info *info, int user) 424{ 425 struct bfin_lq035q1fb_info *fbi = info->par; 426 427 spin_lock(&fbi->lock); 428 429 fbi->lq035_open_cnt--; 430 431 if (fbi->lq035_open_cnt <= 0) { 432 lq035q1_backlight(fbi, 0); 433 bfin_lq035q1_disable_ppi(); 434 SSYNC(); 435 disable_dma(CH_PPI); 436 bfin_lq035q1_stop_timers(); 437 } 438 439 spin_unlock(&fbi->lock); 440 441 return 0; 442} 443 444static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var, 445 struct fb_info *info) 446{ 447 struct bfin_lq035q1fb_info *fbi = info->par; 448 449 if (var->bits_per_pixel == fbi->lcd_bpp) { 450 var->red.offset = info->var.red.offset; 451 var->green.offset = info->var.green.offset; 452 var->blue.offset = info->var.blue.offset; 453 var->red.length = info->var.red.length; 454 var->green.length = info->var.green.length; 455 var->blue.length = info->var.blue.length; 456 var->transp.offset = 0; 457 var->transp.length = 0; 458 var->transp.msb_right = 0; 459 var->red.msb_right = 0; 460 var->green.msb_right = 0; 461 var->blue.msb_right = 0; 462 } else { 463 pr_debug("%s: depth not supported: %u BPP\n", __func__, 464 var->bits_per_pixel); 465 return -EINVAL; 466 } 467 468 if (info->var.xres != var->xres || info->var.yres != var->yres || 469 info->var.xres_virtual != var->xres_virtual || 470 info->var.yres_virtual != var->yres_virtual) { 471 pr_debug("%s: Resolution not supported: X%u x Y%u \n", 472 __func__, var->xres, var->yres); 473 return -EINVAL; 474 } 475 476 /* 477 * Memory limit 478 */ 479 480 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { 481 pr_debug("%s: Memory Limit requested yres_virtual = %u\n", 482 __func__, var->yres_virtual); 483 return -ENOMEM; 484 } 485 486 487 return 0; 488} 489 490int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 491{ 492 if (nocursor) 493 return 0; 494 else 495 return -EINVAL; /* just to force soft_cursor() call */ 496} 497 498static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green, 499 u_int blue, u_int transp, 500 struct fb_info *info) 501{ 502 if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) 503 return -EINVAL; 504 505 if (info->var.grayscale) { 506 /* grayscale = 0.30*R + 0.59*G + 0.11*B */ 507 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 508 } 509 510 if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 511 512 u32 value; 513 /* Place color in the pseudopalette */ 514 if (regno > 16) 515 return -EINVAL; 516 517 red >>= (16 - info->var.red.length); 518 green >>= (16 - info->var.green.length); 519 blue >>= (16 - info->var.blue.length); 520 521 value = (red << info->var.red.offset) | 522 (green << info->var.green.offset) | 523 (blue << info->var.blue.offset); 524 value &= 0xFFFFFF; 525 526 ((u32 *) (info->pseudo_palette))[regno] = value; 527 528 } 529 530 return 0; 531} 532 533static struct fb_ops bfin_lq035q1_fb_ops = { 534 .owner = THIS_MODULE, 535 .fb_open = bfin_lq035q1_fb_open, 536 .fb_release = bfin_lq035q1_fb_release, 537 .fb_check_var = bfin_lq035q1_fb_check_var, 538 .fb_fillrect = cfb_fillrect, 539 .fb_copyarea = cfb_copyarea, 540 .fb_imageblit = cfb_imageblit, 541 .fb_cursor = bfin_lq035q1_fb_cursor, 542 .fb_setcolreg = bfin_lq035q1_fb_setcolreg, 543}; 544 545static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id) 546{ 547 /*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/ 548 549 u16 status = bfin_read_PPI_STATUS(); 550 bfin_write_PPI_STATUS(-1); 551 552 if (status) { 553 bfin_lq035q1_disable_ppi(); 554 disable_dma(CH_PPI); 555 556 /* start dma */ 557 enable_dma(CH_PPI); 558 bfin_lq035q1_enable_ppi(); 559 bfin_write_PPI_STATUS(-1); 560 } 561 562 return IRQ_HANDLED; 563} 564 565static int bfin_lq035q1_probe(struct platform_device *pdev) 566{ 567 struct bfin_lq035q1fb_info *info; 568 struct fb_info *fbinfo; 569 u32 active_video_mem_offset; 570 int ret; 571 572 ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI"); 573 if (ret < 0) { 574 dev_err(&pdev->dev, "PPI DMA unavailable\n"); 575 goto out1; 576 } 577 578 fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev); 579 if (!fbinfo) { 580 ret = -ENOMEM; 581 goto out2; 582 } 583 584 info = fbinfo->par; 585 info->fb = fbinfo; 586 info->dev = &pdev->dev; 587 spin_lock_init(&info->lock); 588 589 info->disp_info = pdev->dev.platform_data; 590 591 platform_set_drvdata(pdev, fbinfo); 592 593 ret = bfin_lq035q1_calc_timing(info); 594 if (ret < 0) { 595 dev_err(&pdev->dev, "Failed PPI Mode\n"); 596 goto out3; 597 } 598 599 strcpy(fbinfo->fix.id, DRIVER_NAME); 600 601 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; 602 fbinfo->fix.type_aux = 0; 603 fbinfo->fix.xpanstep = 0; 604 fbinfo->fix.ypanstep = 0; 605 fbinfo->fix.ywrapstep = 0; 606 fbinfo->fix.accel = FB_ACCEL_NONE; 607 fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; 608 609 fbinfo->var.nonstd = 0; 610 fbinfo->var.activate = FB_ACTIVATE_NOW; 611 fbinfo->var.height = -1; 612 fbinfo->var.width = -1; 613 fbinfo->var.accel_flags = 0; 614 fbinfo->var.vmode = FB_VMODE_NONINTERLACED; 615 616 fbinfo->var.xres = LCD_X_RES; 617 fbinfo->var.xres_virtual = LCD_X_RES; 618 fbinfo->var.yres = LCD_Y_RES; 619 fbinfo->var.yres_virtual = LCD_Y_RES; 620 fbinfo->var.bits_per_pixel = info->lcd_bpp; 621 622 if (info->disp_info->mode & LQ035_BGR) { 623 if (info->lcd_bpp == 24) { 624 fbinfo->var.red.offset = 0; 625 fbinfo->var.green.offset = 8; 626 fbinfo->var.blue.offset = 16; 627 } else { 628 fbinfo->var.red.offset = 0; 629 fbinfo->var.green.offset = 5; 630 fbinfo->var.blue.offset = 11; 631 } 632 } else { 633 if (info->lcd_bpp == 24) { 634 fbinfo->var.red.offset = 16; 635 fbinfo->var.green.offset = 8; 636 fbinfo->var.blue.offset = 0; 637 } else { 638 fbinfo->var.red.offset = 11; 639 fbinfo->var.green.offset = 5; 640 fbinfo->var.blue.offset = 0; 641 } 642 } 643 644 fbinfo->var.transp.offset = 0; 645 646 if (info->lcd_bpp == 24) { 647 fbinfo->var.red.length = 8; 648 fbinfo->var.green.length = 8; 649 fbinfo->var.blue.length = 8; 650 } else { 651 fbinfo->var.red.length = 5; 652 fbinfo->var.green.length = 6; 653 fbinfo->var.blue.length = 5; 654 } 655 656 fbinfo->var.transp.length = 0; 657 658 active_video_mem_offset = ((U_LINE / 2) * LCD_X_RES * (info->lcd_bpp / 8)); 659 660 fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * info->lcd_bpp / 8 661 + active_video_mem_offset; 662 663 fbinfo->fix.line_length = fbinfo->var.xres_virtual * 664 fbinfo->var.bits_per_pixel / 8; 665 666 667 fbinfo->fbops = &bfin_lq035q1_fb_ops; 668 fbinfo->flags = FBINFO_FLAG_DEFAULT; 669 670 info->fb_buffer = 671 dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, 672 GFP_KERNEL); 673 674 if (NULL == info->fb_buffer) { 675 dev_err(&pdev->dev, "couldn't allocate dma buffer\n"); 676 ret = -ENOMEM; 677 goto out3; 678 } 679 680 fbinfo->screen_base = (void *)info->fb_buffer + active_video_mem_offset; 681 fbinfo->fix.smem_start = (int)info->fb_buffer + active_video_mem_offset; 682 683 fbinfo->fbops = &bfin_lq035q1_fb_ops; 684 685 fbinfo->pseudo_palette = &info->pseudo_pal; 686 687 ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0); 688 if (ret < 0) { 689 dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n", 690 BFIN_LCD_NBR_PALETTE_ENTRIES); 691 goto out4; 692 } 693 694 ret = bfin_lq035q1_request_ports(pdev, 695 info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI); 696 if (ret) { 697 dev_err(&pdev->dev, "couldn't request gpio port\n"); 698 goto out6; 699 } 700 701 info->irq = platform_get_irq(pdev, 0); 702 if (info->irq < 0) { 703 ret = -EINVAL; 704 goto out7; 705 } 706 707 ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0, 708 DRIVER_NAME" PPI ERROR", info); 709 if (ret < 0) { 710 dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); 711 goto out7; 712 } 713 714 info->spidrv.driver.name = DRIVER_NAME"-spi"; 715 info->spidrv.probe = lq035q1_spidev_probe; 716 info->spidrv.remove = lq035q1_spidev_remove; 717 info->spidrv.shutdown = lq035q1_spidev_shutdown; 718 info->spidrv.driver.pm = LQ035Q1_SPIDEV_PM_OPS; 719 720 ret = spi_register_driver(&info->spidrv); 721 if (ret < 0) { 722 dev_err(&pdev->dev, "couldn't register SPI Interface\n"); 723 goto out8; 724 } 725 726 if (info->disp_info->use_bl) { 727 ret = gpio_request_one(info->disp_info->gpio_bl, 728 GPIOF_OUT_INIT_LOW, "LQ035 Backlight"); 729 730 if (ret) { 731 dev_err(&pdev->dev, "failed to request GPIO %d\n", 732 info->disp_info->gpio_bl); 733 goto out9; 734 } 735 } 736 737 ret = register_framebuffer(fbinfo); 738 if (ret < 0) { 739 dev_err(&pdev->dev, "unable to register framebuffer\n"); 740 goto out10; 741 } 742 743 dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n", 744 LCD_X_RES, LCD_Y_RES, info->lcd_bpp); 745 746 return 0; 747 748 out10: 749 if (info->disp_info->use_bl) 750 gpio_free(info->disp_info->gpio_bl); 751 out9: 752 spi_unregister_driver(&info->spidrv); 753 out8: 754 free_irq(info->irq, info); 755 out7: 756 bfin_lq035q1_free_ports(info->disp_info->ppi_mode == 757 USE_RGB565_16_BIT_PPI); 758 out6: 759 fb_dealloc_cmap(&fbinfo->cmap); 760 out4: 761 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 762 info->dma_handle); 763 out3: 764 framebuffer_release(fbinfo); 765 out2: 766 free_dma(CH_PPI); 767 out1: 768 769 return ret; 770} 771 772static int bfin_lq035q1_remove(struct platform_device *pdev) 773{ 774 struct fb_info *fbinfo = platform_get_drvdata(pdev); 775 struct bfin_lq035q1fb_info *info = fbinfo->par; 776 777 if (info->disp_info->use_bl) 778 gpio_free(info->disp_info->gpio_bl); 779 780 spi_unregister_driver(&info->spidrv); 781 782 unregister_framebuffer(fbinfo); 783 784 free_dma(CH_PPI); 785 free_irq(info->irq, info); 786 787 if (info->fb_buffer != NULL) 788 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 789 info->dma_handle); 790 791 fb_dealloc_cmap(&fbinfo->cmap); 792 793 bfin_lq035q1_free_ports(info->disp_info->ppi_mode == 794 USE_RGB565_16_BIT_PPI); 795 796 framebuffer_release(fbinfo); 797 798 dev_info(&pdev->dev, "unregistered LCD driver\n"); 799 800 return 0; 801} 802 803#ifdef CONFIG_PM 804static int bfin_lq035q1_suspend(struct device *dev) 805{ 806 struct fb_info *fbinfo = dev_get_drvdata(dev); 807 struct bfin_lq035q1fb_info *info = fbinfo->par; 808 809 if (info->lq035_open_cnt) { 810 lq035q1_backlight(info, 0); 811 bfin_lq035q1_disable_ppi(); 812 SSYNC(); 813 disable_dma(CH_PPI); 814 bfin_lq035q1_stop_timers(); 815 bfin_write_PPI_STATUS(-1); 816 } 817 818 return 0; 819} 820 821static int bfin_lq035q1_resume(struct device *dev) 822{ 823 struct fb_info *fbinfo = dev_get_drvdata(dev); 824 struct bfin_lq035q1fb_info *info = fbinfo->par; 825 826 if (info->lq035_open_cnt) { 827 bfin_lq035q1_disable_ppi(); 828 SSYNC(); 829 830 bfin_lq035q1_config_dma(info); 831 bfin_lq035q1_config_ppi(info); 832 bfin_lq035q1_init_timers(info); 833 834 /* start dma */ 835 enable_dma(CH_PPI); 836 bfin_lq035q1_enable_ppi(); 837 bfin_lq035q1_start_timers(); 838 lq035q1_backlight(info, 1); 839 } 840 841 return 0; 842} 843 844static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = { 845 .suspend = bfin_lq035q1_suspend, 846 .resume = bfin_lq035q1_resume, 847}; 848#endif 849 850static struct platform_driver bfin_lq035q1_driver = { 851 .probe = bfin_lq035q1_probe, 852 .remove = bfin_lq035q1_remove, 853 .driver = { 854 .name = DRIVER_NAME, 855#ifdef CONFIG_PM 856 .pm = &bfin_lq035q1_dev_pm_ops, 857#endif 858 }, 859}; 860 861module_platform_driver(bfin_lq035q1_driver); 862 863MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); 864MODULE_LICENSE("GPL"); 865