aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-xc2028.c
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 02:14:23 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:21 -0500
commit47cc5b78102b4e9993ea1c054b4f077cf7aac7db (patch)
tree2f4fc9d03c042e1215d56cad7268f1469d80284f /drivers/media/video/tuner-xc2028.c
parent794604c3efb511b74fb664af72c5dd7046e91075 (diff)
V4L/DVB (6631): xc2028: eliminate i2c macro side-effects
The I2C macros have side effects and send_seq could cause a return from a function with a mutex held. Change them to behave like real functions. Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r--drivers/media/video/tuner-xc2028.c82
1 files changed, 46 insertions, 36 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
index d23b33a1f696..6e23fad0e560 100644
--- a/drivers/media/video/tuner-xc2028.c
+++ b/drivers/media/video/tuner-xc2028.c
@@ -83,31 +83,35 @@ struct xc2028_data {
83 struct mutex lock; 83 struct mutex lock;
84}; 84};
85 85
86#define i2c_send(rc, priv, buf, size) do { \ 86#define i2c_send(priv, buf, size) ({ \
87 rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \ 87 int _rc; \
88 if (size != rc) \ 88 _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \
89 tuner_err("i2c output error: rc = %d (should be %d)\n", \ 89 if (size != _rc) \
90 rc, (int)size); \ 90 tuner_info("i2c output error: rc = %d (should be %d)\n",\
91} while (0) 91 _rc, (int)size); \
92 92 _rc; \
93#define i2c_rcv(rc, priv, buf, size) do { \ 93})
94 rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \ 94
95 if (size != rc) \ 95#define i2c_rcv(priv, buf, size) ({ \
96 int _rc; \
97 _rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \
98 if (size != _rc) \
96 tuner_err("i2c input error: rc = %d (should be %d)\n", \ 99 tuner_err("i2c input error: rc = %d (should be %d)\n", \
97 rc, (int)size); \ 100 _rc, (int)size); \
98} while (0) 101 _rc; \
102})
99 103
100#define send_seq(priv, data...) do { \ 104#define send_seq(priv, data...) ({ \
101 int rc; \
102 static u8 _val[] = data; \ 105 static u8 _val[] = data; \
106 int _rc; \
103 if (sizeof(_val) != \ 107 if (sizeof(_val) != \
104 (rc = tuner_i2c_xfer_send(&priv->i2c_props, \ 108 (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \
105 _val, sizeof(_val)))) { \ 109 _val, sizeof(_val)))) { \
106 tuner_err("Error on line %d: %d\n", __LINE__, rc); \ 110 tuner_err("Error on line %d: %d\n", __LINE__, _rc); \
107 return -EINVAL; \ 111 } else \
108 } \ 112 msleep(10); \
109 msleep(10); \ 113 _rc; \
110} while (0) 114})
111 115
112static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg) 116static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
113{ 117{
@@ -119,11 +123,11 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
119 buf[0] = reg>>8; 123 buf[0] = reg>>8;
120 buf[1] = (unsigned char) reg; 124 buf[1] = (unsigned char) reg;
121 125
122 i2c_send(rc, priv, buf, 2); 126 rc = i2c_send(priv, buf, 2);
123 if (rc < 0) 127 if (rc < 0)
124 return rc; 128 return rc;
125 129
126 i2c_rcv(rc, priv, buf, 2); 130 rc = i2c_rcv(priv, buf, 2);
127 if (rc < 0) 131 if (rc < 0)
128 return rc; 132 return rc;
129 133
@@ -505,7 +509,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
505 509
506 memcpy(buf + 1, p, len); 510 memcpy(buf + 1, p, len);
507 511
508 i2c_send(rc, priv, buf, len + 1); 512 rc = i2c_send(priv, buf, len + 1);
509 if (rc < 0) { 513 if (rc < 0) {
510 tuner_err("%d returned from send\n", rc); 514 tuner_err("%d returned from send\n", rc);
511 return -EINVAL; 515 return -EINVAL;
@@ -541,15 +545,20 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
541 if ((priv->firm[pos].size != 12 * 16) || (scode >= 16)) 545 if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
542 return -EINVAL; 546 return -EINVAL;
543 547
544 if (priv->version < 0x0202) { 548 if (priv->version < 0x0202)
545 send_seq(priv, {0x20, 0x00, 0x00, 0x00}); 549 rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
546 } else { 550 else
547 send_seq(priv, {0xa0, 0x00, 0x00, 0x00}); 551 rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
548 } 552 if (rc < 0)
553 return -EIO;
549 554
550 i2c_send(rc, priv, p + 12 * scode, 12); 555 rc = i2c_send(priv, p + 12 * scode, 12);
556 if (rc < 0)
557 return -EIO;
551 558
552 send_seq(priv, {0x00, 0x8c}); 559 rc = send_seq(priv, {0x00, 0x8c});
560 if (rc < 0)
561 return -EIO;
553 562
554 return 0; 563 return 0;
555} 564}
@@ -766,11 +775,12 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
766 775
767 /* CMD= Set frequency */ 776 /* CMD= Set frequency */
768 777
769 if (priv->version < 0x0202) { 778 if (priv->version < 0x0202)
770 send_seq(priv, {0x00, 0x02, 0x00, 0x00}); 779 rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
771 } else { 780 else
772 send_seq(priv, {0x80, 0x02, 0x00, 0x00}); 781 rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
773 } 782 if (rc < 0)
783 goto ret;
774 784
775 rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); 785 rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
776 if (rc < 0) 786 if (rc < 0)
@@ -784,7 +794,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
784 buf[3] = 0xff & (div); 794 buf[3] = 0xff & (div);
785 buf[4] = 0; 795 buf[4] = 0;
786 796
787 i2c_send(rc, priv, buf, sizeof(buf)); 797 rc = i2c_send(priv, buf, sizeof(buf));
788 if (rc < 0) 798 if (rc < 0)
789 goto ret; 799 goto ret;
790 msleep(100); 800 msleep(100);