iwlwifi: don't include iwl-dev.h from iwl-devtrace.h
[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"
67ec09fd 51#include "ivtv-cards.h"
4e7ca40d 52#include "ivtv-i2c.h"
32db7754 53#include "ivtv-udma.h"
32db7754 54#include "ivtv-mailbox.h"
32db7754
HV
55
56/* card parameters */
641ed49d
HV
57static int ivtvfb_card_id = -1;
58static int ivtvfb_debug = 0;
32db7754 59static int osd_laced;
32db7754
HV
60static int osd_depth;
61static int osd_upper;
62static int osd_left;
63static int osd_yres;
64static int osd_xres;
65
641ed49d
HV
66module_param(ivtvfb_card_id, int, 0444);
67module_param_named(debug,ivtvfb_debug, int, 0644);
32db7754 68module_param(osd_laced, bool, 0444);
32db7754
HV
69module_param(osd_depth, int, 0444);
70module_param(osd_upper, int, 0444);
71module_param(osd_left, int, 0444);
72module_param(osd_yres, int, 0444);
73module_param(osd_xres, int, 0444);
74
641ed49d 75MODULE_PARM_DESC(ivtvfb_card_id,
32db7754
HV
76 "Only use framebuffer of the specified ivtv card (0-31)\n"
77 "\t\t\tdefault -1: initialize all available framebuffers");
78
79MODULE_PARM_DESC(debug,
80 "Debug level (bitmask). Default: errors only\n"
81 "\t\t\t(debug = 3 gives full debugging)");
82
32db7754
HV
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
87MODULE_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
93MODULE_PARM_DESC(osd_depth,
be383bd3 94 "Bits per pixel - 8, 16, 32\n"
32db7754
HV
95 "\t\t\tdefault 8");
96
97MODULE_PARM_DESC(osd_upper,
98 "Vertical start position\n"
99 "\t\t\tdefault 0 (Centered)");
100
101MODULE_PARM_DESC(osd_left,
102 "Horizontal start position\n"
103 "\t\t\tdefault 0 (Centered)");
104
105MODULE_PARM_DESC(osd_yres,
106 "Display height\n"
107 "\t\t\tdefault 480 (PAL)\n"
108 "\t\t\t 400 (NTSC)");
109
110MODULE_PARM_DESC(osd_xres,
111 "Display width\n"
112 "\t\t\tdefault 640");
113
114MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
115MODULE_LICENSE("GPL");
116
117/* --------------------------------------------------------------------- */
118
641ed49d
HV
119#define IVTVFB_DBGFLG_WARN (1 << 0)
120#define IVTVFB_DBGFLG_INFO (1 << 1)
32db7754 121
641ed49d 122#define IVTVFB_DEBUG(x, type, fmt, args...) \
32db7754 123 do { \
641ed49d 124 if ((x) & ivtvfb_debug) \
67ec09fd 125 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
32db7754 126 } while (0)
641ed49d
HV
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)
32db7754
HV
129
130/* Standard kernel messages */
67ec09fd
HV
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)
32db7754
HV
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
146struct osd_info {
32db7754
HV
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
182struct 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
641ed49d 195static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
32db7754
HV
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
641ed49d 207static int ivtvfb_get_osd_coords(struct ivtv *itv,
32db7754
HV
208 struct ivtv_osd_coords *osd)
209{
be383bd3 210 struct osd_info *oi = itv->osd_info;
32db7754
HV
211 u32 data[CX2341X_MBOX_MAX_DATA];
212
213 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
214
be383bd3
HV
215 osd->offset = data[0] - oi->video_rbase;
216 osd->max_offset = oi->display_width * oi->display_height * 4;
32db7754
HV
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
641ed49d 224static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
32db7754 225{
be383bd3
HV
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;
32db7754
HV
232
233 return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
be383bd3 234 osd->offset + oi->video_rbase,
32db7754
HV
235 osd->pixel_stride,
236 osd->lines, osd->x, osd->y);
237}
238
641ed49d 239static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
32db7754 240{
32db7754
HV
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) {
641ed49d 249 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
32db7754
HV
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) {
641ed49d 255 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
32db7754
HV
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
641ed49d 275static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
32db7754
HV
276 unsigned long ivtv_dest_addr, void __user *userbuf,
277 int size_in_bytes)
278{
279 DEFINE_WAIT(wait);
32db7754
HV
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);
641ed49d 286 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
32db7754
HV
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
641ed49d 294 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
32db7754
HV
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 */
ec105a42
HV
301 while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
302 test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
32db7754
HV
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
c777549f 321 return 0;
32db7754
HV
322}
323
641ed49d 324static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
be383bd3 325 unsigned long dest_offset, int count)
32db7754
HV
326{
327 DEFINE_WAIT(wait);
aaf9fa21 328 struct osd_info *oi = itv->osd_info;
32db7754
HV
329
330 /* Nothing to do */
331 if (count == 0) {
641ed49d 332 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
32db7754
HV
333 return -EINVAL;
334 }
335
336 /* Check Total FB Size */
aaf9fa21 337 if ((dest_offset + count) > oi->video_buffer_size) {
641ed49d 338 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
aaf9fa21 339 dest_offset + count, oi->video_buffer_size);
32db7754
HV
340 return -E2BIG;
341 }
342
343 /* Not fatal, but will have undesirable results */
344 if ((unsigned long)source & 3)
641ed49d 345 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
be383bd3 346 (unsigned long)source);
32db7754
HV
347
348 if (dest_offset & 3)
641ed49d 349 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
32db7754
HV
350
351 if (count & 3)
641ed49d 352 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
32db7754
HV
353
354 /* Check Source */
355 if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
641ed49d 356 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
32db7754
HV
357 (unsigned long)source);
358
641ed49d 359 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
32db7754
HV
360 dest_offset, (unsigned long)source,
361 count);
362 return -EINVAL;
363 }
364
365 /* OSD Address to send DMA to */
33c0fcad 366 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
32db7754
HV
367
368 /* Fill Buffers */
641ed49d 369 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
32db7754
HV
370}
371
4cbeb371 372static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
4ee0e42b 373 size_t count, loff_t *ppos)
4cbeb371
IA
374{
375 unsigned long p = *ppos;
376 void *dst;
377 int err = 0;
c777549f 378 int dma_err;
4cbeb371
IA
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;
4cbeb371
IA
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
c777549f
IA
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;
4cbeb371 424 }
c777549f
IA
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;
4cbeb371
IA
441 }
442
443 if (!err)
444 *ppos += count;
445
446 return (err) ? err : count;
447}
448
32db7754
HV
449static 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;
be383bd3 453 int rc = 0;
32db7754
HV
454
455 switch (cmd) {
32db7754
HV
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;
be383bd3 462 trace = read_reg(0x028c0) >> 16;
c777549f
IA
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;
a158f355 469 vblank.count = itv->last_vsync_field;
32db7754
HV
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
be383bd3 477 case FBIO_WAITFORVSYNC:
32db7754 478 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
c777549f
IA
479 if (!schedule_timeout(msecs_to_jiffies(50)))
480 rc = -ETIMEDOUT;
be383bd3 481 finish_wait(&itv->vsync_waitq, &wait);
32db7754 482 return rc;
32db7754 483
d715e766
HV
484 case IVTVFB_IOC_DMA_FRAME: {
485 struct ivtvfb_dma_frame args;
32db7754 486
641ed49d 487 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
32db7754
HV
488 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
489 return -EFAULT;
490
641ed49d 491 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
32db7754
HV
492 }
493
494 default:
641ed49d 495 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
32db7754
HV
496 return -EINVAL;
497 }
498 return 0;
499}
500
501/* Framebuffer device handling */
502
503static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
504{
aaf9fa21 505 struct osd_info *oi = itv->osd_info;
32db7754
HV
506 struct ivtv_osd_coords ivtv_osd;
507 struct v4l2_rect ivtv_window;
aaf9fa21 508 int osd_mode = -1;
32db7754 509
641ed49d 510 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
32db7754
HV
511
512 /* Select color space */
513 if (var->nonstd) /* YUV */
be383bd3 514 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
32db7754 515 else /* RGB */
be383bd3 516 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
32db7754 517
aaf9fa21 518 /* Set the color mode */
32db7754
HV
519 switch (var->bits_per_pixel) {
520 case 8:
aaf9fa21 521 osd_mode = IVTV_OSD_BPP_8;
32db7754
HV
522 break;
523 case 32:
aaf9fa21 524 osd_mode = IVTV_OSD_BPP_32;
32db7754
HV
525 break;
526 case 16:
527 switch (var->green.length) {
528 case 4:
aaf9fa21 529 osd_mode = IVTV_OSD_BPP_16_444;
32db7754
HV
530 break;
531 case 5:
aaf9fa21 532 osd_mode = IVTV_OSD_BPP_16_555;
32db7754
HV
533 break;
534 case 6:
aaf9fa21 535 osd_mode = IVTV_OSD_BPP_16_565;
32db7754
HV
536 break;
537 default:
641ed49d 538 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
32db7754
HV
539 }
540 break;
541 default:
641ed49d 542 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
32db7754
HV
543 }
544
6659e3ed
IA
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) {
aaf9fa21
IA
548 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
549 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
aaf9fa21
IA
550 }
551
552 oi->bits_per_pixel = var->bits_per_pixel;
553 oi->bytes_per_pixel = var->bits_per_pixel / 8;
32db7754
HV
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:
641ed49d 564 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
32db7754
HV
565 }
566
567 /* Read the current osd info */
641ed49d 568 ivtvfb_get_osd_coords(itv, &ivtv_osd);
32db7754
HV
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;
641ed49d 575 ivtvfb_set_osd_coords(itv, &ivtv_osd);
32db7754
HV
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 */
be383bd3
HV
583 if (!var->upper_margin) var->upper_margin++;
584 if (!var->left_margin) var->left_margin++;
32db7754
HV
585 ivtv_window.top = var->upper_margin - 1;
586 ivtv_window.left = var->left_margin - 1;
587
641ed49d 588 ivtvfb_set_display_window(itv, &ivtv_window);
32db7754 589
77aded6b
IA
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
32db7754
HV
594 /* Force update of yuv registers */
595 itv->yuv_info.yuv_forced_update = 1;
596
641ed49d 597 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
be383bd3
HV
598 var->xres, var->yres,
599 var->xres_virtual, var->yres_virtual,
600 var->bits_per_pixel);
32db7754 601
641ed49d 602 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
be383bd3 603 var->left_margin, var->upper_margin);
32db7754 604
641ed49d 605 IVTVFB_DEBUG_INFO("Display filter: %s\n",
be383bd3 606 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
641ed49d 607 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
32db7754
HV
608
609 return 0;
610}
611
612static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
613{
be383bd3
HV
614 struct osd_info *oi = itv->osd_info;
615
641ed49d 616 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
32db7754 617 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
cebfadff 618 strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
be383bd3
HV
619 fix->smem_start = oi->video_pbase;
620 fix->smem_len = oi->video_buffer_size;
32db7754 621 fix->type = FB_TYPE_PACKED_PIXELS;
be383bd3 622 fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
32db7754
HV
623 fix->xpanstep = 1;
624 fix->ypanstep = 1;
625 fix->ywrapstep = 0;
be383bd3 626 fix->line_length = oi->display_byte_stride;
32db7754
HV
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
634static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
635{
be383bd3 636 struct osd_info *oi = itv->osd_info;
68a341a5
IA
637 int osd_height_limit;
638 u32 pixclock, hlimit, vlimit;
32db7754 639
641ed49d 640 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
32db7754 641
68a341a5
IA
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
32db7754
HV
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:
32db7754
HV
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;
459a52fa
HV
676 var->transp.offset = 12;
677 var->transp.length = 1;
32db7754
HV
678 break;
679 case 5:
32db7754
HV
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;
459a52fa
HV
686 var->transp.offset = 15;
687 var->transp.length = 1;
32db7754
HV
688 break;
689 default:
32db7754
HV
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;
459a52fa
HV
696 var->transp.offset = 0;
697 var->transp.length = 0;
32db7754
HV
698 break;
699 }
700 }
701 else {
641ed49d 702 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
32db7754
HV
703 return -EINVAL;
704 }
705
706 /* Check the resolution */
6b1ec9da
IA
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;
32db7754 711 }
32db7754 712
6b1ec9da
IA
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;
32db7754
HV
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) {
641ed49d 727 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
32db7754
HV
728 return -EINVAL;
729 }
730 if (var->xres_virtual & 3) {
641ed49d 731 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
32db7754
HV
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) {
641ed49d 738 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
32db7754
HV
739 return -EINVAL;
740 }
741 if (var->xres_virtual & 1) {
641ed49d 742 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
32db7754
HV
743 return -EINVAL;
744 }
745 }
746
747 /* Now check the offsets */
748 if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
641ed49d 749 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
be383bd3 750 var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
32db7754
HV
751 return -EINVAL;
752 }
753
754 /* Check pixel format */
755 if (var->nonstd > 1) {
641ed49d 756 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
32db7754
HV
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)) {
641ed49d 763 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
32db7754
HV
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 */
68a341a5
IA
779 var->right_margin = hlimit - var->left_margin - var->xres;
780 var->lower_margin = vlimit - var->upper_margin - var->yres;
32db7754
HV
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. */
32db7754 789 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
68a341a5
IA
790 var->pixclock = pixclock / 2;
791 else
792 var->pixclock = pixclock;
32db7754 793
37f89f95
HV
794 itv->osd_rect.width = var->xres;
795 itv->osd_rect.height = var->yres;
796
641ed49d 797 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
be383bd3
HV
798 var->xres, var->yres,
799 var->xres_virtual, var->yres_virtual,
32db7754
HV
800 var->bits_per_pixel);
801
641ed49d 802 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
be383bd3 803 var->left_margin, var->upper_margin);
32db7754 804
641ed49d 805 IVTVFB_DEBUG_INFO("Display filter: %s\n",
be383bd3 806 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
641ed49d 807 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
32db7754
HV
808 return 0;
809}
810
811static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
812{
813 struct ivtv *itv = (struct ivtv *) info->par;
641ed49d 814 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
be383bd3 815 return _ivtvfb_check_var(var, itv);
32db7754
HV
816}
817
818static 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;
be383bd3 824 write_reg(osd_pan_index, 0x02A0C);
32db7754
HV
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
834static int ivtvfb_set_par(struct fb_info *info)
835{
836 int rc = 0;
837 struct ivtv *itv = (struct ivtv *) info->par;
838
641ed49d 839 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
32db7754
HV
840
841 rc = ivtvfb_set_var(itv, &info->var);
842 ivtvfb_pan_display(&info->var, info);
be383bd3 843 ivtvfb_get_fix(itv, &info->fix);
32db7754
HV
844 return rc;
845}
846
847static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
848 unsigned blue, unsigned transp,
849 struct fb_info *info)
850{
851 u32 color, *palette;
be383bd3 852 struct ivtv *itv = (struct ivtv *)info->par;
32db7754
HV
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);
be383bd3 861 return 0;
32db7754 862 }
be383bd3
HV
863 if (regno >= 16)
864 return -EINVAL;
32db7754 865
be383bd3
HV
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;
32db7754 884 }
32db7754 885 }
be383bd3 886 palette[regno] = color;
32db7754
HV
887 return 0;
888}
889
890/* We don't really support blanking. All this does is enable or
891 disable the OSD. */
892static int ivtvfb_blank(int blank_mode, struct fb_info *info)
893{
894 struct ivtv *itv = (struct ivtv *)info->par;
895
641ed49d 896 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
32db7754
HV
897 switch (blank_mode) {
898 case FB_BLANK_UNBLANK:
899 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
67ec09fd 900 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
32db7754
HV
901 break;
902 case FB_BLANK_NORMAL:
903 case FB_BLANK_HSYNC_SUSPEND:
904 case FB_BLANK_VSYNC_SUSPEND:
4e7ca40d 905 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
67ec09fd 906 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
4e7ca40d 907 break;
32db7754 908 case FB_BLANK_POWERDOWN:
67ec09fd 909 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
32db7754
HV
910 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
911 break;
912 }
913 return 0;
914}
915
916static struct fb_ops ivtvfb_ops = {
917 .owner = THIS_MODULE,
4cbeb371 918 .fb_write = ivtvfb_write,
32db7754
HV
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 */
935static int ivtvfb_init_vidmode(struct ivtv *itv)
936{
be383bd3 937 struct osd_info *oi = itv->osd_info;
32db7754 938 struct v4l2_rect start_window;
be383bd3 939 int max_height;
32db7754 940
32db7754
HV
941 /* Color mode */
942
6b1ec9da
IA
943 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
944 osd_depth = 8;
be383bd3
HV
945 oi->bits_per_pixel = osd_depth;
946 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
32db7754
HV
947
948 /* Horizontal size & position */
949
6b1ec9da
IA
950 if (osd_xres > 720)
951 osd_xres = 720;
32db7754
HV
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
6b1ec9da 959 start_window.width = osd_xres ? osd_xres : 640;
32db7754
HV
960
961 /* Check horizontal start (osd_left). */
962 if (osd_left && osd_left + start_window.width > 721) {
641ed49d 963 IVTVFB_ERR("Invalid osd_left - assuming default\n");
32db7754
HV
964 osd_left = 0;
965 }
966
967 /* Hardware coords start at 0, user coords start at 1. */
be383bd3 968 osd_left--;
32db7754 969
be383bd3 970 start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
32db7754 971
be383bd3
HV
972 oi->display_byte_stride =
973 start_window.width * oi->bytes_per_pixel;
32db7754
HV
974
975 /* Vertical size & position */
976
977 max_height = itv->is_50hz ? 576 : 480;
978
be383bd3
HV
979 if (osd_yres > max_height)
980 osd_yres = max_height;
32db7754 981
6b1ec9da 982 start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
32db7754
HV
983
984 /* Check vertical start (osd_upper). */
985 if (osd_upper + start_window.height > max_height + 1) {
641ed49d 986 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
32db7754
HV
987 osd_upper = 0;
988 }
989
990 /* Hardware coords start at 0, user coords start at 1. */
be383bd3 991 osd_upper--;
32db7754
HV
992
993 start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
994
be383bd3
HV
995 oi->display_width = start_window.width;
996 oi->display_height = start_window.height;
32db7754
HV
997
998 /* Generate a valid fb_var_screeninfo */
999
be383bd3
HV
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;
32db7754
HV
1010
1011 /* We've filled in the most data, let the usual mode check
1012 routine fill in the rest. */
be383bd3 1013 _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
32db7754
HV
1014
1015 /* Generate valid fb_fix_screeninfo */
1016
be383bd3 1017 ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
32db7754
HV
1018
1019 /* Generate valid fb_info */
1020
be383bd3
HV
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;
32db7754
HV
1029
1030 /* Supply some monitor specs. Bogus values will do for now */
be383bd3
HV
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;
32db7754
HV
1035
1036 /* Allocate color map */
be383bd3 1037 if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
641ed49d 1038 IVTVFB_ERR("abort, unable to alloc cmap\n");
32db7754
HV
1039 return -ENOMEM;
1040 }
1041
1042 /* Allocate the pseudo palette */
3f98387e
HV
1043 oi->ivtvfb_info.pseudo_palette =
1044 kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
32db7754 1045
be383bd3 1046 if (!oi->ivtvfb_info.pseudo_palette) {
641ed49d 1047 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
32db7754
HV
1048 return -ENOMEM;
1049 }
1050
1051 return 0;
1052}
1053
1054/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1055
1056static int ivtvfb_init_io(struct ivtv *itv)
1057{
be383bd3
HV
1058 struct osd_info *oi = itv->osd_info;
1059
26e9d599 1060 mutex_lock(&itv->serialize_lock);
6e5eb591 1061 if (ivtv_init_on_first_open(itv)) {
26e9d599 1062 mutex_unlock(&itv->serialize_lock);
641ed49d 1063 IVTVFB_ERR("Failed to initialize ivtv\n");
6e5eb591
HV
1064 return -ENXIO;
1065 }
26e9d599 1066 mutex_unlock(&itv->serialize_lock);
6e5eb591 1067
641ed49d 1068 ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
32db7754
HV
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. */
be383bd3 1073 oi->video_buffer_size = 1704960;
32db7754 1074
be383bd3
HV
1075 oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1076 oi->video_vbase = itv->dec_mem + oi->video_rbase;
32db7754 1077
be383bd3 1078 if (!oi->video_vbase) {
641ed49d 1079 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
be383bd3 1080 oi->video_buffer_size, oi->video_pbase);
32db7754
HV
1081 return -EIO;
1082 }
1083
641ed49d 1084 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
be383bd3
HV
1085 oi->video_pbase, oi->video_vbase,
1086 oi->video_buffer_size / 1024);
32db7754
HV
1087
1088#ifdef CONFIG_MTRR
1089 {
1090 /* Find the largest power of two that maps the whole buffer */
1091 int size_shift = 31;
1092
be383bd3 1093 while (!(oi->video_buffer_size & (1 << size_shift))) {
32db7754
HV
1094 size_shift--;
1095 }
1096 size_shift++;
be383bd3
HV
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,
32db7754 1103 MTRR_TYPE_WRCOMB, 1) < 0) {
641ed49d 1104 IVTVFB_INFO("disabled mttr\n");
be383bd3
HV
1105 oi->fb_start_aligned_physaddr = 0;
1106 oi->fb_end_aligned_physaddr = 0;
32db7754
HV
1107 }
1108 }
be383bd3 1109#endif
32db7754
HV
1110
1111 /* Blank the entire osd. */
be383bd3 1112 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
32db7754
HV
1113
1114 return 0;
1115}
1116
1117/* Release any memory we've grabbed & remove mtrr entry */
1118static void ivtvfb_release_buffers (struct ivtv *itv)
1119{
be383bd3
HV
1120 struct osd_info *oi = itv->osd_info;
1121
32db7754 1122 /* Release cmap */
13628032
AB
1123 if (oi->ivtvfb_info.cmap.len)
1124 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
32db7754
HV
1125
1126 /* Release pseudo palette */
be383bd3
HV
1127 if (oi->ivtvfb_info.pseudo_palette)
1128 kfree(oi->ivtvfb_info.pseudo_palette);
32db7754
HV
1129
1130#ifdef CONFIG_MTRR
be383bd3
HV
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
32db7754 1136
be383bd3 1137 kfree(oi);
32db7754
HV
1138 itv->osd_info = NULL;
1139}
1140
1141/* Initialize the specified card */
1142
be383bd3 1143static int ivtvfb_init_card(struct ivtv *itv)
32db7754
HV
1144{
1145 int rc;
1146
1147 if (itv->osd_info) {
641ed49d 1148 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
32db7754
HV
1149 return -EBUSY;
1150 }
1151
3f98387e
HV
1152 itv->osd_info = kzalloc(sizeof(struct osd_info),
1153 GFP_ATOMIC|__GFP_NOWARN);
14d5deba 1154 if (itv->osd_info == NULL) {
641ed49d 1155 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
32db7754
HV
1156 return -ENOMEM;
1157 }
1158
1159 /* Find & setup the OSD buffer */
be383bd3 1160 if ((rc = ivtvfb_init_io(itv)))
32db7754
HV
1161 return rc;
1162
1163 /* Set the startup video mode information */
be383bd3 1164 if ((rc = ivtvfb_init_vidmode(itv))) {
32db7754
HV
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
32db7754
HV
1187 /* Allocate DMA */
1188 ivtv_udma_alloc(itv);
1189 return 0;
1190
1191}
1192
67ec09fd
HV
1193static int __init ivtvfb_callback_init(struct device *dev, void *p)
1194{
1195 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
8ac05ae3 1196 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
67ec09fd
HV
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",
8ac05ae3 1201 itv->v4l2_dev.name);
67ec09fd
HV
1202 (*(int *)p)++;
1203 }
1204 }
1205 return 0;
1206}
1207
1208static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1209{
1210 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
8ac05ae3 1211 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
67ec09fd
HV
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
32db7754
HV
1227static int __init ivtvfb_init(void)
1228{
67ec09fd
HV
1229 struct device_driver *drv;
1230 int registered = 0;
1231 int err;
32db7754 1232
641ed49d
HV
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",
32db7754
HV
1235 IVTV_MAX_CARDS - 1);
1236 return -EINVAL;
1237 }
1238
67ec09fd
HV
1239 drv = driver_find("ivtv", &pci_bus_type);
1240 err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1241 put_driver(drv);
32db7754 1242 if (!registered) {
67ec09fd 1243 printk(KERN_ERR "ivtvfb: no cards found\n");
32db7754
HV
1244 return -ENODEV;
1245 }
1246 return 0;
1247}
1248
1249static void ivtvfb_cleanup(void)
1250{
67ec09fd
HV
1251 struct device_driver *drv;
1252 int err;
32db7754 1253
7b3a0d49 1254 printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
32db7754 1255
67ec09fd
HV
1256 drv = driver_find("ivtv", &pci_bus_type);
1257 err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1258 put_driver(drv);
32db7754
HV
1259}
1260
1261module_init(ivtvfb_init);
1262module_exit(ivtvfb_cleanup);