V4L/DVB (8151): saa7134-empress: fix MPEG control support
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>
This commit is contained in:
parent
e5e4cd8df6
commit
8b53b39d62
|
@ -448,6 +448,104 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
|
||||||
return 0;
|
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)
|
static int saa6752hs_init(struct i2c_client* client)
|
||||||
{
|
{
|
||||||
unsigned char buf[9], buf2[4];
|
unsigned char buf[9], buf2[4];
|
||||||
|
@ -662,6 +760,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||||
}
|
}
|
||||||
h->params = params;
|
h->params = params;
|
||||||
break;
|
break;
|
||||||
|
case VIDIOC_QUERYCTRL:
|
||||||
|
return saa6752hs_qctrl(&h->params, arg);
|
||||||
|
case VIDIOC_QUERYMENU:
|
||||||
|
return saa6752hs_qmenu(&h->params, arg);
|
||||||
case VIDIOC_G_FMT:
|
case VIDIOC_G_FMT:
|
||||||
{
|
{
|
||||||
struct v4l2_format *f = arg;
|
struct v4l2_format *f = arg;
|
||||||
|
|
|
@ -294,10 +294,20 @@ static int empress_streamoff(struct file *file, void *priv,
|
||||||
return videobuf_streamoff(&dev->empress_tsq);
|
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,
|
static int empress_s_ext_ctrls(struct file *file, void *priv,
|
||||||
struct v4l2_ext_controls *ctrls)
|
struct v4l2_ext_controls *ctrls)
|
||||||
{
|
{
|
||||||
struct saa7134_dev *dev = file->private_data;
|
struct saa7134_dev *dev = file->private_data;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* count == 0 is abused in saa6752hs.c, so that special
|
/* count == 0 is abused in saa6752hs.c, so that special
|
||||||
case is handled here explicitly. */
|
case is handled here explicitly. */
|
||||||
|
@ -307,10 +317,10 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
|
||||||
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
||||||
return -EINVAL;
|
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);
|
ts_init_encoder(dev);
|
||||||
|
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int empress_g_ext_ctrls(struct file *file, void *priv,
|
static int empress_g_ext_ctrls(struct file *file, void *priv,
|
||||||
|
@ -320,9 +330,62 @@ static int empress_g_ext_ctrls(struct file *file, void *priv,
|
||||||
|
|
||||||
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
||||||
return -EINVAL;
|
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 =
|
static const struct file_operations ts_fops =
|
||||||
|
@ -363,7 +426,8 @@ static struct video_device saa7134_empress_template =
|
||||||
.vidioc_g_input = empress_g_input,
|
.vidioc_g_input = empress_g_input,
|
||||||
.vidioc_s_input = empress_s_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_g_ctrl = saa7134_g_ctrl,
|
||||||
.vidioc_s_ctrl = saa7134_s_ctrl,
|
.vidioc_s_ctrl = saa7134_s_ctrl,
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,8 @@ static int attach_inform(struct i2c_client *client)
|
||||||
|
|
||||||
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
|
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
|
||||||
client->driver->driver.name, client->addr, client->name);
|
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? */
|
/* Am I an i2c remote control? */
|
||||||
|
|
||||||
|
|
|
@ -553,6 +553,7 @@ struct saa7134_dev {
|
||||||
struct saa7134_ts ts;
|
struct saa7134_ts ts;
|
||||||
struct saa7134_dmaqueue ts_q;
|
struct saa7134_dmaqueue ts_q;
|
||||||
struct saa7134_mpeg_ops *mops;
|
struct saa7134_mpeg_ops *mops;
|
||||||
|
struct i2c_client *mpeg_i2c_client;
|
||||||
|
|
||||||
/* SAA7134_MPEG_EMPRESS only */
|
/* SAA7134_MPEG_EMPRESS only */
|
||||||
struct video_device *empress_dev;
|
struct video_device *empress_dev;
|
||||||
|
|
Loading…
Reference in New Issue