Commit 25581ad1 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (244 commits)
  V4L/DVB (4210b): git-dvb: tea575x-tuner build fix
  V4L/DVB (4210a): git-dvb versus matroxfb
  V4L/DVB (4209): Added some BTTV PCI IDs for newer boards
  Fixes some sync issues between V4L/DVB development and GIT
  V4L/DVB (4206): Cx88-blackbird: always set encoder height based on tvnorm->id
  V4L/DVB (4205): Merge tda9887 module into tuner.
  V4L/DVB (4203): Explicitly set the enum values.
  V4L/DVB (4202): allow selecting CX2341x port mode
  V4L/DVB (4200): Disable bitrate_mode when encoding mpeg-1.
  V4L/DVB (4199): Add cx2341x-specific control array to cx2341x.c
  V4L/DVB (4198): Avoid newer usages of obsoleted experimental MPEGCOMP API
  V4L/DVB (4197): Port new MPEG API to saa7134-empress with saa6752hs
  V4L/DVB (4196): Port cx88-blackbird to the new MPEG API.
  V4L/DVB (4193): Update cx2341x fw encoding API doc.
  V4L/DVB (4192): Use control helpers for saa7115, cx25840, msp3400.
  V4L/DVB (4191): Add CX2341X MPEG encoder module.
  V4L/DVB (4190): Add helper functions for control processing to v4l2-common.
  V4L/DVB (4189): Add videodev support for VIDIOC_S/G/TRY_EXT_CTRLS.
  V4L/DVB (4188): Add new MPEG control/ioctl definitions to videodev2.h
  V4L/DVB (4186): Add support for the DNTV Live! mini DVB-T card.
  ...
parents 72cf2709 7477ddaa
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
86 -> Osprey 101/151 w/ svid 86 -> Osprey 101/151 w/ svid
87 -> Osprey 200/201/250/251 87 -> Osprey 200/201/250/251
88 -> Osprey 200/250 [0070:ff01] 88 -> Osprey 200/250 [0070:ff01]
89 -> Osprey 210/220 89 -> Osprey 210/220/230
90 -> Osprey 500 [0070:ff02] 90 -> Osprey 500 [0070:ff02]
91 -> Osprey 540 [0070:ff04] 91 -> Osprey 540 [0070:ff04]
92 -> Osprey 2000 [0070:ff03] 92 -> Osprey 2000 [0070:ff03]
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
110 -> IVC-100 [ff00:a132] 110 -> IVC-100 [ff00:a132]
111 -> IVC-120G [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182] 111 -> IVC-120G [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
112 -> pcHDTV HD-2000 TV [7063:2000] 112 -> pcHDTV HD-2000 TV [7063:2000]
113 -> Twinhan DST + clones [11bd:0026,1822:0001,270f:fc00] 113 -> Twinhan DST + clones [11bd:0026,1822:0001,270f:fc00,1822:0026]
114 -> Winfast VC100 [107d:6607] 114 -> Winfast VC100 [107d:6607]
115 -> Teppro TEV-560/InterVision IV-560 115 -> Teppro TEV-560/InterVision IV-560
116 -> SIMUS GVC1100 [aa6a:82b2] 116 -> SIMUS GVC1100 [aa6a:82b2]
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
14 -> KWorld/VStream XPert DVB-T [17de:08a6] 14 -> KWorld/VStream XPert DVB-T [17de:08a6]
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00] 15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
16 -> KWorld LTV883RF 16 -> KWorld LTV883RF
17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810] 17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810,18ac:d800]
18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001] 18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001]
19 -> Conexant DVB-T reference design [14f1:0187] 19 -> Conexant DVB-T reference design [14f1:0187]
20 -> Provideo PV259 [1540:2580] 20 -> Provideo PV259 [1540:2580]
...@@ -40,8 +40,13 @@ ...@@ -40,8 +40,13 @@
39 -> KWorld DVB-S 100 [17de:08b2] 39 -> KWorld DVB-S 100 [17de:08b2]
40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402] 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402]
41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802]
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019]
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1]
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
45 -> KWorld HardwareMpegTV XPert [17de:0840] 45 -> KWorld HardwareMpegTV XPert [17de:0840]
46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44]
47 -> pcHDTV HD5500 HDTV [7063:5500]
48 -> Kworld MCE 200 Deluxe [17de:0841]
49 -> PixelView PlayTV P7000 [1554:4813]
50 -> NPG Tech Real TV FM Top 10 [14f1:0842]
51 -> WinFast DTV2000 H [107d:665e]
...@@ -93,3 +93,4 @@ ...@@ -93,3 +93,4 @@
92 -> AVerMedia A169 B1 [1461:6360] 92 -> AVerMedia A169 B1 [1461:6360]
93 -> Medion 7134 Bridge #2 [16be:0005] 93 -> Medion 7134 Bridge #2 [16be:0005]
94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502] 94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502]
95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138]
...@@ -62,7 +62,7 @@ tuner=60 - Thomson DTT 761X (ATSC/NTSC) ...@@ -62,7 +62,7 @@ tuner=60 - Thomson DTT 761X (ATSC/NTSC)
tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
tuner=62 - Philips TEA5767HN FM Radio tuner=62 - Philips TEA5767HN FM Radio
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
tuner=64 - LG TDVS-H062F/TUA6034 tuner=64 - LG TDVS-H06xF
tuner=65 - Ymec TVF66T5-B/DFF tuner=65 - Ymec TVF66T5-B/DFF
tuner=66 - LG TALN series tuner=66 - LG TALN series
tuner=67 - Philips TD1316 Hybrid Tuner tuner=67 - Philips TD1316 Hybrid Tuner
...@@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar models ...@@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar models
tuner=70 - Samsung TCPN 2121P30A tuner=70 - Samsung TCPN 2121P30A
tuner=71 - Xceive xc3028 tuner=71 - Xceive xc3028
tuner=72 - Thomson FE6600 tuner=72 - Thomson FE6600
tuner=73 - Samsung TCPG 6121P30A
...@@ -185,207 +185,10 @@ this work is documented at the video4linux2 site listed below. ...@@ -185,207 +185,10 @@ this work is documented at the video4linux2 site listed below.
9.0 --- A sample program using v4lgrabber, 9.0 --- A sample program using v4lgrabber,
This program is a simple image grabber that will copy a frame from the v4lgrab is a simple image grabber that will copy a frame from the
first video device, /dev/video0 to standard output in portable pixmap first video device, /dev/video0 to standard output in portable pixmap
format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg' format (.ppm) To produce .jpg output, you can use it like this:
produced this picture of me at 'v4lgrab | convert - c-qcam.jpg'
http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-------------------- 8< ---------------- 8< -----------------------------
/* Simple Video4Linux image grabber. */
/*
* Video4Linux Driver Test/Example Framegrabbing Program
*
* Compile with:
* gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
* Use as:
* v4lgrab >image.ppm
*
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
* with minor modifications (Dave Forrest, drf5n@virginia.edu).
*
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/videodev.h>
#define FILE "/dev/video0"
/* Stole this from tvset.c */
#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
{ \
switch (format) \
{ \
case VIDEO_PALETTE_GREY: \
switch (depth) \
{ \
case 4: \
case 6: \
case 8: \
(r) = (g) = (b) = (*buf++ << 8);\
break; \
\
case 16: \
(r) = (g) = (b) = \
*((unsigned short *) buf); \
buf += 2; \
break; \
} \
break; \
\
\
case VIDEO_PALETTE_RGB565: \
{ \
unsigned short tmp = *(unsigned short *)buf; \
(r) = tmp&0xF800; \
(g) = (tmp<<5)&0xFC00; \
(b) = (tmp<<11)&0xF800; \
buf += 2; \
} \
break; \
\
case VIDEO_PALETTE_RGB555: \
(r) = (buf[0]&0xF8)<<8; \
(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
(b) = ((buf[1] << 2 ) & 0xF8)<<8; \
buf += 2; \
break; \
\
case VIDEO_PALETTE_RGB24: \
(r) = buf[0] << 8; (g) = buf[1] << 8; \
(b) = buf[2] << 8; \
buf += 3; \
break; \
\
default: \
fprintf(stderr, \
"Format %d not yet supported\n", \
format); \
} \
}
int get_brightness_adj(unsigned char *image, long size, int *brightness) {
long i, tot = 0;
for (i=0;i<size*3;i++)
tot += image[i];
*brightness = (128 - tot/(size*3))/3;
return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
}
int main(int argc, char ** argv)
{
int fd = open(FILE, O_RDONLY), f;
struct video_capability cap;
struct video_window win;
struct video_picture vpic;
unsigned char *buffer, *src;
int bpp = 24, r, g, b;
unsigned int i, src_depth;
if (fd < 0) {
perror(FILE);
exit(1);
}
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
perror("VIDIOGCAP");
fprintf(stderr, "(" FILE " not a video4linux device?)\n");
close(fd);
exit(1);
}
if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
perror("VIDIOCGWIN");
close(fd);
exit(1);
}
if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
perror("VIDIOCGPICT");
close(fd);
exit(1);
}
if (cap.type & VID_TYPE_MONOCHROME) {
vpic.depth=8;
vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=6;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=4;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
fprintf(stderr, "Unable to find a supported capture format.\n");
close(fd);
exit(1);
}
}
}
} else {
vpic.depth=24;
vpic.palette=VIDEO_PALETTE_RGB24;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.palette=VIDEO_PALETTE_RGB565;
vpic.depth=16;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
vpic.palette=VIDEO_PALETTE_RGB555;
vpic.depth=15;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
fprintf(stderr, "Unable to find a supported capture format.\n");
return -1;
}
}
}
}
buffer = malloc(win.width * win.height * bpp);
if (!buffer) {
fprintf(stderr, "Out of memory.\n");
exit(1);
}
do {
int newbright;
read(fd, buffer, win.width * win.height * bpp);
f = get_brightness_adj(buffer, win.width * win.height, &newbright);
if (f) {
vpic.brightness += (newbright << 8);
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
perror("VIDIOSPICT");
break;
}
}
} while (f);
fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
src = buffer;
for (i = 0; i < win.width * win.height; i++) {
READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
fputc(r>>8, stdout);
fputc(g>>8, stdout);
fputc(b>>8, stdout);
}
close(fd);
return 0;
}
-------------------- 8< ---------------- 8< -----------------------------
10.0 --- Other Information 10.0 --- Other Information
......
...@@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video ...@@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video
Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 7 Card number: 7
AverMedia 6 Eyes AVS6EYES:
* Zoran zr36067 PCI controller
* Zoran zr36060 MJPEG codec
* Samsung ks0127 TV decoder
* Conexant bt866 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, ks0127, bt866, zr36060, zr36067
Inputs/outputs: Six physical inputs. 1-6 are composite,
1-2, 3-4, 5-6 doubles as S-video,
1-3 triples as component.
One composite output.
Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 8
Not autodetected, card=8 is necessary.
Linux Media Labs LML33: Linux Media Labs LML33:
* Zoran zr36067 PCI controller * Zoran zr36067 PCI controller
* Zoran zr36060 MJPEG codec * Zoran zr36060 MJPEG codec
...@@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder ...@@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder
was introduced in 1996, is used in the DC30 and DC30+ and was introduced in 1996, is used in the DC30 and DC30+ and
can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb
Samsung ks0127 TV decoder
is used in the AVS6EYES card and
can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM
=========================== ===========================
1.2 What the TV encoder can do an what not 1.2 What the TV encoder can do an what not
...@@ -221,6 +240,10 @@ ITT mse3000 TV encoder ...@@ -221,6 +240,10 @@ ITT mse3000 TV encoder
was introduced in 1991, is used in the DC10 old was introduced in 1991, is used in the DC10 old
can generate: PAL , NTSC , SECAM can generate: PAL , NTSC , SECAM
Conexant bt866 TV encoder
is used in AVS6EYES, and
can generate: NTSC/PAL, PAL­M, PAL­N
The adv717x, should be able to produce PAL N. But you find nothing PAL N The adv717x, should be able to produce PAL N. But you find nothing PAL N
specific in the registers. Seem that you have to reuse a other standard specific in the registers. Seem that you have to reuse a other standard
to generate PAL N, maybe it would work if you use the PAL M settings. to generate PAL N, maybe it would work if you use the PAL M settings.
......
This page describes how to make calls to the firmware api.
How to call
===========
The preferred calling convention is known as the firmware mailbox. The
mailboxes are basically a fixed length array that serves as the call-stack.
Firmware mailboxes can be located by searching the encoder and decoder memory
for a 16 byte signature. That signature will be located on a 256-byte boundary.
Signature:
0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34,
0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78
The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are
reserved for API calls. The second 10 are used by the firmware for event
notification.
Index Name
----- ----
0 Flags
1 Command
2 Return value
3 Timeout
4-19 Parameter/Result
The flags are defined in the following table. The direction is from the
perspective of the firmware.
Bit Direction Purpose
--- --------- -------
2 O Firmware has processed the command.
1 I Driver has finished setting the parameters.
0 I Driver is using this mailbox.
The command is a 32-bit enumerator. The API specifics may be found in the
fw-*-api.txt documents.
The return value is a 32-bit enumerator. Only two values are currently defined:
0=success and -1=command undefined.
There are 16 parameters/results 32-bit fields. The driver populates these fields
with values for all the parameters required by the call. The driver overwrites
these fields with result values returned by the call. The API specifics may be
found in the fw-*-api.txt documents.
The timeout value protects the card from a hung driver thread. If the driver
doesn't handle the completed call within the timeout specified, the firmware
will reset that mailbox.
To make an API call, the driver iterates over each mailbox looking for the
first one available (bit 0 has been cleared). The driver sets that bit, fills
in the command enumerator, the timeout value and any required parameters. The
driver then sets the parameter ready bit (bit 1). The firmware scans the
mailboxes for pending commands, processes them, sets the result code, populates
the result value array with that call's return values and sets the call
complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results
and clear all the flags. If the driver does not perform this task within the
time set in the timeout register, the firmware will reset that mailbox.
Event notifications are sent from the firmware to the host. The host tells the
firmware which events it is interested in via an API call. That call tells the
firmware which notification mailbox to use. The firmware signals the host via
an interrupt. Only the 16 Results fields are used, the Flags, Command, Return
value and Timeout words are not used.
Decoder firmware API description
================================
Note: this API is part of the decoder firmware, so it's cx23415 only.
-------------------------------------------------------------------------------
Name CX2341X_DEC_PING_FW
Enum 0/0x00
Description
This API call does nothing. It may be used to check if the firmware
is responding.
-------------------------------------------------------------------------------
Name CX2341X_DEC_START_PLAYBACK
Enum 1/0x01
Description
Begin or resume playback.
Param[0]
0 based frame number in GOP to begin playback from.
Param[1]
Specifies the number of muted audio frames to play before normal
audio resumes.
-------------------------------------------------------------------------------
Name CX2341X_DEC_STOP_PLAYBACK
Enum 2/0x02
Description
Ends playback and clears all decoder buffers. If PTS is not zero,
playback stops at specified PTS.
Param[0]
Display 0=last frame, 1=black
Param[1]
PTS low
Param[2]
PTS high
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_PLAYBACK_SPEED
Enum 3/0x03
Description
Playback stream at speed other than normal. There are two modes of
operation:
Smooth: host transfers entire stream and firmware drops unused
frames.
Coarse: host drops frames based on indexing as required to achieve
desired speed.
Param[0]
Bitmap:
0:7 0 normal
1 fast only "1.5 times"
n nX fast, 1/nX slow
30 Framedrop:
'0' during 1.5 times play, every other B frame is dropped
'1' during 1.5 times play, stream is unchanged (bitrate
must not exceed 8mbps)
31 Speed:
'0' slow
'1' fast
Param[1]
Direction: 0=forward, 1=reverse
Param[2]
Picture mask:
1=I frames
3=I, P frames
7=I, P, B frames
Param[3]
B frames per GOP (for reverse play only)
Param[4]
Mute audio: 0=disable, 1=enable
Param[5]
Display 0=frame, 1=field
Param[6]
Specifies the number of muted audio frames to play before normal audio
resumes.
-------------------------------------------------------------------------------
Name CX2341X_DEC_STEP_VIDEO
Enum 5/0x05
Description
Each call to this API steps the playback to the next unit defined below
in the current playback direction.
Param[0]
0=frame, 1=top field, 2=bottom field
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_DMA_BLOCK_SIZE
Enum 8/0x08
Description
Set DMA transfer block size. Counterpart to API 0xC9
Param[0]
DMA transfer block size in bytes. A different size may be specified
when issuing the DMA transfer command.
-------------------------------------------------------------------------------
Name CX2341X_DEC_GET_XFER_INFO
Enum 9/0x09
Description
This API call may be used to detect an end of stream condtion.
Result[0]
Stream type
Result[1]
Address offset
Result[2]
Maximum bytes to transfer
Result[3]
Buffer fullness
-------------------------------------------------------------------------------
Name CX2341X_DEC_GET_DMA_STATUS
Enum 10/0x0A
Description
Status of the last DMA transfer
Result[0]
Bit 1 set means transfer complete
Bit 2 set means DMA error
Bit 3 set means linked list error
Result[1]
DMA type: 0=MPEG, 1=OSD, 2=YUV
-------------------------------------------------------------------------------
Name CX2341X_DEC_SCHED_DMA_FROM_HOST
Enum 11/0x0B
Description
Setup DMA from host operation. Counterpart to API 0xCC
Param[0]
Memory address of link list
Param[1]
Total # of bytes to transfer
Param[2]
DMA type (0=MPEG, 1=OSD, 2=YUV)
-------------------------------------------------------------------------------
Name CX2341X_DEC_PAUSE_PLAYBACK
Enum 13/0x0D
Description
Freeze playback immediately. In this mode, when internal buffers are
full, no more data will be accepted and data request IRQs will be
masked.
Param[0]
Display: 0=last frame, 1=black
-------------------------------------------------------------------------------
Name CX2341X_DEC_HALT_FW
Enum 14/0x0E
Description
The firmware is halted and no further API calls are serviced until
the firmware is uploaded again.
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_STANDARD
Enum 16/0x10
Description
Selects display standard
Param[0]
0=NTSC, 1=PAL
-------------------------------------------------------------------------------
Name CX2341X_DEC_GET_VERSION
Enum 17/0x11
Description
Returns decoder firmware version information
Result[0]
Version bitmask:
Bits 0:15 build
Bits 16:23 minor
Bits 24:31 major
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_STREAM_INPUT
Enum 20/0x14
Description
Select decoder stream input port
Param[0]
0=memory (default), 1=streaming
-------------------------------------------------------------------------------
Name CX2341X_DEC_GET_TIMING_INFO
Enum 21/0x15
Description
Returns timing information from start of playback
Result[0]
Frame count by decode order
Result[1]
Video PTS bits 0:31 by display order
Result[2]
Video PTS bit 32 by display order
Result[3]
SCR bits 0:31 by display order
Result[4]
SCR bit 32 by display order
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_AUDIO_MODE
Enum 22/0x16
Description
Select audio mode
Param[0]
Dual mono mode action
Param[1]
Stereo mode action:
0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_EVENT_NOTIFICATION
Enum 23/0x17
Description
Setup firmware to notify the host about a particular event.
Counterpart to API 0xD5
Param[0]
Event: 0=Audio mode change between stereo and dual channel
Param[1]
Notification 0=disabled, 1=enabled
Param[2]
Interrupt bit
Param[3]
Mailbox slot, -1 if no mailbox required.
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_DISPLAY_BUFFERS
Enum 24/0x18
Description
Number of display buffers. To decode all frames in reverse playback you
must use nine buffers.
Param[0]
0=six buffers, 1=nine buffers
-------------------------------------------------------------------------------
Name CX2341X_DEC_EXTRACT_VBI
Enum 25/0x19
Description
Extracts VBI data
Param[0]
0=extract from extension & user data, 1=extract from private packets
Result[0]
VBI table location
Result[1]
VBI table size
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_DECODER_SOURCE
Enum 26/0x1A
Description
Selects decoder source. Ensure that the parameters passed to this
API match the encoder settings.
Param[0]
Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host
Param[1]
YUV picture width
Param[2]
YUV picture height
Param[3]
Bitmap: see Param[0] of API 0xBD
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_AUDIO_OUTPUT
Enum 27/0x1B
Description
Select audio output format
Param[0]
Bitmask:
0:1 Data size:
'00' 16 bit
'01' 20 bit
'10' 24 bit
2:7 Unused
8:9 Mode:
'00' 2 channels
'01' 4 channels
'10' 6 channels
'11' 6 channels with one line data mode
(for left justified MSB first mode, 20 bit only)
10:11 Unused
12:13 Channel format:
'00' right justified MSB first mode
'01' left justified MSB first mode
'10' I2S mode
14:15 Unused
16:21 Right justify bit count
22:31 Unused
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_AV_DELAY
Enum 28/0x1C
Description
Set audio/video delay in 90Khz ticks
Param[0]
0=A/V in sync, negative=audio lags, positive=video lags
-------------------------------------------------------------------------------
Name CX2341X_DEC_SET_PREBUFFERING
Enum 30/0x1E
Description
Decoder prebuffering, when enabled up to 128KB are buffered for
streams <8mpbs or 640KB for streams >8mbps
Param[0]
0=off, 1=on
This page describes the structures and procedures used by the cx2341x DMA
engine.
Introduction
============
The cx2341x PCI interface is busmaster capable. This means it has a DMA
engine to efficiently transfer large volumes of data between the card and main
memory without requiring help from a CPU. Like most hardware, it must operate
on contiguous physical memory. This is difficult to come by in large quantities
on virtual memory machines.
Therefore, it also supports a technique called "scatter-gather". The card can
transfer multiple buffers in one operation. Instead of allocating one large
contiguous buffer, the driver can allocate several smaller buffers.
In practice, I've seen the average transfer to be roughly 80K, but transfers
above 128K were not uncommon, particularly at startup. The 128K figure is
important, because that is the largest block that the kernel can normally
allocate. Even still, 128K blocks are hard to come by, so the driver writer is
urged to choose a smaller block size and learn the scatter-gather technique.
Mailbox #10 is reserved for DMA transfer information.
Flow
====
This section describes, in general, the order of events when handling DMA
transfers. Detailed information follows this section.
- The card raises the Encoder interrupt.
- The driver reads the transfer type, offset and size from Mailbox #10.
- The driver constructs the scatter-gather array from enough free dma buffers
to cover the size.
- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call.
- The card raises the DMA Complete interrupt.
- The driver checks the DMA status register for any errors.
- The driver post-processes the newly transferred buffers.
NOTE! It is possible that the Encoder and DMA Complete interrupts get raised
simultaneously. (End of the last, start of the next, etc.)
Mailbox #10
===========
The Flags, Command, Return Value and Timeout fields are ignored.
Name: Mailbox #10
Results[0]: Type: 0: MPEG.
Results[1]: Offset: The position relative to the card's memory space.
Results[2]: Size: The exact number of bytes to transfer.
My speculation is that since the StartCapture API has a capture type of "RAW"
available, that the type field will have other values that correspond to YUV
and PCM data.
Scatter-Gather Array
====================
The scatter-gather array is a contiguously allocated block of memory that
tells the card the source and destination of each data-block to transfer.
Card "addresses" are derived from the offset supplied by Mailbox #10. Host
addresses are the physical memory location of the target DMA buffer.
Each S-G array element is a struct of three 32-bit words. The first word is
the source address, the second is the destination address. Both take up the
entire 32 bits. The lowest 16 bits of the third word is the transfer byte
count. The high-bit of the third word is the "last" flag. The last-flag tells
the card to raise the DMA_DONE interrupt. From hard personal experience, if
you forget to set this bit, the card will still "work" but the stream will
most likely get corrupted.
The transfer count must be a multiple of 256. Therefore, the driver will need
to track how much data in the target buffer is valid and deal with it
accordingly.
Array Element:
- 32-bit Source Address
- 32-bit Destination Address
- 16-bit reserved (high bit is the last flag)
- 16-bit byte count
DMA Transfer Status
===================
Register 0x0004 holds the DMA Transfer Status:
Bit
4 Scatter-Gather array error
3 DMA write error
2 DMA read error
1 write completed
0 read completed
This diff is collapsed.
This document describes the cx2341x memory map and documents some of the register
space.
Warning! This information was figured out from searching through the memory and
registers, this information may not be correct and is certainly not complete, and
was not derived from anything more than searching through the memory space with
commands like:
ivtvctl -O min=0x02000000,max=0x020000ff
So take this as is, I'm always searching for more stuff, it's a large
register space :-).
Memory Map
==========
The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0
(Base Address Register 0). The addresses here are offsets relative to the
address held in BAR0.
0x00000000-0x00ffffff Encoder memory space
0x00000000-0x0003ffff Encode.rom
???-??? MPEG buffer(s)
???-??? Raw video capture buffer(s)
???-??? Raw audio capture buffer(s)
???-??? Display buffers (6 or 9)
0x01000000-0x01ffffff Decoder memory space
0x01000000-0x0103ffff Decode.rom
???-??? MPEG buffers(s)
0x0114b000-0x0115afff Audio.rom (deprecated?)
0x02000000-0x0200ffff Register Space
Registers
=========
The registers occupy the 64k space starting at the 0x02000000 offset from BAR0.
All of these registers are 32 bits wide.
DMA Registers 0x000-0xff:
0x00 - Control:
0=reset/cancel, 1=read, 2=write, 4=stop
0x04 - DMA status:
1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error
0x08 - pci DMA pointer for read link list
0x0c - pci DMA pointer for write link list
0x10 - read/write DMA enable:
1=read enable, 2=write enable
0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes
0x18 - ??
0x1c - always 0x20 or 32, smaller values slow down DMA transactions
0x20 - always value of 0x780a010a
0x24-0x3c - usually just random values???
0x40 - Interrupt status
0x44 - Write a bit here and shows up in Interrupt status 0x40
0x48 - Interrupt Mask
0x4C - always value of 0xfffdffff,
if changed to 0xffffffff DMA write interrupts break.
0x50 - always 0xffffffff
0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are
3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the
interrupt masks???).
0x60-0x7C - random values
0x80 - first write linked list reg, for Encoder Memory addr
0x84 - first write linked list reg, for pci memory addr
0x88 - first write linked list reg, for length of buffer in memory addr
(|0x80000000 or this for last link)
0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
from linked list addr in reg 0x0c, firmware must push through or
something.
0xe0 - first (and only) read linked list reg, for pci memory addr
0xe4 - first (and only) read linked list reg, for Decoder memory addr
0xe8 - first (and only) read linked list reg, for length of buffer
0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000.
Memory locations for Encoder Buffers 0x700-0x7ff:
These registers show offsets of memory locations pertaining to each
buffer area used for encoding, have to shift them by <<1 first.
0x07F8: Encoder SDRAM refresh
0x07FC: Encoder SDRAM pre-charge
Memory locations for Decoder Buffers 0x800-0x8ff:
These registers show offsets of memory locations pertaining to each
buffer area used for decoding, have to shift them by <<1 first.
0x08F8: Decoder SDRAM refresh
0x08FC: Decoder SDRAM pre-charge
Other memory locations:
0x2800: Video Display Module control
0x2D00: AO (audio output?) control
0x2D24: Bytes Flushed
0x7000: LSB I2C write clock bit (inverted)
0x7004: LSB I2C write data bit (inverted)
0x7008: LSB I2C read clock bit
0x700c: LSB I2C read data bit
0x9008: GPIO get input state
0x900c: GPIO set output state
0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output)
0x9050: SPU control
0x9054: Reset HW blocks
0x9058: VPU control
0xA018: Bit6: interrupt pending?
0xA064: APU command
Interrupt Status Register
=========================
The definition of the bits in the interrupt status register 0x0040, and the
interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to
execute.
Bit
31 Encoder Start Capture
30 Encoder EOS
29 Encoder VBI capture
28 Encoder Video Input Module reset event
27 Encoder DMA complete
26
25 Decoder copy protect detection event
24 Decoder audio mode change detection event
23
22 Decoder data request
21 Decoder I-Frame? done
20 Decoder DMA complete
19 Decoder VBI re-insertion
18 Decoder DMA err (linked-list bad)
Missing
Encoder API call completed
Decoder API call completed
Encoder API post(?)
Decoder API post(?)
Decoder VTRACE event
OSD firmware API description
============================
Note: this API is part of the decoder firmware, so it's cx23415 only.
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_FRAMEBUFFER
Enum 65/0x41
Description
Return base and length of contiguous OSD memory.
Result[0]
OSD base address
Result[1]
OSD length
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_PIXEL_FORMAT
Enum 66/0x42
Description
Query OSD format
Result[0]
0=8bit index, 4=AlphaRGB 8:8:8:8
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_PIXEL_FORMAT
Enum 67/0x43
Description
Assign pixel format
Param[0]
0=8bit index, 4=AlphaRGB 8:8:8:8
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_STATE
Enum 68/0x44
Description
Query OSD state
Result[0]
Bit 0 0=off, 1=on
Bits 1:2 alpha control
Bits 3:5 pixel format
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_STATE
Enum 69/0x45
Description
OSD switch
Param[0]
0=off, 1=on
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_OSD_COORDS
Enum 70/0x46
Description
Retrieve coordinates of OSD area blended with video
Result[0]
OSD buffer address
Result[1]
Stride in pixels
Result[2]
Lines in OSD buffer
Result[3]
Horizontal offset in buffer
Result[4]
Vertical offset in buffer
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_OSD_COORDS
Enum 71/0x47
Description
Assign the coordinates of the OSD area to blend with video
Param[0]
buffer address
Param[1]
buffer stride in pixels
Param[2]
lines in buffer
Param[3]
horizontal offset
Param[4]
vertical offset
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_SCREEN_COORDS
Enum 72/0x48
Description
Retrieve OSD screen area coordinates
Result[0]
top left horizontal offset
Result[1]
top left vertical offset
Result[2]
bottom right hotizontal offset
Result[3]
bottom right vertical offset
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_SCREEN_COORDS
Enum 73/0x49
Description
Assign the coordinates of the screen area to blend with video
Param[0]
top left horizontal offset
Param[1]
top left vertical offset
Param[2]
bottom left horizontal offset
Param[3]
bottom left vertical offset
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_GLOBAL_ALPHA
Enum 74/0x4A
Description
Retrieve OSD global alpha
Result[0]
global alpha: 0=off, 1=on
Result[1]
bits 0:7 global alpha
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_GLOBAL_ALPHA
Enum 75/0x4B
Description
Update global alpha
Param[0]
global alpha: 0=off, 1=on
Param[1]
global alpha (8 bits)
Param[2]
local alpha: 0=on, 1=off
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_BLEND_COORDS
Enum 78/0x4C
Description
Move start of blending area within display buffer
Param[0]
horizontal offset in buffer
Param[1]
vertical offset in buffer
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_FLICKER_STATE
Enum 79/0x4F
Description
Retrieve flicker reduction module state
Result[0]
flicker state: 0=off, 1=on
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_FLICKER_STATE
Enum 80/0x50
Description
Set flicker reduction module state
Param[0]
State: 0=off, 1=on
-------------------------------------------------------------------------------
Name CX2341X_OSD_BLT_COPY
Enum 82/0x52
Description
BLT copy
Param[0]
'0000' zero
'0001' ~destination AND ~source
'0010' ~destination AND source
'0011' ~destination
'0100' destination AND ~source
'0101' ~source
'0110' destination XOR source
'0111' ~destination OR ~source
'1000' ~destination AND ~source
'1001' destination XNOR source
'1010' source
'1011' ~destination OR source
'1100' destination
'1101' destination OR ~source
'1110' destination OR source
'1111' one
Param[1]
Resulting alpha blending
'01' source_alpha
'10' destination_alpha
'11' source_alpha*destination_alpha+1
(zero if both source and destination alpha are zero)
Param[2]
'00' output_pixel = source_pixel
'01' if source_alpha=0:
output_pixel = destination_pixel
if 256 > source_alpha > 1:
output_pixel = ((source_alpha + 1)*source_pixel +
(255 - source_alpha)*destination_pixel)/256
'10' if destination_alpha=0:
output_pixel = source_pixel
if 255 > destination_alpha > 0:
output_pixel = ((255 - destination_alpha)*source_pixel +
(destination_alpha + 1)*destination_pixel)/256
'11' if source_alpha=0:
source_temp = 0
if source_alpha=255:
source_temp = source_pixel*256
if 255 > source_alpha > 0:
source_temp = source_pixel*(source_alpha + 1)
if destination_alpha=0:
destination_temp = 0
if destination_alpha=255:
destination_temp = destination_pixel*256
if 255 > destination_alpha > 0:
destination_temp = destination_pixel*(destination_alpha + 1)
output_pixel = (source_temp + destination_temp)/256
Param[3]
width
Param[4]
height
Param[5]
destination pixel mask
Param[6]
destination rectangle start address
Param[7]
destination stride in dwords
Param[8]
source stride in dwords
Param[9]
source rectangle start address
-------------------------------------------------------------------------------
Name CX2341X_OSD_BLT_FILL
Enum 83/0x53
Description
BLT fill color
Param[0]
Same as Param[0] on API 0x52
Param[1]
Same as Param[1] on API 0x52
Param[2]
Same as Param[2] on API 0x52
Param[3]
width
Param[4]
height
Param[5]
destination pixel mask
Param[6]
destination rectangle start address
Param[7]
destination stride in dwords
Param[8]
color fill value
-------------------------------------------------------------------------------
Name CX2341X_OSD_BLT_TEXT
Enum 84/0x54
Description
BLT for 8 bit alpha text source
Param[0]
Same as Param[0] on API 0x52
Param[1]
Same as Param[1] on API 0x52
Param[2]
Same as Param[2] on API 0x52
Param[3]
width
Param[4]
height
Param[5]
destination pixel mask
Param[6]
destination rectangle start address
Param[7]
destination stride in dwords
Param[8]
source stride in dwords
Param[9]
source rectangle start address
Param[10]
color fill value
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_FRAMEBUFFER_WINDOW
Enum 86/0x56
Description
Positions the main output window on the screen. The coordinates must be
such that the entire window fits on the screen.
Param[0]
window width
Param[1]
window height
Param[2]
top left window corner horizontal offset
Param[3]
top left window corner vertical offset
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_CHROMA_KEY
Enum 96/0x60
Description
Chroma key switch and color
Param[0]
state: 0=off, 1=on
Param[1]
color
-------------------------------------------------------------------------------
Name CX2341X_OSD_GET_ALPHA_CONTENT_INDEX
Enum 97/0x61
Description
Retrieve alpha content index
Result[0]
alpha content index, Range 0:15
-------------------------------------------------------------------------------
Name CX2341X_OSD_SET_ALPHA_CONTENT_INDEX
Enum 98/0x62
Description
Assign alpha content index
Param[0]
alpha content index, range 0:15
This document describes how to upload the cx2341x firmware to the card.
How to find
===========
See the web pages of the various projects that uses this chip for information
on how to obtain the firmware.
The firmware stored in a Windows driver can be detected as follows:
- Each firmware image is 256k bytes.
- The 1st 32-bit word of the Encoder image is 0x0000da7
- The 1st 32-bit word of the Decoder image is 0x00003a7
- The 2nd 32-bit word of both images is 0xaa55bb66
How to load
===========
- Issue the FWapi command to stop the encoder if it is running. Wait for the
command to complete.
- Issue the FWapi command to stop the decoder if it is running. Wait for the
command to complete.
- Issue the I2C command to the digitizer to stop emitting VSYNC events.
- Issue the FWapi command to halt the encoder's firmware.
- Sleep for 10ms.
- Issue the FWapi command to halt the decoder's firmware.
- Sleep for 10ms.
- Write 0x00000000 to register 0x2800 to stop the Video Display Module.
- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?).
- Write 0x00000000 to register 0xA064 to ping? the APU.
- Write 0xFFFFFFFE to register 0x9058 to stop the VPU.
- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks.
- Write 0x00000001 to register 0x9050 to stop the SPU.
- Sleep for 10ms.
- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge.
- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us.
- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge.
- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us.
- Sleep for 512ms. (600ms is recommended)
- Transfer the encoder's firmware image to offset 0 in Encoder memory space.
- Transfer the decoder's firmware image to offset 0 in Decoder memory space.
- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to
re-enable the SPU.
- Sleep for 1 second.
- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058
to re-enable the VPU.
- Sleep for 1 second.
- Issue status API commands to both firmware images to verify.
The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
GPIO0 GPIO1
0 0 TV Audio
1 0 FM radio
0 1 Line-In
1 1 Mono tuner bypass or CD passthru (tuner specific)
GPIO 16(i believe) is tied to the IR port (if present).
------------------------------------------------------------------------------------
>From the data sheet:
Register 24'h20004 PCI Interrupt Status
bit [18] IR_SMP_INT Set when 32 input samples have been collected over
gpio[16] pin into GP_SAMPLE register.
What's missing from the data sheet:
Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
compat remote)
set register 0x35C050 to 0xa80a80
enable sampling
set register 0x35C054 to 0x5
Of course, enable the IRQ bit 18 in the interrupt mask register .(and
provide for a handler)
GP_SAMPLE register is at 0x35C058
Bits are then right shifted into the GP_SAMPLE register at the specified
rate; you get an interrupt when a full DWORD is recieved.
You need to recover the actual RC5 bits out of the (oversampled) IR sensor
bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An
actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
I'm pretty sure when no IR signal is present the receiver is always in a
marking state(1); but stray light, etc can cause intermittent noise values
as well. Remember, this is a free running sample of the IR receiver state
over time, so don't assume any sample starts at any particular place.
http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
This data sheet (google search) seems to have a lovely description of the
RC5 basics
http://users.pandora.be/nenya/electronics/rc5/ and more data
http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
and even a reference to how to decode a bi-phase data stream.
http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
still more info
/* Simple Video4Linux image grabber. */
/*
* Video4Linux Driver Test/Example Framegrabbing Program
*
* Compile with:
* gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
* Use as:
* v4lgrab >image.ppm
*
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
* with minor modifications (Dave Forrest, drf5n@virginia.edu).
*
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/videodev.h>
#define FILE "/dev/video0"
/* Stole this from tvset.c */
#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
{ \
switch (format) \
{ \
case VIDEO_PALETTE_GREY: \
switch (depth) \
{ \
case 4: \
case 6: \
case 8: \
(r) = (g) = (b) = (*buf++ << 8);\
break; \
\
case 16: \
(r) = (g) = (b) = \
*((unsigned short *) buf); \
buf += 2; \
break; \
} \
break; \
\
\
case VIDEO_PALETTE_RGB565: \
{ \
unsigned short tmp = *(unsigned short *)buf; \
(r) = tmp&0xF800; \
(g) = (tmp<<5)&0xFC00; \
(b) = (tmp<<11)&0xF800; \
buf += 2; \
} \
break; \
\
case VIDEO_PALETTE_RGB555: \
(r) = (buf[0]&0xF8)<<8; \
(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
(b) = ((buf[1] << 2 ) & 0xF8)<<8; \
buf += 2; \
break; \
\
case VIDEO_PALETTE_RGB24: \
(r) = buf[0] << 8; (g) = buf[1] << 8; \
(b) = buf[2] << 8; \
buf += 3; \
break; \
\
default: \
fprintf(stderr, \
"Format %d not yet supported\n", \
format); \
} \
}
int get_brightness_adj(unsigned char *image, long size, int *brightness) {
long i, tot = 0;
for (i=0;i<size*3;i++)
tot += image[i];
*brightness = (128 - tot/(size*3))/3;
return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
}
int main(int argc, char ** argv)
{
int fd = open(FILE, O_RDONLY), f;
struct video_capability cap;
struct video_window win;
struct video_picture vpic;
unsigned char *buffer, *src;
int bpp = 24, r, g, b;
unsigned int i, src_depth;
if (fd < 0) {
perror(FILE);
exit(1);
}
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
perror("VIDIOGCAP");
fprintf(stderr, "(" FILE " not a video4linux device?)\n");
close(fd);
exit(1);
}
if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
perror("VIDIOCGWIN");
close(fd);
exit(1);
}
if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
perror("VIDIOCGPICT");
close(fd);
exit(1);
}
if (cap.type & VID_TYPE_MONOCHROME) {
vpic.depth=8;
vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=6;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=4;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
fprintf(stderr, "Unable to find a supported capture format.\n");
close(fd);
exit(1);
}
}
}
} else {
vpic.depth=24;
vpic.palette=VIDEO_PALETTE_RGB24;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.palette=VIDEO_PALETTE_RGB565;
vpic.depth=16;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
vpic.palette=VIDEO_PALETTE_RGB555;
vpic.depth=15;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
fprintf(stderr, "Unable to find a supported capture format.\n");
return -1;
}
}
}
}
buffer = malloc(win.width * win.height * bpp);
if (!buffer) {
fprintf(stderr, "Out of memory.\n");
exit(1);
}
do {
int newbright;
read(fd, buffer, win.width * win.height * bpp);
f = get_brightness_adj(buffer, win.width * win.height, &newbright);
if (f) {
vpic.brightness += (newbright << 8);
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
perror("VIDIOSPICT");
break;
}
}
} while (f);
fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
src = buffer;
for (i = 0; i < win.width * win.height; i++) {
READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
fputc(r>>8, stdout);
fputc(g>>8, stdout);
fputc(b>>8, stdout);
}
close(fd);
return 0;
}
ZC0301 Image Processor and Control Chip ZC0301 and ZC0301P Image Processor and Control Chip
Driver for Linux Driver for Linux
======================================= ===================================================
- Documentation - - Documentation -
...@@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ...@@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4. Overview and features 4. Overview and features
======================== ========================
This driver supports the video interface of the devices mounting the ZC0301 This driver supports the video interface of the devices mounting the ZC0301 or
Image Processor and Control Chip. ZC0301P Image Processors and Control Chips.
The driver relies on the Video4Linux2 and USB core modules. It has been The driver relies on the Video4Linux2 and USB core modules. It has been
designed to run properly on SMP systems as well. designed to run properly on SMP systems as well.
The latest version of the ZC0301 driver can be found at the following URL: The latest version of the ZC0301[P] driver can be found at the following URL:
http://www.linux-projects.org/ http://www.linux-projects.org/
Some of the features of the driver are: Some of the features of the driver are:
...@@ -117,7 +117,7 @@ supported by the USB Audio driver thanks to the ALSA API: ...@@ -117,7 +117,7 @@ supported by the USB Audio driver thanks to the ALSA API:
And finally: And finally:
# USB Multimedia devices # V4L USB devices
# #
CONFIG_USB_ZC0301=m CONFIG_USB_ZC0301=m
...@@ -204,11 +204,25 @@ Vendor ID Product ID ...@@ -204,11 +204,25 @@ Vendor ID Product ID
0x041e 0x4017 0x041e 0x4017
0x041e 0x401c 0x041e 0x401c
0x041e 0x401e 0x041e 0x401e
0x041e 0x401f
0x041e 0x4022
0x041e 0x4034 0x041e 0x4034
0x041e 0x4035 0x041e 0x4035
0x041e 0x4036
0x041e 0x403a
0x0458 0x7007
0x0458 0x700C
0x0458 0x700f
0x046d 0x08ae
0x055f 0xd003
0x055f 0xd004
0x046d 0x08ae 0x046d 0x08ae
0x0ac8 0x0301 0x0ac8 0x0301
0x0ac8 0x301b
0x0ac8 0x303b
0x10fd 0x0128
0x10fd 0x8050 0x10fd 0x8050
0x10fd 0x804e
The list above does not imply that all those devices work with this driver: up The list above does not imply that all those devices work with this driver: up
until now only the ones that mount the following image sensors are supported; until now only the ones that mount the following image sensors are supported;
...@@ -217,6 +231,7 @@ kernel messages will always tell you whether this is the case: ...@@ -217,6 +231,7 @@ kernel messages will always tell you whether this is the case:
Model Manufacturer Model Manufacturer
----- ------------ ----- ------------
PAS202BCB PixArt Imaging, Inc. PAS202BCB PixArt Imaging, Inc.
PB-0330 Photobit Corporation
9. Notes for V4L2 application developers 9. Notes for V4L2 application developers
...@@ -250,5 +265,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. ...@@ -250,5 +265,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
been taken from the documentation of the ZC030x Video4Linux1 driver written been taken from the documentation of the ZC030x Video4Linux1 driver written
by Andrew Birkett <andy@nobugs.org>; by Andrew Birkett <andy@nobugs.org>;
- The initialization values of the ZC0301 controller connected to the PAS202BCB - The initialization values of the ZC0301 controller connected to the PAS202BCB
image sensor have been taken from the SPCA5XX driver maintained by and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
Michel Xhaard <mxhaard@magic.fr>. by Michel Xhaard <mxhaard@magic.fr>;
- Stanislav Lechev donated one camera.
...@@ -25,7 +25,7 @@ config VIDEO_DEV ...@@ -25,7 +25,7 @@ config VIDEO_DEV
module will be called videodev. module will be called videodev.
config VIDEO_V4L1 config VIDEO_V4L1
boolean "Enable Video For Linux API 1 (DEPRECATED)" bool "Enable Video For Linux API 1 (DEPRECATED)"
depends on VIDEO_DEV depends on VIDEO_DEV
select VIDEO_V4L1_COMPAT select VIDEO_V4L1_COMPAT
default y default y
...@@ -36,7 +36,7 @@ config VIDEO_V4L1 ...@@ -36,7 +36,7 @@ config VIDEO_V4L1
If you are unsure as to whether this is required, answer Y. If you are unsure as to whether this is required, answer Y.
config VIDEO_V4L1_COMPAT config VIDEO_V4L1_COMPAT
boolean "Enable Video For Linux API 1 compatible Layer" bool "Enable Video For Linux API 1 compatible Layer"
depends on VIDEO_DEV depends on VIDEO_DEV
default y default y
---help--- ---help---
...@@ -82,6 +82,9 @@ config VIDEO_IR ...@@ -82,6 +82,9 @@ config VIDEO_IR
config VIDEO_TVEEPROM config VIDEO_TVEEPROM
tristate tristate
config VIDEO_CX2341X
tristate
config USB_DABUSB config USB_DABUSB
tristate "DABUSB driver" tristate "DABUSB driver"
depends on USB depends on USB
......
saa7146-objs := saa7146_i2c.o saa7146_core.o saa7146-objs := saa7146_i2c.o saa7146_core.o
saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
ir-common-objs := ir-functions.o ir-keymaps.o ir-common-objs := ir-functions.o ir-keymaps.o
obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
......
...@@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); ...@@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
* c-basic-offset: 8 * c-basic-offset: 8
* End: * End:
*/ */
...@@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { ...@@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_em_terratec); EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
[ 0x3a ] = KEY_0, [ 0x3a ] = KEY_0,
[ 0x31 ] = KEY_1, [ 0x31 ] = KEY_1,
[ 0x32 ] = KEY_2, [ 0x32 ] = KEY_2,
...@@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { ...@@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
[ 0x27 ] = KEY_RECORD, [ 0x27 ] = KEY_RECORD,
}; };
EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb); EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
[ 0x0f ] = KEY_0, [ 0x0f ] = KEY_0,
...@@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { ...@@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 0x0f ] = KEY_9, [ 0x0f ] = KEY_9,
[ 0x00 ] = KEY_POWER, [ 0x00 ] = KEY_POWER,
[ 0x02 ] = KEY_TUNER, /* TV/FM */ [ 0x1b ] = KEY_AUDIO, /* Audio Source */
[ 0x1e ] = KEY_VIDEO, [ 0x02 ] = KEY_TUNER, /* TV/FM, not on Y0400052 */
[ 0x1e ] = KEY_VIDEO, /* Video Source */
[ 0x16 ] = KEY_INFO, /* Display information */
[ 0x04 ] = KEY_VOLUMEUP, [ 0x04 ] = KEY_VOLUMEUP,
[ 0x08 ] = KEY_VOLUMEDOWN, [ 0x08 ] = KEY_VOLUMEDOWN,
[ 0x0c ] = KEY_CHANNELUP, [ 0x0c ] = KEY_CHANNELUP,
[ 0x10 ] = KEY_CHANNELDOWN, [ 0x10 ] = KEY_CHANNELDOWN,
[ 0x03 ] = KEY_ZOOM, /* fullscreen */ [ 0x03 ] = KEY_ZOOM, /* fullscreen */
[ 0x1f ] = KEY_SUBTITLE, /* closed caption/teletext */ [ 0x1f ] = KEY_TEXT, /* closed caption/teletext */
[ 0x20 ] = KEY_SLEEP, [ 0x20 ] = KEY_SLEEP,
[ 0x29 ] = KEY_CLEAR, /* boss key */
[ 0x14 ] = KEY_MUTE, [ 0x14 ] = KEY_MUTE,
[ 0x2b ] = KEY_RED, [ 0x2b ] = KEY_RED,
[ 0x2c ] = KEY_GREEN, [ 0x2c ] = KEY_GREEN,
[ 0x2d ] = KEY_YELLOW, [ 0x2d ] = KEY_YELLOW,
[ 0x2e ] = KEY_BLUE, [ 0x2e ] = KEY_BLUE,
[ 0x18 ] = KEY_KPPLUS, /* fine tune + */ [ 0x18 ] = KEY_KPPLUS, /* fine tune + , not on Y040052 */
[ 0x19 ] = KEY_KPMINUS, /* fine tune - */ [ 0x19 ] = KEY_KPMINUS, /* fine tune - , not on Y040052 */
[ 0x2a ] = KEY_MEDIA, /* PIP (Picture in picture */
[ 0x21 ] = KEY_DOT, [ 0x21 ] = KEY_DOT,
[ 0x13 ] = KEY_ENTER, [ 0x13 ] = KEY_ENTER,
[ 0x22 ] = KEY_BACK, [ 0x11 ] = KEY_LAST, /* Recall (last channel */
[ 0x22 ] = KEY_PREVIOUS,
[ 0x23 ] = KEY_PLAYPAUSE, [ 0x23 ] = KEY_PLAYPAUSE,
[ 0x24 ] = KEY_NEXT, [ 0x24 ] = KEY_NEXT,
[ 0x25 ] = KEY_ARCHIVE, /* Time Shifting */
[ 0x26 ] = KEY_STOP, [ 0x26 ] = KEY_STOP,
[ 0x27 ] = KEY_RECORD [ 0x27 ] = KEY_RECORD,
[ 0x28 ] = KEY_SAVE, /* Screenshot */
[ 0x2f ] = KEY_MENU,
[ 0x30 ] = KEY_CANCEL,
[ 0x31 ] = KEY_CHANNEL, /* Channel Surf */
[ 0x32 ] = KEY_SUBTITLE,
[ 0x33 ] = KEY_LANGUAGE,
[ 0x34 ] = KEY_REWIND,
[ 0x35 ] = KEY_FASTFORWARD,
[ 0x36 ] = KEY_TV,
[ 0x37 ] = KEY_RADIO, /* FM */
[ 0x38 ] = KEY_DVD
}; };
EXPORT_SYMBOL_GPL(ir_codes_winfast); EXPORT_SYMBOL_GPL(ir_codes_winfast);
IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
[ 0x59 ] = KEY_MUTE, [ 0x59 ] = KEY_MUTE,
[ 0x4a ] = KEY_POWER, [ 0x4a ] = KEY_POWER,
...@@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { ...@@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
[ 0x0a ] = KEY_BACKSPACE, [ 0x0a ] = KEY_BACKSPACE,
}; };
EXPORT_SYMBOL_GPL(ir_codes_pinnacle); EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color);
/* Hauppauge: the newer, gray remotes (seems there are multiple /* Hauppauge: the newer, gray remotes (seems there are multiple
* slightly different versions), shipped with cx88+ivtv cards. * slightly different versions), shipped with cx88+ivtv cards.
...@@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { ...@@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new);
IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
[ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */
[ 0x2a ] = KEY_FRONT,
[ 0x3e ] = KEY_1,
[ 0x02 ] = KEY_2,
[ 0x06 ] = KEY_3,
[ 0x0a ] = KEY_4,
[ 0x0e ] = KEY_5,
[ 0x12 ] = KEY_6,
[ 0x16 ] = KEY_7,
[ 0x1a ] = KEY_8,
[ 0x1e ] = KEY_9,
[ 0x3a ] = KEY_0,
[ 0x22 ] = KEY_NUMLOCK, /* -/-- */
[ 0x20 ] = KEY_REFRESH,
[ 0x03 ] = KEY_BRIGHTNESSDOWN,
[ 0x28 ] = KEY_AUDIO,
[ 0x3c ] = KEY_UP,
[ 0x3f ] = KEY_LEFT,
[ 0x2e ] = KEY_MUTE,
[ 0x3b ] = KEY_RIGHT,
[ 0x00 ] = KEY_DOWN,
[ 0x07 ] = KEY_BRIGHTNESSUP,
[ 0x2c ] = KEY_TEXT,
[ 0x37 ] = KEY_RECORD,
[ 0x17 ] = KEY_PLAY,
[ 0x13 ] = KEY_PAUSE,
[ 0x26 ] = KEY_STOP,
[ 0x18 ] = KEY_FASTFORWARD,
[ 0x14 ] = KEY_REWIND,
[ 0x33 ] = KEY_ZOOM,
[ 0x32 ] = KEY_KEYBOARD,
[ 0x30 ] = KEY_GOTO, /* Pointing arrow */
[ 0x36 ] = KEY_MACRO, /* Maximize/Minimize (yellow) */
[ 0x0b ] = KEY_RADIO,
[ 0x10 ] = KEY_POWER,
};
EXPORT_SYMBOL_GPL(ir_codes_npgtech);
...@@ -501,6 +501,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) ...@@ -501,6 +501,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_vv_init);
int saa7146_vv_release(struct saa7146_dev* dev) int saa7146_vv_release(struct saa7146_dev* dev)
{ {
...@@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_dev* dev) ...@@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_vv_release);
int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
char *name, int type) char *name, int type)
...@@ -553,6 +555,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, ...@@ -553,6 +555,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
*vid = vfd; *vid = vfd;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_register_device);
int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
{ {
...@@ -571,6 +574,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev ...@@ -571,6 +574,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_unregister_device);
static int __init saa7146_vv_init_module(void) static int __init saa7146_vv_init_module(void)
{ {
......
...@@ -641,6 +641,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy ...@@ -641,6 +641,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
vv->current_hps_source = source; vv->current_hps_source = source;
vv->current_hps_sync = sync; vv->current_hps_sync = sync;
} }
EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
int saa7146_enable_overlay(struct saa7146_fh *fh) int saa7146_enable_overlay(struct saa7146_fh *fh)
{ {
......
...@@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146_fh *fh) ...@@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146_fh *fh)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_start_preview);
int saa7146_stop_preview(struct saa7146_fh *fh) int saa7146_stop_preview(struct saa7146_fh *fh)
{ {
...@@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh) ...@@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(saa7146_stop_preview);
static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
{ {
......
#include <linux/module.h>
#include <media/saa7146_vv.h>
EXPORT_SYMBOL_GPL(saa7146_start_preview);
EXPORT_SYMBOL_GPL(saa7146_stop_preview);
EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
EXPORT_SYMBOL_GPL(saa7146_register_device);
EXPORT_SYMBOL_GPL(saa7146_unregister_device);
EXPORT_SYMBOL_GPL(saa7146_vv_init);
EXPORT_SYMBOL_GPL(saa7146_vv_release);
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "stv0297.h" #include "stv0297.h"
#include "mt312.h" #include "mt312.h"
#include "lgdt330x.h" #include "lgdt330x.h"
#include "lg_h06xf.h"
#include "dvb-pll.h" #include "dvb-pll.h"
/* lnb control */ /* lnb control */
...@@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, ...@@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
return 0; return 0;
} }
static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{ {
u8 buf[4]; u8 buf[4];
u32 div; u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
struct flexcop_device *fc = fe->dvb->priv;
div = params->frequency / 125; div = params->frequency / 125;
...@@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter ...@@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter
if (params->frequency < 1500000) buf[3] |= 0x10; if (params->frequency < 1500000) buf[3] |= 0x10;
if (i2c_transfer(i2c, &msg, 1) != 1) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
return -EIO; return -EIO;
}
return 0; return 0;
} }
...@@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = { ...@@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP1, .volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100, .min_delay_ms = 100,
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate, .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
.pll_set = samsung_tbmu24112_pll_set,
}; };
/* dvb-t mt352 */ /* dvb-t mt352 */
...@@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) ...@@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0; return 0;
} }
static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
{ {
u32 div; u32 div;
unsigned char bs = 0; unsigned char bs = 0;
if (buf_len < 5)
return -EINVAL;
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
...@@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front ...@@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */ pllbuf[0] = 0x61;
pllbuf[1] = div >> 8; pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff; pllbuf[2] = div & 0xff;
pllbuf[3] = 0xcc; pllbuf[3] = 0xcc;
pllbuf[4] = bs; pllbuf[4] = bs;
return 0; return 5;
} }
static struct mt352_config samsung_tdtc9251dh0_config = { static struct mt352_config samsung_tdtc9251dh0_config = {
.demod_address = 0x0f, .demod_address = 0x0f,
.demod_init = samsung_tdtc9251dh0_demod_init, .demod_init = samsung_tdtc9251dh0_demod_init,
.pll_set = samsung_tdtc9251dh0_pll_set,
}; };
static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
...@@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir ...@@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
return request_firmware(fw, name, fc->dev); return request_firmware(fw, name, fc->dev);
} }
static int lgdt3303_pll_set(struct dvb_frontend* fe, static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
struct dvb_frontend_parameters* params)
{ {
struct flexcop_device *fc = fe->dvb->priv; struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4]; return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
struct i2c_msg msg =
{ .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
int err;
dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
printk(KERN_WARNING "lgdt3303: %s error "
"(addr %02x <- %02x, err = %i)\n",
__FUNCTION__, buf[0], buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
buf[0] = 0x86 | 0x18;
buf[1] = 0x50;
msg.len = 2;
if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
printk(KERN_WARNING "lgdt3303: %s error "
"(addr %02x <- %02x, err = %i)\n",
__FUNCTION__, buf[0], buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
return 0;
} }
static struct lgdt330x_config air2pc_atsc_hd5000_config = { static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59, .demod_address = 0x59,
.demod_chip = LGDT3303, .demod_chip = LGDT3303,
.serial_mpeg = 0x04, .serial_mpeg = 0x04,
.pll_set = lgdt3303_pll_set,
.clock_polarity_flip = 1, .clock_polarity_flip = 1,
}; };
static struct nxt200x_config samsung_tbmv_config = { static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a, .demod_address = 0x0a,
.pll_address = 0xc2,
.pll_desc = &dvb_pll_samsung_tbmv,
}; };
static struct bcm3510_config air2pc_atsc_first_gen_config = { static struct bcm3510_config air2pc_atsc_first_gen_config = {
...@@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = { ...@@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = {
.request_firmware = flexcop_fe_request_firmware, .request_firmware = flexcop_fe_request_firmware,
}; };
static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{ {
u8 buf[4]; u8 buf[4];
u32 div; u32 div;
...@@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d ...@@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
if (params->frequency < 1550000) if (params->frequency < 1550000)
buf[3] |= 0x02; buf[3] |= 0x02;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
return -EIO; return -EIO;
return 0; return 0;
...@@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d ...@@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
static struct mt312_config skystar23_samsung_tbdu18132_config = { static struct mt312_config skystar23_samsung_tbdu18132_config = {
.demod_address = 0x0e, .demod_address = 0x0e,
.pll_set = skystar23_samsung_tbdu18132_pll_set,
}; };
static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
u16 div;
int ret;
/* 62.5 kHz * 10 */
#define REF_FREQ 625
#define FREQ_OFFSET 36125
div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz
buf[0] = (u8)( div >> 8) & 0x7f;
buf[1] = (u8) div & 0xff;
/* F(osc) = N * Reference Freq. (62.5 kHz)
* byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
* byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
* byte 4 : 1 * * AGD R3 R2 R1 R0
* byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
* AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
buf[2] = 0x95;
// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
// 47 - 153 0 * 0 0 0 0 0 1 0x01
// 153 - 430 0 * 0 0 0 0 1 0 0x02
// 430 - 822 0 * 0 0 1 0 0 0 0x08
// 822 - 862 1 * 0 0 1 0 0 0 0x88
if (fep->frequency <= 153000000) buf[3] = 0x01;
else if (fep->frequency <= 430000000) buf[3] = 0x02;
else if (fep->frequency <= 822000000) buf[3] = 0x08;
else buf[3] = 0x88;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
deb_tuner("tuner write returned: %d\n",ret);
return 0;
}
static u8 alps_tdee4_stv0297_inittab[] = { static u8 alps_tdee4_stv0297_inittab[] = {
0x80, 0x01, 0x80, 0x01,
...@@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc) ...@@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
ops = fc->fe->ops; ops = &fc->fe->ops;
ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
ops->set_voltage = flexcop_set_voltage; ops->set_voltage = flexcop_set_voltage;
...@@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc) ...@@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
fc->dev_type = FC_AIR_DVB; fc->dev_type = FC_AIR_DVB;
fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
} else } else
/* try the air atsc 2nd generation (nxt2002) */ /* try the air atsc 2nd generation (nxt2002) */
if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2; fc->dev_type = FC_AIR_ATSC2;
dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else } else
/* try the air atsc 3nd generation (lgdt3303) */ /* try the air atsc 3nd generation (lgdt3303) */
if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC3; fc->dev_type = FC_AIR_ATSC3;
fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
} else } else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
...@@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc) ...@@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the cable dvb (stv0297) */ /* try the cable dvb (stv0297) */
if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_CABLE; fc->dev_type = FC_CABLE;
fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
} else } else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
ops = fc->fe->ops; ops = &fc->fe->ops;
ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
ops->diseqc_send_burst = flexcop_diseqc_send_burst; ops->diseqc_send_burst = flexcop_diseqc_send_burst;
...@@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) ...@@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else { } else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!"); err("frontend registration failed!");
ops = fc->fe->ops; ops = &fc->fe->ops;
if (ops->release != NULL) if (ops->release != NULL)
ops->release(fc->fe); ops->release(fc->fe);
fc->fe = NULL; fc->fe = NULL;
......
...@@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci) ...@@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0) if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
return ret; return ret;
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
goto dma1_free; flexcop_dma_free(&fc_pci->dma[0]);
return ret;
}
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
fc_pci->init_state |= FC_PCI_DMA_INIT; fc_pci->init_state |= FC_PCI_DMA_INIT;
goto success;
dma1_free:
flexcop_dma_free(&fc_pci->dma[0]);
success:
return ret; return ret;
} }
...@@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) ...@@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
spin_lock_init(&fc_pci->irq_lock); spin_lock_init(&fc_pci->irq_lock);
fc_pci->init_state |= FC_PCI_INIT; fc_pci->init_state |= FC_PCI_INIT;
goto success; return ret;
err_pci_iounmap: err_pci_iounmap:
pci_iounmap(fc_pci->pdev, fc_pci->io_mem); pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
...@@ -312,8 +309,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) ...@@ -312,8 +309,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
pci_release_regions(fc_pci->pdev); pci_release_regions(fc_pci->pdev);
err_pci_disable_device: err_pci_disable_device:
pci_disable_device(fc_pci->pdev); pci_disable_device(fc_pci->pdev);
success:
return ret; return ret;
} }
...@@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e ...@@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
goto success; return ret;
err_fc_exit: err_fc_exit:
flexcop_device_exit(fc); flexcop_device_exit(fc);
err_pci_exit: err_pci_exit:
flexcop_pci_exit(fc_pci); flexcop_pci_exit(fc_pci);
err_kfree: err_kfree:
flexcop_device_kfree(fc); flexcop_device_kfree(fc);
success:
return ret; return ret;
} }
......
...@@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) ...@@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS); flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1); flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
ret = 0; return 0;
goto success;
urb_error: urb_error:
flexcop_usb_transfer_exit(fc_usb); flexcop_usb_transfer_exit(fc_usb);
success:
return ret; return ret;
} }
...@@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf, ...@@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf,
goto err_fc_exit; goto err_fc_exit;
info("%s successfully initialized and connected.",DRIVER_NAME); info("%s successfully initialized and connected.",DRIVER_NAME);
ret = 0; return 0;
goto success;
err_fc_exit: err_fc_exit:
flexcop_device_exit(fc); flexcop_device_exit(fc);
err_usb_exit: err_usb_exit:
flexcop_usb_exit(fc_usb); flexcop_usb_exit(fc_usb);
err_kfree: err_kfree:
flexcop_device_kfree(fc); flexcop_device_kfree(fc);
success:
return ret; return ret;
} }
......
...@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) ...@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
static int flexcop_dvb_init(struct flexcop_device *fc) static int flexcop_dvb_init(struct flexcop_device *fc)
{ {
int ret; int ret;
if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) { if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
err("error registering DVB adapter"); err("error registering DVB adapter");
return ret; return ret;
} }
...@@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc) ...@@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx); dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
fc->init_state |= FC_STATE_DVB_INIT; fc->init_state |= FC_STATE_DVB_INIT;
goto success; return 0;
err_connect_frontend: err_connect_frontend:
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
...@@ -129,9 +129,6 @@ static int flexcop_dvb_init(struct flexcop_device *fc) ...@@ -129,9 +129,6 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
err_dmx: err_dmx:
dvb_unregister_adapter(&fc->dvb_adapter); dvb_unregister_adapter(&fc->dvb_adapter);
return ret; return ret;
success:
return 0;
} }
static void flexcop_dvb_exit(struct flexcop_device *fc) static void flexcop_dvb_exit(struct flexcop_device *fc)
...@@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc) ...@@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc)
flexcop_device_name(fc,"initialization of","complete"); flexcop_device_name(fc,"initialization of","complete");
ret = 0; return 0;
goto success;
error: error:
flexcop_device_exit(fc); flexcop_device_exit(fc);
success:
return ret; return ret;
} }
EXPORT_SYMBOL(flexcop_device_initialize); EXPORT_SYMBOL(flexcop_device_initialize);
......
...@@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off)."); ...@@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
int bt878_num; int bt878_num;
struct bt878 bt878[BT878_MAX]; struct bt878 bt878[BT878_MAX];
EXPORT_SYMBOL(bt878_debug);
EXPORT_SYMBOL(bt878_verbose);
EXPORT_SYMBOL(bt878_num); EXPORT_SYMBOL(bt878_num);
EXPORT_SYMBOL(bt878); EXPORT_SYMBOL(bt878);
...@@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = { ...@@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = {
{ 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" },
{ 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" },
{ 0, -1, NULL } { 0, -1, NULL }
}; };
...@@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev, ...@@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num); bt878_num);
if (bt878_num >= BT878_MAX) {
printk(KERN_ERR "bt878: Too many devices inserted\n");
result = -ENOMEM;
goto fail0;
}
if (pci_enable_device(dev)) if (pci_enable_device(dev))
return -EIO; return -EIO;
......
This diff is collapsed.
...@@ -68,6 +68,13 @@ static int ca_set_pid(void) ...@@ -68,6 +68,13 @@ static int ca_set_pid(void)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static void put_command_and_length(u8 *data, int command, int length)
{
data[0] = (command >> 16) & 0xff;
data[1] = (command >> 8) & 0xff;
data[2] = command & 0xff;
data[3] = length;
}
static void put_checksum(u8 *check_string, int length) static void put_checksum(u8 *check_string, int length)
{ {
...@@ -124,14 +131,17 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, ...@@ -124,14 +131,17 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
u8 dst_ca_comm_err = 0; u8 dst_ca_comm_err = 0;
while (dst_ca_comm_err < RETRIES) { while (dst_ca_comm_err < RETRIES) {
dst_comm_init(state);
dprintk(verbose, DST_CA_NOTICE, 1, " Put Command"); dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
if (dst_ci_command(state, data, ca_string, len, read)) { // If error if (dst_ci_command(state, data, ca_string, len, read)) { // If error
dst_error_recovery(state); dst_error_recovery(state);
dst_ca_comm_err++; // work required here. dst_ca_comm_err++; // work required here.
} } else {
break; break;
} }
}
if(dst_ca_comm_err == RETRIES)
return -1;
return 0; return 0;
} }
...@@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, ...@@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
static int ca_get_app_info(struct dst_state *state) static int ca_get_app_info(struct dst_state *state)
{ {
int length, str_length;
static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff}; static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
put_checksum(&command[0], command[0]); put_checksum(&command[0], command[0]);
...@@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state) ...@@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state)
(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
// Transform dst message to correct application_info message
length = state->messages[5];
str_length = length - 6;
if (str_length < 0) {
str_length = 0;
dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
}
// First, the command and length fields
put_command_and_length(&state->messages[0], CA_APP_INFO, length);
// Copy application_type, application_manufacturer and manufacturer_code
memcpy(&state->messages[4], &state->messages[7], 5);
// Set string length and copy string
state->messages[9] = str_length;
memcpy(&state->messages[10], &state->messages[12], str_length);
return 0;
}
static int ca_get_ca_info(struct dst_state *state)
{
int srcPtr, dstPtr, i, num_ids;
static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
put_checksum(&slot_command[0], slot_command[0]);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
// Print raw data
dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
for (i = 0; i < state->messages[0] + 1; i++) {
dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
}
dprintk(verbose, DST_CA_INFO, 0, "]\n");
// Set the command and length of the output
num_ids = state->messages[in_num_ids_pos];
if (num_ids >= 100) {
num_ids = 100;
dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
}
put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
srcPtr = in_system_id_pos;
dstPtr = out_system_id_pos;
for(i = 0; i < num_ids; i++) {
dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
// Append to output
state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
srcPtr += 2;
dstPtr += 2;
}
dprintk(verbose, DST_CA_INFO, 0, "]\n");
return 0; return 0;
} }
...@@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, ...@@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]); dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
dprintk(verbose, DST_CA_INFO, 0, "===================================\n"); dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
for (i = 0; i < 8; i++) for (i = 0; i < slot_cap[0] + 1; i++)
dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]); dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
dprintk(verbose, DST_CA_INFO, 0, "\n"); dprintk(verbose, DST_CA_INFO, 0, "\n");
...@@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, ...@@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
return -EFAULT; return -EFAULT;
break; break;
case CA_INFO:
memcpy(p_ca_message->msg, state->messages, 128);
if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
return -EFAULT;
break;
} }
} }
...@@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l ...@@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l
rdc_reset_state(state); rdc_reset_state(state);
return -1; return -1;
} }
dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes."); dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
return 0; return 0;
} }
...@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset) ...@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset)
return 0; return 0;
} }
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query) static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
{ {
u32 length = 0; u32 length = 0;
...@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, ...@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
} }
dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
break; break;
case CA_INFO_ENQUIRY:
dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
if ((ca_get_ca_info(state)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
result = -1;
goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
break;
} }
} }
free_mem_and_exit: free_mem_and_exit:
...@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
void __user *arg = (void __user *)ioctl_arg; void __user *arg = (void __user *)ioctl_arg;
int result = 0; int result = 0;
if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
return -ENOMEM; p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
} if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM; result = -ENOMEM;
} goto free_mem_and_exit;
if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
} }
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */ /* We have now only the standard ioctl's, the driver is upposed to handle internals. */
switch (cmd) { switch (cmd) {
case CA_SEND_MSG: case CA_SEND_MSG:
...@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file) ...@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file)
static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{ {
int bytes_read = 0; ssize_t bytes_read = 0;
dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#define DST_TYPE_IS_CABLE 2 #define DST_TYPE_IS_CABLE 2
#define DST_TYPE_IS_ATSC 3 #define DST_TYPE_IS_ATSC 3
#define DST_TYPE_HAS_NEWTUNE 1 #define DST_TYPE_HAS_TS188 1
#define DST_TYPE_HAS_TS204 2 #define DST_TYPE_HAS_TS204 2
#define DST_TYPE_HAS_SYMDIV 4 #define DST_TYPE_HAS_SYMDIV 4
#define DST_TYPE_HAS_FW_1 8 #define DST_TYPE_HAS_FW_1 8
...@@ -52,6 +52,9 @@ ...@@ -52,6 +52,9 @@
#define DST_TYPE_HAS_OBS_REGS 128 #define DST_TYPE_HAS_OBS_REGS 128
#define DST_TYPE_HAS_INC_COUNT 256 #define DST_TYPE_HAS_INC_COUNT 256
#define DST_TYPE_HAS_MULTI_FE 512 #define DST_TYPE_HAS_MULTI_FE 512
#define DST_TYPE_HAS_NEWTUNE_2 1024
#define DST_TYPE_HAS_DBOARD 2048
#define DST_TYPE_HAS_VLF 4096
/* Card capability list */ /* Card capability list */
...@@ -64,6 +67,20 @@ ...@@ -64,6 +67,20 @@
#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */ #define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
#define DST_TYPE_HAS_SESSION 128 #define DST_TYPE_HAS_SESSION 128
#define TUNER_TYPE_MULTI 1
#define TUNER_TYPE_UNKNOWN 2
/* DVB-S */
#define TUNER_TYPE_L64724 4
#define TUNER_TYPE_STV0299 8
#define TUNER_TYPE_MB86A15 16
/* DVB-T */
#define TUNER_TYPE_TDA10046 32
/* ATSC */
#define TUNER_TYPE_NXT200x 64
#define RDC_8820_PIO_0_DISABLE 0 #define RDC_8820_PIO_0_DISABLE 0
#define RDC_8820_PIO_0_ENABLE 1 #define RDC_8820_PIO_0_ENABLE 1
#define RDC_8820_INT 2 #define RDC_8820_INT 2
...@@ -84,8 +101,6 @@ struct dst_state { ...@@ -84,8 +101,6 @@ struct dst_state {
struct bt878* bt; struct bt878* bt;
struct dvb_frontend_ops ops;
/* configuration settings */ /* configuration settings */
const struct dst_config* config; const struct dst_config* config;
...@@ -121,8 +136,17 @@ struct dst_state { ...@@ -121,8 +136,17 @@ struct dst_state {
u8 card_info[8]; u8 card_info[8];
u8 vendor[8]; u8 vendor[8];
u8 board_info[8]; u8 board_info[8];
u32 tuner_type;
char *tuner_name;
struct mutex dst_mutex; struct mutex dst_mutex;
u8 fw_name[8];
};
struct tuner_types {
u32 tuner_type;
char *tuner_name;
char *board_name;
char *fw_name;
}; };
struct dst_types { struct dst_types {
...@@ -131,6 +155,7 @@ struct dst_types { ...@@ -131,6 +155,7 @@ struct dst_types {
u8 dst_type; u8 dst_type;
u32 type_flags; u32 type_flags;
u32 dst_feature; u32 dst_feature;
u32 tuner_type;
}; };
struct dst_config struct dst_config
......
This diff is collapsed.
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "cx24110.h" #include "cx24110.h"
#include "or51211.h" #include "or51211.h"
#include "lgdt330x.h" #include "lgdt330x.h"
#include "lg_h06xf.h"
#include "zl10353.h"
struct dvb_bt8xx_card { struct dvb_bt8xx_card {
struct mutex lock; struct mutex lock;
......
...@@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL ...@@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device" bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING depends on DVB_CINERGYT2_TUNING
default "yes" default y
help help
Enable this option if you want to use the onboard Infrared Remote Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device. Control Receiver as Linux-Input device.
......
...@@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct ...@@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv; struct cinergyt2 *cinergyt2 = dvbdev->priv;
unsigned int mask = 0;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS; return -ERESTARTSYS;
poll_wait(file, &cinergyt2->poll_wq, wait); poll_wait(file, &cinergyt2->poll_wq, wait);
if (cinergyt2->pending_fe_events != 0)
mask |= (POLLIN | POLLRDNORM | POLLPRI);
mutex_unlock(&cinergyt2->sem); mutex_unlock(&cinergyt2->sem);
return (POLLIN | POLLRDNORM | POLLPRI); return mask;
} }
...@@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf, ...@@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
return -ENOMEM; return -ENOMEM;
} }
if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) { if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
kfree(cinergyt2); kfree(cinergyt2);
return err; return err;
} }
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_ca_en50221.o dvb_frontend.o \ dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o dvb_net.o dvb_ringbuffer.o dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o obj-$(CONFIG_DVB_CORE) += dvb-core.o
...@@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, ...@@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
mutex_unlock(&dmxdevfilter->mutex); mutex_unlock(&dmxdevfilter->mutex);
break; break;
case DMX_GET_EVENT:
break;
case DMX_GET_PES_PIDS: case DMX_GET_PES_PIDS:
if (!dmxdev->demux->get_pes_pids) { if (!dmxdev->demux->get_pes_pids) {
ret = -EINVAL; ret = -EINVAL;
......
...@@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data) ...@@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data)
break; break;
case DVB_CA_SLOTSTATE_VALIDATE: case DVB_CA_SLOTSTATE_VALIDATE:
if (dvb_ca_en50221_parse_attributes(ca, slot) if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
!= 0) { /* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
break;
}
}
printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
ca->dvbdev->adapter->num); ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
...@@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data) ...@@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data)
case DVB_CA_SLOTSTATE_LINKINIT: case DVB_CA_SLOTSTATE_LINKINIT:
if (dvb_ca_en50221_link_init(ca, slot) != 0) { if (dvb_ca_en50221_link_init(ca, slot) != 0) {
/* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
break;
}
}
printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca); dvb_ca_en50221_thread_update_delay(ca);
......
...@@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) ...@@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
goto bailout; goto bailout;
} }
memcpy(&demux->tsbuf[i], buf, j); memcpy(&demux->tsbuf[i], buf, j);
if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) { if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
memcpy(tmppack, demux->tsbuf, 188); memcpy(tmppack, demux->tsbuf, 188);
if (tmppack[0] == 0xB8) if (tmppack[0] == 0xB8)
tmppack[0] = 0x47; tmppack[0] = 0x47;
...@@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) ...@@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
} }
while (p < count) { while (p < count) {
if ((buf[p] == 0x47) | (buf[p] == 0xB8)) { if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
if (count - p >= 204) { if (count - p >= 204) {
memcpy(tmppack, &buf[p], 188); memcpy(tmppack, &buf[p], 188);
if (tmppack[0] == 0xB8) if (tmppack[0] == 0xB8)
......
This diff is collapsed.
...@@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings { ...@@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings {
struct dvb_frontend; struct dvb_frontend;
struct dvb_tuner_info {
char name[128];
u32 frequency_min;
u32 frequency_max;
u32 frequency_step;
u32 bandwidth_min;
u32 bandwidth_max;
u32 bandwidth_step;
};
struct dvb_tuner_ops {
struct dvb_tuner_info info;
int (*release)(struct dvb_frontend *fe);
int (*init)(struct dvb_frontend *fe);
int (*sleep)(struct dvb_frontend *fe);
/** This is for simple PLLs - set all parameters in one go. */
int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
#define TUNER_STATUS_LOCKED 1
int (*get_status)(struct dvb_frontend *fe, u32 *status);
/** These are provided seperately from set_params in order to facilitate silicon
* tuners which require sophisticated tuning loops, controlling each parameter seperately. */
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
};
struct dvb_frontend_ops { struct dvb_frontend_ops {
struct dvb_frontend_info info; struct dvb_frontend_info info;
...@@ -64,6 +102,8 @@ struct dvb_frontend_ops { ...@@ -64,6 +102,8 @@ struct dvb_frontend_ops {
unsigned int mode_flags, unsigned int mode_flags,
int *delay, int *delay,
fe_status_t *status); fe_status_t *status);
/* get frontend tuning algorithm from the module */
int (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */ /* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
...@@ -86,6 +126,8 @@ struct dvb_frontend_ops { ...@@ -86,6 +126,8 @@ struct dvb_frontend_ops {
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg); int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
struct dvb_tuner_ops tuner_ops;
}; };
#define MAX_EVENT 8 #define MAX_EVENT 8
...@@ -100,9 +142,10 @@ struct dvb_fe_events { ...@@ -100,9 +142,10 @@ struct dvb_fe_events {
}; };
struct dvb_frontend { struct dvb_frontend {
struct dvb_frontend_ops* ops; struct dvb_frontend_ops ops;
struct dvb_adapter *dvb; struct dvb_adapter *dvb;
void* demodulator_priv; void* demodulator_priv;
void* tuner_priv;
void* frontend_priv; void* frontend_priv;
void* misc_priv; void* misc_priv;
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -51,6 +51,8 @@ struct dvb_adapter { ...@@ -51,6 +51,8 @@ struct dvb_adapter {
u8 proposed_mac [6]; u8 proposed_mac [6];
void* priv; void* priv;
struct device *device;
struct module *module; struct module *module;
}; };
...@@ -76,7 +78,7 @@ struct dvb_device { ...@@ -76,7 +78,7 @@ struct dvb_device {
}; };
extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module); extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
extern int dvb_unregister_adapter (struct dvb_adapter *adap); extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap, extern int dvb_register_device (struct dvb_adapter *adap,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o ...@@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment