aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fsl-diu-fb.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2011-12-02 18:03:27 -0500
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-12-19 15:03:53 -0500
commitddd3d905436b572ebadc09dcf2d12ca5b37020a0 (patch)
treefe4a7c33c2184d2f4bd1a31b25f57825498d9e42 /drivers/video/fsl-diu-fb.c
parent2d9ae7ac48c91e15e693038bf0dff004f7872aaf (diff)
drivers/video: fsl-diu-fb: merge all allocated data into one block
The Freescale DIU driver allocates multiple blocks of memory, including multiple DMA buffers. Merge all of these blocks into one data structure. Specifically: 1) struct fsl_diu_data now contains everything that needs to be allocated, except for the framebuffers themselves. DMA'able objects are aligned correctly within the structure. 2) struct diu_addr is no longer needed, because we don't have to manage multiple blocks of DMA memory. 3) Since there's no diu_addr any more, macro DMA_ADDR is used to calculate the DMA address of any field in fsl_diu_data. 4) Functions allocate_buf() and free_buf() are no longer needed, because we now assume that dma_alloc_coherent() will allocate a page-aligned block, and everything is properly aligned with fsl_diu_data already, so we no longer need to align any memory blocks ourselves. 5) The "dummy" area descriptor is now defined separately from the other five ADs, so NUM_AOIS (previously called FSL_AOI_NUM) is now set to five instead of six. Previously, all six were combined together to avoid a separate call to allocate_buf() just for the dummy AD. 6) framebuffer_alloc() and framebuffer_release() are no longer used. The framebuffer is initialized manually. 7) Error handling is simplified since there's only one memory buffer allocated. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/fsl-diu-fb.c')
-rw-r--r--drivers/video/fsl-diu-fb.c326
1 files changed, 139 insertions, 187 deletions
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index a16beeb5f548..4d54188daa24 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -36,8 +36,7 @@
36#include <linux/fsl-diu-fb.h> 36#include <linux/fsl-diu-fb.h>
37#include "edid.h" 37#include "edid.h"
38 38
39#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ 39#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
40 /* 1 for plane 0, 2 for plane 1&2 each */
41 40
42/* HW cursor parameters */ 41/* HW cursor parameters */
43#define MAX_CURS 32 42#define MAX_CURS 32
@@ -49,12 +48,6 @@
49#define INT_PARERR 0x08 /* Display parameters error interrupt */ 48#define INT_PARERR 0x08 /* Display parameters error interrupt */
50#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ 49#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
51 50
52struct diu_addr {
53 void *vaddr; /* Virtual address */
54 dma_addr_t paddr; /* Physical address */
55 __u32 offset;
56};
57
58/* 51/*
59 * List of supported video modes 52 * List of supported video modes
60 * 53 *
@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
330 323
331static DEFINE_SPINLOCK(diu_lock); 324static DEFINE_SPINLOCK(diu_lock);
332 325
333struct fsl_diu_data {
334 struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
335 /*FSL_AOI_NUM has one dummy AOI */
336 struct device_attribute dev_attr;
337 struct diu_ad *dummy_ad;
338 void *dummy_aoi_virt;
339 unsigned int irq;
340 int fb_enabled;
341 enum fsl_diu_monitor_port monitor_port;
342 struct diu __iomem *diu_reg;
343 spinlock_t reg_lock;
344 struct diu_addr ad;
345 struct diu_addr gamma;
346 struct diu_addr pallete;
347 struct diu_addr cursor;
348};
349
350enum mfb_index { 326enum mfb_index {
351 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ 327 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
352 PLANE1_AOI0, /* Plane 1, first AOI */ 328 PLANE1_AOI0, /* Plane 1, first AOI */
@@ -370,6 +346,44 @@ struct mfb_info {
370 u8 *edid_data; 346 u8 *edid_data;
371}; 347};
372 348
349/**
350 * struct fsl_diu_data - per-DIU data structure
351 * @dma_addr: DMA address of this structure
352 * @fsl_diu_info: fb_info objects, one per AOI
353 * @dev_attr: sysfs structure
354 * @irq: IRQ
355 * @fb_enabled: TRUE if the DIU is enabled, FALSE if not
356 * @monitor_port: the monitor port this DIU is connected to
357 * @diu_reg: pointer to the DIU hardware registers
358 * @reg_lock: spinlock for register access
359 * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
360 * dummy_ad: DIU Area Descriptor for the dummy AOI
361 * @ad[]: Area Descriptors for each real AOI
362 * @gamma: gamma color table
363 * @cursor: hardware cursor data
364 *
365 * This data structure must be allocated with 32-byte alignment, so that the
366 * internal fields can be aligned properly.
367 */
368struct fsl_diu_data {
369 dma_addr_t dma_addr;
370 struct fb_info fsl_diu_info[NUM_AOIS];
371 struct mfb_info mfb[NUM_AOIS];
372 struct device_attribute dev_attr;
373 unsigned int irq;
374 int fb_enabled;
375 enum fsl_diu_monitor_port monitor_port;
376 struct diu __iomem *diu_reg;
377 spinlock_t reg_lock;
378 u8 dummy_aoi[4 * 4 * 4];
379 struct diu_ad dummy_ad __aligned(8);
380 struct diu_ad ad[NUM_AOIS] __aligned(8);
381 u8 gamma[256 * 3] __aligned(32);
382 u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
383} __aligned(32);
384
385/* Determine the DMA address of a member of the fsl_diu_data structure */
386#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
373 387
374static struct mfb_info mfb_template[] = { 388static struct mfb_info mfb_template[] = {
375 { 389 {
@@ -504,7 +518,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
504 wr_reg_wa(&hw->desc[0], ad->paddr); 518 wr_reg_wa(&hw->desc[0], ad->paddr);
505 break; 519 break;
506 case PLANE1_AOI0: 520 case PLANE1_AOI0:
507 cmfbi = machine_data->fsl_diu_info[2]->par; 521 cmfbi = &machine_data->mfb[2];
508 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ 522 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
509 if (cmfbi->count > 0) /* AOI1 open */ 523 if (cmfbi->count > 0) /* AOI1 open */
510 ad->next_ad = 524 ad->next_ad =
@@ -515,7 +529,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
515 } 529 }
516 break; 530 break;
517 case PLANE2_AOI0: 531 case PLANE2_AOI0:
518 cmfbi = machine_data->fsl_diu_info[4]->par; 532 cmfbi = &machine_data->mfb[4];
519 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ 533 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
520 if (cmfbi->count > 0) /* AOI1 open */ 534 if (cmfbi->count > 0) /* AOI1 open */
521 ad->next_ad = 535 ad->next_ad =
@@ -526,17 +540,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
526 } 540 }
527 break; 541 break;
528 case PLANE1_AOI1: 542 case PLANE1_AOI1:
529 pmfbi = machine_data->fsl_diu_info[1]->par; 543 pmfbi = &machine_data->mfb[1];
530 ad->next_ad = 0; 544 ad->next_ad = 0;
531 if (hw->desc[1] == machine_data->dummy_ad->paddr) 545 if (hw->desc[1] == machine_data->dummy_ad.paddr)
532 wr_reg_wa(&hw->desc[1], ad->paddr); 546 wr_reg_wa(&hw->desc[1], ad->paddr);
533 else /* AOI0 open */ 547 else /* AOI0 open */
534 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 548 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
535 break; 549 break;
536 case PLANE2_AOI1: 550 case PLANE2_AOI1:
537 pmfbi = machine_data->fsl_diu_info[3]->par; 551 pmfbi = &machine_data->mfb[3];
538 ad->next_ad = 0; 552 ad->next_ad = 0;
539 if (hw->desc[2] == machine_data->dummy_ad->paddr) 553 if (hw->desc[2] == machine_data->dummy_ad.paddr)
540 wr_reg_wa(&hw->desc[2], ad->paddr); 554 wr_reg_wa(&hw->desc[2], ad->paddr);
541 else /* AOI0 was open */ 555 else /* AOI0 was open */
542 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 556 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
@@ -553,47 +567,47 @@ static void fsl_diu_disable_panel(struct fb_info *info)
553 567
554 switch (mfbi->index) { 568 switch (mfbi->index) {
555 case PLANE0: 569 case PLANE0:
556 if (hw->desc[0] != machine_data->dummy_ad->paddr) 570 if (hw->desc[0] != machine_data->dummy_ad.paddr)
557 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); 571 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad.paddr);
558 break; 572 break;
559 case PLANE1_AOI0: 573 case PLANE1_AOI0:
560 cmfbi = machine_data->fsl_diu_info[2]->par; 574 cmfbi = &machine_data->mfb[2];
561 if (cmfbi->count > 0) /* AOI1 is open */ 575 if (cmfbi->count > 0) /* AOI1 is open */
562 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); 576 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
563 /* move AOI1 to the first */ 577 /* move AOI1 to the first */
564 else /* AOI1 was closed */ 578 else /* AOI1 was closed */
565 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 579 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad.paddr);
566 /* close AOI 0 */ 580 /* close AOI 0 */
567 break; 581 break;
568 case PLANE2_AOI0: 582 case PLANE2_AOI0:
569 cmfbi = machine_data->fsl_diu_info[4]->par; 583 cmfbi = &machine_data->mfb[4];
570 if (cmfbi->count > 0) /* AOI1 is open */ 584 if (cmfbi->count > 0) /* AOI1 is open */
571 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); 585 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
572 /* move AOI1 to the first */ 586 /* move AOI1 to the first */
573 else /* AOI1 was closed */ 587 else /* AOI1 was closed */
574 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 588 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad.paddr);
575 /* close AOI 0 */ 589 /* close AOI 0 */
576 break; 590 break;
577 case PLANE1_AOI1: 591 case PLANE1_AOI1:
578 pmfbi = machine_data->fsl_diu_info[1]->par; 592 pmfbi = &machine_data->mfb[1];
579 if (hw->desc[1] != ad->paddr) { 593 if (hw->desc[1] != ad->paddr) {
580 /* AOI1 is not the first in the chain */ 594 /* AOI1 is not the first in the chain */
581 if (pmfbi->count > 0) 595 if (pmfbi->count > 0)
582 /* AOI0 is open, must be the first */ 596 /* AOI0 is open, must be the first */
583 pmfbi->ad->next_ad = 0; 597 pmfbi->ad->next_ad = 0;
584 } else /* AOI1 is the first in the chain */ 598 } else /* AOI1 is the first in the chain */
585 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 599 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad.paddr);
586 /* close AOI 1 */ 600 /* close AOI 1 */
587 break; 601 break;
588 case PLANE2_AOI1: 602 case PLANE2_AOI1:
589 pmfbi = machine_data->fsl_diu_info[3]->par; 603 pmfbi = &machine_data->mfb[3];
590 if (hw->desc[2] != ad->paddr) { 604 if (hw->desc[2] != ad->paddr) {
591 /* AOI1 is not the first in the chain */ 605 /* AOI1 is not the first in the chain */
592 if (pmfbi->count > 0) 606 if (pmfbi->count > 0)
593 /* AOI0 is open, must be the first */ 607 /* AOI0 is open, must be the first */
594 pmfbi->ad->next_ad = 0; 608 pmfbi->ad->next_ad = 0;
595 } else /* AOI1 is the first in the chain */ 609 } else /* AOI1 is the first in the chain */
596 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 610 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad.paddr);
597 /* close AOI 1 */ 611 /* close AOI 1 */
598 break; 612 break;
599 } 613 }
@@ -633,8 +647,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
633 int lower_aoi_is_open, upper_aoi_is_open; 647 int lower_aoi_is_open, upper_aoi_is_open;
634 __u32 base_plane_width, base_plane_height, upper_aoi_height; 648 __u32 base_plane_width, base_plane_height, upper_aoi_height;
635 649
636 base_plane_width = machine_data->fsl_diu_info[0]->var.xres; 650 base_plane_width = machine_data->fsl_diu_info[0].var.xres;
637 base_plane_height = machine_data->fsl_diu_info[0]->var.yres; 651 base_plane_height = machine_data->fsl_diu_info[0].var.yres;
638 652
639 if (mfbi->x_aoi_d < 0) 653 if (mfbi->x_aoi_d < 0)
640 mfbi->x_aoi_d = 0; 654 mfbi->x_aoi_d = 0;
@@ -649,7 +663,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
649 break; 663 break;
650 case PLANE1_AOI0: 664 case PLANE1_AOI0:
651 case PLANE2_AOI0: 665 case PLANE2_AOI0:
652 lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; 666 lower_aoi_mfbi = machine_data->fsl_diu_info[index+1].par;
653 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; 667 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
654 if (var->xres > base_plane_width) 668 if (var->xres > base_plane_width)
655 var->xres = base_plane_width; 669 var->xres = base_plane_width;
@@ -667,9 +681,9 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
667 break; 681 break;
668 case PLANE1_AOI1: 682 case PLANE1_AOI1:
669 case PLANE2_AOI1: 683 case PLANE2_AOI1:
670 upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; 684 upper_aoi_mfbi = machine_data->fsl_diu_info[index-1].par;
671 upper_aoi_height = 685 upper_aoi_height =
672 machine_data->fsl_diu_info[index-1]->var.yres; 686 machine_data->fsl_diu_info[index-1].var.yres;
673 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; 687 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
674 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; 688 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
675 if (var->xres > base_plane_width) 689 if (var->xres > base_plane_width)
@@ -812,15 +826,15 @@ static void update_lcdc(struct fb_info *info)
812 struct fsl_diu_data *machine_data = mfbi->parent; 826 struct fsl_diu_data *machine_data = mfbi->parent;
813 struct diu __iomem *hw; 827 struct diu __iomem *hw;
814 int i, j; 828 int i, j;
815 char __iomem *cursor_base, *gamma_table_base; 829 u8 *gamma_table_base;
816 830
817 u32 temp; 831 u32 temp;
818 832
819 hw = machine_data->diu_reg; 833 hw = machine_data->diu_reg;
820 834
821 diu_ops.set_monitor_port(machine_data->monitor_port); 835 diu_ops.set_monitor_port(machine_data->monitor_port);
822 gamma_table_base = machine_data->gamma.vaddr; 836 gamma_table_base = machine_data->gamma;
823 cursor_base = machine_data->cursor.vaddr; 837
824 /* Prep for DIU init - gamma table, cursor table */ 838 /* Prep for DIU init - gamma table, cursor table */
825 839
826 for (i = 0; i <= 2; i++) 840 for (i = 0; i <= 2; i++)
@@ -828,14 +842,14 @@ static void update_lcdc(struct fb_info *info)
828 *gamma_table_base++ = j; 842 *gamma_table_base++ = j;
829 843
830 diu_ops.set_gamma_table(machine_data->monitor_port, 844 diu_ops.set_gamma_table(machine_data->monitor_port,
831 machine_data->gamma.vaddr); 845 machine_data->gamma);
832 846
833 disable_lcdc(info); 847 disable_lcdc(info);
834 848
835 /* Program DIU registers */ 849 /* Program DIU registers */
836 850
837 out_be32(&hw->gamma, machine_data->gamma.paddr); 851 out_be32(&hw->gamma, DMA_ADDR(machine_data, gamma));
838 out_be32(&hw->cursor, machine_data->cursor.paddr); 852 out_be32(&hw->cursor, DMA_ADDR(machine_data, cursor));
839 853
840 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ 854 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
841 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ 855 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
@@ -1423,37 +1437,6 @@ static int fsl_diu_resume(struct platform_device *ofdev)
1423#define fsl_diu_resume NULL 1437#define fsl_diu_resume NULL
1424#endif /* CONFIG_PM */ 1438#endif /* CONFIG_PM */
1425 1439
1426/* Align to 64-bit(8-byte), 32-byte, etc. */
1427static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
1428 u32 bytes_align)
1429{
1430 u32 offset;
1431 dma_addr_t mask;
1432
1433 buf->vaddr =
1434 dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
1435 GFP_DMA | __GFP_ZERO);
1436 if (!buf->vaddr)
1437 return -ENOMEM;
1438
1439 mask = bytes_align - 1;
1440 offset = buf->paddr & mask;
1441 if (offset) {
1442 buf->offset = bytes_align - offset;
1443 buf->paddr = buf->paddr + offset;
1444 } else
1445 buf->offset = 0;
1446
1447 return 0;
1448}
1449
1450static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
1451 u32 bytes_align)
1452{
1453 dma_free_coherent(dev, size + bytes_align, buf->vaddr,
1454 buf->paddr - buf->offset);
1455}
1456
1457static ssize_t store_monitor(struct device *device, 1440static ssize_t store_monitor(struct device *device,
1458 struct device_attribute *attr, const char *buf, size_t count) 1441 struct device_attribute *attr, const char *buf, size_t count)
1459{ 1442{
@@ -1468,11 +1451,10 @@ static ssize_t store_monitor(struct device *device,
1468 /* All AOIs need adjust pixel format 1451 /* All AOIs need adjust pixel format
1469 * fsl_diu_set_par only change the pixsel format here 1452 * fsl_diu_set_par only change the pixsel format here
1470 * unlikely to fail. */ 1453 * unlikely to fail. */
1471 fsl_diu_set_par(machine_data->fsl_diu_info[0]); 1454 unsigned int i;
1472 fsl_diu_set_par(machine_data->fsl_diu_info[1]); 1455
1473 fsl_diu_set_par(machine_data->fsl_diu_info[2]); 1456 for (i=0; i < NUM_AOIS; i++)
1474 fsl_diu_set_par(machine_data->fsl_diu_info[3]); 1457 fsl_diu_set_par(&machine_data->fsl_diu_info[i]);
1475 fsl_diu_set_par(machine_data->fsl_diu_info[4]);
1476 } 1458 }
1477 return count; 1459 return count;
1478} 1460}
@@ -1499,28 +1481,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1499{ 1481{
1500 struct device_node *np = pdev->dev.of_node; 1482 struct device_node *np = pdev->dev.of_node;
1501 struct mfb_info *mfbi; 1483 struct mfb_info *mfbi;
1502 phys_addr_t dummy_ad_addr = 0;
1503 int ret, i, error = 0;
1504 struct fsl_diu_data *machine_data; 1484 struct fsl_diu_data *machine_data;
1505 int diu_mode; 1485 int diu_mode;
1486 dma_addr_t dma_addr; /* DMA addr of machine_data struct */
1487 unsigned int i;
1488 int ret;
1506 1489
1507 machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); 1490 machine_data = dma_alloc_coherent(&pdev->dev,
1491 sizeof(struct fsl_diu_data), &dma_addr, GFP_DMA | __GFP_ZERO);
1508 if (!machine_data) 1492 if (!machine_data)
1509 return -ENOMEM; 1493 return -ENOMEM;
1494 machine_data->dma_addr = dma_addr;
1495
1496 /*
1497 * dma_alloc_coherent() uses a page allocator, so the address is
1498 * always page-aligned. We need the memory to be 32-byte aligned,
1499 * so that's good. However, if one day the allocator changes, we
1500 * need to catch that. It's not worth the effort to handle unaligned
1501 * alloctions now because it's highly unlikely to ever be a problem.
1502 */
1503 if ((unsigned long)machine_data & 31) {
1504 dev_err(&pdev->dev, "misaligned allocation");
1505 ret = -ENOMEM;
1506 goto error;
1507 }
1510 1508
1511 spin_lock_init(&machine_data->reg_lock); 1509 spin_lock_init(&machine_data->reg_lock);
1512 1510
1513 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1511 for (i = 0; i < NUM_AOIS; i++) {
1514 machine_data->fsl_diu_info[i] = 1512 struct fb_info *info = &machine_data->fsl_diu_info[i];
1515 framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev); 1513
1516 if (!machine_data->fsl_diu_info[i]) { 1514 info->device = &pdev->dev;
1517 dev_err(&pdev->dev, "cannot allocate memory\n"); 1515 info->par = &machine_data->mfb[i];
1518 ret = -ENOMEM; 1516
1519 goto error2; 1517 /*
1520 } 1518 * We store the physical address of the AD in the reserved
1521 mfbi = machine_data->fsl_diu_info[i]->par; 1519 * 'paddr' field of the AD itself.
1520 */
1521 machine_data->ad[i].paddr = DMA_ADDR(machine_data, ad[i]);
1522
1523 info->fix.smem_start = 0;
1524
1525 /* Initialize the AOI data structure */
1526 mfbi = info->par;
1522 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1527 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
1523 mfbi->parent = machine_data; 1528 mfbi->parent = machine_data;
1529 mfbi->ad = &machine_data->ad[i];
1524 1530
1525 if (mfbi->index == PLANE0) { 1531 if (mfbi->index == PLANE0) {
1526 const u8 *prop; 1532 const u8 *prop;
@@ -1538,7 +1544,7 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1538 if (!machine_data->diu_reg) { 1544 if (!machine_data->diu_reg) {
1539 dev_err(&pdev->dev, "cannot map DIU registers\n"); 1545 dev_err(&pdev->dev, "cannot map DIU registers\n");
1540 ret = -EFAULT; 1546 ret = -EFAULT;
1541 goto error2; 1547 goto error;
1542 } 1548 }
1543 1549
1544 diu_mode = in_be32(&machine_data->diu_reg->diu_mode); 1550 diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
@@ -1555,41 +1561,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1555 } 1561 }
1556 machine_data->monitor_port = monitor_port; 1562 machine_data->monitor_port = monitor_port;
1557 1563
1558 /* Area descriptor memory pool aligns to 64-bit boundary */ 1564 /* Initialize the dummy Area Descriptor */
1559 if (allocate_buf(&pdev->dev, &machine_data->ad, 1565 machine_data->dummy_ad.addr =
1560 sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) 1566 cpu_to_le32(DMA_ADDR(machine_data, dummy_aoi));
1561 return -ENOMEM; 1567 machine_data->dummy_ad.pix_fmt = 0x88882317;
1562 1568 machine_data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
1563 /* Get memory for Gamma Table - 32-byte aligned memory */ 1569 machine_data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
1564 if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { 1570 machine_data->dummy_ad.offset_xyi = 0;
1565 ret = -ENOMEM; 1571 machine_data->dummy_ad.offset_xyd = 0;
1566 goto error; 1572 machine_data->dummy_ad.next_ad = 0;
1567 } 1573 machine_data->dummy_ad.paddr = DMA_ADDR(machine_data, dummy_ad);
1568
1569 /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
1570 if (allocate_buf(&pdev->dev, &machine_data->cursor,
1571 MAX_CURS * MAX_CURS * 2, 32)) {
1572 ret = -ENOMEM;
1573 goto error;
1574 }
1575
1576 i = ARRAY_SIZE(machine_data->fsl_diu_info);
1577 machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
1578 machine_data->ad.offset) + i;
1579 machine_data->dummy_ad->paddr = machine_data->ad.paddr +
1580 i * sizeof(struct diu_ad);
1581 machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
1582 if (!machine_data->dummy_aoi_virt) {
1583 ret = -ENOMEM;
1584 goto error;
1585 }
1586 machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
1587 machine_data->dummy_ad->pix_fmt = 0x88882317;
1588 machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
1589 machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
1590 machine_data->dummy_ad->offset_xyi = 0;
1591 machine_data->dummy_ad->offset_xyd = 0;
1592 machine_data->dummy_ad->next_ad = 0;
1593 1574
1594 /* 1575 /*
1595 * Let DIU display splash screen if it was pre-initialized 1576 * Let DIU display splash screen if it was pre-initialized
@@ -1597,19 +1578,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1597 */ 1578 */
1598 if (diu_mode == MFB_MODE0) 1579 if (diu_mode == MFB_MODE0)
1599 out_be32(&machine_data->diu_reg->desc[0], 1580 out_be32(&machine_data->diu_reg->desc[0],
1600 machine_data->dummy_ad->paddr); 1581 machine_data->dummy_ad.paddr);
1601 1582
1602 out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); 1583 out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad.paddr);
1603 out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); 1584 out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad.paddr);
1604 1585
1605 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1586 for (i = 0; i < NUM_AOIS; i++) {
1606 machine_data->fsl_diu_info[i]->fix.smem_start = 0; 1587 ret = install_fb(&machine_data->fsl_diu_info[i]);
1607 mfbi = machine_data->fsl_diu_info[i]->par;
1608 mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
1609 + machine_data->ad.offset) + i;
1610 mfbi->ad->paddr =
1611 machine_data->ad.paddr + i * sizeof(struct diu_ad);
1612 ret = install_fb(machine_data->fsl_diu_info[i]);
1613 if (ret) { 1588 if (ret) {
1614 dev_err(&pdev->dev, "could not register fb %d\n", i); 1589 dev_err(&pdev->dev, "could not register fb %d\n", i);
1615 goto error; 1590 goto error;
@@ -1626,9 +1601,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1626 machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1601 machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
1627 machine_data->dev_attr.show = show_monitor; 1602 machine_data->dev_attr.show = show_monitor;
1628 machine_data->dev_attr.store = store_monitor; 1603 machine_data->dev_attr.store = store_monitor;
1629 error = device_create_file(machine_data->fsl_diu_info[0]->dev, 1604 ret = device_create_file(&pdev->dev, &machine_data->dev_attr);
1630 &machine_data->dev_attr); 1605 if (ret) {
1631 if (error) {
1632 dev_err(&pdev->dev, "could not create sysfs file %s\n", 1606 dev_err(&pdev->dev, "could not create sysfs file %s\n",
1633 machine_data->dev_attr.attr.name); 1607 machine_data->dev_attr.attr.name);
1634 } 1608 }
@@ -1637,26 +1611,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1637 return 0; 1611 return 0;
1638 1612
1639error: 1613error:
1640 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1614 for (i = 0; i < NUM_AOIS; i++)
1641 uninstall_fb(machine_data->fsl_diu_info[i]); 1615 uninstall_fb(&machine_data->fsl_diu_info[i]);
1642 1616
1643 if (machine_data->ad.vaddr)
1644 free_buf(&pdev->dev, &machine_data->ad,
1645 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
1646 if (machine_data->gamma.vaddr)
1647 free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
1648 if (machine_data->cursor.vaddr)
1649 free_buf(&pdev->dev, &machine_data->cursor,
1650 MAX_CURS * MAX_CURS * 2, 32);
1651 if (machine_data->dummy_aoi_virt)
1652 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1653 iounmap(machine_data->diu_reg); 1617 iounmap(machine_data->diu_reg);
1654 1618
1655error2: 1619 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
1656 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1620 machine_data, machine_data->dma_addr);
1657 if (machine_data->fsl_diu_info[i])
1658 framebuffer_release(machine_data->fsl_diu_info[i]);
1659 kfree(machine_data);
1660 1621
1661 return ret; 1622 return ret;
1662} 1623}
@@ -1667,25 +1628,16 @@ static int fsl_diu_remove(struct platform_device *pdev)
1667 int i; 1628 int i;
1668 1629
1669 machine_data = dev_get_drvdata(&pdev->dev); 1630 machine_data = dev_get_drvdata(&pdev->dev);
1670 disable_lcdc(machine_data->fsl_diu_info[0]); 1631 disable_lcdc(&machine_data->fsl_diu_info[0]);
1671 free_irq_local(machine_data); 1632 free_irq_local(machine_data);
1672 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1633
1673 uninstall_fb(machine_data->fsl_diu_info[i]); 1634 for (i = 0; i < NUM_AOIS; i++)
1674 if (machine_data->ad.vaddr) 1635 uninstall_fb(&machine_data->fsl_diu_info[i]);
1675 free_buf(&pdev->dev, &machine_data->ad, 1636
1676 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
1677 if (machine_data->gamma.vaddr)
1678 free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
1679 if (machine_data->cursor.vaddr)
1680 free_buf(&pdev->dev, &machine_data->cursor,
1681 MAX_CURS * MAX_CURS * 2, 32);
1682 if (machine_data->dummy_aoi_virt)
1683 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1684 iounmap(machine_data->diu_reg); 1637 iounmap(machine_data->diu_reg);
1685 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1638
1686 if (machine_data->fsl_diu_info[i]) 1639 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
1687 framebuffer_release(machine_data->fsl_diu_info[i]); 1640 machine_data, machine_data->dma_addr);
1688 kfree(machine_data);
1689 1641
1690 return 0; 1642 return 0;
1691} 1643}