aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2011-01-13 09:58:36 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:45:20 -0500
commit567aba0b7997dad5fe3fb4aeb174ee9018df8c5b (patch)
treec4eacb99986d5efcc1e4f398b5478f6d213b8238 /drivers/media
parent5a85025f7dabc5b039335a7d1fb5f9002efa9488 (diff)
[media] tda8290: Make all read operations atomic
Read operations should be preceeded by a write operation. However, nothing prevents that an I2C operation could happen between the two transactions. To avoid that problem, use an unique I2C transfer for both parts of the I2C transaction. Cc: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/common/tuners/tda8290.c119
1 files changed, 66 insertions, 53 deletions
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
index c9062ceddc71..5f889c1b91d0 100644
--- a/drivers/media/common/tuners/tda8290.c
+++ b/drivers/media/common/tuners/tda8290.c
@@ -95,8 +95,7 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
95 msleep(20); 95 msleep(20);
96 } else { 96 } else {
97 msg = disable; 97 msg = disable;
98 tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); 98 tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1);
99 tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
100 99
101 buf[2] = msg[1]; 100 buf[2] = msg[1];
102 buf[2] &= ~0x04; 101 buf[2] &= ~0x04;
@@ -239,13 +238,15 @@ static void tda8290_set_params(struct dvb_frontend *fe,
239 fe->ops.tuner_ops.set_analog_params(fe, params); 238 fe->ops.tuner_ops.set_analog_params(fe, params);
240 239
241 for (i = 0; i < 3; i++) { 240 for (i = 0; i < 3; i++) {
242 tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); 241 tuner_i2c_xfer_send_recv(&priv->i2c_props,
243 tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); 242 &addr_pll_stat, 1, &pll_stat, 1);
244 if (pll_stat & 0x80) { 243 if (pll_stat & 0x80) {
245 tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); 244 tuner_i2c_xfer_send_recv(&priv->i2c_props,
246 tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); 245 &addr_adc_sat, 1,
247 tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); 246 &adc_sat, 1);
248 tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); 247 tuner_i2c_xfer_send_recv(&priv->i2c_props,
248 &addr_agc_stat, 1,
249 &agc_stat, 1);
249 tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); 250 tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
250 break; 251 break;
251 } else { 252 } else {
@@ -259,20 +260,22 @@ static void tda8290_set_params(struct dvb_frontend *fe,
259 agc_stat, adc_sat, pll_stat & 0x80); 260 agc_stat, adc_sat, pll_stat & 0x80);
260 tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); 261 tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
261 msleep(100); 262 msleep(100);
262 tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); 263 tuner_i2c_xfer_send_recv(&priv->i2c_props,
263 tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); 264 &addr_agc_stat, 1, &agc_stat, 1);
264 tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); 265 tuner_i2c_xfer_send_recv(&priv->i2c_props,
265 tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); 266 &addr_pll_stat, 1, &pll_stat, 1);
266 if ((agc_stat > 115) || !(pll_stat & 0x80)) { 267 if ((agc_stat > 115) || !(pll_stat & 0x80)) {
267 tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", 268 tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
268 agc_stat, pll_stat & 0x80); 269 agc_stat, pll_stat & 0x80);
269 if (priv->cfg.agcf) 270 if (priv->cfg.agcf)
270 priv->cfg.agcf(fe); 271 priv->cfg.agcf(fe);
271 msleep(100); 272 msleep(100);
272 tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); 273 tuner_i2c_xfer_send_recv(&priv->i2c_props,
273 tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); 274 &addr_agc_stat, 1,
274 tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); 275 &agc_stat, 1);
275 tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); 276 tuner_i2c_xfer_send_recv(&priv->i2c_props,
277 &addr_pll_stat, 1,
278 &pll_stat, 1);
276 if((agc_stat > 115) || !(pll_stat & 0x80)) { 279 if((agc_stat > 115) || !(pll_stat & 0x80)) {
277 tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); 280 tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
278 tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); 281 tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
@@ -284,10 +287,12 @@ static void tda8290_set_params(struct dvb_frontend *fe,
284 287
285 /* l/ l' deadlock? */ 288 /* l/ l' deadlock? */
286 if(priv->tda8290_easy_mode & 0x60) { 289 if(priv->tda8290_easy_mode & 0x60) {
287 tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); 290 tuner_i2c_xfer_send_recv(&priv->i2c_props,
288 tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); 291 &addr_adc_sat, 1,
289 tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); 292 &adc_sat, 1);
290 tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); 293 tuner_i2c_xfer_send_recv(&priv->i2c_props,
294 &addr_pll_stat, 1,
295 &pll_stat, 1);
291 if ((adc_sat > 20) || !(pll_stat & 0x80)) { 296 if ((adc_sat > 20) || !(pll_stat & 0x80)) {
292 tuner_dbg("trying to resolve SECAM L deadlock\n"); 297 tuner_dbg("trying to resolve SECAM L deadlock\n");
293 tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); 298 tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
@@ -307,8 +312,7 @@ static void tda8295_power(struct dvb_frontend *fe, int enable)
307 struct tda8290_priv *priv = fe->analog_demod_priv; 312 struct tda8290_priv *priv = fe->analog_demod_priv;
308 unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ 313 unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
309 314
310 tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); 315 tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
311 tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
312 316
313 if (enable) 317 if (enable)
314 buf[1] = 0x01; 318 buf[1] = 0x01;
@@ -323,8 +327,7 @@ static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
323 struct tda8290_priv *priv = fe->analog_demod_priv; 327 struct tda8290_priv *priv = fe->analog_demod_priv;
324 unsigned char buf[] = { 0x01, 0x00 }; 328 unsigned char buf[] = { 0x01, 0x00 };
325 329
326 tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); 330 tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
327 tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
328 331
329 if (enable) 332 if (enable)
330 buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ 333 buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
@@ -353,8 +356,7 @@ static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
353 struct tda8290_priv *priv = fe->analog_demod_priv; 356 struct tda8290_priv *priv = fe->analog_demod_priv;
354 unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ 357 unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
355 358
356 tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); 359 tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
357 tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
358 360
359 if (enable) 361 if (enable)
360 buf[1] &= ~0x40; 362 buf[1] &= ~0x40;
@@ -370,10 +372,10 @@ static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
370 unsigned char set_gpio_cf[] = { 0x44, 0x00 }; 372 unsigned char set_gpio_cf[] = { 0x44, 0x00 };
371 unsigned char set_gpio_val[] = { 0x46, 0x00 }; 373 unsigned char set_gpio_val[] = { 0x46, 0x00 };
372 374
373 tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); 375 tuner_i2c_xfer_send_recv(&priv->i2c_props,
374 tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); 376 &set_gpio_cf[0], 1, &set_gpio_cf[1], 1);
375 tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); 377 tuner_i2c_xfer_send_recv(&priv->i2c_props,
376 tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); 378 &set_gpio_val[0], 1, &set_gpio_val[1], 1);
377 379
378 set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ 380 set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
379 381
@@ -392,8 +394,7 @@ static int tda8295_has_signal(struct dvb_frontend *fe)
392 unsigned char hvpll_stat = 0x26; 394 unsigned char hvpll_stat = 0x26;
393 unsigned char ret; 395 unsigned char ret;
394 396
395 tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); 397 tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
396 tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
397 return (ret & 0x01) ? 65535 : 0; 398 return (ret & 0x01) ? 65535 : 0;
398} 399}
399 400
@@ -413,8 +414,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
413 tda8295_power(fe, 1); 414 tda8295_power(fe, 1);
414 tda8295_agc1_out(fe, 1); 415 tda8295_agc1_out(fe, 1);
415 416
416 tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); 417 tuner_i2c_xfer_send_recv(&priv->i2c_props,
417 tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); 418 &blanking_mode[0], 1, &blanking_mode[1], 1);
418 419
419 tda8295_set_video_std(fe); 420 tda8295_set_video_std(fe);
420 421
@@ -447,8 +448,8 @@ static int tda8290_has_signal(struct dvb_frontend *fe)
447 unsigned char i2c_get_afc[1] = { 0x1B }; 448 unsigned char i2c_get_afc[1] = { 0x1B };
448 unsigned char afc = 0; 449 unsigned char afc = 0;
449 450
450 tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); 451 tuner_i2c_xfer_send_recv(&priv->i2c_props,
451 tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); 452 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
452 return (afc & 0x80)? 65535:0; 453 return (afc & 0x80)? 65535:0;
453} 454}
454 455
@@ -654,20 +655,26 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
654static int tda8290_probe(struct tuner_i2c_props *i2c_props) 655static int tda8290_probe(struct tuner_i2c_props *i2c_props)
655{ 656{
656#define TDA8290_ID 0x89 657#define TDA8290_ID 0x89
657 unsigned char tda8290_id[] = { 0x1f, 0x00 }; 658 u8 reg = 0x1f, id;
659 struct i2c_msg msg_read[] = {
660 { .addr = 0x4b, .flags = 0, .len = 1, .buf = &reg },
661 { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id },
662 };
658 663
659 /* detect tda8290 */ 664 /* detect tda8290 */
660 tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); 665 if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
661 tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); 666 printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n",
667 __func__, reg);
668 return -ENODEV;
669 }
662 670
663 if (tda8290_id[1] == TDA8290_ID) { 671 if (id == TDA8290_ID) {
664 if (debug) 672 if (debug)
665 printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", 673 printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
666 __func__, i2c_adapter_id(i2c_props->adap), 674 __func__, i2c_adapter_id(i2c_props->adap),
667 i2c_props->addr); 675 i2c_props->addr);
668 return 0; 676 return 0;
669 } 677 }
670
671 return -ENODEV; 678 return -ENODEV;
672} 679}
673 680
@@ -675,16 +682,23 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
675{ 682{
676#define TDA8295_ID 0x8a 683#define TDA8295_ID 0x8a
677#define TDA8295C2_ID 0x8b 684#define TDA8295C2_ID 0x8b
678 unsigned char tda8295_id[] = { 0x2f, 0x00 }; 685 u8 reg = 0x2f, id;
686 struct i2c_msg msg_read[] = {
687 { .addr = 0x4b, .flags = 0, .len = 1, .buf = &reg },
688 { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id },
689 };
679 690
680 /* detect tda8295 */ 691 /* detect tda8290 */
681 tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); 692 if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
682 tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); 693 printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n",
694 __func__, reg);
695 return -ENODEV;
696 }
683 697
684 if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { 698 if ((id & 0xfe) == TDA8295_ID) {
685 if (debug) 699 if (debug)
686 printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", 700 printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
687 __func__, (tda8295_id[1] == TDA8295_ID) ? 701 __func__, (id == TDA8295_ID) ?
688 "tda8295c1" : "tda8295c2", 702 "tda8295c1" : "tda8295c2",
689 i2c_adapter_id(i2c_props->adap), 703 i2c_adapter_id(i2c_props->adap),
690 i2c_props->addr); 704 i2c_props->addr);
@@ -809,8 +823,8 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
809 int i; 823 int i;
810 824
811 /* rule out tda9887, which would return the same byte repeatedly */ 825 /* rule out tda9887, which would return the same byte repeatedly */
812 tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); 826 tuner_i2c_xfer_send_recv(&i2c_props,
813 tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); 827 soft_reset, 1, buf, PROBE_BUFFER_SIZE);
814 for (i = 1; i < PROBE_BUFFER_SIZE; i++) { 828 for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
815 if (buf[i] != buf[0]) 829 if (buf[i] != buf[0])
816 break; 830 break;
@@ -827,13 +841,12 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
827 /* fall back to old probing method */ 841 /* fall back to old probing method */
828 tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); 842 tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
829 tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); 843 tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
830 tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); 844 tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1);
831 tuner_i2c_xfer_recv(&i2c_props, &data, 1);
832 if (data == 0) { 845 if (data == 0) {
833 tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); 846 tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
834 tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); 847 tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
835 tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); 848 tuner_i2c_xfer_send_recv(&i2c_props,
836 tuner_i2c_xfer_recv(&i2c_props, &data, 1); 849 &addr_dto_lsb, 1, &data, 1);
837 if (data == 0x7b) { 850 if (data == 0x7b) {
838 return 0; 851 return 0;
839 } 852 }