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

media: adv7842: support EDIDs up to 4 blocks



The adv7842 driver didn't support EDIDs of 3 or 4 blocks, even though the
hardware supports this.

It is a bit more complicated due to the fact that the adv7842 can expose
two EDIDs: one digital, one analog, for DVI-I connectors. In that case the
VGA_EDID_ENABLE bit is set and blocks 0 and 1 of the EDID eeprom are used
for the DVI-D part and block 2 is used for the DVI-A part of the DVI-I
connector.

Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent d84b9202
Loading
Loading
Loading
Loading
+27 −10
Original line number Diff line number Diff line
@@ -98,12 +98,12 @@ struct adv7842_state {

	v4l2_std_id norm;
	struct {
		u8 edid[256];
		u8 edid[512];
		u32 blocks;
		u32 present;
	} hdmi_edid;
	struct {
		u8 edid[256];
		u8 edid[128];
		u32 blocks;
		u32 present;
	} vga_edid;
@@ -720,6 +720,9 @@ static int edid_write_vga_segment(struct v4l2_subdev *sd)

	v4l2_dbg(2, debug, sd, "%s: write EDID on VGA port\n", __func__);

	if (!state->vga_edid.present)
		return 0;

	/* HPA disable on port A and B */
	io_write_and_or(sd, 0x20, 0xcf, 0x00);

@@ -763,7 +766,7 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)
	struct adv7842_state *state = to_state(sd);
	const u8 *edid = state->hdmi_edid.edid;
	u32 blocks = state->hdmi_edid.blocks;
	int spa_loc;
	unsigned int spa_loc;
	u16 pa, parent_pa;
	int err = 0;
	int i;
@@ -796,12 +799,14 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)
		pa = (edid[spa_loc] << 8) | edid[spa_loc + 1];
	}

	/* edid segment pointer '0' for HDMI ports */
	rep_write_and_or(sd, 0x77, 0xef, 0x00);

	for (i = 0; !err && i < blocks * 128; i += I2C_SMBUS_BLOCK_MAX)
	for (i = 0; !err && i < blocks * 128; i += I2C_SMBUS_BLOCK_MAX) {
		/* set edid segment pointer for HDMI ports */
		if (i % 256 == 0)
			rep_write_and_or(sd, 0x77, 0xef, i >= 256 ? 0x10 : 0x00);
		err = i2c_smbus_write_i2c_block_data(state->i2c_edid, i,
						     I2C_SMBUS_BLOCK_MAX, edid + i);
	}
	if (err)
		return err;

@@ -2491,9 +2496,17 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
	return 0;
}

/*
 * If the VGA_EDID_ENABLE bit is set (Repeater Map 0x7f, bit 7), then
 * the first two blocks of the EDID are for the HDMI, and the first block
 * of segment 1 (i.e. the third block of the EDID) is for VGA.
 * So if a VGA EDID is installed, then the maximum size of the HDMI EDID
 * is 2 blocks.
 */
static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
{
	struct adv7842_state *state = to_state(sd);
	unsigned int max_blocks = e->pad == ADV7842_EDID_PORT_VGA ? 1 : 4;
	int err = 0;

	memset(e->reserved, 0, sizeof(e->reserved));
@@ -2502,8 +2515,12 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
		return -EINVAL;
	if (e->start_block != 0)
		return -EINVAL;
	if (e->blocks > 2) {
		e->blocks = 2;
	if (e->pad < ADV7842_EDID_PORT_VGA && state->vga_edid.blocks)
		max_blocks = 2;
	if (e->pad == ADV7842_EDID_PORT_VGA && state->hdmi_edid.blocks > 2)
		return -EBUSY;
	if (e->blocks > max_blocks) {
		e->blocks = max_blocks;
		return -E2BIG;
	}

@@ -2514,7 +2531,7 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)

	switch (e->pad) {
	case ADV7842_EDID_PORT_VGA:
		memset(&state->vga_edid.edid, 0, 256);
		memset(&state->vga_edid.edid, 0, sizeof(state->vga_edid.edid));
		state->vga_edid.blocks = e->blocks;
		state->vga_edid.present = e->blocks ? 0x1 : 0x0;
		if (e->blocks)
@@ -2523,7 +2540,7 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
		break;
	case ADV7842_EDID_PORT_A:
	case ADV7842_EDID_PORT_B:
		memset(&state->hdmi_edid.edid, 0, 256);
		memset(&state->hdmi_edid.edid, 0, sizeof(state->hdmi_edid.edid));
		state->hdmi_edid.blocks = e->blocks;
		if (e->blocks) {
			state->hdmi_edid.present |= 0x04 << e->pad;