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 v3.0-rc5 832 lines 20 kB view raw
1/* 2 * Frame buffer driver for ADV7393/2 video encoder 3 * 4 * Copyright 2006-2009 Analog Devices Inc. 5 * Licensed under the GPL-2 or late. 6 */ 7 8/* 9 * TODO: Remove Globals 10 * TODO: Code Cleanup 11 */ 12 13#define pr_fmt(fmt) DRIVER_NAME ": " fmt 14 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/errno.h> 18#include <linux/string.h> 19#include <linux/mm.h> 20#include <linux/tty.h> 21#include <linux/slab.h> 22#include <linux/delay.h> 23#include <linux/fb.h> 24#include <linux/ioport.h> 25#include <linux/init.h> 26#include <linux/types.h> 27#include <linux/interrupt.h> 28#include <linux/sched.h> 29#include <asm/blackfin.h> 30#include <asm/irq.h> 31#include <asm/dma.h> 32#include <linux/uaccess.h> 33#include <linux/gpio.h> 34#include <asm/portmux.h> 35 36#include <linux/dma-mapping.h> 37#include <linux/proc_fs.h> 38#include <linux/platform_device.h> 39 40#include <linux/i2c.h> 41#include <linux/i2c-dev.h> 42 43#include "bfin_adv7393fb.h" 44 45static int mode = VMODE; 46static int mem = VMEM; 47static int nocursor = 1; 48 49static const unsigned short ppi_pins[] = { 50 P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 51 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, 52 P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, 53 P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, 54 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 55 0 56}; 57 58/* 59 * card parameters 60 */ 61 62static struct bfin_adv7393_fb_par { 63 /* structure holding blackfin / adv7393 paramters when 64 screen is blanked */ 65 struct { 66 u8 Mode; /* ntsc/pal/? */ 67 } vga_state; 68 atomic_t ref_count; 69} bfin_par; 70 71/* --------------------------------------------------------------------- */ 72 73static struct fb_var_screeninfo bfin_adv7393_fb_defined = { 74 .xres = 720, 75 .yres = 480, 76 .xres_virtual = 720, 77 .yres_virtual = 480, 78 .bits_per_pixel = 16, 79 .activate = FB_ACTIVATE_TEST, 80 .height = -1, 81 .width = -1, 82 .left_margin = 0, 83 .right_margin = 0, 84 .upper_margin = 0, 85 .lower_margin = 0, 86 .vmode = FB_VMODE_INTERLACED, 87 .red = {11, 5, 0}, 88 .green = {5, 6, 0}, 89 .blue = {0, 5, 0}, 90 .transp = {0, 0, 0}, 91}; 92 93static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = { 94 .id = "BFIN ADV7393", 95 .smem_len = 720 * 480 * 2, 96 .type = FB_TYPE_PACKED_PIXELS, 97 .visual = FB_VISUAL_TRUECOLOR, 98 .xpanstep = 0, 99 .ypanstep = 0, 100 .line_length = 720 * 2, 101 .accel = FB_ACCEL_NONE 102}; 103 104static struct fb_ops bfin_adv7393_fb_ops = { 105 .owner = THIS_MODULE, 106 .fb_open = bfin_adv7393_fb_open, 107 .fb_release = bfin_adv7393_fb_release, 108 .fb_check_var = bfin_adv7393_fb_check_var, 109 .fb_pan_display = bfin_adv7393_fb_pan_display, 110 .fb_blank = bfin_adv7393_fb_blank, 111 .fb_fillrect = cfb_fillrect, 112 .fb_copyarea = cfb_copyarea, 113 .fb_imageblit = cfb_imageblit, 114 .fb_cursor = bfin_adv7393_fb_cursor, 115 .fb_setcolreg = bfin_adv7393_fb_setcolreg, 116}; 117 118static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg) 119{ 120 if (arg == BUILD) { /* Build */ 121 fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg)); 122 if (fbdev->vb1 == NULL) 123 goto error; 124 125 fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg)); 126 if (fbdev->av1 == NULL) 127 goto error; 128 129 fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg)); 130 if (fbdev->vb2 == NULL) 131 goto error; 132 133 fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg)); 134 if (fbdev->av2 == NULL) 135 goto error; 136 137 /* Build linked DMA descriptor list */ 138 fbdev->vb1->next_desc_addr = fbdev->av1; 139 fbdev->av1->next_desc_addr = fbdev->vb2; 140 fbdev->vb2->next_desc_addr = fbdev->av2; 141 fbdev->av2->next_desc_addr = fbdev->vb1; 142 143 /* Save list head */ 144 fbdev->descriptor_list_head = fbdev->av2; 145 146 /* Vertical Blanking Field 1 */ 147 fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE; 148 fbdev->vb1->cfg = DMA_CFG_VAL; 149 150 fbdev->vb1->x_count = 151 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; 152 153 fbdev->vb1->x_modify = 0; 154 fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines; 155 fbdev->vb1->y_modify = 0; 156 157 /* Active Video Field 1 */ 158 159 fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem; 160 fbdev->av1->cfg = DMA_CFG_VAL; 161 fbdev->av1->x_count = 162 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; 163 fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8; 164 fbdev->av1->y_count = fbdev->modes[mode].a_lines; 165 fbdev->av1->y_modify = 166 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank + 167 1) * (fbdev->modes[mode].bpp / 8); 168 169 /* Vertical Blanking Field 2 */ 170 171 fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE; 172 fbdev->vb2->cfg = DMA_CFG_VAL; 173 fbdev->vb2->x_count = 174 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; 175 176 fbdev->vb2->x_modify = 0; 177 fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines; 178 fbdev->vb2->y_modify = 0; 179 180 /* Active Video Field 2 */ 181 182 fbdev->av2->start_addr = 183 (unsigned long)fbdev->fb_mem + fbdev->line_len; 184 185 fbdev->av2->cfg = DMA_CFG_VAL; 186 187 fbdev->av2->x_count = 188 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; 189 190 fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8); 191 fbdev->av2->y_count = fbdev->modes[mode].a_lines; 192 193 fbdev->av2->y_modify = 194 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank + 195 1) * (fbdev->modes[mode].bpp / 8); 196 197 return 1; 198 } 199 200error: 201 l1_data_sram_free(fbdev->vb1); 202 l1_data_sram_free(fbdev->av1); 203 l1_data_sram_free(fbdev->vb2); 204 l1_data_sram_free(fbdev->av2); 205 206 return 0; 207} 208 209static int bfin_config_dma(struct adv7393fb_device *fbdev) 210{ 211 BUG_ON(!(fbdev->fb_mem)); 212 213 set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count); 214 set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify); 215 set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count); 216 set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify); 217 set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr); 218 set_dma_next_desc_addr(CH_PPI, 219 fbdev->descriptor_list_head->next_desc_addr); 220 set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg); 221 222 return 1; 223} 224 225static void bfin_disable_dma(void) 226{ 227 bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN); 228} 229 230static void bfin_config_ppi(struct adv7393fb_device *fbdev) 231{ 232 if (ANOMALY_05000183) { 233 bfin_write_TIMER2_CONFIG(WDTH_CAP); 234 bfin_write_TIMER_ENABLE(TIMEN2); 235 } 236 237 bfin_write_PPI_CONTROL(0x381E); 238 bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines); 239 bfin_write_PPI_COUNT(fbdev->modes[mode].xres + 240 fbdev->modes[mode].boeft_blank - 1); 241 bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1); 242} 243 244static void bfin_enable_ppi(void) 245{ 246 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); 247} 248 249static void bfin_disable_ppi(void) 250{ 251 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); 252} 253 254static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value) 255{ 256 return i2c_smbus_write_byte_data(client, reg, value); 257} 258 259static inline int adv7393_read(struct i2c_client *client, u8 reg) 260{ 261 return i2c_smbus_read_byte_data(client, reg); 262} 263 264static int 265adv7393_write_block(struct i2c_client *client, 266 const u8 *data, unsigned int len) 267{ 268 int ret = -1; 269 u8 reg; 270 271 while (len >= 2) { 272 reg = *data++; 273 ret = adv7393_write(client, reg, *data++); 274 if (ret < 0) 275 break; 276 len -= 2; 277 } 278 279 return ret; 280} 281 282static int adv7393_mode(struct i2c_client *client, u16 mode) 283{ 284 switch (mode) { 285 case POWER_ON: /* ADV7393 Sleep mode OFF */ 286 adv7393_write(client, 0x00, 0x1E); 287 break; 288 case POWER_DOWN: /* ADV7393 Sleep mode ON */ 289 adv7393_write(client, 0x00, 0x1F); 290 break; 291 case BLANK_OFF: /* Pixel Data Valid */ 292 adv7393_write(client, 0x82, 0xCB); 293 break; 294 case BLANK_ON: /* Pixel Data Invalid */ 295 adv7393_write(client, 0x82, 0x8B); 296 break; 297 default: 298 return -EINVAL; 299 break; 300 } 301 return 0; 302} 303 304static irqreturn_t ppi_irq_error(int irq, void *dev_id) 305{ 306 307 struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id; 308 309 u16 status = bfin_read_PPI_STATUS(); 310 311 pr_debug("%s: PPI Status = 0x%X\n", __func__, status); 312 313 if (status) { 314 bfin_disable_dma(); /* TODO: Check Sequence */ 315 bfin_disable_ppi(); 316 bfin_clear_PPI_STATUS(); 317 bfin_config_dma(fbdev); 318 bfin_enable_ppi(); 319 } 320 321 return IRQ_HANDLED; 322 323} 324 325static int proc_output(char *buf) 326{ 327 char *p = buf; 328 329 p += sprintf(p, 330 "Usage:\n" 331 "echo 0x[REG][Value] > adv7393\n" 332 "example: echo 0x1234 >adv7393\n" 333 "writes 0x34 into Register 0x12\n"); 334 335 return p - buf; 336} 337 338static int 339adv7393_read_proc(char *page, char **start, off_t off, 340 int count, int *eof, void *data) 341{ 342 int len; 343 344 len = proc_output(page); 345 if (len <= off + count) 346 *eof = 1; 347 *start = page + off; 348 len -= off; 349 if (len > count) 350 len = count; 351 if (len < 0) 352 len = 0; 353 return len; 354} 355 356static int 357adv7393_write_proc(struct file *file, const char __user * buffer, 358 unsigned long count, void *data) 359{ 360 struct adv7393fb_device *fbdev = data; 361 char line[8]; 362 unsigned int val; 363 int ret; 364 365 ret = copy_from_user(line, buffer, count); 366 if (ret) 367 return -EFAULT; 368 369 val = simple_strtoul(line, NULL, 0); 370 adv7393_write(fbdev->client, val >> 8, val & 0xff); 371 372 return count; 373} 374 375static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, 376 const struct i2c_device_id *id) 377{ 378 int ret = 0; 379 struct proc_dir_entry *entry; 380 int num_modes = ARRAY_SIZE(known_modes); 381 382 struct adv7393fb_device *fbdev = NULL; 383 384 if (mem > 2) { 385 dev_err(&client->dev, "mem out of allowed range [1;2]\n"); 386 return -EINVAL; 387 } 388 389 if (mode > num_modes) { 390 dev_err(&client->dev, "mode %d: not supported", mode); 391 return -EFAULT; 392 } 393 394 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); 395 if (!fbdev) { 396 dev_err(&client->dev, "failed to allocate device private record"); 397 return -ENOMEM; 398 } 399 400 i2c_set_clientdata(client, fbdev); 401 402 fbdev->modes = known_modes; 403 fbdev->client = client; 404 405 fbdev->fb_len = 406 mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres * 407 (fbdev->modes[mode].bpp / 8); 408 409 fbdev->line_len = 410 fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8); 411 412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */ 413 if (ANOMALY_05000400) { 414 if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) { 415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); 416 ret = -EBUSY; 417 goto out_8; 418 } 419 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0); 420 } 421 422 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { 423 dev_err(&client->dev, "requesting PPI peripheral failed\n"); 424 ret = -EFAULT; 425 goto out_8; 426 } 427 428 fbdev->fb_mem = 429 dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle, 430 GFP_KERNEL); 431 432 if (NULL == fbdev->fb_mem) { 433 dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n", 434 (u32) fbdev->fb_len); 435 ret = -ENOMEM; 436 goto out_7; 437 } 438 439 fbdev->info.screen_base = (void *)fbdev->fb_mem; 440 bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem; 441 442 bfin_adv7393_fb_fix.smem_len = fbdev->fb_len; 443 bfin_adv7393_fb_fix.line_length = fbdev->line_len; 444 445 if (mem > 1) 446 bfin_adv7393_fb_fix.ypanstep = 1; 447 448 bfin_adv7393_fb_defined.red.length = 5; 449 bfin_adv7393_fb_defined.green.length = 6; 450 bfin_adv7393_fb_defined.blue.length = 5; 451 452 bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres; 453 bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres; 454 bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres; 455 bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres; 456 bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp; 457 458 fbdev->info.fbops = &bfin_adv7393_fb_ops; 459 fbdev->info.var = bfin_adv7393_fb_defined; 460 fbdev->info.fix = bfin_adv7393_fb_fix; 461 fbdev->info.par = &bfin_par; 462 fbdev->info.flags = FBINFO_DEFAULT; 463 464 fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); 465 if (!fbdev->info.pseudo_palette) { 466 dev_err(&client->dev, "failed to allocate pseudo_palette\n"); 467 ret = -ENOMEM; 468 goto out_6; 469 } 470 471 if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { 472 dev_err(&client->dev, "failed to allocate colormap (%d entries)\n", 473 BFIN_LCD_NBR_PALETTE_ENTRIES); 474 ret = -EFAULT; 475 goto out_5; 476 } 477 478 if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) { 479 dev_err(&client->dev, "unable to request PPI DMA\n"); 480 ret = -EFAULT; 481 goto out_4; 482 } 483 484 if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED, 485 "PPI ERROR", fbdev) < 0) { 486 dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); 487 ret = -EFAULT; 488 goto out_3; 489 } 490 491 fbdev->open = 0; 492 493 ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd, 494 fbdev->modes[mode].adv7393_i2c_initd_len); 495 496 if (ret) { 497 dev_err(&client->dev, "i2c attach: init error\n"); 498 goto out_1; 499 } 500 501 502 if (register_framebuffer(&fbdev->info) < 0) { 503 dev_err(&client->dev, "unable to register framebuffer\n"); 504 ret = -EFAULT; 505 goto out_1; 506 } 507 508 dev_info(&client->dev, "fb%d: %s frame buffer device\n", 509 fbdev->info.node, fbdev->info.fix.id); 510 dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem); 511 512 entry = create_proc_entry("driver/adv7393", 0, NULL); 513 if (!entry) { 514 dev_err(&client->dev, "unable to create /proc entry\n"); 515 ret = -EFAULT; 516 goto out_0; 517 } 518 519 entry->read_proc = adv7393_read_proc; 520 entry->write_proc = adv7393_write_proc; 521 entry->data = fbdev; 522 523 return 0; 524 525 out_0: 526 unregister_framebuffer(&fbdev->info); 527 out_1: 528 free_irq(IRQ_PPI_ERROR, fbdev); 529 out_3: 530 free_dma(CH_PPI); 531 out_4: 532 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, 533 fbdev->dma_handle); 534 out_5: 535 fb_dealloc_cmap(&fbdev->info.cmap); 536 out_6: 537 kfree(fbdev->info.pseudo_palette); 538 out_7: 539 peripheral_free_list(ppi_pins); 540 out_8: 541 kfree(fbdev); 542 543 return ret; 544} 545 546static int bfin_adv7393_fb_open(struct fb_info *info, int user) 547{ 548 struct adv7393fb_device *fbdev = to_adv7393fb_device(info); 549 550 fbdev->info.screen_base = (void *)fbdev->fb_mem; 551 if (!fbdev->info.screen_base) { 552 dev_err(&fbdev->client->dev, "unable to map device\n"); 553 return -ENOMEM; 554 } 555 556 fbdev->open = 1; 557 dma_desc_list(fbdev, BUILD); 558 adv7393_mode(fbdev->client, BLANK_OFF); 559 bfin_config_ppi(fbdev); 560 bfin_config_dma(fbdev); 561 bfin_enable_ppi(); 562 563 return 0; 564} 565 566static int bfin_adv7393_fb_release(struct fb_info *info, int user) 567{ 568 struct adv7393fb_device *fbdev = to_adv7393fb_device(info); 569 570 adv7393_mode(fbdev->client, BLANK_ON); 571 bfin_disable_dma(); 572 bfin_disable_ppi(); 573 dma_desc_list(fbdev, DESTRUCT); 574 fbdev->open = 0; 575 return 0; 576} 577 578static int 579bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 580{ 581 582 switch (var->bits_per_pixel) { 583 case 16:/* DIRECTCOLOUR, 64k */ 584 var->red.offset = info->var.red.offset; 585 var->green.offset = info->var.green.offset; 586 var->blue.offset = info->var.blue.offset; 587 var->red.length = info->var.red.length; 588 var->green.length = info->var.green.length; 589 var->blue.length = info->var.blue.length; 590 var->transp.offset = 0; 591 var->transp.length = 0; 592 var->transp.msb_right = 0; 593 var->red.msb_right = 0; 594 var->green.msb_right = 0; 595 var->blue.msb_right = 0; 596 break; 597 default: 598 pr_debug("%s: depth not supported: %u BPP\n", __func__, 599 var->bits_per_pixel); 600 return -EINVAL; 601 } 602 603 if (info->var.xres != var->xres || 604 info->var.yres != var->yres || 605 info->var.xres_virtual != var->xres_virtual || 606 info->var.yres_virtual != var->yres_virtual) { 607 pr_debug("%s: Resolution not supported: X%u x Y%u\n", 608 __func__, var->xres, var->yres); 609 return -EINVAL; 610 } 611 612 /* 613 * Memory limit 614 */ 615 616 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { 617 pr_debug("%s: Memory Limit requested yres_virtual = %u\n", 618 __func__, var->yres_virtual); 619 return -ENOMEM; 620 } 621 622 return 0; 623} 624 625static int 626bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 627{ 628 int dy; 629 u32 dmaaddr; 630 struct adv7393fb_device *fbdev = to_adv7393fb_device(info); 631 632 if (!var || !info) 633 return -EINVAL; 634 635 if (var->xoffset - info->var.xoffset) { 636 /* No support for X panning for now! */ 637 return -EINVAL; 638 } 639 dy = var->yoffset - info->var.yoffset; 640 641 if (dy) { 642 pr_debug("%s: Panning screen of %d lines\n", __func__, dy); 643 644 dmaaddr = fbdev->av1->start_addr; 645 dmaaddr += (info->fix.line_length * dy); 646 /* TODO: Wait for current frame to finished */ 647 648 fbdev->av1->start_addr = (unsigned long)dmaaddr; 649 fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len; 650 } 651 652 return 0; 653 654} 655 656/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ 657static int bfin_adv7393_fb_blank(int blank, struct fb_info *info) 658{ 659 struct adv7393fb_device *fbdev = to_adv7393fb_device(info); 660 661 switch (blank) { 662 663 case VESA_NO_BLANKING: 664 /* Turn on panel */ 665 adv7393_mode(fbdev->client, BLANK_OFF); 666 break; 667 668 case VESA_VSYNC_SUSPEND: 669 case VESA_HSYNC_SUSPEND: 670 case VESA_POWERDOWN: 671 /* Turn off panel */ 672 adv7393_mode(fbdev->client, BLANK_ON); 673 break; 674 675 default: 676 return -EINVAL; 677 break; 678 } 679 return 0; 680} 681 682int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 683{ 684 if (nocursor) 685 return 0; 686 else 687 return -EINVAL; /* just to force soft_cursor() call */ 688} 689 690static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green, 691 u_int blue, u_int transp, 692 struct fb_info *info) 693{ 694 if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) 695 return -EINVAL; 696 697 if (info->var.grayscale) 698 /* grayscale = 0.30*R + 0.59*G + 0.11*B */ 699 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 700 701 if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 702 u32 value; 703 /* Place color in the pseudopalette */ 704 if (regno > 16) 705 return -EINVAL; 706 707 red >>= (16 - info->var.red.length); 708 green >>= (16 - info->var.green.length); 709 blue >>= (16 - info->var.blue.length); 710 711 value = (red << info->var.red.offset) | 712 (green << info->var.green.offset)| 713 (blue << info->var.blue.offset); 714 value &= 0xFFFF; 715 716 ((u32 *) (info->pseudo_palette))[regno] = value; 717 } 718 719 return 0; 720} 721 722static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client) 723{ 724 struct adv7393fb_device *fbdev = i2c_get_clientdata(client); 725 726 adv7393_mode(client, POWER_DOWN); 727 728 if (fbdev->fb_mem) 729 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle); 730 free_dma(CH_PPI); 731 free_irq(IRQ_PPI_ERROR, fbdev); 732 unregister_framebuffer(&fbdev->info); 733 remove_proc_entry("driver/adv7393", NULL); 734 fb_dealloc_cmap(&fbdev->info.cmap); 735 kfree(fbdev->info.pseudo_palette); 736 737 if (ANOMALY_05000400) 738 gpio_free(P_IDENT(P_PPI0_FS3)); /* FS3 */ 739 peripheral_free_list(ppi_pins); 740 kfree(fbdev); 741 742 return 0; 743} 744 745#ifdef CONFIG_PM 746static int bfin_adv7393_fb_suspend(struct device *dev) 747{ 748 struct adv7393fb_device *fbdev = dev_get_drvdata(dev); 749 750 if (fbdev->open) { 751 bfin_disable_dma(); 752 bfin_disable_ppi(); 753 dma_desc_list(fbdev, DESTRUCT); 754 } 755 adv7393_mode(fbdev->client, POWER_DOWN); 756 757 return 0; 758} 759 760static int bfin_adv7393_fb_resume(struct device *dev) 761{ 762 struct adv7393fb_device *fbdev = dev_get_drvdata(dev); 763 764 adv7393_mode(fbdev->client, POWER_ON); 765 766 if (fbdev->open) { 767 dma_desc_list(fbdev, BUILD); 768 bfin_config_ppi(fbdev); 769 bfin_config_dma(fbdev); 770 bfin_enable_ppi(); 771 } 772 773 return 0; 774} 775 776static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = { 777 .suspend = bfin_adv7393_fb_suspend, 778 .resume = bfin_adv7393_fb_resume, 779}; 780#endif 781 782static const struct i2c_device_id bfin_adv7393_id[] = { 783 {DRIVER_NAME, 0}, 784 {} 785}; 786 787MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id); 788 789static struct i2c_driver bfin_adv7393_fb_driver = { 790 .driver = { 791 .name = DRIVER_NAME, 792#ifdef CONFIG_PM 793 .pm = &bfin_adv7393_dev_pm_ops, 794#endif 795 }, 796 .probe = bfin_adv7393_fb_probe, 797 .remove = __devexit_p(bfin_adv7393_fb_remove), 798 .id_table = bfin_adv7393_id, 799}; 800 801static int __init bfin_adv7393_fb_driver_init(void) 802{ 803#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) 804 request_module("i2c-bfin-twi"); 805#else 806 request_module("i2c-gpio"); 807#endif 808 809 return i2c_add_driver(&bfin_adv7393_fb_driver); 810} 811module_init(bfin_adv7393_fb_driver_init); 812 813static void __exit bfin_adv7393_fb_driver_cleanup(void) 814{ 815 i2c_del_driver(&bfin_adv7393_fb_driver); 816} 817module_exit(bfin_adv7393_fb_driver_cleanup); 818 819MODULE_LICENSE("GPL"); 820MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 821MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder"); 822 823module_param(mode, int, 0); 824MODULE_PARM_DESC(mode, 825 "Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)"); 826 827module_param(mem, int, 0); 828MODULE_PARM_DESC(mem, 829 "Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)"); 830 831module_param(nocursor, int, 0644); 832MODULE_PARM_DESC(nocursor, "cursor enable/disable");