mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
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. ...
This commit is contained in:
commit
25581ad107
304 changed files with 21100 additions and 6532 deletions
|
@ -87,7 +87,7 @@
|
|||
86 -> Osprey 101/151 w/ svid
|
||||
87 -> Osprey 200/201/250/251
|
||||
88 -> Osprey 200/250 [0070:ff01]
|
||||
89 -> Osprey 210/220
|
||||
89 -> Osprey 210/220/230
|
||||
90 -> Osprey 500 [0070:ff02]
|
||||
91 -> Osprey 540 [0070:ff04]
|
||||
92 -> Osprey 2000 [0070:ff03]
|
||||
|
@ -111,7 +111,7 @@
|
|||
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]
|
||||
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]
|
||||
115 -> Teppro TEV-560/InterVision IV-560
|
||||
116 -> SIMUS GVC1100 [aa6a:82b2]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
14 -> KWorld/VStream XPert DVB-T [17de:08a6]
|
||||
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
|
||||
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]
|
||||
19 -> Conexant DVB-T reference design [14f1:0187]
|
||||
20 -> Provideo PV259 [1540:2580]
|
||||
|
@ -40,8 +40,13 @@
|
|||
39 -> KWorld DVB-S 100 [17de:08b2]
|
||||
40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402]
|
||||
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]
|
||||
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
|
||||
45 -> KWorld HardwareMpegTV XPert [17de:0840]
|
||||
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 @@
|
|||
92 -> AVerMedia A169 B1 [1461:6360]
|
||||
93 -> Medion 7134 Bridge #2 [16be:0005]
|
||||
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)
|
|||
tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
|
||||
tuner=62 - Philips TEA5767HN FM Radio
|
||||
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=66 - LG TALN series
|
||||
tuner=67 - Philips TD1316 Hybrid Tuner
|
||||
|
@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar models
|
|||
tuner=70 - Samsung TCPN 2121P30A
|
||||
tuner=71 - Xceive xc3028
|
||||
tuner=72 - Thomson FE6600
|
||||
tuner=73 - Samsung TCPG 6121P30A
|
||||
|
|
|
@ -185,207 +185,10 @@ this work is documented at the video4linux2 site listed below.
|
|||
|
||||
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
|
||||
format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg'
|
||||
produced this picture of me at
|
||||
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< -----------------------------
|
||||
format (.ppm) To produce .jpg output, you can use it like this:
|
||||
'v4lgrab | convert - c-qcam.jpg'
|
||||
|
||||
|
||||
10.0 --- Other Information
|
||||
|
|
|
@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video
|
|||
Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
|
||||
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:
|
||||
* Zoran zr36067 PCI controller
|
||||
* Zoran zr36060 MJPEG codec
|
||||
|
@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder
|
|||
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
|
||||
|
||||
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
|
||||
|
@ -221,6 +240,10 @@ ITT mse3000 TV encoder
|
|||
was introduced in 1991, is used in the DC10 old
|
||||
can generate: PAL , NTSC , SECAM
|
||||
|
||||
Conexant bt866 TV encoder
|
||||
is used in AVS6EYES, and
|
||||
can generate: NTSC/PAL, PALM, PALN
|
||||
|
||||
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
|
||||
to generate PAL N, maybe it would work if you use the PAL M settings.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Contributors to bttv:
|
||||
Contributors to bttv:
|
||||
|
||||
Michael Chu <mmchu@pobox.com>
|
||||
AverMedia fix and more flexible card recognition
|
||||
|
@ -8,8 +8,8 @@ Alan Cox <alan@redhat.com>
|
|||
|
||||
Chris Kleitsch
|
||||
Hardware I2C
|
||||
|
||||
Gerd Knorr <kraxel@cs.tu-berlin.de>
|
||||
|
||||
Gerd Knorr <kraxel@cs.tu-berlin.de>
|
||||
Radio card (ITT sound processor)
|
||||
|
||||
bigfoot <bigfoot@net-way.net>
|
||||
|
@ -18,7 +18,7 @@ Ragnar Hojland Espinosa <ragnar@macula.net>
|
|||
|
||||
|
||||
+ many more (please mail me if you are missing in this list and would
|
||||
like to be mentioned)
|
||||
like to be mentioned)
|
||||
|
||||
|
||||
|
||||
|
|
69
Documentation/video4linux/cx2341x/fw-calling.txt
Normal file
69
Documentation/video4linux/cx2341x/fw-calling.txt
Normal file
|
@ -0,0 +1,69 @@
|
|||
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.
|
||||
|
319
Documentation/video4linux/cx2341x/fw-decoder-api.txt
Normal file
319
Documentation/video4linux/cx2341x/fw-decoder-api.txt
Normal file
|
@ -0,0 +1,319 @@
|
|||
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
|
94
Documentation/video4linux/cx2341x/fw-dma.txt
Normal file
94
Documentation/video4linux/cx2341x/fw-dma.txt
Normal file
|
@ -0,0 +1,94 @@
|
|||
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
|
694
Documentation/video4linux/cx2341x/fw-encoder-api.txt
Normal file
694
Documentation/video4linux/cx2341x/fw-encoder-api.txt
Normal file
|
@ -0,0 +1,694 @@
|
|||
Encoder firmware API description
|
||||
================================
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_PING_FW
|
||||
Enum 128/0x80
|
||||
Description
|
||||
Does nothing. Can be used to check if the firmware is responding.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_START_CAPTURE
|
||||
Enum 129/0x81
|
||||
Description
|
||||
Commences the capture of video, audio and/or VBI data. All encoding
|
||||
parameters must be initialized prior to this API call. Captures frames
|
||||
continuously or until a predefined number of frames have been captured.
|
||||
Param[0]
|
||||
Capture stream type:
|
||||
0=MPEG
|
||||
1=Raw
|
||||
2=Raw passthrough
|
||||
3=VBI
|
||||
|
||||
Param[1]
|
||||
Bitmask:
|
||||
Bit 0 when set, captures YUV
|
||||
Bit 1 when set, captures PCM audio
|
||||
Bit 2 when set, captures VBI (same as param[0]=3)
|
||||
Bit 3 when set, the capture destination is the decoder
|
||||
(same as param[0]=2)
|
||||
Bit 4 when set, the capture destination is the host
|
||||
Note: this parameter is only meaningful for RAW capture type.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_STOP_CAPTURE
|
||||
Enum 130/0x82
|
||||
Description
|
||||
Ends a capture in progress
|
||||
Param[0]
|
||||
0=stop at end of GOP (generates IRQ)
|
||||
1=stop immediate (no IRQ)
|
||||
Param[1]
|
||||
Stream type to stop, see param[0] of API 0x81
|
||||
Param[2]
|
||||
Subtype, see param[1] of API 0x81
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_AUDIO_ID
|
||||
Enum 137/0x89
|
||||
Description
|
||||
Assigns the transport stream ID of the encoded audio stream
|
||||
Param[0]
|
||||
Audio Stream ID
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_VIDEO_ID
|
||||
Enum 139/0x8B
|
||||
Description
|
||||
Set video transport stream ID
|
||||
Param[0]
|
||||
Video stream ID
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_PCR_ID
|
||||
Enum 141/0x8D
|
||||
Description
|
||||
Assigns the transport stream ID for PCR packets
|
||||
Param[0]
|
||||
PCR Stream ID
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_FRAME_RATE
|
||||
Enum 143/0x8F
|
||||
Description
|
||||
Set video frames per second. Change occurs at start of new GOP.
|
||||
Param[0]
|
||||
0=30fps
|
||||
1=25fps
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_FRAME_SIZE
|
||||
Enum 145/0x91
|
||||
Description
|
||||
Select video stream encoding resolution.
|
||||
Param[0]
|
||||
Height in lines. Default 480
|
||||
Param[1]
|
||||
Width in pixels. Default 720
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_BIT_RATE
|
||||
Enum 149/0x95
|
||||
Description
|
||||
Assign average video stream bitrate. Note on the last three params:
|
||||
Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used.
|
||||
Param[0]
|
||||
0=variable bitrate, 1=constant bitrate
|
||||
Param[1]
|
||||
bitrate in bits per second
|
||||
Param[2]
|
||||
peak bitrate in bits per second, divided by 400
|
||||
Param[3]
|
||||
Mux bitrate in bits per second, divided by 400. May be 0 (default).
|
||||
Param[4]
|
||||
Rate Control VBR Padding
|
||||
Param[5]
|
||||
VBV Buffer used by encoder
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_GOP_PROPERTIES
|
||||
Enum 151/0x97
|
||||
Description
|
||||
Setup the GOP structure
|
||||
Param[0]
|
||||
GOP size (maximum is 34)
|
||||
Param[1]
|
||||
Number of B frames between the I and P frame, plus 1.
|
||||
For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3
|
||||
Note that GOP size must be a multiple of (B-frames + 1).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_ASPECT_RATIO
|
||||
Enum 153/0x99
|
||||
Description
|
||||
Sets the encoding aspect ratio. Changes in the aspect ratio take effect
|
||||
at the start of the next GOP.
|
||||
Param[0]
|
||||
'0000' forbidden
|
||||
'0001' 1:1 square
|
||||
'0010' 4:3
|
||||
'0011' 16:9
|
||||
'0100' 2.21:1
|
||||
'0101' reserved
|
||||
....
|
||||
'1111' reserved
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_DNR_FILTER_MODE
|
||||
Enum 155/0x9B
|
||||
Description
|
||||
Assign Dynamic Noise Reduction operating mode
|
||||
Param[0]
|
||||
Bit0: Spatial filter, set=auto, clear=manual
|
||||
Bit1: Temporal filter, set=auto, clear=manual
|
||||
Param[1]
|
||||
Median filter:
|
||||
0=Disabled
|
||||
1=Horizontal
|
||||
2=Vertical
|
||||
3=Horiz/Vert
|
||||
4=Diagonal
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_DNR_FILTER_PROPS
|
||||
Enum 157/0x9D
|
||||
Description
|
||||
These Dynamic Noise Reduction filter values are only meaningful when
|
||||
the respective filter is set to "manual" (See API 0x9B)
|
||||
Param[0]
|
||||
Spatial filter: default 0, range 0:15
|
||||
Param[1]
|
||||
Temporal filter: default 0, range 0:31
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_CORING_LEVELS
|
||||
Enum 159/0x9F
|
||||
Description
|
||||
Assign Dynamic Noise Reduction median filter properties.
|
||||
Param[0]
|
||||
Threshold above which the luminance median filter is enabled.
|
||||
Default: 0, range 0:255
|
||||
Param[1]
|
||||
Threshold below which the luminance median filter is enabled.
|
||||
Default: 255, range 0:255
|
||||
Param[2]
|
||||
Threshold above which the chrominance median filter is enabled.
|
||||
Default: 0, range 0:255
|
||||
Param[3]
|
||||
Threshold below which the chrominance median filter is enabled.
|
||||
Default: 255, range 0:255
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
|
||||
Enum 161/0xA1
|
||||
Description
|
||||
Assign spatial prefilter parameters
|
||||
Param[0]
|
||||
Luminance filter
|
||||
0=Off
|
||||
1=1D Horizontal
|
||||
2=1D Vertical
|
||||
3=2D H/V Separable (default)
|
||||
4=2D Symmetric non-separable
|
||||
Param[1]
|
||||
Chrominance filter
|
||||
0=Off
|
||||
1=1D Horizontal (default)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_3_2_PULLDOWN
|
||||
Enum 177/0xB1
|
||||
Description
|
||||
3:2 pulldown properties
|
||||
Param[0]
|
||||
0=enabled
|
||||
1=disabled
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_VBI_LINE
|
||||
Enum 183/0xB7
|
||||
Description
|
||||
Selects VBI line number.
|
||||
Param[0]
|
||||
Bits 0:4 line number
|
||||
Bit 31 0=top_field, 1=bottom_field
|
||||
Bits 0:31 all set specifies "all lines"
|
||||
Param[1]
|
||||
VBI line information features: 0=disabled, 1=enabled
|
||||
Param[2]
|
||||
Slicing: 0=None, 1=Closed Caption
|
||||
Almost certainly not implemented. Set to 0.
|
||||
Param[3]
|
||||
Luminance samples in this line.
|
||||
Almost certainly not implemented. Set to 0.
|
||||
Param[4]
|
||||
Chrominance samples in this line
|
||||
Almost certainly not implemented. Set to 0.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_STREAM_TYPE
|
||||
Enum 185/0xB9
|
||||
Description
|
||||
Assign stream type
|
||||
Note: Transport stream is not working in recent firmwares.
|
||||
And in older firmwares the timestamps in the TS seem to be
|
||||
unreliable.
|
||||
Param[0]
|
||||
0=Program stream
|
||||
1=Transport stream
|
||||
2=MPEG1 stream
|
||||
3=PES A/V stream
|
||||
5=PES Video stream
|
||||
7=PES Audio stream
|
||||
10=DVD stream
|
||||
11=VCD stream
|
||||
12=SVCD stream
|
||||
13=DVD_S1 stream
|
||||
14=DVD_S2 stream
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_OUTPUT_PORT
|
||||
Enum 187/0xBB
|
||||
Description
|
||||
Assign stream output port. Normally 0 when the data is copied through
|
||||
the PCI bus (DMA), and 1 when the data is streamed to another chip
|
||||
(pvrusb and cx88-blackbird).
|
||||
Param[0]
|
||||
0=Memory (default)
|
||||
1=Streaming
|
||||
2=Serial
|
||||
Param[1]
|
||||
Unknown, but leaving this to 0 seems to work best. Indications are that
|
||||
this might have to do with USB support, although passing anything but 0
|
||||
onl breaks things.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_AUDIO_PROPERTIES
|
||||
Enum 189/0xBD
|
||||
Description
|
||||
Set audio stream properties, may be called while encoding is in progress.
|
||||
Note: all bitfields are consistent with ISO11172 documentation except
|
||||
bits 2:3 which ISO docs define as:
|
||||
'11' Layer I
|
||||
'10' Layer II
|
||||
'01' Layer III
|
||||
'00' Undefined
|
||||
This discrepancy may indicate a possible error in the documentation.
|
||||
Testing indicated that only Layer II is actually working, and that
|
||||
the minimum bitrate should be 192 kbps.
|
||||
Param[0]
|
||||
Bitmask:
|
||||
0:1 '00' 44.1Khz
|
||||
'01' 48Khz
|
||||
'10' 32Khz
|
||||
'11' reserved
|
||||
|
||||
2:3 '01'=Layer I
|
||||
'10'=Layer II
|
||||
|
||||
4:7 Bitrate:
|
||||
Index | Layer I | Layer II
|
||||
------+-------------+------------
|
||||
'0000' | free format | free format
|
||||
'0001' | 32 kbit/s | 32 kbit/s
|
||||
'0010' | 64 kbit/s | 48 kbit/s
|
||||
'0011' | 96 kbit/s | 56 kbit/s
|
||||
'0100' | 128 kbit/s | 64 kbit/s
|
||||
'0101' | 160 kbit/s | 80 kbit/s
|
||||
'0110' | 192 kbit/s | 96 kbit/s
|
||||
'0111' | 224 kbit/s | 112 kbit/s
|
||||
'1000' | 256 kbit/s | 128 kbit/s
|
||||
'1001' | 288 kbit/s | 160 kbit/s
|
||||
'1010' | 320 kbit/s | 192 kbit/s
|
||||
'1011' | 352 kbit/s | 224 kbit/s
|
||||
'1100' | 384 kbit/s | 256 kbit/s
|
||||
'1101' | 416 kbit/s | 320 kbit/s
|
||||
'1110' | 448 kbit/s | 384 kbit/s
|
||||
Note: For Layer II, not all combinations of total bitrate
|
||||
and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2
|
||||
|
||||
8:9 '00'=Stereo
|
||||
'01'=JointStereo
|
||||
'10'=Dual
|
||||
'11'=Mono
|
||||
Note: testing seems to indicate that Mono and possibly
|
||||
JointStereo are not working (default to stereo).
|
||||
Dual does work, though.
|
||||
|
||||
10:11 Mode Extension used in joint_stereo mode.
|
||||
In Layer I and II they indicate which subbands are in
|
||||
intensity_stereo. All other subbands are coded in stereo.
|
||||
'00' subbands 4-31 in intensity_stereo, bound==4
|
||||
'01' subbands 8-31 in intensity_stereo, bound==8
|
||||
'10' subbands 12-31 in intensity_stereo, bound==12
|
||||
'11' subbands 16-31 in intensity_stereo, bound==16
|
||||
|
||||
12:13 Emphasis:
|
||||
'00' None
|
||||
'01' 50/15uS
|
||||
'10' reserved
|
||||
'11' CCITT J.17
|
||||
|
||||
14 CRC:
|
||||
'0' off
|
||||
'1' on
|
||||
|
||||
15 Copyright:
|
||||
'0' off
|
||||
'1' on
|
||||
|
||||
16 Generation:
|
||||
'0' copy
|
||||
'1' original
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_HALT_FW
|
||||
Enum 195/0xC3
|
||||
Description
|
||||
The firmware is halted and no further API calls are serviced until the
|
||||
firmware is uploaded again.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_GET_VERSION
|
||||
Enum 196/0xC4
|
||||
Description
|
||||
Returns the version of the encoder firmware.
|
||||
Result[0]
|
||||
Version bitmask:
|
||||
Bits 0:15 build
|
||||
Bits 16:23 minor
|
||||
Bits 24:31 major
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_GOP_CLOSURE
|
||||
Enum 197/0xC5
|
||||
Description
|
||||
Assigns the GOP open/close property.
|
||||
Param[0]
|
||||
0=Open
|
||||
1=Closed
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_GET_SEQ_END
|
||||
Enum 198/0xC6
|
||||
Description
|
||||
Obtains the sequence end code of the encoder's buffer. When a capture
|
||||
is started a number of interrupts are still generated, the last of
|
||||
which will have Result[0] set to 1 and Result[1] will contain the size
|
||||
of the buffer.
|
||||
Result[0]
|
||||
State of the transfer (1 if last buffer)
|
||||
Result[1]
|
||||
If Result[0] is 1, this contains the size of the last buffer, undefined
|
||||
otherwise.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_PGM_INDEX_INFO
|
||||
Enum 199/0xC7
|
||||
Description
|
||||
Sets the Program Index Information.
|
||||
Param[0]
|
||||
Picture Mask:
|
||||
0=No index capture
|
||||
1=I frames
|
||||
3=I,P frames
|
||||
7=I,P,B frames
|
||||
Param[1]
|
||||
Elements requested (up to 400)
|
||||
Result[0]
|
||||
Offset in SDF memory of the table.
|
||||
Result[1]
|
||||
Number of allocated elements up to a maximum of Param[1]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_VBI_CONFIG
|
||||
Enum 200/0xC8
|
||||
Description
|
||||
Configure VBI settings
|
||||
Param[0]
|
||||
Bitmap:
|
||||
0 Mode '0' Sliced, '1' Raw
|
||||
1:3 Insertion:
|
||||
'000' insert in extension & user data
|
||||
'001' insert in private packets
|
||||
'010' separate stream and user data
|
||||
'111' separate stream and private data
|
||||
8:15 Stream ID (normally 0xBD)
|
||||
Param[1]
|
||||
Frames per interrupt (max 8). Only valid in raw mode.
|
||||
Param[2]
|
||||
Total raw VBI frames. Only valid in raw mode.
|
||||
Param[3]
|
||||
Start codes
|
||||
Param[4]
|
||||
Stop codes
|
||||
Param[5]
|
||||
Lines per frame
|
||||
Param[6]
|
||||
Byte per line
|
||||
Result[0]
|
||||
Observed frames per interrupt in raw mode only. Rage 1 to Param[1]
|
||||
Result[1]
|
||||
Observed number of frames in raw mode. Range 1 to Param[2]
|
||||
Result[2]
|
||||
Memory offset to start or raw VBI data
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_DMA_BLOCK_SIZE
|
||||
Enum 201/0xC9
|
||||
Description
|
||||
Set DMA transfer block size
|
||||
Param[0]
|
||||
DMA transfer block size in bytes or frames. When unit is bytes,
|
||||
supported block sizes are 2^7, 2^8 and 2^9 bytes.
|
||||
Param[1]
|
||||
Unit: 0=bytes, 1=frames
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_10
|
||||
Enum 202/0xCA
|
||||
Description
|
||||
Returns information on the previous DMA transfer in conjunction with
|
||||
bit 27 of the interrupt mask. Uses mailbox 10.
|
||||
Result[0]
|
||||
Type of stream
|
||||
Result[1]
|
||||
Address Offset
|
||||
Result[2]
|
||||
Maximum size of transfer
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
|
||||
Enum 203/0xCB
|
||||
Description
|
||||
Returns information on the previous DMA transfer in conjunction with
|
||||
bit 27 of the interrupt mask. Uses mailbox 9.
|
||||
Result[0]
|
||||
Status bits:
|
||||
Bit 0 set indicates transfer complete
|
||||
Bit 2 set indicates transfer error
|
||||
Bit 4 set indicates linked list error
|
||||
Result[1]
|
||||
DMA type
|
||||
Result[2]
|
||||
Presentation Time Stamp bits 0..31
|
||||
Result[3]
|
||||
Presentation Time Stamp bit 32
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SCHED_DMA_TO_HOST
|
||||
Enum 204/0xCC
|
||||
Description
|
||||
Setup DMA to host operation
|
||||
Param[0]
|
||||
Memory address of link list
|
||||
Param[1]
|
||||
Length of link list (wtf: what units ???)
|
||||
Param[2]
|
||||
DMA type (0=MPEG)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_INITIALIZE_INPUT
|
||||
Enum 205/0xCD
|
||||
Description
|
||||
Initializes the video input
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_FRAME_DROP_RATE
|
||||
Enum 208/0xD0
|
||||
Description
|
||||
For each frame captured, skip specified number of frames.
|
||||
Param[0]
|
||||
Number of frames to skip
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_PAUSE_ENCODER
|
||||
Enum 210/0xD2
|
||||
Description
|
||||
During a pause condition, all frames are dropped instead of being encoded.
|
||||
Param[0]
|
||||
0=Pause encoding
|
||||
1=Continue encoding
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_REFRESH_INPUT
|
||||
Enum 211/0xD3
|
||||
Description
|
||||
Refreshes the video input
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_COPYRIGHT
|
||||
Enum 212/0xD4
|
||||
Description
|
||||
Sets stream copyright property
|
||||
Param[0]
|
||||
0=Stream is not copyrighted
|
||||
1=Stream is copyrighted
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_EVENT_NOTIFICATION
|
||||
Enum 213/0xD5
|
||||
Description
|
||||
Setup firmware to notify the host about a particular event. Host must
|
||||
unmask the interrupt bit.
|
||||
Param[0]
|
||||
Event (0=refresh encoder input)
|
||||
Param[1]
|
||||
Notification 0=disabled 1=enabled
|
||||
Param[2]
|
||||
Interrupt bit
|
||||
Param[3]
|
||||
Mailbox slot, -1 if no mailbox required.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_NUM_VSYNC_LINES
|
||||
Enum 214/0xD6
|
||||
Description
|
||||
Depending on the analog video decoder used, this assigns the number
|
||||
of lines for field 1 and 2.
|
||||
Param[0]
|
||||
Field 1 number of lines:
|
||||
0x00EF for SAA7114
|
||||
0x00F0 for SAA7115
|
||||
0x0105 for Micronas
|
||||
Param[1]
|
||||
Field 2 number of lines:
|
||||
0x00EF for SAA7114
|
||||
0x00F0 for SAA7115
|
||||
0x0106 for Micronas
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_SET_PLACEHOLDER
|
||||
Enum 215/0xD7
|
||||
Description
|
||||
Provides a mechanism of inserting custom user data in the MPEG stream.
|
||||
Param[0]
|
||||
0=extension & user data
|
||||
1=private packet with stream ID 0xBD
|
||||
Param[1]
|
||||
Rate at which to insert data, in units of frames (for private packet)
|
||||
or GOPs (for ext. & user data)
|
||||
Param[2]
|
||||
Number of data DWORDs (below) to insert
|
||||
Param[3]
|
||||
Custom data 0
|
||||
Param[4]
|
||||
Custom data 1
|
||||
Param[5]
|
||||
Custom data 2
|
||||
Param[6]
|
||||
Custom data 3
|
||||
Param[7]
|
||||
Custom data 4
|
||||
Param[8]
|
||||
Custom data 5
|
||||
Param[9]
|
||||
Custom data 6
|
||||
Param[10]
|
||||
Custom data 7
|
||||
Param[11]
|
||||
Custom data 8
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_MUTE_VIDEO
|
||||
Enum 217/0xD9
|
||||
Description
|
||||
Video muting
|
||||
Param[0]
|
||||
Bit usage:
|
||||
0 '0'=video not muted
|
||||
'1'=video muted, creates frames with the YUV color defined below
|
||||
1:7 Unused
|
||||
8:15 V chrominance information
|
||||
16:23 U chrominance information
|
||||
24:31 Y luminance information
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_MUTE_AUDIO
|
||||
Enum 218/0xDA
|
||||
Description
|
||||
Audio muting
|
||||
Param[0]
|
||||
0=audio not muted
|
||||
1=audio muted (produces silent mpeg audio stream)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_UNKNOWN
|
||||
Enum 219/0xDB
|
||||
Description
|
||||
Unknown API, it's used by Hauppauge though.
|
||||
Param[0]
|
||||
0 This is the value Hauppauge uses, Unknown what it means.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name CX2341X_ENC_MISC
|
||||
Enum 220/0xDC
|
||||
Description
|
||||
Miscellaneous actions. Not known for 100% what it does. It's really a
|
||||
sort of ioctl call. The first parameter is a command number, the second
|
||||
the value.
|
||||
Param[0]
|
||||
Command number:
|
||||
1=set initial SCR value when starting encoding.
|
||||
2=set quality mode (apparently some test setting).
|
||||
3=setup advanced VIM protection handling (supposedly only for the cx23416
|
||||
for raw YUV).
|
||||
Actually it looks like this should be 0 for saa7114/5 based card and 1
|
||||
for cx25840 based cards.
|
||||
4=generate artificial PTS timestamps
|
||||
5=USB flush mode
|
||||
6=something to do with the quantization matrix
|
||||
7=set navigation pack insertion for DVD
|
||||
8=enable scene change detection (seems to be a failure)
|
||||
9=set history parameters of the video input module
|
||||
10=set input field order of VIM
|
||||
11=set quantization matrix
|
||||
12=reset audio interface
|
||||
13=set audio volume delay
|
||||
14=set audio delay
|
||||
|
||||
Param[1]
|
||||
Command value.
|
141
Documentation/video4linux/cx2341x/fw-memory.txt
Normal file
141
Documentation/video4linux/cx2341x/fw-memory.txt
Normal file
|
@ -0,0 +1,141 @@
|
|||
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
|
342
Documentation/video4linux/cx2341x/fw-osd-api.txt
Normal file
342
Documentation/video4linux/cx2341x/fw-osd-api.txt
Normal file
|
@ -0,0 +1,342 @@
|
|||
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
|
49
Documentation/video4linux/cx2341x/fw-upload.txt
Normal file
49
Documentation/video4linux/cx2341x/fw-upload.txt
Normal file
|
@ -0,0 +1,49 @@
|
|||
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.
|
||||
|
54
Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
Normal file
54
Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
Normal file
|
@ -0,0 +1,54 @@
|
|||
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
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
ET61X[12]51 PC Camera Controllers
|
||||
Driver for Linux
|
||||
=================================
|
||||
ET61X[12]51 PC Camera Controllers
|
||||
Driver for Linux
|
||||
=================================
|
||||
|
||||
- Documentation -
|
||||
- Documentation -
|
||||
|
||||
|
||||
Index
|
||||
|
@ -156,46 +156,46 @@ Name: video_nr
|
|||
Type: short array (min = 0, max = 64)
|
||||
Syntax: <-1|n[,...]>
|
||||
Description: Specify V4L2 minor mode number:
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
registered camera and use auto for the first one and for every
|
||||
other camera.
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
registered camera and use auto for the first one and for every
|
||||
other camera.
|
||||
Default: -1
|
||||
-------------------------------------------------------------------------------
|
||||
Name: force_munmap
|
||||
Type: bool array (min = 0, max = 64)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Force the application to unmap previously mapped buffer memory
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
Default: 0
|
||||
-------------------------------------------------------------------------------
|
||||
Name: frame_timeout
|
||||
Type: uint array (min = 0, max = 64)
|
||||
Syntax: <n[,...]>
|
||||
Description: Timeout for a video frame in seconds. This parameter is
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
Name: debug
|
||||
Type: ushort
|
||||
Syntax: <n>
|
||||
Description: Debugging information level, from 0 to 3:
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used at the same time. It also shows some more informations
|
||||
about the hardware being detected. This module parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used at the same time. It also shows some more informations
|
||||
about the hardware being detected. This module parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ Internal interface: Video For Linux (V4L)
|
|||
Supported controls:
|
||||
- by V4L: Contrast, Brightness, Color, Hue
|
||||
- by driver options: frame rate, lighting conditions, video format,
|
||||
default picture settings, sharpness.
|
||||
default picture settings, sharpness.
|
||||
|
||||
SUPPORTED CAMERAS:
|
||||
|
||||
|
@ -191,66 +191,66 @@ init_model2_sat Integer 0..255 [0x34] init_model2_sat=65
|
|||
init_model2_yb Integer 0..255 [0xa0] init_model2_yb=200
|
||||
|
||||
debug You don't need this option unless you are a developer.
|
||||
If you are a developer then you will see in the code
|
||||
what values do what. 0=off.
|
||||
If you are a developer then you will see in the code
|
||||
what values do what. 0=off.
|
||||
|
||||
flags This is a bit mask, and you can combine any number of
|
||||
bits to produce what you want. Usually you don't want
|
||||
any of extra features this option provides:
|
||||
bits to produce what you want. Usually you don't want
|
||||
any of extra features this option provides:
|
||||
|
||||
FLAGS_RETRY_VIDIOCSYNC 1 This bit allows to retry failed
|
||||
VIDIOCSYNC ioctls without failing.
|
||||
Will work with xawtv, will not
|
||||
with xrealproducer. Default is
|
||||
not set.
|
||||
FLAGS_MONOCHROME 2 Activates monochrome (b/w) mode.
|
||||
FLAGS_DISPLAY_HINTS 4 Shows colored pixels which have
|
||||
magic meaning to developers.
|
||||
FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen,
|
||||
useful only for debugging.
|
||||
FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
|
||||
FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as
|
||||
it was received from the camera.
|
||||
Default (not set) is to mix the
|
||||
preceding frame in to compensate
|
||||
for occasional loss of Isoc data
|
||||
on high frame rates.
|
||||
FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame
|
||||
prior to use; relevant only if
|
||||
FLAGS_SEPARATE_FRAMES is set.
|
||||
Default is not to clean frames,
|
||||
this is a little faster but may
|
||||
produce flicker if frame rate is
|
||||
too high and Isoc data gets lost.
|
||||
FLAGS_NO_DECODING 128 This flag turns the video stream
|
||||
decoder off, and dumps the raw
|
||||
Isoc data from the camera into
|
||||
the reading process. Useful to
|
||||
developers, but not to users.
|
||||
FLAGS_RETRY_VIDIOCSYNC 1 This bit allows to retry failed
|
||||
VIDIOCSYNC ioctls without failing.
|
||||
Will work with xawtv, will not
|
||||
with xrealproducer. Default is
|
||||
not set.
|
||||
FLAGS_MONOCHROME 2 Activates monochrome (b/w) mode.
|
||||
FLAGS_DISPLAY_HINTS 4 Shows colored pixels which have
|
||||
magic meaning to developers.
|
||||
FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen,
|
||||
useful only for debugging.
|
||||
FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
|
||||
FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as
|
||||
it was received from the camera.
|
||||
Default (not set) is to mix the
|
||||
preceding frame in to compensate
|
||||
for occasional loss of Isoc data
|
||||
on high frame rates.
|
||||
FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame
|
||||
prior to use; relevant only if
|
||||
FLAGS_SEPARATE_FRAMES is set.
|
||||
Default is not to clean frames,
|
||||
this is a little faster but may
|
||||
produce flicker if frame rate is
|
||||
too high and Isoc data gets lost.
|
||||
FLAGS_NO_DECODING 128 This flag turns the video stream
|
||||
decoder off, and dumps the raw
|
||||
Isoc data from the camera into
|
||||
the reading process. Useful to
|
||||
developers, but not to users.
|
||||
|
||||
framerate This setting controls frame rate of the camera. This is
|
||||
an approximate setting (in terms of "worst" ... "best")
|
||||
because camera changes frame rate depending on amount
|
||||
of light available. Setting 0 is slowest, 6 is fastest.
|
||||
Beware - fast settings are very demanding and may not
|
||||
work well with all video sizes. Be conservative.
|
||||
an approximate setting (in terms of "worst" ... "best")
|
||||
because camera changes frame rate depending on amount
|
||||
of light available. Setting 0 is slowest, 6 is fastest.
|
||||
Beware - fast settings are very demanding and may not
|
||||
work well with all video sizes. Be conservative.
|
||||
|
||||
hue_correction This highly optional setting allows to adjust the
|
||||
hue of the image in a way slightly different from
|
||||
what usual "hue" control does. Both controls affect
|
||||
YUV colorspace: regular "hue" control adjusts only
|
||||
U component, and this "hue_correction" option similarly
|
||||
adjusts only V component. However usually it is enough
|
||||
to tweak only U or V to compensate for colored light or
|
||||
color temperature; this option simply allows more
|
||||
complicated correction when and if it is necessary.
|
||||
hue of the image in a way slightly different from
|
||||
what usual "hue" control does. Both controls affect
|
||||
YUV colorspace: regular "hue" control adjusts only
|
||||
U component, and this "hue_correction" option similarly
|
||||
adjusts only V component. However usually it is enough
|
||||
to tweak only U or V to compensate for colored light or
|
||||
color temperature; this option simply allows more
|
||||
complicated correction when and if it is necessary.
|
||||
|
||||
init_brightness These settings specify _initial_ values which will be
|
||||
init_contrast used to set up the camera. If your V4L application has
|
||||
init_color its own controls to adjust the picture then these
|
||||
init_hue controls will be used too. These options allow you to
|
||||
preconfigure the camera when it gets connected, before
|
||||
any V4L application connects to it. Good for webcams.
|
||||
preconfigure the camera when it gets connected, before
|
||||
any V4L application connects to it. Good for webcams.
|
||||
|
||||
init_model2_rg These initial settings alter color balance of the
|
||||
init_model2_rg2 camera on hardware level. All four settings may be used
|
||||
|
@ -258,47 +258,47 @@ init_model2_sat to tune the camera to specific lighting conditions. These
|
|||
init_model2_yb settings only apply to Model 2 cameras.
|
||||
|
||||
lighting This option selects one of three hardware-defined
|
||||
photosensitivity settings of the camera. 0=bright light,
|
||||
1=Medium (default), 2=Low light. This setting affects
|
||||
frame rate: the dimmer the lighting the lower the frame
|
||||
rate (because longer exposition time is needed). The
|
||||
Model 2 cameras allow values more than 2 for this option,
|
||||
thus enabling extremely high sensitivity at cost of frame
|
||||
rate, color saturation and imaging sensor noise.
|
||||
photosensitivity settings of the camera. 0=bright light,
|
||||
1=Medium (default), 2=Low light. This setting affects
|
||||
frame rate: the dimmer the lighting the lower the frame
|
||||
rate (because longer exposition time is needed). The
|
||||
Model 2 cameras allow values more than 2 for this option,
|
||||
thus enabling extremely high sensitivity at cost of frame
|
||||
rate, color saturation and imaging sensor noise.
|
||||
|
||||
sharpness This option controls smoothing (noise reduction)
|
||||
made by camera. Setting 0 is most smooth, setting 6
|
||||
is most sharp. Be aware that CMOS sensor used in the
|
||||
camera is pretty noisy, so if you choose 6 you will
|
||||
be greeted with "snowy" image. Default is 4. Model 2
|
||||
cameras do not support this feature.
|
||||
made by camera. Setting 0 is most smooth, setting 6
|
||||
is most sharp. Be aware that CMOS sensor used in the
|
||||
camera is pretty noisy, so if you choose 6 you will
|
||||
be greeted with "snowy" image. Default is 4. Model 2
|
||||
cameras do not support this feature.
|
||||
|
||||
size This setting chooses one of several image sizes that are
|
||||
supported by this driver. Cameras may support more, but
|
||||
it's difficult to reverse-engineer all formats.
|
||||
Following video sizes are supported:
|
||||
supported by this driver. Cameras may support more, but
|
||||
it's difficult to reverse-engineer all formats.
|
||||
Following video sizes are supported:
|
||||
|
||||
size=0 128x96 (Model 1 only)
|
||||
size=1 160x120
|
||||
size=2 176x144
|
||||
size=3 320x240 (Model 2 only)
|
||||
size=4 352x240 (Model 2 only)
|
||||
size=5 352x288
|
||||
size=6 640x480 (Model 3 only)
|
||||
size=0 128x96 (Model 1 only)
|
||||
size=1 160x120
|
||||
size=2 176x144
|
||||
size=3 320x240 (Model 2 only)
|
||||
size=4 352x240 (Model 2 only)
|
||||
size=5 352x288
|
||||
size=6 640x480 (Model 3 only)
|
||||
|
||||
The 352x288 is the native size of the Model 1 sensor
|
||||
array, so it's the best resolution the camera can
|
||||
yield. The best resolution of Model 2 is 176x144, and
|
||||
larger images are produced by stretching the bitmap.
|
||||
Model 3 has sensor with 640x480 grid, and it works too,
|
||||
but the frame rate will be exceptionally low (1-2 FPS);
|
||||
it may be still OK for some applications, like security.
|
||||
Choose the image size you need. The smaller image can
|
||||
support faster frame rate. Default is 352x288.
|
||||
The 352x288 is the native size of the Model 1 sensor
|
||||
array, so it's the best resolution the camera can
|
||||
yield. The best resolution of Model 2 is 176x144, and
|
||||
larger images are produced by stretching the bitmap.
|
||||
Model 3 has sensor with 640x480 grid, and it works too,
|
||||
but the frame rate will be exceptionally low (1-2 FPS);
|
||||
it may be still OK for some applications, like security.
|
||||
Choose the image size you need. The smaller image can
|
||||
support faster frame rate. Default is 352x288.
|
||||
|
||||
For more information and the Troubleshooting FAQ visit this URL:
|
||||
|
||||
http://www.linux-usb.org/ibmcam/
|
||||
http://www.linux-usb.org/ibmcam/
|
||||
|
||||
WHAT NEEDS TO BE DONE:
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ MODULE PARAMETERS:
|
|||
TYPE: integer (Boolean)
|
||||
DEFAULT: 1
|
||||
DESC: Brightness is normally under automatic control and can't be set
|
||||
manually by the video app. Set to 0 for manual control.
|
||||
manually by the video app. Set to 0 for manual control.
|
||||
|
||||
NAME: autogain
|
||||
TYPE: integer (Boolean)
|
||||
|
@ -97,13 +97,13 @@ MODULE PARAMETERS:
|
|||
TYPE: integer (0-6)
|
||||
DEFAULT: 3
|
||||
DESC: Sets the threshold for printing debug messages. The higher the value,
|
||||
the more is printed. The levels are cumulative, and are as follows:
|
||||
0=no debug messages
|
||||
1=init/detection/unload and other significant messages
|
||||
2=some warning messages
|
||||
3=config/control function calls
|
||||
4=most function calls and data parsing messages
|
||||
5=highly repetitive mesgs
|
||||
the more is printed. The levels are cumulative, and are as follows:
|
||||
0=no debug messages
|
||||
1=init/detection/unload and other significant messages
|
||||
2=some warning messages
|
||||
3=config/control function calls
|
||||
4=most function calls and data parsing messages
|
||||
5=highly repetitive mesgs
|
||||
|
||||
NAME: snapshot
|
||||
TYPE: integer (Boolean)
|
||||
|
@ -116,24 +116,24 @@ MODULE PARAMETERS:
|
|||
TYPE: integer (1-4 for OV511, 1-31 for OV511+)
|
||||
DEFAULT: 1
|
||||
DESC: Number of cameras allowed to stream simultaneously on a single bus.
|
||||
Values higher than 1 reduce the data rate of each camera, allowing two
|
||||
or more to be used at once. If you have a complicated setup involving
|
||||
both OV511 and OV511+ cameras, trial-and-error may be necessary for
|
||||
finding the optimum setting.
|
||||
Values higher than 1 reduce the data rate of each camera, allowing two
|
||||
or more to be used at once. If you have a complicated setup involving
|
||||
both OV511 and OV511+ cameras, trial-and-error may be necessary for
|
||||
finding the optimum setting.
|
||||
|
||||
NAME: compress
|
||||
TYPE: integer (Boolean)
|
||||
DEFAULT: 0
|
||||
DESC: Set this to 1 to turn on the camera's compression engine. This can
|
||||
potentially increase the frame rate at the expense of quality, if you
|
||||
have a fast CPU. You must load the proper compression module for your
|
||||
camera before starting your application (ov511_decomp or ov518_decomp).
|
||||
potentially increase the frame rate at the expense of quality, if you
|
||||
have a fast CPU. You must load the proper compression module for your
|
||||
camera before starting your application (ov511_decomp or ov518_decomp).
|
||||
|
||||
NAME: testpat
|
||||
TYPE: integer (Boolean)
|
||||
DEFAULT: 0
|
||||
DESC: This configures the camera's sensor to transmit a colored test-pattern
|
||||
instead of an image. This does not work correctly yet.
|
||||
instead of an image. This does not work correctly yet.
|
||||
|
||||
NAME: dumppix
|
||||
TYPE: integer (0-2)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
SN9C10x PC Camera Controllers
|
||||
Driver for Linux
|
||||
=============================
|
||||
SN9C10x PC Camera Controllers
|
||||
Driver for Linux
|
||||
=============================
|
||||
|
||||
- Documentation -
|
||||
- Documentation -
|
||||
|
||||
|
||||
Index
|
||||
|
@ -176,46 +176,46 @@ Name: video_nr
|
|||
Type: short array (min = 0, max = 64)
|
||||
Syntax: <-1|n[,...]>
|
||||
Description: Specify V4L2 minor mode number:
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
recognized camera and use auto for the first one and for every
|
||||
other camera.
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
recognized camera and use auto for the first one and for every
|
||||
other camera.
|
||||
Default: -1
|
||||
-------------------------------------------------------------------------------
|
||||
Name: force_munmap
|
||||
Type: bool array (min = 0, max = 64)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Force the application to unmap previously mapped buffer memory
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
Default: 0
|
||||
-------------------------------------------------------------------------------
|
||||
Name: frame_timeout
|
||||
Type: uint array (min = 0, max = 64)
|
||||
Syntax: <n[,...]>
|
||||
Description: Timeout for a video frame in seconds. This parameter is
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
Name: debug
|
||||
Type: ushort
|
||||
Syntax: <n>
|
||||
Description: Debugging information level, from 0 to 3:
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used. It also shows some more informations about the
|
||||
hardware being detected. This parameter can be changed at
|
||||
runtime thanks to the /sys filesystem interface.
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used. It also shows some more informations about the
|
||||
hardware being detected. This parameter can be changed at
|
||||
runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -280,24 +280,24 @@ Byte # Value Description
|
|||
0x04 0xC4 Frame synchronisation pattern.
|
||||
0x05 0x96 Frame synchronisation pattern.
|
||||
0x06 0xXX Unknown meaning. The exact value depends on the chip;
|
||||
possible values are 0x00, 0x01 and 0x20.
|
||||
possible values are 0x00, 0x01 and 0x20.
|
||||
0x07 0xXX Variable value, whose bits are ff00uzzc, where ff is a
|
||||
frame counter, u is unknown, zz is a size indicator
|
||||
(00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
|
||||
"compression enabled" (1 = yes, 0 = no).
|
||||
frame counter, u is unknown, zz is a size indicator
|
||||
(00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
|
||||
"compression enabled" (1 = yes, 0 = no).
|
||||
0x08 0xXX Brightness sum inside Auto-Exposure area (low-byte).
|
||||
0x09 0xXX Brightness sum inside Auto-Exposure area (high-byte).
|
||||
For a pure white image, this number will be equal to 500
|
||||
times the area of the specified AE area. For images
|
||||
that are not pure white, the value scales down according
|
||||
to relative whiteness.
|
||||
For a pure white image, this number will be equal to 500
|
||||
times the area of the specified AE area. For images
|
||||
that are not pure white, the value scales down according
|
||||
to relative whiteness.
|
||||
0x0A 0xXX Brightness sum outside Auto-Exposure area (low-byte).
|
||||
0x0B 0xXX Brightness sum outside Auto-Exposure area (high-byte).
|
||||
For a pure white image, this number will be equal to 125
|
||||
times the area outside of the specified AE area. For
|
||||
images that are not pure white, the value scales down
|
||||
according to relative whiteness.
|
||||
according to relative whiteness.
|
||||
For a pure white image, this number will be equal to 125
|
||||
times the area outside of the specified AE area. For
|
||||
images that are not pure white, the value scales down
|
||||
according to relative whiteness.
|
||||
according to relative whiteness.
|
||||
|
||||
The following bytes are used by the SN9C103 bridge only:
|
||||
|
||||
|
|
192
Documentation/video4linux/v4lgrab.c
Normal file
192
Documentation/video4linux/v4lgrab.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/* 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;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
W996[87]CF JPEG USB Dual Mode Camera Chip
|
||||
Driver for Linux 2.6 (basic version)
|
||||
=========================================
|
||||
W996[87]CF JPEG USB Dual Mode Camera Chip
|
||||
Driver for Linux 2.6 (basic version)
|
||||
=========================================
|
||||
|
||||
- Documentation -
|
||||
- Documentation -
|
||||
|
||||
|
||||
Index
|
||||
|
@ -188,57 +188,57 @@ Name: ovmod_load
|
|||
Type: bool
|
||||
Syntax: <0|1>
|
||||
Description: Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
|
||||
If enabled, 'insmod' searches for the required 'ovcamchip'
|
||||
module in the system, according to its configuration, and
|
||||
loads that module automatically. This action is performed as
|
||||
once soon as the 'w9968cf' module is loaded into memory.
|
||||
If enabled, 'insmod' searches for the required 'ovcamchip'
|
||||
module in the system, according to its configuration, and
|
||||
loads that module automatically. This action is performed as
|
||||
once soon as the 'w9968cf' module is loaded into memory.
|
||||
Default: 1
|
||||
Note: The kernel must be compiled with the CONFIG_KMOD option
|
||||
enabled for the 'ovcamchip' module to be loaded and for
|
||||
this parameter to be present.
|
||||
enabled for the 'ovcamchip' module to be loaded and for
|
||||
this parameter to be present.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: simcams
|
||||
Type: int
|
||||
Syntax: <n>
|
||||
Description: Number of cameras allowed to stream simultaneously.
|
||||
n may vary from 0 to 32.
|
||||
n may vary from 0 to 32.
|
||||
Default: 32
|
||||
-------------------------------------------------------------------------------
|
||||
Name: video_nr
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <-1|n[,...]>
|
||||
Description: Specify V4L minor mode number.
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 32 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
recognized camera and use auto for the first one and for every
|
||||
other camera.
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 32 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
recognized camera and use auto for the first one and for every
|
||||
other camera.
|
||||
Default: -1
|
||||
-------------------------------------------------------------------------------
|
||||
Name: packet_size
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <n[,...]>
|
||||
Description: Specify the maximum data payload size in bytes for alternate
|
||||
settings, for each device. n is scaled between 63 and 1023.
|
||||
settings, for each device. n is scaled between 63 and 1023.
|
||||
Default: 1023
|
||||
-------------------------------------------------------------------------------
|
||||
Name: max_buffers
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <n[,...]>
|
||||
Description: For advanced users.
|
||||
Specify the maximum number of video frame buffers to allocate
|
||||
for each device, from 2 to 32.
|
||||
Specify the maximum number of video frame buffers to allocate
|
||||
for each device, from 2 to 32.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
Name: double_buffer
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Hardware double buffering: 0 disabled, 1 enabled.
|
||||
It should be enabled if you want smooth video output: if you
|
||||
obtain out of sync. video, disable it, or try to
|
||||
decrease the 'clockdiv' module parameter value.
|
||||
It should be enabled if you want smooth video output: if you
|
||||
obtain out of sync. video, disable it, or try to
|
||||
decrease the 'clockdiv' module parameter value.
|
||||
Default: 1 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: clamping
|
||||
|
@ -251,9 +251,9 @@ Name: filter_type
|
|||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <0|1|2[,...]>
|
||||
Description: Video filter type.
|
||||
0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
|
||||
The filter is used to reduce noise and aliasing artifacts
|
||||
produced by the CCD or CMOS image sensor.
|
||||
0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
|
||||
The filter is used to reduce noise and aliasing artifacts
|
||||
produced by the CCD or CMOS image sensor.
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: largeview
|
||||
|
@ -266,9 +266,9 @@ Name: upscaling
|
|||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Software scaling (for non-compressed video only):
|
||||
0 disabled, 1 enabled.
|
||||
Disable it if you have a slow CPU or you don't have enough
|
||||
memory.
|
||||
0 disabled, 1 enabled.
|
||||
Disable it if you have a slow CPU or you don't have enough
|
||||
memory.
|
||||
Default: 0 for every device.
|
||||
Note: If 'w9968cf-vpp' is not present, this parameter is set to 0.
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -276,36 +276,36 @@ Name: decompression
|
|||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <0|1|2[,...]>
|
||||
Description: Software video decompression:
|
||||
0 = disables decompression
|
||||
(doesn't allow formats needing decompression).
|
||||
1 = forces decompression
|
||||
(allows formats needing decompression only).
|
||||
2 = allows any permitted formats.
|
||||
Formats supporting (de)compressed video are YUV422P and
|
||||
YUV420P/YUV420 in any resolutions where width and height are
|
||||
multiples of 16.
|
||||
0 = disables decompression
|
||||
(doesn't allow formats needing decompression).
|
||||
1 = forces decompression
|
||||
(allows formats needing decompression only).
|
||||
2 = allows any permitted formats.
|
||||
Formats supporting (de)compressed video are YUV422P and
|
||||
YUV420P/YUV420 in any resolutions where width and height are
|
||||
multiples of 16.
|
||||
Default: 2 for every device.
|
||||
Note: If 'w9968cf-vpp' is not present, forcing decompression is not
|
||||
allowed; in this case this parameter is set to 2.
|
||||
allowed; in this case this parameter is set to 2.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: force_palette
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
|
||||
Description: Force picture palette.
|
||||
In order:
|
||||
0 = Off - allows any of the following formats:
|
||||
9 = UYVY 16 bpp - Original video, compression disabled
|
||||
10 = YUV420 12 bpp - Original video, compression enabled
|
||||
13 = YUV422P 16 bpp - Original video, compression enabled
|
||||
15 = YUV420P 12 bpp - Original video, compression enabled
|
||||
8 = YUVY 16 bpp - Software conversion from UYVY
|
||||
7 = YUV422 16 bpp - Software conversion from UYVY
|
||||
1 = GREY 8 bpp - Software conversion from UYVY
|
||||
6 = RGB555 16 bpp - Software conversion from UYVY
|
||||
3 = RGB565 16 bpp - Software conversion from UYVY
|
||||
4 = RGB24 24 bpp - Software conversion from UYVY
|
||||
5 = RGB32 32 bpp - Software conversion from UYVY
|
||||
When not 0, this parameter will override 'decompression'.
|
||||
In order:
|
||||
0 = Off - allows any of the following formats:
|
||||
9 = UYVY 16 bpp - Original video, compression disabled
|
||||
10 = YUV420 12 bpp - Original video, compression enabled
|
||||
13 = YUV422P 16 bpp - Original video, compression enabled
|
||||
15 = YUV420P 12 bpp - Original video, compression enabled
|
||||
8 = YUVY 16 bpp - Software conversion from UYVY
|
||||
7 = YUV422 16 bpp - Software conversion from UYVY
|
||||
1 = GREY 8 bpp - Software conversion from UYVY
|
||||
6 = RGB555 16 bpp - Software conversion from UYVY
|
||||
3 = RGB565 16 bpp - Software conversion from UYVY
|
||||
4 = RGB24 24 bpp - Software conversion from UYVY
|
||||
5 = RGB32 32 bpp - Software conversion from UYVY
|
||||
When not 0, this parameter will override 'decompression'.
|
||||
Default: 0 for every device. Initial palette is 9 (UYVY).
|
||||
Note: If 'w9968cf-vpp' is not present, this parameter is set to 9.
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -313,77 +313,77 @@ Name: force_rgb
|
|||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Read RGB video data instead of BGR:
|
||||
1 = use RGB component ordering.
|
||||
0 = use BGR component ordering.
|
||||
This parameter has effect when using RGBX palettes only.
|
||||
1 = use RGB component ordering.
|
||||
0 = use BGR component ordering.
|
||||
This parameter has effect when using RGBX palettes only.
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: autobright
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Image sensor automatically changes brightness:
|
||||
0 = no, 1 = yes
|
||||
0 = no, 1 = yes
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: autoexp
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Image sensor automatically changes exposure:
|
||||
0 = no, 1 = yes
|
||||
0 = no, 1 = yes
|
||||
Default: 1 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: lightfreq
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <50|60[,...]>
|
||||
Description: Light frequency in Hz:
|
||||
50 for European and Asian lighting, 60 for American lighting.
|
||||
50 for European and Asian lighting, 60 for American lighting.
|
||||
Default: 50 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: bandingfilter
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Banding filter to reduce effects of fluorescent
|
||||
lighting:
|
||||
0 disabled, 1 enabled.
|
||||
This filter tries to reduce the pattern of horizontal
|
||||
light/dark bands caused by some (usually fluorescent) lighting.
|
||||
lighting:
|
||||
0 disabled, 1 enabled.
|
||||
This filter tries to reduce the pattern of horizontal
|
||||
light/dark bands caused by some (usually fluorescent) lighting.
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: clockdiv
|
||||
Type: int array (min = 0, max = 32)
|
||||
Syntax: <-1|n[,...]>
|
||||
Description: Force pixel clock divisor to a specific value (for experts):
|
||||
n may vary from 0 to 127.
|
||||
-1 for automatic value.
|
||||
See also the 'double_buffer' module parameter.
|
||||
n may vary from 0 to 127.
|
||||
-1 for automatic value.
|
||||
See also the 'double_buffer' module parameter.
|
||||
Default: -1 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: backlight
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Objects are lit from behind:
|
||||
0 = no, 1 = yes
|
||||
0 = no, 1 = yes
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: mirror
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Reverse image horizontally:
|
||||
0 = no, 1 = yes
|
||||
0 = no, 1 = yes
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: monochrome
|
||||
Type: bool array (min = 0, max = 32)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: The image sensor is monochrome:
|
||||
0 = no, 1 = yes
|
||||
0 = no, 1 = yes
|
||||
Default: 0 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: brightness
|
||||
Type: long array (min = 0, max = 32)
|
||||
Syntax: <n[,...]>
|
||||
Description: Set picture brightness (0-65535).
|
||||
This parameter has no effect if 'autobright' is enabled.
|
||||
This parameter has no effect if 'autobright' is enabled.
|
||||
Default: 31000 for every device.
|
||||
-------------------------------------------------------------------------------
|
||||
Name: hue
|
||||
|
@ -414,23 +414,23 @@ Name: debug
|
|||
Type: int
|
||||
Syntax: <n>
|
||||
Description: Debugging information level, from 0 to 6:
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = configuration or general messages
|
||||
4 = warnings
|
||||
5 = called functions
|
||||
6 = function internals
|
||||
Level 5 and 6 are useful for testing only, when only one
|
||||
device is used.
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = configuration or general messages
|
||||
4 = warnings
|
||||
5 = called functions
|
||||
6 = function internals
|
||||
Level 5 and 6 are useful for testing only, when only one
|
||||
device is used.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
Name: specific_debug
|
||||
Type: bool
|
||||
Syntax: <0|1>
|
||||
Description: Enable or disable specific debugging messages:
|
||||
0 = print messages concerning every level <= 'debug' level.
|
||||
1 = print messages concerning the level indicated by 'debug'.
|
||||
0 = print messages concerning every level <= 'debug' level.
|
||||
1 = print messages concerning the level indicated by 'debug'.
|
||||
Default: 0
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
ZC0301 Image Processor and Control Chip
|
||||
Driver for Linux
|
||||
=======================================
|
||||
ZC0301 and ZC0301P Image Processor and Control Chip
|
||||
Driver for Linux
|
||||
===================================================
|
||||
|
||||
- Documentation -
|
||||
- Documentation -
|
||||
|
||||
|
||||
Index
|
||||
|
@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||
|
||||
4. Overview and features
|
||||
========================
|
||||
This driver supports the video interface of the devices mounting the ZC0301
|
||||
Image Processor and Control Chip.
|
||||
This driver supports the video interface of the devices mounting the ZC0301 or
|
||||
ZC0301P Image Processors and Control Chips.
|
||||
|
||||
The driver relies on the Video4Linux2 and USB core modules. It has been
|
||||
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/
|
||||
|
||||
Some of the features of the driver are:
|
||||
|
@ -117,7 +117,7 @@ supported by the USB Audio driver thanks to the ALSA API:
|
|||
|
||||
And finally:
|
||||
|
||||
# USB Multimedia devices
|
||||
# V4L USB devices
|
||||
#
|
||||
CONFIG_USB_ZC0301=m
|
||||
|
||||
|
@ -146,46 +146,46 @@ Name: video_nr
|
|||
Type: short array (min = 0, max = 64)
|
||||
Syntax: <-1|n[,...]>
|
||||
Description: Specify V4L2 minor mode number:
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
registered camera and use auto for the first one and for every
|
||||
other camera.
|
||||
-1 = use next available
|
||||
n = use minor number n
|
||||
You can specify up to 64 cameras this way.
|
||||
For example:
|
||||
video_nr=-1,2,-1 would assign minor number 2 to the second
|
||||
registered camera and use auto for the first one and for every
|
||||
other camera.
|
||||
Default: -1
|
||||
-------------------------------------------------------------------------------
|
||||
Name: force_munmap
|
||||
Type: bool array (min = 0, max = 64)
|
||||
Syntax: <0|1[,...]>
|
||||
Description: Force the application to unmap previously mapped buffer memory
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
|
||||
all the applications support this feature. This parameter is
|
||||
specific for each detected camera.
|
||||
0 = do not force memory unmapping
|
||||
1 = force memory unmapping (save memory)
|
||||
Default: 0
|
||||
-------------------------------------------------------------------------------
|
||||
Name: frame_timeout
|
||||
Type: uint array (min = 0, max = 64)
|
||||
Syntax: <n[,...]>
|
||||
Description: Timeout for a video frame in seconds. This parameter is
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
specific for each detected camera. This parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
Name: debug
|
||||
Type: ushort
|
||||
Syntax: <n>
|
||||
Description: Debugging information level, from 0 to 3:
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used at the same time. It also shows some more informations
|
||||
about the hardware being detected. This module parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
0 = none (use carefully)
|
||||
1 = critical errors
|
||||
2 = significant informations
|
||||
3 = more verbose messages
|
||||
Level 3 is useful for testing only, when only one device
|
||||
is used at the same time. It also shows some more informations
|
||||
about the hardware being detected. This module parameter can be
|
||||
changed at runtime thanks to the /sys filesystem interface.
|
||||
Default: 2
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -204,11 +204,25 @@ Vendor ID Product ID
|
|||
0x041e 0x4017
|
||||
0x041e 0x401c
|
||||
0x041e 0x401e
|
||||
0x041e 0x401f
|
||||
0x041e 0x4022
|
||||
0x041e 0x4034
|
||||
0x041e 0x4035
|
||||
0x041e 0x4036
|
||||
0x041e 0x403a
|
||||
0x0458 0x7007
|
||||
0x0458 0x700C
|
||||
0x0458 0x700f
|
||||
0x046d 0x08ae
|
||||
0x055f 0xd003
|
||||
0x055f 0xd004
|
||||
0x046d 0x08ae
|
||||
0x0ac8 0x0301
|
||||
0x0ac8 0x301b
|
||||
0x0ac8 0x303b
|
||||
0x10fd 0x0128
|
||||
0x10fd 0x8050
|
||||
0x10fd 0x804e
|
||||
|
||||
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;
|
||||
|
@ -217,6 +231,7 @@ kernel messages will always tell you whether this is the case:
|
|||
Model Manufacturer
|
||||
----- ------------
|
||||
PAS202BCB PixArt Imaging, Inc.
|
||||
PB-0330 Photobit Corporation
|
||||
|
||||
|
||||
9. Notes for V4L2 application developers
|
||||
|
@ -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
|
||||
by Andrew Birkett <andy@nobugs.org>;
|
||||
- The initialization values of the ZC0301 controller connected to the PAS202BCB
|
||||
image sensor have been taken from the SPCA5XX driver maintained by
|
||||
Michel Xhaard <mxhaard@magic.fr>.
|
||||
and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
|
||||
by Michel Xhaard <mxhaard@magic.fr>;
|
||||
- Stanislav Lechev donated one camera.
|
||||
|
|
|
@ -25,7 +25,7 @@ config VIDEO_DEV
|
|||
module will be called videodev.
|
||||
|
||||
config VIDEO_V4L1
|
||||
boolean "Enable Video For Linux API 1 (DEPRECATED)"
|
||||
bool "Enable Video For Linux API 1 (DEPRECATED)"
|
||||
depends on VIDEO_DEV
|
||||
select VIDEO_V4L1_COMPAT
|
||||
default y
|
||||
|
@ -36,7 +36,7 @@ config VIDEO_V4L1
|
|||
If you are unsure as to whether this is required, answer Y.
|
||||
|
||||
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
|
||||
default y
|
||||
---help---
|
||||
|
@ -82,6 +82,9 @@ config VIDEO_IR
|
|||
config VIDEO_TVEEPROM
|
||||
tristate
|
||||
|
||||
config VIDEO_CX2341X
|
||||
tristate
|
||||
|
||||
config USB_DABUSB
|
||||
tristate "DABUSB driver"
|
||||
depends on USB
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
||||
obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
|
||||
|
|
|
@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
|
|||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
|
|
|
@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
|
|||
|
||||
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,
|
||||
[ 0x31 ] = KEY_1,
|
||||
[ 0x32 ] = KEY_2,
|
||||
|
@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
|
|||
[ 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] = {
|
||||
[ 0x0f ] = KEY_0,
|
||||
|
@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
|
|||
[ 0x0f ] = KEY_9,
|
||||
|
||||
[ 0x00 ] = KEY_POWER,
|
||||
[ 0x02 ] = KEY_TUNER, /* TV/FM */
|
||||
[ 0x1e ] = KEY_VIDEO,
|
||||
[ 0x1b ] = KEY_AUDIO, /* Audio Source */
|
||||
[ 0x02 ] = KEY_TUNER, /* TV/FM, not on Y0400052 */
|
||||
[ 0x1e ] = KEY_VIDEO, /* Video Source */
|
||||
[ 0x16 ] = KEY_INFO, /* Display information */
|
||||
[ 0x04 ] = KEY_VOLUMEUP,
|
||||
[ 0x08 ] = KEY_VOLUMEDOWN,
|
||||
[ 0x0c ] = KEY_CHANNELUP,
|
||||
[ 0x10 ] = KEY_CHANNELDOWN,
|
||||
[ 0x03 ] = KEY_ZOOM, /* fullscreen */
|
||||
[ 0x1f ] = KEY_SUBTITLE, /* closed caption/teletext */
|
||||
[ 0x1f ] = KEY_TEXT, /* closed caption/teletext */
|
||||
[ 0x20 ] = KEY_SLEEP,
|
||||
[ 0x29 ] = KEY_CLEAR, /* boss key */
|
||||
[ 0x14 ] = KEY_MUTE,
|
||||
[ 0x2b ] = KEY_RED,
|
||||
[ 0x2c ] = KEY_GREEN,
|
||||
[ 0x2d ] = KEY_YELLOW,
|
||||
[ 0x2e ] = KEY_BLUE,
|
||||
[ 0x18 ] = KEY_KPPLUS, /* fine tune + */
|
||||
[ 0x19 ] = KEY_KPMINUS, /* fine tune - */
|
||||
[ 0x18 ] = KEY_KPPLUS, /* fine tune + , not on Y040052 */
|
||||
[ 0x19 ] = KEY_KPMINUS, /* fine tune - , not on Y040052 */
|
||||
[ 0x2a ] = KEY_MEDIA, /* PIP (Picture in picture */
|
||||
[ 0x21 ] = KEY_DOT,
|
||||
[ 0x13 ] = KEY_ENTER,
|
||||
[ 0x22 ] = KEY_BACK,
|
||||
[ 0x11 ] = KEY_LAST, /* Recall (last channel */
|
||||
[ 0x22 ] = KEY_PREVIOUS,
|
||||
[ 0x23 ] = KEY_PLAYPAUSE,
|
||||
[ 0x24 ] = KEY_NEXT,
|
||||
[ 0x25 ] = KEY_ARCHIVE, /* Time Shifting */
|
||||
[ 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);
|
||||
|
||||
IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
|
||||
IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
|
||||
[ 0x59 ] = KEY_MUTE,
|
||||
[ 0x4a ] = KEY_POWER,
|
||||
|
||||
|
@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
|
|||
[ 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
|
||||
* slightly different versions), shipped with cx88+ivtv cards.
|
||||
|
@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
|
|||
|
||||
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)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_vv_init);
|
||||
|
||||
int saa7146_vv_release(struct saa7146_dev* dev)
|
||||
{
|
||||
|
@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_vv_release);
|
||||
|
||||
int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
|
||||
char *name, int type)
|
||||
|
@ -553,6 +555,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
|
|||
*vid = vfd;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_register_device);
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_unregister_device);
|
||||
|
||||
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
|
|||
vv->current_hps_source = source;
|
||||
vv->current_hps_sync = sync;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
|
||||
|
||||
int saa7146_enable_overlay(struct saa7146_fh *fh)
|
||||
{
|
||||
|
|
|
@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146_fh *fh)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_start_preview);
|
||||
|
||||
int saa7146_stop_preview(struct saa7146_fh *fh)
|
||||
{
|
||||
|
@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_stop_preview);
|
||||
|
||||
static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
|
||||
{
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#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 @@
|
|||
#include "stv0297.h"
|
||||
#include "mt312.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "dvb-pll.h"
|
||||
|
||||
/* lnb control */
|
||||
|
@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
|
|||
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];
|
||||
u32 div;
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
struct flexcop_device *fc = fe->dvb->priv;
|
||||
|
||||
div = params->frequency / 125;
|
||||
|
||||
|
@ -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 (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 0;
|
||||
}
|
||||
|
||||
|
@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
|
|||
.volt13_op0_op1 = STV0299_VOLT13_OP1,
|
||||
.min_delay_ms = 100,
|
||||
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
|
||||
.pll_set = samsung_tbmu24112_pll_set,
|
||||
};
|
||||
|
||||
/* dvb-t mt352 */
|
||||
|
@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
|
|||
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;
|
||||
unsigned char bs = 0;
|
||||
|
||||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
||||
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
|
||||
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
|
|||
if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
|
||||
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[2] = div & 0xff;
|
||||
pllbuf[3] = 0xcc;
|
||||
pllbuf[4] = bs;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static struct mt352_config samsung_tdtc9251dh0_config = {
|
||||
.demod_address = 0x0f,
|
||||
.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)
|
||||
|
@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
|
|||
return request_firmware(fw, name, fc->dev);
|
||||
}
|
||||
|
||||
static int lgdt3303_pll_set(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params)
|
||||
static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct flexcop_device *fc = fe->dvb->priv;
|
||||
u8 buf[4];
|
||||
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;
|
||||
return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
|
||||
}
|
||||
|
||||
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
|
||||
.demod_address = 0x59,
|
||||
.demod_chip = LGDT3303,
|
||||
.serial_mpeg = 0x04,
|
||||
.pll_set = lgdt3303_pll_set,
|
||||
.clock_polarity_flip = 1,
|
||||
};
|
||||
|
||||
static struct nxt200x_config samsung_tbmv_config = {
|
||||
.demod_address = 0x0a,
|
||||
.pll_address = 0xc2,
|
||||
.pll_desc = &dvb_pll_samsung_tbmv,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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];
|
||||
u32 div;
|
||||
|
@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
|
|||
if (params->frequency < 1550000)
|
||||
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)
|
||||
return -EIO;
|
||||
return 0;
|
||||
|
@ -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 = {
|
||||
|
||||
.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[] = {
|
||||
0x80, 0x01,
|
||||
|
@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
|
||||
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
|
||||
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;
|
||||
|
||||
|
@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
|
||||
if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
|
||||
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);
|
||||
} else
|
||||
/* try the air atsc 2nd generation (nxt2002) */
|
||||
if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
|
||||
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);
|
||||
} else
|
||||
/* try the air atsc 3nd generation (lgdt3303) */
|
||||
if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
|
||||
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);
|
||||
} else
|
||||
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
|
||||
|
@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
/* try the cable dvb (stv0297) */
|
||||
if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
|
||||
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);
|
||||
} else
|
||||
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
|
||||
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_burst = flexcop_diseqc_send_burst;
|
||||
|
@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
} else {
|
||||
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
|
||||
err("frontend registration failed!");
|
||||
ops = fc->fe->ops;
|
||||
ops = &fc->fe->ops;
|
||||
if (ops->release != NULL)
|
||||
ops->release(fc->fe);
|
||||
fc->fe = NULL;
|
||||
|
|
|
@ -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)
|
||||
return ret;
|
||||
|
||||
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
|
||||
goto dma1_free;
|
||||
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
|
||||
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_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
|
||||
|
||||
fc_pci->init_state |= FC_PCI_DMA_INIT;
|
||||
|
||||
goto success;
|
||||
dma1_free:
|
||||
flexcop_dma_free(&fc_pci->dma[0]);
|
||||
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
|
|||
spin_lock_init(&fc_pci->irq_lock);
|
||||
|
||||
fc_pci->init_state |= FC_PCI_INIT;
|
||||
goto success;
|
||||
return ret;
|
||||
|
||||
err_pci_iounmap:
|
||||
pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
|
||||
|
@ -312,8 +309,6 @@ err_pci_release_regions:
|
|||
pci_release_regions(fc_pci->pdev);
|
||||
err_pci_disable_device:
|
||||
pci_disable_device(fc_pci->pdev);
|
||||
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
goto success;
|
||||
return ret;
|
||||
|
||||
err_fc_exit:
|
||||
flexcop_device_exit(fc);
|
||||
err_pci_exit:
|
||||
flexcop_pci_exit(fc_pci);
|
||||
err_kfree:
|
||||
flexcop_device_kfree(fc);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_sram_ctrl(fc_usb->fc_dev,1,1,1);
|
||||
|
||||
ret = 0;
|
||||
goto success;
|
||||
return 0;
|
||||
|
||||
urb_error:
|
||||
flexcop_usb_transfer_exit(fc_usb);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf,
|
|||
goto err_fc_exit;
|
||||
|
||||
info("%s successfully initialized and connected.",DRIVER_NAME);
|
||||
ret = 0;
|
||||
goto success;
|
||||
return 0;
|
||||
|
||||
err_fc_exit:
|
||||
flexcop_device_exit(fc);
|
||||
err_usb_exit:
|
||||
flexcop_usb_exit(fc_usb);
|
||||
err_kfree:
|
||||
flexcop_device_kfree(fc);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
|||
static int flexcop_dvb_init(struct flexcop_device *fc)
|
||||
{
|
||||
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");
|
||||
return ret;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
|
|||
dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
|
||||
|
||||
fc->init_state |= FC_STATE_DVB_INIT;
|
||||
goto success;
|
||||
return 0;
|
||||
|
||||
err_connect_frontend:
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
|
||||
|
@ -129,9 +129,6 @@ err_dmx_dev:
|
|||
err_dmx:
|
||||
dvb_unregister_adapter(&fc->dvb_adapter);
|
||||
return ret;
|
||||
|
||||
success:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flexcop_dvb_exit(struct flexcop_device *fc)
|
||||
|
@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc)
|
|||
|
||||
flexcop_device_name(fc,"initialization of","complete");
|
||||
|
||||
ret = 0;
|
||||
goto success;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
flexcop_device_exit(fc);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(flexcop_device_initialize);
|
||||
|
|
|
@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
|
|||
int bt878_num;
|
||||
struct bt878 bt878[BT878_MAX];
|
||||
|
||||
EXPORT_SYMBOL(bt878_debug);
|
||||
EXPORT_SYMBOL(bt878_verbose);
|
||||
EXPORT_SYMBOL(bt878_num);
|
||||
EXPORT_SYMBOL(bt878);
|
||||
|
||||
|
@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = {
|
|||
{ 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
|
||||
{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T 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 }
|
||||
};
|
||||
|
||||
|
@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
|
|||
|
||||
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
|
||||
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))
|
||||
return -EIO;
|
||||
|
||||
|
|
|
@ -38,6 +38,10 @@ static unsigned int dst_addons;
|
|||
module_param(dst_addons, int, 0644);
|
||||
MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
|
||||
|
||||
static unsigned int dst_algo;
|
||||
module_param(dst_algo, int, 0644);
|
||||
MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
|
||||
|
||||
#define HAS_LOCK 1
|
||||
#define ATTEMPT_TUNE 2
|
||||
#define HAS_POWER 4
|
||||
|
@ -47,20 +51,24 @@ MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
|
|||
#define DST_INFO 2
|
||||
#define DST_DEBUG 3
|
||||
|
||||
#define dprintk(x, y, z, format, arg...) do { \
|
||||
if (z) { \
|
||||
if ((x > DST_ERROR) && (x > y)) \
|
||||
printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
|
||||
else if ((x > DST_NOTICE) && (x > y)) \
|
||||
printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
|
||||
else if ((x > DST_INFO) && (x > y)) \
|
||||
printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
|
||||
else if ((x > DST_DEBUG) && (x > y)) \
|
||||
printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
|
||||
} else { \
|
||||
if (x > y) \
|
||||
printk(format, ##arg); \
|
||||
} \
|
||||
#define dprintk(x, y, z, format, arg...) do { \
|
||||
if (z) { \
|
||||
if ((x > DST_ERROR) && (x > y)) \
|
||||
printk(KERN_ERR "dst(%d) %s: " format "\n", \
|
||||
state->bt->nr, __func__ , ##arg); \
|
||||
else if ((x > DST_NOTICE) && (x > y)) \
|
||||
printk(KERN_NOTICE "dst(%d) %s: " format "\n", \
|
||||
state->bt->nr, __func__ , ##arg); \
|
||||
else if ((x > DST_INFO) && (x > y)) \
|
||||
printk(KERN_INFO "dst(%d) %s: " format "\n", \
|
||||
state->bt->nr, __func__ , ##arg); \
|
||||
else if ((x > DST_DEBUG) && (x > y)) \
|
||||
printk(KERN_DEBUG "dst(%d) %s: " format "\n", \
|
||||
state->bt->nr, __func__ , ##arg); \
|
||||
} else { \
|
||||
if (x > y) \
|
||||
printk(format, ##arg); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state, u8 *result)
|
|||
|
||||
*result = 0;
|
||||
if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
|
||||
dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
*result = (u8) rd_packet.rd.value;
|
||||
|
@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
|
|||
state->tx_tuna[2] = (freq >> 16) & 0xff;
|
||||
state->tx_tuna[3] = (freq >> 8) & 0xff;
|
||||
state->tx_tuna[4] = (u8) freq;
|
||||
} else if (state->dst_type == DST_TYPE_IS_ATSC) {
|
||||
freq = freq / 1000;
|
||||
if (freq < 51000 || freq > 858000)
|
||||
return -EINVAL;
|
||||
state->tx_tuna[2] = (freq >> 16) & 0xff;
|
||||
state->tx_tuna[3] = (freq >> 8) & 0xff;
|
||||
state->tx_tuna[4] = (u8) freq;
|
||||
state->tx_tuna[5] = 0x00; /* ATSC */
|
||||
state->tx_tuna[6] = 0x00;
|
||||
if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
|
||||
state->tx_tuna[7] = 0x00; /* Digital */
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
|
|||
}
|
||||
dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
|
||||
srate /= 1000;
|
||||
if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
|
||||
sval = srate;
|
||||
sval <<= 20;
|
||||
do_div(sval, 88000);
|
||||
symcalc = (u32) sval;
|
||||
dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
|
||||
state->tx_tuna[5] = (u8) (symcalc >> 12);
|
||||
state->tx_tuna[6] = (u8) (symcalc >> 4);
|
||||
state->tx_tuna[7] = (u8) (symcalc << 4);
|
||||
} else {
|
||||
state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
|
||||
state->tx_tuna[6] = (u8) (srate >> 8);
|
||||
state->tx_tuna[7] = (u8) srate;
|
||||
}
|
||||
state->tx_tuna[8] &= ~0x20;
|
||||
if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
|
||||
if (srate > 8000)
|
||||
state->tx_tuna[8] |= 0x20;
|
||||
if (state->dst_type == DST_TYPE_IS_SAT) {
|
||||
if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
|
||||
sval = srate;
|
||||
sval <<= 20;
|
||||
do_div(sval, 88000);
|
||||
symcalc = (u32) sval;
|
||||
dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
|
||||
state->tx_tuna[5] = (u8) (symcalc >> 12);
|
||||
state->tx_tuna[6] = (u8) (symcalc >> 4);
|
||||
state->tx_tuna[7] = (u8) (symcalc << 4);
|
||||
} else {
|
||||
state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
|
||||
state->tx_tuna[6] = (u8) (srate >> 8);
|
||||
state->tx_tuna[7] = (u8) srate;
|
||||
}
|
||||
state->tx_tuna[8] &= ~0x20;
|
||||
if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
|
||||
if (srate > 8000)
|
||||
state->tx_tuna[8] |= 0x20;
|
||||
}
|
||||
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
|
||||
dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
|
||||
if (!strncmp(state->fw_name, "DCTNEW", 6)) {
|
||||
state->tx_tuna[5] = (u8) (srate >> 8);
|
||||
state->tx_tuna[6] = (u8) srate;
|
||||
state->tx_tuna[7] = 0x00;
|
||||
} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
|
||||
state->tx_tuna[5] = 0x00;
|
||||
state->tx_tuna[6] = (u8) (srate >> 8);
|
||||
state->tx_tuna[7] = (u8) srate;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
|
||||
{
|
||||
if (state->dst_type != DST_TYPE_IS_CABLE)
|
||||
|
@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
|
|||
state->tx_tuna[8] = 0x80;
|
||||
break;
|
||||
case QAM_256:
|
||||
state->tx_tuna[8] = 0x00;
|
||||
if (!strncmp(state->fw_name, "DCTNEW", 6))
|
||||
state->tx_tuna[8] = 0xff;
|
||||
else if (!strncmp(state->fw_name, "DCT-CI", 6))
|
||||
state->tx_tuna[8] = 0x00;
|
||||
break;
|
||||
case QPSK:
|
||||
case QAM_AUTO:
|
||||
|
@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len)
|
|||
}
|
||||
EXPORT_SYMBOL(dst_check_sum);
|
||||
|
||||
static void dst_type_flags_print(u32 type_flags)
|
||||
static void dst_type_flags_print(struct dst_state *state)
|
||||
{
|
||||
u32 type_flags = state->type_flags;
|
||||
|
||||
dprintk(verbose, DST_ERROR, 0, "DST type flags :");
|
||||
if (type_flags & DST_TYPE_HAS_NEWTUNE)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
|
||||
if (type_flags & DST_TYPE_HAS_TS188)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
|
||||
if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
|
||||
if (type_flags & DST_TYPE_HAS_TS204)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
|
||||
if (type_flags & DST_TYPE_HAS_VLF)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
|
||||
if (type_flags & DST_TYPE_HAS_SYMDIV)
|
||||
dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
|
||||
if (type_flags & DST_TYPE_HAS_FW_1)
|
||||
|
@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 type_flags)
|
|||
}
|
||||
|
||||
|
||||
static int dst_type_print(u8 type)
|
||||
static int dst_type_print(struct dst_state *state, u8 type)
|
||||
{
|
||||
char *otype;
|
||||
switch (type) {
|
||||
|
@ -558,6 +598,10 @@ static int dst_type_print(u8 type)
|
|||
otype = "cable";
|
||||
break;
|
||||
|
||||
case DST_TYPE_IS_ATSC:
|
||||
otype = "atsc";
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
|
||||
return -EINVAL;
|
||||
|
@ -567,6 +611,127 @@ static int dst_type_print(u8 type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct tuner_types tuner_list[] = {
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_L64724,
|
||||
.tuner_name = "L 64724",
|
||||
.board_name = "UNKNOWN",
|
||||
.fw_name = "UNKNOWN"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_STV0299,
|
||||
.tuner_name = "STV 0299",
|
||||
.board_name = "VP1020",
|
||||
.fw_name = "DST-MOT"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_STV0299,
|
||||
.tuner_name = "STV 0299",
|
||||
.board_name = "VP1020",
|
||||
.fw_name = "DST-03T"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_MB86A15,
|
||||
.tuner_name = "MB 86A15",
|
||||
.board_name = "VP1022",
|
||||
.fw_name = "DST-03T"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_MB86A15,
|
||||
.tuner_name = "MB 86A15",
|
||||
.board_name = "VP1025",
|
||||
.fw_name = "DST-03T"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_STV0299,
|
||||
.tuner_name = "STV 0299",
|
||||
.board_name = "VP1030",
|
||||
.fw_name = "DST-CI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_STV0299,
|
||||
.tuner_name = "STV 0299",
|
||||
.board_name = "VP1030",
|
||||
.fw_name = "DSTMCI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP2021",
|
||||
.fw_name = "DCTNEW"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP2030",
|
||||
.fw_name = "DCT-CI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP2031",
|
||||
.fw_name = "DCT-CI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP2040",
|
||||
.fw_name = "DCT-CI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP3020",
|
||||
.fw_name = "DTTFTA"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP3021",
|
||||
.fw_name = "DTTFTA"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_TDA10046,
|
||||
.tuner_name = "TDA10046",
|
||||
.board_name = "VP3040",
|
||||
.fw_name = "DTT-CI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_UNKNOWN,
|
||||
.tuner_name = "UNKNOWN",
|
||||
.board_name = "VP3051",
|
||||
.fw_name = "DTTNXT"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_NXT200x,
|
||||
.tuner_name = "NXT200x",
|
||||
.board_name = "VP3220",
|
||||
.fw_name = "ATSCDI"
|
||||
},
|
||||
|
||||
{
|
||||
.tuner_type = TUNER_TYPE_NXT200x,
|
||||
.tuner_name = "NXT200x",
|
||||
.board_name = "VP3250",
|
||||
.fw_name = "ATSCAD"
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
Known cards list
|
||||
Satellite
|
||||
|
@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 0,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
|
||||
.dst_feature = 0
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
}, /* obsolete */
|
||||
|
||||
{
|
||||
|
@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 0,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
}, /* obsolete */
|
||||
|
||||
{
|
||||
.device_id = "DST-030",
|
||||
.offset = 0,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
}, /* obsolete */
|
||||
|
||||
{
|
||||
|
@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = {
|
|||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
|
||||
| DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
|
||||
| DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
|
||||
.tuner_type = TUNER_TYPE_MULTI
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 0,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
}, /* obsolete */
|
||||
|
||||
{
|
||||
.device_id = "DST-CI",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = DST_TYPE_HAS_CA
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = DST_TYPE_HAS_CA,
|
||||
.tuner_type = 0
|
||||
}, /* An OEM board */
|
||||
|
||||
{
|
||||
.device_id = "DSTMCI",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
|
||||
.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
|
||||
.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
|
||||
| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
|
||||
| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
|
||||
.tuner_type = TUNER_TYPE_MULTI
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = "DSTFCI",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_SAT,
|
||||
.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0
|
||||
.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
}, /* unknown to vendor */
|
||||
|
||||
{
|
||||
.device_id = "DCT-CI",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_CABLE,
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
|
||||
| DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = DST_TYPE_HAS_CA
|
||||
.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
|
||||
.dst_feature = DST_TYPE_HAS_CA,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = "DCTNEW",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_CABLE,
|
||||
.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
|
||||
.dst_feature = 0
|
||||
.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = "DTT-CI",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_TERR,
|
||||
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
|
||||
.dst_feature = DST_TYPE_HAS_CA
|
||||
.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
|
||||
.dst_feature = DST_TYPE_HAS_CA,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_TERR,
|
||||
.type_flags = DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = 0
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_TERR,
|
||||
.type_flags = DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = DST_TYPE_HAS_ANALOG
|
||||
.dst_feature = DST_TYPE_HAS_ANALOG,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = {
|
|||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_ATSC,
|
||||
.type_flags = DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = 0
|
||||
.dst_feature = 0,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = "ATSCAD",
|
||||
.offset = 1,
|
||||
.dst_type = DST_TYPE_IS_ATSC,
|
||||
.type_flags = DST_TYPE_HAS_FW_2,
|
||||
.dst_feature = 0
|
||||
.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
|
||||
.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
|
||||
.tuner_type = 0
|
||||
},
|
||||
|
||||
{ }
|
||||
|
@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state *state)
|
|||
|
||||
static int dst_card_type(struct dst_state *state)
|
||||
{
|
||||
int j;
|
||||
struct tuner_types *p_tuner_list = NULL;
|
||||
|
||||
u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
get_type[7] = dst_check_sum(get_type, 7);
|
||||
if (dst_command(state, get_type, 8) < 0) {
|
||||
|
@ -775,9 +957,17 @@ static int dst_card_type(struct dst_state *state)
|
|||
return -1;
|
||||
}
|
||||
memset(&state->card_info, '\0', 8);
|
||||
memcpy(&state->card_info, &state->rxbuffer, 8);
|
||||
memcpy(&state->card_info, &state->rxbuffer, 7);
|
||||
dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
|
||||
|
||||
for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
|
||||
if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
|
||||
state->tuner_type = p_tuner_list->tuner_type;
|
||||
dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
|
||||
p_tuner_list->tuner_name, p_tuner_list->tuner_type);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_state *state)
|
|||
return -1;
|
||||
}
|
||||
memset(&state->vendor, '\0', 8);
|
||||
memcpy(&state->vendor, &state->rxbuffer, 8);
|
||||
memcpy(&state->vendor, &state->rxbuffer, 7);
|
||||
dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_dst_buffer(struct dst_state *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (verbose > 2) {
|
||||
printk("%s: [", __func__);
|
||||
for (i = 0; i < 8; i++)
|
||||
printk(" %02x", state->rxbuffer[i]);
|
||||
printk("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int dst_check_stv0299(struct dst_state *state)
|
||||
{
|
||||
u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
check_stv0299[7] = dst_check_sum(check_stv0299, 7);
|
||||
if (dst_command(state, check_stv0299, 8) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
|
||||
return -1;
|
||||
}
|
||||
debug_dst_buffer(state);
|
||||
|
||||
if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
|
||||
dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
|
||||
state->tuner_type = TUNER_TYPE_STV0299;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dst_check_mb86a15(struct dst_state *state)
|
||||
{
|
||||
u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
|
||||
if (dst_command(state, check_mb86a15, 8) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
|
||||
return -1;
|
||||
}
|
||||
debug_dst_buffer(state);
|
||||
|
||||
if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
|
||||
state->tuner_type = TUNER_TYPE_MB86A15;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dst_get_tuner_info(struct dst_state *state)
|
||||
{
|
||||
u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst_state *state)
|
|||
|
||||
get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
|
||||
get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
|
||||
dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
|
||||
if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
|
||||
if (dst_command(state, get_tuner_2, 8) < 0) {
|
||||
dprintk(verbose, DST_INFO, 1, "Unsupported Command");
|
||||
return -1;
|
||||
if (dst_command(state, get_tuner_1, 8) < 0) {
|
||||
dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
|
||||
goto force;
|
||||
}
|
||||
} else {
|
||||
if (dst_command(state, get_tuner_1, 8) < 0) {
|
||||
dprintk(verbose, DST_INFO, 1, "Unsupported Command");
|
||||
return -1;
|
||||
if (dst_command(state, get_tuner_2, 8) < 0) {
|
||||
dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
|
||||
goto force;
|
||||
}
|
||||
}
|
||||
memset(&state->board_info, '\0', 8);
|
||||
memcpy(&state->board_info, &state->rxbuffer, 8);
|
||||
if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
|
||||
if (state->board_info[1] == 0x0b) {
|
||||
if (state->type_flags & DST_TYPE_HAS_TS204)
|
||||
state->type_flags &= ~DST_TYPE_HAS_TS204;
|
||||
state->type_flags |= DST_TYPE_HAS_NEWTUNE;
|
||||
dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
|
||||
} else {
|
||||
if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
|
||||
state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
|
||||
state->type_flags |= DST_TYPE_HAS_TS204;
|
||||
dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
|
||||
}
|
||||
} else {
|
||||
if (state->board_info[0] == 0xbc) {
|
||||
if (state->type_flags & DST_TYPE_HAS_TS204)
|
||||
state->type_flags &= ~DST_TYPE_HAS_TS204;
|
||||
state->type_flags |= DST_TYPE_HAS_NEWTUNE;
|
||||
dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
|
||||
dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
|
||||
}
|
||||
if (state->board_info[0] == 0xbc) {
|
||||
if (state->type_flags != DST_TYPE_IS_ATSC)
|
||||
state->type_flags |= DST_TYPE_HAS_TS188;
|
||||
else
|
||||
state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
|
||||
|
||||
} else if (state->board_info[0] == 0xcc) {
|
||||
if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
|
||||
state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
|
||||
state->type_flags |= DST_TYPE_HAS_TS204;
|
||||
dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
|
||||
if (state->board_info[1] == 0x01) {
|
||||
state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
|
||||
dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
force:
|
||||
if (!strncmp(state->fw_name, "DCT-CI", 6)) {
|
||||
state->type_flags |= DST_TYPE_HAS_TS204;
|
||||
dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dst_get_device_id(struct dst_state *state)
|
||||
{
|
||||
u8 reply;
|
||||
|
||||
int i;
|
||||
struct dst_types *p_dst_type;
|
||||
int i, j;
|
||||
struct dst_types *p_dst_type = NULL;
|
||||
struct tuner_types *p_tuner_list = NULL;
|
||||
|
||||
u8 use_dst_type = 0;
|
||||
u32 use_type_flags = 0;
|
||||
|
||||
static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
|
||||
|
||||
state->tuner_type = 0;
|
||||
device_type[7] = dst_check_sum(device_type, 7);
|
||||
|
||||
if (write_dst(state, device_type, FIXED_COMM))
|
||||
|
@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_state *state)
|
|||
|
||||
/* Card capabilities */
|
||||
state->dst_hw_cap = p_dst_type->dst_feature;
|
||||
dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
|
||||
|
||||
dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
|
||||
strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
|
||||
/* Multiple tuners */
|
||||
if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
|
||||
switch (use_dst_type) {
|
||||
case DST_TYPE_IS_SAT:
|
||||
/* STV0299 check */
|
||||
if (dst_check_stv0299(state) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "Unsupported");
|
||||
state->tuner_type = TUNER_TYPE_MB86A15;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (dst_check_mb86a15(state) < 0)
|
||||
dprintk(verbose, DST_ERROR, 1, "Unsupported");
|
||||
/* Single tuner */
|
||||
} else {
|
||||
state->tuner_type = p_dst_type->tuner_type;
|
||||
}
|
||||
for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
|
||||
if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
|
||||
p_tuner_list->tuner_type == state->tuner_type) {
|
||||
dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
|
||||
p_dst_type->device_id, p_tuner_list->tuner_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_state *state)
|
|||
use_dst_type = DST_TYPE_IS_SAT;
|
||||
use_type_flags = DST_TYPE_HAS_SYMDIV;
|
||||
}
|
||||
dst_type_print(use_dst_type);
|
||||
dst_type_print(state, use_dst_type);
|
||||
state->type_flags = use_type_flags;
|
||||
state->dst_type = use_dst_type;
|
||||
dst_type_flags_print(state->type_flags);
|
||||
dst_type_flags_print(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_state *state)
|
|||
static int dst_probe(struct dst_state *state)
|
||||
{
|
||||
mutex_init(&state->dst_mutex);
|
||||
if ((rdc_8820_reset(state)) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
|
||||
return -1;
|
||||
}
|
||||
if (dst_addons & DST_TYPE_HAS_CA)
|
||||
if (dst_addons & DST_TYPE_HAS_CA) {
|
||||
if ((rdc_8820_reset(state)) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
|
||||
return -1;
|
||||
}
|
||||
msleep(4000);
|
||||
else
|
||||
} else {
|
||||
msleep(100);
|
||||
|
||||
}
|
||||
if ((dst_comm_init(state)) < 0) {
|
||||
dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
|
||||
return -1;
|
||||
|
@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *state)
|
|||
}
|
||||
if (dst_get_mac(state) < 0) {
|
||||
dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
|
||||
return 0;
|
||||
}
|
||||
if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
|
||||
if (dst_get_tuner_info(state) < 0)
|
||||
|
@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_state *state)
|
|||
state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
|
||||
state->decode_strength = state->rxbuffer[4] << 8;
|
||||
state->decode_snr = state->rxbuffer[3] << 8;
|
||||
} else if (state->dst_type == DST_TYPE_IS_ATSC) {
|
||||
state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
|
||||
state->decode_strength = state->rxbuffer[4] << 8;
|
||||
state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
|
||||
}
|
||||
state->cur_jiff = jiffies;
|
||||
}
|
||||
|
@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state *state)
|
|||
state->diseq_flags &= ~(HAS_LOCK);
|
||||
if (!dst_wait_dst_ready(state, NO_DELAY))
|
||||
return -EIO;
|
||||
if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
|
||||
/* how to get variable length reply ???? */
|
||||
if ((state->type_flags & DST_TYPE_HAS_VLF) &&
|
||||
!(state->dst_type == DST_TYPE_IS_ATSC))
|
||||
|
||||
retval = read_dst(state, state->rx_tuna, 10);
|
||||
else
|
||||
retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
|
||||
|
@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state *state)
|
|||
dprintk(verbose, DST_DEBUG, 1, "read not successful");
|
||||
return retval;
|
||||
}
|
||||
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
|
||||
if ((state->type_flags & DST_TYPE_HAS_VLF) &&
|
||||
!(state->dst_type == DST_TYPE_IS_CABLE) &&
|
||||
!(state->dst_type == DST_TYPE_IS_ATSC)) {
|
||||
|
||||
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
|
||||
dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
|
||||
return -EIO;
|
||||
|
@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_frontend *fe)
|
|||
dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
|
||||
goto error;
|
||||
}
|
||||
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
|
||||
// if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
|
||||
if ((state->type_flags & DST_TYPE_HAS_VLF) &&
|
||||
(!(state->dst_type == DST_TYPE_IS_ATSC))) {
|
||||
|
||||
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
|
||||
retval = write_dst(state, &state->tx_tuna[0], 10);
|
||||
} else {
|
||||
|
@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
|
|||
|
||||
if (state->dst_type != DST_TYPE_IS_SAT)
|
||||
return 0;
|
||||
if (cmd->msg_len == 0 || cmd->msg_len > 4)
|
||||
if (cmd->msg_len > 0 && cmd->msg_len < 5)
|
||||
memcpy(&paket[3], cmd->msg, cmd->msg_len);
|
||||
else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
|
||||
memcpy(&paket[2], cmd->msg, cmd->msg_len);
|
||||
else
|
||||
return -EINVAL;
|
||||
memcpy(&paket[3], cmd->msg, cmd->msg_len);
|
||||
paket[7] = dst_check_sum(&paket[0], 7);
|
||||
dst_command(state, paket, 8);
|
||||
return 0;
|
||||
|
@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend *fe)
|
|||
static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
|
||||
static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
state->inversion = INVERSION_OFF;
|
||||
state->voltage = SEC_VOLTAGE_13;
|
||||
|
@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend *fe)
|
|||
state->bandwidth = BANDWIDTH_7_MHZ;
|
||||
state->cur_jiff = jiffies;
|
||||
if (state->dst_type == DST_TYPE_IS_SAT)
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
|
||||
else if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
|
||||
else if (state->dst_type == DST_TYPE_IS_CABLE)
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
|
||||
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
|
||||
else if (state->dst_type == DST_TYPE_IS_ATSC)
|
||||
memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dst_set_frontend(struct dvb_frontend* fe,
|
||||
static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dst_state *state = fe->demodulator_priv;
|
||||
|
||||
if (p != NULL) {
|
||||
dst_set_freq(state, p->frequency);
|
||||
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
|
||||
|
||||
if (state->dst_type == DST_TYPE_IS_SAT) {
|
||||
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
|
||||
dst_set_inversion(state, p->inversion);
|
||||
dst_set_fec(state, p->u.qpsk.fec_inner);
|
||||
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
|
||||
dst_set_polarization(state);
|
||||
dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
|
||||
|
||||
} else if (state->dst_type == DST_TYPE_IS_TERR)
|
||||
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
|
||||
else if (state->dst_type == DST_TYPE_IS_CABLE) {
|
||||
dst_set_fec(state, p->u.qam.fec_inner);
|
||||
dst_set_symbolrate(state, p->u.qam.symbol_rate);
|
||||
dst_set_modulation(state, p->u.qam.modulation);
|
||||
}
|
||||
dst_write_tuna(fe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_tune_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* p,
|
||||
unsigned int mode_flags,
|
||||
int *delay,
|
||||
|
@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_frontend* fe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dst_get_tuning_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return dst_algo;
|
||||
}
|
||||
|
||||
static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dst_state *state = fe->demodulator_priv;
|
||||
|
@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_frontend *fe)
|
|||
static struct dvb_frontend_ops dst_dvbt_ops;
|
||||
static struct dvb_frontend_ops dst_dvbs_ops;
|
||||
static struct dvb_frontend_ops dst_dvbc_ops;
|
||||
static struct dvb_frontend_ops dst_atsc_ops;
|
||||
|
||||
struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
|
||||
{
|
||||
|
@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
|
|||
return NULL;
|
||||
}
|
||||
/* determine settings based on type */
|
||||
/* create dvb_frontend */
|
||||
switch (state->dst_type) {
|
||||
case DST_TYPE_IS_TERR:
|
||||
memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case DST_TYPE_IS_CABLE:
|
||||
memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case DST_TYPE_IS_SAT:
|
||||
memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case DST_TYPE_IS_ATSC:
|
||||
memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
default:
|
||||
dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
return state; /* Manu (DST is a card not a frontend) */
|
||||
|
@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
|
|||
|
||||
.release = dst_release,
|
||||
.init = dst_init,
|
||||
.tune = dst_set_frontend,
|
||||
.tune = dst_tune_frontend,
|
||||
.set_frontend = dst_set_frontend,
|
||||
.get_frontend = dst_get_frontend,
|
||||
.get_frontend_algo = dst_get_tuning_algo,
|
||||
.read_status = dst_read_status,
|
||||
.read_signal_strength = dst_read_signal_strength,
|
||||
.read_snr = dst_read_snr,
|
||||
|
@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
|
|||
|
||||
.release = dst_release,
|
||||
.init = dst_init,
|
||||
.tune = dst_set_frontend,
|
||||
.tune = dst_tune_frontend,
|
||||
.set_frontend = dst_set_frontend,
|
||||
.get_frontend = dst_get_frontend,
|
||||
.get_frontend_algo = dst_get_tuning_algo,
|
||||
.read_status = dst_read_status,
|
||||
.read_signal_strength = dst_read_signal_strength,
|
||||
.read_snr = dst_read_snr,
|
||||
|
@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
|
|||
|
||||
.release = dst_release,
|
||||
.init = dst_init,
|
||||
.tune = dst_set_frontend,
|
||||
.tune = dst_tune_frontend,
|
||||
.set_frontend = dst_set_frontend,
|
||||
.get_frontend = dst_get_frontend,
|
||||
.get_frontend_algo = dst_get_tuning_algo,
|
||||
.read_status = dst_read_status,
|
||||
.read_signal_strength = dst_read_signal_strength,
|
||||
.read_snr = dst_read_snr,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
|
||||
static struct dvb_frontend_ops dst_atsc_ops = {
|
||||
.info = {
|
||||
.name = "DST ATSC",
|
||||
.type = FE_ATSC,
|
||||
.frequency_stepsize = 62500,
|
||||
.frequency_min = 510000000,
|
||||
.frequency_max = 858000000,
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
|
||||
},
|
||||
|
||||
.release = dst_release,
|
||||
.init = dst_init,
|
||||
.tune = dst_tune_frontend,
|
||||
.set_frontend = dst_set_frontend,
|
||||
.get_frontend = dst_get_frontend,
|
||||
.get_frontend_algo = dst_get_tuning_algo,
|
||||
.read_status = dst_read_status,
|
||||
.read_signal_strength = dst_read_signal_strength,
|
||||
.read_snr = dst_read_snr,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
|
||||
MODULE_AUTHOR("Jamie Honan, Manu Abraham");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -68,6 +68,13 @@ static int ca_set_pid(void)
|
|||
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)
|
||||
{
|
||||
|
@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
|
|||
u8 dst_ca_comm_err = 0;
|
||||
|
||||
while (dst_ca_comm_err < RETRIES) {
|
||||
dst_comm_init(state);
|
||||
dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
|
||||
if (dst_ci_command(state, data, ca_string, len, read)) { // If error
|
||||
dst_error_recovery(state);
|
||||
dst_ca_comm_err++; // work required here.
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(dst_ca_comm_err == RETRIES)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
int length, str_length;
|
||||
static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
|
||||
|
||||
put_checksum(&command[0], command[0]);
|
||||
|
@ -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]));
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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, 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, "\n");
|
||||
|
||||
|
@ -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)) )
|
||||
return -EFAULT;
|
||||
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
|
|||
rdc_reset_state(state);
|
||||
return -1;
|
||||
}
|
||||
dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
|
||||
dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset)
|
|||
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)
|
||||
{
|
||||
u32 length = 0;
|
||||
|
@ -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 !");
|
||||
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:
|
||||
|
@ -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;
|
||||
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);
|
||||
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
|
||||
p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
|
||||
if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
|
||||
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
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");
|
||||
return -ENOMEM;
|
||||
}
|
||||
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;
|
||||
result = -ENOMEM;
|
||||
goto free_mem_and_exit;
|
||||
}
|
||||
|
||||
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */
|
||||
switch (cmd) {
|
||||
case CA_SEND_MSG:
|
||||
|
@ -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)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
ssize_t bytes_read = 0;
|
||||
|
||||
dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#define DST_TYPE_IS_CABLE 2
|
||||
#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_SYMDIV 4
|
||||
#define DST_TYPE_HAS_FW_1 8
|
||||
|
@ -52,6 +52,9 @@
|
|||
#define DST_TYPE_HAS_OBS_REGS 128
|
||||
#define DST_TYPE_HAS_INC_COUNT 256
|
||||
#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 */
|
||||
|
||||
|
@ -64,6 +67,20 @@
|
|||
#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
|
||||
#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_ENABLE 1
|
||||
#define RDC_8820_INT 2
|
||||
|
@ -84,8 +101,6 @@ struct dst_state {
|
|||
|
||||
struct bt878* bt;
|
||||
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
/* configuration settings */
|
||||
const struct dst_config* config;
|
||||
|
||||
|
@ -121,8 +136,17 @@ struct dst_state {
|
|||
u8 card_info[8];
|
||||
u8 vendor[8];
|
||||
u8 board_info[8];
|
||||
|
||||
u32 tuner_type;
|
||||
char *tuner_name;
|
||||
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 {
|
||||
|
@ -131,6 +155,7 @@ struct dst_types {
|
|||
u8 dst_type;
|
||||
u32 type_flags;
|
||||
u32 dst_feature;
|
||||
u32 tuner_type;
|
||||
};
|
||||
|
||||
struct dst_config
|
||||
|
|
|
@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
|
||||
static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
|
||||
{
|
||||
u32 div;
|
||||
unsigned char bs = 0;
|
||||
unsigned char cp = 0;
|
||||
|
||||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
||||
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
|
||||
|
||||
if (params->frequency < 542000000)
|
||||
|
@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
|
|||
else
|
||||
bs = 0x08;
|
||||
|
||||
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
|
||||
pllbuf[0] = 0x60;
|
||||
pllbuf[1] = div >> 8;
|
||||
pllbuf[2] = div & 0xff;
|
||||
pllbuf[3] = cp;
|
||||
pllbuf[4] = bs;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static struct mt352_config thomson_dtt7579_config = {
|
||||
.demod_address = 0x0f,
|
||||
.demod_init = thomson_dtt7579_demod_init,
|
||||
.pll_set = thomson_dtt7579_pll_set,
|
||||
};
|
||||
|
||||
static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
static struct zl10353_config thomson_dtt7579_zl10353_config = {
|
||||
.demod_address = 0x0f,
|
||||
};
|
||||
|
||||
static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
u32 freq = params->frequency;
|
||||
|
||||
|
@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pinnsat_pll_init(struct dvb_frontend* fe)
|
||||
static int pinnsat_tuner_init(struct dvb_frontend* fe)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = fe->dvb->priv;
|
||||
|
||||
|
@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pinnsat_pll_sleep(struct dvb_frontend* fe)
|
||||
static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = fe->dvb->priv;
|
||||
|
||||
|
@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe)
|
|||
|
||||
static struct cx24110_config pctvsat_config = {
|
||||
.demod_address = 0x55,
|
||||
.pll_init = pinnsat_pll_init,
|
||||
.pll_set = cx24108_pll_set,
|
||||
.pll_sleep = pinnsat_pll_sleep,
|
||||
};
|
||||
|
||||
static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
|
||||
u8 cfg, cpump, band_select;
|
||||
|
@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
|
|||
data[2] = ((div >> 10) & 0x60) | cfg;
|
||||
data[3] = (cpump << 6) | band_select;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(card->i2c_adapter, &msg, 1);
|
||||
return (div * 166666 - 36000000);
|
||||
}
|
||||
|
@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
|
|||
|
||||
static struct sp887x_config microtune_mt7202dtf_config = {
|
||||
.demod_address = 0x70,
|
||||
.pll_set = microtune_mt7202dtf_pll_set,
|
||||
.request_firmware = microtune_mt7202dtf_request_firmware,
|
||||
};
|
||||
|
||||
|
@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
|
||||
static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
|
||||
{
|
||||
u32 div;
|
||||
unsigned char bs = 0;
|
||||
unsigned char cp = 0;
|
||||
|
||||
if (buf_len < 5) return -EINVAL;
|
||||
|
||||
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
|
||||
|
||||
if (params->frequency < 150000000)
|
||||
|
@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
|
|||
else
|
||||
bs = 0x08;
|
||||
|
||||
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
|
||||
pllbuf[0] = 0x61;
|
||||
pllbuf[1] = div >> 8;
|
||||
pllbuf[2] = div & 0xff;
|
||||
pllbuf[3] = cp;
|
||||
pllbuf[4] = bs;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
|
||||
.demod_address = 0x0f,
|
||||
.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
|
||||
.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
|
||||
};
|
||||
|
||||
static struct dst_config dst_config = {
|
||||
|
@ -455,7 +460,7 @@ static struct or51211_config or51211_config = {
|
|||
.sleep = or51211_sleep,
|
||||
};
|
||||
|
||||
static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
|
||||
u8 buf[4];
|
||||
|
@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
|
|||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(card->i2c_adapter, &msg, 1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
|
|||
static struct nxt6000_config vp3021_alps_tded4_config = {
|
||||
.demod_address = 0x0a,
|
||||
.clock_inversion = 1,
|
||||
.pll_set = vp3021_alps_tded4_pll_set,
|
||||
};
|
||||
|
||||
static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
|
||||
|
@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
|
||||
static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
|
||||
{
|
||||
u32 div;
|
||||
struct dvb_ofdm_parameters *op = ¶ms->u.ofdm;
|
||||
|
||||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
||||
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
|
||||
|
||||
pllbuf[0] = 0xc2;
|
||||
pllbuf[0] = 0x61;
|
||||
pllbuf[1] = (div >> 8) & 0x7F;
|
||||
pllbuf[2] = div & 0xFF;
|
||||
pllbuf[3] = 0x85;
|
||||
|
@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
|
|||
if (op->bandwidth == 8)
|
||||
pllbuf[4] |= 0x04;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
|
||||
|
@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
|
|||
static struct mt352_config digitv_alps_tded4_config = {
|
||||
.demod_address = 0x0a,
|
||||
.demod_init = digitv_alps_tded4_demod_init,
|
||||
.pll_set = digitv_alps_tded4_pll_set,
|
||||
};
|
||||
|
||||
static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
int err;
|
||||
|
||||
dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
|
||||
dprintk("%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(card->i2c_adapter, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "dvb-bt8xx: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* Set the Auxiliary Byte. */
|
||||
buf[2] &= ~0x20;
|
||||
buf[2] |= 0x18;
|
||||
buf[3] = 0x50;
|
||||
i2c_transfer(card->i2c_adapter, &msg, 1);
|
||||
|
||||
return 0;
|
||||
return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
|
||||
}
|
||||
|
||||
static struct lgdt330x_config tdvs_tua6034_config = {
|
||||
.demod_address = 0x0e,
|
||||
.demod_chip = LGDT3303,
|
||||
.serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
|
||||
.pll_set = tdvs_tua6034_pll_set,
|
||||
};
|
||||
|
||||
static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
|
||||
|
@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
switch(type) {
|
||||
case BTTV_BOARD_DVICO_DVBT_LITE:
|
||||
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
|
||||
|
||||
if (card->fe == NULL)
|
||||
card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
|
||||
card->i2c_adapter);
|
||||
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops->info.frequency_min = 174000000;
|
||||
card->fe->ops->info.frequency_max = 862000000;
|
||||
card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
|
||||
card->fe->ops.info.frequency_min = 174000000;
|
||||
card->fe->ops.info.frequency_max = 862000000;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
||||
lgdt330x_reset(card);
|
||||
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
|
||||
if (card->fe != NULL)
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
|
||||
dprintk ("dvb_bt8xx: lgdt330x detected\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_NEBULA_DIGITV:
|
||||
|
@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
digitv_alps_tded4_reset(card);
|
||||
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
|
||||
dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
|
||||
break;
|
||||
}
|
||||
|
@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
digitv_alps_tded4_reset(card);
|
||||
card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
|
||||
|
||||
if (card->fe != NULL)
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
|
||||
dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_AVDVBT_761:
|
||||
card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter);
|
||||
if (card->fe) {
|
||||
card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_AVDVBT_771:
|
||||
card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops->info.frequency_min = 174000000;
|
||||
card->fe->ops->info.frequency_max = 862000000;
|
||||
card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
|
||||
card->fe->ops.info.frequency_min = 174000000;
|
||||
card->fe->ops.info.frequency_max = 862000000;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
|
||||
case BTTV_BOARD_PINNACLESAT:
|
||||
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
|
||||
if (card->fe) {
|
||||
card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
|
||||
card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
|
||||
card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_PC_HDTV:
|
||||
|
@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
else
|
||||
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
|
||||
printk("dvb-bt8xx: Frontend registration failed!\n");
|
||||
if (card->fe->ops->release)
|
||||
card->fe->ops->release(card->fe);
|
||||
if (card->fe->ops.release)
|
||||
card->fe->ops.release(card->fe);
|
||||
card->fe = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
|
|||
{
|
||||
int result;
|
||||
|
||||
if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
|
||||
if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
|
||||
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "cx24110.h"
|
||||
#include "or51211.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "zl10353.h"
|
||||
|
||||
struct dvb_bt8xx_card {
|
||||
struct mutex lock;
|
||||
|
|
|
@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL
|
|||
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
|
||||
bool "Register the onboard IR Remote Control Receiver as Input Device"
|
||||
depends on DVB_CINERGYT2_TUNING
|
||||
default "yes"
|
||||
default y
|
||||
help
|
||||
Enable this option if you want to use the onboard Infrared Remote
|
||||
Control Receiver as Linux-Input device.
|
||||
|
|
|
@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
|
|||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
poll_wait(file, &cinergyt2->poll_wq, wait);
|
||||
|
||||
if (cinergyt2->pending_fe_events != 0)
|
||||
mask |= (POLLIN | POLLRDNORM | POLLPRI);
|
||||
|
||||
mutex_unlock(&cinergyt2->sem);
|
||||
|
||||
return (POLLIN | POLLRDNORM | POLLPRI);
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
|
@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
|
|||
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);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# Makefile for the kernel DVB device drivers.
|
||||
#
|
||||
|
||||
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
dvb_net.o dvb_ringbuffer.o
|
||||
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
dvb_net.o dvb_ringbuffer.o dvb_math.o
|
||||
|
||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
|
||||
|
|
|
@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
|
|||
mutex_unlock(&dmxdevfilter->mutex);
|
||||
break;
|
||||
|
||||
case DMX_GET_EVENT:
|
||||
break;
|
||||
|
||||
case DMX_GET_PES_PIDS:
|
||||
if (!dmxdev->demux->get_pes_pids) {
|
||||
ret = -EINVAL;
|
||||
|
|
|
@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
break;
|
||||
|
||||
case DVB_CA_SLOTSTATE_VALIDATE:
|
||||
if (dvb_ca_en50221_parse_attributes(ca, slot)
|
||||
!= 0) {
|
||||
if (dvb_ca_en50221_parse_attributes(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: Invalid PC card inserted :(\n",
|
||||
ca->dvbdev->adapter->num);
|
||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||
|
@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
|
||||
case DVB_CA_SLOTSTATE_LINKINIT:
|
||||
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);
|
||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||
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)
|
|||
goto bailout;
|
||||
}
|
||||
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);
|
||||
if (tmppack[0] == 0xB8)
|
||||
tmppack[0] = 0x47;
|
||||
|
@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
|||
}
|
||||
|
||||
while (p < count) {
|
||||
if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
|
||||
if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
|
||||
if (count - p >= 204) {
|
||||
memcpy(tmppack, &buf[p], 188);
|
||||
if (tmppack[0] == 0xB8)
|
||||
|
|
|
@ -56,7 +56,7 @@ MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AU
|
|||
module_param(dvb_override_tune_delay, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
|
||||
module_param(dvb_powerdown_on_sleep, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
|
||||
MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
|
||||
|
||||
#define dprintk if (dvb_frontend_debug) printk
|
||||
|
||||
|
@ -72,6 +72,8 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola
|
|||
#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
|
||||
#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
|
||||
#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
|
||||
|
||||
#define FE_ALGO_HW 1
|
||||
/*
|
||||
* FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
|
||||
* FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
|
||||
|
@ -151,8 +153,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
|||
sizeof (struct dvb_frontend_parameters));
|
||||
|
||||
if (status & FE_HAS_LOCK)
|
||||
if (fe->ops->get_frontend)
|
||||
fe->ops->get_frontend(fe, &e->parameters);
|
||||
if (fe->ops.get_frontend)
|
||||
fe->ops.get_frontend(fe, &e->parameters);
|
||||
|
||||
events->eventw = wp;
|
||||
|
||||
|
@ -211,10 +213,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
|
|||
{
|
||||
dprintk ("DVB: initialising frontend %i (%s)...\n",
|
||||
fe->dvb->num,
|
||||
fe->ops->info.name);
|
||||
fe->ops.info.name);
|
||||
|
||||
if (fe->ops->init)
|
||||
fe->ops->init(fe);
|
||||
if (fe->ops.init)
|
||||
fe->ops.init(fe);
|
||||
if (fe->ops.tuner_ops.init) {
|
||||
fe->ops.tuner_ops.init(fe);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void dvb_frontend_reinitialise(struct dvb_frontend *fe)
|
||||
|
@ -259,7 +266,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
|
|||
u32 original_frequency = fepriv->parameters.frequency;
|
||||
|
||||
/* are we using autoinversion? */
|
||||
autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
(fepriv->parameters.inversion == INVERSION_AUTO));
|
||||
|
||||
/* setup parameters correctly */
|
||||
|
@ -329,8 +336,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
|
|||
fepriv->parameters.frequency += fepriv->lnb_drift;
|
||||
if (autoinversion)
|
||||
fepriv->parameters.inversion = fepriv->inversion;
|
||||
if (fe->ops->set_frontend)
|
||||
fe->ops->set_frontend(fe, &fepriv->parameters);
|
||||
if (fe->ops.set_frontend)
|
||||
fe->ops.set_frontend(fe, &fepriv->parameters);
|
||||
|
||||
fepriv->parameters.frequency = original_frequency;
|
||||
fepriv->parameters.inversion = original_inversion;
|
||||
|
@ -354,8 +361,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
/* in SCAN mode, we just set the frontend when asked and leave it alone */
|
||||
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
|
||||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
if (fe->ops->set_frontend)
|
||||
fe->ops->set_frontend(fe, &fepriv->parameters);
|
||||
if (fe->ops.set_frontend)
|
||||
fe->ops.set_frontend(fe, &fepriv->parameters);
|
||||
fepriv->state = FESTATE_TUNED;
|
||||
}
|
||||
fepriv->delay = 3*HZ;
|
||||
|
@ -367,8 +374,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
s = 0;
|
||||
} else {
|
||||
if (fe->ops->read_status)
|
||||
fe->ops->read_status(fe, &s);
|
||||
if (fe->ops.read_status)
|
||||
fe->ops.read_status(fe, &s);
|
||||
if (s != fepriv->status) {
|
||||
dvb_frontend_add_event(fe, s);
|
||||
fepriv->status = s;
|
||||
|
@ -381,7 +388,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
fepriv->state = FESTATE_TUNED;
|
||||
|
||||
/* if we're tuned, then we have determined the correct inversion */
|
||||
if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
(fepriv->parameters.inversion == INVERSION_AUTO)) {
|
||||
fepriv->parameters.inversion = fepriv->inversion;
|
||||
}
|
||||
|
@ -405,7 +412,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
/* don't actually do anything if we're in the LOSTLOCK state,
|
||||
* the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
|
||||
if ((fepriv->state & FESTATE_LOSTLOCK) &&
|
||||
(fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
|
||||
(fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
|
||||
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
|
||||
return;
|
||||
}
|
||||
|
@ -540,16 +547,16 @@ static int dvb_frontend_thread(void *data)
|
|||
if (fepriv->reinitialise) {
|
||||
dvb_frontend_init(fe);
|
||||
if (fepriv->tone != -1) {
|
||||
fe->ops->set_tone(fe, fepriv->tone);
|
||||
fe->ops.set_tone(fe, fepriv->tone);
|
||||
}
|
||||
if (fepriv->voltage != -1) {
|
||||
fe->ops->set_voltage(fe, fepriv->voltage);
|
||||
fe->ops.set_voltage(fe, fepriv->voltage);
|
||||
}
|
||||
fepriv->reinitialise = 0;
|
||||
}
|
||||
|
||||
/* do an iteration of the tuning loop */
|
||||
if (fe->ops->tune) {
|
||||
if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
|
||||
/* have we been asked to retune? */
|
||||
params = NULL;
|
||||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
|
@ -557,7 +564,7 @@ static int dvb_frontend_thread(void *data)
|
|||
fepriv->state = FESTATE_TUNED;
|
||||
}
|
||||
|
||||
fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
|
||||
fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
|
||||
if (s != fepriv->status) {
|
||||
dvb_frontend_add_event(fe, s);
|
||||
fepriv->status = s;
|
||||
|
@ -569,10 +576,15 @@ static int dvb_frontend_thread(void *data)
|
|||
|
||||
if (dvb_shutdown_timeout) {
|
||||
if (dvb_powerdown_on_sleep)
|
||||
if (fe->ops->set_voltage)
|
||||
fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
if (fe->ops->sleep)
|
||||
fe->ops->sleep(fe);
|
||||
if (fe->ops.set_voltage)
|
||||
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
if (fe->ops.tuner_ops.sleep) {
|
||||
fe->ops.tuner_ops.sleep(fe);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
if (fe->ops.sleep)
|
||||
fe->ops.sleep(fe);
|
||||
}
|
||||
|
||||
fepriv->thread_pid = 0;
|
||||
|
@ -724,7 +736,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
switch (cmd) {
|
||||
case FE_GET_INFO: {
|
||||
struct dvb_frontend_info* info = parg;
|
||||
memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
|
||||
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
|
||||
|
||||
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
|
||||
* do it, it is done for it. */
|
||||
|
@ -744,58 +756,58 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
}
|
||||
|
||||
if (fe->ops->read_status)
|
||||
err = fe->ops->read_status(fe, status);
|
||||
if (fe->ops.read_status)
|
||||
err = fe->ops.read_status(fe, status);
|
||||
break;
|
||||
}
|
||||
case FE_READ_BER:
|
||||
if (fe->ops->read_ber)
|
||||
err = fe->ops->read_ber(fe, (__u32*) parg);
|
||||
if (fe->ops.read_ber)
|
||||
err = fe->ops.read_ber(fe, (__u32*) parg);
|
||||
break;
|
||||
|
||||
case FE_READ_SIGNAL_STRENGTH:
|
||||
if (fe->ops->read_signal_strength)
|
||||
err = fe->ops->read_signal_strength(fe, (__u16*) parg);
|
||||
if (fe->ops.read_signal_strength)
|
||||
err = fe->ops.read_signal_strength(fe, (__u16*) parg);
|
||||
break;
|
||||
|
||||
case FE_READ_SNR:
|
||||
if (fe->ops->read_snr)
|
||||
err = fe->ops->read_snr(fe, (__u16*) parg);
|
||||
if (fe->ops.read_snr)
|
||||
err = fe->ops.read_snr(fe, (__u16*) parg);
|
||||
break;
|
||||
|
||||
case FE_READ_UNCORRECTED_BLOCKS:
|
||||
if (fe->ops->read_ucblocks)
|
||||
err = fe->ops->read_ucblocks(fe, (__u32*) parg);
|
||||
if (fe->ops.read_ucblocks)
|
||||
err = fe->ops.read_ucblocks(fe, (__u32*) parg);
|
||||
break;
|
||||
|
||||
|
||||
case FE_DISEQC_RESET_OVERLOAD:
|
||||
if (fe->ops->diseqc_reset_overload) {
|
||||
err = fe->ops->diseqc_reset_overload(fe);
|
||||
if (fe->ops.diseqc_reset_overload) {
|
||||
err = fe->ops.diseqc_reset_overload(fe);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case FE_DISEQC_SEND_MASTER_CMD:
|
||||
if (fe->ops->diseqc_send_master_cmd) {
|
||||
err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
|
||||
if (fe->ops.diseqc_send_master_cmd) {
|
||||
err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case FE_DISEQC_SEND_BURST:
|
||||
if (fe->ops->diseqc_send_burst) {
|
||||
err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
|
||||
if (fe->ops.diseqc_send_burst) {
|
||||
err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case FE_SET_TONE:
|
||||
if (fe->ops->set_tone) {
|
||||
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
|
||||
if (fe->ops.set_tone) {
|
||||
err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
|
||||
fepriv->tone = (fe_sec_tone_mode_t) parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
|
@ -803,8 +815,8 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
|
||||
case FE_SET_VOLTAGE:
|
||||
if (fe->ops->set_voltage) {
|
||||
err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
|
||||
if (fe->ops.set_voltage) {
|
||||
err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
|
||||
fepriv->voltage = (fe_sec_voltage_t) parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
|
@ -812,11 +824,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
|
||||
case FE_DISHNETWORK_SEND_LEGACY_CMD:
|
||||
if (fe->ops->dishnetwork_send_legacy_command) {
|
||||
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
|
||||
if (fe->ops.dishnetwork_send_legacy_command) {
|
||||
err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
} else if (fe->ops->set_voltage) {
|
||||
} else if (fe->ops.set_voltage) {
|
||||
/*
|
||||
* NOTE: This is a fallback condition. Some frontends
|
||||
* (stv0299 for instance) take longer than 8msec to
|
||||
|
@ -846,7 +858,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
/* before sending a command, initialize by sending
|
||||
* a 32ms 18V to the switch
|
||||
*/
|
||||
fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
|
||||
fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
|
||||
dvb_frontend_sleep_until(&nexttime, 32000);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
|
@ -854,7 +866,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
do_gettimeofday(&tv[i + 1]);
|
||||
if ((cmd & 0x01) != last) {
|
||||
/* set voltage to (last ? 13V : 18V) */
|
||||
fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
|
||||
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
|
||||
last = (last) ? 0 : 1;
|
||||
}
|
||||
cmd = cmd >> 1;
|
||||
|
@ -874,13 +886,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
|
||||
case FE_DISEQC_RECV_SLAVE_REPLY:
|
||||
if (fe->ops->diseqc_recv_slave_reply)
|
||||
err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
|
||||
if (fe->ops.diseqc_recv_slave_reply)
|
||||
err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
|
||||
break;
|
||||
|
||||
case FE_ENABLE_HIGH_LNB_VOLTAGE:
|
||||
if (fe->ops->enable_high_lnb_voltage)
|
||||
err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
|
||||
if (fe->ops.enable_high_lnb_voltage)
|
||||
err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
|
||||
break;
|
||||
|
||||
case FE_SET_FRONTEND: {
|
||||
|
@ -898,7 +910,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
fepriv->parameters.inversion = INVERSION_AUTO;
|
||||
fetunesettings.parameters.inversion = INVERSION_AUTO;
|
||||
}
|
||||
if (fe->ops->info.type == FE_OFDM) {
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* without hierachical coding code_rate_LP is irrelevant,
|
||||
* so we tolerate the otherwise invalid FEC_NONE setting */
|
||||
if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
|
||||
|
@ -907,13 +919,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
}
|
||||
|
||||
/* get frontend-specific tuning settings */
|
||||
if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
|
||||
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
|
||||
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
|
||||
fepriv->max_drift = fetunesettings.max_drift;
|
||||
fepriv->step_size = fetunesettings.step_size;
|
||||
} else {
|
||||
/* default values */
|
||||
switch(fe->ops->info.type) {
|
||||
switch(fe->ops.info.type) {
|
||||
case FE_QPSK:
|
||||
fepriv->min_delay = HZ/20;
|
||||
fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
|
||||
|
@ -928,11 +940,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
|
||||
case FE_OFDM:
|
||||
fepriv->min_delay = HZ/20;
|
||||
fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
|
||||
fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
|
||||
fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
|
||||
fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
printk("dvb-core: FE_ATSC not handled yet.\n");
|
||||
fepriv->min_delay = HZ/20;
|
||||
fepriv->step_size = 0;
|
||||
fepriv->max_drift = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -952,9 +966,9 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
|
||||
case FE_GET_FRONTEND:
|
||||
if (fe->ops->get_frontend) {
|
||||
if (fe->ops.get_frontend) {
|
||||
memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
|
||||
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
|
||||
err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1067,7 +1081,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||
|
||||
printk ("DVB: registering frontend %i (%s)...\n",
|
||||
fe->dvb->num,
|
||||
fe->ops->info.name);
|
||||
fe->ops.info.name);
|
||||
|
||||
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
|
||||
fe, DVB_DEVICE_FRONTEND);
|
||||
|
@ -1085,10 +1099,15 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
|
|||
mutex_lock(&frontend_mutex);
|
||||
dvb_unregister_device (fepriv->dvbdev);
|
||||
dvb_frontend_stop (fe);
|
||||
if (fe->ops->release)
|
||||
fe->ops->release(fe);
|
||||
if (fe->ops.tuner_ops.release) {
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
else
|
||||
printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
|
||||
printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
|
||||
/* fe is invalid now */
|
||||
kfree(fepriv);
|
||||
mutex_unlock(&frontend_mutex);
|
||||
|
|
|
@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings {
|
|||
|
||||
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_info info;
|
||||
|
@ -64,6 +102,8 @@ struct dvb_frontend_ops {
|
|||
unsigned int mode_flags,
|
||||
int *delay,
|
||||
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 */
|
||||
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
|
@ -86,6 +126,8 @@ struct dvb_frontend_ops {
|
|||
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
|
||||
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
|
||||
|
||||
struct dvb_tuner_ops tuner_ops;
|
||||
};
|
||||
|
||||
#define MAX_EVENT 8
|
||||
|
@ -100,9 +142,10 @@ struct dvb_fe_events {
|
|||
};
|
||||
|
||||
struct dvb_frontend {
|
||||
struct dvb_frontend_ops* ops;
|
||||
struct dvb_frontend_ops ops;
|
||||
struct dvb_adapter *dvb;
|
||||
void* demodulator_priv;
|
||||
void* tuner_priv;
|
||||
void* frontend_priv;
|
||||
void* misc_priv;
|
||||
};
|
||||
|
|
145
drivers/media/dvb/dvb-core/dvb_math.c
Normal file
145
drivers/media/dvb/dvb-core/dvb_math.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* dvb-math provides some complex fixed-point math
|
||||
* operations shared between the dvb related stuff
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/bug.h>
|
||||
#include "dvb_math.h"
|
||||
|
||||
static const unsigned short logtable[256] = {
|
||||
0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
|
||||
0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
|
||||
0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
|
||||
0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
|
||||
0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
|
||||
0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
|
||||
0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
|
||||
0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
|
||||
0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
|
||||
0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
|
||||
0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
|
||||
0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
|
||||
0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
|
||||
0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
|
||||
0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
|
||||
0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
|
||||
0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
|
||||
0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
|
||||
0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
|
||||
0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
|
||||
0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
|
||||
0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
|
||||
0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
|
||||
0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
|
||||
0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
|
||||
0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
|
||||
0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
|
||||
0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
|
||||
0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
|
||||
0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
|
||||
0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
|
||||
0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
|
||||
};
|
||||
|
||||
unsigned int intlog2(u32 value)
|
||||
{
|
||||
/**
|
||||
* returns: log2(value) * 2^24
|
||||
* wrong result if value = 0 (log2(0) is undefined)
|
||||
*/
|
||||
unsigned int msb;
|
||||
unsigned int logentry;
|
||||
unsigned int significand;
|
||||
unsigned int interpolation;
|
||||
|
||||
if (unlikely(value == 0)) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* first detect the msb (count begins at 0) */
|
||||
msb = fls(value) - 1;
|
||||
|
||||
/**
|
||||
* now we use a logtable after the following method:
|
||||
*
|
||||
* log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
|
||||
* where x = msb and therefore 1 <= y < 2
|
||||
* first y is determined by shifting the value left
|
||||
* so that msb is bit 31
|
||||
* 0x00231f56 -> 0x8C7D5800
|
||||
* the result is y * 2^31 -> "significand"
|
||||
* then the highest 9 bits are used for a table lookup
|
||||
* the highest bit is discarded because it's always set
|
||||
* the highest nine bits in our example are 100011000
|
||||
* so we would use the entry 0x18
|
||||
*/
|
||||
significand = value << (31 - msb);
|
||||
logentry = (significand >> 23) & 0xff;
|
||||
|
||||
/**
|
||||
* last step we do is interpolation because of the
|
||||
* limitations of the log table the error is that part of
|
||||
* the significand which isn't used for lookup then we
|
||||
* compute the ratio between the error and the next table entry
|
||||
* and interpolate it between the log table entry used and the
|
||||
* next one the biggest error possible is 0x7fffff
|
||||
* (in our example it's 0x7D5800)
|
||||
* needed value for next table entry is 0x800000
|
||||
* so the interpolation is
|
||||
* (error / 0x800000) * (logtable_next - logtable_current)
|
||||
* in the implementation the division is moved to the end for
|
||||
* better accuracy there is also an overflow correction if
|
||||
* logtable_next is 256
|
||||
*/
|
||||
interpolation = ((significand & 0x7fffff) *
|
||||
((logtable[(logentry + 1) & 0xff] -
|
||||
logtable[logentry]) & 0xffff)) >> 15;
|
||||
|
||||
/* now we return the result */
|
||||
return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
|
||||
}
|
||||
EXPORT_SYMBOL(intlog2);
|
||||
|
||||
unsigned int intlog10(u32 value)
|
||||
{
|
||||
/**
|
||||
* returns: log10(value) * 2^24
|
||||
* wrong result if value = 0 (log10(0) is undefined)
|
||||
*/
|
||||
u64 log;
|
||||
|
||||
if (unlikely(value == 0)) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log = intlog2(value);
|
||||
|
||||
/**
|
||||
* we use the following method:
|
||||
* log10(x) = log2(x) * log10(2)
|
||||
*/
|
||||
|
||||
return (log * 646456993) >> 31;
|
||||
}
|
||||
EXPORT_SYMBOL(intlog10);
|
58
drivers/media/dvb/dvb-core/dvb_math.h
Normal file
58
drivers/media/dvb/dvb-core/dvb_math.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* dvb-math provides some complex fixed-point math
|
||||
* operations shared between the dvb related stuff
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __DVB_MATH_H
|
||||
#define __DVB_MATH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* computes log2 of a value; the result is shifted left by 24 bits
|
||||
*
|
||||
* to use rational values you can use the following method:
|
||||
* intlog2(value) = intlog2(value * 2^x) - x * 2^24
|
||||
*
|
||||
* example: intlog2(8) will give 3 << 24 = 3 * 2^24
|
||||
* example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
|
||||
* example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
|
||||
*
|
||||
* @param value The value (must be != 0)
|
||||
* @return log2(value) * 2^24
|
||||
*/
|
||||
extern unsigned int intlog2(u32 value);
|
||||
|
||||
/**
|
||||
* computes log10 of a value; the result is shifted left by 24 bits
|
||||
*
|
||||
* to use rational values you can use the following method:
|
||||
* intlog10(value) = intlog10(value * 10^x) - x * 2^24
|
||||
*
|
||||
* example: intlog10(1000) will give 3 << 24 = 3 * 2^24
|
||||
* due to the implementation intlog10(1000) might be not exactly 3 * 2^24
|
||||
*
|
||||
* look at intlog2 for similar examples
|
||||
*
|
||||
* @param value The value (must be != 0)
|
||||
* @return log10(value) * 2^24
|
||||
*/
|
||||
extern unsigned int intlog10(u32 value);
|
||||
|
||||
#endif
|
|
@ -12,7 +12,7 @@
|
|||
* Hilmar Linder <hlinder@cosy.sbg.ac.at>
|
||||
* and Wolfram Stering <wstering@cosy.sbg.ac.at>
|
||||
*
|
||||
* ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
|
||||
* ULE Decaps according to RFC 4326.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -42,6 +42,9 @@
|
|||
* Bugfixes and robustness improvements.
|
||||
* Filtering on dest MAC addresses, if present (D-Bit = 0)
|
||||
* ULE_DEBUG compile-time option.
|
||||
* Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by
|
||||
* Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
|
||||
* Paris Lodron University of Salzburg.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -49,9 +52,6 @@
|
|||
*
|
||||
* Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
|
||||
*
|
||||
* TS_FEED callback is called once for every single TS cell although it is
|
||||
* registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -89,6 +89,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
|||
|
||||
#ifdef ULE_DEBUG
|
||||
|
||||
#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
|
||||
#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
|
||||
|
||||
#define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
|
||||
|
||||
static void hexdump( const unsigned char *buf, unsigned short len )
|
||||
|
@ -214,6 +217,8 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
|
|||
#define ULE_TEST 0
|
||||
#define ULE_BRIDGED 1
|
||||
|
||||
#define ULE_OPTEXTHDR_PADDING 0
|
||||
|
||||
static int ule_test_sndu( struct dvb_net_priv *p )
|
||||
{
|
||||
return -1;
|
||||
|
@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net_priv *p )
|
|||
|
||||
static int ule_bridged_sndu( struct dvb_net_priv *p )
|
||||
{
|
||||
/* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
|
||||
* This has to be the last extension header, otherwise it won't work.
|
||||
* Blame the authors!
|
||||
struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
|
||||
if(ntohs(hdr->h_proto) < 1536) {
|
||||
int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
|
||||
/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
|
||||
if(framelen != ntohs(hdr->h_proto)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Note:
|
||||
* From RFC4326:
|
||||
* "A bridged SNDU is a Mandatory Extension Header of Type 1.
|
||||
* It must be the final (or only) extension header specified in the header chain of a SNDU."
|
||||
* The 'ule_bridged' flag will cause the extension header processing loop to terminate.
|
||||
*/
|
||||
p->ule_bridged = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ule_exthdr_padding(struct dvb_net_priv *p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Handle ULE extension headers.
|
||||
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
|
||||
|
@ -242,7 +261,8 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
|
|||
{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, };
|
||||
|
||||
/* Table of optional extension header handlers. The header type is the index. */
|
||||
static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, };
|
||||
static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
|
||||
{ [0] = ule_exthdr_padding, [1] = NULL, };
|
||||
|
||||
int ext_len = 0;
|
||||
unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
|
||||
|
@ -253,25 +273,31 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
|
|||
/* Mandatory extension header */
|
||||
if (ule_mandatory_ext_handlers[htype]) {
|
||||
ext_len = ule_mandatory_ext_handlers[htype]( p );
|
||||
p->ule_next_hdr += ext_len;
|
||||
if (! p->ule_bridged) {
|
||||
p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
|
||||
p->ule_next_hdr += 2;
|
||||
} else {
|
||||
p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) );
|
||||
/* This assures the extension handling loop will terminate. */
|
||||
if(ext_len >= 0) {
|
||||
p->ule_next_hdr += ext_len;
|
||||
if (!p->ule_bridged) {
|
||||
p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
|
||||
p->ule_next_hdr += 2;
|
||||
} else {
|
||||
p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
|
||||
/* This assures the extension handling loop will terminate. */
|
||||
}
|
||||
}
|
||||
// else: extension handler failed or SNDU should be discarded
|
||||
} else
|
||||
ext_len = -1; /* SNDU has to be discarded. */
|
||||
} else {
|
||||
/* Optional extension header. Calculate the length. */
|
||||
ext_len = hlen << 2;
|
||||
ext_len = hlen << 1;
|
||||
/* Process the optional extension header according to its type. */
|
||||
if (ule_optional_ext_handlers[htype])
|
||||
(void)ule_optional_ext_handlers[htype]( p );
|
||||
p->ule_next_hdr += ext_len;
|
||||
p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
|
||||
p->ule_next_hdr += 2;
|
||||
p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
|
||||
/*
|
||||
* note: the length of the next header type is included in the
|
||||
* length of THIS optional extension header
|
||||
*/
|
||||
}
|
||||
|
||||
return ext_len;
|
||||
|
@ -284,8 +310,14 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
|
|||
p->ule_next_hdr = p->ule_skb->data;
|
||||
do {
|
||||
l = handle_one_ule_extension( p );
|
||||
if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */
|
||||
if (l < 0)
|
||||
return l; /* Stop extension header processing and discard SNDU. */
|
||||
total_ext_len += l;
|
||||
#ifdef ULE_DEBUG
|
||||
dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
|
||||
"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
|
||||
(int) p->ule_sndu_type, l, total_ext_len);
|
||||
#endif
|
||||
|
||||
} while (p->ule_sndu_type < 1536);
|
||||
|
||||
|
@ -355,8 +387,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
if (priv->ule_skb) {
|
||||
dev_kfree_skb( priv->ule_skb );
|
||||
/* Prepare for next SNDU. */
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
|
||||
priv->stats.rx_errors++;
|
||||
priv->stats.rx_frame_errors++;
|
||||
}
|
||||
reset_ule(priv);
|
||||
priv->need_pusi = 1;
|
||||
|
@ -396,27 +428,25 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
}
|
||||
}
|
||||
|
||||
/* Check continuity counter. */
|
||||
if (new_ts) {
|
||||
/* Check continuity counter. */
|
||||
if ((ts[3] & 0x0F) == priv->tscc)
|
||||
priv->tscc = (priv->tscc + 1) & 0x0F;
|
||||
else {
|
||||
/* TS discontinuity handling: */
|
||||
printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
|
||||
"exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
|
||||
"expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
|
||||
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
|
||||
if (priv->ule_skb) {
|
||||
dev_kfree_skb( priv->ule_skb );
|
||||
/* Prepare for next SNDU. */
|
||||
// reset_ule(priv); moved to below.
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
|
||||
priv->stats.rx_errors++;
|
||||
priv->stats.rx_frame_errors++;
|
||||
}
|
||||
reset_ule(priv);
|
||||
/* skip to next PUSI. */
|
||||
priv->need_pusi = 1;
|
||||
ts += TS_SZ;
|
||||
priv->ts_count++;
|
||||
continue;
|
||||
}
|
||||
/* If we still have an incomplete payload, but PUSI is
|
||||
|
@ -425,7 +455,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
* cells (continuity counter wrap). */
|
||||
if (ts[1] & TS_PUSI) {
|
||||
if (! priv->need_pusi) {
|
||||
if (*from_where > 181) {
|
||||
if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
|
||||
/* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */
|
||||
printk(KERN_WARNING "%lu: Invalid pointer "
|
||||
"field: %u.\n", priv->ts_count, *from_where);
|
||||
|
@ -438,8 +468,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
}
|
||||
reset_ule(priv);
|
||||
priv->need_pusi = 1;
|
||||
ts += TS_SZ;
|
||||
priv->ts_count++;
|
||||
continue;
|
||||
}
|
||||
/* Skip pointer field (we're processing a
|
||||
|
@ -452,8 +480,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
if (priv->ule_sndu_remain > 183) {
|
||||
/* Current SNDU lacks more data than there could be available in the
|
||||
* current TS cell. */
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
|
||||
priv->stats.rx_errors++;
|
||||
priv->stats.rx_length_errors++;
|
||||
printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
|
||||
"got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n",
|
||||
priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
|
||||
|
@ -492,9 +520,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
} else
|
||||
priv->ule_dbit = 0;
|
||||
|
||||
if (priv->ule_sndu_len > 32763) {
|
||||
if (priv->ule_sndu_len < 5) {
|
||||
printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
|
||||
"Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
|
||||
priv->stats.rx_errors++;
|
||||
priv->stats.rx_length_errors++;
|
||||
priv->ule_sndu_len = 0;
|
||||
priv->need_pusi = 1;
|
||||
new_ts = 1;
|
||||
|
@ -608,58 +638,103 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
ule_dump = 1;
|
||||
#endif
|
||||
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
|
||||
priv->stats.rx_errors++;
|
||||
priv->stats.rx_crc_errors++;
|
||||
dev_kfree_skb(priv->ule_skb);
|
||||
} else {
|
||||
/* CRC32 verified OK. */
|
||||
/* Handle ULE Extension Headers. */
|
||||
if (priv->ule_sndu_type < 1536) {
|
||||
/* There is an extension header. Handle it accordingly. */
|
||||
int l = handle_ule_extensions( priv );
|
||||
if (l < 0) {
|
||||
/* Mandatory extension header unknown or TEST SNDU. Drop it. */
|
||||
// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
|
||||
dev_kfree_skb( priv->ule_skb );
|
||||
goto sndu_done;
|
||||
}
|
||||
skb_pull( priv->ule_skb, l );
|
||||
}
|
||||
u8 dest_addr[ETH_ALEN];
|
||||
static const u8 bc_addr[ETH_ALEN] =
|
||||
{ [ 0 ... ETH_ALEN-1] = 0xff };
|
||||
|
||||
/* CRC32 was OK. Remove it from skb. */
|
||||
priv->ule_skb->tail -= 4;
|
||||
priv->ule_skb->len -= 4;
|
||||
|
||||
/* Filter on receiver's destination MAC address, if present. */
|
||||
if (!priv->ule_dbit) {
|
||||
/* The destination MAC address is the next data in the skb. */
|
||||
if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {
|
||||
/* MAC addresses don't match. Drop SNDU. */
|
||||
// printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );
|
||||
dev_kfree_skb( priv->ule_skb );
|
||||
/*
|
||||
* The destination MAC address is the
|
||||
* next data in the skb. It comes
|
||||
* before any extension headers.
|
||||
*
|
||||
* Check if the payload of this SNDU
|
||||
* should be passed up the stack.
|
||||
*/
|
||||
register int drop = 0;
|
||||
if (priv->rx_mode != RX_MODE_PROMISC) {
|
||||
if (priv->ule_skb->data[0] & 0x01) {
|
||||
/* multicast or broadcast */
|
||||
if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
|
||||
/* multicast */
|
||||
if (priv->rx_mode == RX_MODE_MULTI) {
|
||||
int i;
|
||||
for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
|
||||
;
|
||||
if (i == priv->multi_num)
|
||||
drop = 1;
|
||||
} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
|
||||
drop = 1; /* no broadcast; */
|
||||
/* else: all multicast mode: accept all multicast packets */
|
||||
}
|
||||
/* else: broadcast */
|
||||
}
|
||||
else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
|
||||
drop = 1;
|
||||
/* else: destination address matches the MAC address of our receiver device */
|
||||
}
|
||||
/* else: promiscious mode; pass everything up the stack */
|
||||
|
||||
if (drop) {
|
||||
#ifdef ULE_DEBUG
|
||||
dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
|
||||
MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
|
||||
#endif
|
||||
dev_kfree_skb(priv->ule_skb);
|
||||
goto sndu_done;
|
||||
}
|
||||
if (! priv->ule_bridged) {
|
||||
skb_push( priv->ule_skb, ETH_ALEN + 2 );
|
||||
ethh = (struct ethhdr *)priv->ule_skb->data;
|
||||
memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );
|
||||
memset( ethh->h_source, 0, ETH_ALEN );
|
||||
ethh->h_proto = htons( priv->ule_sndu_type );
|
||||
} else {
|
||||
/* Skip the Receiver destination MAC address. */
|
||||
skb_pull( priv->ule_skb, ETH_ALEN );
|
||||
}
|
||||
} else {
|
||||
if (! priv->ule_bridged) {
|
||||
skb_push( priv->ule_skb, ETH_HLEN );
|
||||
ethh = (struct ethhdr *)priv->ule_skb->data;
|
||||
memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );
|
||||
memset( ethh->h_source, 0, ETH_ALEN );
|
||||
ethh->h_proto = htons( priv->ule_sndu_type );
|
||||
} else {
|
||||
/* skb is in correct state; nothing to do. */
|
||||
else
|
||||
{
|
||||
memcpy(dest_addr, priv->ule_skb->data, ETH_ALEN);
|
||||
skb_pull(priv->ule_skb, ETH_ALEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle ULE Extension Headers. */
|
||||
if (priv->ule_sndu_type < 1536) {
|
||||
/* There is an extension header. Handle it accordingly. */
|
||||
int l = handle_ule_extensions(priv);
|
||||
if (l < 0) {
|
||||
/* Mandatory extension header unknown or TEST SNDU. Drop it. */
|
||||
// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
|
||||
dev_kfree_skb(priv->ule_skb);
|
||||
goto sndu_done;
|
||||
}
|
||||
skb_pull(priv->ule_skb, l);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct/assure correct ethernet header.
|
||||
* Note: in bridged mode (priv->ule_bridged !=
|
||||
* 0) we already have the (original) ethernet
|
||||
* header at the start of the payload (after
|
||||
* optional dest. address and any extension
|
||||
* headers).
|
||||
*/
|
||||
|
||||
if (!priv->ule_bridged) {
|
||||
skb_push(priv->ule_skb, ETH_HLEN);
|
||||
ethh = (struct ethhdr *)priv->ule_skb->data;
|
||||
if (!priv->ule_dbit) {
|
||||
/* dest_addr buffer is only valid if priv->ule_dbit == 0 */
|
||||
memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
|
||||
memset(ethh->h_source, 0, ETH_ALEN);
|
||||
}
|
||||
else /* zeroize source and dest */
|
||||
memset( ethh, 0, ETH_ALEN*2 );
|
||||
|
||||
ethh->h_proto = htons(priv->ule_sndu_type);
|
||||
}
|
||||
/* else: skb is in correct state; nothing to do. */
|
||||
priv->ule_bridged = 0;
|
||||
|
||||
/* Stuff into kernel's protocol stack. */
|
||||
|
@ -668,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
* receive the packet anyhow. */
|
||||
/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
|
||||
priv->ule_skb->pkt_type = PACKET_HOST; */
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;
|
||||
((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;
|
||||
priv->stats.rx_packets++;
|
||||
priv->stats.rx_bytes += priv->ule_skb->len;
|
||||
netif_rx(priv->ule_skb);
|
||||
}
|
||||
sndu_done:
|
||||
|
@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
|||
dprintk("%s: start filtering\n", __FUNCTION__);
|
||||
priv->secfeed->start_filtering(priv->secfeed);
|
||||
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
||||
struct timespec timeout = { 0, 30000000 }; // 30 msec
|
||||
struct timespec timeout = { 0, 10000000 }; // 10 msec
|
||||
|
||||
/* we have payloads encapsulated in TS */
|
||||
dprintk("%s: alloc tsfeed\n", __FUNCTION__);
|
||||
|
@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net_device *dev)
|
|||
|
||||
/* Set netdevice pointer for ts decaps callback. */
|
||||
priv->tsfeed->priv = (void *)dev;
|
||||
ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
|
||||
TS_PACKET, DMX_TS_PES_OTHER,
|
||||
ret = priv->tsfeed->set(priv->tsfeed,
|
||||
priv->pid, /* pid */
|
||||
TS_PACKET, /* type */
|
||||
DMX_TS_PES_OTHER, /* pes type */
|
||||
32768, /* circular buffer size */
|
||||
timeout);
|
||||
timeout /* timeout */
|
||||
);
|
||||
|
||||
if (ret < 0) {
|
||||
printk("%s: could not set ts feed\n", dev->name);
|
||||
|
|
|
@ -236,7 +236,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
|
||||
|
||||
class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
|
||||
NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
|
||||
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
|
||||
|
@ -285,7 +285,7 @@ skip:
|
|||
}
|
||||
|
||||
|
||||
int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
|
||||
int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
|
||||
{
|
||||
int num;
|
||||
|
||||
|
@ -306,6 +306,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
|
|||
adap->num = num;
|
||||
adap->name = name;
|
||||
adap->module = module;
|
||||
adap->device = device;
|
||||
|
||||
list_add_tail (&adap->list_head, &dvb_adapter_list);
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ struct dvb_adapter {
|
|||
u8 proposed_mac [6];
|
||||
void* priv;
|
||||
|
||||
struct device *device;
|
||||
|
||||
struct module *module;
|
||||
};
|
||||
|
||||
|
@ -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_register_device (struct dvb_adapter *adap,
|
||||
|
|
|
@ -88,6 +88,7 @@ config DVB_USB_CXUSB
|
|||
select DVB_CX22702
|
||||
select DVB_LGDT330X
|
||||
select DVB_MT352
|
||||
select DVB_ZL10353
|
||||
help
|
||||
Say Y here to support the Conexant USB2.0 hybrid reference design.
|
||||
Currently, only DVB and ATSC modes are supported, analog mode
|
||||
|
@ -130,6 +131,15 @@ config DVB_USB_VP702X
|
|||
|
||||
DVB-S USB2.0 receivers.
|
||||
|
||||
config DVB_USB_GP8PSK
|
||||
tristate "GENPIX 8PSK->USB module support"
|
||||
depends on DVB_USB
|
||||
help
|
||||
Say Y here to support the
|
||||
GENPIX 8psk module
|
||||
|
||||
DVB-S USB2.0 receivers.
|
||||
|
||||
config DVB_USB_NOVA_T_USB2
|
||||
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
|
||||
depends on DVB_USB
|
||||
|
|
|
@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
|
|||
dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
|
||||
obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
|
||||
|
||||
dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
|
||||
obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
|
||||
|
||||
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
|
||||
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
|
||||
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
#include "cx22702.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "mt352.h"
|
||||
#include "mt352_priv.h"
|
||||
#include "zl10353.h"
|
||||
|
||||
/* debug */
|
||||
int dvb_usb_cxusb_debug;
|
||||
|
@ -322,32 +324,37 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dvb_usb_device *d = fe->dvb->priv;
|
||||
return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
|
||||
}
|
||||
|
||||
static struct cx22702_config cxusb_cx22702_config = {
|
||||
.demod_address = 0x63,
|
||||
|
||||
.output_mode = CX22702_PARALLEL_OUTPUT,
|
||||
|
||||
.pll_init = dvb_usb_pll_init_i2c,
|
||||
.pll_set = dvb_usb_pll_set_i2c,
|
||||
};
|
||||
|
||||
static struct lgdt330x_config cxusb_lgdt3303_config = {
|
||||
.demod_address = 0x0e,
|
||||
.demod_chip = LGDT3303,
|
||||
.pll_set = dvb_usb_pll_set_i2c,
|
||||
};
|
||||
|
||||
static struct mt352_config cxusb_dee1601_config = {
|
||||
.demod_address = 0x0f,
|
||||
.demod_init = cxusb_dee1601_demod_init,
|
||||
.pll_set = dvb_usb_pll_set,
|
||||
};
|
||||
|
||||
struct mt352_config cxusb_mt352_config = {
|
||||
static struct zl10353_config cxusb_zl10353_dee1601_config = {
|
||||
.demod_address = 0x0f,
|
||||
};
|
||||
|
||||
static struct mt352_config cxusb_mt352_config = {
|
||||
/* used in both lgz201 and th7579 */
|
||||
.demod_address = 0x0f,
|
||||
.demod_init = cxusb_mt352_demod_init,
|
||||
.pll_set = dvb_usb_pll_set,
|
||||
};
|
||||
|
||||
/* Callbacks for DVB USB */
|
||||
|
@ -357,17 +364,10 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
|
|||
d->pll_addr = 0x61;
|
||||
memcpy(d->pll_init, bpll, 4);
|
||||
d->pll_desc = &dvb_pll_fmd1216me;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
|
||||
/* bpll[2] : unset bit 3, set bits 4&5
|
||||
bpll[3] : 0x50 - digital, 0x20 - analog */
|
||||
d->pll_addr = 0x61;
|
||||
memcpy(d->pll_init, bpll, 4);
|
||||
d->pll_desc = &dvb_pll_tdvs_tua6034;
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -375,6 +375,7 @@ static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
|
|||
{
|
||||
d->pll_addr = 0x61;
|
||||
d->pll_desc = &dvb_pll_thomson_dtt7579;
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -382,6 +383,7 @@ static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
|
|||
{
|
||||
d->pll_addr = 0x61;
|
||||
d->pll_desc = &dvb_pll_lg_z201;
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -389,6 +391,13 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
|
|||
{
|
||||
d->pll_addr = 0x60;
|
||||
d->pll_desc = &dvb_pll_thomson_dtt7579;
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -439,7 +448,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
|
||||
if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
|
||||
((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -555,7 +565,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
|
|||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
.frontend_attach = cxusb_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_lgh064f_tuner_attach,
|
||||
.tuner_attach = cxusb_lgdt3303_tuner_attach,
|
||||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
|
|
|
@ -173,11 +173,10 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
|
|||
struct dib3000_config demod_cfg;
|
||||
struct dibusb_state *st = d->priv;
|
||||
|
||||
demod_cfg.pll_set = dvb_usb_pll_set_i2c;
|
||||
demod_cfg.pll_init = dvb_usb_pll_init_i2c;
|
||||
|
||||
for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
|
||||
if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -190,6 +189,10 @@ int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
|
|||
{
|
||||
d->pll_addr = 0x60;
|
||||
d->pll_desc = &dvb_pll_env57h1xd5;
|
||||
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
||||
|
|
|
@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
|
|||
struct dibusb_state *st = d->priv;
|
||||
|
||||
demod_cfg.demod_address = 0x8;
|
||||
demod_cfg.pll_set = dvb_usb_pll_set_i2c;
|
||||
demod_cfg.pll_init = dvb_usb_pll_init_i2c;
|
||||
|
||||
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
|
||||
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||
|
||||
|
|
|
@ -112,27 +112,30 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
|
|||
|
||||
static struct mt352_config digitv_mt352_config = {
|
||||
.demod_init = digitv_mt352_demod_init,
|
||||
.pll_set = dvb_usb_pll_set,
|
||||
};
|
||||
|
||||
static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||
static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dvb_usb_device *d = fe->dvb->priv;
|
||||
u8 b[5];
|
||||
dvb_usb_pll_set(fe,fep,b);
|
||||
dvb_usb_tuner_calc_regs(fe,fep,b, 5);
|
||||
return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
|
||||
}
|
||||
|
||||
static struct nxt6000_config digitv_nxt6000_config = {
|
||||
.clock_inversion = 1,
|
||||
.pll_set = digitv_nxt6000_pll_set,
|
||||
};
|
||||
|
||||
static int digitv_frontend_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
|
||||
(d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
|
||||
if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
|
||||
d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
|
||||
return 0;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ struct dtt200u_fe_state {
|
|||
|
||||
struct dvb_frontend_parameters fep;
|
||||
struct dvb_frontend frontend;
|
||||
struct dvb_frontend_ops ops;
|
||||
};
|
||||
|
||||
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
|
||||
|
@ -163,16 +162,13 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
|
|||
deb_info("attaching frontend dtt200u\n");
|
||||
|
||||
state->d = d;
|
||||
memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
|
||||
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
goto success;
|
||||
return &state->frontend;
|
||||
error:
|
||||
return NULL;
|
||||
success:
|
||||
return &state->frontend;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops dtt200u_fe_ops = {
|
||||
|
|
|
@ -82,7 +82,7 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
|
|||
int ret;
|
||||
|
||||
if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
|
||||
d->owner)) < 0) {
|
||||
d->owner, &d->udev->dev)) < 0) {
|
||||
deb_info("dvb_register_adapter failed: error %d", ret);
|
||||
goto err;
|
||||
}
|
||||
|
@ -121,16 +121,15 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
|
|||
|
||||
dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
|
||||
|
||||
goto success;
|
||||
d->state |= DVB_USB_STATE_DVB;
|
||||
return 0;
|
||||
|
||||
err_dmx_dev:
|
||||
dvb_dmx_release(&d->demux);
|
||||
err_dmx:
|
||||
dvb_unregister_adapter(&d->dvb_adap);
|
||||
err:
|
||||
return ret;
|
||||
success:
|
||||
d->state |= DVB_USB_STATE_DVB;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_dvb_exit(struct dvb_usb_device *d)
|
||||
|
@ -184,13 +183,13 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
|
|||
|
||||
/* re-assign sleep and wakeup functions */
|
||||
if (d->fe != NULL) {
|
||||
d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup;
|
||||
d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
|
||||
d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup;
|
||||
d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
|
||||
|
||||
if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
|
||||
err("Frontend registration failed.");
|
||||
if (d->fe->ops->release)
|
||||
d->fe->ops->release(d->fe);
|
||||
if (d->fe->ops.release)
|
||||
d->fe->ops.release(d->fe);
|
||||
d->fe = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ int dvb_usb_i2c_exit(struct dvb_usb_device *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
|
||||
int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_device *d = fe->dvb->priv;
|
||||
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
|
||||
|
@ -63,6 +63,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
|
|||
deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
|
||||
d->pll_init[2],d->pll_init[3]);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
|
||||
err("tuner i2c write failed for pll_init.");
|
||||
ret = -EREMOTEIO;
|
||||
|
@ -73,38 +75,42 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
|
|||
d->tuner_pass_ctrl(fe,0,d->pll_addr);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
|
||||
EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
|
||||
|
||||
int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
|
||||
int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
|
||||
{
|
||||
struct dvb_usb_device *d = fe->dvb->priv;
|
||||
|
||||
if (buf_len != 5)
|
||||
return -EINVAL;
|
||||
if (d->pll_desc == NULL)
|
||||
return 0;
|
||||
|
||||
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
|
||||
|
||||
b[0] = d->pll_addr << 1;
|
||||
b[0] = d->pll_addr;
|
||||
dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
|
||||
|
||||
deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_pll_set);
|
||||
EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
|
||||
|
||||
int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||
int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dvb_usb_device *d = fe->dvb->priv;
|
||||
int ret = 0;
|
||||
u8 b[5];
|
||||
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
|
||||
|
||||
dvb_usb_pll_set(fe,fep,b);
|
||||
dvb_usb_tuner_calc_regs(fe,fep,b,5);
|
||||
|
||||
if (d->tuner_pass_ctrl)
|
||||
d->tuner_pass_ctrl(fe,1,d->pll_addr);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
|
||||
err("tuner i2c write failed for pll_set.");
|
||||
ret = -EREMOTEIO;
|
||||
|
@ -116,4 +122,4 @@ int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
|
||||
EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define USB_VID_VISIONPLUS 0x13d3
|
||||
#define USB_VID_TWINHAN 0x1822
|
||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||
#define USB_VID_GENPIX 0x09c0
|
||||
|
||||
/* Product IDs */
|
||||
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
||||
|
@ -104,5 +105,6 @@
|
|||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
|
||||
#define USB_PID_GENPIX_8PSK_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||
#endif
|
||||
|
|
|
@ -330,9 +330,9 @@ extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
|
|||
extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
|
||||
|
||||
/* commonly used pll init and set functions */
|
||||
extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
|
||||
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
|
||||
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
|
||||
extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
|
||||
extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
|
||||
extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
|
||||
|
||||
/* commonly used firmware download types and function */
|
||||
struct hexline {
|
||||
|
|
272
drivers/media/dvb/dvb-usb/gp8psk-fe.c
Normal file
272
drivers/media/dvb/dvb-usb/gp8psk-fe.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
* This module is based off the vp7045 and vp702x modules
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#include "gp8psk.h"
|
||||
|
||||
struct gp8psk_fe_state {
|
||||
struct dvb_frontend fe;
|
||||
|
||||
struct dvb_usb_device *d;
|
||||
|
||||
u16 snr;
|
||||
|
||||
unsigned long next_snr_check;
|
||||
};
|
||||
|
||||
static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
u8 lock;
|
||||
|
||||
if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
|
||||
return -EINVAL;
|
||||
|
||||
if (lock)
|
||||
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
else
|
||||
*status = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not supported by this Frontend */
|
||||
static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
|
||||
{
|
||||
(void) fe;
|
||||
*ber = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not supported by this Frontend */
|
||||
static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||
{
|
||||
(void) fe;
|
||||
*unc = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
u8 buf[2];
|
||||
|
||||
if (time_after(jiffies,st->next_snr_check)) {
|
||||
gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
|
||||
*snr = (int)(buf[1]) << 8 | buf[0];
|
||||
/* snr is reported in dBu*256 */
|
||||
/* snr / 38.4 ~= 100% strength */
|
||||
/* snr * 17 returns 100% strength as 65535 */
|
||||
if (*snr <= 3855)
|
||||
*snr = (*snr<<4) + *snr; // snr * 17
|
||||
else
|
||||
*snr = 65535;
|
||||
st->next_snr_check = jiffies + (10*HZ)/1000;
|
||||
} else {
|
||||
*snr = st->snr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
|
||||
{
|
||||
return gp8psk_fe_read_snr(fe, strength);
|
||||
}
|
||||
|
||||
static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||
{
|
||||
tune->min_delay_ms = 800;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct gp8psk_fe_state *state = fe->demodulator_priv;
|
||||
u8 cmd[10];
|
||||
u32 freq = fep->frequency * 1000;
|
||||
|
||||
cmd[4] = freq & 0xff;
|
||||
cmd[5] = (freq >> 8) & 0xff;
|
||||
cmd[6] = (freq >> 16) & 0xff;
|
||||
cmd[7] = (freq >> 24) & 0xff;
|
||||
|
||||
switch(fe->ops.info.type) {
|
||||
case FE_QPSK:
|
||||
cmd[0] = fep->u.qpsk.symbol_rate & 0xff;
|
||||
cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff;
|
||||
cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
|
||||
cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
|
||||
cmd[8] = ADV_MOD_DVB_QPSK;
|
||||
cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
|
||||
break;
|
||||
default:
|
||||
// other modes are unsuported right now
|
||||
cmd[0] = 0;
|
||||
cmd[1] = 0;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
cmd[8] = 0;
|
||||
cmd[9] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
|
||||
|
||||
state->next_snr_check = jiffies;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
|
||||
struct dvb_diseqc_master_cmd *m)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
|
||||
deb_fe("%s\n",__FUNCTION__);
|
||||
|
||||
if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
|
||||
m->msg, m->msg_len)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
|
||||
fe_sec_mini_cmd_t burst)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
u8 cmd;
|
||||
|
||||
deb_fe("%s\n",__FUNCTION__);
|
||||
|
||||
/* These commands are certainly wrong */
|
||||
cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
|
||||
|
||||
if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
|
||||
&cmd, 0)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
{
|
||||
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||
|
||||
if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
|
||||
(tone == SEC_TONE_ON), 0, NULL, 0)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||
|
||||
if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
|
||||
voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
|
||||
{
|
||||
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||
u8 cmd = sw_cmd & 0x7f;
|
||||
|
||||
if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
|
||||
NULL, 0)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
|
||||
0, NULL, 0)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gp8psk_fe_release(struct dvb_frontend* fe)
|
||||
{
|
||||
struct gp8psk_fe_state *state = fe->demodulator_priv;
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops gp8psk_fe_ops;
|
||||
|
||||
struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
|
||||
if (s == NULL)
|
||||
goto error;
|
||||
|
||||
s->d = d;
|
||||
memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
|
||||
s->fe.demodulator_priv = s;
|
||||
|
||||
goto success;
|
||||
error:
|
||||
return NULL;
|
||||
success:
|
||||
return &s->fe;
|
||||
}
|
||||
|
||||
|
||||
static struct dvb_frontend_ops gp8psk_fe_ops = {
|
||||
.info = {
|
||||
.name = "Genpix 8psk-USB DVB-S",
|
||||
.type = FE_QPSK,
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.frequency_stepsize = 100,
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
.symbol_rate_tolerance = 500, /* ppm */
|
||||
.caps = FE_CAN_INVERSION_AUTO |
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK
|
||||
},
|
||||
|
||||
.release = gp8psk_fe_release,
|
||||
|
||||
.init = NULL,
|
||||
.sleep = NULL,
|
||||
|
||||
.set_frontend = gp8psk_fe_set_frontend,
|
||||
.get_frontend = gp8psk_fe_get_frontend,
|
||||
.get_tune_settings = gp8psk_fe_get_tune_settings,
|
||||
|
||||
.read_status = gp8psk_fe_read_status,
|
||||
.read_ber = gp8psk_fe_read_ber,
|
||||
.read_signal_strength = gp8psk_fe_read_signal_strength,
|
||||
.read_snr = gp8psk_fe_read_snr,
|
||||
.read_ucblocks = gp8psk_fe_read_unc_blocks,
|
||||
|
||||
.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
|
||||
.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
|
||||
.set_tone = gp8psk_fe_set_tone,
|
||||
.set_voltage = gp8psk_fe_set_voltage,
|
||||
.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
|
||||
};
|
256
drivers/media/dvb/dvb-usb/gp8psk.c
Normal file
256
drivers/media/dvb/dvb-usb/gp8psk.c
Normal file
|
@ -0,0 +1,256 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
* This module is based off the vp7045 and vp702x modules
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#include "gp8psk.h"
|
||||
|
||||
/* debug */
|
||||
static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
|
||||
int dvb_usb_gp8psk_debug;
|
||||
module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret = 0,try = 0;
|
||||
|
||||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
while (ret >= 0 && ret != blen && try < 3) {
|
||||
ret = usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev,0),
|
||||
req,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
value,index,b,blen,
|
||||
2000);
|
||||
deb_info("reading number %d (ret: %d)\n",try,ret);
|
||||
try++;
|
||||
}
|
||||
|
||||
if (ret < 0 || ret != blen) {
|
||||
warn("usb in operation failed.");
|
||||
ret = -EIO;
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
|
||||
debug_dump(b,blen,deb_xfer);
|
||||
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
|
||||
debug_dump(b,blen,deb_xfer);
|
||||
|
||||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
if (usb_control_msg(d->udev,
|
||||
usb_sndctrlpipe(d->udev,0),
|
||||
req,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
value,index,b,blen,
|
||||
2000) != blen) {
|
||||
warn("usb out operation failed.");
|
||||
ret = -EIO;
|
||||
} else
|
||||
ret = 0;
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
|
||||
{
|
||||
int ret;
|
||||
const struct firmware *fw = NULL;
|
||||
u8 *ptr, *buf;
|
||||
if ((ret = request_firmware(&fw, bcm4500_firmware,
|
||||
&d->udev->dev)) != 0) {
|
||||
err("did not find the bcm4500 firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
|
||||
bcm4500_firmware,ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
|
||||
if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
|
||||
goto out_rel_fw;
|
||||
|
||||
info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
|
||||
|
||||
ptr = fw->data;
|
||||
buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
|
||||
|
||||
while (ptr[0] != 0xff) {
|
||||
u16 buflen = ptr[0] + 4;
|
||||
if (ptr + buflen >= fw->data + fw->size) {
|
||||
err("failed to load bcm4500 firmware.");
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(buf, ptr, buflen);
|
||||
if (dvb_usb_generic_write(d, buf, buflen)) {
|
||||
err("failed to load bcm4500 firmware.");
|
||||
goto out_free;
|
||||
}
|
||||
ptr += buflen;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
kfree(buf);
|
||||
out_rel_fw:
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
u8 status, buf;
|
||||
if (onoff) {
|
||||
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||
if (! (status & 0x01)) /* started */
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (! (status & 0x02)) /* BCM4500 firmware loaded */
|
||||
if(gp8psk_load_bcm4500fw(d))
|
||||
return EINVAL;
|
||||
|
||||
if (! (status & 0x04)) /* LNB Power */
|
||||
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
|
||||
&buf, 1))
|
||||
return EINVAL;
|
||||
|
||||
/* Set DVB mode */
|
||||
if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
|
||||
return -EINVAL;
|
||||
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||
} else {
|
||||
/* Turn off LNB power */
|
||||
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
|
||||
return EINVAL;
|
||||
/* Turn off 8psk power */
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
|
||||
}
|
||||
|
||||
static int gp8psk_frontend_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
d->fe = gp8psk_fe_attach(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_properties gp8psk_properties;
|
||||
|
||||
static int gp8psk_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
|
||||
}
|
||||
|
||||
static struct usb_device_id gp8psk_usb_table [] = {
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
|
||||
|
||||
static struct dvb_usb_properties gp8psk_properties = {
|
||||
.caps = 0,
|
||||
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-gp8psk-01.fw",
|
||||
|
||||
.streaming_ctrl = gp8psk_streaming_ctrl,
|
||||
.power_ctrl = gp8psk_power_ctrl,
|
||||
.frontend_attach = gp8psk_frontend_attach,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.urb = {
|
||||
.type = DVB_USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
|
||||
.cold_ids = { &gp8psk_usb_table[0], NULL },
|
||||
.warm_ids = { &gp8psk_usb_table[1], NULL },
|
||||
},
|
||||
{ 0 },
|
||||
}
|
||||
};
|
||||
|
||||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver gp8psk_usb_driver = {
|
||||
.name = "dvb_usb_gp8psk",
|
||||
.probe = gp8psk_usb_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = gp8psk_usb_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
static int __init gp8psk_usb_module_init(void)
|
||||
{
|
||||
int result;
|
||||
if ((result = usb_register(&gp8psk_usb_driver))) {
|
||||
err("usb_register failed. (%d)",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit gp8psk_usb_module_exit(void)
|
||||
{
|
||||
/* deregister this driver from the USB subsystem */
|
||||
usb_deregister(&gp8psk_usb_driver);
|
||||
}
|
||||
|
||||
module_init(gp8psk_usb_module_init);
|
||||
module_exit(gp8psk_usb_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
|
||||
MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
79
drivers/media/dvb/dvb-usb/gp8psk.h
Normal file
79
drivers/media/dvb/dvb-usb/gp8psk.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
* This module is based off the vp7045 and vp702x modules
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#ifndef _DVB_USB_GP8PSK_H_
|
||||
#define _DVB_USB_GP8PSK_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "gp8psk"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
extern int dvb_usb_gp8psk_debug;
|
||||
#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
|
||||
#define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args)
|
||||
#define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args)
|
||||
/* gp8psk commands */
|
||||
|
||||
/* Twinhan Vendor requests */
|
||||
#define TH_COMMAND_IN 0xC0
|
||||
#define TH_COMMAND_OUT 0xC1
|
||||
|
||||
/* command bytes */
|
||||
#define GET_8PSK_CONFIG 0x80
|
||||
#define SET_8PSK_CONFIG 0x81
|
||||
#define ARM_TRANSFER 0x85
|
||||
#define TUNE_8PSK 0x86
|
||||
#define GET_SIGNAL_STRENGTH 0x87
|
||||
#define LOAD_BCM4500 0x88
|
||||
#define BOOT_8PSK 0x89
|
||||
#define START_INTERSIL 0x8A
|
||||
#define SET_LNB_VOLTAGE 0x8B
|
||||
#define SET_22KHZ_TONE 0x8C
|
||||
#define SEND_DISEQC_COMMAND 0x8D
|
||||
#define SET_DVB_MODE 0x8E
|
||||
#define SET_DN_SWITCH 0x8F
|
||||
#define GET_SIGNAL_LOCK 0x90
|
||||
|
||||
/* Satellite modulation modes */
|
||||
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
|
||||
#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */
|
||||
#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */
|
||||
#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */
|
||||
|
||||
#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */
|
||||
#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */
|
||||
#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */
|
||||
#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
|
||||
#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */
|
||||
#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */
|
||||
|
||||
#define GET_USB_SPEED 0x07
|
||||
#define USB_SPEED_LOW 0
|
||||
#define USB_SPEED_FULL 1
|
||||
#define USB_SPEED_HIGH 2
|
||||
|
||||
#define RESET_FX2 0x13
|
||||
|
||||
#define FW_VERSION_READ 0x0B
|
||||
#define VENDOR_STRING_READ 0x0C
|
||||
#define PRODUCT_STRING_READ 0x0D
|
||||
#define FW_BCD_VERSION_READ 0x14
|
||||
|
||||
extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
|
||||
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
|
||||
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen);
|
||||
|
||||
#endif
|
|
@ -57,7 +57,6 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
|
|||
memset(&umt_config,0,sizeof(struct mt352_config));
|
||||
umt_config.demod_init = umt_mt352_demod_init;
|
||||
umt_config.demod_address = 0xf;
|
||||
umt_config.pll_set = dvb_usb_pll_set;
|
||||
|
||||
d->fe = mt352_attach(&umt_config, &d->i2c_adap);
|
||||
|
||||
|
@ -68,6 +67,7 @@ static int umt_tuner_attach (struct dvb_usb_device *d)
|
|||
{
|
||||
d->pll_addr = 0x61;
|
||||
d->pll_desc = &dvb_pll_tua6034;
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -287,17 +287,16 @@ struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
|
|||
goto error;
|
||||
|
||||
s->d = d;
|
||||
s->fe.ops = &vp702x_fe_ops;
|
||||
|
||||
memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
|
||||
s->fe.demodulator_priv = s;
|
||||
|
||||
s->lnb_buf[1] = SET_LNB_POWER;
|
||||
s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
|
||||
|
||||
goto success;
|
||||
return &s->fe;
|
||||
error:
|
||||
return NULL;
|
||||
success:
|
||||
return &s->fe;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
struct vp7045_fe_state {
|
||||
struct dvb_frontend fe;
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
struct dvb_usb_device *d;
|
||||
};
|
||||
|
||||
|
@ -151,15 +149,12 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
|
|||
goto error;
|
||||
|
||||
s->d = d;
|
||||
memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
|
||||
s->fe.ops = &s->ops;
|
||||
memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
|
||||
s->fe.demodulator_priv = s;
|
||||
|
||||
goto success;
|
||||
return &s->fe;
|
||||
error:
|
||||
return NULL;
|
||||
success:
|
||||
return &s->fe;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ config DVB_STV0297
|
|||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
comment "ATSC (North American/Korean Terresterial DTV) frontends"
|
||||
comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_NXT200X
|
||||
|
@ -216,4 +216,20 @@ config DVB_LGDT330X
|
|||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
|
||||
comment "Miscellaneous devices"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_LNBP21
|
||||
tristate "LNBP21 SEC controller"
|
||||
depends on DVB_CORE
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
config DVB_ISL6421
|
||||
tristate "ISL6421 SEC controller"
|
||||
depends on DVB_CORE
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
|
|||
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
|
||||
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
|
||||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
|
||||
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
struct bcm3510_state {
|
||||
|
||||
struct i2c_adapter* i2c;
|
||||
struct dvb_frontend_ops ops;
|
||||
const struct bcm3510_config* config;
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
|
@ -791,10 +790,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
|
|||
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
mutex_init(&state->hab_mutex);
|
||||
|
|
|
@ -89,12 +89,13 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
|
||||
static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
int ret;
|
||||
u8 data[4];
|
||||
u32 div;
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
|
||||
struct i2c_adapter *i2c = fe->tuner_priv;
|
||||
|
||||
if ((params->frequency < 950000) || (params->frequency > 2150000))
|
||||
return -EINVAL;
|
||||
|
@ -105,6 +106,8 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c,
|
|||
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
|
||||
data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
ret = i2c_transfer(i2c, &msg, 1);
|
||||
return (ret != 1) ? -EIO : 0;
|
||||
}
|
||||
|
@ -117,7 +120,6 @@ static struct stv0299_config alps_bsbe1_config = {
|
|||
.skip_reinit = 0,
|
||||
.min_delay_ms = 100,
|
||||
.set_symbol_rate = alps_bsbe1_set_symbol_rate,
|
||||
.pll_set = alps_bsbe1_pll_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -101,11 +101,12 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
|
||||
static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
u8 buf[4];
|
||||
u32 div;
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
struct i2c_adapter *i2c = fe->tuner_priv;
|
||||
|
||||
if ((params->frequency < 950000) || (params->frequency > 2150000))
|
||||
return -EINVAL;
|
||||
|
@ -119,6 +120,8 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c,
|
|||
if (params->frequency > 1530000)
|
||||
buf[3] = 0xc0;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(i2c, &msg, 1) != 1)
|
||||
return -EIO;
|
||||
return 0;
|
||||
|
@ -134,7 +137,6 @@ static struct stv0299_config alps_bsru6_config = {
|
|||
.volt13_op0_op1 = STV0299_VOLT13_OP1,
|
||||
.min_delay_ms = 100,
|
||||
.set_symbol_rate = alps_bsru6_set_symbol_rate,
|
||||
.pll_set = alps_bsru6_pll_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,8 +34,6 @@ struct cx22700_state {
|
|||
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
const struct cx22700_config* config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
|
@ -247,12 +245,6 @@ static int cx22700_init (struct dvb_frontend* fe)
|
|||
|
||||
cx22700_writereg (state, 0x00, 0x01);
|
||||
|
||||
if (state->config->pll_init) {
|
||||
cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */
|
||||
state->config->pll_init(fe);
|
||||
cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -333,9 +325,11 @@ static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
|
|||
cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
|
||||
cx22700_writereg (state, 0x00, 0x00);
|
||||
|
||||
cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */
|
||||
state->config->pll_set(fe, p);
|
||||
cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
cx22700_set_inversion (state, p->inversion);
|
||||
cx22700_set_tps (state, &p->u.ofdm);
|
||||
cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */
|
||||
|
@ -353,6 +347,17 @@ static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
|
|||
return cx22700_get_tps (state, &p->u.ofdm);
|
||||
}
|
||||
|
||||
static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct cx22700_state* state = fe->demodulator_priv;
|
||||
|
||||
if (enable) {
|
||||
return cx22700_writereg(state, 0x0a, 0x00);
|
||||
} else {
|
||||
return cx22700_writereg(state, 0x0a, 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
|
||||
{
|
||||
fesettings->min_delay_ms = 150;
|
||||
|
@ -381,13 +386,12 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* check if the demod is there */
|
||||
if (cx22700_readreg(state, 0x07) < 0) goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
@ -413,6 +417,7 @@ static struct dvb_frontend_ops cx22700_ops = {
|
|||
.release = cx22700_release,
|
||||
|
||||
.init = cx22700_init,
|
||||
.i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = cx22700_set_frontend,
|
||||
.get_frontend = cx22700_get_frontend,
|
||||
|
|
|
@ -29,10 +29,6 @@ struct cx22700_config
|
|||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* PLL maintenance */
|
||||
int (*pll_init)(struct dvb_frontend* fe);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
|
||||
|
|
|
@ -40,8 +40,6 @@ struct cx22702_state {
|
|||
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
/* configuration settings */
|
||||
const struct cx22702_config* config;
|
||||
|
||||
|
@ -211,22 +209,10 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
|
|||
u8 val;
|
||||
struct cx22702_state* state = fe->demodulator_priv;
|
||||
|
||||
/* set PLL */
|
||||
cx22702_i2c_gate_ctrl(fe, 1);
|
||||
if (state->config->pll_set) {
|
||||
state->config->pll_set(fe, p);
|
||||
} else if (state->config->pll_desc) {
|
||||
u8 pllbuf[4];
|
||||
struct i2c_msg msg = { .addr = state->config->pll_address,
|
||||
.buf = pllbuf, .len = 4 };
|
||||
dvb_pll_configure(state->config->pll_desc, pllbuf,
|
||||
p->frequency,
|
||||
p->u.ofdm.bandwidth);
|
||||
i2c_transfer(state->i2c, &msg, 1);
|
||||
} else {
|
||||
BUG();
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
cx22702_i2c_gate_ctrl(fe, 0);
|
||||
|
||||
/* set inversion */
|
||||
cx22702_set_inversion (state, p->inversion);
|
||||
|
@ -358,10 +344,6 @@ static int cx22702_init (struct dvb_frontend* fe)
|
|||
|
||||
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
|
||||
|
||||
/* init PLL */
|
||||
if (state->config->pll_init)
|
||||
state->config->pll_init(fe);
|
||||
|
||||
cx22702_i2c_gate_ctrl(fe, 0);
|
||||
|
||||
return 0;
|
||||
|
@ -495,7 +477,6 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->prevUCBlocks = 0;
|
||||
|
||||
/* check if the demod is there */
|
||||
|
@ -503,7 +484,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
|
|||
goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
@ -530,6 +511,7 @@ static struct dvb_frontend_ops cx22702_ops = {
|
|||
.release = cx22702_release,
|
||||
|
||||
.init = cx22702_init,
|
||||
.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = cx22702_set_tps,
|
||||
.get_frontend = cx22702_get_frontend,
|
||||
|
@ -540,7 +522,6 @@ static struct dvb_frontend_ops cx22702_ops = {
|
|||
.read_signal_strength = cx22702_read_signal_strength,
|
||||
.read_snr = cx22702_read_snr,
|
||||
.read_ucblocks = cx22702_read_ucblocks,
|
||||
.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
|
||||
};
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
|
|
|
@ -39,13 +39,6 @@ struct cx22702_config
|
|||
#define CX22702_PARALLEL_OUTPUT 0
|
||||
#define CX22702_SERIAL_OUTPUT 1
|
||||
u8 output_mode;
|
||||
|
||||
/* PLL maintenance */
|
||||
u8 pll_address;
|
||||
struct dvb_pll_desc *pll_desc;
|
||||
|
||||
int (*pll_init)(struct dvb_frontend* fe);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
|
||||
|
|
|
@ -36,8 +36,6 @@ struct cx24110_state {
|
|||
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
const struct cx24110_config* config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
|
@ -250,7 +248,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
|
|||
static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
|
||||
int i;
|
||||
|
||||
dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
|
||||
dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
|
||||
if (srate>90999000UL/2)
|
||||
srate=90999000UL/2;
|
||||
if (srate<500000)
|
||||
|
@ -366,17 +364,6 @@ static int cx24110_initfe(struct dvb_frontend* fe)
|
|||
cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
|
||||
};
|
||||
|
||||
if (state->config->pll_init) state->config->pll_init(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24110_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cx24110_state *state = fe->demodulator_priv;
|
||||
|
||||
if (state->config->pll_sleep)
|
||||
return state->config->pll_sleep(fe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -548,7 +535,12 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
|
|||
{
|
||||
struct cx24110_state *state = fe->demodulator_priv;
|
||||
|
||||
state->config->pll_set(fe, p);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
cx24110_set_inversion (state, p->inversion);
|
||||
cx24110_set_fec (state, p->u.qpsk.fec_inner);
|
||||
cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
|
||||
|
@ -612,7 +604,6 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->lastber = 0;
|
||||
state->lastbler = 0;
|
||||
state->lastesn0 = 0;
|
||||
|
@ -622,7 +613,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
|
|||
if ((ret != 0x5a) && (ret != 0x69)) goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
@ -651,7 +642,6 @@ static struct dvb_frontend_ops cx24110_ops = {
|
|||
.release = cx24110_release,
|
||||
|
||||
.init = cx24110_initfe,
|
||||
.sleep = cx24110_sleep,
|
||||
.set_frontend = cx24110_set_frontend,
|
||||
.get_frontend = cx24110_get_frontend,
|
||||
.read_status = cx24110_read_status,
|
||||
|
|
|
@ -31,11 +31,6 @@ struct cx24110_config
|
|||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* PLL maintenance */
|
||||
int (*pll_init)(struct dvb_frontend* fe);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
int (*pll_sleep)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
|
||||
|
|
|
@ -41,14 +41,12 @@ static int debug;
|
|||
struct cx24123_state
|
||||
{
|
||||
struct i2c_adapter* i2c;
|
||||
struct dvb_frontend_ops ops;
|
||||
const struct cx24123_config* config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
u32 lastber;
|
||||
u16 snr;
|
||||
u8 lnbreg;
|
||||
|
||||
/* Some PLL specifics for tuning */
|
||||
u32 VCAarg;
|
||||
|
@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
|
||||
{
|
||||
u8 buf[] = { reg, data };
|
||||
/* fixme: put the intersil addr int the config */
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
|
||||
int err;
|
||||
|
||||
if (debug>1)
|
||||
printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
|
||||
__FUNCTION__,reg, data);
|
||||
|
||||
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
|
||||
printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
|
||||
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* cache the write, no way to read back */
|
||||
state->lnbreg = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_readreg(struct cx24123_state* state, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
|
|||
return b1[0];
|
||||
}
|
||||
|
||||
static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
|
||||
{
|
||||
return state->lnbreg;
|
||||
}
|
||||
|
||||
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
|
||||
{
|
||||
u8 nom_reg = cx24123_readreg(state, 0x0e);
|
||||
|
@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
|
|||
u8 pll_mult;
|
||||
|
||||
/* check if symbol rate is within limits */
|
||||
if ((srate > state->ops.info.symbol_rate_max) ||
|
||||
(srate < state->ops.info.symbol_rate_min))
|
||||
if ((srate > state->frontend.ops.info.symbol_rate_max) ||
|
||||
(srate < state->frontend.ops.info.symbol_rate_min))
|
||||
return -EOPNOTSUPP;;
|
||||
|
||||
/* choose the sampling rate high enough for the required operation,
|
||||
|
@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
|
|||
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
|
||||
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
|
||||
|
||||
if (state->config->pll_init)
|
||||
state->config->pll_init(fe);
|
||||
|
||||
/* Configure the LNB for 14V */
|
||||
if (state->config->use_isl6421)
|
||||
cx24123_writelnbreg(state, 0x0, 0x2a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
|
|||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
switch (state->config->use_isl6421) {
|
||||
val = cx24123_readreg(state, 0x29) & ~0x40;
|
||||
|
||||
case 1:
|
||||
|
||||
val = cx24123_readlnbreg(state, 0x0);
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
|
||||
case SEC_VOLTAGE_OFF:
|
||||
dprintk("%s: isl5421 voltage off\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x30);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
case 0:
|
||||
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk("%s: setting voltage 13V\n", __FUNCTION__);
|
||||
if (state->config->enable_lnb_voltage)
|
||||
state->config->enable_lnb_voltage(fe, 1);
|
||||
return cx24123_writereg(state, 0x29, val | 0x80);
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: setting voltage 18V\n", __FUNCTION__);
|
||||
if (state->config->enable_lnb_voltage)
|
||||
state->config->enable_lnb_voltage(fe, 1);
|
||||
return cx24123_writereg(state, 0x29, val & 0x7f);
|
||||
case SEC_VOLTAGE_OFF:
|
||||
dprintk("%s: setting voltage off\n", __FUNCTION__);
|
||||
if (state->config->enable_lnb_voltage)
|
||||
state->config->enable_lnb_voltage(fe, 0);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk("%s: setting voltage 13V\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val | 0x80);
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: setting voltage 18V\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val & 0x7f);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
|
|||
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
int i, val;
|
||||
int i, val, tone;
|
||||
|
||||
dprintk("%s:\n",__FUNCTION__);
|
||||
|
||||
/* check if continuous tone has been stopped */
|
||||
if (state->config->use_isl6421)
|
||||
val = cx24123_readlnbreg(state, 0x00) & 0x10;
|
||||
else
|
||||
val = cx24123_readreg(state, 0x29) & 0x10;
|
||||
|
||||
|
||||
if (val) {
|
||||
printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
/* stop continuous tone if enabled */
|
||||
tone = cx24123_readreg(state, 0x29);
|
||||
if (tone & 0x10)
|
||||
cx24123_writereg(state, 0x29, tone & ~0x50);
|
||||
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
|
||||
|
||||
for (i = 0; i < cmd->msg_len; i++)
|
||||
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
|
||||
|
@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
|
|||
/* wait for diseqc message to finish sending */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* restart continuous tone if enabled */
|
||||
if (tone & 0x10) {
|
||||
cx24123_writereg(state, 0x29, tone & ~0x40);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
int val;
|
||||
int val, tone;
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
/* check if continuous tone has been stoped */
|
||||
if (state->config->use_isl6421)
|
||||
val = cx24123_readlnbreg(state, 0x00) & 0x10;
|
||||
else
|
||||
val = cx24123_readreg(state, 0x29) & 0x10;
|
||||
|
||||
|
||||
if (val) {
|
||||
printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
/* stop continuous tone if enabled */
|
||||
tone = cx24123_readreg(state, 0x29);
|
||||
if (tone & 0x10)
|
||||
cx24123_writereg(state, 0x29, tone & ~0x50);
|
||||
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
val = cx24123_readreg(state, 0x2a) & 0xf8;
|
||||
cx24123_writereg(state, 0x2a, val | 0x04);
|
||||
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
|
||||
msleep(30);
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
|
||||
if (burst == SEC_MINI_A)
|
||||
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
|
||||
else if (burst == SEC_MINI_B)
|
||||
|
@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
|
|||
return -EINVAL;
|
||||
|
||||
cx24123_wait_for_diseqc(state);
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
|
||||
|
||||
/* restart continuous tone if enabled */
|
||||
if (tone & 0x10) {
|
||||
cx24123_writereg(state, 0x29, tone & ~0x40);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
|||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
switch (state->config->use_isl6421) {
|
||||
case 1:
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
val = cx24123_readlnbreg(state, 0x0);
|
||||
val = cx24123_readreg(state, 0x29) & ~0x40;
|
||||
|
||||
switch (tone) {
|
||||
case SEC_TONE_ON:
|
||||
dprintk("%s: isl6421 sec tone on\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val | 0x10);
|
||||
case SEC_TONE_OFF:
|
||||
dprintk("%s: isl6421 sec tone off\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x2f);
|
||||
default:
|
||||
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
case 0:
|
||||
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
|
||||
switch (tone) {
|
||||
case SEC_TONE_ON:
|
||||
dprintk("%s: setting tone on\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val | 0x10);
|
||||
case SEC_TONE_OFF:
|
||||
dprintk("%s: setting tone off\n",__FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val & 0xef);
|
||||
default:
|
||||
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (tone) {
|
||||
case SEC_TONE_ON:
|
||||
dprintk("%s: setting tone on\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val | 0x10);
|
||||
case SEC_TONE_OFF:
|
||||
dprintk("%s: setting tone off\n",__FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val & 0xef);
|
||||
default:
|
||||
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->lastber = 0;
|
||||
state->snr = 0;
|
||||
state->lnbreg = 0;
|
||||
state->VCAarg = 0;
|
||||
state->VGAarg = 0;
|
||||
state->bandselectarg = 0;
|
||||
|
@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
|||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
|
|
@ -28,21 +28,8 @@ struct cx24123_config
|
|||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/*
|
||||
cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
|
||||
for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
|
||||
from register 0x29 of the CX24123 demodulator
|
||||
*/
|
||||
int use_isl6421;
|
||||
|
||||
/* PLL maintenance */
|
||||
int (*pll_init)(struct dvb_frontend* fe);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
|
||||
/* Need to set device param for start_dma */
|
||||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
|
||||
void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
struct dib3000_state {
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
/* configuration settings */
|
||||
struct dib3000_config config;
|
||||
|
||||
|
|
|
@ -30,10 +30,6 @@ struct dib3000_config
|
|||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* PLL maintenance and the i2c address of the PLL */
|
||||
int (*pll_init)(struct dvb_frontend *fe);
|
||||
int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
|
||||
};
|
||||
|
||||
struct dib_fe_xfer_ops
|
||||
|
|
|
@ -60,8 +60,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
|
|||
fe_code_rate_t fe_cr = FEC_NONE;
|
||||
int search_state, seq;
|
||||
|
||||
if (tuner && state->config.pll_set) {
|
||||
state->config.pll_set(fe, fep);
|
||||
if (tuner && fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, fep);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
deb_setf("bandwidth: ");
|
||||
switch (ofdm->bandwidth) {
|
||||
|
@ -386,9 +387,6 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
|||
|
||||
wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
|
||||
|
||||
if (state->config.pll_init)
|
||||
state->config.pll_init(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -707,7 +705,6 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
|
|||
/* setup the state */
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->config,config,sizeof(struct dib3000_config));
|
||||
memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* check for the correct demod */
|
||||
if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
|
||||
|
@ -717,7 +714,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
|
|||
goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* set the xfer operations */
|
||||
|
|
|
@ -462,8 +462,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
|||
int search_state,auto_val;
|
||||
u16 val;
|
||||
|
||||
if (tuner && state->config.pll_set) { /* initial call from dvb */
|
||||
state->config.pll_set(fe,fep);
|
||||
if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
|
||||
fe->ops.tuner_ops.set_params(fe, fep);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
state->last_tuned_freq = fep->frequency;
|
||||
// if (!scanboost) {
|
||||
|
@ -642,9 +643,6 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
|||
|
||||
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
|
||||
|
||||
if (state->config.pll_init)
|
||||
state->config.pll_init(fe);
|
||||
|
||||
deb_info("init end\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -839,7 +837,6 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
|
|||
/* setup the state */
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->config,config,sizeof(struct dib3000_config));
|
||||
memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* check for the correct demod */
|
||||
if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
|
||||
|
@ -859,7 +856,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
|
|||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* set the xfer operations */
|
||||
|
@ -876,6 +873,7 @@ error:
|
|||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(dib3000mc_attach);
|
||||
|
||||
static struct dvb_frontend_ops dib3000mc_ops = {
|
||||
|
||||
|
@ -914,5 +912,3 @@ static struct dvb_frontend_ops dib3000mc_ops = {
|
|||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(dib3000mc_attach);
|
||||
|
|
|
@ -227,10 +227,10 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
|
|||
EXPORT_SYMBOL(dvb_pll_tua6034);
|
||||
|
||||
/* Infineon TUA6034
|
||||
* used in LG TDVS H061F and LG TDVS H062F
|
||||
* used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
|
||||
*/
|
||||
struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
|
||||
.name = "LG/Infineon TUA6034",
|
||||
struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
|
||||
.name = "LG TDVS-H06xF",
|
||||
.min = 54000000,
|
||||
.max = 863000000,
|
||||
.count = 3,
|
||||
|
@ -240,7 +240,7 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
|
|||
{ 999999999, 44000000, 62500, 0xce, 0x04 },
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
|
||||
EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
|
||||
|
||||
/* Philips FMD1216ME
|
||||
* used in Medion Hybrid PCMCIA card and USB Box
|
||||
|
@ -419,6 +419,19 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
|
|||
};
|
||||
EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
|
||||
|
||||
struct dvb_pll_priv {
|
||||
/* i2c details */
|
||||
int pll_i2c_address;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
/* the PLL descriptor */
|
||||
struct dvb_pll_desc *pll_desc;
|
||||
|
||||
/* cached frequency/bandwidth */
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* code */
|
||||
|
||||
|
@ -443,7 +456,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
if (debug)
|
||||
printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
|
||||
desc->name, freq, bandwidth, i, desc->count);
|
||||
BUG_ON(i == desc->count);
|
||||
if (i == desc->count)
|
||||
return -EINVAL;
|
||||
|
||||
div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
|
||||
buf[0] = div >> 8;
|
||||
|
@ -462,6 +476,163 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
}
|
||||
EXPORT_SYMBOL(dvb_pll_configure);
|
||||
|
||||
static int dvb_pll_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg =
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
int i;
|
||||
int result;
|
||||
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (priv->pll_desc->entries[i].limit == 0)
|
||||
break;
|
||||
}
|
||||
if (i == priv->pll_desc->count)
|
||||
return 0;
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
buf[2] = priv->pll_desc->entries[i].config;
|
||||
buf[3] = priv->pll_desc->entries[i].cb;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg =
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
int result;
|
||||
u32 div;
|
||||
int i;
|
||||
u32 bandwidth = 0;
|
||||
|
||||
if (priv->i2c == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
// DVBT bandwidth only just now
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
bandwidth = params->u.ofdm.bandwidth;
|
||||
}
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
|
||||
return result;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// calculate the frequency we set it to
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (params->frequency > priv->pll_desc->entries[i].limit)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
|
||||
priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
|
||||
priv->bandwidth = bandwidth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
int result;
|
||||
u32 div;
|
||||
int i;
|
||||
u32 bandwidth = 0;
|
||||
|
||||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
||||
// DVBT bandwidth only just now
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
bandwidth = params->u.ofdm.bandwidth;
|
||||
}
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
|
||||
return result;
|
||||
buf[0] = priv->pll_i2c_address;
|
||||
|
||||
// calculate the frequency we set it to
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (params->frequency > priv->pll_desc->entries[i].limit)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
|
||||
priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
|
||||
priv->bandwidth = bandwidth;
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
*bandwidth = priv->bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops dvb_pll_tuner_ops = {
|
||||
.release = dvb_pll_release,
|
||||
.sleep = dvb_pll_sleep,
|
||||
.set_params = dvb_pll_set_params,
|
||||
.calc_regs = dvb_pll_calc_regs,
|
||||
.get_frequency = dvb_pll_get_frequency,
|
||||
.get_bandwidth = dvb_pll_get_bandwidth,
|
||||
};
|
||||
|
||||
int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
|
||||
{
|
||||
struct dvb_pll_priv *priv = NULL;
|
||||
|
||||
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->pll_i2c_address = pll_addr;
|
||||
priv->i2c = i2c;
|
||||
priv->pll_desc = desc;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
|
||||
fe->ops.tuner_ops.info.frequency_min = desc->min;
|
||||
fe->ops.tuner_ops.info.frequency_min = desc->max;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_pll_attach);
|
||||
|
||||
MODULE_DESCRIPTION("dvb pll library");
|
||||
MODULE_AUTHOR("Gerd Knorr");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#ifndef __DVB_PLL_H__
|
||||
#define __DVB_PLL_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
struct dvb_pll_desc {
|
||||
char *name;
|
||||
u32 min;
|
||||
|
@ -31,7 +34,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
|
|||
extern struct dvb_pll_desc dvb_pll_tua6010xs;
|
||||
extern struct dvb_pll_desc dvb_pll_env57h1xd5;
|
||||
extern struct dvb_pll_desc dvb_pll_tua6034;
|
||||
extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
|
||||
extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
|
||||
extern struct dvb_pll_desc dvb_pll_tda665x;
|
||||
extern struct dvb_pll_desc dvb_pll_fmd1216me;
|
||||
extern struct dvb_pll_desc dvb_pll_tded4;
|
||||
|
@ -44,7 +47,18 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
|
|||
|
||||
extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
|
||||
|
||||
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
||||
extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
||||
u32 freq, int bandwidth);
|
||||
|
||||
/**
|
||||
* Attach a dvb-pll to the supplied frontend structure.
|
||||
*
|
||||
* @param fe Frontend to attach to.
|
||||
* @param pll_addr i2c address of the PLL (if used).
|
||||
* @param i2c i2c adapter to use (set to NULL if not used).
|
||||
* @param desc dvb_pll_desc to use.
|
||||
* @return 0 on success, nonzero on failure.
|
||||
*/
|
||||
extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
|
||||
struct dvb_dummy_fe_state {
|
||||
struct dvb_frontend_ops ops;
|
||||
struct dvb_frontend frontend;
|
||||
};
|
||||
|
||||
|
@ -77,6 +76,11 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
|
|||
|
||||
static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
if (fe->ops->tuner_ops->set_params) {
|
||||
fe->ops->tuner_ops->set_params(fe, p);
|
||||
if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -116,11 +120,8 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
|
|||
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
|
||||
/* setup the state */
|
||||
memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
@ -139,11 +140,8 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
|
|||
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
|
||||
/* setup the state */
|
||||
memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
@ -162,11 +160,8 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
|
|||
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
|
||||
/* setup the state */
|
||||
memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
|
149
drivers/media/dvb/frontends/isl6421.c
Normal file
149
drivers/media/dvb/frontends/isl6421.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* isl6421.h - driver for lnb supply and control ic ISL6421
|
||||
*
|
||||
* Copyright (C) 2006 Andrew de Quincey
|
||||
* Copyright (C) 2006 Oliver Endriss
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*
|
||||
* the project's page is at http://www.linuxtv.org
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "isl6421.h"
|
||||
|
||||
struct isl6421 {
|
||||
u8 config;
|
||||
u8 override_or;
|
||||
u8 override_and;
|
||||
struct i2c_adapter *i2c;
|
||||
u8 i2c_addr;
|
||||
void (*release_chain)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
|
||||
.buf = &isl6421->config,
|
||||
.len = sizeof(isl6421->config) };
|
||||
|
||||
isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
|
||||
|
||||
switch(voltage) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
isl6421->config |= ISL6421_EN1;
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
isl6421->config |= isl6421->override_or;
|
||||
isl6421->config &= isl6421->override_and;
|
||||
|
||||
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
|
||||
.buf = &isl6421->config,
|
||||
.len = sizeof(isl6421->config) };
|
||||
|
||||
if (arg)
|
||||
isl6421->config |= ISL6421_LLC1;
|
||||
else
|
||||
isl6421->config &= ~ISL6421_LLC1;
|
||||
|
||||
isl6421->config |= isl6421->override_or;
|
||||
isl6421->config &= isl6421->override_and;
|
||||
|
||||
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static void isl6421_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
|
||||
/* power off */
|
||||
isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
/* free data & call next release routine */
|
||||
fe->ops.release = isl6421->release_chain;
|
||||
kfree(fe->misc_priv);
|
||||
fe->misc_priv = NULL;
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
}
|
||||
|
||||
int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
u8 override_set, u8 override_clear)
|
||||
{
|
||||
struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
|
||||
if (!isl6421)
|
||||
return -ENOMEM;
|
||||
|
||||
/* default configuration */
|
||||
isl6421->config = ISL6421_ISEL1;
|
||||
isl6421->i2c = i2c;
|
||||
isl6421->i2c_addr = i2c_addr;
|
||||
fe->misc_priv = isl6421;
|
||||
|
||||
/* bits which should be forced to '1' */
|
||||
isl6421->override_or = override_set;
|
||||
|
||||
/* bits which should be forced to '0' */
|
||||
isl6421->override_and = ~override_clear;
|
||||
|
||||
/* detect if it is present or not */
|
||||
if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
|
||||
kfree(isl6421);
|
||||
fe->misc_priv = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* install release callback */
|
||||
isl6421->release_chain = fe->ops.release;
|
||||
fe->ops.release = isl6421_release;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = isl6421_set_voltage;
|
||||
fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(isl6421_attach);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
|
||||
MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
|
||||
MODULE_LICENSE("GPL");
|
46
drivers/media/dvb/frontends/isl6421.h
Normal file
46
drivers/media/dvb/frontends/isl6421.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* isl6421.h - driver for lnb supply and control ic ISL6421
|
||||
*
|
||||
* Copyright (C) 2006 Andrew de Quincey
|
||||
* Copyright (C) 2006 Oliver Endriss
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*
|
||||
* the project's page is at http://www.linuxtv.org
|
||||
*/
|
||||
|
||||
#ifndef _ISL6421_H
|
||||
#define _ISL6421_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
/* system register bits */
|
||||
#define ISL6421_OLF1 0x01
|
||||
#define ISL6421_EN1 0x02
|
||||
#define ISL6421_VSEL1 0x04
|
||||
#define ISL6421_LLC1 0x08
|
||||
#define ISL6421_ENT1 0x10
|
||||
#define ISL6421_ISEL1 0x20
|
||||
#define ISL6421_DCL 0x40
|
||||
|
||||
/* override_set and override_clear control which system register bits (above) to always set & clear */
|
||||
extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
u8 override_set, u8 override_clear);
|
||||
|
||||
#endif
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
struct l64781_state {
|
||||
struct i2c_adapter* i2c;
|
||||
struct dvb_frontend_ops ops;
|
||||
const struct l64781_config* config;
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
|
@ -141,7 +140,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
|
|||
u8 val0x06;
|
||||
int bw = p->bandwidth - BANDWIDTH_8_MHZ;
|
||||
|
||||
state->config->pll_set(fe, param);
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, param);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
if (param->inversion != INVERSION_ON &&
|
||||
param->inversion != INVERSION_OFF)
|
||||
|
@ -463,8 +465,6 @@ static int l64781_init(struct dvb_frontend* fe)
|
|||
/* Everything is two's complement, soft bit and CSI_OUT too */
|
||||
l64781_writereg (state, 0x1e, 0x09);
|
||||
|
||||
if (state->config->pll_init) state->config->pll_init(fe);
|
||||
|
||||
/* delay a bit after first init attempt */
|
||||
if (state->first) {
|
||||
state->first = 0;
|
||||
|
@ -508,7 +508,6 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->first = 1;
|
||||
|
||||
/**
|
||||
|
@ -554,7 +553,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
|
|||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@ struct l64781_config
|
|||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* PLL maintenance */
|
||||
int (*pll_init)(struct dvb_frontend* fe);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
};
|
||||
|
||||
|
||||
|
|
64
drivers/media/dvb/frontends/lg_h06xf.h
Normal file
64
drivers/media/dvb/frontends/lg_h06xf.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _LG_H06XF_H_
|
||||
#define _LG_H06XF_H_
|
||||
#include "dvb-pll.h"
|
||||
|
||||
static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
|
||||
struct dvb_frontend_parameters* params)
|
||||
{
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
int err;
|
||||
|
||||
dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lg_h06xf: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* Set the Auxiliary Byte. */
|
||||
buf[0] = buf[2];
|
||||
buf[0] &= ~0x20;
|
||||
buf[0] |= 0x18;
|
||||
buf[1] = 0x50;
|
||||
msg.len = 2;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lg_h06xf: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -29,6 +29,7 @@
|
|||
* DViCO FusionHDTV 5 Lite
|
||||
* DViCO FusionHDTV 5 USB Gold
|
||||
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
|
||||
* pcHDTV HD5500
|
||||
*
|
||||
* TODO:
|
||||
* signal strength always returns 0.
|
||||
|
@ -59,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
|
|||
struct lgdt330x_state
|
||||
{
|
||||
struct i2c_adapter* i2c;
|
||||
struct dvb_frontend_ops ops;
|
||||
|
||||
/* Configuration settings */
|
||||
const struct lgdt330x_config* config;
|
||||
|
@ -399,8 +399,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
|
|||
}
|
||||
|
||||
/* Tune to the specified frequency */
|
||||
if (state->config->pll_set)
|
||||
state->config->pll_set(fe, param);
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, param);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
/* Keep track of the new frequency */
|
||||
/* FIXME this is the wrong way to do this... */
|
||||
|
@ -672,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
|
|||
|
||||
if (state->current_modulation == VSB_8) {
|
||||
|
||||
i2c_read_demod_bytes(state, 0x6e, buf, 5);
|
||||
/* Phase Tracker Mean-Square Error Register for VSB */
|
||||
noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
|
||||
} else {
|
||||
|
@ -721,16 +724,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
|
|||
/* Setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
||||
/* Create dvb_frontend */
|
||||
switch (config->demod_chip) {
|
||||
case LGDT3302:
|
||||
memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case LGDT3303:
|
||||
memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* Verify communication with demod chip */
|
||||
if (i2c_read_demod_bytes(state, 2, buf, 1))
|
||||
|
@ -739,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
|
|||
state->current_frequency = -1;
|
||||
state->current_modulation = -1;
|
||||
|
||||
/* Create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
|
|
|
@ -43,7 +43,6 @@ struct lgdt330x_config
|
|||
|
||||
/* PLL interface */
|
||||
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
|
||||
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
|
||||
|
||||
/* Need to set device param for start_dma */
|
||||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
|
|
145
drivers/media/dvb/frontends/lnbp21.c
Normal file
145
drivers/media/dvb/frontends/lnbp21.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* lnbp21.h - driver for lnb supply and control ic lnbp21
|
||||
*
|
||||
* Copyright (C) 2006 Oliver Endriss
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*
|
||||
* the project's page is at http://www.linuxtv.org
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "lnbp21.h"
|
||||
|
||||
struct lnbp21 {
|
||||
u8 config;
|
||||
u8 override_or;
|
||||
u8 override_and;
|
||||
struct i2c_adapter *i2c;
|
||||
void (*release_chain)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
||||
lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
|
||||
|
||||
switch(voltage) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
lnbp21->config |= LNBP21_EN;
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
||||
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
||||
if (arg)
|
||||
lnbp21->config |= LNBP21_LLC;
|
||||
else
|
||||
lnbp21->config &= ~LNBP21_LLC;
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
||||
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static void lnbp21_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
|
||||
/* LNBP power off */
|
||||
lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
/* free data & call next release routine */
|
||||
fe->ops.release = lnbp21->release_chain;
|
||||
kfree(fe->misc_priv);
|
||||
fe->misc_priv = NULL;
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
}
|
||||
|
||||
int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
|
||||
if (!lnbp21)
|
||||
return -ENOMEM;
|
||||
|
||||
/* default configuration */
|
||||
lnbp21->config = LNBP21_ISEL;
|
||||
lnbp21->i2c = i2c;
|
||||
fe->misc_priv = lnbp21;
|
||||
|
||||
/* bits which should be forced to '1' */
|
||||
lnbp21->override_or = override_set;
|
||||
|
||||
/* bits which should be forced to '0' */
|
||||
lnbp21->override_and = ~override_clear;
|
||||
|
||||
/* detect if it is present or not */
|
||||
if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
|
||||
kfree(lnbp21);
|
||||
fe->misc_priv = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* install release callback */
|
||||
lnbp21->release_chain = fe->ops.release;
|
||||
fe->ops.release = lnbp21_release;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = lnbp21_set_voltage;
|
||||
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lnbp21_attach);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
|
||||
MODULE_AUTHOR("Oliver Endriss");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -27,7 +27,7 @@
|
|||
#ifndef _LNBP21_H
|
||||
#define _LNBP21_H
|
||||
|
||||
/* system register */
|
||||
/* system register bits */
|
||||
#define LNBP21_OLF 0x01
|
||||
#define LNBP21_OTF 0x02
|
||||
#define LNBP21_EN 0x04
|
||||
|
@ -37,103 +37,9 @@
|
|||
#define LNBP21_ISEL 0x40
|
||||
#define LNBP21_PCL 0x80
|
||||
|
||||
struct lnbp21 {
|
||||
u8 config;
|
||||
u8 override_or;
|
||||
u8 override_and;
|
||||
struct i2c_adapter *i2c;
|
||||
void (*release_chain)(struct dvb_frontend* fe);
|
||||
};
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
||||
lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
|
||||
|
||||
switch(voltage) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
lnbp21->config |= LNBP21_EN;
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
||||
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
||||
if (arg)
|
||||
lnbp21->config |= LNBP21_LLC;
|
||||
else
|
||||
lnbp21->config &= ~LNBP21_LLC;
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
||||
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static void lnbp21_exit(struct dvb_frontend *fe)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
|
||||
/* LNBP power off */
|
||||
lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
/* free data & call next release routine */
|
||||
fe->ops->release = lnbp21->release_chain;
|
||||
kfree(fe->misc_priv);
|
||||
fe->misc_priv = NULL;
|
||||
if (fe->ops->release)
|
||||
fe->ops->release(fe);
|
||||
}
|
||||
|
||||
static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
|
||||
|
||||
if (!lnbp21)
|
||||
return -ENOMEM;
|
||||
|
||||
/* default configuration */
|
||||
lnbp21->config = LNBP21_ISEL;
|
||||
|
||||
/* bits which should be forced to '1' */
|
||||
lnbp21->override_or = override_set;
|
||||
|
||||
/* bits which should be forced to '0' */
|
||||
lnbp21->override_and = ~override_clear;
|
||||
|
||||
/* install release callback */
|
||||
lnbp21->release_chain = fe->ops->release;
|
||||
fe->ops->release = lnbp21_exit;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops->set_voltage = lnbp21_set_voltage;
|
||||
fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
|
||||
|
||||
lnbp21->i2c = i2c;
|
||||
fe->misc_priv = lnbp21;
|
||||
|
||||
return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
}
|
||||
/* override_set and override_clear control which system register bits (above) to always set & clear */
|
||||
extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
struct mt312_state {
|
||||
struct i2c_adapter* i2c;
|
||||
struct dvb_frontend_ops ops;
|
||||
/* configuration settings */
|
||||
const struct mt312_config* config;
|
||||
struct dvb_frontend frontend;
|
||||
|
@ -277,12 +276,6 @@ static int mt312_initfe(struct dvb_frontend* fe)
|
|||
if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
|
||||
return ret;
|
||||
|
||||
if (state->config->pll_init) {
|
||||
mt312_writereg(state, GPP_CTRL, 0x40);
|
||||
state->config->pll_init(fe);
|
||||
mt312_writereg(state, GPP_CTRL, 0x00);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -477,16 +470,16 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
|
|||
|
||||
dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
|
||||
|
||||
if ((p->frequency < fe->ops->info.frequency_min)
|
||||
|| (p->frequency > fe->ops->info.frequency_max))
|
||||
if ((p->frequency < fe->ops.info.frequency_min)
|
||||
|| (p->frequency > fe->ops.info.frequency_max))
|
||||
return -EINVAL;
|
||||
|
||||
if ((p->inversion < INVERSION_OFF)
|
||||
|| (p->inversion > INVERSION_ON))
|
||||
return -EINVAL;
|
||||
|
||||
if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min)
|
||||
|| (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max))
|
||||
if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
|
||||
|| (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
|
||||
return -EINVAL;
|
||||
|
||||
if ((p->u.qpsk.fec_inner < FEC_NONE)
|
||||
|
@ -529,9 +522,10 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mt312_writereg(state, GPP_CTRL, 0x40);
|
||||
state->config->pll_set(fe, p);
|
||||
mt312_writereg(state, GPP_CTRL, 0x00);
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
/* sr = (u16)(sr * 256.0 / 1000000.0) */
|
||||
sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
|
||||
|
@ -578,6 +572,17 @@ static int mt312_get_frontend(struct dvb_frontend* fe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct mt312_state* state = fe->demodulator_priv;
|
||||
|
||||
if (enable) {
|
||||
return mt312_writereg(state, GPP_CTRL, 0x40);
|
||||
} else {
|
||||
return mt312_writereg(state, GPP_CTRL, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static int mt312_sleep(struct dvb_frontend* fe)
|
||||
{
|
||||
struct mt312_state *state = fe->demodulator_priv;
|
||||
|
@ -633,6 +638,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
|
|||
|
||||
.init = mt312_initfe,
|
||||
.sleep = mt312_sleep,
|
||||
.i2c_gate_ctrl = mt312_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = mt312_set_frontend,
|
||||
.get_frontend = mt312_get_frontend,
|
||||
|
@ -663,19 +669,22 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
||||
/* check if the demod is there */
|
||||
if (mt312_readreg(state, ID, &state->id) < 0)
|
||||
goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
switch (state->id) {
|
||||
case ID_VP310:
|
||||
strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
|
||||
strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
|
||||
state->frequency = 90;
|
||||
break;
|
||||
case ID_MT312:
|
||||
strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
|
||||
strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
|
||||
state->frequency = 60;
|
||||
break;
|
||||
default:
|
||||
|
@ -683,9 +692,6 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
state->frontend.ops = &state->ops;
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue