2 On Screen Display cx23415 Framebuffer driver
4 This module presents the cx23415 OSD (onscreen display) framebuffer memory
5 as a standard Linux /dev/fb style framebuffer device. The framebuffer has
6 support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
7 mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
8 local alpha. The colorspace is selectable between rgb & yuv.
9 Depending on the TV standard configured in the ivtv module at load time,
10 the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
11 Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
14 Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
16 Derived from drivers/video/vesafb.c
17 Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
20 Copyright (C) 2004 Matthias Badaire
22 Copyright (C) 2004 Chris Kennedy <c@groovy.org>
24 Copyright (C) 2006 Ian Armstrong <ian@iarmst.demon.co.uk>
26 This program is free software; you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation; either version 2 of the License, or
29 (at your option) any later version.
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
36 You should have received a copy of the GNU General Public License
37 along with this program; if not, write to the Free Software
38 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #include <linux/module.h>
42 #include <linux/kernel.h>
44 #include <linux/ivtvfb.h>
50 #include "ivtv-driver.h"
51 #include "ivtv-cards.h"
53 #include "ivtv-udma.h"
54 #include "ivtv-mailbox.h"
57 static int ivtvfb_card_id
= -1;
58 static int ivtvfb_debug
= 0;
66 module_param(ivtvfb_card_id
, int, 0444);
67 module_param_named(debug
,ivtvfb_debug
, int, 0644);
68 module_param(osd_laced
, bool, 0444);
69 module_param(osd_depth
, int, 0444);
70 module_param(osd_upper
, int, 0444);
71 module_param(osd_left
, int, 0444);
72 module_param(osd_yres
, int, 0444);
73 module_param(osd_xres
, int, 0444);
75 MODULE_PARM_DESC(ivtvfb_card_id
,
76 "Only use framebuffer of the specified ivtv card (0-31)\n"
77 "\t\t\tdefault -1: initialize all available framebuffers");
79 MODULE_PARM_DESC(debug
,
80 "Debug level (bitmask). Default: errors only\n"
81 "\t\t\t(debug = 3 gives full debugging)");
83 /* Why upper, left, xres, yres, depth, laced ? To match terminology used
85 Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
87 MODULE_PARM_DESC(osd_laced
,
93 MODULE_PARM_DESC(osd_depth
,
94 "Bits per pixel - 8, 16, 32\n"
97 MODULE_PARM_DESC(osd_upper
,
98 "Vertical start position\n"
99 "\t\t\tdefault 0 (Centered)");
101 MODULE_PARM_DESC(osd_left
,
102 "Horizontal start position\n"
103 "\t\t\tdefault 0 (Centered)");
105 MODULE_PARM_DESC(osd_yres
,
107 "\t\t\tdefault 480 (PAL)\n"
108 "\t\t\t 400 (NTSC)");
110 MODULE_PARM_DESC(osd_xres
,
112 "\t\t\tdefault 640");
114 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
115 MODULE_LICENSE("GPL");
117 /* --------------------------------------------------------------------- */
119 #define IVTVFB_DBGFLG_WARN (1 << 0)
120 #define IVTVFB_DBGFLG_INFO (1 << 1)
122 #define IVTVFB_DEBUG(x, type, fmt, args...) \
124 if ((x) & ivtvfb_debug) \
125 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
127 #define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
128 #define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
130 /* Standard kernel messages */
131 #define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args)
132 #define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args)
133 #define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
135 /* --------------------------------------------------------------------- */
137 #define IVTV_OSD_MAX_WIDTH 720
138 #define IVTV_OSD_MAX_HEIGHT 576
140 #define IVTV_OSD_BPP_8 0x00
141 #define IVTV_OSD_BPP_16_444 0x03
142 #define IVTV_OSD_BPP_16_555 0x02
143 #define IVTV_OSD_BPP_16_565 0x01
144 #define IVTV_OSD_BPP_32 0x04
147 /* Physical base address */
148 unsigned long video_pbase
;
149 /* Relative base address (relative to start of decoder memory) */
151 /* Mapped base address */
152 volatile char __iomem
*video_vbase
;
154 u32 video_buffer_size
;
157 /* video_base rounded down as required by hardware MTRRs */
158 unsigned long fb_start_aligned_physaddr
;
159 /* video_base rounded up as required by hardware MTRRs */
160 unsigned long fb_end_aligned_physaddr
;
163 /* Store the buffer offset */
164 int set_osd_coords_x
;
165 int set_osd_coords_y
;
167 /* Current dimensions (NOT VISIBLE SIZE!) */
170 int display_byte_stride
;
172 /* Current bits per pixel */
176 /* Frame buffer stuff */
177 struct fb_info ivtvfb_info
;
178 struct fb_var_screeninfo ivtvfb_defined
;
179 struct fb_fix_screeninfo ivtvfb_fix
;
182 struct ivtv_osd_coords
{
183 unsigned long offset
;
184 unsigned long max_offset
;
191 /* --------------------------------------------------------------------- */
193 /* ivtv API calls for framebuffer related support */
195 static int ivtvfb_get_framebuffer(struct ivtv
*itv
, u32
*fbbase
,
198 u32 data
[CX2341X_MBOX_MAX_DATA
];
201 rc
= ivtv_vapi_result(itv
, data
, CX2341X_OSD_GET_FRAMEBUFFER
, 0);
207 static int ivtvfb_get_osd_coords(struct ivtv
*itv
,
208 struct ivtv_osd_coords
*osd
)
210 struct osd_info
*oi
= itv
->osd_info
;
211 u32 data
[CX2341X_MBOX_MAX_DATA
];
213 ivtv_vapi_result(itv
, data
, CX2341X_OSD_GET_OSD_COORDS
, 0);
215 osd
->offset
= data
[0] - oi
->video_rbase
;
216 osd
->max_offset
= oi
->display_width
* oi
->display_height
* 4;
217 osd
->pixel_stride
= data
[1];
218 osd
->lines
= data
[2];
224 static int ivtvfb_set_osd_coords(struct ivtv
*itv
, const struct ivtv_osd_coords
*osd
)
226 struct osd_info
*oi
= itv
->osd_info
;
228 oi
->display_width
= osd
->pixel_stride
;
229 oi
->display_byte_stride
= osd
->pixel_stride
* oi
->bytes_per_pixel
;
230 oi
->set_osd_coords_x
+= osd
->x
;
231 oi
->set_osd_coords_y
= osd
->y
;
233 return ivtv_vapi(itv
, CX2341X_OSD_SET_OSD_COORDS
, 5,
234 osd
->offset
+ oi
->video_rbase
,
236 osd
->lines
, osd
->x
, osd
->y
);
239 static int ivtvfb_set_display_window(struct ivtv
*itv
, struct v4l2_rect
*ivtv_window
)
241 int osd_height_limit
= itv
->is_50hz
? 576 : 480;
243 /* Only fail if resolution too high, otherwise fudge the start coords. */
244 if ((ivtv_window
->height
> osd_height_limit
) || (ivtv_window
->width
> IVTV_OSD_MAX_WIDTH
))
247 /* Ensure we don't exceed display limits */
248 if (ivtv_window
->top
+ ivtv_window
->height
> osd_height_limit
) {
249 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
250 ivtv_window
->top
, ivtv_window
->height
);
251 ivtv_window
->top
= osd_height_limit
- ivtv_window
->height
;
254 if (ivtv_window
->left
+ ivtv_window
->width
> IVTV_OSD_MAX_WIDTH
) {
255 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
256 ivtv_window
->left
, ivtv_window
->width
);
257 ivtv_window
->left
= IVTV_OSD_MAX_WIDTH
- ivtv_window
->width
;
260 /* Set the OSD origin */
261 write_reg((ivtv_window
->top
<< 16) | ivtv_window
->left
, 0x02a04);
263 /* How much to display */
264 write_reg(((ivtv_window
->top
+ivtv_window
->height
) << 16) | (ivtv_window
->left
+ivtv_window
->width
), 0x02a08);
266 /* Pass this info back the yuv handler */
267 itv
->yuv_info
.osd_vis_w
= ivtv_window
->width
;
268 itv
->yuv_info
.osd_vis_h
= ivtv_window
->height
;
269 itv
->yuv_info
.osd_x_offset
= ivtv_window
->left
;
270 itv
->yuv_info
.osd_y_offset
= ivtv_window
->top
;
275 static int ivtvfb_prep_dec_dma_to_device(struct ivtv
*itv
,
276 unsigned long ivtv_dest_addr
, void __user
*userbuf
,
282 mutex_lock(&itv
->udma
.lock
);
284 if (ivtv_udma_setup(itv
, ivtv_dest_addr
, userbuf
, size_in_bytes
) <= 0) {
285 mutex_unlock(&itv
->udma
.lock
);
286 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
287 "Error with get_user_pages: %d bytes, %d pages returned\n",
288 size_in_bytes
, itv
->udma
.page_count
);
290 /* get_user_pages must have failed completely */
294 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
295 size_in_bytes
, itv
->udma
.page_count
);
297 ivtv_udma_prepare(itv
);
298 prepare_to_wait(&itv
->dma_waitq
, &wait
, TASK_INTERRUPTIBLE
);
299 /* if no UDMA is pending and no UDMA is in progress, then the DMA
301 while (test_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
) ||
302 test_bit(IVTV_F_I_UDMA
, &itv
->i_flags
)) {
303 /* don't interrupt if the DMA is in progress but break off
304 a still pending DMA. */
305 got_sig
= signal_pending(current
);
306 if (got_sig
&& test_and_clear_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
))
311 finish_wait(&itv
->dma_waitq
, &wait
);
313 /* Unmap Last DMA Xfer */
314 ivtv_udma_unmap(itv
);
315 mutex_unlock(&itv
->udma
.lock
);
317 IVTV_DEBUG_INFO("User stopped OSD\n");
324 static int ivtvfb_prep_frame(struct ivtv
*itv
, int cmd
, void __user
*source
,
325 unsigned long dest_offset
, int count
)
328 struct osd_info
*oi
= itv
->osd_info
;
332 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
336 /* Check Total FB Size */
337 if ((dest_offset
+ count
) > oi
->video_buffer_size
) {
338 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
339 dest_offset
+ count
, oi
->video_buffer_size
);
343 /* Not fatal, but will have undesirable results */
344 if ((unsigned long)source
& 3)
345 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
346 (unsigned long)source
);
349 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset
);
352 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count
);
355 if (!access_ok(VERIFY_READ
, source
+ dest_offset
, count
)) {
356 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
357 (unsigned long)source
);
359 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
360 dest_offset
, (unsigned long)source
,
365 /* OSD Address to send DMA to */
366 dest_offset
+= IVTV_DECODER_OFFSET
+ oi
->video_rbase
;
369 return ivtvfb_prep_dec_dma_to_device(itv
, dest_offset
, source
, count
);
372 static ssize_t
ivtvfb_write(struct fb_info
*info
, const char __user
*buf
,
373 size_t count
, loff_t
*ppos
)
375 unsigned long p
= *ppos
;
379 unsigned long total_size
;
380 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
381 unsigned long dma_offset
=
382 IVTV_DECODER_OFFSET
+ itv
->osd_info
->video_rbase
;
383 unsigned long dma_size
;
384 u16 lead
= 0, tail
= 0;
386 if (info
->state
!= FBINFO_STATE_RUNNING
)
389 total_size
= info
->screen_size
;
392 total_size
= info
->fix
.smem_len
;
397 if (count
> total_size
) {
402 if (count
+ p
> total_size
) {
405 count
= total_size
- p
;
408 dst
= (void __force
*) (info
->screen_base
+ p
);
410 if (info
->fbops
->fb_sync
)
411 info
->fbops
->fb_sync(info
);
413 /* If transfer size > threshold and both src/dst
414 addresses are aligned, use DMA */
416 ((unsigned long)buf
& 3) == ((unsigned long)dst
& 3)) {
417 /* Odd address = can't DMA. Align */
418 if ((unsigned long)dst
& 3) {
419 lead
= 4 - ((unsigned long)dst
& 3);
420 if (copy_from_user(dst
, buf
, lead
))
425 /* DMA resolution is 32 bits */
426 if ((count
- lead
) & 3)
427 tail
= (count
- lead
) & 3;
429 dma_size
= count
- lead
- tail
;
430 dma_err
= ivtvfb_prep_dec_dma_to_device(itv
,
431 p
+ lead
+ dma_offset
, (void __user
*)buf
, dma_size
);
436 /* Copy any leftover data */
437 if (tail
&& copy_from_user(dst
, buf
, tail
))
439 } else if (copy_from_user(dst
, buf
, count
)) {
446 return (err
) ? err
: count
;
449 static int ivtvfb_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
452 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
456 case FBIOGET_VBLANK
: {
457 struct fb_vblank vblank
;
460 vblank
.flags
= FB_VBLANK_HAVE_COUNT
|FB_VBLANK_HAVE_VCOUNT
|
461 FB_VBLANK_HAVE_VSYNC
;
462 trace
= read_reg(0x028c0) >> 16;
463 if (itv
->is_50hz
&& trace
> 312)
465 else if (itv
->is_60hz
&& trace
> 262)
468 vblank
.flags
|= FB_VBLANK_VSYNCING
;
469 vblank
.count
= itv
->last_vsync_field
;
470 vblank
.vcount
= trace
;
472 if (copy_to_user((void __user
*)arg
, &vblank
, sizeof(vblank
)))
477 case FBIO_WAITFORVSYNC
:
478 prepare_to_wait(&itv
->vsync_waitq
, &wait
, TASK_INTERRUPTIBLE
);
479 if (!schedule_timeout(msecs_to_jiffies(50)))
481 finish_wait(&itv
->vsync_waitq
, &wait
);
484 case IVTVFB_IOC_DMA_FRAME
: {
485 struct ivtvfb_dma_frame args
;
487 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
488 if (copy_from_user(&args
, (void __user
*)arg
, sizeof(args
)))
491 return ivtvfb_prep_frame(itv
, cmd
, args
.source
, args
.dest_offset
, args
.count
);
495 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd
);
501 /* Framebuffer device handling */
503 static int ivtvfb_set_var(struct ivtv
*itv
, struct fb_var_screeninfo
*var
)
505 struct osd_info
*oi
= itv
->osd_info
;
506 struct ivtv_osd_coords ivtv_osd
;
507 struct v4l2_rect ivtv_window
;
510 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
512 /* Select color space */
513 if (var
->nonstd
) /* YUV */
514 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
516 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
518 /* Set the color mode */
519 switch (var
->bits_per_pixel
) {
521 osd_mode
= IVTV_OSD_BPP_8
;
524 osd_mode
= IVTV_OSD_BPP_32
;
527 switch (var
->green
.length
) {
529 osd_mode
= IVTV_OSD_BPP_16_444
;
532 osd_mode
= IVTV_OSD_BPP_16_555
;
535 osd_mode
= IVTV_OSD_BPP_16_565
;
538 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
542 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
545 /* Set video mode. Although rare, the display can become scrambled even
546 if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
547 if (osd_mode
!= -1) {
548 ivtv_vapi(itv
, CX2341X_OSD_SET_PIXEL_FORMAT
, 1, 0);
549 ivtv_vapi(itv
, CX2341X_OSD_SET_PIXEL_FORMAT
, 1, osd_mode
);
552 oi
->bits_per_pixel
= var
->bits_per_pixel
;
553 oi
->bytes_per_pixel
= var
->bits_per_pixel
/ 8;
555 /* Set the flicker filter */
556 switch (var
->vmode
& FB_VMODE_MASK
) {
557 case FB_VMODE_NONINTERLACED
: /* Filter on */
558 ivtv_vapi(itv
, CX2341X_OSD_SET_FLICKER_STATE
, 1, 1);
560 case FB_VMODE_INTERLACED
: /* Filter off */
561 ivtv_vapi(itv
, CX2341X_OSD_SET_FLICKER_STATE
, 1, 0);
564 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
567 /* Read the current osd info */
568 ivtvfb_get_osd_coords(itv
, &ivtv_osd
);
570 /* Now set the OSD to the size we want */
571 ivtv_osd
.pixel_stride
= var
->xres_virtual
;
572 ivtv_osd
.lines
= var
->yres_virtual
;
575 ivtvfb_set_osd_coords(itv
, &ivtv_osd
);
577 /* Can't seem to find the right API combo for this.
578 Use another function which does what we need through direct register access. */
579 ivtv_window
.width
= var
->xres
;
580 ivtv_window
.height
= var
->yres
;
582 /* Minimum margin cannot be 0, as X won't allow such a mode */
583 if (!var
->upper_margin
) var
->upper_margin
++;
584 if (!var
->left_margin
) var
->left_margin
++;
585 ivtv_window
.top
= var
->upper_margin
- 1;
586 ivtv_window
.left
= var
->left_margin
- 1;
588 ivtvfb_set_display_window(itv
, &ivtv_window
);
590 /* Pass screen size back to yuv handler */
591 itv
->yuv_info
.osd_full_w
= ivtv_osd
.pixel_stride
;
592 itv
->yuv_info
.osd_full_h
= ivtv_osd
.lines
;
594 /* Force update of yuv registers */
595 itv
->yuv_info
.yuv_forced_update
= 1;
597 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
598 var
->xres
, var
->yres
,
599 var
->xres_virtual
, var
->yres_virtual
,
600 var
->bits_per_pixel
);
602 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
603 var
->left_margin
, var
->upper_margin
);
605 IVTVFB_DEBUG_INFO("Display filter: %s\n",
606 (var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
? "on" : "off");
607 IVTVFB_DEBUG_INFO("Color space: %s\n", var
->nonstd
? "YUV" : "RGB");
612 static int ivtvfb_get_fix(struct ivtv
*itv
, struct fb_fix_screeninfo
*fix
)
614 struct osd_info
*oi
= itv
->osd_info
;
616 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
617 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
618 strlcpy(fix
->id
, "cx23415 TV out", sizeof(fix
->id
));
619 fix
->smem_start
= oi
->video_pbase
;
620 fix
->smem_len
= oi
->video_buffer_size
;
621 fix
->type
= FB_TYPE_PACKED_PIXELS
;
622 fix
->visual
= (oi
->bits_per_pixel
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
626 fix
->line_length
= oi
->display_byte_stride
;
627 fix
->accel
= FB_ACCEL_NONE
;
631 /* Check the requested display mode, returning -EINVAL if we can't
634 static int _ivtvfb_check_var(struct fb_var_screeninfo
*var
, struct ivtv
*itv
)
636 struct osd_info
*oi
= itv
->osd_info
;
637 int osd_height_limit
;
638 u32 pixclock
, hlimit
, vlimit
;
640 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
642 /* Set base references for mode calcs. */
647 osd_height_limit
= 576;
653 osd_height_limit
= 480;
656 if (var
->bits_per_pixel
== 8 || var
->bits_per_pixel
== 32) {
657 var
->transp
.offset
= 24;
658 var
->transp
.length
= 8;
659 var
->red
.offset
= 16;
661 var
->green
.offset
= 8;
662 var
->green
.length
= 8;
663 var
->blue
.offset
= 0;
664 var
->blue
.length
= 8;
666 else if (var
->bits_per_pixel
== 16) {
667 /* To find out the true mode, check green length */
668 switch (var
->green
.length
) {
672 var
->green
.offset
= 4;
673 var
->green
.length
= 4;
674 var
->blue
.offset
= 0;
675 var
->blue
.length
= 4;
676 var
->transp
.offset
= 12;
677 var
->transp
.length
= 1;
680 var
->red
.offset
= 10;
682 var
->green
.offset
= 5;
683 var
->green
.length
= 5;
684 var
->blue
.offset
= 0;
685 var
->blue
.length
= 5;
686 var
->transp
.offset
= 15;
687 var
->transp
.length
= 1;
690 var
->red
.offset
= 11;
692 var
->green
.offset
= 5;
693 var
->green
.length
= 6;
694 var
->blue
.offset
= 0;
695 var
->blue
.length
= 5;
696 var
->transp
.offset
= 0;
697 var
->transp
.length
= 0;
702 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var
->bits_per_pixel
);
706 /* Check the resolution */
707 if (var
->xres
> IVTV_OSD_MAX_WIDTH
|| var
->yres
> osd_height_limit
) {
708 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
709 var
->xres
, var
->yres
);
713 /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
714 if (var
->xres_virtual
> 4095 / (var
->bits_per_pixel
/ 8) ||
715 var
->xres_virtual
* var
->yres_virtual
* (var
->bits_per_pixel
/ 8) > oi
->video_buffer_size
||
716 var
->xres_virtual
< var
->xres
||
717 var
->yres_virtual
< var
->yres
) {
718 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
719 var
->xres_virtual
, var
->yres_virtual
);
723 /* Some extra checks if in 8 bit mode */
724 if (var
->bits_per_pixel
== 8) {
725 /* Width must be a multiple of 4 */
727 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var
->xres
);
730 if (var
->xres_virtual
& 3) {
731 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var
->xres_virtual
);
735 else if (var
->bits_per_pixel
== 16) {
736 /* Width must be a multiple of 2 */
738 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var
->xres
);
741 if (var
->xres_virtual
& 1) {
742 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var
->xres_virtual
);
747 /* Now check the offsets */
748 if (var
->xoffset
>= var
->xres_virtual
|| var
->yoffset
>= var
->yres_virtual
) {
749 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
750 var
->xoffset
, var
->xres_virtual
, var
->yoffset
, var
->yres_virtual
);
754 /* Check pixel format */
755 if (var
->nonstd
> 1) {
756 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var
->nonstd
);
760 /* Check video mode */
761 if (((var
->vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
) &&
762 ((var
->vmode
& FB_VMODE_MASK
) != FB_VMODE_INTERLACED
)) {
763 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var
->vmode
& FB_VMODE_MASK
);
767 /* Check the left & upper margins
768 If the margins are too large, just center the screen
769 (enforcing margins causes too many problems) */
771 if (var
->left_margin
+ var
->xres
> IVTV_OSD_MAX_WIDTH
+ 1) {
772 var
->left_margin
= 1 + ((IVTV_OSD_MAX_WIDTH
- var
->xres
) / 2);
774 if (var
->upper_margin
+ var
->yres
> (itv
->is_50hz
? 577 : 481)) {
775 var
->upper_margin
= 1 + (((itv
->is_50hz
? 576 : 480) - var
->yres
) / 2);
778 /* Maintain overall 'size' for a constant refresh rate */
779 var
->right_margin
= hlimit
- var
->left_margin
- var
->xres
;
780 var
->lower_margin
= vlimit
- var
->upper_margin
- var
->yres
;
782 /* Fixed sync times */
786 /* Non-interlaced / interlaced mode is used to switch the OSD filter
787 on or off. Adjust the clock timings to maintain a constant
788 vertical refresh rate. */
789 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
790 var
->pixclock
= pixclock
/ 2;
792 var
->pixclock
= pixclock
;
794 itv
->osd_rect
.width
= var
->xres
;
795 itv
->osd_rect
.height
= var
->yres
;
797 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
798 var
->xres
, var
->yres
,
799 var
->xres_virtual
, var
->yres_virtual
,
800 var
->bits_per_pixel
);
802 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
803 var
->left_margin
, var
->upper_margin
);
805 IVTVFB_DEBUG_INFO("Display filter: %s\n",
806 (var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
? "on" : "off");
807 IVTVFB_DEBUG_INFO("Color space: %s\n", var
->nonstd
? "YUV" : "RGB");
811 static int ivtvfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
813 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
814 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
815 return _ivtvfb_check_var(var
, itv
);
818 static int ivtvfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
821 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
823 osd_pan_index
= (var
->xoffset
+ (var
->yoffset
* var
->xres_virtual
))*var
->bits_per_pixel
/8;
824 write_reg(osd_pan_index
, 0x02A0C);
826 /* Pass this info back the yuv handler */
827 itv
->yuv_info
.osd_x_pan
= var
->xoffset
;
828 itv
->yuv_info
.osd_y_pan
= var
->yoffset
;
829 /* Force update of yuv registers */
830 itv
->yuv_info
.yuv_forced_update
= 1;
834 static int ivtvfb_set_par(struct fb_info
*info
)
837 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
839 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
841 rc
= ivtvfb_set_var(itv
, &info
->var
);
842 ivtvfb_pan_display(&info
->var
, info
);
843 ivtvfb_get_fix(itv
, &info
->fix
);
847 static int ivtvfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
848 unsigned blue
, unsigned transp
,
849 struct fb_info
*info
)
852 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
854 if (regno
>= info
->cmap
.len
)
857 color
= ((transp
& 0xFF00) << 16) |((red
& 0xFF00) << 8) | (green
& 0xFF00) | ((blue
& 0xFF00) >> 8);
858 if (info
->var
.bits_per_pixel
<= 8) {
859 write_reg(regno
, 0x02a30);
860 write_reg(color
, 0x02a34);
866 palette
= info
->pseudo_palette
;
867 if (info
->var
.bits_per_pixel
== 16) {
868 switch (info
->var
.green
.length
) {
870 color
= ((red
& 0xf000) >> 4) |
871 ((green
& 0xf000) >> 8) |
872 ((blue
& 0xf000) >> 12);
875 color
= ((red
& 0xf800) >> 1) |
876 ((green
& 0xf800) >> 6) |
877 ((blue
& 0xf800) >> 11);
880 color
= (red
& 0xf800 ) |
881 ((green
& 0xfc00) >> 5) |
882 ((blue
& 0xf800) >> 11);
886 palette
[regno
] = color
;
890 /* We don't really support blanking. All this does is enable or
892 static int ivtvfb_blank(int blank_mode
, struct fb_info
*info
)
894 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
896 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode
);
897 switch (blank_mode
) {
898 case FB_BLANK_UNBLANK
:
899 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 1);
900 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 1);
902 case FB_BLANK_NORMAL
:
903 case FB_BLANK_HSYNC_SUSPEND
:
904 case FB_BLANK_VSYNC_SUSPEND
:
905 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 0);
906 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 1);
908 case FB_BLANK_POWERDOWN
:
909 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 0);
910 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 0);
916 static struct fb_ops ivtvfb_ops
= {
917 .owner
= THIS_MODULE
,
918 .fb_write
= ivtvfb_write
,
919 .fb_check_var
= ivtvfb_check_var
,
920 .fb_set_par
= ivtvfb_set_par
,
921 .fb_setcolreg
= ivtvfb_setcolreg
,
922 .fb_fillrect
= cfb_fillrect
,
923 .fb_copyarea
= cfb_copyarea
,
924 .fb_imageblit
= cfb_imageblit
,
926 .fb_ioctl
= ivtvfb_ioctl
,
927 .fb_pan_display
= ivtvfb_pan_display
,
928 .fb_blank
= ivtvfb_blank
,
934 /* Setup our initial video mode */
935 static int ivtvfb_init_vidmode(struct ivtv
*itv
)
937 struct osd_info
*oi
= itv
->osd_info
;
938 struct v4l2_rect start_window
;
943 if (osd_depth
!= 8 && osd_depth
!= 16 && osd_depth
!= 32)
945 oi
->bits_per_pixel
= osd_depth
;
946 oi
->bytes_per_pixel
= oi
->bits_per_pixel
/ 8;
948 /* Horizontal size & position */
953 /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
956 else if (osd_depth
== 16)
959 start_window
.width
= osd_xres
? osd_xres
: 640;
961 /* Check horizontal start (osd_left). */
962 if (osd_left
&& osd_left
+ start_window
.width
> 721) {
963 IVTVFB_ERR("Invalid osd_left - assuming default\n");
967 /* Hardware coords start at 0, user coords start at 1. */
970 start_window
.left
= osd_left
>= 0 ? osd_left
: ((IVTV_OSD_MAX_WIDTH
- start_window
.width
) / 2);
972 oi
->display_byte_stride
=
973 start_window
.width
* oi
->bytes_per_pixel
;
975 /* Vertical size & position */
977 max_height
= itv
->is_50hz
? 576 : 480;
979 if (osd_yres
> max_height
)
980 osd_yres
= max_height
;
982 start_window
.height
= osd_yres
? osd_yres
: itv
->is_50hz
? 480 : 400;
984 /* Check vertical start (osd_upper). */
985 if (osd_upper
+ start_window
.height
> max_height
+ 1) {
986 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
990 /* Hardware coords start at 0, user coords start at 1. */
993 start_window
.top
= osd_upper
>= 0 ? osd_upper
: ((max_height
- start_window
.height
) / 2);
995 oi
->display_width
= start_window
.width
;
996 oi
->display_height
= start_window
.height
;
998 /* Generate a valid fb_var_screeninfo */
1000 oi
->ivtvfb_defined
.xres
= oi
->display_width
;
1001 oi
->ivtvfb_defined
.yres
= oi
->display_height
;
1002 oi
->ivtvfb_defined
.xres_virtual
= oi
->display_width
;
1003 oi
->ivtvfb_defined
.yres_virtual
= oi
->display_height
;
1004 oi
->ivtvfb_defined
.bits_per_pixel
= oi
->bits_per_pixel
;
1005 oi
->ivtvfb_defined
.vmode
= (osd_laced
? FB_VMODE_INTERLACED
: FB_VMODE_NONINTERLACED
);
1006 oi
->ivtvfb_defined
.left_margin
= start_window
.left
+ 1;
1007 oi
->ivtvfb_defined
.upper_margin
= start_window
.top
+ 1;
1008 oi
->ivtvfb_defined
.accel_flags
= FB_ACCEL_NONE
;
1009 oi
->ivtvfb_defined
.nonstd
= 0;
1011 /* We've filled in the most data, let the usual mode check
1012 routine fill in the rest. */
1013 _ivtvfb_check_var(&oi
->ivtvfb_defined
, itv
);
1015 /* Generate valid fb_fix_screeninfo */
1017 ivtvfb_get_fix(itv
, &oi
->ivtvfb_fix
);
1019 /* Generate valid fb_info */
1021 oi
->ivtvfb_info
.node
= -1;
1022 oi
->ivtvfb_info
.flags
= FBINFO_FLAG_DEFAULT
;
1023 oi
->ivtvfb_info
.fbops
= &ivtvfb_ops
;
1024 oi
->ivtvfb_info
.par
= itv
;
1025 oi
->ivtvfb_info
.var
= oi
->ivtvfb_defined
;
1026 oi
->ivtvfb_info
.fix
= oi
->ivtvfb_fix
;
1027 oi
->ivtvfb_info
.screen_base
= (u8 __iomem
*)oi
->video_vbase
;
1028 oi
->ivtvfb_info
.fbops
= &ivtvfb_ops
;
1030 /* Supply some monitor specs. Bogus values will do for now */
1031 oi
->ivtvfb_info
.monspecs
.hfmin
= 8000;
1032 oi
->ivtvfb_info
.monspecs
.hfmax
= 70000;
1033 oi
->ivtvfb_info
.monspecs
.vfmin
= 10;
1034 oi
->ivtvfb_info
.monspecs
.vfmax
= 100;
1036 /* Allocate color map */
1037 if (fb_alloc_cmap(&oi
->ivtvfb_info
.cmap
, 256, 1)) {
1038 IVTVFB_ERR("abort, unable to alloc cmap\n");
1042 /* Allocate the pseudo palette */
1043 oi
->ivtvfb_info
.pseudo_palette
=
1044 kmalloc(sizeof(u32
) * 16, GFP_KERNEL
|__GFP_NOWARN
);
1046 if (!oi
->ivtvfb_info
.pseudo_palette
) {
1047 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
1054 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1056 static int ivtvfb_init_io(struct ivtv
*itv
)
1058 struct osd_info
*oi
= itv
->osd_info
;
1060 mutex_lock(&itv
->serialize_lock
);
1061 if (ivtv_init_on_first_open(itv
)) {
1062 mutex_unlock(&itv
->serialize_lock
);
1063 IVTVFB_ERR("Failed to initialize ivtv\n");
1066 mutex_unlock(&itv
->serialize_lock
);
1068 ivtvfb_get_framebuffer(itv
, &oi
->video_rbase
, &oi
->video_buffer_size
);
1070 /* The osd buffer size depends on the number of video buffers allocated
1071 on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1072 size to prevent any overlap. */
1073 oi
->video_buffer_size
= 1704960;
1075 oi
->video_pbase
= itv
->base_addr
+ IVTV_DECODER_OFFSET
+ oi
->video_rbase
;
1076 oi
->video_vbase
= itv
->dec_mem
+ oi
->video_rbase
;
1078 if (!oi
->video_vbase
) {
1079 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1080 oi
->video_buffer_size
, oi
->video_pbase
);
1084 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1085 oi
->video_pbase
, oi
->video_vbase
,
1086 oi
->video_buffer_size
/ 1024);
1090 /* Find the largest power of two that maps the whole buffer */
1091 int size_shift
= 31;
1093 while (!(oi
->video_buffer_size
& (1 << size_shift
))) {
1097 oi
->fb_start_aligned_physaddr
= oi
->video_pbase
& ~((1 << size_shift
) - 1);
1098 oi
->fb_end_aligned_physaddr
= oi
->video_pbase
+ oi
->video_buffer_size
;
1099 oi
->fb_end_aligned_physaddr
+= (1 << size_shift
) - 1;
1100 oi
->fb_end_aligned_physaddr
&= ~((1 << size_shift
) - 1);
1101 if (mtrr_add(oi
->fb_start_aligned_physaddr
,
1102 oi
->fb_end_aligned_physaddr
- oi
->fb_start_aligned_physaddr
,
1103 MTRR_TYPE_WRCOMB
, 1) < 0) {
1104 IVTVFB_INFO("disabled mttr\n");
1105 oi
->fb_start_aligned_physaddr
= 0;
1106 oi
->fb_end_aligned_physaddr
= 0;
1111 /* Blank the entire osd. */
1112 memset_io(oi
->video_vbase
, 0, oi
->video_buffer_size
);
1117 /* Release any memory we've grabbed & remove mtrr entry */
1118 static void ivtvfb_release_buffers (struct ivtv
*itv
)
1120 struct osd_info
*oi
= itv
->osd_info
;
1123 if (oi
->ivtvfb_info
.cmap
.len
)
1124 fb_dealloc_cmap(&oi
->ivtvfb_info
.cmap
);
1126 /* Release pseudo palette */
1127 if (oi
->ivtvfb_info
.pseudo_palette
)
1128 kfree(oi
->ivtvfb_info
.pseudo_palette
);
1131 if (oi
->fb_end_aligned_physaddr
) {
1132 mtrr_del(-1, oi
->fb_start_aligned_physaddr
,
1133 oi
->fb_end_aligned_physaddr
- oi
->fb_start_aligned_physaddr
);
1138 itv
->osd_info
= NULL
;
1141 /* Initialize the specified card */
1143 static int ivtvfb_init_card(struct ivtv
*itv
)
1147 if (itv
->osd_info
) {
1148 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id
);
1152 itv
->osd_info
= kzalloc(sizeof(struct osd_info
),
1153 GFP_ATOMIC
|__GFP_NOWARN
);
1154 if (itv
->osd_info
== NULL
) {
1155 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1159 /* Find & setup the OSD buffer */
1160 if ((rc
= ivtvfb_init_io(itv
)))
1163 /* Set the startup video mode information */
1164 if ((rc
= ivtvfb_init_vidmode(itv
))) {
1165 ivtvfb_release_buffers(itv
);
1169 /* Register the framebuffer */
1170 if (register_framebuffer(&itv
->osd_info
->ivtvfb_info
) < 0) {
1171 ivtvfb_release_buffers(itv
);
1175 itv
->osd_video_pbase
= itv
->osd_info
->video_pbase
;
1177 /* Set the card to the requested mode */
1178 ivtvfb_set_par(&itv
->osd_info
->ivtvfb_info
);
1180 /* Set color 0 to black */
1181 write_reg(0, 0x02a30);
1182 write_reg(0, 0x02a34);
1184 /* Enable the osd */
1185 ivtvfb_blank(FB_BLANK_UNBLANK
, &itv
->osd_info
->ivtvfb_info
);
1188 ivtv_udma_alloc(itv
);
1193 static int __init
ivtvfb_callback_init(struct device
*dev
, void *p
)
1195 struct v4l2_device
*v4l2_dev
= dev_get_drvdata(dev
);
1196 struct ivtv
*itv
= container_of(v4l2_dev
, struct ivtv
, v4l2_dev
);
1198 if (itv
&& (itv
->v4l2_cap
& V4L2_CAP_VIDEO_OUTPUT
)) {
1199 if (ivtvfb_init_card(itv
) == 0) {
1200 IVTVFB_INFO("Framebuffer registered on %s\n",
1201 itv
->v4l2_dev
.name
);
1208 static int ivtvfb_callback_cleanup(struct device
*dev
, void *p
)
1210 struct v4l2_device
*v4l2_dev
= dev_get_drvdata(dev
);
1211 struct ivtv
*itv
= container_of(v4l2_dev
, struct ivtv
, v4l2_dev
);
1213 if (itv
&& (itv
->v4l2_cap
& V4L2_CAP_VIDEO_OUTPUT
)) {
1214 if (unregister_framebuffer(&itv
->osd_info
->ivtvfb_info
)) {
1215 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1219 IVTVFB_INFO("Unregister framebuffer %d\n", itv
->instance
);
1220 ivtvfb_blank(FB_BLANK_POWERDOWN
, &itv
->osd_info
->ivtvfb_info
);
1221 ivtvfb_release_buffers(itv
);
1222 itv
->osd_video_pbase
= 0;
1227 static int __init
ivtvfb_init(void)
1229 struct device_driver
*drv
;
1233 if (ivtvfb_card_id
< -1 || ivtvfb_card_id
>= IVTV_MAX_CARDS
) {
1234 printk(KERN_ERR
"ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1235 IVTV_MAX_CARDS
- 1);
1239 drv
= driver_find("ivtv", &pci_bus_type
);
1240 err
= driver_for_each_device(drv
, NULL
, ®istered
, ivtvfb_callback_init
);
1243 printk(KERN_ERR
"ivtvfb: no cards found\n");
1249 static void ivtvfb_cleanup(void)
1251 struct device_driver
*drv
;
1254 printk(KERN_INFO
"ivtvfb: Unloading framebuffer module\n");
1256 drv
= driver_find("ivtv", &pci_bus_type
);
1257 err
= driver_for_each_device(drv
, NULL
, NULL
, ivtvfb_callback_cleanup
);
1261 module_init(ivtvfb_init
);
1262 module_exit(ivtvfb_cleanup
);