diff options
author | Anatolij Gustschin <agust@denx.de> | 2011-05-13 07:31:37 -0400 |
---|---|---|
committer | Anatolij Gustschin <agust@denx.de> | 2011-05-24 10:28:52 -0400 |
commit | f64d8a5fdec35ed36f76130517a5580974a324a4 (patch) | |
tree | 97e278a48d00c6c0d7feeb038b9d89fecf480a9f /drivers/video/mb862xx/mb862xxfbdrv.c | |
parent | f8a6b1f44833a4eb4c323b8b71fc592646212090 (diff) |
video: mb862xxfb: add support for L1 displaying
Allow displaying L1 video data on top of the primary L0 layer.
The L1 layer position and dimensions can be configured and the
layer enabled/disabled by using the appropriate L1 controls
added by this patch.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Diffstat (limited to 'drivers/video/mb862xx/mb862xxfbdrv.c')
-rw-r--r-- | drivers/video/mb862xx/mb862xxfbdrv.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 0cc20b4fbcb5..ea39336addfb 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #define NR_PALETTE 256 | 28 | #define NR_PALETTE 256 |
29 | #define MB862XX_MEM_SIZE 0x1000000 | 29 | #define MB862XX_MEM_SIZE 0x1000000 |
30 | #define CORALP_MEM_SIZE 0x4000000 | 30 | #define CORALP_MEM_SIZE 0x2000000 |
31 | #define CARMINE_MEM_SIZE 0x8000000 | 31 | #define CARMINE_MEM_SIZE 0x8000000 |
32 | #define DRV_NAME "mb862xxfb" | 32 | #define DRV_NAME "mb862xxfb" |
33 | 33 | ||
@@ -309,6 +309,97 @@ static int mb862xxfb_blank(int mode, struct fb_info *fbi) | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, | ||
313 | unsigned long arg) | ||
314 | { | ||
315 | struct mb862xxfb_par *par = fbi->par; | ||
316 | struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg; | ||
317 | void __user *argp = (void __user *)arg; | ||
318 | int *enable; | ||
319 | u32 l1em = 0; | ||
320 | |||
321 | switch (cmd) { | ||
322 | case MB862XX_L1_GET_CFG: | ||
323 | if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg))) | ||
324 | return -EFAULT; | ||
325 | break; | ||
326 | case MB862XX_L1_SET_CFG: | ||
327 | if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) | ||
328 | return -EFAULT; | ||
329 | if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { | ||
330 | /* downscaling */ | ||
331 | outreg(cap, GC_CAP_CSC, | ||
332 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
333 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
334 | l1em = inreg(disp, GC_L1EM); | ||
335 | l1em &= ~GC_L1EM_DM; | ||
336 | } else if ((l1_cfg->sw <= l1_cfg->dw) && | ||
337 | (l1_cfg->sh <= l1_cfg->dh)) { | ||
338 | /* upscaling */ | ||
339 | outreg(cap, GC_CAP_CSC, | ||
340 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
341 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
342 | outreg(cap, GC_CAP_CMSS, | ||
343 | pack(l1_cfg->sw >> 1, l1_cfg->sh)); | ||
344 | outreg(cap, GC_CAP_CMDS, | ||
345 | pack(l1_cfg->dw >> 1, l1_cfg->dh)); | ||
346 | l1em = inreg(disp, GC_L1EM); | ||
347 | l1em |= GC_L1EM_DM; | ||
348 | } | ||
349 | |||
350 | if (l1_cfg->mirror) { | ||
351 | outreg(cap, GC_CAP_CBM, | ||
352 | inreg(cap, GC_CAP_CBM) | GC_CBM_HRV); | ||
353 | l1em |= l1_cfg->dw * 2 - 8; | ||
354 | } else { | ||
355 | outreg(cap, GC_CAP_CBM, | ||
356 | inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV); | ||
357 | l1em &= 0xffff0000; | ||
358 | } | ||
359 | outreg(disp, GC_L1EM, l1em); | ||
360 | break; | ||
361 | case MB862XX_L1_ENABLE: | ||
362 | enable = (int *)arg; | ||
363 | if (*enable) { | ||
364 | outreg(disp, GC_L1DA, par->cap_buf); | ||
365 | outreg(cap, GC_CAP_IMG_START, | ||
366 | pack(l1_cfg->sy >> 1, l1_cfg->sx)); | ||
367 | outreg(cap, GC_CAP_IMG_END, | ||
368 | pack(l1_cfg->sh, l1_cfg->sw)); | ||
369 | outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS | | ||
370 | (par->l1_stride << 16)); | ||
371 | outreg(disp, GC_L1WY_L1WX, | ||
372 | pack(l1_cfg->dy, l1_cfg->dx)); | ||
373 | outreg(disp, GC_L1WH_L1WW, | ||
374 | pack(l1_cfg->dh - 1, l1_cfg->dw)); | ||
375 | outreg(disp, GC_DLS, 1); | ||
376 | outreg(cap, GC_CAP_VCM, | ||
377 | GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL); | ||
378 | outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) | | ||
379 | GC_DCM1_DEN | GC_DCM1_L1E); | ||
380 | } else { | ||
381 | outreg(cap, GC_CAP_VCM, | ||
382 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
383 | outreg(disp, GC_DCM1, | ||
384 | inreg(disp, GC_DCM1) & ~GC_DCM1_L1E); | ||
385 | } | ||
386 | break; | ||
387 | case MB862XX_L1_CAP_CTL: | ||
388 | enable = (int *)arg; | ||
389 | if (*enable) { | ||
390 | outreg(cap, GC_CAP_VCM, | ||
391 | inreg(cap, GC_CAP_VCM) | GC_VCM_VIE); | ||
392 | } else { | ||
393 | outreg(cap, GC_CAP_VCM, | ||
394 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
395 | } | ||
396 | break; | ||
397 | default: | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | return 0; | ||
401 | } | ||
402 | |||
312 | /* framebuffer ops */ | 403 | /* framebuffer ops */ |
313 | static struct fb_ops mb862xxfb_ops = { | 404 | static struct fb_ops mb862xxfb_ops = { |
314 | .owner = THIS_MODULE, | 405 | .owner = THIS_MODULE, |
@@ -320,6 +411,7 @@ static struct fb_ops mb862xxfb_ops = { | |||
320 | .fb_fillrect = cfb_fillrect, | 411 | .fb_fillrect = cfb_fillrect, |
321 | .fb_copyarea = cfb_copyarea, | 412 | .fb_copyarea = cfb_copyarea, |
322 | .fb_imageblit = cfb_imageblit, | 413 | .fb_imageblit = cfb_imageblit, |
414 | .fb_ioctl = mb862xxfb_ioctl, | ||
323 | }; | 415 | }; |
324 | 416 | ||
325 | /* initialize fb_info data */ | 417 | /* initialize fb_info data */ |
@@ -328,6 +420,7 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
328 | struct mb862xxfb_par *par = fbi->par; | 420 | struct mb862xxfb_par *par = fbi->par; |
329 | struct mb862xx_gc_mode *mode = par->gc_mode; | 421 | struct mb862xx_gc_mode *mode = par->gc_mode; |
330 | unsigned long reg; | 422 | unsigned long reg; |
423 | int stride; | ||
331 | 424 | ||
332 | fbi->fbops = &mb862xxfb_ops; | 425 | fbi->fbops = &mb862xxfb_ops; |
333 | fbi->pseudo_palette = par->pseudo_palette; | 426 | fbi->pseudo_palette = par->pseudo_palette; |
@@ -420,6 +513,27 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
420 | fbi->fix.line_length = (fbi->var.xres_virtual * | 513 | fbi->fix.line_length = (fbi->var.xres_virtual * |
421 | fbi->var.bits_per_pixel) / 8; | 514 | fbi->var.bits_per_pixel) / 8; |
422 | fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual; | 515 | fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual; |
516 | |||
517 | /* | ||
518 | * reserve space for capture buffers and two cursors | ||
519 | * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16. | ||
520 | */ | ||
521 | par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000; | ||
522 | par->cap_len = 0x1bd800; | ||
523 | par->l1_cfg.sx = 0; | ||
524 | par->l1_cfg.sy = 0; | ||
525 | par->l1_cfg.sw = 720; | ||
526 | par->l1_cfg.sh = 576; | ||
527 | par->l1_cfg.dx = 0; | ||
528 | par->l1_cfg.dy = 0; | ||
529 | par->l1_cfg.dw = 720; | ||
530 | par->l1_cfg.dh = 576; | ||
531 | stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8); | ||
532 | par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0); | ||
533 | outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST | | ||
534 | (par->l1_stride << 16)); | ||
535 | outreg(cap, GC_CAP_CBOA, par->cap_buf); | ||
536 | outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len); | ||
423 | return 0; | 537 | return 0; |
424 | } | 538 | } |
425 | 539 | ||