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