diff options
Diffstat (limited to 'drivers/video/omap2')
| -rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 2 | ||||
| -rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 8 | ||||
| -rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 2 | ||||
| -rw-r--r-- | drivers/video/omap2/vrfb.c | 142 |
4 files changed, 125 insertions, 29 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 606b89f12351..55a39be694a5 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
| 31 | 31 | ||
| 32 | #include <video/omapdss.h> | 32 | #include <video/omapdss.h> |
| 33 | #include <plat/vrfb.h> | 33 | #include <video/omapvrfb.h> |
| 34 | #include <plat/vram.h> | 34 | #include <plat/vram.h> |
| 35 | 35 | ||
| 36 | #include "omapfb.h" | 36 | #include "omapfb.h" |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 16db1589bd91..bc225e46fdd2 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
| @@ -31,9 +31,8 @@ | |||
| 31 | #include <linux/omapfb.h> | 31 | #include <linux/omapfb.h> |
| 32 | 32 | ||
| 33 | #include <video/omapdss.h> | 33 | #include <video/omapdss.h> |
| 34 | #include <plat/cpu.h> | ||
| 35 | #include <plat/vram.h> | 34 | #include <plat/vram.h> |
| 36 | #include <plat/vrfb.h> | 35 | #include <video/omapvrfb.h> |
| 37 | 36 | ||
| 38 | #include "omapfb.h" | 37 | #include "omapfb.h" |
| 39 | 38 | ||
| @@ -2396,10 +2395,7 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
| 2396 | goto err0; | 2395 | goto err0; |
| 2397 | } | 2396 | } |
| 2398 | 2397 | ||
| 2399 | /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE | 2398 | if (def_vrfb && !omap_vrfb_supported()) { |
| 2400 | * available for OMAP2 and OMAP3 | ||
| 2401 | */ | ||
| 2402 | if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) { | ||
| 2403 | def_vrfb = 0; | 2399 | def_vrfb = 0; |
| 2404 | dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " | 2400 | dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " |
| 2405 | "ignoring the module parameter vrfb=y\n"); | 2401 | "ignoring the module parameter vrfb=y\n"); |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index e8d8cc76a435..17aa174e187c 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <linux/omapfb.h> | 30 | #include <linux/omapfb.h> |
| 31 | 31 | ||
| 32 | #include <video/omapdss.h> | 32 | #include <video/omapdss.h> |
| 33 | #include <plat/vrfb.h> | 33 | #include <video/omapvrfb.h> |
| 34 | 34 | ||
| 35 | #include "omapfb.h" | 35 | #include "omapfb.h" |
| 36 | 36 | ||
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c index 7e990220ad2a..5d8fdac3b800 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 <video/omapvrfb.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 */ |
| 58 | static unsigned long ctx_map; | 57 | static unsigned long ctx_map; |
| 59 | 58 | ||
| 59 | struct vrfb_ctx { | ||
| 60 | u32 base; | ||
| 61 | u32 physical_ba; | ||
| 62 | u32 control; | ||
| 63 | u32 size; | ||
| 64 | }; | ||
| 65 | |||
| 60 | static DEFINE_MUTEX(ctx_lock); | 66 | static DEFINE_MUTEX(ctx_lock); |
| 61 | 67 | ||
| 62 | /* | 68 | /* |
| @@ -65,17 +71,34 @@ 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 | */ |
| 68 | static struct { | 74 | |
| 69 | u32 physical_ba; | 75 | static void __iomem *vrfb_base; |
| 70 | u32 control; | 76 | |
| 71 | u32 size; | 77 | static int num_ctxs; |
| 72 | } vrfb_hw_context[VRFB_NUM_CTXS]; | 78 | static struct vrfb_ctx *ctxs; |
| 79 | |||
| 80 | static bool vrfb_loaded; | ||
| 81 | |||
| 82 | static void omap2_sms_write_rot_control(u32 val, unsigned ctx) | ||
| 83 | { | ||
| 84 | __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx)); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void omap2_sms_write_rot_size(u32 val, unsigned ctx) | ||
| 88 | { | ||
| 89 | __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx)); | ||
| 90 | } | ||
| 91 | |||
| 92 | static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx) | ||
| 93 | { | ||
| 94 | __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx)); | ||
| 95 | } | ||
| 73 | 96 | ||
| 74 | static inline void restore_hw_context(int ctx) | 97 | static inline void restore_hw_context(int ctx) |
| 75 | { | 98 | { |
| 76 | omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); | 99 | omap2_sms_write_rot_control(ctxs[ctx].control, ctx); |
| 77 | omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); | 100 | omap2_sms_write_rot_size(ctxs[ctx].size, ctx); |
| 78 | omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); | 101 | omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx); |
| 79 | } | 102 | } |
| 80 | 103 | ||
| 81 | static u32 get_image_width_roundup(u16 width, u8 bytespp) | 104 | static u32 get_image_width_roundup(u16 width, u8 bytespp) |
| @@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, | |||
| 196 | control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; | 219 | control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; |
| 197 | control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; | 220 | control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; |
| 198 | 221 | ||
| 199 | vrfb_hw_context[ctx].physical_ba = paddr; | 222 | ctxs[ctx].physical_ba = paddr; |
| 200 | vrfb_hw_context[ctx].size = size; | 223 | ctxs[ctx].size = size; |
| 201 | vrfb_hw_context[ctx].control = control; | 224 | ctxs[ctx].control = control; |
| 202 | 225 | ||
| 203 | omap2_sms_write_rot_physical_ba(paddr, ctx); | 226 | omap2_sms_write_rot_physical_ba(paddr, ctx); |
| 204 | omap2_sms_write_rot_size(size, ctx); | 227 | omap2_sms_write_rot_size(size, ctx); |
| @@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb) | |||
| 274 | 297 | ||
| 275 | mutex_lock(&ctx_lock); | 298 | mutex_lock(&ctx_lock); |
| 276 | 299 | ||
| 277 | for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) | 300 | for (ctx = 0; ctx < num_ctxs; ++ctx) |
| 278 | if ((ctx_map & (1 << ctx)) == 0) | 301 | if ((ctx_map & (1 << ctx)) == 0) |
| 279 | break; | 302 | break; |
| 280 | 303 | ||
| 281 | if (ctx == VRFB_NUM_CTXS) { | 304 | if (ctx == num_ctxs) { |
| 282 | pr_err("vrfb: no free contexts\n"); | 305 | pr_err("vrfb: no free contexts\n"); |
| 283 | r = -EBUSY; | 306 | r = -EBUSY; |
| 284 | goto out; | 307 | goto out; |
| @@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb) | |||
| 293 | vrfb->context = ctx; | 316 | vrfb->context = ctx; |
| 294 | 317 | ||
| 295 | for (rot = 0; rot < 4; ++rot) { | 318 | for (rot = 0; rot < 4; ++rot) { |
| 296 | paddr = SMS_ROT_VIRT_BASE(ctx, rot); | 319 | paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot); |
| 297 | if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { | 320 | if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { |
| 298 | pr_err("vrfb: failed to reserve VRFB " | 321 | pr_err("vrfb: failed to reserve VRFB " |
| 299 | "area for ctx %d, rotation %d\n", | 322 | "area for ctx %d, rotation %d\n", |
| @@ -314,3 +337,80 @@ out: | |||
| 314 | return r; | 337 | return r; |
| 315 | } | 338 | } |
| 316 | EXPORT_SYMBOL(omap_vrfb_request_ctx); | 339 | EXPORT_SYMBOL(omap_vrfb_request_ctx); |
| 340 | |||
| 341 | bool omap_vrfb_supported(void) | ||
| 342 | { | ||
| 343 | return vrfb_loaded; | ||
| 344 | } | ||
| 345 | EXPORT_SYMBOL(omap_vrfb_supported); | ||
| 346 | |||
| 347 | static int __init vrfb_probe(struct platform_device *pdev) | ||
| 348 | { | ||
| 349 | struct resource *mem; | ||
| 350 | int i; | ||
| 351 | |||
| 352 | /* first resource is the register res, the rest are vrfb contexts */ | ||
| 353 | |||
| 354 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 355 | if (!mem) { | ||
| 356 | dev_err(&pdev->dev, "can't get vrfb base address\n"); | ||
| 357 | return -EINVAL; | ||
| 358 | } | ||
| 359 | |||
| 360 | vrfb_base = devm_request_and_ioremap(&pdev->dev, mem); | ||
| 361 | if (!vrfb_base) { | ||
| 362 | dev_err(&pdev->dev, "can't ioremap vrfb memory\n"); | ||
| 363 | return -ENOMEM; | ||
| 364 | } | ||
| 365 | |||
| 366 | num_ctxs = pdev->num_resources - 1; | ||
| 367 | |||
| 368 | ctxs = devm_kzalloc(&pdev->dev, | ||
| 369 | sizeof(struct vrfb_ctx) * num_ctxs, | ||
| 370 | GFP_KERNEL); | ||
| 371 | |||
| 372 | if (!ctxs) | ||
| 373 | return -ENOMEM; | ||
| 374 | |||
| 375 | for (i = 0; i < num_ctxs; ++i) { | ||
| 376 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i); | ||
| 377 | if (!mem) { | ||
| 378 | dev_err(&pdev->dev, "can't get vrfb ctx %d address\n", | ||
| 379 | i); | ||
| 380 | return -EINVAL; | ||
| 381 | } | ||
| 382 | |||
| 383 | ctxs[i].base = mem->start; | ||
| 384 | } | ||
| 385 | |||
| 386 | vrfb_loaded = true; | ||
| 387 | |||
| 388 | return 0; | ||
| 389 | } | ||
| 390 | |||
| 391 | static void __exit vrfb_remove(struct platform_device *pdev) | ||
| 392 | { | ||
| 393 | vrfb_loaded = false; | ||
| 394 | } | ||
| 395 | |||
| 396 | static struct platform_driver vrfb_driver = { | ||
| 397 | .driver.name = "omapvrfb", | ||
| 398 | .remove = __exit_p(vrfb_remove), | ||
| 399 | }; | ||
| 400 | |||
| 401 | static int __init vrfb_init(void) | ||
| 402 | { | ||
| 403 | return platform_driver_probe(&vrfb_driver, &vrfb_probe); | ||
| 404 | } | ||
| 405 | |||
| 406 | static void __exit vrfb_exit(void) | ||
| 407 | { | ||
| 408 | platform_driver_unregister(&vrfb_driver); | ||
| 409 | } | ||
| 410 | |||
| 411 | module_init(vrfb_init); | ||
| 412 | module_exit(vrfb_exit); | ||
| 413 | |||
| 414 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); | ||
| 415 | MODULE_DESCRIPTION("OMAP VRFB"); | ||
| 416 | MODULE_LICENSE("GPL v2"); | ||
