diff options
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 27 | ||||
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.h | 2 | ||||
-rw-r--r-- | drivers/video/sh_mobile_meram.c | 345 | ||||
-rw-r--r-- | include/video/sh_mobile_meram.h | 27 |
4 files changed, 215 insertions, 186 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index adc911f..d0c9026 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -840,6 +840,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) @@ -856,9 +857,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) { @@ -880,13 +881,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. */ @@ -951,13 +952,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; } } @@ -1070,14 +1069,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 92dc9bd..085c49a 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> @@ -106,14 +107,16 @@ static const unsigned long icb_regs[] = { /* * sh_mobile_meram_icb - MERAM ICB information * @regs: Registers cache + * @index: ICB index * @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 +127,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 +197,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 +248,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 +345,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 +356,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 +379,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 +393,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 +414,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 +428,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 +477,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 +628,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) { @@ -627,8 +649,13 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) return -ENOMEM; } - /* initialize private data */ + /* Initialize private data. */ mutex_init(&priv->lock); + priv->used_icb = pdata->reserved_icbs; + + 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..e0f650c 100644 --- a/include/video/sh_mobile_meram.h +++ b/include/video/sh_mobile_meram.h @@ -17,8 +17,13 @@ enum { struct sh_mobile_meram_priv; struct sh_mobile_meram_ops; +/* + * struct sh_mobile_meram_info - MERAM platform data + * @reserved_icbs: Bitmask of reserved ICBs (for instance used through UIO) + */ struct sh_mobile_meram_info { int addr_mode; + u32 reserved_icbs; struct sh_mobile_meram_ops *ops; struct sh_mobile_meram_priv *priv; struct platform_device *pdev; @@ -39,23 +44,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, |