aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-xc2028.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-09-27 17:27:03 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:01:04 -0500
commit3b20532c791399182bd04f0fcc70b60a95637fa5 (patch)
treed2f9341a91c4cdb0335a7b262a62ea27653fa9ae /drivers/media/video/tuner-xc2028.c
parentff7326d4f09aee7fc0416d3b3d6f7106d0961f1f (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.c40
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
287static int xc2028_signal(struct i2c_client *c) 290static 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
312ret:
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
380ret:
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
501EXPORT_SYMBOL(xc2028_attach); 521EXPORT_SYMBOL(xc2028_attach);
502 522