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.29-rc7 1111 lines 31 kB view raw
1/* 2 * Driver for AT91/AT32 LCD Controller 3 * 4 * Copyright (C) 2007 Atmel Corporation 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive for 8 * more details. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/platform_device.h> 13#include <linux/dma-mapping.h> 14#include <linux/interrupt.h> 15#include <linux/clk.h> 16#include <linux/fb.h> 17#include <linux/init.h> 18#include <linux/delay.h> 19#include <linux/backlight.h> 20 21#include <mach/board.h> 22#include <mach/cpu.h> 23#include <mach/gpio.h> 24 25#include <video/atmel_lcdc.h> 26 27#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) 28#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) 29 30/* configurable parameters */ 31#define ATMEL_LCDC_CVAL_DEFAULT 0xc8 32#define ATMEL_LCDC_DMA_BURST_LEN 8 33 34#if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9) || \ 35 defined(CONFIG_ARCH_AT91SAM9RL) 36#define ATMEL_LCDC_FIFO_SIZE 2048 37#else 38#define ATMEL_LCDC_FIFO_SIZE 512 39#endif 40 41#if defined(CONFIG_ARCH_AT91) 42#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ 43 | FBINFO_PARTIAL_PAN_OK \ 44 | FBINFO_HWACCEL_YPAN) 45 46static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, 47 struct fb_var_screeninfo *var) 48{ 49 50} 51#elif defined(CONFIG_AVR32) 52#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ 53 | FBINFO_PARTIAL_PAN_OK \ 54 | FBINFO_HWACCEL_XPAN \ 55 | FBINFO_HWACCEL_YPAN) 56 57static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, 58 struct fb_var_screeninfo *var) 59{ 60 u32 dma2dcfg; 61 u32 pixeloff; 62 63 pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; 64 65 dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; 66 dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; 67 lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); 68 69 /* Update configuration */ 70 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 71 lcdc_readl(sinfo, ATMEL_LCDC_DMACON) 72 | ATMEL_LCDC_DMAUPDT); 73} 74#endif 75 76static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 77 | ATMEL_LCDC_POL_POSITIVE 78 | ATMEL_LCDC_ENA_PWMENABLE; 79 80#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC 81 82/* some bl->props field just changed */ 83static int atmel_bl_update_status(struct backlight_device *bl) 84{ 85 struct atmel_lcdfb_info *sinfo = bl_get_data(bl); 86 int power = sinfo->bl_power; 87 int brightness = bl->props.brightness; 88 89 /* REVISIT there may be a meaningful difference between 90 * fb_blank and power ... there seem to be some cases 91 * this doesn't handle correctly. 92 */ 93 if (bl->props.fb_blank != sinfo->bl_power) 94 power = bl->props.fb_blank; 95 else if (bl->props.power != sinfo->bl_power) 96 power = bl->props.power; 97 98 if (brightness < 0 && power == FB_BLANK_UNBLANK) 99 brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 100 else if (power != FB_BLANK_UNBLANK) 101 brightness = 0; 102 103 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); 104 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 105 brightness ? contrast_ctr : 0); 106 107 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; 108 109 return 0; 110} 111 112static int atmel_bl_get_brightness(struct backlight_device *bl) 113{ 114 struct atmel_lcdfb_info *sinfo = bl_get_data(bl); 115 116 return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 117} 118 119static struct backlight_ops atmel_lcdc_bl_ops = { 120 .update_status = atmel_bl_update_status, 121 .get_brightness = atmel_bl_get_brightness, 122}; 123 124static void init_backlight(struct atmel_lcdfb_info *sinfo) 125{ 126 struct backlight_device *bl; 127 128 sinfo->bl_power = FB_BLANK_UNBLANK; 129 130 if (sinfo->backlight) 131 return; 132 133 bl = backlight_device_register("backlight", &sinfo->pdev->dev, 134 sinfo, &atmel_lcdc_bl_ops); 135 if (IS_ERR(bl)) { 136 dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", 137 PTR_ERR(bl)); 138 return; 139 } 140 sinfo->backlight = bl; 141 142 bl->props.power = FB_BLANK_UNBLANK; 143 bl->props.fb_blank = FB_BLANK_UNBLANK; 144 bl->props.max_brightness = 0xff; 145 bl->props.brightness = atmel_bl_get_brightness(bl); 146} 147 148static void exit_backlight(struct atmel_lcdfb_info *sinfo) 149{ 150 if (sinfo->backlight) 151 backlight_device_unregister(sinfo->backlight); 152} 153 154#else 155 156static void init_backlight(struct atmel_lcdfb_info *sinfo) 157{ 158 dev_warn(&sinfo->pdev->dev, "backlight control is not available\n"); 159} 160 161static void exit_backlight(struct atmel_lcdfb_info *sinfo) 162{ 163} 164 165#endif 166 167static void init_contrast(struct atmel_lcdfb_info *sinfo) 168{ 169 /* have some default contrast/backlight settings */ 170 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); 171 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); 172 173 if (sinfo->lcdcon_is_backlight) 174 init_backlight(sinfo); 175} 176 177 178static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { 179 .type = FB_TYPE_PACKED_PIXELS, 180 .visual = FB_VISUAL_TRUECOLOR, 181 .xpanstep = 0, 182 .ypanstep = 1, 183 .ywrapstep = 0, 184 .accel = FB_ACCEL_NONE, 185}; 186 187static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) 188{ 189 unsigned long value; 190 191 if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000())) 192 return xres; 193 194 value = xres; 195 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { 196 /* STN display */ 197 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) { 198 value *= 3; 199 } 200 if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4 201 || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8 202 && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL )) 203 value = DIV_ROUND_UP(value, 4); 204 else 205 value = DIV_ROUND_UP(value, 8); 206 } 207 208 return value; 209} 210 211static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo) 212{ 213 /* Turn off the LCD controller and the DMA controller */ 214 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, 215 sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); 216 217 /* Wait for the LCDC core to become idle */ 218 while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) 219 msleep(10); 220 221 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); 222} 223 224static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo) 225{ 226 atmel_lcdfb_stop_nowait(sinfo); 227 228 /* Wait for DMA engine to become idle... */ 229 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) 230 msleep(10); 231} 232 233static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo) 234{ 235 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); 236 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, 237 (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) 238 | ATMEL_LCDC_PWR); 239} 240 241static void atmel_lcdfb_update_dma(struct fb_info *info, 242 struct fb_var_screeninfo *var) 243{ 244 struct atmel_lcdfb_info *sinfo = info->par; 245 struct fb_fix_screeninfo *fix = &info->fix; 246 unsigned long dma_addr; 247 248 dma_addr = (fix->smem_start + var->yoffset * fix->line_length 249 + var->xoffset * var->bits_per_pixel / 8); 250 251 dma_addr &= ~3UL; 252 253 /* Set framebuffer DMA base address and pixel offset */ 254 lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); 255 256 atmel_lcdfb_update_dma2d(sinfo, var); 257} 258 259static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) 260{ 261 struct fb_info *info = sinfo->info; 262 263 dma_free_writecombine(info->device, info->fix.smem_len, 264 info->screen_base, info->fix.smem_start); 265} 266 267/** 268 * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory 269 * @sinfo: the frame buffer to allocate memory for 270 */ 271static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) 272{ 273 struct fb_info *info = sinfo->info; 274 struct fb_var_screeninfo *var = &info->var; 275 unsigned int smem_len; 276 277 smem_len = (var->xres_virtual * var->yres_virtual 278 * ((var->bits_per_pixel + 7) / 8)); 279 info->fix.smem_len = max(smem_len, sinfo->smem_len); 280 281 info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, 282 (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); 283 284 if (!info->screen_base) { 285 return -ENOMEM; 286 } 287 288 memset(info->screen_base, 0, info->fix.smem_len); 289 290 return 0; 291} 292 293static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var, 294 struct fb_info *info) 295{ 296 struct fb_videomode varfbmode; 297 const struct fb_videomode *fbmode = NULL; 298 299 fb_var_to_videomode(&varfbmode, var); 300 fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist); 301 if (fbmode) 302 fb_videomode_to_var(var, fbmode); 303 return fbmode; 304} 305 306 307/** 308 * atmel_lcdfb_check_var - Validates a var passed in. 309 * @var: frame buffer variable screen structure 310 * @info: frame buffer structure that represents a single frame buffer 311 * 312 * Checks to see if the hardware supports the state requested by 313 * var passed in. This function does not alter the hardware 314 * state!!! This means the data stored in struct fb_info and 315 * struct atmel_lcdfb_info do not change. This includes the var 316 * inside of struct fb_info. Do NOT change these. This function 317 * can be called on its own if we intent to only test a mode and 318 * not actually set it. The stuff in modedb.c is a example of 319 * this. If the var passed in is slightly off by what the 320 * hardware can support then we alter the var PASSED in to what 321 * we can do. If the hardware doesn't support mode change a 322 * -EINVAL will be returned by the upper layers. You don't need 323 * to implement this function then. If you hardware doesn't 324 * support changing the resolution then this function is not 325 * needed. In this case the driver would just provide a var that 326 * represents the static state the screen is in. 327 * 328 * Returns negative errno on error, or zero on success. 329 */ 330static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, 331 struct fb_info *info) 332{ 333 struct device *dev = info->device; 334 struct atmel_lcdfb_info *sinfo = info->par; 335 unsigned long clk_value_khz; 336 337 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 338 339 dev_dbg(dev, "%s:\n", __func__); 340 341 if (!(var->pixclock && var->bits_per_pixel)) { 342 /* choose a suitable mode if possible */ 343 if (!atmel_lcdfb_choose_mode(var, info)) { 344 dev_err(dev, "needed value not specified\n"); 345 return -EINVAL; 346 } 347 } 348 349 dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); 350 dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); 351 dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); 352 dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz); 353 354 if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) { 355 dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock)); 356 return -EINVAL; 357 } 358 359 /* Do not allow to have real resoulution larger than virtual */ 360 if (var->xres > var->xres_virtual) 361 var->xres_virtual = var->xres; 362 363 if (var->yres > var->yres_virtual) 364 var->yres_virtual = var->yres; 365 366 /* Force same alignment for each line */ 367 var->xres = (var->xres + 3) & ~3UL; 368 var->xres_virtual = (var->xres_virtual + 3) & ~3UL; 369 370 var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; 371 var->transp.msb_right = 0; 372 var->transp.offset = var->transp.length = 0; 373 var->xoffset = var->yoffset = 0; 374 375 if (info->fix.smem_len) { 376 unsigned int smem_len = (var->xres_virtual * var->yres_virtual 377 * ((var->bits_per_pixel + 7) / 8)); 378 if (smem_len > info->fix.smem_len) 379 return -EINVAL; 380 } 381 382 /* Saturate vertical and horizontal timings at maximum values */ 383 var->vsync_len = min_t(u32, var->vsync_len, 384 (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); 385 var->upper_margin = min_t(u32, var->upper_margin, 386 ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET); 387 var->lower_margin = min_t(u32, var->lower_margin, 388 ATMEL_LCDC_VFP); 389 var->right_margin = min_t(u32, var->right_margin, 390 (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); 391 var->hsync_len = min_t(u32, var->hsync_len, 392 (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); 393 var->left_margin = min_t(u32, var->left_margin, 394 ATMEL_LCDC_HBP + 1); 395 396 /* Some parameters can't be zero */ 397 var->vsync_len = max_t(u32, var->vsync_len, 1); 398 var->right_margin = max_t(u32, var->right_margin, 1); 399 var->hsync_len = max_t(u32, var->hsync_len, 1); 400 var->left_margin = max_t(u32, var->left_margin, 1); 401 402 switch (var->bits_per_pixel) { 403 case 1: 404 case 2: 405 case 4: 406 case 8: 407 var->red.offset = var->green.offset = var->blue.offset = 0; 408 var->red.length = var->green.length = var->blue.length 409 = var->bits_per_pixel; 410 break; 411 case 15: 412 case 16: 413 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { 414 /* RGB:565 mode */ 415 var->red.offset = 11; 416 var->blue.offset = 0; 417 var->green.length = 6; 418 } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) { 419 var->red.offset = 10; 420 var->blue.offset = 0; 421 var->green.length = 5; 422 } else { 423 /* BGR:555 mode */ 424 var->red.offset = 0; 425 var->blue.offset = 10; 426 var->green.length = 5; 427 } 428 var->green.offset = 5; 429 var->red.length = var->blue.length = 5; 430 break; 431 case 32: 432 var->transp.offset = 24; 433 var->transp.length = 8; 434 /* fall through */ 435 case 24: 436 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { 437 /* RGB:888 mode */ 438 var->red.offset = 16; 439 var->blue.offset = 0; 440 } else { 441 /* BGR:888 mode */ 442 var->red.offset = 0; 443 var->blue.offset = 16; 444 } 445 var->green.offset = 8; 446 var->red.length = var->green.length = var->blue.length = 8; 447 break; 448 default: 449 dev_err(dev, "color depth %d not supported\n", 450 var->bits_per_pixel); 451 return -EINVAL; 452 } 453 454 return 0; 455} 456 457/* 458 * LCD reset sequence 459 */ 460static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) 461{ 462 might_sleep(); 463 464 atmel_lcdfb_stop(sinfo); 465 atmel_lcdfb_start(sinfo); 466} 467 468/** 469 * atmel_lcdfb_set_par - Alters the hardware state. 470 * @info: frame buffer structure that represents a single frame buffer 471 * 472 * Using the fb_var_screeninfo in fb_info we set the resolution 473 * of the this particular framebuffer. This function alters the 474 * par AND the fb_fix_screeninfo stored in fb_info. It doesn't 475 * not alter var in fb_info since we are using that data. This 476 * means we depend on the data in var inside fb_info to be 477 * supported by the hardware. atmel_lcdfb_check_var is always called 478 * before atmel_lcdfb_set_par to ensure this. Again if you can't 479 * change the resolution you don't need this function. 480 * 481 */ 482static int atmel_lcdfb_set_par(struct fb_info *info) 483{ 484 struct atmel_lcdfb_info *sinfo = info->par; 485 unsigned long hozval_linesz; 486 unsigned long value; 487 unsigned long clk_value_khz; 488 unsigned long bits_per_line; 489 490 might_sleep(); 491 492 dev_dbg(info->device, "%s:\n", __func__); 493 dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", 494 info->var.xres, info->var.yres, 495 info->var.xres_virtual, info->var.yres_virtual); 496 497 atmel_lcdfb_stop_nowait(sinfo); 498 499 if (info->var.bits_per_pixel == 1) 500 info->fix.visual = FB_VISUAL_MONO01; 501 else if (info->var.bits_per_pixel <= 8) 502 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 503 else 504 info->fix.visual = FB_VISUAL_TRUECOLOR; 505 506 bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel; 507 info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8); 508 509 /* Re-initialize the DMA engine... */ 510 dev_dbg(info->device, " * update DMA engine\n"); 511 atmel_lcdfb_update_dma(info, &info->var); 512 513 /* ...set frame size and burst length = 8 words (?) */ 514 value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32; 515 value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET); 516 lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); 517 518 /* Now, the LCDC core... */ 519 520 /* Set pixel clock */ 521 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 522 523 value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); 524 525 if (value < 2) { 526 dev_notice(info->device, "Bypassing pixel clock divider\n"); 527 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); 528 } else { 529 value = (value / 2) - 1; 530 dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", 531 value); 532 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, 533 value << ATMEL_LCDC_CLKVAL_OFFSET); 534 info->var.pixclock = KHZ2PICOS(clk_value_khz / (2 * (value + 1))); 535 dev_dbg(info->device, " updated pixclk: %lu KHz\n", 536 PICOS2KHZ(info->var.pixclock)); 537 } 538 539 540 /* Initialize control register 2 */ 541 value = sinfo->default_lcdcon2; 542 543 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) 544 value |= ATMEL_LCDC_INVLINE_INVERTED; 545 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) 546 value |= ATMEL_LCDC_INVFRAME_INVERTED; 547 548 switch (info->var.bits_per_pixel) { 549 case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break; 550 case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; 551 case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; 552 case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; 553 case 15: /* fall through */ 554 case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; 555 case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; 556 case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; 557 default: BUG(); break; 558 } 559 dev_dbg(info->device, " * LCDCON2 = %08lx\n", value); 560 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value); 561 562 /* Vertical timing */ 563 value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET; 564 value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET; 565 value |= info->var.lower_margin; 566 dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value); 567 lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); 568 569 /* Horizontal timing */ 570 value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; 571 value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; 572 value |= (info->var.left_margin - 1); 573 dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); 574 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); 575 576 /* Horizontal value (aka line size) */ 577 hozval_linesz = compute_hozval(info->var.xres, 578 lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2)); 579 580 /* Display size */ 581 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; 582 value |= info->var.yres - 1; 583 dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value); 584 lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); 585 586 /* FIFO Threshold: Use formula from data sheet */ 587 value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3); 588 lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value); 589 590 /* Toggle LCD_MODE every frame */ 591 lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); 592 593 /* Disable all interrupts */ 594 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); 595 /* Enable FIFO & DMA errors */ 596 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); 597 598 /* ...wait for DMA engine to become idle... */ 599 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) 600 msleep(10); 601 602 atmel_lcdfb_start(sinfo); 603 604 dev_dbg(info->device, " * DONE\n"); 605 606 return 0; 607} 608 609static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf) 610{ 611 chan &= 0xffff; 612 chan >>= 16 - bf->length; 613 return chan << bf->offset; 614} 615 616/** 617 * atmel_lcdfb_setcolreg - Optional function. Sets a color register. 618 * @regno: Which register in the CLUT we are programming 619 * @red: The red value which can be up to 16 bits wide 620 * @green: The green value which can be up to 16 bits wide 621 * @blue: The blue value which can be up to 16 bits wide. 622 * @transp: If supported the alpha value which can be up to 16 bits wide. 623 * @info: frame buffer info structure 624 * 625 * Set a single color register. The values supplied have a 16 bit 626 * magnitude which needs to be scaled in this function for the hardware. 627 * Things to take into consideration are how many color registers, if 628 * any, are supported with the current color visual. With truecolor mode 629 * no color palettes are supported. Here a psuedo palette is created 630 * which we store the value in pseudo_palette in struct fb_info. For 631 * pseudocolor mode we have a limited color palette. To deal with this 632 * we can program what color is displayed for a particular pixel value. 633 * DirectColor is similar in that we can program each color field. If 634 * we have a static colormap we don't need to implement this function. 635 * 636 * Returns negative errno on error, or zero on success. In an 637 * ideal world, this would have been the case, but as it turns 638 * out, the other drivers return 1 on failure, so that's what 639 * we're going to do. 640 */ 641static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, 642 unsigned int green, unsigned int blue, 643 unsigned int transp, struct fb_info *info) 644{ 645 struct atmel_lcdfb_info *sinfo = info->par; 646 unsigned int val; 647 u32 *pal; 648 int ret = 1; 649 650 if (info->var.grayscale) 651 red = green = blue = (19595 * red + 38470 * green 652 + 7471 * blue) >> 16; 653 654 switch (info->fix.visual) { 655 case FB_VISUAL_TRUECOLOR: 656 if (regno < 16) { 657 pal = info->pseudo_palette; 658 659 val = chan_to_field(red, &info->var.red); 660 val |= chan_to_field(green, &info->var.green); 661 val |= chan_to_field(blue, &info->var.blue); 662 663 pal[regno] = val; 664 ret = 0; 665 } 666 break; 667 668 case FB_VISUAL_PSEUDOCOLOR: 669 if (regno < 256) { 670 val = ((red >> 11) & 0x001f); 671 val |= ((green >> 6) & 0x03e0); 672 val |= ((blue >> 1) & 0x7c00); 673 674 /* 675 * TODO: intensity bit. Maybe something like 676 * ~(red[10] ^ green[10] ^ blue[10]) & 1 677 */ 678 679 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 680 ret = 0; 681 } 682 break; 683 684 case FB_VISUAL_MONO01: 685 if (regno < 2) { 686 val = (regno == 0) ? 0x00 : 0x1F; 687 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 688 ret = 0; 689 } 690 break; 691 692 } 693 694 return ret; 695} 696 697static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, 698 struct fb_info *info) 699{ 700 dev_dbg(info->device, "%s\n", __func__); 701 702 atmel_lcdfb_update_dma(info, var); 703 704 return 0; 705} 706 707static struct fb_ops atmel_lcdfb_ops = { 708 .owner = THIS_MODULE, 709 .fb_check_var = atmel_lcdfb_check_var, 710 .fb_set_par = atmel_lcdfb_set_par, 711 .fb_setcolreg = atmel_lcdfb_setcolreg, 712 .fb_pan_display = atmel_lcdfb_pan_display, 713 .fb_fillrect = cfb_fillrect, 714 .fb_copyarea = cfb_copyarea, 715 .fb_imageblit = cfb_imageblit, 716}; 717 718static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) 719{ 720 struct fb_info *info = dev_id; 721 struct atmel_lcdfb_info *sinfo = info->par; 722 u32 status; 723 724 status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); 725 if (status & ATMEL_LCDC_UFLWI) { 726 dev_warn(info->device, "FIFO underflow %#x\n", status); 727 /* reset DMA and FIFO to avoid screen shifting */ 728 schedule_work(&sinfo->task); 729 } 730 lcdc_writel(sinfo, ATMEL_LCDC_ICR, status); 731 return IRQ_HANDLED; 732} 733 734/* 735 * LCD controller task (to reset the LCD) 736 */ 737static void atmel_lcdfb_task(struct work_struct *work) 738{ 739 struct atmel_lcdfb_info *sinfo = 740 container_of(work, struct atmel_lcdfb_info, task); 741 742 atmel_lcdfb_reset(sinfo); 743} 744 745static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) 746{ 747 struct fb_info *info = sinfo->info; 748 int ret = 0; 749 750 info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; 751 752 dev_info(info->device, 753 "%luKiB frame buffer at %08lx (mapped at %p)\n", 754 (unsigned long)info->fix.smem_len / 1024, 755 (unsigned long)info->fix.smem_start, 756 info->screen_base); 757 758 /* Allocate colormap */ 759 ret = fb_alloc_cmap(&info->cmap, 256, 0); 760 if (ret < 0) 761 dev_err(info->device, "Alloc color map failed\n"); 762 763 return ret; 764} 765 766static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) 767{ 768 if (sinfo->bus_clk) 769 clk_enable(sinfo->bus_clk); 770 clk_enable(sinfo->lcdc_clk); 771} 772 773static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) 774{ 775 if (sinfo->bus_clk) 776 clk_disable(sinfo->bus_clk); 777 clk_disable(sinfo->lcdc_clk); 778} 779 780 781static int __init atmel_lcdfb_probe(struct platform_device *pdev) 782{ 783 struct device *dev = &pdev->dev; 784 struct fb_info *info; 785 struct atmel_lcdfb_info *sinfo; 786 struct atmel_lcdfb_info *pdata_sinfo; 787 struct fb_videomode fbmode; 788 struct resource *regs = NULL; 789 struct resource *map = NULL; 790 int ret; 791 792 dev_dbg(dev, "%s BEGIN\n", __func__); 793 794 ret = -ENOMEM; 795 info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); 796 if (!info) { 797 dev_err(dev, "cannot allocate memory\n"); 798 goto out; 799 } 800 801 sinfo = info->par; 802 803 if (dev->platform_data) { 804 pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data; 805 sinfo->default_bpp = pdata_sinfo->default_bpp; 806 sinfo->default_dmacon = pdata_sinfo->default_dmacon; 807 sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2; 808 sinfo->default_monspecs = pdata_sinfo->default_monspecs; 809 sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; 810 sinfo->guard_time = pdata_sinfo->guard_time; 811 sinfo->smem_len = pdata_sinfo->smem_len; 812 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; 813 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; 814 } else { 815 dev_err(dev, "cannot get default configuration\n"); 816 goto free_info; 817 } 818 sinfo->info = info; 819 sinfo->pdev = pdev; 820 821 strcpy(info->fix.id, sinfo->pdev->name); 822 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; 823 info->pseudo_palette = sinfo->pseudo_palette; 824 info->fbops = &atmel_lcdfb_ops; 825 826 memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); 827 info->fix = atmel_lcdfb_fix; 828 829 /* Enable LCDC Clocks */ 830 if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { 831 sinfo->bus_clk = clk_get(dev, "hck1"); 832 if (IS_ERR(sinfo->bus_clk)) { 833 ret = PTR_ERR(sinfo->bus_clk); 834 goto free_info; 835 } 836 } 837 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); 838 if (IS_ERR(sinfo->lcdc_clk)) { 839 ret = PTR_ERR(sinfo->lcdc_clk); 840 goto put_bus_clk; 841 } 842 atmel_lcdfb_start_clock(sinfo); 843 844 ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, 845 info->monspecs.modedb_len, info->monspecs.modedb, 846 sinfo->default_bpp); 847 if (!ret) { 848 dev_err(dev, "no suitable video mode found\n"); 849 goto stop_clk; 850 } 851 852 853 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 854 if (!regs) { 855 dev_err(dev, "resources unusable\n"); 856 ret = -ENXIO; 857 goto stop_clk; 858 } 859 860 sinfo->irq_base = platform_get_irq(pdev, 0); 861 if (sinfo->irq_base < 0) { 862 dev_err(dev, "unable to get irq\n"); 863 ret = sinfo->irq_base; 864 goto stop_clk; 865 } 866 867 /* Initialize video memory */ 868 map = platform_get_resource(pdev, IORESOURCE_MEM, 1); 869 if (map) { 870 /* use a pre-allocated memory buffer */ 871 info->fix.smem_start = map->start; 872 info->fix.smem_len = map->end - map->start + 1; 873 if (!request_mem_region(info->fix.smem_start, 874 info->fix.smem_len, pdev->name)) { 875 ret = -EBUSY; 876 goto stop_clk; 877 } 878 879 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 880 if (!info->screen_base) 881 goto release_intmem; 882 883 /* 884 * Don't clear the framebuffer -- someone may have set 885 * up a splash image. 886 */ 887 } else { 888 /* alocate memory buffer */ 889 ret = atmel_lcdfb_alloc_video_memory(sinfo); 890 if (ret < 0) { 891 dev_err(dev, "cannot allocate framebuffer: %d\n", ret); 892 goto stop_clk; 893 } 894 } 895 896 /* LCDC registers */ 897 info->fix.mmio_start = regs->start; 898 info->fix.mmio_len = regs->end - regs->start + 1; 899 900 if (!request_mem_region(info->fix.mmio_start, 901 info->fix.mmio_len, pdev->name)) { 902 ret = -EBUSY; 903 goto free_fb; 904 } 905 906 sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); 907 if (!sinfo->mmio) { 908 dev_err(dev, "cannot map LCDC registers\n"); 909 goto release_mem; 910 } 911 912 /* Initialize PWM for contrast or backlight ("off") */ 913 init_contrast(sinfo); 914 915 /* interrupt */ 916 ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); 917 if (ret) { 918 dev_err(dev, "request_irq failed: %d\n", ret); 919 goto unmap_mmio; 920 } 921 922 /* Some operations on the LCDC might sleep and 923 * require a preemptible task context */ 924 INIT_WORK(&sinfo->task, atmel_lcdfb_task); 925 926 ret = atmel_lcdfb_init_fbinfo(sinfo); 927 if (ret < 0) { 928 dev_err(dev, "init fbinfo failed: %d\n", ret); 929 goto unregister_irqs; 930 } 931 932 /* 933 * This makes sure that our colour bitfield 934 * descriptors are correctly initialised. 935 */ 936 atmel_lcdfb_check_var(&info->var, info); 937 938 ret = fb_set_var(info, &info->var); 939 if (ret) { 940 dev_warn(dev, "unable to set display parameters\n"); 941 goto free_cmap; 942 } 943 944 dev_set_drvdata(dev, info); 945 946 /* 947 * Tell the world that we're ready to go 948 */ 949 ret = register_framebuffer(info); 950 if (ret < 0) { 951 dev_err(dev, "failed to register framebuffer device: %d\n", ret); 952 goto reset_drvdata; 953 } 954 955 /* add selected videomode to modelist */ 956 fb_var_to_videomode(&fbmode, &info->var); 957 fb_add_videomode(&fbmode, &info->modelist); 958 959 /* Power up the LCDC screen */ 960 if (sinfo->atmel_lcdfb_power_control) 961 sinfo->atmel_lcdfb_power_control(1); 962 963 dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", 964 info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); 965 966 return 0; 967 968reset_drvdata: 969 dev_set_drvdata(dev, NULL); 970free_cmap: 971 fb_dealloc_cmap(&info->cmap); 972unregister_irqs: 973 cancel_work_sync(&sinfo->task); 974 free_irq(sinfo->irq_base, info); 975unmap_mmio: 976 exit_backlight(sinfo); 977 iounmap(sinfo->mmio); 978release_mem: 979 release_mem_region(info->fix.mmio_start, info->fix.mmio_len); 980free_fb: 981 if (map) 982 iounmap(info->screen_base); 983 else 984 atmel_lcdfb_free_video_memory(sinfo); 985 986release_intmem: 987 if (map) 988 release_mem_region(info->fix.smem_start, info->fix.smem_len); 989stop_clk: 990 atmel_lcdfb_stop_clock(sinfo); 991 clk_put(sinfo->lcdc_clk); 992put_bus_clk: 993 if (sinfo->bus_clk) 994 clk_put(sinfo->bus_clk); 995free_info: 996 framebuffer_release(info); 997out: 998 dev_dbg(dev, "%s FAILED\n", __func__); 999 return ret; 1000} 1001 1002static int __exit atmel_lcdfb_remove(struct platform_device *pdev) 1003{ 1004 struct device *dev = &pdev->dev; 1005 struct fb_info *info = dev_get_drvdata(dev); 1006 struct atmel_lcdfb_info *sinfo; 1007 1008 if (!info || !info->par) 1009 return 0; 1010 sinfo = info->par; 1011 1012 cancel_work_sync(&sinfo->task); 1013 exit_backlight(sinfo); 1014 if (sinfo->atmel_lcdfb_power_control) 1015 sinfo->atmel_lcdfb_power_control(0); 1016 unregister_framebuffer(info); 1017 atmel_lcdfb_stop_clock(sinfo); 1018 clk_put(sinfo->lcdc_clk); 1019 if (sinfo->bus_clk) 1020 clk_put(sinfo->bus_clk); 1021 fb_dealloc_cmap(&info->cmap); 1022 free_irq(sinfo->irq_base, info); 1023 iounmap(sinfo->mmio); 1024 release_mem_region(info->fix.mmio_start, info->fix.mmio_len); 1025 if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { 1026 iounmap(info->screen_base); 1027 release_mem_region(info->fix.smem_start, info->fix.smem_len); 1028 } else { 1029 atmel_lcdfb_free_video_memory(sinfo); 1030 } 1031 1032 dev_set_drvdata(dev, NULL); 1033 framebuffer_release(info); 1034 1035 return 0; 1036} 1037 1038#ifdef CONFIG_PM 1039 1040static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) 1041{ 1042 struct fb_info *info = platform_get_drvdata(pdev); 1043 struct atmel_lcdfb_info *sinfo = info->par; 1044 1045 /* 1046 * We don't want to handle interrupts while the clock is 1047 * stopped. It may take forever. 1048 */ 1049 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); 1050 1051 sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 1052 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); 1053 if (sinfo->atmel_lcdfb_power_control) 1054 sinfo->atmel_lcdfb_power_control(0); 1055 1056 atmel_lcdfb_stop(sinfo); 1057 atmel_lcdfb_stop_clock(sinfo); 1058 1059 return 0; 1060} 1061 1062static int atmel_lcdfb_resume(struct platform_device *pdev) 1063{ 1064 struct fb_info *info = platform_get_drvdata(pdev); 1065 struct atmel_lcdfb_info *sinfo = info->par; 1066 1067 atmel_lcdfb_start_clock(sinfo); 1068 atmel_lcdfb_start(sinfo); 1069 if (sinfo->atmel_lcdfb_power_control) 1070 sinfo->atmel_lcdfb_power_control(1); 1071 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); 1072 1073 /* Enable FIFO & DMA errors */ 1074 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI 1075 | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); 1076 1077 return 0; 1078} 1079 1080#else 1081#define atmel_lcdfb_suspend NULL 1082#define atmel_lcdfb_resume NULL 1083#endif 1084 1085static struct platform_driver atmel_lcdfb_driver = { 1086 .remove = __exit_p(atmel_lcdfb_remove), 1087 .suspend = atmel_lcdfb_suspend, 1088 .resume = atmel_lcdfb_resume, 1089 1090 .driver = { 1091 .name = "atmel_lcdfb", 1092 .owner = THIS_MODULE, 1093 }, 1094}; 1095 1096static int __init atmel_lcdfb_init(void) 1097{ 1098 return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); 1099} 1100 1101static void __exit atmel_lcdfb_exit(void) 1102{ 1103 platform_driver_unregister(&atmel_lcdfb_driver); 1104} 1105 1106module_init(atmel_lcdfb_init); 1107module_exit(atmel_lcdfb_exit); 1108 1109MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); 1110MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); 1111MODULE_LICENSE("GPL");