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
  ...
This commit is contained in:
Linus Torvalds 2012-01-18 12:53:54 -08:00
commit 4a7c1ff236
56 changed files with 729 additions and 681 deletions

View File

@ -163,14 +163,16 @@ get/set up to 64 properties. The actual meaning of each property is described on
<section id="DTV-FREQUENCY">
<title><constant>DTV_FREQUENCY</constant></title>
<para>Central frequency of the channel, in HZ.</para>
<para>Central frequency of the channel.</para>
<para>Notes:</para>
<para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
<para>1)For satellital delivery systems, it is measured in kHz.
For the other ones, it is measured in Hz.</para>
<para>2)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
the channel which is 6MHz.</para>
<para>2)As in ISDB-Tsb the channel consists of only one or three segments the
<para>3)As in ISDB-Tsb the channel consists of only one or three segments the
frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
central frequency of the channel is expected.</para>
</section>
@ -735,14 +737,10 @@ typedef enum fe_hierarchy {
<listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
<listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
<listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
<listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
<listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
<listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
<listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
<listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
<listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
<listitem><para><link linkend="DTV-ISDBT-LAYER-ENABLED"><constant>DTV_ISDBT_LAYER_ENABLED</constant></link></para></listitem>
<listitem><para><link linkend="DTV-ISDBT-PARTIAL-RECEPTION"><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></link></para></listitem>
<listitem><para><link linkend="DTV-ISDBT-SOUND-BROADCASTING"><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></link></para></listitem>

View File

@ -183,7 +183,12 @@ applications must set the array to zero.</entry>
<entry>__u32</entry>
<entry><structfield>ctrl_class</structfield></entry>
<entry>The control class to which all controls belong, see
<xref linkend="ctrl-class" />.</entry>
<xref linkend="ctrl-class" />. Drivers that use a kernel framework for handling
controls will also accept a value of 0 here, meaning that the controls can
belong to any control class. Whether drivers support this can be tested by setting
<structfield>ctrl_class</structfield> to 0 and calling <constant>VIDIOC_TRY_EXT_CTRLS</constant>
with a <structfield>count</structfield> of 0. If that succeeds, then the driver
supports this feature.</entry>
</row>
<row>
<entry>__u32</entry>
@ -194,10 +199,13 @@ also be zero.</entry>
<row>
<entry>__u32</entry>
<entry><structfield>error_idx</structfield></entry>
<entry>Set by the driver in case of an error. It is the
index of the control causing the error or equal to 'count' when the
error is not associated with a particular control. Undefined when the
ioctl returns 0 (success).</entry>
<entry>Set by the driver in case of an error. If it is equal
to <structfield>count</structfield>, then no actual changes were made to
controls. In other words, the error was not associated with setting a particular
control. If it is another value, then only the controls up to <structfield>error_idx-1</structfield>
were modified and control <structfield>error_idx</structfield> is the one that
caused the error. The <structfield>error_idx</structfield> value is undefined
if the ioctl returned 0 (success).</entry>
</row>
<row>
<entry>__u32</entry>

View File

@ -364,15 +364,20 @@ capability and it is cleared otherwise.</entry>
<row>
<entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry>
<entry>0x0002</entry>
<entry>The frame buffer is an overlay surface the same
size as the capture. [?]</entry>
</row>
<row>
<entry spanname="hspan">The purpose of
<constant>V4L2_FBUF_FLAG_OVERLAY</constant> was never quite clear.
Most drivers seem to ignore this flag. For compatibility with the
<wordasword>bttv</wordasword> driver applications should set the
<constant>V4L2_FBUF_FLAG_OVERLAY</constant> flag.</entry>
<entry>If this flag is set for a video capture device, then the
driver will set the initial overlay size to cover the full framebuffer size,
otherwise the existing overlay size (as set by &VIDIOC-S-FMT;) will be used.
Only one video capture driver (bttv) supports this flag. The use of this flag
for capture devices is deprecated. There is no way to detect which drivers
support this flag, so the only reliable method of setting the overlay size is
through &VIDIOC-S-FMT;.
If this flag is set for a video output device, then the video output overlay
window is relative to the top-left corner of the framebuffer and restricted
to the size of the framebuffer. If it is cleared, then the video output
overlay window is relative to the video output display.
</entry>
</row>
<row>
<entry><constant>V4L2_FBUF_FLAG_CHROMAKEY</constant></entry>

View File

@ -98,8 +98,11 @@ the &v4l2-output; <structfield>modulator</structfield> field and the
<entry>&v4l2-tuner-type;</entry>
<entry><structfield>type</structfield></entry>
<entry>The tuner type. This is the same value as in the
&v4l2-tuner; <structfield>type</structfield> field. The field is not
applicable to modulators, &ie; ignored by drivers.</entry>
&v4l2-tuner; <structfield>type</structfield> field. The type must be set
to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename>
device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant>
for all others. The field is not applicable to modulators, &ie; ignored
by drivers.</entry>
</row>
<row>
<entry>__u32</entry>

View File

@ -61,8 +61,8 @@ desired input in an integer and call the
<constant>VIDIOC_S_INPUT</constant> ioctl with a pointer to this
integer. Side effects are possible. For example inputs may support
different video standards, so the driver may implicitly switch the
current standard. It is good practice to select an input before
querying or negotiating any other parameters.</para>
current standard. Because of these possible side effects applications
must select an input before querying or negotiating any other parameters.</para>
<para>Information about video inputs is available using the
&VIDIOC-ENUMINPUT; ioctl.</para>

View File

@ -61,8 +61,9 @@ desired output in an integer and call the
<constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this integer.
Side effects are possible. For example outputs may support different
video standards, so the driver may implicitly switch the current
standard. It is good practice to select an output before querying or
negotiating any other parameters.</para>
standard.
standard. Because of these possible side effects applications
must select an output before querying or negotiating any other parameters.</para>
<para>Information about video outputs is available using the
&VIDIOC-ENUMOUTPUT; ioctl.</para>

View File

@ -439,17 +439,6 @@ Who: Jean Delvare <khali@linux-fr.org>
----------------------------
What: For VIDIOC_S_FREQUENCY the type field must match the device node's type.
If not, return -EINVAL.
When: 3.2
Why: It makes no sense to switch the tuner to radio mode by calling
VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by
calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a
move to more consistent handling of tv and radio tuners.
Who: Hans Verkuil <hans.verkuil@cisco.com>
----------------------------
What: Opening a radio device node will no longer automatically switch the
tuner mode from tv to radio.
When: 3.3

View File

@ -666,27 +666,6 @@ a control of this type whenever the first control belonging to a new control
class is added.
Differences from the Spec
=========================
There are a few places where the framework acts slightly differently from the
V4L2 Specification. Those differences are described in this section. We will
have to see whether we need to adjust the spec or not.
1) It is no longer required to have all controls contained in a
v4l2_ext_control array be from the same control class. The framework will be
able to handle any type of control in the array. You need to set ctrl_class
to 0 in order to enable this. If ctrl_class is non-zero, then it will still
check that all controls belong to that control class.
If you set ctrl_class to 0 and count to 0, then it will only return an error
if there are no controls at all.
2) Clarified the way error_idx works. For get and set it will be equal to
count if nothing was done yet. If it is less than count then only the controls
up to error_idx-1 were successfully applied.
Proposals for Extensions
========================

View File

@ -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 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
mutex_lock(&priv->lock);
/* Sync Lock Indicator */
rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
if (rc < 0)
goto ret;
@ -894,7 +909,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
signal = 1 << 11;
/* Get SNR of the video signal */
rc = xc2028_get_reg(priv, 0x0040, &signal);
rc = xc2028_get_reg(priv, XREG_SNR, &signal);
if (rc < 0)
goto ret;
@ -1019,9 +1034,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
/* CMD= Set frequency */
if (priv->firm_version < 0x0202)
rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00});
else
rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00});
if (rc < 0)
goto ret;
@ -1201,9 +1216,9 @@ static int xc2028_sleep(struct dvb_frontend *fe)
mutex_lock(&priv->lock);
if (priv->firm_version < 0x0202)
rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00});
else
rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
priv->cur_fw.type = 0; /* need firmware reload */

View File

@ -154,6 +154,8 @@ struct xc4000_priv {
#define XREG_SNR 0x06
#define XREG_VERSION 0x07
#define XREG_PRODUCT_ID 0x08
#define XREG_SIGNAL_LEVEL 0x0A
#define XREG_NOISE_LEVEL 0x0B
/*
Basic firmware description. This will remain with
@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
return xc4000_readreg(priv, XREG_QUALITY, quality);
}
static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
{
return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
}
static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
{
return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
}
static u16 xc_wait_for_lock(struct xc4000_priv *priv)
{
u16 lock_state = 0;
@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv)
u32 hsync_freq_hz = 0;
u16 frame_lines;
u16 quality;
u16 signal = 0;
u16 noise = 0;
u8 hw_majorversion = 0, hw_minorversion = 0;
u8 fw_majorversion = 0, fw_minorversion = 0;
@ -1119,6 +1133,12 @@ static void xc_debug_dump(struct xc4000_priv *priv)
xc_get_quality(priv, &quality);
dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
xc_get_signal_level(priv, &signal);
dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
xc_get_noise_level(priv, &noise);
dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
}
static int xc4000_set_params(struct dvb_frontend *fe)
@ -1432,6 +1452,71 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe,
return ret;
}
static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
{
struct xc4000_priv *priv = fe->tuner_priv;
u16 value = 0;
int rc;
mutex_lock(&priv->lock);
rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
mutex_unlock(&priv->lock);
if (rc < 0)
goto ret;
/* Informations from real testing of DVB-T and radio part,
coeficient for one dB is 0xff.
*/
tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
/* all known digital modes */
if ((priv->video_standard == XC4000_DTV6) ||
(priv->video_standard == XC4000_DTV7) ||
(priv->video_standard == XC4000_DTV7_8) ||
(priv->video_standard == XC4000_DTV8))
goto digital;
/* Analog mode has NOISE LEVEL important, signal
depends only on gain of antenna and amplifiers,
but it doesn't tell anything about real quality
of reception.
*/
mutex_lock(&priv->lock);
rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
mutex_unlock(&priv->lock);
tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
/* highest noise level: 32dB */
if (value >= 0x2000) {
value = 0;
} else {
value = ~value << 3;
}
goto ret;
/* Digital mode has SIGNAL LEVEL important and real
noise level is stored in demodulator registers.
*/
digital:
/* best signal: -50dB */
if (value <= 0x3200) {
value = 0xffff;
/* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
} else if (value >= 0x713A) {
value = 0;
} else {
value = ~(value - 0x3200) << 2;
}
ret:
*strength = value;
return rc;
}
static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc4000_priv *priv = fe->tuner_priv;
@ -1559,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = {
.set_params = xc4000_set_params,
.set_analog_params = xc4000_set_analog_params,
.get_frequency = xc4000_get_frequency,
.get_rf_strength = xc4000_get_signal,
.get_bandwidth = xc4000_get_bandwidth,
.get_status = xc4000_get_status
};

View File

@ -904,8 +904,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i;
u32 delsys;
delsys = c->delivery_system;
memset(c, 0, sizeof(struct dtv_frontend_properties));
c->delivery_system = delsys;
c->state = DTV_CLEAR;
@ -1009,25 +1012,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
_DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
_DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
@ -1413,6 +1397,15 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
enum dvbv3_emulation_type type;
/*
* It was reported that some old DVBv5 applications were
* filling delivery_system with SYS_UNDEFINED. If this happens,
* assume that the application wants to use the first supported
* delivery system.
*/
if (c->delivery_system == SYS_UNDEFINED)
c->delivery_system = fe->ops.delsys[0];
if (desired_system == SYS_UNDEFINED) {
/*
* A DVBv3 call doesn't know what's the desired system.
@ -1732,6 +1725,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int err = 0;
@ -1798,9 +1792,14 @@ static int dvb_frontend_ioctl_properties(struct file *file,
/*
* Fills the cache out struct with the cache contents, plus
* the data retrieved from get_frontend.
* the data retrieved from get_frontend, if the frontend
* is not idle. Otherwise, returns the cached content
*/
dtv_get_frontend(fe, NULL);
if (fepriv->state != FESTATE_IDLE) {
err = dtv_get_frontend(fe, NULL);
if (err < 0)
goto out;
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(fe, c, tvp + i, file);
if (err < 0)

View File

@ -877,24 +877,18 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
case ANYSEE_HW_508T2C: /* 20 */
/* E7 T2C */
if (state->fe_id)
break;
/* enable DVB-T/T2/C demod on IOE[5] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
if (ret)
goto error;
if (state->fe_id == 0) {
/* DVB-T/T2 */
adap->fe_adap[state->fe_id].fe =
dvb_attach(cxd2820r_attach,
&anysee_cxd2820r_config,
&adap->dev->i2c_adap, NULL);
} else {
/* DVB-C */
adap->fe_adap[state->fe_id].fe =
dvb_attach(cxd2820r_attach,
&anysee_cxd2820r_config,
&adap->dev->i2c_adap, adap->fe_adap[0].fe);
}
/* attach demod */
adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
&anysee_cxd2820r_config, &adap->dev->i2c_adap,
NULL);
state->has_ci = true;

View File

@ -48,6 +48,8 @@ struct dib0700_state {
u8 disable_streaming_master_mode;
u32 fw_version;
u32 nb_packet_buffer_size;
int (*read_status)(struct dvb_frontend *, fe_status_t *);
int (*sleep)(struct dvb_frontend* fe);
u8 buf[255];
};

View File

@ -834,6 +834,7 @@ static struct usb_driver dib0700_driver = {
module_usb_driver(dib0700_driver);
MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
MODULE_VERSION("1.0");

View File

@ -3066,19 +3066,25 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
}
};
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 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int novatd_read_status_override(struct dvb_frontend *fe,
fe_status_t *stat)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dvb_usb_device *dev = adap->dev;
struct dib0700_state *state = dev->priv;
int ret;
ret = state->read_status(fe, stat);
if (!ret)
dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT,
!!(*stat & FE_HAS_LOCK));
return ret;
}
static int novatd_sleep_override(struct dvb_frontend* fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dvb_usb_device *dev = adap->dev;
struct dib0700_state *state = dev->priv;
/* turn off LED */
dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0);
return state->sleep(fe);
}
/**
* novatd_frontend_attach - Nova-TD specific attach
*
* Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for
* information purposes.
*/
static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *dev = adap->dev;
struct dib0700_state *st = dev->priv;
if (adap->id == 0) {
stk7070pd_init(dev);
/* turn the power LED on, the other two off (just in case) */
dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0);
dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
__func__);
return -ENODEV;
}
}
adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
adap->id == 0 ? 0x80 : 0x82,
&stk7070pd_dib7000p_config[adap->id]);
if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
st->read_status = adap->fe_adap[0].fe->ops.read_status;
adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override;
st->sleep = adap->fe_adap[0].fe->ops.sleep;
adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override;
return 0;
}
/* S5H1411 */
static struct s5h1411_config pinnacle_801e_config = {
.output_mode = S5H1411_PARALLEL_OUTPUT,
@ -3861,6 +3938,57 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
.adapter = {
{
.num_frontends = 1,
.fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = novatd_frontend_attach,
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
}},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}, {
.num_frontends = 1,
.fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = novatd_frontend_attach,
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
}},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}
},
.num_device_descs = 1,
.devices = {
{ "Hauppauge Nova-TD Stick (52009)",
{ &dib0700_usb_id_table[35], NULL },
{ NULL },
},
},
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
.adapter = {
{
@ -3892,7 +4020,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}
},
.num_device_descs = 6,
.num_device_descs = 5,
.devices = {
{ "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL },
@ -3902,10 +4030,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[18], NULL },
{ NULL },
},
{ "Hauppauge Nova-TD Stick (52009)",
{ &dib0700_usb_id_table[35], NULL },
{ NULL },
},
{ "Hauppauge Nova-TD-500 (84xxx)",
{ &dib0700_usb_id_table[36], NULL },
{ NULL },

View File

@ -309,9 +309,14 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int cxd2820r_get_frontend(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
if (priv->delivery_system == SYS_UNDEFINED)
return 0;
switch (fe->dtv_property_cache.delivery_system) {
case SYS_DVBT:
ret = cxd2820r_get_frontend_t(fe);
@ -476,10 +481,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
/* switch between DVB-T and DVB-T2 when tune fails */
if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) {
if (priv->last_tune_failed) {
if (priv->delivery_system == SYS_DVBT)
c->delivery_system = SYS_DVBT2;
else
else if (priv->delivery_system == SYS_DVBT2)
c->delivery_system = SYS_DVBT;
}
@ -492,6 +497,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
/* frontend lock wait loop count */
switch (priv->delivery_system) {
case SYS_DVBT:
case SYS_DVBC_ANNEX_A:
i = 20;
break;
case SYS_DVBT2:

View File

@ -1195,7 +1195,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
for (i = 0; i < 30 ; i++) {
ds3000_read_status(fe, &status);
if (status && FE_HAS_LOCK)
if (status & FE_HAS_LOCK)
break;
msleep(10);

View File

@ -402,7 +402,7 @@ static int mb86a20s_get_modulation(struct mb86a20s_state *state,
[2] = 0x8e, /* Layer C */
};
if (layer > ARRAY_SIZE(reg))
if (layer >= ARRAY_SIZE(reg))
return -EINVAL;
rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
if (rc < 0)
@ -435,7 +435,7 @@ static int mb86a20s_get_fec(struct mb86a20s_state *state,
[2] = 0x8f, /* Layer C */
};
if (layer > ARRAY_SIZE(reg))
if (layer >= ARRAY_SIZE(reg))
return -EINVAL;
rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
if (rc < 0)
@ -470,7 +470,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
[2] = 0x90, /* Layer C */
};
if (layer > ARRAY_SIZE(reg))
if (layer >= ARRAY_SIZE(reg))
return -EINVAL;
rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
if (rc < 0)
@ -494,7 +494,7 @@ static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
[2] = 0x91, /* Layer C */
};
if (layer > ARRAY_SIZE(reg))
if (layer >= ARRAY_SIZE(reg))
return -EINVAL;
rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
if (rc < 0)

View File

@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/version.h>
#include <asm/div64.h>
#include "dvb_frontend.h"

View File

@ -29,6 +29,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <media/as3645a.h>
#include <media/v4l2-ctrls.h>

View File

@ -751,20 +751,10 @@ int cx18_v4l2_close(struct file *filp)
CX18_DEBUG_IOCTL("close() of %s\n", s->name);
v4l2_fh_del(fh);
v4l2_fh_exit(fh);
/* Easy case first: this stream was never claimed by us */
if (s->id != id->open_id) {
kfree(id);
return 0;
}
/* 'Unclaim' this stream */
/* Stop radio */
mutex_lock(&cx->serialize_lock);
if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
/* Stop radio */
if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
v4l2_fh_is_singular_file(filp)) {
/* Closing radio device, return to TV mode */
cx18_mute(cx);
/* Mark that the radio is no longer in use */
@ -781,10 +771,14 @@ int cx18_v4l2_close(struct file *filp)
}
/* Done! Unmute and continue. */
cx18_unmute(cx);
cx18_release_stream(s);
} else {
cx18_stop_capture(id, 0);
}
v4l2_fh_del(fh);
v4l2_fh_exit(fh);
/* 'Unclaim' this stream */
if (s->id == id->open_id)
cx18_stop_capture(id, 0);
kfree(id);
mutex_unlock(&cx->serialize_lock);
return 0;
@ -810,21 +804,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
item->open_id = cx->open_id++;
filp->private_data = &item->fh;
v4l2_fh_add(&item->fh);
if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
/* Try to claim this stream */
if (cx18_claim_stream(item, item->type)) {
/* No, it's already in use */
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
}
if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
v4l2_fh_is_singular_file(filp)) {
if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
if (atomic_read(&cx->ana_capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
cx18_release_stream(s);
v4l2_fh_del(&item->fh);
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
@ -842,7 +830,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
/* Done! Unmute and continue. */
cx18_unmute(cx);
}
v4l2_fh_add(&item->fh);
return 0;
}

View File

@ -1052,7 +1052,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
cx231xx_err(DRIVER_NAME ": out of memory!\n");
clear_bit(dev->devno, &cx231xx_devused);
clear_bit(nr, &cx231xx_devused);
return -ENOMEM;
}

View File

@ -213,8 +213,8 @@ struct cx23885_board cx23885_boards[] = {
.portc = CX23885_MPEG_DVB,
.tuner_type = TUNER_XC4000,
.tuner_addr = 0x61,
.radio_type = TUNER_XC4000,
.radio_addr = 0x61,
.radio_type = UNSET,
.radio_addr = ADDR_UNSET,
.input = {{
.type = CX23885_VMUX_TELEVISION,
.vmux = CX25840_VIN2_CH1 |

View File

@ -943,6 +943,11 @@ static int dvb_register(struct cx23885_tsport *port)
fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
&dev->i2c_bus[1].i2c_adap, &cfg);
if (!fe) {
printk(KERN_ERR "%s/2: xc4000 attach failed\n",
dev->name);
goto frontend_detach;
}
}
break;
case CX23885_BOARD_TBS_6920:

View File

@ -1550,7 +1550,6 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
struct v4l2_control ctrl;
struct videobuf_dvb_frontend *vfe;
struct dvb_frontend *fe;
int err = 0;
struct analog_parameters params = {
.mode = V4L2_TUNER_ANALOG_TV,
@ -1572,8 +1571,10 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
params.frequency, f->tuner, params.std);
vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
if (!vfe)
err = -EINVAL;
if (!vfe) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
fe = vfe->dvb.frontend;

View File

@ -1573,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Pinnacle Hybrid PCTV",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.radio_type = TUNER_XC2028,
.radio_addr = 0x61,
.radio_type = UNSET,
.radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@ -1611,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Leadtek TV2000 XP Global",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.radio_type = TUNER_XC2028,
.radio_addr = 0x61,
.radio_type = UNSET,
.radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@ -2115,8 +2115,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Terratec Cinergy HT PCI MKII",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.radio_type = TUNER_XC2028,
.radio_addr = 0x61,
.radio_type = UNSET,
.radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@ -2154,9 +2154,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV1800H] = {
.name = "Leadtek WinFast DTV1800 Hybrid",
.tuner_type = TUNER_XC2028,
.radio_type = TUNER_XC2028,
.radio_type = UNSET,
.tuner_addr = 0x61,
.radio_addr = 0x61,
.radio_addr = ADDR_UNSET,
/*
* GPIO setting
*
@ -2195,9 +2195,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
.name = "Leadtek WinFast DTV1800 H (XC4000)",
.tuner_type = TUNER_XC4000,
.radio_type = TUNER_XC4000,
.radio_type = UNSET,
.tuner_addr = 0x61,
.radio_addr = 0x61,
.radio_addr = ADDR_UNSET,
/*
* GPIO setting
*
@ -2236,9 +2236,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
.name = "Leadtek WinFast DTV2000 H PLUS",
.tuner_type = TUNER_XC4000,
.radio_type = TUNER_XC4000,
.radio_type = UNSET,
.tuner_addr = 0x61,
.radio_addr = 0x61,
.radio_addr = ADDR_UNSET,
/*
* GPIO
* 2: 1: mute audio

View File

@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
/* start counting open_id at 1 */
itv->open_id = 1;
/* Initial settings */
itv->cxhdl.port = CX2341X_PORT_MEMORY;
itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;

View File

@ -332,7 +332,7 @@ struct ivtv_stream {
const char *name; /* name of the stream */
int type; /* stream type */
u32 id;
struct v4l2_fh *fh; /* pointer to the streaming filehandle */
spinlock_t qlock; /* locks access to the queues */
unsigned long s_flags; /* status flags, see above */
int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
@ -379,7 +379,6 @@ struct ivtv_stream {
struct ivtv_open_id {
struct v4l2_fh fh;
u32 open_id; /* unique ID for this file descriptor */
int type; /* stream type */
int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */
struct ivtv *itv;

View File

@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
/* someone already claimed this stream */
if (s->id == id->open_id) {
if (s->fh == &id->fh) {
/* yes, this file descriptor did. So that's OK. */
return 0;
}
if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI ||
if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
type == IVTV_ENC_STREAM_TYPE_VBI)) {
/* VBI is handled already internally, now also assign
the file descriptor to this stream for external
reading of the stream. */
s->id = id->open_id;
s->fh = &id->fh;
IVTV_DEBUG_INFO("Start Read VBI\n");
return 0;
}
@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
IVTV_DEBUG_INFO("Stream %d is busy\n", type);
return -EBUSY;
}
s->id = id->open_id;
s->fh = &id->fh;
if (type == IVTV_DEC_STREAM_TYPE_VBI) {
/* Enable reinsertion interrupt */
ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
struct ivtv *itv = s->itv;
struct ivtv_stream *s_vbi;
s->id = -1;
s->fh = NULL;
if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
/* this stream is still in use internally */
@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
/* was already cleared */
return;
}
if (s_vbi->id != -1) {
if (s_vbi->fh) {
/* VBI stream still claimed by a file descriptor */
return;
}
@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
}
/* wait for more data to arrive */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added to the waitqueue */
if (!s->q_full.buffers)
schedule();
finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (signal_pending(current)) {
/* return if a signal was received */
IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
size_t tot_written = 0;
int single_frame = 0;
if (atomic_read(&itv->capturing) == 0 && s->id == -1) {
if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
/* shouldn't happen */
IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
return -EIO;
@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id);
mutex_unlock(&itv->serialize_lock);
if (rc)
return rc;
return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
/* Start decoder (returns 0 if already started) */
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_decoding(id, itv->speed);
mutex_unlock(&itv->serialize_lock);
if (rc) {
IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
@ -627,11 +625,13 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
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 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
if (mode == OUT_YUV)
ivtv_yuv_setup_stream_frame(itv);
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
schedule();
}
finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (got_sig) {
IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
return -EINTR;
@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
int rc;
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id);
mutex_unlock(&itv->serialize_lock);
if (rc) {
IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
s->name, rc);
@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
/* Also used internally, don't stop capturing */
s->id = -1;
s->fh = NULL;
}
else {
ivtv_stop_v4l2_encode_stream(s, gop_end);
@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp)
IVTV_DEBUG_FILE("close %s\n", s->name);
v4l2_fh_del(fh);
v4l2_fh_exit(fh);
/* Easy case first: this stream was never claimed by us */
if (s->id != id->open_id) {
kfree(id);
return 0;
}
/* 'Unclaim' this stream */
/* Stop radio */
mutex_lock(&itv->serialize_lock);
if (id->type == IVTV_ENC_STREAM_TYPE_RAD) {
if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
v4l2_fh_is_singular_file(filp)) {
/* Closing radio device, return to TV mode */
ivtv_mute(itv);
/* Mark that the radio is no longer in use */
@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp)
if (atomic_read(&itv->capturing) > 0) {
/* Undo video mute */
ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
(v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
(v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
}
/* Done! Unmute and continue. */
ivtv_unmute(itv);
ivtv_release_stream(s);
} else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
}
v4l2_fh_del(fh);
v4l2_fh_exit(fh);
/* Easy case first: this stream was never claimed by us */
if (s->fh != &id->fh) {
kfree(id);
return 0;
}
/* 'Unclaim' this stream */
if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
ivtv_stop_capture(id, 0);
}
kfree(id);
mutex_unlock(&itv->serialize_lock);
return 0;
}
static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
int ivtv_v4l2_open(struct file *filp)
{
#ifdef CONFIG_VIDEO_ADV_DEBUG
struct video_device *vdev = video_devdata(filp);
#endif
struct ivtv_stream *s = video_get_drvdata(vdev);
struct ivtv *itv = s->itv;
struct ivtv_open_id *item;
int res = 0;
IVTV_DEBUG_FILE("open %s\n", s->name);
if (ivtv_init_on_first_open(itv)) {
IVTV_ERR("Failed to initialize on device %s\n",
video_device_node_name(vdev));
return -ENXIO;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* Unless ivtv_fw_debug is set, error out if firmware dead. */
if (ivtv_fw_debug) {
@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
return -ENOMEM;
}
v4l2_fh_init(&item->fh, s->vdev);
if (res < 0) {
v4l2_fh_exit(&item->fh);
kfree(item);
return res;
}
item->itv = itv;
item->type = s->type;
item->open_id = itv->open_id++;
filp->private_data = &item->fh;
v4l2_fh_add(&item->fh);
if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
/* Try to claim this stream */
if (ivtv_claim_stream(item, item->type)) {
/* No, it's already in use */
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
}
if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
v4l2_fh_is_singular_file(filp)) {
if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
if (atomic_read(&itv->capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
ivtv_release_stream(s);
v4l2_fh_del(&item->fh);
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
itv->yuv_info.stream_size = 0;
}
v4l2_fh_add(&item->fh);
return 0;
}
int ivtv_v4l2_open(struct file *filp)
{
int res;
struct ivtv *itv = NULL;
struct ivtv_stream *s = NULL;
struct video_device *vdev = video_devdata(filp);
s = video_get_drvdata(vdev);
itv = s->itv;
mutex_lock(&itv->serialize_lock);
if (ivtv_init_on_first_open(itv)) {
IVTV_ERR("Failed to initialize on device %s\n",
video_device_node_name(vdev));
mutex_unlock(&itv->serialize_lock);
return -ENXIO;
}
res = ivtv_serialized_open(s, filp);
mutex_unlock(&itv->serialize_lock);
return res;
}
void ivtv_mute(struct ivtv *itv)
{
if (atomic_read(&itv->capturing))

View File

@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
/* Wait for any DMA to finish */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
got_sig = signal_pending(current);
@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
schedule();
}
finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (got_sig)
return -EINTR;
@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
* happens within the first 100 lines of the top field.
* Make 4 attempts to sync to the decoder before giving up.
*/
mutex_unlock(&itv->serialize_lock);
for (f = 0; f < 4; f++) {
prepare_to_wait(&itv->vsync_waitq, &wait,
TASK_UNINTERRUPTIBLE);
@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
schedule_timeout(msecs_to_jiffies(25));
}
finish_wait(&itv->vsync_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (f == 4)
IVTV_WARN("Mode change failed to sync to decoder\n");
@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
return 0;
}
static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
unsigned int cmd, unsigned long arg)
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
long ret;
@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
return ret;
}
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ivtv_open_id *id = fh2id(filp->private_data);
struct ivtv *itv = id->itv;
long res;
/* DQEVENT can block, so this should not run with the serialize lock */
if (cmd == VIDIOC_DQEVENT)
return ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_lock(&itv->serialize_lock);
res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_unlock(&itv->serialize_lock);
return res;
}
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
.vidioc_querycap = ivtv_querycap,
.vidioc_s_audio = ivtv_s_audio,

View File

@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s)
ivtv_process_vbi_data(itv, buf, 0, s->type);
s->q_dma.bytesused += buf->bytesused;
}
if (s->id == -1) {
if (s->fh == NULL) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return;
}
}
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
if (s->id != -1)
if (s->fh)
wake_up(&s->waitq);
}

View File

@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
spin_lock_init(&s->qlock);
init_waitqueue_head(&s->waitq);
s->id = -1;
s->sg_handle = IVTV_DMA_UNMAPPED;
ivtv_queue_init(&s->q_free);
ivtv_queue_init(&s->q_full);
@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
s->vdev->fops = ivtv_stream_info[type].fops;
s->vdev->release = video_device_release;
s->vdev->tvnorms = V4L2_STD_ALL;
s->vdev->lock = &itv->serialize_lock;
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;

View File

@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{
struct yuv_playback_info *yi = &itv->yuv_info;
struct ivtv_dma_frame dma_args;
int res;
ivtv_yuv_setup_stream_frame(itv);
/* We only need to supply source addresses for this */
dma_args.y_source = src;
dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
return ivtv_yuv_udma_frame(itv, &dma_args);
/* Wait for frame DMA. Note that serialize_lock is locked,
so to allow other processes to access the driver while
we are waiting unlock first and later lock again. */
mutex_unlock(&itv->serialize_lock);
res = ivtv_yuv_udma_frame(itv, &dma_args);
mutex_lock(&itv->serialize_lock);
return res;
}
/* IVTV_IOC_DMA_FRAME ioctl handler */
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
{
/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
int res;
/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
ivtv_yuv_next_free(itv);
ivtv_yuv_setup_frame(itv, args);
return ivtv_yuv_udma_frame(itv, args);
/* Wait for frame DMA. Note that serialize_lock is locked,
so to allow other processes to access the driver while
we are waiting unlock first and later lock again. */
mutex_unlock(&itv->serialize_lock);
res = ivtv_yuv_udma_frame(itv, args);
mutex_lock(&itv->serialize_lock);
return res;
}
void ivtv_yuv_close(struct ivtv *itv)
@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
int h_filter, v_filter_1, v_filter_2;
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
mutex_unlock(&itv->serialize_lock);
ivtv_waitq(&itv->vsync_waitq);
mutex_lock(&itv->serialize_lock);
yi->running = 0;
atomic_set(&yi->next_dma_frame, -1);

View File

@ -1042,7 +1042,8 @@ static int vidioc_querycap(struct file *file, void *fh,
strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
cap->bus_info[0] = '\0';
cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
return 0;
}
@ -1825,7 +1826,9 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
ovid = &vout->vid_info;
ovl = ovid->overlays[0];
a->flags = 0x0;
/* The video overlay must stay within the framebuffer and can't be
positioned independently. */
a->flags = V4L2_FBUF_FLAG_OVERLAY;
a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
| V4L2_FBUF_CAP_SRC_CHROMAKEY;

View File

@ -104,47 +104,16 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
/****************************************************************************/
static int _send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, int index, void *buf, int buflen)
{
int rc;
void *kbuf = NULL;
if (buflen) {
kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
if (kbuf == NULL)
return -ENOMEM;
}
rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
request,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
kbuf, buflen, USB_CTRL_SET_TIMEOUT);
kfree(kbuf);
return rc;
}
static int recv_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen)
u8 request, u16 value, int recv_count)
{
int rc;
void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
if (kbuf == NULL)
return -ENOMEM;
rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
pdev->vcinterface,
kbuf, buflen, USB_CTRL_GET_TIMEOUT);
memcpy(buf, kbuf, buflen);
kfree(kbuf);
value, pdev->vcinterface,
pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
if (rc < 0)
PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
rc, request, value);
@ -152,27 +121,39 @@ static int recv_control_msg(struct pwc_device *pdev,
}
static inline int send_video_command(struct pwc_device *pdev,
int index, void *buf, int buflen)
int index, const unsigned char *buf, int buflen)
{
return _send_control_msg(pdev,
SET_EP_STREAM_CTL,
VIDEO_OUTPUT_CONTROL_FORMATTER,
index,
buf, buflen);
int rc;
memcpy(pdev->ctrl_buf, buf, buflen);
rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
SET_EP_STREAM_CTL,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
VIDEO_OUTPUT_CONTROL_FORMATTER, index,
pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
if (rc >= 0)
memcpy(pdev->cmd_buf, buf, buflen);
else
PWC_ERROR("send_video_command error %d\n", rc);
return rc;
}
int send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen)
{
return _send_control_msg(pdev,
request, value, pdev->vcinterface, buf, buflen);
return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
request,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, pdev->vcinterface,
buf, buflen, USB_CTRL_SET_TIMEOUT);
}
static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
int *compression)
static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
unsigned char buf[3];
int ret, fps;
int fps, ret = 0;
struct Nala_table_entry *pEntry;
int frames2frames[31] =
{ /* closest match of framerate */
@ -194,30 +175,29 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
7 /* 30 */
};
if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
if (size < 0 || size > PSZ_CIF)
return -EINVAL;
if (frames < 4)
frames = 4;
else if (frames > 25)
frames = 25;
frames = frames2frames[frames];
fps = frames2table[frames];
pEntry = &Nala_table[size][fps];
if (pEntry->alternate == 0)
return -EINVAL;
memcpy(buf, pEntry->mode, 3);
ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
if (ret < 0) {
PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
if (send_to_cam)
ret = send_video_command(pdev, pdev->vendpoint,
pEntry->mode, 3);
if (ret < 0)
return ret;
}
if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
if (ret < 0)
return ret;
}
pdev->cmd_len = 3;
memcpy(pdev->cmd_buf, buf, 3);
if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec1_init(pdev, pEntry->mode);
/* Set various parameters */
pdev->pixfmt = pixfmt;
pdev->vframes = frames;
pdev->valternate = pEntry->alternate;
pdev->width = pwc_image_sizes[size][0];
@ -243,18 +223,20 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
}
static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
int *compression)
static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
unsigned char buf[13];
const struct Timon_table_entry *pChoose;
int ret, fps;
int fps, ret = 0;
if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
*compression < 0 || *compression > 3)
return -EINVAL;
if (size == PSZ_VGA && frames > 15)
if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
if (frames < 5)
frames = 5;
else if (size == PSZ_VGA && frames > 15)
frames = 15;
else if (frames > 30)
frames = 30;
fps = (frames / 5) - 1;
/* Find a supported framerate with progressively higher compression */
@ -268,22 +250,18 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
memcpy(buf, pChoose->mode, 13);
ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
if (send_to_cam)
ret = send_video_command(pdev, pdev->vendpoint,
pChoose->mode, 13);
if (ret < 0)
return ret;
if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
ret = pwc_dec23_init(pdev, pdev->type, buf);
if (ret < 0)
return ret;
}
pdev->cmd_len = 13;
memcpy(pdev->cmd_buf, buf, 13);
if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec23_init(pdev, pChoose->mode);
/* Set various parameters */
pdev->vframes = frames;
pdev->pixfmt = pixfmt;
pdev->vframes = (fps + 1) * 5;
pdev->valternate = pChoose->alternate;
pdev->width = pwc_image_sizes[size][0];
pdev->height = pwc_image_sizes[size][1];
@ -296,18 +274,20 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
}
static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
int *compression)
static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
const struct Kiara_table_entry *pChoose = NULL;
int fps, ret;
unsigned char buf[12];
int fps, ret = 0;
if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
*compression < 0 || *compression > 3)
return -EINVAL;
if (size == PSZ_VGA && frames > 15)
if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
if (frames < 5)
frames = 5;
else if (size == PSZ_VGA && frames > 15)
frames = 15;
else if (frames > 30)
frames = 30;
fps = (frames / 5) - 1;
/* Find a supported framerate with progressively higher compression */
@ -320,26 +300,18 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
/* usb_control_msg won't take staticly allocated arrays as argument?? */
memcpy(buf, pChoose->mode, 12);
/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
if (send_to_cam)
ret = send_video_command(pdev, 4, pChoose->mode, 12);
if (ret < 0)
return ret;
if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
ret = pwc_dec23_init(pdev, pdev->type, buf);
if (ret < 0)
return ret;
}
if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec23_init(pdev, pChoose->mode);
pdev->cmd_len = 12;
memcpy(pdev->cmd_buf, buf, 12);
/* All set and go */
pdev->vframes = frames;
pdev->pixfmt = pixfmt;
pdev->vframes = (fps + 1) * 5;
pdev->valternate = pChoose->alternate;
pdev->width = pwc_image_sizes[size][0];
pdev->height = pwc_image_sizes[size][1];
@ -354,22 +326,24 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
}
int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int frames, int *compression)
int pixfmt, int frames, int *compression, int send_to_cam)
{
int ret, size;
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
width, height, frames, pixfmt);
size = pwc_get_size(pdev, width, height);
PWC_TRACE("decode_size = %d.\n", size);
if (DEVICE_USE_CODEC1(pdev->type)) {
ret = set_video_mode_Nala(pdev, size, frames, compression);
ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
compression, send_to_cam);
} else if (DEVICE_USE_CODEC3(pdev->type)) {
ret = set_video_mode_Kiara(pdev, size, frames, compression);
ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
compression, send_to_cam);
} else {
ret = set_video_mode_Timon(pdev, size, frames, compression);
ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
compression, send_to_cam);
}
if (ret < 0) {
PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
@ -436,13 +410,12 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
u8 buf;
ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
*data = buf;
*data = pdev->ctrl_buf[0];
return 0;
}
@ -450,7 +423,8 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
{
int ret;
ret = send_control_msg(pdev, request, value, &data, sizeof(data));
pdev->ctrl_buf[0] = data;
ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
if (ret < 0)
return ret;
@ -460,37 +434,34 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
s8 buf;
ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
*data = buf;
*data = ((s8 *)pdev->ctrl_buf)[0];
return 0;
}
int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
u8 buf[2];
ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
ret = recv_control_msg(pdev, request, value, 2);
if (ret < 0)
return ret;
*data = (buf[1] << 8) | buf[0];
*data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
return 0;
}
int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
{
int ret;
u8 buf[2];
buf[0] = data & 0xff;
buf[1] = data >> 8;
ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
pdev->ctrl_buf[0] = data & 0xff;
pdev->ctrl_buf[1] = data >> 8;
ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
if (ret < 0)
return ret;
@ -511,7 +482,6 @@ int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
/* POWER */
void pwc_camera_power(struct pwc_device *pdev, int power)
{
char buf;
int r;
if (!pdev->power_save)
@ -521,13 +491,11 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
return; /* Not supported by Nala or Timon < release 6 */
if (power)
buf = 0x00; /* active */
pdev->ctrl_buf[0] = 0x00; /* active */
else
buf = 0xFF; /* power save */
r = send_control_msg(pdev,
SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
&buf, sizeof(buf));
pdev->ctrl_buf[0] = 0xFF; /* power save */
r = send_control_msg(pdev, SET_STATUS_CTL,
SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
if (r < 0)
PWC_ERROR("Failed to power %s camera (%d)\n",
power ? "on" : "off", r);
@ -535,7 +503,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
unsigned char buf[2];
int r;
if (pdev->type < 730)
@ -551,11 +518,11 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
if (off_value > 0xff)
off_value = 0xff;
buf[0] = on_value;
buf[1] = off_value;
pdev->ctrl_buf[0] = on_value;
pdev->ctrl_buf[1] = off_value;
r = send_control_msg(pdev,
SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
if (r < 0)
PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
@ -565,7 +532,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
{
unsigned char buf;
int ret = -1, request;
if (pdev->type < 675)
@ -575,14 +541,13 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
else
request = SENSOR_TYPE_FORMATTER2;
ret = recv_control_msg(pdev,
GET_STATUS_CTL, request, &buf, sizeof(buf));
ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
if (ret < 0)
return ret;
if (pdev->type < 675)
*sensor = buf | 0x100;
*sensor = pdev->ctrl_buf[0] | 0x100;
else
*sensor = buf;
*sensor = pdev->ctrl_buf[0];
return 0;
}
#endif

View File

@ -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;
}

View File

@ -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

View File

@ -294,22 +294,17 @@ static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
/* If the type or the command change, we rebuild the lookup table */
int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
{
int flags, version, shift, i;
struct pwc_dec23_private *pdec;
if (pwc->decompress_data == NULL) {
pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
if (pdec == NULL)
return -ENOMEM;
pwc->decompress_data = pdec;
}
pdec = pwc->decompress_data;
struct pwc_dec23_private *pdec = &pdev->dec23;
mutex_init(&pdec->lock);
if (DEVICE_USE_CODEC3(type)) {
if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
return;
if (DEVICE_USE_CODEC3(pdev->type)) {
flags = cmd[2] & 0x18;
if (flags == 8)
pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */
@ -356,7 +351,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
#endif
return 0;
pdec->last_cmd = cmd[2];
pdec->last_cmd_valid = 1;
}
/*
@ -659,12 +655,12 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
* src: raw data
* dst: image output
*/
void pwc_dec23_decompress(const struct pwc_device *pwc,
void pwc_dec23_decompress(struct pwc_device *pdev,
const void *src,
void *dst)
{
int bandlines_left, bytes_per_block;
struct pwc_dec23_private *pdec = pwc->decompress_data;
struct pwc_dec23_private *pdec = &pdev->dec23;
/* YUV420P image format */
unsigned char *pout_planar_y;
@ -674,23 +670,22 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
mutex_lock(&pdec->lock);
bandlines_left = pwc->height / 4;
bytes_per_block = pwc->width * 4;
plane_size = pwc->height * pwc->width;
bandlines_left = pdev->height / 4;
bytes_per_block = pdev->width * 4;
plane_size = pdev->height * pdev->width;
pout_planar_y = dst;
pout_planar_u = dst + plane_size;
pout_planar_v = dst + plane_size + plane_size / 4;
while (bandlines_left--) {
DecompressBand23(pwc->decompress_data,
src,
DecompressBand23(pdec, src,
pout_planar_y, pout_planar_u, pout_planar_v,
pwc->width, pwc->width);
src += pwc->vbandlength;
pdev->width, pdev->width);
src += pdev->vbandlength;
pout_planar_y += bytes_per_block;
pout_planar_u += pwc->width;
pout_planar_v += pwc->width;
pout_planar_u += pdev->width;
pout_planar_v += pdev->width;
}
mutex_unlock(&pdec->lock);
}

View File

@ -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 @@ struct pwc_dec23_private
};
int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
void pwc_dec23_decompress(const struct pwc_device *pwc,
void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
void pwc_dec23_decompress(struct pwc_device *pdev,
const void *src,
void *dst);
#endif

View File

@ -128,18 +128,11 @@ static struct usb_driver pwc_driver = {
#define MAX_DEV_HINTS 20
#define MAX_ISOC_ERRORS 20
static int default_fps = 10;
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_trace = PWC_DEBUG_LEVEL;
#endif
static int power_save = -1;
static int led_on = 100, led_off; /* defaults to LED that is on while in use */
static struct {
int type;
char serial_number[30];
int device_node;
struct pwc_device *pdev;
} device_hint[MAX_DEV_HINTS];
static int leds[2] = { 100, 0 };
/***/
@ -386,8 +379,8 @@ static int pwc_isoc_init(struct pwc_device *pdev)
retry:
/* We first try with low compression and then retry with a higher
compression setting if there is not enough bandwidth. */
ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
pdev->vframes, &compression);
ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
pdev->vframes, &compression, 1);
/* Get the current alternate interface, adjust packet size */
intf = usb_ifnum_to_if(udev, 0);
@ -597,23 +590,9 @@ int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
static void pwc_video_release(struct v4l2_device *v)
{
struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
int hint;
/* search device_hint[] table if we occupy a slot, by any chance */
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
if (device_hint[hint].pdev == pdev)
device_hint[hint].pdev = NULL;
/* Free intermediate decompression buffer & tables */
if (pdev->decompress_data != NULL) {
PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
pdev->decompress_data);
kfree(pdev->decompress_data);
pdev->decompress_data = NULL;
}
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
kfree(pdev->ctrl_buf);
kfree(pdev);
}
@ -758,7 +737,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
/* Turn on camera and set LEDS on */
pwc_camera_power(pdev, 1);
pwc_set_leds(pdev, led_on, led_off);
pwc_set_leds(pdev, leds[0], leds[1]);
r = pwc_isoc_init(pdev);
if (r) {
@ -813,10 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
struct usb_device *udev = interface_to_usbdev(intf);
struct pwc_device *pdev = NULL;
int vendor_id, product_id, type_id;
int hint, rc;
int rc;
int features = 0;
int compression = 0;
int video_nr = -1; /* default: use next available device */
int my_power_save = power_save;
char serial_number[30], *name;
@ -1076,7 +1054,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
pdev->type = type_id;
pdev->vframes = default_fps;
pdev->features = features;
pwc_construct(pdev); /* set min/max sizes correct */
@ -1107,24 +1084,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
/* Now search device_hint[] table for a match, so we can hint a node number. */
for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
(device_hint[hint].pdev == NULL)) {
/* so far, so good... try serial number */
if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
/* match! */
video_nr = device_hint[hint].device_node;
PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
break;
}
}
/* Allocate USB command buffers */
pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
if (!pdev->ctrl_buf) {
PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
rc = -ENOMEM;
goto err_free_mem;
}
/* occupy slot */
if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev;
#ifdef CONFIG_USB_PWC_DEBUG
/* Query sensor type */
if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@ -1138,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pwc_set_leds(pdev, 0, 0);
/* Setup intial videomode */
rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
&compression);
rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
V4L2_PIX_FMT_YUV420, 30, &compression, 1);
if (rc)
goto err_free_mem;
@ -1164,7 +1131,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
if (rc < 0) {
PWC_ERROR("Failed to register as video device (%d).\n", rc);
goto err_unregister_v4l2_dev;
@ -1207,8 +1174,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
err_free_controls:
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
err_free_mem:
if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = NULL;
kfree(pdev->ctrl_buf);
kfree(pdev);
return rc;
}
@ -1243,27 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
* Initialization code & module stuff
*/
static int fps;
static int leds[2] = { -1, -1 };
static unsigned int leds_nargs;
static char *dev_hint[MAX_DEV_HINTS];
static unsigned int dev_hint_nargs;
module_param(fps, int, 0444);
#ifdef CONFIG_USB_PWC_DEBUG
module_param_named(trace, pwc_trace, int, 0644);
#endif
module_param(power_save, int, 0644);
module_param_array(leds, int, &leds_nargs, 0444);
module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
#ifdef CONFIG_USB_PWC_DEBUG
MODULE_PARM_DESC(trace, "For debugging purposes");
#endif
MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
MODULE_PARM_DESC(dev_hint, "Device node hints");
MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@ -1273,114 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
static int __init usb_pwc_init(void)
{
int i;
#ifdef CONFIG_USB_PWC_DEBUG
PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
if (pwc_trace >= 0) {
PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
}
#endif
if (fps) {
if (fps < 4 || fps > 30) {
PWC_ERROR("Framerate out of bounds (4-30).\n");
return -EINVAL;
}
default_fps = fps;
PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
}
if (leds[0] >= 0)
led_on = leds[0];
if (leds[1] >= 0)
led_off = leds[1];
/* Big device node whoopla. Basically, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
& serial number. The format is [type[.serialnumber]:]node.
Any camera that isn't matched by these rules gets the next
available free device node.
*/
for (i = 0; i < MAX_DEV_HINTS; i++) {
char *s, *colon, *dot;
/* This loop also initializes the array */
device_hint[i].pdev = NULL;
s = dev_hint[i];
if (s != NULL && *s != '\0') {
device_hint[i].type = -1; /* wildcard */
strcpy(device_hint[i].serial_number, "*");
/* parse string: chop at ':' & '/' */
colon = dot = s;
while (*colon != '\0' && *colon != ':')
colon++;
while (*dot != '\0' && *dot != '.')
dot++;
/* Few sanity checks */
if (*dot != '\0' && dot > colon) {
PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
return -EINVAL;
}
if (*colon == '\0') {
/* No colon */
if (*dot != '\0') {
PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
return -EINVAL;
}
else {
/* No type or serial number specified, just a number. */
device_hint[i].device_node =
simple_strtol(s, NULL, 10);
}
}
else {
/* There's a colon, so we have at least a type and a device node */
device_hint[i].type =
simple_strtol(s, NULL, 10);
device_hint[i].device_node =
simple_strtol(colon + 1, NULL, 10);
if (*dot != '\0') {
/* There's a serial number as well */
int k;
dot++;
k = 0;
while (*dot != ':' && k < 29) {
device_hint[i].serial_number[k++] = *dot;
dot++;
}
device_hint[i].serial_number[k] = '\0';
}
}
PWC_TRACE("device_hint[%d]:\n", i);
PWC_TRACE(" type : %d\n", device_hint[i].type);
PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
PWC_TRACE(" node : %d\n", device_hint[i].device_node);
}
else
device_hint[i].type = 0; /* not filled */
} /* ..for MAX_DEV_HINTS */
PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver);
}
static void __exit usb_pwc_exit(void)
{
PWC_DEBUG_MODULE("Deregistering driver.\n");
usb_deregister(&pwc_driver);
PWC_INFO("Philips webcam module removed.\n");
}
module_init(usb_pwc_init);
module_exit(usb_pwc_exit);
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

View File

@ -90,5 +90,4 @@ void pwc_construct(struct pwc_device *pdev)
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
}
pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
}

View File

@ -493,16 +493,11 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
(pixelformat>>24)&255);
ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
pdev->vframes, &compression);
pixelformat, 30, &compression, 0);
PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
if (ret == 0) {
pdev->pixfmt = pixelformat;
pwc_vidioc_fill_fmt(f, pdev->width, pdev->height,
pdev->pixfmt);
}
pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
leave:
mutex_unlock(&pdev->udevlock);
return ret;
@ -777,33 +772,33 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
static int pwc_set_motor(struct pwc_device *pdev)
{
int ret;
u8 buf[4];
buf[0] = 0;
pdev->ctrl_buf[0] = 0;
if (pdev->motor_pan_reset->is_new)
buf[0] |= 0x01;
pdev->ctrl_buf[0] |= 0x01;
if (pdev->motor_tilt_reset->is_new)
buf[0] |= 0x02;
pdev->ctrl_buf[0] |= 0x02;
if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
ret = send_control_msg(pdev, SET_MPT_CTL,
PT_RESET_CONTROL_FORMATTER, buf, 1);
PT_RESET_CONTROL_FORMATTER,
pdev->ctrl_buf, 1);
if (ret < 0)
return ret;
}
memset(buf, 0, sizeof(buf));
memset(pdev->ctrl_buf, 0, 4);
if (pdev->motor_pan->is_new) {
buf[0] = pdev->motor_pan->val & 0xFF;
buf[1] = (pdev->motor_pan->val >> 8);
pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
}
if (pdev->motor_tilt->is_new) {
buf[2] = pdev->motor_tilt->val & 0xFF;
buf[3] = (pdev->motor_tilt->val >> 8);
pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
}
if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
ret = send_control_msg(pdev, SET_MPT_CTL,
PT_RELATIVE_CONTROL_FORMATTER,
buf, sizeof(buf));
pdev->ctrl_buf, 4);
if (ret < 0)
return ret;
}
@ -1094,6 +1089,63 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
return 0;
}
static int pwc_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *parm)
{
struct pwc_device *pdev = video_drvdata(file);
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
memset(parm, 0, sizeof(*parm));
parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm->parm.capture.readbuffers = MIN_FRAMES;
parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
parm->parm.capture.timeperframe.denominator = pdev->vframes;
parm->parm.capture.timeperframe.numerator = 1;
return 0;
}
static int pwc_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *parm)
{
struct pwc_device *pdev = video_drvdata(file);
int compression = 0;
int ret, fps;
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
parm->parm.capture.timeperframe.numerator == 0)
return -EINVAL;
if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;
fps = parm->parm.capture.timeperframe.denominator /
parm->parm.capture.timeperframe.numerator;
mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
ret = -ENODEV;
goto leave;
}
if (pdev->iso_init) {
ret = -EBUSY;
goto leave;
}
ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
fps, &compression, 0);
pwc_g_parm(file, fh, parm);
leave:
mutex_unlock(&pdev->udevlock);
return ret;
}
static int pwc_log_status(struct file *file, void *priv)
{
struct pwc_device *pdev = video_drvdata(file);
@ -1120,4 +1172,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
.vidioc_log_status = pwc_log_status,
.vidioc_enum_framesizes = pwc_enum_framesizes,
.vidioc_enum_frameintervals = pwc_enum_frameintervals,
.vidioc_g_parm = pwc_g_parm,
.vidioc_s_parm = pwc_s_parm,
};

View File

@ -44,6 +44,8 @@
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/input.h>
#endif
#include "pwc-dec1.h"
#include "pwc-dec23.h"
/* Version block */
#define PWC_VERSION "10.0.15"
@ -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 @@ struct pwc_device
char vmirror; /* for ToUCaM series */
char power_save; /* Do powersaving for this cam */
int cmd_len;
unsigned char cmd_buf[13];
unsigned char *ctrl_buf;
struct urb *urbs[MAX_ISO_BUFS];
char iso_init;
@ -272,7 +271,10 @@ struct pwc_device
int frame_total_size; /* including header & trailer */
int drop_frames;
void *decompress_data; /* private data for decompression engine */
union { /* private data for decompression engine */
struct pwc_dec1_private dec1;
struct pwc_dec23_private dec23;
};
/*
* We have an 'image' and a 'view', where 'image' is the fixed-size img
@ -364,7 +366,7 @@ void pwc_construct(struct pwc_device *pdev);
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int frames, int *compression);
int pixfmt, int frames, int *compression, int send_to_cam);
extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);

View File

@ -693,7 +693,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
mf->code = 0;
continue;
}
if (mf->width != tfmt->width || mf->width != tfmt->width) {
if (mf->width != tfmt->width || mf->height != tfmt->height) {
u32 fcc = ffmt->fourcc;
tfmt->width = mf->width;
tfmt->height = mf->height;
@ -702,7 +702,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
NULL, &fcc, FIMC_SD_PAD_SOURCE);
if (ffmt && ffmt->mbus_code)
mf->code = ffmt->mbus_code;
if (mf->width != tfmt->width || mf->width != tfmt->width)
if (mf->width != tfmt->width ||
mf->height != tfmt->height)
continue;
tfmt->code = mf->code;
}
@ -710,7 +711,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
if (mf->code == tfmt->code &&
mf->width == tfmt->width && mf->width == tfmt->width)
mf->width == tfmt->width && mf->height == tfmt->height)
break;
}

View File

@ -848,11 +848,11 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
V4L2_CID_ROTATE, 0, 270, 90, 0);
ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
V4L2_CID_HFLIP, 0, 1, 1, 0);
ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
V4L2_CID_ROTATE, 0, 270, 90, 0);
V4L2_CID_VFLIP, 0, 1, 1, 0);
if (variant->has_alpha)
ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,

View File

@ -21,7 +21,6 @@
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/media-device.h>

View File

@ -184,6 +184,7 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
ctx->rop = ROP4_INVERT;
else
ctx->rop = ROP4_COPY;
break;
default:
v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
return -EINVAL;

View File

@ -989,9 +989,10 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
* ============================================================================
*/
static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
struct s5p_jpeg_q_data *q_data = NULL;

View File

@ -18,7 +18,6 @@
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <media/videobuf2-core.h>
@ -475,7 +474,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
ctx->mv_size = 0;
}
ctx->dpb_count = s5p_mfc_get_dpb_count();
if (ctx->img_width == 0 || ctx->img_width == 0)
if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
else
ctx->state = MFCINST_HEAD_PARSED;

View File

@ -165,7 +165,7 @@ static struct mfc_control controls[] = {
.maximum = 32,
.step = 1,
.default_value = 1,
.flags = V4L2_CTRL_FLAG_VOLATILE,
.is_volatile = 1,
},
};

View File

@ -269,8 +269,6 @@ struct saa7164_board saa7164_boards[] = {
.portb = SAA7164_MPEG_DVB,
.portc = SAA7164_MPEG_ENCODER,
.portd = SAA7164_MPEG_ENCODER,
.portc = SAA7164_MPEG_ENCODER,
.portd = SAA7164_MPEG_ENCODER,
.porte = SAA7164_MPEG_VBI,
.portf = SAA7164_MPEG_VBI,
.chiprev = SAA7164_CHIP_REV3,
@ -333,8 +331,6 @@ struct saa7164_board saa7164_boards[] = {
.portd = SAA7164_MPEG_ENCODER,
.porte = SAA7164_MPEG_VBI,
.portf = SAA7164_MPEG_VBI,
.porte = SAA7164_MPEG_VBI,
.portf = SAA7164_MPEG_VBI,
.chiprev = SAA7164_CHIP_REV3,
.unit = {{
.id = 0x28,

View File

@ -374,7 +374,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
}
#endif
static bool check_firmware(struct usb_device *udev, int *down_firmware)
static int check_firmware(struct usb_device *udev, int *down_firmware)
{
void *buf;
int ret;
@ -398,7 +398,7 @@ static bool check_firmware(struct usb_device *udev, int *down_firmware)
*down_firmware = 1;
return firmware_download(udev);
}
return ret;
return 0;
}
static int poseidon_probe(struct usb_interface *interface,

View File

@ -465,8 +465,8 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_CHROMA_GAIN: return "Chroma Gain";
case V4L2_CID_ILLUMINATORS_1: return "Illuminator 1";
case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2";
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers";
case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers";
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Min Number of Capture Buffers";
case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min Number of Output Buffers";
case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
/* MPEG controls */
@ -506,25 +506,25 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "The Number of Intra Refresh MBs";
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "The Max Number of Reference Picture";
case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics";
case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_MIN_QP: return "H263 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_H263_MAX_QP: return "H263 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: return "H264 I-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: return "H264 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: return "H264 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: return "H264 8x8 Transform Enable";
case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: return "H264 CPB Buffer Size";
case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entorpy Mode";
case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I Period";
case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entropy Mode";
case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I-Frame Period";
case V4L2_CID_MPEG_VIDEO_H264_LEVEL: return "H264 Level";
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: return "H264 Loop Filter Alpha Offset";
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: return "H264 Loop Filter Beta Offset";
@ -535,16 +535,16 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable";
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC";
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: return "MPEG4 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: return "MPEG4 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: return "MPEG4 Level";
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: return "MPEG4 Profile";
case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: return "Quarter Pixel Search Enable";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "The Maximum Bytes Per Slice";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "The Number of MB in a Slice";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "The Slice Partitioning Method";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "Maximum Bytes in a Slice";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice";
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method";
case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size";
/* CAMERA controls */
@ -580,7 +580,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain";
case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
@ -588,24 +588,24 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled";
case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation";
case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency";
case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings";
case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis";
case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level";
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
/* Flash controls */
case V4L2_CID_FLASH_CLASS: return "Flash controls";
case V4L2_CID_FLASH_LED_MODE: return "LED mode";
case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe source";
case V4L2_CID_FLASH_CLASS: return "Flash Controls";
case V4L2_CID_FLASH_LED_MODE: return "LED Mode";
case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source";
case V4L2_CID_FLASH_STROBE: return "Strobe";
case V4L2_CID_FLASH_STROBE_STOP: return "Stop strobe";
case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe status";
case V4L2_CID_FLASH_TIMEOUT: return "Strobe timeout";
case V4L2_CID_FLASH_INTENSITY: return "Intensity, flash mode";
case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, torch mode";
case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
case V4L2_CID_FLASH_STROBE_STOP: return "Stop Strobe";
case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe Status";
case V4L2_CID_FLASH_TIMEOUT: return "Strobe Timeout";
case V4L2_CID_FLASH_INTENSITY: return "Intensity, Flash Mode";
case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, Torch Mode";
case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
case V4L2_CID_FLASH_FAULT: return "Faults";
case V4L2_CID_FLASH_CHARGE: return "Charge";
case V4L2_CID_FLASH_READY: return "Ready to strobe";
case V4L2_CID_FLASH_READY: return "Ready to Strobe";
default:
return NULL;

View File

@ -1871,6 +1871,7 @@ static long __video_do_ioctl(struct file *file,
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type;
if (!ops->vidioc_s_frequency)
break;
@ -1878,9 +1879,14 @@ static long __video_do_ioctl(struct file *file,
ret = ret_prio;
break;
}
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
ret = ops->vidioc_s_frequency(file, fh, p);
if (p->type != type)
ret = -EINVAL;
else
ret = ops->vidioc_s_frequency(file, fh, p);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:

View File

@ -1958,7 +1958,6 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
mutex_unlock(&zr->resource_lock);
fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
fb->fmt.field = V4L2_FIELD_INTERLACED;
fb->flags = V4L2_FBUF_FLAG_OVERLAY;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
return 0;

View File

@ -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)