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