aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-08 07:35:44 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-17 05:09:35 -0400
commit406c8563a7b07ce91b1310536948477c7a8755de (patch)
tree11c5b6369a7fbf9d588a2f1e02f482cd15009183 /drivers/video
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
OMAP: VRFB: convert vrfb to platform device
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>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/vrfb.c124
1 files changed, 104 insertions, 20 deletions
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e990220ad2a..fda45cc10d48 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/bitops.h> 27#include <linux/bitops.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <linux/platform_device.h>
29 30
30#include <plat/vrfb.h> 31#include <plat/vrfb.h>
31#include <plat/sdrc.h>
32 32
33#ifdef DEBUG 33#ifdef DEBUG
34#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) 34#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
36#define DBG(format, ...) 36#define DBG(format, ...)
37#endif 37#endif
38 38
39#define SMS_ROT_VIRT_BASE(context, rot) \ 39#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
40 (((context >= 4) ? 0xD0000000 : 0x70000000) \ 40#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
41 + (0x4000000 * (context)) \ 41#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
42 + (0x1000000 * (rot))) 42#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
43 43
44#define OMAP_VRFB_SIZE (2048 * 2048 * 4) 44#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
45 45
@@ -53,10 +53,16 @@
53#define SMS_PW_OFFSET 4 53#define SMS_PW_OFFSET 4
54#define SMS_PS_OFFSET 0 54#define SMS_PS_OFFSET 0
55 55
56#define VRFB_NUM_CTXS 12
57/* bitmap of reserved contexts */ 56/* bitmap of reserved contexts */
58static unsigned long ctx_map; 57static unsigned long ctx_map;
59 58
59struct vrfb_ctx {
60 u32 base;
61 u32 physical_ba;
62 u32 control;
63 u32 size;
64};
65
60static DEFINE_MUTEX(ctx_lock); 66static DEFINE_MUTEX(ctx_lock);
61 67
62/* 68/*
@@ -65,17 +71,32 @@ static DEFINE_MUTEX(ctx_lock);
65 * we don't need locking, since no drivers will run until after the wake-up 71 * we don't need locking, since no drivers will run until after the wake-up
66 * has finished. 72 * has finished.
67 */ 73 */
68static struct { 74
69 u32 physical_ba; 75static void __iomem *vrfb_base;
70 u32 control; 76
71 u32 size; 77static int num_ctxs;
72} vrfb_hw_context[VRFB_NUM_CTXS]; 78static struct vrfb_ctx *ctxs;
79
80static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
81{
82 __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
83}
84
85static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
86{
87 __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
88}
89
90static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
91{
92 __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
93}
73 94
74static inline void restore_hw_context(int ctx) 95static inline void restore_hw_context(int ctx)
75{ 96{
76 omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); 97 omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
77 omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); 98 omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
78 omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); 99 omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
79} 100}
80 101
81static u32 get_image_width_roundup(u16 width, u8 bytespp) 102static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +217,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
196 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; 217 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
197 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; 218 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
198 219
199 vrfb_hw_context[ctx].physical_ba = paddr; 220 ctxs[ctx].physical_ba = paddr;
200 vrfb_hw_context[ctx].size = size; 221 ctxs[ctx].size = size;
201 vrfb_hw_context[ctx].control = control; 222 ctxs[ctx].control = control;
202 223
203 omap2_sms_write_rot_physical_ba(paddr, ctx); 224 omap2_sms_write_rot_physical_ba(paddr, ctx);
204 omap2_sms_write_rot_size(size, ctx); 225 omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +295,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
274 295
275 mutex_lock(&ctx_lock); 296 mutex_lock(&ctx_lock);
276 297
277 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) 298 for (ctx = 0; ctx < num_ctxs; ++ctx)
278 if ((ctx_map & (1 << ctx)) == 0) 299 if ((ctx_map & (1 << ctx)) == 0)
279 break; 300 break;
280 301
281 if (ctx == VRFB_NUM_CTXS) { 302 if (ctx == num_ctxs) {
282 pr_err("vrfb: no free contexts\n"); 303 pr_err("vrfb: no free contexts\n");
283 r = -EBUSY; 304 r = -EBUSY;
284 goto out; 305 goto out;
@@ -293,7 +314,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
293 vrfb->context = ctx; 314 vrfb->context = ctx;
294 315
295 for (rot = 0; rot < 4; ++rot) { 316 for (rot = 0; rot < 4; ++rot) {
296 paddr = SMS_ROT_VIRT_BASE(ctx, rot); 317 paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
297 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { 318 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
298 pr_err("vrfb: failed to reserve VRFB " 319 pr_err("vrfb: failed to reserve VRFB "
299 "area for ctx %d, rotation %d\n", 320 "area for ctx %d, rotation %d\n",
@@ -314,3 +335,66 @@ out:
314 return r; 335 return r;
315} 336}
316EXPORT_SYMBOL(omap_vrfb_request_ctx); 337EXPORT_SYMBOL(omap_vrfb_request_ctx);
338
339static int __init vrfb_probe(struct platform_device *pdev)
340{
341 struct resource *mem;
342 int i;
343
344 /* first resource is the register res, the rest are vrfb contexts */
345
346 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
347 if (!mem) {
348 dev_err(&pdev->dev, "can't get vrfb base address\n");
349 return -EINVAL;
350 }
351
352 vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
353 if (!vrfb_base) {
354 dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
355 return -ENOMEM;
356 }
357
358 num_ctxs = pdev->num_resources - 1;
359
360 ctxs = devm_kzalloc(&pdev->dev,
361 sizeof(struct vrfb_ctx) * num_ctxs,
362 GFP_KERNEL);
363
364 if (!ctxs)
365 return -ENOMEM;
366
367 for (i = 0; i < num_ctxs; ++i) {
368 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
369 if (!mem) {
370 dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
371 i);
372 return -EINVAL;
373 }
374
375 ctxs[i].base = mem->start;
376 }
377
378 return 0;
379}
380
381static struct platform_driver vrfb_driver = {
382 .driver.name = "omapvrfb",
383};
384
385static int __init vrfb_init(void)
386{
387 return platform_driver_probe(&vrfb_driver, &vrfb_probe);
388}
389
390static void __exit vrfb_exit(void)
391{
392 platform_driver_unregister(&vrfb_driver);
393}
394
395module_init(vrfb_init);
396module_exit(vrfb_exit);
397
398MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
399MODULE_DESCRIPTION("OMAP VRFB");
400MODULE_LICENSE("GPL v2");