* [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into one block
@ 2011-12-02 23:03 Timur Tabi
2011-12-19 23:11 ` [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into Florian Tobias Schandinat
0 siblings, 1 reply; 2+ messages in thread
From: Timur Tabi @ 2011-12-02 23:03 UTC (permalink / raw)
To: linux-fbdev
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>
---
drivers/video/fsl-diu-fb.c | 326 +++++++++++++++++++-------------------------
1 files changed, 139 insertions(+), 187 deletions(-)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index a16beeb..4d54188 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -36,8 +36,7 @@
#include <linux/fsl-diu-fb.h>
#include "edid.h"
-#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
- /* 1 for plane 0, 2 for plane 1&2 each */
+#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
/* HW cursor parameters */
#define MAX_CURS 32
@@ -49,12 +48,6 @@
#define INT_PARERR 0x08 /* Display parameters error 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
*
@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
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 {
PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
PLANE1_AOI0, /* Plane 1, first AOI */
@@ -370,6 +346,44 @@ struct mfb_info {
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[] = {
{
@@ -504,7 +518,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
wr_reg_wa(&hw->desc[0], ad->paddr);
break;
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 (cmfbi->count > 0) /* AOI1 open */
ad->next_ad @@ -515,7 +529,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
}
break;
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 (cmfbi->count > 0) /* AOI1 open */
ad->next_ad @@ -526,17 +540,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
}
break;
case PLANE1_AOI1:
- pmfbi = machine_data->fsl_diu_info[1]->par;
+ pmfbi = &machine_data->mfb[1];
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);
else /* AOI0 open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
break;
case PLANE2_AOI1:
- pmfbi = machine_data->fsl_diu_info[3]->par;
+ pmfbi = &machine_data->mfb[3];
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);
else /* AOI0 was open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
@@ -553,47 +567,47 @@ static void fsl_diu_disable_panel(struct fb_info *info)
switch (mfbi->index) {
case PLANE0:
- if (hw->desc[0] != machine_data->dummy_ad->paddr)
- wr_reg_wa(&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);
break;
case PLANE1_AOI0:
- cmfbi = machine_data->fsl_diu_info[2]->par;
+ cmfbi = &machine_data->mfb[2];
if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
/* move AOI1 to the first */
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 */
break;
case PLANE2_AOI0:
- cmfbi = machine_data->fsl_diu_info[4]->par;
+ cmfbi = &machine_data->mfb[4];
if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
/* move AOI1 to the first */
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 */
break;
case PLANE1_AOI1:
- pmfbi = machine_data->fsl_diu_info[1]->par;
+ pmfbi = &machine_data->mfb[1];
if (hw->desc[1] != ad->paddr) {
/* AOI1 is not the first in the chain */
if (pmfbi->count > 0)
/* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0;
} 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 */
break;
case PLANE2_AOI1:
- pmfbi = machine_data->fsl_diu_info[3]->par;
+ pmfbi = &machine_data->mfb[3];
if (hw->desc[2] != ad->paddr) {
/* AOI1 is not the first in the chain */
if (pmfbi->count > 0)
/* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0;
} 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 */
break;
}
@@ -633,8 +647,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
int lower_aoi_is_open, upper_aoi_is_open;
__u32 base_plane_width, base_plane_height, upper_aoi_height;
- base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
- base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
+ base_plane_width = machine_data->fsl_diu_info[0].var.xres;
+ base_plane_height = machine_data->fsl_diu_info[0].var.yres;
if (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,
break;
case PLANE1_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;
if (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,
break;
case PLANE1_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 - 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_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
if (var->xres > base_plane_width)
@@ -812,15 +826,15 @@ static void update_lcdc(struct fb_info *info)
struct fsl_diu_data *machine_data = mfbi->parent;
struct diu __iomem *hw;
int i, j;
- char __iomem *cursor_base, *gamma_table_base;
+ u8 *gamma_table_base;
u32 temp;
hw = machine_data->diu_reg;
diu_ops.set_monitor_port(machine_data->monitor_port);
- gamma_table_base = machine_data->gamma.vaddr;
- cursor_base = machine_data->cursor.vaddr;
+ gamma_table_base = machine_data->gamma;
+
/* Prep for DIU init - gamma table, cursor table */
for (i = 0; i <= 2; i++)
@@ -828,14 +842,14 @@ static void update_lcdc(struct fb_info *info)
*gamma_table_base++ = j;
diu_ops.set_gamma_table(machine_data->monitor_port,
- machine_data->gamma.vaddr);
+ machine_data->gamma);
disable_lcdc(info);
/* Program DIU registers */
- out_be32(&hw->gamma, machine_data->gamma.paddr);
- out_be32(&hw->cursor, machine_data->cursor.paddr);
+ out_be32(&hw->gamma, DMA_ADDR(machine_data, gamma));
+ out_be32(&hw->cursor, DMA_ADDR(machine_data, cursor));
out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
@@ -1423,37 +1437,6 @@ static int fsl_diu_resume(struct platform_device *ofdev)
#define fsl_diu_resume NULL
#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,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -1468,11 +1451,10 @@ static ssize_t store_monitor(struct device *device,
/* All AOIs need adjust pixel format
* fsl_diu_set_par only change the pixsel format here
* unlikely to fail. */
- fsl_diu_set_par(machine_data->fsl_diu_info[0]);
- fsl_diu_set_par(machine_data->fsl_diu_info[1]);
- fsl_diu_set_par(machine_data->fsl_diu_info[2]);
- fsl_diu_set_par(machine_data->fsl_diu_info[3]);
- fsl_diu_set_par(machine_data->fsl_diu_info[4]);
+ unsigned int i;
+
+ for (i=0; i < NUM_AOIS; i++)
+ fsl_diu_set_par(&machine_data->fsl_diu_info[i]);
}
return count;
}
@@ -1499,28 +1481,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mfb_info *mfbi;
- phys_addr_t dummy_ad_addr = 0;
- int ret, i, error = 0;
struct fsl_diu_data *machine_data;
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)
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);
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
- machine_data->fsl_diu_info[i] - framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
- if (!machine_data->fsl_diu_info[i]) {
- dev_err(&pdev->dev, "cannot allocate memory\n");
- ret = -ENOMEM;
- goto error2;
- }
- mfbi = machine_data->fsl_diu_info[i]->par;
+ for (i = 0; i < NUM_AOIS; i++) {
+ struct fb_info *info = &machine_data->fsl_diu_info[i];
+
+ info->device = &pdev->dev;
+ info->par = &machine_data->mfb[i];
+
+ /*
+ * We store the physical address of the AD in the reserved
+ * '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));
mfbi->parent = machine_data;
+ mfbi->ad = &machine_data->ad[i];
if (mfbi->index = PLANE0) {
const u8 *prop;
@@ -1538,7 +1544,7 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
if (!machine_data->diu_reg) {
dev_err(&pdev->dev, "cannot map DIU registers\n");
ret = -EFAULT;
- goto error2;
+ goto error;
}
diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
@@ -1555,41 +1561,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
}
machine_data->monitor_port = monitor_port;
- /* Area descriptor memory pool aligns to 64-bit boundary */
- if (allocate_buf(&pdev->dev, &machine_data->ad,
- sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
- return -ENOMEM;
-
- /* Get memory for Gamma Table - 32-byte aligned memory */
- if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
- ret = -ENOMEM;
- goto error;
- }
-
- /* 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;
+ /* Initialize the dummy Area Descriptor */
+ machine_data->dummy_ad.addr + cpu_to_le32(DMA_ADDR(machine_data, dummy_aoi));
+ 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;
+ machine_data->dummy_ad.paddr = DMA_ADDR(machine_data, dummy_ad);
/*
* Let DIU display splash screen if it was pre-initialized
@@ -1597,19 +1578,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
*/
if (diu_mode = MFB_MODE0)
out_be32(&machine_data->diu_reg->desc[0],
- 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);
-
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
- machine_data->fsl_diu_info[i]->fix.smem_start = 0;
- 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]);
+ 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);
+
+ for (i = 0; i < NUM_AOIS; i++) {
+ ret = install_fb(&machine_data->fsl_diu_info[i]);
if (ret) {
dev_err(&pdev->dev, "could not register fb %d\n", i);
goto error;
@@ -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.show = show_monitor;
machine_data->dev_attr.store = store_monitor;
- error = device_create_file(machine_data->fsl_diu_info[0]->dev,
- &machine_data->dev_attr);
- if (error) {
+ ret = device_create_file(&pdev->dev, &machine_data->dev_attr);
+ if (ret) {
dev_err(&pdev->dev, "could not create sysfs file %s\n",
machine_data->dev_attr.attr.name);
}
@@ -1637,26 +1611,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
return 0;
error:
- for (i = 0; i < ARRAY_SIZE(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);
+ for (i = 0; i < NUM_AOIS; i++)
+ uninstall_fb(&machine_data->fsl_diu_info[i]);
+
iounmap(machine_data->diu_reg);
-error2:
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- if (machine_data->fsl_diu_info[i])
- framebuffer_release(machine_data->fsl_diu_info[i]);
- kfree(machine_data);
+ dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
+ machine_data, machine_data->dma_addr);
return ret;
}
@@ -1667,25 +1628,16 @@ static int fsl_diu_remove(struct platform_device *pdev)
int i;
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);
- for (i = 0; i < ARRAY_SIZE(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);
+
+ for (i = 0; i < NUM_AOIS; i++)
+ uninstall_fb(&machine_data->fsl_diu_info[i]);
+
iounmap(machine_data->diu_reg);
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- if (machine_data->fsl_diu_info[i])
- framebuffer_release(machine_data->fsl_diu_info[i]);
- kfree(machine_data);
+
+ dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
+ machine_data, machine_data->dma_addr);
return 0;
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into
2011-12-02 23:03 [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into one block Timur Tabi
@ 2011-12-19 23:11 ` Florian Tobias Schandinat
0 siblings, 0 replies; 2+ messages in thread
From: Florian Tobias Schandinat @ 2011-12-19 23:11 UTC (permalink / raw)
To: linux-fbdev
On 12/02/2011 11:03 PM, Timur Tabi wrote:
> 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>
As you like the idea, applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/fsl-diu-fb.c | 326 +++++++++++++++++++-------------------------
> 1 files changed, 139 insertions(+), 187 deletions(-)
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index a16beeb..4d54188 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -36,8 +36,7 @@
> #include <linux/fsl-diu-fb.h>
> #include "edid.h"
>
> -#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
> - /* 1 for plane 0, 2 for plane 1&2 each */
> +#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
>
> /* HW cursor parameters */
> #define MAX_CURS 32
> @@ -49,12 +48,6 @@
> #define INT_PARERR 0x08 /* Display parameters error 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
> *
> @@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
>
> 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 {
> PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
> PLANE1_AOI0, /* Plane 1, first AOI */
> @@ -370,6 +346,44 @@ struct mfb_info {
> 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[] = {
> {
> @@ -504,7 +518,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
> wr_reg_wa(&hw->desc[0], ad->paddr);
> break;
> 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 (cmfbi->count > 0) /* AOI1 open */
> ad->next_ad > @@ -515,7 +529,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
> }
> break;
> 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 (cmfbi->count > 0) /* AOI1 open */
> ad->next_ad > @@ -526,17 +540,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
> }
> break;
> case PLANE1_AOI1:
> - pmfbi = machine_data->fsl_diu_info[1]->par;
> + pmfbi = &machine_data->mfb[1];
> 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);
> else /* AOI0 open */
> pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
> break;
> case PLANE2_AOI1:
> - pmfbi = machine_data->fsl_diu_info[3]->par;
> + pmfbi = &machine_data->mfb[3];
> 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);
> else /* AOI0 was open */
> pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
> @@ -553,47 +567,47 @@ static void fsl_diu_disable_panel(struct fb_info *info)
>
> switch (mfbi->index) {
> case PLANE0:
> - if (hw->desc[0] != machine_data->dummy_ad->paddr)
> - wr_reg_wa(&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);
> break;
> case PLANE1_AOI0:
> - cmfbi = machine_data->fsl_diu_info[2]->par;
> + cmfbi = &machine_data->mfb[2];
> if (cmfbi->count > 0) /* AOI1 is open */
> wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
> /* move AOI1 to the first */
> 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 */
> break;
> case PLANE2_AOI0:
> - cmfbi = machine_data->fsl_diu_info[4]->par;
> + cmfbi = &machine_data->mfb[4];
> if (cmfbi->count > 0) /* AOI1 is open */
> wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
> /* move AOI1 to the first */
> 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 */
> break;
> case PLANE1_AOI1:
> - pmfbi = machine_data->fsl_diu_info[1]->par;
> + pmfbi = &machine_data->mfb[1];
> if (hw->desc[1] != ad->paddr) {
> /* AOI1 is not the first in the chain */
> if (pmfbi->count > 0)
> /* AOI0 is open, must be the first */
> pmfbi->ad->next_ad = 0;
> } 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 */
> break;
> case PLANE2_AOI1:
> - pmfbi = machine_data->fsl_diu_info[3]->par;
> + pmfbi = &machine_data->mfb[3];
> if (hw->desc[2] != ad->paddr) {
> /* AOI1 is not the first in the chain */
> if (pmfbi->count > 0)
> /* AOI0 is open, must be the first */
> pmfbi->ad->next_ad = 0;
> } 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 */
> break;
> }
> @@ -633,8 +647,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
> int lower_aoi_is_open, upper_aoi_is_open;
> __u32 base_plane_width, base_plane_height, upper_aoi_height;
>
> - base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
> - base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
> + base_plane_width = machine_data->fsl_diu_info[0].var.xres;
> + base_plane_height = machine_data->fsl_diu_info[0].var.yres;
>
> if (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,
> break;
> case PLANE1_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;
> if (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,
> break;
> case PLANE1_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 > - 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_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
> if (var->xres > base_plane_width)
> @@ -812,15 +826,15 @@ static void update_lcdc(struct fb_info *info)
> struct fsl_diu_data *machine_data = mfbi->parent;
> struct diu __iomem *hw;
> int i, j;
> - char __iomem *cursor_base, *gamma_table_base;
> + u8 *gamma_table_base;
>
> u32 temp;
>
> hw = machine_data->diu_reg;
>
> diu_ops.set_monitor_port(machine_data->monitor_port);
> - gamma_table_base = machine_data->gamma.vaddr;
> - cursor_base = machine_data->cursor.vaddr;
> + gamma_table_base = machine_data->gamma;
> +
> /* Prep for DIU init - gamma table, cursor table */
>
> for (i = 0; i <= 2; i++)
> @@ -828,14 +842,14 @@ static void update_lcdc(struct fb_info *info)
> *gamma_table_base++ = j;
>
> diu_ops.set_gamma_table(machine_data->monitor_port,
> - machine_data->gamma.vaddr);
> + machine_data->gamma);
>
> disable_lcdc(info);
>
> /* Program DIU registers */
>
> - out_be32(&hw->gamma, machine_data->gamma.paddr);
> - out_be32(&hw->cursor, machine_data->cursor.paddr);
> + out_be32(&hw->gamma, DMA_ADDR(machine_data, gamma));
> + out_be32(&hw->cursor, DMA_ADDR(machine_data, cursor));
>
> out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
> out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
> @@ -1423,37 +1437,6 @@ static int fsl_diu_resume(struct platform_device *ofdev)
> #define fsl_diu_resume NULL
> #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,
> struct device_attribute *attr, const char *buf, size_t count)
> {
> @@ -1468,11 +1451,10 @@ static ssize_t store_monitor(struct device *device,
> /* All AOIs need adjust pixel format
> * fsl_diu_set_par only change the pixsel format here
> * unlikely to fail. */
> - fsl_diu_set_par(machine_data->fsl_diu_info[0]);
> - fsl_diu_set_par(machine_data->fsl_diu_info[1]);
> - fsl_diu_set_par(machine_data->fsl_diu_info[2]);
> - fsl_diu_set_par(machine_data->fsl_diu_info[3]);
> - fsl_diu_set_par(machine_data->fsl_diu_info[4]);
> + unsigned int i;
> +
> + for (i=0; i < NUM_AOIS; i++)
> + fsl_diu_set_par(&machine_data->fsl_diu_info[i]);
> }
> return count;
> }
> @@ -1499,28 +1481,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
> {
> struct device_node *np = pdev->dev.of_node;
> struct mfb_info *mfbi;
> - phys_addr_t dummy_ad_addr = 0;
> - int ret, i, error = 0;
> struct fsl_diu_data *machine_data;
> 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)
> 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);
>
> - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
> - machine_data->fsl_diu_info[i] > - framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
> - if (!machine_data->fsl_diu_info[i]) {
> - dev_err(&pdev->dev, "cannot allocate memory\n");
> - ret = -ENOMEM;
> - goto error2;
> - }
> - mfbi = machine_data->fsl_diu_info[i]->par;
> + for (i = 0; i < NUM_AOIS; i++) {
> + struct fb_info *info = &machine_data->fsl_diu_info[i];
> +
> + info->device = &pdev->dev;
> + info->par = &machine_data->mfb[i];
> +
> + /*
> + * We store the physical address of the AD in the reserved
> + * '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));
> mfbi->parent = machine_data;
> + mfbi->ad = &machine_data->ad[i];
>
> if (mfbi->index = PLANE0) {
> const u8 *prop;
> @@ -1538,7 +1544,7 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
> if (!machine_data->diu_reg) {
> dev_err(&pdev->dev, "cannot map DIU registers\n");
> ret = -EFAULT;
> - goto error2;
> + goto error;
> }
>
> diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
> @@ -1555,41 +1561,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
> }
> machine_data->monitor_port = monitor_port;
>
> - /* Area descriptor memory pool aligns to 64-bit boundary */
> - if (allocate_buf(&pdev->dev, &machine_data->ad,
> - sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
> - return -ENOMEM;
> -
> - /* Get memory for Gamma Table - 32-byte aligned memory */
> - if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
> - ret = -ENOMEM;
> - goto error;
> - }
> -
> - /* 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;
> + /* Initialize the dummy Area Descriptor */
> + machine_data->dummy_ad.addr > + cpu_to_le32(DMA_ADDR(machine_data, dummy_aoi));
> + 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;
> + machine_data->dummy_ad.paddr = DMA_ADDR(machine_data, dummy_ad);
>
> /*
> * Let DIU display splash screen if it was pre-initialized
> @@ -1597,19 +1578,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
> */
> if (diu_mode = MFB_MODE0)
> out_be32(&machine_data->diu_reg->desc[0],
> - 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);
> -
> - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
> - machine_data->fsl_diu_info[i]->fix.smem_start = 0;
> - 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]);
> + 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);
> +
> + for (i = 0; i < NUM_AOIS; i++) {
> + ret = install_fb(&machine_data->fsl_diu_info[i]);
> if (ret) {
> dev_err(&pdev->dev, "could not register fb %d\n", i);
> goto error;
> @@ -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.show = show_monitor;
> machine_data->dev_attr.store = store_monitor;
> - error = device_create_file(machine_data->fsl_diu_info[0]->dev,
> - &machine_data->dev_attr);
> - if (error) {
> + ret = device_create_file(&pdev->dev, &machine_data->dev_attr);
> + if (ret) {
> dev_err(&pdev->dev, "could not create sysfs file %s\n",
> machine_data->dev_attr.attr.name);
> }
> @@ -1637,26 +1611,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
> return 0;
>
> error:
> - for (i = 0; i < ARRAY_SIZE(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);
> + for (i = 0; i < NUM_AOIS; i++)
> + uninstall_fb(&machine_data->fsl_diu_info[i]);
> +
> iounmap(machine_data->diu_reg);
>
> -error2:
> - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
> - if (machine_data->fsl_diu_info[i])
> - framebuffer_release(machine_data->fsl_diu_info[i]);
> - kfree(machine_data);
> + dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
> + machine_data, machine_data->dma_addr);
>
> return ret;
> }
> @@ -1667,25 +1628,16 @@ static int fsl_diu_remove(struct platform_device *pdev)
> int i;
>
> 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);
> - for (i = 0; i < ARRAY_SIZE(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);
> +
> + for (i = 0; i < NUM_AOIS; i++)
> + uninstall_fb(&machine_data->fsl_diu_info[i]);
> +
> iounmap(machine_data->diu_reg);
> - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
> - if (machine_data->fsl_diu_info[i])
> - framebuffer_release(machine_data->fsl_diu_info[i]);
> - kfree(machine_data);
> +
> + dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
> + machine_data, machine_data->dma_addr);
>
> return 0;
> }
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-12-19 23:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-02 23:03 [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into one block Timur Tabi
2011-12-19 23:11 ` [PATCH] drivers/video: fsl-diu-fb: merge all allocated data into Florian Tobias Schandinat
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.