2 VIDIX driver for Hauppauge PVR 350.
4 Copyright 2007 Lutz Koschorreck.
6 Based on genfb_vid.c and ivtv_xv.c
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 09.05.2007 Lutz Koschorreck
23 First version: Tested with ivtv-0.10.1, xine-ui-0.99.5, xine-lib-1.1.6
35 #include <sys/ioctl.h>
36 #include <linux/types.h>
37 #include <linux/ivtv.h>
44 #include "pci_names.h"
46 #define VIDIX_STATIC ivtv_
48 #define IVTV_MSG "[ivtv-vid] "
50 #define IVTVMAXWIDTH 720
51 #define IVTVMAXHEIGHT 576
53 static int yuvdev
= 0;
54 static void *memBase
= 0;
55 static int frameSize
= 0;
56 static int probed
= 0;
57 static int ivtv_verbose
;
58 static vidix_rect_t destVideo
;
59 static vidix_rect_t srcVideo
;
60 static unsigned char *outbuf
= NULL
;
64 static vidix_capability_t ivtv_cap
=
66 "Hauppauge PVR 350 YUV Video",
75 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
81 static void de_macro_y (unsigned char *src
, unsigned char *dst
,
82 unsigned int w
, unsigned int h
,
84 int height
__attribute__ ((unused
)), int width
)
88 unsigned int h_tail
, w_tail
;
89 unsigned int h_size
, w_size
;
91 // Always round the origin, but compensate by increasing the size
104 // The right / bottom edge might not be a multiple of 16
108 // One block is 16 pixels high
111 // descramble Y plane
112 for (y
= 0; y
< h
; y
+= 16)
114 // Clip if we've reached the bottom & the size isn't a multiple of 16
115 if (y
+ 16 > h
) h_size
= h_tail
;
117 for (x
= 0; x
< w
; x
+= 16)
124 dst_2
= dst
+ (720 * y
) + (720 * src_y
) + (256 * (src_x
>>4)) + (x
* 16);
126 for (i
= 0; i
< h_size
; i
++)
128 memcpy (dst_2
, src
+ src_x
+ x
+ (y
+ i
) * width
+ (src_y
* width
),
136 static void de_macro_uv (unsigned char *srcu
, unsigned char *srcv
,
137 unsigned char *dst
, unsigned int w
, unsigned int h
,
138 int src_x
, int src_y
, int height
, int width
)
140 unsigned int x
, y
, i
, f
;
141 unsigned char *dst_2
;
142 unsigned int h_tail
, w_tail
;
145 /* The uv plane is half the size of the y plane,
146 so 'correct' all dimensions. */
154 // Always round the origin, but compensate by increasing the size
167 // The right / bottom edge may not be a multiple of 16
173 // descramble U/V plane
174 for (y
= 0; y
< h
; y
+= 16)
179 for (x
= 0; x
< w
; x
+= 8)
181 dst_2
= dst
+ (720 * y
) + (720 * src_y
) + (256 * (src_x
>>3)) + (x
* 32);
184 for (i
= 0; i
< h_size
; i
++)
186 int idx
= src_x
+ x
+ ((y
+ i
) * width
) + (src_y
* width
);
187 dst_2
[0] = srcu
[idx
+ 0];
188 dst_2
[1] = srcv
[idx
+ 0];
189 dst_2
[2] = srcu
[idx
+ 1];
190 dst_2
[3] = srcv
[idx
+ 1];
191 dst_2
[4] = srcu
[idx
+ 2];
192 dst_2
[5] = srcv
[idx
+ 2];
193 dst_2
[6] = srcu
[idx
+ 3];
194 dst_2
[7] = srcv
[idx
+ 3];
195 dst_2
[8] = srcu
[idx
+ 4];
196 dst_2
[9] = srcv
[idx
+ 4];
197 dst_2
[10] = srcu
[idx
+ 5];
198 dst_2
[11] = srcv
[idx
+ 5];
199 dst_2
[12] = srcu
[idx
+ 6];
200 dst_2
[13] = srcv
[idx
+ 6];
201 dst_2
[14] = srcu
[idx
+ 7];
202 dst_2
[15] = srcv
[idx
+ 7];
208 for (i
= 0; i
< h_size
; i
++)
210 int idx
= src_x
+ x
+ ((y
+ i
) * width
) + (src_y
* width
);
211 for (f
= 0; f
< w_tail
; f
++)
213 dst_2
[0] = srcu
[idx
+ f
];
214 dst_2
[1] = srcv
[idx
+ f
];
218 dst_2
+= 16 - (w_tail
<< 1);
225 static int ivtv_probe (int verbose
, int force
__attribute__ ((unused
)))
227 pciinfo_t lst
[MAX_PCI_DEVICES
];
228 unsigned int i
, num_pci
;
231 unsigned char fb_number
= 0;
232 unsigned char yuv_device_number
, yuv_device
;
233 char yuv_device_name
[] = "/dev/videoXXX\0";
236 printf (IVTV_MSG
"probe\n");
238 ivtv_verbose
= verbose
;
240 err
= pci_scan (lst
, &num_pci
);
243 printf (IVTV_MSG
"Error occured during pci scan: %s\n", strerror (err
));
248 printf (IVTV_MSG
"Found %d pci devices\n", num_pci
);
250 for (i
= 0; i
< num_pci
; i
++)
252 if (ivtv_verbose
== 2)
253 printf (IVTV_MSG
"Found chip [%04X:%04X] '%s' '%s'\n",
254 lst
[i
].vendor
, lst
[i
].device
, pci_vendor_name (lst
[i
].vendor
),
255 pci_device_name(lst
[i
].vendor
,lst
[i
].device
));
257 if (VENDOR_INTERNEXT
== lst
[i
].vendor
)
259 switch (lst
[i
].device
)
261 case DEVICE_INTERNEXT_ITVC15_MPEG_2_ENCODER
:
263 printf (IVTV_MSG
"Found PVR 350\n");
270 printf (IVTV_MSG
"Can't find chip\n");
276 /* Try to find framebuffer device */
277 procFb
= fopen ("/proc/fb", "r");
280 char procEntry
[MAXLINE
] = {0};
281 while (NULL
!= fgets(procEntry
, MAXLINE
, procFb
))
285 printf (IVTV_MSG
" %s", procEntry
);
287 if (NULL
!= (pos
= strstr(procEntry
, " cx23415 TV out")))
290 fb_number
= atoi (procEntry
);
292 printf (IVTV_MSG
"Framebuffer found #%u\n", fb_number
);
300 printf (IVTV_MSG
"Framebuffer device not found\n");
307 /* Try to find YUV device */
308 yuv_device_number
= 48;
309 yuv_device
= 48 + fb_number
;
312 sprintf (yuv_device_name
, "/dev/video%u", yuv_device
);
313 yuvdev
= open (yuv_device_name
, O_RDWR
);
317 printf (IVTV_MSG
"YUV device found /dev/video%u\n", yuv_device
);
323 printf (IVTV_MSG
"YUV device not found: /dev/video%u\n", yuv_device
);
325 } while (yuv_device
-- > yuv_device_number
);
334 static int ivtv_init (void)
337 printf (IVTV_MSG
"init\n");
342 printf (IVTV_MSG
"Driver was not probed but is being initialized\n");
347 outbuf
= malloc ((IVTVMAXHEIGHT
* IVTVMAXWIDTH
)
348 + (IVTVMAXHEIGHT
* IVTVMAXWIDTH
/ 2));
353 printf (IVTV_MSG
"Not enough memory availabe!\n");
360 static void ivtv_destroy (void)
363 printf (IVTV_MSG
"destory\n");
368 static int ivtv_get_caps (vidix_capability_t
*to
)
371 printf (IVTV_MSG
"GetCap\n");
372 memcpy (to
, &ivtv_cap
, sizeof (vidix_capability_t
));
377 static int ivtv_query_fourcc (vidix_fourcc_t
*to
)
382 printf (IVTV_MSG
"query fourcc (%x)\n", to
->fourcc
);
395 to
->depth
= to
->flags
= 0;
399 to
->depth
= VID_DEPTH_12BPP
|
400 VID_DEPTH_15BPP
| VID_DEPTH_16BPP
|
401 VID_DEPTH_24BPP
| VID_DEPTH_32BPP
;
407 static int ivtv_config_playback (vidix_playback_t
*info
)
410 printf (IVTV_MSG
"config playback\n");
412 if (2 == ivtv_verbose
)
414 printf (IVTV_MSG
"src : x:%d y:%d w:%d h:%d\n",
415 info
->src
.x
, info
->src
.y
, info
->src
.w
, info
->src
.h
);
416 printf (IVTV_MSG
"dest: x:%d y:%d w:%d h:%d\n",
417 info
->dest
.x
, info
->dest
.y
, info
->dest
.w
, info
->dest
.h
);
420 memcpy (&destVideo
, &info
->dest
, sizeof (vidix_rect_t
));
421 memcpy (&srcVideo
, &info
->src
, sizeof (vidix_rect_t
));
423 info
->num_frames
= 2;
424 info
->frame_size
= frameSize
=
425 info
->src
.w
*info
->src
.h
+(info
->src
.w
*info
->src
.h
)/2;
426 info
->dest
.pitch
.y
= 16;
427 info
->dest
.pitch
.u
= info
->dest
.pitch
.v
= 16;
428 info
->offsets
[0] = 0;
429 info
->offsets
[1] = info
->frame_size
;
431 info
->offset
.u
= IVTVMAXWIDTH
* IVTVMAXHEIGHT
;
432 info
->offset
.v
= IVTVMAXWIDTH
* IVTVMAXHEIGHT
433 + (IVTVMAXWIDTH
/ 2) * (IVTVMAXHEIGHT
/ 2);
435 info
->dga_addr
= memBase
= malloc (info
->num_frames
*info
->frame_size
);
438 printf (IVTV_MSG
"frame_size: %d, dga_addr: %p\n",
439 info
->frame_size
, info
->dga_addr
);
444 static int ivtv_playback_on (void)
447 printf (IVTV_MSG
"playback on\n");
452 static int ivtv_playback_off (void)
455 printf (IVTV_MSG
"playback off\n");
460 static int ivtv_frame_sel (unsigned int frame
)
462 struct ivtvyuv_ioctl_dma_host_to_ivtv_args args
;
464 de_macro_y ((memBase
+ (frame
* frameSize
)),
465 outbuf
, srcVideo
.w
, srcVideo
.h
,
466 srcVideo
.x
, srcVideo
.y
, destVideo
.h
, destVideo
.w
);
468 de_macro_uv ((memBase
+ (frame
* frameSize
))
469 + (srcVideo
.w
* srcVideo
.h
) + srcVideo
.w
* srcVideo
.h
/ 4,
470 (memBase
+ (frame
* frameSize
)) + (srcVideo
.w
* srcVideo
.h
),
471 outbuf
+ IVTVMAXWIDTH
* IVTVMAXHEIGHT
,
472 srcVideo
.w
, srcVideo
.h
, srcVideo
.x
, srcVideo
.y
,
473 destVideo
.h
, destVideo
.w
);
475 args
.y_source
= outbuf
;
476 args
.uv_source
= outbuf
+ (IVTVMAXWIDTH
* IVTVMAXHEIGHT
);
477 args
.src_x
= srcVideo
.x
;
478 args
.src_y
= srcVideo
.y
;
479 args
.dst_x
= destVideo
.x
;
480 args
.dst_y
= destVideo
.y
;
481 args
.src_w
= srcVideo
.w
;
482 args
.dst_w
= destVideo
.w
;
483 args
.srcBuf_width
= srcVideo
.w
;
484 args
.src_h
= srcVideo
.h
;
485 args
.dst_h
= destVideo
.h
;
486 args
.srcBuf_height
= srcVideo
.h
;
489 if(ioctl(yuvdev
, IVTV_IOC_PREP_FRAME_YUV
, &args
) == -1)
490 printf ("Ioctl IVTV_IOC_PREP_FRAME_YUV returned failed Error\n");
495 VDXDriver ivtv_drv
= {
499 .get_caps
= ivtv_get_caps
,
500 .query_fourcc
= ivtv_query_fourcc
,
502 .destroy
= ivtv_destroy
,
503 .config_playback
= ivtv_config_playback
,
504 .playback_on
= ivtv_playback_on
,
505 .playback_off
= ivtv_playback_off
,
506 .frame_sel
= ivtv_frame_sel
,