Skip to content

Commit

Permalink
Staging: go7007: saa7134 updates
Browse files Browse the repository at this point in the history
- Added documentation including README files from the original go7007
  driver package.
- Added Video4Linux2 MPEG controls.
- Added Video4Linux2 audio ioctls, which pass thru to the i2c driver.
- Improved saa7134 interface, to pass thru controls and video settings.
- Fixed a bug in sony tuner, as reported by Bifferos on the Go7007 wiki.


Signed-off-by: Pete Eberlein <pete@sensoray.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Pete Eberlein authored and Greg Kroah-Hartman committed Jan 6, 2009
1 parent b2d6a78 commit d73f822
Show file tree
Hide file tree
Showing 7 changed files with 803 additions and 18 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/go7007/go7007-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
return 0;
if (modname != NULL)
printk(KERN_INFO
"go7007: probing for module %s failed", modname);
"go7007: probing for module %s failed\n", modname);
else
printk(KERN_INFO
"go7007: sensor %u seems to be unsupported!\n", id);
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/go7007/go7007-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ struct go7007_hpi_ops {
int (*stream_start)(struct go7007 *go);
int (*stream_stop)(struct go7007 *go);
int (*send_firmware)(struct go7007 *go, u8 *data, int len);
int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg);
};

/* The video buffer size must be a multiple of PAGE_SIZE */
Expand Down
2 changes: 1 addition & 1 deletion drivers/staging/go7007/go7007-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ static struct go7007_usb_board board_px_tv402u = {
.inputs = {
{
.video_input = 1,
.audio_input = TVAUDIO_INPUT_EXTERN,
.audio_input = TVAUDIO_INPUT_EXTERN,
.name = "Composite",
},
{
Expand Down
281 changes: 268 additions & 13 deletions drivers/staging/go7007/go7007-v4l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
#include "go7007-priv.h"
#include "wis-i2c.h"

/* Temporary defines until accepted in v4l-dvb */
#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
#define V4L2_MPEG_STREAM_TYPE_MPEG_ELEM 6 /* MPEG elementary stream */
#endif
#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4
#define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3
#endif

static void deactivate_buffer(struct go7007_buffer *gobuf)
{
int i;
Expand Down Expand Up @@ -375,6 +383,223 @@ static int clip_to_modet_map(struct go7007 *go, int region,
return 0;
}

static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
{
static const u32 user_ctrls[] = {
V4L2_CID_USER_CLASS,
0
};
static const u32 mpeg_ctrls[] = {
V4L2_CID_MPEG_CLASS,
V4L2_CID_MPEG_STREAM_TYPE,
V4L2_CID_MPEG_VIDEO_ENCODING,
V4L2_CID_MPEG_VIDEO_ASPECT,
V4L2_CID_MPEG_VIDEO_GOP_SIZE,
V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
V4L2_CID_MPEG_VIDEO_BITRATE,
0
};
static const u32 *ctrl_classes[] = {
user_ctrls,
mpeg_ctrls,
NULL
};

/* The ctrl may already contain the queried i2c controls,
* query the mpeg controls if the existing ctrl id is
* greater than the next mpeg ctrl id.
*/
id = v4l2_ctrl_next(ctrl_classes, id);
if (id >= ctrl->id && ctrl->name[0])
return 0;

memset(ctrl, 0, sizeof(*ctrl));
ctrl->id = id;

switch (ctrl->id) {
case V4L2_CID_USER_CLASS:
case V4L2_CID_MPEG_CLASS:
return v4l2_ctrl_query_fill_std(ctrl);
case V4L2_CID_MPEG_STREAM_TYPE:
return v4l2_ctrl_query_fill(ctrl,
V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
case V4L2_CID_MPEG_VIDEO_ENCODING:
return v4l2_ctrl_query_fill(ctrl,
V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
case V4L2_CID_MPEG_VIDEO_ASPECT:
return v4l2_ctrl_query_fill(ctrl,
V4L2_MPEG_VIDEO_ASPECT_1x1,
V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
V4L2_MPEG_VIDEO_ASPECT_1x1);
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
return v4l2_ctrl_query_fill_std(ctrl);
case V4L2_CID_MPEG_VIDEO_BITRATE:
return v4l2_ctrl_query_fill(ctrl,
64000,
10000000, 1,
9800000);
default:
break;
}
return -EINVAL;
}

static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
{
/* pretty sure we can't change any of these while streaming */
if (go->streaming)
return -EBUSY;

switch (ctrl->id) {
case V4L2_CID_MPEG_STREAM_TYPE:
switch (ctrl->value) {
case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
go->format = GO7007_FORMAT_MPEG2;
go->bitrate = 9800000;
go->gop_size = 15;
go->pali = 0x48;
go->closed_gop = 1;
go->repeat_seqhead = 0;
go->seq_header_enable = 1;
go->gop_header_enable = 1;
go->dvd_mode = 1;
break;
case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
/* todo: */
break;
default:
return -EINVAL;
}
break;
case V4L2_CID_MPEG_VIDEO_ENCODING:
switch (ctrl->value) {
case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
go->format = GO7007_FORMAT_MPEG1;
go->pali = 0;
break;
case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
go->format = GO7007_FORMAT_MPEG2;
/*if (mpeg->pali >> 24 == 2)
go->pali = mpeg->pali & 0xff;
else*/
go->pali = 0x48;
break;
case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
go->format = GO7007_FORMAT_MPEG4;
/*if (mpeg->pali >> 24 == 4)
go->pali = mpeg->pali & 0xff;
else*/
go->pali = 0xf5;
break;
default:
return -EINVAL;
}
go->gop_header_enable =
/*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
? 0 :*/ 1;
/*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
go->repeat_seqhead = 1;
else*/
go->repeat_seqhead = 0;
go->dvd_mode = 0;
break;
case V4L2_CID_MPEG_VIDEO_ASPECT:
if (go->format == GO7007_FORMAT_MJPEG)
return -EINVAL;
switch (ctrl->value) {
case V4L2_MPEG_VIDEO_ASPECT_1x1:
go->aspect_ratio = GO7007_RATIO_1_1;
break;
case V4L2_MPEG_VIDEO_ASPECT_4x3:
go->aspect_ratio = GO7007_RATIO_4_3;
break;
case V4L2_MPEG_VIDEO_ASPECT_16x9:
go->aspect_ratio = GO7007_RATIO_16_9;
break;
case V4L2_MPEG_VIDEO_ASPECT_221x100:
default:
return -EINVAL;
}
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
go->gop_size = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
if (ctrl->value != 0 && ctrl->value != 1)
return -EINVAL;
go->closed_gop = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
/* Upper bound is kind of arbitrary here */
if (ctrl->value < 64000 || ctrl->value > 10000000)
return -EINVAL;
go->bitrate = ctrl->value;
break;
default:
return -EINVAL;
}
return 0;
}

static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go)
{
switch (ctrl->id) {
case V4L2_CID_MPEG_STREAM_TYPE:
if (go->dvd_mode)
ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
else
ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM;
break;
case V4L2_CID_MPEG_VIDEO_ENCODING:
switch (go->format) {
case GO7007_FORMAT_MPEG1:
ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
break;
case GO7007_FORMAT_MPEG2:
ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
break;
case GO7007_FORMAT_MPEG4:
ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
break;
default:
return -EINVAL;
}
break;
case V4L2_CID_MPEG_VIDEO_ASPECT:
switch (go->aspect_ratio) {
case GO7007_RATIO_1_1:
ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1;
break;
case GO7007_RATIO_4_3:
ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3;
break;
case GO7007_RATIO_16_9:
ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9;
break;
default:
return -EINVAL;
}
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
ctrl->value = go->gop_size;
break;
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
ctrl->value = go->closed_gop;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
ctrl->value = go->bitrate;
break;
default:
return -EINVAL;
}
return 0;
}

static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct go7007_file *gofh = file->private_data;
Expand All @@ -392,7 +617,7 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
strncpy(cap->card, go->name, sizeof(cap->card));
cap->version = KERNEL_VERSION(0, 9, 8);
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
V4L2_CAP_STREAMING | V4L2_CAP_AUDIO;
if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
Expand Down Expand Up @@ -464,6 +689,19 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return -EBUSY;
return set_capture_size(go, fmt, 0);
}
case VIDIOC_ENUMAUDIO:
case VIDIOC_G_AUDIO:
case VIDIOC_S_AUDIO:
{
struct v4l2_audio *audio = arg;

if (!go->i2c_adapter_online)
return -EIO;
i2c_clients_command(&go->i2c_adapter, cmd, arg);
if (cmd == VIDIOC_ENUMAUDIO && !audio->name[0])
return -EINVAL;
return 0;
}
case VIDIOC_G_FBUF:
case VIDIOC_S_FBUF:
return -EINVAL;
Expand Down Expand Up @@ -699,26 +937,33 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_queryctrl *ctrl = arg;
u32 id;

if (!go->i2c_adapter_online)
return -EIO;
id = ctrl->id;
memset(ctrl, 0, sizeof(*ctrl));
ctrl->id = id;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, arg);
if (go->i2c_adapter_online)
i2c_clients_command(&go->i2c_adapter,
VIDIOC_QUERYCTRL, arg);
else if (go->hpi_ops && go->hpi_ops->send_command)
go->hpi_ops->send_command(go, cmd, arg);
if (id & V4L2_CTRL_FLAG_NEXT_CTRL || ctrl->name[0] == 0)
return mpeg_queryctrl(id, ctrl);
return ctrl->name[0] == 0 ? -EINVAL : 0;
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
struct v4l2_queryctrl query;

if (!go->i2c_adapter_online)
return -EIO;
memset(&query, 0, sizeof(query));
query.id = ctrl->id;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
if (go->i2c_adapter_online)
i2c_clients_command(&go->i2c_adapter,
VIDIOC_QUERYCTRL, &query);
else if (go->hpi_ops && go->hpi_ops->send_command)
if (0 == go->hpi_ops->send_command(go, cmd, arg))
return 0;
if (query.name[0] == 0)
return -EINVAL;
return mpeg_g_control(ctrl, go);
i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, arg);
return 0;
}
Expand All @@ -727,13 +972,16 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_control *ctrl = arg;
struct v4l2_queryctrl query;

if (!go->i2c_adapter_online)
return -EIO;
memset(&query, 0, sizeof(query));
query.id = ctrl->id;
i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
if (go->i2c_adapter_online)
i2c_clients_command(&go->i2c_adapter,
VIDIOC_QUERYCTRL, &query);
else if (go->hpi_ops && go->hpi_ops->send_command)
if (0 == go->hpi_ops->send_command(go, cmd, arg))
return 0;
if (query.name[0] == 0)
return -EINVAL;
return mpeg_s_control(ctrl, go);
i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, arg);
return 0;
}
Expand Down Expand Up @@ -826,6 +1074,8 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
*std = V4L2_STD_NTSC;
else
*std = V4L2_STD_PAL | V4L2_STD_SECAM;
} else if (go->hpi_ops && go->hpi_ops->send_command) {
go->hpi_ops->send_command(go, cmd, arg);
} else
*std = 0;
return 0;
Expand Down Expand Up @@ -864,6 +1114,9 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
if (go->i2c_adapter_online)
i2c_clients_command(&go->i2c_adapter,
VIDIOC_S_STD, std);
if (go->hpi_ops && go->hpi_ops->send_command)
go->hpi_ops->send_command(go, cmd, arg);

set_capture_size(go, NULL, 0);
return 0;
}
Expand Down Expand Up @@ -1316,7 +1569,7 @@ static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return clip_to_modet_map(go, region->region, region->clips);
}
default:
printk(KERN_DEBUG "go7007: unsupported ioctl %d\n", cmd);
printk(KERN_INFO "go7007-v4l2: unsupported ioctl %d\n", cmd);
return -ENOIOCTLCMD;
}
return 0;
Expand Down Expand Up @@ -1474,6 +1727,8 @@ int go7007_v4l2_init(struct go7007 *go)
}
video_set_drvdata(go->video_dev, go);
++go->ref_count;
printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
go->video_dev->name, go->video_dev->num);

return 0;
}
Expand Down
Loading

0 comments on commit d73f822

Please sign in to comment.