Staging: strip: delete the driver
[linux/fpc-iii.git] / drivers / media / video / ivtv / ivtvfb.c
blobde2ff1c6ac3476453ef1c3c59732b81510b959fe
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>
45 #include <linux/slab.h>
47 #ifdef CONFIG_MTRR
48 #include <asm/mtrr.h>
49 #endif
51 #include "ivtv-driver.h"
52 #include "ivtv-cards.h"
53 #include "ivtv-i2c.h"
54 #include "ivtv-udma.h"
55 #include "ivtv-mailbox.h"
57 /* card parameters */
58 static int ivtvfb_card_id = -1;
59 static int ivtvfb_debug = 0;
60 static int osd_laced;
61 static int osd_depth;
62 static int osd_upper;
63 static int osd_left;
64 static int osd_yres;
65 static int osd_xres;
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
85 by fbset.
86 Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
88 MODULE_PARM_DESC(osd_laced,
89 "Interlaced mode\n"
90 "\t\t\t0=off\n"
91 "\t\t\t1=on\n"
92 "\t\t\tdefault off");
94 MODULE_PARM_DESC(osd_depth,
95 "Bits per pixel - 8, 16, 32\n"
96 "\t\t\tdefault 8");
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,
107 "Display height\n"
108 "\t\t\tdefault 480 (PAL)\n"
109 "\t\t\t 400 (NTSC)");
111 MODULE_PARM_DESC(osd_xres,
112 "Display width\n"
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...) \
124 do { \
125 if ((x) & ivtvfb_debug) \
126 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
127 } while (0)
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
147 struct osd_info {
148 /* Physical base address */
149 unsigned long video_pbase;
150 /* Relative base address (relative to start of decoder memory) */
151 u32 video_rbase;
152 /* Mapped base address */
153 volatile char __iomem *video_vbase;
154 /* Buffer size */
155 u32 video_buffer_size;
157 #ifdef CONFIG_MTRR
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;
162 #endif
164 /* Store the buffer offset */
165 int set_osd_coords_x;
166 int set_osd_coords_y;
168 /* Current dimensions (NOT VISIBLE SIZE!) */
169 int display_width;
170 int display_height;
171 int display_byte_stride;
173 /* Current bits per pixel */
174 int bits_per_pixel;
175 int bytes_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;
186 int pixel_stride;
187 int lines;
188 int x;
189 int y;
192 /* --------------------------------------------------------------------- */
194 /* ivtv API calls for framebuffer related support */
196 static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
197 u32 *fblength)
199 u32 data[CX2341X_MBOX_MAX_DATA];
200 int rc;
202 rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
203 *fbbase = data[0];
204 *fblength = data[1];
205 return rc;
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];
220 osd->x = data[3];
221 osd->y = data[4];
222 return 0;
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,
236 osd->pixel_stride,
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))
246 return -EINVAL;
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;
273 return 0;
276 static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
277 unsigned long ivtv_dest_addr, void __user *userbuf,
278 int size_in_bytes)
280 DEFINE_WAIT(wait);
281 int got_sig = 0;
283 mutex_lock(&itv->udma.lock);
284 /* Map User DMA */
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 */
292 return -EIO;
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
301 is finished */
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))
308 break;
309 got_sig = 0;
310 schedule();
312 finish_wait(&itv->dma_waitq, &wait);
314 /* Unmap Last DMA Xfer */
315 ivtv_udma_unmap(itv);
316 mutex_unlock(&itv->udma.lock);
317 if (got_sig) {
318 IVTV_DEBUG_INFO("User stopped OSD\n");
319 return -EINTR;
322 return 0;
325 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
326 unsigned long dest_offset, int count)
328 DEFINE_WAIT(wait);
329 struct osd_info *oi = itv->osd_info;
331 /* Nothing to do */
332 if (count == 0) {
333 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
334 return -EINVAL;
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);
341 return -E2BIG;
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);
349 if (dest_offset & 3)
350 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
352 if (count & 3)
353 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
355 /* Check Source */
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,
362 count);
363 return -EINVAL;
366 /* OSD Address to send DMA to */
367 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
369 /* Fill Buffers */
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;
377 void *dst;
378 int err = 0;
379 int dma_err;
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)
388 return -EPERM;
390 total_size = info->screen_size;
392 if (total_size == 0)
393 total_size = info->fix.smem_len;
395 if (p > total_size)
396 return -EFBIG;
398 if (count > total_size) {
399 err = -EFBIG;
400 count = total_size;
403 if (count + p > total_size) {
404 if (!err)
405 err = -ENOSPC;
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 */
416 if (count >= 4096 &&
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))
422 return -EFAULT;
423 buf += lead;
424 dst += lead;
426 /* DMA resolution is 32 bits */
427 if ((count - lead) & 3)
428 tail = (count - lead) & 3;
429 /* DMA the data */
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);
433 if (dma_err)
434 return dma_err;
435 dst += dma_size;
436 buf += dma_size;
437 /* Copy any leftover data */
438 if (tail && copy_from_user(dst, buf, tail))
439 return -EFAULT;
440 } else if (copy_from_user(dst, buf, count)) {
441 return -EFAULT;
444 if (!err)
445 *ppos += count;
447 return (err) ? err : count;
450 static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
452 DEFINE_WAIT(wait);
453 struct ivtv *itv = (struct ivtv *)info->par;
454 int rc = 0;
456 switch (cmd) {
457 case FBIOGET_VBLANK: {
458 struct fb_vblank vblank;
459 u32 trace;
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)
465 trace -= 312;
466 else if (itv->is_60hz && trace > 262)
467 trace -= 262;
468 if (trace == 1)
469 vblank.flags |= FB_VBLANK_VSYNCING;
470 vblank.count = itv->last_vsync_field;
471 vblank.vcount = trace;
472 vblank.hcount = 0;
473 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
474 return -EFAULT;
475 return 0;
478 case FBIO_WAITFORVSYNC:
479 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
480 if (!schedule_timeout(msecs_to_jiffies(50)))
481 rc = -ETIMEDOUT;
482 finish_wait(&itv->vsync_waitq, &wait);
483 return rc;
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)))
490 return -EFAULT;
492 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
495 default:
496 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
497 return -EINVAL;
499 return 0;
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;
509 int osd_mode = -1;
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);
516 else /* RGB */
517 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
519 /* Set the color mode */
520 switch (var->bits_per_pixel) {
521 case 8:
522 osd_mode = IVTV_OSD_BPP_8;
523 break;
524 case 32:
525 osd_mode = IVTV_OSD_BPP_32;
526 break;
527 case 16:
528 switch (var->green.length) {
529 case 4:
530 osd_mode = IVTV_OSD_BPP_16_444;
531 break;
532 case 5:
533 osd_mode = IVTV_OSD_BPP_16_555;
534 break;
535 case 6:
536 osd_mode = IVTV_OSD_BPP_16_565;
537 break;
538 default:
539 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
541 break;
542 default:
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);
560 break;
561 case FB_VMODE_INTERLACED: /* Filter off */
562 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
563 break;
564 default:
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;
574 ivtv_osd.x = 0;
575 ivtv_osd.y = 0;
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");
610 return 0;
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;
624 fix->xpanstep = 1;
625 fix->ypanstep = 1;
626 fix->ywrapstep = 0;
627 fix->line_length = oi->display_byte_stride;
628 fix->accel = FB_ACCEL_NONE;
629 return 0;
632 /* Check the requested display mode, returning -EINVAL if we can't
633 handle it. */
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. */
644 if (itv->is_50hz) {
645 pixclock = 84316;
646 hlimit = 776;
647 vlimit = 591;
648 osd_height_limit = 576;
650 else {
651 pixclock = 83926;
652 hlimit = 776;
653 vlimit = 495;
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;
661 var->red.length = 8;
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) {
670 case 4:
671 var->red.offset = 8;
672 var->red.length = 4;
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;
679 break;
680 case 5:
681 var->red.offset = 10;
682 var->red.length = 5;
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;
689 break;
690 default:
691 var->red.offset = 11;
692 var->red.length = 5;
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;
699 break;
702 else {
703 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
704 return -EINVAL;
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);
711 return -EINVAL;
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);
721 return -EINVAL;
724 /* Some extra checks if in 8 bit mode */
725 if (var->bits_per_pixel == 8) {
726 /* Width must be a multiple of 4 */
727 if (var->xres & 3) {
728 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
729 return -EINVAL;
731 if (var->xres_virtual & 3) {
732 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
733 return -EINVAL;
736 else if (var->bits_per_pixel == 16) {
737 /* Width must be a multiple of 2 */
738 if (var->xres & 1) {
739 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
740 return -EINVAL;
742 if (var->xres_virtual & 1) {
743 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
744 return -EINVAL;
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);
752 return -EINVAL;
755 /* Check pixel format */
756 if (var->nonstd > 1) {
757 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
758 return -EINVAL;
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);
765 return -EINVAL;
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 */
784 var->hsync_len = 24;
785 var->vsync_len = 2;
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;
792 else
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");
809 return 0;
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)
821 u32 osd_pan_index;
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;
832 return 0;
835 static int ivtvfb_set_par(struct fb_info *info)
837 int rc = 0;
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);
845 return rc;
848 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
849 unsigned blue, unsigned transp,
850 struct fb_info *info)
852 u32 color, *palette;
853 struct ivtv *itv = (struct ivtv *)info->par;
855 if (regno >= info->cmap.len)
856 return -EINVAL;
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);
862 return 0;
864 if (regno >= 16)
865 return -EINVAL;
867 palette = info->pseudo_palette;
868 if (info->var.bits_per_pixel == 16) {
869 switch (info->var.green.length) {
870 case 4:
871 color = ((red & 0xf000) >> 4) |
872 ((green & 0xf000) >> 8) |
873 ((blue & 0xf000) >> 12);
874 break;
875 case 5:
876 color = ((red & 0xf800) >> 1) |
877 ((green & 0xf800) >> 6) |
878 ((blue & 0xf800) >> 11);
879 break;
880 case 6:
881 color = (red & 0xf800 ) |
882 ((green & 0xfc00) >> 5) |
883 ((blue & 0xf800) >> 11);
884 break;
887 palette[regno] = color;
888 return 0;
891 /* We don't really support blanking. All this does is enable or
892 disable the OSD. */
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);
902 break;
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);
908 break;
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);
912 break;
914 return 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,
926 .fb_cursor = NULL,
927 .fb_ioctl = ivtvfb_ioctl,
928 .fb_pan_display = ivtvfb_pan_display,
929 .fb_blank = ivtvfb_blank,
932 /* Initialization */
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;
940 int max_height;
942 /* Color mode */
944 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
945 osd_depth = 8;
946 oi->bits_per_pixel = osd_depth;
947 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
949 /* Horizontal size & position */
951 if (osd_xres > 720)
952 osd_xres = 720;
954 /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
955 if (osd_depth == 8)
956 osd_xres &= ~3;
957 else if (osd_depth == 16)
958 osd_xres &= ~1;
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");
965 osd_left = 0;
968 /* Hardware coords start at 0, user coords start at 1. */
969 osd_left--;
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");
988 osd_upper = 0;
991 /* Hardware coords start at 0, user coords start at 1. */
992 osd_upper--;
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");
1040 return -ENOMEM;
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");
1049 return -ENOMEM;
1052 return 0;
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");
1065 return -ENXIO;
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);
1082 return -EIO;
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);
1089 #ifdef CONFIG_MTRR
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))) {
1095 size_shift--;
1097 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;
1110 #endif
1112 /* Blank the entire osd. */
1113 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1115 return 0;
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;
1123 /* Release cmap */
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);
1131 #ifdef CONFIG_MTRR
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);
1136 #endif
1138 kfree(oi);
1139 itv->osd_info = NULL;
1142 /* Initialize the specified card */
1144 static int ivtvfb_init_card(struct ivtv *itv)
1146 int rc;
1148 if (itv->osd_info) {
1149 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1150 return -EBUSY;
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");
1157 return -ENOMEM;
1160 /* Find & setup the OSD buffer */
1161 if ((rc = ivtvfb_init_io(itv)))
1162 return rc;
1164 /* Set the startup video mode information */
1165 if ((rc = ivtvfb_init_vidmode(itv))) {
1166 ivtvfb_release_buffers(itv);
1167 return rc;
1170 /* Register the framebuffer */
1171 if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1172 ivtvfb_release_buffers(itv);
1173 return -EINVAL;
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);
1188 /* Allocate DMA */
1189 ivtv_udma_alloc(itv);
1190 return 0;
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);
1203 (*(int *)p)++;
1206 return 0;
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",
1217 itv->instance);
1218 return 0;
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;
1225 return 0;
1228 static int __init ivtvfb_init(void)
1230 struct device_driver *drv;
1231 int registered = 0;
1232 int err;
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);
1237 return -EINVAL;
1240 drv = driver_find("ivtv", &pci_bus_type);
1241 err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1242 put_driver(drv);
1243 if (!registered) {
1244 printk(KERN_ERR "ivtvfb: no cards found\n");
1245 return -ENODEV;
1247 return 0;
1250 static void ivtvfb_cleanup(void)
1252 struct device_driver *drv;
1253 int err;
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);
1259 put_driver(drv);
1262 module_init(ivtvfb_init);
1263 module_exit(ivtvfb_cleanup);