Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
Linus Torvalds [Tue, 24 May 2011 04:12:49 +0000 (21:12 -0700)]
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (247 commits)
  [media] gspca - sunplus: Fix some warnings and simplify code
  [media] gspca: Fix some warnings tied to 'no debug'
  [media] gspca: Unset debug by default
  [media] gspca - cpia1: Remove a bad conditional compilation instruction
  [media] gspca - main: Remove USB traces
  [media] gspca - main: Version change to 2.13
  [media] gspca - stk014 / t613: Accept the index 0 in querymenu
  [media] gspca - kinect: Remove __devinitdata
  [media] gspca - cpia1: Fix some warnings
  [media] video/Kconfig: Fix mis-classified devices
  [media] support for medion dvb stick 1660:1921
  [media] tm6000: fix uninitialized field, change prink to dprintk
  [media] cx231xx: Add support for Iconbit U100
  [media] saa7134 add new TV cards
  [media] Use a more consistent value for RC repeat period
  [media] cx18: Move spinlock and vb_type initialisation into stream_init
  [media] tm6000: remove tm6010 sif audio start and stop
  [media] tm6000: remove unused exports
  [media] tm6000: add pts logging
  [media] tm6000: change from ioctl to unlocked_ioctl
  ...

228 files changed:
Documentation/DocBook/.gitignore
Documentation/DocBook/dvb/dvbapi.xml
Documentation/DocBook/dvb/dvbproperty.xml
Documentation/DocBook/dvb/frontend.h.xml
Documentation/DocBook/media-entities.tmpl
Documentation/DocBook/v4l/pixfmt-m420.xml [new file with mode: 0644]
Documentation/DocBook/v4l/pixfmt-y10b.xml [new file with mode: 0644]
Documentation/DocBook/v4l/pixfmt.xml
Documentation/DocBook/v4l/subdev-formats.xml
Documentation/DocBook/v4l/videodev2.h.xml
Documentation/feature-removal-schedule.txt
Documentation/ioctl/ioctl-number.txt
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/Zoran
Documentation/video4linux/gspca.txt
Documentation/video4linux/uvcvideo.txt [new file with mode: 0644]
drivers/media/common/saa7146_core.c
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/Makefile
drivers/media/common/tuners/mxl5005s.c
drivers/media/common/tuners/tda18212.c [new file with mode: 0644]
drivers/media/common/tuners/tda18212.h [new file with mode: 0644]
drivers/media/common/tuners/tda18212_priv.h [new file with mode: 0644]
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/xc5000.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/anysee.h
drivers/media/dvb/dvb-usb/au6610.c
drivers/media/dvb/dvb-usb/ce6230.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dw2102.c
drivers/media/dvb/dvb-usb/ec168.c
drivers/media/dvb/dvb-usb/friio.c
drivers/media/dvb/dvb-usb/lmedm04.c
drivers/media/dvb/dvb-usb/lmedm04.h
drivers/media/dvb/dvb-usb/m920x.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/opera1.c
drivers/media/dvb/dvb-usb/vp702x-fe.c
drivers/media/dvb/dvb-usb/vp702x.c
drivers/media/dvb/dvb-usb/vp702x.h
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/bsbe1-d01a.h [new file with mode: 0644]
drivers/media/dvb/frontends/bsru6.h
drivers/media/dvb/frontends/cx24116.c
drivers/media/dvb/frontends/cx24116.h
drivers/media/dvb/frontends/cxd2820r.h [new file with mode: 0644]
drivers/media/dvb/frontends/cxd2820r_c.c [new file with mode: 0644]
drivers/media/dvb/frontends/cxd2820r_core.c [new file with mode: 0644]
drivers/media/dvb/frontends/cxd2820r_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/cxd2820r_t.c [new file with mode: 0644]
drivers/media/dvb/frontends/cxd2820r_t2.c [new file with mode: 0644]
drivers/media/dvb/frontends/dib0070.c
drivers/media/dvb/frontends/dib0090.c
drivers/media/dvb/frontends/dib7000m.c
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib8000.c
drivers/media/dvb/frontends/dib9000.c
drivers/media/dvb/frontends/dibx000_common.c
drivers/media/dvb/frontends/dibx000_common.h
drivers/media/dvb/frontends/drx397xD.c [deleted file]
drivers/media/dvb/frontends/drx397xD.h [deleted file]
drivers/media/dvb/frontends/drx397xD_fw.h [deleted file]
drivers/media/dvb/frontends/drxd.h [new file with mode: 0644]
drivers/media/dvb/frontends/drxd_firm.c [new file with mode: 0644]
drivers/media/dvb/frontends/drxd_firm.h [new file with mode: 0644]
drivers/media/dvb/frontends/drxd_hard.c [new file with mode: 0644]
drivers/media/dvb/frontends/drxd_map_firm.h [new file with mode: 0644]
drivers/media/dvb/frontends/eds1547.h
drivers/media/dvb/frontends/ix2505v.c
drivers/media/dvb/frontends/stv0288.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/z0194a.h
drivers/media/dvb/mantis/hopper_cards.c
drivers/media/dvb/mantis/mantis_cards.c
drivers/media/dvb/mantis/mantis_pci.c
drivers/media/dvb/mantis/mantis_vp1033.c
drivers/media/dvb/pt1/pt1.c
drivers/media/dvb/siano/smsusb.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/radio/si470x/radio-si470x-common.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si470x/radio-si470x.h
drivers/media/radio/wl128x/fmdrv.h
drivers/media/rc/Kconfig
drivers/media/rc/Makefile
drivers/media/rc/imon.c
drivers/media/rc/ite-cir.c
drivers/media/rc/keymaps/Makefile
drivers/media/rc/keymaps/rc-avermedia-cardbus.c
drivers/media/rc/keymaps/rc-imon-mce.c
drivers/media/rc/keymaps/rc-imon-pad.c
drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
drivers/media/rc/keymaps/rc-rc6-mce.c
drivers/media/rc/keymaps/rc-tivo.c [new file with mode: 0644]
drivers/media/rc/keymaps/rc-winfast.c
drivers/media/rc/mceusb.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/nuvoton-cir.h
drivers/media/rc/rc-loopback.c
drivers/media/rc/rc-main.c
drivers/media/rc/redrat3.c [new file with mode: 0644]
drivers/media/rc/winbond-cir.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cx18/Kconfig
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-fileops.h
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-version.h
drivers/media/video/cx18/cx23418.h
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx231xx/cx231xx-dvb.c
drivers/media/video/cx231xx/cx231xx.h
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx.h
drivers/media/video/fsl-viu.c
drivers/media/video/gspca/Kconfig
drivers/media/video/gspca/Makefile
drivers/media/video/gspca/cpia1.c
drivers/media/video/gspca/gl860/gl860.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/jeilinj.c
drivers/media/video/gspca/kinect.c [new file with mode: 0644]
drivers/media/video/gspca/spca508.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9v022.c
drivers/media/video/mt9v032.c [new file with mode: 0644]
drivers/media/video/mx3_camera.c
drivers/media/video/omap1_camera.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pxa_camera.c
drivers/media/video/s2255drv.c
drivers/media/video/s5p-fimc/Makefile
drivers/media/video/s5p-fimc/mipi-csis.c [new file with mode: 0644]
drivers/media/video/s5p-fimc/mipi-csis.h [new file with mode: 0644]
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa7164/saa7164-core.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/soc_camera.c
drivers/media/video/soc_mediabus.c
drivers/media/video/tveeprom.c
drivers/media/video/usbvision/usbvision-cards.c
drivers/media/video/usbvision/usbvision-cards.h
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/usbvision/usbvision.h
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-dev.c
drivers/media/video/via-camera.c
drivers/media/video/zoran/zoran_card.c
drivers/staging/lirc/lirc_sasem.c
drivers/staging/tm6000/CARDLIST [new file with mode: 0644]
drivers/staging/tm6000/tm6000-alsa.c
drivers/staging/tm6000/tm6000-cards.c
drivers/staging/tm6000/tm6000-core.c
drivers/staging/tm6000/tm6000-i2c.c
drivers/staging/tm6000/tm6000-stds.c
drivers/staging/tm6000/tm6000-usb-isoc.h
drivers/staging/tm6000/tm6000-video.c
drivers/staging/tm6000/tm6000.h
include/linux/Kbuild
include/linux/dvb/frontend.h
include/linux/dvb/version.h
include/linux/uvcvideo.h [new file with mode: 0644]
include/linux/v4l2-mediabus.h
include/linux/videodev2.h
include/media/mt9v032.h [new file with mode: 0644]
include/media/rc-core.h
include/media/rc-map.h
include/media/soc_camera.h
include/media/soc_camera_platform.h
include/media/soc_mediabus.h
include/media/v4l2-dev.h

index ad8678d..9fad86c 100644 (file)
 <revhistory>
 <!-- Put document revisions here, newest first. -->
 <revision>
+       <revnumber>2.0.4</revnumber>
+       <date>2011-05-06</date>
+       <authorinitials>mcc</authorinitials>
+       <revremark>
+               Add more information about DVB APIv5, better describing the frontend GET/SET props ioctl's.
+       </revremark>
+</revision>
+<revision>
        <revnumber>2.0.3</revnumber>
        <date>2010-07-03</date>
        <authorinitials>mcc</authorinitials>
index 97f397e..52d5e3c 100644 (file)
@@ -1,6 +1,327 @@
-<section id="FE_GET_PROPERTY">
+<section id="FE_GET_SET_PROPERTY">
 <title>FE_GET_PROPERTY/FE_SET_PROPERTY</title>
 
+<programlisting>
+/* Reserved fields should be set to 0 */
+struct dtv_property {
+       __u32 cmd;
+       union {
+               __u32 data;
+               struct {
+                       __u8 data[32];
+                       __u32 len;
+                       __u32 reserved1[3];
+                       void *reserved2;
+               } buffer;
+       } u;
+       int result;
+} __attribute__ ((packed));
+
+/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
+#define DTV_IOCTL_MAX_MSGS 64
+
+struct dtv_properties {
+       __u32 num;
+       struct dtv_property *props;
+};
+</programlisting>
+
+<section id="FE_GET_PROPERTY">
+<title>FE_GET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call returns one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>ERRORS</para>
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EINVAL</para></entry>
+  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
+ </row><row>
+  <entry align="char"><para>ENOMEM</para></entry>
+  <entry align="char"><para>Out of memory.</para></entry>
+ </row><row>
+  <entry align="char"><para>EFAULT</para></entry>
+  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
+ </row><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<section id="FE_SET_PROPERTY">
+<title>FE_SET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call sets one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>ERRORS
+</para>
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EINVAL</para></entry>
+  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
+ </row><row>
+  <entry align="char"><para>ENOMEM</para></entry>
+  <entry align="char"><para>Out of memory.</para></entry>
+ </row><row>
+  <entry align="char"><para>EFAULT</para></entry>
+  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
+ </row><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<para>
+On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
+get/set up to 64 properties. The actual meaning of each property is described on the next sections.
+</para>
+
+<para>The Available frontend property types are:</para>
+<programlisting>
+#define DTV_UNDEFINED          0
+#define DTV_TUNE               1
+#define DTV_CLEAR              2
+#define DTV_FREQUENCY          3
+#define DTV_MODULATION         4
+#define DTV_BANDWIDTH_HZ       5
+#define DTV_INVERSION          6
+#define DTV_DISEQC_MASTER      7
+#define DTV_SYMBOL_RATE                8
+#define DTV_INNER_FEC          9
+#define DTV_VOLTAGE            10
+#define DTV_TONE               11
+#define DTV_PILOT              12
+#define DTV_ROLLOFF            13
+#define DTV_DISEQC_SLAVE_REPLY 14
+#define DTV_FE_CAPABILITY_COUNT        15
+#define DTV_FE_CAPABILITY      16
+#define DTV_DELIVERY_SYSTEM    17
+#define DTV_ISDBT_PARTIAL_RECEPTION    18
+#define DTV_ISDBT_SOUND_BROADCASTING   19
+#define DTV_ISDBT_SB_SUBCHANNEL_ID     20
+#define DTV_ISDBT_SB_SEGMENT_IDX       21
+#define DTV_ISDBT_SB_SEGMENT_COUNT     22
+#define DTV_ISDBT_LAYERA_FEC                   23
+#define DTV_ISDBT_LAYERA_MODULATION            24
+#define DTV_ISDBT_LAYERA_SEGMENT_COUNT         25
+#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING     26
+#define DTV_ISDBT_LAYERB_FEC                   27
+#define DTV_ISDBT_LAYERB_MODULATION            28
+#define DTV_ISDBT_LAYERB_SEGMENT_COUNT         29
+#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING     30
+#define DTV_ISDBT_LAYERC_FEC                   31
+#define DTV_ISDBT_LAYERC_MODULATION            32
+#define DTV_ISDBT_LAYERC_SEGMENT_COUNT         33
+#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING     34
+#define DTV_API_VERSION                35
+#define DTV_CODE_RATE_HP       36
+#define DTV_CODE_RATE_LP       37
+#define DTV_GUARD_INTERVAL     38
+#define DTV_TRANSMISSION_MODE  39
+#define DTV_HIERARCHY          40
+#define DTV_ISDBT_LAYER_ENABLED        41
+#define DTV_ISDBS_TS_ID                42
+</programlisting>
+
+<section id="fe_property_common">
+       <title>Parameters that are common to all Digital TV standards</title>
+       <section id="DTV_FREQUENCY">
+               <title><constant>DTV_FREQUENCY</constant></title>
+
+               <para>Central frequency of the channel, in HZ.</para>
+
+               <para>Notes:</para>
+               <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
+                       E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
+                       the channel which is 6MHz.</para>
+
+               <para>2)As in ISDB-Tsb the channel consists of only one or three segments the
+                       frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
+                       central frequency of the channel is expected.</para>
+       </section>
+
+       <section id="DTV_BANDWIDTH_HZ">
+               <title><constant>DTV_BANDWIDTH_HZ</constant></title>
+
+               <para>Bandwidth for the channel, in HZ.</para>
+
+               <para>Possible values:
+                       <constant>1712000</constant>,
+                       <constant>5000000</constant>,
+                       <constant>6000000</constant>,
+                       <constant>7000000</constant>,
+                       <constant>8000000</constant>,
+                       <constant>10000000</constant>.
+               </para>
+
+               <para>Notes:</para>
+
+               <para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para>
+               <para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para>
+               <para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth
+                        for DVB-C depends on the symbol rate</para>
+               <para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
+                       other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
+                       DTV_ISDBT_SB_SEGMENT_COUNT).</para>
+               <para>5) DVB-T supports 6, 7 and 8MHz.</para>
+               <para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para>
+       </section>
+
+       <section id="DTV_DELIVERY_SYSTEM">
+               <title><constant>DTV_DELIVERY_SYSTEM</constant></title>
+
+               <para>Specifies the type of Delivery system</para>
+
+               <para>Possible values: </para>
+<programlisting>
+typedef enum fe_delivery_system {
+       SYS_UNDEFINED,
+       SYS_DVBC_ANNEX_AC,
+       SYS_DVBC_ANNEX_B,
+       SYS_DVBT,
+       SYS_DSS,
+       SYS_DVBS,
+       SYS_DVBS2,
+       SYS_DVBH,
+       SYS_ISDBT,
+       SYS_ISDBS,
+       SYS_ISDBC,
+       SYS_ATSC,
+       SYS_ATSCMH,
+       SYS_DMBTH,
+       SYS_CMMB,
+       SYS_DAB,
+       SYS_DVBT2,
+} fe_delivery_system_t;
+</programlisting>
+
+       </section>
+
+       <section id="DTV_TRANSMISSION_MODE">
+               <title><constant>DTV_TRANSMISSION_MODE</constant></title>
+
+               <para>Specifies the number of carriers used by the standard</para>
+
+               <para>Possible values are:</para>
+<programlisting>
+typedef enum fe_transmit_mode {
+       TRANSMISSION_MODE_2K,
+       TRANSMISSION_MODE_8K,
+       TRANSMISSION_MODE_AUTO,
+       TRANSMISSION_MODE_4K,
+       TRANSMISSION_MODE_1K,
+       TRANSMISSION_MODE_16K,
+       TRANSMISSION_MODE_32K,
+} fe_transmit_mode_t;
+</programlisting>
+
+               <para>Notes:</para>
+               <para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
+                       'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
+
+               <para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
+                       hardware will try to find the correct FFT-size (if capable) and will
+                       use TMCC to fill in the missing parameters.</para>
+               <para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
+               <para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
+       </section>
+
+       <section id="DTV_GUARD_INTERVAL">
+               <title><constant>DTV_GUARD_INTERVAL</constant></title>
+
+               <para>Possible values are:</para>
+<programlisting>
+typedef enum fe_guard_interval {
+       GUARD_INTERVAL_1_32,
+       GUARD_INTERVAL_1_16,
+       GUARD_INTERVAL_1_8,
+       GUARD_INTERVAL_1_4,
+       GUARD_INTERVAL_AUTO,
+       GUARD_INTERVAL_1_128,
+       GUARD_INTERVAL_19_128,
+       GUARD_INTERVAL_19_256,
+} fe_guard_interval_t;
+</programlisting>
+
+               <para>Notes:</para>
+               <para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
+                       try to find the correct guard interval (if capable) and will use TMCC to fill
+                       in the missing parameters.</para>
+               <para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
+       </section>
+</section>
+
 <section id="isdbt">
        <title>ISDB-T frontend</title>
        <para>This section describes shortly what are the possible parameters in the Linux
 
        <para>Parameters used by ISDB-T and ISDB-Tsb.</para>
 
-       <section id="isdbt-parms">
-               <title>Parameters that are common with DVB-T and ATSC</title>
-
-               <section id="isdbt-freq">
-                       <title><constant>DTV_FREQUENCY</constant></title>
-
-                       <para>Central frequency of the channel.</para>
-
-                       <para>For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a
-                               valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
-                               the channel which is 6MHz.</para>
-
-                       <para>As in ISDB-Tsb the channel consists of only one or three segments the
-                               frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
-                               central frequency of the channel is expected.</para>
-               </section>
-
-               <section id="isdbt-bw">
-                       <title><constant>DTV_BANDWIDTH_HZ</constant> (optional)</title>
-
-                       <para>Possible values:</para>
-
-                       <para>For ISDB-T it should be always 6000000Hz (6MHz)</para>
-                       <para>For ISDB-Tsb it can vary depending on the number of connected segments</para>
-
-                       <para>Note: Hardware specific values might be given here, but standard
-                               applications should not bother to set a value to this field as
-                               standard demods are ignoring it anyway.</para>
-
-                       <para>Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
-                               other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
-                               DTV_ISDBT_SB_SEGMENT_COUNT).</para>
-               </section>
-
-               <section id="isdbt-delivery-sys">
-                       <title><constant>DTV_DELIVERY_SYSTEM</constant></title>
-
-                       <para>Possible values: <constant>SYS_ISDBT</constant></para>
-               </section>
-
-               <section id="isdbt-tx-mode">
-                       <title><constant>DTV_TRANSMISSION_MODE</constant></title>
-
-                       <para>ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
-                               'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
-
-                       <para>Possible values: <constant>TRANSMISSION_MODE_2K</constant>, <constant>TRANSMISSION_MODE_8K</constant>,
-                               <constant>TRANSMISSION_MODE_AUTO</constant>, <constant>TRANSMISSION_MODE_4K</constant></para>
-
-                       <para>If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
-                               hardware will try to find the correct FFT-size (if capable) and will
-                               use TMCC to fill in the missing parameters.</para>
-
-                       <para><constant>TRANSMISSION_MODE_4K</constant> is added at the same time as the other new parameters.</para>
-               </section>
-
-               <section id="isdbt-guard-interval">
-                       <title><constant>DTV_GUARD_INTERVAL</constant></title>
-
-                       <para>Possible values: <constant>GUARD_INTERVAL_1_32</constant>, <constant>GUARD_INTERVAL_1_16</constant>, <constant>GUARD_INTERVAL_1_8</constant>,
-                               <constant>GUARD_INTERVAL_1_4</constant>, <constant>GUARD_INTERVAL_AUTO</constant></para>
-
-                       <para>If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
-                               try to find the correct guard interval (if capable) and will use TMCC to fill
-                               in the missing parameters.</para>
-               </section>
-       </section>
        <section id="isdbt-new-parms">
                <title>ISDB-T only parameters</title>
 
                        </section>
                </section>
        </section>
+       <section id="dvbt2-params">
+               <title>DVB-T2 parameters</title>
+               
+               <para>This section covers parameters that apply only to the DVB-T2 delivery method. DVB-T2
+                       support is currently in the early stages development so expect this section to grow
+                       and become more detailed with time.</para>
+
+               <section id="dvbt2-plp-id">
+                       <title><constant>DTV_DVBT2_PLP_ID</constant></title>
+
+                       <para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
+                               many data types via a single multiplex. The API will soon support this
+                               at which point this section will be expanded.</para>
+               </section>
+       </section>
 </section>
 </section>
index d08e0d4..d792f78 100644 (file)
@@ -176,14 +176,20 @@ typedef enum fe_transmit_mode {
         TRANSMISSION_MODE_2K,
         TRANSMISSION_MODE_8K,
         TRANSMISSION_MODE_AUTO,
-        TRANSMISSION_MODE_4K
+        TRANSMISSION_MODE_4K,
+        TRANSMISSION_MODE_1K,
+        TRANSMISSION_MODE_16K,
+        TRANSMISSION_MODE_32K,
 } fe_transmit_mode_t;
 
 typedef enum fe_bandwidth {
         BANDWIDTH_8_MHZ,
         BANDWIDTH_7_MHZ,
         BANDWIDTH_6_MHZ,
-        BANDWIDTH_AUTO
+        BANDWIDTH_AUTO,
+        BANDWIDTH_5_MHZ,
+        BANDWIDTH_10_MHZ,
+        BANDWIDTH_1_712_MHZ,
 } fe_bandwidth_t;
 
 
@@ -192,7 +198,10 @@ typedef enum fe_guard_interval {
         GUARD_INTERVAL_1_16,
         GUARD_INTERVAL_1_8,
         GUARD_INTERVAL_1_4,
-        GUARD_INTERVAL_AUTO
+        GUARD_INTERVAL_AUTO,
+        GUARD_INTERVAL_1_128,
+        GUARD_INTERVAL_19_128,
+        GUARD_INTERVAL_19_256,
 } fe_guard_interval_t;
 
 
@@ -306,7 +315,9 @@ struct dvb_frontend_event {
 
 #define DTV_ISDBS_TS_ID         42
 
-#define DTV_MAX_COMMAND                         DTV_ISDBS_TS_ID
+#define DTV_DVBT2_PLP_ID       43
+
+#define DTV_MAX_COMMAND                         DTV_DVBT2_PLP_ID
 
 typedef enum fe_pilot {
         PILOT_ON,
@@ -338,6 +349,7 @@ typedef enum fe_delivery_system {
         SYS_DMBTH,
         SYS_CMMB,
         SYS_DAB,
+        SYS_DVBT2,
 } fe_delivery_system_t;
 
 struct dtv_cmds_h {
index fea63b4..c8abb23 100644 (file)
 <!ENTITY sub-write SYSTEM "v4l/func-write.xml">
 <!ENTITY sub-io SYSTEM "v4l/io.xml">
 <!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
+<!ENTITY sub-m420 SYSTEM "v4l/pixfmt-m420.xml">
 <!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
 <!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
 <!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
 <!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
+<!ENTITY sub-y10b SYSTEM "v4l/pixfmt-y10b.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
diff --git a/Documentation/DocBook/v4l/pixfmt-m420.xml b/Documentation/DocBook/v4l/pixfmt-m420.xml
new file mode 100644 (file)
index 0000000..ce4bc01
--- /dev/null
@@ -0,0 +1,147 @@
+    <refentry id="V4L2-PIX-FMT-M420">
+      <refmeta>
+       <refentrytitle>V4L2_PIX_FMT_M420 ('M420')</refentrytitle>
+       &manvol;
+      </refmeta>
+      <refnamediv>
+       <refname><constant>V4L2_PIX_FMT_M420</constant></refname>
+       <refpurpose>Format with &frac12; horizontal and vertical chroma
+       resolution, also known as YUV 4:2:0. Hybrid plane line-interleaved
+       layout.</refpurpose>
+      </refnamediv>
+      <refsect1>
+       <title>Description</title>
+
+       <para>M420 is a YUV format with &frac12; horizontal and vertical chroma
+       subsampling (YUV 4:2:0). Pixels are organized as interleaved luma and
+       chroma planes. Two lines of luma data are followed by one line of chroma
+       data.</para>
+       <para>The luma plane has one byte per pixel. The chroma plane contains
+       interleaved CbCr pixels subsampled by &frac12; in the horizontal and
+       vertical directions. Each CbCr pair belongs to four pixels. For example,
+Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
+Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.</para>
+
+       <para>All line lengths are identical: if the Y lines include pad bytes
+       so do the CbCr lines.</para>
+
+       <example>
+         <title><constant>V4L2_PIX_FMT_M420</constant> 4 &times; 4
+pixel image</title>
+
+         <formalpara>
+           <title>Byte Order.</title>
+           <para>Each cell is one byte.
+               <informaltable frame="none">
+               <tgroup cols="5" align="center">
+                 <colspec align="left" colwidth="2*" />
+                 <tbody valign="top">
+                   <row>
+                     <entry>start&nbsp;+&nbsp;0:</entry>
+                     <entry>Y'<subscript>00</subscript></entry>
+                     <entry>Y'<subscript>01</subscript></entry>
+                     <entry>Y'<subscript>02</subscript></entry>
+                     <entry>Y'<subscript>03</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;4:</entry>
+                     <entry>Y'<subscript>10</subscript></entry>
+                     <entry>Y'<subscript>11</subscript></entry>
+                     <entry>Y'<subscript>12</subscript></entry>
+                     <entry>Y'<subscript>13</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;8:</entry>
+                     <entry>Cb<subscript>00</subscript></entry>
+                     <entry>Cr<subscript>00</subscript></entry>
+                     <entry>Cb<subscript>01</subscript></entry>
+                     <entry>Cr<subscript>01</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;16:</entry>
+                     <entry>Y'<subscript>20</subscript></entry>
+                     <entry>Y'<subscript>21</subscript></entry>
+                     <entry>Y'<subscript>22</subscript></entry>
+                     <entry>Y'<subscript>23</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;20:</entry>
+                     <entry>Y'<subscript>30</subscript></entry>
+                     <entry>Y'<subscript>31</subscript></entry>
+                     <entry>Y'<subscript>32</subscript></entry>
+                     <entry>Y'<subscript>33</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;24:</entry>
+                     <entry>Cb<subscript>10</subscript></entry>
+                     <entry>Cr<subscript>10</subscript></entry>
+                     <entry>Cb<subscript>11</subscript></entry>
+                     <entry>Cr<subscript>11</subscript></entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+               </informaltable>
+             </para>
+         </formalpara>
+
+         <formalpara>
+           <title>Color Sample Location.</title>
+           <para>
+               <informaltable frame="none">
+               <tgroup cols="7" align="center">
+                 <tbody valign="top">
+                   <row>
+                     <entry></entry>
+                     <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+                     <entry>2</entry><entry></entry><entry>3</entry>
+                   </row>
+                   <row>
+                     <entry>0</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry><entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry>
+                   </row>
+                   <row>
+                     <entry>1</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                   </row>
+                   <row>
+                     <entry>2</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry><entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry>
+                   </row>
+                   <row>
+                     <entry>3</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+               </informaltable>
+             </para>
+         </formalpara>
+       </example>
+      </refsect1>
+    </refentry>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "pixfmt.sgml"
+indent-tabs-mode: nil
+End:
+  -->
diff --git a/Documentation/DocBook/v4l/pixfmt-y10b.xml b/Documentation/DocBook/v4l/pixfmt-y10b.xml
new file mode 100644 (file)
index 0000000..adb0ad8
--- /dev/null
@@ -0,0 +1,43 @@
+<refentry id="V4L2-PIX-FMT-Y10BPACK">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y10BPACK ('Y10B')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y10BPACK</constant></refname>
+    <refpurpose>Grey-scale image as a bit-packed array</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a packed grey-scale image format with a depth of 10 bits per
+      pixel. Pixels are stored in a bit-packed array of 10bit bits per pixel,
+      with no padding between them and with the most significant bits coming
+      first from the left.</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y10BPACK</constant> 4 pixel data stream taking 5 bytes</title>
+
+      <formalpara>
+       <title>Bit-packed representation</title>
+       <para>pixels cross the byte boundary and have a ratio of 5 bytes for each 4
+          pixels.
+         <informaltable frame="all">
+           <tgroup cols="5" align="center">
+             <colspec align="left" colwidth="2*" />
+             <tbody valign="top">
+               <row>
+                 <entry>Y'<subscript>00[9:2]</subscript></entry>
+                 <entry>Y'<subscript>00[1:0]</subscript>Y'<subscript>01[9:4]</subscript></entry>
+                 <entry>Y'<subscript>01[3:0]</subscript>Y'<subscript>02[9:6]</subscript></entry>
+                 <entry>Y'<subscript>02[5:0]</subscript>Y'<subscript>03[9:8]</subscript></entry>
+                 <entry>Y'<subscript>03[7:0]</subscript></entry>
+               </row>
+             </tbody>
+           </tgroup>
+         </informaltable>
+       </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
index 40af4be..dbfe3b0 100644 (file)
@@ -697,6 +697,7 @@ information.</para>
     &sub-grey;
     &sub-y10;
     &sub-y12;
+    &sub-y10b;
     &sub-y16;
     &sub-yuyv;
     &sub-uyvy;
@@ -712,6 +713,7 @@ information.</para>
     &sub-nv12m;
     &sub-nv12mt;
     &sub-nv16;
+    &sub-m420;
   </section>
 
   <section>
index d7ccd25..a26b10c 100644 (file)
        </tgroup>
       </table>
     </section>
+
+    <section>
+      <title>JPEG Compressed Formats</title>
+
+      <para>Those data formats consist of an ordered sequence of 8-bit bytes
+       obtained from JPEG compression process. Additionally to the
+       <constant>_JPEG</constant> prefix the format code is made of
+       the following information.
+       <itemizedlist>
+         <listitem>The number of bus samples per entropy encoded byte.</listitem>
+         <listitem>The bus width.</listitem>
+       </itemizedlist>
+
+       <para>For instance, for a JPEG baseline process and an 8-bit bus width
+         the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>.
+       </para>
+      </para>
+
+      <para>The following table lists existing JPEG compressed formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-jpeg">
+       <title>JPEG Formats</title>
+       <tgroup cols="3">
+         <colspec colname="id" align="left" />
+         <colspec colname="code" align="left"/>
+         <colspec colname="remarks" align="left"/>
+         <thead>
+           <row>
+             <entry>Identifier</entry>
+             <entry>Code</entry>
+             <entry>Remarks</entry>
+           </row>
+         </thead>
+         <tbody valign="top">
+           <row id="V4L2-MBUS-FMT-JPEG-1X8">
+             <entry>V4L2_MBUS_FMT_JPEG_1X8</entry>
+             <entry>0x4001</entry>
+             <entry>Besides of its usage for the parallel bus this format is
+               recommended for transmission of JPEG data over MIPI CSI bus
+               using the User Defined 8-bit Data types.
+             </entry>
+           </row>
+         </tbody>
+       </tgroup>
+      </table>
+    </section>
   </section>
 </section>
index 2b796a2..c50536a 100644 (file)
@@ -311,6 +311,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link>     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
+/* Grey bit-packed formats */
+#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link>    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
+
 /* Palette formats */
 #define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link>    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
 
@@ -333,6 +336,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link>  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
 #define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link>   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
 #define <link linkend="V4L2-PIX-FMT-HM12">V4L2_PIX_FMT_HM12</link>    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
+#define <link linkend="V4L2-PIX-FMT-M420">V4L2_PIX_FMT_M420</link>    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
 
 /* two planes -- one Y, one Cr + Cb interleaved  */
 #define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link>    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
index 19132ca..95788ad 100644 (file)
@@ -551,3 +551,26 @@ Why:       These legacy callbacks should no longer be used as i2c-core offers
 Who:   Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
+
+What:  Support for UVCIOC_CTRL_ADD in the uvcvideo driver
+When:  2.6.42
+Why:   The information passed to the driver by this ioctl is now queried
+       dynamically from the device.
+Who:   Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------
+
+What:  Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
+When:  2.6.42
+Why:   Used only by applications compiled against older driver versions.
+       Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
+Who:   Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------
+
+What:  Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
+When:  2.6.42
+Why:   Superseded by the UVCIOC_CTRL_QUERY ioctl.
+Who:   Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------
index a0a5d82..2d1ad12 100644 (file)
@@ -166,7 +166,6 @@ Code  Seq#(hex)     Include File            Comments
 'T'    all     arch/x86/include/asm/ioctls.h   conflict!
 'T'    C0-DF   linux/if_tun.h          conflict!
 'U'    all     sound/asound.h          conflict!
-'U'    00-0F   drivers/media/video/uvc/uvcvideo.h      conflict!
 'U'    00-CF   linux/uinput.h          conflict!
 'U'    00-EF   linux/usbdevice_fs.h
 'U'    C0-CF   drivers/bluetooth/hci_uart.h
@@ -259,6 +258,7 @@ 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
+'u'    20-3F   linux/uvcvideo.h        USB video class host driver
 'v'    00-1F   linux/ext2_fs.h         conflict!
 'v'    00-1F   linux/fs.h              conflict!
 'v'    00-0F   linux/sonypi.h          conflict!
index 31b4857..9aae449 100644 (file)
@@ -54,7 +54,7 @@
  53 -> Pinnacle Hybrid Pro                      (em2881)
  54 -> Kworld VS-DVB-T 323UR                    (em2882)        [eb1a:e323]
  55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882)        [0ccd:005e,0ccd:0042]
- 56 -> Pinnacle Hybrid Pro (2)                  (em2882)        [2304:0226]
+ 56 -> Pinnacle Hybrid Pro (330e)               (em2882)        [2304:0226]
  57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
  60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]
index c40e3ba..9ed629d 100644 (file)
@@ -130,7 +130,6 @@ Card number: 4
 
 Note: No module for the mse3000 is available yet
 Note: No module for the vpx3224 is available yet
-Note: use encoder=X or decoder=X for non-default i2c chips
 
 ===========================
 
index 5c542e6..5bfa9a7 100644 (file)
@@ -275,6 +275,7 @@ pac7302             093a:2629       Genious iSlim 300
 pac7302                093a:262a       Webcam 300k
 pac7302                093a:262c       Philips SPC 230 NC
 jeilinj                0979:0280       Sakar 57379
+jeilinj                0979:0280       Sportscam DV15
 zc3xx          0ac8:0302       Z-star Vimicro zc0302
 vc032x         0ac8:0321       Vimicro generic vc0321
 vc032x         0ac8:0323       Vimicro Vc0323
diff --git a/Documentation/video4linux/uvcvideo.txt b/Documentation/video4linux/uvcvideo.txt
new file mode 100644 (file)
index 0000000..848d620
--- /dev/null
@@ -0,0 +1,239 @@
+Linux USB Video Class (UVC) driver
+==================================
+
+This file documents some driver-specific aspects of the UVC driver, such as
+driver-specific ioctls and implementation notes.
+
+Questions and remarks can be sent to the Linux UVC development mailing list at
+linux-uvc-devel@lists.berlios.de.
+
+
+Extension Unit (XU) support
+---------------------------
+
+1. Introduction
+
+The UVC specification allows for vendor-specific extensions through extension
+units (XUs). The Linux UVC driver supports extension unit controls (XU controls)
+through two separate mechanisms:
+
+  - through mappings of XU controls to V4L2 controls
+  - through a driver-specific ioctl interface
+
+The first one allows generic V4L2 applications to use XU controls by mapping
+certain XU controls onto V4L2 controls, which then show up during ordinary
+control enumeration.
+
+The second mechanism requires uvcvideo-specific knowledge for the application to
+access XU controls but exposes the entire UVC XU concept to user space for
+maximum flexibility.
+
+Both mechanisms complement each other and are described in more detail below.
+
+
+2. Control mappings
+
+The UVC driver provides an API for user space applications to define so-called
+control mappings at runtime. These allow for individual XU controls or byte
+ranges thereof to be mapped to new V4L2 controls. Such controls appear and
+function exactly like normal V4L2 controls (i.e. the stock controls, such as
+brightness, contrast, etc.). However, reading or writing of such a V4L2 controls
+triggers a read or write of the associated XU control.
+
+The ioctl used to create these control mappings is called UVCIOC_CTRL_MAP.
+Previous driver versions (before 0.2.0) required another ioctl to be used
+beforehand (UVCIOC_CTRL_ADD) to pass XU control information to the UVC driver.
+This is no longer necessary as newer uvcvideo versions query the information
+directly from the device.
+
+For details on the UVCIOC_CTRL_MAP ioctl please refer to the section titled
+"IOCTL reference" below.
+
+
+3. Driver specific XU control interface
+
+For applications that need to access XU controls directly, e.g. for testing
+purposes, firmware upload, or accessing binary controls, a second mechanism to
+access XU controls is provided in the form of a driver-specific ioctl, namely
+UVCIOC_CTRL_QUERY.
+
+A call to this ioctl allows applications to send queries to the UVC driver that
+directly map to the low-level UVC control requests.
+
+In order to make such a request the UVC unit ID of the control's extension unit
+and the control selector need to be known. This information either needs to be
+hardcoded in the application or queried using other ways such as by parsing the
+UVC descriptor or, if available, using the media controller API to enumerate a
+device's entities.
+
+Unless the control size is already known it is necessary to first make a
+UVC_GET_LEN requests in order to be able to allocate a sufficiently large buffer
+and set the buffer size to the correct value. Similarly, to find out whether
+UVC_GET_CUR or UVC_SET_CUR are valid requests for a given control, a
+UVC_GET_INFO request should be made. The bits 0 (GET supported) and 1 (SET
+supported) of the resulting byte indicate which requests are valid.
+
+With the addition of the UVCIOC_CTRL_QUERY ioctl the UVCIOC_CTRL_GET and
+UVCIOC_CTRL_SET ioctls have become obsolete since their functionality is a
+subset of the former ioctl. For the time being they are still supported but
+application developers are encouraged to use UVCIOC_CTRL_QUERY instead.
+
+For details on the UVCIOC_CTRL_QUERY ioctl please refer to the section titled
+"IOCTL reference" below.
+
+
+4. Security
+
+The API doesn't currently provide a fine-grained access control facility. The
+UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls require super user permissions.
+
+Suggestions on how to improve this are welcome.
+
+
+5. Debugging
+
+In order to debug problems related to XU controls or controls in general it is
+recommended to enable the UVC_TRACE_CONTROL bit in the module parameter 'trace'.
+This causes extra output to be written into the system log.
+
+
+6. IOCTL reference
+
+---- UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ----
+
+Argument: struct uvc_xu_control_mapping
+
+Description:
+       This ioctl creates a mapping between a UVC control or part of a UVC
+       control and a V4L2 control. Once mappings are defined, userspace
+       applications can access vendor-defined UVC control through the V4L2
+       control API.
+
+       To create a mapping, applications fill the uvc_xu_control_mapping
+       structure with information about an existing UVC control defined with
+       UVCIOC_CTRL_ADD and a new V4L2 control.
+
+       A UVC control can be mapped to several V4L2 controls. For instance,
+       a UVC pan/tilt control could be mapped to separate pan and tilt V4L2
+       controls. The UVC control is divided into non overlapping fields using
+       the 'size' and 'offset' fields and are then independantly mapped to
+       V4L2 control.
+
+       For signed integer V4L2 controls the data_type field should be set to
+       UVC_CTRL_DATA_TYPE_SIGNED. Other values are currently ignored.
+
+Return value:
+       On success 0 is returned. On error -1 is returned and errno is set
+       appropriately.
+
+       ENOMEM
+               Not enough memory to perform the operation.
+       EPERM
+               Insufficient privileges (super user privileges are required).
+       EINVAL
+               No such UVC control.
+       EOVERFLOW
+               The requested offset and size would overflow the UVC control.
+       EEXIST
+               Mapping already exists.
+
+Data types:
+       * struct uvc_xu_control_mapping
+
+       __u32   id              V4L2 control identifier
+       __u8    name[32]        V4L2 control name
+       __u8    entity[16]      UVC extension unit GUID
+       __u8    selector        UVC control selector
+       __u8    size            V4L2 control size (in bits)
+       __u8    offset          V4L2 control offset (in bits)
+       enum v4l2_ctrl_type
+               v4l2_type       V4L2 control type
+       enum uvc_control_data_type
+               data_type       UVC control data type
+       struct uvc_menu_info
+               *menu_info      Array of menu entries (for menu controls only)
+       __u32   menu_count      Number of menu entries (for menu controls only)
+
+       * struct uvc_menu_info
+
+       __u32   value           Menu entry value used by the device
+       __u8    name[32]        Menu entry name
+
+
+       * enum uvc_control_data_type
+
+       UVC_CTRL_DATA_TYPE_RAW          Raw control (byte array)
+       UVC_CTRL_DATA_TYPE_SIGNED       Signed integer
+       UVC_CTRL_DATA_TYPE_UNSIGNED     Unsigned integer
+       UVC_CTRL_DATA_TYPE_BOOLEAN      Boolean
+       UVC_CTRL_DATA_TYPE_ENUM         Enumeration
+       UVC_CTRL_DATA_TYPE_BITMASK      Bitmask
+
+
+---- UVCIOC_CTRL_QUERY - Query a UVC XU control ----
+
+Argument: struct uvc_xu_control_query
+
+Description:
+       This ioctl queries a UVC XU control identified by its extension unit ID
+       and control selector.
+
+       There are a number of different queries available that closely
+       correspond to the low-level control requests described in the UVC
+       specification. These requests are:
+
+       UVC_GET_CUR
+               Obtain the current value of the control.
+       UVC_GET_MIN
+               Obtain the minimum value of the control.
+       UVC_GET_MAX
+               Obtain the maximum value of the control.
+       UVC_GET_DEF
+               Obtain the default value of the control.
+       UVC_GET_RES
+               Query the resolution of the control, i.e. the step size of the
+               allowed control values.
+       UVC_GET_LEN
+               Query the size of the control in bytes.
+       UVC_GET_INFO
+               Query the control information bitmap, which indicates whether
+               get/set requests are supported.
+       UVC_SET_CUR
+               Update the value of the control.
+
+       Applications must set the 'size' field to the correct length for the
+       control. Exceptions are the UVC_GET_LEN and UVC_GET_INFO queries, for
+       which the size must be set to 2 and 1, respectively. The 'data' field
+       must point to a valid writable buffer big enough to hold the indicated
+       number of data bytes.
+
+       Data is copied directly from the device without any driver-side
+       processing. Applications are responsible for data buffer formatting,
+       including little-endian/big-endian conversion. This is particularly
+       important for the result of the UVC_GET_LEN requests, which is always
+       returned as a little-endian 16-bit integer by the device.
+
+Return value:
+       On success 0 is returned. On error -1 is returned and errno is set
+       appropriately.
+
+       ENOENT
+               The device does not support the given control or the specified
+               extension unit could not be found.
+       ENOBUFS
+               The specified buffer size is incorrect (too big or too small).
+       EINVAL
+               An invalid request code was passed.
+       EBADRQC
+               The given request is not supported by the given control.
+       EFAULT
+               The data pointer references an inaccessible memory area.
+
+Data types:
+       * struct uvc_xu_control_query
+
+       __u8    unit            Extension unit ID
+       __u8    selector        Control selector
+       __u8    query           Request code to send to the device
+       __u16   size            Control data size (in bytes)
+       __u8    *data           Control value
index 9f47e38..9af2140 100644 (file)
@@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
        dev->pci = pci;
 
        /* get chip-revision; this is needed to enable bug-fixes */
-       err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
-       if (err < 0) {
-               ERR(("pci_read_config_dword() failed.\n"));
-               goto err_disable;
-       }
-       dev->revision &= 0xf;
+       dev->revision = pci->revision;
 
        /* remap the memory from virtual to physical address */
 
index 6fc79f1..22d3ca3 100644 (file)
@@ -186,4 +186,12 @@ config MEDIA_TUNER_TDA18218
        default m if MEDIA_TUNER_CUSTOMISE
        help
          NXP TDA18218 silicon tuner driver.
+
+config MEDIA_TUNER_TDA18212
+       tristate "NXP TDA18212 silicon tuner"
+       depends on VIDEO_MEDIA && I2C
+       default m if MEDIA_TUNER_CUSTOMISE
+       help
+         NXP TDA18212 silicon tuner driver.
+
 endmenu
index 96da03d..2cb4f53 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 0d6e094..56fe75c 100644 (file)
@@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
                        case BANDWIDTH_8_MHZ:
                                req_bw  = MXL5005S_BANDWIDTH_8MHZ;
                                break;
+                       default:
+                               return -EINVAL;
                        }
                }
 
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c
new file mode 100644 (file)
index 0000000..1f1db20
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tda18212_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+/* write multiple registers */
+static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
+       int len)
+{
+       int ret;
+       u8 buf[len+1];
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = priv->cfg->i2c_address,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = reg;
+       memcpy(&buf[1], val, len);
+
+       ret = i2c_transfer(priv->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+       return ret;
+}
+
+/* read multiple registers */
+static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
+       int len)
+{
+       int ret;
+       u8 buf[len];
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = priv->cfg->i2c_address,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = &reg,
+               }, {
+                       .addr = priv->cfg->i2c_address,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       ret = i2c_transfer(priv->i2c, msg, 2);
+       if (ret == 2) {
+               memcpy(val, buf, len);
+               ret = 0;
+       } else {
+               warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+
+       return ret;
+}
+
+/* write single register */
+static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val)
+{
+       return tda18212_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val)
+{
+       return tda18212_rd_regs(priv, reg, val, 1);
+}
+
+#if 0 /* keep, useful when developing driver */
+static void tda18212_dump_regs(struct tda18212_priv *priv)
+{
+       int i;
+       u8 buf[256];
+
+       #define TDA18212_RD_LEN 32
+       for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN)
+               tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN);
+
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf,
+               sizeof(buf), true);
+
+       return;
+}
+#endif
+
+static int tda18212_set_params(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct tda18212_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret, i;
+       u32 if_khz;
+       u8 buf[9];
+       static const u8 bw_params[][3] = {
+               /*  0f    13    23 */
+               { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
+               { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
+               { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
+               { 0x92, 0x53, 0x03 }, /* DVB-C */
+       };
+
+       dbg("%s: delsys=%d RF=%d BW=%d", __func__,
+               c->delivery_system, c->frequency, c->bandwidth_hz);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+       switch (c->delivery_system) {
+       case SYS_DVBT:
+               switch (c->bandwidth_hz) {
+               case 6000000:
+                       if_khz = priv->cfg->if_dvbt_6;
+                       i = 0;
+                       break;
+               case 7000000:
+                       if_khz = priv->cfg->if_dvbt_7;
+                       i = 1;
+                       break;
+               case 8000000:
+                       if_khz = priv->cfg->if_dvbt_8;
+                       i = 2;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto error;
+               }
+               break;
+       case SYS_DVBC_ANNEX_AC:
+               if_khz = priv->cfg->if_dvbc;
+               i = 3;
+               break;
+       default:
+               ret = -EINVAL;
+               goto error;
+       }
+
+       ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]);
+       if (ret)
+               goto error;
+
+       ret = tda18212_wr_reg(priv, 0x06, 0x00);
+       if (ret)
+               goto error;
+
+       ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]);
+       if (ret)
+               goto error;
+
+       buf[0] = 0x02;
+       buf[1] = bw_params[i][1];
+       buf[2] = 0x03; /* default value */
+       buf[3] = if_khz / 50;
+       buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
+       buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
+       buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
+       buf[7] = 0xc1;
+       buf[8] = 0x01;
+       ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf));
+       if (ret)
+               goto error;
+
+exit:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+       return ret;
+
+error:
+       dbg("%s: failed:%d", __func__, ret);
+       goto exit;
+}
+
+static int tda18212_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static const struct dvb_tuner_ops tda18212_tuner_ops = {
+       .info = {
+               .name           = "NXP TDA18212",
+
+               .frequency_min  =  48000000,
+               .frequency_max  = 864000000,
+               .frequency_step =      1000,
+       },
+
+       .release       = tda18212_release,
+
+       .set_params    = tda18212_set_params,
+};
+
+struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, struct tda18212_config *cfg)
+{
+       struct tda18212_priv *priv = NULL;
+       int ret;
+       u8 val;
+
+       priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->cfg = cfg;
+       priv->i2c = i2c;
+       fe->tuner_priv = priv;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+       /* check if the tuner is there */
+       ret = tda18212_rd_reg(priv, 0x00, &val);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+       dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+       if (ret || val != 0xc7) {
+               kfree(priv);
+               return NULL;
+       }
+
+       info("NXP TDA18212HN successfully identified.");
+
+       memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
+               sizeof(struct dvb_tuner_ops));
+
+       return fe;
+}
+EXPORT_SYMBOL(tda18212_attach);
+
+MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h
new file mode 100644 (file)
index 0000000..83b497f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA18212_H
+#define TDA18212_H
+
+#include "dvb_frontend.h"
+
+struct tda18212_config {
+       u8 i2c_address;
+
+       u16 if_dvbt_6;
+       u16 if_dvbt_7;
+       u16 if_dvbt_8;
+       u16 if_dvbc;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \
+       (defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, struct tda18212_config *cfg);
+#else
+static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, struct tda18212_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/common/tuners/tda18212_priv.h b/drivers/media/common/tuners/tda18212_priv.h
new file mode 100644 (file)
index 0000000..9adff93
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA18212_PRIV_H
+#define TDA18212_PRIV_H
+
+#include "tda18212.h"
+
+#define LOG_PREFIX "tda18212"
+
+#undef dbg
+#define dbg(f, arg...) \
+       if (debug) \
+               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct tda18212_priv {
+       struct tda18212_config *cfg;
+       struct i2c_adapter *i2c;
+};
+
+#endif
index d884f5e..57022e8 100644 (file)
@@ -976,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe,
                        tda_warn("bandwidth not set!\n");
                        return -EINVAL;
                }
+       } else if (fe->ops.info.type == FE_QAM) {
+               /* DVB-C */
+               map = &std_map->qam_8;
+               bw = 8000000;
        } else {
                tda_warn("modulation type not supported!\n");
                return -EINVAL;
index 1e28f7d..aa1b2e8 100644 (file)
@@ -628,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv)
        dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
 }
 
+/*
+ * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
+ * So, the amount of the needed bandwith is given by:
+ *     Bw = Symbol_rate * (1 + 0.15)
+ * As such, the maximum symbol rate supported by 6 MHz is given by:
+ *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
+ */
+#define MAX_SYMBOL_RATE_6MHz   5217391
+
 static int xc5000_set_params(struct dvb_frontend *fe,
        struct dvb_frontend_parameters *params)
 {
@@ -688,21 +697,32 @@ static int xc5000_set_params(struct dvb_frontend *fe,
                }
                priv->rf_mode = XC_RF_MODE_AIR;
        } else if (fe->ops.info.type == FE_QAM) {
-               dprintk(1, "%s() QAM\n", __func__);
                switch (params->u.qam.modulation) {
+               case QAM_256:
+               case QAM_AUTO:
                case QAM_16:
                case QAM_32:
                case QAM_64:
                case QAM_128:
-               case QAM_256:
-               case QAM_AUTO:
                        dprintk(1, "%s() QAM modulation\n", __func__);
-                       priv->bandwidth = BANDWIDTH_8_MHZ;
-                       priv->video_standard = DTV7_8;
-                       priv->freq_hz = params->frequency - 2750000;
                        priv->rf_mode = XC_RF_MODE_CABLE;
+                       /*
+                        * Using a 8MHz bandwidth sometimes fail
+                        * with 6MHz-spaced channels, due to inter-carrier
+                        * interference. So, use DTV6 firmware
+                        */
+                       if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) {
+                               priv->bandwidth = BANDWIDTH_6_MHZ;
+                               priv->video_standard = DTV6;
+                               priv->freq_hz = params->frequency - 1750000;
+                       } else {
+                               priv->bandwidth = BANDWIDTH_8_MHZ;
+                               priv->video_standard = DTV7_8;
+                               priv->freq_hz = params->frequency - 2750000;
+                       }
                        break;
                default:
+                       dprintk(1, "%s() Unsupported QAM type\n", __func__);
                        return -EINVAL;
                }
        } else {
index 03f96d6..44f8fb5 100644 (file)
@@ -290,10 +290,8 @@ static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
 static int flexcop_pci_init(struct flexcop_pci *fc_pci)
 {
        int ret;
-       u8 card_rev;
 
-       pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
-       info("card revision %x", card_rev);
+       info("card revision %x", fc_pci->pdev->revision);
 
        if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
                return ret;
index 99d6209..b34fa95 100644 (file)
@@ -460,7 +460,7 @@ static int __devinit bt878_probe(struct pci_dev *dev,
                goto fail0;
        }
 
-       pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
+       bt->revision = dev->revision;
        pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
 
 
index 4a88a3e..faa3671 100644 (file)
@@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+static inline int find_next_packet(const u8 *buf, int pos, size_t count,
+                                  const int pktsize)
 {
-       int p = 0, i, j;
+       int start = pos, lost;
 
-       spin_lock(&demux->lock);
-
-       if (demux->tsbufp) {
-               i = demux->tsbufp;
-               j = 188 - i;
-               if (count < j) {
-                       memcpy(&demux->tsbuf[i], buf, count);
-                       demux->tsbufp += count;
-                       goto bailout;
-               }
-               memcpy(&demux->tsbuf[i], buf, j);
-               if (demux->tsbuf[0] == 0x47)
-                       dvb_dmx_swfilter_packet(demux, demux->tsbuf);
-               demux->tsbufp = 0;
-               p += j;
+       while (pos < count) {
+               if (buf[pos] == 0x47 ||
+                   (pktsize == 204 && buf[pos] == 0xB8))
+                       break;
+               pos++;
        }
 
-       while (p < count) {
-               if (buf[p] == 0x47) {
-                       if (count - p >= 188) {
-                               dvb_dmx_swfilter_packet(demux, &buf[p]);
-                               p += 188;
-                       } else {
-                               i = count - p;
-                               memcpy(demux->tsbuf, &buf[p], i);
-                               demux->tsbufp = i;
-                               goto bailout;
-                       }
-               } else
-                       p++;
+       lost = pos - start;
+       if (lost) {
+               /* This garbage is part of a valid packet? */
+               int backtrack = pos - pktsize;
+               if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
+                   (pktsize == 204 && buf[backtrack] == 0xB8)))
+                       return backtrack;
        }
 
-bailout:
-       spin_unlock(&demux->lock);
+       return pos;
 }
 
-EXPORT_SYMBOL(dvb_dmx_swfilter);
-
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
+static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
+               size_t count, const int pktsize)
 {
        int p = 0, i, j;
-       u8 tmppack[188];
+       const u8 *q;
 
        spin_lock(&demux->lock);
 
-       if (demux->tsbufp) {
+       if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
                i = demux->tsbufp;
-               j = 204 - i;
+               j = pktsize - i;
                if (count < j) {
                        memcpy(&demux->tsbuf[i], buf, count);
                        demux->tsbufp += count;
                        goto bailout;
                }
                memcpy(&demux->tsbuf[i], buf, j);
-               if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
-                       memcpy(tmppack, demux->tsbuf, 188);
-                       if (tmppack[0] == 0xB8)
-                               tmppack[0] = 0x47;
-                       dvb_dmx_swfilter_packet(demux, tmppack);
-               }
+               if (demux->tsbuf[0] == 0x47) /* double check */
+                       dvb_dmx_swfilter_packet(demux, demux->tsbuf);
                demux->tsbufp = 0;
                p += j;
        }
 
-       while (p < count) {
-               if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
-                       if (count - p >= 204) {
-                               memcpy(tmppack, &buf[p], 188);
-                               if (tmppack[0] == 0xB8)
-                                       tmppack[0] = 0x47;
-                               dvb_dmx_swfilter_packet(demux, tmppack);
-                               p += 204;
-                       } else {
-                               i = count - p;
-                               memcpy(demux->tsbuf, &buf[p], i);
-                               demux->tsbufp = i;
-                               goto bailout;
-                       }
-               } else {
-                       p++;
+       while (1) {
+               p = find_next_packet(buf, p, count, pktsize);
+               if (p >= count)
+                       break;
+               if (count - p < pktsize)
+                       break;
+
+               q = &buf[p];
+
+               if (pktsize == 204 && (*q == 0xB8)) {
+                       memcpy(demux->tsbuf, q, 188);
+                       demux->tsbuf[0] = 0x47;
+                       q = demux->tsbuf;
                }
+               dvb_dmx_swfilter_packet(demux, q);
+               p += pktsize;
+       }
+
+       i = count - p;
+       if (i) {
+               memcpy(demux->tsbuf, &buf[p], i);
+               demux->tsbufp = i;
+               if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
+                       demux->tsbuf[0] = 0x47;
        }
 
 bailout:
        spin_unlock(&demux->lock);
 }
 
+void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+       _dvb_dmx_swfilter(demux, buf, count, 188);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter);
+
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+       _dvb_dmx_swfilter(demux, buf, count, 204);
+}
 EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 
 static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
index 31e2c0d..9827804 100644 (file)
@@ -105,7 +105,8 @@ struct dvb_frontend_private {
 
        /* thread/frontend values */
        struct dvb_device *dvbdev;
-       struct dvb_frontend_parameters parameters;
+       struct dvb_frontend_parameters parameters_in;
+       struct dvb_frontend_parameters parameters_out;
        struct dvb_fe_events events;
        struct semaphore sem;
        struct list_head list_head;
@@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 
        e = &events->events[events->eventw];
 
-       memcpy (&e->parameters, &fepriv->parameters,
-               sizeof (struct dvb_frontend_parameters));
-
        if (status & FE_HAS_LOCK)
                if (fe->ops.get_frontend)
-                       fe->ops.get_frontend(fe, &e->parameters);
+                       fe->ops.get_frontend(fe, &fepriv->parameters_out);
+
+       e->parameters = fepriv->parameters_out;
 
        events->eventw = wp;
 
@@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
        int ready = 0;
        int fe_set_err = 0;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int original_inversion = fepriv->parameters.inversion;
-       u32 original_frequency = fepriv->parameters.frequency;
+       int original_inversion = fepriv->parameters_in.inversion;
+       u32 original_frequency = fepriv->parameters_in.frequency;
 
        /* are we using autoinversion? */
        autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-                        (fepriv->parameters.inversion == INVERSION_AUTO));
+                        (fepriv->parameters_in.inversion == INVERSION_AUTO));
 
        /* setup parameters correctly */
        while(!ready) {
@@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
                fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
 
        /* set the frontend itself */
-       fepriv->parameters.frequency += fepriv->lnb_drift;
+       fepriv->parameters_in.frequency += fepriv->lnb_drift;
        if (autoinversion)
-               fepriv->parameters.inversion = fepriv->inversion;
+               fepriv->parameters_in.inversion = fepriv->inversion;
        if (fe->ops.set_frontend)
-               fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters);
+               fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in);
+       fepriv->parameters_out = fepriv->parameters_in;
        if (fe_set_err < 0) {
                fepriv->state = FESTATE_ERROR;
                return fe_set_err;
        }
 
-       fepriv->parameters.frequency = original_frequency;
-       fepriv->parameters.inversion = original_inversion;
+       fepriv->parameters_in.frequency = original_frequency;
+       fepriv->parameters_in.inversion = original_inversion;
 
        fepriv->auto_sub_step++;
        return 0;
@@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
                if (fepriv->state & FESTATE_RETUNE) {
                        if (fe->ops.set_frontend)
                                retval = fe->ops.set_frontend(fe,
-                                                       &fepriv->parameters);
+                                                       &fepriv->parameters_in);
+                       fepriv->parameters_out = fepriv->parameters_in;
                        if (retval < 0)
                                fepriv->state = FESTATE_ERROR;
                        else
@@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 
                /* if we're tuned, then we have determined the correct inversion */
                if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-                   (fepriv->parameters.inversion == INVERSION_AUTO)) {
-                       fepriv->parameters.inversion = fepriv->inversion;
+                   (fepriv->parameters_in.inversion == INVERSION_AUTO)) {
+                       fepriv->parameters_in.inversion = fepriv->inversion;
                }
                return;
        }
@@ -594,12 +596,14 @@ restart:
 
                                if (fepriv->state & FESTATE_RETUNE) {
                                        dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
-                                       params = &fepriv->parameters;
+                                       params = &fepriv->parameters_in;
                                        fepriv->state = FESTATE_TUNED;
                                }
 
                                if (fe->ops.tune)
                                        fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+                               if (params)
+                                       fepriv->parameters_out = *params;
 
                                if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
                                        dprintk("%s: state changed, adding current state\n", __func__);
@@ -612,11 +616,9 @@ restart:
                                dvb_frontend_swzigzag(fe);
                                break;
                        case DVBFE_ALGO_CUSTOM:
-                               params = NULL; /* have we been asked to RETUNE ?        */
                                dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
                                if (fepriv->state & FESTATE_RETUNE) {
                                        dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
-                                       params = &fepriv->parameters;
                                        fepriv->state = FESTATE_TUNED;
                                }
                                /* Case where we are going to search for a carrier
@@ -625,7 +627,7 @@ restart:
                                 */
                                if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
                                        if (fe->ops.search) {
-                                               fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
+                                               fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in);
                                                /* We did do a search as was requested, the flags are
                                                 * now unset as well and has the flags wrt to search.
                                                 */
@@ -636,11 +638,12 @@ restart:
                                /* Track the carrier if the search was successful */
                                if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
                                        if (fe->ops.track)
-                                               fe->ops.track(fe, &fepriv->parameters);
+                                               fe->ops.track(fe, &fepriv->parameters_in);
                                } else {
                                        fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
                                        fepriv->delay = HZ / 2;
                                }
+                               fepriv->parameters_out = fepriv->parameters_in;
                                fe->ops.read_status(fe, &s);
                                if (s != fepriv->status) {
                                        dvb_frontend_add_event(fe, s); /* update event list */
@@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
 
 static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int i;
 
-       memset(&(fe->dtv_property_cache), 0,
-                       sizeof(struct dtv_frontend_properties));
-
-       fe->dtv_property_cache.state = DTV_CLEAR;
-       fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
-       fe->dtv_property_cache.inversion = INVERSION_AUTO;
-       fe->dtv_property_cache.fec_inner = FEC_AUTO;
-       fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
-       fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO;
-       fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
-       fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
-       fe->dtv_property_cache.symbol_rate = QAM_AUTO;
-       fe->dtv_property_cache.code_rate_HP = FEC_AUTO;
-       fe->dtv_property_cache.code_rate_LP = FEC_AUTO;
-
-       fe->dtv_property_cache.isdbt_partial_reception = -1;
-       fe->dtv_property_cache.isdbt_sb_mode = -1;
-       fe->dtv_property_cache.isdbt_sb_subchannel = -1;
-       fe->dtv_property_cache.isdbt_sb_segment_idx = -1;
-       fe->dtv_property_cache.isdbt_sb_segment_count = -1;
-       fe->dtv_property_cache.isdbt_layer_enabled = 0x7;
+       memset(c, 0, sizeof(struct dtv_frontend_properties));
+
+       c->state = DTV_CLEAR;
+       c->delivery_system = SYS_UNDEFINED;
+       c->inversion = INVERSION_AUTO;
+       c->fec_inner = FEC_AUTO;
+       c->transmission_mode = TRANSMISSION_MODE_AUTO;
+       c->bandwidth_hz = BANDWIDTH_AUTO;
+       c->guard_interval = GUARD_INTERVAL_AUTO;
+       c->hierarchy = HIERARCHY_AUTO;
+       c->symbol_rate = QAM_AUTO;
+       c->code_rate_HP = FEC_AUTO;
+       c->code_rate_LP = FEC_AUTO;
+
+       c->isdbt_partial_reception = -1;
+       c->isdbt_sb_mode = -1;
+       c->isdbt_sb_subchannel = -1;
+       c->isdbt_sb_segment_idx = -1;
+       c->isdbt_sb_segment_count = -1;
+       c->isdbt_layer_enabled = 0x7;
        for (i = 0; i < 3; i++) {
-               fe->dtv_property_cache.layer[i].fec = FEC_AUTO;
-               fe->dtv_property_cache.layer[i].modulation = QAM_AUTO;
-               fe->dtv_property_cache.layer[i].interleaving = -1;
-               fe->dtv_property_cache.layer[i].segment_count = -1;
+               c->layer[i].fec = FEC_AUTO;
+               c->layer[i].modulation = QAM_AUTO;
+               c->layer[i].interleaving = -1;
+               c->layer[i].segment_count = -1;
        }
 
        return 0;
@@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
  * it's being used for the legacy or new API, reducing code and complexity.
  */
 static void dtv_property_cache_sync(struct dvb_frontend *fe,
-                                   struct dvb_frontend_parameters *p)
+                                   struct dtv_frontend_properties *c,
+                                   const struct dvb_frontend_parameters *p)
 {
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
        c->frequency = p->frequency;
        c->inversion = p->inversion;
 
@@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
  */
 static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
 {
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       struct dvb_frontend_parameters *p = &fepriv->parameters;
+       struct dvb_frontend_parameters *p = &fepriv->parameters_in;
 
        p->frequency = c->frequency;
        p->inversion = c->inversion;
@@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
                dprintk("%s() Preparing QPSK req\n", __func__);
                p->u.qpsk.symbol_rate = c->symbol_rate;
                p->u.qpsk.fec_inner = c->fec_inner;
-               c->delivery_system = SYS_DVBS;
                break;
        case FE_QAM:
                dprintk("%s() Preparing QAM req\n", __func__);
                p->u.qam.symbol_rate = c->symbol_rate;
                p->u.qam.fec_inner = c->fec_inner;
                p->u.qam.modulation = c->modulation;
-               c->delivery_system = SYS_DVBC_ANNEX_AC;
                break;
        case FE_OFDM:
                dprintk("%s() Preparing OFDM req\n", __func__);
@@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
                p->u.ofdm.transmission_mode = c->transmission_mode;
                p->u.ofdm.guard_interval = c->guard_interval;
                p->u.ofdm.hierarchy_information = c->hierarchy;
-               c->delivery_system = SYS_DVBT;
                break;
        case FE_ATSC:
                dprintk("%s() Preparing VSB req\n", __func__);
                p->u.vsb.modulation = c->modulation;
-               if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
-                       c->delivery_system = SYS_ATSC;
-               else
-                       c->delivery_system = SYS_DVBC_ANNEX_B;
                break;
        }
 }
@@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
  */
 static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
 {
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       struct dvb_frontend_parameters *p = &fepriv->parameters;
+       struct dvb_frontend_parameters *p = &fepriv->parameters_in;
 
        p->frequency = c->frequency;
        p->inversion = c->inversion;
@@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
                break;
        }
 
-       if(c->delivery_system == SYS_ISDBT) {
-               /* Fake out a generic DVB-T request so we pass validation in the ioctl */
-               p->frequency = c->frequency;
-               p->inversion = c->inversion;
+       /* Fake out a generic DVB-T request so we pass validation in the ioctl */
+       if ((c->delivery_system == SYS_ISDBT) ||
+           (c->delivery_system == SYS_DVBT2)) {
                p->u.ofdm.constellation = QAM_AUTO;
                p->u.ofdm.code_rate_HP = FEC_AUTO;
                p->u.ofdm.code_rate_LP = FEC_AUTO;
@@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
 
 static void dtv_property_cache_submit(struct dvb_frontend *fe)
 {
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
        /* For legacy delivery systems we don't need the delivery_system to
         * be specified, but we populate the older structures from the cache
@@ -1204,133 +1198,149 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
                                    struct dtv_property *tvp,
                                    struct file *file)
 {
-       int r = 0;
-
-       /* Allow the frontend to validate incoming properties */
-       if (fe->ops.get_property)
-               r = fe->ops.get_property(fe, tvp);
+       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dtv_frontend_properties cdetected;
+       int r;
 
-       if (r < 0)
-               return r;
+       /*
+        * If the driver implements a get_frontend function, then convert
+        * detected parameters to S2API properties.
+        */
+       if (fe->ops.get_frontend) {
+               cdetected = *c;
+               dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out);
+               c = &cdetected;
+       }
 
        switch(tvp->cmd) {
        case DTV_FREQUENCY:
-               tvp->u.data = fe->dtv_property_cache.frequency;
+               tvp->u.data = c->frequency;
                break;
        case DTV_MODULATION:
-               tvp->u.data = fe->dtv_property_cache.modulation;
+               tvp->u.data = c->modulation;
                break;
        case DTV_BANDWIDTH_HZ:
-               tvp->u.data = fe->dtv_property_cache.bandwidth_hz;
+               tvp->u.data = c->bandwidth_hz;
                break;
        case DTV_INVERSION:
-               tvp->u.data = fe->dtv_property_cache.inversion;
+               tvp->u.data = c->inversion;
                break;
        case DTV_SYMBOL_RATE:
-               tvp->u.data = fe->dtv_property_cache.symbol_rate;
+               tvp->u.data = c->symbol_rate;
                break;
        case DTV_INNER_FEC:
-               tvp->u.data = fe->dtv_property_cache.fec_inner;
+               tvp->u.data = c->fec_inner;
                break;
        case DTV_PILOT:
-               tvp->u.data = fe->dtv_property_cache.pilot;
+               tvp->u.data = c->pilot;
                break;
        case DTV_ROLLOFF:
-               tvp->u.data = fe->dtv_property_cache.rolloff;
+               tvp->u.data = c->rolloff;
                break;
        case DTV_DELIVERY_SYSTEM:
-               tvp->u.data = fe->dtv_property_cache.delivery_system;
+               tvp->u.data = c->delivery_system;
                break;
        case DTV_VOLTAGE:
-               tvp->u.data = fe->dtv_property_cache.voltage;
+               tvp->u.data = c->voltage;
                break;
        case DTV_TONE:
-               tvp->u.data = fe->dtv_property_cache.sectone;
+               tvp->u.data = c->sectone;
                break;
        case DTV_API_VERSION:
                tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
                break;
        case DTV_CODE_RATE_HP:
-               tvp->u.data = fe->dtv_property_cache.code_rate_HP;
+               tvp->u.data = c->code_rate_HP;
                break;
        case DTV_CODE_RATE_LP:
-               tvp->u.data = fe->dtv_property_cache.code_rate_LP;
+               tvp->u.data = c->code_rate_LP;
                break;
        case DTV_GUARD_INTERVAL:
-               tvp->u.data = fe->dtv_property_cache.guard_interval;
+               tvp->u.data = c->guard_interval;
                break;
        case DTV_TRANSMISSION_MODE:
-               tvp->u.data = fe->dtv_property_cache.transmission_mode;
+               tvp->u.data = c->transmission_mode;
                break;
        case DTV_HIERARCHY:
-               tvp->u.data = fe->dtv_property_cache.hierarchy;
+               tvp->u.data = c->hierarchy;
                break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
-               tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception;
+               tvp->u.data = c->isdbt_partial_reception;
                break;
        case DTV_ISDBT_SOUND_BROADCASTING:
-               tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode;
+               tvp->u.data = c->isdbt_sb_mode;
                break;
        case DTV_ISDBT_SB_SUBCHANNEL_ID:
-               tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel;
+               tvp->u.data = c->isdbt_sb_subchannel;
                break;
        case DTV_ISDBT_SB_SEGMENT_IDX:
-               tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx;
+               tvp->u.data = c->isdbt_sb_segment_idx;
                break;
        case DTV_ISDBT_SB_SEGMENT_COUNT:
-               tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count;
+               tvp->u.data = c->isdbt_sb_segment_count;
                break;
        case DTV_ISDBT_LAYER_ENABLED:
-               tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled;
+               tvp->u.data = c->isdbt_layer_enabled;
                break;
        case DTV_ISDBT_LAYERA_FEC:
-               tvp->u.data = fe->dtv_property_cache.layer[0].fec;
+               tvp->u.data = c->layer[0].fec;
                break;
        case DTV_ISDBT_LAYERA_MODULATION:
-               tvp->u.data = fe->dtv_property_cache.layer[0].modulation;
+               tvp->u.data = c->layer[0].modulation;
                break;
        case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-               tvp->u.data = fe->dtv_property_cache.layer[0].segment_count;
+               tvp->u.data = c->layer[0].segment_count;
                break;
        case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-               tvp->u.data = fe->dtv_property_cache.layer[0].interleaving;
+               tvp->u.data = c->layer[0].interleaving;
                break;
        case DTV_ISDBT_LAYERB_FEC:
-               tvp->u.data = fe->dtv_property_cache.layer[1].fec;
+               tvp->u.data = c->layer[1].fec;
                break;
        case DTV_ISDBT_LAYERB_MODULATION:
-               tvp->u.data = fe->dtv_property_cache.layer[1].modulation;
+               tvp->u.data = c->layer[1].modulation;
                break;
        case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-               tvp->u.data = fe->dtv_property_cache.layer[1].segment_count;
+               tvp->u.data = c->layer[1].segment_count;
                break;
        case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-               tvp->u.data = fe->dtv_property_cache.layer[1].interleaving;
+               tvp->u.data = c->layer[1].interleaving;
                break;
        case DTV_ISDBT_LAYERC_FEC:
-               tvp->u.data = fe->dtv_property_cache.layer[2].fec;
+               tvp->u.data = c->layer[2].fec;
                break;
        case DTV_ISDBT_LAYERC_MODULATION:
-               tvp->u.data = fe->dtv_property_cache.layer[2].modulation;
+               tvp->u.data = c->layer[2].modulation;
                break;
        case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-               tvp->u.data = fe->dtv_property_cache.layer[2].segment_count;
+               tvp->u.data = c->layer[2].segment_count;
                break;
        case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-               tvp->u.data = fe->dtv_property_cache.layer[2].interleaving;
+               tvp->u.data = c->layer[2].interleaving;
                break;
        case DTV_ISDBS_TS_ID:
-               tvp->u.data = fe->dtv_property_cache.isdbs_ts_id;
+               tvp->u.data = c->isdbs_ts_id;
+               break;
+       case DTV_DVBT2_PLP_ID:
+               tvp->u.data = c->dvbt2_plp_id;
                break;
        default:
-               r = -1;
+               return -EINVAL;
+       }
+
+       /* Allow the frontend to override outgoing properties */
+       if (fe->ops.get_property) {
+               r = fe->ops.get_property(fe, tvp);
+               if (r < 0)
+                       return r;
        }
 
        dtv_property_dump(tvp);
 
-       return r;
+       return 0;
 }
 
 static int dtv_property_process_set(struct dvb_frontend *fe,
@@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                                    struct file *file)
 {
        int r = 0;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        dtv_property_dump(tvp);
 
        /* Allow the frontend to validate incoming properties */
-       if (fe->ops.set_property)
+       if (fe->ops.set_property) {
                r = fe->ops.set_property(fe, tvp);
-
-       if (r < 0)
-               return r;
+               if (r < 0)
+                       return r;
+       }
 
        switch(tvp->cmd) {
        case DTV_CLEAR:
@@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                 * tunerequest so we can pass validation in the FE_SET_FRONTEND
                 * ioctl.
                 */
-               fe->dtv_property_cache.state = tvp->cmd;
+               c->state = tvp->cmd;
                dprintk("%s() Finalised property cache\n", __func__);
                dtv_property_cache_submit(fe);
 
-               r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
-                       &fepriv->parameters);
+               r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
+                       &fepriv->parameters_in);
                break;
        case DTV_FREQUENCY:
-               fe->dtv_property_cache.frequency = tvp->u.data;
+               c->frequency = tvp->u.data;
                break;
        case DTV_MODULATION:
-               fe->dtv_property_cache.modulation = tvp->u.data;
+               c->modulation = tvp->u.data;
                break;
        case DTV_BANDWIDTH_HZ:
-               fe->dtv_property_cache.bandwidth_hz = tvp->u.data;
+               c->bandwidth_hz = tvp->u.data;
                break;
        case DTV_INVERSION:
-               fe->dtv_property_cache.inversion = tvp->u.data;
+               c->inversion = tvp->u.data;
                break;
        case DTV_SYMBOL_RATE:
-               fe->dtv_property_cache.symbol_rate = tvp->u.data;
+               c->symbol_rate = tvp->u.data;
                break;
        case DTV_INNER_FEC:
-               fe->dtv_property_cache.fec_inner = tvp->u.data;
+               c->fec_inner = tvp->u.data;
                break;
        case DTV_PILOT:
-               fe->dtv_property_cache.pilot = tvp->u.data;
+               c->pilot = tvp->u.data;
                break;
        case DTV_ROLLOFF:
-               fe->dtv_property_cache.rolloff = tvp->u.data;
+               c->rolloff = tvp->u.data;
                break;
        case DTV_DELIVERY_SYSTEM:
-               fe->dtv_property_cache.delivery_system = tvp->u.data;
+               c->delivery_system = tvp->u.data;
                break;
        case DTV_VOLTAGE:
-               fe->dtv_property_cache.voltage = tvp->u.data;
+               c->voltage = tvp->u.data;
                r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
-                       (void *)fe->dtv_property_cache.voltage);
+                       (void *)c->voltage);
                break;
        case DTV_TONE:
-               fe->dtv_property_cache.sectone = tvp->u.data;
+               c->sectone = tvp->u.data;
                r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
-                       (void *)fe->dtv_property_cache.sectone);
+                       (void *)c->sectone);
                break;
        case DTV_CODE_RATE_HP:
-               fe->dtv_property_cache.code_rate_HP = tvp->u.data;
+               c->code_rate_HP = tvp->u.data;
                break;
        case DTV_CODE_RATE_LP:
-               fe->dtv_property_cache.code_rate_LP = tvp->u.data;
+               c->code_rate_LP = tvp->u.data;
                break;
        case DTV_GUARD_INTERVAL:
-               fe->dtv_property_cache.guard_interval = tvp->u.data;
+               c->guard_interval = tvp->u.data;
                break;
        case DTV_TRANSMISSION_MODE:
-               fe->dtv_property_cache.transmission_mode = tvp->u.data;
+               c->transmission_mode = tvp->u.data;
                break;
        case DTV_HIERARCHY:
-               fe->dtv_property_cache.hierarchy = tvp->u.data;
+               c->hierarchy = tvp->u.data;
                break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
-               fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data;
+               c->isdbt_partial_reception = tvp->u.data;
                break;
        case DTV_ISDBT_SOUND_BROADCASTING:
-               fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data;
+               c->isdbt_sb_mode = tvp->u.data;
                break;
        case DTV_ISDBT_SB_SUBCHANNEL_ID:
-               fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data;
+               c->isdbt_sb_subchannel = tvp->u.data;
                break;
        case DTV_ISDBT_SB_SEGMENT_IDX:
-               fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data;
+               c->isdbt_sb_segment_idx = tvp->u.data;
                break;
        case DTV_ISDBT_SB_SEGMENT_COUNT:
-               fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data;
+               c->isdbt_sb_segment_count = tvp->u.data;
                break;
        case DTV_ISDBT_LAYER_ENABLED:
-               fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data;
+               c->isdbt_layer_enabled = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERA_FEC:
-               fe->dtv_property_cache.layer[0].fec = tvp->u.data;
+               c->layer[0].fec = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERA_MODULATION:
-               fe->dtv_property_cache.layer[0].modulation = tvp->u.data;
+               c->layer[0].modulation = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-               fe->dtv_property_cache.layer[0].segment_count = tvp->u.data;
+               c->layer[0].segment_count = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-               fe->dtv_property_cache.layer[0].interleaving = tvp->u.data;
+               c->layer[0].interleaving = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERB_FEC:
-               fe->dtv_property_cache.layer[1].fec = tvp->u.data;
+               c->layer[1].fec = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERB_MODULATION:
-               fe->dtv_property_cache.layer[1].modulation = tvp->u.data;
+               c->layer[1].modulation = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-               fe->dtv_property_cache.layer[1].segment_count = tvp->u.data;
+               c->layer[1].segment_count = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-               fe->dtv_property_cache.layer[1].interleaving = tvp->u.data;
+               c->layer[1].interleaving = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERC_FEC:
-               fe->dtv_property_cache.layer[2].fec = tvp->u.data;
+               c->layer[2].fec = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERC_MODULATION:
-               fe->dtv_property_cache.layer[2].modulation = tvp->u.data;
+               c->layer[2].modulation = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-               fe->dtv_property_cache.layer[2].segment_count = tvp->u.data;
+               c->layer[2].segment_count = tvp->u.data;
                break;
        case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-               fe->dtv_property_cache.layer[2].interleaving = tvp->u.data;
+               c->layer[2].interleaving = tvp->u.data;
                break;
        case DTV_ISDBS_TS_ID:
-               fe->dtv_property_cache.isdbs_ts_id = tvp->u.data;
+               c->isdbs_ts_id = tvp->u.data;
+               break;
+       case DTV_DVBT2_PLP_ID:
+               c->dvbt2_plp_id = tvp->u.data;
                break;
        default:
-               r = -1;
+               return -EINVAL;
        }
 
        return r;
@@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int err = -EOPNOTSUPP;
 
@@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file,
        if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
                err = dvb_frontend_ioctl_properties(file, cmd, parg);
        else {
-               fe->dtv_property_cache.state = DTV_UNDEFINED;
+               c->state = DTV_UNDEFINED;
                err = dvb_frontend_ioctl_legacy(file, cmd, parg);
        }
 
@@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int err = 0;
 
        struct dtv_properties *tvps = NULL;
@@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                }
 
                for (i = 0; i < tvps->num; i++) {
-                       (tvp + i)->result = dtv_property_process_set(fe, tvp + i, file);
-                       err |= (tvp + i)->result;
+                       err = dtv_property_process_set(fe, tvp + i, file);
+                       if (err < 0)
+                               goto out;
+                       (tvp + i)->result = err;
                }
 
-               if(fe->dtv_property_cache.state == DTV_TUNE)
+               if (c->state == DTV_TUNE)
                        dprintk("%s() Property cache is full, tuning\n", __func__);
 
        } else
@@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                }
 
                for (i = 0; i < tvps->num; i++) {
-                       (tvp + i)->result = dtv_property_process_get(fe, tvp + i, file);
-                       err |= (tvp + i)->result;
+                       err = dtv_property_process_get(fe, tvp + i, file);
+                       if (err < 0)
+                               goto out;
+                       (tvp + i)->result = err;
                }
 
                if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
@@ -1787,10 +1807,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                break;
 
        case FE_SET_FRONTEND: {
+               struct dtv_frontend_properties *c = &fe->dtv_property_cache;
                struct dvb_frontend_tune_settings fetunesettings;
 
-               if(fe->dtv_property_cache.state == DTV_TUNE) {
-                       if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
+               if (c->state == DTV_TUNE) {
+                       if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) {
                                err = -EINVAL;
                                break;
                        }
@@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                                break;
                        }
 
-                       memcpy (&fepriv->parameters, parg,
+                       memcpy (&fepriv->parameters_in, parg,
                                sizeof (struct dvb_frontend_parameters));
-                       dtv_property_cache_sync(fe, &fepriv->parameters);
+                       dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
                }
 
                memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
@@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 
                /* force auto frequency inversion if requested */
                if (dvb_force_auto_inversion) {
-                       fepriv->parameters.inversion = INVERSION_AUTO;
+                       fepriv->parameters_in.inversion = INVERSION_AUTO;
                        fetunesettings.parameters.inversion = INVERSION_AUTO;
                }
                if (fe->ops.info.type == FE_OFDM) {
                        /* without hierarchical coding code_rate_LP is irrelevant,
                         * so we tolerate the otherwise invalid FEC_NONE setting */
-                       if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
-                           fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
-                               fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
+                       if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
+                           fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE)
+                               fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO;
                }
 
                /* get frontend-specific tuning settings */
@@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                        switch(fe->ops.info.type) {
                        case FE_QPSK:
                                fepriv->min_delay = HZ/20;
-                               fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
-                               fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
+                               fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000;
+                               fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000;
                                break;
 
                        case FE_QAM:
@@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 
        case FE_GET_FRONTEND:
                if (fe->ops.get_frontend) {
-                       memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
-                       err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+                       err = fe->ops.get_frontend(fe, &fepriv->parameters_out);
+                       memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters));
                }
                break;
 
index 3b86050..5590eb6 100644 (file)
@@ -358,6 +358,9 @@ struct dtv_frontend_properties {
 
        /* ISDB-T specifics */
        u32                     isdbs_ts_id;
+
+       /* DVB-T2 specifics */
+       u32                     dvbt2_plp_id;
 };
 
 struct dvb_frontend {
index c545039..e85304c 100644 (file)
@@ -292,6 +292,11 @@ config DVB_USB_ANYSEE
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_STV0900 if !DVB_FE_CUSTOMISE
+       select DVB_STV6110 if !DVB_FE_CUSTOMISE
+       select DVB_ISL6423 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Anysee E30, Anysee E30 Plus or
          Anysee E30 C Plus DVB USB2.0 receiver.
index f8e9bf1..b95a95e 100644 (file)
@@ -78,17 +78,26 @@ static struct rc_map_table rc_map_a800_table[] = {
 
 static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       u8 key[5];
+       int ret;
+       u8 *key = kmalloc(5, GFP_KERNEL);
+       if (!key)
+               return -ENOMEM;
+
        if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
                                0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
-                               2000) != 5)
-               return -ENODEV;
+                               2000) != 5) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        /* call the universal NEC remote processor, to find out the key's state and event */
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
                deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-       return 0;
+       ret = 0;
+out:
+       kfree(key);
+       return ret;
 }
 
 /* USB Driver stuff */
index 6b402e9..4dc1ca3 100644 (file)
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
+#include "tda18212.h"
+#include "cx24116.h"
+#include "stv0900.h"
+#include "stv6110.h"
+#include "isl6423.h"
 
 /* debug */
 static int dvb_usb_anysee_debug;
@@ -105,6 +110,27 @@ static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
        return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
+/* write single register with mask */
+static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
+       u8 mask)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = anysee_read_reg(d, reg, &tmp);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return anysee_write_reg(d, reg, val);
+}
+
 static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
 {
        u8 buf[] = {CMD_GET_HW_INFO};
@@ -162,18 +188,18 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
                        u8 buf[6];
                        buf[0] = CMD_I2C_READ;
-                       buf[1] = msg[i].addr + 1;
+                       buf[1] = (msg[i].addr << 1) | 0x01;
                        buf[2] = msg[i].buf[0];
-                       buf[3] = 0x00;
-                       buf[4] = 0x00;
-                       buf[5] = 0x01;
+                       buf[3] = msg[i].buf[1];
+                       buf[4] = msg[i].len-1;
+                       buf[5] = msg[i+1].len;
                        ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
                                msg[i+1].len);
                        inc = 2;
                } else {
                        u8 buf[4+msg[i].len];
                        buf[0] = CMD_I2C_WRITE;
-                       buf[1] = msg[i].addr;
+                       buf[1] = (msg[i].addr << 1);
                        buf[2] = msg[i].len;
                        buf[3] = 0x01;
                        memcpy(&buf[4], msg[i].buf, msg[i].len);
@@ -224,7 +250,7 @@ static int anysee_mt352_demod_init(struct dvb_frontend *fe)
 
 /* Callbacks for DVB USB */
 static struct tda10023_config anysee_tda10023_config = {
-       .demod_address = 0x1a,
+       .demod_address = (0x1a >> 1),
        .invert = 0,
        .xtal   = 16000000,
        .pll_m  = 11,
@@ -235,143 +261,539 @@ static struct tda10023_config anysee_tda10023_config = {
 };
 
 static struct mt352_config anysee_mt352_config = {
-       .demod_address = 0x1e,
+       .demod_address = (0x1e >> 1),
        .demod_init    = anysee_mt352_demod_init,
 };
 
 static struct zl10353_config anysee_zl10353_config = {
-       .demod_address = 0x1e,
+       .demod_address = (0x1e >> 1),
        .parallel_ts = 1,
 };
 
+static struct zl10353_config anysee_zl10353_tda18212_config2 = {
+       .demod_address = (0x1e >> 1),
+       .parallel_ts = 1,
+       .disable_i2c_gate_ctrl = 1,
+       .no_tuner = 1,
+       .if2 = 41500,
+};
+
+static struct zl10353_config anysee_zl10353_tda18212_config = {
+       .demod_address = (0x18 >> 1),
+       .parallel_ts = 1,
+       .disable_i2c_gate_ctrl = 1,
+       .no_tuner = 1,
+       .if2 = 41500,
+};
+
+static struct tda10023_config anysee_tda10023_tda18212_config = {
+       .demod_address = (0x1a >> 1),
+       .xtal   = 16000000,
+       .pll_m  = 12,
+       .pll_p  = 3,
+       .pll_n  = 1,
+       .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+       .deltaf = 0xba02,
+};
+
+static struct tda18212_config anysee_tda18212_config = {
+       .i2c_address = (0xc0 >> 1),
+       .if_dvbt_6 = 4150,
+       .if_dvbt_7 = 4150,
+       .if_dvbt_8 = 4150,
+       .if_dvbc = 5000,
+};
+
+static struct cx24116_config anysee_cx24116_config = {
+       .demod_address = (0xaa >> 1),
+       .mpg_clk_pos_pol = 0x00,
+       .i2c_wr_max = 48,
+};
+
+static struct stv0900_config anysee_stv0900_config = {
+       .demod_address = (0xd0 >> 1),
+       .demod_mode = 0,
+       .xtal = 8000000,
+       .clkmode = 3,
+       .diseqc_mode = 2,
+       .tun1_maddress = 0,
+       .tun1_adc = 1, /* 1 Vpp */
+       .path1_mode = 3,
+};
+
+static struct stv6110_config anysee_stv6110_config = {
+       .i2c_address = (0xc0 >> 1),
+       .mclk = 16000000,
+       .clk_div = 1,
+};
+
+static struct isl6423_config anysee_isl6423_config = {
+       .current_max = SEC_CURRENT_800m,
+       .curlim  = SEC_CURRENT_LIM_OFF,
+       .mod_extern = 1,
+       .addr = (0x10 >> 1),
+};
+
+/*
+ * New USB device strings: Mfr=1, Product=2, SerialNumber=0
+ * Manufacturer: AMT.CO.KR
+ *
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
+ * PCB: ?
+ * parts: DNOS404ZH102A(MT352, DTT7579(?))
+ *
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
+ * PCB: ?
+ * parts: DNOS404ZH103A(ZL10353, DTT7579(?))
+ *
+ * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
+ * PCB: 507CD (rev1.1)
+ * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
+ * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01
+ * IOD[0] ZL10353 1=enabled
+ * IOA[7] TS 0=enabled
+ * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
+ *
+ * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
+ * PCB: 507DC (rev0.2)
+ * parts: TDA10023, DTOS403IH102B TM, CST56I01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
+ * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01
+ * IOD[0] TDA10023 1=enabled
+ *
+ * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
+ * PCB: 507SI (rev2.1)
+ * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe
+ * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01
+ * IOD[0] CX24116 1=enabled
+ *
+ * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
+ * PCB: 507FA (rev0.4)
+ * parts: TDA10023, DTOS403IH102B TM, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] tuner 1=enabled
+ *
+ * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
+ * PCB: 507FA (rev1.1)
+ * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * DVB-C:
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] tuner 1=enabled
+ * DVB-T:
+ * IOD[0] ZL10353 1=enabled
+ * IOE[0] tuner 0=enabled
+ * tuner is behind ZL10353 I2C-gate
+ *
+ * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
+ * PCB: 508TC (rev0.6)
+ * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4
+ * IOA[7] TS 1=enabled
+ * IOE[4] TDA18212 1=enabled
+ * DVB-C:
+ * IOD[6] ZL10353 0=disabled
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] IF 1=enabled
+ * DVB-T:
+ * IOD[5] TDA10023 0=disabled
+ * IOD[6] ZL10353 1=enabled
+ * IOE[0] IF 0=enabled
+ *
+ * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
+ * PCB: 508S2 (rev0.7)
+ * parts: DNBU10512IST(STV0903, STV6110), ISL6423
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] STV0903 1=enabled
+ *
+ */
+
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
        struct anysee_state *state = adap->dev->priv;
        u8 hw_info[3];
-       u8 io_d; /* IO port D */
+       u8 tmp;
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = anysee_tda18212_config.i2c_address,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = "\x00",
+               }, {
+                       .addr = anysee_tda18212_config.i2c_address,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = &tmp,
+               }
+       };
 
-       /* check which hardware we have
-          We must do this call two times to get reliable values (hw bug). */
+       /* Check which hardware we have.
+        * We must do this call two times to get reliable values (hw bug).
+        */
        ret = anysee_get_hw_info(adap->dev, hw_info);
        if (ret)
-               return ret;
+               goto error;
+
        ret = anysee_get_hw_info(adap->dev, hw_info);
        if (ret)
-               return ret;
+               goto error;
 
        /* Meaning of these info bytes are guessed. */
-       info("firmware version:%d.%d.%d hardware id:%d",
-               0, hw_info[1], hw_info[2], hw_info[0]);
+       info("firmware version:%d.%d hardware id:%d",
+               hw_info[1], hw_info[2], hw_info[0]);
 
-       ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
-       if (ret)
-               return ret;
-       deb_info("%s: IO port D:%02x\n", __func__, io_d);
-
-       /* Select demod using trial and error method. */
-
-       /* Try to attach demodulator in following order:
-             model      demod     hw  firmware
-          1. E30        MT352     02  0.2.1
-          2. E30        ZL10353   02  0.2.1
-          3. E30 Combo  ZL10353   0f  0.1.2    DVB-T/C combo
-          4. E30 Plus   ZL10353   06  0.1.0
-          5. E30C Plus  TDA10023  0a  0.1.0    rev 0.2
-             E30C Plus  TDA10023  0f  0.1.2    rev 0.4
-             E30 Combo  TDA10023  0f  0.1.2    DVB-T/C combo
-       */
-
-       /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
-       adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe != NULL) {
-               state->tuner = DVB_PLL_THOMSON_DTT7579;
-               return 0;
-       }
+       state->hw = hw_info[0];
 
-       /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
-       adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe != NULL) {
-               state->tuner = DVB_PLL_THOMSON_DTT7579;
-               return 0;
-       }
+       switch (state->hw) {
+       case ANYSEE_HW_02: /* 2 */
+               /* E30 */
+
+               /* attach demod */
+               adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+                       &adap->dev->i2c_adap);
+               if (adap->fe)
+                       break;
+
+               /* attach demod */
+               adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                       &adap->dev->i2c_adap);
+
+               break;
+       case ANYSEE_HW_507CD: /* 6 */
+               /* E30 Plus */
 
-       /* for E30 Combo Plus DVB-T demodulator */
-       if (dvb_usb_anysee_delsys) {
-               ret = anysee_write_reg(adap->dev, 0xb0, 0x01);
+               /* enable DVB-T demod on IOD[0] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
                if (ret)
-                       return ret;
+                       goto error;
+
+               /* enable transport stream on IOA[7] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80);
+               if (ret)
+                       goto error;
 
-               /* Zarlink ZL10353 DVB-T demod */
+               /* attach demod */
                adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-                                     &adap->dev->i2c_adap);
-               if (adap->fe != NULL) {
-                       state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
-                       return 0;
+                       &adap->dev->i2c_adap);
+
+               break;
+       case ANYSEE_HW_507DC: /* 10 */
+               /* E30 C Plus */
+
+               /* enable DVB-C demod on IOD[0] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+               if (ret)
+                       goto error;
+
+               /* attach demod */
+               adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
+                       &adap->dev->i2c_adap, 0x48);
+
+               break;
+       case ANYSEE_HW_507SI: /* 11 */
+               /* E30 S2 Plus */
+
+               /* enable DVB-S/S2 demod on IOD[0] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+               if (ret)
+                       goto error;
+
+               /* attach demod */
+               adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+                       &adap->dev->i2c_adap);
+
+               break;
+       case ANYSEE_HW_507FA: /* 15 */
+               /* E30 Combo Plus */
+               /* E30 C Plus */
+
+               /* enable tuner on IOE[4] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+               if (ret)
+                       goto error;
+
+               /* probe TDA18212 */
+               tmp = 0;
+               ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2);
+               if (ret == 2 && tmp == 0xc7)
+                       deb_info("%s: TDA18212 found\n", __func__);
+               else
+                       tmp = 0;
+
+               /* disable tuner on IOE[4] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
+               if (ret)
+                       goto error;
+
+               if (dvb_usb_anysee_delsys) {
+                       /* disable DVB-C demod on IOD[5] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+                               0x20);
+                       if (ret)
+                               goto error;
+
+                       /* enable DVB-T demod on IOD[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+
+                       /* attach demod */
+                       if (tmp == 0xc7) {
+                               /* TDA18212 config */
+                               adap->fe = dvb_attach(zl10353_attach,
+                                       &anysee_zl10353_tda18212_config2,
+                                       &adap->dev->i2c_adap);
+                       } else {
+                               /* PLL config */
+                               adap->fe = dvb_attach(zl10353_attach,
+                                       &anysee_zl10353_config,
+                                       &adap->dev->i2c_adap);
+                       }
+               } else {
+                       /* disable DVB-T demod on IOD[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+
+                       /* enable DVB-C demod on IOD[5] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+                               0x20);
+                       if (ret)
+                               goto error;
+
+                       /* attach demod */
+                       if (tmp == 0xc7) {
+                               /* TDA18212 config */
+                               adap->fe = dvb_attach(tda10023_attach,
+                                       &anysee_tda10023_tda18212_config,
+                                       &adap->dev->i2c_adap, 0x48);
+                       } else {
+                               /* PLL config */
+                               adap->fe = dvb_attach(tda10023_attach,
+                                       &anysee_tda10023_config,
+                                       &adap->dev->i2c_adap, 0x48);
+                       }
                }
-       }
 
-       /* connect demod on IO port D for TDA10023 & ZL10353 */
-       ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
-       if (ret)
-               return ret;
+               break;
+       case ANYSEE_HW_508TC: /* 18 */
+               /* E7 TC */
 
-       /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
-       adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe != NULL) {
-               state->tuner = DVB_PLL_THOMSON_DTT7579;
-               return 0;
-       }
+               /* enable transport stream on IOA[7] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+               if (ret)
+                       goto error;
+
+               if (dvb_usb_anysee_delsys) {
+                       /* disable DVB-C demod on IOD[5] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+                               0x20);
+                       if (ret)
+                               goto error;
+
+                       /* enable DVB-T demod on IOD[6] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+                               0x40);
+                       if (ret)
+                               goto error;
+
+                       /* enable IF route on IOE[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+
+                       /* attach demod */
+                       adap->fe = dvb_attach(zl10353_attach,
+                               &anysee_zl10353_tda18212_config,
+                               &adap->dev->i2c_adap);
+               } else {
+                       /* disable DVB-T demod on IOD[6] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+                               0x40);
+                       if (ret)
+                               goto error;
+
+                       /* enable DVB-C demod on IOD[5] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+                               0x20);
+                       if (ret)
+                               goto error;
+
+                       /* enable IF route on IOE[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+
+                       /* attach demod */
+                       adap->fe = dvb_attach(tda10023_attach,
+                               &anysee_tda10023_tda18212_config,
+                               &adap->dev->i2c_adap, 0x48);
+               }
 
-       /* IO port E - E30C rev 0.4 board requires this */
-       ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
-       if (ret)
-               return ret;
+               break;
+       case ANYSEE_HW_508S2: /* 19 */
+               /* E7 S2 */
 
-       /* Philips TDA10023 DVB-C demod */
-       adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
-                             &adap->dev->i2c_adap, 0x48);
-       if (adap->fe != NULL) {
-               state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
-               return 0;
-       }
+               /* enable transport stream on IOA[7] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+               if (ret)
+                       goto error;
 
-       /* return IO port D to init value for safe */
-       ret = anysee_write_reg(adap->dev, 0xb0, io_d);
-       if (ret)
-               return ret;
+               /* enable DVB-S/S2 demod on IOE[5] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
+               if (ret)
+                       goto error;
+
+               /* attach demod */
+               adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+                       &adap->dev->i2c_adap, 0);
 
-       err("Unknown Anysee version: %02x %02x %02x. "\
-           "Please report the <linux-dvb@linuxtv.org>.",
-           hw_info[0], hw_info[1], hw_info[2]);
+               break;
+       }
 
-       return -ENODEV;
+       if (!adap->fe) {
+               /* we have no frontend :-( */
+               ret = -ENODEV;
+               err("Unsupported Anysee version. " \
+                       "Please report the <linux-media@vger.kernel.org>.");
+       }
+error:
+       return ret;
 }
 
 static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 {
        struct anysee_state *state = adap->dev->priv;
+       struct dvb_frontend *fe;
+       int ret;
        deb_info("%s:\n", __func__);
 
-       switch (state->tuner) {
-       case DVB_PLL_THOMSON_DTT7579:
-               /* Thomson dtt7579 (not sure) PLL inside of:
-                  Samsung DNOS404ZH102A NIM
-                  Samsung DNOS404ZH103A NIM */
-               dvb_attach(dvb_pll_attach, adap->fe, 0x61,
-                          NULL, DVB_PLL_THOMSON_DTT7579);
+       switch (state->hw) {
+       case ANYSEE_HW_02: /* 2 */
+               /* E30 */
+
+               /* attach tuner */
+               fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+                       NULL, DVB_PLL_THOMSON_DTT7579);
+
+               break;
+       case ANYSEE_HW_507CD: /* 6 */
+               /* E30 Plus */
+
+               /* attach tuner */
+               fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+                       &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
+
+               break;
+       case ANYSEE_HW_507DC: /* 10 */
+               /* E30 C Plus */
+
+               /* attach tuner */
+               fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+                       &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+
+               break;
+       case ANYSEE_HW_507SI: /* 11 */
+               /* E30 S2 Plus */
+
+               /* attach LNB controller */
+               fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
+                       &anysee_isl6423_config);
+
+               break;
+       case ANYSEE_HW_507FA: /* 15 */
+               /* E30 Combo Plus */
+               /* E30 C Plus */
+
+               if (dvb_usb_anysee_delsys) {
+                       /* enable DVB-T tuner on IOE[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+               } else {
+                       /* enable DVB-C tuner on IOE[0] */
+                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+                               0x01);
+                       if (ret)
+                               goto error;
+               }
+
+               /* Try first attach TDA18212 silicon tuner on IOE[4], if that
+                * fails attach old simple PLL. */
+
+               /* enable tuner on IOE[4] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+               if (ret)
+                       goto error;
+
+               /* attach tuner */
+               fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
+                       &anysee_tda18212_config);
+               if (fe)
+                       break;
+
+               /* disable tuner on IOE[4] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
+               if (ret)
+                       goto error;
+
+               /* attach tuner */
+               fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+                       &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+
                break;
-       case DVB_PLL_SAMSUNG_DTOS403IH102A:
-               /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
-               dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
-                          &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+       case ANYSEE_HW_508TC: /* 18 */
+               /* E7 TC */
+
+               /* enable tuner on IOE[4] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+               if (ret)
+                       goto error;
+
+               /* attach tuner */
+               fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
+                       &anysee_tda18212_config);
+
                break;
+       case ANYSEE_HW_508S2: /* 19 */
+               /* E7 S2 */
+
+               /* attach tuner */
+               fe = dvb_attach(stv6110_attach, adap->fe,
+                       &anysee_stv6110_config, &adap->dev->i2c_adap);
+
+               if (fe) {
+                       /* attach LNB controller */
+                       fe = dvb_attach(isl6423_attach, adap->fe,
+                               &adap->dev->i2c_adap, &anysee_isl6423_config);
+               }
+
+               break;
+       default:
+               fe = NULL;
        }
 
-       return 0;
+       if (fe)
+               ret = 0;
+       else
+               ret = -ENODEV;
+
+error:
+       return ret;
 }
 
 static int anysee_rc_query(struct dvb_usb_device *d)
index 7ca01ff..a7673aa 100644 (file)
@@ -57,10 +57,29 @@ enum cmd {
 };
 
 struct anysee_state {
-       u8 tuner;
+       u8 hw; /* PCB ID */
        u8 seq;
 };
 
+#define ANYSEE_HW_02     2 /* E30 */
+#define ANYSEE_HW_507CD  6 /* E30 Plus */
+#define ANYSEE_HW_507DC 10 /* E30 C Plus */
+#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
+#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
+#define ANYSEE_HW_508TC 18 /* E7 TC */
+#define ANYSEE_HW_508S2 19 /* E7 S2 */
+
+#define REG_IOA       0x80 /* Port A (bit addressable) */
+#define REG_IOB       0x90 /* Port B (bit addressable) */
+#define REG_IOC       0xa0 /* Port C (bit addressable) */
+#define REG_IOD       0xb0 /* Port D (bit addressable) */
+#define REG_IOE       0xb1 /* Port E (NOT bit addressable) */
+#define REG_OEA       0xb2 /* Port A Output Enable */
+#define REG_OEB       0xb3 /* Port B Output Enable */
+#define REG_OEC       0xb4 /* Port C Output Enable */
+#define REG_OED       0xb5 /* Port D Output Enable */
+#define REG_OEE       0xb6 /* Port E Output Enable */
+
 #endif
 
 /***************************************************************************
@@ -136,7 +155,7 @@ General reply packet(s) are always used if not own reply defined.
 ----------------------------------------------------------------------------
 |    04 | 0x00
 ----------------------------------------------------------------------------
-|    05 | 0x01
+|    05 | data length
 ----------------------------------------------------------------------------
 | 06-59 | don't care
 ----------------------------------------------------------------------------
index eb34cc3..2351077 100644 (file)
@@ -33,8 +33,16 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
 {
        int ret;
        u16 index;
-       u8 usb_buf[6]; /* enough for all known requests,
-                         read returns 5 and write 6 bytes */
+       u8 *usb_buf;
+
+       /*
+        * allocate enough for all known requests,
+        * read returns 5 and write 6 bytes
+        */
+       usb_buf = kmalloc(6, GFP_KERNEL);
+       if (!usb_buf)
+               return -ENOMEM;
+
        switch (wlen) {
        case 1:
                index = wbuf[0] << 8;
@@ -45,14 +53,15 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
                break;
        default:
                warn("wlen = %x, aborting.", wlen);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto error;
        }
 
        ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
                              USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
-                             usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
+                             usb_buf, 6, AU6610_USB_TIMEOUT);
        if (ret < 0)
-               return ret;
+               goto error;
 
        switch (operation) {
        case AU6610_REQ_I2C_READ:
@@ -60,7 +69,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
                /* requested value is always 5th byte in buffer */
                rbuf[0] = usb_buf[4];
        }
-
+error:
+       kfree(usb_buf);
        return ret;
 }
 
index 3df2045..6d1a304 100644 (file)
@@ -39,7 +39,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
        u8 requesttype;
        u16 value;
        u16 index;
-       u8 buf[req->data_len];
+       u8 *buf;
 
        request = req->cmd;
        value = req->value;
@@ -62,6 +62,12 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
                goto error;
        }
 
+       buf = kmalloc(req->data_len, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
                /* write */
                memcpy(buf, req->data, req->data_len);
@@ -74,7 +80,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
        msleep(1); /* avoid I2C errors */
 
        ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
-                               buf, sizeof(buf), CE6230_USB_TIMEOUT);
+                               buf, req->data_len, CE6230_USB_TIMEOUT);
 
        ce6230_debug_dump(request, requesttype, value, index, buf,
                req->data_len, deb_xfer);
@@ -88,6 +94,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
        if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
                memcpy(req->data, buf, req->data_len);
 
+       kfree(buf);
 error:
        return ret;
 }
index b2a87f2..9bd6d51 100644 (file)
@@ -46,8 +46,9 @@ struct dib0700_state {
        u8 is_dib7000pc;
        u8 fw_use_new_i2c_api;
        u8 disable_streaming_master_mode;
-    u32 fw_version;
-    u32 nb_packet_buffer_size;
+       u32 fw_version;
+       u32 nb_packet_buffer_size;
+       u8 buf[255];
 };
 
 extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
index b79af68..5eb91b4 100644 (file)
@@ -27,19 +27,25 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
                        u32 *romversion, u32 *ramversion, u32 *fwtype)
 {
-       u8 b[16];
-       int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+       struct dib0700_state *st = d->priv;
+       int ret;
+
+       ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
                                  REQUEST_GET_VERSION,
                                  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-                                 b, sizeof(b), USB_CTRL_GET_TIMEOUT);
+                                 st->buf, 16, USB_CTRL_GET_TIMEOUT);
        if (hwversion != NULL)
-               *hwversion  = (b[0] << 24)  | (b[1] << 16)  | (b[2] << 8)  | b[3];
+               *hwversion  = (st->buf[0] << 24)  | (st->buf[1] << 16)  |
+                       (st->buf[2] << 8)  | st->buf[3];
        if (romversion != NULL)
-               *romversion = (b[4] << 24)  | (b[5] << 16)  | (b[6] << 8)  | b[7];
+               *romversion = (st->buf[4] << 24)  | (st->buf[5] << 16)  |
+                       (st->buf[6] << 8)  | st->buf[7];
        if (ramversion != NULL)
-               *ramversion = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
+               *ramversion = (st->buf[8] << 24)  | (st->buf[9] << 16)  |
+                       (st->buf[10] << 8) | st->buf[11];
        if (fwtype != NULL)
-               *fwtype     = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+               *fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
+                       (st->buf[14] << 8) | st->buf[15];
        return ret;
 }
 
@@ -101,24 +107,31 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
 
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
-       u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
-       return dib0700_ctrl_wr(d, buf, sizeof(buf));
+       struct dib0700_state *st = d->priv;
+       s16 ret;
+
+       st->buf[0] = REQUEST_SET_GPIO;
+       st->buf[1] = gpio;
+       st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);
+
+       ret = dib0700_ctrl_wr(d, st->buf, 3);
+
+       return ret;
 }
 
 static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
 {
        struct dib0700_state *st = d->priv;
-       u8 b[3];
        int ret;
 
        if (st->fw_version >= 0x10201) {
-               b[0] = REQUEST_SET_USB_XFER_LEN;
-               b[1] = (nb_ts_packets >> 8) & 0xff;
-               b[2] = nb_ts_packets & 0xff;
+               st->buf[0] = REQUEST_SET_USB_XFER_LEN;
+               st->buf[1] = (nb_ts_packets >> 8) & 0xff;
+               st->buf[2] = nb_ts_packets & 0xff;
 
                deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
 
-               ret = dib0700_ctrl_wr(d, b, sizeof(b));
+               ret = dib0700_ctrl_wr(d, st->buf, 3);
        } else {
                deb_info("this firmware does not allow to change the USB xfer len\n");
                ret = -EIO;
@@ -137,11 +150,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
           properly support i2c read calls not preceded by a write */
 
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       struct dib0700_state *st = d->priv;
        uint8_t bus_mode = 1;  /* 0=eeprom bus, 1=frontend bus */
        uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
        uint8_t en_start = 0;
        uint8_t en_stop = 0;
-       uint8_t buf[255]; /* TBV: malloc ? */
        int result, i;
 
        /* Ensure nobody else hits the i2c bus while we're sending our
@@ -195,24 +208,24 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
 
                } else {
                        /* Write request */
-                       buf[0] = REQUEST_NEW_I2C_WRITE;
-                       buf[1] = msg[i].addr << 1;
-                       buf[2] = (en_start << 7) | (en_stop << 6) |
+                       st->buf[0] = REQUEST_NEW_I2C_WRITE;
+                       st->buf[1] = msg[i].addr << 1;
+                       st->buf[2] = (en_start << 7) | (en_stop << 6) |
                                (msg[i].len & 0x3F);
                        /* I2C ctrl + FE bus; */
-                       buf[3] = ((gen_mode << 6) & 0xC0) |
+                       st->buf[3] = ((gen_mode << 6) & 0xC0) |
                                 ((bus_mode << 4) & 0x30);
                        /* The Actual i2c payload */
-                       memcpy(&buf[4], msg[i].buf, msg[i].len);
+                       memcpy(&st->buf[4], msg[i].buf, msg[i].len);
 
                        deb_data(">>> ");
-                       debug_dump(buf, msg[i].len + 4, deb_data);
+                       debug_dump(st->buf, msg[i].len + 4, deb_data);
 
                        result = usb_control_msg(d->udev,
                                                 usb_sndctrlpipe(d->udev, 0),
                                                 REQUEST_NEW_I2C_WRITE,
                                                 USB_TYPE_VENDOR | USB_DIR_OUT,
-                                                0, 0, buf, msg[i].len + 4,
+                                                0, 0, st->buf, msg[i].len + 4,
                                                 USB_CTRL_GET_TIMEOUT);
                        if (result < 0) {
                                deb_info("i2c write error (status = %d)\n", result);
@@ -231,27 +244,29 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
                                   struct i2c_msg *msg, int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       struct dib0700_state *st = d->priv;
        int i,len;
-       u8 buf[255];
 
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
 
        for (i = 0; i < num; i++) {
                /* fill in the address */
-               buf[1] = msg[i].addr << 1;
+               st->buf[1] = msg[i].addr << 1;
                /* fill the buffer */
-               memcpy(&buf[2], msg[i].buf, msg[i].len);
+               memcpy(&st->buf[2], msg[i].buf, msg[i].len);
 
                /* write/read request */
                if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-                       buf[0] = REQUEST_I2C_READ;
-                       buf[1] |= 1;
+                       st->buf[0] = REQUEST_I2C_READ;
+                       st->buf[1] |= 1;
 
                        /* special thing in the current firmware: when length is zero the read-failed */
-                       if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
+                       len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
+                                       msg[i+1].buf, msg[i+1].len);
+                       if (len <= 0) {
                                deb_info("I2C read failed on address 0x%02x\n",
-                                        msg[i].addr);
+                                               msg[i].addr);
                                break;
                        }
 
@@ -259,13 +274,13 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
 
                        i++;
                } else {
-                       buf[0] = REQUEST_I2C_WRITE;
-                       if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0)
+                       st->buf[0] = REQUEST_I2C_WRITE;
+                       if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0)
                                break;
                }
        }
-
        mutex_unlock(&d->i2c_mutex);
+
        return i;
 }
 
@@ -297,15 +312,23 @@ struct i2c_algorithm dib0700_i2c_algo = {
 int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
                        struct dvb_usb_device_description **desc, int *cold)
 {
-       u8 b[16];
-       s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
+       s16 ret;
+       u8 *b;
+
+       b = kmalloc(16, GFP_KERNEL);
+       if (!b)
+               return  -ENOMEM;
+
+
+       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
 
        deb_info("FW GET_VERSION length: %d\n",ret);
 
        *cold = ret <= 0;
-
        deb_info("cold: %d\n", *cold);
+
+       kfree(b);
        return 0;
 }
 
@@ -313,43 +336,50 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
        u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
        u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
 {
-       u8 b[10];
-       b[0] = REQUEST_SET_CLOCK;
-       b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
-       b[2] = (pll_prediv >> 8)  & 0xff; // MSB
-       b[3] =  pll_prediv        & 0xff; // LSB
-       b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
-       b[5] =  pll_loopdiv       & 0xff; // LSB
-       b[6] = (free_div >> 8)    & 0xff; // MSB
-       b[7] =  free_div          & 0xff; // LSB
-       b[8] = (dsuScaler >> 8)   & 0xff; // MSB
-       b[9] =  dsuScaler         & 0xff; // LSB
-
-       return dib0700_ctrl_wr(d, b, 10);
+       struct dib0700_state *st = d->priv;
+       s16 ret;
+
+       st->buf[0] = REQUEST_SET_CLOCK;
+       st->buf[1] = (en_pll << 7) | (pll_src << 6) |
+               (pll_range << 5) | (clock_gpio3 << 4);
+       st->buf[2] = (pll_prediv >> 8)  & 0xff; /* MSB */
+       st->buf[3] =  pll_prediv        & 0xff; /* LSB */
+       st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */
+       st->buf[5] =  pll_loopdiv       & 0xff; /* LSB */
+       st->buf[6] = (free_div >> 8)    & 0xff; /* MSB */
+       st->buf[7] =  free_div          & 0xff; /* LSB */
+       st->buf[8] = (dsuScaler >> 8)   & 0xff; /* MSB */
+       st->buf[9] =  dsuScaler         & 0xff; /* LSB */
+
+       ret = dib0700_ctrl_wr(d, st->buf, 10);
+
+       return ret;
 }
 
 int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
 {
+       struct dib0700_state *st = d->priv;
        u16 divider;
-       u8 b[8];
 
        if (scl_kHz == 0)
                return -EINVAL;
 
-       b[0] = REQUEST_SET_I2C_PARAM;
+       st->buf[0] = REQUEST_SET_I2C_PARAM;
        divider = (u16) (30000 / scl_kHz);
-       b[2] = (u8) (divider >> 8);
-       b[3] = (u8) (divider & 0xff);
+       st->buf[1] = 0;
+       st->buf[2] = (u8) (divider >> 8);
+       st->buf[3] = (u8) (divider & 0xff);
        divider = (u16) (72000 / scl_kHz);
-       b[4] = (u8) (divider >> 8);
-       b[5] = (u8) (divider & 0xff);
+       st->buf[4] = (u8) (divider >> 8);
+       st->buf[5] = (u8) (divider & 0xff);
        divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
-       b[6] = (u8) (divider >> 8);
-       b[7] = (u8) (divider & 0xff);
+       st->buf[6] = (u8) (divider >> 8);
+       st->buf[7] = (u8) (divider & 0xff);
 
        deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
-               (b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz);
-       return dib0700_ctrl_wr(d, b, 8);
+               (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
+               st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
+       return dib0700_ctrl_wr(d, st->buf, 8);
 }
 
 
@@ -364,32 +394,45 @@ int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
 
 static int dib0700_jumpram(struct usb_device *udev, u32 address)
 {
-       int ret, actlen;
-       u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
-               (address >> 24) & 0xff,
-               (address >> 16) & 0xff,
-               (address >> 8)  & 0xff,
-                address        & 0xff };
+       int ret = 0, actlen;
+       u8 *buf;
+
+       buf = kmalloc(8, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       buf[0] = REQUEST_JUMPRAM;
+       buf[1] = 0;
+       buf[2] = 0;
+       buf[3] = 0;
+       buf[4] = (address >> 24) & 0xff;
+       buf[5] = (address >> 16) & 0xff;
+       buf[6] = (address >> 8)  & 0xff;
+       buf[7] =  address        & 0xff;
 
        if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
                deb_fw("jumpram to 0x%x failed\n",address);
-               return ret;
+               goto out;
        }
        if (actlen != 8) {
                deb_fw("jumpram to 0x%x failed\n",address);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
-       return 0;
+out:
+       kfree(buf);
+       return ret;
 }
 
 int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
 {
        struct hexline hx;
        int pos = 0, ret, act_len, i, adap_num;
-       u8 b[16];
+       u8 *buf;
        u32 fw_version;
 
-       u8 buf[260];
+       buf = kmalloc(260, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
                deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
@@ -411,7 +454,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 
                if (ret < 0) {
                        err("firmware download failed at %d with %d",pos,ret);
-                       return ret;
+                       goto out;
                }
        }
 
@@ -432,8 +475,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
        usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                                  REQUEST_GET_VERSION,
                                  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-                                 b, sizeof(b), USB_CTRL_GET_TIMEOUT);
-       fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+                                 buf, 16, USB_CTRL_GET_TIMEOUT);
+       fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
 
        /* set the buffer size - DVB-USB is allocating URB buffers
         * only after the firwmare download was successful */
@@ -451,14 +494,14 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
                        }
                }
        }
-
+out:
+       kfree(buf);
        return ret;
 }
 
 int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
        struct dib0700_state *st = adap->dev->priv;
-       u8 b[4];
        int ret;
 
        if ((onoff != 0) && (st->fw_version >= 0x10201)) {
@@ -472,15 +515,17 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
                }
        }
 
-       b[0] = REQUEST_ENABLE_VIDEO;
-       b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
+       st->buf[0] = REQUEST_ENABLE_VIDEO;
+       /* this bit gives a kind of command,
+        * rather than enabling something or not */
+       st->buf[1] = (onoff << 4) | 0x00;
 
        if (st->disable_streaming_master_mode == 1)
-               b[2] = 0x00;
+               st->buf[2] = 0x00;
        else
-               b[2] = 0x01 << 4; /* Master mode */
+               st->buf[2] = 0x01 << 4; /* Master mode */
 
-       b[3] = 0x00;
+       st->buf[3] = 0x00;
 
        deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
 
@@ -499,20 +544,23 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
                        st->channel_state |=    1 << (3-adap->stream.props.endpoint);
        }
 
-       b[2] |= st->channel_state;
+       st->buf[2] |= st->channel_state;
 
-       deb_info("data for streaming: %x %x\n", b[1], b[2]);
+       deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
 
-       return dib0700_ctrl_wr(adap->dev, b, 4);
+       return dib0700_ctrl_wr(adap->dev, st->buf, 4);
 }
 
 int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
        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;
 
+       st->buf[0] = REQUEST_SET_RC;
+       st->buf[1] = 0;
+       st->buf[2] = 0;
+
        /* Set the IR mode */
        if (rc_type == RC_TYPE_RC5)
                new_proto = 1;
@@ -526,9 +574,9 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
        } else
                return -EINVAL;
 
-       rc_setup[1] = new_proto;
+       st->buf[1] = new_proto;
 
-       ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
+       ret = dib0700_ctrl_wr(d, st->buf, 3);
        if (ret < 0) {
                err("ir protocol setup failed");
                return ret;
@@ -561,7 +609,6 @@ struct dib0700_rc_response {
 static void dib0700_rc_urb_completion(struct urb *purb)
 {
        struct dvb_usb_device *d = purb->context;
-       struct dib0700_state *st;
        struct dib0700_rc_response *poll_reply;
        u32 uninitialized_var(keycode);
        u8 toggle;
@@ -576,7 +623,6 @@ static void dib0700_rc_urb_completion(struct urb *purb)
                return;
        }
 
-       st = d->priv;
        poll_reply = purb->transfer_buffer;
 
        if (purb->status < 0) {
index 65214af..c519ad5 100644 (file)
@@ -2439,7 +2439,6 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
 
        dib0700_set_i2c_speed(adap->dev, 340);
        adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
-
        if (adap->fe == NULL)
                return -ENODEV;
 
@@ -2802,6 +2801,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM7090) },
        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090PVR) },
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
+/* 75 */{ USB_DEVICE(USB_VID_MEDION,    USB_PID_CREATIX_CTX1921) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -3411,7 +3411,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 3,
+               .num_device_descs = 4,
                .devices = {
                        {   "DiBcom STK7770P reference design",
                                { &dib0700_usb_id_table[59], NULL },
@@ -3427,6 +3427,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[74], NULL },
                                { NULL },
                        },
+                       {   "Medion CTX1921 DVB-T USB",
+                               { &dib0700_usb_id_table[75], NULL },
+                               { NULL },
+                       },
                },
 
                .rc.core = {
index 956f7ae..4c2a689 100644 (file)
@@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = {
 
        { 0x8008, KEY_DVD },
        { 0x8009, KEY_AUDIO },
-       { 0x800a, KEY_MEDIA },      /* Pictures */
+       { 0x800a, KEY_IMAGES },      /* Pictures */
        { 0x800b, KEY_VIDEO },
 
        { 0x800c, KEY_BACK },
index df1ec3e..b3cb626 100644 (file)
@@ -12,7 +12,7 @@
 static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
        struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
-       int newfeedcount,ret;
+       int newfeedcount, ret;
 
        if (adap == NULL)
                return -ENODEV;
@@ -24,9 +24,13 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
                deb_ts("stop feeding\n");
                usb_urb_kill(&adap->stream);
 
-               if (adap->props.streaming_ctrl != NULL)
-                       if ((ret = adap->props.streaming_ctrl(adap,0)))
+               if (adap->props.streaming_ctrl != NULL) {
+                       ret = adap->props.streaming_ctrl(adap, 0);
+                       if (ret < 0) {
                                err("error while stopping stream.");
+                               return ret;
+                       }
+               }
        }
 
        adap->feedcount = newfeedcount;
@@ -49,17 +53,24 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 
                deb_ts("controlling pid parser\n");
                if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-                       adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-                       adap->props.pid_filter_ctrl != NULL)
-                       if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0)
+                       adap->props.caps &
+                       DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
+                       adap->props.pid_filter_ctrl != NULL) {
+                       ret = adap->props.pid_filter_ctrl(adap,
+                               adap->pid_filtering);
+                       if (ret < 0) {
                                err("could not handle pid_parser");
-
+                               return ret;
+                       }
+               }
                deb_ts("start feeding\n");
-               if (adap->props.streaming_ctrl != NULL)
-                       if (adap->props.streaming_ctrl(adap,1)) {
+               if (adap->props.streaming_ctrl != NULL) {
+                       ret = adap->props.streaming_ctrl(adap, 1);
+                       if (ret < 0) {
                                err("error while enabling fifo.");
-                               return -ENODEV;
+                               return ret;
                        }
+               }
 
        }
        return 0;
index 3a8b744..21b1549 100644 (file)
@@ -91,6 +91,7 @@
 #define USB_PID_COMPRO_VIDEOMATE_U500_PC               0x1e80
 #define USB_PID_CONCEPTRONIC_CTVDIGRCU                 0xe397
 #define USB_PID_CONEXANT_D680_DMB                      0x86d6
+#define USB_PID_CREATIX_CTX1921                                0x1921
 #define USB_PID_DIBCOM_HOOK_DEFAULT                    0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM             0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD                    0x0bb8
index d312323..058b231 100644 (file)
@@ -121,12 +121,16 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
                        u16 index, u8 * data, u16 len, int flags)
 {
        int ret;
-       u8 u8buf[len];
-
+       u8 *u8buf;
        unsigned int pipe = (flags == DW210X_READ_MSG) ?
                                usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
        u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
 
+       u8buf = kmalloc(len, GFP_KERNEL);
+       if (!u8buf)
+               return -ENOMEM;
+
+
        if (flags == DW210X_WRITE_MSG)
                memcpy(u8buf, data, len);
        ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
@@ -134,6 +138,8 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
 
        if (flags == DW210X_READ_MSG)
                memcpy(data, u8buf, len);
+
+       kfree(u8buf);
        return ret;
 }
 
index 52f5d4f..1ba3e5d 100644 (file)
@@ -36,7 +36,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
        int ret;
        unsigned int pipe;
        u8 request, requesttype;
-       u8 buf[req->size];
+       u8 *buf;
+
+
 
        switch (req->cmd) {
        case DOWNLOAD_FIRMWARE:
@@ -72,6 +74,12 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
                goto error;
        }
 
+       buf = kmalloc(req->size, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
                /* write */
                memcpy(buf, req->data, req->size);
@@ -84,13 +92,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
        msleep(1); /* avoid I2C errors */
 
        ret = usb_control_msg(udev, pipe, request, requesttype, req->value,
-               req->index, buf, sizeof(buf), EC168_USB_TIMEOUT);
+               req->index, buf, req->size, EC168_USB_TIMEOUT);
 
        ec168_debug_dump(request, requesttype, req->value, req->index, buf,
                req->size, deb_xfer);
 
        if (ret < 0)
-               goto error;
+               goto err_dealloc;
        else
                ret = 0;
 
@@ -98,7 +106,11 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
        if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
                memcpy(req->data, buf, req->size);
 
+       kfree(buf);
        return ret;
+
+err_dealloc:
+       kfree(buf);
 error:
        deb_info("%s: failed:%d\n", __func__, ret);
        return ret;
index 14a65b4..76159ae 100644 (file)
@@ -142,17 +142,20 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter)
        return I2C_FUNC_I2C;
 }
 
-
 static int friio_ext_ctl(struct dvb_usb_adapter *adap,
                         u32 sat_color, int lnb_on)
 {
        int i;
        int ret;
        struct i2c_msg msg;
-       u8 buf[2];
+       u8 *buf;
        u32 mask;
        u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
 
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        msg.addr = 0x00;
        msg.flags = 0;
        msg.len = 2;
@@ -189,6 +192,7 @@ static int friio_ext_ctl(struct dvb_usb_adapter *adap,
        buf[1] |= FRIIO_CTL_CLK;
        ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
 
+       kfree(buf);
        return (ret == 70);
 }
 
@@ -219,11 +223,20 @@ static int friio_initialize(struct dvb_usb_device *d)
        int ret;
        int i;
        int retry = 0;
-       u8 rbuf[2];
-       u8 wbuf[3];
+       u8 *rbuf, *wbuf;
 
        deb_info("%s called.\n", __func__);
 
+       wbuf = kmalloc(3, GFP_KERNEL);
+       if (!wbuf)
+               return -ENOMEM;
+
+       rbuf = kmalloc(2, GFP_KERNEL);
+       if (!rbuf) {
+               kfree(wbuf);
+               return -ENOMEM;
+       }
+
        /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
        /* because the i2c device is not set up yet. */
        wbuf[0] = 0x11;
@@ -358,6 +371,8 @@ restart:
        return 0;
 
 error:
+       kfree(wbuf);
+       kfree(rbuf);
        deb_info("%s:ret == %d\n", __func__, ret);
        return -EIO;
 }
index f2db012..f36f471 100644 (file)
@@ -62,8 +62,6 @@
  *     LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
  * with other tuners. After a cold reset streaming will not start.
  *
- *     PID functions have been removed from this driver version due to
- * problems with different firmware and application versions.
  */
 #define DVB_USB_LOG_PREFIX "LME2510(C)"
 #include <linux/usb.h>
@@ -104,6 +102,10 @@ static int dvb_usb_lme2510_firmware;
 module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
 MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
 
+static int pid_filter;
+module_param_named(pid, pid_filter, int, 0644);
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
+
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -125,6 +127,7 @@ struct lme2510_state {
        u8 i2c_tuner_gate_r;
        u8 i2c_tuner_addr;
        u8 stream_on;
+       u8 pid_size;
        void *buffer;
        struct urb *lme_urb;
        void *usb_buffer;
@@ -167,14 +170,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
        }
        buff = st->usb_buffer;
 
-       /* the read/write capped at 512 */
-       memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
-
        ret = mutex_lock_interruptible(&d->usb_mutex);
 
        if (ret < 0)
                return -EAGAIN;
 
+       /* the read/write capped at 512 */
+       memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+
        ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
 
        ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
@@ -216,6 +219,37 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
        return 0;
 }
 
+static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
+{
+       struct lme2510_state *st = d->priv;
+       static u8 pid_buff[] = LME_ZERO_PID;
+       static u8 rbuf[1];
+       u8 pid_no = index * 2;
+       u8 pid_len = pid_no + 2;
+       int ret = 0;
+       deb_info(1, "PID Setting Pid %04x", pid_out);
+
+       if (st->pid_size == 0)
+               ret |= lme2510_stream_restart(d);
+
+       pid_buff[2] = pid_no;
+       pid_buff[3] = (u8)pid_out & 0xff;
+       pid_buff[4] = pid_no + 1;
+       pid_buff[5] = (u8)(pid_out >> 8);
+
+       if (pid_len > st->pid_size)
+               st->pid_size = pid_len;
+       pid_buff[7] = 0x80 + st->pid_size;
+
+       ret |= lme2510_usb_talk(d, pid_buff ,
+               sizeof(pid_buff) , rbuf, sizeof(rbuf));
+
+       if (st->stream_on)
+               ret |= lme2510_stream_restart(d);
+
+       return ret;
+}
+
 static void lme2510_int_response(struct urb *lme_urb)
 {
        struct dvb_usb_adapter *adap = lme_urb->context;
@@ -326,16 +360,68 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
        return 0;
 }
 
+static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       struct lme2510_state *st = adap->dev->priv;
+       static u8 clear_pid_reg[] = LME_CLEAR_PID;
+       static u8 rbuf[1];
+       int ret;
+
+       deb_info(1, "PID Clearing Filter");
+
+       ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+       if (ret < 0)
+               return -EAGAIN;
+
+       if (!onoff)
+               ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
+                       sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
+
+       st->pid_size = 0;
+
+       mutex_unlock(&adap->dev->i2c_mutex);
+
+       return 0;
+}
+
+static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+       int onoff)
+{
+       int ret = 0;
+
+       deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
+               pid, index, onoff);
+
+       if (onoff)
+               if (!pid_filter) {
+                       ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+                       if (ret < 0)
+                               return -EAGAIN;
+                       ret |= lme2510_enable_pid(adap->dev, index, pid);
+                       mutex_unlock(&adap->dev->i2c_mutex);
+       }
+
+
+       return ret;
+}
+
+
 static int lme2510_return_status(struct usb_device *dev)
 {
        int ret = 0;
-       u8 data[10] = {0};
+       u8 *data;
+
+       data = kzalloc(10, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
        ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                        0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
        info("Firmware Status: %x (%x)", ret , data[2]);
 
-       return (ret < 0) ? -ENODEV : data[2];
+       ret = (ret < 0) ? -ENODEV : data[2];
+       kfree(data);
+       return ret;
 }
 
 static int lme2510_msg(struct dvb_usb_device *d,
@@ -591,9 +677,10 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        else {
                deb_info(1, "STM Steam Off");
                /* mutex is here only to avoid collision with I2C */
-               ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+               if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+                       return -EAGAIN;
 
-               ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
+               ret = lme2510_usb_talk(adap->dev, clear_reg_3,
                                sizeof(clear_reg_3), rbuf, rlen);
                st->stream_on = 0;
                st->i2c_talk_onoff = 1;
@@ -655,7 +742,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
                                        const struct firmware *fw)
 {
        int ret = 0;
-       u8 data[512] = {0};
+       u8 *data;
        u16 j, wlen, len_in, start, end;
        u8 packet_size, dlen, i;
        u8 *fw_data;
@@ -663,6 +750,11 @@ static int lme2510_download_firmware(struct usb_device *dev,
        packet_size = 0x31;
        len_in = 1;
 
+       data = kzalloc(512, GFP_KERNEL);
+       if (!data) {
+               info("FRM Could not start Firmware Download (Buffer allocation failed)");
+               return -ENOMEM;
+       }
 
        info("FRM Starting Firmware Download");
 
@@ -678,15 +770,15 @@ static int lme2510_download_firmware(struct usb_device *dev,
                                data[0] = i | 0x80;
                                dlen = (u8)(end - j)-1;
                        }
-               data[1] = dlen;
-               memcpy(&data[2], fw_data, dlen+1);
-               wlen = (u8) dlen + 4;
-               data[wlen-1] = check_sum(fw_data, dlen+1);
-               deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
+                       data[1] = dlen;
+                       memcpy(&data[2], fw_data, dlen+1);
+                       wlen = (u8) dlen + 4;
+                       data[wlen-1] = check_sum(fw_data, dlen+1);
+                       deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
                                data[dlen+2], data[dlen+3]);
-               ret |= lme2510_bulk_write(dev, data,  wlen, 1);
-               ret |= lme2510_bulk_read(dev, data, len_in , 1);
-               ret |= (data[0] == 0x88) ? 0 : -1;
+                       ret |= lme2510_bulk_write(dev, data,  wlen, 1);
+                       ret |= lme2510_bulk_read(dev, data, len_in , 1);
+                       ret |= (data[0] == 0x88) ? 0 : -1;
                }
        }
 
@@ -706,7 +798,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
        else
                info("FRM Firmware Download Completed - Resetting Device");
 
-
+       kfree(data);
        return (ret < 0) ? -ENODEV : 0;
 }
 
@@ -747,7 +839,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
                        fw_lme = fw_s0194;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
                        if (ret == 0) {
-                               cold = 0;/*lme2510-s0194 cannot cold reset*/
+                               cold = 0;
                                break;
                        }
                        dvb_usb_lme2510_firmware = TUNER_LG;
@@ -769,8 +861,10 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
                case TUNER_S7395:
                        fw_lme = fw_c_s7395;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
-                       if (ret == 0)
+                       if (ret == 0) {
+                               cold = 0;
                                break;
+                       }
                        dvb_usb_lme2510_firmware = TUNER_LG;
                case TUNER_LG:
                        fw_lme = fw_c_lg;
@@ -796,14 +890,14 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
                ret = lme2510_download_firmware(udev, fw);
        }
 
+       release_firmware(fw);
+
        if (cold) {
                info("FRM Changing to %s firmware", fw_lme);
                lme_coldreset(udev);
                return -ENODEV;
        }
 
-       release_firmware(fw);
-
        return ret;
 }
 
@@ -1017,12 +1111,13 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
        static u8 rbuf[1];
        int ret, len = 3, rlen = 1;
 
-       ret = mutex_lock_interruptible(&d->i2c_mutex);
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
 
        if (onoff)
-               ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
+               ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
        else
-               ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
+               ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
 
        st->i2c_talk_onoff = 1;
 
@@ -1086,7 +1181,13 @@ static struct dvb_usb_device_properties lme2510_properties = {
        .num_adapters = 1,
        .adapter = {
                {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+                               DVB_USB_ADAP_NEED_PID_FILTERING|
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .streaming_ctrl   = lme2510_streaming_ctrl,
+                       .pid_filter_count = 15,
+                       .pid_filter = lme2510_pid_filter,
+                       .pid_filter_ctrl  = lme2510_pid_filter_ctrl,
                        .frontend_attach  = dm04_lme2510_frontend_attach,
                        .tuner_attach = dm04_lme2510_tuner,
                        /* parameter for the MPEG2-data transfer */
@@ -1122,7 +1223,13 @@ static struct dvb_usb_device_properties lme2510c_properties = {
        .num_adapters = 1,
        .adapter = {
                {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+                               DVB_USB_ADAP_NEED_PID_FILTERING|
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .streaming_ctrl   = lme2510_streaming_ctrl,
+                       .pid_filter_count = 15,
+                       .pid_filter = lme2510_pid_filter,
+                       .pid_filter_ctrl  = lme2510_pid_filter_ctrl,
                        .frontend_attach  = dm04_lme2510_frontend_attach,
                        .tuner_attach = dm04_lme2510_tuner,
                        /* parameter for the MPEG2-data transfer */
@@ -1151,7 +1258,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
        }
 };
 
-void *lme2510_exit_int(struct dvb_usb_device *d)
+static void *lme2510_exit_int(struct dvb_usb_device *d)
 {
        struct lme2510_state *st = d->priv;
        struct dvb_usb_adapter *adap = &d->adapter[0];
@@ -1178,7 +1285,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d)
        return buffer;
 }
 
-void lme2510_exit(struct usb_interface *intf)
+static void lme2510_exit(struct usb_interface *intf)
 {
        struct dvb_usb_device *d = usb_get_intfdata(intf);
        void *usb_buffer;
@@ -1220,5 +1327,5 @@ module_exit(lme2510_module_exit);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.80");
+MODULE_VERSION("1.86");
 MODULE_LICENSE("GPL");
index e6af16c..ab21e2e 100644 (file)
@@ -40,6 +40,7 @@
 */
 #define LME_ST_ON_W    {0x06, 0x00}
 #define LME_CLEAR_PID   {0x03, 0x02, 0x20, 0xa0}
+#define LME_ZERO_PID   {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c}
 
 /*  LNB Voltage
  *  07 XX XX
@@ -108,14 +109,14 @@ static u8 s7395_inittab[] = {
        0x3d, 0x30,
        0x40, 0x63,
        0x41, 0x04,
-       0x42, 0x60,
+       0x42, 0x20,
        0x43, 0x00,
        0x44, 0x00,
        0x45, 0x00,
        0x46, 0x00,
        0x47, 0x00,
        0x4a, 0x00,
-       0x50, 0x12,
+       0x50, 0x10,
        0x51, 0x36,
        0x52, 0x21,
        0x53, 0x94,
index da9dc91..9456792 100644 (file)
@@ -134,13 +134,17 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        struct m920x_state *m = d->priv;
        int i, ret = 0;
-       u8 rc_state[2];
+       u8 *rc_state;
+
+       rc_state = kmalloc(2, GFP_KERNEL);
+       if (!rc_state)
+               return -ENOMEM;
 
        if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
-               goto unlock;
+               goto out;
 
        if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
-               goto unlock;
+               goto out;
 
        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]) {
@@ -149,7 +153,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                        switch(rc_state[0]) {
                        case 0x80:
                                *state = REMOTE_NO_KEY_PRESSED;
-                               goto unlock;
+                               goto out;
 
                        case 0x88: /* framing error or "invalid code" */
                        case 0x99:
@@ -157,7 +161,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                        case 0xd8:
                                *state = REMOTE_NO_KEY_PRESSED;
                                m->rep_count = 0;
-                               goto unlock;
+                               goto out;
 
                        case 0x93:
                        case 0x92:
@@ -165,7 +169,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                        case 0x82:
                                m->rep_count = 0;
                                *state = REMOTE_KEY_PRESSED;
-                               goto unlock;
+                               goto out;
 
                        case 0x91:
                        case 0x81: /* pinnacle PCTV310e */
@@ -174,12 +178,12 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                                        *state = REMOTE_KEY_REPEAT;
                                else
                                        *state = REMOTE_NO_KEY_PRESSED;
-                               goto unlock;
+                               goto out;
 
                        default:
                                deb("Unexpected rc state %02x\n", rc_state[0]);
                                *state = REMOTE_NO_KEY_PRESSED;
-                               goto unlock;
+                               goto out;
                        }
                }
 
@@ -188,8 +192,8 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 
        *state = REMOTE_NO_KEY_PRESSED;
 
- unlock:
-
+ out:
+       kfree(rc_state);
        return ret;
 }
 
@@ -339,13 +343,19 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in
 static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
 {
        u16 value, index, size;
-       u8 read[4], *buff;
+       u8 *read, *buff;
        int i, pass, ret = 0;
 
        buff = kmalloc(65536, GFP_KERNEL);
        if (buff == NULL)
                return -ENOMEM;
 
+       read = kmalloc(4, GFP_KERNEL);
+       if (!read) {
+               kfree(buff);
+               return -ENOMEM;
+       }
+
        if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
                goto done;
        deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
@@ -396,6 +406,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
        deb("firmware uploaded!\n");
 
  done:
+       kfree(read);
        kfree(buff);
 
        return ret;
@@ -632,9 +643,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
        { 0x16, KEY_POWER },
        { 0x17, KEY_FAVORITES },
        { 0x0f, KEY_TEXT },
-       { 0x48, KEY_MEDIA },            /* preview */
+       { 0x48, KEY_PROGRAM },          /* preview */
        { 0x1c, KEY_EPG },
-       { 0x04, KEY_LIST },                     /* record list */
+       { 0x04, KEY_LIST },             /* record list */
        { 0x03, KEY_1 },
        { 0x01, KEY_2 },
        { 0x06, KEY_3 },
@@ -674,14 +685,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
        { 0x0e, KEY_MUTE },
 /*     { 0x49, KEY_LR },       */              /* L/R */
        { 0x07, KEY_SLEEP },            /* Hibernate */
-       { 0x08, KEY_MEDIA },            /* A/V */
-       { 0x0e, KEY_MENU },                     /* Recall */
+       { 0x08, KEY_VIDEO },            /* A/V */
+       { 0x0e, KEY_MENU },             /* Recall */
        { 0x45, KEY_ZOOMIN },
        { 0x46, KEY_ZOOMOUT },
-       { 0x18, KEY_TV },                       /* Red */
-       { 0x53, KEY_VCR },                      /* Green */
-       { 0x5e, KEY_SAT },                      /* Yellow */
-       { 0x5f, KEY_PLAYER },           /* Blue */
+       { 0x18, KEY_RED },              /* Red */
+       { 0x53, KEY_GREEN },            /* Green */
+       { 0x5e, KEY_YELLOW },           /* Yellow */
+       { 0x5f, KEY_BLUE },             /* Blue */
 };
 
 /* DVB USB Driver stuff */
index 9d3cd2d..bc350e9 100644 (file)
@@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = {
        { 0x1e17, KEY_RIGHT },
        { 0x1e18, KEY_VIDEO },
        { 0x1e19, KEY_AUDIO },
-       { 0x1e1a, KEY_MEDIA },
+       { 0x1e1a, KEY_IMAGES },
        { 0x1e1b, KEY_EPG },
        { 0x1e1c, KEY_TV },
        { 0x1e1e, KEY_NEXT },
index 7e569f4..2e4fab7 100644 (file)
@@ -53,27 +53,36 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
                            u8 * data, u16 len, int flags)
 {
        int ret;
-       u8 r;
-       u8 u8buf[len];
-
+       u8 tmp;
+       u8 *buf;
        unsigned int pipe = (flags == OPERA_READ_MSG) ?
                usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
        u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
 
+       buf = kmalloc(len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        if (flags == OPERA_WRITE_MSG)
-               memcpy(u8buf, data, len);
-       ret =
-               usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
-                       value, 0x0, u8buf, len, 2000);
+               memcpy(buf, data, len);
+       ret = usb_control_msg(dev, pipe, request,
+                       request_type | USB_TYPE_VENDOR, value, 0x0,
+                       buf, len, 2000);
 
        if (request == OPERA_TUNER_REQ) {
+               tmp = buf[0];
                if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                               OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
-                               0x01, 0x0, &r, 1, 2000)<1 || r!=0x08)
-                                       return 0;
+                           OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
+                           0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) {
+                       ret = 0;
+                       goto out;
+               }
+               buf[0] = tmp;
        }
        if (flags == OPERA_READ_MSG)
-               memcpy(data, u8buf, len);
+               memcpy(data, buf, len);
+out:
+       kfree(buf);
        return ret;
 }
 
@@ -189,7 +198,7 @@ static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
 static u8 opera1_inittab[] = {
        0x00, 0xa1,
        0x01, 0x15,
-       0x02, 0x00,
+       0x02, 0x30,
        0x03, 0x00,
        0x04, 0x7d,
        0x05, 0x05,
index ccc7e44..2bb8d4c 100644 (file)
@@ -41,14 +41,23 @@ struct vp702x_fe_state {
 
 static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
 {
-       u8 buf[10];
-       if (time_after(jiffies,st->next_status_check)) {
-               vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
+       struct vp702x_device_state *dst = st->d->priv;
+       u8 *buf;
 
+       if (time_after(jiffies, st->next_status_check)) {
+               mutex_lock(&dst->buf_mutex);
+               buf = dst->buf;
+
+               vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
                st->lock = buf[4];
-               vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
-               vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
 
+               vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
+               st->snr = buf[0];
+
+               vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
+               st->sig = buf[0];
+
+               mutex_unlock(&dst->buf_mutex);
                st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
        }
        return 0;
@@ -130,11 +139,17 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
+       struct vp702x_device_state *dst = st->d->priv;
        u32 freq = fep->frequency/1000;
        /*CalFrequency*/
 /*     u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
        u64 sr;
-       u8 cmd[8] = { 0 },ibuf[10];
+       u8 *cmd;
+
+       mutex_lock(&dst->buf_mutex);
+
+       cmd = dst->buf;
+       memset(cmd, 0, 10);
 
        cmd[0] = (freq >> 8) & 0x7f;
        cmd[1] =  freq       & 0xff;
@@ -170,13 +185,15 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
        st->status_check_interval = 250;
        st->next_status_check = jiffies;
 
-       vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+       vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
 
-       if (ibuf[2] == 0 && ibuf[3] == 0)
+       if (cmd[2] == 0 && cmd[3] == 0)
                deb_fe("tuning failed.\n");
        else
                deb_fe("tuning succeeded.\n");
 
+       mutex_unlock(&dst->buf_mutex);
+
        return 0;
 }
 
@@ -204,27 +221,32 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
                                    struct dvb_diseqc_master_cmd *m)
 {
+       u8 *cmd;
        struct vp702x_fe_state *st = fe->demodulator_priv;
-       u8 cmd[8],ibuf[10];
-       memset(cmd,0,8);
+       struct vp702x_device_state *dst = st->d->priv;
 
        deb_fe("%s\n",__func__);
 
        if (m->msg_len > 4)
                return -EINVAL;
 
+       mutex_lock(&dst->buf_mutex);
+
+       cmd = dst->buf;
        cmd[1] = SET_DISEQC_CMD;
        cmd[2] = m->msg_len;
        memcpy(&cmd[3], m->msg, m->msg_len);
-       cmd[7] = vp702x_chksum(cmd,0,7);
+       cmd[7] = vp702x_chksum(cmd, 0, 7);
 
-       vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+       vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
 
-       if (ibuf[2] == 0 && ibuf[3] == 0)
+       if (cmd[2] == 0 && cmd[3] == 0)
                deb_fe("diseqc cmd failed.\n");
        else
                deb_fe("diseqc cmd succeeded.\n");
 
+       mutex_unlock(&dst->buf_mutex);
+
        return 0;
 }
 
@@ -237,7 +259,9 @@ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd
 static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
-       u8 ibuf[10];
+       struct vp702x_device_state *dst = st->d->priv;
+       u8 *buf;
+
        deb_fe("%s\n",__func__);
 
        st->tone_mode = tone;
@@ -247,14 +271,21 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        else
                st->lnb_buf[2] = 0x00;
 
-       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
+
+       mutex_lock(&dst->buf_mutex);
+
+       buf = dst->buf;
+       memcpy(buf, st->lnb_buf, 8);
 
-       vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
-       if (ibuf[2] == 0 && ibuf[3] == 0)
+       vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
+       if (buf[2] == 0 && buf[3] == 0)
                deb_fe("set_tone cmd failed.\n");
        else
                deb_fe("set_tone cmd succeeded.\n");
 
+       mutex_unlock(&dst->buf_mutex);
+
        return 0;
 }
 
@@ -262,7 +293,8 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
                voltage)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
-       u8 ibuf[10];
+       struct vp702x_device_state *dst = st->d->priv;
+       u8 *buf;
        deb_fe("%s\n",__func__);
 
        st->voltage = voltage;
@@ -272,14 +304,20 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
        else
                st->lnb_buf[4] = 0x00;
 
-       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
+
+       mutex_lock(&dst->buf_mutex);
+
+       buf = dst->buf;
+       memcpy(buf, st->lnb_buf, 8);
 
-       vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
-       if (ibuf[2] == 0 && ibuf[3] == 0)
+       vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
+       if (buf[2] == 0 && buf[3] == 0)
                deb_fe("set_voltage cmd failed.\n");
        else
                deb_fe("set_voltage cmd succeeded.\n");
 
+       mutex_unlock(&dst->buf_mutex);
        return 0;
 }
 
index 7890e75..54355f8 100644 (file)
@@ -15,6 +15,7 @@
  * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "vp702x.h"
+#include <linux/mutex.h>
 
 /* debug */
 int dvb_usb_vp702x_debug;
@@ -23,27 +24,23 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-struct vp702x_state {
+struct vp702x_adapter_state {
        int pid_filter_count;
        int pid_filter_can_bypass;
        u8  pid_filter_state;
 };
 
-struct vp702x_device_state {
-       u8 power_state;
-};
-
-/* check for mutex FIXME */
-int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
+                                    u16 value, u16 index, u8 *b, int blen)
 {
-       int ret = -1;
+       int ret;
 
-               ret = usb_control_msg(d->udev,
-                       usb_rcvctrlpipe(d->udev,0),
-                       req,
-                       USB_TYPE_VENDOR | USB_DIR_IN,
-                       value,index,b,blen,
-                       2000);
+       ret = usb_control_msg(d->udev,
+               usb_rcvctrlpipe(d->udev, 0),
+               req,
+               USB_TYPE_VENDOR | USB_DIR_IN,
+               value, index, b, blen,
+               2000);
 
        if (ret < 0) {
                warn("usb in operation failed. (%d)", ret);
@@ -58,8 +55,20 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
        return ret;
 }
 
-static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
-                            u16 index, u8 *b, int blen)
+int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
+                           u16 index, u8 *b, int blen)
+{
+       int ret;
+
+       mutex_lock(&d->usb_mutex);
+       ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen);
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
+int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
+                                     u16 index, u8 *b, int blen)
 {
        int ret;
        deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
@@ -77,6 +86,18 @@ static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
                return 0;
 }
 
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+                            u16 index, u8 *b, int blen)
+{
+       int ret;
+
+       mutex_lock(&d->usb_mutex);
+       ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen);
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
 int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
 {
        int ret;
@@ -84,50 +105,93 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il
        if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
                return ret;
 
-       ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen);
+       ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen);
        msleep(msec);
-       ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
+       ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen);
 
        mutex_unlock(&d->usb_mutex);
-
        return ret;
 }
 
 static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
                                int olen, u8 *i, int ilen, int msec)
 {
-       u8 bout[olen+2];
-       u8 bin[ilen+1];
+       struct vp702x_device_state *st = d->priv;
        int ret = 0;
+       u8 *buf;
+       int buflen = max(olen + 2, ilen + 1);
+
+       ret = mutex_lock_interruptible(&st->buf_mutex);
+       if (ret < 0)
+               return ret;
+
+       if (buflen > st->buf_len) {
+               buf = kmalloc(buflen, GFP_KERNEL);
+               if (!buf) {
+                       mutex_unlock(&st->buf_mutex);
+                       return -ENOMEM;
+               }
+               info("successfully reallocated a bigger buffer");
+               kfree(st->buf);
+               st->buf = buf;
+               st->buf_len = buflen;
+       } else {
+               buf = st->buf;
+       }
 
-       bout[0] = 0x00;
-       bout[1] = cmd;
-       memcpy(&bout[2],o,olen);
+       buf[0] = 0x00;
+       buf[1] = cmd;
+       memcpy(&buf[2], o, olen);
 
-       ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
+       ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec);
 
        if (ret == 0)
-               memcpy(i,&bin[1],ilen);
+               memcpy(i, &buf[1], ilen);
+       mutex_unlock(&st->buf_mutex);
 
        return ret;
 }
 
 static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
 {
-       u8 buf[16] = { 0 };
-       return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16);
+       int ret;
+       struct vp702x_device_state *st = adap->dev->priv;
+       u8 *buf;
+
+       mutex_lock(&st->buf_mutex);
+
+       buf = st->buf;
+       memset(buf, 0, 16);
+
+       ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e,
+                       0, buf, 16);
+       mutex_unlock(&st->buf_mutex);
+       return ret;
 }
 
 static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
 {
-       u8 buf[16] = { 0 };
-       return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16);
+       int ret;
+       struct vp702x_device_state *st = adap->dev->priv;
+       u8 *buf;
+
+       mutex_lock(&st->buf_mutex);
+
+       buf = st->buf;
+       memset(buf, 0, 16);
+       ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f,
+                       0, buf, 16);
+
+       mutex_unlock(&st->buf_mutex);
+
+       return ret;
 }
 
 static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
 {
-       struct vp702x_state *st = adap->priv;
-       u8 buf[16] = { 0 };
+       struct vp702x_adapter_state *st = adap->priv;
+       struct vp702x_device_state *dst = adap->dev->priv;
+       u8 *buf;
 
        if (onoff)
                st->pid_filter_state |=  (1 << id);
@@ -139,32 +203,45 @@ static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onof
        id = 0x10 + id*2;
 
        vp702x_set_pld_state(adap, st->pid_filter_state);
+
+       mutex_lock(&dst->buf_mutex);
+
+       buf = dst->buf;
+       memset(buf, 0, 16);
        vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
        vp702x_usb_in_op(adap->dev, 0xe0, (((pid     ) & 0xff) << 8) | (id+1), 0, buf, 16);
+
+       mutex_unlock(&dst->buf_mutex);
+
        return 0;
 }
 
 
 static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
 {
-       struct vp702x_state *st = adap->priv;
+       struct vp702x_adapter_state *st = adap->priv;
+       struct vp702x_device_state *dst = adap->dev->priv;
        int i;
-       u8 b[10] = { 0 };
+       u8 *b;
 
        st->pid_filter_count = 8;
        st->pid_filter_can_bypass = 1;
        st->pid_filter_state = 0x00;
 
-       vp702x_set_pld_mode(adap, 1); // bypass
+       vp702x_set_pld_mode(adap, 1); /* bypass */
 
        for (i = 0; i < st->pid_filter_count; i++)
                vp702x_set_pid(adap, 0xffff, i, 1);
 
+       mutex_lock(&dst->buf_mutex);
+       b = dst->buf;
+       memset(b, 0, 10);
        vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
        vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
        vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
+       mutex_unlock(&dst->buf_mutex);
+       /*vp702x_set_pld_mode(d, 0); // filter */
 
-       //vp702x_set_pld_mode(d, 0); // filter
        return 0;
 }
 
@@ -182,18 +259,23 @@ static struct rc_map_table rc_map_vp702x_table[] = {
 /* remote control stuff (does not work with my box) */
 static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       u8 key[10];
+       u8 *key;
        int i;
 
 /* remove the following return to enabled remote querying */
        return 0;
 
+       key = kmalloc(10, GFP_KERNEL);
+       if (!key)
+               return -ENOMEM;
+
        vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
 
        deb_rc("remote query key: %x %d\n",key[1],key[1]);
 
        if (key[1] == 0x44) {
                *state = REMOTE_NO_KEY_PRESSED;
+               kfree(key);
                return 0;
        }
 
@@ -203,15 +285,23 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                        *event = rc_map_vp702x_table[i].keycode;
                        break;
                }
+       kfree(key);
        return 0;
 }
 
 
 static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
 {
-       u8 i;
+       u8 i, *buf;
+       struct vp702x_device_state *st = d->priv;
+
+       mutex_lock(&st->buf_mutex);
+       buf = st->buf;
        for (i = 6; i < 12; i++)
-               vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1);
+               vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
+
+       memcpy(mac, buf, 6);
+       mutex_unlock(&st->buf_mutex);
        return 0;
 }
 
@@ -221,7 +311,8 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
 
        vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
 
-       if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10))
+       if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0,
+                                  buf, 10, 10))
                return -EIO;
 
        buf[9] = '\0';
@@ -240,8 +331,38 @@ static struct dvb_usb_device_properties vp702x_properties;
 static int vp702x_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &vp702x_properties,
-                                  THIS_MODULE, NULL, adapter_nr);
+       struct dvb_usb_device *d;
+       struct vp702x_device_state *st;
+       int ret;
+
+       ret = dvb_usb_device_init(intf, &vp702x_properties,
+                                  THIS_MODULE, &d, adapter_nr);
+       if (ret)
+               goto out;
+
+       st = d->priv;
+       st->buf_len = 16;
+       st->buf = kmalloc(st->buf_len, GFP_KERNEL);
+       if (!st->buf) {
+               ret = -ENOMEM;
+               dvb_usb_device_exit(intf);
+               goto out;
+       }
+       mutex_init(&st->buf_mutex);
+
+out:
+       return ret;
+
+}
+
+static void vp702x_usb_disconnect(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       struct vp702x_device_state *st = d->priv;
+       mutex_lock(&st->buf_mutex);
+       kfree(st->buf);
+       mutex_unlock(&st->buf_mutex);
+       dvb_usb_device_exit(intf);
 }
 
 static struct usb_device_id vp702x_usb_table [] = {
@@ -278,7 +399,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
                                        }
                                }
                        },
-                       .size_of_priv     = sizeof(struct vp702x_state),
+                       .size_of_priv     = sizeof(struct vp702x_adapter_state),
                }
        },
        .read_mac_address = vp702x_read_mac_addr,
@@ -307,9 +428,9 @@ static struct dvb_usb_device_properties vp702x_properties = {
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp702x_usb_driver = {
        .name           = "dvb_usb_vp702x",
-       .probe          = vp702x_usb_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table       = vp702x_usb_table,
+       .probe          = vp702x_usb_probe,
+       .disconnect     = vp702x_usb_disconnect,
+       .id_table       = vp702x_usb_table,
 };
 
 /* module stuff */
index c2f97f9..20b9005 100644 (file)
@@ -98,6 +98,13 @@ extern int dvb_usb_vp702x_debug;
 #define RESET_TUNER            0xBE
 /* IN  i: 0, v: 0, no extra buffer */
 
+struct vp702x_device_state {
+       struct mutex buf_mutex;
+       int buf_len;
+       u8 *buf;
+};
+
+
 extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
 
 extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
index ab0ab3c..3db89e3 100644 (file)
@@ -28,9 +28,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
 {
        int ret = 0;
-       u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
+       u8 *buf = d->priv;
 
-       outbuf[0] = cmd;
+       buf[0] = cmd;
 
        if (outlen > 19)
                outlen = 19;
@@ -38,19 +38,21 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
        if (inlen > 11)
                inlen = 11;
 
+       ret = mutex_lock_interruptible(&d->usb_mutex);
+       if (ret)
+               return ret;
+
        if (out != NULL && outlen > 0)
-               memcpy(&outbuf[1], out, outlen);
+               memcpy(&buf[1], out, outlen);
 
        deb_xfer("out buffer: ");
-       debug_dump(outbuf,outlen+1,deb_xfer);
+       debug_dump(buf, outlen+1, deb_xfer);
 
-       if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-               return ret;
 
        if (usb_control_msg(d->udev,
                        usb_sndctrlpipe(d->udev,0),
                        TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
-                       outbuf, 20, 2000) != 20) {
+                       buf, 20, 2000) != 20) {
                err("USB control message 'out' went wrong.");
                ret = -EIO;
                goto unlock;
@@ -61,17 +63,17 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
        if (usb_control_msg(d->udev,
                        usb_rcvctrlpipe(d->udev,0),
                        TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-                       inbuf, 12, 2000) != 12) {
+                       buf, 12, 2000) != 12) {
                err("USB control message 'in' went wrong.");
                ret = -EIO;
                goto unlock;
        }
 
        deb_xfer("in buffer: ");
-       debug_dump(inbuf,12,deb_xfer);
+       debug_dump(buf, 12, deb_xfer);
 
        if (in != NULL && inlen > 0)
-               memcpy(in,&inbuf[1],inlen);
+               memcpy(in, &buf[1], inlen);
 
 unlock:
        mutex_unlock(&d->usb_mutex);
@@ -222,8 +224,26 @@ static struct dvb_usb_device_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &vp7045_properties,
-                                  THIS_MODULE, NULL, adapter_nr);
+       struct dvb_usb_device *d;
+       int ret = dvb_usb_device_init(intf, &vp7045_properties,
+                                  THIS_MODULE, &d, adapter_nr);
+       if (ret)
+               return ret;
+
+       d->priv = kmalloc(20, GFP_KERNEL);
+       if (!d->priv) {
+               dvb_usb_device_exit(intf);
+               return -ENOMEM;
+       }
+
+       return ret;
+}
+
+static void vp7045_usb_disconnect(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       kfree(d->priv);
+       dvb_usb_device_exit(intf);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
@@ -238,6 +258,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
 static struct dvb_usb_device_properties vp7045_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-vp7045-01.fw",
+       .size_of_priv = sizeof(u8 *),
 
        .num_adapters = 1,
        .adapter = {
@@ -284,7 +305,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
 static struct usb_driver vp7045_usb_driver = {
        .name           = "dvb_usb_vp7045",
        .probe          = vp7045_usb_probe,
-       .disconnect = dvb_usb_device_exit,
+       .disconnect     = vp7045_usb_disconnect,
        .id_table       = vp7045_usb_table,
 };
 
index 83093d1..44b816f 100644 (file)
@@ -263,18 +263,16 @@ config DVB_S5H1432
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
-config DVB_DRX397XD
-       tristate "Micronas DRX3975D/DRX3977D based"
+config DVB_DRXD
+       tristate "Micronas DRXD driver"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
-         TODO:
-         This driver needs external firmware. Please use the command
-         "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
-         download/extract them, and then copy them to /usr/lib/hotplug/firmware
-         or /lib/firmware (depending on configuration of firmware hotplug).
+         Note: this driver was based on vendor driver reference code (released
+         under the GPL) as opposed to the existing drx397xd driver, which
+         was written via reverse engineering.
 
 config DVB_L64781
        tristate "LSI L64781"
@@ -385,6 +383,13 @@ config DVB_STV0367
        help
          A DVB-T/C tuner module. Say Y when you want to support this frontend.
 
+config DVB_CXD2820R
+       tristate "Sony CXD2820R"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
        depends on DVB_CORE
 
index 3b0c4bd..2f3a6f7 100644 (file)
@@ -8,6 +8,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
 au8522-objs = au8522_dig.o au8522_decoder.o
+drxd-objs = drxd_firm.o drxd_hard.o
+cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -36,7 +38,7 @@ obj-$(CONFIG_DVB_ZL10036) += zl10036.o
 obj-$(CONFIG_DVB_ZL10039) += zl10039.o
 obj-$(CONFIG_DVB_ZL10353) += zl10353.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
+obj-$(CONFIG_DVB_DRXD) += drxd.o
 obj-$(CONFIG_DVB_TDA10021) += tda10021.o
 obj-$(CONFIG_DVB_TDA10023) += tda10023.o
 obj-$(CONFIG_DVB_STV0297) += stv0297.o
@@ -85,3 +87,5 @@ obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
 obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
 obj-$(CONFIG_DVB_STV0367) += stv0367.o
+obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+
diff --git a/drivers/media/dvb/frontends/bsbe1-d01a.h b/drivers/media/dvb/frontends/bsbe1-d01a.h
new file mode 100644 (file)
index 0000000..7ed3c42
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support
+ *
+ * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef BSBE1_D01A_H
+#define BSBE1_D01A_H
+
+#include "stb6000.h"
+#include "stv0288.h"
+
+static u8 stv0288_bsbe1_d01a_inittab[] = {
+       0x01, 0x15,
+       0x02, 0x20,
+       0x09, 0x0,
+       0x0a, 0x4,
+       0x0b, 0x0,
+       0x0c, 0x0,
+       0x0d, 0x0,
+       0x0e, 0xd4,
+       0x0f, 0x30,
+       0x11, 0x80,
+       0x12, 0x03,
+       0x13, 0x48,
+       0x14, 0x84,
+       0x15, 0x45,
+       0x16, 0xb7,
+       0x17, 0x9c,
+       0x18, 0x0,
+       0x19, 0xa6,
+       0x1a, 0x88,
+       0x1b, 0x8f,
+       0x1c, 0xf0,
+       0x20, 0x0b,
+       0x21, 0x54,
+       0x22, 0x0,
+       0x23, 0x0,
+       0x2b, 0xff,
+       0x2c, 0xf7,
+       0x30, 0x0,
+       0x31, 0x1e,
+       0x32, 0x14,
+       0x33, 0x0f,
+       0x34, 0x09,
+       0x35, 0x0c,
+       0x36, 0x05,
+       0x37, 0x2f,
+       0x38, 0x16,
+       0x39, 0xbd,
+       0x3a, 0x03,
+       0x3b, 0x13,
+       0x3c, 0x11,
+       0x3d, 0x30,
+       0x40, 0x63,
+       0x41, 0x04,
+       0x42, 0x60,
+       0x43, 0x00,
+       0x44, 0x00,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x47, 0x00,
+       0x4a, 0x00,
+       0x50, 0x10,
+       0x51, 0x36,
+       0x52, 0x09,
+       0x53, 0x94,
+       0x54, 0x62,
+       0x55, 0x29,
+       0x56, 0x64,
+       0x57, 0x2b,
+       0x58, 0x54,
+       0x59, 0x86,
+       0x5a, 0x0,
+       0x5b, 0x9b,
+       0x5c, 0x08,
+       0x5d, 0x7f,
+       0x5e, 0x0,
+       0x5f, 0xff,
+       0x70, 0x0,
+       0x71, 0x0,
+       0x72, 0x0,
+       0x74, 0x0,
+       0x75, 0x0,
+       0x76, 0x0,
+       0x81, 0x0,
+       0x82, 0x3f,
+       0x83, 0x3f,
+       0x84, 0x0,
+       0x85, 0x0,
+       0x88, 0x0,
+       0x89, 0x0,
+       0x8a, 0x0,
+       0x8b, 0x0,
+       0x8c, 0x0,
+       0x90, 0x0,
+       0x91, 0x0,
+       0x92, 0x0,
+       0x93, 0x0,
+       0x94, 0x1c,
+       0x97, 0x0,
+       0xa0, 0x48,
+       0xa1, 0x0,
+       0xb0, 0xb8,
+       0xb1, 0x3a,
+       0xb2, 0x10,
+       0xb3, 0x82,
+       0xb4, 0x80,
+       0xb5, 0x82,
+       0xb6, 0x82,
+       0xb7, 0x82,
+       0xb8, 0x20,
+       0xb9, 0x0,
+       0xf0, 0x0,
+       0xf1, 0x0,
+       0xf2, 0xc0,
+       0xff, 0xff,
+};
+
+static struct stv0288_config stv0288_bsbe1_d01a_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+       .inittab = stv0288_bsbe1_d01a_inittab,
+};
+
+#endif
index 45a6dfd..c480c83 100644 (file)
@@ -27,7 +27,7 @@
 
 static u8 alps_bsru6_inittab[] = {
        0x01, 0x15,
-       0x02, 0x00,
+       0x02, 0x30,
        0x03, 0x00,
        0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
        0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
index 2410d8b..95c6465 100644 (file)
@@ -137,7 +137,7 @@ MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
 /* SNR measurements */
 static int esno_snr;
 module_param(esno_snr, int, 0644);
-MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
+MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
        "1=ESNO(db * 10) (default:0)");
 
 enum cmds {
@@ -566,7 +566,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
 {
        struct cx24116_state *state = fe->demodulator_priv;
        struct cx24116_cmd cmd;
-       int i, ret;
+       int i, ret, len, max, remaining;
        unsigned char vers[4];
 
        dprintk("%s\n", __func__);
@@ -603,8 +603,21 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
        cx24116_writereg(state, 0xF5, 0x00);
        cx24116_writereg(state, 0xF6, 0x00);
 
-       /* write the entire firmware as one transaction */
-       cx24116_writeregN(state, 0xF7, fw->data, fw->size);
+       /* Split firmware to the max I2C write len and write.
+        * Writes whole firmware as one write when i2c_wr_max is set to 0. */
+       if (state->config->i2c_wr_max)
+               max = state->config->i2c_wr_max;
+       else
+               max = INT_MAX; /* enough for 32k firmware */
+
+       for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
+               len = remaining;
+               if (len > max - 1)
+                       len = max - 1;
+
+               cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
+                       len);
+       }
 
        cx24116_writereg(state, 0xF4, 0x10);
        cx24116_writereg(state, 0xF0, 0x00);
index b1b76b4..7d90ab9 100644 (file)
@@ -35,6 +35,9 @@ struct cx24116_config {
 
        /* Need to set MPEG parameters */
        u8 mpg_clk_pos_pol:0x02;
+
+       /* max bytes I2C provider can write at once */
+       u16 i2c_wr_max;
 };
 
 #if defined(CONFIG_DVB_CX24116) || \
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
new file mode 100644 (file)
index 0000000..ad17845
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef CXD2820R_H
+#define CXD2820R_H
+
+#include <linux/dvb/frontend.h>
+
+#define CXD2820R_GPIO_D (0 << 0) /* disable */
+#define CXD2820R_GPIO_E (1 << 0) /* enable */
+#define CXD2820R_GPIO_O (0 << 1) /* output */
+#define CXD2820R_GPIO_I (1 << 1) /* input */
+#define CXD2820R_GPIO_L (0 << 2) /* output low */
+#define CXD2820R_GPIO_H (1 << 2) /* output high */
+
+#define CXD2820R_TS_SERIAL        0x08
+#define CXD2820R_TS_SERIAL_MSB    0x28
+#define CXD2820R_TS_PARALLEL      0x30
+#define CXD2820R_TS_PARALLEL_MSB  0x70
+
+struct cxd2820r_config {
+       /* Demodulator I2C address.
+        * Driver determines DVB-C slave I2C address automatically from master
+        * address.
+        * Default: none, must set
+        * Values: 0x6c, 0x6d
+        */
+       u8 i2c_address;
+
+       /* TS output mode.
+        * Default: none, must set.
+        * Values:
+        */
+       u8 ts_mode;
+
+       /* IF AGC polarity.
+        * Default: 0
+        * Values: 0, 1
+        */
+       int if_agc_polarity:1;
+
+       /* Spectrum inversion.
+        * Default: 0
+        * Values: 0, 1
+        */
+       int spec_inv:1;
+
+       /* IFs for all used modes.
+        * Default: none, must set
+        * Values: <kHz>
+        */
+       u16 if_dvbt_6;
+       u16 if_dvbt_7;
+       u16 if_dvbt_8;
+       u16 if_dvbt2_5;
+       u16 if_dvbt2_6;
+       u16 if_dvbt2_7;
+       u16 if_dvbt2_8;
+       u16 if_dvbc;
+
+       /* GPIOs for all used modes.
+        * Default: none, disabled
+        * Values: <see above>
+        */
+       u8 gpio_dvbt[3];
+       u8 gpio_dvbt2[3];
+       u8 gpio_dvbc[3];
+};
+
+
+#if defined(CONFIG_DVB_CXD2820R) || \
+       (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cxd2820r_attach(
+       const struct cxd2820r_config *config,
+       struct i2c_adapter *i2c,
+       struct dvb_frontend *fe
+);
+extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
+       struct dvb_frontend *fe
+);
+#else
+static inline struct dvb_frontend *cxd2820r_attach(
+       const struct cxd2820r_config *config,
+       struct i2c_adapter *i2c,
+       struct dvb_frontend *fe
+)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
+       struct dvb_frontend *fe
+)
+{
+       return NULL;
+}
+
+#endif
+
+#endif /* CXD2820R_H */
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c
new file mode 100644 (file)
index 0000000..3c07d40
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public Lice