]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Jan 2012 20:53:54 +0000 (12:53 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Jan 2012 20:53:54 +0000 (12:53 -0800)
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (57 commits)
  [media] as3645a: Fix compilation by including slab.h
  [media] s5p-fimc: Remove linux/version.h include from fimc-mdevice.c
  [media] s5p-mfc: Remove linux/version.h include from s5p_mfc.c
  [media] ds3000: using logical && instead of bitwise &
  [media] v4l2-ctrls: make control names consistent
  [media] DVB: dib0700, add support for Nova-TD LEDs
  [media] DVB: dib0700, add corrected Nova-TD frontend_attach
  [media] DVB: dib0700, separate stk7070pd initialization
  [media] DVB: dib0700, move Nova-TD Stick to a separate set
  [media] : add MODULE_FIRMWARE to dib0700
  [media] DVB-CORE: remove superfluous DTV_CMDs
  [media] s5p-jpeg: adapt to recent videobuf2 changes
  [media] s5p-g2d: fixed a bug in controls setting function
  [media] s5p-mfc: Fix volatile controls setup
  [media] drivers/media/video/s5p-mfc/s5p_mfc.c: adjust double test
  [media] drivers/media/video/s5p-fimc/fimc-capture.c: adjust double test
  [media] s5p-fimc: Fix incorrect control ID assignment
  [media] dvb_frontend: Don't call get_frontend() if idle
  [media] DocBook/dvbproperty.xml: Remove DTV_MODULATION from ISDB-T
  [media] DocBook/dvbproperty.xml: Fix ISDB-T delivery system parameters
  ...

56 files changed:
Documentation/DocBook/media/dvb/dvbproperty.xml
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
Documentation/DocBook/media/v4l/vidioc-g-input.xml
Documentation/DocBook/media/v4l/vidioc-g-output.xml
Documentation/feature-removal-schedule.txt
Documentation/video4linux/v4l2-controls.txt
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/xc4000.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-usb/anysee.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/frontends/cxd2820r_core.c
drivers/media/dvb/frontends/ds3000.c
drivers/media/dvb/frontends/mb86a20s.c
drivers/media/dvb/frontends/tda18271c2dd.c
drivers/media/video/as3645a.c
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-dec1.c
drivers/media/video/pwc/pwc-dec1.h
drivers/media/video/pwc/pwc-dec23.c
drivers/media/video/pwc/pwc-dec23.h
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-misc.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-mdevice.c
drivers/media/video/s5p-g2d/g2d.c
drivers/media/video/s5p-jpeg/jpeg-core.c
drivers/media/video/s5p-mfc/s5p_mfc.c
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/saa7164/saa7164-cards.c
drivers/media/video/tlg2300/pd-main.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/zoran/zoran_driver.c
include/media/tuner.h

index ffee1fbbc001ae316f40be9def3b2456e20c9118..c7a4ca51785980264b37b19b3b63987a3871fe33 100644 (file)
@@ -163,14 +163,16 @@ get/set up to 64 properties. The actual meaning of each property is described on
        <section id="DTV-FREQUENCY">
                <title><constant>DTV_FREQUENCY</constant></title>
 
-               <para>Central frequency of the channel, in HZ.</para>
+               <para>Central frequency of the channel.</para>
 
                <para>Notes:</para>
-               <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
+               <para>1)For satellital delivery systems, it is measured in kHz.
+                       For the other ones, it is measured in Hz.</para>
+               <para>2)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
+               <para>3)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>
@@ -735,14 +737,10 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-LAYER-ENABLED"><constant>DTV_ISDBT_LAYER_ENABLED</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-PARTIAL-RECEPTION"><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-SOUND-BROADCASTING"><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></link></para></listitem>
index 6f1f9a629dc34d1508bd550342d810f05f2b5028..b17a7aac6997482379e1b43c8b0d7e5cf914e1f0 100644 (file)
@@ -183,7 +183,12 @@ applications must set the array to zero.</entry>
            <entry>__u32</entry>
            <entry><structfield>ctrl_class</structfield></entry>
            <entry>The control class to which all controls belong, see
-<xref linkend="ctrl-class" />.</entry>
+<xref linkend="ctrl-class" />. Drivers that use a kernel framework for handling
+controls will also accept a value of 0 here, meaning that the controls can
+belong to any control class. Whether drivers support this can be tested by setting
+<structfield>ctrl_class</structfield> to 0 and calling <constant>VIDIOC_TRY_EXT_CTRLS</constant>
+with a <structfield>count</structfield> of 0. If that succeeds, then the driver
+supports this feature.</entry>
          </row>
          <row>
            <entry>__u32</entry>
@@ -194,10 +199,13 @@ also be zero.</entry>
          <row>
            <entry>__u32</entry>
            <entry><structfield>error_idx</structfield></entry>
-           <entry>Set by the driver in case of an error. It is the
-index of the control causing the error or equal to 'count' when the
-error is not associated with a particular control. Undefined when the
-ioctl returns 0 (success).</entry>
+           <entry>Set by the driver in case of an error. If it is equal
+to <structfield>count</structfield>, then no actual changes were made to
+controls. In other words, the error was not associated with setting a particular
+control. If it is another value, then only the controls up to <structfield>error_idx-1</structfield>
+were modified and control <structfield>error_idx</structfield> is the one that
+caused the error. The <structfield>error_idx</structfield> value is undefined
+if the ioctl returned 0 (success).</entry>
          </row>
          <row>
            <entry>__u32</entry>
index 93817f33703305beae49acafa52b1bceb0613dd2..7c63815e7afd0eb964a1848513dea5be14eb677e 100644 (file)
@@ -364,15 +364,20 @@ capability and it is cleared otherwise.</entry>
          <row>
            <entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry>
            <entry>0x0002</entry>
-           <entry>The frame buffer is an overlay surface the same
-size as the capture. [?]</entry>
-         </row>
-         <row>
-           <entry spanname="hspan">The purpose of
-<constant>V4L2_FBUF_FLAG_OVERLAY</constant> was never quite clear.
-Most drivers seem to ignore this flag. For compatibility with the
-<wordasword>bttv</wordasword> driver applications should set the
-<constant>V4L2_FBUF_FLAG_OVERLAY</constant> flag.</entry>
+           <entry>If this flag is set for a video capture device, then the
+driver will set the initial overlay size to cover the full framebuffer size,
+otherwise the existing overlay size (as set by &VIDIOC-S-FMT;) will be used.
+
+Only one video capture driver (bttv) supports this flag. The use of this flag
+for capture devices is deprecated. There is no way to detect which drivers
+support this flag, so the only reliable method of setting the overlay size is
+through &VIDIOC-S-FMT;.
+
+If this flag is set for a video output device, then the video output overlay
+window is relative to the top-left corner of the framebuffer and restricted
+to the size of the framebuffer. If it is cleared, then the video output
+overlay window is relative to the video output display.
+            </entry>
          </row>
          <row>
            <entry><constant>V4L2_FBUF_FLAG_CHROMAKEY</constant></entry>
index 16431813bebd253f87965029088ee733328c36e5..66e9a5257861ab1c5f65b197e3bc7e52304659e6 100644 (file)
@@ -98,8 +98,11 @@ the &v4l2-output; <structfield>modulator</structfield> field and the
            <entry>&v4l2-tuner-type;</entry>
            <entry><structfield>type</structfield></entry>
            <entry>The tuner type. This is the same value as in the
-&v4l2-tuner; <structfield>type</structfield> field. The field is not
-applicable to modulators, &ie; ignored by drivers.</entry>
+&v4l2-tuner; <structfield>type</structfield> field. The type must be set
+to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename>
+device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant>
+for all others. The field is not applicable to modulators, &ie; ignored
+by drivers.</entry>
          </row>
          <row>
            <entry>__u32</entry>
index 08ae82f131f2b952df2a0f5488b49d0747776153..1d43065090dd1087be1c26a8f54804ac8a4ee2c2 100644 (file)
@@ -61,8 +61,8 @@ desired input in an integer and call the
 <constant>VIDIOC_S_INPUT</constant> ioctl with a pointer to this
 integer. Side effects are possible. For example inputs may support
 different video standards, so the driver may implicitly switch the
-current standard. It is good practice to select an input before
-querying or negotiating any other parameters.</para>
+current standard. Because of these possible side effects applications
+must select an input before querying or negotiating any other parameters.</para>
 
     <para>Information about video inputs is available using the
 &VIDIOC-ENUMINPUT; ioctl.</para>
index fd45f1c13ccf445b89e582036b40c3a7a94ab86c..4533068ecb8ad5dd221512d5f6dc8a7266b66ecb 100644 (file)
@@ -61,8 +61,9 @@ desired output in an integer and call the
 <constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this integer.
 Side effects are possible. For example outputs may support different
 video standards, so the driver may implicitly switch the current
-standard. It is good practice to select an output before querying or
-negotiating any other parameters.</para>
+standard.
+standard. Because of these possible side effects applications
+must select an output before querying or negotiating any other parameters.</para>
 
     <para>Information about video outputs is available using the
 &VIDIOC-ENUMOUTPUT; ioctl.</para>
index d725c0dfe032f0692ab9de9a4358dfdcdd711f39..1bea46a54b1ca252b5390c422f291dafe41a7c32 100644 (file)
@@ -439,17 +439,6 @@ Who:       Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
 
-What:  For VIDIOC_S_FREQUENCY the type field must match the device node's type.
-       If not, return -EINVAL.
-When:  3.2
-Why:   It makes no sense to switch the tuner to radio mode by calling
-       VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by
-       calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a
-       move to more consistent handling of tv and radio tuners.
-Who:   Hans Verkuil <hans.verkuil@cisco.com>
-
-----------------------------
-
 What:  Opening a radio device node will no longer automatically switch the
        tuner mode from tv to radio.
 When:  3.3
index 26aa0573933e8f5f970f7f18b3f53f0afd37eb6d..e2492a9d1027b95be62b9fde675b043643a7f01c 100644 (file)
@@ -666,27 +666,6 @@ a control of this type whenever the first control belonging to a new control
 class is added.
 
 
-Differences from the Spec
-=========================
-
-There are a few places where the framework acts slightly differently from the
-V4L2 Specification. Those differences are described in this section. We will
-have to see whether we need to adjust the spec or not.
-
-1) It is no longer required to have all controls contained in a
-v4l2_ext_control array be from the same control class. The framework will be
-able to handle any type of control in the array. You need to set ctrl_class
-to 0 in order to enable this. If ctrl_class is non-zero, then it will still
-check that all controls belong to that control class.
-
-If you set ctrl_class to 0 and count to 0, then it will only return an error
-if there are no controls at all.
-
-2) Clarified the way error_idx works. For get and set it will be equal to
-count if nothing was done yet. If it is less than count then only the controls
-up to error_idx-1 were successfully applied.
-
-
 Proposals for Extensions
 ========================
 
index 27555995f7e4c344f74afdfa14824ecbfac2b912..b5ee3ebfcfca03e2f9fd5973cd5d72b52d1c5f53 100644 (file)
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
+/* Registers (Write-only) */
+#define XREG_INIT         0x00
+#define XREG_RF_FREQ      0x02
+#define XREG_POWER_DOWN   0x08
+
+/* Registers (Read-only) */
+#define XREG_FREQ_ERROR   0x01
+#define XREG_LOCK         0x02
+#define XREG_VERSION      0x04
+#define XREG_PRODUCT_ID   0x08
+#define XREG_HSYNC_FREQ   0x10
+#define XREG_FRAME_LINES  0x20
+#define XREG_SNR          0x40
+
+#define XREG_ADC_ENV      0x0100
 
 static int debug;
 module_param(debug, int, 0644);
@@ -885,7 +900,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
        mutex_lock(&priv->lock);
 
        /* Sync Lock Indicator */
-       rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
+       rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
        if (rc < 0)
                goto ret;
 
@@ -894,7 +909,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
                signal = 1 << 11;
 
        /* Get SNR of the video signal */
-       rc = xc2028_get_reg(priv, 0x0040, &signal);
+       rc = xc2028_get_reg(priv, XREG_SNR, &signal);
        if (rc < 0)
                goto ret;
 
@@ -1019,9 +1034,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
 
        /* CMD= Set frequency */
        if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+               rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00});
        else
-               rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+               rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00});
        if (rc < 0)
                goto ret;
 
@@ -1201,9 +1216,9 @@ static int xc2028_sleep(struct dvb_frontend *fe)
        mutex_lock(&priv->lock);
 
        if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+               rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00});
        else
-               rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+               rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
 
        priv->cur_fw.type = 0;  /* need firmware reload */
 
index d218c1d68c33a622cdc791aa684e5645441965bf..68397110b7d932fec46c3cdd4ecc0b9d2e99ddf4 100644 (file)
@@ -154,6 +154,8 @@ struct xc4000_priv {
 #define XREG_SNR          0x06
 #define XREG_VERSION      0x07
 #define XREG_PRODUCT_ID   0x08
+#define XREG_SIGNAL_LEVEL 0x0A
+#define XREG_NOISE_LEVEL  0x0B
 
 /*
    Basic firmware description. This will remain with
@@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
        return xc4000_readreg(priv, XREG_QUALITY, quality);
 }
 
+static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
+{
+       return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
+}
+
+static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
+{
+       return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
+}
+
 static u16 xc_wait_for_lock(struct xc4000_priv *priv)
 {
        u16     lock_state = 0;
@@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv)
        u32     hsync_freq_hz = 0;
        u16     frame_lines;
        u16     quality;
+       u16     signal = 0;
+       u16     noise = 0;
        u8      hw_majorversion = 0, hw_minorversion = 0;
        u8      fw_majorversion = 0, fw_minorversion = 0;
 
@@ -1119,6 +1133,12 @@ static void xc_debug_dump(struct xc4000_priv *priv)
 
        xc_get_quality(priv, &quality);
        dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+
+       xc_get_signal_level(priv, &signal);
+       dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
+
+       xc_get_noise_level(priv, &noise);
+       dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
 }
 
 static int xc4000_set_params(struct dvb_frontend *fe)
@@ -1432,6 +1452,71 @@ fail:
        return ret;
 }
 
+static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       u16 value = 0;
+       int rc;
+
+       mutex_lock(&priv->lock);
+       rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
+       mutex_unlock(&priv->lock);
+
+       if (rc < 0)
+               goto ret;
+
+       /* Informations from real testing of DVB-T and radio part,
+          coeficient for one dB is 0xff.
+        */
+       tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
+
+       /* all known digital modes */
+       if ((priv->video_standard == XC4000_DTV6) ||
+           (priv->video_standard == XC4000_DTV7) ||
+           (priv->video_standard == XC4000_DTV7_8) ||
+           (priv->video_standard == XC4000_DTV8))
+               goto digital;
+
+       /* Analog mode has NOISE LEVEL important, signal
+          depends only on gain of antenna and amplifiers,
+          but it doesn't tell anything about real quality
+          of reception.
+        */
+       mutex_lock(&priv->lock);
+       rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
+       mutex_unlock(&priv->lock);
+
+       tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
+
+       /* highest noise level: 32dB */
+       if (value >= 0x2000) {
+               value = 0;
+       } else {
+               value = ~value << 3;
+       }
+
+       goto ret;
+
+       /* Digital mode has SIGNAL LEVEL important and real
+          noise level is stored in demodulator registers.
+        */
+digital:
+       /* best signal: -50dB */
+       if (value <= 0x3200) {
+               value = 0xffff;
+       /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
+       } else if (value >= 0x713A) {
+               value = 0;
+       } else {
+               value = ~(value - 0x3200) << 2;
+       }
+
+ret:
+       *strength = value;
+
+       return rc;
+}
+
 static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
        struct xc4000_priv *priv = fe->tuner_priv;
@@ -1559,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = {
        .set_params        = xc4000_set_params,
        .set_analog_params = xc4000_set_analog_params,
        .get_frequency     = xc4000_get_frequency,
+       .get_rf_strength   = xc4000_get_signal,
        .get_bandwidth     = xc4000_get_bandwidth,
        .get_status        = xc4000_get_status
 };
index b15db4fe347b9218ec8b9e348802f424abb5d72b..fbbe545a74cb5357c3c1cdf445511c80f32dd724 100644 (file)
@@ -904,8 +904,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int i;
+       u32 delsys;
 
+       delsys = c->delivery_system;
        memset(c, 0, sizeof(struct dtv_frontend_properties));
+       c->delivery_system = delsys;
 
        c->state = DTV_CLEAR;
 
@@ -1009,25 +1012,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
        _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
 
-       _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
-
        _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
        _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
 
@@ -1413,6 +1397,15 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        enum dvbv3_emulation_type type;
 
+       /*
+        * It was reported that some old DVBv5 applications were
+        * filling delivery_system with SYS_UNDEFINED. If this happens,
+        * assume that the application wants to use the first supported
+        * delivery system.
+        */
+       if (c->delivery_system == SYS_UNDEFINED)
+               c->delivery_system = fe->ops.delsys[0];
+
        if (desired_system == SYS_UNDEFINED) {
                /*
                 * A DVBv3 call doesn't know what's the desired system.
@@ -1732,6 +1725,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int err = 0;
 
@@ -1798,9 +1792,14 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 
                /*
                 * Fills the cache out struct with the cache contents, plus
-                * the data retrieved from get_frontend.
+                * the data retrieved from get_frontend, if the frontend
+                * is not idle. Otherwise, returns the cached content
                 */
-               dtv_get_frontend(fe, NULL);
+               if (fepriv->state != FESTATE_IDLE) {
+                       err = dtv_get_frontend(fe, NULL);
+                       if (err < 0)
+                               goto out;
+               }
                for (i = 0; i < tvps->num; i++) {
                        err = dtv_property_process_get(fe, c, tvp + i, file);
                        if (err < 0)
index d66192974d68a0a2de44fd41f156f7b6c9c90a85..1455e2644ab5e4e08a0a5324a0d3e873b9941256 100644 (file)
@@ -877,24 +877,18 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
        case ANYSEE_HW_508T2C: /* 20 */
                /* E7 T2C */
 
+               if (state->fe_id)
+                       break;
+
                /* enable DVB-T/T2/C demod on IOE[5] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
-               if (state->fe_id == 0)  {
-                       /* DVB-T/T2 */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(cxd2820r_attach,
-                               &anysee_cxd2820r_config,
-                               &adap->dev->i2c_adap, NULL);
-               } else {
-                       /* DVB-C */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(cxd2820r_attach,
-                               &anysee_cxd2820r_config,
-                               &adap->dev->i2c_adap, adap->fe_adap[0].fe);
-               }
+               /* attach demod */
+               adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
+                               &anysee_cxd2820r_config, &adap->dev->i2c_adap,
+                               NULL);
 
                state->has_ci = true;
 
index 9bd6d51b3b938b21659dffe90f7ee68877ad6302..7de125c0b36f4576f951ea8e90a87d7c308f0857 100644 (file)
@@ -48,6 +48,8 @@ struct dib0700_state {
        u8 disable_streaming_master_mode;
        u32 fw_version;
        u32 nb_packet_buffer_size;
+       int (*read_status)(struct dvb_frontend *, fe_status_t *);
+       int (*sleep)(struct dvb_frontend* fe);
        u8 buf[255];
 };
 
index 206999476f028238c430797ba11b762b55dee379..070e82aa53f53248f33448d9e61d22b484e6b28a 100644 (file)
@@ -834,6 +834,7 @@ static struct usb_driver dib0700_driver = {
 
 module_usb_driver(dib0700_driver);
 
+MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
 MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
 MODULE_VERSION("1.0");
index 81ef4b46f790f936129b849e55878e8b8a9ff89e..f9e966aa26e75d19b0ce129221be038bd6787fe5 100644 (file)
@@ -3066,19 +3066,25 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
        }
 };
 
-static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+static void stk7070pd_init(struct dvb_usb_device *dev)
 {
-       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1);
        msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       dib0700_set_gpio(dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 0);
 
-       dib0700_ctrl_clock(adap->dev, 72, 1);
+       dib0700_ctrl_clock(dev, 72, 1);
 
        msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1);
+}
+
+static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+{
+       stk7070pd_init(adap->dev);
+
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
@@ -3099,6 +3105,77 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
        return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
+static int novatd_read_status_override(struct dvb_frontend *fe,
+               fe_status_t *stat)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *state = dev->priv;
+       int ret;
+
+       ret = state->read_status(fe, stat);
+
+       if (!ret)
+               dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT,
+                               !!(*stat & FE_HAS_LOCK));
+
+       return ret;
+}
+
+static int novatd_sleep_override(struct dvb_frontend* fe)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *state = dev->priv;
+
+       /* turn off LED */
+       dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0);
+
+       return state->sleep(fe);
+}
+
+/**
+ * novatd_frontend_attach - Nova-TD specific attach
+ *
+ * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for
+ * information purposes.
+ */
+static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *st = dev->priv;
+
+       if (adap->id == 0) {
+               stk7070pd_init(dev);
+
+               /* turn the power LED on, the other two off (just in case) */
+               dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0);
+               dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
+               dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
+
+               if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+                                            stk7070pd_dib7000p_config) != 0) {
+                       err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+                           __func__);
+                       return -ENODEV;
+               }
+       }
+
+       adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+                       adap->id == 0 ? 0x80 : 0x82,
+                       &stk7070pd_dib7000p_config[adap->id]);
+
+       if (adap->fe_adap[0].fe == NULL)
+               return -ENODEV;
+
+       st->read_status = adap->fe_adap[0].fe->ops.read_status;
+       adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override;
+       st->sleep = adap->fe_adap[0].fe->ops.sleep;
+       adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override;
+
+       return 0;
+}
+
 /* S5H1411 */
 static struct s5h1411_config pinnacle_801e_config = {
        .output_mode   = S5H1411_PARALLEL_OUTPUT,
@@ -3861,6 +3938,57 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
+               .num_adapters = 2,
+               .adapter = {
+                       {
+                       .num_frontends = 1,
+                       .fe = {{
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                               .pid_filter_count = 32,
+                               .pid_filter       = stk70x0p_pid_filter,
+                               .pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+                               .frontend_attach  = novatd_frontend_attach,
+                               .tuner_attach     = dib7070p_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+                       }},
+                               .size_of_priv     = sizeof(struct dib0700_adapter_state),
+                       }, {
+                       .num_frontends = 1,
+                       .fe = {{
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                               .pid_filter_count = 32,
+                               .pid_filter       = stk70x0p_pid_filter,
+                               .pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+                               .frontend_attach  = novatd_frontend_attach,
+                               .tuner_attach     = dib7070p_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+                       }},
+                               .size_of_priv     = sizeof(struct dib0700_adapter_state),
+                       }
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "Hauppauge Nova-TD Stick (52009)",
+                               { &dib0700_usb_id_table[35], NULL },
+                               { NULL },
+                       },
+               },
+
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
                .num_adapters = 2,
                .adapter = {
                        {
@@ -3892,7 +4020,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        }
                },
 
-               .num_device_descs = 6,
+               .num_device_descs = 5,
                .devices = {
                        {   "DiBcom STK7070PD reference design",
                                { &dib0700_usb_id_table[17], NULL },
@@ -3902,10 +4030,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[18], NULL },
                                { NULL },
                        },
-                       {   "Hauppauge Nova-TD Stick (52009)",
-                               { &dib0700_usb_id_table[35], NULL },
-                               { NULL },
-                       },
                        {   "Hauppauge Nova-TD-500 (84xxx)",
                                { &dib0700_usb_id_table[36], NULL },
                                { NULL },
index 93e1b12e79077ddc851ffd5fd85c8240c795eed7..caae7f79c8379323d1bce9c6b998bc996c63fda4 100644 (file)
@@ -309,9 +309,14 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
 static int cxd2820r_get_frontend(struct dvb_frontend *fe)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+       if (priv->delivery_system == SYS_UNDEFINED)
+               return 0;
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_get_frontend_t(fe);
@@ -476,10 +481,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
        /* switch between DVB-T and DVB-T2 when tune fails */
-       if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) {
+       if (priv->last_tune_failed) {
                if (priv->delivery_system == SYS_DVBT)
                        c->delivery_system = SYS_DVBT2;
-               else
+               else if (priv->delivery_system == SYS_DVBT2)
                        c->delivery_system = SYS_DVBT;
        }
 
@@ -492,6 +497,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        /* frontend lock wait loop count */
        switch (priv->delivery_system) {
        case SYS_DVBT:
+       case SYS_DVBC_ANNEX_A:
                i = 20;
                break;
        case SYS_DVBT2:
index 938777065de6d1d14effed1ab4f9a01b3f7dc8c7..af65d013db11e8ed843c555fe0dc73d114103729 100644 (file)
@@ -1195,7 +1195,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
 
        for (i = 0; i < 30 ; i++) {
                ds3000_read_status(fe, &status);
-               if (status && FE_HAS_LOCK)
+               if (status & FE_HAS_LOCK)
                        break;
 
                msleep(10);
index 7fa3e472cdcaf40e0af6d97a4515a6b383dea0dd..fade566927c3ee93d65cba68a14309c798051d7b 100644 (file)
@@ -402,7 +402,7 @@ static int mb86a20s_get_modulation(struct mb86a20s_state *state,
                [2] = 0x8e,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -435,7 +435,7 @@ static int mb86a20s_get_fec(struct mb86a20s_state *state,
                [2] = 0x8f,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -470,7 +470,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
                [2] = 0x90,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -494,7 +494,7 @@ static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
                [2] = 0x91,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
index 86da3d816498e320772a3a094702d9699b894e19..ad7c72e8f517728539f93adde89f63ddf980d137 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
index ec859a580651e327475f0ce57f7faba7f5a1d26b..f241702a0f36442aa7e3ab1c8d9fe55213e00d78 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include <media/as3645a.h>
 #include <media/v4l2-ctrls.h>
index 14cb961c22bdba5ef506ba56ad55e59d2dc1ade5..4bfd865a4106069538b893720622e424b0097915 100644 (file)
@@ -751,20 +751,10 @@ int cx18_v4l2_close(struct file *filp)
 
        CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* Easy case first: this stream was never claimed by us */
-       if (s->id != id->open_id) {
-               kfree(id);
-               return 0;
-       }
-
-       /* 'Unclaim' this stream */
-
-       /* Stop radio */
        mutex_lock(&cx->serialize_lock);
-       if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
+       /* Stop radio */
+       if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                /* Closing radio device, return to TV mode */
                cx18_mute(cx);
                /* Mark that the radio is no longer in use */
@@ -781,10 +771,14 @@ int cx18_v4l2_close(struct file *filp)
                }
                /* Done! Unmute and continue. */
                cx18_unmute(cx);
-               cx18_release_stream(s);
-       } else {
-               cx18_stop_capture(id, 0);
        }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* 'Unclaim' this stream */
+       if (s->id == id->open_id)
+               cx18_stop_capture(id, 0);
        kfree(id);
        mutex_unlock(&cx->serialize_lock);
        return 0;
@@ -810,21 +804,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
 
        item->open_id = cx->open_id++;
        filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
 
-       if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
-               /* Try to claim this stream */
-               if (cx18_claim_stream(item, item->type)) {
-                       /* No, it's already in use */
-                       v4l2_fh_exit(&item->fh);
-                       kfree(item);
-                       return -EBUSY;
-               }
-
+       if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
                        if (atomic_read(&cx->ana_capturing) > 0) {
                                /* switching to radio while capture is
                                   in progress is not polite */
-                               cx18_release_stream(s);
+                               v4l2_fh_del(&item->fh);
                                v4l2_fh_exit(&item->fh);
                                kfree(item);
                                return -EBUSY;
@@ -842,7 +830,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
                /* Done! Unmute and continue. */
                cx18_unmute(cx);
        }
-       v4l2_fh_add(&item->fh);
        return 0;
 }
 
index 919ed77b32f2dec7fc6e6b195a9722c6f77f6fbb..875a7ce947361ffb720ced4e811dd909cb03b15b 100644 (file)
@@ -1052,7 +1052,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                cx231xx_err(DRIVER_NAME ": out of memory!\n");
-               clear_bit(dev->devno, &cx231xx_devused);
+               clear_bit(nr, &cx231xx_devused);
                return -ENOMEM;
        }
 
index 3c01be999e353817718ab342c27943fc1a52d78f..19b5499d2624cc9b130e8340062222fd12a465e3 100644 (file)
@@ -213,8 +213,8 @@ struct cx23885_board cx23885_boards[] = {
                .portc          = CX23885_MPEG_DVB,
                .tuner_type     = TUNER_XC4000,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC4000,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = {{
                        .type   = CX23885_VMUX_TELEVISION,
                        .vmux   = CX25840_VIN2_CH1 |
index af8a225763d3dbfc3a41068855625a83bf13d4cd..6835eb1fc09319cb52c006f6af6e299f7fc76833 100644 (file)
@@ -943,6 +943,11 @@ static int dvb_register(struct cx23885_tsport *port)
 
                        fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
                                        &dev->i2c_bus[1].i2c_adap, &cfg);
+                       if (!fe) {
+                               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+                                      dev->name);
+                               goto frontend_detach;
+                       }
                }
                break;
        case CX23885_BOARD_TBS_6920:
index 4bbf9bb97bde984e23c0665fda59a72bc7dbd80a..c654bdc7ccb201dd4e285c0b7ddfe703ab89cb61 100644 (file)
@@ -1550,7 +1550,6 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
        struct v4l2_control ctrl;
        struct videobuf_dvb_frontend *vfe;
        struct dvb_frontend *fe;
-       int err = 0;
 
        struct analog_parameters params = {
                .mode      = V4L2_TUNER_ANALOG_TV,
@@ -1572,8 +1571,10 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
                params.frequency, f->tuner, params.std);
 
        vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
-       if (!vfe)
-               err = -EINVAL;
+       if (!vfe) {
+               mutex_unlock(&dev->lock);
+               return -EINVAL;
+       }
 
        fe = vfe->dvb.frontend;
 
index 62c7ad050f9bb0b067a963405ddda6e8cbcd1838..cbd5d119a2c660ebd7f8e9aba9b4206795d290e9 100644 (file)
@@ -1573,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Pinnacle Hybrid PCTV",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -1611,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Leadtek TV2000 XP Global",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -2115,8 +2115,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Terratec Cinergy HT PCI MKII",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -2154,9 +2154,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV1800H] = {
                .name           = "Leadtek WinFast DTV1800 Hybrid",
                .tuner_type     = TUNER_XC2028,
-               .radio_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO setting
                 *
@@ -2195,9 +2195,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
                .name           = "Leadtek WinFast DTV1800 H (XC4000)",
                .tuner_type     = TUNER_XC4000,
-               .radio_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO setting
                 *
@@ -2236,9 +2236,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
                .name           = "Leadtek WinFast DTV2000 H PLUS",
                .tuner_type     = TUNER_XC4000,
-               .radio_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO
                 *   2: 1: mute audio
index 544af91cbdc1b0fb9962d6550cb9c4892299a74b..3949b7dc2368370ebe6d28f15b3b83bc2999babe 100644 (file)
@@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
 
        init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
 
-       /* start counting open_id at 1 */
-       itv->open_id = 1;
-
        /* Initial settings */
        itv->cxhdl.port = CX2341X_PORT_MEMORY;
        itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
index 8f9cc17b518eaaf6320e092d0a667d8d4876e586..06f3d78389bfbb250f89d655a9d6e57ebe359d24 100644 (file)
@@ -332,7 +332,7 @@ struct ivtv_stream {
        const char *name;               /* name of the stream */
        int type;                       /* stream type */
 
-       u32 id;
+       struct v4l2_fh *fh;             /* pointer to the streaming filehandle */
        spinlock_t qlock;               /* locks access to the queues */
        unsigned long s_flags;          /* status flags, see above */
        int dma;                        /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
@@ -379,7 +379,6 @@ struct ivtv_stream {
 
 struct ivtv_open_id {
        struct v4l2_fh fh;
-       u32 open_id;                    /* unique ID for this file descriptor */
        int type;                       /* stream type */
        int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
        struct ivtv *itv;
index 38f052257f4620498d6b23e0bf3b7cfb88aa5ba9..2cd6c89b7d917d618de7791bf919bb1015c899b9 100644 (file)
@@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
 
        if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
                /* someone already claimed this stream */
-               if (s->id == id->open_id) {
+               if (s->fh == &id->fh) {
                        /* yes, this file descriptor did. So that's OK. */
                        return 0;
                }
-               if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI ||
+               if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
                                         type == IVTV_ENC_STREAM_TYPE_VBI)) {
                        /* VBI is handled already internally, now also assign
                           the file descriptor to this stream for external
                           reading of the stream. */
-                       s->id = id->open_id;
+                       s->fh = &id->fh;
                        IVTV_DEBUG_INFO("Start Read VBI\n");
                        return 0;
                }
@@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
                IVTV_DEBUG_INFO("Stream %d is busy\n", type);
                return -EBUSY;
        }
-       s->id = id->open_id;
+       s->fh = &id->fh;
        if (type == IVTV_DEC_STREAM_TYPE_VBI) {
                /* Enable reinsertion interrupt */
                ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
@@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
        struct ivtv *itv = s->itv;
        struct ivtv_stream *s_vbi;
 
-       s->id = -1;
+       s->fh = NULL;
        if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
                test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
                /* this stream is still in use internally */
@@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
                /* was already cleared */
                return;
        }
-       if (s_vbi->id != -1) {
+       if (s_vbi->fh) {
                /* VBI stream still claimed by a file descriptor */
                return;
        }
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
                }
 
                /* wait for more data to arrive */
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
                /* New buffers might have become available before we were added to the waitqueue */
                if (!s->q_full.buffers)
                        schedule();
                finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (signal_pending(current)) {
                        /* return if a signal was received */
                        IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
        size_t tot_written = 0;
        int single_frame = 0;
 
-       if (atomic_read(&itv->capturing) == 0 && s->id == -1) {
+       if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
                /* shouldn't happen */
                IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
                return -EIO;
@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
 
        IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
 
-       mutex_lock(&itv->serialize_lock);
        rc = ivtv_start_capture(id);
-       mutex_unlock(&itv->serialize_lock);
        if (rc)
                return rc;
        return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
        set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
 
        /* Start decoder (returns 0 if already started) */
-       mutex_lock(&itv->serialize_lock);
        rc = ivtv_start_decoding(id, itv->speed);
-       mutex_unlock(&itv->serialize_lock);
        if (rc) {
                IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
 
@@ -627,11 +625,13 @@ retry:
                        break;
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
                /* New buffers might have become free before we were added to the waitqueue */
                if (!s->q_free.buffers)
                        schedule();
                finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (signal_pending(current)) {
                        IVTV_DEBUG_INFO("User stopped %s\n", s->name);
                        return -EINTR;
@@ -686,12 +686,14 @@ retry:
                        if (mode == OUT_YUV)
                                ivtv_yuv_setup_stream_frame(itv);
 
+                       mutex_unlock(&itv->serialize_lock);
                        prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
                        while (!(got_sig = signal_pending(current)) &&
                                        test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
                                schedule();
                        }
                        finish_wait(&itv->dma_waitq, &wait);
+                       mutex_lock(&itv->serialize_lock);
                        if (got_sig) {
                                IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
                                return -EINTR;
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
                int rc;
 
-               mutex_lock(&itv->serialize_lock);
                rc = ivtv_start_capture(id);
-               mutex_unlock(&itv->serialize_lock);
                if (rc) {
                        IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
                                        s->name, rc);
@@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
                     id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
                    test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
                        /* Also used internally, don't stop capturing */
-                       s->id = -1;
+                       s->fh = NULL;
                }
                else {
                        ivtv_stop_v4l2_encode_stream(s, gop_end);
@@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp)
 
        IVTV_DEBUG_FILE("close %s\n", s->name);
 
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* Easy case first: this stream was never claimed by us */
-       if (s->id != id->open_id) {
-               kfree(id);
-               return 0;
-       }
-
-       /* 'Unclaim' this stream */
-
        /* Stop radio */
-       mutex_lock(&itv->serialize_lock);
-       if (id->type == IVTV_ENC_STREAM_TYPE_RAD) {
+       if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                /* Closing radio device, return to TV mode */
                ivtv_mute(itv);
                /* Mark that the radio is no longer in use */
@@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp)
                if (atomic_read(&itv->capturing) > 0) {
                        /* Undo video mute */
                        ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
-                               v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
-                               (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+                                       v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
+                                       (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
                }
                /* Done! Unmute and continue. */
                ivtv_unmute(itv);
-               ivtv_release_stream(s);
-       } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+       }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* Easy case first: this stream was never claimed by us */
+       if (s->fh != &id->fh) {
+               kfree(id);
+               return 0;
+       }
+
+       /* 'Unclaim' this stream */
+
+       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
                struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
 
                ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
@@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
                ivtv_stop_capture(id, 0);
        }
        kfree(id);
-       mutex_unlock(&itv->serialize_lock);
        return 0;
 }
 
-static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
+int ivtv_v4l2_open(struct file *filp)
 {
-#ifdef CONFIG_VIDEO_ADV_DEBUG
        struct video_device *vdev = video_devdata(filp);
-#endif
+       struct ivtv_stream *s = video_get_drvdata(vdev);
        struct ivtv *itv = s->itv;
        struct ivtv_open_id *item;
        int res = 0;
 
        IVTV_DEBUG_FILE("open %s\n", s->name);
 
+       if (ivtv_init_on_first_open(itv)) {
+               IVTV_ERR("Failed to initialize on device %s\n",
+                        video_device_node_name(vdev));
+               return -ENXIO;
+       }
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        /* Unless ivtv_fw_debug is set, error out if firmware dead. */
        if (ivtv_fw_debug) {
@@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
                return -ENOMEM;
        }
        v4l2_fh_init(&item->fh, s->vdev);
-       if (res < 0) {
-               v4l2_fh_exit(&item->fh);
-               kfree(item);
-               return res;
-       }
        item->itv = itv;
        item->type = s->type;
 
-       item->open_id = itv->open_id++;
        filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
 
-       if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
-               /* Try to claim this stream */
-               if (ivtv_claim_stream(item, item->type)) {
-                       /* No, it's already in use */
-                       v4l2_fh_exit(&item->fh);
-                       kfree(item);
-                       return -EBUSY;
-               }
-
+       if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
                        if (atomic_read(&itv->capturing) > 0) {
                                /* switching to radio while capture is
                                   in progress is not polite */
-                               ivtv_release_stream(s);
+                               v4l2_fh_del(&item->fh);
                                v4l2_fh_exit(&item->fh);
                                kfree(item);
                                return -EBUSY;
@@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
                itv->yuv_info.stream_size = 0;
        }
-       v4l2_fh_add(&item->fh);
        return 0;
 }
 
-int ivtv_v4l2_open(struct file *filp)
-{
-       int res;
-       struct ivtv *itv = NULL;
-       struct ivtv_stream *s = NULL;
-       struct video_device *vdev = video_devdata(filp);
-
-       s = video_get_drvdata(vdev);
-       itv = s->itv;
-
-       mutex_lock(&itv->serialize_lock);
-       if (ivtv_init_on_first_open(itv)) {
-               IVTV_ERR("Failed to initialize on device %s\n",
-                        video_device_node_name(vdev));
-               mutex_unlock(&itv->serialize_lock);
-               return -ENXIO;
-       }
-       res = ivtv_serialized_open(s, filp);
-       mutex_unlock(&itv->serialize_lock);
-       return res;
-}
-
 void ivtv_mute(struct ivtv *itv)
 {
        if (atomic_read(&itv->capturing))
index ecafa697326e302803ab85604c0a7ab8aec697f6..c4bc481430985c6405580a461e2cc8e518ae2d73 100644 (file)
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
                ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
 
                /* Wait for any DMA to finish */
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
                while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
                        got_sig = signal_pending(current);
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
                        schedule();
                }
                finish_wait(&itv->dma_waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (got_sig)
                        return -EINTR;
 
@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
         * happens within the first 100 lines of the top field.
         * Make 4 attempts to sync to the decoder before giving up.
         */
+       mutex_unlock(&itv->serialize_lock);
        for (f = 0; f < 4; f++) {
                prepare_to_wait(&itv->vsync_waitq, &wait,
                                TASK_UNINTERRUPTIBLE);
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
                schedule_timeout(msecs_to_jiffies(25));
        }
        finish_wait(&itv->vsync_waitq, &wait);
+       mutex_lock(&itv->serialize_lock);
 
        if (f == 4)
                IVTV_WARN("Mode change failed to sync to decoder\n");
@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
        return 0;
 }
 
-static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct video_device *vfd = video_devdata(filp);
        long ret;
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
        return ret;
 }
 
-long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       long res;
-
-       /* DQEVENT can block, so this should not run with the serialize lock */
-       if (cmd == VIDIOC_DQEVENT)
-               return ivtv_serialized_ioctl(itv, filp, cmd, arg);
-       mutex_lock(&itv->serialize_lock);
-       res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
-       mutex_unlock(&itv->serialize_lock);
-       return res;
-}
-
 static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
        .vidioc_querycap                    = ivtv_querycap,
        .vidioc_s_audio                     = ivtv_s_audio,
index 9c29e964d400b955d36074487c17c22e1195bbcd..1b3b9578bf47657915b464e9b9513f48b481aa0e 100644 (file)
@@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s)
                        ivtv_process_vbi_data(itv, buf, 0, s->type);
                        s->q_dma.bytesused += buf->bytesused;
                }
-               if (s->id == -1) {
+               if (s->fh == NULL) {
                        ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
                        return;
                }
        }
        ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
-       if (s->id != -1)
+       if (s->fh)
                wake_up(&s->waitq);
 }
 
index e7794dc1330e50348a5e358714abf9f54702e56d..c6e28b4ebbed6dfe3e821e443dcff04d8e4694e3 100644 (file)
@@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
                s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
        spin_lock_init(&s->qlock);
        init_waitqueue_head(&s->waitq);
-       s->id = -1;
        s->sg_handle = IVTV_DMA_UNMAPPED;
        ivtv_queue_init(&s->q_free);
        ivtv_queue_init(&s->q_full);
@@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
        s->vdev->fops = ivtv_stream_info[type].fops;
        s->vdev->release = video_device_release;
        s->vdev->tvnorms = V4L2_STD_ALL;
+       s->vdev->lock = &itv->serialize_lock;
        set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
        ivtv_set_funcs(s->vdev);
        return 0;
index dcbab6ad4c26ee8843336f673aeb1f9f7fe7ef80..2ad65eb29832754b54a5d190257cadd5d6a09031 100644 (file)
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
 {
        struct yuv_playback_info *yi = &itv->yuv_info;
        struct ivtv_dma_frame dma_args;
+       int res;
 
        ivtv_yuv_setup_stream_frame(itv);
 
        /* We only need to supply source addresses for this */
        dma_args.y_source = src;
        dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
-       return ivtv_yuv_udma_frame(itv, &dma_args);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, &dma_args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
 }
 
 /* IVTV_IOC_DMA_FRAME ioctl handler */
 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
-/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
+       int res;
 
+/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
        ivtv_yuv_next_free(itv);
        ivtv_yuv_setup_frame(itv, args);
-       return ivtv_yuv_udma_frame(itv, args);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
 }
 
 void ivtv_yuv_close(struct ivtv *itv)
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
        int h_filter, v_filter_1, v_filter_2;
 
        IVTV_DEBUG_YUV("ivtv_yuv_close\n");
+       mutex_unlock(&itv->serialize_lock);
        ivtv_waitq(&itv->vsync_waitq);
+       mutex_lock(&itv->serialize_lock);
 
        yi->running = 0;
        atomic_set(&yi->next_dma_frame, -1);
index a277f95091ef2b481b369dca5cacc30cbf04afe4..1fb7d5bd5ec26a3f8955e8a6cdc3e7a6cd3841f9 100644 (file)
@@ -1042,7 +1042,8 @@ static int vidioc_querycap(struct file *file, void *fh,
        strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
        strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
        cap->bus_info[0] = '\0';
-       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+               V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
 
        return 0;
 }
@@ -1825,7 +1826,9 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
 
-       a->flags = 0x0;
+       /* The video overlay must stay within the framebuffer and can't be
+          positioned independently. */
+       a->flags = V4L2_FBUF_FLAG_OVERLAY;
        a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
                | V4L2_FBUF_CAP_SRC_CHROMAKEY;
 
index 905d41d90c6aa816b7162ddf1d0f5e99bee4912a..1f506fde97d0a52433a7477f6ac843cc60af1f2f 100644 (file)
@@ -104,47 +104,16 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
 
 /****************************************************************************/
 
-static int _send_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, int index, void *buf, int buflen)
-{
-       int rc;
-       void *kbuf = NULL;
-
-       if (buflen) {
-               kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
-               if (kbuf == NULL)
-                       return -ENOMEM;
-       }
-
-       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-               request,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               index,
-               kbuf, buflen, USB_CTRL_SET_TIMEOUT);
-
-       kfree(kbuf);
-       return rc;
-}
-
 static int recv_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, void *buf, int buflen)
+       u8 request, u16 value, int recv_count)
 {
        int rc;
-       void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
-
-       if (kbuf == NULL)
-               return -ENOMEM;
 
        rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
                request,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               pdev->vcinterface,
-               kbuf, buflen, USB_CTRL_GET_TIMEOUT);
-       memcpy(buf, kbuf, buflen);
-       kfree(kbuf);
-
+               value, pdev->vcinterface,
+               pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
        if (rc < 0)
                PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
                          rc, request, value);
@@ -152,27 +121,39 @@ static int recv_control_msg(struct pwc_device *pdev,
 }
 
 static inline int send_video_command(struct pwc_device *pdev,
-       int index, void *buf, int buflen)
+       int index, const unsigned char *buf, int buflen)
 {
-       return _send_control_msg(pdev,
-               SET_EP_STREAM_CTL,
-               VIDEO_OUTPUT_CONTROL_FORMATTER,
-               index,
-               buf, buflen);
+       int rc;
+
+       memcpy(pdev->ctrl_buf, buf, buflen);
+
+       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       SET_EP_STREAM_CTL,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       VIDEO_OUTPUT_CONTROL_FORMATTER, index,
+                       pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
+       if (rc >= 0)
+               memcpy(pdev->cmd_buf, buf, buflen);
+       else
+               PWC_ERROR("send_video_command error %d\n", rc);
+
+       return rc;
 }
 
 int send_control_msg(struct pwc_device *pdev,
        u8 request, u16 value, void *buf, int buflen)
 {
-       return _send_control_msg(pdev,
-               request, value, pdev->vcinterface, buf, buflen);
+       return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       request,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, pdev->vcinterface,
+                       buf, buflen, USB_CTRL_SET_TIMEOUT);
 }
 
-static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
-                              int *compression)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
+                              int frames, int *compression, int send_to_cam)
 {
-       unsigned char buf[3];
-       int ret, fps;
+       int fps, ret = 0;
        struct Nala_table_entry *pEntry;
        int frames2frames[31] =
        { /* closest match of framerate */
@@ -194,30 +175,29 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
          7              /* 30    */
        };
 
-       if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+       if (size < 0 || size > PSZ_CIF)
                return -EINVAL;
+       if (frames < 4)
+               frames = 4;
+       else if (frames > 25)
+               frames = 25;
        frames = frames2frames[frames];
        fps = frames2table[frames];
        pEntry = &Nala_table[size][fps];
        if (pEntry->alternate == 0)
                return -EINVAL;
 
-       memcpy(buf, pEntry->mode, 3);
-       ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
-       if (ret < 0) {
-               PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pEntry->mode, 3);
+       if (ret < 0)
                return ret;
-       }
-       if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
-               if (ret < 0)
-                       return ret;
-       }
 
-       pdev->cmd_len = 3;
-       memcpy(pdev->cmd_buf, buf, 3);
+       if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec1_init(pdev, pEntry->mode);
 
        /* Set various parameters */
+       pdev->pixfmt = pixfmt;
        pdev->vframes = frames;
        pdev->valternate = pEntry->alternate;
        pdev->width  = pwc_image_sizes[size][0];
@@ -243,18 +223,20 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
 }
 
 
-static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
-       int *compression)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
 {
-       unsigned char buf[13];
        const struct Timon_table_entry *pChoose;
-       int ret, fps;
+       int fps, ret = 0;
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
-           *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (size == PSZ_VGA && frames > 15)
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
                return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
        fps = (frames / 5) - 1;
 
        /* Find a supported framerate with progressively higher compression */
@@ -268,22 +250,18 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
-       memcpy(buf, pChoose->mode, 13);
-       ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pChoose->mode, 13);
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec23_init(pdev, pdev->type, buf);
-               if (ret < 0)
-                       return ret;
-       }
-
-       pdev->cmd_len = 13;
-       memcpy(pdev->cmd_buf, buf, 13);
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
 
        /* Set various parameters */
-       pdev->vframes = frames;
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
        pdev->valternate = pChoose->alternate;
        pdev->width  = pwc_image_sizes[size][0];
        pdev->height = pwc_image_sizes[size][1];
@@ -296,18 +274,20 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
 }
 
 
-static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
-       int *compression)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
 {
        const struct Kiara_table_entry *pChoose = NULL;
-       int fps, ret;
-       unsigned char buf[12];
+       int fps, ret = 0;
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
-           *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (size == PSZ_VGA && frames > 15)
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
                return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
        fps = (frames / 5) - 1;
 
        /* Find a supported framerate with progressively higher compression */
@@ -320,26 +300,18 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
-       PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
-
-       /* usb_control_msg won't take staticly allocated arrays as argument?? */
-       memcpy(buf, pChoose->mode, 12);
-
        /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
-       ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
+       if (send_to_cam)
+               ret = send_video_command(pdev, 4, pChoose->mode, 12);
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec23_init(pdev, pdev->type, buf);
-               if (ret < 0)
-                       return ret;
-       }
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
 
-       pdev->cmd_len = 12;
-       memcpy(pdev->cmd_buf, buf, 12);
        /* All set and go */
-       pdev->vframes = frames;
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
        pdev->valternate = pChoose->alternate;
        pdev->width  = pwc_image_sizes[size][0];
        pdev->height = pwc_image_sizes[size][1];
@@ -354,22 +326,24 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
 }
 
 int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-       int frames, int *compression)
+       int pixfmt, int frames, int *compression, int send_to_cam)
 {
        int ret, size;
 
-       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
+       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
+                      width, height, frames, pixfmt);
        size = pwc_get_size(pdev, width, height);
        PWC_TRACE("decode_size = %d.\n", size);
 
        if (DEVICE_USE_CODEC1(pdev->type)) {
-               ret = set_video_mode_Nala(pdev, size, frames, compression);
-
+               ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
+                                         compression, send_to_cam);
        } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               ret = set_video_mode_Kiara(pdev, size, frames, compression);
-
+               ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
        } else {
-               ret = set_video_mode_Timon(pdev, size, frames, compression);
+               ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
        }
        if (ret < 0) {
                PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
@@ -436,13 +410,12 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       u8 buf;
 
-       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 1);
        if (ret < 0)
                return ret;
 
-       *data = buf;
+       *data = pdev->ctrl_buf[0];
        return 0;
 }
 
@@ -450,7 +423,8 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
 {
        int ret;
 
-       ret = send_control_msg(pdev, request, value, &data, sizeof(data));
+       pdev->ctrl_buf[0] = data;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
        if (ret < 0)
                return ret;
 
@@ -460,37 +434,34 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
 int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       s8 buf;
 
-       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 1);
        if (ret < 0)
                return ret;
 
-       *data = buf;
+       *data = ((s8 *)pdev->ctrl_buf)[0];
        return 0;
 }
 
 int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       u8 buf[2];
 
-       ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 2);
        if (ret < 0)
                return ret;
 
-       *data = (buf[1] << 8) | buf[0];
+       *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
        return 0;
 }
 
 int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
 {
        int ret;
-       u8 buf[2];
 
-       buf[0] = data & 0xff;
-       buf[1] = data >> 8;
-       ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
+       pdev->ctrl_buf[0] = data & 0xff;
+       pdev->ctrl_buf[1] = data >> 8;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
        if (ret < 0)
                return ret;
 
@@ -511,7 +482,6 @@ int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
 /* POWER */
 void pwc_camera_power(struct pwc_device *pdev, int power)
 {
-       char buf;
        int r;
 
        if (!pdev->power_save)
@@ -521,13 +491,11 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
                return; /* Not supported by Nala or Timon < release 6 */
 
        if (power)
-               buf = 0x00; /* active */
+               pdev->ctrl_buf[0] = 0x00; /* active */
        else
-               buf = 0xFF; /* power save */
-       r = send_control_msg(pdev,
-               SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
-               &buf, sizeof(buf));
-
+               pdev->ctrl_buf[0] = 0xFF; /* power save */
+       r = send_control_msg(pdev, SET_STATUS_CTL,
+               SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
        if (r < 0)
                PWC_ERROR("Failed to power %s camera (%d)\n",
                          power ? "on" : "off", r);
@@ -535,7 +503,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
 
 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
-       unsigned char buf[2];
        int r;
 
        if (pdev->type < 730)
@@ -551,11 +518,11 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
        if (off_value > 0xff)
                off_value = 0xff;
 
-       buf[0] = on_value;
-       buf[1] = off_value;
+       pdev->ctrl_buf[0] = on_value;
+       pdev->ctrl_buf[1] = off_value;
 
        r = send_control_msg(pdev,
-               SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
+               SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
        if (r < 0)
                PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
 
@@ -565,7 +532,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 #ifdef CONFIG_USB_PWC_DEBUG
 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 {
-       unsigned char buf;
        int ret = -1, request;
 
        if (pdev->type < 675)
@@ -575,14 +541,13 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
        else
                request = SENSOR_TYPE_FORMATTER2;
 
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, request, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
        if (ret < 0)
                return ret;
        if (pdev->type < 675)
-               *sensor = buf | 0x100;
+               *sensor = pdev->ctrl_buf[0] | 0x100;
        else
-               *sensor = buf;
+               *sensor = pdev->ctrl_buf[0];
        return 0;
 }
 #endif
index be0e02cb487f1ff2cba5f32fbccd1826056eb93f..e899036aadf4a4734e0dd611386bf47909fe34bb 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
-#include "pwc-dec1.h"
+#include "pwc.h"
 
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer)
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
 {
-       struct pwc_dec1_private *pdec;
+       struct pwc_dec1_private *pdec = &pdev->dec1;
 
-       if (pwc->decompress_data == NULL) {
-               pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
-               if (pdec == NULL)
-                       return -ENOMEM;
-               pwc->decompress_data = pdec;
-       }
-       pdec = pwc->decompress_data;
-
-       return 0;
+       pdec->version = pdev->release;
 }
index a57d8601080babf0ca5ed403aef63220f900f2af..c565ef8f52fb3a83e29f5c428744aaf354b16db6 100644 (file)
 #ifndef PWC_DEC1_H
 #define PWC_DEC1_H
 
-#include "pwc.h"
+#include <linux/mutex.h>
+
+struct pwc_device;
 
 struct pwc_dec1_private
 {
        int version;
 };
 
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer);
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
 
 #endif
index 2c6709112b2f2c4d206e40701505658c73483a38..3792fedff9515e85734200d8ffb22aa1ed15bb93 100644 (file)
@@ -294,22 +294,17 @@ static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
 
 
 /* If the type or the command change, we rebuild the lookup table */
-int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
 {
        int flags, version, shift, i;
-       struct pwc_dec23_private *pdec;
-
-       if (pwc->decompress_data == NULL) {
-               pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-               if (pdec == NULL)
-                       return -ENOMEM;
-               pwc->decompress_data = pdec;
-       }
-       pdec = pwc->decompress_data;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
 
        mutex_init(&pdec->lock);
 
-       if (DEVICE_USE_CODEC3(type)) {
+       if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
+               return;
+
+       if (DEVICE_USE_CODEC3(pdev->type)) {
                flags = cmd[2] & 0x18;
                if (flags == 8)
                        pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
@@ -356,7 +351,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
                pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
 #endif
 
-       return 0;
+       pdec->last_cmd = cmd[2];
+       pdec->last_cmd_valid = 1;
 }
 
 /*
@@ -659,12 +655,12 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
  * src: raw data
  * dst: image output
  */
-void pwc_dec23_decompress(const struct pwc_device *pwc,
+void pwc_dec23_decompress(struct pwc_device *pdev,
                          const void *src,
                          void *dst)
 {
        int bandlines_left, bytes_per_block;
-       struct pwc_dec23_private *pdec = pwc->decompress_data;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
 
        /* YUV420P image format */
        unsigned char *pout_planar_y;
@@ -674,23 +670,22 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
 
        mutex_lock(&pdec->lock);
 
-       bandlines_left = pwc->height / 4;
-       bytes_per_block = pwc->width * 4;
-       plane_size = pwc->height * pwc->width;
+       bandlines_left = pdev->height / 4;
+       bytes_per_block = pdev->width * 4;
+       plane_size = pdev->height * pdev->width;
 
        pout_planar_y = dst;
        pout_planar_u = dst + plane_size;
        pout_planar_v = dst + plane_size + plane_size / 4;
 
        while (bandlines_left--) {
-               DecompressBand23(pwc->decompress_data,
-                                src,
+               DecompressBand23(pdec, src,
                                 pout_planar_y, pout_planar_u, pout_planar_v,
-                                pwc->width, pwc->width);
-               src += pwc->vbandlength;
+                                pdev->width, pdev->width);
+               src += pdev->vbandlength;
                pout_planar_y += bytes_per_block;
-               pout_planar_u += pwc->width;
-               pout_planar_v += pwc->width;
+               pout_planar_u += pdev->width;
+               pout_planar_v += pdev->width;
        }
        mutex_unlock(&pdec->lock);
 }
index d64a3c281af6aa0d5fe03471c5cd03d16f010588..c655b1c1e6a9f7d7c7e8ff725672190bb2829e0c 100644 (file)
 #ifndef PWC_DEC23_H
 #define PWC_DEC23_H
 
-#include "pwc.h"
+struct pwc_device;
 
 struct pwc_dec23_private
 {
        struct mutex lock;
 
+       unsigned char last_cmd, last_cmd_valid;
+
   unsigned int scalebits;
   unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
 
   unsigned int reservoir;
   unsigned int nbits_in_reservoir;
+
   const unsigned char *stream;
   int temp_colors[16];
 
@@ -51,8 +54,8 @@ struct pwc_dec23_private
 
 };
 
-int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
-void pwc_dec23_decompress(const struct pwc_device *pwc,
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
+void pwc_dec23_decompress(struct pwc_device *pdev,
                          const void *src,
                          void *dst);
 #endif
index 943d37ad0d33dd3983318bbddd0f4d19f185f55b..122fbd0081eb548a3416f2848661cc144066a78b 100644 (file)
@@ -128,18 +128,11 @@ static struct usb_driver pwc_driver = {
 #define MAX_DEV_HINTS  20
 #define MAX_ISOC_ERRORS        20
 
-static int default_fps = 10;
 #ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
 static int power_save = -1;
-static int led_on = 100, led_off; /* defaults to LED that is on while in use */
-static struct {
-       int type;
-       char serial_number[30];
-       int device_node;
-       struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
+static int leds[2] = { 100, 0 };
 
 /***/
 
@@ -386,8 +379,8 @@ static int pwc_isoc_init(struct pwc_device *pdev)
 retry:
        /* We first try with low compression and then retry with a higher
           compression setting if there is not enough bandwidth. */
-       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
-                                pdev->vframes, &compression);
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                pdev->vframes, &compression, 1);
 
        /* Get the current alternate interface, adjust packet size */
        intf = usb_ifnum_to_if(udev, 0);
@@ -597,23 +590,9 @@ leave:
 static void pwc_video_release(struct v4l2_device *v)
 {
        struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
-       int hint;
-
-       /* search device_hint[] table if we occupy a slot, by any chance */
-       for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-               if (device_hint[hint].pdev == pdev)
-                       device_hint[hint].pdev = NULL;
-
-       /* Free intermediate decompression buffer & tables */
-       if (pdev->decompress_data != NULL) {
-               PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
-                                pdev->decompress_data);
-               kfree(pdev->decompress_data);
-               pdev->decompress_data = NULL;
-       }
 
        v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-
+       kfree(pdev->ctrl_buf);
        kfree(pdev);
 }
 
@@ -758,7 +737,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
 
        /* Turn on camera and set LEDS on */
        pwc_camera_power(pdev, 1);
-       pwc_set_leds(pdev, led_on, led_off);
+       pwc_set_leds(pdev, leds[0], leds[1]);
 
        r = pwc_isoc_init(pdev);
        if (r) {
@@ -813,10 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        struct usb_device *udev = interface_to_usbdev(intf);
        struct pwc_device *pdev = NULL;
        int vendor_id, product_id, type_id;
-       int hint, rc;
+       int rc;
        int features = 0;
        int compression = 0;
-       int video_nr = -1; /* default: use next available device */
        int my_power_save = power_save;
        char serial_number[30], *name;
 
@@ -1076,7 +1054,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                return -ENOMEM;
        }
        pdev->type = type_id;
-       pdev->vframes = default_fps;
        pdev->features = features;
        pwc_construct(pdev); /* set min/max sizes correct */
 
@@ -1107,24 +1084,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
        PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
 
-       /* Now search device_hint[] table for a match, so we can hint a node number. */
-       for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
-               if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
-                    (device_hint[hint].pdev == NULL)) {
-                       /* so far, so good... try serial number */
-                       if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-                               /* match! */
-                               video_nr = device_hint[hint].device_node;
-                               PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
-                               break;
-                       }
-               }
+       /* Allocate USB command buffers */
+       pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+       if (!pdev->ctrl_buf) {
+               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+               rc = -ENOMEM;
+               goto err_free_mem;
        }
 
-       /* occupy slot */
-       if (hint < MAX_DEV_HINTS)
-               device_hint[hint].pdev = pdev;
-
 #ifdef CONFIG_USB_PWC_DEBUG
        /* Query sensor type */
        if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1138,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pwc_set_leds(pdev, 0, 0);
 
        /* Setup intial videomode */
-       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
-                               &compression);
+       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
+                               V4L2_PIX_FMT_YUV420, 30, &compression, 1);
        if (rc)
                goto err_free_mem;
 
@@ -1164,7 +1131,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
        pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
 
-       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
        if (rc < 0) {
                PWC_ERROR("Failed to register as video device (%d).\n", rc);
                goto err_unregister_v4l2_dev;
@@ -1207,8 +1174,7 @@ err_unregister_v4l2_dev:
 err_free_controls:
        v4l2_ctrl_handler_free(&pdev->ctrl_handler);
 err_free_mem:
-       if (hint < MAX_DEV_HINTS)
-               device_hint[hint].pdev = NULL;
+       kfree(pdev->ctrl_buf);
        kfree(pdev);
        return rc;
 }
@@ -1243,27 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
  * Initialization code & module stuff
  */
 
-static int fps;
-static int leds[2] = { -1, -1 };
 static unsigned int leds_nargs;
-static char *dev_hint[MAX_DEV_HINTS];
-static unsigned int dev_hint_nargs;
 
-module_param(fps, int, 0444);
 #ifdef CONFIG_USB_PWC_DEBUG
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
 module_param(power_save, int, 0644);
 module_param_array(leds, int, &leds_nargs, 0444);
-module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
 
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
 #ifdef CONFIG_USB_PWC_DEBUG
 MODULE_PARM_DESC(trace, "For debugging purposes");
 #endif
 MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@@ -1273,114 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
 
 static int __init usb_pwc_init(void)
 {
-       int i;
-
-#ifdef CONFIG_USB_PWC_DEBUG
-       PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
-       PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
-       PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
-       PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
-
-       if (pwc_trace >= 0) {
-               PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
-       }
-#endif
-
-       if (fps) {
-               if (fps < 4 || fps > 30) {
-                       PWC_ERROR("Framerate out of bounds (4-30).\n");
-                       return -EINVAL;
-               }
-               default_fps = fps;
-               PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
-       }
-
-       if (leds[0] >= 0)
-               led_on = leds[0];
-       if (leds[1] >= 0)
-               led_off = leds[1];
-
-       /* Big device node whoopla. Basically, it allows you to assign a
-          device node (/dev/videoX) to a camera, based on its type
-          & serial number. The format is [type[.serialnumber]:]node.
-
-          Any camera that isn't matched by these rules gets the next
-          available free device node.
-        */
-       for (i = 0; i < MAX_DEV_HINTS; i++) {
-               char *s, *colon, *dot;
-
-               /* This loop also initializes the array */
-               device_hint[i].pdev = NULL;
-               s = dev_hint[i];
-               if (s != NULL && *s != '\0') {
-                       device_hint[i].type = -1; /* wildcard */
-                       strcpy(device_hint[i].serial_number, "*");
-
-                       /* parse string: chop at ':' & '/' */
-                       colon = dot = s;
-                       while (*colon != '\0' && *colon != ':')
-                               colon++;
-                       while (*dot != '\0' && *dot != '.')
-                               dot++;
-                       /* Few sanity checks */
-                       if (*dot != '\0' && dot > colon) {
-                               PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
-                               return -EINVAL;
-                       }
-
-                       if (*colon == '\0') {
-                               /* No colon */
-                               if (*dot != '\0') {
-                                       PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
-                                       return -EINVAL;
-                               }
-                               else {
-                                       /* No type or serial number specified, just a number. */
-                                       device_hint[i].device_node =
-                                               simple_strtol(s, NULL, 10);
-                               }
-                       }
-                       else {
-                               /* There's a colon, so we have at least a type and a device node */
-                               device_hint[i].type =
-                                       simple_strtol(s, NULL, 10);
-                               device_hint[i].device_node =
-                                       simple_strtol(colon + 1, NULL, 10);
-                               if (*dot != '\0') {
-                                       /* There's a serial number as well */
-                                       int k;
-
-                                       dot++;
-                                       k = 0;
-                                       while (*dot != ':' && k < 29) {
-                                               device_hint[i].serial_number[k++] = *dot;
-                                               dot++;
-                                       }
-                                       device_hint[i].serial_number[k] = '\0';
-                               }
-                       }
-                       PWC_TRACE("device_hint[%d]:\n", i);
-                       PWC_TRACE("  type    : %d\n", device_hint[i].type);
-                       PWC_TRACE("  serial# : %s\n", device_hint[i].serial_number);
-                       PWC_TRACE("  node    : %d\n", device_hint[i].device_node);
-               }
-               else
-                       device_hint[i].type = 0; /* not filled */
-       } /* ..for MAX_DEV_HINTS */
-
-       PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
        return usb_register(&pwc_driver);
 }
 
 static void __exit usb_pwc_exit(void)
 {
-       PWC_DEBUG_MODULE("Deregistering driver.\n");
        usb_deregister(&pwc_driver);
-       PWC_INFO("Philips webcam module removed.\n");
 }
 
 module_init(usb_pwc_init);
 module_exit(usb_pwc_exit);
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 23a55b5814fc494ea2f2c95e8fb37b4142769726..9be5adffa874683929ec57d41e17eeb36bf600aa 100644 (file)
@@ -90,5 +90,4 @@ void pwc_construct(struct pwc_device *pdev)
                pdev->frame_header_size = 0;
                pdev->frame_trailer_size = 0;
        }
-       pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
 }
index 80e25842e84a218dc3dada13e96ced27e68c3b39..f495eeb5403aaff31dd66ba582a07d86297752b9 100644 (file)
@@ -493,16 +493,11 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
                        (pixelformat>>24)&255);
 
        ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
-                                pdev->vframes, &compression);
+                                pixelformat, 30, &compression, 0);
 
        PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
 
-       if (ret == 0) {
-               pdev->pixfmt = pixelformat;
-               pwc_vidioc_fill_fmt(f, pdev->width, pdev->height,
-                                   pdev->pixfmt);
-       }
-
+       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
 leave:
        mutex_unlock(&pdev->udevlock);
        return ret;
@@ -777,33 +772,33 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
 static int pwc_set_motor(struct pwc_device *pdev)
 {
        int ret;
-       u8 buf[4];
 
-       buf[0] = 0;
+       pdev->ctrl_buf[0] = 0;
        if (pdev->motor_pan_reset->is_new)
-               buf[0] |= 0x01;
+               pdev->ctrl_buf[0] |= 0x01;
        if (pdev->motor_tilt_reset->is_new)
-               buf[0] |= 0x02;
+               pdev->ctrl_buf[0] |= 0x02;
        if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
                ret = send_control_msg(pdev, SET_MPT_CTL,
-                                      PT_RESET_CONTROL_FORMATTER, buf, 1);
+                                      PT_RESET_CONTROL_FORMATTER,
+                                      pdev->ctrl_buf, 1);
                if (ret < 0)
                        return ret;
        }
 
-       memset(buf, 0, sizeof(buf));
+       memset(pdev->ctrl_buf, 0, 4);
        if (pdev->motor_pan->is_new) {
-               buf[0] = pdev->motor_pan->val & 0xFF;
-               buf[1] = (pdev->motor_pan->val >> 8);
+               pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
+               pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
        }
        if (pdev->motor_tilt->is_new) {
-               buf[2] = pdev->motor_tilt->val & 0xFF;
-               buf[3] = (pdev->motor_tilt->val >> 8);
+               pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
+               pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
        }
        if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
                ret = send_control_msg(pdev, SET_MPT_CTL,
                                       PT_RELATIVE_CONTROL_FORMATTER,
-                                      buf, sizeof(buf));
+                                      pdev->ctrl_buf, 4);
                if (ret < 0)
                        return ret;
        }
@@ -1094,6 +1089,63 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
        return 0;
 }
 
+static int pwc_g_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(parm, 0, sizeof(*parm));
+
+       parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       parm->parm.capture.readbuffers = MIN_FRAMES;
+       parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.timeperframe.denominator = pdev->vframes;
+       parm->parm.capture.timeperframe.numerator = 1;
+
+       return 0;
+}
+
+static int pwc_s_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int compression = 0;
+       int ret, fps;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           parm->parm.capture.timeperframe.numerator == 0)
+               return -EINVAL;
+
+       if (pwc_test_n_set_capt_file(pdev, file))
+               return -EBUSY;
+
+       fps = parm->parm.capture.timeperframe.denominator /
+             parm->parm.capture.timeperframe.numerator;
+
+       mutex_lock(&pdev->udevlock);
+       if (!pdev->udev) {
+               ret = -ENODEV;
+               goto leave;
+       }
+
+       if (pdev->iso_init) {
+               ret = -EBUSY;
+               goto leave;
+       }
+
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                fps, &compression, 0);
+
+       pwc_g_parm(file, fh, parm);
+
+leave:
+       mutex_unlock(&pdev->udevlock);
+       return ret;
+}
+
 static int pwc_log_status(struct file *file, void *priv)
 {
        struct pwc_device *pdev = video_drvdata(file);
@@ -1120,4 +1172,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
        .vidioc_log_status                  = pwc_log_status,
        .vidioc_enum_framesizes             = pwc_enum_framesizes,
        .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
+       .vidioc_g_parm                      = pwc_g_parm,
+       .vidioc_s_parm                      = pwc_s_parm,
 };
index 47c518fef179949be25f50c51eac12f95ea7c819..e4d4d711dd1f4df7182d20bcc3591fda9e32f628 100644 (file)
@@ -44,6 +44,8 @@
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/input.h>
 #endif
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 /* Version block */
 #define PWC_VERSION    "10.0.15"
 #define DEVICE_USE_CODEC3(x) ((x)>=700)
 #define DEVICE_USE_CODEC23(x) ((x)>=675)
 
-/* from pwc-dec.h */
-#define PWCX_FLAG_PLANAR        0x0001
-
 /* Request types: video */
 #define SET_LUM_CTL                    0x01
 #define GET_LUM_CTL                    0x02
@@ -248,8 +247,8 @@ struct pwc_device
        char vmirror;           /* for ToUCaM series */
        char power_save;        /* Do powersaving for this cam */
 
-       int cmd_len;
        unsigned char cmd_buf[13];
+       unsigned char *ctrl_buf;
 
        struct urb *urbs[MAX_ISO_BUFS];
        char iso_init;
@@ -272,7 +271,10 @@ struct pwc_device
        int frame_total_size;   /* including header & trailer */
        int drop_frames;
 
-       void *decompress_data;  /* private data for decompression engine */
+       union { /* private data for decompression engine */
+               struct pwc_dec1_private dec1;
+               struct pwc_dec23_private dec23;
+       };
 
        /*
         * We have an 'image' and a 'view', where 'image' is the fixed-size img
@@ -364,7 +366,7 @@ void pwc_construct(struct pwc_device *pdev);
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-                             int frames, int *compression);
+       int pixfmt, int frames, int *compression, int send_to_cam);
 extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
index 510cfab477fff48c57ddd2d9151b53ec144f91ea..a9e9653beeb4581a90ea34eed1b3d96eab2aae5d 100644 (file)
@@ -693,7 +693,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                        mf->code = 0;
                        continue;
                }
-               if (mf->width != tfmt->width || mf->width != tfmt->width) {
+               if (mf->width != tfmt->width || mf->height != tfmt->height) {
                        u32 fcc = ffmt->fourcc;
                        tfmt->width  = mf->width;
                        tfmt->height = mf->height;
@@ -702,7 +702,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                                               NULL, &fcc, FIMC_SD_PAD_SOURCE);
                        if (ffmt && ffmt->mbus_code)
                                mf->code = ffmt->mbus_code;
-                       if (mf->width != tfmt->width || mf->width != tfmt->width)
+                       if (mf->width != tfmt->width ||
+                           mf->height != tfmt->height)
                                continue;
                        tfmt->code = mf->code;
                }
@@ -710,7 +711,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                        ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
 
                if (mf->code == tfmt->code &&
-                   mf->width == tfmt->width && mf->width == tfmt->width)
+                   mf->width == tfmt->width && mf->height == tfmt->height)
                        break;
        }
 
index f5cbb8a4c540fc7d6beac2891c36aa812f05f281..81bcbb9492ea0a6d425375a57f3600837082d773 100644 (file)
@@ -848,11 +848,11 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
        v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
 
        ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                    V4L2_CID_HFLIP, 0, 1, 1, 0);
+                                       V4L2_CID_ROTATE, 0, 270, 90, 0);
        ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                   V4L2_CID_VFLIP, 0, 1, 1, 0);
+                                       V4L2_CID_HFLIP, 0, 1, 1, 0);
        ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                   V4L2_CID_ROTATE, 0, 270, 90, 0);
+                                       V4L2_CID_VFLIP, 0, 1, 1, 0);
        if (variant->has_alpha)
                ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
                                    &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
index 615c862f0360ef20061e28701d1a99f460d0a7e1..8ea4ee116e46900224a528fa415d300d2c43196b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <media/v4l2-ctrls.h>
 #include <media/media-device.h>
 
index c40b0dde188353eb9dba6b9f88e894c7f586d4c3..febaa673d3635c019011ff174c70eee17818de17 100644 (file)
@@ -184,6 +184,7 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
                        ctx->rop = ROP4_INVERT;
                else
                        ctx->rop = ROP4_COPY;
+               break;
        default:
                v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
                return -EINVAL;
index f841a3e9845c6f6a00028884beedd27595a0da1e..1105a8749c8b23922c979adf2abe7dee222fe14c 100644 (file)
@@ -989,9 +989,10 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
  * ============================================================================
  */
 
-static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
+                          const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
 {
        struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
        struct s5p_jpeg_q_data *q_data = NULL;
index e43e128baf5f7c3ec7051337a1574821e9e863a2..83fe461af263529df7502f020886f58d63b68c1c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
@@ -475,7 +474,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                        ctx->mv_size = 0;
                }
                ctx->dpb_count = s5p_mfc_get_dpb_count();
-               if (ctx->img_width == 0 || ctx->img_width == 0)
+               if (ctx->img_width == 0 || ctx->img_height == 0)
                        ctx->state = MFCINST_ERROR;
                else
                        ctx->state = MFCINST_HEAD_PARSED;
index 844a4d7797bc0be85ff01eae08837d5d49dbee69..c25ec022d2678f734e46b1f1f3b5b0d496150c8d 100644 (file)
@@ -165,7 +165,7 @@ static struct mfc_control controls[] = {
                .maximum = 32,
                .step = 1,
                .default_value = 1,
-               .flags = V4L2_CTRL_FLAG_VOLATILE,
+               .is_volatile = 1,
        },
 };
 
index 971591d6450fccc5a7164adb94cb40e3404fb635..5b72da5ce4183c15bf98dd570762f2f8f2ffb9de 100644 (file)
@@ -269,8 +269,6 @@ struct saa7164_board saa7164_boards[] = {
                .portb          = SAA7164_MPEG_DVB,
                .portc          = SAA7164_MPEG_ENCODER,
                .portd          = SAA7164_MPEG_ENCODER,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
                .porte          = SAA7164_MPEG_VBI,
                .portf          = SAA7164_MPEG_VBI,
                .chiprev        = SAA7164_CHIP_REV3,
@@ -333,8 +331,6 @@ struct saa7164_board saa7164_boards[] = {
                .portd          = SAA7164_MPEG_ENCODER,
                .porte          = SAA7164_MPEG_VBI,
                .portf          = SAA7164_MPEG_VBI,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
                .chiprev        = SAA7164_CHIP_REV3,
                .unit           = {{
                        .id             = 0x28,
index 129f135d5a5fe1deffaa12fdc81611bd2ecd12d4..c096b3f742003bcbcfc40df79b49a2728f8b9539 100644 (file)
@@ -374,7 +374,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
 }
 #endif
 
-static bool check_firmware(struct usb_device *udev, int *down_firmware)
+static int check_firmware(struct usb_device *udev, int *down_firmware)
 {
        void *buf;
        int ret;
@@ -398,7 +398,7 @@ static bool check_firmware(struct usb_device *udev, int *down_firmware)
                *down_firmware = 1;
                return firmware_download(udev);
        }
-       return ret;
+       return 0;
 }
 
 static int poseidon_probe(struct usb_interface *interface,
index da1f4c2d2d4b8d217cd2e3dafc716b88a25ef762..cccd42be718ae7cc25d2b21189f9880528f38225 100644 (file)
@@ -465,8 +465,8 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_CHROMA_GAIN:              return "Chroma Gain";
        case V4L2_CID_ILLUMINATORS_1:           return "Illuminator 1";
        case V4L2_CID_ILLUMINATORS_2:           return "Illuminator 2";
-       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Minimum Number of Capture Buffers";
-       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Minimum Number of Output Buffers";
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Min Number of Capture Buffers";
+       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Min Number of Output Buffers";
        case V4L2_CID_ALPHA_COMPONENT:          return "Alpha Component";
 
        /* MPEG controls */
@@ -506,25 +506,25 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:      return "Video Mute YUV";
        case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:       return "Decoder Slice Interface";
        case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:  return "MPEG4 Loop Filter Enable";
-       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:       return "The Number of Intra Refresh MBs";
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:       return "Number of Intra Refresh MBs";
        case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:               return "Frame Level Rate Control Enable";
        case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:                  return "H264 MB Level Rate Control";
        case V4L2_CID_MPEG_VIDEO_HEADER_MODE:                   return "Sequence Header Mode";
-       case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:                   return "The Max Number of Reference Picture";
+       case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:                   return "Max Number of Reference Pics";
        case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:               return "H263 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:               return "H263 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:               return "H263 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:               return "H263 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:               return "H263 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:                   return "H263 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:                   return "H263 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:               return "H264 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:               return "H264 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:               return "H264 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:               return "H264 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:               return "H264 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:                   return "H264 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:                   return "H264 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:            return "H264 8x8 Transform Enable";
        case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:                 return "H264 CPB Buffer Size";
-       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:             return "H264 Entorpy Mode";
-       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:                 return "H264 I Period";
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:             return "H264 Entropy Mode";
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:                 return "H264 I-Frame Period";
        case V4L2_CID_MPEG_VIDEO_H264_LEVEL:                    return "H264 Level";
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:        return "H264 Loop Filter Alpha Offset";
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:         return "H264 Loop Filter Beta Offset";
@@ -535,16 +535,16 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:           return "Aspect Ratio VUI Enable";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:              return "VUI Aspect Ratio IDC";
        case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:              return "MPEG4 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:                  return "MPEG4 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:                  return "MPEG4 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:                   return "MPEG4 Level";
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:                 return "MPEG4 Profile";
        case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:                    return "Quarter Pixel Search Enable";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:         return "The Maximum Bytes Per Slice";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:            return "The Number of MB in a Slice";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:              return "The Slice Partitioning Method";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:         return "Maximum Bytes in a Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:            return "Number of MBs in a Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:              return "Slice Partitioning Method";
        case V4L2_CID_MPEG_VIDEO_VBV_SIZE:                      return "VBV Buffer Size";
 
        /* CAMERA controls */
@@ -580,7 +580,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_AUDIO_LIMITER_ENABLED:    return "Audio Limiter Feature Enabled";
        case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
        case V4L2_CID_AUDIO_LIMITER_DEVIATION:  return "Audio Limiter Deviation";
-       case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
+       case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
        case V4L2_CID_AUDIO_COMPRESSION_GAIN:   return "Audio Compression Gain";
        case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
        case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
@@ -588,24 +588,24 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_PILOT_TONE_ENABLED:       return "Pilot Tone Feature Enabled";
        case V4L2_CID_PILOT_TONE_DEVIATION:     return "Pilot Tone Deviation";
        case V4L2_CID_PILOT_TONE_FREQUENCY:     return "Pilot Tone Frequency";
-       case V4L2_CID_TUNE_PREEMPHASIS:         return "Pre-emphasis settings";
+       case V4L2_CID_TUNE_PREEMPHASIS:         return "Pre-Emphasis";
        case V4L2_CID_TUNE_POWER_LEVEL:         return "Tune Power Level";
        case V4L2_CID_TUNE_ANTENNA_CAPACITOR:   return "Tune Antenna Capacitor";
 
        /* Flash controls */
-       case V4L2_CID_FLASH_CLASS:              return "Flash controls";
-       case V4L2_CID_FLASH_LED_MODE:           return "LED mode";
-       case V4L2_CID_FLASH_STROBE_SOURCE:      return "Strobe source";
+       case V4L2_CID_FLASH_CLASS:              return "Flash Controls";
+       case V4L2_CID_FLASH_LED_MODE:           return "LED Mode";
+       case V4L2_CID_FLASH_STROBE_SOURCE:      return "Strobe Source";
        case V4L2_CID_FLASH_STROBE:             return "Strobe";
-       case V4L2_CID_FLASH_STROBE_STOP:        return "Stop strobe";
-       case V4L2_CID_FLASH_STROBE_STATUS:      return "Strobe status";
-       case V4L2_CID_FLASH_TIMEOUT:            return "Strobe timeout";
-       case V4L2_CID_FLASH_INTENSITY:          return "Intensity, flash mode";
-       case V4L2_CID_FLASH_TORCH_INTENSITY:    return "Intensity, torch mode";
-       case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
+       case V4L2_CID_FLASH_STROBE_STOP:        return "Stop Strobe";
+       case V4L2_CID_FLASH_STROBE_STATUS:      return "Strobe Status";
+       case V4L2_CID_FLASH_TIMEOUT:            return "Strobe Timeout";
+       case V4L2_CID_FLASH_INTENSITY:          return "Intensity, Flash Mode";
+       case V4L2_CID_FLASH_TORCH_INTENSITY:    return "Intensity, Torch Mode";
+       case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
        case V4L2_CID_FLASH_FAULT:              return "Faults";
        case V4L2_CID_FLASH_CHARGE:             return "Charge";
-       case V4L2_CID_FLASH_READY:              return "Ready to strobe";
+       case V4L2_CID_FLASH_READY:              return "Ready to Strobe";
 
        default:
                return NULL;
index 77feeb67e2db389334e186299c882ce4fd87e847..3f623859a337126aa035df7c00817a6ad5da6fee 100644 (file)
@@ -1871,6 +1871,7 @@ static long __video_do_ioctl(struct file *file,
        case VIDIOC_S_FREQUENCY:
        {
                struct v4l2_frequency *p = arg;
+               enum v4l2_tuner_type type;
 
                if (!ops->vidioc_s_frequency)
                        break;
@@ -1878,9 +1879,14 @@ static long __video_do_ioctl(struct file *file,
                        ret = ret_prio;
                        break;
                }
+               type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+                       V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
                dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
                                p->tuner, p->type, p->frequency);
-               ret = ops->vidioc_s_frequency(file, fh, p);
+               if (p->type != type)
+                       ret = -EINVAL;
+               else
+                       ret = ops->vidioc_s_frequency(file, fh, p);
                break;
        }
        case VIDIOC_G_SLICED_VBI_CAP:
index f6d26419445ee8728367fe925ed3f80d2d484092..4c09ab781ec3a3cbf503f2626c64b449e94dabf3 100644 (file)
@@ -1958,7 +1958,6 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
        mutex_unlock(&zr->resource_lock);
        fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
        fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->flags = V4L2_FBUF_FLAG_OVERLAY;
        fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
 
        return 0;
index 89c290b69a5c6bf345f7d6e27d3b1921301b87fc..29e1920e7339867124e3605e1afd1a2777d66e8a 100644 (file)
 #define TUNER_PHILIPS_FMD1216MEX_MK3   78
 #define TUNER_PHILIPS_FM1216MK5                79
 #define TUNER_PHILIPS_FQ1216LME_MK3    80      /* Active loopthrough, no FM */
-#define TUNER_XC4000                   81      /* Xceive Silicon Tuner */
 
 #define TUNER_PARTSNIC_PTI_5NF05       81
 #define TUNER_PHILIPS_CU1216L           82
 #define TUNER_PHILIPS_FQ1236_MK5       85      /* NTSC, TDA9885, no FM radio */
 #define TUNER_TENA_TNF_5337            86
 
+#define TUNER_XC4000                   87      /* Xceive Silicon Tuner */
+
 /* tv card specific */
 #define TDA9887_PRESENT                (1<<0)
 #define TDA9887_PORT1_INACTIVE                 (1<<1)