Commit 40b8d50a authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman

staging/easycap: Implement interlaced modes and reduced framerates

Interlaced modes are requested by tvtime.  Reduced framerates are
preferred by some userspace programs, e.g. astronomy applications.
Signed-off-by: default avatarMike Thomas <rmthomas@sciolus.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f36bc37a
...@@ -200,7 +200,17 @@ ...@@ -200,7 +200,17 @@
#define NTSC_M_JP 5 #define NTSC_M_JP 5
#define PAL_60 7 #define PAL_60 7
#define PAL_M 9 #define PAL_M 9
#define STANDARD_MANY 10 #define PAL_BGHIN_SLOW 10
#define PAL_Nc_SLOW 12
#define SECAM_SLOW 14
#define NTSC_N_SLOW 16
#define NTSC_N_443_SLOW 18
#define NTSC_M_SLOW 11
#define NTSC_443_SLOW 13
#define NTSC_M_JP_SLOW 15
#define PAL_60_SLOW 17
#define PAL_M_SLOW 19
#define STANDARD_MANY 20
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* ENUMS * ENUMS
...@@ -228,7 +238,6 @@ PIXELFORMAT_MANY ...@@ -228,7 +238,6 @@ PIXELFORMAT_MANY
enum { enum {
FIELD_NONE, FIELD_NONE,
FIELD_INTERLACED, FIELD_INTERLACED,
FIELD_ALTERNATE,
INTERLACE_MANY INTERLACE_MANY
}; };
#define SETTINGS_MANY (STANDARD_MANY * \ #define SETTINGS_MANY (STANDARD_MANY * \
...@@ -333,6 +342,8 @@ bool ntsc; ...@@ -333,6 +342,8 @@ bool ntsc;
int fps; int fps;
int usec; int usec;
int tolerate; int tolerate;
int skip;
int skipped;
int merit[180]; int merit[180];
struct timeval timeval0; struct timeval timeval0;
...@@ -399,7 +410,6 @@ int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */ ...@@ -399,7 +410,6 @@ int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
__u32 pixelformat; __u32 pixelformat;
__u32 field;
int width; int width;
int height; int height;
int bytesperpixel; int bytesperpixel;
......
This diff is collapsed.
...@@ -471,7 +471,7 @@ if (NULL == peasycap->pusb_device) { ...@@ -471,7 +471,7 @@ if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
return -ENODEV; return -ENODEV;
} }
rc = usb_set_interface(peasycap->pusb_device, \ rc = usb_set_interface(peasycap->pusb_device,
peasycap->video_interface, \ peasycap->video_interface, \
peasycap->video_altsetting_off); peasycap->video_altsetting_off);
if (0 != rc) { if (0 != rc) {
...@@ -1103,7 +1103,7 @@ else ...@@ -1103,7 +1103,7 @@ else
int int
easycap_dqbuf(struct easycap *peasycap, int mode) easycap_dqbuf(struct easycap *peasycap, int mode)
{ {
int miss, rc; int ifield, miss, rc;
JOT(8, "\n"); JOT(8, "\n");
...@@ -1111,16 +1111,18 @@ if (NULL == peasycap) { ...@@ -1111,16 +1111,18 @@ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
return -EFAULT; return -EFAULT;
} }
ifield = 0;
JOM(8, "%i=ifield\n", ifield);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* WAIT FOR FIELD 0 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
miss = 0; miss = 0;
while ((peasycap->field_read == peasycap->field_fill) || \ while ((peasycap->field_read == peasycap->field_fill) || \
(0 != (0xFF00 & peasycap->field_buffer\ (0 != (0xFF00 & peasycap->field_buffer\
[peasycap->field_read][0].kount)) || \ [peasycap->field_read][0].kount)) || \
(0 != (0x00FF & peasycap->field_buffer\ (ifield != (0x00FF & peasycap->field_buffer\
[peasycap->field_read][0].kount))) { [peasycap->field_read][0].kount))) {
if (mode) if (mode)
return -EAGAIN; return -EAGAIN;
...@@ -1134,7 +1136,7 @@ while ((peasycap->field_read == peasycap->field_fill) || \ ...@@ -1134,7 +1136,7 @@ while ((peasycap->field_read == peasycap->field_fill) || \
((peasycap->field_read != peasycap->field_fill) && \ ((peasycap->field_read != peasycap->field_fill) && \
(0 == (0xFF00 & peasycap->field_buffer\ (0 == (0xFF00 & peasycap->field_buffer\
[peasycap->field_read][0].kount)) && \ [peasycap->field_read][0].kount)) && \
(0 == (0x00FF & peasycap->field_buffer\ (ifield == (0x00FF & peasycap->field_buffer\
[peasycap->field_read][0].kount))))))) { [peasycap->field_read][0].kount))))))) {
SAM("aborted by signal\n"); SAM("aborted by signal\n");
return -EIO; return -EIO;
...@@ -1176,33 +1178,20 @@ JOM(8, "first awakening on wq_video after %i waits\n", miss); ...@@ -1176,33 +1178,20 @@ JOM(8, "first awakening on wq_video after %i waits\n", miss);
rc = field2frame(peasycap); rc = field2frame(peasycap);
if (0 != rc) if (0 != rc)
SAM("ERROR: field2frame() returned %i\n", rc); SAM("ERROR: field2frame() returned %i\n", rc);
if (true == peasycap->offerfields) {
peasycap->frame_read = peasycap->frame_fill;
(peasycap->frame_fill)++;
if (peasycap->frame_buffer_many <= peasycap->frame_fill)
peasycap->frame_fill = 0;
if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
peasycap->frame_buffer[peasycap->frame_read][0].kount = \
V4L2_FIELD_BOTTOM;
} else {
peasycap->frame_buffer[peasycap->frame_read][0].kount = \
V4L2_FIELD_TOP;
}
JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* WAIT FOR FIELD 1 * WAIT FOR THE OTHER FIELD
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if (ifield)
ifield = 0;
else
ifield = 1;
miss = 0; miss = 0;
while ((peasycap->field_read == peasycap->field_fill) || \ while ((peasycap->field_read == peasycap->field_fill) || \
(0 != (0xFF00 & peasycap->field_buffer\ (0 != (0xFF00 & peasycap->field_buffer\
[peasycap->field_read][0].kount)) || \ [peasycap->field_read][0].kount)) || \
(0 == (0x00FF & peasycap->field_buffer\ (ifield != (0x00FF & peasycap->field_buffer\
[peasycap->field_read][0].kount))) { [peasycap->field_read][0].kount))) {
if (mode) if (mode)
return -EAGAIN; return -EAGAIN;
...@@ -1215,8 +1204,9 @@ while ((peasycap->field_read == peasycap->field_fill) || \ ...@@ -1215,8 +1204,9 @@ while ((peasycap->field_read == peasycap->field_fill) || \
((peasycap->field_read != peasycap->field_fill) && \ ((peasycap->field_read != peasycap->field_fill) && \
(0 == (0xFF00 & peasycap->field_buffer\ (0 == (0xFF00 & peasycap->field_buffer\
[peasycap->field_read][0].kount)) && \ [peasycap->field_read][0].kount)) && \
(0 != (0x00FF & peasycap->field_buffer\ (ifield == (0x00FF & peasycap->field_buffer\
[peasycap->field_read][0].kount))))))) { [peasycap->field_read][0].\
kount))))))) {
SAM("aborted by signal\n"); SAM("aborted by signal\n");
return -EIO; return -EIO;
} }
...@@ -1257,7 +1247,18 @@ JOM(8, "second awakening on wq_video after %i waits\n", miss); ...@@ -1257,7 +1247,18 @@ JOM(8, "second awakening on wq_video after %i waits\n", miss);
rc = field2frame(peasycap); rc = field2frame(peasycap);
if (0 != rc) if (0 != rc)
SAM("ERROR: field2frame() returned %i\n", rc); SAM("ERROR: field2frame() returned %i\n", rc);
/*---------------------------------------------------------------------------*/
/*
* WASTE THIS FRAME
*/
/*---------------------------------------------------------------------------*/
if (0 != peasycap->skip) {
peasycap->skipped++;
if (peasycap->skip != peasycap->skipped)
return peasycap->skip - peasycap->skipped;
peasycap->skipped = 0;
}
/*---------------------------------------------------------------------------*/
peasycap->frame_read = peasycap->frame_fill; peasycap->frame_read = peasycap->frame_fill;
peasycap->queued[peasycap->frame_read] = 0; peasycap->queued[peasycap->frame_read] = 0;
peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE; peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
...@@ -1289,8 +1290,7 @@ return 0; ...@@ -1289,8 +1290,7 @@ return 0;
* odd==false IS TRANSFERRED TO THE FRAME BUFFER. * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
* *
* THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
* CHOOSES THE OPTION V4L2_FIELD_ALTERNATE. NO USERSPACE PROGRAM TESTED * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
* TO DATE HAS DONE THIS. BUGS ARE LIKELY.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
...@@ -1315,8 +1315,10 @@ if ((struct easycap *)NULL == peasycap) { ...@@ -1315,8 +1315,10 @@ if ((struct easycap *)NULL == peasycap) {
badinput = false; badinput = false;
JOM(8, "===== parity %i, field buffer %i --> frame buffer %i\n", \ JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> " \
"frame buffer %i\n", \
peasycap->field_buffer[peasycap->field_read][0].kount,\ peasycap->field_buffer[peasycap->field_read][0].kount,\
peasycap->field_buffer[peasycap->field_read][0].input,\
peasycap->field_read, peasycap->frame_fill); peasycap->field_read, peasycap->frame_fill);
JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel); JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
if (true == peasycap->offerfields) if (true == peasycap->offerfields)
...@@ -1374,7 +1376,7 @@ if (peasycap->field_buffer[kex][0].kount) ...@@ -1374,7 +1376,7 @@ if (peasycap->field_buffer[kex][0].kount)
else else
odd = false; odd = false;
if ((true == odd) && (false == offerfields) &&(false == decimatepixel)) { if ((true == odd) && (false == decimatepixel)) {
JOM(8, " initial skipping %4i bytes p.%4i\n", \ JOM(8, " initial skipping %4i bytes p.%4i\n", \
w3/multiplier, mad); w3/multiplier, mad);
pad += (w3 / multiplier); rad -= (w3 / multiplier); pad += (w3 / multiplier); rad -= (w3 / multiplier);
...@@ -1494,7 +1496,7 @@ while (cz < wz) { ...@@ -1494,7 +1496,7 @@ while (cz < wz) {
* UNLESS IT IS THE LAST LINE OF AN ODD FRAME * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if (((false == odd) || (cz != wz))&&(false == offerfields)) { if ((false == odd) || (cz != wz)) {
over = w3; over = w3;
do { do {
if (!rad) { if (!rad) {
...@@ -3162,6 +3164,15 @@ if (purb->status) { ...@@ -3162,6 +3164,15 @@ if (purb->status) {
[peasycap->field_page]; [peasycap->field_page];
pfield_buffer->pto = \ pfield_buffer->pto = \
pfield_buffer->pgo; pfield_buffer->pgo;
pfield_buffer->input = 0x08 | \
(0x07 & peasycap->input);
if ((peasycap->field_buffer[peasycap->\
field_fill][0]).\
input != \
pfield_buffer->input)
(peasycap->field_buffer\
[peasycap->field_fill]\
[0]).kount |= 0x1000;
} }
much = PAGE_SIZE - (int)(pfield_buffer->pto - \ much = PAGE_SIZE - (int)(pfield_buffer->pto - \
...@@ -3441,7 +3452,6 @@ if (0 == bInterfaceNumber) { ...@@ -3441,7 +3452,6 @@ if (0 == bInterfaceNumber) {
break; break;
} }
} }
if (DONGLE_MANY <= dongle_this) { if (DONGLE_MANY <= dongle_this) {
SAM("ERROR: too many dongles\n"); SAM("ERROR: too many dongles\n");
return -ENOMEM; return -ENOMEM;
...@@ -3481,6 +3491,8 @@ if (0 == bInterfaceNumber) { ...@@ -3481,6 +3491,8 @@ if (0 == bInterfaceNumber) {
peasycap->frame_buffer_many = FRAME_BUFFER_MANY; peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
peasycap->skip = 0;
peasycap->skipped = 0;
peasycap->offerfields = 0; peasycap->offerfields = 0;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment