summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-06-29 21:43:32 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-30 02:04:21 +0400
commit20bfe7ae089076b0af72a6d67f0298621ae90a9d (patch)
tree27c5aab38bcc6c34917098004055a0db70b54142
parent2a5f6720ff45e7545c3058bc6bfdb498247b4f5c (diff)
downloadlinux-20bfe7ae089076b0af72a6d67f0298621ae90a9d.tar.xz
[media] drxk: Lock I2C bus during firmware load
Don't allow other devices at the same I2C bus to use it during firmware load, in order to prevent using the device while it is not on a sane state. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.c29
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.h3
2 files changed, 30 insertions, 2 deletions
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index 5b3a17ce3d1d..87cb3f02ebc0 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
+#include <linux/hardirq.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
@@ -308,10 +309,30 @@ static u32 Log10Times100(u32 x)
/* I2C **********************************************************************/
/****************************************************************************/
+static int drxk_i2c_lock(struct drxk_state *state)
+{
+ i2c_lock_adapter(state->i2c);
+ state->drxk_i2c_exclusive_lock = true;
+
+ return 0;
+}
+
+static void drxk_i2c_unlock(struct drxk_state *state)
+{
+ if (!state->drxk_i2c_exclusive_lock)
+ return;
+
+ i2c_unlock_adapter(state->i2c);
+ state->drxk_i2c_exclusive_lock = false;
+}
+
static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
unsigned len)
{
- return i2c_transfer(state->i2c, msgs, len);
+ if (state->drxk_i2c_exclusive_lock)
+ return __i2c_transfer(state->i2c, msgs, len);
+ else
+ return i2c_transfer(state->i2c, msgs, len);
}
static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
@@ -5982,6 +6003,7 @@ static int init_drxk(struct drxk_state *state)
dprintk(1, "\n");
if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
+ drxk_i2c_lock(state);
status = PowerUpDevice(state);
if (status < 0)
goto error;
@@ -6171,10 +6193,13 @@ static int init_drxk(struct drxk_state *state)
strlcat(state->frontend.ops.info.name, " DVB-T",
sizeof(state->frontend.ops.info.name));
}
+ drxk_i2c_unlock(state);
}
error:
- if (status < 0)
+ if (status < 0) {
+ drxk_i2c_unlock(state);
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+ }
return status;
}
diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h
index 36677cdc01d8..c35ab2b37795 100644
--- a/drivers/media/dvb/frontends/drxk_hard.h
+++ b/drivers/media/dvb/frontends/drxk_hard.h
@@ -325,6 +325,9 @@ struct drxk_state {
enum DRXPowerMode m_currentPowerMode;
+ /* when true, avoids other devices to use the I2C bus */
+ bool drxk_i2c_exclusive_lock;
+
/*
* Configurable parameters at the driver. They stores the values found
* at struct drxk_config.