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