Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

* '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
  ...
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
index ffee1fb..c7a4ca5 100644
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ b/Documentation/DocBook/media/dvb/dvbproperty.xml
@@ -163,14 +163,16 @@
 	<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 @@
 			<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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index 6f1f9a6..b17a7aa 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -183,7 +183,12 @@
 	    <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 @@
 	  <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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
index 93817f3..7c63815 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
@@ -364,15 +364,20 @@
 	  <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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
index 1643181..66e9a52 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
@@ -98,8 +98,11 @@
 	    <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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-input.xml b/Documentation/DocBook/media/v4l/vidioc-g-input.xml
index 08ae82f..1d43065 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-input.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-input.xml
@@ -61,8 +61,8 @@
 <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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-output.xml b/Documentation/DocBook/media/v4l/vidioc-g-output.xml
index fd45f1c..4533068 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-output.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-output.xml
@@ -61,8 +61,9 @@
 <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>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index d725c0d..1bea46a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -439,17 +439,6 @@
 
 ----------------------------
 
-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
diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 26aa057..e2492a9 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -666,27 +666,6 @@
 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
 ========================
 
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 2755599..b5ee3eb 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -24,6 +24,21 @@
 #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 @@
 	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 @@
 		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 @@
 
 	/* 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 @@
 	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 */
 
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
index d218c1d..6839711 100644
--- a/drivers/media/common/tuners/xc4000.c
+++ b/drivers/media/common/tuners/xc4000.c
@@ -154,6 +154,8 @@
 #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 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	.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
 };
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index b15db4f..fbbe545 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -904,8 +904,11 @@
 {
 	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 @@
 	_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 @@
 	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 @@
 {
 	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 @@
 
 		/*
 		 * 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)
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index d661929..1455e26 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -877,24 +877,18 @@
 	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;
 
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 9bd6d51..7de125c 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -48,6 +48,8 @@
 	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];
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 2069994..070e82a 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -834,6 +834,7 @@
 
 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");
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 81ef4b4..f9e966a 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -3066,19 +3066,25 @@
 	}
 };
 
+static void stk7070pd_init(struct dvb_usb_device *dev)
+{
+	dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1);
+	msleep(10);
+	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(dev, 72, 1);
+
+	msleep(10);
+	dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1);
+}
+
 static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
 {
-	dib0700_set_gpio(adap->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);
+	stk7070pd_init(adap->dev);
 
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
@@ -3099,6 +3105,77 @@
 	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,
@@ -3870,6 +3947,57 @@
 				.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 = {
+			{
+			.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  = stk7070pd_frontend_attach0,
 				.tuner_attach     = dib7070p_tuner_attach,
 
@@ -3892,7 +4020,7 @@
 			}
 		},
 
-		.num_device_descs = 6,
+		.num_device_descs = 5,
 		.devices = {
 			{   "DiBcom STK7070PD reference design",
 				{ &dib0700_usb_id_table[17], NULL },
@@ -3902,10 +4030,6 @@
 				{ &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 },
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index 93e1b12..caae7f7 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -309,9 +309,14 @@
 
 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 @@
 	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 @@
 	/* frontend lock wait loop count */
 	switch (priv->delivery_system) {
 	case SYS_DVBT:
+	case SYS_DVBC_ANNEX_A:
 		i = 20;
 		break;
 	case SYS_DVBT2:
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 9387770..af65d01 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -1195,7 +1195,7 @@
 
 	for (i = 0; i < 30 ; i++) {
 		ds3000_read_status(fe, &status);
-		if (status && FE_HAS_LOCK)
+		if (status & FE_HAS_LOCK)
 			break;
 
 		msleep(10);
diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
index 7fa3e47..fade566 100644
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -402,7 +402,7 @@
 		[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 @@
 		[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 @@
 		[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 @@
 		[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)
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c
index 86da3d8..ad7c72e 100644
--- a/drivers/media/dvb/frontends/tda18271c2dd.c
+++ b/drivers/media/dvb/frontends/tda18271c2dd.c
@@ -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"
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c
index ec859a5..f241702 100644
--- a/drivers/media/video/as3645a.c
+++ b/drivers/media/video/as3645a.c
@@ -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>
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 14cb961..4bfd865 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -751,20 +751,10 @@
 
 	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 @@
 		}
 		/* 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 @@
 
 	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 @@
 		/* Done! Unmute and continue. */
 		cx18_unmute(cx);
 	}
-	v4l2_fh_add(&item->fh);
 	return 0;
 }
 
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 919ed77..875a7ce 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -1052,7 +1052,7 @@
 	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;
 	}
 
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 3c01be9..19b5499 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -213,8 +213,8 @@
 		.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 |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index af8a225..6835eb1 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -943,6 +943,11 @@
 
 			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:
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 4bbf9bb..c654bdc 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -1550,7 +1550,6 @@
 	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 @@
 		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;
 
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 62c7ad0..cbd5d11 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1573,8 +1573,8 @@
 		.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 @@
 		.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 @@
 		.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 @@
 	[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 @@
 	[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 @@
 	[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
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 544af91..3949b7d 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -731,9 +731,6 @@
 
 	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;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 8f9cc17..06f3d78 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -332,7 +332,7 @@
 	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_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;
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 38f0522..2cd6c89 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -50,16 +50,16 @@
 
 	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 @@
 		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 @@
 	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 @@
 		/* 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 @@
 		}
 
 		/* 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 @@
 	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 @@
 
 	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 @@
 	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 @@
 			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 @@
 			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 @@
 	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 @@
 		     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 @@
 
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 				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))
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index ecafa69..c4bc481 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -179,6 +179,7 @@
 		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 @@
 			schedule();
 		}
 		finish_wait(&itv->dma_waitq, &wait);
+		mutex_lock(&itv->serialize_lock);
 		if (got_sig)
 			return -EINTR;
 
@@ -1107,6 +1109,7 @@
 	 * 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 @@
 		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 @@
 	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 @@
 	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,
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index 9c29e96..1b3b957 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -288,13 +288,13 @@
 			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);
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index e7794dc..c6e28b4 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -159,7 +159,6 @@
 		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 @@
 	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;
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index dcbab6a..2ad65eb 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -1149,23 +1149,37 @@
 {
 	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 @@
 	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);
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index a277f95..1fb7d5b 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -1042,7 +1042,8 @@
 	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 @@
 	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;
 
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 905d41d..1f506fd 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -104,47 +104,16 @@
 
 /****************************************************************************/
 
-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 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 @@
 	  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_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)
+	if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
 		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		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 @@
 	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_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)
+	if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
 		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		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 @@
 	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 @@
 }
 
 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 @@
 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 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_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 @@
 /* POWER */
 void pwc_camera_power(struct pwc_device *pdev, int power)
 {
-	char buf;
 	int r;
 
 	if (!pdev->power_save)
@@ -521,13 +491,11 @@
 		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 @@
 
 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 @@
 	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 @@
 #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 @@
 	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
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
index be0e02c..e899036 100644
--- a/drivers/media/video/pwc/pwc-dec1.c
+++ b/drivers/media/video/pwc/pwc-dec1.c
@@ -22,19 +22,11 @@
    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;
 }
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
index a57d860..c565ef8 100644
--- a/drivers/media/video/pwc/pwc-dec1.h
+++ b/drivers/media/video/pwc/pwc-dec1.h
@@ -25,13 +25,15 @@
 #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
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
index 2c67091..3792fed 100644
--- a/drivers/media/video/pwc/pwc-dec23.c
+++ b/drivers/media/video/pwc/pwc-dec23.c
@@ -294,22 +294,17 @@
 
 
 /* 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 @@
 		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 @@
  * 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 @@
 
 	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);
 }
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
index d64a3c2..c655b1c 100644
--- a/drivers/media/video/pwc/pwc-dec23.h
+++ b/drivers/media/video/pwc/pwc-dec23.h
@@ -25,17 +25,20 @@
 #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 @@
 
 };
 
-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
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 943d37a..122fbd0 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -128,18 +128,11 @@
 #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 @@
 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 @@
 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 @@
 
 	/* 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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	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_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 @@
  * 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 @@
 
 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: */
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
index 23a55b5..9be5adf 100644
--- a/drivers/media/video/pwc/pwc-misc.c
+++ b/drivers/media/video/pwc/pwc-misc.c
@@ -90,5 +90,4 @@
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
 	}
-	pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
 }
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 80e2584..f495eeb 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -493,16 +493,11 @@
 			(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_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 @@
 	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 @@
 	.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,
 };
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 47c518f..e4d4d71 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -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"
@@ -132,9 +134,6 @@
 #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 @@
 	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 @@
 	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 @@
 /** 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);
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 510cfab..a9e9653 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -693,7 +693,7 @@
 			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 @@
 					       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 @@
 			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;
 	}
 
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index f5cbb8a..81bcbb9 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -848,11 +848,11 @@
 	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,
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index 615c862..8ea4ee1 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -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>
 
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
index c40b0dd..febaa67 100644
--- a/drivers/media/video/s5p-g2d/g2d.c
+++ b/drivers/media/video/s5p-g2d/g2d.c
@@ -184,6 +184,7 @@
 			ctx->rop = ROP4_INVERT;
 		else
 			ctx->rop = ROP4_COPY;
+		break;
 	default:
 		v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
 		return -EINVAL;
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
index f841a3e..1105a87 100644
--- a/drivers/media/video/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -989,9 +989,10 @@
  * ============================================================================
  */
 
-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;
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index e43e128..83fe461 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -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 @@
 			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;
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index 844a4d7..c25ec02 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -165,7 +165,7 @@
 		.maximum = 32,
 		.step = 1,
 		.default_value = 1,
-		.flags = V4L2_CTRL_FLAG_VOLATILE,
+		.is_volatile = 1,
 	},
 };
 
diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index 971591d..5b72da5 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -269,8 +269,6 @@
 		.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 @@
 		.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,
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
index 129f135..c096b3f 100644
--- a/drivers/media/video/tlg2300/pd-main.c
+++ b/drivers/media/video/tlg2300/pd-main.c
@@ -374,7 +374,7 @@
 }
 #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 @@
 		*down_firmware = 1;
 		return firmware_download(udev);
 	}
-	return ret;
+	return 0;
 }
 
 static int poseidon_probe(struct usb_interface *interface,
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index da1f4c2..cccd42b 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -465,8 +465,8 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 77feeb6..3f62385 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -1871,6 +1871,7 @@
 	case VIDIOC_S_FREQUENCY:
 	{
 		struct v4l2_frequency *p = arg;
+		enum v4l2_tuner_type type;
 
 		if (!ops->vidioc_s_frequency)
 			break;
@@ -1878,9 +1879,14 @@
 			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:
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index f6d2641..4c09ab7 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -1958,7 +1958,6 @@
 	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;
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 89c290b..29e1920 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -127,7 +127,6 @@
 #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
@@ -136,6 +135,8 @@
 #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)