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