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>
45 #include <linux/slab.h>
51 #include "ivtv-driver.h"
52 #include "ivtv-cards.h"
54 #include "ivtv-udma.h"
55 #include "ivtv-mailbox.h"
58 static int ivtvfb_card_id
= -1;
59 static int ivtvfb_debug
= 0;
67 module_param(ivtvfb_card_id
, int, 0444);
68 module_param_named(debug
,ivtvfb_debug
, int, 0644);
69 module_param(osd_laced
, bool, 0444);
70 module_param(osd_depth
, int, 0444);
71 module_param(osd_upper
, int, 0444);
72 module_param(osd_left
, int, 0444);
73 module_param(osd_yres
, int, 0444);
74 module_param(osd_xres
, int, 0444);
76 MODULE_PARM_DESC(ivtvfb_card_id
,
77 "Only use framebuffer of the specified ivtv card (0-31)\n"
78 "\t\t\tdefault -1: initialize all available framebuffers");
80 MODULE_PARM_DESC(debug
,
81 "Debug level (bitmask). Default: errors only\n"
82 "\t\t\t(debug = 3 gives full debugging)");
84 /* Why upper, left, xres, yres, depth, laced ? To match terminology used
86 Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
88 MODULE_PARM_DESC(osd_laced
,
94 MODULE_PARM_DESC(osd_depth
,
95 "Bits per pixel - 8, 16, 32\n"
98 MODULE_PARM_DESC(osd_upper
,
99 "Vertical start position\n"
100 "\t\t\tdefault 0 (Centered)");
102 MODULE_PARM_DESC(osd_left
,
103 "Horizontal start position\n"
104 "\t\t\tdefault 0 (Centered)");
106 MODULE_PARM_DESC(osd_yres
,
108 "\t\t\tdefault 480 (PAL)\n"
109 "\t\t\t 400 (NTSC)");
111 MODULE_PARM_DESC(osd_xres
,
113 "\t\t\tdefault 640");
115 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
116 MODULE_LICENSE("GPL");
118 /* --------------------------------------------------------------------- */
120 #define IVTVFB_DBGFLG_WARN (1 << 0)
121 #define IVTVFB_DBGFLG_INFO (1 << 1)
123 #define IVTVFB_DEBUG(x, type, fmt, args...) \
125 if ((x) & ivtvfb_debug) \
126 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
128 #define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
129 #define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
131 /* Standard kernel messages */
132 #define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args)
133 #define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args)
134 #define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
136 /* --------------------------------------------------------------------- */
138 #define IVTV_OSD_MAX_WIDTH 720
139 #define IVTV_OSD_MAX_HEIGHT 576
141 #define IVTV_OSD_BPP_8 0x00
142 #define IVTV_OSD_BPP_16_444 0x03
143 #define IVTV_OSD_BPP_16_555 0x02
144 #define IVTV_OSD_BPP_16_565 0x01
145 #define IVTV_OSD_BPP_32 0x04
148 /* Physical base address */
149 unsigned long video_pbase
;
150 /* Relative base address (relative to start of decoder memory) */
152 /* Mapped base address */
153 volatile char __iomem
*video_vbase
;
155 u32 video_buffer_size
;
158 /* video_base rounded down as required by hardware MTRRs */
159 unsigned long fb_start_aligned_physaddr
;
160 /* video_base rounded up as required by hardware MTRRs */
161 unsigned long fb_end_aligned_physaddr
;
164 /* Store the buffer offset */
165 int set_osd_coords_x
;
166 int set_osd_coords_y
;
168 /* Current dimensions (NOT VISIBLE SIZE!) */
171 int display_byte_stride
;
173 /* Current bits per pixel */
177 /* Frame buffer stuff */
178 struct fb_info ivtvfb_info
;
179 struct fb_var_screeninfo ivtvfb_defined
;
180 struct fb_fix_screeninfo ivtvfb_fix
;
183 struct ivtv_osd_coords
{
184 unsigned long offset
;
185 unsigned long max_offset
;
192 /* --------------------------------------------------------------------- */
194 /* ivtv API calls for framebuffer related support */
196 static int ivtvfb_get_framebuffer(struct ivtv
*itv
, u32
*fbbase
,
199 u32 data
[CX2341X_MBOX_MAX_DATA
];
202 rc
= ivtv_vapi_result(itv
, data
, CX2341X_OSD_GET_FRAMEBUFFER
, 0);
208 static int ivtvfb_get_osd_coords(struct ivtv
*itv
,
209 struct ivtv_osd_coords
*osd
)
211 struct osd_info
*oi
= itv
->osd_info
;
212 u32 data
[CX2341X_MBOX_MAX_DATA
];
214 ivtv_vapi_result(itv
, data
, CX2341X_OSD_GET_OSD_COORDS
, 0);
216 osd
->offset
= data
[0] - oi
->video_rbase
;
217 osd
->max_offset
= oi
->display_width
* oi
->display_height
* 4;
218 osd
->pixel_stride
= data
[1];
219 osd
->lines
= data
[2];
225 static int ivtvfb_set_osd_coords(struct ivtv
*itv
, const struct ivtv_osd_coords
*osd
)
227 struct osd_info
*oi
= itv
->osd_info
;
229 oi
->display_width
= osd
->pixel_stride
;
230 oi
->display_byte_stride
= osd
->pixel_stride
* oi
->bytes_per_pixel
;
231 oi
->set_osd_coords_x
+= osd
->x
;
232 oi
->set_osd_coords_y
= osd
->y
;
234 return ivtv_vapi(itv
, CX2341X_OSD_SET_OSD_COORDS
, 5,
235 osd
->offset
+ oi
->video_rbase
,
237 osd
->lines
, osd
->x
, osd
->y
);
240 static int ivtvfb_set_display_window(struct ivtv
*itv
, struct v4l2_rect
*ivtv_window
)
242 int osd_height_limit
= itv
->is_50hz
? 576 : 480;
244 /* Only fail if resolution too high, otherwise fudge the start coords. */
245 if ((ivtv_window
->height
> osd_height_limit
) || (ivtv_window
->width
> IVTV_OSD_MAX_WIDTH
))
248 /* Ensure we don't exceed display limits */
249 if (ivtv_window
->top
+ ivtv_window
->height
> osd_height_limit
) {
250 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
251 ivtv_window
->top
, ivtv_window
->height
);
252 ivtv_window
->top
= osd_height_limit
- ivtv_window
->height
;
255 if (ivtv_window
->left
+ ivtv_window
->width
> IVTV_OSD_MAX_WIDTH
) {
256 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
257 ivtv_window
->left
, ivtv_window
->width
);
258 ivtv_window
->left
= IVTV_OSD_MAX_WIDTH
- ivtv_window
->width
;
261 /* Set the OSD origin */
262 write_reg((ivtv_window
->top
<< 16) | ivtv_window
->left
, 0x02a04);
264 /* How much to display */
265 write_reg(((ivtv_window
->top
+ivtv_window
->height
) << 16) | (ivtv_window
->left
+ivtv_window
->width
), 0x02a08);
267 /* Pass this info back the yuv handler */
268 itv
->yuv_info
.osd_vis_w
= ivtv_window
->width
;
269 itv
->yuv_info
.osd_vis_h
= ivtv_window
->height
;
270 itv
->yuv_info
.osd_x_offset
= ivtv_window
->left
;
271 itv
->yuv_info
.osd_y_offset
= ivtv_window
->top
;
276 static int ivtvfb_prep_dec_dma_to_device(struct ivtv
*itv
,
277 unsigned long ivtv_dest_addr
, void __user
*userbuf
,
283 mutex_lock(&itv
->udma
.lock
);
285 if (ivtv_udma_setup(itv
, ivtv_dest_addr
, userbuf
, size_in_bytes
) <= 0) {
286 mutex_unlock(&itv
->udma
.lock
);
287 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
288 "Error with get_user_pages: %d bytes, %d pages returned\n",
289 size_in_bytes
, itv
->udma
.page_count
);
291 /* get_user_pages must have failed completely */
295 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
296 size_in_bytes
, itv
->udma
.page_count
);
298 ivtv_udma_prepare(itv
);
299 prepare_to_wait(&itv
->dma_waitq
, &wait
, TASK_INTERRUPTIBLE
);
300 /* if no UDMA is pending and no UDMA is in progress, then the DMA
302 while (test_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
) ||
303 test_bit(IVTV_F_I_UDMA
, &itv
->i_flags
)) {
304 /* don't interrupt if the DMA is in progress but break off
305 a still pending DMA. */
306 got_sig
= signal_pending(current
);
307 if (got_sig
&& test_and_clear_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
))
312 finish_wait(&itv
->dma_waitq
, &wait
);
314 /* Unmap Last DMA Xfer */
315 ivtv_udma_unmap(itv
);
316 mutex_unlock(&itv
->udma
.lock
);
318 IVTV_DEBUG_INFO("User stopped OSD\n");
325 static int ivtvfb_prep_frame(struct ivtv
*itv
, int cmd
, void __user
*source
,
326 unsigned long dest_offset
, int count
)
329 struct osd_info
*oi
= itv
->osd_info
;
333 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
337 /* Check Total FB Size */
338 if ((dest_offset
+ count
) > oi
->video_buffer_size
) {
339 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
340 dest_offset
+ count
, oi
->video_buffer_size
);
344 /* Not fatal, but will have undesirable results */
345 if ((unsigned long)source
& 3)
346 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
347 (unsigned long)source
);
350 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset
);
353 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count
);
356 if (!access_ok(VERIFY_READ
, source
+ dest_offset
, count
)) {
357 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
358 (unsigned long)source
);
360 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
361 dest_offset
, (unsigned long)source
,
366 /* OSD Address to send DMA to */
367 dest_offset
+= IVTV_DECODER_OFFSET
+ oi
->video_rbase
;
370 return ivtvfb_prep_dec_dma_to_device(itv
, dest_offset
, source
, count
);
373 static ssize_t
ivtvfb_write(struct fb_info
*info
, const char __user
*buf
,
374 size_t count
, loff_t
*ppos
)
376 unsigned long p
= *ppos
;
380 unsigned long total_size
;
381 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
382 unsigned long dma_offset
=
383 IVTV_DECODER_OFFSET
+ itv
->osd_info
->video_rbase
;
384 unsigned long dma_size
;
385 u16 lead
= 0, tail
= 0;
387 if (info
->state
!= FBINFO_STATE_RUNNING
)
390 total_size
= info
->screen_size
;
393 total_size
= info
->fix
.smem_len
;
398 if (count
> total_size
) {
403 if (count
+ p
> total_size
) {
406 count
= total_size
- p
;
409 dst
= (void __force
*) (info
->screen_base
+ p
);
411 if (info
->fbops
->fb_sync
)
412 info
->fbops
->fb_sync(info
);
414 /* If transfer size > threshold and both src/dst
415 addresses are aligned, use DMA */
417 ((unsigned long)buf
& 3) == ((unsigned long)dst
& 3)) {
418 /* Odd address = can't DMA. Align */
419 if ((unsigned long)dst
& 3) {
420 lead
= 4 - ((unsigned long)dst
& 3);
421 if (copy_from_user(dst
, buf
, lead
))
426 /* DMA resolution is 32 bits */
427 if ((count
- lead
) & 3)
428 tail
= (count
- lead
) & 3;
430 dma_size
= count
- lead
- tail
;
431 dma_err
= ivtvfb_prep_dec_dma_to_device(itv
,
432 p
+ lead
+ dma_offset
, (void __user
*)buf
, dma_size
);
437 /* Copy any leftover data */
438 if (tail
&& copy_from_user(dst
, buf
, tail
))
440 } else if (copy_from_user(dst
, buf
, count
)) {
447 return (err
) ? err
: count
;
450 static int ivtvfb_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
453 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
457 case FBIOGET_VBLANK
: {
458 struct fb_vblank vblank
;
461 vblank
.flags
= FB_VBLANK_HAVE_COUNT
|FB_VBLANK_HAVE_VCOUNT
|
462 FB_VBLANK_HAVE_VSYNC
;
463 trace
= read_reg(0x028c0) >> 16;
464 if (itv
->is_50hz
&& trace
> 312)
466 else if (itv
->is_60hz
&& trace
> 262)
469 vblank
.flags
|= FB_VBLANK_VSYNCING
;
470 vblank
.count
= itv
->last_vsync_field
;
471 vblank
.vcount
= trace
;
473 if (copy_to_user((void __user
*)arg
, &vblank
, sizeof(vblank
)))
478 case FBIO_WAITFORVSYNC
:
479 prepare_to_wait(&itv
->vsync_waitq
, &wait
, TASK_INTERRUPTIBLE
);
480 if (!schedule_timeout(msecs_to_jiffies(50)))
482 finish_wait(&itv
->vsync_waitq
, &wait
);
485 case IVTVFB_IOC_DMA_FRAME
: {
486 struct ivtvfb_dma_frame args
;
488 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
489 if (copy_from_user(&args
, (void __user
*)arg
, sizeof(args
)))
492 return ivtvfb_prep_frame(itv
, cmd
, args
.source
, args
.dest_offset
, args
.count
);
496 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd
);
502 /* Framebuffer device handling */
504 static int ivtvfb_set_var(struct ivtv
*itv
, struct fb_var_screeninfo
*var
)
506 struct osd_info
*oi
= itv
->osd_info
;
507 struct ivtv_osd_coords ivtv_osd
;
508 struct v4l2_rect ivtv_window
;
511 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
513 /* Select color space */
514 if (var
->nonstd
) /* YUV */
515 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
517 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
519 /* Set the color mode */
520 switch (var
->bits_per_pixel
) {
522 osd_mode
= IVTV_OSD_BPP_8
;
525 osd_mode
= IVTV_OSD_BPP_32
;
528 switch (var
->green
.length
) {
530 osd_mode
= IVTV_OSD_BPP_16_444
;
533 osd_mode
= IVTV_OSD_BPP_16_555
;
536 osd_mode
= IVTV_OSD_BPP_16_565
;
539 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
543 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
546 /* Set video mode. Although rare, the display can become scrambled even
547 if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
548 if (osd_mode
!= -1) {
549 ivtv_vapi(itv
, CX2341X_OSD_SET_PIXEL_FORMAT
, 1, 0);
550 ivtv_vapi(itv
, CX2341X_OSD_SET_PIXEL_FORMAT
, 1, osd_mode
);
553 oi
->bits_per_pixel
= var
->bits_per_pixel
;
554 oi
->bytes_per_pixel
= var
->bits_per_pixel
/ 8;
556 /* Set the flicker filter */
557 switch (var
->vmode
& FB_VMODE_MASK
) {
558 case FB_VMODE_NONINTERLACED
: /* Filter on */
559 ivtv_vapi(itv
, CX2341X_OSD_SET_FLICKER_STATE
, 1, 1);
561 case FB_VMODE_INTERLACED
: /* Filter off */
562 ivtv_vapi(itv
, CX2341X_OSD_SET_FLICKER_STATE
, 1, 0);
565 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
568 /* Read the current osd info */
569 ivtvfb_get_osd_coords(itv
, &ivtv_osd
);
571 /* Now set the OSD to the size we want */
572 ivtv_osd
.pixel_stride
= var
->xres_virtual
;
573 ivtv_osd
.lines
= var
->yres_virtual
;
576 ivtvfb_set_osd_coords(itv
, &ivtv_osd
);
578 /* Can't seem to find the right API combo for this.
579 Use another function which does what we need through direct register access. */
580 ivtv_window
.width
= var
->xres
;
581 ivtv_window
.height
= var
->yres
;
583 /* Minimum margin cannot be 0, as X won't allow such a mode */
584 if (!var
->upper_margin
) var
->upper_margin
++;
585 if (!var
->left_margin
) var
->left_margin
++;
586 ivtv_window
.top
= var
->upper_margin
- 1;
587 ivtv_window
.left
= var
->left_margin
- 1;
589 ivtvfb_set_display_window(itv
, &ivtv_window
);
591 /* Pass screen size back to yuv handler */
592 itv
->yuv_info
.osd_full_w
= ivtv_osd
.pixel_stride
;
593 itv
->yuv_info
.osd_full_h
= ivtv_osd
.lines
;
595 /* Force update of yuv registers */
596 itv
->yuv_info
.yuv_forced_update
= 1;
598 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
599 var
->xres
, var
->yres
,
600 var
->xres_virtual
, var
->yres_virtual
,
601 var
->bits_per_pixel
);
603 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
604 var
->left_margin
, var
->upper_margin
);
606 IVTVFB_DEBUG_INFO("Display filter: %s\n",
607 (var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
? "on" : "off");
608 IVTVFB_DEBUG_INFO("Color space: %s\n", var
->nonstd
? "YUV" : "RGB");
613 static int ivtvfb_get_fix(struct ivtv
*itv
, struct fb_fix_screeninfo
*fix
)
615 struct osd_info
*oi
= itv
->osd_info
;
617 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
618 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
619 strlcpy(fix
->id
, "cx23415 TV out", sizeof(fix
->id
));
620 fix
->smem_start
= oi
->video_pbase
;
621 fix
->smem_len
= oi
->video_buffer_size
;
622 fix
->type
= FB_TYPE_PACKED_PIXELS
;
623 fix
->visual
= (oi
->bits_per_pixel
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
627 fix
->line_length
= oi
->display_byte_stride
;
628 fix
->accel
= FB_ACCEL_NONE
;
632 /* Check the requested display mode, returning -EINVAL if we can't
635 static int _ivtvfb_check_var(struct fb_var_screeninfo
*var
, struct ivtv
*itv
)
637 struct osd_info
*oi
= itv
->osd_info
;
638 int osd_height_limit
;
639 u32 pixclock
, hlimit
, vlimit
;
641 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
643 /* Set base references for mode calcs. */
648 osd_height_limit
= 576;
654 osd_height_limit
= 480;
657 if (var
->bits_per_pixel
== 8 || var
->bits_per_pixel
== 32) {
658 var
->transp
.offset
= 24;
659 var
->transp
.length
= 8;
660 var
->red
.offset
= 16;
662 var
->green
.offset
= 8;
663 var
->green
.length
= 8;
664 var
->blue
.offset
= 0;
665 var
->blue
.length
= 8;
667 else if (var
->bits_per_pixel
== 16) {
668 /* To find out the true mode, check green length */
669 switch (var
->green
.length
) {
673 var
->green
.offset
= 4;
674 var
->green
.length
= 4;
675 var
->blue
.offset
= 0;
676 var
->blue
.length
= 4;
677 var
->transp
.offset
= 12;
678 var
->transp
.length
= 1;
681 var
->red
.offset
= 10;
683 var
->green
.offset
= 5;
684 var
->green
.length
= 5;
685 var
->blue
.offset
= 0;
686 var
->blue
.length
= 5;
687 var
->transp
.offset
= 15;
688 var
->transp
.length
= 1;
691 var
->red
.offset
= 11;
693 var
->green
.offset
= 5;
694 var
->green
.length
= 6;
695 var
->blue
.offset
= 0;
696 var
->blue
.length
= 5;
697 var
->transp
.offset
= 0;
698 var
->transp
.length
= 0;
703 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var
->bits_per_pixel
);
707 /* Check the resolution */
708 if (var
->xres
> IVTV_OSD_MAX_WIDTH
|| var
->yres
> osd_height_limit
) {
709 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
710 var
->xres
, var
->yres
);
714 /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
715 if (var
->xres_virtual
> 4095 / (var
->bits_per_pixel
/ 8) ||
716 var
->xres_virtual
* var
->yres_virtual
* (var
->bits_per_pixel
/ 8) > oi
->video_buffer_size
||
717 var
->xres_virtual
< var
->xres
||
718 var
->yres_virtual
< var
->yres
) {
719 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
720 var
->xres_virtual
, var
->yres_virtual
);
724 /* Some extra checks if in 8 bit mode */
725 if (var
->bits_per_pixel
== 8) {
726 /* Width must be a multiple of 4 */
728 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var
->xres
);
731 if (var
->xres_virtual
& 3) {
732 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var
->xres_virtual
);
736 else if (var
->bits_per_pixel
== 16) {
737 /* Width must be a multiple of 2 */
739 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var
->xres
);
742 if (var
->xres_virtual
& 1) {
743 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var
->xres_virtual
);
748 /* Now check the offsets */
749 if (var
->xoffset
>= var
->xres_virtual
|| var
->yoffset
>= var
->yres_virtual
) {
750 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
751 var
->xoffset
, var
->xres_virtual
, var
->yoffset
, var
->yres_virtual
);
755 /* Check pixel format */
756 if (var
->nonstd
> 1) {
757 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var
->nonstd
);
761 /* Check video mode */
762 if (((var
->vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
) &&
763 ((var
->vmode
& FB_VMODE_MASK
) != FB_VMODE_INTERLACED
)) {
764 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var
->vmode
& FB_VMODE_MASK
);
768 /* Check the left & upper margins
769 If the margins are too large, just center the screen
770 (enforcing margins causes too many problems) */
772 if (var
->left_margin
+ var
->xres
> IVTV_OSD_MAX_WIDTH
+ 1) {
773 var
->left_margin
= 1 + ((IVTV_OSD_MAX_WIDTH
- var
->xres
) / 2);
775 if (var
->upper_margin
+ var
->yres
> (itv
->is_50hz
? 577 : 481)) {
776 var
->upper_margin
= 1 + (((itv
->is_50hz
? 576 : 480) - var
->yres
) / 2);
779 /* Maintain overall 'size' for a constant refresh rate */
780 var
->right_margin
= hlimit
- var
->left_margin
- var
->xres
;
781 var
->lower_margin
= vlimit
- var
->upper_margin
- var
->yres
;
783 /* Fixed sync times */
787 /* Non-interlaced / interlaced mode is used to switch the OSD filter
788 on or off. Adjust the clock timings to maintain a constant
789 vertical refresh rate. */
790 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
791 var
->pixclock
= pixclock
/ 2;
793 var
->pixclock
= pixclock
;
795 itv
->osd_rect
.width
= var
->xres
;
796 itv
->osd_rect
.height
= var
->yres
;
798 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
799 var
->xres
, var
->yres
,
800 var
->xres_virtual
, var
->yres_virtual
,
801 var
->bits_per_pixel
);
803 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
804 var
->left_margin
, var
->upper_margin
);
806 IVTVFB_DEBUG_INFO("Display filter: %s\n",
807 (var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
? "on" : "off");
808 IVTVFB_DEBUG_INFO("Color space: %s\n", var
->nonstd
? "YUV" : "RGB");
812 static int ivtvfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
814 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
815 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
816 return _ivtvfb_check_var(var
, itv
);
819 static int ivtvfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
822 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
824 osd_pan_index
= (var
->xoffset
+ (var
->yoffset
* var
->xres_virtual
))*var
->bits_per_pixel
/8;
825 write_reg(osd_pan_index
, 0x02A0C);
827 /* Pass this info back the yuv handler */
828 itv
->yuv_info
.osd_x_pan
= var
->xoffset
;
829 itv
->yuv_info
.osd_y_pan
= var
->yoffset
;
830 /* Force update of yuv registers */
831 itv
->yuv_info
.yuv_forced_update
= 1;
835 static int ivtvfb_set_par(struct fb_info
*info
)
838 struct ivtv
*itv
= (struct ivtv
*) info
->par
;
840 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
842 rc
= ivtvfb_set_var(itv
, &info
->var
);
843 ivtvfb_pan_display(&info
->var
, info
);
844 ivtvfb_get_fix(itv
, &info
->fix
);
848 static int ivtvfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
849 unsigned blue
, unsigned transp
,
850 struct fb_info
*info
)
853 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
855 if (regno
>= info
->cmap
.len
)
858 color
= ((transp
& 0xFF00) << 16) |((red
& 0xFF00) << 8) | (green
& 0xFF00) | ((blue
& 0xFF00) >> 8);
859 if (info
->var
.bits_per_pixel
<= 8) {
860 write_reg(regno
, 0x02a30);
861 write_reg(color
, 0x02a34);
867 palette
= info
->pseudo_palette
;
868 if (info
->var
.bits_per_pixel
== 16) {
869 switch (info
->var
.green
.length
) {
871 color
= ((red
& 0xf000) >> 4) |
872 ((green
& 0xf000) >> 8) |
873 ((blue
& 0xf000) >> 12);
876 color
= ((red
& 0xf800) >> 1) |
877 ((green
& 0xf800) >> 6) |
878 ((blue
& 0xf800) >> 11);
881 color
= (red
& 0xf800 ) |
882 ((green
& 0xfc00) >> 5) |
883 ((blue
& 0xf800) >> 11);
887 palette
[regno
] = color
;
891 /* We don't really support blanking. All this does is enable or
893 static int ivtvfb_blank(int blank_mode
, struct fb_info
*info
)
895 struct ivtv
*itv
= (struct ivtv
*)info
->par
;
897 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode
);
898 switch (blank_mode
) {
899 case FB_BLANK_UNBLANK
:
900 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 1);
901 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 1);
903 case FB_BLANK_NORMAL
:
904 case FB_BLANK_HSYNC_SUSPEND
:
905 case FB_BLANK_VSYNC_SUSPEND
:
906 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 0);
907 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 1);
909 case FB_BLANK_POWERDOWN
:
910 ivtv_call_hw(itv
, IVTV_HW_SAA7127
, video
, s_stream
, 0);
911 ivtv_vapi(itv
, CX2341X_OSD_SET_STATE
, 1, 0);
917 static struct fb_ops ivtvfb_ops
= {
918 .owner
= THIS_MODULE
,
919 .fb_write
= ivtvfb_write
,
920 .fb_check_var
= ivtvfb_check_var
,
921 .fb_set_par
= ivtvfb_set_par
,
922 .fb_setcolreg
= ivtvfb_setcolreg
,
923 .fb_fillrect
= cfb_fillrect
,
924 .fb_copyarea
= cfb_copyarea
,
925 .fb_imageblit
= cfb_imageblit
,
927 .fb_ioctl
= ivtvfb_ioctl
,
928 .fb_pan_display
= ivtvfb_pan_display
,
929 .fb_blank
= ivtvfb_blank
,
935 /* Setup our initial video mode */
936 static int ivtvfb_init_vidmode(struct ivtv
*itv
)
938 struct osd_info
*oi
= itv
->osd_info
;
939 struct v4l2_rect start_window
;
944 if (osd_depth
!= 8 && osd_depth
!= 16 && osd_depth
!= 32)
946 oi
->bits_per_pixel
= osd_depth
;
947 oi
->bytes_per_pixel
= oi
->bits_per_pixel
/ 8;
949 /* Horizontal size & position */
954 /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
957 else if (osd_depth
== 16)
960 start_window
.width
= osd_xres
? osd_xres
: 640;
962 /* Check horizontal start (osd_left). */
963 if (osd_left
&& osd_left
+ start_window
.width
> 721) {
964 IVTVFB_ERR("Invalid osd_left - assuming default\n");
968 /* Hardware coords start at 0, user coords start at 1. */
971 start_window
.left
= osd_left
>= 0 ? osd_left
: ((IVTV_OSD_MAX_WIDTH
- start_window
.width
) / 2);
973 oi
->display_byte_stride
=
974 start_window
.width
* oi
->bytes_per_pixel
;
976 /* Vertical size & position */
978 max_height
= itv
->is_50hz
? 576 : 480;
980 if (osd_yres
> max_height
)
981 osd_yres
= max_height
;
983 start_window
.height
= osd_yres
? osd_yres
: itv
->is_50hz
? 480 : 400;
985 /* Check vertical start (osd_upper). */
986 if (osd_upper
+ start_window
.height
> max_height
+ 1) {
987 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
991 /* Hardware coords start at 0, user coords start at 1. */
994 start_window
.top
= osd_upper
>= 0 ? osd_upper
: ((max_height
- start_window
.height
) / 2);
996 oi
->display_width
= start_window
.width
;
997 oi
->display_height
= start_window
.height
;
999 /* Generate a valid fb_var_screeninfo */
1001 oi
->ivtvfb_defined
.xres
= oi
->display_width
;
1002 oi
->ivtvfb_defined
.yres
= oi
->display_height
;
1003 oi
->ivtvfb_defined
.xres_virtual
= oi
->display_width
;
1004 oi
->ivtvfb_defined
.yres_virtual
= oi
->display_height
;
1005 oi
->ivtvfb_defined
.bits_per_pixel
= oi
->bits_per_pixel
;
1006 oi
->ivtvfb_defined
.vmode
= (osd_laced
? FB_VMODE_INTERLACED
: FB_VMODE_NONINTERLACED
);
1007 oi
->ivtvfb_defined
.left_margin
= start_window
.left
+ 1;
1008 oi
->ivtvfb_defined
.upper_margin
= start_window
.top
+ 1;
1009 oi
->ivtvfb_defined
.accel_flags
= FB_ACCEL_NONE
;
1010 oi
->ivtvfb_defined
.nonstd
= 0;
1012 /* We've filled in the most data, let the usual mode check
1013 routine fill in the rest. */
1014 _ivtvfb_check_var(&oi
->ivtvfb_defined
, itv
);
1016 /* Generate valid fb_fix_screeninfo */
1018 ivtvfb_get_fix(itv
, &oi
->ivtvfb_fix
);
1020 /* Generate valid fb_info */
1022 oi
->ivtvfb_info
.node
= -1;
1023 oi
->ivtvfb_info
.flags
= FBINFO_FLAG_DEFAULT
;
1024 oi
->ivtvfb_info
.fbops
= &ivtvfb_ops
;
1025 oi
->ivtvfb_info
.par
= itv
;
1026 oi
->ivtvfb_info
.var
= oi
->ivtvfb_defined
;
1027 oi
->ivtvfb_info
.fix
= oi
->ivtvfb_fix
;
1028 oi
->ivtvfb_info
.screen_base
= (u8 __iomem
*)oi
->video_vbase
;
1029 oi
->ivtvfb_info
.fbops
= &ivtvfb_ops
;
1031 /* Supply some monitor specs. Bogus values will do for now */
1032 oi
->ivtvfb_info
.monspecs
.hfmin
= 8000;
1033 oi
->ivtvfb_info
.monspecs
.hfmax
= 70000;
1034 oi
->ivtvfb_info
.monspecs
.vfmin
= 10;
1035 oi
->ivtvfb_info
.monspecs
.vfmax
= 100;
1037 /* Allocate color map */
1038 if (fb_alloc_cmap(&oi
->ivtvfb_info
.cmap
, 256, 1)) {
1039 IVTVFB_ERR("abort, unable to alloc cmap\n");
1043 /* Allocate the pseudo palette */
1044 oi
->ivtvfb_info
.pseudo_palette
=
1045 kmalloc(sizeof(u32
) * 16, GFP_KERNEL
|__GFP_NOWARN
);
1047 if (!oi
->ivtvfb_info
.pseudo_palette
) {
1048 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
1055 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1057 static int ivtvfb_init_io(struct ivtv
*itv
)
1059 struct osd_info
*oi
= itv
->osd_info
;
1061 mutex_lock(&itv
->serialize_lock
);
1062 if (ivtv_init_on_first_open(itv
)) {
1063 mutex_unlock(&itv
->serialize_lock
);
1064 IVTVFB_ERR("Failed to initialize ivtv\n");
1067 mutex_unlock(&itv
->serialize_lock
);
1069 ivtvfb_get_framebuffer(itv
, &oi
->video_rbase
, &oi
->video_buffer_size
);
1071 /* The osd buffer size depends on the number of video buffers allocated
1072 on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1073 size to prevent any overlap. */
1074 oi
->video_buffer_size
= 1704960;
1076 oi
->video_pbase
= itv
->base_addr
+ IVTV_DECODER_OFFSET
+ oi
->video_rbase
;
1077 oi
->video_vbase
= itv
->dec_mem
+ oi
->video_rbase
;
1079 if (!oi
->video_vbase
) {
1080 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1081 oi
->video_buffer_size
, oi
->video_pbase
);
1085 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1086 oi
->video_pbase
, oi
->video_vbase
,
1087 oi
->video_buffer_size
/ 1024);
1091 /* Find the largest power of two that maps the whole buffer */
1092 int size_shift
= 31;
1094 while (!(oi
->video_buffer_size
& (1 << size_shift
))) {
1098 oi
->fb_start_aligned_physaddr
= oi
->video_pbase
& ~((1 << size_shift
) - 1);
1099 oi
->fb_end_aligned_physaddr
= oi
->video_pbase
+ oi
->video_buffer_size
;
1100 oi
->fb_end_aligned_physaddr
+= (1 << size_shift
) - 1;
1101 oi
->fb_end_aligned_physaddr
&= ~((1 << size_shift
) - 1);
1102 if (mtrr_add(oi
->fb_start_aligned_physaddr
,
1103 oi
->fb_end_aligned_physaddr
- oi
->fb_start_aligned_physaddr
,
1104 MTRR_TYPE_WRCOMB
, 1) < 0) {
1105 IVTVFB_INFO("disabled mttr\n");
1106 oi
->fb_start_aligned_physaddr
= 0;
1107 oi
->fb_end_aligned_physaddr
= 0;
1112 /* Blank the entire osd. */
1113 memset_io(oi
->video_vbase
, 0, oi
->video_buffer_size
);
1118 /* Release any memory we've grabbed & remove mtrr entry */
1119 static void ivtvfb_release_buffers (struct ivtv
*itv
)
1121 struct osd_info
*oi
= itv
->osd_info
;
1124 if (oi
->ivtvfb_info
.cmap
.len
)
1125 fb_dealloc_cmap(&oi
->ivtvfb_info
.cmap
);
1127 /* Release pseudo palette */
1128 if (oi
->ivtvfb_info
.pseudo_palette
)
1129 kfree(oi
->ivtvfb_info
.pseudo_palette
);
1132 if (oi
->fb_end_aligned_physaddr
) {
1133 mtrr_del(-1, oi
->fb_start_aligned_physaddr
,
1134 oi
->fb_end_aligned_physaddr
- oi
->fb_start_aligned_physaddr
);
1139 itv
->osd_info
= NULL
;
1142 /* Initialize the specified card */
1144 static int ivtvfb_init_card(struct ivtv
*itv
)
1148 if (itv
->osd_info
) {
1149 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id
);
1153 itv
->osd_info
= kzalloc(sizeof(struct osd_info
),
1154 GFP_ATOMIC
|__GFP_NOWARN
);
1155 if (itv
->osd_info
== NULL
) {
1156 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1160 /* Find & setup the OSD buffer */
1161 if ((rc
= ivtvfb_init_io(itv
)))
1164 /* Set the startup video mode information */
1165 if ((rc
= ivtvfb_init_vidmode(itv
))) {
1166 ivtvfb_release_buffers(itv
);
1170 /* Register the framebuffer */
1171 if (register_framebuffer(&itv
->osd_info
->ivtvfb_info
) < 0) {
1172 ivtvfb_release_buffers(itv
);
1176 itv
->osd_video_pbase
= itv
->osd_info
->video_pbase
;
1178 /* Set the card to the requested mode */
1179 ivtvfb_set_par(&itv
->osd_info
->ivtvfb_info
);
1181 /* Set color 0 to black */
1182 write_reg(0, 0x02a30);
1183 write_reg(0, 0x02a34);
1185 /* Enable the osd */
1186 ivtvfb_blank(FB_BLANK_UNBLANK
, &itv
->osd_info
->ivtvfb_info
);
1189 ivtv_udma_alloc(itv
);
1194 static int __init
ivtvfb_callback_init(struct device
*dev
, void *p
)
1196 struct v4l2_device
*v4l2_dev
= dev_get_drvdata(dev
);
1197 struct ivtv
*itv
= container_of(v4l2_dev
, struct ivtv
, v4l2_dev
);
1199 if (itv
&& (itv
->v4l2_cap
& V4L2_CAP_VIDEO_OUTPUT
)) {
1200 if (ivtvfb_init_card(itv
) == 0) {
1201 IVTVFB_INFO("Framebuffer registered on %s\n",
1202 itv
->v4l2_dev
.name
);
1209 static int ivtvfb_callback_cleanup(struct device
*dev
, void *p
)
1211 struct v4l2_device
*v4l2_dev
= dev_get_drvdata(dev
);
1212 struct ivtv
*itv
= container_of(v4l2_dev
, struct ivtv
, v4l2_dev
);
1214 if (itv
&& (itv
->v4l2_cap
& V4L2_CAP_VIDEO_OUTPUT
)) {
1215 if (unregister_framebuffer(&itv
->osd_info
->ivtvfb_info
)) {
1216 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1220 IVTVFB_INFO("Unregister framebuffer %d\n", itv
->instance
);
1221 ivtvfb_blank(FB_BLANK_POWERDOWN
, &itv
->osd_info
->ivtvfb_info
);
1222 ivtvfb_release_buffers(itv
);
1223 itv
->osd_video_pbase
= 0;
1228 static int __init
ivtvfb_init(void)
1230 struct device_driver
*drv
;
1234 if (ivtvfb_card_id
< -1 || ivtvfb_card_id
>= IVTV_MAX_CARDS
) {
1235 printk(KERN_ERR
"ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1236 IVTV_MAX_CARDS
- 1);
1240 drv
= driver_find("ivtv", &pci_bus_type
);
1241 err
= driver_for_each_device(drv
, NULL
, ®istered
, ivtvfb_callback_init
);
1244 printk(KERN_ERR
"ivtvfb: no cards found\n");
1250 static void ivtvfb_cleanup(void)
1252 struct device_driver
*drv
;
1255 printk(KERN_INFO
"ivtvfb: Unloading framebuffer module\n");
1257 drv
= driver_find("ivtv", &pci_bus_type
);
1258 err
= driver_for_each_device(drv
, NULL
, NULL
, ivtvfb_callback_cleanup
);
1262 module_init(ivtvfb_init
);
1263 module_exit(ivtvfb_cleanup
);