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