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 | |
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>
-rw-r--r-- | drivers/video/mb862xx/mb862xx_reg.h | 31 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfb.h | 27 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfbdrv.c | 116 |
3 files changed, 173 insertions, 1 deletions
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h index 5784b018f15d..9df48b8edc94 100644 --- a/drivers/video/mb862xx/mb862xx_reg.h +++ b/drivers/video/mb862xx/mb862xx_reg.h | |||
@@ -51,10 +51,16 @@ | |||
51 | #define GC_L0OA0 0x00000024 | 51 | #define GC_L0OA0 0x00000024 |
52 | #define GC_L0DA0 0x00000028 | 52 | #define GC_L0DA0 0x00000028 |
53 | #define GC_L0DY_L0DX 0x0000002c | 53 | #define GC_L0DY_L0DX 0x0000002c |
54 | #define GC_L1M 0x00000030 | ||
55 | #define GC_L1DA 0x00000034 | ||
54 | #define GC_DCM1 0x00000100 | 56 | #define GC_DCM1 0x00000100 |
55 | #define GC_L0EM 0x00000110 | 57 | #define GC_L0EM 0x00000110 |
56 | #define GC_L0WY_L0WX 0x00000114 | 58 | #define GC_L0WY_L0WX 0x00000114 |
57 | #define GC_L0WH_L0WW 0x00000118 | 59 | #define GC_L0WH_L0WW 0x00000118 |
60 | #define GC_L1EM 0x00000120 | ||
61 | #define GC_L1WY_L1WX 0x00000124 | ||
62 | #define GC_L1WH_L1WW 0x00000128 | ||
63 | #define GC_DLS 0x00000180 | ||
58 | #define GC_DCM2 0x00000104 | 64 | #define GC_DCM2 0x00000104 |
59 | #define GC_DCM3 0x00000108 | 65 | #define GC_DCM3 0x00000108 |
60 | #define GC_CPM_CUTC 0x000000a0 | 66 | #define GC_CPM_CUTC 0x000000a0 |
@@ -66,6 +72,11 @@ | |||
66 | 72 | ||
67 | #define GC_CPM_CEN0 0x00100000 | 73 | #define GC_CPM_CEN0 0x00100000 |
68 | #define GC_CPM_CEN1 0x00200000 | 74 | #define GC_CPM_CEN1 0x00200000 |
75 | #define GC_DCM1_DEN 0x80000000 | ||
76 | #define GC_DCM1_L1E 0x00020000 | ||
77 | #define GC_L1M_16 0x80000000 | ||
78 | #define GC_L1M_YC 0x40000000 | ||
79 | #define GC_L1M_CS 0x20000000 | ||
69 | 80 | ||
70 | #define GC_DCM01_ESY 0x00000004 | 81 | #define GC_DCM01_ESY 0x00000004 |
71 | #define GC_DCM01_SC 0x00003f00 | 82 | #define GC_DCM01_SC 0x00003f00 |
@@ -77,6 +88,7 @@ | |||
77 | #define GC_L0M_L0C_16 0x80000000 | 88 | #define GC_L0M_L0C_16 0x80000000 |
78 | #define GC_L0EM_L0EC_24 0x40000000 | 89 | #define GC_L0EM_L0EC_24 0x40000000 |
79 | #define GC_L0M_L0W_UNIT 64 | 90 | #define GC_L0M_L0W_UNIT 64 |
91 | #define GC_L1EM_DM 0x02000000 | ||
80 | 92 | ||
81 | #define GC_DISP_REFCLK_400 400 | 93 | #define GC_DISP_REFCLK_400 400 |
82 | 94 | ||
@@ -101,6 +113,25 @@ | |||
101 | #define I2C_TRX 0x80 | 113 | #define I2C_TRX 0x80 |
102 | #define I2C_LRB 0x10 | 114 | #define I2C_LRB 0x10 |
103 | 115 | ||
116 | /* Capture registers and bits */ | ||
117 | #define GC_CAP_VCM 0x00000000 | ||
118 | #define GC_CAP_CSC 0x00000004 | ||
119 | #define GC_CAP_VCS 0x00000008 | ||
120 | #define GC_CAP_CBM 0x00000010 | ||
121 | #define GC_CAP_CBOA 0x00000014 | ||
122 | #define GC_CAP_CBLA 0x00000018 | ||
123 | #define GC_CAP_IMG_START 0x0000001C | ||
124 | #define GC_CAP_IMG_END 0x00000020 | ||
125 | #define GC_CAP_CMSS 0x00000048 | ||
126 | #define GC_CAP_CMDS 0x0000004C | ||
127 | |||
128 | #define GC_VCM_VIE 0x80000000 | ||
129 | #define GC_VCM_CM 0x03000000 | ||
130 | #define GC_VCM_VS_PAL 0x00000002 | ||
131 | #define GC_CBM_OO 0x80000000 | ||
132 | #define GC_CBM_HRV 0x00000010 | ||
133 | #define GC_CBM_CBST 0x00000001 | ||
134 | |||
104 | /* Carmine specific */ | 135 | /* Carmine specific */ |
105 | #define MB86297_DRAW_BASE 0x00020000 | 136 | #define MB86297_DRAW_BASE 0x00020000 |
106 | #define MB86297_DISP0_BASE 0x00100000 | 137 | #define MB86297_DISP0_BASE 0x00100000 |
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h index d5dd7d9ec0cd..8550630c1e01 100644 --- a/drivers/video/mb862xx/mb862xxfb.h +++ b/drivers/video/mb862xx/mb862xxfb.h | |||
@@ -1,6 +1,26 @@ | |||
1 | #ifndef __MB862XX_H__ | 1 | #ifndef __MB862XX_H__ |
2 | #define __MB862XX_H__ | 2 | #define __MB862XX_H__ |
3 | 3 | ||
4 | struct mb862xx_l1_cfg { | ||
5 | unsigned short sx; | ||
6 | unsigned short sy; | ||
7 | unsigned short sw; | ||
8 | unsigned short sh; | ||
9 | unsigned short dx; | ||
10 | unsigned short dy; | ||
11 | unsigned short dw; | ||
12 | unsigned short dh; | ||
13 | int mirror; | ||
14 | }; | ||
15 | |||
16 | #define MB862XX_BASE 'M' | ||
17 | #define MB862XX_L1_GET_CFG _IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*) | ||
18 | #define MB862XX_L1_SET_CFG _IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*) | ||
19 | #define MB862XX_L1_ENABLE _IOW(MB862XX_BASE, 2, int) | ||
20 | #define MB862XX_L1_CAP_CTL _IOW(MB862XX_BASE, 3, int) | ||
21 | |||
22 | #ifdef __KERNEL__ | ||
23 | |||
4 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf | 24 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf |
5 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 | 25 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 |
6 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e | 26 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e |
@@ -38,6 +58,8 @@ struct mb862xxfb_par { | |||
38 | void __iomem *mmio_base; /* remapped registers */ | 58 | void __iomem *mmio_base; /* remapped registers */ |
39 | size_t mapped_vram; /* length of remapped vram */ | 59 | size_t mapped_vram; /* length of remapped vram */ |
40 | size_t mmio_len; /* length of register region */ | 60 | size_t mmio_len; /* length of register region */ |
61 | unsigned long cap_buf; /* capture buffers offset */ | ||
62 | size_t cap_len; /* length of capture buffers */ | ||
41 | 63 | ||
42 | void __iomem *host; /* relocatable reg. bases */ | 64 | void __iomem *host; /* relocatable reg. bases */ |
43 | void __iomem *i2c; | 65 | void __iomem *i2c; |
@@ -60,6 +82,9 @@ struct mb862xxfb_par { | |||
60 | struct i2c_adapter *adap; /* GDC I2C bus adapter */ | 82 | struct i2c_adapter *adap; /* GDC I2C bus adapter */ |
61 | int i2c_rs; | 83 | int i2c_rs; |
62 | 84 | ||
85 | struct mb862xx_l1_cfg l1_cfg; | ||
86 | int l1_stride; | ||
87 | |||
63 | u32 pseudo_palette[16]; | 88 | u32 pseudo_palette[16]; |
64 | }; | 89 | }; |
65 | 90 | ||
@@ -91,4 +116,6 @@ static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { } | |||
91 | 116 | ||
92 | #define pack(a, b) (((a) << 16) | (b)) | 117 | #define pack(a, b) (((a) << 16) | (b)) |
93 | 118 | ||
119 | #endif /* __KERNEL__ */ | ||
120 | |||
94 | #endif | 121 | #endif |
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 | ||