Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b53b39d authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent e5e4cd8d
Loading
Loading
Loading
Loading
+102 −0
Original line number Diff line number Diff line
@@ -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];
@@ -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;
+69 −5
Original line number Diff line number Diff line
@@ -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. */
@@ -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,
@@ -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 =
@@ -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,

+2 −0
Original line number Diff line number Diff line
@@ -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? */

+1 −0
Original line number Diff line number Diff line
@@ -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;