Commit 60bdc2ff authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

media: i2c: adv7604: export InfoFrames to debugfs



Export InfoFrames to debugfs.

Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Tested-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent c6a38df9
Loading
Loading
Loading
Loading
+70 −20
Original line number Diff line number Diff line
@@ -193,6 +193,9 @@ struct adv76xx_state {
	struct delayed_work delayed_work_enable_hotplug;
	bool restart_stdi_once;

	struct dentry *debugfs_dir;
	struct v4l2_debugfs_if *infoframes;

	/* CEC */
	struct cec_adapter *cec_adap;
	u8   cec_addr[ADV76XX_MAX_ADDRS];
@@ -2458,10 +2461,9 @@ static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
	{ "Vendor", 0x10, 0xec, 0x54 }
};

static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
				  union hdmi_infoframe *frame)
static int adv76xx_read_infoframe_buf(struct v4l2_subdev *sd, int index,
				      u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
{
	uint8_t buffer[32];
	u8 len;
	int i;

@@ -2472,27 +2474,20 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
	}

	for (i = 0; i < 3; i++)
		buffer[i] = infoframe_read(sd,
					   adv76xx_cri[index].head_addr + i);
		buf[i] = infoframe_read(sd, adv76xx_cri[index].head_addr + i);

	len = buffer[2] + 1;
	len = buf[2] + 1;

	if (len + 3 > sizeof(buffer)) {
	if (len + 3 > V4L2_DEBUGFS_IF_MAX_LEN) {
		v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__,
			 adv76xx_cri[index].desc, len);
		return -ENOENT;
	}

	for (i = 0; i < len; i++)
		buffer[i + 3] = infoframe_read(sd,
		buf[i + 3] = infoframe_read(sd,
					    adv76xx_cri[index].payload_addr + i);

	if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
			 adv76xx_cri[index].desc);
		return -ENOENT;
	}
	return 0;
	return len + 3;
}

static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
@@ -2505,10 +2500,19 @@ static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
	}

	for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) {
		union hdmi_infoframe frame;
		struct i2c_client *client = v4l2_get_subdevdata(sd);
		u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
		union hdmi_infoframe frame;
		int len;

		if (!adv76xx_read_infoframe(sd, i, &frame))
		len = adv76xx_read_infoframe_buf(sd, i, buffer);
		if (len < 0)
			continue;

		if (hdmi_infoframe_unpack(&frame, buffer, len) < 0)
			v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
				 __func__, adv76xx_cri[i].desc);
		else
			hdmi_infoframe_log(KERN_INFO, &client->dev, &frame);
	}
}
@@ -2686,6 +2690,41 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd,
	}
}

static ssize_t
adv76xx_debugfs_if_read(u32 type, void *priv, struct file *filp,
			char __user *ubuf, size_t count, loff_t *ppos)
{
	u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
	struct v4l2_subdev *sd = priv;
	int index;
	int len;

	if (!is_hdmi(sd))
		return 0;

	switch (type) {
	case V4L2_DEBUGFS_IF_AVI:
		index = 0;
		break;
	case V4L2_DEBUGFS_IF_AUDIO:
		index = 1;
		break;
	case V4L2_DEBUGFS_IF_SPD:
		index = 2;
		break;
	case V4L2_DEBUGFS_IF_HDMI:
		index = 3;
		break;
	default:
		return 0;
	}

	len = adv76xx_read_infoframe_buf(sd, index, buf);
	if (len > 0)
		len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
	return len < 0 ? 0 : len;
}

static int adv76xx_registered(struct v4l2_subdev *sd)
{
	struct adv76xx_state *state = to_state(sd);
@@ -2693,16 +2732,27 @@ static int adv76xx_registered(struct v4l2_subdev *sd)
	int err;

	err = cec_register_adapter(state->cec_adap, &client->dev);
	if (err)
	if (err) {
		cec_delete_adapter(state->cec_adap);
		return err;
	}
	state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
	state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
		V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
		V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI, sd,
		adv76xx_debugfs_if_read);
	return 0;
}

static void adv76xx_unregistered(struct v4l2_subdev *sd)
{
	struct adv76xx_state *state = to_state(sd);

	cec_unregister_adapter(state->cec_adap);
	v4l2_debugfs_if_free(state->infoframes);
	state->infoframes = NULL;
	debugfs_remove_recursive(state->debugfs_dir);
	state->debugfs_dir = NULL;
}

/* ----------------------------------------------------------------------- */