1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/fb.h>
44#include <linux/ivtvfb.h>
45#include <linux/slab.h>
46
47#ifdef CONFIG_MTRR
48#include <asm/mtrr.h>
49#endif
50
51#include "ivtv-driver.h"
52#include "ivtv-cards.h"
53#include "ivtv-i2c.h"
54#include "ivtv-udma.h"
55#include "ivtv-mailbox.h"
56#include "ivtv-firmware.h"
57
58
59static int ivtvfb_card_id = -1;
60static int ivtvfb_debug = 0;
61static bool osd_laced;
62static int osd_depth;
63static int osd_upper;
64static int osd_left;
65static int osd_yres;
66static int osd_xres;
67
68module_param(ivtvfb_card_id, int, 0444);
69module_param_named(debug,ivtvfb_debug, int, 0644);
70module_param(osd_laced, bool, 0444);
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
77MODULE_PARM_DESC(ivtvfb_card_id,
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
85
86
87
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,
96 "Bits per pixel - 8, 16, 32\n"
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
121#define IVTVFB_DBGFLG_WARN (1 << 0)
122#define IVTVFB_DBGFLG_INFO (1 << 1)
123
124#define IVTVFB_DEBUG(x, type, fmt, args...) \
125 do { \
126 if ((x) & ivtvfb_debug) \
127 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
128 } while (0)
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)
131
132
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)
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 {
149
150 unsigned long video_pbase;
151
152 u32 video_rbase;
153
154 volatile char __iomem *video_vbase;
155
156 u32 video_buffer_size;
157
158#ifdef CONFIG_MTRR
159
160 unsigned long fb_start_aligned_physaddr;
161
162 unsigned long fb_end_aligned_physaddr;
163#endif
164
165
166 int set_osd_coords_x;
167 int set_osd_coords_y;
168
169
170 int display_width;
171 int display_height;
172 int display_byte_stride;
173
174
175 int bits_per_pixel;
176 int bytes_per_pixel;
177
178
179 struct fb_info ivtvfb_info;
180 struct fb_var_screeninfo ivtvfb_defined;
181 struct fb_fix_screeninfo ivtvfb_fix;
182
183
184 struct fb_var_screeninfo fbvar_cur;
185 int blank_cur;
186 u32 palette_cur[256];
187 u32 pan_cur;
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
202
203static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
204 u32 *fblength)
205{
206 u32 data[CX2341X_MBOX_MAX_DATA];
207 int rc;
208
209 ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
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
216static int ivtvfb_get_osd_coords(struct ivtv *itv,
217 struct ivtv_osd_coords *osd)
218{
219 struct osd_info *oi = itv->osd_info;
220 u32 data[CX2341X_MBOX_MAX_DATA];
221
222 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
223
224 osd->offset = data[0] - oi->video_rbase;
225 osd->max_offset = oi->display_width * oi->display_height * 4;
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
233static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
234{
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;
241
242 return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
243 osd->offset + oi->video_rbase,
244 osd->pixel_stride,
245 osd->lines, osd->x, osd->y);
246}
247
248static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
249{
250 int osd_height_limit = itv->is_out_50hz ? 576 : 480;
251
252
253 if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
254 return -EINVAL;
255
256
257 if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
258 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
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) {
264 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
265 ivtv_window->left, ivtv_window->width);
266 ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
267 }
268
269
270 write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
271
272
273 write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
274
275
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
284static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
285 unsigned long ivtv_dest_addr, void __user *userbuf,
286 int size_in_bytes)
287{
288 DEFINE_WAIT(wait);
289 int got_sig = 0;
290
291 mutex_lock(&itv->udma.lock);
292
293 if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
294 mutex_unlock(&itv->udma.lock);
295 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
296 "Error with get_user_pages: %d bytes, %d pages returned\n",
297 size_in_bytes, itv->udma.page_count);
298
299
300 return -EIO;
301 }
302
303 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
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
309
310 while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
311 test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
312
313
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
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
330 return 0;
331}
332
333static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
334 unsigned long dest_offset, int count)
335{
336 DEFINE_WAIT(wait);
337 struct osd_info *oi = itv->osd_info;
338
339
340 if (count == 0) {
341 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
342 return -EINVAL;
343 }
344
345
346 if ((dest_offset + count) > oi->video_buffer_size) {
347 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
348 dest_offset + count, oi->video_buffer_size);
349 return -E2BIG;
350 }
351
352
353 if ((unsigned long)source & 3)
354 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
355 (unsigned long)source);
356
357 if (dest_offset & 3)
358 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
359
360 if (count & 3)
361 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
362
363
364 if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
365 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
366 (unsigned long)source);
367
368 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
369 dest_offset, (unsigned long)source,
370 count);
371 return -EINVAL;
372 }
373
374
375 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
376
377
378 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
379}
380
381static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
382 size_t count, loff_t *ppos)
383{
384 unsigned long p = *ppos;
385 void *dst;
386 int err = 0;
387 int dma_err;
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;
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
422
423
424 if (count >= 4096 &&
425 ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
426
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;
433 }
434
435 if ((count - lead) & 3)
436 tail = (count - lead) & 3;
437
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
446 if (tail && copy_from_user(dst, buf, tail))
447 return -EFAULT;
448 } else if (copy_from_user(dst, buf, count)) {
449 return -EFAULT;
450 }
451
452 if (!err)
453 *ppos += count;
454
455 return (err) ? err : count;
456}
457
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;
462 int rc = 0;
463
464 switch (cmd) {
465 case FBIOGET_VBLANK: {
466 struct fb_vblank vblank;
467 u32 trace;
468
469 memset(&vblank, 0, sizeof(struct fb_vblank));
470
471 vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
472 FB_VBLANK_HAVE_VSYNC;
473 trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
474 if (itv->is_out_50hz && trace > 312)
475 trace -= 312;
476 else if (itv->is_out_60hz && trace > 262)
477 trace -= 262;
478 if (trace == 1)
479 vblank.flags |= FB_VBLANK_VSYNCING;
480 vblank.count = itv->last_vsync_field;
481 vblank.vcount = trace;
482 vblank.hcount = 0;
483 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
484 return -EFAULT;
485 return 0;
486 }
487
488 case FBIO_WAITFORVSYNC:
489 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
490 if (!schedule_timeout(msecs_to_jiffies(50)))
491 rc = -ETIMEDOUT;
492 finish_wait(&itv->vsync_waitq, &wait);
493 return rc;
494
495 case IVTVFB_IOC_DMA_FRAME: {
496 struct ivtvfb_dma_frame args;
497
498 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
499 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
500 return -EFAULT;
501
502 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
503 }
504
505 default:
506 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
507 return -EINVAL;
508 }
509 return 0;
510}
511
512
513
514static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
515{
516 struct osd_info *oi = itv->osd_info;
517 struct ivtv_osd_coords ivtv_osd;
518 struct v4l2_rect ivtv_window;
519 int osd_mode = -1;
520
521 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
522
523
524 if (var->nonstd)
525 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
526 else
527 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
528
529
530 switch (var->bits_per_pixel) {
531 case 8:
532 osd_mode = IVTV_OSD_BPP_8;
533 break;
534 case 32:
535 osd_mode = IVTV_OSD_BPP_32;
536 break;
537 case 16:
538 switch (var->green.length) {
539 case 4:
540 osd_mode = IVTV_OSD_BPP_16_444;
541 break;
542 case 5:
543 osd_mode = IVTV_OSD_BPP_16_555;
544 break;
545 case 6:
546 osd_mode = IVTV_OSD_BPP_16_565;
547 break;
548 default:
549 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
550 }
551 break;
552 default:
553 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
554 }
555
556
557
558 if (osd_mode != -1) {
559 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
560 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
561 }
562
563 oi->bits_per_pixel = var->bits_per_pixel;
564 oi->bytes_per_pixel = var->bits_per_pixel / 8;
565
566
567 switch (var->vmode & FB_VMODE_MASK) {
568 case FB_VMODE_NONINTERLACED:
569 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
570 break;
571 case FB_VMODE_INTERLACED:
572 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
573 break;
574 default:
575 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
576 }
577
578
579 ivtvfb_get_osd_coords(itv, &ivtv_osd);
580
581
582 ivtv_osd.pixel_stride = var->xres_virtual;
583 ivtv_osd.lines = var->yres_virtual;
584 ivtv_osd.x = 0;
585 ivtv_osd.y = 0;
586 ivtvfb_set_osd_coords(itv, &ivtv_osd);
587
588
589
590 ivtv_window.width = var->xres;
591 ivtv_window.height = var->yres;
592
593
594 if (!var->upper_margin)
595 var->upper_margin++;
596 if (!var->left_margin)
597 var->left_margin++;
598 ivtv_window.top = var->upper_margin - 1;
599 ivtv_window.left = var->left_margin - 1;
600
601 ivtvfb_set_display_window(itv, &ivtv_window);
602
603
604 itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
605 itv->yuv_info.osd_full_h = ivtv_osd.lines;
606
607
608 itv->yuv_info.yuv_forced_update = 1;
609
610
611 memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
612
613 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
614 var->xres, var->yres,
615 var->xres_virtual, var->yres_virtual,
616 var->bits_per_pixel);
617
618 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
619 var->left_margin, var->upper_margin);
620
621 IVTVFB_DEBUG_INFO("Display filter: %s\n",
622 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
623 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
624
625 return 0;
626}
627
628static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
629{
630 struct osd_info *oi = itv->osd_info;
631
632 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
633 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
634 strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
635 fix->smem_start = oi->video_pbase;
636 fix->smem_len = oi->video_buffer_size;
637 fix->type = FB_TYPE_PACKED_PIXELS;
638 fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
639 fix->xpanstep = 1;
640 fix->ypanstep = 1;
641 fix->ywrapstep = 0;
642 fix->line_length = oi->display_byte_stride;
643 fix->accel = FB_ACCEL_NONE;
644 return 0;
645}
646
647
648
649
650static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
651{
652 struct osd_info *oi = itv->osd_info;
653 int osd_height_limit;
654 u32 pixclock, hlimit, vlimit;
655
656 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
657
658
659 if (itv->is_out_50hz) {
660 pixclock = 84316;
661 hlimit = 776;
662 vlimit = 591;
663 osd_height_limit = 576;
664 }
665 else {
666 pixclock = 83926;
667 hlimit = 776;
668 vlimit = 495;
669 osd_height_limit = 480;
670 }
671
672 if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
673 var->transp.offset = 24;
674 var->transp.length = 8;
675 var->red.offset = 16;
676 var->red.length = 8;
677 var->green.offset = 8;
678 var->green.length = 8;
679 var->blue.offset = 0;
680 var->blue.length = 8;
681 }
682 else if (var->bits_per_pixel == 16) {
683
684 switch (var->green.length) {
685 case 4:
686 var->red.offset = 8;
687 var->red.length = 4;
688 var->green.offset = 4;
689 var->green.length = 4;
690 var->blue.offset = 0;
691 var->blue.length = 4;
692 var->transp.offset = 12;
693 var->transp.length = 1;
694 break;
695 case 5:
696 var->red.offset = 10;
697 var->red.length = 5;
698 var->green.offset = 5;
699 var->green.length = 5;
700 var->blue.offset = 0;
701 var->blue.length = 5;
702 var->transp.offset = 15;
703 var->transp.length = 1;
704 break;
705 default:
706 var->red.offset = 11;
707 var->red.length = 5;
708 var->green.offset = 5;
709 var->green.length = 6;
710 var->blue.offset = 0;
711 var->blue.length = 5;
712 var->transp.offset = 0;
713 var->transp.length = 0;
714 break;
715 }
716 }
717 else {
718 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
719 return -EINVAL;
720 }
721
722
723 if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
724 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
725 var->xres, var->yres);
726 return -EINVAL;
727 }
728
729
730 if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
731 var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
732 var->xres_virtual < var->xres ||
733 var->yres_virtual < var->yres) {
734 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
735 var->xres_virtual, var->yres_virtual);
736 return -EINVAL;
737 }
738
739
740 if (var->bits_per_pixel == 8) {
741
742 if (var->xres & 3) {
743 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
744 return -EINVAL;
745 }
746 if (var->xres_virtual & 3) {
747 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
748 return -EINVAL;
749 }
750 }
751 else if (var->bits_per_pixel == 16) {
752
753 if (var->xres & 1) {
754 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
755 return -EINVAL;
756 }
757 if (var->xres_virtual & 1) {
758 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
759 return -EINVAL;
760 }
761 }
762
763
764 if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
765 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
766 var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
767 return -EINVAL;
768 }
769
770
771 if (var->nonstd > 1) {
772 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
773 return -EINVAL;
774 }
775
776
777 if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
778 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
779 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
780 return -EINVAL;
781 }
782
783
784
785
786
787 if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
788 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
789
790 if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
791 var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
792 var->yres) / 2);
793
794
795 var->right_margin = hlimit - var->left_margin - var->xres;
796 var->lower_margin = vlimit - var->upper_margin - var->yres;
797
798
799 var->hsync_len = 24;
800 var->vsync_len = 2;
801
802
803
804
805 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
806 var->pixclock = pixclock / 2;
807 else
808 var->pixclock = pixclock;
809
810 itv->osd_rect.width = var->xres;
811 itv->osd_rect.height = var->yres;
812
813 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
814 var->xres, var->yres,
815 var->xres_virtual, var->yres_virtual,
816 var->bits_per_pixel);
817
818 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
819 var->left_margin, var->upper_margin);
820
821 IVTVFB_DEBUG_INFO("Display filter: %s\n",
822 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
823 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
824 return 0;
825}
826
827static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
828{
829 struct ivtv *itv = (struct ivtv *) info->par;
830 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
831 return _ivtvfb_check_var(var, itv);
832}
833
834static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
835{
836 u32 osd_pan_index;
837 struct ivtv *itv = (struct ivtv *) info->par;
838
839 if (var->yoffset + info->var.yres > info->var.yres_virtual ||
840 var->xoffset + info->var.xres > info->var.xres_virtual)
841 return -EINVAL;
842
843 osd_pan_index = var->yoffset * info->fix.line_length
844 + var->xoffset * info->var.bits_per_pixel / 8;
845 write_reg(osd_pan_index, 0x02A0C);
846
847
848 itv->yuv_info.osd_x_pan = var->xoffset;
849 itv->yuv_info.osd_y_pan = var->yoffset;
850
851 itv->yuv_info.yuv_forced_update = 1;
852
853 itv->osd_info->pan_cur = osd_pan_index;
854 return 0;
855}
856
857static int ivtvfb_set_par(struct fb_info *info)
858{
859 int rc = 0;
860 struct ivtv *itv = (struct ivtv *) info->par;
861
862 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
863
864 rc = ivtvfb_set_var(itv, &info->var);
865 ivtvfb_pan_display(&info->var, info);
866 ivtvfb_get_fix(itv, &info->fix);
867 ivtv_firmware_check(itv, "ivtvfb_set_par");
868 return rc;
869}
870
871static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
872 unsigned blue, unsigned transp,
873 struct fb_info *info)
874{
875 u32 color, *palette;
876 struct ivtv *itv = (struct ivtv *)info->par;
877
878 if (regno >= info->cmap.len)
879 return -EINVAL;
880
881 color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
882 if (info->var.bits_per_pixel <= 8) {
883 write_reg(regno, 0x02a30);
884 write_reg(color, 0x02a34);
885 itv->osd_info->palette_cur[regno] = color;
886 return 0;
887 }
888 if (regno >= 16)
889 return -EINVAL;
890
891 palette = info->pseudo_palette;
892 if (info->var.bits_per_pixel == 16) {
893 switch (info->var.green.length) {
894 case 4:
895 color = ((red & 0xf000) >> 4) |
896 ((green & 0xf000) >> 8) |
897 ((blue & 0xf000) >> 12);
898 break;
899 case 5:
900 color = ((red & 0xf800) >> 1) |
901 ((green & 0xf800) >> 6) |
902 ((blue & 0xf800) >> 11);
903 break;
904 case 6:
905 color = (red & 0xf800 ) |
906 ((green & 0xfc00) >> 5) |
907 ((blue & 0xf800) >> 11);
908 break;
909 }
910 }
911 palette[regno] = color;
912 return 0;
913}
914
915
916
917static int ivtvfb_blank(int blank_mode, struct fb_info *info)
918{
919 struct ivtv *itv = (struct ivtv *)info->par;
920
921 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
922 switch (blank_mode) {
923 case FB_BLANK_UNBLANK:
924 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
925 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
926 break;
927 case FB_BLANK_NORMAL:
928 case FB_BLANK_HSYNC_SUSPEND:
929 case FB_BLANK_VSYNC_SUSPEND:
930 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
931 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
932 break;
933 case FB_BLANK_POWERDOWN:
934 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
935 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
936 break;
937 }
938 itv->osd_info->blank_cur = blank_mode;
939 return 0;
940}
941
942static struct fb_ops ivtvfb_ops = {
943 .owner = THIS_MODULE,
944 .fb_write = ivtvfb_write,
945 .fb_check_var = ivtvfb_check_var,
946 .fb_set_par = ivtvfb_set_par,
947 .fb_setcolreg = ivtvfb_setcolreg,
948 .fb_fillrect = cfb_fillrect,
949 .fb_copyarea = cfb_copyarea,
950 .fb_imageblit = cfb_imageblit,
951 .fb_cursor = NULL,
952 .fb_ioctl = ivtvfb_ioctl,
953 .fb_pan_display = ivtvfb_pan_display,
954 .fb_blank = ivtvfb_blank,
955};
956
957
958static void ivtvfb_restore(struct ivtv *itv)
959{
960 struct osd_info *oi = itv->osd_info;
961 int i;
962
963 ivtvfb_set_var(itv, &oi->fbvar_cur);
964 ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
965 for (i = 0; i < 256; i++) {
966 write_reg(i, 0x02a30);
967 write_reg(oi->palette_cur[i], 0x02a34);
968 }
969 write_reg(oi->pan_cur, 0x02a0c);
970}
971
972
973
974
975
976static int ivtvfb_init_vidmode(struct ivtv *itv)
977{
978 struct osd_info *oi = itv->osd_info;
979 struct v4l2_rect start_window;
980 int max_height;
981
982
983
984 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
985 osd_depth = 8;
986 oi->bits_per_pixel = osd_depth;
987 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
988
989
990
991 if (osd_xres > 720)
992 osd_xres = 720;
993
994
995 if (osd_depth == 8)
996 osd_xres &= ~3;
997 else if (osd_depth == 16)
998 osd_xres &= ~1;
999
1000 start_window.width = osd_xres ? osd_xres : 640;
1001
1002
1003 if (osd_left && osd_left + start_window.width > 721) {
1004 IVTVFB_ERR("Invalid osd_left - assuming default\n");
1005 osd_left = 0;
1006 }
1007
1008
1009 osd_left--;
1010
1011 start_window.left = osd_left >= 0 ?
1012 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
1013
1014 oi->display_byte_stride =
1015 start_window.width * oi->bytes_per_pixel;
1016
1017
1018
1019 max_height = itv->is_out_50hz ? 576 : 480;
1020
1021 if (osd_yres > max_height)
1022 osd_yres = max_height;
1023
1024 start_window.height = osd_yres ?
1025 osd_yres : itv->is_out_50hz ? 480 : 400;
1026
1027
1028 if (osd_upper + start_window.height > max_height + 1) {
1029 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1030 osd_upper = 0;
1031 }
1032
1033
1034 osd_upper--;
1035
1036 start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1037
1038 oi->display_width = start_window.width;
1039 oi->display_height = start_window.height;
1040
1041
1042
1043 oi->ivtvfb_defined.xres = oi->display_width;
1044 oi->ivtvfb_defined.yres = oi->display_height;
1045 oi->ivtvfb_defined.xres_virtual = oi->display_width;
1046 oi->ivtvfb_defined.yres_virtual = oi->display_height;
1047 oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
1048 oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1049 oi->ivtvfb_defined.left_margin = start_window.left + 1;
1050 oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1051 oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1052 oi->ivtvfb_defined.nonstd = 0;
1053
1054
1055
1056 _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1057
1058
1059
1060 ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1061
1062
1063
1064 oi->ivtvfb_info.node = -1;
1065 oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1066 oi->ivtvfb_info.fbops = &ivtvfb_ops;
1067 oi->ivtvfb_info.par = itv;
1068 oi->ivtvfb_info.var = oi->ivtvfb_defined;
1069 oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1070 oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1071 oi->ivtvfb_info.fbops = &ivtvfb_ops;
1072
1073
1074 oi->ivtvfb_info.monspecs.hfmin = 8000;
1075 oi->ivtvfb_info.monspecs.hfmax = 70000;
1076 oi->ivtvfb_info.monspecs.vfmin = 10;
1077 oi->ivtvfb_info.monspecs.vfmax = 100;
1078
1079
1080 if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1081 IVTVFB_ERR("abort, unable to alloc cmap\n");
1082 return -ENOMEM;
1083 }
1084
1085
1086 oi->ivtvfb_info.pseudo_palette =
1087 kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1088
1089 if (!oi->ivtvfb_info.pseudo_palette) {
1090 IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1091 return -ENOMEM;
1092 }
1093
1094 return 0;
1095}
1096
1097
1098
1099static int ivtvfb_init_io(struct ivtv *itv)
1100{
1101 struct osd_info *oi = itv->osd_info;
1102
1103 mutex_lock(&itv->serialize_lock);
1104 if (ivtv_init_on_first_open(itv)) {
1105 mutex_unlock(&itv->serialize_lock);
1106 IVTVFB_ERR("Failed to initialize ivtv\n");
1107 return -ENXIO;
1108 }
1109 mutex_unlock(&itv->serialize_lock);
1110
1111 if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1112 &oi->video_buffer_size) < 0) {
1113 IVTVFB_ERR("Firmware failed to respond\n");
1114 return -EIO;
1115 }
1116
1117
1118
1119
1120 oi->video_buffer_size = 1704960;
1121
1122 oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1123 oi->video_vbase = itv->dec_mem + oi->video_rbase;
1124
1125 if (!oi->video_vbase) {
1126 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1127 oi->video_buffer_size, oi->video_pbase);
1128 return -EIO;
1129 }
1130
1131 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1132 oi->video_pbase, oi->video_vbase,
1133 oi->video_buffer_size / 1024);
1134
1135#ifdef CONFIG_MTRR
1136 {
1137
1138 int size_shift = 31;
1139
1140 while (!(oi->video_buffer_size & (1 << size_shift))) {
1141 size_shift--;
1142 }
1143 size_shift++;
1144 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1145 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1146 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1147 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1148 if (mtrr_add(oi->fb_start_aligned_physaddr,
1149 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1150 MTRR_TYPE_WRCOMB, 1) < 0) {
1151 IVTVFB_INFO("disabled mttr\n");
1152 oi->fb_start_aligned_physaddr = 0;
1153 oi->fb_end_aligned_physaddr = 0;
1154 }
1155 }
1156#endif
1157
1158
1159 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1160
1161 return 0;
1162}
1163
1164
1165static void ivtvfb_release_buffers (struct ivtv *itv)
1166{
1167 struct osd_info *oi = itv->osd_info;
1168
1169
1170 if (oi->ivtvfb_info.cmap.len)
1171 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1172
1173
1174 if (oi->ivtvfb_info.pseudo_palette)
1175 kfree(oi->ivtvfb_info.pseudo_palette);
1176
1177#ifdef CONFIG_MTRR
1178 if (oi->fb_end_aligned_physaddr) {
1179 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1180 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1181 }
1182#endif
1183
1184 kfree(oi);
1185 itv->osd_info = NULL;
1186}
1187
1188
1189
1190static int ivtvfb_init_card(struct ivtv *itv)
1191{
1192 int rc;
1193
1194 if (itv->osd_info) {
1195 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1196 return -EBUSY;
1197 }
1198
1199 itv->osd_info = kzalloc(sizeof(struct osd_info),
1200 GFP_ATOMIC|__GFP_NOWARN);
1201 if (itv->osd_info == NULL) {
1202 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1203 return -ENOMEM;
1204 }
1205
1206
1207 rc = ivtvfb_init_io(itv);
1208 if (rc) {
1209 ivtvfb_release_buffers(itv);
1210 return rc;
1211 }
1212
1213
1214 if ((rc = ivtvfb_init_vidmode(itv))) {
1215 ivtvfb_release_buffers(itv);
1216 return rc;
1217 }
1218
1219
1220 if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1221 ivtvfb_release_buffers(itv);
1222 return -EINVAL;
1223 }
1224
1225 itv->osd_video_pbase = itv->osd_info->video_pbase;
1226
1227
1228 ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1229
1230
1231 write_reg(0, 0x02a30);
1232 write_reg(0, 0x02a34);
1233
1234
1235 ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1236
1237
1238 itv->ivtvfb_restore = ivtvfb_restore;
1239
1240
1241 ivtv_udma_alloc(itv);
1242 return 0;
1243
1244}
1245
1246static int __init ivtvfb_callback_init(struct device *dev, void *p)
1247{
1248 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1249 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1250
1251 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1252 if (ivtvfb_init_card(itv) == 0) {
1253 IVTVFB_INFO("Framebuffer registered on %s\n",
1254 itv->v4l2_dev.name);
1255 (*(int *)p)++;
1256 }
1257 }
1258 return 0;
1259}
1260
1261static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1262{
1263 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1264 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1265 struct osd_info *oi = itv->osd_info;
1266
1267 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1268 if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1269 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1270 itv->instance);
1271 return 0;
1272 }
1273 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1274 itv->ivtvfb_restore = NULL;
1275 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1276 ivtvfb_release_buffers(itv);
1277 itv->osd_video_pbase = 0;
1278 }
1279 return 0;
1280}
1281
1282static int __init ivtvfb_init(void)
1283{
1284 struct device_driver *drv;
1285 int registered = 0;
1286 int err;
1287
1288 if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1289 printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1290 IVTV_MAX_CARDS - 1);
1291 return -EINVAL;
1292 }
1293
1294 drv = driver_find("ivtv", &pci_bus_type);
1295 err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init);
1296 put_driver(drv);
1297 if (!registered) {
1298 printk(KERN_ERR "ivtvfb: no cards found\n");
1299 return -ENODEV;
1300 }
1301 return 0;
1302}
1303
1304static void ivtvfb_cleanup(void)
1305{
1306 struct device_driver *drv;
1307 int err;
1308
1309 printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
1310
1311 drv = driver_find("ivtv", &pci_bus_type);
1312 err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1313 put_driver(drv);
1314}
1315
1316module_init(ivtvfb_init);
1317module_exit(ivtvfb_cleanup);
1318