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