* [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation
@ 2011-12-13 14:02 Laurent Pinchart
2011-12-15 2:43 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage Damian Hobson-Garcia
2011-12-15 11:37 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
0 siblings, 2 replies; 3+ messages in thread
From: Laurent Pinchart @ 2011-12-13 14:02 UTC (permalink / raw)
To: linux-fbdev
Instead of requiring the users to hardcode MERAM allocation in platform
data, allocate blocks at runtime using genalloc.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/mach-shmobile/board-ap4evb.c | 4 -
arch/arm/mach-shmobile/board-mackerel.c | 4 -
drivers/video/Kconfig | 1 +
drivers/video/sh_mobile_meram.c | 110 +++++++++++++++++++------------
include/video/sh_mobile_meram.h | 1 -
5 files changed, 69 insertions(+), 51 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index a980645..d3896dc 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -591,13 +591,11 @@ static struct sh_mobile_meram_cfg lcd_meram_cfg = {
.icb[0] = {
.marker_icb = 28,
.cache_icb = 24,
- .meram_offset = 0x0,
.meram_size = 0x40,
},
.icb[1] = {
.marker_icb = 29,
.cache_icb = 25,
- .meram_offset = 0x40,
.meram_size = 0x40,
},
};
@@ -862,13 +860,11 @@ static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
.icb[0] = {
.marker_icb = 30,
.cache_icb = 26,
- .meram_offset = 0x80,
.meram_size = 0x100,
},
.icb[1] = {
.marker_icb = 31,
.cache_icb = 27,
- .meram_offset = 0x180,
.meram_size = 0x100,
},
};
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 0021994..d555d9e 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -378,13 +378,11 @@ static struct sh_mobile_meram_cfg lcd_meram_cfg = {
.icb[0] = {
.marker_icb = 28,
.cache_icb = 24,
- .meram_offset = 0x0,
.meram_size = 0x40,
},
.icb[1] = {
.marker_icb = 29,
.cache_icb = 25,
- .meram_offset = 0x40,
.meram_size = 0x40,
},
};
@@ -470,13 +468,11 @@ static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
.icb[0] = {
.marker_icb = 30,
.cache_icb = 26,
- .meram_offset = 0x80,
.meram_size = 0x100,
},
.icb[1] = {
.marker_icb = 31,
.cache_icb = 27,
- .meram_offset = 0x180,
.meram_size = 0x100,
},
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index dcf0a82..e4c5a76 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2004,6 +2004,7 @@ config FB_SH_MOBILE_HDMI
config FB_SH_MOBILE_MERAM
tristate "SuperH Mobile MERAM read ahead support for LCDC"
depends on FB_SH_MOBILE_LCDC
+ select GENERIC_ALLOCATOR
default y
---help---
Enable MERAM support for the SH-Mobile LCD controller.
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 30a3305..7cd706d 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/genalloc.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -105,15 +106,17 @@ static const unsigned long icb_regs[] = {
/*
* sh_mobile_meram_icb - MERAM ICB information
* @regs: Registers cache
- * @region: Start and end addresses of the MERAM region
+ * @offset: MERAM block offset
+ * @size: MERAM block size in bytes
* @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 long offset;
+ unsigned int size;
- unsigned long region;
unsigned int cache_unit;
unsigned int pixelformat;
unsigned int current_reg;
@@ -124,21 +127,27 @@ struct sh_mobile_meram_icb {
/*
* sh_mobile_meram_priv - MERAM device
* @base: Registers base address
+ * @meram: MERAM physical address
* @regs: Registers cache
* @lock: Protects used_icb and icbs
* @used_icb: Bitmask of used ICBs
* @icbs: ICBs
+ * @pool: Allocation pool to manage the MERAM
*/
struct sh_mobile_meram_priv {
void __iomem *base;
+ unsigned long meram;
unsigned long regs[MERAM_REGS_SIZE];
struct mutex lock;
unsigned long used_icb;
struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
+
+ struct gen_pool *pool;
};
/* settings */
+#define MERAM_GRANULARITY 1024
#define MERAM_SEC_LINE 15
#define MERAM_LINE_WIDTH 2048
@@ -175,18 +184,10 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
* Allocation
*/
-#define MERAM_CACHE_START(p) ((p) >> 16)
-#define MERAM_CACHE_END(p) ((p) & 0xffff)
-#define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \
- (((o) + (s) - 1) & 0xffff))
-
/* 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)
{
- unsigned int used_start, used_end, meram_start, meram_end;
- unsigned int i;
-
/* valid ICB? */
if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f)
return 1;
@@ -195,43 +196,40 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv,
test_bit(new->cache_icb, &priv->used_icb))
return 1;
- for (i = 0; i < MERAM_ICB_NUM; i++) {
- if (!test_bit(i, &priv->used_icb))
- continue;
-
- used_start = MERAM_CACHE_START(priv->icbs[i].region);
- used_end = MERAM_CACHE_END(priv->icbs[i].region);
- meram_start = new->meram_offset;
- meram_end = new->meram_offset + new->meram_size;
-
- if ((meram_start >= used_start && meram_start < used_end) ||
- (meram_end > used_start && meram_end < used_end))
- return 1;
- }
-
return 0;
}
-/* Mark the specified ICB as used. */
-static void meram_mark(struct sh_mobile_meram_priv *priv,
+/* 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;
+
+ mem = gen_pool_alloc(priv->pool, new->meram_size * 1024);
+ if (mem = 0)
+ return -ENOMEM;
+
__set_bit(new->marker_icb, &priv->used_icb);
__set_bit(new->cache_icb, &priv->used_icb);
- priv->icbs[new->marker_icb].region = MERAM_CACHE_SET(new->meram_offset,
- new->meram_size);
- priv->icbs[new->cache_icb].region = MERAM_CACHE_SET(new->meram_offset,
- new->meram_size);
- priv->icbs[new->marker_icb].current_reg = 1;
- priv->icbs[new->marker_icb].pixelformat = pixelformat;
+ marker->offset = mem - priv->meram;
+ marker->size = new->meram_size * 1024;
+ marker->current_reg = 1;
+ marker->pixelformat = pixelformat;
+
+ return 0;
}
/* Unmark the specified ICB as used. */
-static void meram_unmark(struct sh_mobile_meram_priv *priv,
- const struct sh_mobile_meram_icb_cfg *icb)
+static void meram_free(struct sh_mobile_meram_priv *priv,
+ const struct sh_mobile_meram_icb_cfg *icb)
{
+ struct sh_mobile_meram_icb *marker = &priv->icbs[icb->marker_icb];
+
+ 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);
}
@@ -302,6 +300,7 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
unsigned int xres, unsigned int yres,
unsigned int *out_pitch)
{
+ struct sh_mobile_meram_icb *marker = &priv->icbs[icb->marker_icb];
unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
unsigned long bnm;
unsigned int lcdc_pitch;
@@ -356,11 +355,11 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
* 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, icb->meram_offset) |
+ MERAM_MExxCTL_VAL(icb->marker_icb, 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, icb->meram_offset +
+ MERAM_MExxCTL_VAL(icb->cache_icb, marker->offset +
icb->meram_size / 2) |
MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
MExxCTL_MD_FB);
@@ -454,10 +453,18 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
goto err;
}
- /* we now register the ICB */
- meram_mark(priv, &cfg->icb[0], pixelformat);
- if (is_nvcolor(pixelformat))
- meram_mark(priv, &cfg->icb[1], pixelformat);
+ /* We now register the ICBs and allocate the MERAM regions. */
+ error = meram_alloc(priv, &cfg->icb[0], pixelformat);
+ if (error < 0)
+ 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);
@@ -497,10 +504,10 @@ static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
/* deinit & unmark */
if (is_nvcolor(icb->pixelformat)) {
meram_deinit(priv, &cfg->icb[1]);
- meram_unmark(priv, &cfg->icb[1]);
+ meram_free(priv, &cfg->icb[1]);
}
meram_deinit(priv, &cfg->icb[0]);
- meram_unmark(priv, &cfg->icb[0]);
+ meram_free(priv, &cfg->icb[0]);
mutex_unlock(&priv->lock);
@@ -626,6 +633,7 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
pdata->priv = priv;
pdata->pdev = pdev;
+ /* Request memory regions and remap the registers. */
if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
dev_err(&pdev->dev, "MERAM registers region already claimed\n");
error = -EBUSY;
@@ -646,6 +654,18 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
goto err_ioremap;
}
+ /* Create and initialize the MERAM memory pool. */
+ priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
+ if (priv->pool = NULL) {
+ error = -ENOMEM;
+ goto err_genpool;
+ }
+
+ error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
+ -1);
+ if (error < 0)
+ goto err_genpool;
+
/* initialize ICB addressing mode */
if (pdata->addr_mode = SH_MOBILE_MERAM_MODE1)
meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
@@ -657,6 +677,10 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
return 0;
+err_genpool:
+ if (priv->pool)
+ gen_pool_destroy(priv->pool);
+ iounmap(priv->base);
err_ioremap:
release_mem_region(meram->start, resource_size(meram));
err_req_meram:
@@ -677,6 +701,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
+ gen_pool_destroy(priv->pool);
+
iounmap(priv->base);
release_mem_region(meram->start, resource_size(meram));
release_mem_region(regs->start, resource_size(regs));
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 05ca3f9..f7700fc 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -28,7 +28,6 @@ struct sh_mobile_meram_info {
struct sh_mobile_meram_icb_cfg {
unsigned int marker_icb; /* ICB # for Marker ICB */
unsigned int cache_icb; /* ICB # for Cache ICB */
- unsigned int meram_offset; /* MERAM Buffer Offset to use */
unsigned int meram_size; /* MERAM Buffer Size to use */
};
--
1.7.3.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage
2011-12-13 14:02 [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
@ 2011-12-15 2:43 ` Damian Hobson-Garcia
2011-12-15 11:37 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: Damian Hobson-Garcia @ 2011-12-15 2:43 UTC (permalink / raw)
To: linux-fbdev
On 2011/12/13 23:02, Laurent Pinchart wrote:
> @@ -195,43 +196,40 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv,
> test_bit(new->cache_icb, &priv->used_icb))
> return 1;
>
> - for (i = 0; i < MERAM_ICB_NUM; i++) {
> - if (!test_bit(i, &priv->used_icb))
> - continue;
> -
> - used_start = MERAM_CACHE_START(priv->icbs[i].region);
> - used_end = MERAM_CACHE_END(priv->icbs[i].region);
> - meram_start = new->meram_offset;
> - meram_end = new->meram_offset + new->meram_size;
> -
> - if ((meram_start >= used_start && meram_start < used_end) ||
> - (meram_end > used_start && meram_end < used_end))
> - return 1;
> - }
> -
> return 0;
> }
>
> -/* Mark the specified ICB as used. */
> -static void meram_mark(struct sh_mobile_meram_priv *priv,
> +/* 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;
> +
> + mem = gen_pool_alloc(priv->pool, new->meram_size * 1024);
> + if (mem = 0)
> + return -ENOMEM;
> +
> __set_bit(new->marker_icb, &priv->used_icb);
> __set_bit(new->cache_icb, &priv->used_icb);
>
> - priv->icbs[new->marker_icb].region = MERAM_CACHE_SET(new->meram_offset,
> - new->meram_size);
> - priv->icbs[new->cache_icb].region = MERAM_CACHE_SET(new->meram_offset,
> - new->meram_size);
> - priv->icbs[new->marker_icb].current_reg = 1;
> - priv->icbs[new->marker_icb].pixelformat = pixelformat;
> + marker->offset = mem - priv->meram;
I might have missed this somewhere, but it doesn't look like priv->meram
is assigned anywhere.
Damian
--
Damian Hobson-Garcia
IGEL Co.,Ltd
http://www.igel.co.jp
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation
2011-12-13 14:02 [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
2011-12-15 2:43 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage Damian Hobson-Garcia
@ 2011-12-15 11:37 ` Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Pinchart @ 2011-12-15 11:37 UTC (permalink / raw)
To: linux-fbdev
Hi Damian,
Thanks for the review.
On Thursday 15 December 2011 03:43:06 Damian Hobson-Garcia wrote:
> On 2011/12/13 23:02, Laurent Pinchart wrote:
> > @@ -195,43 +196,40 @@ static int meram_check_overlap(struct
> > sh_mobile_meram_priv *priv,
> >
> > test_bit(new->cache_icb, &priv->used_icb))
> >
> > return 1;
> >
> > - for (i = 0; i < MERAM_ICB_NUM; i++) {
> > - if (!test_bit(i, &priv->used_icb))
> > - continue;
> > -
> > - used_start = MERAM_CACHE_START(priv->icbs[i].region);
> > - used_end = MERAM_CACHE_END(priv->icbs[i].region);
> > - meram_start = new->meram_offset;
> > - meram_end = new->meram_offset + new->meram_size;
> > -
> > - if ((meram_start >= used_start && meram_start < used_end) ||
> > - (meram_end > used_start && meram_end < used_end))
> > - return 1;
> > - }
> > -
> >
> > return 0;
> >
> > }
> >
> > -/* Mark the specified ICB as used. */
> > -static void meram_mark(struct sh_mobile_meram_priv *priv,
> > +/* 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;
> > +
> > + mem = gen_pool_alloc(priv->pool, new->meram_size * 1024);
> > + if (mem = 0)
> > + return -ENOMEM;
> > +
> >
> > __set_bit(new->marker_icb, &priv->used_icb);
> > __set_bit(new->cache_icb, &priv->used_icb);
> >
> > - priv->icbs[new->marker_icb].region = MERAM_CACHE_SET(new->meram_offset,
> > - new->meram_size);
> > - priv->icbs[new->cache_icb].region = MERAM_CACHE_SET(new->meram_offset,
> > - new->meram_size);
> > - priv->icbs[new->marker_icb].current_reg = 1;
> > - priv->icbs[new->marker_icb].pixelformat = pixelformat;
> > + marker->offset = mem - priv->meram;
>
> I might have missed this somewhere, but it doesn't look like priv->meram
> is assigned anywhere.
Oops. That got lost in a rebase operation :-/ I'll fix it.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-12-15 11:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-13 14:02 [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
2011-12-15 2:43 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage Damian Hobson-Garcia
2011-12-15 11:37 ` [PATCH 47/57] fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation Laurent Pinchart
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).