|
@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
|
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
- * Allocation
|
|
|
+ * LCDC cache planes allocation, init, cleanup and free
|
|
|
*/
|
|
|
|
|
|
/* 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)
|
|
|
+static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
|
|
|
+ struct sh_mobile_meram_fb_plane *plane,
|
|
|
+ size_t size)
|
|
|
{
|
|
|
unsigned long mem;
|
|
|
unsigned long idx;
|
|
@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
|
|
|
}
|
|
|
|
|
|
/* Free ICBs and MERAM for a plane. */
|
|
|
-static void __meram_free(struct sh_mobile_meram_priv *priv,
|
|
|
- struct sh_mobile_meram_fb_plane *plane)
|
|
|
+static void meram_plane_free(struct sh_mobile_meram_priv *priv,
|
|
|
+ struct sh_mobile_meram_fb_plane *plane)
|
|
|
{
|
|
|
gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
|
|
|
plane->marker->size * 1024);
|
|
@@ -248,62 +248,6 @@ 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,
|
|
|
struct sh_mobile_meram_fb_cache *cache,
|
|
@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
|
|
|
(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
|
|
|
|
|
|
/* Initialize MERAM. */
|
|
|
-static int meram_init(struct sh_mobile_meram_priv *priv,
|
|
|
- struct sh_mobile_meram_fb_plane *plane,
|
|
|
- unsigned int xres, unsigned int yres,
|
|
|
- unsigned int *out_pitch)
|
|
|
+static int meram_plane_init(struct sh_mobile_meram_priv *priv,
|
|
|
+ struct sh_mobile_meram_fb_plane *plane,
|
|
|
+ unsigned int xres, unsigned int yres,
|
|
|
+ unsigned int *out_pitch)
|
|
|
{
|
|
|
struct sh_mobile_meram_icb *marker = plane->marker;
|
|
|
unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
|
|
@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void meram_deinit(struct sh_mobile_meram_priv *priv,
|
|
|
- struct sh_mobile_meram_fb_plane *plane)
|
|
|
+static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
|
|
|
+ struct sh_mobile_meram_fb_plane *plane)
|
|
|
{
|
|
|
/* disable ICB */
|
|
|
meram_write_icb(priv->base, plane->cache->index, MExxCTL,
|
|
@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
|
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
- * Registration/unregistration
|
|
|
+ * LCDC cache operations
|
|
|
*/
|
|
|
|
|
|
-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 int *pitch)
|
|
|
+/* Allocate memory for the ICBs and mark them as used. */
|
|
|
+static struct sh_mobile_meram_fb_cache *
|
|
|
+meram_cache_alloc(struct sh_mobile_meram_priv *priv,
|
|
|
+ const struct sh_mobile_meram_cfg *cfg,
|
|
|
+ int pixelformat)
|
|
|
+{
|
|
|
+ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
|
|
|
+ struct sh_mobile_meram_fb_cache *cache;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ cache = kzalloc(sizeof(*cache), GFP_KERNEL);
|
|
|
+ if (cache == NULL)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+
|
|
|
+ cache->nplanes = nplanes;
|
|
|
+
|
|
|
+ ret = meram_plane_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_plane_alloc(priv, &cache->planes[1],
|
|
|
+ cfg->icb[1].meram_size);
|
|
|
+ if (ret < 0) {
|
|
|
+ meram_plane_free(priv, &cache->planes[0]);
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ return cache;
|
|
|
+
|
|
|
+error:
|
|
|
+ kfree(cache);
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+}
|
|
|
+
|
|
|
+static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
|
|
|
+ const struct sh_mobile_meram_cfg *cfg,
|
|
|
+ unsigned int xres, unsigned int yres,
|
|
|
+ unsigned int pixelformat,
|
|
|
+ unsigned int *pitch)
|
|
|
{
|
|
|
struct sh_mobile_meram_fb_cache *cache;
|
|
|
struct sh_mobile_meram_priv *priv = pdata->priv;
|
|
|
struct platform_device *pdev = pdata->pdev;
|
|
|
+ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
|
|
|
unsigned int out_pitch;
|
|
|
|
|
|
if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
|
|
@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
|
|
|
+ if (cfg->icb[0].meram_size == 0)
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
+
|
|
|
+ if (nplanes == 2 && cfg->icb[1].meram_size == 0)
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
+
|
|
|
mutex_lock(&priv->lock);
|
|
|
|
|
|
/* We now register the ICBs and allocate the MERAM regions. */
|
|
|
- cache = meram_alloc(priv, cfg, pixelformat);
|
|
|
+ cache = meram_cache_alloc(priv, cfg, pixelformat);
|
|
|
if (IS_ERR(cache)) {
|
|
|
dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
|
|
|
PTR_ERR(cache));
|
|
@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
|
|
|
}
|
|
|
|
|
|
/* initialize MERAM */
|
|
|
- meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
|
|
|
+ meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
|
|
|
*pitch = out_pitch;
|
|
|
if (pixelformat == SH_MOBILE_MERAM_PF_NV)
|
|
|
- meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
|
|
|
- &out_pitch);
|
|
|
+ meram_plane_init(priv, &cache->planes[1],
|
|
|
+ xres, (yres + 1) / 2, &out_pitch);
|
|
|
else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
|
|
|
- meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
|
|
|
- &out_pitch);
|
|
|
+ meram_plane_init(priv, &cache->planes[1],
|
|
|
+ 2 * xres, (yres + 1) / 2, &out_pitch);
|
|
|
|
|
|
err:
|
|
|
mutex_unlock(&priv->lock);
|
|
@@ -495,25 +487,29 @@ err:
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
|
|
|
+sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
|
|
|
{
|
|
|
struct sh_mobile_meram_fb_cache *cache = data;
|
|
|
struct sh_mobile_meram_priv *priv = pdata->priv;
|
|
|
|
|
|
mutex_lock(&priv->lock);
|
|
|
|
|
|
- /* deinit & free */
|
|
|
- meram_deinit(priv, &cache->planes[0]);
|
|
|
- if (cache->nplanes == 2)
|
|
|
- meram_deinit(priv, &cache->planes[1]);
|
|
|
+ /* Cleanup and free. */
|
|
|
+ meram_plane_cleanup(priv, &cache->planes[0]);
|
|
|
+ meram_plane_free(priv, &cache->planes[0]);
|
|
|
|
|
|
- meram_free(priv, cache);
|
|
|
+ if (cache->nplanes == 2) {
|
|
|
+ meram_plane_cleanup(priv, &cache->planes[1]);
|
|
|
+ meram_plane_free(priv, &cache->planes[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(cache);
|
|
|
|
|
|
mutex_unlock(&priv->lock);
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
|
|
|
+sh_mobile_cache_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)
|
|
|
{
|
|
@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
|
|
|
|
|
|
static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
|
|
|
.module = THIS_MODULE,
|
|
|
- .meram_register = sh_mobile_meram_register,
|
|
|
- .meram_unregister = sh_mobile_meram_unregister,
|
|
|
- .meram_update = sh_mobile_meram_update,
|
|
|
+ .cache_alloc = sh_mobile_cache_alloc,
|
|
|
+ .cache_free = sh_mobile_cache_free,
|
|
|
+ .cache_update = sh_mobile_cache_update,
|
|
|
};
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|