Skip to content

Commit

Permalink
V4L/DVB (8151): saa7134-empress: fix MPEG control support
Browse files Browse the repository at this point in the history
The MPEG controls could not be enumerated and so could not be read or set
through the v4l2-ctl utility or shown in control panels.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Jul 20, 2008
1 parent e5e4cd8 commit 8b53b39
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 5 deletions.
102 changes: 102 additions & 0 deletions drivers/media/video/saa7134/saa6752hs.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,104 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
return 0;
}

static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
struct v4l2_queryctrl *qctrl)
{
int err;

switch (qctrl->id) {
case V4L2_CID_MPEG_AUDIO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2);

case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_L2_BITRATE_256K,
V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
V4L2_MPEG_AUDIO_L2_BITRATE_256K);

case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);

case V4L2_CID_MPEG_VIDEO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
V4L2_MPEG_VIDEO_ENCODING_MPEG_2);

case V4L2_CID_MPEG_VIDEO_ASPECT:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_VIDEO_ASPECT_4x3,
V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
V4L2_MPEG_VIDEO_ASPECT_4x3);

case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
err = v4l2_ctrl_query_fill_std(qctrl);
if (err == 0 &&
params->vi_bitrate_mode ==
V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return err;

case V4L2_CID_MPEG_STREAM_TYPE:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
V4L2_MPEG_STREAM_TYPE_MPEG2_TS);

case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
case V4L2_CID_MPEG_VIDEO_BITRATE:
case V4L2_CID_MPEG_STREAM_PID_PMT:
case V4L2_CID_MPEG_STREAM_PID_AUDIO:
case V4L2_CID_MPEG_STREAM_PID_VIDEO:
case V4L2_CID_MPEG_STREAM_PID_PCR:
return v4l2_ctrl_query_fill_std(qctrl);

default:
break;
}
return -EINVAL;
}

static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
struct v4l2_querymenu *qmenu)
{
static const char *mpeg_audio_l2_bitrate[] = {
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"256 kbps",
"",
"384 kbps",
NULL
};
struct v4l2_queryctrl qctrl;
int err;

qctrl.id = qmenu->id;
err = saa6752hs_qctrl(params, &qctrl);
if (err)
return err;
if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
return v4l2_ctrl_query_menu(qmenu, &qctrl,
mpeg_audio_l2_bitrate);
return v4l2_ctrl_query_menu(qmenu, &qctrl,
v4l2_ctrl_get_menu(qmenu->id));
}

static int saa6752hs_init(struct i2c_client* client)
{
unsigned char buf[9], buf2[4];
Expand Down Expand Up @@ -662,6 +760,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
h->params = params;
break;
case VIDIOC_QUERYCTRL:
return saa6752hs_qctrl(&h->params, arg);
case VIDIOC_QUERYMENU:
return saa6752hs_qmenu(&h->params, arg);
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
Expand Down
74 changes: 69 additions & 5 deletions drivers/media/video/saa7134/saa7134-empress.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,20 @@ static int empress_streamoff(struct file *file, void *priv,
return videobuf_streamoff(&dev->empress_tsq);
}

static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
unsigned int cmd, void *arg)
{
if (dev->mpeg_i2c_client == NULL)
return -EINVAL;
return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
cmd, arg);
}

static int empress_s_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctrls)
{
struct saa7134_dev *dev = file->private_data;
int err;

/* count == 0 is abused in saa6752hs.c, so that special
case is handled here explicitly. */
Expand All @@ -307,10 +317,10 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;

saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, ctrls);
err = saa7134_i2c_call_saa6752(dev, VIDIOC_S_EXT_CTRLS, ctrls);
ts_init_encoder(dev);

return 0;
return err;
}

static int empress_g_ext_ctrls(struct file *file, void *priv,
Expand All @@ -320,9 +330,62 @@ static int empress_g_ext_ctrls(struct file *file, void *priv,

if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, ctrls);
return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls);
}

return 0;
static int empress_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *c)
{
static const u32 user_ctrls[] = {
V4L2_CID_USER_CLASS,
V4L2_CID_BRIGHTNESS,
V4L2_CID_CONTRAST,
V4L2_CID_SATURATION,
V4L2_CID_HUE,
V4L2_CID_AUDIO_VOLUME,
V4L2_CID_AUDIO_MUTE,
V4L2_CID_HFLIP,
0
};

static const u32 mpeg_ctrls[] = {
V4L2_CID_MPEG_CLASS,
V4L2_CID_MPEG_STREAM_TYPE,
V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
V4L2_CID_MPEG_AUDIO_ENCODING,
V4L2_CID_MPEG_AUDIO_L2_BITRATE,
V4L2_CID_MPEG_VIDEO_ENCODING,
V4L2_CID_MPEG_VIDEO_ASPECT,
V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
V4L2_CID_MPEG_VIDEO_BITRATE,
V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
0
};
static const u32 *ctrl_classes[] = {
user_ctrls,
mpeg_ctrls,
NULL
};
struct saa7134_dev *dev = file->private_data;

c->id = v4l2_ctrl_next(ctrl_classes, c->id);
if (c->id == 0)
return -EINVAL;
if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
return v4l2_ctrl_query_fill_std(c);
if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
return saa7134_queryctrl(file, priv, c);
return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYCTRL, c);
}

static int empress_querymenu(struct file *file, void *priv,
struct v4l2_querymenu *c)
{
struct saa7134_dev *dev = file->private_data;

if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
}

static const struct file_operations ts_fops =
Expand Down Expand Up @@ -363,7 +426,8 @@ static struct video_device saa7134_empress_template =
.vidioc_g_input = empress_g_input,
.vidioc_s_input = empress_s_input,

.vidioc_queryctrl = saa7134_queryctrl,
.vidioc_queryctrl = empress_queryctrl,
.vidioc_querymenu = empress_querymenu,
.vidioc_g_ctrl = saa7134_g_ctrl,
.vidioc_s_ctrl = saa7134_s_ctrl,

Expand Down
2 changes: 2 additions & 0 deletions drivers/media/video/saa7134/saa7134-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ static int attach_inform(struct i2c_client *client)

d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
client->driver->driver.name, client->addr, client->name);
if (client->addr == 0x20 && client->driver && client->driver->command)
dev->mpeg_i2c_client = client;

/* Am I an i2c remote control? */

Expand Down
1 change: 1 addition & 0 deletions drivers/media/video/saa7134/saa7134.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ struct saa7134_dev {
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
struct saa7134_mpeg_ops *mops;
struct i2c_client *mpeg_i2c_client;

/* SAA7134_MPEG_EMPRESS only */
struct video_device *empress_dev;
Expand Down

0 comments on commit 8b53b39

Please sign in to comment.