linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).