* [RFC PATCH 00/15] adv7604: fixes
@ 2013-12-10 13:23 Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
0 siblings, 1 reply; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media
This patch series updates the adv7604 driver with the latest fixes
from our internal tree.
Regards,
Hans
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC PATCH 01/15] adv7604: add support for all the digital input ports
2013-12-10 13:23 [RFC PATCH 00/15] adv7604: fixes Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 02/15] adv7604: add hdmi driver strength adjustment Hans Verkuil
` (13 more replies)
0 siblings, 14 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
The adv7604 supports four digital input ports. This patch adds support
for all of them, instead of just port A.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 266 ++++++++++++++++++++++++++------------------
include/media/adv7604.h | 20 ++--
2 files changed, 168 insertions(+), 118 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index a324106b..6372d31 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,8 +53,6 @@ MODULE_LICENSE("GPL");
/* ADV7604 system clock frequency */
#define ADV7604_fsc (28636360)
-#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
-
/*
**********************************************************************
*
@@ -67,10 +65,13 @@ struct adv7604_state {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler hdl;
- enum adv7604_mode mode;
+ enum adv7604_input_port selected_input;
struct v4l2_dv_timings timings;
- u8 edid[256];
- unsigned edid_blocks;
+ struct {
+ u8 edid[256];
+ u32 present;
+ unsigned blocks;
+ } edid;
struct v4l2_fract aspect_ratio;
u32 rgb_quantization_range;
struct workqueue_struct *work_queues;
@@ -516,7 +517,7 @@ static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)1);
+ v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
}
static inline int edid_write_block(struct v4l2_subdev *sd,
@@ -529,8 +530,6 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
-
/* Disables I2C access to internal EDID ram from DDC port */
rep_write_and_or(sd, 0x77, 0xf0, 0x0);
@@ -541,22 +540,19 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
return err;
/* adv7604 calculates the checksums and enables I2C access to internal
- EDID ram from DDC port. */
- rep_write_and_or(sd, 0x77, 0xf0, 0x1);
+ EDID RAM from DDC port. */
+ rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
for (i = 0; i < 1000; i++) {
- if (rep_read(sd, 0x7d) & 1)
+ if (rep_read(sd, 0x7d) & state->edid.present)
break;
mdelay(1);
}
if (i == 1000) {
- v4l_err(client, "error enabling edid\n");
+ v4l_err(client, "error enabling edid (0x%x)\n", state->edid.present);
return -EIO;
}
- /* enable hotplug after 100 ms */
- queue_delayed_work(state->work_queues,
- &state->delayed_work_enable_hotplug, HZ / 10);
return 0;
}
@@ -574,6 +570,11 @@ static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val);
}
+static inline int hdmi_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+ return hdmi_write(sd, reg, (hdmi_read(sd, reg) & mask) | val);
+}
+
static inline int test_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
@@ -623,6 +624,26 @@ static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
/* ----------------------------------------------------------------------- */
+static inline bool is_analog_input(struct v4l2_subdev *sd)
+{
+ struct adv7604_state *state = to_state(sd);
+
+ return state->selected_input == ADV7604_INPUT_VGA_RGB ||
+ state->selected_input == ADV7604_INPUT_VGA_COMP;
+}
+
+static inline bool is_digital_input(struct v4l2_subdev *sd)
+{
+ struct adv7604_state *state = to_state(sd);
+
+ return state->selected_input == ADV7604_INPUT_HDMI_PORT_A ||
+ state->selected_input == ADV7604_INPUT_HDMI_PORT_B ||
+ state->selected_input == ADV7604_INPUT_HDMI_PORT_C ||
+ state->selected_input == ADV7604_INPUT_HDMI_PORT_D;
+}
+
+/* ----------------------------------------------------------------------- */
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
static void adv7604_inv_register(struct v4l2_subdev *sd)
{
@@ -748,10 +769,13 @@ static int adv7604_s_register(struct v4l2_subdev *sd,
static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ u8 reg_io_6f = io_read(sd, 0x6f);
- /* port A only */
return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
- ((io_read(sd, 0x6f) & 0x10) >> 4));
+ ((reg_io_6f & 0x10) >> 4) |
+ ((reg_io_6f & 0x08) >> 2) |
+ (reg_io_6f & 0x04) |
+ ((reg_io_6f & 0x02) << 2));
}
static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
@@ -759,12 +783,11 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
const struct adv7604_video_standards *predef_vid_timings,
const struct v4l2_dv_timings *timings)
{
- struct adv7604_state *state = to_state(sd);
int i;
for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings,
- DIGITAL_INPUT ? 250000 : 1000000))
+ is_digital_input(sd) ? 250000 : 1000000))
continue;
io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
@@ -799,27 +822,22 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
cp_write(sd, 0xab, 0x00);
cp_write(sd, 0xac, 0x00);
- switch (state->mode) {
- case ADV7604_MODE_COMP:
- case ADV7604_MODE_GR:
+ if (is_analog_input(sd)) {
err = find_and_set_predefined_video_timings(sd,
0x01, adv7604_prim_mode_comp, timings);
if (err)
err = find_and_set_predefined_video_timings(sd,
0x02, adv7604_prim_mode_gr, timings);
- break;
- case ADV7604_MODE_HDMI:
+ } else if (is_digital_input(sd)) {
err = find_and_set_predefined_video_timings(sd,
0x05, adv7604_prim_mode_hdmi_comp, timings);
if (err)
err = find_and_set_predefined_video_timings(sd,
0x06, adv7604_prim_mode_hdmi_gr, timings);
- break;
- default:
- v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
- __func__, state->mode);
+ } else {
+ v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
+ __func__, state->selected_input);
err = -1;
- break;
}
@@ -846,9 +864,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s\n", __func__);
- switch (state->mode) {
- case ADV7604_MODE_COMP:
- case ADV7604_MODE_GR:
+ if (is_analog_input(sd)) {
/* auto graphics */
io_write(sd, 0x00, 0x07); /* video std */
io_write(sd, 0x01, 0x02); /* prim mode */
@@ -858,33 +874,28 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
/* IO-map reg. 0x16 and 0x17 should be written in sequence */
- if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
+ if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll))
v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
- break;
- }
/* active video - horizontal timing */
cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
- ((cp_start_eav >> 8) & 0x0f));
+ ((cp_start_eav >> 8) & 0x0f));
cp_write(sd, 0xa4, cp_start_eav & 0xff);
/* active video - vertical timing */
cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
- ((cp_end_vbi >> 8) & 0xf));
+ ((cp_end_vbi >> 8) & 0xf));
cp_write(sd, 0xa7, cp_end_vbi & 0xff);
- break;
- case ADV7604_MODE_HDMI:
+ } else if (is_digital_input(sd)) {
/* set default prim_mode/vid_std for HDMI
according to [REF_03, c. 4.2] */
io_write(sd, 0x00, 0x02); /* video std */
io_write(sd, 0x01, 0x06); /* prim mode */
- break;
- default:
- v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
- __func__, state->mode);
- break;
+ } else {
+ v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
+ __func__, state->selected_input);
}
cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
@@ -900,7 +911,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
/* automatic */
- if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
+ if (is_digital_input(sd) && !(hdmi_read(sd, 0x05) & 0x80)) {
/* receiving DVI-D signal */
/* ADV7604 selects RGB limited range regardless of
@@ -983,8 +994,9 @@ static inline bool no_power(struct v4l2_subdev *sd)
static inline bool no_signal_tmds(struct v4l2_subdev *sd)
{
- /* TODO port B, C and D */
- return !(io_read(sd, 0x6a) & 0x10);
+ struct adv7604_state *state = to_state(sd);
+
+ return !(io_read(sd, 0x6a) & (0x10 >> state->selected_input));
}
static inline bool no_lock_tmds(struct v4l2_subdev *sd)
@@ -1011,7 +1023,6 @@ static inline bool no_lock_stdi(struct v4l2_subdev *sd)
static inline bool no_signal(struct v4l2_subdev *sd)
{
- struct adv7604_state *state = to_state(sd);
bool ret;
ret = no_power(sd);
@@ -1019,7 +1030,7 @@ static inline bool no_signal(struct v4l2_subdev *sd)
ret |= no_lock_stdi(sd);
ret |= no_lock_sspd(sd);
- if (DIGITAL_INPUT) {
+ if (is_digital_input(sd)) {
ret |= no_lock_tmds(sd);
ret |= no_signal_tmds(sd);
}
@@ -1036,13 +1047,11 @@ static inline bool no_lock_cp(struct v4l2_subdev *sd)
static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
- struct adv7604_state *state = to_state(sd);
-
*status = 0;
*status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0;
*status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
if (no_lock_cp(sd))
- *status |= DIGITAL_INPUT ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
+ *status |= is_digital_input(sd) ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
@@ -1157,13 +1166,11 @@ static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
struct v4l2_dv_timings_cap *cap)
{
- struct adv7604_state *state = to_state(sd);
-
cap->type = V4L2_DV_BT_656_1120;
cap->bt.max_width = 1920;
cap->bt.max_height = 1200;
cap->bt.min_pixelclock = 25000000;
- if (DIGITAL_INPUT)
+ if (is_digital_input(sd))
cap->bt.max_pixelclock = 225000000;
else
cap->bt.max_pixelclock = 170000000;
@@ -1179,12 +1186,11 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
- struct adv7604_state *state = to_state(sd);
int i;
for (i = 0; adv7604_timings[i].bt.width; i++) {
if (v4l2_match_dv_timings(timings, &adv7604_timings[i],
- DIGITAL_INPUT ? 250000 : 1000000)) {
+ is_digital_input(sd) ? 250000 : 1000000)) {
*timings = adv7604_timings[i];
break;
}
@@ -1216,7 +1222,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
bt->interlaced = stdi.interlaced ?
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
- if (DIGITAL_INPUT) {
+ if (is_digital_input(sd)) {
uint32_t freq;
timings->type = V4L2_DV_BT_656_1120;
@@ -1305,8 +1311,8 @@ found:
return -ENOLINK;
}
- if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
- (DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+ if ((is_analog_input(sd) && bt->pixelclock > 170000000) ||
+ (is_digital_input(sd) && bt->pixelclock > 225000000)) {
v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
__func__, (u32)bt->pixelclock);
return -ERANGE;
@@ -1331,8 +1337,8 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
bt = &timings->bt;
- if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
- (DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+ if ((is_analog_input(sd) && bt->pixelclock > 170000000) ||
+ (is_digital_input(sd) && bt->pixelclock > 225000000)) {
v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
__func__, (u32)bt->pixelclock);
return -ERANGE;
@@ -1374,22 +1380,18 @@ static void enable_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
- switch (state->mode) {
- case ADV7604_MODE_COMP:
- case ADV7604_MODE_GR:
+ if (is_analog_input(sd)) {
/* enable */
io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
- break;
- case ADV7604_MODE_HDMI:
+ } else if (is_digital_input(sd)) {
/* enable */
+ hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
- break;
- default:
- v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
- __func__, state->mode);
- break;
+ } else {
+ v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
+ __func__, state->selected_input);
}
}
@@ -1405,9 +1407,7 @@ static void select_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
- switch (state->mode) {
- case ADV7604_MODE_COMP:
- case ADV7604_MODE_GR:
+ if (is_analog_input(sd)) {
/* reset ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
@@ -1433,9 +1433,9 @@ static void select_input(struct v4l2_subdev *sd)
cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */
cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
- break;
+ } else if (is_digital_input(sd)) {
+ hdmi_write(sd, 0x00, state->selected_input & 0x03);
- case ADV7604_MODE_HDMI:
/* set ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
@@ -1461,12 +1461,9 @@ static void select_input(struct v4l2_subdev *sd)
cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
-
- break;
- default:
- v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
- __func__, state->mode);
- break;
+ } else {
+ v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
+ __func__, state->selected_input);
}
}
@@ -1477,7 +1474,7 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
- state->mode = input;
+ state->selected_input = input;
disable_input(sd);
@@ -1524,7 +1521,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
fmt_change = io_read(sd, 0x43) & 0x98;
if (fmt_change)
io_write(sd, 0x44, fmt_change);
- fmt_change_digital = DIGITAL_INPUT ? (io_read(sd, 0x6b) & 0xc0) : 0;
+ fmt_change_digital = is_digital_input(sd) ? (io_read(sd, 0x6b) & 0xc0) : 0;
if (fmt_change_digital)
io_write(sd, 0x6c, fmt_change_digital);
if (fmt_change || fmt_change_digital) {
@@ -1545,7 +1542,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
*handled = true;
}
/* tx 5v detect */
- tx_5v = io_read(sd, 0x70) & 0x10;
+ tx_5v = io_read(sd, 0x70) & 0x1e;
if (tx_5v) {
v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
io_write(sd, 0x71, tx_5v);
@@ -1559,19 +1556,41 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
{
struct adv7604_state *state = to_state(sd);
+ u8 *data = NULL;
- if (edid->pad != 0)
+ if (edid->pad > ADV7604_EDID_PORT_D)
return -EINVAL;
if (edid->blocks == 0)
return -EINVAL;
- if (edid->start_block >= state->edid_blocks)
+ if (edid->blocks > 2)
return -EINVAL;
- if (edid->start_block + edid->blocks > state->edid_blocks)
- edid->blocks = state->edid_blocks - edid->start_block;
+ if (edid->start_block > 1)
+ return -EINVAL;
+ if (edid->start_block == 1)
+ edid->blocks = 1;
if (!edid->edid)
return -EINVAL;
- memcpy(edid->edid + edid->start_block * 128,
- state->edid + edid->start_block * 128,
+
+ if (edid->blocks > state->edid.blocks)
+ edid->blocks = state->edid.blocks;
+
+ switch (edid->pad) {
+ case ADV7604_EDID_PORT_A:
+ case ADV7604_EDID_PORT_B:
+ case ADV7604_EDID_PORT_C:
+ case ADV7604_EDID_PORT_D:
+ if (state->edid.present & (1 << edid->pad))
+ data = state->edid.edid;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ if (!data)
+ return -ENODATA;
+
+ memcpy(edid->edid,
+ data + edid->start_block * 128,
edid->blocks * 128);
return 0;
}
@@ -1581,33 +1600,50 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
struct adv7604_state *state = to_state(sd);
int err;
- if (edid->pad != 0)
+ if (edid->pad > ADV7604_EDID_PORT_D)
return -EINVAL;
if (edid->start_block != 0)
return -EINVAL;
if (edid->blocks == 0) {
/* Pull down the hotplug pin */
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
+ state->edid.present &= ~(1 << edid->pad);
+ v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
/* Disables I2C access to internal EDID ram from DDC port */
rep_write_and_or(sd, 0x77, 0xf0, 0x0);
- state->edid_blocks = 0;
+ state->edid.blocks = 0;
/* Fall back to a 16:9 aspect ratio */
state->aspect_ratio.numerator = 16;
state->aspect_ratio.denominator = 9;
+ v4l2_dbg(2, debug, sd, "%s: clear edid\n", __func__);
return 0;
}
- if (edid->blocks > 2)
+ if (edid->blocks > 2) {
+ edid->blocks = 2;
return -E2BIG;
+ }
if (!edid->edid)
return -EINVAL;
- memcpy(state->edid, edid->edid, 128 * edid->blocks);
- state->edid_blocks = edid->blocks;
+
+ cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
+ state->edid.present &= ~(1 << edid->pad);
+ v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
+
+ memcpy(state->edid.edid, edid->edid, 128 * edid->blocks);
+ state->edid.blocks = edid->blocks;
state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15],
edid->edid[0x16]);
- err = edid_write_block(sd, 128 * edid->blocks, state->edid);
- if (err < 0)
+ state->edid.present |= edid->pad;
+
+ err = edid_write_block(sd, 128 * edid->blocks, state->edid.edid);
+ if (err < 0) {
v4l2_err(sd, "error %d writing edid\n", err);
- return err;
+ return err;
+ }
+
+ /* enable hotplug after 100 ms */
+ queue_delayed_work(state->work_queues,
+ &state->delayed_work_enable_hotplug, HZ / 10);
+ return 0;
}
/*********** avi info frame CEA-861-E **************/
@@ -1690,15 +1726,21 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "-----Chip status-----\n");
v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ?
- "HDMI" : (DIGITAL_INPUT ? "DVI-D" : "DVI-A"));
- v4l2_info(sd, "EDID: %s\n", ((rep_read(sd, 0x7d) & 0x01) &&
- (rep_read(sd, 0x77) & 0x01)) ? "enabled" : "disabled ");
+ "HDMI" : (is_digital_input(sd) ? "DVI-D" : "DVI-A"));
+ v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
+ ((rep_read(sd, 0x7d) & 0x01) ? "Yes" : "No"),
+ ((rep_read(sd, 0x7d) & 0x02) ? "Yes" : "No"),
+ ((rep_read(sd, 0x7d) & 0x04) ? "Yes" : "No"),
+ ((rep_read(sd, 0x7d) & 0x08) ? "Yes" : "No"));
v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?
"enabled" : "disabled");
v4l2_info(sd, "-----Signal status-----\n");
- v4l2_info(sd, "Cable detected (+5V power): %s\n",
- (io_read(sd, 0x6f) & 0x10) ? "true" : "false");
+ v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n",
+ ((io_read(sd, 0x6f) & 0x10) ? "Yes" : "No"),
+ ((io_read(sd, 0x6f) & 0x08) ? "Yes" : "No"),
+ ((io_read(sd, 0x6f) & 0x04) ? "Yes" : "No"),
+ ((io_read(sd, 0x6f) & 0x02) ? "Yes" : "No"));
v4l2_info(sd, "TMDS signal detected: %s\n",
no_signal_tmds(sd) ? "false" : "true");
v4l2_info(sd, "TMDS signal locked: %s\n",
@@ -1744,11 +1786,14 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "Color space conversion: %s\n",
csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]);
- if (!DIGITAL_INPUT)
+ if (!is_digital_input(sd))
return 0;
v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D");
- v4l2_info(sd, "HDCP encrypted content: %s\n", (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false");
+ v4l2_info(sd, "Digital video port selected: %c\n",
+ (hdmi_read(sd, 0x00) & 0x03) + 'A');
+ v4l2_info(sd, "HDCP encrypted content: %s\n",
+ (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false");
v4l2_info(sd, "HDCP keys read: %s%s\n",
(hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no",
(hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : "");
@@ -1906,6 +1951,7 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
for digital formats */
+ rep_write(sd, 0x76, 0xc0); /* SPA location for port B, C and D */
/* TODO from platform data */
afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */
@@ -1918,7 +1964,7 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
io_write(sd, 0x6e, 0xc0); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
- io_write(sd, 0x73, 0x10); /* Enable CABLE_DET_A_ST (+5v) interrupt */
+ io_write(sd, 0x73, 0x1e); /* Enable CABLE_DET_A_ST (+5v) interrupts */
return v4l2_ctrl_handler_setup(sd->ctrl_handler);
}
@@ -2020,7 +2066,7 @@ static int adv7604_probe(struct i2c_client *client,
/* private controls */
state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
- V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
+ V4L2_CID_DV_RX_POWER_PRESENT, 0, 0x0f, 0, 0);
state->rgb_quantization_range_ctrl =
v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index dc004bc..0c96e16 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -131,16 +131,20 @@ struct adv7604_platform_data {
u8 i2c_vdp;
};
-/*
- * Mode of operation.
- * This is used as the input argument of the s_routing video op.
- */
-enum adv7604_mode {
- ADV7604_MODE_COMP,
- ADV7604_MODE_GR,
- ADV7604_MODE_HDMI,
+enum adv7604_input_port {
+ ADV7604_INPUT_HDMI_PORT_A,
+ ADV7604_INPUT_HDMI_PORT_B,
+ ADV7604_INPUT_HDMI_PORT_C,
+ ADV7604_INPUT_HDMI_PORT_D,
+ ADV7604_INPUT_VGA_RGB,
+ ADV7604_INPUT_VGA_COMP,
};
+#define ADV7604_EDID_PORT_A 0
+#define ADV7604_EDID_PORT_B 1
+#define ADV7604_EDID_PORT_C 2
+#define ADV7604_EDID_PORT_D 3
+
#define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002)
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 02/15] adv7604: add hdmi driver strength adjustment
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 03/15] adv7604: support 1366x768 DMT Reduced Blanking Hans Verkuil
` (12 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mikhail Khelik, Hans Verkuil
From: Mikhail Khelik <mkhelik@cisco.com>
The driver strength is board dependent, so set it from the platform_data.
Signed-off-by: Mikhail Khelik <mkhelik@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 7 ++++++-
include/media/adv7604.h | 5 +++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 6372d31..99734b2 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1942,7 +1942,12 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
/* TODO from platform data */
cp_write(sd, 0x69, 0x30); /* Enable CP CSC */
io_write(sd, 0x06, 0xa6); /* positive VS and HS */
- io_write(sd, 0x14, 0x7f); /* Drive strength adjusted to max */
+
+ /* Adjust drive strength */
+ io_write(sd, 0x14, 0x40 | pdata->dr_str << 4 |
+ pdata->dr_str_clk << 2 |
+ pdata->dr_str_sync);
+
cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold -
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 0c96e16..0e13d1b 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -110,6 +110,11 @@ struct adv7604_platform_data {
unsigned replicate_av_codes:1;
unsigned invert_cbcr:1;
+ /* IO register 0x14 */
+ unsigned dr_str:2;
+ unsigned dr_str_clk:2;
+ unsigned dr_str_sync:2;
+
/* IO register 0x30 */
unsigned output_bus_lsb_to_msb:1;
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 03/15] adv7604: support 1366x768 DMT Reduced Blanking
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 02/15] adv7604: add hdmi driver strength adjustment Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 04/15] adv7604: adv7604_s_register clean up Hans Verkuil
` (11 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Martin Bugge, Hans Verkuil
From: Martin Bugge <marbugge@cisco.com>
Signed-off-by: Martin Bugge <marbugge@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 99734b2..417468c 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -161,6 +161,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_DMT_1792X1344P60,
V4L2_DV_BT_DMT_1856X1392P60,
V4L2_DV_BT_DMT_1920X1200P60_RB,
+ V4L2_DV_BT_DMT_1366X768P60_RB,
V4L2_DV_BT_DMT_1366X768P60,
V4L2_DV_BT_DMT_1920X1080P60,
{ },
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 04/15] adv7604: adv7604_s_register clean up.
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 02/15] adv7604: add hdmi driver strength adjustment Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 03/15] adv7604: support 1366x768 DMT Reduced Blanking Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 05/15] adv7604: Receive CEA formats as RGB on VGA (RGB) input Hans Verkuil
` (10 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 417468c..37f3994 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -718,45 +718,47 @@ static int adv7604_g_register(struct v4l2_subdev *sd,
static int adv7604_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg)
{
+ u8 val = reg->val & 0xff;
+
switch (reg->reg >> 8) {
case 0:
- io_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ io_write(sd, reg->reg & 0xff, val);
break;
case 1:
- avlink_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ avlink_write(sd, reg->reg & 0xff, val);
break;
case 2:
- cec_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ cec_write(sd, reg->reg & 0xff, val);
break;
case 3:
- infoframe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ infoframe_write(sd, reg->reg & 0xff, val);
break;
case 4:
- esdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ esdp_write(sd, reg->reg & 0xff, val);
break;
case 5:
- dpp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ dpp_write(sd, reg->reg & 0xff, val);
break;
case 6:
- afe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ afe_write(sd, reg->reg & 0xff, val);
break;
case 7:
- rep_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ rep_write(sd, reg->reg & 0xff, val);
break;
case 8:
- edid_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ edid_write(sd, reg->reg & 0xff, val);
break;
case 9:
- hdmi_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ hdmi_write(sd, reg->reg & 0xff, val);
break;
case 0xa:
- test_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ test_write(sd, reg->reg & 0xff, val);
break;
case 0xb:
- cp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ cp_write(sd, reg->reg & 0xff, val);
break;
case 0xc:
- vdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ vdp_write(sd, reg->reg & 0xff, val);
break;
default:
v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 05/15] adv7604: Receive CEA formats as RGB on VGA (RGB) input
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (2 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 04/15] adv7604: adv7604_s_register clean up Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 06/15] adv7604: select YPbPr if RGB_RANGE_FULL/LIMITED is set for VGA_COMP inputs Hans Verkuil
` (9 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
If the input is ADV7604_INPUT_VGA_RGB and RGB quantization range is
set to V4L2_DV_RGB_RANGE_AUTO, video with CEA timings will be
received as RGB. For ADV7604_INPUT_VGA_COMP, automatic CSC mode
will be selected.
See table 44 on page 205 in "ADV7604 Hardware Manual, Rev. F, August 2010"
for details.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 50 ++++++++++++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 17 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 37f3994..7187378 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -911,25 +911,41 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ v4l2_dbg(2, debug, sd, "%s: rgb_quantization_range = %d\n",
+ __func__, state->rgb_quantization_range);
+
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
- /* automatic */
- if (is_digital_input(sd) && !(hdmi_read(sd, 0x05) & 0x80)) {
- /* receiving DVI-D signal */
-
- /* ADV7604 selects RGB limited range regardless of
- input format (CE/IT) in automatic mode */
- if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
- /* RGB limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x00);
-
- } else {
- /* RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
- }
- } else {
- /* receiving HDMI or analog signal, set automode */
+ if (state->selected_input == ADV7604_INPUT_VGA_RGB) {
+ /* Receiving analog RGB signal
+ * Set RGB full range (0-255) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ break;
+ }
+
+ if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ /* Receiving analog YPbPr signal
+ * Set automode */
+ io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+ break;
+ }
+
+ if (hdmi_read(sd, 0x05) & 0x80) {
+ /* Receiving HDMI signal
+ * Set automode */
io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+ break;
+ }
+
+ /* Receiving DVI-D signal
+ * ADV7604 selects RGB limited range regardless of
+ * input format (CE/IT) in automatic mode */
+ if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+ /* RGB limited range (16-235) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ } else {
+ /* RGB full range (0-255) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x10);
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
@@ -1709,7 +1725,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
char *input_color_space_txt[16] = {
"RGB limited range (16-235)", "RGB full range (0-255)",
"YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
- "XvYCC Bt.601", "XvYCC Bt.709",
+ "xvYCC Bt.601", "xvYCC Bt.709",
"YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
"invalid", "invalid", "invalid", "invalid", "invalid",
"invalid", "invalid", "automatic"
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 06/15] adv7604: select YPbPr if RGB_RANGE_FULL/LIMITED is set for VGA_COMP inputs
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (3 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 05/15] adv7604: Receive CEA formats as RGB on VGA (RGB) input Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 07/15] adv7604: set CEC address (SPA) in EDID Hans Verkuil
` (8 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 7187378..b53373b 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -949,17 +949,26 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
- /* RGB limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ /* YCrCb limited range (16-235) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x20);
+ } else {
+ /* RGB limited range (16-235) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ }
break;
case V4L2_DV_RGB_RANGE_FULL:
- /* RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ /* YCrCb full range (0-255) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x60);
+ } else {
+ /* RGB full range (0-255) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ }
break;
}
}
-
static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 07/15] adv7604: set CEC address (SPA) in EDID
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (4 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 06/15] adv7604: select YPbPr if RGB_RANGE_FULL/LIMITED is set for VGA_COMP inputs Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 08/15] adv7604: improve EDID handling Hans Verkuil
` (7 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 83 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 70 insertions(+), 13 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index b53373b..5e40a60 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -72,6 +72,7 @@ struct adv7604_state {
u32 present;
unsigned blocks;
} edid;
+ u16 spa_port_a;
struct v4l2_fract aspect_ratio;
u32 rgb_quantization_range;
struct workqueue_struct *work_queues;
@@ -531,9 +532,6 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
- /* Disables I2C access to internal EDID ram from DDC port */
- rep_write_and_or(sd, 0x77, 0xf0, 0x0);
-
for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
I2C_SMBUS_BLOCK_MAX, val + i);
@@ -1623,9 +1621,39 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
return 0;
}
+static int get_edid_spa_location(struct v4l2_subdev *sd, const u8 *edid)
+{
+ u8 d;
+
+ if ((edid[0x7e] != 1) ||
+ (edid[0x80] != 0x02) ||
+ (edid[0x81] != 0x03)) {
+ return -1;
+ }
+
+ /* search Vendor Specific Data Block (tag 3) */
+ d = edid[0x82] & 0x7f;
+ if (d > 4) {
+ int i = 0x84;
+ int end = 0x80 + d;
+
+ do {
+ u8 tag = edid[i] >> 5;
+ u8 len = edid[i] & 0x1f;
+
+ if ((tag == 3) && (len >= 5))
+ return i + 4;
+ i += len + 1;
+ } while (i < end);
+ }
+ return -1;
+}
+
static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
{
struct adv7604_state *state = to_state(sd);
+ int spa_loc = get_edid_spa_location(sd, edid->edid);
+ int tmp = 0;
int err;
if (edid->pad > ADV7604_EDID_PORT_D)
@@ -1633,16 +1661,20 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
if (edid->start_block != 0)
return -EINVAL;
if (edid->blocks == 0) {
- /* Pull down the hotplug pin */
+ /* Disable hotplug and I2C access to EDID RAM from DDC port */
state->edid.present &= ~(1 << edid->pad);
v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
- /* Disables I2C access to internal EDID ram from DDC port */
- rep_write_and_or(sd, 0x77, 0xf0, 0x0);
- state->edid.blocks = 0;
+ rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+
/* Fall back to a 16:9 aspect ratio */
state->aspect_ratio.numerator = 16;
state->aspect_ratio.denominator = 9;
- v4l2_dbg(2, debug, sd, "%s: clear edid\n", __func__);
+
+ if (!state->edid.present)
+ state->edid.blocks = 0;
+
+ v4l2_dbg(2, debug, sd, "%s: clear EDID pad %d, edid.present = 0x%x\n",
+ __func__, edid->pad, state->edid.present);
return 0;
}
if (edid->blocks > 2) {
@@ -1652,19 +1684,45 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
if (!edid->edid)
return -EINVAL;
+ /* Disable hotplug and I2C access to EDID RAM from DDC port */
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
- state->edid.present &= ~(1 << edid->pad);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
+ v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
+ rep_write_and_or(sd, 0x77, 0xf0, 0x00);
+
+ v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
+ __func__, edid->pad, state->edid.present);
+ switch (edid->pad) {
+ case ADV7604_EDID_PORT_A:
+ state->spa_port_a = edid->edid[spa_loc];
+ break;
+ case ADV7604_EDID_PORT_B:
+ rep_write(sd, 0x70, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
+ rep_write(sd, 0x71, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ break;
+ case ADV7604_EDID_PORT_C:
+ rep_write(sd, 0x72, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
+ rep_write(sd, 0x73, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ break;
+ case ADV7604_EDID_PORT_D:
+ rep_write(sd, 0x74, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
+ rep_write(sd, 0x75, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ break;
+ }
+ rep_write(sd, 0x76, (spa_loc < 0) ? 0x00 : spa_loc);
+ rep_write_and_or(sd, 0x77, 0xbf, (spa_loc < 0) ? 0x00 : (spa_loc >> 2) & 0x40);
+
+ if (spa_loc > 0)
+ edid->edid[spa_loc] = state->spa_port_a;
memcpy(state->edid.edid, edid->edid, 128 * edid->blocks);
state->edid.blocks = edid->blocks;
state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15],
edid->edid[0x16]);
- state->edid.present |= edid->pad;
+ state->edid.present |= 1 << edid->pad;
err = edid_write_block(sd, 128 * edid->blocks, state->edid.edid);
if (err < 0) {
- v4l2_err(sd, "error %d writing edid\n", err);
+ v4l2_err(sd, "error %d writing edid pad %d\n", err, edid->pad);
return err;
}
@@ -1984,7 +2042,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
for digital formats */
- rep_write(sd, 0x76, 0xc0); /* SPA location for port B, C and D */
/* TODO from platform data */
afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 08/15] adv7604: improve EDID handling
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (5 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 07/15] adv7604: set CEC address (SPA) in EDID Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 09/15] adv7604: remove connector type. Never used for anything useful Hans Verkuil
` (6 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
- split edid_write_block()
- do not use edid->edid before the validity check
- Return -EINVAL if edid->pad is invalid
- Save both registers for SPA port A
- Set SPA location to default value if it is not found
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 94 ++++++++++++++++++++++++---------------------
1 file changed, 50 insertions(+), 44 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 5e40a60..4ce3815 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -72,7 +72,7 @@ struct adv7604_state {
u32 present;
unsigned blocks;
} edid;
- u16 spa_port_a;
+ u16 spa_port_a[2];
struct v4l2_fract aspect_ratio;
u32 rgb_quantization_range;
struct workqueue_struct *work_queues;
@@ -510,22 +510,9 @@ static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
return 0;
}
-static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct adv7604_state *state = container_of(dwork, struct adv7604_state,
- delayed_work_enable_hotplug);
- struct v4l2_subdev *sd = &state->sd;
-
- v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
-
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
-}
-
static inline int edid_write_block(struct v4l2_subdev *sd,
unsigned len, const u8 *val)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
struct adv7604_state *state = to_state(sd);
int err = 0;
int i;
@@ -535,24 +522,19 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
I2C_SMBUS_BLOCK_MAX, val + i);
- if (err)
- return err;
+ return err;
+}
- /* adv7604 calculates the checksums and enables I2C access to internal
- EDID RAM from DDC port. */
- rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct adv7604_state *state = container_of(dwork, struct adv7604_state,
+ delayed_work_enable_hotplug);
+ struct v4l2_subdev *sd = &state->sd;
- for (i = 0; i < 1000; i++) {
- if (rep_read(sd, 0x7d) & state->edid.present)
- break;
- mdelay(1);
- }
- if (i == 1000) {
- v4l_err(client, "error enabling edid (0x%x)\n", state->edid.present);
- return -EIO;
- }
+ v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
- return 0;
+ v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
}
static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
@@ -1621,7 +1603,7 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
return 0;
}
-static int get_edid_spa_location(struct v4l2_subdev *sd, const u8 *edid)
+static int get_edid_spa_location(const u8 *edid)
{
u8 d;
@@ -1652,9 +1634,10 @@ static int get_edid_spa_location(struct v4l2_subdev *sd, const u8 *edid)
static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
{
struct adv7604_state *state = to_state(sd);
- int spa_loc = get_edid_spa_location(sd, edid->edid);
+ int spa_loc;
int tmp = 0;
int err;
+ int i;
if (edid->pad > ADV7604_EDID_PORT_D)
return -EINVAL;
@@ -1684,35 +1667,43 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
if (!edid->edid)
return -EINVAL;
+ v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
+ __func__, edid->pad, state->edid.present);
+
/* Disable hotplug and I2C access to EDID RAM from DDC port */
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
rep_write_and_or(sd, 0x77, 0xf0, 0x00);
- v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
- __func__, edid->pad, state->edid.present);
+ spa_loc = get_edid_spa_location(edid->edid);
+ if (spa_loc < 0)
+ spa_loc = 0xc0; /* Default value [REF_02, p. 116] */
+
switch (edid->pad) {
case ADV7604_EDID_PORT_A:
- state->spa_port_a = edid->edid[spa_loc];
+ state->spa_port_a[0] = edid->edid[spa_loc];
+ state->spa_port_a[1] = edid->edid[spa_loc + 1];
break;
case ADV7604_EDID_PORT_B:
- rep_write(sd, 0x70, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
- rep_write(sd, 0x71, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ rep_write(sd, 0x70, edid->edid[spa_loc]);
+ rep_write(sd, 0x71, edid->edid[spa_loc + 1]);
break;
case ADV7604_EDID_PORT_C:
- rep_write(sd, 0x72, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
- rep_write(sd, 0x73, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ rep_write(sd, 0x72, edid->edid[spa_loc]);
+ rep_write(sd, 0x73, edid->edid[spa_loc + 1]);
break;
case ADV7604_EDID_PORT_D:
- rep_write(sd, 0x74, (spa_loc < 0) ? 0 : edid->edid[spa_loc]);
- rep_write(sd, 0x75, (spa_loc < 0) ? 0 : edid->edid[spa_loc + 1]);
+ rep_write(sd, 0x74, edid->edid[spa_loc]);
+ rep_write(sd, 0x75, edid->edid[spa_loc + 1]);
break;
+ default:
+ return -EINVAL;
}
- rep_write(sd, 0x76, (spa_loc < 0) ? 0x00 : spa_loc);
- rep_write_and_or(sd, 0x77, 0xbf, (spa_loc < 0) ? 0x00 : (spa_loc >> 2) & 0x40);
+ rep_write(sd, 0x76, spa_loc & 0xff);
+ rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40);
- if (spa_loc > 0)
- edid->edid[spa_loc] = state->spa_port_a;
+ edid->edid[spa_loc] = state->spa_port_a[0];
+ edid->edid[spa_loc + 1] = state->spa_port_a[1];
memcpy(state->edid.edid, edid->edid, 128 * edid->blocks);
state->edid.blocks = edid->blocks;
@@ -1726,6 +1717,21 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
return err;
}
+ /* adv7604 calculates the checksums and enables I2C access to internal
+ EDID RAM from DDC port. */
+ rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+
+ for (i = 0; i < 1000; i++) {
+ if (rep_read(sd, 0x7d) & state->edid.present)
+ break;
+ mdelay(1);
+ }
+ if (i == 1000) {
+ v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present);
+ return -EIO;
+ }
+
+
/* enable hotplug after 100 ms */
queue_delayed_work(state->work_queues,
&state->delayed_work_enable_hotplug, HZ / 10);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 09/15] adv7604: remove connector type. Never used for anything useful.
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (6 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 08/15] adv7604: improve EDID handling Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 10/15] adv7604: return immediately if the new input is equal to what is configured Hans Verkuil
` (5 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
May also be wrong if the receiver is connected to more than one connector.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 4 ----
include/media/adv7604.h | 3 ---
2 files changed, 7 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 4ce3815..7d95a28 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -77,7 +77,6 @@ struct adv7604_state {
u32 rgb_quantization_range;
struct workqueue_struct *work_queues;
struct delayed_work delayed_work_enable_hotplug;
- bool connector_hdmi;
bool restart_stdi_once;
u32 prev_input_status;
@@ -1817,8 +1816,6 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "-----Chip status-----\n");
v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
- v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ?
- "HDMI" : (is_digital_input(sd) ? "DVI-D" : "DVI-A"));
v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
((rep_read(sd, 0x7d) & 0x01) ? "Yes" : "No"),
((rep_read(sd, 0x7d) & 0x02) ? "Yes" : "No"),
@@ -2138,7 +2135,6 @@ static int adv7604_probe(struct i2c_client *client,
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- state->connector_hdmi = pdata->connector_hdmi;
/* i2c access to adv7604? */
if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 0e13d1b..0162c31 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -80,9 +80,6 @@ enum adv7604_op_format_sel {
/* Platform dependent definition */
struct adv7604_platform_data {
- /* connector - HDMI or DVI? */
- unsigned connector_hdmi:1;
-
/* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
unsigned disable_pwrdnb:1;
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 10/15] adv7604: return immediately if the new input is equal to what is configured
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (7 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 09/15] adv7604: remove connector type. Never used for anything useful Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 11/15] adv7604: remove debouncing of ADV7604_FMT_CHANGE events Hans Verkuil
` (4 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 7d95a28..fa98229 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1479,7 +1479,11 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
{
struct adv7604_state *state = to_state(sd);
- v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
+ v4l2_dbg(2, debug, sd, "%s: input %d, selected input %d",
+ __func__, input, state->selected_input);
+
+ if (input == state->selected_input)
+ return 0;
state->selected_input = input;
@@ -1524,6 +1528,8 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
u8 fmt_change, fmt_change_digital, tx_5v;
u32 input_status;
+ v4l2_dbg(2, debug, sd, "%s: ", __func__);
+
/* format change */
fmt_change = io_read(sd, 0x43) & 0x98;
if (fmt_change)
@@ -2124,6 +2130,7 @@ static int adv7604_probe(struct i2c_client *client,
/* initialize variables */
state->restart_stdi_once = true;
state->prev_input_status = ~0;
+ state->selected_input = ~0;
/* platform data */
if (!pdata) {
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 11/15] adv7604: remove debouncing of ADV7604_FMT_CHANGE events
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (8 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 10/15] adv7604: return immediately if the new input is equal to what is configured Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 12/15] adv7604: improve HDMI audio handling Hans Verkuil
` (3 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
ADV7604_FMT_CHANGE events was debounced in adv7604_isr() to avoid
that a receiver with a unstable input signal would block the event
handling for other inputs. This solution was prone to errors.
A better protection agains interrupt blocking is to delay the call
of the interrupt service routine in the adv7604 driver if too many
interrupts are received within a given time.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index fa98229..50f0279 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -78,7 +78,6 @@ struct adv7604_state {
struct workqueue_struct *work_queues;
struct delayed_work delayed_work_enable_hotplug;
bool restart_stdi_once;
- u32 prev_input_status;
/* i2c clients */
struct i2c_client *i2c_avlink;
@@ -1524,9 +1523,7 @@ static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
- struct adv7604_state *state = to_state(sd);
u8 fmt_change, fmt_change_digital, tx_5v;
- u32 input_status;
v4l2_dbg(2, debug, sd, "%s: ", __func__);
@@ -1534,22 +1531,17 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
fmt_change = io_read(sd, 0x43) & 0x98;
if (fmt_change)
io_write(sd, 0x44, fmt_change);
+
fmt_change_digital = is_digital_input(sd) ? (io_read(sd, 0x6b) & 0xc0) : 0;
if (fmt_change_digital)
io_write(sd, 0x6c, fmt_change_digital);
+
if (fmt_change || fmt_change_digital) {
v4l2_dbg(1, debug, sd,
"%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
__func__, fmt_change, fmt_change_digital);
- adv7604_g_input_status(sd, &input_status);
- if (input_status != state->prev_input_status) {
- v4l2_dbg(1, debug, sd,
- "%s: input_status = 0x%x, prev_input_status = 0x%x\n",
- __func__, input_status, state->prev_input_status);
- state->prev_input_status = input_status;
- v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
- }
+ v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
if (handled)
*handled = true;
@@ -2129,7 +2121,6 @@ static int adv7604_probe(struct i2c_client *client,
/* initialize variables */
state->restart_stdi_once = true;
- state->prev_input_status = ~0;
state->selected_input = ~0;
/* platform data */
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 12/15] adv7604: improve HDMI audio handling
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (9 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 11/15] adv7604: remove debouncing of ADV7604_FMT_CHANGE events Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 13/15] adv7604: set restart_stdi_once flag when signal is lost Hans Verkuil
` (2 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
- Mute audio before switching inputs to avoid noise/pops
- Mute audio if audio FIFO over-/underflows (AD Recommended setting)
- Reset FIFO if it over-/underflows (AD Recommended setting)
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 50f0279..cbeda0f 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1387,14 +1387,12 @@ static void enable_input(struct v4l2_subdev *sd)
struct adv7604_state *state = to_state(sd);
if (is_analog_input(sd)) {
- /* enable */
io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
} else if (is_digital_input(sd)) {
- /* enable */
hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
- hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
+ hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */
} else {
v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
__func__, state->selected_input);
@@ -1403,9 +1401,9 @@ static void enable_input(struct v4l2_subdev *sd)
static void disable_input(struct v4l2_subdev *sd)
{
- /* disable */
+ hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */
+ msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */
- hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */
hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
}
@@ -2044,6 +2042,11 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
for digital formats */
+ /* HDMI audio */
+ hdmi_write_and_or(sd, 0x15, 0xfc, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
+ hdmi_write_and_or(sd, 0x1a, 0xf1, 0x08); /* Wait 1 s before unmute */
+ hdmi_write_and_or(sd, 0x68, 0xf9, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
+
/* TODO from platform data */
afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 13/15] adv7604: set restart_stdi_once flag when signal is lost.
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (10 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 12/15] adv7604: improve HDMI audio handling Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 14/15] adv7604: adjust gain and offset for DVI-D signals Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Martin Bugge, Mats Randgaard, Hans Verkuil
From: Martin Bugge <marbugge@cisco.com>
If the restart_stdi_once trick fails to find a valid
format the flag was never reset.
Signed-off-by: Martin Bugge <marbugge@cisco.com>
Cc: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index cbeda0f..0e69b24 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1216,6 +1216,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
memset(timings, 0, sizeof(struct v4l2_dv_timings));
if (no_signal(sd)) {
+ state->restart_stdi_once = true;
v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__);
return -ENOLINK;
}
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 14/15] adv7604: adjust gain and offset for DVI-D signals
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (11 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 13/15] adv7604: set restart_stdi_once flag when signal is lost Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
13 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
If the input signal is DVI-D and quantization range is RGB full range,
gain and offset must be adjusted to get the right range on the output.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 98 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 89 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 0e69b24..c195a92 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -885,12 +885,72 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
cp_write(sd, 0xac, (height & 0x0f) << 4);
}
+static void adv7604_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
+{
+ struct adv7604_state *state = to_state(sd);
+ u8 offset_buf[4];
+
+ if (auto_offset) {
+ offset_a = 0x3ff;
+ offset_b = 0x3ff;
+ offset_c = 0x3ff;
+ }
+
+ v4l2_dbg(2, debug, sd, "%s: %s offset: a = 0x%x, b = 0x%x, c = 0x%x\n",
+ __func__, auto_offset ? "Auto" : "Manual",
+ offset_a, offset_b, offset_c);
+
+ offset_buf[0] = (cp_read(sd, 0x77) & 0xc0) | ((offset_a & 0x3f0) >> 4);
+ offset_buf[1] = ((offset_a & 0x00f) << 4) | ((offset_b & 0x3c0) >> 6);
+ offset_buf[2] = ((offset_b & 0x03f) << 2) | ((offset_c & 0x300) >> 8);
+ offset_buf[3] = offset_c & 0x0ff;
+
+ /* Registers must be written in this order with no i2c access in between */
+ if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x77, 4, offset_buf))
+ v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
+}
+
+static void adv7604_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
+{
+ struct adv7604_state *state = to_state(sd);
+ u8 gain_buf[4];
+ u8 gain_man = 1;
+ u8 agc_mode_man = 1;
+
+ if (auto_gain) {
+ gain_man = 0;
+ agc_mode_man = 0;
+ gain_a = 0x100;
+ gain_b = 0x100;
+ gain_c = 0x100;
+ }
+
+ v4l2_dbg(2, debug, sd, "%s: %s gain: a = 0x%x, b = 0x%x, c = 0x%x\n",
+ __func__, auto_gain ? "Auto" : "Manual",
+ gain_a, gain_b, gain_c);
+
+ gain_buf[0] = ((gain_man << 7) | (agc_mode_man << 6) | ((gain_a & 0x3f0) >> 4));
+ gain_buf[1] = (((gain_a & 0x00f) << 4) | ((gain_b & 0x3c0) >> 6));
+ gain_buf[2] = (((gain_b & 0x03f) << 2) | ((gain_c & 0x300) >> 8));
+ gain_buf[3] = ((gain_c & 0x0ff));
+
+ /* Registers must be written in this order with no i2c access in between */
+ if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x73, 4, gain_buf))
+ v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
+}
+
static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ bool rgb_output = io_read(sd, 0x02) & 0x02;
+ bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
+
+ v4l2_dbg(2, debug, sd, "%s: RGB quantization range: %d, RGB out: %d, HDMI: %d\n",
+ __func__, state->rgb_quantization_range,
+ rgb_output, hdmi_signal);
- v4l2_dbg(2, debug, sd, "%s: rgb_quantization_range = %d\n",
- __func__, state->rgb_quantization_range);
+ adv7604_set_gain(sd, true, 0x0, 0x0, 0x0);
+ adv7604_set_offset(sd, true, 0x0, 0x0, 0x0);
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
@@ -908,7 +968,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
break;
}
- if (hdmi_read(sd, 0x05) & 0x80) {
+ if (hdmi_signal) {
/* Receiving HDMI signal
* Set automode */
io_write_and_or(sd, 0x02, 0x0f, 0xf0);
@@ -924,24 +984,45 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
} else {
/* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10);
+
+ if (is_digital_input(sd) && rgb_output) {
+ adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
+ } else {
+ adv7604_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
+ adv7604_set_offset(sd, false, 0x70, 0x70, 0x70);
+ }
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
/* YCrCb limited range (16-235) */
io_write_and_or(sd, 0x02, 0x0f, 0x20);
- } else {
- /* RGB limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ break;
}
+
+ /* RGB limited range (16-235) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x00);
+
break;
case V4L2_DV_RGB_RANGE_FULL:
if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
/* YCrCb full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x60);
+ break;
+ }
+
+ /* RGB full range (0-255) */
+ io_write_and_or(sd, 0x02, 0x0f, 0x10);
+
+ if (is_analog_input(sd) || hdmi_signal)
+ break;
+
+ /* Adjust gain/offset for DVI-D signals only */
+ if (rgb_output) {
+ adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
} else {
- /* RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ adv7604_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
+ adv7604_set_offset(sd, false, 0x70, 0x70, 0x70);
}
break;
}
@@ -1367,7 +1448,6 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
set_rgb_quantization_range(sd);
-
if (debug > 1)
v4l2_print_dv_timings(sd->name, "adv7604_s_dv_timings: ",
timings, true);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
` (12 preceding siblings ...)
2013-12-10 13:23 ` [RFC PATCH 14/15] adv7604: adjust gain and offset for DVI-D signals Hans Verkuil
@ 2013-12-10 13:23 ` Hans Verkuil
2013-12-17 13:14 ` [RFC PATCH 16/15] adv7604: return immediately if the new timings are equal to what is configured Hans Verkuil
` (2 more replies)
13 siblings, 3 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-10 13:23 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
From: Mats Randgaard <matrandg@cisco.com>
Some sources are initially detected as DVI, and change to HDMI later.
This must be detected to set the right RGB quantization range.
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index c195a92..cfeaaaf 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1602,18 +1602,25 @@ static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
- u8 fmt_change, fmt_change_digital, tx_5v;
+ const u8 irq_reg_0x43 = io_read(sd, 0x43);
+ const u8 irq_reg_0x6b = io_read(sd, 0x6b);
+ const u8 irq_reg_0x70 = io_read(sd, 0x70);
+ u8 fmt_change_digital;
+ u8 fmt_change;
+ u8 tx_5v;
+
+ if (irq_reg_0x43)
+ io_write(sd, 0x44, irq_reg_0x43);
+ if (irq_reg_0x70)
+ io_write(sd, 0x71, irq_reg_0x70);
+ if (irq_reg_0x6b)
+ io_write(sd, 0x6c, irq_reg_0x6b);
v4l2_dbg(2, debug, sd, "%s: ", __func__);
/* format change */
- fmt_change = io_read(sd, 0x43) & 0x98;
- if (fmt_change)
- io_write(sd, 0x44, fmt_change);
-
- fmt_change_digital = is_digital_input(sd) ? (io_read(sd, 0x6b) & 0xc0) : 0;
- if (fmt_change_digital)
- io_write(sd, 0x6c, fmt_change_digital);
+ fmt_change = irq_reg_0x43 & 0x98;
+ fmt_change_digital = is_digital_input(sd) ? (irq_reg_0x6b & 0xc0) : 0;
if (fmt_change || fmt_change_digital) {
v4l2_dbg(1, debug, sd,
@@ -1625,6 +1632,15 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
if (handled)
*handled = true;
}
+ /* HDMI/DVI mode */
+ if (irq_reg_0x6b & 0x01) {
+ v4l2_dbg(1, debug, sd, "%s: irq %s mode\n", __func__,
+ (io_read(sd, 0x6a) & 0x01) ? "HDMI" : "DVI");
+ set_rgb_quantization_range(sd);
+ if (handled)
+ *handled = true;
+ }
+
/* tx 5v detect */
tx_5v = io_read(sd, 0x70) & 0x1e;
if (tx_5v) {
@@ -2138,7 +2154,7 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
io_write(sd, 0x40, 0xc2); /* Configure INT1 */
io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
- io_write(sd, 0x6e, 0xc0); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
+ io_write(sd, 0x6e, 0xc1); /* Enable V_LOCKED, DE_REGEN_LCK, HDMI_MODE interrupts */
io_write(sd, 0x73, 0x1e); /* Enable CABLE_DET_A_ST (+5v) interrupts */
return v4l2_ctrl_handler_setup(sd->ctrl_handler);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 16/15] adv7604: return immediately if the new timings are equal to what is configured
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
@ 2013-12-17 13:14 ` Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 17/15] adv7604: sync polarities from platform data Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 18/15] adv7604: initialize timings to CEA 640x480p59.94 Hans Verkuil
2 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-17 13:14 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index cfeaaaf..a1fa9a0 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1423,6 +1423,11 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
if (!timings)
return -EINVAL;
+ if (v4l2_match_dv_timings(&state->timings, timings, 0)) {
+ v4l2_dbg(1, debug, sd, "%s: no change\n", __func__);
+ return 0;
+ }
+
bt = &timings->bt;
if ((is_analog_input(sd) && bt->pixelclock > 170000000) ||
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 17/15] adv7604: sync polarities from platform data
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
2013-12-17 13:14 ` [RFC PATCH 16/15] adv7604: return immediately if the new timings are equal to what is configured Hans Verkuil
@ 2013-12-17 13:15 ` Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 18/15] adv7604: initialize timings to CEA 640x480p59.94 Hans Verkuil
2 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-17 13:15 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
Signed-off-by: Martin Bugge <marbugge@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 5 +++--
include/media/adv7604.h | 4 ++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index a1fa9a0..3f40616 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2126,9 +2126,10 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
pdata->replicate_av_codes << 1 |
pdata->invert_cbcr << 0);
- /* TODO from platform data */
cp_write(sd, 0x69, 0x30); /* Enable CP CSC */
- io_write(sd, 0x06, 0xa6); /* positive VS and HS */
+
+ /* VS, HS polarities */
+ io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 | pdata->inv_hs_pol << 1);
/* Adjust drive strength */
io_write(sd, 0x14, 0x40 | pdata->dr_str << 4 |
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 0162c31..053b13c 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -107,6 +107,10 @@ struct adv7604_platform_data {
unsigned replicate_av_codes:1;
unsigned invert_cbcr:1;
+ /* IO register 0x06 */
+ unsigned inv_vs_pol:1;
+ unsigned inv_hs_pol:1;
+
/* IO register 0x14 */
unsigned dr_str:2;
unsigned dr_str_clk:2;
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 18/15] adv7604: initialize timings to CEA 640x480p59.94.
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
2013-12-17 13:14 ` [RFC PATCH 16/15] adv7604: return immediately if the new timings are equal to what is configured Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 17/15] adv7604: sync polarities from platform data Hans Verkuil
@ 2013-12-17 13:15 ` Hans Verkuil
2 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2013-12-17 13:15 UTC (permalink / raw)
To: linux-media; +Cc: Mats Randgaard, Hans Verkuil
This timing must be supported by all HDMI equipment, so that's a
reasonable default.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/i2c/adv7604.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 3f40616..f063162 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2207,6 +2207,8 @@ static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
static int adv7604_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ static const struct v4l2_dv_timings cea640x480 =
+ V4L2_DV_BT_CEA_640X480P59_94;
struct adv7604_state *state;
struct adv7604_platform_data *pdata = client->dev.platform_data;
struct v4l2_ctrl_handler *hdl;
@@ -2234,7 +2236,8 @@ static int adv7604_probe(struct i2c_client *client,
v4l_err(client, "No platform data!\n");
return -ENODEV;
}
- memcpy(&state->pdata, pdata, sizeof(state->pdata));
+ state->pdata = *pdata;
+ state->timings = cea640x480;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2013-12-17 13:17 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-10 13:23 [RFC PATCH 00/15] adv7604: fixes Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 01/15] adv7604: add support for all the digital input ports Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 02/15] adv7604: add hdmi driver strength adjustment Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 03/15] adv7604: support 1366x768 DMT Reduced Blanking Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 04/15] adv7604: adv7604_s_register clean up Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 05/15] adv7604: Receive CEA formats as RGB on VGA (RGB) input Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 06/15] adv7604: select YPbPr if RGB_RANGE_FULL/LIMITED is set for VGA_COMP inputs Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 07/15] adv7604: set CEC address (SPA) in EDID Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 08/15] adv7604: improve EDID handling Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 09/15] adv7604: remove connector type. Never used for anything useful Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 10/15] adv7604: return immediately if the new input is equal to what is configured Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 11/15] adv7604: remove debouncing of ADV7604_FMT_CHANGE events Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 12/15] adv7604: improve HDMI audio handling Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 13/15] adv7604: set restart_stdi_once flag when signal is lost Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 14/15] adv7604: adjust gain and offset for DVI-D signals Hans Verkuil
2013-12-10 13:23 ` [RFC PATCH 15/15] adv7604: Enable HDMI_MODE interrupt Hans Verkuil
2013-12-17 13:14 ` [RFC PATCH 16/15] adv7604: return immediately if the new timings are equal to what is configured Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 17/15] adv7604: sync polarities from platform data Hans Verkuil
2013-12-17 13:15 ` [RFC PATCH 18/15] adv7604: initialize timings to CEA 640x480p59.94 Hans Verkuil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox