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

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc3 1025 lines 24 kB view raw
1/* 2 * Copyright (C) 2008-2009 MontaVista Software Inc. 3 * Copyright (C) 2008-2009 Texas Instruments Inc 4 * 5 * Based on the LCD driver for TI Avalanche processors written by 6 * Ajay Singh and Shalom Hai. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option)any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22#include <linux/module.h> 23#include <linux/kernel.h> 24#include <linux/fb.h> 25#include <linux/dma-mapping.h> 26#include <linux/device.h> 27#include <linux/platform_device.h> 28#include <linux/uaccess.h> 29#include <linux/interrupt.h> 30#include <linux/clk.h> 31#include <linux/cpufreq.h> 32#include <linux/console.h> 33#include <video/da8xx-fb.h> 34 35#define DRIVER_NAME "da8xx_lcdc" 36 37/* LCD Status Register */ 38#define LCD_END_OF_FRAME0 BIT(8) 39#define LCD_FIFO_UNDERFLOW BIT(5) 40#define LCD_SYNC_LOST BIT(2) 41 42/* LCD DMA Control Register */ 43#define LCD_DMA_BURST_SIZE(x) ((x) << 4) 44#define LCD_DMA_BURST_1 0x0 45#define LCD_DMA_BURST_2 0x1 46#define LCD_DMA_BURST_4 0x2 47#define LCD_DMA_BURST_8 0x3 48#define LCD_DMA_BURST_16 0x4 49#define LCD_END_OF_FRAME_INT_ENA BIT(2) 50#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) 51 52/* LCD Control Register */ 53#define LCD_CLK_DIVISOR(x) ((x) << 8) 54#define LCD_RASTER_MODE 0x01 55 56/* LCD Raster Control Register */ 57#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) 58#define PALETTE_AND_DATA 0x00 59#define PALETTE_ONLY 0x01 60 61#define LCD_MONO_8BIT_MODE BIT(9) 62#define LCD_RASTER_ORDER BIT(8) 63#define LCD_TFT_MODE BIT(7) 64#define LCD_UNDERFLOW_INT_ENA BIT(6) 65#define LCD_MONOCHROME_MODE BIT(1) 66#define LCD_RASTER_ENABLE BIT(0) 67#define LCD_TFT_ALT_ENABLE BIT(23) 68#define LCD_STN_565_ENABLE BIT(24) 69 70/* LCD Raster Timing 2 Register */ 71#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) 72#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) 73#define LCD_SYNC_CTRL BIT(25) 74#define LCD_SYNC_EDGE BIT(24) 75#define LCD_INVERT_PIXEL_CLOCK BIT(22) 76#define LCD_INVERT_LINE_CLOCK BIT(21) 77#define LCD_INVERT_FRAME_CLOCK BIT(20) 78 79/* LCD Block */ 80#define LCD_CTRL_REG 0x4 81#define LCD_STAT_REG 0x8 82#define LCD_RASTER_CTRL_REG 0x28 83#define LCD_RASTER_TIMING_0_REG 0x2C 84#define LCD_RASTER_TIMING_1_REG 0x30 85#define LCD_RASTER_TIMING_2_REG 0x34 86#define LCD_DMA_CTRL_REG 0x40 87#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 88#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 89 90#define WSI_TIMEOUT 50 91#define PALETTE_SIZE 256 92#define LEFT_MARGIN 64 93#define RIGHT_MARGIN 64 94#define UPPER_MARGIN 32 95#define LOWER_MARGIN 32 96 97static resource_size_t da8xx_fb_reg_base; 98static struct resource *lcdc_regs; 99 100static inline unsigned int lcdc_read(unsigned int addr) 101{ 102 return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); 103} 104 105static inline void lcdc_write(unsigned int val, unsigned int addr) 106{ 107 __raw_writel(val, da8xx_fb_reg_base + (addr)); 108} 109 110struct da8xx_fb_par { 111 resource_size_t p_palette_base; 112 unsigned char *v_palette_base; 113 struct clk *lcdc_clk; 114 int irq; 115 unsigned short pseudo_palette[16]; 116 unsigned int databuf_sz; 117 unsigned int palette_sz; 118 unsigned int pxl_clk; 119 int blank; 120#ifdef CONFIG_CPU_FREQ 121 struct notifier_block freq_transition; 122#endif 123 void (*panel_power_ctrl)(int); 124}; 125 126/* Variable Screen Information */ 127static struct fb_var_screeninfo da8xx_fb_var __devinitdata = { 128 .xoffset = 0, 129 .yoffset = 0, 130 .transp = {0, 0, 0}, 131 .nonstd = 0, 132 .activate = 0, 133 .height = -1, 134 .width = -1, 135 .pixclock = 46666, /* 46us - AUO display */ 136 .accel_flags = 0, 137 .left_margin = LEFT_MARGIN, 138 .right_margin = RIGHT_MARGIN, 139 .upper_margin = UPPER_MARGIN, 140 .lower_margin = LOWER_MARGIN, 141 .sync = 0, 142 .vmode = FB_VMODE_NONINTERLACED 143}; 144 145static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { 146 .id = "DA8xx FB Drv", 147 .type = FB_TYPE_PACKED_PIXELS, 148 .type_aux = 0, 149 .visual = FB_VISUAL_PSEUDOCOLOR, 150 .xpanstep = 1, 151 .ypanstep = 1, 152 .ywrapstep = 1, 153 .accel = FB_ACCEL_NONE 154}; 155 156struct da8xx_panel { 157 const char name[25]; /* Full name <vendor>_<model> */ 158 unsigned short width; 159 unsigned short height; 160 int hfp; /* Horizontal front porch */ 161 int hbp; /* Horizontal back porch */ 162 int hsw; /* Horizontal Sync Pulse Width */ 163 int vfp; /* Vertical front porch */ 164 int vbp; /* Vertical back porch */ 165 int vsw; /* Vertical Sync Pulse Width */ 166 unsigned int pxl_clk; /* Pixel clock */ 167 unsigned char invert_pxl_clk; /* Invert Pixel clock */ 168}; 169 170static struct da8xx_panel known_lcd_panels[] = { 171 /* Sharp LCD035Q3DG01 */ 172 [0] = { 173 .name = "Sharp_LCD035Q3DG01", 174 .width = 320, 175 .height = 240, 176 .hfp = 8, 177 .hbp = 6, 178 .hsw = 0, 179 .vfp = 2, 180 .vbp = 2, 181 .vsw = 0, 182 .pxl_clk = 4608000, 183 .invert_pxl_clk = 1, 184 }, 185 /* Sharp LK043T1DG01 */ 186 [1] = { 187 .name = "Sharp_LK043T1DG01", 188 .width = 480, 189 .height = 272, 190 .hfp = 2, 191 .hbp = 2, 192 .hsw = 41, 193 .vfp = 2, 194 .vbp = 2, 195 .vsw = 10, 196 .pxl_clk = 7833600, 197 .invert_pxl_clk = 0, 198 }, 199}; 200 201/* Enable the Raster Engine of the LCD Controller */ 202static inline void lcd_enable_raster(void) 203{ 204 u32 reg; 205 206 reg = lcdc_read(LCD_RASTER_CTRL_REG); 207 if (!(reg & LCD_RASTER_ENABLE)) 208 lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); 209} 210 211/* Disable the Raster Engine of the LCD Controller */ 212static inline void lcd_disable_raster(void) 213{ 214 u32 reg; 215 216 reg = lcdc_read(LCD_RASTER_CTRL_REG); 217 if (reg & LCD_RASTER_ENABLE) 218 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); 219} 220 221static void lcd_blit(int load_mode, struct da8xx_fb_par *par) 222{ 223 u32 tmp = par->p_palette_base + par->databuf_sz - 4; 224 u32 reg; 225 226 /* Update the databuf in the hw. */ 227 lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 228 lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); 229 230 /* Start the DMA. */ 231 reg = lcdc_read(LCD_RASTER_CTRL_REG); 232 reg &= ~(3 << 20); 233 if (load_mode == LOAD_DATA) 234 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA); 235 else if (load_mode == LOAD_PALETTE) 236 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); 237 238 lcdc_write(reg, LCD_RASTER_CTRL_REG); 239} 240 241/* Configure the Burst Size of DMA */ 242static int lcd_cfg_dma(int burst_size) 243{ 244 u32 reg; 245 246 reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; 247 switch (burst_size) { 248 case 1: 249 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); 250 break; 251 case 2: 252 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); 253 break; 254 case 4: 255 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); 256 break; 257 case 8: 258 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); 259 break; 260 case 16: 261 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); 262 break; 263 default: 264 return -EINVAL; 265 } 266 lcdc_write(reg, LCD_DMA_CTRL_REG); 267 268 return 0; 269} 270 271static void lcd_cfg_ac_bias(int period, int transitions_per_int) 272{ 273 u32 reg; 274 275 /* Set the AC Bias Period and Number of Transisitons per Interrupt */ 276 reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; 277 reg |= LCD_AC_BIAS_FREQUENCY(period) | 278 LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); 279 lcdc_write(reg, LCD_RASTER_TIMING_2_REG); 280} 281 282static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, 283 int front_porch) 284{ 285 u32 reg; 286 287 reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf; 288 reg |= ((back_porch & 0xff) << 24) 289 | ((front_porch & 0xff) << 16) 290 | ((pulse_width & 0x3f) << 10); 291 lcdc_write(reg, LCD_RASTER_TIMING_0_REG); 292} 293 294static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, 295 int front_porch) 296{ 297 u32 reg; 298 299 reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; 300 reg |= ((back_porch & 0xff) << 24) 301 | ((front_porch & 0xff) << 16) 302 | ((pulse_width & 0x3f) << 10); 303 lcdc_write(reg, LCD_RASTER_TIMING_1_REG); 304} 305 306static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) 307{ 308 u32 reg; 309 310 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | 311 LCD_MONO_8BIT_MODE | 312 LCD_MONOCHROME_MODE); 313 314 switch (cfg->p_disp_panel->panel_shade) { 315 case MONOCHROME: 316 reg |= LCD_MONOCHROME_MODE; 317 if (cfg->mono_8bit_mode) 318 reg |= LCD_MONO_8BIT_MODE; 319 break; 320 case COLOR_ACTIVE: 321 reg |= LCD_TFT_MODE; 322 if (cfg->tft_alt_mode) 323 reg |= LCD_TFT_ALT_ENABLE; 324 break; 325 326 case COLOR_PASSIVE: 327 if (cfg->stn_565_mode) 328 reg |= LCD_STN_565_ENABLE; 329 break; 330 331 default: 332 return -EINVAL; 333 } 334 335 /* enable additional interrupts here */ 336 reg |= LCD_UNDERFLOW_INT_ENA; 337 338 lcdc_write(reg, LCD_RASTER_CTRL_REG); 339 340 reg = lcdc_read(LCD_RASTER_TIMING_2_REG); 341 342 if (cfg->sync_ctrl) 343 reg |= LCD_SYNC_CTRL; 344 else 345 reg &= ~LCD_SYNC_CTRL; 346 347 if (cfg->sync_edge) 348 reg |= LCD_SYNC_EDGE; 349 else 350 reg &= ~LCD_SYNC_EDGE; 351 352 if (cfg->invert_line_clock) 353 reg |= LCD_INVERT_LINE_CLOCK; 354 else 355 reg &= ~LCD_INVERT_LINE_CLOCK; 356 357 if (cfg->invert_frm_clock) 358 reg |= LCD_INVERT_FRAME_CLOCK; 359 else 360 reg &= ~LCD_INVERT_FRAME_CLOCK; 361 362 lcdc_write(reg, LCD_RASTER_TIMING_2_REG); 363 364 return 0; 365} 366 367static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, 368 u32 bpp, u32 raster_order) 369{ 370 u32 bpl, reg; 371 372 /* Disable Dual Frame Buffer. */ 373 reg = lcdc_read(LCD_DMA_CTRL_REG); 374 lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE, 375 LCD_DMA_CTRL_REG); 376 /* Set the Panel Width */ 377 /* Pixels per line = (PPL + 1)*16 */ 378 /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ 379 width &= 0x3f0; 380 reg = lcdc_read(LCD_RASTER_TIMING_0_REG); 381 reg &= 0xfffffc00; 382 reg |= ((width >> 4) - 1) << 4; 383 lcdc_write(reg, LCD_RASTER_TIMING_0_REG); 384 385 /* Set the Panel Height */ 386 reg = lcdc_read(LCD_RASTER_TIMING_1_REG); 387 reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); 388 lcdc_write(reg, LCD_RASTER_TIMING_1_REG); 389 390 /* Set the Raster Order of the Frame Buffer */ 391 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); 392 if (raster_order) 393 reg |= LCD_RASTER_ORDER; 394 lcdc_write(reg, LCD_RASTER_CTRL_REG); 395 396 switch (bpp) { 397 case 1: 398 case 2: 399 case 4: 400 case 16: 401 par->palette_sz = 16 * 2; 402 break; 403 404 case 8: 405 par->palette_sz = 256 * 2; 406 break; 407 408 default: 409 return -EINVAL; 410 } 411 412 bpl = width * bpp / 8; 413 par->databuf_sz = height * bpl + par->palette_sz; 414 415 return 0; 416} 417 418static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, 419 unsigned blue, unsigned transp, 420 struct fb_info *info) 421{ 422 struct da8xx_fb_par *par = info->par; 423 unsigned short *palette = (unsigned short *)par->v_palette_base; 424 u_short pal; 425 426 if (regno > 255) 427 return 1; 428 429 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 430 return 1; 431 432 if (info->var.bits_per_pixel == 8) { 433 red >>= 4; 434 green >>= 8; 435 blue >>= 12; 436 437 pal = (red & 0x0f00); 438 pal |= (green & 0x00f0); 439 pal |= (blue & 0x000f); 440 441 palette[regno] = pal; 442 443 } else if ((info->var.bits_per_pixel == 16) && regno < 16) { 444 red >>= (16 - info->var.red.length); 445 red <<= info->var.red.offset; 446 447 green >>= (16 - info->var.green.length); 448 green <<= info->var.green.offset; 449 450 blue >>= (16 - info->var.blue.length); 451 blue <<= info->var.blue.offset; 452 453 par->pseudo_palette[regno] = red | green | blue; 454 455 palette[0] = 0x4000; 456 } 457 458 return 0; 459} 460 461static void lcd_reset(struct da8xx_fb_par *par) 462{ 463 /* Disable the Raster if previously Enabled */ 464 lcd_disable_raster(); 465 466 /* DMA has to be disabled */ 467 lcdc_write(0, LCD_DMA_CTRL_REG); 468 lcdc_write(0, LCD_RASTER_CTRL_REG); 469} 470 471static void lcd_calc_clk_divider(struct da8xx_fb_par *par) 472{ 473 unsigned int lcd_clk, div; 474 475 lcd_clk = clk_get_rate(par->lcdc_clk); 476 div = lcd_clk / par->pxl_clk; 477 478 /* Configure the LCD clock divisor. */ 479 lcdc_write(LCD_CLK_DIVISOR(div) | 480 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); 481} 482 483static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, 484 struct da8xx_panel *panel) 485{ 486 u32 bpp; 487 int ret = 0; 488 489 lcd_reset(par); 490 491 /* Calculate the divider */ 492 lcd_calc_clk_divider(par); 493 494 if (panel->invert_pxl_clk) 495 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | 496 LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); 497 else 498 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & 499 ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); 500 501 /* Configure the DMA burst size. */ 502 ret = lcd_cfg_dma(cfg->dma_burst_sz); 503 if (ret < 0) 504 return ret; 505 506 /* Configure the AC bias properties. */ 507 lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); 508 509 /* Configure the vertical and horizontal sync properties. */ 510 lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); 511 lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); 512 513 /* Configure for disply */ 514 ret = lcd_cfg_display(cfg); 515 if (ret < 0) 516 return ret; 517 518 if (QVGA != cfg->p_disp_panel->panel_type) 519 return -EINVAL; 520 521 if (cfg->bpp <= cfg->p_disp_panel->max_bpp && 522 cfg->bpp >= cfg->p_disp_panel->min_bpp) 523 bpp = cfg->bpp; 524 else 525 bpp = cfg->p_disp_panel->max_bpp; 526 if (bpp == 12) 527 bpp = 16; 528 ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, 529 (unsigned int)panel->height, bpp, 530 cfg->raster_order); 531 if (ret < 0) 532 return ret; 533 534 /* Configure FDD */ 535 lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | 536 (cfg->fdd << 12), LCD_RASTER_CTRL_REG); 537 538 return 0; 539} 540 541static irqreturn_t lcdc_irq_handler(int irq, void *arg) 542{ 543 u32 stat = lcdc_read(LCD_STAT_REG); 544 545 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 546 lcd_disable_raster(); 547 lcdc_write(stat, LCD_STAT_REG); 548 lcd_enable_raster(); 549 } else 550 lcdc_write(stat, LCD_STAT_REG); 551 552 return IRQ_HANDLED; 553} 554 555static int fb_check_var(struct fb_var_screeninfo *var, 556 struct fb_info *info) 557{ 558 int err = 0; 559 560 switch (var->bits_per_pixel) { 561 case 1: 562 case 8: 563 var->red.offset = 0; 564 var->red.length = 8; 565 var->green.offset = 0; 566 var->green.length = 8; 567 var->blue.offset = 0; 568 var->blue.length = 8; 569 var->transp.offset = 0; 570 var->transp.length = 0; 571 break; 572 case 4: 573 var->red.offset = 0; 574 var->red.length = 4; 575 var->green.offset = 0; 576 var->green.length = 4; 577 var->blue.offset = 0; 578 var->blue.length = 4; 579 var->transp.offset = 0; 580 var->transp.length = 0; 581 break; 582 case 16: /* RGB 565 */ 583 var->red.offset = 11; 584 var->red.length = 5; 585 var->green.offset = 5; 586 var->green.length = 6; 587 var->blue.offset = 0; 588 var->blue.length = 5; 589 var->transp.offset = 0; 590 var->transp.length = 0; 591 break; 592 default: 593 err = -EINVAL; 594 } 595 596 var->red.msb_right = 0; 597 var->green.msb_right = 0; 598 var->blue.msb_right = 0; 599 var->transp.msb_right = 0; 600 return err; 601} 602 603#ifdef CONFIG_CPU_FREQ 604static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, 605 unsigned long val, void *data) 606{ 607 struct da8xx_fb_par *par; 608 609 par = container_of(nb, struct da8xx_fb_par, freq_transition); 610 if (val == CPUFREQ_PRECHANGE) { 611 lcd_disable_raster(); 612 } else if (val == CPUFREQ_POSTCHANGE) { 613 lcd_calc_clk_divider(par); 614 lcd_enable_raster(); 615 } 616 617 return 0; 618} 619 620static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) 621{ 622 par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; 623 624 return cpufreq_register_notifier(&par->freq_transition, 625 CPUFREQ_TRANSITION_NOTIFIER); 626} 627 628static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) 629{ 630 cpufreq_unregister_notifier(&par->freq_transition, 631 CPUFREQ_TRANSITION_NOTIFIER); 632} 633#endif 634 635static int __devexit fb_remove(struct platform_device *dev) 636{ 637 struct fb_info *info = dev_get_drvdata(&dev->dev); 638 639 if (info) { 640 struct da8xx_fb_par *par = info->par; 641 642#ifdef CONFIG_CPU_FREQ 643 lcd_da8xx_cpufreq_deregister(par); 644#endif 645 if (par->panel_power_ctrl) 646 par->panel_power_ctrl(0); 647 648 lcd_disable_raster(); 649 lcdc_write(0, LCD_RASTER_CTRL_REG); 650 651 /* disable DMA */ 652 lcdc_write(0, LCD_DMA_CTRL_REG); 653 654 unregister_framebuffer(info); 655 fb_dealloc_cmap(&info->cmap); 656 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, 657 info->screen_base - PAGE_SIZE, 658 info->fix.smem_start); 659 free_irq(par->irq, par); 660 clk_disable(par->lcdc_clk); 661 clk_put(par->lcdc_clk); 662 framebuffer_release(info); 663 iounmap((void __iomem *)da8xx_fb_reg_base); 664 release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); 665 666 } 667 return 0; 668} 669 670static int fb_ioctl(struct fb_info *info, unsigned int cmd, 671 unsigned long arg) 672{ 673 struct lcd_sync_arg sync_arg; 674 675 switch (cmd) { 676 case FBIOGET_CONTRAST: 677 case FBIOPUT_CONTRAST: 678 case FBIGET_BRIGHTNESS: 679 case FBIPUT_BRIGHTNESS: 680 case FBIGET_COLOR: 681 case FBIPUT_COLOR: 682 return -ENOTTY; 683 case FBIPUT_HSYNC: 684 if (copy_from_user(&sync_arg, (char *)arg, 685 sizeof(struct lcd_sync_arg))) 686 return -EFAULT; 687 lcd_cfg_horizontal_sync(sync_arg.back_porch, 688 sync_arg.pulse_width, 689 sync_arg.front_porch); 690 break; 691 case FBIPUT_VSYNC: 692 if (copy_from_user(&sync_arg, (char *)arg, 693 sizeof(struct lcd_sync_arg))) 694 return -EFAULT; 695 lcd_cfg_vertical_sync(sync_arg.back_porch, 696 sync_arg.pulse_width, 697 sync_arg.front_porch); 698 break; 699 default: 700 return -EINVAL; 701 } 702 return 0; 703} 704 705static int cfb_blank(int blank, struct fb_info *info) 706{ 707 struct da8xx_fb_par *par = info->par; 708 int ret = 0; 709 710 if (par->blank == blank) 711 return 0; 712 713 par->blank = blank; 714 switch (blank) { 715 case FB_BLANK_UNBLANK: 716 if (par->panel_power_ctrl) 717 par->panel_power_ctrl(1); 718 719 lcd_enable_raster(); 720 break; 721 case FB_BLANK_POWERDOWN: 722 if (par->panel_power_ctrl) 723 par->panel_power_ctrl(0); 724 725 lcd_disable_raster(); 726 break; 727 default: 728 ret = -EINVAL; 729 } 730 731 return ret; 732} 733 734static struct fb_ops da8xx_fb_ops = { 735 .owner = THIS_MODULE, 736 .fb_check_var = fb_check_var, 737 .fb_setcolreg = fb_setcolreg, 738 .fb_ioctl = fb_ioctl, 739 .fb_fillrect = cfb_fillrect, 740 .fb_copyarea = cfb_copyarea, 741 .fb_imageblit = cfb_imageblit, 742 .fb_blank = cfb_blank, 743}; 744 745static int __init fb_probe(struct platform_device *device) 746{ 747 struct da8xx_lcdc_platform_data *fb_pdata = 748 device->dev.platform_data; 749 struct lcd_ctrl_config *lcd_cfg; 750 struct da8xx_panel *lcdc_info; 751 struct fb_info *da8xx_fb_info; 752 struct clk *fb_clk = NULL; 753 struct da8xx_fb_par *par; 754 resource_size_t len; 755 int ret, i; 756 757 if (fb_pdata == NULL) { 758 dev_err(&device->dev, "Can not get platform data\n"); 759 return -ENOENT; 760 } 761 762 lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); 763 if (!lcdc_regs) { 764 dev_err(&device->dev, 765 "Can not get memory resource for LCD controller\n"); 766 return -ENOENT; 767 } 768 769 len = resource_size(lcdc_regs); 770 771 lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name); 772 if (!lcdc_regs) 773 return -EBUSY; 774 775 da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len); 776 if (!da8xx_fb_reg_base) { 777 ret = -EBUSY; 778 goto err_request_mem; 779 } 780 781 fb_clk = clk_get(&device->dev, NULL); 782 if (IS_ERR(fb_clk)) { 783 dev_err(&device->dev, "Can not get device clock\n"); 784 ret = -ENODEV; 785 goto err_ioremap; 786 } 787 ret = clk_enable(fb_clk); 788 if (ret) 789 goto err_clk_put; 790 791 for (i = 0, lcdc_info = known_lcd_panels; 792 i < ARRAY_SIZE(known_lcd_panels); 793 i++, lcdc_info++) { 794 if (strcmp(fb_pdata->type, lcdc_info->name) == 0) 795 break; 796 } 797 798 if (i == ARRAY_SIZE(known_lcd_panels)) { 799 dev_err(&device->dev, "GLCD: No valid panel found\n"); 800 ret = -ENODEV; 801 goto err_clk_disable; 802 } else 803 dev_info(&device->dev, "GLCD: Found %s panel\n", 804 fb_pdata->type); 805 806 lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; 807 808 da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), 809 &device->dev); 810 if (!da8xx_fb_info) { 811 dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); 812 ret = -ENOMEM; 813 goto err_clk_disable; 814 } 815 816 par = da8xx_fb_info->par; 817 par->lcdc_clk = fb_clk; 818 par->pxl_clk = lcdc_info->pxl_clk; 819 if (fb_pdata->panel_power_ctrl) { 820 par->panel_power_ctrl = fb_pdata->panel_power_ctrl; 821 par->panel_power_ctrl(1); 822 } 823 824 if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { 825 dev_err(&device->dev, "lcd_init failed\n"); 826 ret = -EFAULT; 827 goto err_release_fb; 828 } 829 830 /* allocate frame buffer */ 831 da8xx_fb_info->screen_base = dma_alloc_coherent(NULL, 832 par->databuf_sz + PAGE_SIZE, 833 (resource_size_t *) 834 &da8xx_fb_info->fix.smem_start, 835 GFP_KERNEL | GFP_DMA); 836 837 if (!da8xx_fb_info->screen_base) { 838 dev_err(&device->dev, 839 "GLCD: kmalloc for frame buffer failed\n"); 840 ret = -EINVAL; 841 goto err_release_fb; 842 } 843 844 /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */ 845 par->v_palette_base = da8xx_fb_info->screen_base + 846 (PAGE_SIZE - par->palette_sz); 847 par->p_palette_base = da8xx_fb_info->fix.smem_start + 848 (PAGE_SIZE - par->palette_sz); 849 850 /* the rest of the frame buffer is pixel data */ 851 da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz; 852 da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz; 853 da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; 854 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; 855 856 par->irq = platform_get_irq(device, 0); 857 if (par->irq < 0) { 858 ret = -ENOENT; 859 goto err_release_fb_mem; 860 } 861 862 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); 863 if (ret) 864 goto err_release_fb_mem; 865 866 /* Initialize par */ 867 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; 868 869 da8xx_fb_var.xres = lcdc_info->width; 870 da8xx_fb_var.xres_virtual = lcdc_info->width; 871 872 da8xx_fb_var.yres = lcdc_info->height; 873 da8xx_fb_var.yres_virtual = lcdc_info->height; 874 875 da8xx_fb_var.grayscale = 876 lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; 877 da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; 878 879 da8xx_fb_var.hsync_len = lcdc_info->hsw; 880 da8xx_fb_var.vsync_len = lcdc_info->vsw; 881 882 /* Initialize fbinfo */ 883 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; 884 da8xx_fb_info->fix = da8xx_fb_fix; 885 da8xx_fb_info->var = da8xx_fb_var; 886 da8xx_fb_info->fbops = &da8xx_fb_ops; 887 da8xx_fb_info->pseudo_palette = par->pseudo_palette; 888 da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? 889 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 890 891 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); 892 if (ret) 893 goto err_free_irq; 894 895 /* First palette_sz byte of the frame buffer is the palette */ 896 da8xx_fb_info->cmap.len = par->palette_sz; 897 898 /* Flush the buffer to the screen. */ 899 lcd_blit(LOAD_DATA, par); 900 901 /* initialize var_screeninfo */ 902 da8xx_fb_var.activate = FB_ACTIVATE_FORCE; 903 fb_set_var(da8xx_fb_info, &da8xx_fb_var); 904 905 dev_set_drvdata(&device->dev, da8xx_fb_info); 906 /* Register the Frame Buffer */ 907 if (register_framebuffer(da8xx_fb_info) < 0) { 908 dev_err(&device->dev, 909 "GLCD: Frame Buffer Registration Failed!\n"); 910 ret = -EINVAL; 911 goto err_dealloc_cmap; 912 } 913 914#ifdef CONFIG_CPU_FREQ 915 ret = lcd_da8xx_cpufreq_register(par); 916 if (ret) { 917 dev_err(&device->dev, "failed to register cpufreq\n"); 918 goto err_cpu_freq; 919 } 920#endif 921 922 /* enable raster engine */ 923 lcd_enable_raster(); 924 925 return 0; 926 927#ifdef CONFIG_CPU_FREQ 928err_cpu_freq: 929 unregister_framebuffer(da8xx_fb_info); 930#endif 931 932err_dealloc_cmap: 933 fb_dealloc_cmap(&da8xx_fb_info->cmap); 934 935err_free_irq: 936 free_irq(par->irq, par); 937 938err_release_fb_mem: 939 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, 940 da8xx_fb_info->screen_base - PAGE_SIZE, 941 da8xx_fb_info->fix.smem_start); 942 943err_release_fb: 944 framebuffer_release(da8xx_fb_info); 945 946err_clk_disable: 947 clk_disable(fb_clk); 948 949err_clk_put: 950 clk_put(fb_clk); 951 952err_ioremap: 953 iounmap((void __iomem *)da8xx_fb_reg_base); 954 955err_request_mem: 956 release_mem_region(lcdc_regs->start, len); 957 958 return ret; 959} 960 961#ifdef CONFIG_PM 962static int fb_suspend(struct platform_device *dev, pm_message_t state) 963{ 964 struct fb_info *info = platform_get_drvdata(dev); 965 struct da8xx_fb_par *par = info->par; 966 967 acquire_console_sem(); 968 if (par->panel_power_ctrl) 969 par->panel_power_ctrl(0); 970 971 fb_set_suspend(info, 1); 972 lcd_disable_raster(); 973 clk_disable(par->lcdc_clk); 974 release_console_sem(); 975 976 return 0; 977} 978static int fb_resume(struct platform_device *dev) 979{ 980 struct fb_info *info = platform_get_drvdata(dev); 981 struct da8xx_fb_par *par = info->par; 982 983 acquire_console_sem(); 984 if (par->panel_power_ctrl) 985 par->panel_power_ctrl(1); 986 987 clk_enable(par->lcdc_clk); 988 lcd_enable_raster(); 989 fb_set_suspend(info, 0); 990 release_console_sem(); 991 992 return 0; 993} 994#else 995#define fb_suspend NULL 996#define fb_resume NULL 997#endif 998 999static struct platform_driver da8xx_fb_driver = { 1000 .probe = fb_probe, 1001 .remove = fb_remove, 1002 .suspend = fb_suspend, 1003 .resume = fb_resume, 1004 .driver = { 1005 .name = DRIVER_NAME, 1006 .owner = THIS_MODULE, 1007 }, 1008}; 1009 1010static int __init da8xx_fb_init(void) 1011{ 1012 return platform_driver_register(&da8xx_fb_driver); 1013} 1014 1015static void __exit da8xx_fb_cleanup(void) 1016{ 1017 platform_driver_unregister(&da8xx_fb_driver); 1018} 1019 1020module_init(da8xx_fb_init); 1021module_exit(da8xx_fb_cleanup); 1022 1023MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); 1024MODULE_AUTHOR("Texas Instruments"); 1025MODULE_LICENSE("GPL");