diff options
| -rw-r--r-- | drivers/media/video/tuner-xc2028.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 78e83700a13c..0e68002a4a04 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/videodev.h> | 12 | #include <linux/videodev.h> |
| 13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 14 | #include <media/tuner.h> | 14 | #include <media/tuner.h> |
| 15 | #include <linux/mutex.h> | ||
| 15 | #include "tuner-driver.h" | 16 | #include "tuner-driver.h" |
| 16 | #include "tuner-xc2028.h" | 17 | #include "tuner-xc2028.h" |
| 17 | 18 | ||
| @@ -47,6 +48,8 @@ struct xc2028_data { | |||
| 47 | were loaded? */ | 48 | were loaded? */ |
| 48 | enum tuner_mode mode; | 49 | enum tuner_mode mode; |
| 49 | struct i2c_client *i2c_client; | 50 | struct i2c_client *i2c_client; |
| 51 | |||
| 52 | struct mutex lock; | ||
| 50 | }; | 53 | }; |
| 51 | 54 | ||
| 52 | #define i2c_send(rc,c,buf,size) \ | 55 | #define i2c_send(rc,c,buf,size) \ |
| @@ -286,20 +289,28 @@ static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode, | |||
| 286 | 289 | ||
| 287 | static int xc2028_signal(struct i2c_client *c) | 290 | static int xc2028_signal(struct i2c_client *c) |
| 288 | { | 291 | { |
| 289 | int lock, signal; | 292 | struct tuner *t = i2c_get_clientdata(c); |
| 293 | struct xc2028_data *xc2028 = t->priv; | ||
| 294 | int frq_lock, signal=0; | ||
| 295 | |||
| 296 | mutex_lock(&xc2028->lock); | ||
| 290 | 297 | ||
| 291 | printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); | 298 | printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__); |
| 292 | 299 | ||
| 293 | lock = xc2028_get_reg(c, 0x2); | 300 | frq_lock = xc2028_get_reg(c, 0x2); |
| 294 | if (lock<=0) | 301 | if (frq_lock<=0) |
| 295 | return lock; | 302 | goto ret; |
| 296 | 303 | ||
| 297 | /* Frequency is locked. Return signal quality */ | 304 | /* Frequency is locked. Return signal quality */ |
| 298 | 305 | ||
| 299 | signal = xc2028_get_reg(c, 0x40); | 306 | signal = xc2028_get_reg(c, 0x40); |
| 300 | 307 | ||
| 301 | if(signal<=0) | 308 | if(signal<=0) { |
| 302 | return lock; | 309 | signal=frq_lock; |
| 310 | } | ||
| 311 | |||
| 312 | ret: | ||
| 313 | mutex_unlock(&xc2028->lock); | ||
| 303 | 314 | ||
| 304 | return signal; | 315 | return signal; |
| 305 | } | 316 | } |
| @@ -318,6 +329,8 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, | |||
| 318 | when freq is changed */ | 329 | when freq is changed */ |
| 319 | struct xc2028_data *xc2028 = t->priv; | 330 | struct xc2028_data *xc2028 = t->priv; |
| 320 | 331 | ||
| 332 | mutex_lock(&xc2028->lock); | ||
| 333 | |||
| 321 | xc2028->firm_type=0; | 334 | xc2028->firm_type=0; |
| 322 | 335 | ||
| 323 | /* Reset GPIO 1 */ | 336 | /* Reset GPIO 1 */ |
| @@ -325,13 +338,13 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, | |||
| 325 | rc = t->tuner_callback( c->adapter->algo_data, | 338 | rc = t->tuner_callback( c->adapter->algo_data, |
| 326 | XC2028_TUNER_RESET, 0); | 339 | XC2028_TUNER_RESET, 0); |
| 327 | if (rc<0) | 340 | if (rc<0) |
| 328 | return; | 341 | goto ret; |
| 329 | } | 342 | } |
| 330 | msleep(10); | 343 | msleep(10); |
| 331 | printk("xc3028: should set frequency %d kHz)\n", freq / 1000); | 344 | printk("xc3028: should set frequency %d kHz)\n", freq / 1000); |
| 332 | 345 | ||
| 333 | if (check_firmware(c, new_mode, bandwidth)<0) | 346 | if (check_firmware(c, new_mode, bandwidth)<0) |
| 334 | return; | 347 | goto ret; |
| 335 | 348 | ||
| 336 | if(new_mode == T_DIGITAL_TV) | 349 | if(new_mode == T_DIGITAL_TV) |
| 337 | offset = 2750000; | 350 | offset = 2750000; |
| @@ -344,7 +357,7 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, | |||
| 344 | rc = t->tuner_callback( c->adapter->algo_data, | 357 | rc = t->tuner_callback( c->adapter->algo_data, |
| 345 | XC2028_RESET_CLK, 1); | 358 | XC2028_RESET_CLK, 1); |
| 346 | if (rc<0) | 359 | if (rc<0) |
| 347 | return; | 360 | goto ret; |
| 348 | } | 361 | } |
| 349 | 362 | ||
| 350 | msleep(10); | 363 | msleep(10); |
| @@ -357,12 +370,15 @@ static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */, | |||
| 357 | 370 | ||
| 358 | i2c_send(rc, c, buf, sizeof(buf)); | 371 | i2c_send(rc, c, buf, sizeof(buf)); |
| 359 | if (rc<0) | 372 | if (rc<0) |
| 360 | return; | 373 | goto ret; |
| 361 | msleep(100); | 374 | msleep(100); |
| 362 | 375 | ||
| 363 | printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", | 376 | printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n", |
| 364 | buf[1],buf[2],buf[3],buf[4], | 377 | buf[1],buf[2],buf[3],buf[4], |
| 365 | freq / 16, freq % 16 * 100 / 16); | 378 | freq / 16, freq % 16 * 100 / 16); |
| 379 | |||
| 380 | ret: | ||
| 381 | mutex_unlock(&xc2028->lock); | ||
| 366 | } | 382 | } |
| 367 | 383 | ||
| 368 | 384 | ||
| @@ -416,6 +432,8 @@ int xc2028_tuner_init(struct i2c_client *c) | |||
| 416 | xc2028->need_load_generic=1; | 432 | xc2028->need_load_generic=1; |
| 417 | xc2028->mode = T_UNINITIALIZED; | 433 | xc2028->mode = T_UNINITIALIZED; |
| 418 | 434 | ||
| 435 | mutex_init(&xc2028->lock); | ||
| 436 | |||
| 419 | /* FIXME: Check where t->priv will be freed */ | 437 | /* FIXME: Check where t->priv will be freed */ |
| 420 | 438 | ||
| 421 | if (version<0) | 439 | if (version<0) |
| @@ -498,5 +516,7 @@ int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe) | |||
| 498 | return 0; | 516 | return 0; |
| 499 | } | 517 | } |
| 500 | 518 | ||
| 519 | |||
| 520 | |||
| 501 | EXPORT_SYMBOL(xc2028_attach); | 521 | EXPORT_SYMBOL(xc2028_attach); |
| 502 | 522 | ||
