Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (255 commits) [media] radio-aimslab.c: Fix gcc 4.5+ bug [media] cx25821: Fix compilation breakage due to BKL dependency [media] v4l2-compat-ioctl32: fix compile warning [media] zoran: fix compiler warning [media] tda18218: fix compile warning [media] ngene: fix compile warning [media] DVB: IR support for TechnoTrend CT-3650 [media] cx23885, cimax2.c: Fix case of two CAM insertion irq [media] ir-nec-decoder: fix repeat key issue [media] staging: se401 depends on USB [media] staging: usbvideo/vicam depends on USB [media] soc_camera: Add the ability to bind regulators to soc_camedra devices [media] V4L2: Add a v4l2-subdev (soc-camera) driver for OmniVision OV2640 sensor [media] v4l: soc-camera: switch to .unlocked_ioctl [media] v4l: ov772x: simplify pointer dereference [media] ov9640: fix OmniVision OV9640 sensor driver's priv data retrieving [media] ov9640: use macro to request OmniVision OV9640 sensor private data [media] ivtv-i2c: Fix two warnings [media] staging/lirc: Update lirc TODO files [media] cx88: Remove the obsolete i2c_adapter.id field ...
This commit is contained in:
commit
9e9bc97367
500 changed files with 17757 additions and 28845 deletions
|
@ -34,8 +34,7 @@
|
|||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>V4L2 ioctl request code as defined in the <link
|
||||
linkend="videodev">videodev.h</link> header file, for example
|
||||
<para>V4L2 ioctl request code as defined in the <filename>videodev2.h</filename> header file, for example
|
||||
VIDIOC_QUERYCAP.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -57,7 +56,7 @@ file descriptor. An ioctl <parameter>request</parameter> has encoded
|
|||
in it whether the argument is an input, output or read/write
|
||||
parameter, and the size of the argument <parameter>argp</parameter> in
|
||||
bytes. Macros and defines specifying V4L2 ioctl requests are located
|
||||
in the <link linkend="videodev">videodev.h</link> header file.
|
||||
in the <filename>videodev2.h</filename> header file.
|
||||
Applications should use their own copy, not include the version in the
|
||||
kernel sources on the system they compile on. All V4L2 ioctl requests,
|
||||
their respective function and parameters are specified in <xref
|
||||
|
|
|
@ -142,8 +142,8 @@ leftmost pixel of the second row from the top, and so on. The last row
|
|||
has just as many pad bytes after it as the other rows.</para>
|
||||
|
||||
<para>In V4L2 each format has an identifier which looks like
|
||||
<constant>PIX_FMT_XXX</constant>, defined in the <link
|
||||
linkend="videodev">videodev.h</link> header file. These identifiers
|
||||
<constant>PIX_FMT_XXX</constant>, defined in the <filename>videodev2.h</filename>
|
||||
header file. These identifiers
|
||||
represent <link linkend="v4l2-fourcc">four character codes</link>
|
||||
which are also listed below, however they are not the same as those
|
||||
used in the Windows world.</para>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
|
||||
filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
|
||||
pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/
|
||||
pcmcia/ spi/ timers/ vm/ watchdog/src/
|
||||
|
|
|
@ -46,7 +46,7 @@ and run
|
|||
Other LG firmware can be extracted manually from US280D.sys
|
||||
only found in windows/system32/driver.
|
||||
|
||||
dd if=US280D.sys ibs=1 skip=42616 count=3668 of=dvb-usb-lme2510-lg.fw
|
||||
dd if=US280D.sys ibs=1 skip=42360 count=3924 of=dvb-usb-lme2510-lg.fw
|
||||
|
||||
for DM04 LME2510C (LG Tuner)
|
||||
---------------------------
|
||||
|
|
|
@ -97,36 +97,38 @@ Who: Pavel Machek <pavel@ucw.cz>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux API 1 ioctls and from Video devices.
|
||||
When: kernel 2.6.38
|
||||
Files: include/linux/videodev.h
|
||||
Check: include/linux/videodev.h
|
||||
Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
|
||||
series. The old API have lots of drawbacks and don't provide enough
|
||||
means to work with all video and audio standards. The newer API is
|
||||
already available on the main drivers and should be used instead.
|
||||
Newer drivers should use v4l_compat_translate_ioctl function to handle
|
||||
old calls, replacing to newer ones.
|
||||
Decoder iocts are using internally to allow video drivers to
|
||||
communicate with video decoders. This should also be improved to allow
|
||||
V4L2 calls being translated into compatible internal ioctls.
|
||||
Compatibility ioctls will be provided, for a while, via
|
||||
v4l1-compat module.
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux obsolete drivers using V4L1 API
|
||||
When: kernel 2.6.38
|
||||
Files: drivers/staging/cpia/* drivers/staging/stradis/*
|
||||
Check: drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
|
||||
When: kernel 2.6.39
|
||||
Files: drivers/staging/se401/* drivers/staging/usbvideo/*
|
||||
Check: drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c
|
||||
Why: There are some drivers still using V4L1 API, despite all efforts we've done
|
||||
to migrate. Those drivers are for obsolete hardware that the old maintainer
|
||||
didn't care (or not have the hardware anymore), and that no other developer
|
||||
could find any hardware to buy. They probably have no practical usage today,
|
||||
and people with such old hardware could probably keep using an older version
|
||||
of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
|
||||
care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
|
||||
of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody
|
||||
cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39.
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux: Remove obsolete ioctl's
|
||||
When: kernel 2.6.39
|
||||
Files: include/media/videodev2.h
|
||||
Why: Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
|
||||
type of R/W arguments. They were fixed, but the old ioctl names are
|
||||
still there, maintained to avoid breaking binary compatibility:
|
||||
#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int)
|
||||
#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm)
|
||||
#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control)
|
||||
#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio)
|
||||
#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout)
|
||||
#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap)
|
||||
There's no sense on preserving those forever, as it is very doubtful
|
||||
that someone would try to use a such old binary with a modern kernel.
|
||||
Removing them will allow us to remove some magic done at the V4L ioctl
|
||||
handler.
|
||||
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
|
|
@ -155,7 +155,6 @@ Code Seq#(hex) Include File Comments
|
|||
'Q' all linux/soundcard.h
|
||||
'R' 00-1F linux/random.h conflict!
|
||||
'R' 01 linux/rfkill.h conflict!
|
||||
'R' 01-0F media/rds.h conflict!
|
||||
'R' C0-DF net/bluetooth/rfcomm.h
|
||||
'S' all linux/cdrom.h conflict!
|
||||
'S' 80-81 scsi/scsi_ioctl.h conflict!
|
||||
|
@ -194,7 +193,6 @@ Code Seq#(hex) Include File Comments
|
|||
<http://lrcwww.epfl.ch/>
|
||||
'b' 00-FF conflict! bit3 vme host bridge
|
||||
<mailto:natalia@nikhefk.nikhef.nl>
|
||||
'b' 00-0F media/bt819.h conflict!
|
||||
'c' all linux/cm4000_cs.h conflict!
|
||||
'c' 00-7F linux/comstats.h conflict!
|
||||
'c' 00-7F linux/coda.h conflict!
|
||||
|
@ -260,14 +258,11 @@ Code Seq#(hex) Include File Comments
|
|||
't' 80-8F linux/isdn_ppp.h
|
||||
't' 90 linux/toshiba.h
|
||||
'u' 00-1F linux/smb_fs.h gone
|
||||
'v' all linux/videodev.h conflict!
|
||||
'v' 00-1F linux/ext2_fs.h conflict!
|
||||
'v' 00-1F linux/fs.h conflict!
|
||||
'v' 00-0F linux/sonypi.h conflict!
|
||||
'v' C0-CF drivers/media/video/ov511.h conflict!
|
||||
'v' C0-DF media/pwc-ioctl.h conflict!
|
||||
'v' C0-FF linux/meye.h conflict!
|
||||
'v' C0-CF drivers/media/video/zoran/zoran.h conflict!
|
||||
'v' D0-DF drivers/media/video/cpia2/cpia2dev.h conflict!
|
||||
'w' all CERN SCI driver
|
||||
'y' 00-1F packet based user level communications
|
||||
|
@ -278,7 +273,6 @@ Code Seq#(hex) Include File Comments
|
|||
<mailto:oe@port.de>
|
||||
'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict!
|
||||
0x80 00-1F linux/fb.h
|
||||
0x88 00-3F media/ovcamchip.h
|
||||
0x89 00-06 arch/x86/include/asm/sockios.h
|
||||
0x89 0B-DF linux/sockios.h
|
||||
0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
|
||||
1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868]
|
||||
1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868,eb1a:2875]
|
||||
2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
|
||||
3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
|
||||
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201]
|
||||
|
@ -9,7 +9,7 @@
|
|||
8 -> Kworld USB2800 (em2800)
|
||||
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
|
||||
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
|
||||
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
|
||||
11 -> Terratec Hybrid XS (em2880)
|
||||
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
|
||||
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
|
||||
14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
|
||||
|
@ -53,7 +53,7 @@
|
|||
52 -> DNT DA2 Hybrid (em2881)
|
||||
53 -> Pinnacle Hybrid Pro (em2881)
|
||||
54 -> Kworld VS-DVB-T 323UR (em2882) [eb1a:e323]
|
||||
55 -> Terratec Hybrid XS (em2882) (em2882) [0ccd:005e]
|
||||
55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882) [0ccd:005e,0ccd:0042]
|
||||
56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226]
|
||||
57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316]
|
||||
58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041]
|
||||
|
|
|
@ -180,3 +180,5 @@
|
|||
179 -> Beholder BeholdTV A7 [5ace:7090]
|
||||
180 -> Avermedia PCI M733A [1461:4155,1461:4255]
|
||||
181 -> TechoTrend TT-budget T-3000 [13c2:2804]
|
||||
182 -> Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid [17de:b136]
|
||||
183 -> Compro VideoMate Vista M1F [185b:c900]
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||
obj- := dummy.o
|
||||
|
||||
# List of programs to build
|
||||
hostprogs-y := v4lgrab
|
||||
|
||||
# Tell kbuild to always build the programs
|
||||
always := $(hostprogs-y)
|
|
@ -1,191 +0,0 @@
|
|||
This is a driver for the CPiA PPC2 driven parallel connected
|
||||
Camera. For example the Creative WebcamII is CPiA driven.
|
||||
|
||||
) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
USAGE:
|
||||
|
||||
General:
|
||||
========
|
||||
|
||||
1) Make sure you have created the video devices (/dev/video*):
|
||||
|
||||
- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video'
|
||||
- otherwise do a:
|
||||
|
||||
cd /dev
|
||||
mknod video0 c 81 0
|
||||
ln -s video0 video
|
||||
|
||||
2) Compile the kernel (see below for the list of options to use),
|
||||
configure your parport and reboot.
|
||||
|
||||
3) If all worked well you should get messages similar
|
||||
to the following (your versions may be different) on the console:
|
||||
|
||||
V4L-Driver for Vision CPiA based cameras v0.7.4
|
||||
parport0: read2 timeout.
|
||||
parport0: Multimedia device, VLSI Vision Ltd PPC2
|
||||
Parallel port driver for Vision CPiA based camera
|
||||
CPIA Version: 1.20 (2.0)
|
||||
CPIA PnP-ID: 0553:0002:0100
|
||||
VP-Version: 1.0 0100
|
||||
1 camera(s) found
|
||||
|
||||
|
||||
As modules:
|
||||
===========
|
||||
|
||||
Make sure you have selected the following kernel options (you can
|
||||
select all stuff as modules):
|
||||
|
||||
The cpia-stuff is in the section 'Character devices -> Video For Linux'.
|
||||
|
||||
CONFIG_PARPORT=m
|
||||
CONFIG_PARPORT_PC=m
|
||||
CONFIG_PARPORT_PC_FIFO=y
|
||||
CONFIG_PARPORT_1284=y
|
||||
CONFIG_VIDEO_DEV=m
|
||||
CONFIG_VIDEO_CPIA=m
|
||||
CONFIG_VIDEO_CPIA_PP=m
|
||||
|
||||
For autoloading of all those modules you need to tell module-init-tools
|
||||
some stuff. Add the following line to your module-init-tools config-file
|
||||
(e.g. /etc/modprobe.conf or wherever your distribution does store that
|
||||
stuff):
|
||||
|
||||
options parport_pc io=0x378 irq=7 dma=3
|
||||
alias char-major-81 cpia_pp
|
||||
|
||||
The first line tells the dma/irq channels to use. Those _must_ match
|
||||
the settings of your BIOS. Do NOT simply use the values above. See
|
||||
Documentation/parport.txt for more information about this. The second
|
||||
line associates the video-device file with the driver. Of cause you
|
||||
can also load the modules once upon boot (usually done in /etc/modules).
|
||||
|
||||
Linked into the kernel:
|
||||
=======================
|
||||
|
||||
Make sure you have selected the following kernel options. Note that
|
||||
you cannot compile the parport-stuff as modules and the cpia-driver
|
||||
statically (the other way round is okay though).
|
||||
|
||||
The cpia-stuff is in the section 'Character devices -> Video For Linux'.
|
||||
|
||||
CONFIG_PARPORT=y
|
||||
CONFIG_PARPORT_PC=y
|
||||
CONFIG_PARPORT_PC_FIFO=y
|
||||
CONFIG_PARPORT_1284=y
|
||||
CONFIG_VIDEO_DEV=y
|
||||
CONFIG_VIDEO_CPIA=y
|
||||
CONFIG_VIDEO_CPIA_PP=y
|
||||
|
||||
To use DMA/irq you will need to tell the kernel upon boot time the
|
||||
hardware configuration of the parport. You can give the boot-parameter
|
||||
at the LILO-prompt or specify it in lilo.conf. I use the following
|
||||
append-line in lilo.conf:
|
||||
|
||||
append="parport=0x378,7,3"
|
||||
|
||||
See Documentation/parport.txt for more information about the
|
||||
configuration of the parport and the values given above. Do not simply
|
||||
use the values given above.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
FEATURES:
|
||||
|
||||
- mmap/read v4l-interface (but no overlay)
|
||||
- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel;
|
||||
note: all sizes except CIF/QCIF are implemented by clipping, i.e.
|
||||
pixels are not uploaded from the camera
|
||||
- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555,
|
||||
VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV,
|
||||
VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422
|
||||
- state information (color balance, exposure, ...) is preserved between
|
||||
device opens
|
||||
- complete control over camera via proc-interface (_all_ camera settings are
|
||||
supported), there is also a python-gtk application available for this [3]
|
||||
- works under SMP (but the driver is completely serialized and synchronous)
|
||||
so you get no benefit from SMP, but at least it does not crash your box
|
||||
- might work for non-Intel architecture, let us know about this
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
TESTED APPLICATIONS:
|
||||
|
||||
- a simple test application based on Xt is available at [3]
|
||||
- another test-application based on gqcam-0.4 (uses GTK)
|
||||
- gqcam-0.6 should work
|
||||
- xawtv-3.x (also the webcam software)
|
||||
- xawtv-2.46
|
||||
- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat |xv
|
||||
-maxpect -root -quit +noresetroot -rmode 5 -')
|
||||
- vic, the MBONE video conferencing tool (version 2.8ucl4-1)
|
||||
- isabel 3R4beta (barely working, but AFAICT all the problems are on
|
||||
their side)
|
||||
- camserv-0.40
|
||||
|
||||
See [3] for pointers to v4l-applications.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
KNOWN PROBLEMS:
|
||||
|
||||
- some applications do not handle the image format correctly, you will
|
||||
see strange horizontal stripes instead of a nice picture -> make sure
|
||||
your application does use a supported image size or queries the driver
|
||||
for the actually used size (reason behind this: the camera cannot
|
||||
provide any image format, so if size NxM is requested the driver will
|
||||
use a format to the closest fitting N1xM1, the application should now
|
||||
query for this granted size, most applications do not).
|
||||
- all the todo ;)
|
||||
- if there is not enough light and the picture is too dark try to
|
||||
adjust the SetSensorFPS setting, automatic frame rate adjustment
|
||||
has its price
|
||||
- do not try out isabel 3R4beta (built 135), you will be disappointed
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
TODO:
|
||||
|
||||
- multiple camera support (struct camera or something) - This should work,
|
||||
but hasn't been tested yet.
|
||||
- architecture independence?
|
||||
- SMP-safe asynchronous mmap interface
|
||||
- nibble mode for old parport interfaces
|
||||
- streaming capture, this should give a performance gain
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
IMPLEMENTATION NOTES:
|
||||
|
||||
The camera can act in two modes, streaming or grabbing. Right now a
|
||||
polling grab-scheme is used. Maybe interrupt driven streaming will be
|
||||
used for a asynchronous mmap interface in the next major release of the
|
||||
driver. This might give a better frame rate.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
THANKS (in no particular order):
|
||||
|
||||
- Scott J. Bertin <sbertin@mindspring.com> for cleanups, the proc-filesystem
|
||||
and much more
|
||||
- Henry Bruce <whb@vvl.co.uk> for providing developers information about
|
||||
the CPiA chip, I wish all companies would treat Linux as seriously
|
||||
- Karoly Erdei <Karoly.Erdei@risc.uni-linz.ac.at> and RISC-Linz for being
|
||||
my boss ;) resp. my employer and for providing me the hardware and
|
||||
allow me to devote some working time to this project
|
||||
- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
|
||||
with Isabel (http://isabel.dit.upm.es/)
|
||||
- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
|
||||
- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
|
||||
and maintaining the web-server[3]
|
||||
- Chris Whiteford <Chris@informinteractive.com> for fixes related to the
|
||||
1.02 firmware
|
||||
- special kudos to all the tester whose machines crashed and/or
|
||||
will crash. :)
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
REFERENCES
|
||||
|
||||
1. http://www.risc.uni-linz.ac.at/
|
||||
mailto:Peter_Pregler@email.com
|
||||
2. see the file COPYING in the top directory of the kernel tree
|
||||
3. http://webcam.sourceforge.net/
|
|
@ -322,76 +322,11 @@ your IRQs and make sure the card has its own interrupts.
|
|||
|
||||
4. Programming interface
|
||||
|
||||
This driver conforms to video4linux and video4linux2, both can be used to
|
||||
use the driver. Since video4linux didn't provide adequate calls to fully
|
||||
use the cards' features, we've introduced several programming extensions,
|
||||
which are currently officially accepted in the 2.4.x branch of the kernel.
|
||||
These extensions are known as the v4l/mjpeg extensions. See zoran.h for
|
||||
details (structs/ioctls).
|
||||
|
||||
Information - video4linux:
|
||||
http://linux.bytesex.org/v4l2/API.html
|
||||
Documentation/video4linux/API.html
|
||||
/usr/include/linux/videodev.h
|
||||
|
||||
Information - video4linux/mjpeg extensions:
|
||||
./zoran.h
|
||||
(also see below)
|
||||
|
||||
Information - video4linux2:
|
||||
http://linuxtv.org
|
||||
http://v4l2spec.bytesex.org/
|
||||
/usr/include/linux/videodev2.h
|
||||
|
||||
More information on the video4linux/mjpeg extensions, by Serguei
|
||||
Miridonovi and Rainer Johanni:
|
||||
--
|
||||
The ioctls for that interface are as follows:
|
||||
|
||||
BUZIOC_G_PARAMS
|
||||
BUZIOC_S_PARAMS
|
||||
|
||||
Get and set the parameters of the buz. The user should always do a
|
||||
BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default
|
||||
settings, change what he likes and then make a BUZIOC_S_PARAMS call.
|
||||
|
||||
BUZIOC_REQBUFS
|
||||
|
||||
Before being able to capture/playback, the user has to request
|
||||
the buffers he is wanting to use. Fill the structure
|
||||
zoran_requestbuffers with the size (recommended: 256*1024) and
|
||||
the number (recommended 32 up to 256). There are no such restrictions
|
||||
as for the Video for Linux buffers, you should LEAVE SUFFICIENT
|
||||
MEMORY for your system however, else strange things will happen ....
|
||||
On return, the zoran_requestbuffers structure contains number and
|
||||
size of the actually allocated buffers.
|
||||
You should use these numbers for doing a mmap of the buffers
|
||||
into the user space.
|
||||
The BUZIOC_REQBUFS ioctl also makes it happen, that the next mmap
|
||||
maps the MJPEG buffer instead of the V4L buffers.
|
||||
|
||||
BUZIOC_QBUF_CAPT
|
||||
BUZIOC_QBUF_PLAY
|
||||
|
||||
Queue a buffer for capture or playback. The first call also starts
|
||||
streaming capture. When streaming capture is going on, you may
|
||||
only queue further buffers or issue syncs until streaming
|
||||
capture is switched off again with a argument of -1 to
|
||||
a BUZIOC_QBUF_CAPT/BUZIOC_QBUF_PLAY ioctl.
|
||||
|
||||
BUZIOC_SYNC
|
||||
|
||||
Issue this ioctl when all buffers are queued. This ioctl will
|
||||
block until the first buffer becomes free for saving its
|
||||
data to disk (after BUZIOC_QBUF_CAPT) or for reuse (after BUZIOC_QBUF_PLAY).
|
||||
|
||||
BUZIOC_G_STATUS
|
||||
|
||||
Get the status of the input lines (video source connected/norm).
|
||||
This driver conforms to video4linux2. Support for V4L1 and for the custom
|
||||
zoran ioctls has been removed in kernel 2.6.38.
|
||||
|
||||
For programming example, please, look at lavrec.c and lavplay.c code in
|
||||
lavtools-1.2p2 package (URL: http://www.cicese.mx/)
|
||||
and the 'examples' directory in the original Buz driver distribution.
|
||||
the MJPEG-tools (http://mjpeg.sf.net/).
|
||||
|
||||
Additional notes for software developers:
|
||||
|
||||
|
@ -402,9 +337,6 @@ Additional notes for software developers:
|
|||
standard is "more constant" for current country than geometry
|
||||
settings of a variety of TV capture cards which may work in ITU or
|
||||
square pixel format.
|
||||
--
|
||||
Please note that lavplay/lavrec are also included in the MJPEG-tools
|
||||
(http://mjpeg.sf.net/).
|
||||
|
||||
===========================
|
||||
|
||||
|
|
|
@ -464,10 +464,6 @@ Siemens
|
|||
-------
|
||||
Multimedia eXtension Board (MXB) (SAA7146, SAA7111)
|
||||
|
||||
Stradis
|
||||
-------
|
||||
SDM275,SDM250,SDM026,SDM025 (SAA7146, IBMMPEG2): MPEG2 decoder only
|
||||
|
||||
Powercolor
|
||||
----------
|
||||
MTV878
|
||||
|
|
|
@ -366,6 +366,7 @@ t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops
|
|||
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
|
||||
pac207 2001:f115 D-Link DSB-C120
|
||||
sq905c 2770:9050 Disney pix micro (CIF)
|
||||
sq905c 2770:9051 Lego Bionicle
|
||||
sq905c 2770:9052 Disney pix micro 2 (VGA)
|
||||
sq905c 2770:905c All 11 known cameras with this ID
|
||||
sq905 2770:9120 All 24 known cameras with this ID
|
||||
|
|
|
@ -45,8 +45,6 @@ module argument syntax (<param>=<value> when passing the option to the
|
|||
module or meye.<param>=<value> on the kernel boot line when meye is
|
||||
statically linked into the kernel). Those options are:
|
||||
|
||||
forcev4l1: force use of V4L1 API instead of V4L2
|
||||
|
||||
gbuffers: number of capture buffers, default is 2 (32 max)
|
||||
|
||||
gbufsize: size of each capture buffer, default is 614400
|
||||
|
@ -79,9 +77,8 @@ Usage:
|
|||
Private API:
|
||||
------------
|
||||
|
||||
The driver supports frame grabbing with the video4linux API
|
||||
(either v4l1 or v4l2), so all video4linux tools (like xawtv)
|
||||
should work with this driver.
|
||||
The driver supports frame grabbing with the video4linux API,
|
||||
so all video4linux tools (like xawtv) should work with this driver.
|
||||
|
||||
Besides the video4linux interface, the driver has a private interface
|
||||
for accessing the Motion Eye extended parameters (camera sharpness,
|
||||
|
@ -123,7 +120,4 @@ Private API:
|
|||
Bugs / Todo:
|
||||
------------
|
||||
|
||||
- the driver could be much cleaned up by removing the v4l1 support.
|
||||
However, this means all v4l1-only applications will stop working.
|
||||
|
||||
- 'motioneye' still uses the meye private v4l1 API extensions.
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
/* 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).
|
||||
*
|
||||
*
|
||||
* For some cameras you may need to pre-load libv4l to perform
|
||||
* the necessary decompression, e.g.:
|
||||
*
|
||||
* export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
|
||||
* ./v4lgrab >image.ppm
|
||||
*
|
||||
* see http://hansdegoede.livejournal.com/3636.html for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 VIDEO_DEV "/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); \
|
||||
} \
|
||||
}
|
||||
|
||||
static 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(VIDEO_DEV, O_RDONLY), f;
|
||||
struct video_capability cap;
|
||||
struct video_window win;
|
||||
struct video_picture vpic;
|
||||
|
||||
unsigned char *buffer, *src;
|
||||
int bpp = 24, r = 0, g = 0, b = 0;
|
||||
unsigned int i, src_depth = 16;
|
||||
|
||||
if (fd < 0) {
|
||||
perror(VIDEO_DEV);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
|
||||
perror("VIDIOGCAP");
|
||||
fprintf(stderr, "(" VIDEO_DEV " 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;
|
||||
}
|
|
@ -247,8 +247,6 @@ calls. The relevant helper functions are:
|
|||
int nonblocking);
|
||||
int videobuf_streamon(struct videobuf_queue *q);
|
||||
int videobuf_streamoff(struct videobuf_queue *q);
|
||||
int videobuf_cgmbuf(struct videobuf_queue *q, struct video_mbuf *mbuf,
|
||||
int count);
|
||||
|
||||
So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's
|
||||
vidioc_reqbufs() callback which, in turn, usually only needs to locate the
|
||||
|
@ -258,10 +256,7 @@ boilerplate in a lot of V4L2 drivers.
|
|||
|
||||
The vidioc_streamon() and vidioc_streamoff() functions will be a bit more
|
||||
complex, of course, since they will also need to deal with starting and
|
||||
stopping the capture engine. videobuf_cgmbuf(), called from the driver's
|
||||
vidiocgmbuf() function, only exists if the V4L1 compatibility module has
|
||||
been selected with CONFIG_VIDEO_V4L1_COMPAT, so its use must be surrounded
|
||||
with #ifdef directives.
|
||||
stopping the capture engine.
|
||||
|
||||
Buffer allocation
|
||||
|
||||
|
|
|
@ -5754,12 +5754,6 @@ M: Ion Badulescu <ionut@badula.org>
|
|||
S: Odd Fixes
|
||||
F: drivers/net/starfire*
|
||||
|
||||
STRADIS MPEG-2 DECODER DRIVER
|
||||
M: Nathan Laredo <laredo@gnu.org>
|
||||
W: http://www.stradis.com/
|
||||
S: Maintained
|
||||
F: drivers/media/video/stradis.c
|
||||
|
||||
SUN3/3X
|
||||
M: Sam Creasey <sammy@sammy.net>
|
||||
W: http://sammy.net/sun3/
|
||||
|
|
|
@ -294,24 +294,6 @@ config INPUT_SGI_BTNS
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called sgi_btns.
|
||||
|
||||
config INPUT_WINBOND_CIR
|
||||
tristate "Winbond IR remote control"
|
||||
depends on X86 && PNP
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
select LEDS_TRIGGERS
|
||||
select BITREVERSE
|
||||
help
|
||||
Say Y here if you want to use the IR remote functionality found
|
||||
in some Winbond SuperI/O chips. Currently only the WPCD376I
|
||||
chip is supported (included in some Intel Media series motherboards).
|
||||
|
||||
IR Receive and wake-on-IR from suspend and power-off is currently
|
||||
supported.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called winbond_cir.
|
||||
|
||||
config HP_SDC_RTC
|
||||
tristate "HP SDC Real Time Clock"
|
||||
depends on (GSC || HP300) && SERIO
|
||||
|
|
|
@ -38,7 +38,6 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
|
|||
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
|
||||
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
|
||||
obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o
|
||||
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
|
||||
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
|
||||
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
|
||||
|
|
|
@ -1,356 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* some common structs and functions to handle infrared remotes via
|
||||
* input layer ...
|
||||
*
|
||||
* (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <media/ir-common.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int repeat = 1;
|
||||
module_param(repeat, int, 0444);
|
||||
MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
|
||||
{
|
||||
if (KEY_RESERVED == ir->keycode) {
|
||||
printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n",
|
||||
dev->name, ir->ir_key, ir->keypressed);
|
||||
return;
|
||||
}
|
||||
IR_dprintk(1,"%s: key event code=%d down=%d\n",
|
||||
dev->name,ir->keycode,ir->keypressed);
|
||||
input_report_key(dev,ir->keycode,ir->keypressed);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
|
||||
const u64 ir_type)
|
||||
{
|
||||
ir->ir_type = ir_type;
|
||||
|
||||
if (repeat)
|
||||
set_bit(EV_REP, dev->evbit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_input_init);
|
||||
|
||||
|
||||
void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
|
||||
{
|
||||
if (ir->keypressed) {
|
||||
ir->keypressed = 0;
|
||||
ir_input_key_event(dev,ir);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_input_nokey);
|
||||
|
||||
void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
|
||||
u32 ir_key)
|
||||
{
|
||||
u32 keycode = ir_g_keycode_from_table(dev, ir_key);
|
||||
|
||||
if (ir->keypressed && ir->keycode != keycode) {
|
||||
ir->keypressed = 0;
|
||||
ir_input_key_event(dev,ir);
|
||||
}
|
||||
if (!ir->keypressed) {
|
||||
ir->ir_key = ir_key;
|
||||
ir->keycode = keycode;
|
||||
ir->keypressed = 1;
|
||||
ir_input_key_event(dev,ir);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_input_keydown);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* extract mask bits out of data and pack them into the result */
|
||||
u32 ir_extract_bits(u32 data, u32 mask)
|
||||
{
|
||||
u32 vbit = 1, value = 0;
|
||||
|
||||
do {
|
||||
if (mask&1) {
|
||||
if (data&1)
|
||||
value |= vbit;
|
||||
vbit<<=1;
|
||||
}
|
||||
data>>=1;
|
||||
} while (mask>>=1);
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_extract_bits);
|
||||
|
||||
static int inline getbit(u32 *samples, int bit)
|
||||
{
|
||||
return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* sump raw samples for visual debugging ;) */
|
||||
int ir_dump_samples(u32 *samples, int count)
|
||||
{
|
||||
int i, bit, start;
|
||||
|
||||
printk(KERN_DEBUG "ir samples: ");
|
||||
start = 0;
|
||||
for (i = 0; i < count * 32; i++) {
|
||||
bit = getbit(samples,i);
|
||||
if (bit)
|
||||
start = 1;
|
||||
if (0 == start)
|
||||
continue;
|
||||
printk("%s", bit ? "#" : "_");
|
||||
}
|
||||
printk("\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_dump_samples);
|
||||
|
||||
/* decode raw samples, pulse distance coding used by NEC remotes */
|
||||
int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
|
||||
{
|
||||
int i,last,bit,len;
|
||||
u32 curBit;
|
||||
u32 value;
|
||||
|
||||
/* find start burst */
|
||||
for (i = len = 0; i < count * 32; i++) {
|
||||
bit = getbit(samples,i);
|
||||
if (bit) {
|
||||
len++;
|
||||
} else {
|
||||
if (len >= 29)
|
||||
break;
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* start burst to short */
|
||||
if (len < 29)
|
||||
return 0xffffffff;
|
||||
|
||||
/* find start silence */
|
||||
for (len = 0; i < count * 32; i++) {
|
||||
bit = getbit(samples,i);
|
||||
if (bit) {
|
||||
break;
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
/* silence to short */
|
||||
if (len < 7)
|
||||
return 0xffffffff;
|
||||
|
||||
/* go decoding */
|
||||
len = 0;
|
||||
last = 1;
|
||||
value = 0; curBit = 1;
|
||||
for (; i < count * 32; i++) {
|
||||
bit = getbit(samples,i);
|
||||
if (last) {
|
||||
if(bit) {
|
||||
continue;
|
||||
} else {
|
||||
len = 1;
|
||||
}
|
||||
} else {
|
||||
if (bit) {
|
||||
if (len > (low + high) /2)
|
||||
value |= curBit;
|
||||
curBit <<= 1;
|
||||
if (curBit == 1)
|
||||
break;
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
last = bit;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
|
||||
|
||||
/* decode raw samples, biphase coding, used by rc5 for example */
|
||||
int ir_decode_biphase(u32 *samples, int count, int low, int high)
|
||||
{
|
||||
int i,last,bit,len,flips;
|
||||
u32 value;
|
||||
|
||||
/* find start bit (1) */
|
||||
for (i = 0; i < 32; i++) {
|
||||
bit = getbit(samples,i);
|
||||
if (bit)
|
||||
break;
|
||||
}
|
||||
|
||||
/* go decoding */
|
||||
len = 0;
|
||||
flips = 0;
|
||||
value = 1;
|
||||
for (; i < count * 32; i++) {
|
||||
if (len > high)
|
||||
break;
|
||||
if (flips > 1)
|
||||
break;
|
||||
last = bit;
|
||||
bit = getbit(samples,i);
|
||||
if (last == bit) {
|
||||
len++;
|
||||
continue;
|
||||
}
|
||||
if (len < low) {
|
||||
len++;
|
||||
flips++;
|
||||
continue;
|
||||
}
|
||||
value <<= 1;
|
||||
value |= bit;
|
||||
flips = 0;
|
||||
len = 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_decode_biphase);
|
||||
|
||||
/* RC5 decoding stuff, moved from bttv-input.c to share it with
|
||||
* saa7134 */
|
||||
|
||||
/* decode raw bit pattern to RC5 code */
|
||||
u32 ir_rc5_decode(unsigned int code)
|
||||
{
|
||||
unsigned int org_code = code;
|
||||
unsigned int pair;
|
||||
unsigned int rc5 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 14; ++i) {
|
||||
pair = code & 0x3;
|
||||
code >>= 2;
|
||||
|
||||
rc5 <<= 1;
|
||||
switch (pair) {
|
||||
case 0:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
rc5 |= 1;
|
||||
break;
|
||||
case 3:
|
||||
IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
|
||||
"instr=%x\n", rc5, org_code, RC5_START(rc5),
|
||||
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
|
||||
return rc5;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_rc5_decode);
|
||||
|
||||
void ir_rc5_timer_end(unsigned long data)
|
||||
{
|
||||
struct card_ir *ir = (struct card_ir *)data;
|
||||
struct timeval tv;
|
||||
unsigned long current_jiffies, timeout;
|
||||
u32 gap;
|
||||
u32 rc5 = 0;
|
||||
|
||||
/* get time */
|
||||
current_jiffies = jiffies;
|
||||
do_gettimeofday(&tv);
|
||||
|
||||
/* avoid overflow with gap >1s */
|
||||
if (tv.tv_sec - ir->base_time.tv_sec > 1) {
|
||||
gap = 200000;
|
||||
} else {
|
||||
gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
|
||||
tv.tv_usec - ir->base_time.tv_usec;
|
||||
}
|
||||
|
||||
/* signal we're ready to start a new code */
|
||||
ir->active = 0;
|
||||
|
||||
/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
|
||||
if (gap < 28000) {
|
||||
IR_dprintk(1, "ir-common: spurious timer_end\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ir->last_bit < 20) {
|
||||
/* ignore spurious codes (caused by light/other remotes) */
|
||||
IR_dprintk(1, "ir-common: short code: %x\n", ir->code);
|
||||
} else {
|
||||
ir->code = (ir->code << ir->shift_by) | 1;
|
||||
rc5 = ir_rc5_decode(ir->code);
|
||||
|
||||
/* two start bits? */
|
||||
if (RC5_START(rc5) != ir->start) {
|
||||
IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
|
||||
|
||||
/* right address? */
|
||||
} else if (RC5_ADDR(rc5) == ir->addr) {
|
||||
u32 toggle = RC5_TOGGLE(rc5);
|
||||
u32 instr = RC5_INSTR(rc5);
|
||||
|
||||
/* Good code, decide if repeat/repress */
|
||||
if (toggle != RC5_TOGGLE(ir->last_rc5) ||
|
||||
instr != RC5_INSTR(ir->last_rc5)) {
|
||||
IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr,
|
||||
toggle);
|
||||
ir_input_nokey(ir->dev, &ir->ir);
|
||||
ir_input_keydown(ir->dev, &ir->ir, instr);
|
||||
}
|
||||
|
||||
/* Set/reset key-up timer */
|
||||
timeout = current_jiffies +
|
||||
msecs_to_jiffies(ir->rc5_key_timeout);
|
||||
mod_timer(&ir->timer_keyup, timeout);
|
||||
|
||||
/* Save code for repeat test */
|
||||
ir->last_rc5 = rc5;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
|
||||
|
||||
void ir_rc5_timer_keyup(unsigned long data)
|
||||
{
|
||||
struct card_ir *ir = (struct card_ir *)data;
|
||||
|
||||
IR_dprintk(1, "ir-common: key released\n");
|
||||
ir_input_nokey(ir->dev, &ir->ir);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
|
|
@ -1,710 +0,0 @@
|
|||
/* ir-keytable.c - handle IR scancode->keycode tables
|
||||
*
|
||||
* Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
|
||||
#define IR_TAB_MIN_SIZE 256
|
||||
#define IR_TAB_MAX_SIZE 8192
|
||||
|
||||
/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
|
||||
#define IR_KEYPRESS_TIMEOUT 250
|
||||
|
||||
/**
|
||||
* ir_create_table() - initializes a scancode table
|
||||
* @rc_tab: the ir_scancode_table to initialize
|
||||
* @name: name to assign to the table
|
||||
* @ir_type: ir type to assign to the new table
|
||||
* @size: initial size of the table
|
||||
* @return: zero on success or a negative error code
|
||||
*
|
||||
* This routine will initialize the ir_scancode_table and will allocate
|
||||
* memory to hold at least the specified number elements.
|
||||
*/
|
||||
static int ir_create_table(struct ir_scancode_table *rc_tab,
|
||||
const char *name, u64 ir_type, size_t size)
|
||||
{
|
||||
rc_tab->name = name;
|
||||
rc_tab->ir_type = ir_type;
|
||||
rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
|
||||
rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
|
||||
rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
|
||||
if (!rc_tab->scan)
|
||||
return -ENOMEM;
|
||||
|
||||
IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
|
||||
rc_tab->size, rc_tab->alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_free_table() - frees memory allocated by a scancode table
|
||||
* @rc_tab: the table whose mappings need to be freed
|
||||
*
|
||||
* This routine will free memory alloctaed for key mappings used by given
|
||||
* scancode table.
|
||||
*/
|
||||
static void ir_free_table(struct ir_scancode_table *rc_tab)
|
||||
{
|
||||
rc_tab->size = 0;
|
||||
kfree(rc_tab->scan);
|
||||
rc_tab->scan = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_resize_table() - resizes a scancode table if necessary
|
||||
* @rc_tab: the ir_scancode_table to resize
|
||||
* @gfp_flags: gfp flags to use when allocating memory
|
||||
* @return: zero on success or a negative error code
|
||||
*
|
||||
* This routine will shrink the ir_scancode_table if it has lots of
|
||||
* unused entries and grow it if it is full.
|
||||
*/
|
||||
static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
|
||||
{
|
||||
unsigned int oldalloc = rc_tab->alloc;
|
||||
unsigned int newalloc = oldalloc;
|
||||
struct ir_scancode *oldscan = rc_tab->scan;
|
||||
struct ir_scancode *newscan;
|
||||
|
||||
if (rc_tab->size == rc_tab->len) {
|
||||
/* All entries in use -> grow keytable */
|
||||
if (rc_tab->alloc >= IR_TAB_MAX_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
newalloc *= 2;
|
||||
IR_dprintk(1, "Growing table to %u bytes\n", newalloc);
|
||||
}
|
||||
|
||||
if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) {
|
||||
/* Less than 1/3 of entries in use -> shrink keytable */
|
||||
newalloc /= 2;
|
||||
IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc);
|
||||
}
|
||||
|
||||
if (newalloc == oldalloc)
|
||||
return 0;
|
||||
|
||||
newscan = kmalloc(newalloc, gfp_flags);
|
||||
if (!newscan) {
|
||||
IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode));
|
||||
rc_tab->scan = newscan;
|
||||
rc_tab->alloc = newalloc;
|
||||
rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
|
||||
kfree(oldscan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_update_mapping() - set a keycode in the scancode->keycode table
|
||||
* @dev: the struct input_dev device descriptor
|
||||
* @rc_tab: scancode table to be adjusted
|
||||
* @index: index of the mapping that needs to be updated
|
||||
* @keycode: the desired keycode
|
||||
* @return: previous keycode assigned to the mapping
|
||||
*
|
||||
* This routine is used to update scancode->keycopde mapping at given
|
||||
* position.
|
||||
*/
|
||||
static unsigned int ir_update_mapping(struct input_dev *dev,
|
||||
struct ir_scancode_table *rc_tab,
|
||||
unsigned int index,
|
||||
unsigned int new_keycode)
|
||||
{
|
||||
int old_keycode = rc_tab->scan[index].keycode;
|
||||
int i;
|
||||
|
||||
/* Did the user wish to remove the mapping? */
|
||||
if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
|
||||
IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
|
||||
index, rc_tab->scan[index].scancode);
|
||||
rc_tab->len--;
|
||||
memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
|
||||
(rc_tab->len - index) * sizeof(struct ir_scancode));
|
||||
} else {
|
||||
IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
|
||||
index,
|
||||
old_keycode == KEY_RESERVED ? "New" : "Replacing",
|
||||
rc_tab->scan[index].scancode, new_keycode);
|
||||
rc_tab->scan[index].keycode = new_keycode;
|
||||
__set_bit(new_keycode, dev->keybit);
|
||||
}
|
||||
|
||||
if (old_keycode != KEY_RESERVED) {
|
||||
/* A previous mapping was updated... */
|
||||
__clear_bit(old_keycode, dev->keybit);
|
||||
/* ... but another scancode might use the same keycode */
|
||||
for (i = 0; i < rc_tab->len; i++) {
|
||||
if (rc_tab->scan[i].keycode == old_keycode) {
|
||||
__set_bit(old_keycode, dev->keybit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Possibly shrink the keytable, failure is not a problem */
|
||||
ir_resize_table(rc_tab, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
return old_keycode;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_locate_scancode() - set a keycode in the scancode->keycode table
|
||||
* @ir_dev: the struct ir_input_dev device descriptor
|
||||
* @rc_tab: scancode table to be searched
|
||||
* @scancode: the desired scancode
|
||||
* @resize: controls whether we allowed to resize the table to
|
||||
* accomodate not yet present scancodes
|
||||
* @return: index of the mapping containing scancode in question
|
||||
* or -1U in case of failure.
|
||||
*
|
||||
* This routine is used to locate given scancode in ir_scancode_table.
|
||||
* If scancode is not yet present the routine will allocate a new slot
|
||||
* for it.
|
||||
*/
|
||||
static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
|
||||
struct ir_scancode_table *rc_tab,
|
||||
unsigned int scancode,
|
||||
bool resize)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Unfortunately, some hardware-based IR decoders don't provide
|
||||
* all bits for the complete IR code. In general, they provide only
|
||||
* the command part of the IR code. Yet, as it is possible to replace
|
||||
* the provided IR with another one, it is needed to allow loading
|
||||
* IR tables from other remotes. So,
|
||||
*/
|
||||
if (ir_dev->props && ir_dev->props->scanmask)
|
||||
scancode &= ir_dev->props->scanmask;
|
||||
|
||||
/* First check if we already have a mapping for this ir command */
|
||||
for (i = 0; i < rc_tab->len; i++) {
|
||||
if (rc_tab->scan[i].scancode == scancode)
|
||||
return i;
|
||||
|
||||
/* Keytable is sorted from lowest to highest scancode */
|
||||
if (rc_tab->scan[i].scancode >= scancode)
|
||||
break;
|
||||
}
|
||||
|
||||
/* No previous mapping found, we might need to grow the table */
|
||||
if (rc_tab->size == rc_tab->len) {
|
||||
if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
|
||||
return -1U;
|
||||
}
|
||||
|
||||
/* i is the proper index to insert our new keycode */
|
||||
if (i < rc_tab->len)
|
||||
memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
|
||||
(rc_tab->len - i) * sizeof(struct ir_scancode));
|
||||
rc_tab->scan[i].scancode = scancode;
|
||||
rc_tab->scan[i].keycode = KEY_RESERVED;
|
||||
rc_tab->len++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_setkeycode() - set a keycode in the scancode->keycode table
|
||||
* @dev: the struct input_dev device descriptor
|
||||
* @scancode: the desired scancode
|
||||
* @keycode: result
|
||||
* @return: -EINVAL if the keycode could not be inserted, otherwise zero.
|
||||
*
|
||||
* This routine is used to handle evdev EVIOCSKEY ioctl.
|
||||
*/
|
||||
static int ir_setkeycode(struct input_dev *dev,
|
||||
const struct input_keymap_entry *ke,
|
||||
unsigned int *old_keycode)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
|
||||
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
|
||||
unsigned int index;
|
||||
unsigned int scancode;
|
||||
int retval;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rc_tab->lock, flags);
|
||||
|
||||
if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
|
||||
index = ke->index;
|
||||
if (index >= rc_tab->len) {
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
retval = input_scancode_to_scalar(ke, &scancode);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
|
||||
if (index >= rc_tab->len) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
*old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&rc_tab->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_setkeytable() - sets several entries in the scancode->keycode table
|
||||
* @dev: the struct input_dev device descriptor
|
||||
* @to: the struct ir_scancode_table to copy entries to
|
||||
* @from: the struct ir_scancode_table to copy entries from
|
||||
* @return: -ENOMEM if all keycodes could not be inserted, otherwise zero.
|
||||
*
|
||||
* This routine is used to handle table initialization.
|
||||
*/
|
||||
static int ir_setkeytable(struct ir_input_dev *ir_dev,
|
||||
const struct ir_scancode_table *from)
|
||||
{
|
||||
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
|
||||
unsigned int i, index;
|
||||
int rc;
|
||||
|
||||
rc = ir_create_table(&ir_dev->rc_tab,
|
||||
from->name, from->ir_type, from->size);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
|
||||
rc_tab->size, rc_tab->alloc);
|
||||
|
||||
for (i = 0; i < from->size; i++) {
|
||||
index = ir_establish_scancode(ir_dev, rc_tab,
|
||||
from->scan[i].scancode, false);
|
||||
if (index >= rc_tab->len) {
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
ir_update_mapping(ir_dev->input_dev, rc_tab, index,
|
||||
from->scan[i].keycode);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
ir_free_table(rc_tab);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_lookup_by_scancode() - locate mapping by scancode
|
||||
* @rc_tab: the &struct ir_scancode_table to search
|
||||
* @scancode: scancode to look for in the table
|
||||
* @return: index in the table, -1U if not found
|
||||
*
|
||||
* This routine performs binary search in RC keykeymap table for
|
||||
* given scancode.
|
||||
*/
|
||||
static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
|
||||
unsigned int scancode)
|
||||
{
|
||||
int start = 0;
|
||||
int end = rc_tab->len - 1;
|
||||
int mid;
|
||||
|
||||
while (start <= end) {
|
||||
mid = (start + end) / 2;
|
||||
if (rc_tab->scan[mid].scancode < scancode)
|
||||
start = mid + 1;
|
||||
else if (rc_tab->scan[mid].scancode > scancode)
|
||||
end = mid - 1;
|
||||
else
|
||||
return mid;
|
||||
}
|
||||
|
||||
return -1U;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_getkeycode() - get a keycode from the scancode->keycode table
|
||||
* @dev: the struct input_dev device descriptor
|
||||
* @scancode: the desired scancode
|
||||
* @keycode: used to return the keycode, if found, or KEY_RESERVED
|
||||
* @return: always returns zero.
|
||||
*
|
||||
* This routine is used to handle evdev EVIOCGKEY ioctl.
|
||||
*/
|
||||
static int ir_getkeycode(struct input_dev *dev,
|
||||
struct input_keymap_entry *ke)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
|
||||
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
|
||||
struct ir_scancode *entry;
|
||||
unsigned long flags;
|
||||
unsigned int index;
|
||||
unsigned int scancode;
|
||||
int retval;
|
||||
|
||||
spin_lock_irqsave(&rc_tab->lock, flags);
|
||||
|
||||
if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
|
||||
index = ke->index;
|
||||
} else {
|
||||
retval = input_scancode_to_scalar(ke, &scancode);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
index = ir_lookup_by_scancode(rc_tab, scancode);
|
||||
}
|
||||
|
||||
if (index >= rc_tab->len) {
|
||||
if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
|
||||
IR_dprintk(1, "unknown key for scancode 0x%04x\n",
|
||||
scancode);
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
entry = &rc_tab->scan[index];
|
||||
|
||||
ke->index = index;
|
||||
ke->keycode = entry->keycode;
|
||||
ke->len = sizeof(entry->scancode);
|
||||
memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&rc_tab->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @scancode: the scancode that we're seeking
|
||||
*
|
||||
* This routine is used by the input routines when a key is pressed at the
|
||||
* IR. The scancode is received and needs to be converted into a keycode.
|
||||
* If the key is not found, it returns KEY_RESERVED. Otherwise, returns the
|
||||
* corresponding keycode from the table.
|
||||
*/
|
||||
u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
|
||||
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
|
||||
unsigned int keycode;
|
||||
unsigned int index;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rc_tab->lock, flags);
|
||||
|
||||
index = ir_lookup_by_scancode(rc_tab, scancode);
|
||||
keycode = index < rc_tab->len ?
|
||||
rc_tab->scan[index].keycode : KEY_RESERVED;
|
||||
|
||||
spin_unlock_irqrestore(&rc_tab->lock, flags);
|
||||
|
||||
if (keycode != KEY_RESERVED)
|
||||
IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
|
||||
dev->name, scancode, keycode);
|
||||
|
||||
return keycode;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
|
||||
|
||||
/**
|
||||
* ir_keyup() - generates input event to cleanup a key press
|
||||
* @ir: the struct ir_input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used to signal that a key has been released on the
|
||||
* remote control. It reports a keyup input event via input_report_key().
|
||||
*/
|
||||
void ir_keyup(struct ir_input_dev *ir)
|
||||
{
|
||||
if (!ir->keypressed)
|
||||
return;
|
||||
|
||||
IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode);
|
||||
input_report_key(ir->input_dev, ir->last_keycode, 0);
|
||||
input_sync(ir->input_dev);
|
||||
ir->keypressed = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_keyup);
|
||||
|
||||
/**
|
||||
* ir_timer_keyup() - generates a keyup event after a timeout
|
||||
* @cookie: a pointer to struct ir_input_dev passed to setup_timer()
|
||||
*
|
||||
* This routine will generate a keyup event some time after a keydown event
|
||||
* is generated when no further activity has been detected.
|
||||
*/
|
||||
static void ir_timer_keyup(unsigned long cookie)
|
||||
{
|
||||
struct ir_input_dev *ir = (struct ir_input_dev *)cookie;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* ir->keyup_jiffies is used to prevent a race condition if a
|
||||
* hardware interrupt occurs at this point and the keyup timer
|
||||
* event is moved further into the future as a result.
|
||||
*
|
||||
* The timer will then be reactivated and this function called
|
||||
* again in the future. We need to exit gracefully in that case
|
||||
* to allow the input subsystem to do its auto-repeat magic or
|
||||
* a keyup event might follow immediately after the keydown.
|
||||
*/
|
||||
spin_lock_irqsave(&ir->keylock, flags);
|
||||
if (time_is_before_eq_jiffies(ir->keyup_jiffies))
|
||||
ir_keyup(ir);
|
||||
spin_unlock_irqrestore(&ir->keylock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_repeat() - notifies the IR core that a key is still pressed
|
||||
* @dev: the struct input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used by IR decoders when a repeat message which does
|
||||
* not include the necessary bits to reproduce the scancode has been
|
||||
* received.
|
||||
*/
|
||||
void ir_repeat(struct input_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct ir_input_dev *ir = input_get_drvdata(dev);
|
||||
|
||||
spin_lock_irqsave(&ir->keylock, flags);
|
||||
|
||||
input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
|
||||
|
||||
if (!ir->keypressed)
|
||||
goto out;
|
||||
|
||||
ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
|
||||
mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&ir->keylock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_repeat);
|
||||
|
||||
/**
|
||||
* ir_keydown() - generates input event for a key press
|
||||
* @dev: the struct input_dev descriptor of the device
|
||||
* @scancode: the scancode that we're seeking
|
||||
* @toggle: the toggle value (protocol dependent, if the protocol doesn't
|
||||
* support toggle values, this should be set to zero)
|
||||
*
|
||||
* This routine is used by the input routines when a key is pressed at the
|
||||
* IR. It gets the keycode for a scancode and reports an input event via
|
||||
* input_report_key().
|
||||
*/
|
||||
void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct ir_input_dev *ir = input_get_drvdata(dev);
|
||||
|
||||
u32 keycode = ir_g_keycode_from_table(dev, scancode);
|
||||
|
||||
spin_lock_irqsave(&ir->keylock, flags);
|
||||
|
||||
input_event(dev, EV_MSC, MSC_SCAN, scancode);
|
||||
|
||||
/* Repeat event? */
|
||||
if (ir->keypressed &&
|
||||
ir->last_scancode == scancode &&
|
||||
ir->last_toggle == toggle)
|
||||
goto set_timer;
|
||||
|
||||
/* Release old keypress */
|
||||
ir_keyup(ir);
|
||||
|
||||
ir->last_scancode = scancode;
|
||||
ir->last_toggle = toggle;
|
||||
ir->last_keycode = keycode;
|
||||
|
||||
|
||||
if (keycode == KEY_RESERVED)
|
||||
goto out;
|
||||
|
||||
|
||||
/* Register a keypress */
|
||||
ir->keypressed = true;
|
||||
IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
|
||||
dev->name, keycode, scancode);
|
||||
input_report_key(dev, ir->last_keycode, 1);
|
||||
input_sync(dev);
|
||||
|
||||
set_timer:
|
||||
ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
|
||||
mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
|
||||
out:
|
||||
spin_unlock_irqrestore(&ir->keylock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_keydown);
|
||||
|
||||
static int ir_open(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
return ir_dev->props->open(ir_dev->props->priv);
|
||||
}
|
||||
|
||||
static void ir_close(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
ir_dev->props->close(ir_dev->props->priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* __ir_input_register() - sets the IR keycode table and add the handlers
|
||||
* for keymap table get/set
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @rc_tab: the struct ir_scancode_table table of scancode/keymap
|
||||
*
|
||||
* This routine is used to initialize the input infrastructure
|
||||
* to work with an IR.
|
||||
* It will register the input/evdev interface for the device and
|
||||
* register the syfs code for IR class
|
||||
*/
|
||||
int __ir_input_register(struct input_dev *input_dev,
|
||||
const struct ir_scancode_table *rc_tab,
|
||||
struct ir_dev_props *props,
|
||||
const char *driver_name)
|
||||
{
|
||||
struct ir_input_dev *ir_dev;
|
||||
int rc;
|
||||
|
||||
if (rc_tab->scan == NULL || !rc_tab->size)
|
||||
return -EINVAL;
|
||||
|
||||
ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
|
||||
if (!ir_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name);
|
||||
if (!ir_dev->driver_name) {
|
||||
rc = -ENOMEM;
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
input_dev->getkeycode_new = ir_getkeycode;
|
||||
input_dev->setkeycode_new = ir_setkeycode;
|
||||
input_set_drvdata(input_dev, ir_dev);
|
||||
ir_dev->input_dev = input_dev;
|
||||
|
||||
spin_lock_init(&ir_dev->rc_tab.lock);
|
||||
spin_lock_init(&ir_dev->keylock);
|
||||
setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
|
||||
|
||||
if (props) {
|
||||
ir_dev->props = props;
|
||||
if (props->open)
|
||||
input_dev->open = ir_open;
|
||||
if (props->close)
|
||||
input_dev->close = ir_close;
|
||||
}
|
||||
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
set_bit(EV_REP, input_dev->evbit);
|
||||
set_bit(EV_MSC, input_dev->evbit);
|
||||
set_bit(MSC_SCAN, input_dev->mscbit);
|
||||
|
||||
rc = ir_setkeytable(ir_dev, rc_tab);
|
||||
if (rc)
|
||||
goto out_name;
|
||||
|
||||
rc = ir_register_class(input_dev);
|
||||
if (rc < 0)
|
||||
goto out_table;
|
||||
|
||||
if (ir_dev->props)
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
|
||||
rc = ir_raw_event_register(input_dev);
|
||||
if (rc < 0)
|
||||
goto out_event;
|
||||
}
|
||||
|
||||
rc = ir_register_input(input_dev);
|
||||
if (rc < 0)
|
||||
goto out_event;
|
||||
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
|
||||
driver_name, rc_tab->name,
|
||||
(ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
|
||||
" in raw mode" : "");
|
||||
|
||||
/*
|
||||
* Default delay of 250ms is too short for some protocols, expecially
|
||||
* since the timeout is currently set to 250ms. Increase it to 500ms,
|
||||
* to avoid wrong repetition of the keycodes.
|
||||
*/
|
||||
input_dev->rep[REP_DELAY] = 500;
|
||||
|
||||
return 0;
|
||||
|
||||
out_event:
|
||||
ir_unregister_class(input_dev);
|
||||
out_table:
|
||||
ir_free_table(&ir_dev->rc_tab);
|
||||
out_name:
|
||||
kfree(ir_dev->driver_name);
|
||||
out_dev:
|
||||
kfree(ir_dev);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__ir_input_register);
|
||||
|
||||
/**
|
||||
* ir_input_unregister() - unregisters IR and frees resources
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
||||
* This routine is used to free memory and de-register interfaces.
|
||||
*/
|
||||
void ir_input_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
if (!ir_dev)
|
||||
return;
|
||||
|
||||
IR_dprintk(1, "Freed keycode table\n");
|
||||
|
||||
del_timer_sync(&ir_dev->timer_keyup);
|
||||
if (ir_dev->props)
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
|
||||
ir_raw_event_unregister(input_dev);
|
||||
|
||||
ir_free_table(&ir_dev->rc_tab);
|
||||
|
||||
ir_unregister_class(input_dev);
|
||||
|
||||
kfree(ir_dev->driver_name);
|
||||
kfree(ir_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_input_unregister);
|
||||
|
||||
int ir_core_debug; /* ir_debug level (0,1,2) */
|
||||
EXPORT_SYMBOL_GPL(ir_core_debug);
|
||||
module_param_named(debug, ir_core_debug, int, 0644);
|
||||
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,362 +0,0 @@
|
|||
/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc)
|
||||
*
|
||||
* Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/device.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
#define IRRCV_NUM_DEVICES 256
|
||||
|
||||
/* bit array to represent IR sysfs device number */
|
||||
static unsigned long ir_core_dev_number;
|
||||
|
||||
/* class for /sys/class/rc */
|
||||
static char *ir_devnode(struct device *dev, mode_t *mode)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
|
||||
}
|
||||
|
||||
static struct class ir_input_class = {
|
||||
.name = "rc",
|
||||
.devnode = ir_devnode,
|
||||
};
|
||||
|
||||
static struct {
|
||||
u64 type;
|
||||
char *name;
|
||||
} proto_names[] = {
|
||||
{ IR_TYPE_UNKNOWN, "unknown" },
|
||||
{ IR_TYPE_RC5, "rc-5" },
|
||||
{ IR_TYPE_NEC, "nec" },
|
||||
{ IR_TYPE_RC6, "rc-6" },
|
||||
{ IR_TYPE_JVC, "jvc" },
|
||||
{ IR_TYPE_SONY, "sony" },
|
||||
{ IR_TYPE_RC5_SZ, "rc-5-sz" },
|
||||
{ IR_TYPE_LIRC, "lirc" },
|
||||
};
|
||||
|
||||
#define PROTO_NONE "none"
|
||||
|
||||
/**
|
||||
* show_protocols() - shows the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the output buffer
|
||||
*
|
||||
* This routine is a callback routine for input read the IR protocol type(s).
|
||||
* it is trigged by reading /sys/class/rc/rc?/protocols.
|
||||
* It returns the protocol names of supported protocols.
|
||||
* Enabled protocols are printed in brackets.
|
||||
*/
|
||||
static ssize_t show_protocols(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 allowed, enabled;
|
||||
char *tmp = buf;
|
||||
int i;
|
||||
|
||||
/* Device is being removed */
|
||||
if (!ir_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
enabled = ir_dev->rc_tab.ir_type;
|
||||
allowed = ir_dev->props->allowed_protos;
|
||||
} else if (ir_dev->raw) {
|
||||
enabled = ir_dev->raw->enabled_protocols;
|
||||
allowed = ir_raw_get_allowed_protocols();
|
||||
} else
|
||||
return sprintf(tmp, "[builtin]\n");
|
||||
|
||||
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
|
||||
(long long)allowed,
|
||||
(long long)enabled);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (allowed & enabled & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
|
||||
else if (allowed & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "%s ", proto_names[i].name);
|
||||
}
|
||||
|
||||
if (tmp != buf)
|
||||
tmp--;
|
||||
*tmp = '\n';
|
||||
return tmp + 1 - buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* store_protocols() - changes the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the input buffer
|
||||
* @len: length of the input buffer
|
||||
*
|
||||
* This routine is a callback routine for changing the IR protocol type.
|
||||
* It is trigged by writing to /sys/class/rc/rc?/protocols.
|
||||
* Writing "+proto" will add a protocol to the list of enabled protocols.
|
||||
* Writing "-proto" will remove a protocol from the list of enabled protocols.
|
||||
* Writing "proto" will enable only "proto".
|
||||
* Writing "none" will disable all protocols.
|
||||
* Returns -EINVAL if an invalid protocol combination or unknown protocol name
|
||||
* is used, otherwise @len.
|
||||
*/
|
||||
static ssize_t store_protocols(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
bool enable, disable;
|
||||
const char *tmp;
|
||||
u64 type;
|
||||
u64 mask;
|
||||
int rc, i, count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* Device is being removed */
|
||||
if (!ir_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
type = ir_dev->rc_tab.ir_type;
|
||||
else if (ir_dev->raw)
|
||||
type = ir_dev->raw->enabled_protocols;
|
||||
else {
|
||||
IR_dprintk(1, "Protocol switching not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
|
||||
if (!*tmp)
|
||||
break;
|
||||
|
||||
if (*tmp == '+') {
|
||||
enable = true;
|
||||
disable = false;
|
||||
tmp++;
|
||||
} else if (*tmp == '-') {
|
||||
enable = false;
|
||||
disable = true;
|
||||
tmp++;
|
||||
} else {
|
||||
enable = false;
|
||||
disable = false;
|
||||
}
|
||||
|
||||
if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
|
||||
tmp += sizeof(PROTO_NONE);
|
||||
mask = 0;
|
||||
count++;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
|
||||
tmp += strlen(proto_names[i].name);
|
||||
mask = proto_names[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(proto_names)) {
|
||||
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
type |= mask;
|
||||
else if (disable)
|
||||
type &= ~mask;
|
||||
else
|
||||
type = mask;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
IR_dprintk(1, "Protocol not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->change_protocol) {
|
||||
rc = ir_dev->props->change_protocol(ir_dev->props->priv,
|
||||
type);
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
|
||||
(long long)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
} else {
|
||||
ir_dev->raw->enabled_protocols = type;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
|
||||
(long long)type);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#define ADD_HOTPLUG_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(env, fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(device);
|
||||
|
||||
if (ir_dev->rc_tab.name)
|
||||
ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name);
|
||||
if (ir_dev->driver_name)
|
||||
ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Static device attribute struct with the sysfs attributes for IR's
|
||||
*/
|
||||
static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
|
||||
show_protocols, store_protocols);
|
||||
|
||||
static struct attribute *rc_dev_attrs[] = {
|
||||
&dev_attr_protocols.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group rc_dev_attr_grp = {
|
||||
.attrs = rc_dev_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *rc_dev_attr_groups[] = {
|
||||
&rc_dev_attr_grp,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct device_type rc_dev_type = {
|
||||
.groups = rc_dev_attr_groups,
|
||||
.uevent = rc_dev_uevent,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_register_class() - creates the sysfs for /sys/class/rc/rc?
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used to register the syfs code for IR class
|
||||
*/
|
||||
int ir_register_class(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int devno = find_first_zero_bit(&ir_core_dev_number,
|
||||
IRRCV_NUM_DEVICES);
|
||||
|
||||
if (unlikely(devno < 0))
|
||||
return devno;
|
||||
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
ir_dev->devno = devno;
|
||||
|
||||
ir_dev->dev.class = &ir_input_class;
|
||||
ir_dev->dev.parent = input_dev->dev.parent;
|
||||
input_dev->dev.parent = &ir_dev->dev;
|
||||
dev_set_name(&ir_dev->dev, "rc%d", devno);
|
||||
dev_set_drvdata(&ir_dev->dev, ir_dev);
|
||||
return device_register(&ir_dev->dev);
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_register_input - registers ir input device with input subsystem
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*/
|
||||
|
||||
int ir_register_input(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
const char *path;
|
||||
|
||||
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0) {
|
||||
device_del(&ir_dev->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL);
|
||||
printk(KERN_INFO "%s: %s as %s\n",
|
||||
dev_name(&ir_dev->dev),
|
||||
input_dev->name ? input_dev->name : "Unspecified device",
|
||||
path ? path : "N/A");
|
||||
kfree(path);
|
||||
|
||||
set_bit(ir_dev->devno, &ir_core_dev_number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_unregister_class() - removes the sysfs for sysfs for
|
||||
* /sys/class/rc/rc?
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used to unregister the syfs code for IR class
|
||||
*/
|
||||
void ir_unregister_class(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
input_set_drvdata(input_dev, NULL);
|
||||
clear_bit(ir_dev->devno, &ir_core_dev_number);
|
||||
input_unregister_device(input_dev);
|
||||
device_del(&ir_dev->dev);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init/exit code for the module. Basically, creates/removes /sys/class/rc
|
||||
*/
|
||||
|
||||
static int __init ir_core_init(void)
|
||||
{
|
||||
int rc = class_register(&ir_input_class);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "ir_core: unable to register rc class\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Initialize/load the decoders/keymap code that will be used */
|
||||
ir_raw_init();
|
||||
ir_rcmap_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ir_core_exit(void)
|
||||
{
|
||||
class_unregister(&ir_input_class);
|
||||
ir_rcmap_cleanup();
|
||||
}
|
||||
|
||||
module_init(ir_core_init);
|
||||
module_exit(ir_core_exit);
|
|
@ -1,73 +0,0 @@
|
|||
/* tbs-nec.h - Keytable for tbs_nec Remote Controller
|
||||
*
|
||||
* keymap imported from ir-keymaps.c
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode tbs_nec[] = {
|
||||
{ 0x04, KEY_POWER2}, /*power*/
|
||||
{ 0x14, KEY_MUTE}, /*mute*/
|
||||
{ 0x07, KEY_1},
|
||||
{ 0x06, KEY_2},
|
||||
{ 0x05, KEY_3},
|
||||
{ 0x0b, KEY_4},
|
||||
{ 0x0a, KEY_5},
|
||||
{ 0x09, KEY_6},
|
||||
{ 0x0f, KEY_7},
|
||||
{ 0x0e, KEY_8},
|
||||
{ 0x0d, KEY_9},
|
||||
{ 0x12, KEY_0},
|
||||
{ 0x16, KEY_CHANNELUP}, /*ch+*/
|
||||
{ 0x11, KEY_CHANNELDOWN},/*ch-*/
|
||||
{ 0x13, KEY_VOLUMEUP}, /*vol+*/
|
||||
{ 0x0c, KEY_VOLUMEDOWN},/*vol-*/
|
||||
{ 0x03, KEY_RECORD}, /*rec*/
|
||||
{ 0x18, KEY_PAUSE}, /*pause*/
|
||||
{ 0x19, KEY_OK}, /*ok*/
|
||||
{ 0x1a, KEY_CAMERA}, /* snapshot */
|
||||
{ 0x01, KEY_UP},
|
||||
{ 0x10, KEY_LEFT},
|
||||
{ 0x02, KEY_RIGHT},
|
||||
{ 0x08, KEY_DOWN},
|
||||
{ 0x15, KEY_FAVORITES},
|
||||
{ 0x17, KEY_SUBTITLE},
|
||||
{ 0x1d, KEY_ZOOM},
|
||||
{ 0x1f, KEY_EXIT},
|
||||
{ 0x1e, KEY_MENU},
|
||||
{ 0x1c, KEY_EPG},
|
||||
{ 0x00, KEY_PREVIOUS},
|
||||
{ 0x1b, KEY_MODE},
|
||||
};
|
||||
|
||||
static struct rc_keymap tbs_nec_map = {
|
||||
.map = {
|
||||
.scan = tbs_nec,
|
||||
.size = ARRAY_SIZE(tbs_nec),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.name = RC_MAP_TBS_NEC,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_tbs_nec(void)
|
||||
{
|
||||
return ir_register_map(&tbs_nec_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_tbs_nec(void)
|
||||
{
|
||||
ir_unregister_map(&tbs_nec_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_tbs_nec)
|
||||
module_exit(exit_rc_map_tbs_nec)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
|
@ -1,82 +0,0 @@
|
|||
/* tt-1500.h - Keytable for tt_1500 Remote Controller
|
||||
*
|
||||
* keymap imported from ir-keymaps.c
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
/* for the Technotrend 1500 bundled remotes (grey and black): */
|
||||
|
||||
static struct ir_scancode tt_1500[] = {
|
||||
{ 0x01, KEY_POWER },
|
||||
{ 0x02, KEY_SHUFFLE }, /* ? double-arrow key */
|
||||
{ 0x03, KEY_1 },
|
||||
{ 0x04, KEY_2 },
|
||||
{ 0x05, KEY_3 },
|
||||
{ 0x06, KEY_4 },
|
||||
{ 0x07, KEY_5 },
|
||||
{ 0x08, KEY_6 },
|
||||
{ 0x09, KEY_7 },
|
||||
{ 0x0a, KEY_8 },
|
||||
{ 0x0b, KEY_9 },
|
||||
{ 0x0c, KEY_0 },
|
||||
{ 0x0d, KEY_UP },
|
||||
{ 0x0e, KEY_LEFT },
|
||||
{ 0x0f, KEY_OK },
|
||||
{ 0x10, KEY_RIGHT },
|
||||
{ 0x11, KEY_DOWN },
|
||||
{ 0x12, KEY_INFO },
|
||||
{ 0x13, KEY_EXIT },
|
||||
{ 0x14, KEY_RED },
|
||||
{ 0x15, KEY_GREEN },
|
||||
{ 0x16, KEY_YELLOW },
|
||||
{ 0x17, KEY_BLUE },
|
||||
{ 0x18, KEY_MUTE },
|
||||
{ 0x19, KEY_TEXT },
|
||||
{ 0x1a, KEY_MODE }, /* ? TV/Radio */
|
||||
{ 0x21, KEY_OPTION },
|
||||
{ 0x22, KEY_EPG },
|
||||
{ 0x23, KEY_CHANNELUP },
|
||||
{ 0x24, KEY_CHANNELDOWN },
|
||||
{ 0x25, KEY_VOLUMEUP },
|
||||
{ 0x26, KEY_VOLUMEDOWN },
|
||||
{ 0x27, KEY_SETUP },
|
||||
{ 0x3a, KEY_RECORD }, /* these keys are only in the black remote */
|
||||
{ 0x3b, KEY_PLAY },
|
||||
{ 0x3c, KEY_STOP },
|
||||
{ 0x3d, KEY_REWIND },
|
||||
{ 0x3e, KEY_PAUSE },
|
||||
{ 0x3f, KEY_FORWARD },
|
||||
};
|
||||
|
||||
static struct rc_keymap tt_1500_map = {
|
||||
.map = {
|
||||
.scan = tt_1500,
|
||||
.size = ARRAY_SIZE(tt_1500),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.name = RC_MAP_TT_1500,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_tt_1500(void)
|
||||
{
|
||||
return ir_register_map(&tt_1500_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_tt_1500(void)
|
||||
{
|
||||
ir_unregister_map(&tt_1500_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_tt_1500)
|
||||
module_exit(exit_rc_map_tt_1500)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
|
@ -1,107 +0,0 @@
|
|||
/* ir-raw-event.c - handle IR Pulse/Space event
|
||||
*
|
||||
* Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <media/ir-core.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static LIST_HEAD(rc_map_list);
|
||||
static DEFINE_SPINLOCK(rc_map_lock);
|
||||
|
||||
static struct rc_keymap *seek_rc_map(const char *name)
|
||||
{
|
||||
struct rc_keymap *map = NULL;
|
||||
|
||||
spin_lock(&rc_map_lock);
|
||||
list_for_each_entry(map, &rc_map_list, list) {
|
||||
if (!strcmp(name, map->map.name)) {
|
||||
spin_unlock(&rc_map_lock);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
spin_unlock(&rc_map_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ir_scancode_table *get_rc_map(const char *name)
|
||||
{
|
||||
|
||||
struct rc_keymap *map;
|
||||
|
||||
map = seek_rc_map(name);
|
||||
#ifdef MODULE
|
||||
if (!map) {
|
||||
int rc = request_module(name);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
msleep(20); /* Give some time for IR to register */
|
||||
|
||||
map = seek_rc_map(name);
|
||||
}
|
||||
#endif
|
||||
if (!map) {
|
||||
printk(KERN_ERR "IR keymap %s not found\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
|
||||
|
||||
return &map->map;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_rc_map);
|
||||
|
||||
int ir_register_map(struct rc_keymap *map)
|
||||
{
|
||||
spin_lock(&rc_map_lock);
|
||||
list_add_tail(&map->list, &rc_map_list);
|
||||
spin_unlock(&rc_map_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_register_map);
|
||||
|
||||
void ir_unregister_map(struct rc_keymap *map)
|
||||
{
|
||||
spin_lock(&rc_map_lock);
|
||||
list_del(&map->list);
|
||||
spin_unlock(&rc_map_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_unregister_map);
|
||||
|
||||
|
||||
static struct ir_scancode empty[] = {
|
||||
{ 0x2a, KEY_COFFEE },
|
||||
};
|
||||
|
||||
static struct rc_keymap empty_map = {
|
||||
.map = {
|
||||
.scan = empty,
|
||||
.size = ARRAY_SIZE(empty),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.name = RC_MAP_EMPTY,
|
||||
}
|
||||
};
|
||||
|
||||
int ir_rcmap_init(void)
|
||||
{
|
||||
return ir_register_map(&empty_map);
|
||||
}
|
||||
|
||||
void ir_rcmap_cleanup(void)
|
||||
{
|
||||
ir_unregister_map(&empty_map);
|
||||
}
|
|
@ -40,35 +40,6 @@ config VIDEO_V4L2_COMMON
|
|||
depends on (I2C || I2C=n) && VIDEO_DEV
|
||||
default (I2C || I2C=n) && VIDEO_DEV
|
||||
|
||||
config VIDEO_ALLOW_V4L1
|
||||
bool "Enable Video For Linux API 1 (DEPRECATED)"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
|
||||
default VIDEO_DEV && VIDEO_V4L2_COMMON
|
||||
---help---
|
||||
Enables drivers based on the legacy V4L1 API.
|
||||
|
||||
This api were developed to be used at Kernel 2.2 and 2.4, but
|
||||
lacks support for several video standards. There are several
|
||||
drivers at kernel that still depends on it.
|
||||
|
||||
If you are unsure as to whether this is required, answer Y.
|
||||
|
||||
config VIDEO_V4L1_COMPAT
|
||||
bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1
|
||||
depends on VIDEO_DEV
|
||||
default y
|
||||
---help---
|
||||
Enables a compatibility API used by most V4L2 devices to allow
|
||||
its usage with legacy applications that supports only V4L1 api.
|
||||
|
||||
Documentation for the original API is included in the file
|
||||
<Documentation/video4linux/API.html>.
|
||||
|
||||
User tools for this are available from
|
||||
<ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
|
||||
|
||||
If you are unsure as to whether this is required, answer Y.
|
||||
|
||||
#
|
||||
# DVB Core
|
||||
#
|
||||
|
@ -99,7 +70,7 @@ config VIDEO_MEDIA
|
|||
comment "Multimedia drivers"
|
||||
|
||||
source "drivers/media/common/Kconfig"
|
||||
source "drivers/media/IR/Kconfig"
|
||||
source "drivers/media/rc/Kconfig"
|
||||
|
||||
#
|
||||
# Tuner drivers for DVB and V4L
|
||||
|
@ -121,26 +92,4 @@ source "drivers/media/radio/Kconfig"
|
|||
|
||||
source "drivers/media/dvb/Kconfig"
|
||||
|
||||
config DAB
|
||||
boolean "DAB adapters"
|
||||
---help---
|
||||
Allow selecting support for Digital Audio Broadcasting (DAB)
|
||||
Receiver adapters.
|
||||
|
||||
if DAB
|
||||
config USB_DABUSB
|
||||
tristate "DABUSB driver"
|
||||
depends on USB
|
||||
---help---
|
||||
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
|
||||
brought to you by the DAB-Team
|
||||
<http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
|
||||
as an example for URB-based bulk, control, and isochronous
|
||||
transactions. URB's are explained in
|
||||
<Documentation/usb/URB.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dabusb.
|
||||
endif # DAB
|
||||
|
||||
endif # MEDIA_SUPPORT
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Makefile for the kernel multimedia device drivers.
|
||||
#
|
||||
|
||||
obj-y += common/ IR/ video/
|
||||
obj-y += common/ rc/ video/
|
||||
|
||||
obj-$(CONFIG_VIDEO_DEV) += radio/
|
||||
obj-$(CONFIG_DVB_CORE) += dvb/
|
||||
|
|
|
@ -1129,35 +1129,6 @@ static int vidioc_g_chip_ident(struct file *file, void *__fh,
|
|||
core, g_chip_ident, chip);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf)
|
||||
{
|
||||
struct saa7146_fh *fh = __fh;
|
||||
struct videobuf_queue *q = &fh->video_q;
|
||||
int err, i;
|
||||
|
||||
/* fixme: number of capture buffers and sizes for v4l apps */
|
||||
int gbuffers = 2;
|
||||
int gbufsize = 768 * 576 * 4;
|
||||
|
||||
DEB_D(("VIDIOCGMBUF \n"));
|
||||
|
||||
q = &fh->video_q;
|
||||
err = videobuf_mmap_setup(q, gbuffers, gbufsize,
|
||||
V4L2_MEMORY_MMAP);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
gbuffers = err;
|
||||
memset(mbuf, 0, sizeof(*mbuf));
|
||||
mbuf->frames = gbuffers;
|
||||
mbuf->size = gbuffers * gbufsize;
|
||||
for (i = 0; i < gbuffers; i++)
|
||||
mbuf->offsets[i] = i * gbufsize;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
||||
|
@ -1186,9 +1157,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
|
|||
.vidioc_streamon = vidioc_streamon,
|
||||
.vidioc_streamoff = vidioc_streamoff,
|
||||
.vidioc_g_parm = vidioc_g_parm,
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
.vidiocgmbuf = vidiocgmbuf,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*********************************************************************************/
|
||||
|
|
|
@ -52,13 +52,12 @@ static int max2165_write_reg(struct max2165_priv *priv, u8 reg, u8 data)
|
|||
msg.addr = priv->config->i2c_address;
|
||||
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
|
||||
__func__, reg, data);
|
||||
dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, &msg, 1);
|
||||
|
||||
if (ret != 1)
|
||||
dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
|
||||
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
|
||||
__func__, reg, data, ret);
|
||||
|
||||
return (ret != 1) ? -EIO : 0;
|
||||
|
@ -78,14 +77,13 @@ static int max2165_read_reg(struct max2165_priv *priv, u8 reg, u8 *p_data)
|
|||
|
||||
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||
if (ret != 2) {
|
||||
dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
|
||||
__func__, reg, ret);
|
||||
dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*p_data = b1[0];
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
|
||||
dprintk("%s: reg=0x%02X, data=0x%02X\n",
|
||||
__func__, reg, b1[0]);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
|||
/* write multiple registers */
|
||||
static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
config DVB_DM1105
|
||||
tristate "SDMC DM1105 based PCI cards"
|
||||
depends on DVB_CORE && PCI && I2C
|
||||
depends on INPUT
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0288 if !DVB_FE_CUSTOMISE
|
||||
|
@ -9,7 +8,7 @@ config DVB_DM1105
|
|||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_SI21XX if !DVB_FE_CUSTOMISE
|
||||
select DVB_DS3000 if !DVB_FE_CUSTOMISE
|
||||
depends on VIDEO_IR
|
||||
depends on RC_CORE
|
||||
help
|
||||
Support for cards based on the SDMC DM1105 PCI chip like
|
||||
DvbWorld 2002
|
||||
|
|
|
@ -26,9 +26,8 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#include "demux.h"
|
||||
#include "dmxdev.h"
|
||||
|
@ -266,7 +265,7 @@ static void dm1105_card_list(struct pci_dev *pci)
|
|||
|
||||
/* infrared remote control */
|
||||
struct infrared {
|
||||
struct input_dev *input_dev;
|
||||
struct rc_dev *dev;
|
||||
char input_phys[32];
|
||||
struct work_struct work;
|
||||
u32 ir_command;
|
||||
|
@ -532,7 +531,7 @@ static void dm1105_emit_key(struct work_struct *work)
|
|||
|
||||
data = (ircom >> 8) & 0x7f;
|
||||
|
||||
ir_keydown(ir->input_dev, data, 0);
|
||||
rc_keydown(ir->dev, data, 0);
|
||||
}
|
||||
|
||||
/* work handler */
|
||||
|
@ -593,46 +592,47 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
|
|||
|
||||
int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
char *ir_codes = RC_MAP_DM1105_NEC;
|
||||
struct rc_dev *dev;
|
||||
int err = -ENOMEM;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
dev = rc_allocate_device();
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dm1105->ir.input_dev = input_dev;
|
||||
snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
|
||||
"pci-%s/ir0", pci_name(dm1105->pdev));
|
||||
|
||||
input_dev->name = "DVB on-card IR receiver";
|
||||
input_dev->phys = dm1105->ir.input_phys;
|
||||
input_dev->id.bustype = BUS_PCI;
|
||||
input_dev->id.version = 1;
|
||||
dev->driver_name = MODULE_NAME;
|
||||
dev->map_name = RC_MAP_DM1105_NEC;
|
||||
dev->driver_type = RC_DRIVER_SCANCODE;
|
||||
dev->input_name = "DVB on-card IR receiver";
|
||||
dev->input_phys = dm1105->ir.input_phys;
|
||||
dev->input_id.bustype = BUS_PCI;
|
||||
dev->input_id.version = 1;
|
||||
if (dm1105->pdev->subsystem_vendor) {
|
||||
input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
|
||||
input_dev->id.product = dm1105->pdev->subsystem_device;
|
||||
dev->input_id.vendor = dm1105->pdev->subsystem_vendor;
|
||||
dev->input_id.product = dm1105->pdev->subsystem_device;
|
||||
} else {
|
||||
input_dev->id.vendor = dm1105->pdev->vendor;
|
||||
input_dev->id.product = dm1105->pdev->device;
|
||||
dev->input_id.vendor = dm1105->pdev->vendor;
|
||||
dev->input_id.product = dm1105->pdev->device;
|
||||
}
|
||||
|
||||
input_dev->dev.parent = &dm1105->pdev->dev;
|
||||
dev->dev.parent = &dm1105->pdev->dev;
|
||||
|
||||
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
|
||||
|
||||
err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
|
||||
err = rc_register_device(dev);
|
||||
if (err < 0) {
|
||||
input_free_device(input_dev);
|
||||
rc_free_device(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
dm1105->ir.dev = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
|
||||
{
|
||||
ir_input_unregister(dm1105->ir.input_dev);
|
||||
rc_unregister_device(dm1105->ir.dev);
|
||||
}
|
||||
|
||||
static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
|
||||
|
|
|
@ -572,13 +572,13 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
|||
dmx_output_t otype;
|
||||
int ret;
|
||||
int ts_type;
|
||||
enum dmx_ts_pes ts_pes;
|
||||
dmx_pes_type_t ts_pes;
|
||||
struct dmx_ts_feed *tsfeed;
|
||||
|
||||
feed->ts = NULL;
|
||||
otype = para->output;
|
||||
|
||||
ts_pes = (enum dmx_ts_pes)para->pes_type;
|
||||
ts_pes = para->pes_type;
|
||||
|
||||
if (ts_pes < DMX_PES_OTHER)
|
||||
ts_type = TS_DECODER;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config DVB_USB
|
||||
tristate "Support for various USB DVB devices"
|
||||
depends on DVB_CORE && USB && I2C && IR_CORE
|
||||
depends on DVB_CORE && USB && I2C && RC_CORE
|
||||
help
|
||||
By enabling this you will be able to choose the various supported
|
||||
USB1.1 and USB2.0 DVB devices.
|
||||
|
|
|
@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_a800_table[] = {
|
||||
static struct rc_map_table rc_map_a800_table[] = {
|
||||
{ 0x0201, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0200, KEY_POWER }, /* POWER */
|
||||
{ 0x0205, KEY_1 }, /* 1 */
|
||||
|
@ -148,8 +148,8 @@ static struct dvb_usb_device_properties a800_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_a800_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table),
|
||||
.rc_map_table = rc_map_a800_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_a800_table),
|
||||
.rc_query = a800_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug,
|
|||
|
||||
#define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args)
|
||||
|
||||
struct ir_scancode ir_codes_af9005_table[] = {
|
||||
struct rc_map_table rc_map_af9005_table[] = {
|
||||
|
||||
{0x01b7, KEY_POWER},
|
||||
{0x01a7, KEY_VOLUMEUP},
|
||||
|
@ -74,7 +74,7 @@ struct ir_scancode ir_codes_af9005_table[] = {
|
|||
{0x00d5, KEY_GOTO}, /* marked jump on the remote */
|
||||
};
|
||||
|
||||
int ir_codes_af9005_table_size = ARRAY_SIZE(ir_codes_af9005_table);
|
||||
int rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table);
|
||||
|
||||
static int repeatable_keys[] = {
|
||||
KEY_VOLUMEUP,
|
||||
|
@ -130,10 +130,10 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
|
|||
deb_decode("code != inverted code\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < ir_codes_af9005_table_size; i++) {
|
||||
if (rc5_custom(&ir_codes_af9005_table[i]) == cust
|
||||
&& rc5_data(&ir_codes_af9005_table[i]) == dat) {
|
||||
*event = ir_codes_af9005_table[i].keycode;
|
||||
for (i = 0; i < rc_map_af9005_table_size; i++) {
|
||||
if (rc5_custom(&rc_map_af9005_table[i]) == cust
|
||||
&& rc5_data(&rc_map_af9005_table[i]) == dat) {
|
||||
*event = rc_map_af9005_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
deb_decode
|
||||
("key pressed, event %x\n", *event);
|
||||
|
@ -146,8 +146,8 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ir_codes_af9005_table);
|
||||
EXPORT_SYMBOL(ir_codes_af9005_table_size);
|
||||
EXPORT_SYMBOL(rc_map_af9005_table);
|
||||
EXPORT_SYMBOL(rc_map_af9005_table_size);
|
||||
EXPORT_SYMBOL(af9005_rc_decode);
|
||||
|
||||
MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
|
||||
|
|
|
@ -1027,8 +1027,8 @@ static struct dvb_usb_device_properties af9005_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 200,
|
||||
.rc_key_map = NULL,
|
||||
.rc_key_map_size = 0,
|
||||
.rc_map_table = NULL,
|
||||
.rc_map_size = 0,
|
||||
.rc_query = af9005_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1070,14 +1070,14 @@ static int __init af9005_usb_module_init(void)
|
|||
return result;
|
||||
}
|
||||
rc_decode = symbol_request(af9005_rc_decode);
|
||||
rc_keys = symbol_request(ir_codes_af9005_table);
|
||||
rc_keys_size = symbol_request(ir_codes_af9005_table_size);
|
||||
rc_keys = symbol_request(rc_map_af9005_table);
|
||||
rc_keys_size = symbol_request(rc_map_af9005_table_size);
|
||||
if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
|
||||
err("af9005_rc_decode function not found, disabling remote");
|
||||
af9005_properties.rc.legacy.rc_query = NULL;
|
||||
} else {
|
||||
af9005_properties.rc.legacy.rc_key_map = rc_keys;
|
||||
af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size;
|
||||
af9005_properties.rc.legacy.rc_map_table = rc_keys;
|
||||
af9005_properties.rc.legacy.rc_map_size = *rc_keys_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1089,9 +1089,9 @@ static void __exit af9005_usb_module_exit(void)
|
|||
if (rc_decode != NULL)
|
||||
symbol_put(af9005_rc_decode);
|
||||
if (rc_keys != NULL)
|
||||
symbol_put(ir_codes_af9005_table);
|
||||
symbol_put(rc_map_af9005_table);
|
||||
if (rc_keys_size != NULL)
|
||||
symbol_put(ir_codes_af9005_table_size);
|
||||
symbol_put(rc_map_af9005_table_size);
|
||||
/* deregister this driver from the USB subsystem */
|
||||
usb_deregister(&af9005_usb_driver);
|
||||
}
|
||||
|
|
|
@ -3490,7 +3490,7 @@ extern u8 regmask[8];
|
|||
/* remote control decoder */
|
||||
extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
|
||||
u32 * event, int *state);
|
||||
extern struct ir_scancode ir_codes_af9005_table[];
|
||||
extern int ir_codes_af9005_table_size;
|
||||
extern struct rc_map_table rc_map_af9005_table[];
|
||||
extern int rc_map_af9005_table_size;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1041,13 +1041,13 @@ static int af9015_rc_query(struct dvb_usb_device *d)
|
|||
priv->rc_keycode = buf[12] << 16 |
|
||||
buf[13] << 8 | buf[14];
|
||||
}
|
||||
ir_keydown(d->rc_input_dev, priv->rc_keycode, 0);
|
||||
rc_keydown(d->rc_dev, priv->rc_keycode, 0);
|
||||
} else {
|
||||
priv->rc_keycode = 0; /* clear just for sure */
|
||||
}
|
||||
} else if (priv->rc_repeat != buf[6] || buf[0]) {
|
||||
deb_rc("%s: key repeated\n", __func__);
|
||||
ir_keydown(d->rc_input_dev, priv->rc_keycode, 0);
|
||||
rc_keydown(d->rc_dev, priv->rc_keycode, 0);
|
||||
} else {
|
||||
deb_rc("%s: no key press\n", __func__);
|
||||
}
|
||||
|
@ -1344,13 +1344,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc.core = {
|
||||
.protocol = IR_TYPE_NEC,
|
||||
.protocol = RC_TYPE_NEC,
|
||||
.module_name = "af9015",
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = AF9015_RC_INTERVAL,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_NEC,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_NEC,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
@ -1474,13 +1472,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc.core = {
|
||||
.protocol = IR_TYPE_NEC,
|
||||
.protocol = RC_TYPE_NEC,
|
||||
.module_name = "af9015",
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = AF9015_RC_INTERVAL,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_NEC,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_NEC,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
@ -1588,13 +1584,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc.core = {
|
||||
.protocol = IR_TYPE_NEC,
|
||||
.protocol = RC_TYPE_NEC,
|
||||
.module_name = "af9015",
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = AF9015_RC_INTERVAL,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_NEC,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_NEC,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
|
|
@ -394,7 +394,7 @@ static int anysee_rc_query(struct dvb_usb_device *d)
|
|||
|
||||
if (ircode[0]) {
|
||||
deb_rc("%s: key pressed %02x\n", __func__, ircode[1]);
|
||||
ir_keydown(d->rc_input_dev, 0x08 << 8 | ircode[1], 0);
|
||||
rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -476,7 +476,7 @@ static struct dvb_usb_device_properties anysee_properties = {
|
|||
|
||||
.rc.core = {
|
||||
.rc_codes = RC_MAP_ANYSEE,
|
||||
.protocol = IR_TYPE_OTHER,
|
||||
.protocol = RC_TYPE_OTHER,
|
||||
.module_name = "anysee",
|
||||
.rc_query = anysee_rc_query,
|
||||
.rc_interval = 250, /* windows driver uses 500ms */
|
||||
|
|
|
@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct ir_scancode ir_codes_az6027_table[] = {
|
||||
static struct rc_map_table rc_map_az6027_table[] = {
|
||||
{ 0x01, KEY_1 },
|
||||
{ 0x02, KEY_2 },
|
||||
};
|
||||
|
@ -1089,6 +1089,7 @@ static struct usb_device_id az6027_usb_table[] = {
|
|||
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V2) },
|
||||
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) },
|
||||
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
|
||||
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -1126,15 +1127,15 @@ static struct dvb_usb_device_properties az6027_properties = {
|
|||
.read_mac_address = az6027_read_mac_addr,
|
||||
*/
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_az6027_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table),
|
||||
.rc_map_table = rc_map_az6027_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_az6027_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = az6027_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &az6027_i2c_algo,
|
||||
|
||||
.num_device_descs = 5,
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{
|
||||
.name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
|
||||
|
@ -1156,6 +1157,10 @@ static struct dvb_usb_device_properties az6027_properties = {
|
|||
.name = "Technisat SkyStar USB 2 HD CI",
|
||||
.cold_ids = { &az6027_usb_table[4], NULL },
|
||||
.warm_ids = { NULL },
|
||||
}, {
|
||||
.name = "Elgato EyeTV Sat",
|
||||
.cold_ids = { &az6027_usb_table[5], NULL },
|
||||
.warm_ids = { NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_cinergyt2_table[] = {
|
||||
static struct rc_map_table rc_map_cinergyt2_table[] = {
|
||||
{ 0x0401, KEY_POWER },
|
||||
{ 0x0402, KEY_1 },
|
||||
{ 0x0403, KEY_2 },
|
||||
|
@ -219,8 +219,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 50,
|
||||
.rc_key_map = ir_codes_cinergyt2_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table),
|
||||
.rc_map_table = rc_map_cinergyt2_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_cinergyt2_table),
|
||||
.rc_query = cinergyt2_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl(
|
|||
|
||||
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
|
||||
|
@ -394,7 +394,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[2] &&
|
||||
rc5_data(&keymap[i]) == ircode[3]) {
|
||||
*event = keymap[i].keycode;
|
||||
|
@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
|
||||
|
@ -422,7 +422,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[1] &&
|
||||
rc5_data(&keymap[i]) == ircode[2]) {
|
||||
*event = keymap[i].keycode;
|
||||
|
@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
u8 ircode[2];
|
||||
int i;
|
||||
|
||||
|
@ -448,7 +448,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[0] &&
|
||||
rc5_data(&keymap[i]) == ircode[1]) {
|
||||
*event = keymap[i].keycode;
|
||||
|
@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_dvico_mce_table[] = {
|
||||
static struct rc_map_table rc_map_dvico_mce_table[] = {
|
||||
{ 0xfe02, KEY_TV },
|
||||
{ 0xfe0e, KEY_MP3 },
|
||||
{ 0xfe1a, KEY_DVD },
|
||||
|
@ -509,7 +509,7 @@ static struct ir_scancode ir_codes_dvico_mce_table[] = {
|
|||
{ 0xfe4e, KEY_POWER },
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_dvico_portable_table[] = {
|
||||
static struct rc_map_table rc_map_dvico_portable_table[] = {
|
||||
{ 0xfc02, KEY_SETUP }, /* Profile */
|
||||
{ 0xfc43, KEY_POWER2 },
|
||||
{ 0xfc06, KEY_EPG },
|
||||
|
@ -548,7 +548,7 @@ static struct ir_scancode ir_codes_dvico_portable_table[] = {
|
|||
{ 0xfc00, KEY_UNKNOWN }, /* HD */
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_d680_dmb_table[] = {
|
||||
static struct rc_map_table rc_map_d680_dmb_table[] = {
|
||||
{ 0x0038, KEY_UNKNOWN }, /* TV/AV */
|
||||
{ 0x080c, KEY_ZOOM },
|
||||
{ 0x0800, KEY_0 },
|
||||
|
@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return -EIO;
|
||||
|
||||
/* try to determine if there is no IR decoder on the I2C bus */
|
||||
for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) {
|
||||
for (i = 0; adap->dev->props.rc.legacy.rc_map_table != NULL && i < 5; i++) {
|
||||
msleep(20);
|
||||
if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
|
||||
goto no_IR;
|
||||
|
@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
continue;
|
||||
if (ircode[2] + ircode[3] != 0xff) {
|
||||
no_IR:
|
||||
adap->dev->props.rc.legacy.rc_key_map = NULL;
|
||||
adap->dev->props.rc.legacy.rc_map_table = NULL;
|
||||
info("No IR receiver detected on this device.");
|
||||
break;
|
||||
}
|
||||
|
@ -1453,8 +1453,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_map_table = rc_map_dvico_portable_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1506,8 +1506,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 150,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_map_table = rc_map_dvico_mce_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1567,8 +1567,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_map_table = rc_map_dvico_portable_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1619,8 +1619,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_map_table = rc_map_dvico_portable_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1670,8 +1670,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_map_table = rc_map_dvico_mce_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1720,8 +1720,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_map_table = rc_map_dvico_portable_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1772,8 +1772,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_map_table = rc_map_dvico_portable_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1865,8 +1865,8 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_map_table = rc_map_dvico_mce_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1915,8 +1915,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_map_table = rc_map_d680_dmb_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -1966,8 +1966,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_map_table = rc_map_d680_dmb_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
|||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold);
|
||||
extern int dib0700_change_protocol(void *priv, u64 ir_type);
|
||||
extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
|
||||
|
||||
extern int dib0700_device_count;
|
||||
extern int dvb_usb_dib0700_ir_proto;
|
||||
|
|
|
@ -471,19 +471,19 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
}
|
||||
|
||||
int dib0700_change_protocol(void *priv, u64 ir_type)
|
||||
int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
||||
{
|
||||
struct dvb_usb_device *d = priv;
|
||||
struct dvb_usb_device *d = rc->priv;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
|
||||
int new_proto, ret;
|
||||
|
||||
/* Set the IR mode */
|
||||
if (ir_type == IR_TYPE_RC5)
|
||||
if (rc_type == RC_TYPE_RC5)
|
||||
new_proto = 1;
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
else if (rc_type == RC_TYPE_NEC)
|
||||
new_proto = 0;
|
||||
else if (ir_type == IR_TYPE_RC6) {
|
||||
else if (rc_type == RC_TYPE_RC6) {
|
||||
if (st->fw_version < 0x10200)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -499,7 +499,7 @@ int dib0700_change_protocol(void *priv, u64 ir_type)
|
|||
return ret;
|
||||
}
|
||||
|
||||
d->props.rc.core.protocol = ir_type;
|
||||
d->props.rc.core.protocol = rc_type;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
if (d == NULL)
|
||||
return;
|
||||
|
||||
if (d->rc_input_dev == NULL) {
|
||||
if (d->rc_dev == NULL) {
|
||||
/* This will occur if disable_rc_polling=1 */
|
||||
usb_free_urb(purb);
|
||||
return;
|
||||
|
@ -562,7 +562,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
purb->actual_length);
|
||||
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
case RC_TYPE_NEC:
|
||||
toggle = 0;
|
||||
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
|
@ -600,7 +600,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
goto resubmit;
|
||||
}
|
||||
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
rc_keydown(d->rc_dev, keycode, toggle);
|
||||
|
||||
resubmit:
|
||||
/* Clean the buffer before we requeue */
|
||||
|
|
|
@ -510,7 +510,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
|
|||
|
||||
d->last_event = 0;
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
case RC_TYPE_NEC:
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
|
||||
(key[3] == 0xff))
|
||||
|
@ -520,13 +520,13 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
|
|||
d->last_event = keycode;
|
||||
}
|
||||
|
||||
ir_keydown(d->rc_input_dev, keycode, 0);
|
||||
rc_keydown(d->rc_dev, keycode, 0);
|
||||
break;
|
||||
default:
|
||||
/* RC-5 protocol changes toggle bit on new keypress */
|
||||
keycode = key[3-2] << 8 | key[3-3];
|
||||
toggle = key[3-1];
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
rc_keydown(d->rc_dev, keycode, toggle);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1924,12 +1924,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -1960,12 +1958,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2021,12 +2017,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2065,12 +2059,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2143,12 +2135,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2189,12 +2179,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2259,12 +2247,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2308,12 +2294,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -2379,12 +2363,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
|
@ -2417,12 +2399,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
|
@ -2487,12 +2467,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
|
@ -2533,12 +2511,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 2,
|
||||
|
@ -2584,12 +2560,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
|
@ -2623,12 +2597,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
.allowed_protos = RC_TYPE_RC5 |
|
||||
RC_TYPE_RC6 |
|
||||
RC_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
|||
/*
|
||||
* common remote control stuff
|
||||
*/
|
||||
struct ir_scancode ir_codes_dibusb_table[] = {
|
||||
struct rc_map_table rc_map_dibusb_table[] = {
|
||||
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
|
@ -456,7 +456,7 @@ struct ir_scancode ir_codes_dibusb_table[] = {
|
|||
{ 0x804e, KEY_ENTER },
|
||||
{ 0x804f, KEY_VOLUMEDOWN },
|
||||
};
|
||||
EXPORT_SYMBOL(ir_codes_dibusb_table);
|
||||
EXPORT_SYMBOL(rc_map_dibusb_table);
|
||||
|
||||
int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
|
|
|
@ -213,8 +213,8 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_map_table = rc_map_dibusb_table,
|
||||
.rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -299,8 +299,8 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_map_table = rc_map_dibusb_table,
|
||||
.rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -365,8 +365,8 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_map_table = rc_map_dibusb_table,
|
||||
.rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
|
@ -424,8 +424,8 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_map_table = rc_map_dibusb_table,
|
||||
.rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -83,8 +83,8 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_map_table = rc_map_dibusb_table,
|
||||
.rc_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
|
|||
#define DEFAULT_RC_INTERVAL 150
|
||||
//#define DEFAULT_RC_INTERVAL 100000
|
||||
|
||||
extern struct ir_scancode ir_codes_dibusb_table[];
|
||||
extern struct rc_map_table rc_map_dibusb_table[];
|
||||
extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
|
||||
extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_digitv_table[] = {
|
||||
static struct rc_map_table rc_map_digitv_table[] = {
|
||||
{ 0x5f55, KEY_0 },
|
||||
{ 0x6f55, KEY_1 },
|
||||
{ 0x9f55, KEY_2 },
|
||||
|
@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
/* if something is inside the buffer, simulate key press */
|
||||
if (key[1] != 0)
|
||||
{
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc.legacy.rc_map_table[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc.legacy.rc_map_table[i]) == key[2]) {
|
||||
*event = d->props.rc.legacy.rc_map_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
@ -312,8 +312,8 @@ static struct dvb_usb_device_properties digitv_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 1000,
|
||||
.rc_key_map = ir_codes_digitv_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table),
|
||||
.rc_map_table = rc_map_digitv_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_digitv_table),
|
||||
.rc_query = digitv_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
|||
|
||||
/* remote control */
|
||||
/* key list for the tiny remote control (Yakumo, don't know about the others) */
|
||||
static struct ir_scancode ir_codes_dtt200u_table[] = {
|
||||
static struct rc_map_table rc_map_dtt200u_table[] = {
|
||||
{ 0x8001, KEY_MUTE },
|
||||
{ 0x8002, KEY_CHANNELDOWN },
|
||||
{ 0x8003, KEY_VOLUMEDOWN },
|
||||
|
@ -163,8 +163,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_map_table = rc_map_dtt200u_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
|
@ -210,8 +210,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_map_table = rc_map_dtt200u_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
|
@ -257,8 +257,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_map_table = rc_map_dtt200u_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
|
@ -304,8 +304,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_map_table = rc_map_dtt200u_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -301,6 +301,7 @@
|
|||
#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
|
||||
#define USB_PID_ELGATO_EYETV_DTT 0x0021
|
||||
#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
|
||||
#define USB_PID_ELGATO_EYETV_SAT 0x002a
|
||||
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000
|
||||
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001
|
||||
#define USB_PID_FRIIO_WHITE 0x0001
|
||||
|
|
|
@ -13,11 +13,11 @@ static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
|
|||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
int i;
|
||||
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
*keycode = keymap[i].keycode;
|
||||
return 0;
|
||||
|
@ -28,7 +28,7 @@ static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
|
|||
* otherwise, input core won't let legacy_dvb_usb_setkeycode
|
||||
* to work
|
||||
*/
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
*keycode = KEY_RESERVED;
|
||||
|
@ -43,18 +43,18 @@ static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
|
|||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
int i;
|
||||
|
||||
/* Search if it is replacing an existing keycode */
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
keymap[i].keycode = keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search if is there a clean entry. If so, use it */
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
keymap[i].scancode = scancode;
|
||||
|
@ -106,10 +106,10 @@ static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
|
|||
d->last_event = event;
|
||||
case REMOTE_KEY_REPEAT:
|
||||
deb_rc("key repeated\n");
|
||||
input_event(d->rc_input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->input_dev);
|
||||
input_event(d->input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->input_dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -154,20 +154,32 @@ schedule:
|
|||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
|
||||
}
|
||||
|
||||
static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
int i, err, rc_interval;
|
||||
struct input_dev *input_dev;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
input_dev->name = "IR-receiver inside an USB DVB receiver";
|
||||
input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
input_dev->dev.parent = &d->udev->dev;
|
||||
d->input_dev = input_dev;
|
||||
d->rc_dev = NULL;
|
||||
|
||||
input_dev->getkeycode = legacy_dvb_usb_getkeycode;
|
||||
input_dev->setkeycode = legacy_dvb_usb_setkeycode;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc.legacy.rc_key_map[i].keycode, i);
|
||||
set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit);
|
||||
d->props.rc.legacy.rc_map_table[i].keycode, i);
|
||||
set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
|
@ -221,18 +233,34 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
msecs_to_jiffies(d->props.rc.core.rc_interval));
|
||||
}
|
||||
|
||||
static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
int err, rc_interval;
|
||||
struct rc_dev *dev;
|
||||
|
||||
d->props.rc.core.rc_props.priv = d;
|
||||
err = ir_input_register(input_dev,
|
||||
d->props.rc.core.rc_codes,
|
||||
&d->props.rc.core.rc_props,
|
||||
d->props.rc.core.module_name);
|
||||
if (err < 0)
|
||||
dev = rc_allocate_device();
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->driver_name = d->props.rc.core.module_name;
|
||||
dev->map_name = d->props.rc.core.rc_codes;
|
||||
dev->change_protocol = d->props.rc.core.change_protocol;
|
||||
dev->allowed_protos = d->props.rc.core.allowed_protos;
|
||||
dev->driver_type = RC_DRIVER_SCANCODE;
|
||||
usb_to_input_id(d->udev, &dev->input_id);
|
||||
dev->input_name = "IR-receiver inside an USB DVB receiver";
|
||||
dev->input_phys = d->rc_phys;
|
||||
dev->dev.parent = &d->udev->dev;
|
||||
dev->priv = d;
|
||||
|
||||
err = rc_register_device(dev);
|
||||
if (err < 0) {
|
||||
rc_free_device(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
d->input_dev = NULL;
|
||||
d->rc_dev = dev;
|
||||
|
||||
if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
|
||||
return 0;
|
||||
|
@ -251,13 +279,12 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
|
|||
|
||||
int dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
if (dvb_usb_disable_rc_polling)
|
||||
return 0;
|
||||
|
||||
if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query)
|
||||
if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
|
||||
d->props.rc.mode = DVB_RC_LEGACY;
|
||||
else if (d->props.rc.core.rc_codes)
|
||||
d->props.rc.mode = DVB_RC_CORE;
|
||||
|
@ -267,26 +294,14 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
input_dev->name = "IR-receiver inside an USB DVB receiver";
|
||||
input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
input_dev->dev.parent = &d->udev->dev;
|
||||
|
||||
/* Start the remote-control polling. */
|
||||
if (d->props.rc.legacy.rc_interval < 40)
|
||||
d->props.rc.legacy.rc_interval = 100; /* default */
|
||||
|
||||
d->rc_input_dev = input_dev;
|
||||
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
err = legacy_dvb_usb_remote_init(d, input_dev);
|
||||
err = legacy_dvb_usb_remote_init(d);
|
||||
else
|
||||
err = rc_core_dvb_usb_remote_init(d, input_dev);
|
||||
err = rc_core_dvb_usb_remote_init(d);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -301,9 +316,9 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
|
|||
cancel_rearming_delayed_work(&d->rc_query_work);
|
||||
flush_scheduled_work();
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
input_unregister_device(d->rc_input_dev);
|
||||
input_unregister_device(d->input_dev);
|
||||
else
|
||||
ir_input_unregister(d->rc_input_dev);
|
||||
rc_unregister_device(d->rc_dev);
|
||||
}
|
||||
d->state &= ~DVB_USB_STATE_REMOTE;
|
||||
return 0;
|
||||
|
@ -316,7 +331,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
u8 keybuf[5], u32 *event, int *state)
|
||||
{
|
||||
int i;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
switch (keybuf[0]) {
|
||||
|
@ -329,7 +344,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
break;
|
||||
}
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (rc5_custom(&keymap[i]) == keybuf[1] &&
|
||||
rc5_data(&keymap[i]) == keybuf[3]) {
|
||||
*event = keymap[i].keycode;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_demux.h"
|
||||
|
@ -75,17 +75,17 @@ struct dvb_usb_device_description {
|
|||
struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
|
||||
};
|
||||
|
||||
static inline u8 rc5_custom(struct ir_scancode *key)
|
||||
static inline u8 rc5_custom(struct rc_map_table *key)
|
||||
{
|
||||
return (key->scancode >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_data(struct ir_scancode *key)
|
||||
static inline u8 rc5_data(struct rc_map_table *key)
|
||||
{
|
||||
return key->scancode & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_scan(struct ir_scancode *key)
|
||||
static inline u8 rc5_scan(struct rc_map_table *key)
|
||||
{
|
||||
return key->scancode & 0xffff;
|
||||
}
|
||||
|
@ -159,9 +159,9 @@ struct dvb_usb_adapter_properties {
|
|||
|
||||
/**
|
||||
* struct dvb_rc_legacy - old properties of remote controller
|
||||
* @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable
|
||||
* @rc_map_table: a hard-wired array of struct rc_map_table (NULL to disable
|
||||
* remote control handling).
|
||||
* @rc_key_map_size: number of items in @rc_key_map.
|
||||
* @rc_map_size: number of items in @rc_map_table.
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
*/
|
||||
|
@ -170,8 +170,8 @@ struct dvb_rc_legacy {
|
|||
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||
#define REMOTE_KEY_PRESSED 0x01
|
||||
#define REMOTE_KEY_REPEAT 0x02
|
||||
struct ir_scancode *rc_key_map;
|
||||
int rc_key_map_size;
|
||||
struct rc_map_table *rc_map_table;
|
||||
int rc_map_size;
|
||||
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||
int rc_interval;
|
||||
};
|
||||
|
@ -180,18 +180,20 @@ struct dvb_rc_legacy {
|
|||
* struct dvb_rc properties of remote controller, using rc-core
|
||||
* @rc_codes: name of rc codes table
|
||||
* @protocol: type of protocol(s) currently used by the driver
|
||||
* @allowed_protos: protocol(s) supported by the driver
|
||||
* @change_protocol: callback to change protocol
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
* @rc_props: remote controller properties
|
||||
* @bulk_mode: device supports bulk mode for RC (disable polling mode)
|
||||
*/
|
||||
struct dvb_rc {
|
||||
char *rc_codes;
|
||||
u64 protocol;
|
||||
u64 allowed_protos;
|
||||
int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
|
||||
char *module_name;
|
||||
int (*rc_query) (struct dvb_usb_device *d);
|
||||
int rc_interval;
|
||||
struct ir_dev_props rc_props;
|
||||
bool bulk_mode; /* uses bulk mode */
|
||||
};
|
||||
|
||||
|
@ -385,7 +387,8 @@ struct dvb_usb_adapter {
|
|||
*
|
||||
* @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
|
||||
*
|
||||
* @rc_input_dev: input device for the remote control.
|
||||
* @rc_dev: rc device for the remote control (rc-core mode)
|
||||
* @input_dev: input device for the remote control (legacy mode)
|
||||
* @rc_query_work: struct work_struct frequent rc queries
|
||||
* @last_event: last triggered event
|
||||
* @last_state: last state (no, pressed, repeat)
|
||||
|
@ -418,7 +421,8 @@ struct dvb_usb_device {
|
|||
struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
|
||||
|
||||
/* remote control */
|
||||
struct input_dev *rc_input_dev;
|
||||
struct rc_dev *rc_dev;
|
||||
struct input_dev *input_dev;
|
||||
char rc_phys[64];
|
||||
struct delayed_work rc_query_work;
|
||||
u32 last_event;
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
"Please see linux/Documentation/dvb/ for more details " \
|
||||
"on firmware-problems."
|
||||
|
||||
struct ir_codes_dvb_usb_table_table {
|
||||
struct ir_scancode *rc_keys;
|
||||
struct rc_map_dvb_usb_table_table {
|
||||
struct rc_map_table *rc_keys;
|
||||
int rc_keys_size;
|
||||
};
|
||||
|
||||
|
@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_dw210x_table[] = {
|
||||
static struct rc_map_table rc_map_dw210x_table[] = {
|
||||
{ 0xf80a, KEY_Q }, /*power*/
|
||||
{ 0xf80c, KEY_M }, /*mute*/
|
||||
{ 0xf811, KEY_1 },
|
||||
|
@ -982,7 +982,7 @@ static struct ir_scancode ir_codes_dw210x_table[] = {
|
|||
{ 0xf81b, KEY_B }, /*recall*/
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_tevii_table[] = {
|
||||
static struct rc_map_table rc_map_tevii_table[] = {
|
||||
{ 0xf80a, KEY_POWER },
|
||||
{ 0xf80c, KEY_MUTE },
|
||||
{ 0xf811, KEY_1 },
|
||||
|
@ -1032,7 +1032,7 @@ static struct ir_scancode ir_codes_tevii_table[] = {
|
|||
{ 0xf858, KEY_SWITCHVIDEOMODE },
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_tbs_table[] = {
|
||||
static struct rc_map_table rc_map_tbs_table[] = {
|
||||
{ 0xf884, KEY_POWER },
|
||||
{ 0xf894, KEY_MUTE },
|
||||
{ 0xf887, KEY_1 },
|
||||
|
@ -1067,16 +1067,16 @@ static struct ir_scancode ir_codes_tbs_table[] = {
|
|||
{ 0xf89b, KEY_MODE }
|
||||
};
|
||||
|
||||
static struct ir_codes_dvb_usb_table_table keys_tables[] = {
|
||||
{ ir_codes_dw210x_table, ARRAY_SIZE(ir_codes_dw210x_table) },
|
||||
{ ir_codes_tevii_table, ARRAY_SIZE(ir_codes_tevii_table) },
|
||||
{ ir_codes_tbs_table, ARRAY_SIZE(ir_codes_tbs_table) },
|
||||
static struct rc_map_dvb_usb_table_table keys_tables[] = {
|
||||
{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
|
||||
{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
|
||||
{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
|
||||
};
|
||||
|
||||
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int keymap_size = d->props.rc.legacy.rc_key_map_size;
|
||||
struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
|
||||
int keymap_size = d->props.rc.legacy.rc_map_size;
|
||||
u8 key[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = DW2102_RC_QUERY,
|
||||
|
@ -1185,14 +1185,14 @@ static int dw2102_load_firmware(struct usb_device *dev,
|
|||
/* init registers */
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case USB_PID_PROF_1100:
|
||||
s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
s6x0_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tbs_table);
|
||||
s6x0_properties.rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
s6x0_properties.rc.legacy.rc_map_size =
|
||||
ARRAY_SIZE(rc_map_tbs_table);
|
||||
break;
|
||||
case USB_PID_TEVII_S650:
|
||||
dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table;
|
||||
dw2104_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tevii_table);
|
||||
dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
|
||||
dw2104_properties.rc.legacy.rc_map_size =
|
||||
ARRAY_SIZE(rc_map_tevii_table);
|
||||
case USB_PID_DW2104:
|
||||
reset = 1;
|
||||
dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
|
||||
|
@ -1257,8 +1257,8 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
|||
.i2c_algo = &dw2102_serit_i2c_algo,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_map_table = rc_map_dw210x_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
@ -1310,8 +1310,8 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
|||
|
||||
.i2c_algo = &dw2104_i2c_algo,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_map_table = rc_map_dw210x_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
@ -1359,8 +1359,8 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
|||
|
||||
.i2c_algo = &dw3101_i2c_algo,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_map_table = rc_map_dw210x_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
@ -1404,8 +1404,8 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_tevii_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
|
||||
.rc_map_table = rc_map_tevii_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_tevii_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
@ -1468,8 +1468,8 @@ static int dw2102_probe(struct usb_interface *intf,
|
|||
/* fill only different fields */
|
||||
p7500->firmware = "dvb-usb-p7500.fw";
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
|
||||
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
|
||||
p7500->adapter->frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
|
|
|
@ -24,6 +24,33 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
|
|||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
|
||||
{
|
||||
return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
|
||||
}
|
||||
|
||||
static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers)
|
||||
{
|
||||
return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1));
|
||||
}
|
||||
|
||||
static void gp8psk_info(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 fpga_vers, fw_vers[6];
|
||||
|
||||
if (!gp8psk_get_fw_version(d, fw_vers))
|
||||
info("FW Version = %i.%02i.%i (0x%x) Build %4i/%02i/%02i",
|
||||
fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers),
|
||||
2000 + fw_vers[5], fw_vers[4], fw_vers[3]);
|
||||
else
|
||||
info("failed to get FW version");
|
||||
|
||||
if (!gp8psk_get_fpga_version(d, &fpga_vers))
|
||||
info("FPGA Version = %i", fpga_vers);
|
||||
else
|
||||
info("failed to get FPGA version");
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -146,6 +173,7 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
gp8psk_info(d);
|
||||
}
|
||||
|
||||
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
|
||||
|
|
|
@ -25,7 +25,6 @@ extern int dvb_usb_gp8psk_debug;
|
|||
#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
|
||||
|
@ -49,8 +48,10 @@ extern int dvb_usb_gp8psk_debug;
|
|||
#define SET_DVB_MODE 0x8E
|
||||
#define SET_DN_SWITCH 0x8F
|
||||
#define GET_SIGNAL_LOCK 0x90 /* in */
|
||||
#define GET_FW_VERS 0x92
|
||||
#define GET_SERIAL_NUMBER 0x93 /* in */
|
||||
#define USE_EXTRA_VOLT 0x94
|
||||
#define GET_FPGA_VERS 0x95
|
||||
#define CW3K_INIT 0x9d
|
||||
|
||||
/* PSK_configuration bits */
|
||||
|
@ -88,6 +89,11 @@ extern int dvb_usb_gp8psk_debug;
|
|||
#define PRODUCT_STRING_READ 0x0D
|
||||
#define FW_BCD_VERSION_READ 0x14
|
||||
|
||||
/* firmware revision id's */
|
||||
#define GP8PSK_FW_REV1 0x020604
|
||||
#define GP8PSK_FW_REV2 0x020704
|
||||
#define GP8PSK_FW_VERS(_fw_vers) ((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0])
|
||||
|
||||
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,
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
#define DVB_USB_LOG_PREFIX "LME2510(C)"
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#include "dvb-usb.h"
|
||||
#include "lmedm04.h"
|
||||
|
@ -112,7 +112,6 @@ struct lme2510_state {
|
|||
u8 i2c_tuner_gate_r;
|
||||
u8 i2c_tuner_addr;
|
||||
u8 stream_on;
|
||||
u8 one_tune;
|
||||
void *buffer;
|
||||
struct urb *lme_urb;
|
||||
void *usb_buffer;
|
||||
|
@ -125,7 +124,7 @@ static int lme2510_bulk_write(struct usb_device *dev,
|
|||
int ret, actual_l;
|
||||
|
||||
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
|
||||
snd, len , &actual_l, 500);
|
||||
snd, len , &actual_l, 100);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -135,7 +134,7 @@ static int lme2510_bulk_read(struct usb_device *dev,
|
|||
int ret, actual_l;
|
||||
|
||||
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
|
||||
rev, len , &actual_l, 500);
|
||||
rev, len , &actual_l, 200);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -167,7 +166,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
|||
|
||||
ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
|
||||
|
||||
msleep(12);
|
||||
msleep(10);
|
||||
|
||||
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
|
||||
|
||||
|
@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
|||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int lme2510_usb_talk_restart(struct dvb_usb_device *d,
|
||||
u8 *wbuf, int wlen, u8 *rbuf, int rlen) {
|
||||
static int lme2510_stream_restart(struct dvb_usb_device *d)
|
||||
{
|
||||
static u8 stream_on[] = LME_ST_ON_W;
|
||||
int ret;
|
||||
u8 rbuff[10];
|
||||
/*Send Normal Command*/
|
||||
ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
||||
/*Restart Stream Command*/
|
||||
ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on),
|
||||
ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
|
||||
rbuff, sizeof(rbuff));
|
||||
return ret;
|
||||
}
|
||||
|
@ -201,7 +198,7 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress)
|
|||
deb_info(1, "INT Key Keypress =%04x", keypress);
|
||||
|
||||
if (keypress > 0)
|
||||
ir_keydown(d->rc_input_dev, keypress, 0);
|
||||
rc_keydown(d->rc_dev, keypress, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb)
|
|||
case TUNER_S7395:
|
||||
/* Tweak for earlier firmware*/
|
||||
if (ibuf[1] == 0x03) {
|
||||
if (ibuf[2] > 1)
|
||||
st->signal_lock = ibuf[2];
|
||||
st->signal_level = ibuf[3];
|
||||
st->signal_sn = ibuf[4];
|
||||
} else {
|
||||
st->signal_level = ibuf[4];
|
||||
st->signal_sn = ibuf[5];
|
||||
st->signal_lock =
|
||||
(st->signal_lock & 0xf7) +
|
||||
((ibuf[2] & 0x01) << 0x03);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -341,11 +343,10 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
st->signal_lock = rbuf[1];
|
||||
if ((st->stream_on & 1) &&
|
||||
(st->signal_lock & 0x10)) {
|
||||
lme2510_usb_talk_restart(d,
|
||||
wbuf, wlen, rbuf, rlen);
|
||||
lme2510_stream_restart(d);
|
||||
st->i2c_talk_onoff = 0;
|
||||
}
|
||||
msleep(80);
|
||||
msleep(80);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
st->signal_lock = rbuf[1];
|
||||
if ((st->stream_on & 1) &&
|
||||
(st->signal_lock & 0x8)) {
|
||||
lme2510_usb_talk_restart(d,
|
||||
wbuf, wlen, rbuf, rlen);
|
||||
lme2510_stream_restart(d);
|
||||
st->i2c_talk_onoff = 0;
|
||||
}
|
||||
}
|
||||
if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
|
||||
msleep(5);
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
rbuf[0] = 0x55;
|
||||
rbuf[1] = st->signal_sn;
|
||||
break;
|
||||
/*DiSEqC functions as per TDA10086*/
|
||||
case 0x36:
|
||||
case 0x48:
|
||||
case 0x49:
|
||||
case 0x4a:
|
||||
case 0x4b:
|
||||
case 0x4c:
|
||||
case 0x4d:
|
||||
if (wbuf[2] == 0x1c)
|
||||
lme2510_usb_talk_restart(d,
|
||||
wbuf, wlen, rbuf, rlen);
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
case 0x18:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = 0x00;
|
||||
break;
|
||||
default:
|
||||
lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
||||
st->i2c_talk_onoff = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
break;
|
||||
case 0x24:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = (st->signal_level & 0x80)
|
||||
? 0 : st->signal_lock;
|
||||
rbuf[1] = st->signal_lock;
|
||||
break;
|
||||
case 0x6:
|
||||
if (wbuf[2] == 0xd0)
|
||||
lme2510_usb_talk(d,
|
||||
wbuf, wlen, rbuf, rlen);
|
||||
break;
|
||||
case 0x1:
|
||||
if (st->one_tune > 0)
|
||||
break;
|
||||
st->one_tune++;
|
||||
st->i2c_talk_onoff = 1;
|
||||
/*DiSEqC functions as per STV0288*/
|
||||
case 0x5:
|
||||
case 0x7:
|
||||
case 0x8:
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
if (wbuf[2] == 0xd0)
|
||||
lme2510_usb_talk_restart(d,
|
||||
wbuf, wlen, rbuf, rlen);
|
||||
break;
|
||||
default:
|
||||
case 0x2e:
|
||||
case 0x26:
|
||||
case 0x27:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = 0x00;
|
||||
break;
|
||||
default:
|
||||
lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
||||
st->i2c_talk_onoff = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
|
||||
|
@ -548,35 +527,26 @@ static int lme2510_identify_state(struct usb_device *udev,
|
|||
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
static u8 stream_on[] = LME_ST_ON_W;
|
||||
static u8 clear_reg_3[] = LME_CLEAR_PID;
|
||||
static u8 rbuf[1];
|
||||
static u8 timeout;
|
||||
int ret = 0, len = 2, rlen = sizeof(rbuf);
|
||||
int ret = 0, rlen = sizeof(rbuf);
|
||||
|
||||
deb_info(1, "STM (%02x)", onoff);
|
||||
|
||||
if (onoff == 1) {
|
||||
st->i2c_talk_onoff = 0;
|
||||
timeout = 0;
|
||||
/* wait for i2C to be free */
|
||||
while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) {
|
||||
timeout++;
|
||||
if (timeout > 5)
|
||||
return -ENODEV;
|
||||
}
|
||||
msleep(100);
|
||||
ret |= lme2510_usb_talk(adap->dev,
|
||||
stream_on, len, rbuf, rlen);
|
||||
/* Streaming is started by FE_HAS_LOCK */
|
||||
if (onoff == 1)
|
||||
st->stream_on = 1;
|
||||
st->one_tune = 0;
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
} else {
|
||||
else {
|
||||
deb_info(1, "STM Steam Off");
|
||||
/* mutex is here only to avoid collision with I2C */
|
||||
ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
|
||||
|
||||
ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
|
||||
sizeof(clear_reg_3), rbuf, rlen);
|
||||
st->stream_on = 0;
|
||||
st->i2c_talk_onoff = 1;
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
}
|
||||
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
|
@ -585,41 +555,40 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
static int lme2510_int_service(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct input_dev *input_dev;
|
||||
char *ir_codes = RC_MAP_LME2510;
|
||||
int ret = 0;
|
||||
struct rc_dev *rc;
|
||||
int ret;
|
||||
|
||||
info("STA Configuring Remote");
|
||||
|
||||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
|
||||
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
rc = rc_allocate_device();
|
||||
if (!rc)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev->name = "LME2510 Remote Control";
|
||||
input_dev->phys = d->rc_phys;
|
||||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
||||
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
|
||||
ret |= ir_input_register(input_dev, ir_codes, NULL, "LME 2510");
|
||||
rc->input_name = "LME2510 Remote Control";
|
||||
rc->input_phys = d->rc_phys;
|
||||
rc->map_name = RC_MAP_LME2510;
|
||||
rc->driver_name = "LME 2510";
|
||||
usb_to_input_id(d->udev, &rc->input_id);
|
||||
|
||||
ret = rc_register_device(rc);
|
||||
if (ret) {
|
||||
input_free_device(input_dev);
|
||||
rc_free_device(rc);
|
||||
return ret;
|
||||
}
|
||||
d->rc_dev = rc;
|
||||
|
||||
d->rc_input_dev = input_dev;
|
||||
/* Start the Interupt */
|
||||
ret = lme2510_int_read(adap);
|
||||
|
||||
if (ret < 0) {
|
||||
ir_input_unregister(input_dev);
|
||||
input_free_device(input_dev);
|
||||
rc_unregister_device(rc);
|
||||
info("INT Unable to start Interupt Service");
|
||||
return -ENODEV;
|
||||
}
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 check_sum(u8 *p, u8 len)
|
||||
|
@ -668,6 +637,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
ret |= (data[0] == 0x88) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
|
||||
|
||||
|
@ -701,10 +671,11 @@ static void lme_coldreset(struct usb_device *dev)
|
|||
info("FRM Firmware Cold Reset");
|
||||
ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
|
||||
ret |= lme2510_bulk_read(dev, data, len_in, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void lme_firmware_switch(struct usb_device *udev, int cold)
|
||||
static int lme_firmware_switch(struct usb_device *udev, int cold)
|
||||
{
|
||||
const struct firmware *fw = NULL;
|
||||
char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
|
||||
|
@ -712,8 +683,10 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
|
|||
char *firm_msg[] = {"Loading", "Switching to"};
|
||||
int ret;
|
||||
|
||||
cold = (cold > 0) ? (cold & 1) : 0;
|
||||
|
||||
if (udev->descriptor.idProduct == 0x1122)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
switch (dvb_usb_lme2510_firmware) {
|
||||
case 0:
|
||||
|
@ -740,22 +713,28 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
|
|||
cold = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
if (cold)
|
||||
|
||||
if (cold) {
|
||||
lme_coldreset(udev);
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lme2510_kill_urb(struct usb_data_stream *stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < stream->urbs_submitted; i++) {
|
||||
deb_info(3, "killing URB no. %d.", i);
|
||||
|
||||
/* stop the URB */
|
||||
usb_kill_urb(stream->urb_list[i]);
|
||||
}
|
||||
stream->urbs_submitted = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
|
|||
fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
static u8 voltage_low[] = LME_VOLTAGE_L;
|
||||
static u8 voltage_high[] = LME_VOLTAGE_H;
|
||||
static u8 lnb_on[] = LNB_ON;
|
||||
static u8 lnb_off[] = LNB_OFF;
|
||||
static u8 rbuf[1];
|
||||
int ret = 0, len = 3, rlen = 1;
|
||||
|
||||
if (st->stream_on == 1)
|
||||
return 0;
|
||||
|
||||
ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
|
||||
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_18:
|
||||
|
@ -803,94 +777,143 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
|
|||
break;
|
||||
|
||||
case SEC_VOLTAGE_OFF:
|
||||
ret |= lme2510_usb_talk(adap->dev,
|
||||
lnb_off, len, rbuf, rlen);
|
||||
case SEC_VOLTAGE_13:
|
||||
default:
|
||||
ret |= lme2510_usb_talk(adap->dev,
|
||||
voltage_low, len, rbuf, rlen);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
|
||||
};
|
||||
st->i2c_talk_onoff = 1;
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int lme_name(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
const char *desc = adap->dev->desc->name;
|
||||
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"};
|
||||
char *name = adap->fe->ops.info.name;
|
||||
|
||||
strlcpy(name, desc, 128);
|
||||
strlcat(name, fe_name[st->tuner_config], 128);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
|
||||
/* Interupt Start */
|
||||
ret = lme2510_int_service(adap);
|
||||
if (ret < 0) {
|
||||
info("INT Unable to start Interupt Service");
|
||||
return -ENODEV;
|
||||
}
|
||||
int ret = 0;
|
||||
|
||||
st->i2c_talk_onoff = 1;
|
||||
st->i2c_gate = 4;
|
||||
|
||||
st->i2c_gate = 4;
|
||||
adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe) {
|
||||
info("TUN Found Frontend TDA10086");
|
||||
memcpy(&adap->fe->ops.info.name,
|
||||
&"DM04_LG_TDQY-P001F DVB-S", 24);
|
||||
adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 4;
|
||||
st->i2c_tuner_addr = 0xc0;
|
||||
if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
|
||||
&adap->dev->i2c_adap, 1)) {
|
||||
info("TUN TDA8263 Found");
|
||||
st->tuner_config = TUNER_LG;
|
||||
if (dvb_usb_lme2510_firmware != 1) {
|
||||
dvb_usb_lme2510_firmware = 1;
|
||||
lme_firmware_switch(adap->dev->udev, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
kfree(adap->fe);
|
||||
adap->fe = NULL;
|
||||
st->tuner_config = TUNER_LG;
|
||||
if (dvb_usb_lme2510_firmware != 1) {
|
||||
dvb_usb_lme2510_firmware = 1;
|
||||
ret = lme_firmware_switch(adap->dev->udev, 1);
|
||||
} else /*stops LG/Sharp multi tuner problems*/
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
st->i2c_gate = 5;
|
||||
adap->fe = dvb_attach(stv0288_attach, &lme_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe) {
|
||||
info("FE Found Stv0288");
|
||||
memcpy(&adap->fe->ops.info.name,
|
||||
&"DM04_SHARP:BS2F7HZ7395", 22);
|
||||
adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
st->i2c_tuner_addr = 0xc0;
|
||||
if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
|
||||
&adap->dev->i2c_adap)) {
|
||||
st->tuner_config = TUNER_S7395;
|
||||
info("TUN Sharp IX2505V silicon tuner");
|
||||
if (dvb_usb_lme2510_firmware != 0) {
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
lme_firmware_switch(adap->dev->udev, 1);
|
||||
}
|
||||
return 0;
|
||||
st->tuner_config = TUNER_S7395;
|
||||
if (dvb_usb_lme2510_firmware != 0) {
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
ret = lme_firmware_switch(adap->dev->udev, 1);
|
||||
}
|
||||
kfree(adap->fe);
|
||||
adap->fe = NULL;
|
||||
} else {
|
||||
info("DM04 Not Supported");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
info("DM04 Not Supported");
|
||||
return -ENODEV;
|
||||
end: if (ret) {
|
||||
kfree(adap->fe);
|
||||
adap->fe = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
ret = lme_name(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
char *tun_msg[] = {"", "TDA8263", "IX2505V"};
|
||||
int ret = 0;
|
||||
|
||||
switch (st->tuner_config) {
|
||||
case TUNER_LG:
|
||||
if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
|
||||
&adap->dev->i2c_adap, 1))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
case TUNER_S7395:
|
||||
if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
|
||||
&adap->dev->i2c_adap))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
info("TUN Found %s tuner", tun_msg[ret]);
|
||||
else {
|
||||
info("TUN No tuner found --- reseting device");
|
||||
lme_coldreset(adap->dev->udev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Start the Interupt & Remote*/
|
||||
ret = lme2510_int_service(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
struct lme2510_state *st = d->priv;
|
||||
static u8 lnb_on[] = LNB_ON;
|
||||
static u8 lnb_off[] = LNB_OFF;
|
||||
static u8 rbuf[1];
|
||||
int ret, len = 3, rlen = 1;
|
||||
|
||||
ret = mutex_lock_interruptible(&d->i2c_mutex);
|
||||
|
||||
if (onoff)
|
||||
ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
|
||||
else
|
||||
ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
|
||||
|
||||
st->i2c_talk_onoff = 1;
|
||||
return 0;
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
|
@ -951,6 +974,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|||
{
|
||||
.streaming_ctrl = lme2510_streaming_ctrl,
|
||||
.frontend_attach = dm04_lme2510_frontend_attach,
|
||||
.tuner_attach = dm04_lme2510_tuner,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
|
@ -971,7 +995,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|||
.generic_bulk_ctrl_endpoint = 0,
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "DM04 LME2510 DVB-S USB 2.0",
|
||||
{ "DM04_LME2510_DVB-S",
|
||||
{ &lme2510_table[0], NULL },
|
||||
},
|
||||
|
||||
|
@ -989,6 +1013,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|||
{
|
||||
.streaming_ctrl = lme2510_streaming_ctrl,
|
||||
.frontend_attach = dm04_lme2510_frontend_attach,
|
||||
.tuner_attach = dm04_lme2510_tuner,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
|
@ -1009,7 +1034,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|||
.generic_bulk_ctrl_endpoint = 0,
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "DM04 LME2510C USB2.0",
|
||||
{ "DM04_LME2510C_DVB-S",
|
||||
{ &lme2510_table[1], NULL },
|
||||
},
|
||||
}
|
||||
|
@ -1036,7 +1061,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d)
|
|||
usb_free_coherent(d->udev, 5000, st->buffer,
|
||||
st->lme_urb->transfer_dma);
|
||||
info("Interupt Service Stopped");
|
||||
ir_input_unregister(d->rc_input_dev);
|
||||
rc_unregister_device(d->rc_dev);
|
||||
info("Remote Stopped");
|
||||
}
|
||||
return buffer;
|
||||
|
@ -1055,7 +1080,7 @@ void lme2510_exit(struct usb_interface *intf)
|
|||
}
|
||||
|
||||
static struct usb_driver lme2510_driver = {
|
||||
.name = "LME2510C_DVBS",
|
||||
.name = "LME2510C_DVB-S",
|
||||
.probe = lme2510_probe,
|
||||
.disconnect = lme2510_exit,
|
||||
.id_table = lme2510_table,
|
||||
|
@ -1083,6 +1108,6 @@ module_init(lme2510_module_init);
|
|||
module_exit(lme2510_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
||||
MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0");
|
||||
MODULE_VERSION("1.60");
|
||||
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
|
||||
MODULE_VERSION("1.74");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
|
||||
*event = d->props.rc.legacy.rc_map_table[i].keycode;
|
||||
|
||||
switch(rc_state[0]) {
|
||||
case 0x80:
|
||||
|
@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = {
|
|||
};
|
||||
|
||||
/* ir keymaps */
|
||||
static struct ir_scancode ir_codes_megasky_table[] = {
|
||||
static struct rc_map_table rc_map_megasky_table[] = {
|
||||
{ 0x0012, KEY_POWER },
|
||||
{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
|
||||
{ 0x0002, KEY_CHANNELUP },
|
||||
|
@ -608,7 +608,7 @@ static struct ir_scancode ir_codes_megasky_table[] = {
|
|||
{ 0x000e, KEY_COFFEE }, /* "MTS" */
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
|
||||
static struct rc_map_table rc_map_tvwalkertwin_table[] = {
|
||||
{ 0x0001, KEY_ZOOM }, /* Full Screen */
|
||||
{ 0x0002, KEY_CAMERA }, /* snapshot */
|
||||
{ 0x0003, KEY_MUTE },
|
||||
|
@ -628,7 +628,7 @@ static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
|
|||
{ 0x001e, KEY_VOLUMEUP },
|
||||
};
|
||||
|
||||
static struct ir_scancode ir_codes_pinnacle310e_table[] = {
|
||||
static struct rc_map_table rc_map_pinnacle310e_table[] = {
|
||||
{ 0x16, KEY_POWER },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
|
@ -786,8 +786,8 @@ static struct dvb_usb_device_properties megasky_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_megasky_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table),
|
||||
.rc_map_table = rc_map_megasky_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_megasky_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
|
@ -889,8 +889,8 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_tvwalkertwin_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
|
||||
.rc_map_table = rc_map_tvwalkertwin_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_tvwalkertwin_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
|
@ -998,8 +998,8 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_pinnacle310e_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table),
|
||||
.rc_map_table = rc_map_pinnacle310e_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_pinnacle310e_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
#define deb_ee(args...) dprintk(debug,0x02,args)
|
||||
|
||||
/* Hauppauge NOVA-T USB2 keys */
|
||||
static struct ir_scancode ir_codes_haupp_table[] = {
|
||||
static struct rc_map_table rc_map_haupp_table[] = {
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
|
@ -91,14 +91,14 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
|
||||
deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_codes_haupp_table); i++) {
|
||||
if (rc5_data(&ir_codes_haupp_table[i]) == data &&
|
||||
rc5_custom(&ir_codes_haupp_table[i]) == custom) {
|
||||
for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {
|
||||
if (rc5_data(&rc_map_haupp_table[i]) == data &&
|
||||
rc5_custom(&rc_map_haupp_table[i]) == custom) {
|
||||
|
||||
deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]),
|
||||
rc5_custom(&ir_codes_haupp_table[i]));
|
||||
deb_rc("c: %x, d: %x\n", rc5_data(&rc_map_haupp_table[i]),
|
||||
rc5_custom(&rc_map_haupp_table[i]));
|
||||
|
||||
*event = ir_codes_haupp_table[i].keycode;
|
||||
*event = rc_map_haupp_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
if (st->old_toggle == toggle) {
|
||||
if (st->last_repeat_count++ < 2)
|
||||
|
@ -197,8 +197,8 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_haupp_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table),
|
||||
.rc_map_table = rc_map_haupp_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_haupp_table),
|
||||
.rc_query = nova_t_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
struct opera1_state {
|
||||
u32 last_key_pressed;
|
||||
};
|
||||
struct ir_codes_opera_table {
|
||||
struct rc_map_opera_table {
|
||||
u32 keycode;
|
||||
u32 event;
|
||||
};
|
||||
|
@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_scancode ir_codes_opera1_table[] = {
|
||||
static struct rc_map_table rc_map_opera1_table[] = {
|
||||
{0x5fa0, KEY_1},
|
||||
{0x51af, KEY_2},
|
||||
{0x5da2, KEY_3},
|
||||
|
@ -404,12 +404,12 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
|
|||
|
||||
send_key = (send_key & 0xffff) | 0x0100;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) {
|
||||
if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) {
|
||||
for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) {
|
||||
if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_opera1_table[i].keycode;
|
||||
*event = rc_map_opera1_table[i].keycode;
|
||||
opst->last_key_pressed =
|
||||
ir_codes_opera1_table[i].keycode;
|
||||
rc_map_opera1_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
opst->last_key_pressed = 0;
|
||||
|
@ -497,8 +497,8 @@ static struct dvb_usb_device_properties opera1_properties = {
|
|||
.i2c_algo = &opera1_i2c_algo,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_opera1_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
|
||||
.rc_map_table = rc_map_opera1_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_opera1_table),
|
||||
.rc_interval = 200,
|
||||
.rc_query = opera1_rc_query,
|
||||
},
|
||||
|
|
|
@ -43,6 +43,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
|
||||
struct ttusb2_state {
|
||||
u8 id;
|
||||
u16 last_rc_key;
|
||||
};
|
||||
|
||||
static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
|
||||
|
@ -128,6 +129,33 @@ static struct i2c_algorithm ttusb2_i2c_algo = {
|
|||
.functionality = ttusb2_i2c_func,
|
||||
};
|
||||
|
||||
/* command to poll IR receiver (copied from pctv452e.c) */
|
||||
#define CMD_GET_IR_CODE 0x1b
|
||||
|
||||
/* IR */
|
||||
static int tt3650_rc_query(struct dvb_usb_device *d)
|
||||
{
|
||||
int ret;
|
||||
u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
|
||||
struct ttusb2_state *st = d->priv;
|
||||
ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (rx[8] & 0x01) {
|
||||
/* got a "press" event */
|
||||
st->last_rc_key = (rx[3] << 8) | rx[2];
|
||||
deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
|
||||
rc_keydown(d->rc_dev, st->last_rc_key, 0);
|
||||
} else if (st->last_rc_key) {
|
||||
rc_keyup(d->rc_dev);
|
||||
st->last_rc_key = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Callbacks for DVB USB */
|
||||
static int ttusb2_identify_state (struct usb_device *udev, struct
|
||||
dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
|
||||
|
@ -345,6 +373,13 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
|
|||
|
||||
.size_of_priv = sizeof(struct ttusb2_state),
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */
|
||||
.rc_codes = RC_MAP_TT_1500,
|
||||
.rc_query = tt3650_rc_query,
|
||||
.allowed_protos = RC_TYPE_UNKNOWN,
|
||||
},
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
|
|
|
@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct ir_scancode ir_codes_vp702x_table[] = {
|
||||
static struct rc_map_table rc_map_vp702x_table[] = {
|
||||
{ 0x0001, KEY_1 },
|
||||
{ 0x0002, KEY_2 },
|
||||
};
|
||||
|
@ -197,10 +197,10 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
|
||||
if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
|
||||
for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++)
|
||||
if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp702x_table[i].keycode;
|
||||
*event = rc_map_vp702x_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -284,8 +284,8 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
.read_mac_address = vp702x_read_mac_addr,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_vp702x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table),
|
||||
.rc_map_table = rc_map_vp702x_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_vp702x_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = vp702x_rc_query,
|
||||
},
|
||||
|
|
|
@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
|
||||
/* The keymapping struct. Somehow this should be loaded to the driver, but
|
||||
* currently it is hardcoded. */
|
||||
static struct ir_scancode ir_codes_vp7045_table[] = {
|
||||
static struct rc_map_table rc_map_vp7045_table[] = {
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
{ 0x0003, KEY_1 },
|
||||
|
@ -165,10 +165,10 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++)
|
||||
if (rc5_data(&ir_codes_vp7045_table[i]) == key) {
|
||||
for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++)
|
||||
if (rc5_data(&rc_map_vp7045_table[i]) == key) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp7045_table[i].keycode;
|
||||
*event = rc_map_vp7045_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -261,8 +261,8 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
|||
|
||||
.rc.legacy = {
|
||||
.rc_interval = 400,
|
||||
.rc_key_map = ir_codes_vp7045_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table),
|
||||
.rc_map_table = rc_map_vp7045_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_vp7045_table),
|
||||
.rc_query = vp7045_rc_query,
|
||||
},
|
||||
|
||||
|
|
|
@ -497,7 +497,7 @@ comment "ISDB-T (terrestrial) frontends"
|
|||
depends on DVB_CORE
|
||||
|
||||
config DVB_S921
|
||||
tristate "Sharp S921 tuner"
|
||||
tristate "Sharp S921 frontend"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
|
@ -512,6 +512,14 @@ config DVB_DIB8000
|
|||
A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MB86A20S
|
||||
tristate "Fujitsu mb86a20s"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "Digital terrestrial only tuners/PLL"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
||||
|
||||
s921-objs := s921_module.o s921_core.o
|
||||
stb0899-objs = stb0899_drv.o stb0899_algo.o
|
||||
stv0900-objs = stv0900_core.o stv0900_sw.o
|
||||
au8522-objs = au8522_dig.o au8522_decoder.o
|
||||
|
@ -82,4 +81,5 @@ obj-$(CONFIG_DVB_ISL6423) += isl6423.o
|
|||
obj-$(CONFIG_DVB_EC100) += ec100.o
|
||||
obj-$(CONFIG_DVB_DS3000) += ds3000.o
|
||||
obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
|
||||
obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
|
||||
obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
|
||||
|
|
|
@ -964,7 +964,7 @@ error:
|
|||
static int af9013_update_signal_strength(struct dvb_frontend *fe)
|
||||
{
|
||||
struct af9013_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
u8 rf_gain, if_gain;
|
||||
int signal_strength;
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data)
|
|||
msg2.addr = dev_addr;
|
||||
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n",
|
||||
__func__, reg, data);
|
||||
dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, &msg1, 1);
|
||||
if (ret != 1)
|
||||
|
@ -77,8 +76,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data)
|
|||
|
||||
ret = i2c_transfer(priv->i2c, &msg1, 1);
|
||||
if (ret != 1) {
|
||||
dprintk(KERN_DEBUG "%s: error reg=0x%04x, ret=%i\n",
|
||||
__func__, reg, ret);
|
||||
dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -88,7 +86,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data)
|
|||
|
||||
*p_data = buf2[0];
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n",
|
||||
dprintk("%s: reg=0x%04X, data=0x%02X\n",
|
||||
__func__, reg, buf2[0]);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -278,10 +278,18 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
|
||||
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
|
||||
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
|
||||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
|
||||
} else {
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
|
||||
}
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
|
||||
|
@ -347,9 +355,11 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state)
|
|||
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
|
||||
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
|
||||
|
||||
/* PGA in automatic mode */
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
|
||||
|
||||
/* Enable clamping control */
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
|
||||
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
|
||||
AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
|
||||
|
@ -366,14 +376,14 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
|
|||
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
|
||||
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
|
||||
|
||||
/* It's not clear why they turn off the PGA before enabling the clamp
|
||||
control, but the Windows trace does it so we will too... */
|
||||
/* It's not clear why we have to have the PGA in automatic mode while
|
||||
enabling clamp control, but it's what Windows does */
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
|
||||
|
||||
/* Enable clamping control */
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
|
||||
|
||||
/* Turn on the PGA */
|
||||
/* Disable automatic PGA (since the CVBS is coming from the tuner) */
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
|
||||
|
||||
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
|
||||
|
@ -396,7 +406,10 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
|
|||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
|
||||
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
|
||||
|
||||
/* Disable clamping control (required for S-video) */
|
||||
/* PGA in automatic mode */
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
|
||||
|
||||
/* Enable clamping control */
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
|
||||
|
||||
setup_decoder_defaults(state,
|
||||
|
@ -410,29 +423,15 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
|
|||
|
||||
static void disable_audio_input(struct au8522_state *state)
|
||||
{
|
||||
/* This can probably be optimized */
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
|
||||
au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
|
||||
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
|
||||
|
||||
au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
|
||||
au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
|
||||
au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
|
||||
|
||||
au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
|
||||
msleep(5);
|
||||
au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
|
||||
au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
|
||||
au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
|
||||
}
|
||||
|
||||
/* 0=disable, 1=SIF */
|
||||
|
@ -622,7 +621,7 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
|
|||
return v4l2_ctrl_query_fill(qc, 0, 255, 1,
|
||||
AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
|
||||
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
|
||||
case V4L2_CID_SATURATION:
|
||||
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
|
||||
case V4L2_CID_HUE:
|
||||
|
|
|
@ -397,7 +397,9 @@ void au8522_release_state(struct au8522_state *state);
|
|||
#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS 0x0A
|
||||
#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS 0x32
|
||||
#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS 0x34
|
||||
#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO 0x2a
|
||||
#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS 0x05
|
||||
#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO 0x15
|
||||
#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS 0x6E
|
||||
#define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS 0x0F
|
||||
#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS 0x80
|
||||
|
|
|
@ -805,7 +805,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
|
|||
value = 0;
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
|
||||
case /* 4K MODE */ 255: value |= (2 << 7); break;
|
||||
case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
|
||||
}
|
||||
|
@ -866,7 +866,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
|
|||
/* P_dvsy_sync_wait */
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_8K: value = 256; break;
|
||||
case /* 4K MODE */ 255: value = 128; break;
|
||||
case TRANSMISSION_MODE_4K: value = 128; break;
|
||||
case TRANSMISSION_MODE_2K:
|
||||
default: value = 64; break;
|
||||
}
|
||||
|
@ -1020,7 +1020,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
value = (6 << 8) | 0x80;
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
|
||||
case /* 4K MODE */ 255: value |= (8 << 12); break;
|
||||
case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
|
||||
}
|
||||
|
@ -1030,7 +1030,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
value = (0 << 4);
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= 0x6; break;
|
||||
case /* 4K MODE */ 255: value |= 0x7; break;
|
||||
case TRANSMISSION_MODE_4K: value |= 0x7; break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= 0x8; break;
|
||||
}
|
||||
|
@ -1040,7 +1040,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
value = (0 << 4);
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= 0x6; break;
|
||||
case /* 4K MODE */ 255: value |= 0x7; break;
|
||||
case TRANSMISSION_MODE_4K: value |= 0x7; break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= 0x8; break;
|
||||
}
|
||||
|
|
|
@ -717,7 +717,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
|
|||
value = 0;
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
|
||||
case /* 4K MODE */ 255: value |= (2 << 7); break;
|
||||
case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
|
||||
}
|
||||
|
@ -770,7 +770,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
|
|||
/* P_dvsy_sync_wait */
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_8K: value = 256; break;
|
||||
case /* 4K MODE */ 255: value = 128; break;
|
||||
case TRANSMISSION_MODE_4K: value = 128; break;
|
||||
case TRANSMISSION_MODE_2K:
|
||||
default: value = 64; break;
|
||||
}
|
||||
|
@ -994,7 +994,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
tmp = (6 << 8) | 0x80;
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
|
||||
case /* 4K MODE */ 255: tmp |= (8 << 12); break;
|
||||
case TRANSMISSION_MODE_4K: tmp |= (8 << 12); break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
|
||||
}
|
||||
|
@ -1004,7 +1004,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
tmp = (0 << 4);
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
|
||||
case /* 4K MODE */ 255: tmp |= 0x7; break;
|
||||
case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
|
||||
}
|
||||
|
@ -1014,7 +1014,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
|
|||
tmp = (0 << 4);
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
|
||||
case /* 4K MODE */ 255: tmp |= 0x7; break;
|
||||
case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ static int ix2505v_read_status_reg(struct ix2505v_state *state)
|
|||
ret = i2c_transfer(state->i2c, msg, 1);
|
||||
deb_i2c("Read %s ", __func__);
|
||||
|
||||
return (ret = 1) ? (int) b2[0] : -1;
|
||||
return (ret == 1) ? (int) b2[0] : -1;
|
||||
}
|
||||
|
||||
static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count)
|
||||
|
|
|
@ -60,13 +60,12 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
|
|||
msg.addr += 0x02;
|
||||
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
|
||||
__func__, reg, data);
|
||||
dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, &msg, 1);
|
||||
|
||||
if (ret != 1)
|
||||
dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
|
||||
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
|
||||
__func__, reg, data, ret);
|
||||
|
||||
return (ret != 1) ? -1 : 0;
|
||||
|
@ -91,15 +90,13 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
|
|||
|
||||
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||
if (ret != 2) {
|
||||
dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
|
||||
__func__, reg, ret);
|
||||
dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*p_data = b1[0];
|
||||
if (debug >= 2)
|
||||
printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
|
||||
__func__, reg, b1[0]);
|
||||
dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
615
drivers/media/dvb/frontends/mb86a20s.c
Normal file
615
drivers/media/dvb/frontends/mb86a20s.c
Normal file
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
|
||||
*
|
||||
* Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
* Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
|
||||
*
|
||||
* FIXME: Need to port to DVB v5.2 API
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "mb86a20s.h"
|
||||
|
||||
static int debug = 1;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
|
||||
|
||||
#define rc(args...) do { \
|
||||
printk(KERN_ERR "mb86a20s: " args); \
|
||||
} while (0)
|
||||
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
if (debug) { \
|
||||
printk(KERN_DEBUG "mb86a20s: %s: ", __func__); \
|
||||
printk(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct mb86a20s_state {
|
||||
struct i2c_adapter *i2c;
|
||||
const struct mb86a20s_config *config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
};
|
||||
|
||||
struct regdata {
|
||||
u8 reg;
|
||||
u8 data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialization sequence: Use whatevere default values that PV SBTVD
|
||||
* does on its initialisation, obtained via USB snoop
|
||||
*/
|
||||
static struct regdata mb86a20s_init[] = {
|
||||
{ 0x70, 0x0f },
|
||||
{ 0x70, 0xff },
|
||||
{ 0x08, 0x01 },
|
||||
{ 0x09, 0x3e },
|
||||
{ 0x50, 0xd1 },
|
||||
{ 0x51, 0x22 },
|
||||
{ 0x39, 0x01 },
|
||||
{ 0x71, 0x00 },
|
||||
{ 0x28, 0x2a },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0xff },
|
||||
{ 0x2b, 0x80 },
|
||||
{ 0x28, 0x20 },
|
||||
{ 0x29, 0x33 },
|
||||
{ 0x2a, 0xdf },
|
||||
{ 0x2b, 0xa9 },
|
||||
{ 0x3b, 0x21 },
|
||||
{ 0x3c, 0x3a },
|
||||
{ 0x01, 0x0d },
|
||||
{ 0x04, 0x08 },
|
||||
{ 0x05, 0x05 },
|
||||
{ 0x04, 0x0e },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x0f },
|
||||
{ 0x05, 0x14 },
|
||||
{ 0x04, 0x0b },
|
||||
{ 0x05, 0x8c },
|
||||
{ 0x04, 0x00 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x01 },
|
||||
{ 0x05, 0x07 },
|
||||
{ 0x04, 0x02 },
|
||||
{ 0x05, 0x0f },
|
||||
{ 0x04, 0x03 },
|
||||
{ 0x05, 0xa0 },
|
||||
{ 0x04, 0x09 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x0a },
|
||||
{ 0x05, 0xff },
|
||||
{ 0x04, 0x27 },
|
||||
{ 0x05, 0x64 },
|
||||
{ 0x04, 0x28 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x1e },
|
||||
{ 0x05, 0xff },
|
||||
{ 0x04, 0x29 },
|
||||
{ 0x05, 0x0a },
|
||||
{ 0x04, 0x32 },
|
||||
{ 0x05, 0x0a },
|
||||
{ 0x04, 0x14 },
|
||||
{ 0x05, 0x02 },
|
||||
{ 0x04, 0x04 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x05 },
|
||||
{ 0x05, 0x22 },
|
||||
{ 0x04, 0x06 },
|
||||
{ 0x05, 0x0e },
|
||||
{ 0x04, 0x07 },
|
||||
{ 0x05, 0xd8 },
|
||||
{ 0x04, 0x12 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x04, 0x13 },
|
||||
{ 0x05, 0xff },
|
||||
{ 0x52, 0x01 },
|
||||
{ 0x50, 0xa7 },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0xa8 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xa9 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xaa },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0xab },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xac },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xad },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0xae },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xaf },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x5e, 0x07 },
|
||||
{ 0x50, 0xdc },
|
||||
{ 0x51, 0x01 },
|
||||
{ 0x50, 0xdd },
|
||||
{ 0x51, 0xf4 },
|
||||
{ 0x50, 0xde },
|
||||
{ 0x51, 0x01 },
|
||||
{ 0x50, 0xdf },
|
||||
{ 0x51, 0xf4 },
|
||||
{ 0x50, 0xe0 },
|
||||
{ 0x51, 0x01 },
|
||||
{ 0x50, 0xe1 },
|
||||
{ 0x51, 0xf4 },
|
||||
{ 0x50, 0xb0 },
|
||||
{ 0x51, 0x07 },
|
||||
{ 0x50, 0xb2 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xb3 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xb4 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xb5 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xb6 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0xb7 },
|
||||
{ 0x51, 0xff },
|
||||
{ 0x50, 0x50 },
|
||||
{ 0x51, 0x02 },
|
||||
{ 0x50, 0x51 },
|
||||
{ 0x51, 0x04 },
|
||||
{ 0x45, 0x04 },
|
||||
{ 0x48, 0x04 },
|
||||
{ 0x50, 0xd5 },
|
||||
{ 0x51, 0x01 }, /* Serial */
|
||||
{ 0x50, 0xd6 },
|
||||
{ 0x51, 0x1f },
|
||||
{ 0x50, 0xd2 },
|
||||
{ 0x51, 0x03 },
|
||||
{ 0x50, 0xd7 },
|
||||
{ 0x51, 0x3f },
|
||||
{ 0x1c, 0x01 },
|
||||
{ 0x28, 0x06 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x03 },
|
||||
{ 0x28, 0x07 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x0d },
|
||||
{ 0x28, 0x08 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x02 },
|
||||
{ 0x28, 0x09 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x01 },
|
||||
{ 0x28, 0x0a },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x21 },
|
||||
{ 0x28, 0x0b },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x29 },
|
||||
{ 0x28, 0x0c },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x16 },
|
||||
{ 0x28, 0x0d },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x31 },
|
||||
{ 0x28, 0x0e },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x0e },
|
||||
{ 0x28, 0x0f },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x4e },
|
||||
{ 0x28, 0x10 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x46 },
|
||||
{ 0x28, 0x11 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x0f },
|
||||
{ 0x28, 0x12 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x56 },
|
||||
{ 0x28, 0x13 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x35 },
|
||||
{ 0x28, 0x14 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x01 },
|
||||
{ 0x2b, 0xbe },
|
||||
{ 0x28, 0x15 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x01 },
|
||||
{ 0x2b, 0x84 },
|
||||
{ 0x28, 0x16 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x03 },
|
||||
{ 0x2b, 0xee },
|
||||
{ 0x28, 0x17 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x98 },
|
||||
{ 0x28, 0x18 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x2b, 0x9f },
|
||||
{ 0x28, 0x19 },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x07 },
|
||||
{ 0x2b, 0xb2 },
|
||||
{ 0x28, 0x1a },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x06 },
|
||||
{ 0x2b, 0xc2 },
|
||||
{ 0x28, 0x1b },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x07 },
|
||||
{ 0x2b, 0x4a },
|
||||
{ 0x28, 0x1c },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x01 },
|
||||
{ 0x2b, 0xbc },
|
||||
{ 0x28, 0x1d },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x04 },
|
||||
{ 0x2b, 0xba },
|
||||
{ 0x28, 0x1e },
|
||||
{ 0x29, 0x00 },
|
||||
{ 0x2a, 0x06 },
|
||||
{ 0x2b, 0x14 },
|
||||
{ 0x50, 0x1e },
|
||||
{ 0x51, 0x5d },
|
||||
{ 0x50, 0x22 },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0x23 },
|
||||
{ 0x51, 0xc8 },
|
||||
{ 0x50, 0x24 },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0x25 },
|
||||
{ 0x51, 0xf0 },
|
||||
{ 0x50, 0x26 },
|
||||
{ 0x51, 0x00 },
|
||||
{ 0x50, 0x27 },
|
||||
{ 0x51, 0xc3 },
|
||||
{ 0x50, 0x39 },
|
||||
{ 0x51, 0x02 },
|
||||
{ 0x50, 0xd5 },
|
||||
{ 0x51, 0x01 },
|
||||
{ 0xd0, 0x00 },
|
||||
};
|
||||
|
||||
static struct regdata mb86a20s_reset_reception[] = {
|
||||
{ 0x70, 0xf0 },
|
||||
{ 0x70, 0xff },
|
||||
{ 0x08, 0x01 },
|
||||
{ 0x08, 0x00 },
|
||||
};
|
||||
|
||||
static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
|
||||
u8 i2c_addr, int reg, int data)
|
||||
{
|
||||
u8 buf[] = { reg, data };
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = i2c_transfer(state->i2c, &msg, 1);
|
||||
if (rc != 1) {
|
||||
printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
|
||||
" data == 0x%02x)\n", __func__, rc, reg, data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
|
||||
u8 i2c_addr, struct regdata *rd, int size)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
|
||||
rd[i].data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
|
||||
u8 i2c_addr, u8 reg)
|
||||
{
|
||||
u8 val;
|
||||
int rc;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
|
||||
};
|
||||
|
||||
rc = i2c_transfer(state->i2c, msg, 2);
|
||||
|
||||
if (rc != 2) {
|
||||
rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define mb86a20s_readreg(state, reg) \
|
||||
mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
|
||||
#define mb86a20s_writereg(state, reg, val) \
|
||||
mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
|
||||
#define mb86a20s_writeregdata(state, regdata) \
|
||||
mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
|
||||
regdata, ARRAY_SIZE(regdata))
|
||||
|
||||
static int mb86a20s_initfe(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
int rc;
|
||||
u8 regD5 = 1;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
/* Initialize the frontend */
|
||||
rc = mb86a20s_writeregdata(state, mb86a20s_init);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (!state->config->is_serial) {
|
||||
regD5 &= ~1;
|
||||
|
||||
rc = mb86a20s_writereg(state, 0x50, 0xd5);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = mb86a20s_writereg(state, 0x51, regD5);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
unsigned rf_max, rf_min, rf;
|
||||
u8 val;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
/* Does a binary search to get RF strength */
|
||||
rf_max = 0xfff;
|
||||
rf_min = 0;
|
||||
do {
|
||||
rf = (rf_max + rf_min) / 2;
|
||||
mb86a20s_writereg(state, 0x04, 0x1f);
|
||||
mb86a20s_writereg(state, 0x05, rf >> 8);
|
||||
mb86a20s_writereg(state, 0x04, 0x20);
|
||||
mb86a20s_writereg(state, 0x04, rf);
|
||||
|
||||
val = mb86a20s_readreg(state, 0x02);
|
||||
if (val & 0x08)
|
||||
rf_min = (rf_max + rf_min) / 2;
|
||||
else
|
||||
rf_max = (rf_max + rf_min) / 2;
|
||||
if (rf_max - rf_min < 4) {
|
||||
*strength = (((rf_max + rf_min) / 2) * 65535) / 4095;
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
dprintk("signal strength = %d\n", *strength);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
dprintk("\n");
|
||||
*status = 0;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
val = mb86a20s_readreg(state, 0x0a) & 0xf;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
if (val >= 2)
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
|
||||
if (val >= 4)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
|
||||
if (val >= 5)
|
||||
*status |= FE_HAS_VITERBI;
|
||||
|
||||
if (val >= 7)
|
||||
*status |= FE_HAS_SYNC;
|
||||
|
||||
if (val >= 8) /* Maybe 9? */
|
||||
*status |= FE_HAS_LOCK;
|
||||
|
||||
dprintk("val = %d, status = 0x%02x\n", val, *status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
int rc;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mb86a20s_get_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
|
||||
/* FIXME: For now, it does nothing */
|
||||
|
||||
fe->dtv_property_cache.bandwidth_hz = 6000000;
|
||||
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
|
||||
fe->dtv_property_cache.isdbt_partial_reception = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mb86a20s_tune(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay,
|
||||
fe_status_t *status)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
if (params != NULL)
|
||||
rc = mb86a20s_set_frontend(fe, params);
|
||||
|
||||
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
|
||||
mb86a20s_read_status(fe, status);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void mb86a20s_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops mb86a20s_ops;
|
||||
|
||||
struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
u8 rev;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
struct mb86a20s_state *state =
|
||||
kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
|
||||
|
||||
dprintk("\n");
|
||||
if (state == NULL) {
|
||||
rc("Unable to kzalloc\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &mb86a20s_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* Check if it is a mb86a20s frontend */
|
||||
rev = mb86a20s_readreg(state, 0);
|
||||
|
||||
if (rev == 0x13) {
|
||||
printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n");
|
||||
} else {
|
||||
printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n",
|
||||
rev);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(mb86a20s_attach);
|
||||
|
||||
static struct dvb_frontend_ops mb86a20s_ops = {
|
||||
/* Use dib8000 values per default */
|
||||
.info = {
|
||||
.name = "Fujitsu mb86A20s",
|
||||
.type = FE_OFDM,
|
||||
.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
|
||||
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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
|
||||
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
|
||||
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
|
||||
/* Actually, those values depend on the used tuner */
|
||||
.frequency_min = 45000000,
|
||||
.frequency_max = 864000000,
|
||||
.frequency_stepsize = 62500,
|
||||
},
|
||||
|
||||
.release = mb86a20s_release,
|
||||
|
||||
.init = mb86a20s_initfe,
|
||||
.set_frontend = mb86a20s_set_frontend,
|
||||
.get_frontend = mb86a20s_get_frontend,
|
||||
.read_status = mb86a20s_read_status,
|
||||
.read_signal_strength = mb86a20s_read_signal_strength,
|
||||
.tune = mb86a20s_tune,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
52
drivers/media/dvb/frontends/mb86a20s.h
Normal file
52
drivers/media/dvb/frontends/mb86a20s.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Fujitsu mb86a20s driver
|
||||
*
|
||||
* Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MB86A20S_H
|
||||
#define MB86A20S_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
/**
|
||||
* struct mb86a20s_config - Define the per-device attributes of the frontend
|
||||
*
|
||||
* @demod_address: the demodulator's i2c address
|
||||
*/
|
||||
|
||||
struct mb86a20s_config {
|
||||
u8 demod_address;
|
||||
bool is_serial;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
|
||||
&& defined(MODULE))
|
||||
extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
|
||||
#else
|
||||
static inline struct dvb_frontend *mb86a20s_attach(
|
||||
const struct mb86a20s_config *config, struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
static struct i2c_adapter *
|
||||
mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MB86A20S */
|
548
drivers/media/dvb/frontends/s921.c
Normal file
548
drivers/media/dvb/frontends/s921.c
Normal file
|
@ -0,0 +1,548 @@
|
|||
/*
|
||||
* Sharp VA3A5JZ921 One Seg Broadcast Module driver
|
||||
* This device is labeled as just S. 921 at the top of the frontend can
|
||||
*
|
||||
* Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
* Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
|
||||
*
|
||||
* Developed for Leadership SBTVD 1seg device sold in Brazil
|
||||
*
|
||||
* Frontend module based on cx24123 driver, getting some info from
|
||||
* the old s921 driver.
|
||||
*
|
||||
* FIXME: Need to port to DVB v5.2 API
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "s921.h"
|
||||
|
||||
static int debug = 1;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
|
||||
|
||||
#define rc(args...) do { \
|
||||
printk(KERN_ERR "s921: " args); \
|
||||
} while (0)
|
||||
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
if (debug) { \
|
||||
printk(KERN_DEBUG "s921: %s: ", __func__); \
|
||||
printk(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct s921_state {
|
||||
struct i2c_adapter *i2c;
|
||||
const struct s921_config *config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
/* The Demod can't easily provide these, we cache them */
|
||||
u32 currentfreq;
|
||||
};
|
||||
|
||||
/*
|
||||
* Various tuner defaults need to be established for a given frequency kHz.
|
||||
* fixme: The bounds on the bands do not match the doc in real life.
|
||||
* fixme: Some of them have been moved, other might need adjustment.
|
||||
*/
|
||||
static struct s921_bandselect_val {
|
||||
u32 freq_low;
|
||||
u8 band_reg;
|
||||
} s921_bandselect[] = {
|
||||
{ 0, 0x7b },
|
||||
{ 485140000, 0x5b },
|
||||
{ 515140000, 0x3b },
|
||||
{ 545140000, 0x1b },
|
||||
{ 599140000, 0xfb },
|
||||
{ 623140000, 0xdb },
|
||||
{ 659140000, 0xbb },
|
||||
{ 713140000, 0x9b },
|
||||
};
|
||||
|
||||
struct regdata {
|
||||
u8 reg;
|
||||
u8 data;
|
||||
};
|
||||
|
||||
static struct regdata s921_init[] = {
|
||||
{ 0x01, 0x80 }, /* Probably, a reset sequence */
|
||||
{ 0x01, 0x40 },
|
||||
{ 0x01, 0x80 },
|
||||
{ 0x01, 0x40 },
|
||||
|
||||
{ 0x02, 0x00 },
|
||||
{ 0x03, 0x40 },
|
||||
{ 0x04, 0x01 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x06, 0x00 },
|
||||
{ 0x07, 0x00 },
|
||||
{ 0x08, 0x00 },
|
||||
{ 0x09, 0x00 },
|
||||
{ 0x0a, 0x00 },
|
||||
{ 0x0b, 0x5a },
|
||||
{ 0x0c, 0x00 },
|
||||
{ 0x0d, 0x00 },
|
||||
{ 0x0f, 0x00 },
|
||||
{ 0x13, 0x1b },
|
||||
{ 0x14, 0x80 },
|
||||
{ 0x15, 0x40 },
|
||||
{ 0x17, 0x70 },
|
||||
{ 0x18, 0x01 },
|
||||
{ 0x19, 0x12 },
|
||||
{ 0x1a, 0x01 },
|
||||
{ 0x1b, 0x12 },
|
||||
{ 0x1c, 0xa0 },
|
||||
{ 0x1d, 0x00 },
|
||||
{ 0x1e, 0x0a },
|
||||
{ 0x1f, 0x08 },
|
||||
{ 0x20, 0x40 },
|
||||
{ 0x21, 0xff },
|
||||
{ 0x22, 0x4c },
|
||||
{ 0x23, 0x4e },
|
||||
{ 0x24, 0x4c },
|
||||
{ 0x25, 0x00 },
|
||||
{ 0x26, 0x00 },
|
||||
{ 0x27, 0xf4 },
|
||||
{ 0x28, 0x60 },
|
||||
{ 0x29, 0x88 },
|
||||
{ 0x2a, 0x40 },
|
||||
{ 0x2b, 0x40 },
|
||||
{ 0x2c, 0xff },
|
||||
{ 0x2d, 0x00 },
|
||||
{ 0x2e, 0xff },
|
||||
{ 0x2f, 0x00 },
|
||||
{ 0x30, 0x20 },
|
||||
{ 0x31, 0x06 },
|
||||
{ 0x32, 0x0c },
|
||||
{ 0x34, 0x0f },
|
||||
{ 0x37, 0xfe },
|
||||
{ 0x38, 0x00 },
|
||||
{ 0x39, 0x63 },
|
||||
{ 0x3a, 0x10 },
|
||||
{ 0x3b, 0x10 },
|
||||
{ 0x47, 0x00 },
|
||||
{ 0x49, 0xe5 },
|
||||
{ 0x4b, 0x00 },
|
||||
{ 0x50, 0xc0 },
|
||||
{ 0x52, 0x20 },
|
||||
{ 0x54, 0x5a },
|
||||
{ 0x55, 0x5b },
|
||||
{ 0x56, 0x40 },
|
||||
{ 0x57, 0x70 },
|
||||
{ 0x5c, 0x50 },
|
||||
{ 0x5d, 0x00 },
|
||||
{ 0x62, 0x17 },
|
||||
{ 0x63, 0x2f },
|
||||
{ 0x64, 0x6f },
|
||||
{ 0x68, 0x00 },
|
||||
{ 0x69, 0x89 },
|
||||
{ 0x6a, 0x00 },
|
||||
{ 0x6b, 0x00 },
|
||||
{ 0x6c, 0x00 },
|
||||
{ 0x6d, 0x00 },
|
||||
{ 0x6e, 0x00 },
|
||||
{ 0x70, 0x10 },
|
||||
{ 0x71, 0x00 },
|
||||
{ 0x75, 0x00 },
|
||||
{ 0x76, 0x30 },
|
||||
{ 0x77, 0x01 },
|
||||
{ 0xaf, 0x00 },
|
||||
{ 0xb0, 0xa0 },
|
||||
{ 0xb2, 0x3d },
|
||||
{ 0xb3, 0x25 },
|
||||
{ 0xb4, 0x8b },
|
||||
{ 0xb5, 0x4b },
|
||||
{ 0xb6, 0x3f },
|
||||
{ 0xb7, 0xff },
|
||||
{ 0xb8, 0xff },
|
||||
{ 0xb9, 0xfc },
|
||||
{ 0xba, 0x00 },
|
||||
{ 0xbb, 0x00 },
|
||||
{ 0xbc, 0x00 },
|
||||
{ 0xd0, 0x30 },
|
||||
{ 0xe4, 0x84 },
|
||||
{ 0xf0, 0x48 },
|
||||
{ 0xf1, 0x19 },
|
||||
{ 0xf2, 0x5a },
|
||||
{ 0xf3, 0x8e },
|
||||
{ 0xf4, 0x2d },
|
||||
{ 0xf5, 0x07 },
|
||||
{ 0xf6, 0x5a },
|
||||
{ 0xf7, 0xba },
|
||||
{ 0xf8, 0xd7 },
|
||||
};
|
||||
|
||||
static struct regdata s921_prefreq[] = {
|
||||
{ 0x47, 0x60 },
|
||||
{ 0x68, 0x00 },
|
||||
{ 0x69, 0x89 },
|
||||
{ 0xf0, 0x48 },
|
||||
{ 0xf1, 0x19 },
|
||||
};
|
||||
|
||||
static struct regdata s921_postfreq[] = {
|
||||
{ 0xf5, 0xae },
|
||||
{ 0xf6, 0xb7 },
|
||||
{ 0xf7, 0xba },
|
||||
{ 0xf8, 0xd7 },
|
||||
{ 0x68, 0x0a },
|
||||
{ 0x69, 0x09 },
|
||||
};
|
||||
|
||||
static int s921_i2c_writereg(struct s921_state *state,
|
||||
u8 i2c_addr, int reg, int data)
|
||||
{
|
||||
u8 buf[] = { reg, data };
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = i2c_transfer(state->i2c, &msg, 1);
|
||||
if (rc != 1) {
|
||||
printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
|
||||
" data == 0x%02x)\n", __func__, rc, reg, data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
|
||||
struct regdata *rd, int size)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
|
||||
{
|
||||
u8 val;
|
||||
int rc;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
|
||||
};
|
||||
|
||||
rc = i2c_transfer(state->i2c, msg, 2);
|
||||
|
||||
if (rc != 2) {
|
||||
rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define s921_readreg(state, reg) \
|
||||
s921_i2c_readreg(state, state->config->demod_address, reg)
|
||||
#define s921_writereg(state, reg, val) \
|
||||
s921_i2c_writereg(state, state->config->demod_address, reg, val)
|
||||
#define s921_writeregdata(state, regdata) \
|
||||
s921_i2c_writeregdata(state, state->config->demod_address, \
|
||||
regdata, ARRAY_SIZE(regdata))
|
||||
|
||||
static int s921_pll_tune(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
int band, rc, i;
|
||||
unsigned long f_offset;
|
||||
u8 f_switch;
|
||||
u64 offset;
|
||||
|
||||
dprintk("frequency=%i\n", p->frequency);
|
||||
|
||||
for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
|
||||
if (p->frequency < s921_bandselect[band].freq_low)
|
||||
break;
|
||||
band--;
|
||||
|
||||
if (band < 0) {
|
||||
rc("%s: frequency out of range\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f_switch = s921_bandselect[band].band_reg;
|
||||
|
||||
offset = ((u64)p->frequency) * 258;
|
||||
do_div(offset, 6000000);
|
||||
f_offset = ((unsigned long)offset) + 2321;
|
||||
|
||||
rc = s921_writeregdata(state, s921_prefreq);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = s921_writereg(state, 0xf3, f_offset & 0xff);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = s921_writereg(state, 0xf4, f_switch);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = s921_writeregdata(state, s921_postfreq);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
for (i = 0 ; i < 6; i++) {
|
||||
rc = s921_readreg(state, 0x80);
|
||||
dprintk("status 0x80: %02x\n", rc);
|
||||
}
|
||||
rc = s921_writereg(state, 0x01, 0x40);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = s921_readreg(state, 0x01);
|
||||
dprintk("status 0x01: %02x\n", rc);
|
||||
|
||||
rc = s921_readreg(state, 0x80);
|
||||
dprintk("status 0x80: %02x\n", rc);
|
||||
|
||||
rc = s921_readreg(state, 0x80);
|
||||
dprintk("status 0x80: %02x\n", rc);
|
||||
|
||||
rc = s921_readreg(state, 0x32);
|
||||
dprintk("status 0x32: %02x\n", rc);
|
||||
|
||||
dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_initfe(struct dvb_frontend *fe)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
int rc;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
rc = s921_writeregdata(state, s921_init);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
int regstatus, rc;
|
||||
|
||||
*status = 0;
|
||||
|
||||
rc = s921_readreg(state, 0x81);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
regstatus = rc << 8;
|
||||
|
||||
rc = s921_readreg(state, 0x82);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
regstatus |= rc;
|
||||
|
||||
dprintk("status = %04x\n", regstatus);
|
||||
|
||||
/* Full Sync - We don't know what each bit means on regs 0x81/0x82 */
|
||||
if ((regstatus & 0xff) == 0x40) {
|
||||
*status = FE_HAS_SIGNAL |
|
||||
FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI |
|
||||
FE_HAS_SYNC |
|
||||
FE_HAS_LOCK;
|
||||
} else if (regstatus & 0x40) {
|
||||
/* This is close to Full Sync, but not enough to get useful info */
|
||||
*status = FE_HAS_SIGNAL |
|
||||
FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI |
|
||||
FE_HAS_SYNC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
fe_status_t status;
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
int rc;
|
||||
|
||||
/* FIXME: Use the proper register for it... 0x80? */
|
||||
rc = s921_read_status(fe, &status);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
*strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
|
||||
|
||||
dprintk("strength = 0x%04x\n", *strength);
|
||||
|
||||
rc = s921_readreg(state, 0x01);
|
||||
dprintk("status 0x01: %02x\n", rc);
|
||||
|
||||
rc = s921_readreg(state, 0x80);
|
||||
dprintk("status 0x80: %02x\n", rc);
|
||||
|
||||
rc = s921_readreg(state, 0x32);
|
||||
dprintk("status 0x32: %02x\n", rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
int rc;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
/* FIXME: We don't know how to use non-auto mode */
|
||||
|
||||
rc = s921_pll_tune(fe, p);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
state->currentfreq = p->frequency;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_get_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
|
||||
/* FIXME: Probably it is possible to get it from regs f1 and f2 */
|
||||
p->frequency = state->currentfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_tune(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay,
|
||||
fe_status_t *status)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
dprintk("\n");
|
||||
|
||||
if (params != NULL)
|
||||
rc = s921_set_frontend(fe, params);
|
||||
|
||||
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
|
||||
s921_read_status(fe, status);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int s921_get_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return 1; /* FE_ALGO_HW */
|
||||
}
|
||||
|
||||
static void s921_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct s921_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk("\n");
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops s921_ops;
|
||||
|
||||
struct dvb_frontend *s921_attach(const struct s921_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
/* allocate memory for the internal state */
|
||||
struct s921_state *state =
|
||||
kzalloc(sizeof(struct s921_state), GFP_KERNEL);
|
||||
|
||||
dprintk("\n");
|
||||
if (state == NULL) {
|
||||
rc("Unable to kzalloc\n");
|
||||
goto rcor;
|
||||
}
|
||||
|
||||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &s921_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
rcor:
|
||||
kfree(state);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(s921_attach);
|
||||
|
||||
static struct dvb_frontend_ops s921_ops = {
|
||||
/* Use dib8000 values per default */
|
||||
.info = {
|
||||
.name = "Sharp S921",
|
||||
.type = FE_OFDM,
|
||||
.frequency_min = 470000000,
|
||||
/*
|
||||
* Max should be 770MHz instead, according with Sharp docs,
|
||||
* but Leadership doc says it works up to 806 MHz. This is
|
||||
* required to get channel 69, used in Brazil
|
||||
*/
|
||||
.frequency_max = 806000000,
|
||||
.frequency_tolerance = 0,
|
||||
.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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
|
||||
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
|
||||
FE_CAN_HIERARCHY_AUTO,
|
||||
},
|
||||
|
||||
.release = s921_release,
|
||||
|
||||
.init = s921_initfe,
|
||||
.set_frontend = s921_set_frontend,
|
||||
.get_frontend = s921_get_frontend,
|
||||
.read_status = s921_read_status,
|
||||
.read_signal_strength = s921_read_signal_strength,
|
||||
.tune = s921_tune,
|
||||
.get_frontend_algo = s921_get_algo,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
||||
MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
47
drivers/media/dvb/frontends/s921.h
Normal file
47
drivers/media/dvb/frontends/s921.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Sharp s921 driver
|
||||
*
|
||||
* Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
* Copyright (C) 2009 Douglas Landgraf <dougsland@redhat.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef S921_H
|
||||
#define S921_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
struct s921_config {
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
|
||||
&& defined(MODULE))
|
||||
extern struct dvb_frontend *s921_attach(const struct s921_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
|
||||
#else
|
||||
static inline struct dvb_frontend *s921_attach(
|
||||
const struct s921_config *config, struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
static struct i2c_adapter *
|
||||
s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* S921_H */
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
* Driver for Sharp s921 driver
|
||||
*
|
||||
* Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include "s921_core.h"
|
||||
|
||||
static int s921_isdb_init(struct s921_isdb_t *dev);
|
||||
static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params);
|
||||
static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params);
|
||||
static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data);
|
||||
|
||||
static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01,
|
||||
0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
|
||||
0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00,
|
||||
0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80,
|
||||
0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12,
|
||||
0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00,
|
||||
0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff,
|
||||
0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00,
|
||||
0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88,
|
||||
0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00,
|
||||
0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06,
|
||||
0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00,
|
||||
0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00,
|
||||
0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20,
|
||||
0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70,
|
||||
0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f,
|
||||
0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00,
|
||||
0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00,
|
||||
0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30,
|
||||
0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d,
|
||||
0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f,
|
||||
0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00,
|
||||
0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84,
|
||||
0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e,
|
||||
0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba,
|
||||
0xf8, 0xd7 };
|
||||
|
||||
static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b,
|
||||
0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b,
|
||||
0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b,
|
||||
0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b,
|
||||
0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b,
|
||||
0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b,
|
||||
0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b,
|
||||
0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb,
|
||||
0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb,
|
||||
0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb,
|
||||
0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb,
|
||||
0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb,
|
||||
0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb,
|
||||
0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b,
|
||||
0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b,
|
||||
0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b,
|
||||
0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b };
|
||||
|
||||
int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) {
|
||||
switch(cmd) {
|
||||
case ISDB_T_CMD_INIT:
|
||||
s921_isdb_init(dev);
|
||||
break;
|
||||
case ISDB_T_CMD_SET_PARAM:
|
||||
s921_isdb_set_parameters(dev, data);
|
||||
break;
|
||||
case ISDB_T_CMD_TUNE:
|
||||
s921_isdb_tune(dev, data);
|
||||
break;
|
||||
case ISDB_T_CMD_GET_STATUS:
|
||||
s921_isdb_get_status(dev, data);
|
||||
break;
|
||||
default:
|
||||
printk("unhandled command\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_isdb_init(struct s921_isdb_t *dev) {
|
||||
unsigned int i;
|
||||
unsigned int ret;
|
||||
printk("isdb_init\n");
|
||||
for (i = 0; i < sizeof(init_table); i+=2) {
|
||||
ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]);
|
||||
if (ret != 0) {
|
||||
printk("i2c write failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) {
|
||||
|
||||
int ret;
|
||||
/* auto is sufficient for now, lateron this should be reflected in an extra interface */
|
||||
|
||||
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2);
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2);
|
||||
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) {
|
||||
|
||||
int ret;
|
||||
int index;
|
||||
|
||||
index = (params->frequency - 473143000)/6000000;
|
||||
|
||||
if (index > 48) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->i2c_write(dev->priv_dev, 0x47, 0x60);
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
dev->i2c_write(dev->priv_dev, 0x01, 0x40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) {
|
||||
unsigned int *ret = (unsigned int*)data;
|
||||
u8 ifagc_dt;
|
||||
u8 rfagc_dt;
|
||||
|
||||
mdelay(10);
|
||||
ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81);
|
||||
rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82);
|
||||
if (rfagc_dt == 0x40) {
|
||||
*ret = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
#ifndef _S921_CORE_H
|
||||
#define _S921_CORE_H
|
||||
//#define u8 unsigned int
|
||||
//#define u32 unsigned int
|
||||
|
||||
|
||||
|
||||
//#define EINVAL -1
|
||||
#define E_OK 0
|
||||
|
||||
struct s921_isdb_t {
|
||||
void *priv_dev;
|
||||
int (*i2c_write)(void *dev, u8 reg, u8 val);
|
||||
int (*i2c_read)(void *dev, u8 reg);
|
||||
};
|
||||
|
||||
#define ISDB_T_CMD_INIT 0
|
||||
#define ISDB_T_CMD_SET_PARAM 1
|
||||
#define ISDB_T_CMD_TUNE 2
|
||||
#define ISDB_T_CMD_GET_STATUS 3
|
||||
|
||||
struct s921_isdb_t_tune_params {
|
||||
u32 frequency;
|
||||
};
|
||||
|
||||
struct s921_isdb_t_status {
|
||||
};
|
||||
|
||||
struct s921_isdb_t_transmission_mode_params {
|
||||
u8 mode;
|
||||
u8 layer_a_mode;
|
||||
#define ISDB_T_LA_MODE_1 0
|
||||
#define ISDB_T_LA_MODE_2 1
|
||||
#define ISDB_T_LA_MODE_3 2
|
||||
u8 layer_a_carrier_modulation;
|
||||
#define ISDB_T_LA_CM_DQPSK 0
|
||||
#define ISDB_T_LA_CM_QPSK 1
|
||||
#define ISDB_T_LA_CM_16QAM 2
|
||||
#define ISDB_T_LA_CM_64QAM 3
|
||||
#define ISDB_T_LA_CM_NOLAYER 4
|
||||
u8 layer_a_code_rate;
|
||||
#define ISDB_T_LA_CR_1_2 0
|
||||
#define ISDB_T_LA_CR_2_3 1
|
||||
#define ISDB_T_LA_CR_3_4 2
|
||||
#define ISDB_T_LA_CR_5_6 4
|
||||
#define ISDB_T_LA_CR_7_8 8
|
||||
#define ISDB_T_LA_CR_NOLAYER 16
|
||||
u8 layer_a_time_interleave;
|
||||
#define ISDB_T_LA_TI_0 0
|
||||
#define ISDB_T_LA_TI_1 1
|
||||
#define ISDB_T_LA_TI_2 2
|
||||
#define ISDB_T_LA_TI_4 4
|
||||
#define ISDB_T_LA_TI_8 8
|
||||
#define ISDB_T_LA_TI_16 16
|
||||
#define ISDB_T_LA_TI_32 32
|
||||
u8 layer_a_nseg;
|
||||
|
||||
u8 layer_b_mode;
|
||||
#define ISDB_T_LB_MODE_1 0
|
||||
#define ISDB_T_LB_MODE_2 1
|
||||
#define ISDB_T_LB_MODE_3 2
|
||||
u8 layer_b_carrier_modulation;
|
||||
#define ISDB_T_LB_CM_DQPSK 0
|
||||
#define ISDB_T_LB_CM_QPSK 1
|
||||
#define ISDB_T_LB_CM_16QAM 2
|
||||
#define ISDB_T_LB_CM_64QAM 3
|
||||
#define ISDB_T_LB_CM_NOLAYER 4
|
||||
u8 layer_b_code_rate;
|
||||
#define ISDB_T_LB_CR_1_2 0
|
||||
#define ISDB_T_LB_CR_2_3 1
|
||||
#define ISDB_T_LB_CR_3_4 2
|
||||
#define ISDB_T_LB_CR_5_6 4
|
||||
#define ISDB_T_LB_CR_7_8 8
|
||||
#define ISDB_T_LB_CR_NOLAYER 16
|
||||
u8 layer_b_time_interleave;
|
||||
#define ISDB_T_LB_TI_0 0
|
||||
#define ISDB_T_LB_TI_1 1
|
||||
#define ISDB_T_LB_TI_2 2
|
||||
#define ISDB_T_LB_TI_4 4
|
||||
#define ISDB_T_LB_TI_8 8
|
||||
#define ISDB_T_LB_TI_16 16
|
||||
#define ISDB_T_LB_TI_32 32
|
||||
u8 layer_b_nseg;
|
||||
|
||||
u8 layer_c_mode;
|
||||
#define ISDB_T_LC_MODE_1 0
|
||||
#define ISDB_T_LC_MODE_2 1
|
||||
#define ISDB_T_LC_MODE_3 2
|
||||
u8 layer_c_carrier_modulation;
|
||||
#define ISDB_T_LC_CM_DQPSK 0
|
||||
#define ISDB_T_LC_CM_QPSK 1
|
||||
#define ISDB_T_LC_CM_16QAM 2
|
||||
#define ISDB_T_LC_CM_64QAM 3
|
||||
#define ISDB_T_LC_CM_NOLAYER 4
|
||||
u8 layer_c_code_rate;
|
||||
#define ISDB_T_LC_CR_1_2 0
|
||||
#define ISDB_T_LC_CR_2_3 1
|
||||
#define ISDB_T_LC_CR_3_4 2
|
||||
#define ISDB_T_LC_CR_5_6 4
|
||||
#define ISDB_T_LC_CR_7_8 8
|
||||
#define ISDB_T_LC_CR_NOLAYER 16
|
||||
u8 layer_c_time_interleave;
|
||||
#define ISDB_T_LC_TI_0 0
|
||||
#define ISDB_T_LC_TI_1 1
|
||||
#define ISDB_T_LC_TI_2 2
|
||||
#define ISDB_T_LC_TI_4 4
|
||||
#define ISDB_T_LC_TI_8 8
|
||||
#define ISDB_T_LC_TI_16 16
|
||||
#define ISDB_T_LC_TI_32 32
|
||||
u8 layer_c_nseg;
|
||||
};
|
||||
|
||||
int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
|
||||
#endif
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Driver for Sharp s921 driver
|
||||
*
|
||||
* Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "s921_module.h"
|
||||
#include "s921_core.h"
|
||||
|
||||
static unsigned int debug = 0;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,"s921 debugging (default off)");
|
||||
|
||||
#define dprintk(fmt, args...) if (debug) do {\
|
||||
printk("s921 debug: " fmt, ##args); } while (0)
|
||||
|
||||
struct s921_state
|
||||
{
|
||||
struct dvb_frontend frontend;
|
||||
fe_modulation_t current_modulation;
|
||||
__u32 snr;
|
||||
__u32 current_frequency;
|
||||
__u8 addr;
|
||||
struct s921_isdb_t dev;
|
||||
struct i2c_adapter *i2c;
|
||||
};
|
||||
|
||||
static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
|
||||
struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
|
||||
struct s921_isdb_t_transmission_mode_params params;
|
||||
struct s921_isdb_t_tune_params tune_params;
|
||||
|
||||
tune_params.frequency = param->frequency;
|
||||
s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, ¶ms);
|
||||
s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params);
|
||||
mdelay(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_init(struct dvb_frontend *fe) {
|
||||
printk("s921 init\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_sleep(struct dvb_frontend *fe) {
|
||||
printk("s921 sleep\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
|
||||
unsigned int ret;
|
||||
mdelay(5);
|
||||
s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret);
|
||||
*status = 0;
|
||||
|
||||
printk("status: %02x\n", ret);
|
||||
if (ret == 1) {
|
||||
*status |= FE_HAS_CARRIER;
|
||||
*status |= FE_HAS_VITERBI;
|
||||
*status |= FE_HAS_LOCK;
|
||||
*status |= FE_HAS_SYNC;
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber)
|
||||
{
|
||||
dprintk("read ber\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr)
|
||||
{
|
||||
dprintk("read snr\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
|
||||
{
|
||||
dprintk("read ucblocks\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s921_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops demod_s921={
|
||||
.info = {
|
||||
.name = "SHARP S921",
|
||||
.type = FE_OFDM,
|
||||
.frequency_min = 473143000,
|
||||
.frequency_max = 767143000,
|
||||
.frequency_stepsize = 6000000,
|
||||
.frequency_tolerance = 0,
|
||||
.caps = 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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
|
||||
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
|
||||
FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
|
||||
FE_CAN_MUTE_TS
|
||||
},
|
||||
.init = s921_init,
|
||||
.sleep = s921_sleep,
|
||||
.set_frontend = s921_set_parameters,
|
||||
.read_snr = s921_read_snr,
|
||||
.read_ber = s921_read_ber,
|
||||
.read_status = s921_read_status,
|
||||
.read_ucblocks = s921_read_ucblocks,
|
||||
.release = s921_release,
|
||||
};
|
||||
|
||||
static int s921_write(void *dev, u8 reg, u8 val) {
|
||||
struct s921_state *state = dev;
|
||||
char buf[2]={reg,val};
|
||||
int err;
|
||||
struct i2c_msg i2cmsgs = {
|
||||
.addr = state->addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = buf
|
||||
};
|
||||
|
||||
if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
|
||||
printk("%s i2c_transfer error %d\n", __func__, err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s921_read(void *dev, u8 reg) {
|
||||
struct s921_state *state = dev;
|
||||
u8 b1;
|
||||
int ret;
|
||||
struct i2c_msg msg[2] = { { .addr = state->addr,
|
||||
.flags = 0,
|
||||
.buf = ®, .len = 1 },
|
||||
{ .addr = state->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = &b1, .len = 1 } };
|
||||
|
||||
ret = i2c_transfer(state->i2c, msg, 2);
|
||||
if (ret != 2)
|
||||
return ret;
|
||||
return b1;
|
||||
}
|
||||
|
||||
struct dvb_frontend* s921_attach(const struct s921_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
|
||||
struct s921_state *state;
|
||||
state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
state->addr = config->i2c_address;
|
||||
state->i2c = i2c;
|
||||
state->dev.i2c_write = &s921_write;
|
||||
state->dev.i2c_read = &s921_read;
|
||||
state->dev.priv_dev = state;
|
||||
|
||||
s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL);
|
||||
|
||||
memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(s921_attach);
|
||||
MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
|
||||
MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Driver for DVB-T s921 demodulator
|
||||
*
|
||||
* Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
|
||||
*
|
||||
* 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 S921_MODULE_H
|
||||
#define S921_MODULE_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include "s921_core.h"
|
||||
|
||||
int s921_isdb_init(struct s921_isdb_t *dev);
|
||||
int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
|
||||
|
||||
struct s921_config
|
||||
{
|
||||
/* demodulator's I2C address */
|
||||
u8 i2c_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend* s921_attach(const struct s921_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* s921_attach(const struct s921_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_S921 */
|
||||
|
||||
#endif /* S921_H */
|
|
@ -714,7 +714,7 @@ static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
|
|||
reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
|
||||
STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
|
||||
stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
|
||||
|
||||
msleep(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ module_param(verbose, int, 0644);
|
|||
if (x > y) \
|
||||
printk(format, ##arg); \
|
||||
} \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
struct stb6100_lkup {
|
||||
u32 val_low;
|
||||
|
@ -117,7 +117,10 @@ static const struct stb6100_regmask stb6100_template[] = {
|
|||
[STB6100_TEST3] = { 0x00, 0xde },
|
||||
};
|
||||
|
||||
static void stb6100_normalise_regs(u8 regs[])
|
||||
/*
|
||||
* Currently unused. Some boards might need it in the future
|
||||
*/
|
||||
static inline void stb6100_normalise_regs(u8 regs[])
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -157,13 +160,25 @@ static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
|
|||
u8 regs[STB6100_NUMREGS];
|
||||
int rc;
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->config->tuner_address + reg,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = regs,
|
||||
.len = 1
|
||||
};
|
||||
|
||||
rc = i2c_transfer(state->i2c, &msg, 1);
|
||||
|
||||
if (unlikely(reg >= STB6100_NUMREGS)) {
|
||||
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((rc = stb6100_read_regs(state, regs)) < 0)
|
||||
return rc;
|
||||
return (unsigned int)regs[reg];
|
||||
if (unlikely(verbose > FE_DEBUG)) {
|
||||
dprintk(verbose, FE_DEBUG, 1, " Read from 0x%02x", state->config->tuner_address);
|
||||
dprintk(verbose, FE_DEBUG, 1, " %s: 0x%02x", stb6100_regnames[reg], regs[0]);
|
||||
}
|
||||
|
||||
return (unsigned int)regs[0];
|
||||
}
|
||||
|
||||
static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
|
||||
|
@ -211,20 +226,17 @@ static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
|
|||
return stb6100_write_reg_range(state, &data, reg, 1);
|
||||
}
|
||||
|
||||
static int stb6100_write_regs(struct stb6100_state *state, u8 regs[])
|
||||
{
|
||||
stb6100_normalise_regs(regs);
|
||||
return stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 1);
|
||||
}
|
||||
|
||||
static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
|
||||
{
|
||||
int rc;
|
||||
struct stb6100_state *state = fe->tuner_priv;
|
||||
|
||||
if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0)
|
||||
rc = stb6100_read_reg(state, STB6100_LD);
|
||||
if (rc < 0) {
|
||||
dprintk(verbose, FE_ERROR, 1, "%s failed", __func__);
|
||||
return rc;
|
||||
|
||||
}
|
||||
return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
|
||||
}
|
||||
|
||||
|
@ -234,7 +246,8 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
u8 f;
|
||||
struct stb6100_state *state = fe->tuner_priv;
|
||||
|
||||
if ((rc = stb6100_read_reg(state, STB6100_F)) < 0)
|
||||
rc = stb6100_read_reg(state, STB6100_F);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
f = rc & STB6100_F_F;
|
||||
|
||||
|
@ -265,14 +278,21 @@ static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
|
|||
/* Turn on LPF bandwidth setting clock control,
|
||||
* set bandwidth, wait 10ms, turn off.
|
||||
*/
|
||||
if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0)
|
||||
rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0)
|
||||
rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
msleep(1);
|
||||
if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0)
|
||||
|
||||
msleep(5); /* This is dangerous as another (related) thread may start */
|
||||
|
||||
rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
msleep(10); /* This is dangerous as another (related) thread may start */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -284,7 +304,8 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|||
struct stb6100_state *state = fe->tuner_priv;
|
||||
u8 regs[STB6100_NUMREGS];
|
||||
|
||||
if ((rc = stb6100_read_regs(state, regs)) < 0)
|
||||
rc = stb6100_read_regs(state, regs);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
|
||||
|
@ -312,8 +333,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
|||
u8 regs[STB6100_NUMREGS];
|
||||
u8 g, psd2, odiv;
|
||||
|
||||
if ((rc = stb6100_read_regs(state, regs)) < 0)
|
||||
return rc;
|
||||
dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51");
|
||||
|
||||
if (fe->ops.get_frontend) {
|
||||
dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
|
||||
|
@ -321,96 +341,140 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
|||
}
|
||||
srate = p.u.qpsk.symbol_rate;
|
||||
|
||||
regs[STB6100_DLB] = 0xdc;
|
||||
/* Disable LPEN */
|
||||
regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */
|
||||
/* Set up tuner cleanly, LPF calibration on */
|
||||
rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
|
||||
if (rc < 0)
|
||||
return rc; /* allow LPF calibration */
|
||||
|
||||
if ((rc = stb6100_write_regs(state, regs)) < 0)
|
||||
/* PLL Loop disabled, bias on, VCO on, synth on */
|
||||
regs[STB6100_LPEN] = 0xeb;
|
||||
rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Baseband gain. */
|
||||
if (srate >= 15000000)
|
||||
g = 9; // +4 dB
|
||||
else if (srate >= 5000000)
|
||||
g = 11; // +8 dB
|
||||
else
|
||||
g = 14; // +14 dB
|
||||
|
||||
regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g;
|
||||
regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
|
||||
regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
|
||||
/* Program the registers with their data values */
|
||||
|
||||
/* VCO divide ratio (LO divide ratio, VCO prescaler enable). */
|
||||
if (frequency <= 1075000)
|
||||
odiv = 1;
|
||||
else
|
||||
odiv = 0;
|
||||
regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT);
|
||||
|
||||
if ((frequency > 1075000) && (frequency <= 1325000))
|
||||
psd2 = 0;
|
||||
else
|
||||
psd2 = 1;
|
||||
regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
|
||||
/* VCO enabled, seach clock off as per LL3.7, 3.4.1 */
|
||||
regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT);
|
||||
|
||||
/* OSM */
|
||||
for (ptr = lkup;
|
||||
(ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
|
||||
ptr++);
|
||||
|
||||
if (ptr->val_high == 0) {
|
||||
printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
|
||||
return -EINVAL;
|
||||
}
|
||||
regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
|
||||
rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if ((frequency > 1075000) && (frequency <= 1325000))
|
||||
psd2 = 0;
|
||||
else
|
||||
psd2 = 1;
|
||||
/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4) */
|
||||
fvco = frequency << (1 + odiv);
|
||||
/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */
|
||||
nint = fvco / (state->reference << psd2);
|
||||
/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */
|
||||
nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2))
|
||||
<< (9 - psd2),
|
||||
state->reference);
|
||||
<< (9 - psd2), state->reference);
|
||||
|
||||
/* NI */
|
||||
regs[STB6100_NI] = nint;
|
||||
rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* NF */
|
||||
regs[STB6100_NF_LSB] = nfrac;
|
||||
rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* K */
|
||||
regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
|
||||
regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
|
||||
rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* G Baseband gain. */
|
||||
if (srate >= 15000000)
|
||||
g = 9; /* +4 dB */
|
||||
else if (srate >= 5000000)
|
||||
g = 11; /* +8 dB */
|
||||
else
|
||||
g = 14; /* +14 dB */
|
||||
|
||||
regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g;
|
||||
regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
|
||||
regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
|
||||
rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* F we don't write as it is set up in BW set */
|
||||
|
||||
/* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */
|
||||
regs[STB6100_DLB] = 0xcc;
|
||||
rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
dprintk(verbose, FE_DEBUG, 1,
|
||||
"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
|
||||
frequency, srate, (unsigned int)g, (unsigned int)odiv,
|
||||
(unsigned int)psd2, state->reference,
|
||||
ptr->reg, fvco, nint, nfrac);
|
||||
regs[STB6100_NI] = nint;
|
||||
regs[STB6100_NF_LSB] = nfrac;
|
||||
regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
|
||||
regs[STB6100_VCO] |= STB6100_VCO_OSCH; /* VCO search enabled */
|
||||
regs[STB6100_VCO] |= STB6100_VCO_OCK; /* VCO search clock off */
|
||||
regs[STB6100_FCCK] |= STB6100_FCCK_FCCK; /* LPF BW setting clock enabled */
|
||||
regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL loop disabled */
|
||||
/* Power up. */
|
||||
regs[STB6100_LPEN] |= STB6100_LPEN_SYNP | STB6100_LPEN_OSCP | STB6100_LPEN_BEN;
|
||||
|
||||
msleep(2);
|
||||
if ((rc = stb6100_write_regs(state, regs)) < 0)
|
||||
/* Set up the test registers */
|
||||
regs[STB6100_TEST1] = 0x8f;
|
||||
rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
regs[STB6100_TEST3] = 0xde;
|
||||
rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Bring up tuner according to LLA 3.7 3.4.1, step 2 */
|
||||
regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */
|
||||
rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
msleep(2);
|
||||
regs[STB6100_LPEN] |= STB6100_LPEN_LPEN; /* PLL loop enabled */
|
||||
if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
|
||||
return rc;
|
||||
|
||||
/* Bring up tuner according to LLA 3.7 3.4.1, step 3 */
|
||||
regs[STB6100_VCO] &= ~STB6100_VCO_OCK; /* VCO fast search */
|
||||
if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
|
||||
rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
msleep(10); /* wait for LO to lock */
|
||||
msleep(10); /* This is dangerous as another (related) thread may start */ /* wait for LO to lock */
|
||||
|
||||
regs[STB6100_VCO] &= ~STB6100_VCO_OSCH; /* vco search disabled */
|
||||
regs[STB6100_VCO] |= STB6100_VCO_OCK; /* search clock off */
|
||||
if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
|
||||
return rc;
|
||||
regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK; /* LPF BW clock disabled */
|
||||
stb6100_normalise_regs(regs);
|
||||
if ((rc = stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 3)) < 0)
|
||||
rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
msleep(100);
|
||||
rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
|
||||
if (rc < 0)
|
||||
return rc; /* Stop LPF calibration */
|
||||
|
||||
msleep(10); /* This is dangerous as another (related) thread may start */
|
||||
/* wait for stabilisation, (should not be necessary) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -433,8 +497,8 @@ static int stb6100_init(struct dvb_frontend *fe)
|
|||
state->bandwidth = status->bandwidth * 1000; /* Hz */
|
||||
state->reference = status->refclock / 1000; /* kHz */
|
||||
|
||||
/* Set default bandwidth. */
|
||||
return stb6100_set_bandwidth(fe, state->bandwidth);
|
||||
/* Set default bandwidth. Modified, PN 13-May-10 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stb6100_get_state(struct dvb_frontend *fe,
|
||||
|
|
|
@ -1483,8 +1483,8 @@ static int stv090x_start_search(struct stv090x_state *state)
|
|||
if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
|
||||
goto err;
|
||||
|
||||
if ((state->search_mode == STV090x_DVBS1) ||
|
||||
(state->search_mode == STV090x_DSS) ||
|
||||
if ((state->search_mode == STV090x_SEARCH_DVBS1) ||
|
||||
(state->search_mode == STV090x_SEARCH_DSS) ||
|
||||
(state->search_mode == STV090x_SEARCH_AUTO)) {
|
||||
|
||||
if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
|
||||
|
@ -2940,7 +2940,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
|
|||
STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
|
||||
break;
|
||||
|
||||
case STV090x_UNKNOWN:
|
||||
case STV090x_ERROR:
|
||||
default:
|
||||
reg = STV090x_READ_DEMOD(state, DMDCFGMD);
|
||||
STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config MANTIS_CORE
|
||||
tristate "Mantis/Hopper PCI bridge based devices"
|
||||
depends on PCI && I2C && INPUT && IR_CORE
|
||||
depends on PCI && I2C && INPUT && RC_CORE
|
||||
|
||||
help
|
||||
Support for PCI cards based on the Mantis and Hopper PCi bridge.
|
||||
|
|
|
@ -251,6 +251,8 @@ static struct pci_device_id hopper_pci_table[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, hopper_pci_table);
|
||||
|
||||
static struct pci_driver hopper_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = hopper_pci_table,
|
||||
|
|
|
@ -47,17 +47,17 @@ static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
struct mantis_hwconfig *config = mantis->hwconfig;
|
||||
int err = 0;
|
||||
|
||||
gpio_set_bits(mantis, config->reset, 0);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 0);
|
||||
msleep(100);
|
||||
err = mantis_frontend_power(mantis, POWER_ON);
|
||||
msleep(100);
|
||||
gpio_set_bits(mantis, config->reset, 1);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 1);
|
||||
|
||||
err = mantis_frontend_power(mantis, POWER_ON);
|
||||
if (err == 0) {
|
||||
msleep(250);
|
||||
dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
|
||||
fe = zl10353_attach(&hopper_vp3028_config, adapter);
|
||||
fe = dvb_attach(zl10353_attach, &hopper_vp3028_config, adapter);
|
||||
|
||||
if (!fe)
|
||||
return -1;
|
||||
|
|
|
@ -281,6 +281,8 @@ static struct pci_device_id mantis_pci_table[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, mantis_pci_table);
|
||||
|
||||
static struct pci_driver mantis_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = mantis_pci_table,
|
||||
|
|
|
@ -171,7 +171,9 @@ struct mantis_pci {
|
|||
struct work_struct uart_work;
|
||||
spinlock_t uart_lock;
|
||||
|
||||
struct input_dev *rc;
|
||||
struct rc_dev *rc;
|
||||
char input_name[80];
|
||||
char input_phys[80];
|
||||
};
|
||||
|
||||
#define MANTIS_HIF_STATUS (mantis->gpio_status)
|
||||
|
|
|
@ -47,15 +47,15 @@ int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
|
|||
switch (power) {
|
||||
case POWER_ON:
|
||||
dprintk(MANTIS_DEBUG, 1, "Power ON");
|
||||
gpio_set_bits(mantis, config->power, POWER_ON);
|
||||
mantis_gpio_set_bits(mantis, config->power, POWER_ON);
|
||||
msleep(100);
|
||||
gpio_set_bits(mantis, config->power, POWER_ON);
|
||||
mantis_gpio_set_bits(mantis, config->power, POWER_ON);
|
||||
msleep(100);
|
||||
break;
|
||||
|
||||
case POWER_OFF:
|
||||
dprintk(MANTIS_DEBUG, 1, "Power OFF");
|
||||
gpio_set_bits(mantis, config->power, POWER_OFF);
|
||||
mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
|
||||
msleep(100);
|
||||
break;
|
||||
|
||||
|
@ -73,13 +73,13 @@ void mantis_frontend_soft_reset(struct mantis_pci *mantis)
|
|||
struct mantis_hwconfig *config = mantis->hwconfig;
|
||||
|
||||
dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
|
||||
gpio_set_bits(mantis, config->reset, 0);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 0);
|
||||
msleep(100);
|
||||
gpio_set_bits(mantis, config->reset, 0);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 0);
|
||||
msleep(100);
|
||||
gpio_set_bits(mantis, config->reset, 1);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 1);
|
||||
msleep(100);
|
||||
gpio_set_bits(mantis, config->reset, 1);
|
||||
mantis_gpio_set_bits(mantis, config->reset, 1);
|
||||
msleep(100);
|
||||
|
||||
return;
|
||||
|
@ -117,6 +117,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
|
|||
if (mantis->feeds == 1) {
|
||||
dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
|
||||
mantis_dma_start(mantis);
|
||||
tasklet_enable(&mantis->tasklet);
|
||||
}
|
||||
|
||||
return mantis->feeds;
|
||||
|
@ -136,6 +137,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
|||
mantis->feeds--;
|
||||
if (mantis->feeds == 0) {
|
||||
dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
|
||||
tasklet_disable(&mantis->tasklet);
|
||||
mantis_dma_stop(mantis);
|
||||
}
|
||||
|
||||
|
@ -216,6 +218,7 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis)
|
|||
|
||||
dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
|
||||
tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
|
||||
tasklet_disable(&mantis->tasklet);
|
||||
if (mantis->hwconfig) {
|
||||
result = config->frontend_init(mantis, mantis->fe);
|
||||
if (result < 0) {
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <media/rc-core.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
|
@ -33,8 +32,9 @@
|
|||
#include "mantis_uart.h"
|
||||
|
||||
#define MODULE_NAME "mantis_core"
|
||||
#define RC_MAP_MANTIS "rc-mantis"
|
||||
|
||||
static struct ir_scancode mantis_ir_table[] = {
|
||||
static struct rc_map_table mantis_ir_table[] = {
|
||||
{ 0x29, KEY_POWER },
|
||||
{ 0x28, KEY_FAVORITES },
|
||||
{ 0x30, KEY_TEXT },
|
||||
|
@ -95,53 +95,65 @@ static struct ir_scancode mantis_ir_table[] = {
|
|||
{ 0x00, KEY_BLUE },
|
||||
};
|
||||
|
||||
struct ir_scancode_table ir_mantis = {
|
||||
.scan = mantis_ir_table,
|
||||
.size = ARRAY_SIZE(mantis_ir_table),
|
||||
static struct rc_map_list ir_mantis_map = {
|
||||
.map = {
|
||||
.scan = mantis_ir_table,
|
||||
.size = ARRAY_SIZE(mantis_ir_table),
|
||||
.rc_type = RC_TYPE_UNKNOWN,
|
||||
.name = RC_MAP_MANTIS,
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ir_mantis);
|
||||
|
||||
int mantis_input_init(struct mantis_pci *mantis)
|
||||
{
|
||||
struct input_dev *rc;
|
||||
char name[80], dev[80];
|
||||
struct rc_dev *dev;
|
||||
int err;
|
||||
|
||||
rc = input_allocate_device();
|
||||
if (!rc) {
|
||||
dprintk(MANTIS_ERROR, 1, "Input device allocate failed");
|
||||
return -ENOMEM;
|
||||
err = rc_map_register(&ir_mantis_map);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
dev = rc_allocate_device();
|
||||
if (!dev) {
|
||||
dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
|
||||
err = -ENOMEM;
|
||||
goto out_map;
|
||||
}
|
||||
|
||||
sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
|
||||
sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev));
|
||||
sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
|
||||
sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
|
||||
|
||||
rc->name = name;
|
||||
rc->phys = dev;
|
||||
dev->input_name = mantis->input_name;
|
||||
dev->input_phys = mantis->input_phys;
|
||||
dev->input_id.bustype = BUS_PCI;
|
||||
dev->input_id.vendor = mantis->vendor_id;
|
||||
dev->input_id.product = mantis->device_id;
|
||||
dev->input_id.version = 1;
|
||||
dev->driver_name = MODULE_NAME;
|
||||
dev->map_name = RC_MAP_MANTIS;
|
||||
dev->dev.parent = &mantis->pdev->dev;
|
||||
|
||||
rc->id.bustype = BUS_PCI;
|
||||
rc->id.vendor = mantis->vendor_id;
|
||||
rc->id.product = mantis->device_id;
|
||||
rc->id.version = 1;
|
||||
rc->dev = mantis->pdev->dev;
|
||||
|
||||
err = __ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME);
|
||||
err = rc_register_device(dev);
|
||||
if (err) {
|
||||
dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
|
||||
input_free_device(rc);
|
||||
return -ENODEV;
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
mantis->rc = rc;
|
||||
|
||||
mantis->rc = dev;
|
||||
return 0;
|
||||
|
||||
out_dev:
|
||||
rc_free_device(dev);
|
||||
out_map:
|
||||
rc_map_unregister(&ir_mantis_map);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int mantis_exit(struct mantis_pci *mantis)
|
||||
{
|
||||
struct input_dev *rc = mantis->rc;
|
||||
|
||||
ir_input_unregister(rc);
|
||||
|
||||
rc_unregister_device(mantis->rc);
|
||||
rc_map_unregister(&ir_mantis_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ int mantis_get_mac(struct mantis_pci *mantis)
|
|||
EXPORT_SYMBOL_GPL(mantis_get_mac);
|
||||
|
||||
/* Turn the given bit on or off. */
|
||||
void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
|
||||
void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
|
||||
{
|
||||
u32 cur;
|
||||
|
||||
|
@ -90,7 +90,7 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
|
|||
mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
|
||||
mmwrite(0x00, MANTIS_GPIF_DOUT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpio_set_bits);
|
||||
EXPORT_SYMBOL_GPL(mantis_gpio_set_bits);
|
||||
|
||||
int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl)
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ enum mantis_stream_control {
|
|||
};
|
||||
|
||||
extern int mantis_get_mac(struct mantis_pci *mantis);
|
||||
extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
|
||||
extern void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
|
||||
|
||||
extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl);
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
msleep(250);
|
||||
|
||||
dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
|
||||
fe = stv0299_attach(&lgtdqcs001f_config, adapter);
|
||||
fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter);
|
||||
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
|
||||
|
|
|
@ -50,13 +50,13 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk(MANTIS_ERROR, 1, "Polarization=[13V]");
|
||||
gpio_set_bits(mantis, 13, 1);
|
||||
gpio_set_bits(mantis, 14, 0);
|
||||
mantis_gpio_set_bits(mantis, 13, 1);
|
||||
mantis_gpio_set_bits(mantis, 14, 0);
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk(MANTIS_ERROR, 1, "Polarization=[18V]");
|
||||
gpio_set_bits(mantis, 13, 1);
|
||||
gpio_set_bits(mantis, 14, 1);
|
||||
mantis_gpio_set_bits(mantis, 13, 1);
|
||||
mantis_gpio_set_bits(mantis, 14, 1);
|
||||
break;
|
||||
case SEC_VOLTAGE_OFF:
|
||||
dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN");
|
||||
|
@ -82,7 +82,7 @@ static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
msleep(250);
|
||||
|
||||
dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
|
||||
fe = mb86a16_attach(&vp1034_mb86a16_config, adapter);
|
||||
fe = dvb_attach(mb86a16_attach, &vp1034_mb86a16_config, adapter);
|
||||
if (fe) {
|
||||
dprintk(MANTIS_ERROR, 1,
|
||||
"found MB86A16 DVB-S/DSS frontend @0x%02x",
|
||||
|
|
|
@ -316,14 +316,14 @@ static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
if (err == 0) {
|
||||
mantis_frontend_soft_reset(mantis);
|
||||
msleep(250);
|
||||
mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter);
|
||||
mantis->fe = dvb_attach(stb0899_attach, &vp1041_stb0899_config, adapter);
|
||||
if (mantis->fe) {
|
||||
dprintk(MANTIS_ERROR, 1,
|
||||
"found STB0899 DVB-S/DVB-S2 frontend @0x%02x",
|
||||
vp1041_stb0899_config.demod_address);
|
||||
|
||||
if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) {
|
||||
if (!lnbp21_attach(mantis->fe, adapter, 0, 0))
|
||||
if (dvb_attach(stb6100_attach, mantis->fe, &vp1041_stb6100_config, adapter)) {
|
||||
if (!dvb_attach(lnbp21_attach, mantis->fe, adapter, 0, 0))
|
||||
dprintk(MANTIS_ERROR, 1, "No LNBP21 found!");
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -132,7 +132,7 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
msleep(250);
|
||||
|
||||
dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
|
||||
fe = tda10021_attach(&vp2033_tda1002x_cu1216_config,
|
||||
fe = dvb_attach(tda10021_attach, &vp2033_tda1002x_cu1216_config,
|
||||
adapter,
|
||||
read_pwm(mantis));
|
||||
|
||||
|
@ -141,7 +141,7 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
|
||||
vp2033_tda1002x_cu1216_config.demod_address);
|
||||
} else {
|
||||
fe = tda10023_attach(&vp2033_tda10023_cu1216_config,
|
||||
fe = dvb_attach(tda10023_attach, &vp2033_tda10023_cu1216_config,
|
||||
adapter,
|
||||
read_pwm(mantis));
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
msleep(250);
|
||||
|
||||
dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
|
||||
fe = tda10021_attach(&vp2040_tda1002x_cu1216_config,
|
||||
fe = dvb_attach(tda10021_attach, &vp2040_tda1002x_cu1216_config,
|
||||
adapter,
|
||||
read_pwm(mantis));
|
||||
|
||||
|
@ -141,7 +141,7 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
|
|||
"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
|
||||
vp2040_tda1002x_cu1216_config.demod_address);
|
||||
} else {
|
||||
fe = tda10023_attach(&vp2040_tda10023_cu1216_config,
|
||||
fe = dvb_attach(tda10023_attach, &vp2040_tda10023_cu1216_config,
|
||||
adapter,
|
||||
read_pwm(mantis));
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue