This source file includes following definitions.
- ivtvfb_get_framebuffer
- ivtvfb_get_osd_coords
- ivtvfb_set_osd_coords
- ivtvfb_set_display_window
- ivtvfb_prep_dec_dma_to_device
- ivtvfb_prep_frame
- ivtvfb_write
- ivtvfb_ioctl
- ivtvfb_set_var
- ivtvfb_get_fix
- _ivtvfb_check_var
- ivtvfb_check_var
- ivtvfb_pan_display
- ivtvfb_set_par
- ivtvfb_setcolreg
- ivtvfb_blank
- ivtvfb_restore
- ivtvfb_init_vidmode
- ivtvfb_init_io
- ivtvfb_release_buffers
- ivtvfb_init_card
- ivtvfb_callback_init
- ivtvfb_callback_cleanup
- ivtvfb_init
- ivtvfb_cleanup
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 #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"
35
36 #include <linux/fb.h>
37 #include <linux/ivtvfb.h>
38
39 #ifdef CONFIG_X86_64
40 #include <asm/pat.h>
41 #endif
42
43
44 static int ivtvfb_card_id = -1;
45 static int ivtvfb_debug = 0;
46 static bool ivtvfb_force_pat = IS_ENABLED(CONFIG_VIDEO_FB_IVTV_FORCE_PAT);
47 static bool osd_laced;
48 static int osd_depth;
49 static int osd_upper;
50 static int osd_left;
51 static int osd_yres;
52 static int osd_xres;
53
54 module_param(ivtvfb_card_id, int, 0444);
55 module_param_named(debug,ivtvfb_debug, int, 0644);
56 module_param_named(force_pat, ivtvfb_force_pat, bool, 0644);
57 module_param(osd_laced, bool, 0444);
58 module_param(osd_depth, int, 0444);
59 module_param(osd_upper, int, 0444);
60 module_param(osd_left, int, 0444);
61 module_param(osd_yres, int, 0444);
62 module_param(osd_xres, int, 0444);
63
64 MODULE_PARM_DESC(ivtvfb_card_id,
65 "Only use framebuffer of the specified ivtv card (0-31)\n"
66 "\t\t\tdefault -1: initialize all available framebuffers");
67
68 MODULE_PARM_DESC(debug,
69 "Debug level (bitmask). Default: errors only\n"
70 "\t\t\t(debug = 3 gives full debugging)");
71
72 MODULE_PARM_DESC(force_pat,
73 "Force initialization on x86 PAT-enabled systems (bool).\n");
74
75
76
77
78
79 MODULE_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
85 MODULE_PARM_DESC(osd_depth,
86 "Bits per pixel - 8, 16, 32\n"
87 "\t\t\tdefault 8");
88
89 MODULE_PARM_DESC(osd_upper,
90 "Vertical start position\n"
91 "\t\t\tdefault 0 (Centered)");
92
93 MODULE_PARM_DESC(osd_left,
94 "Horizontal start position\n"
95 "\t\t\tdefault 0 (Centered)");
96
97 MODULE_PARM_DESC(osd_yres,
98 "Display height\n"
99 "\t\t\tdefault 480 (PAL)\n"
100 "\t\t\t 400 (NTSC)");
101
102 MODULE_PARM_DESC(osd_xres,
103 "Display width\n"
104 "\t\t\tdefault 640");
105
106 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
107 MODULE_LICENSE("GPL");
108
109
110
111 #define IVTVFB_DBGFLG_WARN (1 << 0)
112 #define IVTVFB_DBGFLG_INFO (1 << 1)
113
114 #define IVTVFB_DEBUG(x, type, fmt, args...) \
115 do { \
116 if ((x) & ivtvfb_debug) \
117 printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
118 } while (0)
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)
121
122
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)
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
138 struct osd_info {
139
140 unsigned long video_pbase;
141
142 u32 video_rbase;
143
144 volatile char __iomem *video_vbase;
145
146 u32 video_buffer_size;
147
148
149 unsigned long fb_start_aligned_physaddr;
150
151 unsigned long fb_end_aligned_physaddr;
152 int wc_cookie;
153
154
155 int set_osd_coords_x;
156 int set_osd_coords_y;
157
158
159 int display_width;
160 int display_height;
161 int display_byte_stride;
162
163
164 int bits_per_pixel;
165 int bytes_per_pixel;
166
167
168 struct fb_info ivtvfb_info;
169 struct fb_var_screeninfo ivtvfb_defined;
170 struct fb_fix_screeninfo ivtvfb_fix;
171
172
173 struct fb_var_screeninfo fbvar_cur;
174 int blank_cur;
175 u32 palette_cur[256];
176 u32 pan_cur;
177 };
178
179 struct 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
191
192 static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
193 u32 *fblength)
194 {
195 u32 data[CX2341X_MBOX_MAX_DATA];
196 int rc;
197
198 ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
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
205 static int ivtvfb_get_osd_coords(struct ivtv *itv,
206 struct ivtv_osd_coords *osd)
207 {
208 struct osd_info *oi = itv->osd_info;
209 u32 data[CX2341X_MBOX_MAX_DATA];
210
211 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
212
213 osd->offset = data[0] - oi->video_rbase;
214 osd->max_offset = oi->display_width * oi->display_height * 4;
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
222 static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
223 {
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;
230
231 return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
232 osd->offset + oi->video_rbase,
233 osd->pixel_stride,
234 osd->lines, osd->x, osd->y);
235 }
236
237 static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
238 {
239 int osd_height_limit = itv->is_out_50hz ? 576 : 480;
240
241
242 if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
243 return -EINVAL;
244
245
246 if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
247 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
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) {
253 IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
254 ivtv_window->left, ivtv_window->width);
255 ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
256 }
257
258
259 write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
260
261
262 write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
263
264
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
273 static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
274 unsigned long ivtv_dest_addr, void __user *userbuf,
275 int size_in_bytes)
276 {
277 DEFINE_WAIT(wait);
278 int got_sig = 0;
279
280 mutex_lock(&itv->udma.lock);
281
282 if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
283 mutex_unlock(&itv->udma.lock);
284 IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with get_user_pages: %d bytes, %d pages returned\n",
285 size_in_bytes, itv->udma.page_count);
286
287
288 return -EIO;
289 }
290
291 IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
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
297
298 while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
299 test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
300
301
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
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
318 return 0;
319 }
320
321 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
322 unsigned long dest_offset, int count)
323 {
324 DEFINE_WAIT(wait);
325 struct osd_info *oi = itv->osd_info;
326
327
328 if (count == 0) {
329 IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
330 return -EINVAL;
331 }
332
333
334 if ((dest_offset + count) > oi->video_buffer_size) {
335 IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
336 dest_offset + count, oi->video_buffer_size);
337 return -E2BIG;
338 }
339
340
341 if ((unsigned long)source & 3)
342 IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (%p)\n",
343 source);
344
345 if (dest_offset & 3)
346 IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
347
348 if (count & 3)
349 IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
350
351
352 if (!access_ok(source + dest_offset, count)) {
353 IVTVFB_WARN("Invalid userspace pointer %p\n", source);
354
355 IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source %p count %d\n",
356 dest_offset, source, count);
357 return -EINVAL;
358 }
359
360
361 dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
362
363
364 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
365 }
366
367 static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
368 size_t count, loff_t *ppos)
369 {
370 unsigned long p = *ppos;
371 void *dst;
372 int err = 0;
373 int dma_err;
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;
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
408
409
410 if (count >= 4096 &&
411 ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
412
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;
419 }
420
421 if ((count - lead) & 3)
422 tail = (count - lead) & 3;
423
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
432 if (tail && copy_from_user(dst, buf, tail))
433 return -EFAULT;
434 } else if (copy_from_user(dst, buf, count)) {
435 return -EFAULT;
436 }
437
438 if (!err)
439 *ppos += count;
440
441 return (err) ? err : count;
442 }
443
444 static 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;
448 int rc = 0;
449
450 switch (cmd) {
451 case FBIOGET_VBLANK: {
452 struct fb_vblank vblank;
453 u32 trace;
454
455 memset(&vblank, 0, sizeof(struct fb_vblank));
456
457 vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
458 FB_VBLANK_HAVE_VSYNC;
459 trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
460 if (itv->is_out_50hz && trace > 312)
461 trace -= 312;
462 else if (itv->is_out_60hz && trace > 262)
463 trace -= 262;
464 if (trace == 1)
465 vblank.flags |= FB_VBLANK_VSYNCING;
466 vblank.count = itv->last_vsync_field;
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
474 case FBIO_WAITFORVSYNC:
475 prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
476 if (!schedule_timeout(msecs_to_jiffies(50)))
477 rc = -ETIMEDOUT;
478 finish_wait(&itv->vsync_waitq, &wait);
479 return rc;
480
481 case IVTVFB_IOC_DMA_FRAME: {
482 struct ivtvfb_dma_frame args;
483
484 IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
485 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
486 return -EFAULT;
487
488 return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
489 }
490
491 default:
492 IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
493 return -EINVAL;
494 }
495 return 0;
496 }
497
498
499
500 static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
501 {
502 struct osd_info *oi = itv->osd_info;
503 struct ivtv_osd_coords ivtv_osd;
504 struct v4l2_rect ivtv_window;
505 int osd_mode = -1;
506
507 IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
508
509
510 if (var->nonstd)
511 write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
512 else
513 write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
514
515
516 switch (var->bits_per_pixel) {
517 case 8:
518 osd_mode = IVTV_OSD_BPP_8;
519 break;
520 case 32:
521 osd_mode = IVTV_OSD_BPP_32;
522 break;
523 case 16:
524 switch (var->green.length) {
525 case 4:
526 osd_mode = IVTV_OSD_BPP_16_444;
527 break;
528 case 5:
529 osd_mode = IVTV_OSD_BPP_16_555;
530 break;
531 case 6:
532 osd_mode = IVTV_OSD_BPP_16_565;
533 break;
534 default:
535 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
536 }
537 break;
538 default:
539 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
540 }
541
542
543
544 if (osd_mode != -1) {
545 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
546 ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
547 }
548
549 oi->bits_per_pixel = var->bits_per_pixel;
550 oi->bytes_per_pixel = var->bits_per_pixel / 8;
551
552
553 switch (var->vmode & FB_VMODE_MASK) {
554 case FB_VMODE_NONINTERLACED:
555 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
556 break;
557 case FB_VMODE_INTERLACED:
558 ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
559 break;
560 default:
561 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
562 }
563
564
565 ivtvfb_get_osd_coords(itv, &ivtv_osd);
566
567
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;
572 ivtvfb_set_osd_coords(itv, &ivtv_osd);
573
574
575
576 ivtv_window.width = var->xres;
577 ivtv_window.height = var->yres;
578
579
580 if (!var->upper_margin)
581 var->upper_margin++;
582 if (!var->left_margin)
583 var->left_margin++;
584 ivtv_window.top = var->upper_margin - 1;
585 ivtv_window.left = var->left_margin - 1;
586
587 ivtvfb_set_display_window(itv, &ivtv_window);
588
589
590 itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
591 itv->yuv_info.osd_full_h = ivtv_osd.lines;
592
593
594 itv->yuv_info.yuv_forced_update = 1;
595
596
597 memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
598
599 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
600 var->xres, var->yres,
601 var->xres_virtual, var->yres_virtual,
602 var->bits_per_pixel);
603
604 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
605 var->left_margin, var->upper_margin);
606
607 IVTVFB_DEBUG_INFO("Display filter: %s\n",
608 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
609 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
610
611 return 0;
612 }
613
614 static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
615 {
616 struct osd_info *oi = itv->osd_info;
617
618 IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
619 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
620 strscpy(fix->id, "cx23415 TV out", sizeof(fix->id));
621 fix->smem_start = oi->video_pbase;
622 fix->smem_len = oi->video_buffer_size;
623 fix->type = FB_TYPE_PACKED_PIXELS;
624 fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
625 fix->xpanstep = 1;
626 fix->ypanstep = 1;
627 fix->ywrapstep = 0;
628 fix->line_length = oi->display_byte_stride;
629 fix->accel = FB_ACCEL_NONE;
630 return 0;
631 }
632
633
634
635
636 static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
637 {
638 struct osd_info *oi = itv->osd_info;
639 int osd_height_limit;
640 u32 pixclock, hlimit, vlimit;
641
642 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
643
644
645 if (itv->is_out_50hz) {
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
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
670 switch (var->green.length) {
671 case 4:
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;
678 var->transp.offset = 12;
679 var->transp.length = 1;
680 break;
681 case 5:
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;
688 var->transp.offset = 15;
689 var->transp.length = 1;
690 break;
691 default:
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;
698 var->transp.offset = 0;
699 var->transp.length = 0;
700 break;
701 }
702 }
703 else {
704 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
705 return -EINVAL;
706 }
707
708
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;
713 }
714
715
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;
723 }
724
725
726 if (var->bits_per_pixel == 8) {
727
728 if (var->xres & 3) {
729 IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
730 return -EINVAL;
731 }
732 if (var->xres_virtual & 3) {
733 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
734 return -EINVAL;
735 }
736 }
737 else if (var->bits_per_pixel == 16) {
738
739 if (var->xres & 1) {
740 IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
741 return -EINVAL;
742 }
743 if (var->xres_virtual & 1) {
744 IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
745 return -EINVAL;
746 }
747 }
748
749
750 if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
751 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
752 var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
753 return -EINVAL;
754 }
755
756
757 if (var->nonstd > 1) {
758 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
759 return -EINVAL;
760 }
761
762
763 if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
764 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
765 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
766 return -EINVAL;
767 }
768
769
770
771
772
773 if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
774 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
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);
779
780
781 var->right_margin = hlimit - var->left_margin - var->xres;
782 var->lower_margin = vlimit - var->upper_margin - var->yres;
783
784
785 var->hsync_len = 24;
786 var->vsync_len = 2;
787
788
789
790
791 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
792 var->pixclock = pixclock / 2;
793 else
794 var->pixclock = pixclock;
795
796 itv->osd_rect.width = var->xres;
797 itv->osd_rect.height = var->yres;
798
799 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
800 var->xres, var->yres,
801 var->xres_virtual, var->yres_virtual,
802 var->bits_per_pixel);
803
804 IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
805 var->left_margin, var->upper_margin);
806
807 IVTVFB_DEBUG_INFO("Display filter: %s\n",
808 (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
809 IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
810 return 0;
811 }
812
813 static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
814 {
815 struct ivtv *itv = (struct ivtv *) info->par;
816 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
817 return _ivtvfb_check_var(var, itv);
818 }
819
820 static 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
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
829 osd_pan_index = var->yoffset * info->fix.line_length
830 + var->xoffset * info->var.bits_per_pixel / 8;
831 write_reg(osd_pan_index, 0x02A0C);
832
833
834 itv->yuv_info.osd_x_pan = var->xoffset;
835 itv->yuv_info.osd_y_pan = var->yoffset;
836
837 itv->yuv_info.yuv_forced_update = 1;
838
839 itv->osd_info->pan_cur = osd_pan_index;
840 return 0;
841 }
842
843 static int ivtvfb_set_par(struct fb_info *info)
844 {
845 int rc = 0;
846 struct ivtv *itv = (struct ivtv *) info->par;
847
848 IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
849
850 rc = ivtvfb_set_var(itv, &info->var);
851 ivtvfb_pan_display(&info->var, info);
852 ivtvfb_get_fix(itv, &info->fix);
853 ivtv_firmware_check(itv, "ivtvfb_set_par");
854 return rc;
855 }
856
857 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
858 unsigned blue, unsigned transp,
859 struct fb_info *info)
860 {
861 u32 color, *palette;
862 struct ivtv *itv = (struct ivtv *)info->par;
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);
871 itv->osd_info->palette_cur[regno] = color;
872 return 0;
873 }
874 if (regno >= 16)
875 return -EINVAL;
876
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;
895 }
896 }
897 palette[regno] = color;
898 return 0;
899 }
900
901
902
903 static int ivtvfb_blank(int blank_mode, struct fb_info *info)
904 {
905 struct ivtv *itv = (struct ivtv *)info->par;
906
907 IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
908 switch (blank_mode) {
909 case FB_BLANK_UNBLANK:
910 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
911 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
912 break;
913 case FB_BLANK_NORMAL:
914 case FB_BLANK_HSYNC_SUSPEND:
915 case FB_BLANK_VSYNC_SUSPEND:
916 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
917 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
918 break;
919 case FB_BLANK_POWERDOWN:
920 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
921 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
922 break;
923 }
924 itv->osd_info->blank_cur = blank_mode;
925 return 0;
926 }
927
928 static struct fb_ops ivtvfb_ops = {
929 .owner = THIS_MODULE,
930 .fb_write = ivtvfb_write,
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
943
944 static 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
958
959
960
961
962 static int ivtvfb_init_vidmode(struct ivtv *itv)
963 {
964 struct osd_info *oi = itv->osd_info;
965 struct v4l2_rect start_window;
966 int max_height;
967
968
969
970 if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
971 osd_depth = 8;
972 oi->bits_per_pixel = osd_depth;
973 oi->bytes_per_pixel = oi->bits_per_pixel / 8;
974
975
976
977 if (osd_xres > 720)
978 osd_xres = 720;
979
980
981 if (osd_depth == 8)
982 osd_xres &= ~3;
983 else if (osd_depth == 16)
984 osd_xres &= ~1;
985
986 start_window.width = osd_xres ? osd_xres : 640;
987
988
989 if (osd_left && osd_left + start_window.width > 721) {
990 IVTVFB_ERR("Invalid osd_left - assuming default\n");
991 osd_left = 0;
992 }
993
994
995 osd_left--;
996
997 start_window.left = osd_left >= 0 ?
998 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
999
1000 oi->display_byte_stride =
1001 start_window.width * oi->bytes_per_pixel;
1002
1003
1004
1005 max_height = itv->is_out_50hz ? 576 : 480;
1006
1007 if (osd_yres > max_height)
1008 osd_yres = max_height;
1009
1010 start_window.height = osd_yres ?
1011 osd_yres : itv->is_out_50hz ? 480 : 400;
1012
1013
1014 if (osd_upper + start_window.height > max_height + 1) {
1015 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1016 osd_upper = 0;
1017 }
1018
1019
1020 osd_upper--;
1021
1022 start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1023
1024 oi->display_width = start_window.width;
1025 oi->display_height = start_window.height;
1026
1027
1028
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;
1039
1040
1041
1042 _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1043
1044
1045
1046 ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1047
1048
1049
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;
1058
1059
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;
1064
1065
1066 if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1067 IVTVFB_ERR("abort, unable to alloc cmap\n");
1068 return -ENOMEM;
1069 }
1070
1071
1072 oi->ivtvfb_info.pseudo_palette =
1073 kmalloc_array(16, sizeof(u32), GFP_KERNEL|__GFP_NOWARN);
1074
1075 if (!oi->ivtvfb_info.pseudo_palette) {
1076 IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1077 return -ENOMEM;
1078 }
1079
1080 return 0;
1081 }
1082
1083
1084
1085 static int ivtvfb_init_io(struct ivtv *itv)
1086 {
1087 struct osd_info *oi = itv->osd_info;
1088
1089 int size_shift = 31;
1090
1091 mutex_lock(&itv->serialize_lock);
1092 if (ivtv_init_on_first_open(itv)) {
1093 mutex_unlock(&itv->serialize_lock);
1094 IVTVFB_ERR("Failed to initialize ivtv\n");
1095 return -ENXIO;
1096 }
1097 mutex_unlock(&itv->serialize_lock);
1098
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 }
1104
1105
1106
1107
1108 oi->video_buffer_size = 1704960;
1109
1110 oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1111 oi->video_vbase = itv->dec_mem + oi->video_rbase;
1112
1113 if (!oi->video_vbase) {
1114 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1115 oi->video_buffer_size, oi->video_pbase);
1116 return -EIO;
1117 }
1118
1119 IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1120 oi->video_pbase, oi->video_vbase,
1121 oi->video_buffer_size / 1024);
1122
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);
1133
1134 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1135
1136 return 0;
1137 }
1138
1139
1140 static void ivtvfb_release_buffers (struct ivtv *itv)
1141 {
1142 struct osd_info *oi = itv->osd_info;
1143
1144
1145 if (oi->ivtvfb_info.cmap.len)
1146 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1147
1148
1149 kfree(oi->ivtvfb_info.pseudo_palette);
1150 arch_phys_wc_del(oi->wc_cookie);
1151 kfree(oi);
1152 itv->osd_info = NULL;
1153 }
1154
1155
1156
1157 static int ivtvfb_init_card(struct ivtv *itv)
1158 {
1159 int rc;
1160
1161 #ifdef CONFIG_X86_64
1162 if (pat_enabled()) {
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 }
1172 }
1173 #endif
1174
1175 if (itv->osd_info) {
1176 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1177 return -EBUSY;
1178 }
1179
1180 itv->osd_info = kzalloc(sizeof(struct osd_info),
1181 GFP_KERNEL|__GFP_NOWARN);
1182 if (itv->osd_info == NULL) {
1183 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1184 return -ENOMEM;
1185 }
1186
1187
1188 rc = ivtvfb_init_io(itv);
1189 if (rc) {
1190 ivtvfb_release_buffers(itv);
1191 return rc;
1192 }
1193
1194
1195 if ((rc = ivtvfb_init_vidmode(itv))) {
1196 ivtvfb_release_buffers(itv);
1197 return rc;
1198 }
1199
1200
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
1209 ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1210
1211
1212 write_reg(0, 0x02a30);
1213 write_reg(0, 0x02a34);
1214
1215
1216 ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1217
1218
1219 itv->ivtvfb_restore = ivtvfb_restore;
1220
1221
1222 ivtv_udma_alloc(itv);
1223 itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps |=
1224 V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1225 itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps |=
1226 V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1227 itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1228 return 0;
1229
1230 }
1231
1232 static int __init ivtvfb_callback_init(struct device *dev, void *p)
1233 {
1234 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1235 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1236
1237 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1238 if (ivtvfb_init_card(itv) == 0) {
1239 IVTVFB_INFO("Framebuffer registered on %s\n",
1240 itv->v4l2_dev.name);
1241 (*(int *)p)++;
1242 }
1243 }
1244 return 0;
1245 }
1246
1247 static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1248 {
1249 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1250 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1251 struct osd_info *oi = itv->osd_info;
1252
1253 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1254 itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps &=
1255 ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1256 itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps &=
1257 ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1258 itv->v4l2_cap &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1259 unregister_framebuffer(&itv->osd_info->ivtvfb_info);
1260 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1261 itv->ivtvfb_restore = NULL;
1262 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1263 ivtvfb_release_buffers(itv);
1264 itv->osd_video_pbase = 0;
1265 }
1266 return 0;
1267 }
1268
1269 static int __init ivtvfb_init(void)
1270 {
1271 struct device_driver *drv;
1272 int registered = 0;
1273 int err;
1274
1275
1276 if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1277 pr_err("ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1278 IVTV_MAX_CARDS - 1);
1279 return -EINVAL;
1280 }
1281
1282 drv = driver_find("ivtv", &pci_bus_type);
1283 err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init);
1284 (void)err;
1285 if (!registered) {
1286 pr_err("no cards found\n");
1287 return -ENODEV;
1288 }
1289 return 0;
1290 }
1291
1292 static void ivtvfb_cleanup(void)
1293 {
1294 struct device_driver *drv;
1295 int err;
1296
1297 pr_info("Unloading framebuffer module\n");
1298
1299 drv = driver_find("ivtv", &pci_bus_type);
1300 err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1301 (void)err;
1302 }
1303
1304 module_init(ivtvfb_init);
1305 module_exit(ivtvfb_cleanup);