[PATCH 48/57] fbdev: sh_mobile_meram: Allocate ICBs automatically

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead of manually specifying the ICBs to use in platform data,
allocate them automatically at runtime.

The MERAM registration function now returns a pointer to an opaque MERAM
object, which is passed to the update and unregistration functions.

Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
 drivers/video/sh_mobile_lcdcfb.c |   27 ++--
 drivers/video/sh_mobile_lcdcfb.h |    2 +-
 drivers/video/sh_mobile_meram.c  |  341 ++++++++++++++++++++------------------
 include/video/sh_mobile_meram.h  |   22 ++--
 4 files changed, 207 insertions(+), 185 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 453fc92..c1f1e03 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -838,6 +838,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		struct sh_mobile_meram_cfg *cfg;
 		int pixelformat;
+		void *meram;
 
 		ch = &priv->ch[k];
 		if (!ch->enabled)
@@ -854,9 +855,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 		/* we need to de-init configured ICBs before we can
 		 * re-initialize them.
 		 */
-		if (ch->meram_enabled) {
-			mdev->ops->meram_unregister(mdev, cfg);
-			ch->meram_enabled = 0;
+		if (ch->meram) {
+			mdev->ops->meram_unregister(mdev, ch->meram);
+			ch->meram = NULL;
 		}
 
 		switch (ch->format->fourcc) {
@@ -878,13 +879,13 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			break;
 		}
 
-		ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
+		meram = mdev->ops->meram_register(mdev, cfg, ch->pitch,
 					ch->yres, pixelformat,
 					ch->base_addr_y, ch->base_addr_c,
 					&ch->base_addr_y, &ch->base_addr_c,
 					&ch->pitch);
-		if (!ret)
-			ch->meram_enabled = 1;
+		if (!IS_ERR(meram))
+			ch->meram = meram;
 	}
 
 	/* Start the LCDC. */
@@ -949,13 +950,11 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 		sh_mobile_lcdc_display_off(ch);
 
 		/* disable the meram */
-		if (ch->meram_enabled) {
-			struct sh_mobile_meram_cfg *cfg;
+		if (ch->meram) {
 			struct sh_mobile_meram_info *mdev;
-			cfg = ch->cfg.meram_cfg;
 			mdev = priv->meram_dev;
-			mdev->ops->meram_unregister(mdev, cfg);
-			ch->meram_enabled = 0;
+			mdev->ops->meram_unregister(mdev, ch->meram);
+			ch->meram = 0;
 		}
 
 	}
@@ -1068,14 +1067,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 			base_addr_c += var->xoffset;
 	}
 
-	if (ch->meram_enabled) {
-		struct sh_mobile_meram_cfg *cfg;
+	if (ch->meram) {
 		struct sh_mobile_meram_info *mdev;
 		int ret;
 
-		cfg = ch->cfg.meram_cfg;
 		mdev = priv->meram_dev;
-		ret = mdev->ops->meram_update(mdev, cfg,
+		ret = mdev->ops->meram_update(mdev, ch->meram,
 					base_addr_y, base_addr_c,
 					&base_addr_y, &base_addr_c);
 		if (ret)
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 19a4cd7..bf1707c 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan {
 	unsigned long *reg_offs;
 	unsigned long ldmt1r_value;
 	unsigned long enabled; /* ME and SE in LDCNT2R */
-	int meram_enabled;
+	void *meram;
 
 	struct mutex open_lock;		/* protects the use counter */
 	int use_count;
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 7cd706d..01ae5b6 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/genalloc.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -107,13 +108,14 @@ static const unsigned long icb_regs[] = {
  * sh_mobile_meram_icb - MERAM ICB information
  * @regs: Registers cache
  * @offset: MERAM block offset
- * @size: MERAM block size in bytes
+ * @size: MERAM block size in KiB
  * @cache_unit: Bytes to cache per ICB
  * @pixelformat: Video pixel format of the data stored in the ICB
  * @current_reg: Which of Start Address Register A (0) or B (1) is in use
  */
 struct sh_mobile_meram_icb {
 	unsigned long regs[ICB_REGS_SIZE];
+	unsigned int index;
 	unsigned long offset;
 	unsigned int size;
 
@@ -124,6 +126,16 @@ struct sh_mobile_meram_icb {
 
 #define MERAM_ICB_NUM			32
 
+struct sh_mobile_meram_fb_plane {
+	struct sh_mobile_meram_icb *marker;
+	struct sh_mobile_meram_icb *cache;
+};
+
+struct sh_mobile_meram_fb_cache {
+	unsigned int nplanes;
+	struct sh_mobile_meram_fb_plane planes[2];
+};
+
 /*
  * sh_mobile_meram_priv - MERAM device
  * @base: Registers base address
@@ -184,54 +196,46 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
  * Allocation
  */
 
-/* Check if there's no overlaps in MERAM allocation. */
-static int meram_check_overlap(struct sh_mobile_meram_priv *priv,
-			       const struct sh_mobile_meram_icb_cfg *new)
+/* Allocate ICBs and MERAM for a plane. */
+static int __meram_alloc(struct sh_mobile_meram_priv *priv,
+			 struct sh_mobile_meram_fb_plane *plane,
+			 size_t size)
 {
-	/* valid ICB? */
-	if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f)
-		return 1;
-
-	if (test_bit(new->marker_icb, &priv->used_icb) ||
-	    test_bit(new->cache_icb,  &priv->used_icb))
-		return  1;
+	unsigned long mem;
+	unsigned long idx;
 
-	return 0;
-}
+	idx = find_first_zero_bit(&priv->used_icb, 28);
+	if (idx == 28)
+		return -ENOMEM;
+	plane->cache = &priv->icbs[idx];
 
-/* Allocate memory for the ICBs and mark them as used. */
-static int meram_alloc(struct sh_mobile_meram_priv *priv,
-		       const struct sh_mobile_meram_icb_cfg *new,
-		       int pixelformat)
-{
-	struct sh_mobile_meram_icb *marker = &priv->icbs[new->marker_icb];
-	unsigned long mem;
+	idx = find_next_zero_bit(&priv->used_icb, 32, 28);
+	if (idx == 32)
+		return -ENOMEM;
+	plane->marker = &priv->icbs[idx];
 
-	mem = gen_pool_alloc(priv->pool, new->meram_size * 1024);
+	mem = gen_pool_alloc(priv->pool, size * 1024);
 	if (mem == 0)
 		return -ENOMEM;
 
-	__set_bit(new->marker_icb, &priv->used_icb);
-	__set_bit(new->cache_icb, &priv->used_icb);
+	__set_bit(plane->marker->index, &priv->used_icb);
+	__set_bit(plane->cache->index, &priv->used_icb);
 
-	marker->offset = mem - priv->meram;
-	marker->size = new->meram_size * 1024;
-	marker->current_reg = 1;
-	marker->pixelformat = pixelformat;
+	plane->marker->offset = mem - priv->meram;
+	plane->marker->size = size;
 
 	return 0;
 }
 
-/* Unmark the specified ICB as used. */
-static void meram_free(struct sh_mobile_meram_priv *priv,
-		       const struct sh_mobile_meram_icb_cfg *icb)
+/* Free ICBs and MERAM for a plane. */
+static void __meram_free(struct sh_mobile_meram_priv *priv,
+			 struct sh_mobile_meram_fb_plane *plane)
 {
-	struct sh_mobile_meram_icb *marker = &priv->icbs[icb->marker_icb];
+	gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
+		      plane->marker->size * 1024);
 
-	gen_pool_free(priv->pool, priv->meram + marker->offset, marker->size);
-
-	__clear_bit(icb->marker_icb, &priv->used_icb);
-	__clear_bit(icb->cache_icb, &priv->used_icb);
+	__clear_bit(plane->marker->index, &priv->used_icb);
+	__clear_bit(plane->cache->index, &priv->used_icb);
 }
 
 /* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
@@ -243,42 +247,96 @@ static int is_nvcolor(int cspace)
 	return 0;
 }
 
+/* Allocate memory for the ICBs and mark them as used. */
+static struct sh_mobile_meram_fb_cache *
+meram_alloc(struct sh_mobile_meram_priv *priv,
+	    const struct sh_mobile_meram_cfg *cfg,
+	    int pixelformat)
+{
+	struct sh_mobile_meram_fb_cache *cache;
+	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+	int ret;
+
+	if (cfg->icb[0].meram_size == 0)
+		return ERR_PTR(-EINVAL);
+
+	if (nplanes == 2 && cfg->icb[1].meram_size == 0)
+		return ERR_PTR(-EINVAL);
+
+	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+	if (cache == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	cache->nplanes = nplanes;
+
+	ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
+	if (ret < 0)
+		goto error;
+
+	cache->planes[0].marker->current_reg = 1;
+	cache->planes[0].marker->pixelformat = pixelformat;
+
+	if (cache->nplanes == 1)
+		return cache;
+
+	ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
+	if (ret < 0) {
+		__meram_free(priv, &cache->planes[0]);
+		goto error;
+	}
+
+	return cache;
+
+error:
+	kfree(cache);
+	return ERR_PTR(-ENOMEM);
+}
+
+/* Unmark the specified ICB as used. */
+static void meram_free(struct sh_mobile_meram_priv *priv,
+		       struct sh_mobile_meram_fb_cache *cache)
+{
+	__meram_free(priv, &cache->planes[0]);
+	if (cache->nplanes == 2)
+		__meram_free(priv, &cache->planes[1]);
+
+	kfree(cache);
+}
+
 /* Set the next address to fetch. */
 static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
-				const struct sh_mobile_meram_cfg *cfg,
+				struct sh_mobile_meram_fb_cache *cache,
 				unsigned long base_addr_y,
 				unsigned long base_addr_c)
 {
-	struct sh_mobile_meram_icb *icb = &priv->icbs[cfg->icb[0].marker_icb];
+	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
 	unsigned long target;
 
 	icb->current_reg ^= 1;
 	target = icb->current_reg ? MExxSARB : MExxSARA;
 
 	/* set the next address to fetch */
-	meram_write_icb(priv->base, cfg->icb[0].cache_icb, target,
+	meram_write_icb(priv->base, cache->planes[0].cache->index, target,
 			base_addr_y);
-	meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
-			base_addr_y +
-			priv->icbs[cfg->icb[0].marker_icb].cache_unit);
-
-	if (is_nvcolor(icb->pixelformat)) {
-		meram_write_icb(priv->base, cfg->icb[1].cache_icb,  target,
-				base_addr_c);
-		meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
-				base_addr_c +
-				priv->icbs[cfg->icb[1].marker_icb].cache_unit);
+	meram_write_icb(priv->base, cache->planes[0].marker->index, target,
+			base_addr_y + cache->planes[0].marker->cache_unit);
+
+	if (cache->nplanes == 2) {
+		meram_write_icb(priv->base, cache->planes[1].cache->index,
+				target, base_addr_c);
+		meram_write_icb(priv->base, cache->planes[1].marker->index,
+				target, base_addr_c +
+				cache->planes[1].marker->cache_unit);
 	}
 }
 
 /* Get the next ICB address. */
 static void
 meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
-			const struct sh_mobile_meram_cfg *cfg,
+			struct sh_mobile_meram_fb_cache *cache,
 			unsigned long *icb_addr_y, unsigned long *icb_addr_c)
 {
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-	struct sh_mobile_meram_icb *icb = &priv->icbs[cfg->icb[0].marker_icb];
+	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
 	unsigned long icb_offset;
 
 	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
@@ -286,9 +344,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
 	else
 		icb_offset = 0xc0000000 | (icb->current_reg << 23);
 
-	*icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
-	if (is_nvcolor(icb->pixelformat))
-		*icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
+	*icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
+	if (cache->nplanes == 2)
+		*icb_addr_c = icb_offset
+			    | (cache->planes[1].marker->index << 24);
 }
 
 #define MERAM_CALC_BYTECOUNT(x, y) \
@@ -296,11 +355,11 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
 
 /* Initialize MERAM. */
 static int meram_init(struct sh_mobile_meram_priv *priv,
-		      const struct sh_mobile_meram_icb_cfg *icb,
+		      struct sh_mobile_meram_fb_plane *plane,
 		      unsigned int xres, unsigned int yres,
 		      unsigned int *out_pitch)
 {
-	struct sh_mobile_meram_icb *marker = &priv->icbs[icb->marker_icb];
+	struct sh_mobile_meram_icb *marker = plane->marker;
 	unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
 	unsigned long bnm;
 	unsigned int lcdc_pitch;
@@ -319,13 +378,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 		lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
 		line_cnt = total_byte_count >> 11;
 		*out_pitch = xres;
-		save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE);
+		save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
 		save_lines *= MERAM_SEC_LINE;
 	} else {
 		xpitch = xres;
 		line_cnt = yres;
 		*out_pitch = lcdc_pitch;
-		save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2;
+		save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
 		save_lines &= 0xff;
 	}
 	bnm = (save_lines - 1) << 16;
@@ -333,20 +392,20 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 	/* TODO: we better to check if we have enough MERAM buffer size */
 
 	/* set up ICB */
-	meram_write_icb(priv->base, icb->cache_icb,  MExxBSIZE,
+	meram_write_icb(priv->base, plane->cache->index,  MExxBSIZE,
 			MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
-	meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE,
+	meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
 			MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
 
-	meram_write_icb(priv->base, icb->cache_icb,  MExxMNCF, bnm);
-	meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm);
+	meram_write_icb(priv->base, plane->cache->index,  MExxMNCF, bnm);
+	meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
 
-	meram_write_icb(priv->base, icb->cache_icb,  MExxSBSIZE, xpitch);
-	meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch);
+	meram_write_icb(priv->base, plane->cache->index,  MExxSBSIZE, xpitch);
+	meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
 
 	/* save a cache unit size */
-	priv->icbs[icb->cache_icb].cache_unit = xres * save_lines;
-	priv->icbs[icb->marker_icb].cache_unit = xres * save_lines;
+	plane->cache->cache_unit = xres * save_lines;
+	plane->marker->cache_unit = xres * save_lines;
 
 	/*
 	 * Set MERAM for framebuffer
@@ -354,13 +413,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 	 * we also chain the cache_icb and the marker_icb.
 	 * we also split the allocated MERAM buffer between two ICBs.
 	 */
-	meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
-			MERAM_MExxCTL_VAL(icb->marker_icb, marker->offset) |
-			MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
+	meram_write_icb(priv->base, plane->cache->index, MExxCTL,
+			MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
+			| MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
 			MExxCTL_MD_FB);
-	meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
-			MERAM_MExxCTL_VAL(icb->cache_icb, marker->offset +
-					  icb->meram_size / 2) |
+	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
+			MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
+					  plane->marker->size / 2) |
 			MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
 			MExxCTL_MD_FB);
 
@@ -368,45 +427,44 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 }
 
 static void meram_deinit(struct sh_mobile_meram_priv *priv,
-			 const struct sh_mobile_meram_icb_cfg *icb)
+			 struct sh_mobile_meram_fb_plane *plane)
 {
 	/* disable ICB */
-	meram_write_icb(priv->base, icb->cache_icb,  MExxCTL,
+	meram_write_icb(priv->base, plane->cache->index,  MExxCTL,
 			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
-	meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
+	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
 			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
 
-	priv->icbs[icb->cache_icb].cache_unit = 0;
-	priv->icbs[icb->marker_icb].cache_unit = 0;
+	plane->cache->cache_unit = 0;
+	plane->marker->cache_unit = 0;
 }
 
 /* -----------------------------------------------------------------------------
  * Registration/unregistration
  */
 
-static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
-				    const struct sh_mobile_meram_cfg *cfg,
-				    unsigned int xres, unsigned int yres,
-				    unsigned int pixelformat,
-				    unsigned long base_addr_y,
-				    unsigned long base_addr_c,
-				    unsigned long *icb_addr_y,
-				    unsigned long *icb_addr_c,
-				    unsigned int *pitch)
+static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+				      const struct sh_mobile_meram_cfg *cfg,
+				      unsigned int xres, unsigned int yres,
+				      unsigned int pixelformat,
+				      unsigned long base_addr_y,
+				      unsigned long base_addr_c,
+				      unsigned long *icb_addr_y,
+				      unsigned long *icb_addr_c,
+				      unsigned int *pitch)
 {
-	struct platform_device *pdev;
+	struct sh_mobile_meram_fb_cache *cache;
 	struct sh_mobile_meram_priv *priv;
+	struct platform_device *pdev;
 	unsigned int out_pitch;
-	unsigned int n;
-	int error = 0;
 
 	if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 
 	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
 	    pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
 	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 
 	priv = pdata->priv;
 	pdev = pdata->pdev;
@@ -418,120 +476,82 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 	/* we can't handle wider than 8192px */
 	if (xres > 8192) {
 		dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
-		return -EINVAL;
-	}
-
-	/* do we have at least one ICB config? */
-	if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
-		dev_err(&pdev->dev, "at least one ICB is required.");
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	mutex_lock(&priv->lock);
 
-	/* make sure that there's no overlaps */
-	if (meram_check_overlap(priv, &cfg->icb[0])) {
-		dev_err(&pdev->dev, "conflicting config detected.");
-		error = -EINVAL;
-		goto err;
-	}
-	n = 1;
-
-	/* do the same if we have the second ICB set */
-	if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
-		if (meram_check_overlap(priv, &cfg->icb[1])) {
-			dev_err(&pdev->dev, "conflicting config detected.");
-			error = -EINVAL;
-			goto err;
-		}
-		n = 2;
-	}
-
-	if (is_nvcolor(pixelformat) && n != 2) {
-		dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
-		error =  -EINVAL;
-		goto err;
-	}
-
 	/* We now register the ICBs and allocate the MERAM regions. */
-	error = meram_alloc(priv, &cfg->icb[0], pixelformat);
-	if (error < 0)
+	cache = meram_alloc(priv, cfg, pixelformat);
+	if (IS_ERR(cache)) {
+		dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
+			PTR_ERR(cache));
 		goto err;
-
-	if (is_nvcolor(pixelformat)) {
-		error = meram_alloc(priv, &cfg->icb[1], pixelformat);
-		if (error < 0) {
-			meram_free(priv, &cfg->icb[0]);
-			goto err;
-		}
 	}
 
 	/* initialize MERAM */
-	meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch);
+	meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
 	*pitch = out_pitch;
 	if (pixelformat == SH_MOBILE_MERAM_PF_NV)
-		meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
+		meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
 			&out_pitch);
 	else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
-		meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
+		meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
 			&out_pitch);
 
-	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
-	meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+	meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
+	meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
 
 	dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
 		*icb_addr_y, *icb_addr_c);
 
 err:
 	mutex_unlock(&priv->lock);
-	return error;
+	return cache;
 }
 
-static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
-				      const struct sh_mobile_meram_cfg *cfg)
+static int
+sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
 {
+	struct sh_mobile_meram_fb_cache *cache = data;
 	struct sh_mobile_meram_priv *priv;
-	struct sh_mobile_meram_icb *icb;
 
-	if (!pdata || !pdata->priv || !cfg)
+	if (!pdata || !pdata->priv || !data)
 		return -EINVAL;
 
 	priv = pdata->priv;
-	icb = &priv->icbs[cfg->icb[0].marker_icb];
 
 	mutex_lock(&priv->lock);
 
-	/* deinit & unmark */
-	if (is_nvcolor(icb->pixelformat)) {
-		meram_deinit(priv, &cfg->icb[1]);
-		meram_free(priv, &cfg->icb[1]);
-	}
-	meram_deinit(priv, &cfg->icb[0]);
-	meram_free(priv, &cfg->icb[0]);
+	/* deinit & free */
+	meram_deinit(priv, &cache->planes[0]);
+	if (cache->nplanes == 2)
+		meram_deinit(priv, &cache->planes[1]);
+
+	meram_free(priv, cache);
 
 	mutex_unlock(&priv->lock);
 
 	return 0;
 }
 
-static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
-				  const struct sh_mobile_meram_cfg *cfg,
-				  unsigned long base_addr_y,
-				  unsigned long base_addr_c,
-				  unsigned long *icb_addr_y,
-				  unsigned long *icb_addr_c)
+static int
+sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
+		       unsigned long base_addr_y, unsigned long base_addr_c,
+		       unsigned long *icb_addr_y, unsigned long *icb_addr_c)
 {
+	struct sh_mobile_meram_fb_cache *cache = data;
 	struct sh_mobile_meram_priv *priv;
 
-	if (!pdata || !pdata->priv || !cfg)
+	if (!pdata || !pdata->priv || !data)
 		return -EINVAL;
 
 	priv = pdata->priv;
 
 	mutex_lock(&priv->lock);
 
-	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
-	meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+	meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
+	meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
 
 	mutex_unlock(&priv->lock);
 
@@ -607,6 +627,7 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
 	struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
 	struct resource *regs;
 	struct resource *meram;
+	unsigned int i;
 	int error;
 
 	if (!pdata) {
@@ -629,6 +650,10 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
 
 	/* initialize private data */
 	mutex_init(&priv->lock);
+
+	for (i = 0; i < MERAM_ICB_NUM; ++i)
+		priv->icbs[i].index = i;
+
 	pdata->ops = &sh_mobile_meram_ops;
 	pdata->priv = priv;
 	pdata->pdev = pdev;
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index f7700fc..ea96b5a 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -39,23 +39,23 @@ struct module;
 struct sh_mobile_meram_ops {
 	struct module	*module;
 	/* register usage of meram */
-	int (*meram_register)(struct sh_mobile_meram_info *meram_dev,
-			      const struct sh_mobile_meram_cfg *cfg,
-			      unsigned int xres, unsigned int yres,
-			      unsigned int pixelformat,
-			      unsigned long base_addr_y,
-			      unsigned long base_addr_c,
-			      unsigned long *icb_addr_y,
-			      unsigned long *icb_addr_c,
-			      unsigned int *pitch);
+	void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
+				const struct sh_mobile_meram_cfg *cfg,
+				unsigned int xres, unsigned int yres,
+				unsigned int pixelformat,
+				unsigned long base_addr_y,
+				unsigned long base_addr_c,
+				unsigned long *icb_addr_y,
+				unsigned long *icb_addr_c,
+				unsigned int *pitch);
 
 	/* unregister usage of meram */
 	int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
-				const struct sh_mobile_meram_cfg *cfg);
+				void *data);
 
 	/* update meram settings */
 	int (*meram_update)(struct sh_mobile_meram_info *meram_dev,
-			    const struct sh_mobile_meram_cfg *cfg,
+			    void *data,
 			    unsigned long base_addr_y,
 			    unsigned long base_addr_c,
 			    unsigned long *icb_addr_y,
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Tourism]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux