V4L/DVB (8103): videodev: fix/improve ioctl debugging
[pandora-kernel.git] / drivers / media / video / ivtv / ivtvfb.c
1 /*
2     On Screen Display cx23415 Framebuffer driver
3
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)
13
14     Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
15
16     Derived from drivers/video/vesafb.c
17     Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
18
19     2.6 kernel port:
20     Copyright (C) 2004 Matthias Badaire
21
22     Copyright (C) 2004  Chris Kennedy <c@groovy.org>
23
24     Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
25
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.
30
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.
35
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
39  */
40
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/fb.h>
44 #include <linux/ivtvfb.h>
45
46 #ifdef CONFIG_MTRR
47 #include <asm/mtrr.h>
48 #endif
49
50 #include "ivtv-driver.h"
51 #include "ivtv-udma.h"
52 #include "ivtv-mailbox.h"
53
54 /* card parameters */
55 static int ivtvfb_card_id = -1;
56 static int ivtvfb_debug = 0;
57 static int osd_laced;
58 static int osd_depth;
59 static int osd_upper;
60 static int osd_left;
61 static int osd_yres;
62 static int osd_xres;
63
64 module_param(ivtvfb_card_id, int, 0444);
65 module_param_named(debug,ivtvfb_debug, int, 0644);
66 module_param(osd_laced, bool, 0444);
67 module_param(osd_depth, int, 0444);
68 module_param(osd_upper, int, 0444);
69 module_param(osd_left, int, 0444);
70 module_param(osd_yres, int, 0444);
71 module_param(osd_xres, int, 0444);
72
73 MODULE_PARM_DESC(ivtvfb_card_id,
74                  "Only use framebuffer of the specified ivtv card (0-31)\n"
75                  "\t\t\tdefault -1: initialize all available framebuffers");
76
77 MODULE_PARM_DESC(debug,
78                  "Debug level (bitmask). Default: errors only\n"
79                  "\t\t\t(debug = 3 gives full debugging)");
80
81 /* Why upper, left, xres, yres, depth, laced ? To match terminology used
82    by fbset.
83    Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
84
85 MODULE_PARM_DESC(osd_laced,
86                  "Interlaced mode\n"
87                  "\t\t\t0=off\n"
88                  "\t\t\t1=on\n"
89                  "\t\t\tdefault off");
90
91 MODULE_PARM_DESC(osd_depth,
92                  "Bits per pixel - 8, 16, 32\n"
93                  "\t\t\tdefault 8");
94
95 MODULE_PARM_DESC(osd_upper,
96                  "Vertical start position\n"
97                  "\t\t\tdefault 0 (Centered)");
98
99 MODULE_PARM_DESC(osd_left,
100                  "Horizontal start position\n"
101                  "\t\t\tdefault 0 (Centered)");
102
103 MODULE_PARM_DESC(osd_yres,
104                  "Display height\n"
105                  "\t\t\tdefault 480 (PAL)\n"
106                  "\t\t\t        400 (NTSC)");
107
108 MODULE_PARM_DESC(osd_xres,
109                  "Display width\n"
110                  "\t\t\tdefault 640");
111
112 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
113 MODULE_LICENSE("GPL");
114
115 /* --------------------------------------------------------------------- */
116
117 #define IVTVFB_DBGFLG_WARN  (1 << 0)
118 #define IVTVFB_DBGFLG_INFO  (1 << 1)
119
120 #define IVTVFB_DEBUG(x, type, fmt, args...) \
121         do { \
122                 if ((x) & ivtvfb_debug) \
123                         printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \
124         } while (0)
125 #define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
126 #define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
127
128 /* Standard kernel messages */
129 #define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->num , ## args)
130 #define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->num , ## args)
131 #define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args)
132
133 /* --------------------------------------------------------------------- */
134
135 #define IVTV_OSD_MAX_WIDTH  720
136 #define IVTV_OSD_MAX_HEIGHT 576
137
138 #define IVTV_OSD_BPP_8      0x00
139 #define IVTV_OSD_BPP_16_444 0x03
140 #define IVTV_OSD_BPP_16_555 0x02
141 #define IVTV_OSD_BPP_16_565 0x01
142 #define IVTV_OSD_BPP_32     0x04
143
144 struct osd_info {
145         /* Physical base address */
146         unsigned long video_pbase;
147         /* Relative base address (relative to start of decoder memory) */
148         u32 video_rbase;
149         /* Mapped base address */
150         volatile char __iomem *video_vbase;
151         /* Buffer size */
152         u32 video_buffer_size;
153
154 #ifdef CONFIG_MTRR
155         /* video_base rounded down as required by hardware MTRRs */
156         unsigned long fb_start_aligned_physaddr;
157         /* video_base rounded up as required by hardware MTRRs */
158         unsigned long fb_end_aligned_physaddr;
159 #endif
160
161         /* Store the buffer offset */
162         int set_osd_coords_x;
163         int set_osd_coords_y;
164
165         /* Current dimensions (NOT VISIBLE SIZE!) */
166         int display_width;
167         int display_height;
168         int display_byte_stride;
169
170         /* Current bits per pixel */
171         int bits_per_pixel;
172         int bytes_per_pixel;
173
174         /* Frame buffer stuff */
175         struct fb_info ivtvfb_info;
176         struct fb_var_screeninfo ivtvfb_defined;
177         struct fb_fix_screeninfo ivtvfb_fix;
178 };
179
180 struct ivtv_osd_coords {
181         unsigned long offset;
182         unsigned long max_offset;
183         int pixel_stride;
184         int lines;
185         int x;
186         int y;
187 };
188
189 /* --------------------------------------------------------------------- */
190
191 /* ivtv API calls for framebuffer related support */
192
193 static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
194                                        u32 *fblength)
195 {
196         u32 data[CX2341X_MBOX_MAX_DATA];
197         int rc;
198
199         rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
200         *fbbase = data[0];
201         *fblength = data[1];
202         return rc;
203 }
204
205 static int ivtvfb_get_osd_coords(struct ivtv *itv,
206                                       struct ivtv_osd_coords *osd)
207 {
208         struct osd_info *oi = itv->osd_info;
209         u32 data[CX2341X_MBOX_MAX_DATA];
210
211         ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
212
213         osd->offset = data[0] - oi->video_rbase;
214         osd->max_offset = oi->display_width * oi->display_height * 4;
215         osd->pixel_stride = data[1];
216         osd->lines = data[2];
217         osd->x = data[3];
218         osd->y = data[4];
219         return 0;
220 }
221
222 static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
223 {
224         struct osd_info *oi = itv->osd_info;
225
226         oi->display_width = osd->pixel_stride;
227         oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
228         oi->set_osd_coords_x += osd->x;
229         oi->set_osd_coords_y = osd->y;
230
231         return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
232                         osd->offset + oi->video_rbase,
233                         osd->pixel_stride,
234                         osd->lines, osd->x, osd->y);
235 }
236
237 static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
238 {
239         int osd_height_limit = itv->is_50hz ? 576 : 480;
240
241         /* Only fail if resolution too high, otherwise fudge the start coords. */
242         if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
243                 return -EINVAL;
244
245         /* Ensure we don't exceed display limits */
246         if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
247                 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
248                         ivtv_window->top, ivtv_window->height);
249                 ivtv_window->top = osd_height_limit - ivtv_window->height;
250         }
251
252         if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
253                 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
254                         ivtv_window->left, ivtv_window->width);
255                 ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
256         }
257
258         /* Set the OSD origin */
259         write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
260
261         /* How much to display */
262         write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
263
264         /* Pass this info back the yuv handler */
265         itv->yuv_info.osd_vis_w = ivtv_window->width;
266         itv->yuv_info.osd_vis_h = ivtv_window->height;
267         itv->yuv_info.osd_x_offset = ivtv_window->left;
268         itv->yuv_info.osd_y_offset = ivtv_window->top;
269
270         return 0;
271 }
272
273 static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
274                                   unsigned long ivtv_dest_addr, void __user *userbuf,
275                                   int size_in_bytes)
276 {
277         DEFINE_WAIT(wait);
278         int ret = 0;
279         int got_sig = 0;
280
281         mutex_lock(&itv->udma.lock);
282         /* Map User DMA */
283         if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
284                 mutex_unlock(&itv->udma.lock);
285                 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
286                                "Error with get_user_pages: %d bytes, %d pages returned\n",
287                                size_in_bytes, itv->udma.page_count);
288
289                 /* get_user_pages must have failed completely */
290                 return -EIO;
291         }
292
293         IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
294                        size_in_bytes, itv->udma.page_count);
295
296         ivtv_udma_prepare(itv);
297         prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
298         /* if no UDMA is pending and no UDMA is in progress, then the DMA
299            is finished */
300         while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
301                 /* don't interrupt if the DMA is in progress but break off
302                    a still pending DMA. */
303                 got_sig = signal_pending(current);
304                 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
305                         break;
306                 got_sig = 0;
307                 schedule();
308         }
309         finish_wait(&itv->dma_waitq, &wait);
310
311         /* Unmap Last DMA Xfer */
312         ivtv_udma_unmap(itv);
313         mutex_unlock(&itv->udma.lock);
314         if (got_sig) {
315                 IVTV_DEBUG_INFO("User stopped OSD\n");
316                 return -EINTR;
317         }
318
319         return ret;
320 }
321
322 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
323                               unsigned long dest_offset, int count)
324 {
325         DEFINE_WAIT(wait);
326         struct osd_info *oi = itv->osd_info;
327
328         /* Nothing to do */
329         if (count == 0) {
330                 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
331                 return -EINVAL;
332         }
333
334         /* Check Total FB Size */
335         if ((dest_offset + count) > oi->video_buffer_size) {
336                 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
337                         dest_offset + count, oi->video_buffer_size);
338                 return -E2BIG;
339         }
340
341         /* Not fatal, but will have undesirable results */
342         if ((unsigned long)source & 3)
343                 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
344                         (unsigned long)source);
345
346         if (dest_offset & 3)
347                 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
348
349         if (count & 3)
350                 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
351
352         /* Check Source */
353         if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
354                 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
355                         (unsigned long)source);
356
357                 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
358                         dest_offset, (unsigned long)source,
359                         count);
360                 return -EINVAL;
361         }
362
363         /* OSD Address to send DMA to */
364         dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
365
366         /* Fill Buffers */
367         return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
368 }
369
370 static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
371                      size_t count, loff_t *ppos)
372 {
373         unsigned long p = *ppos;
374         void *dst;
375         int err = 0;
376         unsigned long total_size;
377         struct ivtv *itv = (struct ivtv *) info->par;
378         unsigned long dma_offset =
379                         IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
380         unsigned long dma_size;
381         u16 lead = 0, tail = 0;
382
383         if (info->state != FBINFO_STATE_RUNNING)
384                 return -EPERM;
385
386         total_size = info->screen_size;
387
388         if (total_size == 0)
389                 total_size = info->fix.smem_len;
390
391         if (p > total_size)
392                 return -EFBIG;
393
394         if (count > total_size) {
395                 err = -EFBIG;
396                 count = total_size;
397         }
398
399         if (count + p > total_size) {
400                 if (!err)
401                         err = -ENOSPC;
402
403                 count = total_size - p;
404         }
405
406         dst = (void __force *) (info->screen_base + p);
407
408         if (info->fbops->fb_sync)
409                 info->fbops->fb_sync(info);
410
411         if (!access_ok(VERIFY_READ, buf, count)) {
412                 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
413                         (unsigned long)buf);
414                 err = -EFAULT;
415         }
416
417         if (!err) {
418                 /* If transfer size > threshold and both src/dst
419                 addresses are aligned, use DMA */
420                 if (count >= 4096 && ((u32)buf & 3) == ((u32)dst & 3)) {
421                         /* Odd address = can't DMA. Align */
422                         if ((u32)dst & 3) {
423                                 lead = 4 - ((u32)dst & 3);
424                                 memcpy(dst, buf, lead);
425                                 buf += lead;
426                                 dst += lead;
427                         }
428                         /* DMA resolution is 32 bits */
429                         if ((count - lead) & 3)
430                                 tail = (count - lead) & 3;
431                         /* DMA the data */
432                         dma_size = count - lead - tail;
433                         err = ivtvfb_prep_dec_dma_to_device(itv,
434                                p + lead + dma_offset, (void *)buf, dma_size);
435                         dst += dma_size;
436                         buf += dma_size;
437                         /* Copy any leftover data */
438                         if (tail)
439                                 memcpy(dst, buf, tail);
440                 } else {
441                         memcpy(dst, buf, count);
442                 }
443         }
444
445         if  (!err)
446                 *ppos += count;
447
448         return (err) ? err : count;
449 }
450
451 static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
452 {
453         DEFINE_WAIT(wait);
454         struct ivtv *itv = (struct ivtv *)info->par;
455         int rc = 0;
456
457         switch (cmd) {
458                 case FBIOGET_VBLANK: {
459                         struct fb_vblank vblank;
460                         u32 trace;
461
462                         vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
463                                         FB_VBLANK_HAVE_VSYNC;
464                         trace = read_reg(0x028c0) >> 16;
465                         if (itv->is_50hz && trace > 312) trace -= 312;
466                         else if (itv->is_60hz && trace > 262) trace -= 262;
467                         if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
468                         vblank.count = itv->last_vsync_field;
469                         vblank.vcount = trace;
470                         vblank.hcount = 0;
471                         if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
472                                 return -EFAULT;
473                         return 0;
474                 }
475
476                 case FBIO_WAITFORVSYNC:
477                         prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
478                         if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
479                         finish_wait(&itv->vsync_waitq, &wait);
480                         return rc;
481
482                 case IVTVFB_IOC_DMA_FRAME: {
483                         struct ivtvfb_dma_frame args;
484
485                         IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
486                         if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
487                                 return -EFAULT;
488
489                         return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
490                 }
491
492                 default:
493                         IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
494                         return -EINVAL;
495         }
496         return 0;
497 }
498
499 /* Framebuffer device handling */
500
501 static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
502 {
503         struct osd_info *oi = itv->osd_info;
504         struct ivtv_osd_coords ivtv_osd;
505         struct v4l2_rect ivtv_window;
506         int osd_mode = -1;
507
508         IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
509
510         /* Select color space */
511         if (var->nonstd) /* YUV */
512                 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
513         else /* RGB  */
514                 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
515
516         /* Set the color mode */
517         switch (var->bits_per_pixel) {
518                 case 8:
519                         osd_mode = IVTV_OSD_BPP_8;
520                         break;
521                 case 32:
522                         osd_mode = IVTV_OSD_BPP_32;
523                         break;
524                 case 16:
525                         switch (var->green.length) {
526                         case 4:
527                                 osd_mode = IVTV_OSD_BPP_16_444;
528                                 break;
529                         case 5:
530                                 osd_mode = IVTV_OSD_BPP_16_555;
531                                 break;
532                         case 6:
533                                 osd_mode = IVTV_OSD_BPP_16_565;
534                                 break;
535                         default:
536                                 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
537                         }
538                         break;
539                 default:
540                         IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
541         }
542
543         /* Set video mode. Although rare, the display can become scrambled even
544            if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
545         if (osd_mode != -1) {
546                 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
547                 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
548         }
549
550         oi->bits_per_pixel = var->bits_per_pixel;
551         oi->bytes_per_pixel = var->bits_per_pixel / 8;
552
553         /* Set the flicker filter */
554         switch (var->vmode & FB_VMODE_MASK) {
555                 case FB_VMODE_NONINTERLACED: /* Filter on */
556                         ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
557                         break;
558                 case FB_VMODE_INTERLACED: /* Filter off */
559                         ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
560                         break;
561                 default:
562                         IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
563         }
564
565         /* Read the current osd info */
566         ivtvfb_get_osd_coords(itv, &ivtv_osd);
567
568         /* Now set the OSD to the size we want */
569         ivtv_osd.pixel_stride = var->xres_virtual;
570         ivtv_osd.lines = var->yres_virtual;
571         ivtv_osd.x = 0;
572         ivtv_osd.y = 0;
573         ivtvfb_set_osd_coords(itv, &ivtv_osd);
574
575         /* Can't seem to find the right API combo for this.
576            Use another function which does what we need through direct register access. */
577         ivtv_window.width = var->xres;
578         ivtv_window.height = var->yres;
579
580         /* Minimum margin cannot be 0, as X won't allow such a mode */
581         if (!var->upper_margin) var->upper_margin++;
582         if (!var->left_margin) var->left_margin++;
583         ivtv_window.top = var->upper_margin - 1;
584         ivtv_window.left = var->left_margin - 1;
585
586         ivtvfb_set_display_window(itv, &ivtv_window);
587
588         /* Pass screen size back to yuv handler */
589         itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
590         itv->yuv_info.osd_full_h = ivtv_osd.lines;
591
592         /* Force update of yuv registers */
593         itv->yuv_info.yuv_forced_update = 1;
594
595         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
596                       var->xres, var->yres,
597                       var->xres_virtual, var->yres_virtual,
598                       var->bits_per_pixel);
599
600         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
601                       var->left_margin, var->upper_margin);
602
603         IVTVFB_DEBUG_INFO("Display filter: %s\n",
604                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
605         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
606
607         return 0;
608 }
609
610 static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
611 {
612         struct osd_info *oi = itv->osd_info;
613
614         IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
615         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
616         strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
617         fix->smem_start = oi->video_pbase;
618         fix->smem_len = oi->video_buffer_size;
619         fix->type = FB_TYPE_PACKED_PIXELS;
620         fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
621         fix->xpanstep = 1;
622         fix->ypanstep = 1;
623         fix->ywrapstep = 0;
624         fix->line_length = oi->display_byte_stride;
625         fix->accel = FB_ACCEL_NONE;
626         return 0;
627 }
628
629 /* Check the requested display mode, returning -EINVAL if we can't
630    handle it. */
631
632 static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
633 {
634         struct osd_info *oi = itv->osd_info;
635         int osd_height_limit;
636         u32 pixclock, hlimit, vlimit;
637
638         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
639
640         /* Set base references for mode calcs. */
641         if (itv->is_50hz) {
642                 pixclock = 84316;
643                 hlimit = 776;
644                 vlimit = 591;
645                 osd_height_limit = 576;
646         }
647         else {
648                 pixclock = 83926;
649                 hlimit = 776;
650                 vlimit = 495;
651                 osd_height_limit = 480;
652         }
653
654         if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
655                 var->transp.offset = 24;
656                 var->transp.length = 8;
657                 var->red.offset = 16;
658                 var->red.length = 8;
659                 var->green.offset = 8;
660                 var->green.length = 8;
661                 var->blue.offset = 0;
662                 var->blue.length = 8;
663         }
664         else if (var->bits_per_pixel == 16) {
665                 /* To find out the true mode, check green length */
666                 switch (var->green.length) {
667                         case 4:
668                                 var->red.offset = 8;
669                                 var->red.length = 4;
670                                 var->green.offset = 4;
671                                 var->green.length = 4;
672                                 var->blue.offset = 0;
673                                 var->blue.length = 4;
674                                 var->transp.offset = 12;
675                                 var->transp.length = 1;
676                                 break;
677                         case 5:
678                                 var->red.offset = 10;
679                                 var->red.length = 5;
680                                 var->green.offset = 5;
681                                 var->green.length = 5;
682                                 var->blue.offset = 0;
683                                 var->blue.length = 5;
684                                 var->transp.offset = 15;
685                                 var->transp.length = 1;
686                                 break;
687                         default:
688                                 var->red.offset = 11;
689                                 var->red.length = 5;
690                                 var->green.offset = 5;
691                                 var->green.length = 6;
692                                 var->blue.offset = 0;
693                                 var->blue.length = 5;
694                                 var->transp.offset = 0;
695                                 var->transp.length = 0;
696                                 break;
697                 }
698         }
699         else {
700                 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
701                 return -EINVAL;
702         }
703
704         /* Check the resolution */
705         if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
706                 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
707                                 var->xres, var->yres);
708                 return -EINVAL;
709         }
710
711         /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
712         if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
713             var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
714             var->xres_virtual < var->xres ||
715             var->yres_virtual < var->yres) {
716                 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
717                         var->xres_virtual, var->yres_virtual);
718                 return -EINVAL;
719         }
720
721         /* Some extra checks if in 8 bit mode */
722         if (var->bits_per_pixel == 8) {
723                 /* Width must be a multiple of 4 */
724                 if (var->xres & 3) {
725                         IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
726                         return -EINVAL;
727                 }
728                 if (var->xres_virtual & 3) {
729                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
730                         return -EINVAL;
731                 }
732         }
733         else if (var->bits_per_pixel == 16) {
734                 /* Width must be a multiple of 2 */
735                 if (var->xres & 1) {
736                         IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
737                         return -EINVAL;
738                 }
739                 if (var->xres_virtual & 1) {
740                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
741                         return -EINVAL;
742                 }
743         }
744
745         /* Now check the offsets */
746         if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
747                 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
748                         var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
749                 return -EINVAL;
750         }
751
752         /* Check pixel format */
753         if (var->nonstd > 1) {
754                 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
755                 return -EINVAL;
756         }
757
758         /* Check video mode */
759         if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
760                 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
761                 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
762                 return -EINVAL;
763         }
764
765         /* Check the left & upper margins
766            If the margins are too large, just center the screen
767            (enforcing margins causes too many problems) */
768
769         if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) {
770                 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
771         }
772         if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) {
773                 var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2);
774         }
775
776         /* Maintain overall 'size' for a constant refresh rate */
777         var->right_margin = hlimit - var->left_margin - var->xres;
778         var->lower_margin = vlimit - var->upper_margin - var->yres;
779
780         /* Fixed sync times */
781         var->hsync_len = 24;
782         var->vsync_len = 2;
783
784         /* Non-interlaced / interlaced mode is used to switch the OSD filter
785            on or off. Adjust the clock timings to maintain a constant
786            vertical refresh rate. */
787         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
788                 var->pixclock = pixclock / 2;
789         else
790                 var->pixclock = pixclock;
791
792         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
793                       var->xres, var->yres,
794                       var->xres_virtual, var->yres_virtual,
795                       var->bits_per_pixel);
796
797         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
798                       var->left_margin, var->upper_margin);
799
800         IVTVFB_DEBUG_INFO("Display filter: %s\n",
801                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
802         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
803         return 0;
804 }
805
806 static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
807 {
808         struct ivtv *itv = (struct ivtv *) info->par;
809         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
810         return _ivtvfb_check_var(var, itv);
811 }
812
813 static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
814 {
815         u32 osd_pan_index;
816         struct ivtv *itv = (struct ivtv *) info->par;
817
818         osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8;
819         write_reg(osd_pan_index, 0x02A0C);
820
821         /* Pass this info back the yuv handler */
822         itv->yuv_info.osd_x_pan = var->xoffset;
823         itv->yuv_info.osd_y_pan = var->yoffset;
824         /* Force update of yuv registers */
825         itv->yuv_info.yuv_forced_update = 1;
826         return 0;
827 }
828
829 static int ivtvfb_set_par(struct fb_info *info)
830 {
831         int rc = 0;
832         struct ivtv *itv = (struct ivtv *) info->par;
833
834         IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
835
836         rc = ivtvfb_set_var(itv, &info->var);
837         ivtvfb_pan_display(&info->var, info);
838         ivtvfb_get_fix(itv, &info->fix);
839         return rc;
840 }
841
842 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
843                                 unsigned blue, unsigned transp,
844                                 struct fb_info *info)
845 {
846         u32 color, *palette;
847         struct ivtv *itv = (struct ivtv *)info->par;
848
849         if (regno >= info->cmap.len)
850                 return -EINVAL;
851
852         color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
853         if (info->var.bits_per_pixel <= 8) {
854                 write_reg(regno, 0x02a30);
855                 write_reg(color, 0x02a34);
856                 return 0;
857         }
858         if (regno >= 16)
859                 return -EINVAL;
860
861         palette = info->pseudo_palette;
862         if (info->var.bits_per_pixel == 16) {
863                 switch (info->var.green.length) {
864                         case 4:
865                                 color = ((red & 0xf000) >> 4) |
866                                         ((green & 0xf000) >> 8) |
867                                         ((blue & 0xf000) >> 12);
868                                 break;
869                         case 5:
870                                 color = ((red & 0xf800) >> 1) |
871                                         ((green & 0xf800) >> 6) |
872                                         ((blue & 0xf800) >> 11);
873                                 break;
874                         case 6:
875                                 color = (red & 0xf800 ) |
876                                         ((green & 0xfc00) >> 5) |
877                                         ((blue & 0xf800) >> 11);
878                                 break;
879                 }
880         }
881         palette[regno] = color;
882         return 0;
883 }
884
885 /* We don't really support blanking. All this does is enable or
886    disable the OSD. */
887 static int ivtvfb_blank(int blank_mode, struct fb_info *info)
888 {
889         struct ivtv *itv = (struct ivtv *)info->par;
890
891         IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
892         switch (blank_mode) {
893         case FB_BLANK_UNBLANK:
894                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
895                 break;
896         case FB_BLANK_NORMAL:
897         case FB_BLANK_HSYNC_SUSPEND:
898         case FB_BLANK_VSYNC_SUSPEND:
899         case FB_BLANK_POWERDOWN:
900                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
901                 break;
902         }
903         return 0;
904 }
905
906 static struct fb_ops ivtvfb_ops = {
907         .owner = THIS_MODULE,
908         .fb_write       = ivtvfb_write,
909         .fb_check_var   = ivtvfb_check_var,
910         .fb_set_par     = ivtvfb_set_par,
911         .fb_setcolreg   = ivtvfb_setcolreg,
912         .fb_fillrect    = cfb_fillrect,
913         .fb_copyarea    = cfb_copyarea,
914         .fb_imageblit   = cfb_imageblit,
915         .fb_cursor      = NULL,
916         .fb_ioctl       = ivtvfb_ioctl,
917         .fb_pan_display = ivtvfb_pan_display,
918         .fb_blank       = ivtvfb_blank,
919 };
920
921 /* Initialization */
922
923
924 /* Setup our initial video mode */
925 static int ivtvfb_init_vidmode(struct ivtv *itv)
926 {
927         struct osd_info *oi = itv->osd_info;
928         struct v4l2_rect start_window;
929         int max_height;
930
931         /* Color mode */
932
933         if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
934                 osd_depth = 8;
935         oi->bits_per_pixel = osd_depth;
936         oi->bytes_per_pixel = oi->bits_per_pixel / 8;
937
938         /* Horizontal size & position */
939
940         if (osd_xres > 720)
941                 osd_xres = 720;
942
943         /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
944         if (osd_depth == 8)
945                 osd_xres &= ~3;
946         else if (osd_depth == 16)
947                 osd_xres &= ~1;
948
949         start_window.width = osd_xres ? osd_xres : 640;
950
951         /* Check horizontal start (osd_left). */
952         if (osd_left && osd_left + start_window.width > 721) {
953                 IVTVFB_ERR("Invalid osd_left - assuming default\n");
954                 osd_left = 0;
955         }
956
957         /* Hardware coords start at 0, user coords start at 1. */
958         osd_left--;
959
960         start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
961
962         oi->display_byte_stride =
963                         start_window.width * oi->bytes_per_pixel;
964
965         /* Vertical size & position */
966
967         max_height = itv->is_50hz ? 576 : 480;
968
969         if (osd_yres > max_height)
970                 osd_yres = max_height;
971
972         start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
973
974         /* Check vertical start (osd_upper). */
975         if (osd_upper + start_window.height > max_height + 1) {
976                 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
977                 osd_upper = 0;
978         }
979
980         /* Hardware coords start at 0, user coords start at 1. */
981         osd_upper--;
982
983         start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
984
985         oi->display_width = start_window.width;
986         oi->display_height = start_window.height;
987
988         /* Generate a valid fb_var_screeninfo */
989
990         oi->ivtvfb_defined.xres = oi->display_width;
991         oi->ivtvfb_defined.yres = oi->display_height;
992         oi->ivtvfb_defined.xres_virtual = oi->display_width;
993         oi->ivtvfb_defined.yres_virtual = oi->display_height;
994         oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
995         oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
996         oi->ivtvfb_defined.left_margin = start_window.left + 1;
997         oi->ivtvfb_defined.upper_margin = start_window.top + 1;
998         oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
999         oi->ivtvfb_defined.nonstd = 0;
1000
1001         /* We've filled in the most data, let the usual mode check
1002            routine fill in the rest. */
1003         _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1004
1005         /* Generate valid fb_fix_screeninfo */
1006
1007         ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1008
1009         /* Generate valid fb_info */
1010
1011         oi->ivtvfb_info.node = -1;
1012         oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1013         oi->ivtvfb_info.fbops = &ivtvfb_ops;
1014         oi->ivtvfb_info.par = itv;
1015         oi->ivtvfb_info.var = oi->ivtvfb_defined;
1016         oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1017         oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1018         oi->ivtvfb_info.fbops = &ivtvfb_ops;
1019
1020         /* Supply some monitor specs. Bogus values will do for now */
1021         oi->ivtvfb_info.monspecs.hfmin = 8000;
1022         oi->ivtvfb_info.monspecs.hfmax = 70000;
1023         oi->ivtvfb_info.monspecs.vfmin = 10;
1024         oi->ivtvfb_info.monspecs.vfmax = 100;
1025
1026         /* Allocate color map */
1027         if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1028                 IVTVFB_ERR("abort, unable to alloc cmap\n");
1029                 return -ENOMEM;
1030         }
1031
1032         /* Allocate the pseudo palette */
1033         oi->ivtvfb_info.pseudo_palette =
1034                 kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1035
1036         if (!oi->ivtvfb_info.pseudo_palette) {
1037                 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
1038                 return -ENOMEM;
1039         }
1040
1041         return 0;
1042 }
1043
1044 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1045
1046 static int ivtvfb_init_io(struct ivtv *itv)
1047 {
1048         struct osd_info *oi = itv->osd_info;
1049
1050         mutex_lock(&itv->serialize_lock);
1051         if (ivtv_init_on_first_open(itv)) {
1052                 mutex_unlock(&itv->serialize_lock);
1053                 IVTVFB_ERR("Failed to initialize ivtv\n");
1054                 return -ENXIO;
1055         }
1056         mutex_unlock(&itv->serialize_lock);
1057
1058         ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
1059
1060         /* The osd buffer size depends on the number of video buffers allocated
1061            on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1062            size to prevent any overlap. */
1063         oi->video_buffer_size = 1704960;
1064
1065         oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1066         oi->video_vbase = itv->dec_mem + oi->video_rbase;
1067
1068         if (!oi->video_vbase) {
1069                 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1070                      oi->video_buffer_size, oi->video_pbase);
1071                 return -EIO;
1072         }
1073
1074         IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1075                         oi->video_pbase, oi->video_vbase,
1076                         oi->video_buffer_size / 1024);
1077
1078 #ifdef CONFIG_MTRR
1079         {
1080                 /* Find the largest power of two that maps the whole buffer */
1081                 int size_shift = 31;
1082
1083                 while (!(oi->video_buffer_size & (1 << size_shift))) {
1084                         size_shift--;
1085                 }
1086                 size_shift++;
1087                 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1088                 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1089                 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1090                 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1091                 if (mtrr_add(oi->fb_start_aligned_physaddr,
1092                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1093                              MTRR_TYPE_WRCOMB, 1) < 0) {
1094                         IVTVFB_INFO("disabled mttr\n");
1095                         oi->fb_start_aligned_physaddr = 0;
1096                         oi->fb_end_aligned_physaddr = 0;
1097                 }
1098         }
1099 #endif
1100
1101         /* Blank the entire osd. */
1102         memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1103
1104         return 0;
1105 }
1106
1107 /* Release any memory we've grabbed & remove mtrr entry */
1108 static void ivtvfb_release_buffers (struct ivtv *itv)
1109 {
1110         struct osd_info *oi = itv->osd_info;
1111
1112         /* Release cmap */
1113         if (oi->ivtvfb_info.cmap.len)
1114                 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1115
1116         /* Release pseudo palette */
1117         if (oi->ivtvfb_info.pseudo_palette)
1118                 kfree(oi->ivtvfb_info.pseudo_palette);
1119
1120 #ifdef CONFIG_MTRR
1121         if (oi->fb_end_aligned_physaddr) {
1122                 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1123                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1124         }
1125 #endif
1126
1127         kfree(oi);
1128         itv->osd_info = NULL;
1129 }
1130
1131 /* Initialize the specified card */
1132
1133 static int ivtvfb_init_card(struct ivtv *itv)
1134 {
1135         int rc;
1136
1137         if (itv->osd_info) {
1138                 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1139                 return -EBUSY;
1140         }
1141
1142         itv->osd_info = kzalloc(sizeof(struct osd_info),
1143                                         GFP_ATOMIC|__GFP_NOWARN);
1144         if (itv->osd_info == NULL) {
1145                 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1146                 return -ENOMEM;
1147         }
1148
1149         /* Find & setup the OSD buffer */
1150         if ((rc = ivtvfb_init_io(itv)))
1151                 return rc;
1152
1153         /* Set the startup video mode information */
1154         if ((rc = ivtvfb_init_vidmode(itv))) {
1155                 ivtvfb_release_buffers(itv);
1156                 return rc;
1157         }
1158
1159         /* Register the framebuffer */
1160         if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1161                 ivtvfb_release_buffers(itv);
1162                 return -EINVAL;
1163         }
1164
1165         itv->osd_video_pbase = itv->osd_info->video_pbase;
1166
1167         /* Set the card to the requested mode */
1168         ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1169
1170         /* Set color 0 to black */
1171         write_reg(0, 0x02a30);
1172         write_reg(0, 0x02a34);
1173
1174         /* Enable the osd */
1175         ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1176
1177         /* Allocate DMA */
1178         ivtv_udma_alloc(itv);
1179         return 0;
1180
1181 }
1182
1183 static int __init ivtvfb_init(void)
1184 {
1185         struct ivtv *itv;
1186         int i, registered = 0;
1187
1188         if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1189                 printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1190                      IVTV_MAX_CARDS - 1);
1191                 return -EINVAL;
1192         }
1193
1194         /* Locate & initialise all cards supporting an OSD. */
1195         for (i = 0; i < ivtv_cards_active; i++) {
1196                 if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)
1197                         continue;
1198                 itv = ivtv_cards[i];
1199                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
1200                         if (ivtvfb_init_card(itv) == 0) {
1201                                 IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
1202                                 registered++;
1203                         }
1204                 }
1205         }
1206         if (!registered) {
1207                 printk(KERN_ERR "ivtvfb:  no cards found");
1208                 return -ENODEV;
1209         }
1210         return 0;
1211 }
1212
1213 static void ivtvfb_cleanup(void)
1214 {
1215         struct ivtv *itv;
1216         int i;
1217
1218         printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
1219
1220         for (i = 0; i < ivtv_cards_active; i++) {
1221                 itv = ivtv_cards[i];
1222                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
1223                         if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1224                                 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
1225                                 return;
1226                         }
1227                         IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
1228                         ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
1229                         ivtvfb_release_buffers(itv);
1230                         itv->osd_video_pbase = 0;
1231                 }
1232         }
1233 }
1234
1235 module_init(ivtvfb_init);
1236 module_exit(ivtvfb_cleanup);