summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-26 11:41:31 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-26 11:41:31 -0300
commitf91c5159e955b9f563132594901d5bafde53a778 (patch)
tree618e0db4f057401737eba947b2a56c351670dbec
parentdb4d37c1958dfc961b95a7440bac15b8cb53693c (diff)
parent1f097239385b1fd33b50c5fee7fb5651d252110c (diff)
downloadmediapointer-dvb-s2-f91c5159e955b9f563132594901d5bafde53a778.tar.gz
mediapointer-dvb-s2-f91c5159e955b9f563132594901d5bafde53a778.tar.bz2
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-cards.c108
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-cards.h5
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.c41
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-gpio.c9
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-i2c.c3
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.c44
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-irq.c4
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-version.h2
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c2
-rw-r--r--v4l2-apps/util/Makefile11
-rw-r--r--v4l2-apps/util/ivtv-ctl.c635
11 files changed, 778 insertions, 86 deletions
diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c
index 92e4b85f9..753d28209 100644
--- a/linux/drivers/media/video/ivtv/ivtv-cards.c
+++ b/linux/drivers/media/video/ivtv/ivtv-cards.c
@@ -40,6 +40,8 @@
#define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM)
+
/* usual i2c tuner addresses to probe */
static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
.radio = { I2C_CLIENT_END },
@@ -298,7 +300,7 @@ static const struct ivtv_card ivtv_card_mpg600 = {
.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
.tuners = {
/* The PAL tuner is confirmed */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_mpg600,
@@ -339,7 +341,7 @@ static const struct ivtv_card ivtv_card_mpg160 = {
.lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 },
.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_mpg160,
@@ -375,7 +377,7 @@ static const struct ivtv_card ivtv_card_pg600 = {
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
},
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_pg600,
@@ -416,7 +418,7 @@ static const struct ivtv_card ivtv_card_avc2410 = {
on the country/region setting of the user to decide which tuner
is available. */
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
.tuner = TUNER_PHILIPS_FM1236_MK3 },
{ .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
@@ -490,7 +492,7 @@ static const struct ivtv_card ivtv_card_tg5000tv = {
.gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
.composite = 0x0010, .svideo = 0x0020 },
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_tg5000tv,
.i2c = &ivtv_i2c_std,
@@ -521,7 +523,7 @@ static const struct ivtv_card ivtv_card_va2000 = {
{ IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
},
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_va2000,
.i2c = &ivtv_i2c_std,
@@ -565,7 +567,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.pci_list = ivtv_pci_cx23416gyc,
@@ -597,7 +599,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.i2c = &ivtv_i2c_std,
@@ -627,7 +629,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.i2c = &ivtv_i2c_std,
@@ -667,7 +669,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
.gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
.tuners = {
/* This card has the Panasonic VP27 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
},
.pci_list = ivtv_pci_gv_mvprx,
.i2c = &ivtv_i2c_std,
@@ -704,7 +706,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
.gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
.tuners = {
/* This card has the Panasonic VP27 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
},
.pci_list = ivtv_pci_gv_mvprx2e,
.i2c = &ivtv_i2c_std,
@@ -739,7 +741,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
.gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
.tuners = {
/* This card has a Philips FQ1216ME MK3 tuner */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
},
.pci_list = ivtv_pci_gotview_pci_dvd,
.i2c = &ivtv_i2c_std,
@@ -778,7 +780,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
.gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
.tuners = {
/* This card has a Philips FQ1216ME MK5 tuner */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
},
.pci_list = ivtv_pci_gotview_pci_dvd2,
.i2c = &ivtv_i2c_std,
@@ -856,7 +858,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
.gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
.composite = 0x0010, .svideo = 0x0020},
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_dctmvtvp1,
.i2c = &ivtv_i2c_std,
@@ -875,6 +877,7 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
static const struct ivtv_card ivtv_card_pg600v2 = {
.type = IVTV_CARD_PG600V2,
.name = "Yuan PG600-2, GotView PCI DVD Lite",
+ .comment = "only Composite and S-Video inputs are supported, not the tuner\n",
.v4l2_capabilities = IVTV_CAP_ENCODER,
.hw_video = IVTV_HW_CX25840,
.hw_audio = IVTV_HW_CX25840,
@@ -895,6 +898,7 @@ static const struct ivtv_card ivtv_card_pg600v2 = {
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
.gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
+ .xceive_pin = 12,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
@@ -942,6 +946,7 @@ static const struct ivtv_card ivtv_card_club3d = {
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
.gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
+ .xceive_pin = 12,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
@@ -965,34 +970,22 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = {
.hw_video = IVTV_HW_CX25840,
.hw_audio = IVTV_HW_CX25840,
.hw_audio_ctrl = IVTV_HW_CX25840,
-#if 0
- /* XC2028 support has problems with fw loading on this card,
- so don't support this tuner for this card until this issue
- has been solved. */
.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
.video_inputs = {
- { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
- { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+ { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
+ { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
},
.audio_inputs = {
+ { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
},
/* enable line-in */
- .gpio_init = { .direction = 0xf000, .initial_value = 0x5000 },
+ .gpio_init = { .direction = 0xe400, .initial_value = 0x4400 },
+ .xceive_pin = 10,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
-#else
- .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
- .video_inputs = {
- { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
- { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
- },
- .audio_inputs = {
- { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
- },
- .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */
-#endif
.pci_list = ivtv_pci_avertv_mce116,
.i2c = &ivtv_i2c_std,
};
@@ -1030,7 +1023,7 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = {
.gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
.tuners = {
/* This card has a Partsnic PTI-5NF05 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_TCL_2002N },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_TCL_2002N },
},
.pci_list = ivtv_pci_aver_pvr150,
.i2c = &ivtv_i2c_radio,
@@ -1098,12 +1091,48 @@ static const struct ivtv_card ivtv_card_asus_falcon2 = {
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.pci_list = ivtv_pci_asus_falcon2,
.i2c = &ivtv_i2c_std,
};
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M104 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
+ { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
+ { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_m104 = {
+ .type = IVTV_CARD_AVER_M104,
+ .name = "AVerMedia M104",
+ .comment = "Not yet supported!\n",
+ .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
+ .hw_video = IVTV_HW_CX25840,
+ .hw_audio = IVTV_HW_CX25840,
+ .hw_audio_ctrl = IVTV_HW_CX25840,
+ .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+ .video_inputs = {
+ { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+ },
+ .audio_inputs = {
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
+ },
+ .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+ /* enable line-in + reset tuner */
+ .gpio_init = { .direction = 0xe400, .initial_value = 0x4000 },
+ .xceive_pin = 10,
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .pci_list = ivtv_pci_aver_m104,
+ .i2c = &ivtv_i2c_std,
+};
+
static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_pvr250,
&ivtv_card_pvr350,
@@ -1129,6 +1158,7 @@ static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_asus_falcon2,
&ivtv_card_aver_pvr150,
&ivtv_card_aver_ezmaker,
+ &ivtv_card_aver_m104,
/* Variations of standard cards but with the same PCI IDs.
These cards must come last in this list. */
@@ -1160,7 +1190,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
if (index >= itv->nof_inputs)
return -EINVAL;
input->index = index;
- strcpy(input->name, input_strs[card_input->video_type - 1]);
+ strlcpy(input->name, input_strs[card_input->video_type - 1],
+ sizeof(input->name));
input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
input->audioset = (1 << itv->nof_audio_inputs) - 1;
@@ -1177,7 +1208,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
if (index >= itv->card->nof_outputs)
return -EINVAL;
output->index = index;
- strcpy(output->name, card_output->name);
+ strlcpy(output->name, card_output->name, sizeof(output->name));
output->type = V4L2_OUTPUT_TYPE_ANALOG;
output->audioset = 1;
output->std = V4L2_STD_ALL;
@@ -1196,7 +1227,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
memset(audio, 0, sizeof(*audio));
if (index >= itv->nof_audio_inputs)
return -EINVAL;
- strcpy(audio->name, input_strs[aud_input->audio_type - 1]);
+ strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+ sizeof(audio->name));
audio->index = index;
audio->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -1207,6 +1239,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud
memset(aud_output, 0, sizeof(*aud_output));
if (itv->card->video_outputs == NULL || index != 0)
return -EINVAL;
- strcpy(aud_output->name, "A/V Audio Out");
+ strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
return 0;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.h b/linux/drivers/media/video/ivtv/ivtv-cards.h
index 9186fa2ee..748485dce 100644
--- a/linux/drivers/media/video/ivtv/ivtv-cards.h
+++ b/linux/drivers/media/video/ivtv/ivtv-cards.h
@@ -48,7 +48,8 @@
#define IVTV_CARD_ASUS_FALCON2 21 /* ASUS Falcon2 */
#define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */
#define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */
-#define IVTV_CARD_LAST 23
+#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */
+#define IVTV_CARD_LAST 24
/* Variants of existing cards but with the same PCI IDs. The driver
detects these based on other device information.
@@ -244,6 +245,7 @@ struct ivtv_card_tuner_i2c {
struct ivtv_card {
int type;
char *name;
+ char *comment;
u32 v4l2_capabilities;
u32 hw_video; /* hardware used to process video */
u32 hw_audio; /* hardware used to process audio */
@@ -256,6 +258,7 @@ struct ivtv_card {
int nof_outputs;
const struct ivtv_card_output *video_outputs;
u8 gr_config; /* config byte for the ghost reduction device */
+ u8 xceive_pin; /* XCeive tuner GPIO reset pin */
/* GPIO card-specific settings */
struct ivtv_gpio_init gpio_init;
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c
index fdb2e5848..dba0295bc 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.c
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.c
@@ -190,6 +190,7 @@ MODULE_PARM_DESC(cardtype,
"\t\t\t22 = ASUS Falcon2\n"
"\t\t\t23 = AverMedia PVR-150 Plus\n"
"\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+ "\t\t\t25 = AverMedia M104 (not yet working)\n"
"\t\t\t 0 = Autodetect (default)\n"
"\t\t\t-1 = Ignore this card\n\t\t");
MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
@@ -1101,6 +1102,13 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
The PCI IDs are not always reliable. */
ivtv_process_eeprom(itv);
}
+ if (itv->card->comment)
+ IVTV_INFO("%s", itv->card->comment);
+ if (itv->card->v4l2_capabilities == 0) {
+ /* card was detected but is not supported */
+ retval = -ENODEV;
+ goto free_i2c;
+ }
if (itv->std == 0) {
itv->std = V4L2_STD_NTSC_M;
@@ -1199,13 +1207,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
}
- retval = ivtv_streams_setup(itv);
- if (retval) {
- IVTV_ERR("Error %d setting up streams\n", retval);
- goto free_i2c;
- }
-
- IVTV_DEBUG_IRQ("Masking interrupts\n");
/* clear interrupt mask, effectively disabling interrupts */
ivtv_set_irq_mask(itv, 0xffffffff);
@@ -1214,32 +1215,38 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv);
if (retval) {
IVTV_ERR("Failed to register irq %d\n", retval);
- goto free_streams;
+ goto free_i2c;
+ }
+
+ retval = ivtv_streams_setup(itv);
+ if (retval) {
+ IVTV_ERR("Error %d setting up streams\n", retval);
+ goto free_irq;
}
retval = ivtv_streams_register(itv);
if (retval) {
IVTV_ERR("Error %d registering devices\n", retval);
- goto free_irq;
+ goto free_streams;
}
IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
return 0;
- free_irq:
- free_irq(itv->dev->irq, (void *)itv);
- free_streams:
+free_streams:
ivtv_streams_cleanup(itv);
- free_i2c:
+free_irq:
+ free_irq(itv->dev->irq, (void *)itv);
+free_i2c:
exit_ivtv_i2c(itv);
- free_io:
+free_io:
ivtv_iounmap(itv);
- free_mem:
+free_mem:
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
- free_workqueue:
+free_workqueue:
destroy_workqueue(itv->irq_work_queues);
- err:
+err:
if (retval == 0)
retval = -ENODEV;
IVTV_ERR("Error %d on initialization\n", retval);
diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c
index 688cd3856..d8ac09f3c 100644
--- a/linux/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c
@@ -128,20 +128,17 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
{
struct i2c_algo_bit_data *algo = dev;
struct ivtv *itv = algo->data;
- int curdir, curout;
+ u32 curout;
if (cmd != XC2028_TUNER_RESET)
return 0;
IVTV_DEBUG_INFO("Resetting tuner\n");
curout = read_reg(IVTV_REG_GPIO_OUT);
- curdir = read_reg(IVTV_REG_GPIO_DIR);
- curdir |= (1 << 12); /* GPIO bit 12 */
-
- curout &= ~(1 << 12);
+ curout &= ~(1 << itv->card->xceive_pin);
write_reg(curout, IVTV_REG_GPIO_OUT);
schedule_timeout_interruptible(msecs_to_jiffies(1));
- curout |= (1 << 12);
+ curout |= 1 << itv->card->xceive_pin;
write_reg(curout, IVTV_REG_GPIO_OUT);
schedule_timeout_interruptible(msecs_to_jiffies(1));
return 0;
diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c
index 77b4f960b..db9243b08 100644
--- a/linux/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c
@@ -168,7 +168,8 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
return -1;
id = hw_driverids[idx];
memset(&info, 0, sizeof(info));
- strcpy(info.driver_name, hw_drivernames[idx]);
+ strlcpy(info.driver_name, hw_drivernames[idx],
+ sizeof(info.driver_name));
info.addr = hw_addrs[idx];
for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {}
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
index b94d1873d..9de530d02 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -243,20 +243,31 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
int fact = new_speed < 0 ? -1 : 1;
int s;
- if (new_speed < 0) new_speed = -new_speed;
- if (cur_speed < 0) cur_speed = -cur_speed;
+ if (cur_speed == 0)
+ cur_speed = 1000;
+ if (new_speed < 0)
+ new_speed = -new_speed;
+ if (cur_speed < 0)
+ cur_speed = -cur_speed;
if (cur_speed <= new_speed) {
- if (new_speed > 1500) return fact * 2000;
- if (new_speed > 1000) return fact * 1500;
+ if (new_speed > 1500)
+ return fact * 2000;
+ if (new_speed > 1000)
+ return fact * 1500;
}
else {
- if (new_speed >= 2000) return fact * 2000;
- if (new_speed >= 1500) return fact * 1500;
- if (new_speed >= 1000) return fact * 1000;
- }
- if (new_speed == 0) return 1000;
- if (new_speed == 1 || new_speed == 1000) return fact * new_speed;
+ if (new_speed >= 2000)
+ return fact * 2000;
+ if (new_speed >= 1500)
+ return fact * 1500;
+ if (new_speed >= 1000)
+ return fact * 1000;
+ }
+ if (new_speed == 0)
+ return 1000;
+ if (new_speed == 1 || new_speed == 1000)
+ return fact * new_speed;
s = new_speed;
new_speed = 1000 / new_speed;
@@ -747,10 +758,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
struct v4l2_capability *vcap = arg;
memset(vcap, 0, sizeof(*vcap));
- strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
- strncpy(vcap->card, itv->card_name,
- sizeof(vcap->card)-1); /* card type */
- strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
+ strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
+ strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
+ strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
vcap->version = IVTV_DRIVER_VERSION; /* version */
vcap->capabilities = itv->v4l2_cap; /* capabilities */
@@ -1024,7 +1034,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_std_60hz : ivtv_std_50hz;
vs->index = idx;
vs->id = enum_stds[idx].std;
- strcpy(vs->name, enum_stds[idx].name);
+ strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
break;
}
@@ -1108,10 +1118,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
- strcpy(vt->name, "ivtv Radio Tuner");
+ strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
vt->type = V4L2_TUNER_RADIO;
} else {
- strcpy(vt->name, "ivtv TV Tuner");
+ strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
vt->type = V4L2_TUNER_ANALOG_TV;
}
break;
diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c
index 0e417d860..41066e87f 100644
--- a/linux/drivers/media/video/ivtv/ivtv-irq.c
+++ b/linux/drivers/media/video/ivtv/ivtv-irq.c
@@ -390,7 +390,7 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
ivtv_stream_sync_for_device(s);
write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
add_timer(&itv->dma_timer);
}
@@ -406,7 +406,7 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
ivtv_stream_sync_for_device(s);
write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
add_timer(&itv->dma_timer);
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-version.h b/linux/drivers/media/video/ivtv/ivtv-version.h
index 0f1d4cc4b..02c5ab071 100644
--- a/linux/drivers/media/video/ivtv/ivtv-version.h
+++ b/linux/drivers/media/video/ivtv/ivtv-version.h
@@ -23,7 +23,7 @@
#define IVTV_DRIVER_NAME "ivtv"
#define IVTV_DRIVER_VERSION_MAJOR 1
#define IVTV_DRIVER_VERSION_MINOR 2
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
+#define IVTV_DRIVER_VERSION_PATCHLEVEL 1
#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
#define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index 3b23fc05f..df789f683 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -532,7 +532,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, "cx23415 TV out");
+ strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
fix->smem_start = oi->video_pbase;
fix->smem_len = oi->video_buffer_size;
fix->type = FB_TYPE_PACKED_PIXELS;
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile
index 34fc9a103..be1e4f83e 100644
--- a/v4l2-apps/util/Makefile
+++ b/v4l2-apps/util/Makefile
@@ -1,8 +1,13 @@
# Makefile for linuxtv.org v4l2-apps/util
-CPPFLAGS += -I../../linux/include
+CPPFLAGS += -I../../linux/include -D_GNU_SOURCE
+LDFLAGS += -lm
-binaries = v4l2-ctl v4l2-dbg
+binaries = v4l2-ctl v4l2-dbg ivtv-ctl
+
+ifeq ($(prefix),)
+prefix = /usr
+endif
.PHONY: all clean install qv4l2
@@ -22,6 +27,8 @@ v4l2-dbg: v4l2-dbg.o v4l2-driverids.o v4l2-chipids.o
$(CXX) $^ -o $@
install:
+ mkdir -p $(prefix)/bin
+ cp $(binaries) $(prefix)/bin
include ../Make.rules
diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c
new file mode 100644
index 000000000..9d9808890
--- /dev/null
+++ b/v4l2-apps/util/ivtv-ctl.c
@@ -0,0 +1,635 @@
+/*
+ Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo dot com>
+
+ Cleanup and VBI and audio in/out options:
+ Copyright (C) 2004 Hans Verkuil <hverkuil@xs4all.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <features.h> /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <math.h>
+#include <linux/types.h>
+#include <sys/klog.h>
+
+#include <linux/videodev2.h>
+#include <linux/dvb/video.h>
+
+/* copied from ivtv-driver.h */
+#define IVTV_DBGFLG_WARN (1 << 0)
+#define IVTV_DBGFLG_INFO (1 << 1)
+#define IVTV_DBGFLG_MB (1 << 2)
+#define IVTV_DBGFLG_IOCTL (1 << 3)
+#define IVTV_DBGFLG_FILE (1 << 4)
+#define IVTV_DBGFLG_DMA (1 << 5)
+#define IVTV_DBGFLG_IRQ (1 << 6)
+#define IVTV_DBGFLG_DEC (1 << 7)
+#define IVTV_DBGFLG_YUV (1 << 8)
+#define IVTV_DBGFLG_I2C (1 << 9)
+/* Flag to turn on high volume debugging */
+#define IVTV_DBGFLG_HIGHVOL (1 << 10)
+
+/* Internals copied from media/v4l2-common.h */
+struct v4l2_routing {
+ __u32 input;
+ __u32 output;
+};
+#define VIDIOC_INT_S_AUDIO_ROUTING _IOW('d', 109, struct v4l2_routing)
+
+#define VIDIOC_INT_RESET _IOW('d', 102, __u32)
+
+#include <linux/ivtv.h>
+
+/* GPIO */
+#define IVTV_REG_GPIO_IN_OFFSET (0x9008 + 0x02000000)
+#define IVTV_REG_GPIO_OUT_OFFSET (0x900c + 0x02000000)
+#define IVTV_REG_GPIO_DIR_OFFSET (0x9020 + 0x02000000)
+
+/* Options */
+enum Option {
+ OptSetDebugLevel = 'D',
+ OptSetDevice = 'd',
+ OptGetDebugLevel = 'e',
+ OptHelp = 'h',
+ OptSetGPIO = 'i',
+ OptListGPIO = 'I',
+ OptPassThrough = 'K',
+ OptFrameSync = 'k',
+ OptSetAudioRoute = 'v',
+ OptReset = 128,
+ OptSetYuvMode,
+ OptGetYuvMode,
+ OptLast = 256
+};
+
+static char options[OptLast];
+
+static struct option long_options[] = {
+ /* Please keep in alphabetical order of the short option.
+ That makes it easier to see which options are still free. */
+ {"set-debug", required_argument, 0, OptSetDebugLevel},
+ {"device", required_argument, 0, OptSetDevice},
+ {"get-debug", no_argument, 0, OptGetDebugLevel},
+ {"help", no_argument, 0, OptHelp},
+ {"set-gpio", required_argument, 0, OptSetGPIO},
+ {"list-gpio", no_argument, 0, OptListGPIO},
+ {"passthrough", required_argument, 0, OptPassThrough},
+ {"sync", no_argument, 0, OptFrameSync},
+ {"audio-route", required_argument, 0, OptSetAudioRoute},
+ {"reset", required_argument, 0, OptReset},
+ {"get-yuv-mode", no_argument, 0, OptGetYuvMode},
+ {"set-yuv-mode", required_argument, 0, OptSetYuvMode},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf(" -d, --device <dev> use device <dev> instead of /dev/video0\n");
+ printf(" -h, --help display this help message\n");
+ printf(" -K, --passthrough <mode>\n");
+ printf(" set passthrough mode: 1 = on, 0 = off [IVTV_IOC_PASSTHROUGH]\n");
+ printf(" --get-yuv-mode display the current yuv mode\n");
+ printf(" --set-yuv-mode mode=<mode>\n");
+ printf(" set the current yuv mode:\n");
+ printf(" mode 0: interlaced (top transmitted first)\n");
+ printf(" mode 1: interlaced (bottom transmitted first)\n");
+ printf(" mode 2: progressive\n");
+ printf(" mode 3: auto\n");
+ printf(" --reset <mask> reset the infrared receiver (1) or digitizer (2) [VIDIOC_INT_RESET]\n");
+ printf("\n");
+ printf("Expert options:\n");
+ printf(" -D, --set-debug <level>\n");
+ printf(" set the module debug variable\n");
+ printf(" 1/0x0001: warning\n");
+ printf(" 2/0x0002: info\n");
+ printf(" 4/0x0004: mailbox\n");
+ printf(" 8/0x0008: ioctl\n");
+ printf(" 16/0x0010: file\n");
+ printf(" 32/0x0020: dma\n");
+ printf(" 64/0x0040: irq\n");
+ printf(" 128/0x0080: decoder\n");
+ printf(" 256/0x0100: yuv\n");
+ printf(" 512/0x0200: i2c\n");
+ printf(" 1024/0x0400: high volume\n");
+ printf(" -e, --get-debug query the module debug variable\n");
+ printf(" -I, --list-gpio\n");
+ printf(" show GPIO input/direction/output bits\n");
+ printf(" -i, --set-gpio [dir=<dir>,]val=<val>\n");
+ printf(" set GPIO direction bits to <dir> and set output to <val>\n");
+ printf(" -k, --sync test vsync's capabilities [VIDEO_GET_EVENT]\n");
+ printf(" -v, --audio-route=input=<in>,output=<out>\n");
+ printf(" set the audio input/output routing [VIDIOC_INT_S_AUDIO_ROUTING]\n");
+ exit(0);
+}
+
+static char *pts_to_string(char *str, unsigned long pts, float fps)
+{
+ static char buf[256];
+ int hours, minutes, seconds, fracsec;
+ int frame;
+ char *p = (str) ? str : buf;
+
+ static const int MPEG_CLOCK_FREQ = 90000;
+ seconds = pts / MPEG_CLOCK_FREQ;
+ fracsec = pts % MPEG_CLOCK_FREQ;
+
+ minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ frame = (int)ceilf(((float)fracsec / (float)MPEG_CLOCK_FREQ) * fps);
+
+ snprintf(p, sizeof(buf), "%d:%02d:%02d:%d", hours, minutes, seconds, frame);
+ return p;
+}
+
+static void print_debug_mask(int mask)
+{
+#define MASK_OR_NOTHING (mask ? " | " : "")
+ if (mask & IVTV_DBGFLG_WARN) {
+ mask &= ~IVTV_DBGFLG_WARN;
+ printf("IVTV_DBGFLG_WARN%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_INFO) {
+ mask &= ~IVTV_DBGFLG_INFO;
+ printf("IVTV_DBGFLG_INFO%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_MB) {
+ mask &= ~IVTV_DBGFLG_MB;
+ printf("IVTV_DBGFLG_MB%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_DMA) {
+ mask &= ~IVTV_DBGFLG_DMA;
+ printf("IVTV_DBGFLG_DMA%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_IOCTL) {
+ mask &= ~IVTV_DBGFLG_IOCTL;
+ printf("IVTV_DBGFLG_IOCTL%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_FILE) {
+ mask &= ~IVTV_DBGFLG_FILE;
+ printf("IVTV_DBGFLG_FILE%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_I2C) {
+ mask &= ~IVTV_DBGFLG_I2C;
+ printf("IVTV_DBGFLG_I2C%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_IRQ) {
+ mask &= ~IVTV_DBGFLG_IRQ;
+ printf("IVTV_DBGFLG_IRQ%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_DEC) {
+ mask &= ~IVTV_DBGFLG_DEC;
+ printf("IVTV_DBGFLG_DEC%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_YUV) {
+ mask &= ~IVTV_DBGFLG_YUV;
+ printf("IVTV_DBGFLG_YUV%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_HIGHVOL) {
+ mask &= ~IVTV_DBGFLG_HIGHVOL;
+ printf("IVTV_DBGFLG_HIGHVOL%s", MASK_OR_NOTHING);
+ }
+ if (mask)
+ printf("0x%08x", mask);
+ printf("\n");
+}
+
+static int dowrite(const char *buf, const char *fn)
+{
+ FILE *f = fopen(fn, "w");
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return errno;
+ }
+ fprintf(f, buf);
+ fclose(f);
+ return 0;
+}
+
+static char *doread(const char *fn)
+{
+ static char buf[1000];
+ FILE *f = fopen(fn, "r");
+ int s;
+
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return NULL;
+ }
+ s = fread(buf, 1, sizeof(buf) - 1, f);
+ buf[s] = 0;
+ fclose(f);
+ return buf;
+}
+
+static const char *field2s(int val)
+{
+ switch (val) {
+ case V4L2_FIELD_ANY:
+ return "Any";
+ case V4L2_FIELD_NONE:
+ return "None";
+ case V4L2_FIELD_TOP:
+ return "Top";
+ case V4L2_FIELD_BOTTOM:
+ return "Bottom";
+ case V4L2_FIELD_INTERLACED:
+ return "Interlaced";
+ case V4L2_FIELD_SEQ_TB:
+ return "Sequential Top-Bottom";
+ case V4L2_FIELD_SEQ_BT:
+ return "Sequential Bottom-Top";
+ case V4L2_FIELD_ALTERNATE:
+ return "Alternating";
+ case V4L2_FIELD_INTERLACED_TB:
+ return "Interlaced Top-Bottom";
+ case V4L2_FIELD_INTERLACED_BT:
+ return "Interlaced Bottom-Top";
+ default:
+ return "Unknown";
+ }
+}
+
+static int doioctl(int fd, int request, void *parm, const char *name)
+{
+ int retVal;
+
+ printf("ioctl %s ", name);
+ retVal = ioctl(fd, request, parm);
+ if (retVal < 0)
+ printf("failed: %s\n", strerror(errno));
+ else
+ printf("ok\n");
+
+ return retVal;
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+ char *subopts[] = {
+#define SUB_VAL 0
+ "val",
+#define SUB_YUV_MODE 1
+ "mode",
+#define SUB_DIR 2
+ "dir",
+#define SUB_INPUT 3
+ "input",
+#define SUB_OUTPUT 4
+ "output",
+
+ NULL
+ };
+
+ int fd = -1;
+
+ /* bitfield for OptSetCodec */
+
+ /* command args */
+ char *device = strdup("/dev/video0"); /* -d device */
+ int ch;
+ int yuv_mode = 0;
+ struct v4l2_routing route; /* audio_route */
+ unsigned short gpio_out = 0x0; /* GPIO output data */
+ unsigned short gpio_dir = 0x0; /* GPIO direction bits */
+ int gpio_set_dir = 0;
+ int passthrough = 0;
+ int debug_level = 0;
+ __u32 reset = 0;
+ int new_debug_level, gdebug_level;
+ double timestamp;
+ char ptsstr[64];
+ char short_options[26 * 2 * 2 + 1];
+
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+ while (1) {
+ int option_index = 0;
+ int idx = 0;
+
+ for (i = 0; long_options[i].name; i++) {
+ if (!isalpha(long_options[i].val))
+ continue;
+ short_options[idx++] = long_options[i].val;
+ if (long_options[i].has_arg == required_argument)
+ short_options[idx++] = ':';
+ }
+ short_options[idx] = 0;
+ ch = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (ch == -1)
+ break;
+
+ options[(int)ch] = 1;
+ switch (ch) {
+ case OptSetYuvMode:
+ {
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_YUV_MODE:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <mode>\n");
+ usage();
+ return 1;
+
+ }
+ yuv_mode = strtol(value, 0L, 0);
+ if (yuv_mode < 0 || yuv_mode > 3) {
+ fprintf(stderr, "invalid yuv mode\n");
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case OptHelp:
+ usage();
+ return 0;
+ case OptSetDebugLevel:{
+ debug_level = strtol(optarg, 0L, 0);
+ break;
+ }
+ case OptSetDevice:
+ device = strdup(optarg);
+ if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
+ char dev = device[0];
+
+ sprintf(device, "/dev/video%c", dev);
+ }
+ break;
+ case OptSetAudioRoute:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_INPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <input>\n");
+ usage();
+ }
+ route.input = strtol(value, 0L, 0);
+ break;
+ case SUB_OUTPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <output>\n");
+ usage();
+ }
+ route.output = strtol(value, 0L, 0);
+ break;
+ default:
+ printf
+ ("Invalid suboptions specified\n");
+ usage();
+ break;
+ }
+ }
+ break;
+ case OptReset:
+ reset = strtol(optarg, 0L, 0);
+ break;
+ case OptPassThrough:
+ passthrough = strtol(optarg, 0L, 0);
+ break;
+ case OptSetGPIO:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_DIR:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <dir>\n");
+ usage();
+ exit(1);
+ }
+ gpio_dir = strtol(value, 0L, 0);
+ gpio_set_dir = 1;
+ break;
+ case SUB_VAL:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <val>\n");
+ usage();
+ exit(1);
+ }
+ gpio_out = (unsigned short)strtol(value, 0L, 0);
+ break;
+ default:
+ fprintf(stderr,
+ "Invalid suboptions specified\n");
+ usage();
+ exit(1);
+ break;
+ }
+ }
+ break;
+ case ':':
+ fprintf(stderr, "Option `%s' requires a value\n",
+ argv[optind]);
+ usage();
+ return 1;
+ case '?':
+ fprintf(stderr, "Unknown argument `%s'\n",
+ argv[optind]);
+ usage();
+ return 1;
+ }
+ }
+ if (optind < argc) {
+ printf("unknown arguments: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ usage();
+ return 1;
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", device,
+ strerror(errno));
+ exit(1);
+ }
+ free(device);
+
+ /* Setting Opts */
+
+ if (options[OptSetAudioRoute])
+ doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route,
+ "VIDIOC_INT_S_AUDIO_ROUTING");
+
+ if (options[OptFrameSync]) {
+ printf("ioctl: VIDEO_GET_EVENT\n");
+
+ for (;;) {
+ struct video_event ev;
+ int fps = 30;
+ v4l2_std_id std;
+
+ if (ioctl(fd, VIDIOC_G_STD, &std) == 0)
+ fps = (std & V4L2_STD_525_60) ? 30 : 25;
+ if (ioctl(fd, VIDEO_GET_EVENT, &ev) < 0) {
+ fprintf(stderr, "ioctl: VIDEO_GET_EVENT failed\n");
+ break;
+ } else if (ev.timestamp == 0) {
+ unsigned long long pts = 0, frame = 0;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ timestamp =
+ (double)tv.tv_sec +
+ ((double)tv.tv_usec / 1000000.0);
+
+ ioctl(fd, VIDEO_GET_PTS, &pts);
+ ioctl(fd, VIDEO_GET_FRAME_COUNT, &frame);
+ pts_to_string(ptsstr, pts, fps);
+ printf("%10.6f: pts %-20s, %lld frames\n",
+ timestamp, ptsstr, frame);
+ }
+ }
+ }
+
+ if (options[OptSetGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = IVTV_REG_GPIO_DIR_OFFSET;
+ reg.val = gpio_dir;
+ if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO dir set to 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_OUT_OFFSET;
+ reg.val = gpio_out;
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO out set to 0x%04llx\n", reg.val);
+ }
+
+ if (options[OptListGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = IVTV_REG_GPIO_IN_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO in: 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_DIR_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO dir: 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_OUT_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO out: 0x%04llx\n", reg.val);
+ }
+
+ if (options[OptSetDebugLevel]) {
+ char buf[20];
+ new_debug_level = debug_level;
+
+ sprintf(buf, "%d", debug_level);
+ if (dowrite(buf, "/sys/module/ivtv/parameters/debug") == 0) {
+ printf(" set debug level: ");
+ print_debug_mask(new_debug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptGetDebugLevel]) {
+ char *buf = doread("/sys/module/ivtv/parameters/debug");
+
+ gdebug_level = 0;
+ if (buf) {
+ gdebug_level = atol(buf);
+ printf(" debug level: ");
+ print_debug_mask(gdebug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptPassThrough]) {
+ int source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
+
+ doioctl(fd, VIDEO_SELECT_SOURCE, (void *)source,
+ "IVTV_IOC_PASSTHROUGH");
+ }
+
+ if (options[OptReset])
+ doioctl(fd, VIDIOC_INT_RESET, &reset, "VIDIOC_INT_RESET");
+
+ if (options[OptSetYuvMode]) {
+ struct ivtv_dma_frame frame;
+ struct v4l2_format fmt;
+ const enum v4l2_field map[4] = {
+ V4L2_FIELD_INTERLACED_TB,
+ V4L2_FIELD_INTERLACED_BT,
+ V4L2_FIELD_NONE,
+ V4L2_FIELD_ANY,
+ };
+
+ printf("set yuv mode\n");
+ memset(&frame, 0, sizeof(frame));
+ frame.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, IVTV_IOC_DMA_FRAME, &frame) < 0) {
+ fprintf(stderr, "Unable to switch to user DMA YUV mode\n");
+ exit(1);
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ ioctl(fd, VIDIOC_G_FMT, &fmt);
+ fmt.fmt.pix.field = map[yuv_mode];
+ doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
+ }
+
+ if (options[OptGetYuvMode]) {
+ struct ivtv_dma_frame frame;
+ struct v4l2_format fmt;
+
+ memset(&frame, 0, sizeof(frame));
+ frame.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, IVTV_IOC_DMA_FRAME, &frame) < 0) {
+ fprintf(stderr, "Unable to switch to user DMA YUV mode\n");
+ exit(1);
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT");
+ printf("Current yuv_mode %d %s\n", fmt.fmt.pix.field,
+ field2s(fmt.fmt.pix.field));
+ }
+
+ close(fd);
+ exit(0);
+}