V4L/DVB (7853): ivtv/cx18: fix compile warnings
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / ivtv / ivtvfb.c
CommitLineData
32db7754
HV
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
be383bd3 6 support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
32db7754
HV
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>
32db7754 43#include <linux/fb.h>
0f45b8c5 44#include <linux/ivtvfb.h>
32db7754
HV
45
46#ifdef CONFIG_MTRR
47#include <asm/mtrr.h>
48#endif
49
50#include "ivtv-driver.h"
32db7754 51#include "ivtv-udma.h"
32db7754 52#include "ivtv-mailbox.h"
32db7754
HV
53
54/* card parameters */
641ed49d
HV
55static int ivtvfb_card_id = -1;
56static int ivtvfb_debug = 0;
32db7754 57static int osd_laced;
32db7754
HV
58static int osd_depth;
59static int osd_upper;
60static int osd_left;
61static int osd_yres;
62static int osd_xres;
63
641ed49d
HV
64module_param(ivtvfb_card_id, int, 0444);
65module_param_named(debug,ivtvfb_debug, int, 0644);
32db7754 66module_param(osd_laced, bool, 0444);
32db7754
HV
67module_param(osd_depth, int, 0444);
68module_param(osd_upper, int, 0444);
69module_param(osd_left, int, 0444);
70module_param(osd_yres, int, 0444);
71module_param(osd_xres, int, 0444);
72
641ed49d 73MODULE_PARM_DESC(ivtvfb_card_id,
32db7754
HV
74 "Only use framebuffer of the specified ivtv card (0-31)\n"
75 "\t\t\tdefault -1: initialize all available framebuffers");
76
77MODULE_PARM_DESC(debug,
78 "Debug level (bitmask). Default: errors only\n"
79 "\t\t\t(debug = 3 gives full debugging)");
80
32db7754
HV
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
85MODULE_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
91MODULE_PARM_DESC(osd_depth,
be383bd3 92 "Bits per pixel - 8, 16, 32\n"
32db7754
HV
93 "\t\t\tdefault 8");
94
95MODULE_PARM_DESC(osd_upper,
96 "Vertical start position\n"
97 "\t\t\tdefault 0 (Centered)");
98
99MODULE_PARM_DESC(osd_left,
100 "Horizontal start position\n"
101 "\t\t\tdefault 0 (Centered)");
102
103MODULE_PARM_DESC(osd_yres,
104 "Display height\n"
105 "\t\t\tdefault 480 (PAL)\n"
106 "\t\t\t 400 (NTSC)");
107
108MODULE_PARM_DESC(osd_xres,
109 "Display width\n"
110 "\t\t\tdefault 640");
111
112MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
113MODULE_LICENSE("GPL");
114
115/* --------------------------------------------------------------------- */
116
641ed49d
HV
117#define IVTVFB_DBGFLG_WARN (1 << 0)
118#define IVTVFB_DBGFLG_INFO (1 << 1)
32db7754 119
641ed49d 120#define IVTVFB_DEBUG(x, type, fmt, args...) \
32db7754 121 do { \
641ed49d 122 if ((x) & ivtvfb_debug) \
7b3a0d49 123 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \
32db7754 124 } while (0)
641ed49d
HV
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)
32db7754
HV
127
128/* Standard kernel messages */
641ed49d
HV
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)
32db7754
HV
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
144struct osd_info {
32db7754
HV
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
180struct 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
641ed49d 193static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
32db7754
HV
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
641ed49d 205static int ivtvfb_get_osd_coords(struct ivtv *itv,
32db7754
HV
206 struct ivtv_osd_coords *osd)
207{
be383bd3 208 struct osd_info *oi = itv->osd_info;
32db7754
HV
209 u32 data[CX2341X_MBOX_MAX_DATA];
210
211 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
212
be383bd3
HV
213 osd->offset = data[0] - oi->video_rbase;
214 osd->max_offset = oi->display_width * oi->display_height * 4;
32db7754
HV
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
641ed49d 222static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
32db7754 223{
be383bd3
HV
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;
32db7754
HV
230
231 return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
be383bd3 232 osd->offset + oi->video_rbase,
32db7754
HV
233 osd->pixel_stride,
234 osd->lines, osd->x, osd->y);
235}
236
641ed49d 237static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
32db7754 238{
32db7754
HV
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) {
641ed49d 247 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
32db7754
HV
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) {
641ed49d 253 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
32db7754
HV
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
641ed49d 273static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
32db7754
HV
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);
641ed49d 285 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
32db7754
HV
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
641ed49d 293 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
32db7754
HV
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
641ed49d 322static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
be383bd3 323 unsigned long dest_offset, int count)
32db7754
HV
324{
325 DEFINE_WAIT(wait);
aaf9fa21 326 struct osd_info *oi = itv->osd_info;
32db7754
HV
327
328 /* Nothing to do */
329 if (count == 0) {
641ed49d 330 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
32db7754
HV
331 return -EINVAL;
332 }
333
334 /* Check Total FB Size */
aaf9fa21 335 if ((dest_offset + count) > oi->video_buffer_size) {
641ed49d 336 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
aaf9fa21 337 dest_offset + count, oi->video_buffer_size);
32db7754
HV
338 return -E2BIG;
339 }
340
341 /* Not fatal, but will have undesirable results */
342 if ((unsigned long)source & 3)
641ed49d 343 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
be383bd3 344 (unsigned long)source);
32db7754
HV
345
346 if (dest_offset & 3)
641ed49d 347 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
32db7754
HV
348
349 if (count & 3)
641ed49d 350 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
32db7754
HV
351
352 /* Check Source */
353 if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
641ed49d 354 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
32db7754
HV
355 (unsigned long)source);
356
641ed49d 357 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
32db7754
HV
358 dest_offset, (unsigned long)source,
359 count);
360 return -EINVAL;
361 }
362
363 /* OSD Address to send DMA to */
33c0fcad 364 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
32db7754
HV
365
366 /* Fill Buffers */
641ed49d 367 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
32db7754
HV
368}
369
370static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
371{
372 DEFINE_WAIT(wait);
373 struct ivtv *itv = (struct ivtv *)info->par;
be383bd3 374 int rc = 0;
32db7754
HV
375
376 switch (cmd) {
32db7754
HV
377 case FBIOGET_VBLANK: {
378 struct fb_vblank vblank;
379 u32 trace;
380
381 vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
382 FB_VBLANK_HAVE_VSYNC;
be383bd3 383 trace = read_reg(0x028c0) >> 16;
32db7754
HV
384 if (itv->is_50hz && trace > 312) trace -= 312;
385 else if (itv->is_60hz && trace > 262) trace -= 262;
386 if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
a158f355 387 vblank.count = itv->last_vsync_field;
32db7754
HV
388 vblank.vcount = trace;
389 vblank.hcount = 0;
390 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
391 return -EFAULT;
392 return 0;
393 }
394
be383bd3 395 case FBIO_WAITFORVSYNC:
32db7754 396 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
84149a0f 397 if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
be383bd3 398 finish_wait(&itv->vsync_waitq, &wait);
32db7754 399 return rc;
32db7754 400
d715e766
HV
401 case IVTVFB_IOC_DMA_FRAME: {
402 struct ivtvfb_dma_frame args;
32db7754 403
641ed49d 404 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
32db7754
HV
405 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
406 return -EFAULT;
407
641ed49d 408 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
32db7754
HV
409 }
410
411 default:
641ed49d 412 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
32db7754
HV
413 return -EINVAL;
414 }
415 return 0;
416}
417
418/* Framebuffer device handling */
419
420static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
421{
aaf9fa21 422 struct osd_info *oi = itv->osd_info;
32db7754
HV
423 struct ivtv_osd_coords ivtv_osd;
424 struct v4l2_rect ivtv_window;
aaf9fa21 425 int osd_mode = -1;
32db7754 426
641ed49d 427 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
32db7754
HV
428
429 /* Select color space */
430 if (var->nonstd) /* YUV */
be383bd3 431 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
32db7754 432 else /* RGB */
be383bd3 433 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
32db7754 434
aaf9fa21 435 /* Set the color mode */
32db7754
HV
436 switch (var->bits_per_pixel) {
437 case 8:
aaf9fa21 438 osd_mode = IVTV_OSD_BPP_8;
32db7754
HV
439 break;
440 case 32:
aaf9fa21 441 osd_mode = IVTV_OSD_BPP_32;
32db7754
HV
442 break;
443 case 16:
444 switch (var->green.length) {
445 case 4:
aaf9fa21 446 osd_mode = IVTV_OSD_BPP_16_444;
32db7754
HV
447 break;
448 case 5:
aaf9fa21 449 osd_mode = IVTV_OSD_BPP_16_555;
32db7754
HV
450 break;
451 case 6:
aaf9fa21 452 osd_mode = IVTV_OSD_BPP_16_565;
32db7754
HV
453 break;
454 default:
641ed49d 455 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
32db7754
HV
456 }
457 break;
458 default:
641ed49d 459 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
32db7754
HV
460 }
461
6659e3ed
IA
462 /* Set video mode. Although rare, the display can become scrambled even
463 if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
464 if (osd_mode != -1) {
aaf9fa21
IA
465 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
466 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
aaf9fa21
IA
467 }
468
469 oi->bits_per_pixel = var->bits_per_pixel;
470 oi->bytes_per_pixel = var->bits_per_pixel / 8;
32db7754
HV
471
472 /* Set the flicker filter */
473 switch (var->vmode & FB_VMODE_MASK) {
474 case FB_VMODE_NONINTERLACED: /* Filter on */
475 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
476 break;
477 case FB_VMODE_INTERLACED: /* Filter off */
478 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
479 break;
480 default:
641ed49d 481 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
32db7754
HV
482 }
483
484 /* Read the current osd info */
641ed49d 485 ivtvfb_get_osd_coords(itv, &ivtv_osd);
32db7754
HV
486
487 /* Now set the OSD to the size we want */
488 ivtv_osd.pixel_stride = var->xres_virtual;
489 ivtv_osd.lines = var->yres_virtual;
490 ivtv_osd.x = 0;
491 ivtv_osd.y = 0;
641ed49d 492 ivtvfb_set_osd_coords(itv, &ivtv_osd);
32db7754
HV
493
494 /* Can't seem to find the right API combo for this.
495 Use another function which does what we need through direct register access. */
496 ivtv_window.width = var->xres;
497 ivtv_window.height = var->yres;
498
499 /* Minimum margin cannot be 0, as X won't allow such a mode */
be383bd3
HV
500 if (!var->upper_margin) var->upper_margin++;
501 if (!var->left_margin) var->left_margin++;
32db7754
HV
502 ivtv_window.top = var->upper_margin - 1;
503 ivtv_window.left = var->left_margin - 1;
504
641ed49d 505 ivtvfb_set_display_window(itv, &ivtv_window);
32db7754 506
77aded6b
IA
507 /* Pass screen size back to yuv handler */
508 itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
509 itv->yuv_info.osd_full_h = ivtv_osd.lines;
510
32db7754
HV
511 /* Force update of yuv registers */
512 itv->yuv_info.yuv_forced_update = 1;
513
641ed49d 514 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
be383bd3
HV
515 var->xres, var->yres,
516 var->xres_virtual, var->yres_virtual,
517 var->bits_per_pixel);
32db7754 518
641ed49d 519 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
be383bd3 520 var->left_margin, var->upper_margin);
32db7754 521
641ed49d 522 IVTVFB_DEBUG_INFO("Display filter: %s\n",
be383bd3 523 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
641ed49d 524 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
32db7754
HV
525
526 return 0;
527}
528
529static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
530{
be383bd3
HV
531 struct osd_info *oi = itv->osd_info;
532
641ed49d 533 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
32db7754 534 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
cebfadff 535 strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
be383bd3
HV
536 fix->smem_start = oi->video_pbase;
537 fix->smem_len = oi->video_buffer_size;
32db7754 538 fix->type = FB_TYPE_PACKED_PIXELS;
be383bd3 539 fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
32db7754
HV
540 fix->xpanstep = 1;
541 fix->ypanstep = 1;
542 fix->ywrapstep = 0;
be383bd3 543 fix->line_length = oi->display_byte_stride;
32db7754
HV
544 fix->accel = FB_ACCEL_NONE;
545 return 0;
546}
547
548/* Check the requested display mode, returning -EINVAL if we can't
549 handle it. */
550
551static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
552{
be383bd3 553 struct osd_info *oi = itv->osd_info;
68a341a5
IA
554 int osd_height_limit;
555 u32 pixclock, hlimit, vlimit;
32db7754 556
641ed49d 557 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
32db7754 558
68a341a5
IA
559 /* Set base references for mode calcs. */
560 if (itv->is_50hz) {
561 pixclock = 84316;
562 hlimit = 776;
563 vlimit = 591;
564 osd_height_limit = 576;
565 }
566 else {
567 pixclock = 83926;
568 hlimit = 776;
569 vlimit = 495;
570 osd_height_limit = 480;
571 }
572
32db7754
HV
573 if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
574 var->transp.offset = 24;
575 var->transp.length = 8;
576 var->red.offset = 16;
577 var->red.length = 8;
578 var->green.offset = 8;
579 var->green.length = 8;
580 var->blue.offset = 0;
581 var->blue.length = 8;
582 }
583 else if (var->bits_per_pixel == 16) {
584 /* To find out the true mode, check green length */
585 switch (var->green.length) {
586 case 4:
32db7754
HV
587 var->red.offset = 8;
588 var->red.length = 4;
589 var->green.offset = 4;
590 var->green.length = 4;
591 var->blue.offset = 0;
592 var->blue.length = 4;
459a52fa
HV
593 var->transp.offset = 12;
594 var->transp.length = 1;
32db7754
HV
595 break;
596 case 5:
32db7754
HV
597 var->red.offset = 10;
598 var->red.length = 5;
599 var->green.offset = 5;
600 var->green.length = 5;
601 var->blue.offset = 0;
602 var->blue.length = 5;
459a52fa
HV
603 var->transp.offset = 15;
604 var->transp.length = 1;
32db7754
HV
605 break;
606 default:
32db7754
HV
607 var->red.offset = 11;
608 var->red.length = 5;
609 var->green.offset = 5;
610 var->green.length = 6;
611 var->blue.offset = 0;
612 var->blue.length = 5;
459a52fa
HV
613 var->transp.offset = 0;
614 var->transp.length = 0;
32db7754
HV
615 break;
616 }
617 }
618 else {
641ed49d 619 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
32db7754
HV
620 return -EINVAL;
621 }
622
623 /* Check the resolution */
6b1ec9da
IA
624 if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
625 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
626 var->xres, var->yres);
627 return -EINVAL;
32db7754 628 }
32db7754 629
6b1ec9da
IA
630 /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
631 if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
632 var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
633 var->xres_virtual < var->xres ||
634 var->yres_virtual < var->yres) {
635 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
636 var->xres_virtual, var->yres_virtual);
637 return -EINVAL;
32db7754
HV
638 }
639
640 /* Some extra checks if in 8 bit mode */
641 if (var->bits_per_pixel == 8) {
642 /* Width must be a multiple of 4 */
643 if (var->xres & 3) {
641ed49d 644 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
32db7754
HV
645 return -EINVAL;
646 }
647 if (var->xres_virtual & 3) {
641ed49d 648 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
32db7754
HV
649 return -EINVAL;
650 }
651 }
652 else if (var->bits_per_pixel == 16) {
653 /* Width must be a multiple of 2 */
654 if (var->xres & 1) {
641ed49d 655 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
32db7754
HV
656 return -EINVAL;
657 }
658 if (var->xres_virtual & 1) {
641ed49d 659 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
32db7754
HV
660 return -EINVAL;
661 }
662 }
663
664 /* Now check the offsets */
665 if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
641ed49d 666 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
be383bd3 667 var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
32db7754
HV
668 return -EINVAL;
669 }
670
671 /* Check pixel format */
672 if (var->nonstd > 1) {
641ed49d 673 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
32db7754
HV
674 return -EINVAL;
675 }
676
677 /* Check video mode */
678 if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
679 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
641ed49d 680 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
32db7754
HV
681 return -EINVAL;
682 }
683
684 /* Check the left & upper margins
685 If the margins are too large, just center the screen
686 (enforcing margins causes too many problems) */
687
688 if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) {
689 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
690 }
691 if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) {
692 var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2);
693 }
694
695 /* Maintain overall 'size' for a constant refresh rate */
68a341a5
IA
696 var->right_margin = hlimit - var->left_margin - var->xres;
697 var->lower_margin = vlimit - var->upper_margin - var->yres;
32db7754
HV
698
699 /* Fixed sync times */
700 var->hsync_len = 24;
701 var->vsync_len = 2;
702
703 /* Non-interlaced / interlaced mode is used to switch the OSD filter
704 on or off. Adjust the clock timings to maintain a constant
705 vertical refresh rate. */
32db7754 706 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
68a341a5
IA
707 var->pixclock = pixclock / 2;
708 else
709 var->pixclock = pixclock;
32db7754 710
641ed49d 711 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
be383bd3
HV
712 var->xres, var->yres,
713 var->xres_virtual, var->yres_virtual,
32db7754
HV
714 var->bits_per_pixel);
715
641ed49d 716 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
be383bd3 717 var->left_margin, var->upper_margin);
32db7754 718
641ed49d 719 IVTVFB_DEBUG_INFO("Display filter: %s\n",
be383bd3 720 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
641ed49d 721 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
32db7754
HV
722 return 0;
723}
724
725static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
726{
727 struct ivtv *itv = (struct ivtv *) info->par;
641ed49d 728 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
be383bd3 729 return _ivtvfb_check_var(var, itv);
32db7754
HV
730}
731
732static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
733{
734 u32 osd_pan_index;
735 struct ivtv *itv = (struct ivtv *) info->par;
736
737 osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8;
be383bd3 738 write_reg(osd_pan_index, 0x02A0C);
32db7754
HV
739
740 /* Pass this info back the yuv handler */
741 itv->yuv_info.osd_x_pan = var->xoffset;
742 itv->yuv_info.osd_y_pan = var->yoffset;
743 /* Force update of yuv registers */
744 itv->yuv_info.yuv_forced_update = 1;
745 return 0;
746}
747
748static int ivtvfb_set_par(struct fb_info *info)
749{
750 int rc = 0;
751 struct ivtv *itv = (struct ivtv *) info->par;
752
641ed49d 753 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
32db7754
HV
754
755 rc = ivtvfb_set_var(itv, &info->var);
756 ivtvfb_pan_display(&info->var, info);
be383bd3 757 ivtvfb_get_fix(itv, &info->fix);
32db7754
HV
758 return rc;
759}
760
761static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
762 unsigned blue, unsigned transp,
763 struct fb_info *info)
764{
765 u32 color, *palette;
be383bd3 766 struct ivtv *itv = (struct ivtv *)info->par;
32db7754
HV
767
768 if (regno >= info->cmap.len)
769 return -EINVAL;
770
771 color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
772 if (info->var.bits_per_pixel <= 8) {
773 write_reg(regno, 0x02a30);
774 write_reg(color, 0x02a34);
be383bd3 775 return 0;
32db7754 776 }
be383bd3
HV
777 if (regno >= 16)
778 return -EINVAL;
32db7754 779
be383bd3
HV
780 palette = info->pseudo_palette;
781 if (info->var.bits_per_pixel == 16) {
782 switch (info->var.green.length) {
783 case 4:
784 color = ((red & 0xf000) >> 4) |
785 ((green & 0xf000) >> 8) |
786 ((blue & 0xf000) >> 12);
787 break;
788 case 5:
789 color = ((red & 0xf800) >> 1) |
790 ((green & 0xf800) >> 6) |
791 ((blue & 0xf800) >> 11);
792 break;
793 case 6:
794 color = (red & 0xf800 ) |
795 ((green & 0xfc00) >> 5) |
796 ((blue & 0xf800) >> 11);
797 break;
32db7754 798 }
32db7754 799 }
be383bd3 800 palette[regno] = color;
32db7754
HV
801 return 0;
802}
803
804/* We don't really support blanking. All this does is enable or
805 disable the OSD. */
806static int ivtvfb_blank(int blank_mode, struct fb_info *info)
807{
808 struct ivtv *itv = (struct ivtv *)info->par;
809
641ed49d 810 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
32db7754
HV
811 switch (blank_mode) {
812 case FB_BLANK_UNBLANK:
813 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
814 break;
815 case FB_BLANK_NORMAL:
816 case FB_BLANK_HSYNC_SUSPEND:
817 case FB_BLANK_VSYNC_SUSPEND:
818 case FB_BLANK_POWERDOWN:
819 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
820 break;
821 }
822 return 0;
823}
824
825static struct fb_ops ivtvfb_ops = {
826 .owner = THIS_MODULE,
827 .fb_check_var = ivtvfb_check_var,
828 .fb_set_par = ivtvfb_set_par,
829 .fb_setcolreg = ivtvfb_setcolreg,
830 .fb_fillrect = cfb_fillrect,
831 .fb_copyarea = cfb_copyarea,
832 .fb_imageblit = cfb_imageblit,
833 .fb_cursor = NULL,
834 .fb_ioctl = ivtvfb_ioctl,
835 .fb_pan_display = ivtvfb_pan_display,
836 .fb_blank = ivtvfb_blank,
837};
838
839/* Initialization */
840
841
842/* Setup our initial video mode */
843static int ivtvfb_init_vidmode(struct ivtv *itv)
844{
be383bd3 845 struct osd_info *oi = itv->osd_info;
32db7754 846 struct v4l2_rect start_window;
be383bd3 847 int max_height;
32db7754 848
32db7754
HV
849 /* Color mode */
850
6b1ec9da
IA
851 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
852 osd_depth = 8;
be383bd3
HV
853 oi->bits_per_pixel = osd_depth;
854 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
32db7754
HV
855
856 /* Horizontal size & position */
857
6b1ec9da
IA
858 if (osd_xres > 720)
859 osd_xres = 720;
32db7754
HV
860
861 /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
862 if (osd_depth == 8)
863 osd_xres &= ~3;
864 else if (osd_depth == 16)
865 osd_xres &= ~1;
866
6b1ec9da 867 start_window.width = osd_xres ? osd_xres : 640;
32db7754
HV
868
869 /* Check horizontal start (osd_left). */
870 if (osd_left && osd_left + start_window.width > 721) {
641ed49d 871 IVTVFB_ERR("Invalid osd_left - assuming default\n");
32db7754
HV
872 osd_left = 0;
873 }
874
875 /* Hardware coords start at 0, user coords start at 1. */
be383bd3 876 osd_left--;
32db7754 877
be383bd3 878 start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
32db7754 879
be383bd3
HV
880 oi->display_byte_stride =
881 start_window.width * oi->bytes_per_pixel;
32db7754
HV
882
883 /* Vertical size & position */
884
885 max_height = itv->is_50hz ? 576 : 480;
886
be383bd3
HV
887 if (osd_yres > max_height)
888 osd_yres = max_height;
32db7754 889
6b1ec9da 890 start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
32db7754
HV
891
892 /* Check vertical start (osd_upper). */
893 if (osd_upper + start_window.height > max_height + 1) {
641ed49d 894 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
32db7754
HV
895 osd_upper = 0;
896 }
897
898 /* Hardware coords start at 0, user coords start at 1. */
be383bd3 899 osd_upper--;
32db7754
HV
900
901 start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
902
be383bd3
HV
903 oi->display_width = start_window.width;
904 oi->display_height = start_window.height;
32db7754
HV
905
906 /* Generate a valid fb_var_screeninfo */
907
be383bd3
HV
908 oi->ivtvfb_defined.xres = oi->display_width;
909 oi->ivtvfb_defined.yres = oi->display_height;
910 oi->ivtvfb_defined.xres_virtual = oi->display_width;
911 oi->ivtvfb_defined.yres_virtual = oi->display_height;
912 oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
913 oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
914 oi->ivtvfb_defined.left_margin = start_window.left + 1;
915 oi->ivtvfb_defined.upper_margin = start_window.top + 1;
916 oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
917 oi->ivtvfb_defined.nonstd = 0;
32db7754
HV
918
919 /* We've filled in the most data, let the usual mode check
920 routine fill in the rest. */
be383bd3 921 _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
32db7754
HV
922
923 /* Generate valid fb_fix_screeninfo */
924
be383bd3 925 ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
32db7754
HV
926
927 /* Generate valid fb_info */
928
be383bd3
HV
929 oi->ivtvfb_info.node = -1;
930 oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
931 oi->ivtvfb_info.fbops = &ivtvfb_ops;
932 oi->ivtvfb_info.par = itv;
933 oi->ivtvfb_info.var = oi->ivtvfb_defined;
934 oi->ivtvfb_info.fix = oi->ivtvfb_fix;
935 oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
936 oi->ivtvfb_info.fbops = &ivtvfb_ops;
32db7754
HV
937
938 /* Supply some monitor specs. Bogus values will do for now */
be383bd3
HV
939 oi->ivtvfb_info.monspecs.hfmin = 8000;
940 oi->ivtvfb_info.monspecs.hfmax = 70000;
941 oi->ivtvfb_info.monspecs.vfmin = 10;
942 oi->ivtvfb_info.monspecs.vfmax = 100;
32db7754
HV
943
944 /* Allocate color map */
be383bd3 945 if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
641ed49d 946 IVTVFB_ERR("abort, unable to alloc cmap\n");
32db7754
HV
947 return -ENOMEM;
948 }
949
950 /* Allocate the pseudo palette */
be383bd3 951 oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
32db7754 952
be383bd3 953 if (!oi->ivtvfb_info.pseudo_palette) {
641ed49d 954 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
32db7754
HV
955 return -ENOMEM;
956 }
957
958 return 0;
959}
960
961/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
962
963static int ivtvfb_init_io(struct ivtv *itv)
964{
be383bd3
HV
965 struct osd_info *oi = itv->osd_info;
966
26e9d599 967 mutex_lock(&itv->serialize_lock);
6e5eb591 968 if (ivtv_init_on_first_open(itv)) {
26e9d599 969 mutex_unlock(&itv->serialize_lock);
641ed49d 970 IVTVFB_ERR("Failed to initialize ivtv\n");
6e5eb591
HV
971 return -ENXIO;
972 }
26e9d599 973 mutex_unlock(&itv->serialize_lock);
6e5eb591 974
641ed49d 975 ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
32db7754
HV
976
977 /* The osd buffer size depends on the number of video buffers allocated
978 on the PVR350 itself. For now we'll hardcode the smallest osd buffer
979 size to prevent any overlap. */
be383bd3 980 oi->video_buffer_size = 1704960;
32db7754 981
be383bd3
HV
982 oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
983 oi->video_vbase = itv->dec_mem + oi->video_rbase;
32db7754 984
be383bd3 985 if (!oi->video_vbase) {
641ed49d 986 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
be383bd3 987 oi->video_buffer_size, oi->video_pbase);
32db7754
HV
988 return -EIO;
989 }
990
641ed49d 991 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
be383bd3
HV
992 oi->video_pbase, oi->video_vbase,
993 oi->video_buffer_size / 1024);
32db7754
HV
994
995#ifdef CONFIG_MTRR
996 {
997 /* Find the largest power of two that maps the whole buffer */
998 int size_shift = 31;
999
be383bd3 1000 while (!(oi->video_buffer_size & (1 << size_shift))) {
32db7754
HV
1001 size_shift--;
1002 }
1003 size_shift++;
be383bd3
HV
1004 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1005 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1006 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1007 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1008 if (mtrr_add(oi->fb_start_aligned_physaddr,
1009 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
32db7754 1010 MTRR_TYPE_WRCOMB, 1) < 0) {
641ed49d 1011 IVTVFB_INFO("disabled mttr\n");
be383bd3
HV
1012 oi->fb_start_aligned_physaddr = 0;
1013 oi->fb_end_aligned_physaddr = 0;
32db7754
HV
1014 }
1015 }
be383bd3 1016#endif
32db7754
HV
1017
1018 /* Blank the entire osd. */
be383bd3 1019 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
32db7754
HV
1020
1021 return 0;
1022}
1023
1024/* Release any memory we've grabbed & remove mtrr entry */
1025static void ivtvfb_release_buffers (struct ivtv *itv)
1026{
be383bd3
HV
1027 struct osd_info *oi = itv->osd_info;
1028
32db7754 1029 /* Release cmap */
13628032
AB
1030 if (oi->ivtvfb_info.cmap.len)
1031 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
32db7754
HV
1032
1033 /* Release pseudo palette */
be383bd3
HV
1034 if (oi->ivtvfb_info.pseudo_palette)
1035 kfree(oi->ivtvfb_info.pseudo_palette);
32db7754
HV
1036
1037#ifdef CONFIG_MTRR
be383bd3
HV
1038 if (oi->fb_end_aligned_physaddr) {
1039 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1040 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1041 }
1042#endif
32db7754 1043
be383bd3 1044 kfree(oi);
32db7754
HV
1045 itv->osd_info = NULL;
1046}
1047
1048/* Initialize the specified card */
1049
be383bd3 1050static int ivtvfb_init_card(struct ivtv *itv)
32db7754
HV
1051{
1052 int rc;
1053
1054 if (itv->osd_info) {
641ed49d 1055 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
32db7754
HV
1056 return -EBUSY;
1057 }
1058
1059 itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC);
14d5deba 1060 if (itv->osd_info == NULL) {
641ed49d 1061 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
32db7754
HV
1062 return -ENOMEM;
1063 }
1064
1065 /* Find & setup the OSD buffer */
be383bd3 1066 if ((rc = ivtvfb_init_io(itv)))
32db7754
HV
1067 return rc;
1068
1069 /* Set the startup video mode information */
be383bd3 1070 if ((rc = ivtvfb_init_vidmode(itv))) {
32db7754
HV
1071 ivtvfb_release_buffers(itv);
1072 return rc;
1073 }
1074
1075 /* Register the framebuffer */
1076 if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1077 ivtvfb_release_buffers(itv);
1078 return -EINVAL;
1079 }
1080
1081 itv->osd_video_pbase = itv->osd_info->video_pbase;
1082
1083 /* Set the card to the requested mode */
1084 ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1085
1086 /* Set color 0 to black */
1087 write_reg(0, 0x02a30);
1088 write_reg(0, 0x02a34);
1089
1090 /* Enable the osd */
1091 ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1092
32db7754
HV
1093 /* Allocate DMA */
1094 ivtv_udma_alloc(itv);
1095 return 0;
1096
1097}
1098
1099static int __init ivtvfb_init(void)
1100{
1101 struct ivtv *itv;
1102 int i, registered = 0;
1103
641ed49d
HV
1104 if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1105 printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
32db7754
HV
1106 IVTV_MAX_CARDS - 1);
1107 return -EINVAL;
1108 }
1109
1110 /* Locate & initialise all cards supporting an OSD. */
1111 for (i = 0; i < ivtv_cards_active; i++) {
641ed49d 1112 if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)
32db7754
HV
1113 continue;
1114 itv = ivtv_cards[i];
1115 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
1116 if (ivtvfb_init_card(itv) == 0) {
641ed49d 1117 IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
32db7754
HV
1118 registered++;
1119 }
1120 }
1121 }
1122 if (!registered) {
7b3a0d49 1123 printk(KERN_ERR "ivtvfb: no cards found");
32db7754
HV
1124 return -ENODEV;
1125 }
1126 return 0;
1127}
1128
1129static void ivtvfb_cleanup(void)
1130{
1131 struct ivtv *itv;
1132 int i;
1133
7b3a0d49 1134 printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
32db7754
HV
1135
1136 for (i = 0; i < ivtv_cards_active; i++) {
1137 itv = ivtv_cards[i];
1138 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
d343d7f9
HV
1139 if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1140 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
1141 return;
1142 }
641ed49d 1143 IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
32db7754 1144 ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
32db7754
HV
1145 ivtvfb_release_buffers(itv);
1146 itv->osd_video_pbase = 0;
1147 }
1148 }
1149}
1150
1151module_init(ivtvfb_init);
1152module_exit(ivtvfb_cleanup);