aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2012-08-06 21:47:02 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-09 19:37:56 -0400
commit4a03dafc7b0a347854bc0a8652ffa314150fd1e5 (patch)
tree590e3ffbb5b9b42cacb3321e4a84066243510b14
parentfc7a74bad1ae1d68a1a9999634baeb4bae277a92 (diff)
[media] au0828: prevent i2c gate from being kept open while in analog mode
The original implementation of the analog support would use an i2c_gate_ctrl function when using the digital side of the au8522, but on the analog side we would always just force the gate open and leave it open all the time. This can have adverse effects on the xc5000 given the tuner is receiving all the spurious i2c traffic (a problem which can be exaggerated due to bugs in the au0828 i2c hardware implementation). Rework the existing hack to only open/close the gate when actually talking to the tuner. This logic might need to be reworked a bit if anybody ever tries to add support for a board that has the au0828/au8522 but doesn't have digital support implemented (because the i2c_gate_ctrl callback is being set in the DVB attach). However given how few different models are in circulation, this can be deferred until such a situation arises (if ever). Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/au8522_common.c13
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c5
-rw-r--r--drivers/media/dvb/frontends/au8522_dig.c2
-rw-r--r--drivers/media/dvb/frontends/au8522_priv.h1
-rw-r--r--drivers/media/video/au0828/au0828-video.c6
5 files changed, 22 insertions, 5 deletions
diff --git a/drivers/media/dvb/frontends/au8522_common.c b/drivers/media/dvb/frontends/au8522_common.c
index 8b4da40192d5..3559ff230045 100644
--- a/drivers/media/dvb/frontends/au8522_common.c
+++ b/drivers/media/dvb/frontends/au8522_common.c
@@ -99,6 +99,19 @@ int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
99} 99}
100EXPORT_SYMBOL(au8522_i2c_gate_ctrl); 100EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
101 101
102int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
103{
104 struct au8522_state *state = fe->demodulator_priv;
105
106 dprintk("%s(%d)\n", __func__, enable);
107
108 if (enable)
109 return au8522_writereg(state, 0x106, 1);
110 else
111 return au8522_writereg(state, 0x106, 0);
112}
113EXPORT_SYMBOL(au8522_analog_i2c_gate_ctrl);
114
102/* Reset the demod hardware and reset all of the configuration registers 115/* Reset the demod hardware and reset all of the configuration registers
103 to a default state. */ 116 to a default state. */
104int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, 117int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index f2e786b606fd..5243ba6295cc 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -659,11 +659,6 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd,
659 659
660 au8522_reset(sd, 0); 660 au8522_reset(sd, 0);
661 661
662 /* Jam open the i2c gate to the tuner. We do this here to handle the
663 case where the user went into digital mode (causing the gate to be
664 closed), and then came back to analog mode */
665 au8522_writereg(state, 0x106, 1);
666
667 if (input == AU8522_COMPOSITE_CH1) { 662 if (input == AU8522_COMPOSITE_CH1) {
668 au8522_setup_cvbs_mode(state); 663 au8522_setup_cvbs_mode(state);
669 } else if (input == AU8522_SVIDEO_CH13) { 664 } else if (input == AU8522_SVIDEO_CH13) {
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
index ee8cf81cf750..a68974f6d708 100644
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -777,6 +777,8 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
777 sizeof(struct dvb_frontend_ops)); 777 sizeof(struct dvb_frontend_ops));
778 state->frontend.demodulator_priv = state; 778 state->frontend.demodulator_priv = state;
779 779
780 state->frontend.ops.analog_ops.i2c_gate_ctrl = au8522_analog_i2c_gate_ctrl;
781
780 if (au8522_init(&state->frontend) != 0) { 782 if (au8522_init(&state->frontend) != 0) {
781 printk(KERN_ERR "%s: Failed to initialize correctly\n", 783 printk(KERN_ERR "%s: Failed to initialize correctly\n",
782 __func__); 784 __func__);
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
index 9f44a7be3148..0529699a27bd 100644
--- a/drivers/media/dvb/frontends/au8522_priv.h
+++ b/drivers/media/dvb/frontends/au8522_priv.h
@@ -82,6 +82,7 @@ int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
82 u8 client_address); 82 u8 client_address);
83void au8522_release_state(struct au8522_state *state); 83void au8522_release_state(struct au8522_state *state);
84int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable); 84int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
85int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
85int au8522_led_ctrl(struct au8522_state *state, int led); 86int au8522_led_ctrl(struct au8522_state *state, int led);
86 87
87/* REGISTERS */ 88/* REGISTERS */
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index f3e6e3f4dfd4..df9232281d64 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -1541,6 +1541,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
1541 1541
1542 dev->ctrl_freq = freq->frequency; 1542 dev->ctrl_freq = freq->frequency;
1543 1543
1544 if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
1545 dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
1546
1544 if (dev->std_set_in_tuner_core == 0) { 1547 if (dev->std_set_in_tuner_core == 0) {
1545 /* If we've never sent the standard in tuner core, do so now. We 1548 /* If we've never sent the standard in tuner core, do so now. We
1546 don't do this at device probe because we don't want to incur 1549 don't do this at device probe because we don't want to incur
@@ -1552,6 +1555,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
1552 1555
1553 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); 1556 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
1554 1557
1558 if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
1559 dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
1560
1555 au0828_analog_stream_reset(dev); 1561 au0828_analog_stream_reset(dev);
1556 1562
1557 return 0; 1563 return 0;