[ARM] pxa: Gumstix Verdex PCMCIA support
[linux-2.6/verdex.git] / drivers / media / video / ivtv / ivtvfb.c
blobfa6bb85cb4b06ebf7626f5dd6557b9d345107bee
1 /*
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)
12 or 59.94 (NTSC)
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>
19 2.6 kernel port:
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>
43 #include <linux/fb.h>
44 #include <linux/ivtvfb.h>
46 #ifdef CONFIG_MTRR
47 #include <asm/mtrr.h>
48 #endif
50 #include "ivtv-driver.h"
51 #include "ivtv-cards.h"
52 #include "ivtv-i2c.h"
53 #include "ivtv-udma.h"
54 #include "ivtv-mailbox.h"
56 /* card parameters */
57 static int ivtvfb_card_id = -1;
58 static int ivtvfb_debug = 0;
59 static int osd_laced;
60 static int osd_depth;
61 static int osd_upper;
62 static int osd_left;
63 static int osd_yres;
64 static int osd_xres;
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
84 by fbset.
85 Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
87 MODULE_PARM_DESC(osd_laced,
88 "Interlaced mode\n"
89 "\t\t\t0=off\n"
90 "\t\t\t1=on\n"
91 "\t\t\tdefault off");
93 MODULE_PARM_DESC(osd_depth,
94 "Bits per pixel - 8, 16, 32\n"
95 "\t\t\tdefault 8");
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,
106 "Display height\n"
107 "\t\t\tdefault 480 (PAL)\n"
108 "\t\t\t 400 (NTSC)");
110 MODULE_PARM_DESC(osd_xres,
111 "Display width\n"
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...) \
123 do { \
124 if ((x) & ivtvfb_debug) \
125 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
126 } while (0)
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
146 struct osd_info {
147 /* Physical base address */
148 unsigned long video_pbase;
149 /* Relative base address (relative to start of decoder memory) */
150 u32 video_rbase;
151 /* Mapped base address */
152 volatile char __iomem *video_vbase;
153 /* Buffer size */
154 u32 video_buffer_size;
156 #ifdef CONFIG_MTRR
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;
161 #endif
163 /* Store the buffer offset */
164 int set_osd_coords_x;
165 int set_osd_coords_y;
167 /* Current dimensions (NOT VISIBLE SIZE!) */
168 int display_width;
169 int display_height;
170 int display_byte_stride;
172 /* Current bits per pixel */
173 int bits_per_pixel;
174 int bytes_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;
185 int pixel_stride;
186 int lines;
187 int x;
188 int y;
191 /* --------------------------------------------------------------------- */
193 /* ivtv API calls for framebuffer related support */
195 static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
196 u32 *fblength)
198 u32 data[CX2341X_MBOX_MAX_DATA];
199 int rc;
201 rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
202 *fbbase = data[0];
203 *fblength = data[1];
204 return rc;
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];
219 osd->x = data[3];
220 osd->y = data[4];
221 return 0;
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,
235 osd->pixel_stride,
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))
245 return -EINVAL;
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;
272 return 0;
275 static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
276 unsigned long ivtv_dest_addr, void __user *userbuf,
277 int size_in_bytes)
279 DEFINE_WAIT(wait);
280 int got_sig = 0;
282 mutex_lock(&itv->udma.lock);
283 /* Map User DMA */
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 */
291 return -EIO;
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
300 is finished */
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))
307 break;
308 got_sig = 0;
309 schedule();
311 finish_wait(&itv->dma_waitq, &wait);
313 /* Unmap Last DMA Xfer */
314 ivtv_udma_unmap(itv);
315 mutex_unlock(&itv->udma.lock);
316 if (got_sig) {
317 IVTV_DEBUG_INFO("User stopped OSD\n");
318 return -EINTR;
321 return 0;
324 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
325 unsigned long dest_offset, int count)
327 DEFINE_WAIT(wait);
328 struct osd_info *oi = itv->osd_info;
330 /* Nothing to do */
331 if (count == 0) {
332 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
333 return -EINVAL;
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);
340 return -E2BIG;
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);
348 if (dest_offset & 3)
349 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
351 if (count & 3)
352 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
354 /* Check Source */
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,
361 count);
362 return -EINVAL;
365 /* OSD Address to send DMA to */
366 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
368 /* Fill Buffers */
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;
376 void *dst;
377 int err = 0;
378 int dma_err;
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)
387 return -EPERM;
389 total_size = info->screen_size;
391 if (total_size == 0)
392 total_size = info->fix.smem_len;
394 if (p > total_size)
395 return -EFBIG;
397 if (count > total_size) {
398 err = -EFBIG;
399 count = total_size;
402 if (count + p > total_size) {
403 if (!err)
404 err = -ENOSPC;
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 */
415 if (count >= 4096 &&
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))
421 return -EFAULT;
422 buf += lead;
423 dst += lead;
425 /* DMA resolution is 32 bits */
426 if ((count - lead) & 3)
427 tail = (count - lead) & 3;
428 /* DMA the data */
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);
432 if (dma_err)
433 return dma_err;
434 dst += dma_size;
435 buf += dma_size;
436 /* Copy any leftover data */
437 if (tail && copy_from_user(dst, buf, tail))
438 return -EFAULT;
439 } else if (copy_from_user(dst, buf, count)) {
440 return -EFAULT;
443 if (!err)
444 *ppos += count;
446 return (err) ? err : count;
449 static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
451 DEFINE_WAIT(wait);
452 struct ivtv *itv = (struct ivtv *)info->par;
453 int rc = 0;
455 switch (cmd) {
456 case FBIOGET_VBLANK: {
457 struct fb_vblank vblank;
458 u32 trace;
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)
464 trace -= 312;
465 else if (itv->is_60hz && trace > 262)
466 trace -= 262;
467 if (trace == 1)
468 vblank.flags |= FB_VBLANK_VSYNCING;
469 vblank.count = itv->last_vsync_field;
470 vblank.vcount = trace;
471 vblank.hcount = 0;
472 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
473 return -EFAULT;
474 return 0;
477 case FBIO_WAITFORVSYNC:
478 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
479 if (!schedule_timeout(msecs_to_jiffies(50)))
480 rc = -ETIMEDOUT;
481 finish_wait(&itv->vsync_waitq, &wait);
482 return rc;
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)))
489 return -EFAULT;
491 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
494 default:
495 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
496 return -EINVAL;
498 return 0;
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;
508 int osd_mode = -1;
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);
515 else /* RGB */
516 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
518 /* Set the color mode */
519 switch (var->bits_per_pixel) {
520 case 8:
521 osd_mode = IVTV_OSD_BPP_8;
522 break;
523 case 32:
524 osd_mode = IVTV_OSD_BPP_32;
525 break;
526 case 16:
527 switch (var->green.length) {
528 case 4:
529 osd_mode = IVTV_OSD_BPP_16_444;
530 break;
531 case 5:
532 osd_mode = IVTV_OSD_BPP_16_555;
533 break;
534 case 6:
535 osd_mode = IVTV_OSD_BPP_16_565;
536 break;
537 default:
538 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
540 break;
541 default:
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);
559 break;
560 case FB_VMODE_INTERLACED: /* Filter off */
561 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
562 break;
563 default:
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;
573 ivtv_osd.x = 0;
574 ivtv_osd.y = 0;
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");
609 return 0;
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;
623 fix->xpanstep = 1;
624 fix->ypanstep = 1;
625 fix->ywrapstep = 0;
626 fix->line_length = oi->display_byte_stride;
627 fix->accel = FB_ACCEL_NONE;
628 return 0;
631 /* Check the requested display mode, returning -EINVAL if we can't
632 handle it. */
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. */
643 if (itv->is_50hz) {
644 pixclock = 84316;
645 hlimit = 776;
646 vlimit = 591;
647 osd_height_limit = 576;
649 else {
650 pixclock = 83926;
651 hlimit = 776;
652 vlimit = 495;
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;
660 var->red.length = 8;
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) {
669 case 4:
670 var->red.offset = 8;
671 var->red.length = 4;
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;
678 break;
679 case 5:
680 var->red.offset = 10;
681 var->red.length = 5;
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;
688 break;
689 default:
690 var->red.offset = 11;
691 var->red.length = 5;
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;
698 break;
701 else {
702 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
703 return -EINVAL;
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);
710 return -EINVAL;
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);
720 return -EINVAL;
723 /* Some extra checks if in 8 bit mode */
724 if (var->bits_per_pixel == 8) {
725 /* Width must be a multiple of 4 */
726 if (var->xres & 3) {
727 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
728 return -EINVAL;
730 if (var->xres_virtual & 3) {
731 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
732 return -EINVAL;
735 else if (var->bits_per_pixel == 16) {
736 /* Width must be a multiple of 2 */
737 if (var->xres & 1) {
738 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
739 return -EINVAL;
741 if (var->xres_virtual & 1) {
742 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
743 return -EINVAL;
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);
751 return -EINVAL;
754 /* Check pixel format */
755 if (var->nonstd > 1) {
756 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
757 return -EINVAL;
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);
764 return -EINVAL;
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 */
783 var->hsync_len = 24;
784 var->vsync_len = 2;
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;
791 else
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");
808 return 0;
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)
820 u32 osd_pan_index;
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;
831 return 0;
834 static int ivtvfb_set_par(struct fb_info *info)
836 int rc = 0;
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);
844 return rc;
847 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
848 unsigned blue, unsigned transp,
849 struct fb_info *info)
851 u32 color, *palette;
852 struct ivtv *itv = (struct ivtv *)info->par;
854 if (regno >= info->cmap.len)
855 return -EINVAL;
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);
861 return 0;
863 if (regno >= 16)
864 return -EINVAL;
866 palette = info->pseudo_palette;
867 if (info->var.bits_per_pixel == 16) {
868 switch (info->var.green.length) {
869 case 4:
870 color = ((red & 0xf000) >> 4) |
871 ((green & 0xf000) >> 8) |
872 ((blue & 0xf000) >> 12);
873 break;
874 case 5:
875 color = ((red & 0xf800) >> 1) |
876 ((green & 0xf800) >> 6) |
877 ((blue & 0xf800) >> 11);
878 break;
879 case 6:
880 color = (red & 0xf800 ) |
881 ((green & 0xfc00) >> 5) |
882 ((blue & 0xf800) >> 11);
883 break;
886 palette[regno] = color;
887 return 0;
890 /* We don't really support blanking. All this does is enable or
891 disable the OSD. */
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);
901 break;
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);
907 break;
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);
911 break;
913 return 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,
925 .fb_cursor = NULL,
926 .fb_ioctl = ivtvfb_ioctl,
927 .fb_pan_display = ivtvfb_pan_display,
928 .fb_blank = ivtvfb_blank,
931 /* Initialization */
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;
939 int max_height;
941 /* Color mode */
943 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
944 osd_depth = 8;
945 oi->bits_per_pixel = osd_depth;
946 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
948 /* Horizontal size & position */
950 if (osd_xres > 720)
951 osd_xres = 720;
953 /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
954 if (osd_depth == 8)
955 osd_xres &= ~3;
956 else if (osd_depth == 16)
957 osd_xres &= ~1;
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");
964 osd_left = 0;
967 /* Hardware coords start at 0, user coords start at 1. */
968 osd_left--;
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");
987 osd_upper = 0;
990 /* Hardware coords start at 0, user coords start at 1. */
991 osd_upper--;
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");
1039 return -ENOMEM;
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");
1048 return -ENOMEM;
1051 return 0;
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");
1064 return -ENXIO;
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);
1081 return -EIO;
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);
1088 #ifdef CONFIG_MTRR
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))) {
1094 size_shift--;
1096 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;
1109 #endif
1111 /* Blank the entire osd. */
1112 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1114 return 0;
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;
1122 /* Release cmap */
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);
1130 #ifdef CONFIG_MTRR
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);
1135 #endif
1137 kfree(oi);
1138 itv->osd_info = NULL;
1141 /* Initialize the specified card */
1143 static int ivtvfb_init_card(struct ivtv *itv)
1145 int rc;
1147 if (itv->osd_info) {
1148 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1149 return -EBUSY;
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");
1156 return -ENOMEM;
1159 /* Find & setup the OSD buffer */
1160 if ((rc = ivtvfb_init_io(itv)))
1161 return rc;
1163 /* Set the startup video mode information */
1164 if ((rc = ivtvfb_init_vidmode(itv))) {
1165 ivtvfb_release_buffers(itv);
1166 return rc;
1169 /* Register the framebuffer */
1170 if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1171 ivtvfb_release_buffers(itv);
1172 return -EINVAL;
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);
1187 /* Allocate DMA */
1188 ivtv_udma_alloc(itv);
1189 return 0;
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);
1202 (*(int *)p)++;
1205 return 0;
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",
1216 itv->instance);
1217 return 0;
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;
1224 return 0;
1227 static int __init ivtvfb_init(void)
1229 struct device_driver *drv;
1230 int registered = 0;
1231 int err;
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);
1236 return -EINVAL;
1239 drv = driver_find("ivtv", &pci_bus_type);
1240 err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1241 put_driver(drv);
1242 if (!registered) {
1243 printk(KERN_ERR "ivtvfb: no cards found\n");
1244 return -ENODEV;
1246 return 0;
1249 static void ivtvfb_cleanup(void)
1251 struct device_driver *drv;
1252 int err;
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);
1258 put_driver(drv);
1261 module_init(ivtvfb_init);
1262 module_exit(ivtvfb_cleanup);