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.33-rc5 1115 lines 32 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 unsigned long pix_factor = 2; 488 489 might_sleep(); 490 491 dev_dbg(info->device, "%s:\n", __func__); 492 dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", 493 info->var.xres, info->var.yres, 494 info->var.xres_virtual, info->var.yres_virtual); 495 496 atmel_lcdfb_stop_nowait(sinfo); 497 498 if (info->var.bits_per_pixel == 1) 499 info->fix.visual = FB_VISUAL_MONO01; 500 else if (info->var.bits_per_pixel <= 8) 501 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 502 else 503 info->fix.visual = FB_VISUAL_TRUECOLOR; 504 505 bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel; 506 info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8); 507 508 /* Re-initialize the DMA engine... */ 509 dev_dbg(info->device, " * update DMA engine\n"); 510 atmel_lcdfb_update_dma(info, &info->var); 511 512 /* ...set frame size and burst length = 8 words (?) */ 513 value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32; 514 value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET); 515 lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); 516 517 /* Now, the LCDC core... */ 518 519 /* Set pixel clock */ 520 if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es()) 521 pix_factor = 1; 522 523 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 524 525 value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); 526 527 if (value < pix_factor) { 528 dev_notice(info->device, "Bypassing pixel clock divider\n"); 529 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); 530 } else { 531 value = (value / pix_factor) - 1; 532 dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", 533 value); 534 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, 535 value << ATMEL_LCDC_CLKVAL_OFFSET); 536 info->var.pixclock = 537 KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1))); 538 dev_dbg(info->device, " updated pixclk: %lu KHz\n", 539 PICOS2KHZ(info->var.pixclock)); 540 } 541 542 543 /* Initialize control register 2 */ 544 value = sinfo->default_lcdcon2; 545 546 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) 547 value |= ATMEL_LCDC_INVLINE_INVERTED; 548 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) 549 value |= ATMEL_LCDC_INVFRAME_INVERTED; 550 551 switch (info->var.bits_per_pixel) { 552 case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break; 553 case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; 554 case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; 555 case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; 556 case 15: /* fall through */ 557 case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; 558 case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; 559 case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; 560 default: BUG(); break; 561 } 562 dev_dbg(info->device, " * LCDCON2 = %08lx\n", value); 563 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value); 564 565 /* Vertical timing */ 566 value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET; 567 value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET; 568 value |= info->var.lower_margin; 569 dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value); 570 lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); 571 572 /* Horizontal timing */ 573 value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; 574 value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; 575 value |= (info->var.left_margin - 1); 576 dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); 577 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); 578 579 /* Horizontal value (aka line size) */ 580 hozval_linesz = compute_hozval(info->var.xres, 581 lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2)); 582 583 /* Display size */ 584 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; 585 value |= info->var.yres - 1; 586 dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value); 587 lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); 588 589 /* FIFO Threshold: Use formula from data sheet */ 590 value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3); 591 lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value); 592 593 /* Toggle LCD_MODE every frame */ 594 lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); 595 596 /* Disable all interrupts */ 597 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); 598 /* Enable FIFO & DMA errors */ 599 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); 600 601 /* ...wait for DMA engine to become idle... */ 602 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) 603 msleep(10); 604 605 atmel_lcdfb_start(sinfo); 606 607 dev_dbg(info->device, " * DONE\n"); 608 609 return 0; 610} 611 612static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf) 613{ 614 chan &= 0xffff; 615 chan >>= 16 - bf->length; 616 return chan << bf->offset; 617} 618 619/** 620 * atmel_lcdfb_setcolreg - Optional function. Sets a color register. 621 * @regno: Which register in the CLUT we are programming 622 * @red: The red value which can be up to 16 bits wide 623 * @green: The green value which can be up to 16 bits wide 624 * @blue: The blue value which can be up to 16 bits wide. 625 * @transp: If supported the alpha value which can be up to 16 bits wide. 626 * @info: frame buffer info structure 627 * 628 * Set a single color register. The values supplied have a 16 bit 629 * magnitude which needs to be scaled in this function for the hardware. 630 * Things to take into consideration are how many color registers, if 631 * any, are supported with the current color visual. With truecolor mode 632 * no color palettes are supported. Here a psuedo palette is created 633 * which we store the value in pseudo_palette in struct fb_info. For 634 * pseudocolor mode we have a limited color palette. To deal with this 635 * we can program what color is displayed for a particular pixel value. 636 * DirectColor is similar in that we can program each color field. If 637 * we have a static colormap we don't need to implement this function. 638 * 639 * Returns negative errno on error, or zero on success. In an 640 * ideal world, this would have been the case, but as it turns 641 * out, the other drivers return 1 on failure, so that's what 642 * we're going to do. 643 */ 644static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, 645 unsigned int green, unsigned int blue, 646 unsigned int transp, struct fb_info *info) 647{ 648 struct atmel_lcdfb_info *sinfo = info->par; 649 unsigned int val; 650 u32 *pal; 651 int ret = 1; 652 653 if (info->var.grayscale) 654 red = green = blue = (19595 * red + 38470 * green 655 + 7471 * blue) >> 16; 656 657 switch (info->fix.visual) { 658 case FB_VISUAL_TRUECOLOR: 659 if (regno < 16) { 660 pal = info->pseudo_palette; 661 662 val = chan_to_field(red, &info->var.red); 663 val |= chan_to_field(green, &info->var.green); 664 val |= chan_to_field(blue, &info->var.blue); 665 666 pal[regno] = val; 667 ret = 0; 668 } 669 break; 670 671 case FB_VISUAL_PSEUDOCOLOR: 672 if (regno < 256) { 673 val = ((red >> 11) & 0x001f); 674 val |= ((green >> 6) & 0x03e0); 675 val |= ((blue >> 1) & 0x7c00); 676 677 /* 678 * TODO: intensity bit. Maybe something like 679 * ~(red[10] ^ green[10] ^ blue[10]) & 1 680 */ 681 682 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 683 ret = 0; 684 } 685 break; 686 687 case FB_VISUAL_MONO01: 688 if (regno < 2) { 689 val = (regno == 0) ? 0x00 : 0x1F; 690 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 691 ret = 0; 692 } 693 break; 694 695 } 696 697 return ret; 698} 699 700static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, 701 struct fb_info *info) 702{ 703 dev_dbg(info->device, "%s\n", __func__); 704 705 atmel_lcdfb_update_dma(info, var); 706 707 return 0; 708} 709 710static struct fb_ops atmel_lcdfb_ops = { 711 .owner = THIS_MODULE, 712 .fb_check_var = atmel_lcdfb_check_var, 713 .fb_set_par = atmel_lcdfb_set_par, 714 .fb_setcolreg = atmel_lcdfb_setcolreg, 715 .fb_pan_display = atmel_lcdfb_pan_display, 716 .fb_fillrect = cfb_fillrect, 717 .fb_copyarea = cfb_copyarea, 718 .fb_imageblit = cfb_imageblit, 719}; 720 721static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) 722{ 723 struct fb_info *info = dev_id; 724 struct atmel_lcdfb_info *sinfo = info->par; 725 u32 status; 726 727 status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); 728 if (status & ATMEL_LCDC_UFLWI) { 729 dev_warn(info->device, "FIFO underflow %#x\n", status); 730 /* reset DMA and FIFO to avoid screen shifting */ 731 schedule_work(&sinfo->task); 732 } 733 lcdc_writel(sinfo, ATMEL_LCDC_ICR, status); 734 return IRQ_HANDLED; 735} 736 737/* 738 * LCD controller task (to reset the LCD) 739 */ 740static void atmel_lcdfb_task(struct work_struct *work) 741{ 742 struct atmel_lcdfb_info *sinfo = 743 container_of(work, struct atmel_lcdfb_info, task); 744 745 atmel_lcdfb_reset(sinfo); 746} 747 748static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) 749{ 750 struct fb_info *info = sinfo->info; 751 int ret = 0; 752 753 info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; 754 755 dev_info(info->device, 756 "%luKiB frame buffer at %08lx (mapped at %p)\n", 757 (unsigned long)info->fix.smem_len / 1024, 758 (unsigned long)info->fix.smem_start, 759 info->screen_base); 760 761 /* Allocate colormap */ 762 ret = fb_alloc_cmap(&info->cmap, 256, 0); 763 if (ret < 0) 764 dev_err(info->device, "Alloc color map failed\n"); 765 766 return ret; 767} 768 769static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) 770{ 771 if (sinfo->bus_clk) 772 clk_enable(sinfo->bus_clk); 773 clk_enable(sinfo->lcdc_clk); 774} 775 776static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) 777{ 778 if (sinfo->bus_clk) 779 clk_disable(sinfo->bus_clk); 780 clk_disable(sinfo->lcdc_clk); 781} 782 783 784static int __init atmel_lcdfb_probe(struct platform_device *pdev) 785{ 786 struct device *dev = &pdev->dev; 787 struct fb_info *info; 788 struct atmel_lcdfb_info *sinfo; 789 struct atmel_lcdfb_info *pdata_sinfo; 790 struct fb_videomode fbmode; 791 struct resource *regs = NULL; 792 struct resource *map = NULL; 793 int ret; 794 795 dev_dbg(dev, "%s BEGIN\n", __func__); 796 797 ret = -ENOMEM; 798 info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); 799 if (!info) { 800 dev_err(dev, "cannot allocate memory\n"); 801 goto out; 802 } 803 804 sinfo = info->par; 805 806 if (dev->platform_data) { 807 pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data; 808 sinfo->default_bpp = pdata_sinfo->default_bpp; 809 sinfo->default_dmacon = pdata_sinfo->default_dmacon; 810 sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2; 811 sinfo->default_monspecs = pdata_sinfo->default_monspecs; 812 sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; 813 sinfo->guard_time = pdata_sinfo->guard_time; 814 sinfo->smem_len = pdata_sinfo->smem_len; 815 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; 816 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; 817 } else { 818 dev_err(dev, "cannot get default configuration\n"); 819 goto free_info; 820 } 821 sinfo->info = info; 822 sinfo->pdev = pdev; 823 824 strcpy(info->fix.id, sinfo->pdev->name); 825 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; 826 info->pseudo_palette = sinfo->pseudo_palette; 827 info->fbops = &atmel_lcdfb_ops; 828 829 memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); 830 info->fix = atmel_lcdfb_fix; 831 832 /* Enable LCDC Clocks */ 833 if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() 834 || cpu_is_at32ap7000()) { 835 sinfo->bus_clk = clk_get(dev, "hck1"); 836 if (IS_ERR(sinfo->bus_clk)) { 837 ret = PTR_ERR(sinfo->bus_clk); 838 goto free_info; 839 } 840 } 841 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); 842 if (IS_ERR(sinfo->lcdc_clk)) { 843 ret = PTR_ERR(sinfo->lcdc_clk); 844 goto put_bus_clk; 845 } 846 atmel_lcdfb_start_clock(sinfo); 847 848 ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, 849 info->monspecs.modedb_len, info->monspecs.modedb, 850 sinfo->default_bpp); 851 if (!ret) { 852 dev_err(dev, "no suitable video mode found\n"); 853 goto stop_clk; 854 } 855 856 857 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 858 if (!regs) { 859 dev_err(dev, "resources unusable\n"); 860 ret = -ENXIO; 861 goto stop_clk; 862 } 863 864 sinfo->irq_base = platform_get_irq(pdev, 0); 865 if (sinfo->irq_base < 0) { 866 dev_err(dev, "unable to get irq\n"); 867 ret = sinfo->irq_base; 868 goto stop_clk; 869 } 870 871 /* Initialize video memory */ 872 map = platform_get_resource(pdev, IORESOURCE_MEM, 1); 873 if (map) { 874 /* use a pre-allocated memory buffer */ 875 info->fix.smem_start = map->start; 876 info->fix.smem_len = map->end - map->start + 1; 877 if (!request_mem_region(info->fix.smem_start, 878 info->fix.smem_len, pdev->name)) { 879 ret = -EBUSY; 880 goto stop_clk; 881 } 882 883 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 884 if (!info->screen_base) 885 goto release_intmem; 886 887 /* 888 * Don't clear the framebuffer -- someone may have set 889 * up a splash image. 890 */ 891 } else { 892 /* alocate memory buffer */ 893 ret = atmel_lcdfb_alloc_video_memory(sinfo); 894 if (ret < 0) { 895 dev_err(dev, "cannot allocate framebuffer: %d\n", ret); 896 goto stop_clk; 897 } 898 } 899 900 /* LCDC registers */ 901 info->fix.mmio_start = regs->start; 902 info->fix.mmio_len = regs->end - regs->start + 1; 903 904 if (!request_mem_region(info->fix.mmio_start, 905 info->fix.mmio_len, pdev->name)) { 906 ret = -EBUSY; 907 goto free_fb; 908 } 909 910 sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); 911 if (!sinfo->mmio) { 912 dev_err(dev, "cannot map LCDC registers\n"); 913 goto release_mem; 914 } 915 916 /* Initialize PWM for contrast or backlight ("off") */ 917 init_contrast(sinfo); 918 919 /* interrupt */ 920 ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); 921 if (ret) { 922 dev_err(dev, "request_irq failed: %d\n", ret); 923 goto unmap_mmio; 924 } 925 926 /* Some operations on the LCDC might sleep and 927 * require a preemptible task context */ 928 INIT_WORK(&sinfo->task, atmel_lcdfb_task); 929 930 ret = atmel_lcdfb_init_fbinfo(sinfo); 931 if (ret < 0) { 932 dev_err(dev, "init fbinfo failed: %d\n", ret); 933 goto unregister_irqs; 934 } 935 936 /* 937 * This makes sure that our colour bitfield 938 * descriptors are correctly initialised. 939 */ 940 atmel_lcdfb_check_var(&info->var, info); 941 942 ret = fb_set_var(info, &info->var); 943 if (ret) { 944 dev_warn(dev, "unable to set display parameters\n"); 945 goto free_cmap; 946 } 947 948 dev_set_drvdata(dev, info); 949 950 /* 951 * Tell the world that we're ready to go 952 */ 953 ret = register_framebuffer(info); 954 if (ret < 0) { 955 dev_err(dev, "failed to register framebuffer device: %d\n", ret); 956 goto reset_drvdata; 957 } 958 959 /* add selected videomode to modelist */ 960 fb_var_to_videomode(&fbmode, &info->var); 961 fb_add_videomode(&fbmode, &info->modelist); 962 963 /* Power up the LCDC screen */ 964 if (sinfo->atmel_lcdfb_power_control) 965 sinfo->atmel_lcdfb_power_control(1); 966 967 dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n", 968 info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); 969 970 return 0; 971 972reset_drvdata: 973 dev_set_drvdata(dev, NULL); 974free_cmap: 975 fb_dealloc_cmap(&info->cmap); 976unregister_irqs: 977 cancel_work_sync(&sinfo->task); 978 free_irq(sinfo->irq_base, info); 979unmap_mmio: 980 exit_backlight(sinfo); 981 iounmap(sinfo->mmio); 982release_mem: 983 release_mem_region(info->fix.mmio_start, info->fix.mmio_len); 984free_fb: 985 if (map) 986 iounmap(info->screen_base); 987 else 988 atmel_lcdfb_free_video_memory(sinfo); 989 990release_intmem: 991 if (map) 992 release_mem_region(info->fix.smem_start, info->fix.smem_len); 993stop_clk: 994 atmel_lcdfb_stop_clock(sinfo); 995 clk_put(sinfo->lcdc_clk); 996put_bus_clk: 997 if (sinfo->bus_clk) 998 clk_put(sinfo->bus_clk); 999free_info: 1000 framebuffer_release(info); 1001out: 1002 dev_dbg(dev, "%s FAILED\n", __func__); 1003 return ret; 1004} 1005 1006static int __exit atmel_lcdfb_remove(struct platform_device *pdev) 1007{ 1008 struct device *dev = &pdev->dev; 1009 struct fb_info *info = dev_get_drvdata(dev); 1010 struct atmel_lcdfb_info *sinfo; 1011 1012 if (!info || !info->par) 1013 return 0; 1014 sinfo = info->par; 1015 1016 cancel_work_sync(&sinfo->task); 1017 exit_backlight(sinfo); 1018 if (sinfo->atmel_lcdfb_power_control) 1019 sinfo->atmel_lcdfb_power_control(0); 1020 unregister_framebuffer(info); 1021 atmel_lcdfb_stop_clock(sinfo); 1022 clk_put(sinfo->lcdc_clk); 1023 if (sinfo->bus_clk) 1024 clk_put(sinfo->bus_clk); 1025 fb_dealloc_cmap(&info->cmap); 1026 free_irq(sinfo->irq_base, info); 1027 iounmap(sinfo->mmio); 1028 release_mem_region(info->fix.mmio_start, info->fix.mmio_len); 1029 if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { 1030 iounmap(info->screen_base); 1031 release_mem_region(info->fix.smem_start, info->fix.smem_len); 1032 } else { 1033 atmel_lcdfb_free_video_memory(sinfo); 1034 } 1035 1036 dev_set_drvdata(dev, NULL); 1037 framebuffer_release(info); 1038 1039 return 0; 1040} 1041 1042#ifdef CONFIG_PM 1043 1044static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) 1045{ 1046 struct fb_info *info = platform_get_drvdata(pdev); 1047 struct atmel_lcdfb_info *sinfo = info->par; 1048 1049 /* 1050 * We don't want to handle interrupts while the clock is 1051 * stopped. It may take forever. 1052 */ 1053 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); 1054 1055 sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 1056 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); 1057 if (sinfo->atmel_lcdfb_power_control) 1058 sinfo->atmel_lcdfb_power_control(0); 1059 1060 atmel_lcdfb_stop(sinfo); 1061 atmel_lcdfb_stop_clock(sinfo); 1062 1063 return 0; 1064} 1065 1066static int atmel_lcdfb_resume(struct platform_device *pdev) 1067{ 1068 struct fb_info *info = platform_get_drvdata(pdev); 1069 struct atmel_lcdfb_info *sinfo = info->par; 1070 1071 atmel_lcdfb_start_clock(sinfo); 1072 atmel_lcdfb_start(sinfo); 1073 if (sinfo->atmel_lcdfb_power_control) 1074 sinfo->atmel_lcdfb_power_control(1); 1075 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); 1076 1077 /* Enable FIFO & DMA errors */ 1078 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI 1079 | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); 1080 1081 return 0; 1082} 1083 1084#else 1085#define atmel_lcdfb_suspend NULL 1086#define atmel_lcdfb_resume NULL 1087#endif 1088 1089static struct platform_driver atmel_lcdfb_driver = { 1090 .remove = __exit_p(atmel_lcdfb_remove), 1091 .suspend = atmel_lcdfb_suspend, 1092 .resume = atmel_lcdfb_resume, 1093 1094 .driver = { 1095 .name = "atmel_lcdfb", 1096 .owner = THIS_MODULE, 1097 }, 1098}; 1099 1100static int __init atmel_lcdfb_init(void) 1101{ 1102 return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); 1103} 1104 1105static void __exit atmel_lcdfb_exit(void) 1106{ 1107 platform_driver_unregister(&atmel_lcdfb_driver); 1108} 1109 1110module_init(atmel_lcdfb_init); 1111module_exit(atmel_lcdfb_exit); 1112 1113MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); 1114MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); 1115MODULE_LICENSE("GPL");