]> Pileus Git - ~andy/linux/blobdiff - drivers/media/dvb/frontends/dibx000_common.c
Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / drivers / media / dvb / frontends / dibx000_common.c
index 977211fec137bdcf668ef7a022f23548e38ae11b..43be7238311ec513726e8ecaa13d0864c2b622dd 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 
 #include "dibx000_common.h"
@@ -11,6 +12,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
 {
+       int ret;
+
+       if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+               dprintk("could not acquire lock");
+               return -EINVAL;
+       }
+
        mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
        mst->i2c_write_buffer[1] = reg & 0xff;
        mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -22,11 +30,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
        mst->msg[0].buf = mst->i2c_write_buffer;
        mst->msg[0].len = 4;
 
-       return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+       ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+       mutex_unlock(&mst->i2c_buffer_lock);
+
+       return ret;
 }
 
 static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
 {
+       u16 ret;
+
+       if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+               dprintk("could not acquire lock");
+               return 0;
+       }
+
        mst->i2c_write_buffer[0] = reg >> 8;
        mst->i2c_write_buffer[1] = reg & 0xff;
 
@@ -43,7 +61,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
        if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
                dprintk("i2c read error on %d", reg);
 
-       return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+       ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+       mutex_unlock(&mst->i2c_buffer_lock);
+
+       return ret;
 }
 
 static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
@@ -258,6 +279,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
                                        struct i2c_msg msg[], int num)
 {
        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+       int ret;
 
        if (num > 32) {
                dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -265,10 +287,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
                return -ENOMEM;
        }
 
-       memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
 
+       if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+               dprintk("could not acquire lock");
+               return -EINVAL;
+       }
+
+       memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
        /* open the gate */
        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
        mst->msg[0].addr = mst->i2c_addr;
@@ -283,7 +310,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
        mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
        mst->msg[num + 1].len = 4;
 
-       return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+       ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+                       num : -EIO);
+
+       mutex_unlock(&mst->i2c_buffer_lock);
+       return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
@@ -295,6 +326,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
                                        struct i2c_msg msg[], int num)
 {
        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+       int ret;
 
        if (num > 32) {
                dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -302,10 +334,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
                return -ENOMEM;
        }
 
-       memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 
+       if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+               dprintk("could not acquire lock");
+               return -EINVAL;
+       }
+       memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
        /* open the gate */
        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
        mst->msg[0].addr = mst->i2c_addr;
@@ -320,7 +356,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
        mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
        mst->msg[num + 1].len = 4;
 
-       return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+       ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+                       num : -EIO);
+       mutex_unlock(&mst->i2c_buffer_lock);
+       return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
@@ -391,8 +430,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
 int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
                                struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
-       u8 tx[4];
-       struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
+       int ret;
+
+       mutex_init(&mst->i2c_buffer_lock);
+       if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+               dprintk("could not acquire lock");
+               return -EINVAL;
+       }
+       memset(mst->msg, 0, sizeof(struct i2c_msg));
+       mst->msg[0].addr = i2c_addr >> 1;
+       mst->msg[0].flags = 0;
+       mst->msg[0].buf = mst->i2c_write_buffer;
+       mst->msg[0].len = 4;
 
        mst->device_rev = device_rev;
        mst->i2c_adap = i2c_adap;
@@ -432,9 +481,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
                                "DiBX000: could not initialize the master i2c_adapter\n");
 
        /* initialize the i2c-master by closing the gate */
-       dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+       dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
+
+       ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
+       mutex_unlock(&mst->i2c_buffer_lock);
 
-       return i2c_transfer(i2c_adap, &m, 1) == 1;
+       return ret;
 }
 
 EXPORT_SYMBOL(dibx000_init_i2c_master);