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