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