Commit ddd3d905 authored by Timur Tabi's avatar Timur Tabi Committed by Florian Tobias Schandinat

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: default avatarTimur Tabi <timur@freescale.com>
Signed-off-by: default avatarFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>
parent 2d9ae7ac
...@@ -36,8 +36,7 @@ ...@@ -36,8 +36,7 @@
#include <linux/fsl-diu-fb.h> #include <linux/fsl-diu-fb.h>
#include "edid.h" #include "edid.h"
#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ #define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
/* 1 for plane 0, 2 for plane 1&2 each */
/* HW cursor parameters */ /* HW cursor parameters */
#define MAX_CURS 32 #define MAX_CURS 32
...@@ -49,12 +48,6 @@ ...@@ -49,12 +48,6 @@
#define INT_PARERR 0x08 /* Display parameters error interrupt */ #define INT_PARERR 0x08 /* Display parameters error interrupt */
#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
struct diu_addr {
void *vaddr; /* Virtual address */
dma_addr_t paddr; /* Physical address */
__u32 offset;
};
/* /*
* List of supported video modes * List of supported video modes
* *
...@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size; ...@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
static DEFINE_SPINLOCK(diu_lock); static DEFINE_SPINLOCK(diu_lock);
struct fsl_diu_data {
struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
/*FSL_AOI_NUM has one dummy AOI */
struct device_attribute dev_attr;
struct diu_ad *dummy_ad;
void *dummy_aoi_virt;
unsigned int irq;
int fb_enabled;
enum fsl_diu_monitor_port monitor_port;
struct diu __iomem *diu_reg;
spinlock_t reg_lock;
struct diu_addr ad;
struct diu_addr gamma;
struct diu_addr pallete;
struct diu_addr cursor;
};
enum mfb_index { enum mfb_index {
PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
PLANE1_AOI0, /* Plane 1, first AOI */ PLANE1_AOI0, /* Plane 1, first AOI */
...@@ -370,6 +346,44 @@ struct mfb_info { ...@@ -370,6 +346,44 @@ struct mfb_info {
u8 *edid_data; u8 *edid_data;
}; };
/**
* struct fsl_diu_data - per-DIU data structure
* @dma_addr: DMA address of this structure
* @fsl_diu_info: fb_info objects, one per AOI
* @dev_attr: sysfs structure
* @irq: IRQ
* @fb_enabled: TRUE if the DIU is enabled, FALSE if not
* @monitor_port: the monitor port this DIU is connected to
* @diu_reg: pointer to the DIU hardware registers
* @reg_lock: spinlock for register access
* @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
* dummy_ad: DIU Area Descriptor for the dummy AOI
* @ad[]: Area Descriptors for each real AOI
* @gamma: gamma color table
* @cursor: hardware cursor data
*
* This data structure must be allocated with 32-byte alignment, so that the
* internal fields can be aligned properly.
*/
struct fsl_diu_data {
dma_addr_t dma_addr;
struct fb_info fsl_diu_info[NUM_AOIS];
struct mfb_info mfb[NUM_AOIS];
struct device_attribute dev_attr;
unsigned int irq;
int fb_enabled;
enum fsl_diu_monitor_port monitor_port;
struct diu __iomem *diu_reg;
spinlock_t reg_lock;
u8 dummy_aoi[4 * 4 * 4];
struct diu_ad dummy_ad __aligned(8);
struct diu_ad ad[NUM_AOIS] __aligned(8);
u8 gamma[256 * 3] __aligned(32);
u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
} __aligned(32);
/* Determine the DMA address of a member of the fsl_diu_data structure */
#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
static struct mfb_info mfb_template[] = { static struct mfb_info mfb_template[] = {
{ {
...@@ -504,7 +518,7 @@ static void fsl_diu_enable_panel(struct fb_info *info) ...@@ -504,7 +518,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
wr_reg_wa(&hw->desc[0], ad->paddr); wr_reg_wa(&hw->desc[0], ad->paddr);
break; break;
case PLANE1_AOI0: case PLANE1_AOI0:
cmfbi = machine_data->fsl_diu_info[2]->par; cmfbi = &machine_data->mfb[2];
if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
if (cmfbi->count > 0) /* AOI1 open */ if (cmfbi->count > 0) /* AOI1 open */
ad->next_ad = ad->next_ad =
...@@ -515,7 +529,7 @@ static void fsl_diu_enable_panel(struct fb_info *info) ...@@ -515,7 +529,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
} }
break; break;
case PLANE2_AOI0: case PLANE2_AOI0:
cmfbi = machine_data->fsl_diu_info[4]->par; cmfbi = &machine_data->mfb[4];
if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
if (cmfbi->count > 0) /* AOI1 open */ if (cmfbi->count > 0) /* AOI1 open */
ad->next_ad = ad->next_ad =
...@@ -526,17 +540,17 @@ static void fsl_diu_enable_panel(struct fb_info *info) ...@@ -526,17 +540,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
} }
break; break;
case PLANE1_AOI1: case PLANE1_AOI1:
pmfbi = machine_data->fsl_diu_info[1]->par; pmfbi = &machine_data->mfb[1];
ad->next_ad = 0; ad->next_ad = 0;
if (hw->desc[1] == machine_data->dummy_ad->paddr) if (hw->desc[1] == machine_data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[1], ad->paddr); wr_reg_wa(&hw->desc[1], ad->paddr);
else /* AOI0 open */ else /* AOI0 open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
break; break;
case PLANE2_AOI1: case PLANE2_AOI1:
pmfbi = machine_data->fsl_diu_info[3]->par; pmfbi = &machine_data->mfb[3];
ad->next_ad = 0; ad->next_ad = 0;
if (hw->desc[2] == machine_data->dummy_ad->paddr) if (hw->desc[2] == machine_data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[2], ad->paddr); wr_reg_wa(&hw->desc[2], ad->paddr);
else /* AOI0 was open */ else /* AOI0 was open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
...@@ -553,47 +567,47 @@ static void fsl_diu_disable_panel(struct fb_info *info) ...@@ -553,47 +567,47 @@ static void fsl_diu_disable_panel(struct fb_info *info)
switch (mfbi->index) { switch (mfbi->index) {
case PLANE0: case PLANE0:
if (hw->desc[0] != machine_data->dummy_ad->paddr) if (hw->desc[0] != machine_data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[0], machine_data->dummy_ad.paddr);
break; break;
case PLANE1_AOI0: case PLANE1_AOI0:
cmfbi = machine_data->fsl_diu_info[2]->par; cmfbi = &machine_data->mfb[2];
if (cmfbi->count > 0) /* AOI1 is open */ if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
/* move AOI1 to the first */ /* move AOI1 to the first */
else /* AOI1 was closed */ else /* AOI1 was closed */
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[1], machine_data->dummy_ad.paddr);
/* close AOI 0 */ /* close AOI 0 */
break; break;
case PLANE2_AOI0: case PLANE2_AOI0:
cmfbi = machine_data->fsl_diu_info[4]->par; cmfbi = &machine_data->mfb[4];
if (cmfbi->count > 0) /* AOI1 is open */ if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
/* move AOI1 to the first */ /* move AOI1 to the first */
else /* AOI1 was closed */ else /* AOI1 was closed */
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[2], machine_data->dummy_ad.paddr);
/* close AOI 0 */ /* close AOI 0 */
break; break;
case PLANE1_AOI1: case PLANE1_AOI1:
pmfbi = machine_data->fsl_diu_info[1]->par; pmfbi = &machine_data->mfb[1];
if (hw->desc[1] != ad->paddr) { if (hw->desc[1] != ad->paddr) {
/* AOI1 is not the first in the chain */ /* AOI1 is not the first in the chain */
if (pmfbi->count > 0) if (pmfbi->count > 0)
/* AOI0 is open, must be the first */ /* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0; pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */ } else /* AOI1 is the first in the chain */
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[1], machine_data->dummy_ad.paddr);
/* close AOI 1 */ /* close AOI 1 */
break; break;
case PLANE2_AOI1: case PLANE2_AOI1:
pmfbi = machine_data->fsl_diu_info[3]->par; pmfbi = &machine_data->mfb[3];
if (hw->desc[2] != ad->paddr) { if (hw->desc[2] != ad->paddr) {
/* AOI1 is not the first in the chain */ /* AOI1 is not the first in the chain */
if (pmfbi->count > 0) if (pmfbi->count > 0)
/* AOI0 is open, must be the first */ /* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0; pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */ } else /* AOI1 is the first in the chain */
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[2], machine_data->dummy_ad.paddr);
/* close AOI 1 */ /* close AOI 1 */
break; break;
} }
...@@ -633,8 +647,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, ...@@ -633,8 +647,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
int lower_aoi_is_open, upper_aoi_is_open; int lower_aoi_is_open, upper_aoi_is_open;
__u32 base_plane_width, base_plane_height, upper_aoi_height; __u32 base_plane_width, base_plane_height, upper_aoi_height;
base_plane_width = machine_data->fsl_diu_info[0]->var.xres; base_plane_width = machine_data->fsl_diu_info[0].var.xres;
base_plane_height = machine_data->fsl_diu_info[0]->var.yres; base_plane_height = machine_data->fsl_diu_info[0].var.yres;
if (mfbi->x_aoi_d < 0) if (mfbi->x_aoi_d < 0)
mfbi->x_aoi_d = 0; mfbi->x_aoi_d = 0;
...@@ -649,7 +663,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, ...@@ -649,7 +663,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
break; break;
case PLANE1_AOI0: case PLANE1_AOI0:
case PLANE2_AOI0: case PLANE2_AOI0:
lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; lower_aoi_mfbi = machine_data->fsl_diu_info[index+1].par;
lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
if (var->xres > base_plane_width) if (var->xres > base_plane_width)
var->xres = base_plane_width; var->xres = base_plane_width;
...@@ -667,9 +681,9 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, ...@@ -667,9 +681,9 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
break; break;
case PLANE1_AOI1: case PLANE1_AOI1:
case PLANE2_AOI1: case PLANE2_AOI1:
upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; upper_aoi_mfbi = machine_data->fsl_diu_info[index-1].par;
upper_aoi_height = upper_aoi_height =
machine_data->fsl_diu_info[index-1]->var.yres; machine_data->fsl_diu_info[index-1].var.yres;
upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
if (var->xres > base_plane_width) if (var->xres > base_plane_width)
...@@ -812,15 +826,15 @@ static void update_lcdc(struct fb_info *info) ...@@ -812,15 +826,15 @@ static void update_lcdc(struct fb_info *info)
struct fsl_diu_data *machine_data = mfbi->parent; struct fsl_diu_data *machine_data = mfbi->parent;
struct diu __iomem *hw; struct diu __iomem *hw;
int i, j; int i, j;
char __iomem *cursor_base, *gamma_table_base; u8 *gamma_table_base;
u32 temp; u32 temp;
hw = machine_data->diu_reg; hw = machine_data->diu_reg;
diu_ops.set_monitor_port(machine_data->monitor_port); diu_ops.set_monitor_port(machine_data->monitor_port);
gamma_table_base = machine_data->gamma.vaddr; gamma_table_base = machine_data->gamma;
cursor_base = machine_data->cursor.vaddr;
/* Prep for DIU init - gamma table, cursor table */ /* Prep for DIU init - gamma table, cursor table */
for (i = 0; i <= 2; i++) for (i = 0; i <= 2; i++)
...@@ -828,14 +842,14 @@ static void update_lcdc(struct fb_info *info) ...@@ -828,14 +842,14 @@ static void update_lcdc(struct fb_info *info)
*gamma_table_base++ = j; *gamma_table_base++ = j;
diu_ops.set_gamma_table(machine_data->monitor_port, diu_ops.set_gamma_table(machine_data->monitor_port,
machine_data->gamma.vaddr); machine_data->gamma);
disable_lcdc(info); disable_lcdc(info);
/* Program DIU registers */ /* Program DIU registers */
out_be32(&hw->gamma, machine_data->gamma.paddr); out_be32(&hw->gamma, DMA_ADDR(machine_data, gamma));
out_be32(&hw->cursor, machine_data->cursor.paddr); out_be32(&hw->cursor, DMA_ADDR(machine_data, cursor));
out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
...@@ -1423,37 +1437,6 @@ static int fsl_diu_resume(struct platform_device *ofdev) ...@@ -1423,37 +1437,6 @@ static int fsl_diu_resume(struct platform_device *ofdev)
#define fsl_diu_resume NULL #define fsl_diu_resume NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/* Align to 64-bit(8-byte), 32-byte, etc. */
static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
u32 bytes_align)
{
u32 offset;
dma_addr_t mask;
buf->vaddr =
dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
GFP_DMA | __GFP_ZERO);
if (!buf->vaddr)
return -ENOMEM;
mask = bytes_align - 1;
offset = buf->paddr & mask;
if (offset) {
buf->offset = bytes_align - offset;
buf->paddr = buf->paddr + offset;
} else
buf->offset = 0;
return 0;
}
static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
u32 bytes_align)
{
dma_free_coherent(dev, size + bytes_align, buf->vaddr,
buf->paddr - buf->offset);
}
static ssize_t store_monitor(struct device *device, static ssize_t store_monitor(struct device *device,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr, const char *buf, size_t count)
{ {
...@@ -1468,11 +1451,10 @@ static ssize_t store_monitor(struct device *device, ...@@ -1468,11 +1451,10 @@ static ssize_t store_monitor(struct device *device,
/* All AOIs need adjust pixel format /* All AOIs need adjust pixel format
* fsl_diu_set_par only change the pixsel format here * fsl_diu_set_par only change the pixsel format here
* unlikely to fail. */ * unlikely to fail. */
fsl_diu_set_par(machine_data->fsl_diu_info[0]); unsigned int i;
fsl_diu_set_par(machine_data->fsl_diu_info[1]);
fsl_diu_set_par(machine_data->fsl_diu_info[2]); for (i=0; i < NUM_AOIS; i++)
fsl_diu_set_par(machine_data->fsl_diu_info[3]); fsl_diu_set_par(&machine_data->fsl_diu_info[i]);
fsl_diu_set_par(machine_data->fsl_diu_info[4]);
} }
return count; return count;
} }
...@@ -1499,28 +1481,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) ...@@ -1499,28 +1481,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct mfb_info *mfbi; struct mfb_info *mfbi;
phys_addr_t dummy_ad_addr = 0;
int ret, i, error = 0;
struct fsl_diu_data *machine_data; struct fsl_diu_data *machine_data;
int diu_mode; int diu_mode;
dma_addr_t dma_addr; /* DMA addr of machine_data struct */
unsigned int i;
int ret;
machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); machine_data = dma_alloc_coherent(&pdev->dev,
sizeof(struct fsl_diu_data), &dma_addr, GFP_DMA | __GFP_ZERO);
if (!machine_data) if (!machine_data)
return -ENOMEM; return -ENOMEM;
machine_data->dma_addr = dma_addr;
/*
* dma_alloc_coherent() uses a page allocator, so the address is
* always page-aligned. We need the memory to be 32-byte aligned,
* so that's good. However, if one day the allocator changes, we
* need to catch that. It's not worth the effort to handle unaligned
* alloctions now because it's highly unlikely to ever be a problem.
*/
if ((unsigned long)machine_data & 31) {
dev_err(&pdev->dev, "misaligned allocation");
ret = -ENOMEM;
goto error;
}
spin_lock_init(&machine_data->reg_lock); spin_lock_init(&machine_data->reg_lock);
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { for (i = 0; i < NUM_AOIS; i++) {
machine_data->fsl_diu_info[i] = struct fb_info *info = &machine_data->fsl_diu_info[i];
framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
if (!machine_data->fsl_diu_info[i]) { info->device = &pdev->dev;
dev_err(&pdev->dev, "cannot allocate memory\n"); info->par = &machine_data->mfb[i];
ret = -ENOMEM;
goto error2; /*
} * We store the physical address of the AD in the reserved
mfbi = machine_data->fsl_diu_info[i]->par; * 'paddr' field of the AD itself.
*/
machine_data->ad[i].paddr = DMA_ADDR(machine_data, ad[i]);
info->fix.smem_start = 0;
/* Initialize the AOI data structure */
mfbi = info->par;
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
mfbi->parent = machine_data; mfbi->parent = machine_data;
mfbi->ad = &machine_data->ad[i];
if (mfbi->index == PLANE0) { if (mfbi->index == PLANE0) {
const u8 *prop; const u8 *prop;
...@@ -1538,7 +1544,7 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) ...@@ -1538,7 +1544,7 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
if (!machine_data->diu_reg) { if (!machine_data->diu_reg) {
dev_err(&pdev->dev, "cannot map DIU registers\n"); dev_err(&pdev->dev, "cannot map DIU registers\n");
ret = -EFAULT; ret = -EFAULT;
goto error2; goto error;
} }
diu_mode = in_be32(&machine_data->diu_reg->diu_mode); 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,41 +1561,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
} }
machine_data->monitor_port = monitor_port; machine_data->monitor_port = monitor_port;
/* Area descriptor memory pool aligns to 64-bit boundary */ /* Initialize the dummy Area Descriptor */
if (allocate_buf(&pdev->dev, &machine_data->ad, machine_data->dummy_ad.addr =
sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) cpu_to_le32(DMA_ADDR(machine_data, dummy_aoi));
return -ENOMEM; machine_data->dummy_ad.pix_fmt = 0x88882317;
machine_data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
/* Get memory for Gamma Table - 32-byte aligned memory */ machine_data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { machine_data->dummy_ad.offset_xyi = 0;
ret = -ENOMEM; machine_data->dummy_ad.offset_xyd = 0;
goto error; machine_data->dummy_ad.next_ad = 0;
} machine_data->dummy_ad.paddr = DMA_ADDR(machine_data, dummy_ad);
/* For performance, cursor bitmap buffer aligns to 32-byte boundary */
if (allocate_buf(&pdev->dev, &machine_data->cursor,
MAX_CURS * MAX_CURS * 2, 32)) {
ret = -ENOMEM;
goto error;
}
i = ARRAY_SIZE(machine_data->fsl_diu_info);
machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
machine_data->ad.offset) + i;
machine_data->dummy_ad->paddr = machine_data->ad.paddr +
i * sizeof(struct diu_ad);
machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
if (!machine_data->dummy_aoi_virt) {
ret = -ENOMEM;
goto error;
}
machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
machine_data->dummy_ad->pix_fmt = 0x88882317;
machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
machine_data->dummy_ad->offset_xyi = 0;
machine_data->dummy_ad->offset_xyd = 0;
machine_data->dummy_ad->next_ad = 0;
/* /*
* Let DIU display splash screen if it was pre-initialized * 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,19 +1578,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
*/ */
if (diu_mode == MFB_MODE0) if (diu_mode == MFB_MODE0)
out_be32(&machine_data->diu_reg->desc[0], out_be32(&machine_data->diu_reg->desc[0],
machine_data->dummy_ad->paddr); machine_data->dummy_ad.paddr);
out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad.paddr);
out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad.paddr);
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { for (i = 0; i < NUM_AOIS; i++) {
machine_data->fsl_diu_info[i]->fix.smem_start = 0; ret = install_fb(&machine_data->fsl_diu_info[i]);
mfbi = machine_data->fsl_diu_info[i]->par;
mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
+ machine_data->ad.offset) + i;
mfbi->ad->paddr =
machine_data->ad.paddr + i * sizeof(struct diu_ad);
ret = install_fb(machine_data->fsl_diu_info[i]);
if (ret) { if (ret) {
dev_err(&pdev->dev, "could not register fb %d\n", i); dev_err(&pdev->dev, "could not register fb %d\n", i);
goto error; goto error;
...@@ -1626,9 +1601,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) ...@@ -1626,9 +1601,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
machine_data->dev_attr.show = show_monitor; machine_data->dev_attr.show = show_monitor;
machine_data->dev_attr.store = store_monitor; machine_data->dev_attr.store = store_monitor;
error = device_create_file(machine_data->fsl_diu_info[0]->dev, ret = device_create_file(&pdev->dev, &machine_data->dev_attr);
&machine_data->dev_attr); if (ret) {
if (error) {
dev_err(&pdev->dev, "could not create sysfs file %s\n", dev_err(&pdev->dev, "could not create sysfs file %s\n",
machine_data->dev_attr.attr.name); machine_data->dev_attr.attr.name);
} }
...@@ -1637,26 +1611,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) ...@@ -1637,26 +1611,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
return 0; return 0;
error: error:
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) for (i = 0; i < NUM_AOIS; i++)
uninstall_fb(machine_data->fsl_diu_info[i]); uninstall_fb(&machine_data->fsl_diu_info[i]);
if (machine_data->ad.vaddr)
free_buf(&pdev->dev, &machine_data->ad,
sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
if (machine_data->gamma.vaddr)
free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
if (machine_data->cursor.vaddr)
free_buf(&pdev->dev, &machine_data->cursor,
MAX_CURS * MAX_CURS * 2, 32);
if (machine_data->dummy_aoi_virt)
fsl_diu_free(machine_data->dummy_aoi_virt, 64);
iounmap(machine_data->diu_reg); iounmap(machine_data->diu_reg);
error2: dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) machine_data, machine_data->dma_addr);
if (machine_data->fsl_diu_info[i])
framebuffer_release(machine_data->fsl_diu_info[i]);
kfree(machine_data);
return ret; return ret;
} }
...@@ -1667,25 +1628,16 @@ static int fsl_diu_remove(struct platform_device *pdev) ...@@ -1667,25 +1628,16 @@ static int fsl_diu_remove(struct platform_device *pdev)
int i; int i;
machine_data = dev_get_drvdata(&pdev->dev); machine_data = dev_get_drvdata(&pdev->dev);
disable_lcdc(machine_data->fsl_diu_info[0]); disable_lcdc(&machine_data->fsl_diu_info[0]);
free_irq_local(machine_data); free_irq_local(machine_data);
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
uninstall_fb(machine_data->fsl_diu_info[i]); for (i = 0; i < NUM_AOIS; i++)
if (machine_data->ad.vaddr) uninstall_fb(&machine_data->fsl_diu_info[i]);
free_buf(&pdev->dev, &machine_data->ad,
sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
if (machine_data->gamma.vaddr)
free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
if (machine_data->cursor.vaddr)
free_buf(&pdev->dev, &machine_data->cursor,
MAX_CURS * MAX_CURS * 2, 32);
if (machine_data->dummy_aoi_virt)
fsl_diu_free(machine_data->dummy_aoi_virt, 64);
iounmap(machine_data->diu_reg); iounmap(machine_data->diu_reg);
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
if (machine_data->fsl_diu_info[i]) dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
framebuffer_release(machine_data->fsl_diu_info[i]); machine_data, machine_data->dma_addr);
kfree(machine_data);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment