diff mbox

[PATCHv2,1/3] OMAP: VRFB: convert vrfb to platform device

Message ID 1349785827-27055-2-git-send-email-tomi.valkeinen@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomi Valkeinen Oct. 9, 2012, 12:30 p.m. UTC
This patch converts vrfb library into a platform device, in an effort to
remove omap dependencies.

The platform device is registered in arch/arm/plat-omap/fb.c and
assigned resources depending on whether running on omap2 or omap3.

The vrfb driver will parse those resources and use them to access vrfb
configuration registers and the vrfb virtual rotation areas.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/fb.c                |   59 +++++++++++++++
 arch/arm/plat-omap/include/plat/vrfb.h |    2 +-
 drivers/video/omap2/Kconfig            |    2 +-
 drivers/video/omap2/vrfb.c             |  124 ++++++++++++++++++++++++++------
 4 files changed, 165 insertions(+), 22 deletions(-)

Comments

Kevin Hilman Oct. 9, 2012, 8:37 p.m. UTC | #1
Hi Tomi,

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> This patch converts vrfb library into a platform device, in an effort to
> remove omap dependencies.
>
> The platform device is registered in arch/arm/plat-omap/fb.c and
> assigned resources depending on whether running on omap2 or omap3.
>
> The vrfb driver will parse those resources and use them to access vrfb
> configuration registers and the vrfb virtual rotation areas.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Tony Lindgren <tony@atomide.com>

[...]

I was having a quick look at this for the context save/restore piece in
order to understand how this driver's context is being saved/restored.

Looking at mainline, I don't see where omap_vrfb_restore_context() is
being called currently.  Am I missing something?

Kevin



--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen Oct. 10, 2012, 4:07 a.m. UTC | #2
On Tue, 2012-10-09 at 13:37 -0700, Kevin Hilman wrote:
> Hi Tomi,
> 
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > This patch converts vrfb library into a platform device, in an effort to
> > remove omap dependencies.
> >
> > The platform device is registered in arch/arm/plat-omap/fb.c and
> > assigned resources depending on whether running on omap2 or omap3.
> >
> > The vrfb driver will parse those resources and use them to access vrfb
> > configuration registers and the vrfb virtual rotation areas.
> >
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> > Cc: Tony Lindgren <tony@atomide.com>
> 
> [...]
> 
> I was having a quick look at this for the context save/restore piece in
> order to understand how this driver's context is being saved/restored.
> 
> Looking at mainline, I don't see where omap_vrfb_restore_context() is
> being called currently.  Am I missing something?

No, the driver is missing something. I noticed the same thing. It seems
ctx restore for vrfb has never been functional in mainline. I don't
really have any recollection if this was left out intentionally from
mainline (possibly because we didn't have a good way to handle it at
that point), or was it just a mistake.

Nobody has complained about it, though, so it can't be a major problem
=).

Vrfb is a platform device/driver after this patch. Do you see any
problem with handling the context restore in runtime PM's runtime_resume
callback? Hmm, I guess then we could have a problem if omapdss and
omapfb are resumed before vrfb.

Any way to manage the suspend/resume ordering of unrelated (i.e. no
parent/child relation) devices?

 Tomi
Kevin Hilman Oct. 10, 2012, 6:12 p.m. UTC | #3
Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> On Tue, 2012-10-09 at 13:37 -0700, Kevin Hilman wrote:
>> Hi Tomi,
>> 
>> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
>> 
>> > This patch converts vrfb library into a platform device, in an effort to
>> > remove omap dependencies.
>> >
>> > The platform device is registered in arch/arm/plat-omap/fb.c and
>> > assigned resources depending on whether running on omap2 or omap3.
>> >
>> > The vrfb driver will parse those resources and use them to access vrfb
>> > configuration registers and the vrfb virtual rotation areas.
>> >
>> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> > Cc: Tony Lindgren <tony@atomide.com>
>> 
>> [...]
>> 
>> I was having a quick look at this for the context save/restore piece in
>> order to understand how this driver's context is being saved/restored.
>> 
>> Looking at mainline, I don't see where omap_vrfb_restore_context() is
>> being called currently.  Am I missing something?
>
> No, the driver is missing something. I noticed the same thing. It seems
> ctx restore for vrfb has never been functional in mainline. I don't
> really have any recollection if this was left out intentionally from
> mainline (possibly because we didn't have a good way to handle it at
> that point), or was it just a mistake.
>
> Nobody has complained about it, though, so it can't be a major problem
> =).

heh

> Vrfb is a platform device/driver after this patch. Do you see any
> problem with handling the context restore in runtime PM's runtime_resume
> callback? 

No, that's the right way to handle it IMO.  In fact, that's what I was
going to check on when reviewing this patch when I noticed that the
restore function wasn't being used.

> Hmm, I guess then we could have a problem if omapdss and
> omapfb are resumed before vrfb.

Possibly, but this could be handled by adding some sanity checks, or
having VRFB functions return -EAGAIN if it hasn't been resumed.  Or
better yet, VRFB functions should be using runtime PM get/put
themselves, if they're used by omapdss/omapfb, a runtime resume (and
context restore) is forced.  (disclaimer: I don't actually know how VRFB
works, so maybe this isn't possible.)

> Any way to manage the suspend/resume ordering of unrelated (i.e. no
> parent/child relation) devices?

No good way at the moment.

And to make things interesting: static suspend/resume ordering is not
dependent on parent/child.  It's based on driver discover/probe order.

runtime PM ordering manages parent/child relationships.

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

Patch

diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index dd6f92c..a390784 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -35,6 +35,65 @@ 
 
 #include <plat/board.h>
 
+#if defined(CONFIG_OMAP2_VRFB) || defined(CONFIG_OMAP2_VRFB_MODULE)
+
+/*
+ * The first memory resource is the register region for VRFB,
+ * the rest are VRFB virtual memory areas for each VRFB context.
+ */
+
+static const struct resource omap2_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+};
+
+static const struct resource omap3_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+	DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
+	DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
+	DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
+	DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
+	DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
+	DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
+	DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
+	DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
+};
+
+static int __init omap_init_vrfb(void)
+{
+	struct platform_device *pdev;
+	const struct resource *res;
+	unsigned int num_res;
+
+	if (cpu_is_omap24xx()) {
+		res = omap2_vrfb_resources;
+		num_res = ARRAY_SIZE(omap2_vrfb_resources);
+	} else if (cpu_is_omap34xx()) {
+		res = omap3_vrfb_resources;
+		num_res = ARRAY_SIZE(omap3_vrfb_resources);
+	} else {
+		return 0;
+	}
+
+	pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
+			res, num_res, NULL, 0);
+
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+	else
+		return 0;
+}
+
+arch_initcall(omap_init_vrfb);
+#endif
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static bool omapfb_lcd_configured;
diff --git a/arch/arm/plat-omap/include/plat/vrfb.h b/arch/arm/plat-omap/include/plat/vrfb.h
index 3792bde..dafbb77 100644
--- a/arch/arm/plat-omap/include/plat/vrfb.h
+++ b/arch/arm/plat-omap/include/plat/vrfb.h
@@ -35,7 +35,7 @@  struct vrfb {
 	bool yuv_mode;
 };
 
-#ifdef CONFIG_OMAP2_VRFB
+#if defined(CONFIG_OMAP2_VRFB) || defined(CONFIG_OMAP2_VRFB_MODULE)
 extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index d877c36..4700ca9 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -2,7 +2,7 @@  config OMAP2_VRAM
 	bool
 
 config OMAP2_VRFB
-	bool
+	tristate
 
 source "drivers/video/omap2/dss/Kconfig"
 source "drivers/video/omap2/omapfb/Kconfig"
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e99022..fda45cc 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@ 
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 
 #include <plat/vrfb.h>
-#include <plat/sdrc.h>
 
 #ifdef DEBUG
 #define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@ 
 #define DBG(format, ...)
 #endif
 
-#define SMS_ROT_VIRT_BASE(context, rot) \
-	(((context >= 4) ? 0xD0000000 : 0x70000000) \
-	 + (0x4000000 * (context)) \
-	 + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context)	(0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context)		(0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context)	(0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot)		(0x1000000 * (rot))
 
 #define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
 
@@ -53,10 +53,16 @@ 
 #define SMS_PW_OFFSET		4
 #define SMS_PS_OFFSET		0
 
-#define VRFB_NUM_CTXS 12
 /* bitmap of reserved contexts */
 static unsigned long ctx_map;
 
+struct vrfb_ctx {
+	u32 base;
+	u32 physical_ba;
+	u32 control;
+	u32 size;
+};
+
 static DEFINE_MUTEX(ctx_lock);
 
 /*
@@ -65,17 +71,32 @@  static DEFINE_MUTEX(ctx_lock);
  * we don't need locking, since no drivers will run until after the wake-up
  * has finished.
  */
-static struct {
-	u32 physical_ba;
-	u32 control;
-	u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
 
 static inline void restore_hw_context(int ctx)
 {
-	omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
-	omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
-	omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+	omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+	omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+	omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
 }
 
 static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +217,9 @@  void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
 	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
 	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
 
-	vrfb_hw_context[ctx].physical_ba = paddr;
-	vrfb_hw_context[ctx].size = size;
-	vrfb_hw_context[ctx].control = control;
+	ctxs[ctx].physical_ba = paddr;
+	ctxs[ctx].size = size;
+	ctxs[ctx].control = control;
 
 	omap2_sms_write_rot_physical_ba(paddr, ctx);
 	omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +295,11 @@  int omap_vrfb_request_ctx(struct vrfb *vrfb)
 
 	mutex_lock(&ctx_lock);
 
-	for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+	for (ctx = 0; ctx < num_ctxs; ++ctx)
 		if ((ctx_map & (1 << ctx)) == 0)
 			break;
 
-	if (ctx == VRFB_NUM_CTXS) {
+	if (ctx == num_ctxs) {
 		pr_err("vrfb: no free contexts\n");
 		r = -EBUSY;
 		goto out;
@@ -293,7 +314,7 @@  int omap_vrfb_request_ctx(struct vrfb *vrfb)
 	vrfb->context = ctx;
 
 	for (rot = 0; rot < 4; ++rot) {
-		paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
 		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
 			pr_err("vrfb: failed to reserve VRFB "
 					"area for ctx %d, rotation %d\n",
@@ -314,3 +335,66 @@  out:
 	return r;
 }
 EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int i;
+
+	/* first resource is the register res, the rest are vrfb contexts */
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "can't get vrfb base address\n");
+		return -EINVAL;
+	}
+
+	vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!vrfb_base) {
+		dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+		return -ENOMEM;
+	}
+
+	num_ctxs = pdev->num_resources - 1;
+
+	ctxs = devm_kzalloc(&pdev->dev,
+			sizeof(struct vrfb_ctx) * num_ctxs,
+			GFP_KERNEL);
+
+	if (!ctxs)
+		return -ENOMEM;
+
+	for (i = 0; i < num_ctxs; ++i) {
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+		if (!mem) {
+			dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+					i);
+			return -EINVAL;
+		}
+
+		ctxs[i].base = mem->start;
+	}
+
+	return 0;
+}
+
+static struct platform_driver vrfb_driver = {
+	.driver.name	= "omapvrfb",
+};
+
+static int __init vrfb_init(void)
+{
+	return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+	platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");