]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/ivtv/ivtvfb.c
V4L/DVB (8249): Fix pointer cast warnings in the ivtv framebuffer driver
[linux-2.6-omap-h63xx.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 &&
421                     ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
422                         /* Odd address = can't DMA. Align */
423                         if ((unsigned long)dst & 3) {
424                                 lead = 4 - ((unsigned long)dst & 3);
425                                 memcpy(dst, buf, lead);
426                                 buf += lead;
427                                 dst += lead;
428                         }
429                         /* DMA resolution is 32 bits */
430                         if ((count - lead) & 3)
431                                 tail = (count - lead) & 3;
432                         /* DMA the data */
433                         dma_size = count - lead - tail;
434                         err = ivtvfb_prep_dec_dma_to_device(itv,
435                                p + lead + dma_offset, (void *)buf, dma_size);
436                         dst += dma_size;
437                         buf += dma_size;
438                         /* Copy any leftover data */
439                         if (tail)
440                                 memcpy(dst, buf, tail);
441                 } else {
442                         memcpy(dst, buf, count);
443                 }
444         }
445
446         if  (!err)
447                 *ppos += count;
448
449         return (err) ? err : count;
450 }
451
452 static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
453 {
454         DEFINE_WAIT(wait);
455         struct ivtv *itv = (struct ivtv *)info->par;
456         int rc = 0;
457
458         switch (cmd) {
459                 case FBIOGET_VBLANK: {
460                         struct fb_vblank vblank;
461                         u32 trace;
462
463                         vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
464                                         FB_VBLANK_HAVE_VSYNC;
465                         trace = read_reg(0x028c0) >> 16;
466                         if (itv->is_50hz && trace > 312) trace -= 312;
467                         else if (itv->is_60hz && trace > 262) trace -= 262;
468                         if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
469                         vblank.count = itv->last_vsync_field;
470                         vblank.vcount = trace;
471                         vblank.hcount = 0;
472                         if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
473                                 return -EFAULT;
474                         return 0;
475                 }
476
477                 case FBIO_WAITFORVSYNC:
478                         prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
479                         if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
480                         finish_wait(&itv->vsync_waitq, &wait);
481                         return rc;
482
483                 case IVTVFB_IOC_DMA_FRAME: {
484                         struct ivtvfb_dma_frame args;
485
486                         IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
487                         if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
488                                 return -EFAULT;
489
490                         return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
491                 }
492
493                 default:
494                         IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
495                         return -EINVAL;
496         }
497         return 0;
498 }
499
500 /* Framebuffer device handling */
501
502 static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
503 {
504         struct osd_info *oi = itv->osd_info;
505         struct ivtv_osd_coords ivtv_osd;
506         struct v4l2_rect ivtv_window;
507         int osd_mode = -1;
508
509         IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
510
511         /* Select color space */
512         if (var->nonstd) /* YUV */
513                 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
514         else /* RGB  */
515                 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
516
517         /* Set the color mode */
518         switch (var->bits_per_pixel) {
519                 case 8:
520                         osd_mode = IVTV_OSD_BPP_8;
521                         break;
522                 case 32:
523                         osd_mode = IVTV_OSD_BPP_32;
524                         break;
525                 case 16:
526                         switch (var->green.length) {
527                         case 4:
528                                 osd_mode = IVTV_OSD_BPP_16_444;
529                                 break;
530                         case 5:
531                                 osd_mode = IVTV_OSD_BPP_16_555;
532                                 break;
533                         case 6:
534                                 osd_mode = IVTV_OSD_BPP_16_565;
535                                 break;
536                         default:
537                                 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
538                         }
539                         break;
540                 default:
541                         IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
542         }
543
544         /* Set video mode. Although rare, the display can become scrambled even
545            if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
546         if (osd_mode != -1) {
547                 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
548                 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
549         }
550
551         oi->bits_per_pixel = var->bits_per_pixel;
552         oi->bytes_per_pixel = var->bits_per_pixel / 8;
553
554         /* Set the flicker filter */
555         switch (var->vmode & FB_VMODE_MASK) {
556                 case FB_VMODE_NONINTERLACED: /* Filter on */
557                         ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
558                         break;
559                 case FB_VMODE_INTERLACED: /* Filter off */
560                         ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
561                         break;
562                 default:
563                         IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
564         }
565
566         /* Read the current osd info */
567         ivtvfb_get_osd_coords(itv, &ivtv_osd);
568
569         /* Now set the OSD to the size we want */
570         ivtv_osd.pixel_stride = var->xres_virtual;
571         ivtv_osd.lines = var->yres_virtual;
572         ivtv_osd.x = 0;
573         ivtv_osd.y = 0;
574         ivtvfb_set_osd_coords(itv, &ivtv_osd);
575
576         /* Can't seem to find the right API combo for this.
577            Use another function which does what we need through direct register access. */
578         ivtv_window.width = var->xres;
579         ivtv_window.height = var->yres;
580
581         /* Minimum margin cannot be 0, as X won't allow such a mode */
582         if (!var->upper_margin) var->upper_margin++;
583         if (!var->left_margin) var->left_margin++;
584         ivtv_window.top = var->upper_margin - 1;
585         ivtv_window.left = var->left_margin - 1;
586
587         ivtvfb_set_display_window(itv, &ivtv_window);
588
589         /* Pass screen size back to yuv handler */
590         itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
591         itv->yuv_info.osd_full_h = ivtv_osd.lines;
592
593         /* Force update of yuv registers */
594         itv->yuv_info.yuv_forced_update = 1;
595
596         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
597                       var->xres, var->yres,
598                       var->xres_virtual, var->yres_virtual,
599                       var->bits_per_pixel);
600
601         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
602                       var->left_margin, var->upper_margin);
603
604         IVTVFB_DEBUG_INFO("Display filter: %s\n",
605                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
606         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
607
608         return 0;
609 }
610
611 static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
612 {
613         struct osd_info *oi = itv->osd_info;
614
615         IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
616         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
617         strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
618         fix->smem_start = oi->video_pbase;
619         fix->smem_len = oi->video_buffer_size;
620         fix->type = FB_TYPE_PACKED_PIXELS;
621         fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
622         fix->xpanstep = 1;
623         fix->ypanstep = 1;
624         fix->ywrapstep = 0;
625         fix->line_length = oi->display_byte_stride;
626         fix->accel = FB_ACCEL_NONE;
627         return 0;
628 }
629
630 /* Check the requested display mode, returning -EINVAL if we can't
631    handle it. */
632
633 static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
634 {
635         struct osd_info *oi = itv->osd_info;
636         int osd_height_limit;
637         u32 pixclock, hlimit, vlimit;
638
639         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
640
641         /* Set base references for mode calcs. */
642         if (itv->is_50hz) {
643                 pixclock = 84316;
644                 hlimit = 776;
645                 vlimit = 591;
646                 osd_height_limit = 576;
647         }
648         else {
649                 pixclock = 83926;
650                 hlimit = 776;
651                 vlimit = 495;
652                 osd_height_limit = 480;
653         }
654
655         if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
656                 var->transp.offset = 24;
657                 var->transp.length = 8;
658                 var->red.offset = 16;
659                 var->red.length = 8;
660                 var->green.offset = 8;
661                 var->green.length = 8;
662                 var->blue.offset = 0;
663                 var->blue.length = 8;
664         }
665         else if (var->bits_per_pixel == 16) {
666                 /* To find out the true mode, check green length */
667                 switch (var->green.length) {
668                         case 4:
669                                 var->red.offset = 8;
670                                 var->red.length = 4;
671                                 var->green.offset = 4;
672                                 var->green.length = 4;
673                                 var->blue.offset = 0;
674                                 var->blue.length = 4;
675                                 var->transp.offset = 12;
676                                 var->transp.length = 1;
677                                 break;
678                         case 5:
679                                 var->red.offset = 10;
680                                 var->red.length = 5;
681                                 var->green.offset = 5;
682                                 var->green.length = 5;
683                                 var->blue.offset = 0;
684                                 var->blue.length = 5;
685                                 var->transp.offset = 15;
686                                 var->transp.length = 1;
687                                 break;
688                         default:
689                                 var->red.offset = 11;
690                                 var->red.length = 5;
691                                 var->green.offset = 5;
692                                 var->green.length = 6;
693                                 var->blue.offset = 0;
694                                 var->blue.length = 5;
695                                 var->transp.offset = 0;
696                                 var->transp.length = 0;
697                                 break;
698                 }
699         }
700         else {
701                 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
702                 return -EINVAL;
703         }
704
705         /* Check the resolution */
706         if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
707                 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
708                                 var->xres, var->yres);
709                 return -EINVAL;
710         }
711
712         /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
713         if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
714             var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
715             var->xres_virtual < var->xres ||
716             var->yres_virtual < var->yres) {
717                 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
718                         var->xres_virtual, var->yres_virtual);
719                 return -EINVAL;
720         }
721
722         /* Some extra checks if in 8 bit mode */
723         if (var->bits_per_pixel == 8) {
724                 /* Width must be a multiple of 4 */
725                 if (var->xres & 3) {
726                         IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
727                         return -EINVAL;
728                 }
729                 if (var->xres_virtual & 3) {
730                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
731                         return -EINVAL;
732                 }
733         }
734         else if (var->bits_per_pixel == 16) {
735                 /* Width must be a multiple of 2 */
736                 if (var->xres & 1) {
737                         IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
738                         return -EINVAL;
739                 }
740                 if (var->xres_virtual & 1) {
741                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
742                         return -EINVAL;
743                 }
744         }
745
746         /* Now check the offsets */
747         if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
748                 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
749                         var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
750                 return -EINVAL;
751         }
752
753         /* Check pixel format */
754         if (var->nonstd > 1) {
755                 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
756                 return -EINVAL;
757         }
758
759         /* Check video mode */
760         if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
761                 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
762                 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
763                 return -EINVAL;
764         }
765
766         /* Check the left & upper margins
767            If the margins are too large, just center the screen
768            (enforcing margins causes too many problems) */
769
770         if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) {
771                 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
772         }
773         if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) {
774                 var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2);
775         }
776
777         /* Maintain overall 'size' for a constant refresh rate */
778         var->right_margin = hlimit - var->left_margin - var->xres;
779         var->lower_margin = vlimit - var->upper_margin - var->yres;
780
781         /* Fixed sync times */
782         var->hsync_len = 24;
783         var->vsync_len = 2;
784
785         /* Non-interlaced / interlaced mode is used to switch the OSD filter
786            on or off. Adjust the clock timings to maintain a constant
787            vertical refresh rate. */
788         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
789                 var->pixclock = pixclock / 2;
790         else
791                 var->pixclock = pixclock;
792
793         itv->osd_rect.width = var->xres;
794         itv->osd_rect.height = var->yres;
795
796         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
797                       var->xres, var->yres,
798                       var->xres_virtual, var->yres_virtual,
799                       var->bits_per_pixel);
800
801         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
802                       var->left_margin, var->upper_margin);
803
804         IVTVFB_DEBUG_INFO("Display filter: %s\n",
805                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
806         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
807         return 0;
808 }
809
810 static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
811 {
812         struct ivtv *itv = (struct ivtv *) info->par;
813         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
814         return _ivtvfb_check_var(var, itv);
815 }
816
817 static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
818 {
819         u32 osd_pan_index;
820         struct ivtv *itv = (struct ivtv *) info->par;
821
822         osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8;
823         write_reg(osd_pan_index, 0x02A0C);
824
825         /* Pass this info back the yuv handler */
826         itv->yuv_info.osd_x_pan = var->xoffset;
827         itv->yuv_info.osd_y_pan = var->yoffset;
828         /* Force update of yuv registers */
829         itv->yuv_info.yuv_forced_update = 1;
830         return 0;
831 }
832
833 static int ivtvfb_set_par(struct fb_info *info)
834 {
835         int rc = 0;
836         struct ivtv *itv = (struct ivtv *) info->par;
837
838         IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
839
840         rc = ivtvfb_set_var(itv, &info->var);
841         ivtvfb_pan_display(&info->var, info);
842         ivtvfb_get_fix(itv, &info->fix);
843         return rc;
844 }
845
846 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
847                                 unsigned blue, unsigned transp,
848                                 struct fb_info *info)
849 {
850         u32 color, *palette;
851         struct ivtv *itv = (struct ivtv *)info->par;
852
853         if (regno >= info->cmap.len)
854                 return -EINVAL;
855
856         color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
857         if (info->var.bits_per_pixel <= 8) {
858                 write_reg(regno, 0x02a30);
859                 write_reg(color, 0x02a34);
860                 return 0;
861         }
862         if (regno >= 16)
863                 return -EINVAL;
864
865         palette = info->pseudo_palette;
866         if (info->var.bits_per_pixel == 16) {
867                 switch (info->var.green.length) {
868                         case 4:
869                                 color = ((red & 0xf000) >> 4) |
870                                         ((green & 0xf000) >> 8) |
871                                         ((blue & 0xf000) >> 12);
872                                 break;
873                         case 5:
874                                 color = ((red & 0xf800) >> 1) |
875                                         ((green & 0xf800) >> 6) |
876                                         ((blue & 0xf800) >> 11);
877                                 break;
878                         case 6:
879                                 color = (red & 0xf800 ) |
880                                         ((green & 0xfc00) >> 5) |
881                                         ((blue & 0xf800) >> 11);
882                                 break;
883                 }
884         }
885         palette[regno] = color;
886         return 0;
887 }
888
889 /* We don't really support blanking. All this does is enable or
890    disable the OSD. */
891 static int ivtvfb_blank(int blank_mode, struct fb_info *info)
892 {
893         struct ivtv *itv = (struct ivtv *)info->par;
894
895         IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
896         switch (blank_mode) {
897         case FB_BLANK_UNBLANK:
898                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
899                 break;
900         case FB_BLANK_NORMAL:
901         case FB_BLANK_HSYNC_SUSPEND:
902         case FB_BLANK_VSYNC_SUSPEND:
903         case FB_BLANK_POWERDOWN:
904                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
905                 break;
906         }
907         return 0;
908 }
909
910 static struct fb_ops ivtvfb_ops = {
911         .owner = THIS_MODULE,
912         .fb_write       = ivtvfb_write,
913         .fb_check_var   = ivtvfb_check_var,
914         .fb_set_par     = ivtvfb_set_par,
915         .fb_setcolreg   = ivtvfb_setcolreg,
916         .fb_fillrect    = cfb_fillrect,
917         .fb_copyarea    = cfb_copyarea,
918         .fb_imageblit   = cfb_imageblit,
919         .fb_cursor      = NULL,
920         .fb_ioctl       = ivtvfb_ioctl,
921         .fb_pan_display = ivtvfb_pan_display,
922         .fb_blank       = ivtvfb_blank,
923 };
924
925 /* Initialization */
926
927
928 /* Setup our initial video mode */
929 static int ivtvfb_init_vidmode(struct ivtv *itv)
930 {
931         struct osd_info *oi = itv->osd_info;
932         struct v4l2_rect start_window;
933         int max_height;
934
935         /* Color mode */
936
937         if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
938                 osd_depth = 8;
939         oi->bits_per_pixel = osd_depth;
940         oi->bytes_per_pixel = oi->bits_per_pixel / 8;
941
942         /* Horizontal size & position */
943
944         if (osd_xres > 720)
945                 osd_xres = 720;
946
947         /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
948         if (osd_depth == 8)
949                 osd_xres &= ~3;
950         else if (osd_depth == 16)
951                 osd_xres &= ~1;
952
953         start_window.width = osd_xres ? osd_xres : 640;
954
955         /* Check horizontal start (osd_left). */
956         if (osd_left && osd_left + start_window.width > 721) {
957                 IVTVFB_ERR("Invalid osd_left - assuming default\n");
958                 osd_left = 0;
959         }
960
961         /* Hardware coords start at 0, user coords start at 1. */
962         osd_left--;
963
964         start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
965
966         oi->display_byte_stride =
967                         start_window.width * oi->bytes_per_pixel;
968
969         /* Vertical size & position */
970
971         max_height = itv->is_50hz ? 576 : 480;
972
973         if (osd_yres > max_height)
974                 osd_yres = max_height;
975
976         start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
977
978         /* Check vertical start (osd_upper). */
979         if (osd_upper + start_window.height > max_height + 1) {
980                 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
981                 osd_upper = 0;
982         }
983
984         /* Hardware coords start at 0, user coords start at 1. */
985         osd_upper--;
986
987         start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
988
989         oi->display_width = start_window.width;
990         oi->display_height = start_window.height;
991
992         /* Generate a valid fb_var_screeninfo */
993
994         oi->ivtvfb_defined.xres = oi->display_width;
995         oi->ivtvfb_defined.yres = oi->display_height;
996         oi->ivtvfb_defined.xres_virtual = oi->display_width;
997         oi->ivtvfb_defined.yres_virtual = oi->display_height;
998         oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
999         oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1000         oi->ivtvfb_defined.left_margin = start_window.left + 1;
1001         oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1002         oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1003         oi->ivtvfb_defined.nonstd = 0;
1004
1005         /* We've filled in the most data, let the usual mode check
1006            routine fill in the rest. */
1007         _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1008
1009         /* Generate valid fb_fix_screeninfo */
1010
1011         ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1012
1013         /* Generate valid fb_info */
1014
1015         oi->ivtvfb_info.node = -1;
1016         oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1017         oi->ivtvfb_info.fbops = &ivtvfb_ops;
1018         oi->ivtvfb_info.par = itv;
1019         oi->ivtvfb_info.var = oi->ivtvfb_defined;
1020         oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1021         oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1022         oi->ivtvfb_info.fbops = &ivtvfb_ops;
1023
1024         /* Supply some monitor specs. Bogus values will do for now */
1025         oi->ivtvfb_info.monspecs.hfmin = 8000;
1026         oi->ivtvfb_info.monspecs.hfmax = 70000;
1027         oi->ivtvfb_info.monspecs.vfmin = 10;
1028         oi->ivtvfb_info.monspecs.vfmax = 100;
1029
1030         /* Allocate color map */
1031         if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1032                 IVTVFB_ERR("abort, unable to alloc cmap\n");
1033                 return -ENOMEM;
1034         }
1035
1036         /* Allocate the pseudo palette */
1037         oi->ivtvfb_info.pseudo_palette =
1038                 kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1039
1040         if (!oi->ivtvfb_info.pseudo_palette) {
1041                 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
1042                 return -ENOMEM;
1043         }
1044
1045         return 0;
1046 }
1047
1048 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1049
1050 static int ivtvfb_init_io(struct ivtv *itv)
1051 {
1052         struct osd_info *oi = itv->osd_info;
1053
1054         mutex_lock(&itv->serialize_lock);
1055         if (ivtv_init_on_first_open(itv)) {
1056                 mutex_unlock(&itv->serialize_lock);
1057                 IVTVFB_ERR("Failed to initialize ivtv\n");
1058                 return -ENXIO;
1059         }
1060         mutex_unlock(&itv->serialize_lock);
1061
1062         ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
1063
1064         /* The osd buffer size depends on the number of video buffers allocated
1065            on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1066            size to prevent any overlap. */
1067         oi->video_buffer_size = 1704960;
1068
1069         oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1070         oi->video_vbase = itv->dec_mem + oi->video_rbase;
1071
1072         if (!oi->video_vbase) {
1073                 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1074                      oi->video_buffer_size, oi->video_pbase);
1075                 return -EIO;
1076         }
1077
1078         IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1079                         oi->video_pbase, oi->video_vbase,
1080                         oi->video_buffer_size / 1024);
1081
1082 #ifdef CONFIG_MTRR
1083         {
1084                 /* Find the largest power of two that maps the whole buffer */
1085                 int size_shift = 31;
1086
1087                 while (!(oi->video_buffer_size & (1 << size_shift))) {
1088                         size_shift--;
1089                 }
1090                 size_shift++;
1091                 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1092                 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1093                 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1094                 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1095                 if (mtrr_add(oi->fb_start_aligned_physaddr,
1096                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1097                              MTRR_TYPE_WRCOMB, 1) < 0) {
1098                         IVTVFB_INFO("disabled mttr\n");
1099                         oi->fb_start_aligned_physaddr = 0;
1100                         oi->fb_end_aligned_physaddr = 0;
1101                 }
1102         }
1103 #endif
1104
1105         /* Blank the entire osd. */
1106         memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1107
1108         return 0;
1109 }
1110
1111 /* Release any memory we've grabbed & remove mtrr entry */
1112 static void ivtvfb_release_buffers (struct ivtv *itv)
1113 {
1114         struct osd_info *oi = itv->osd_info;
1115
1116         /* Release cmap */
1117         if (oi->ivtvfb_info.cmap.len)
1118                 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1119
1120         /* Release pseudo palette */
1121         if (oi->ivtvfb_info.pseudo_palette)
1122                 kfree(oi->ivtvfb_info.pseudo_palette);
1123
1124 #ifdef CONFIG_MTRR
1125         if (oi->fb_end_aligned_physaddr) {
1126                 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1127                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1128         }
1129 #endif
1130
1131         kfree(oi);
1132         itv->osd_info = NULL;
1133 }
1134
1135 /* Initialize the specified card */
1136
1137 static int ivtvfb_init_card(struct ivtv *itv)
1138 {
1139         int rc;
1140
1141         if (itv->osd_info) {
1142                 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1143                 return -EBUSY;
1144         }
1145
1146         itv->osd_info = kzalloc(sizeof(struct osd_info),
1147                                         GFP_ATOMIC|__GFP_NOWARN);
1148         if (itv->osd_info == NULL) {
1149                 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1150                 return -ENOMEM;
1151         }
1152
1153         /* Find & setup the OSD buffer */
1154         if ((rc = ivtvfb_init_io(itv)))
1155                 return rc;
1156
1157         /* Set the startup video mode information */
1158         if ((rc = ivtvfb_init_vidmode(itv))) {
1159                 ivtvfb_release_buffers(itv);
1160                 return rc;
1161         }
1162
1163         /* Register the framebuffer */
1164         if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1165                 ivtvfb_release_buffers(itv);
1166                 return -EINVAL;
1167         }
1168
1169         itv->osd_video_pbase = itv->osd_info->video_pbase;
1170
1171         /* Set the card to the requested mode */
1172         ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1173
1174         /* Set color 0 to black */
1175         write_reg(0, 0x02a30);
1176         write_reg(0, 0x02a34);
1177
1178         /* Enable the osd */
1179         ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1180
1181         /* Allocate DMA */
1182         ivtv_udma_alloc(itv);
1183         return 0;
1184
1185 }
1186
1187 static int __init ivtvfb_init(void)
1188 {
1189         struct ivtv *itv;
1190         int i, registered = 0;
1191
1192         if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1193                 printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1194                      IVTV_MAX_CARDS - 1);
1195                 return -EINVAL;
1196         }
1197
1198         /* Locate & initialise all cards supporting an OSD. */
1199         for (i = 0; i < ivtv_cards_active; i++) {
1200                 if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)
1201                         continue;
1202                 itv = ivtv_cards[i];
1203                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
1204                         if (ivtvfb_init_card(itv) == 0) {
1205                                 IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
1206                                 registered++;
1207                         }
1208                 }
1209         }
1210         if (!registered) {
1211                 printk(KERN_ERR "ivtvfb:  no cards found");
1212                 return -ENODEV;
1213         }
1214         return 0;
1215 }
1216
1217 static void ivtvfb_cleanup(void)
1218 {
1219         struct ivtv *itv;
1220         int i;
1221
1222         printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
1223
1224         for (i = 0; i < ivtv_cards_active; i++) {
1225                 itv = ivtv_cards[i];
1226                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
1227                         if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1228                                 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
1229                                 return;
1230                         }
1231                         IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
1232                         ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
1233                         ivtvfb_release_buffers(itv);
1234                         itv->osd_video_pbase = 0;
1235                 }
1236         }
1237 }
1238
1239 module_init(ivtvfb_init);
1240 module_exit(ivtvfb_cleanup);