diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-09-27 17:27:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:01:04 -0500 |
commit | 3b20532c791399182bd04f0fcc70b60a95637fa5 (patch) | |
tree | d2f9341a91c4cdb0335a7b262a62ea27653fa9ae /drivers/media/video/tuner-xc2028.c | |
parent | ff7326d4f09aee7fc0416d3b3d6f7106d0961f1f (diff) |
V4L/DVB (6429): Avoid having two tuner commands happening at the same time
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.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 | ||