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