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