diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-13 11:55:39 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-14 11:24:44 -0500 |
commit | dd03e970a18f266faf120e47355349d224f64e3f (patch) | |
tree | b4cc3088f239eaa60c58826f532505178358a339 /drivers/media/video/tvaudio.c | |
parent | af1a9951fc5c89518c25c4d9f2c4b391b2e72b83 (diff) |
V4L/DVB (9617): tvtime: remove generic_checkmode callback
generic_checkmode() were called, via a callback, for some tvaudio chips.
There's just one callback code used on all those boards. So, it makes no
sense on keeping this as a callback.
Since there were some OOPS reported on tvaudio on kerneloops.org, this
patch removes this callback, adding the code at the only place were it
is called: inside chip_tread. A flag were added to indicate the need for
a kernel thread to set stereo mode on cards that needs it.
Using this more direct approach simplifies the code, making it more
robust against human errors.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/tvaudio.c')
-rw-r--r-- | drivers/media/video/tvaudio.c | 71 |
1 files changed, 35 insertions, 36 deletions
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1fa481ca0861..1387c54b7f02 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -58,7 +58,6 @@ typedef int (*checkit)(struct CHIPSTATE*); | |||
58 | typedef int (*initialize)(struct CHIPSTATE*); | 58 | typedef int (*initialize)(struct CHIPSTATE*); |
59 | typedef int (*getmode)(struct CHIPSTATE*); | 59 | typedef int (*getmode)(struct CHIPSTATE*); |
60 | typedef void (*setmode)(struct CHIPSTATE*, int mode); | 60 | typedef void (*setmode)(struct CHIPSTATE*, int mode); |
61 | typedef void (*checkmode)(struct CHIPSTATE*); | ||
62 | 61 | ||
63 | /* i2c command */ | 62 | /* i2c command */ |
64 | typedef struct AUDIOCMD { | 63 | typedef struct AUDIOCMD { |
@@ -79,6 +78,7 @@ struct CHIPDESC { | |||
79 | #define CHIP_HAS_VOLUME 1 | 78 | #define CHIP_HAS_VOLUME 1 |
80 | #define CHIP_HAS_BASSTREBLE 2 | 79 | #define CHIP_HAS_BASSTREBLE 2 |
81 | #define CHIP_HAS_INPUTSEL 4 | 80 | #define CHIP_HAS_INPUTSEL 4 |
81 | #define CHIP_NEED_CHECKMODE 8 | ||
82 | 82 | ||
83 | /* various i2c command sequences */ | 83 | /* various i2c command sequences */ |
84 | audiocmd init; | 84 | audiocmd init; |
@@ -96,9 +96,6 @@ struct CHIPDESC { | |||
96 | getmode getmode; | 96 | getmode getmode; |
97 | setmode setmode; | 97 | setmode setmode; |
98 | 98 | ||
99 | /* check / autoswitch audio after channel switches */ | ||
100 | checkmode checkmode; | ||
101 | |||
102 | /* input switch register + values for v4l inputs */ | 99 | /* input switch register + values for v4l inputs */ |
103 | int inputreg; | 100 | int inputreg; |
104 | int inputmap[4]; | 101 | int inputmap[4]; |
@@ -264,6 +261,7 @@ static int chip_thread(void *data) | |||
264 | { | 261 | { |
265 | struct CHIPSTATE *chip = data; | 262 | struct CHIPSTATE *chip = data; |
266 | struct CHIPDESC *desc = chiplist + chip->type; | 263 | struct CHIPDESC *desc = chiplist + chip->type; |
264 | int mode; | ||
267 | 265 | ||
268 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); | 266 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); |
269 | set_freezable(); | 267 | set_freezable(); |
@@ -282,7 +280,26 @@ static int chip_thread(void *data) | |||
282 | continue; | 280 | continue; |
283 | 281 | ||
284 | /* have a look what's going on */ | 282 | /* have a look what's going on */ |
285 | desc->checkmode(chip); | 283 | mode = desc->getmode(chip); |
284 | if (mode == chip->prevmode) | ||
285 | continue; | ||
286 | |||
287 | /* chip detected a new audio mode - set it */ | ||
288 | v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", | ||
289 | chip->c->name); | ||
290 | |||
291 | chip->prevmode = mode; | ||
292 | |||
293 | if (mode & V4L2_TUNER_MODE_STEREO) | ||
294 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
295 | if (mode & V4L2_TUNER_MODE_LANG1_LANG2) | ||
296 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
297 | else if (mode & V4L2_TUNER_MODE_LANG1) | ||
298 | desc->setmode(chip, V4L2_TUNER_MODE_LANG1); | ||
299 | else if (mode & V4L2_TUNER_MODE_LANG2) | ||
300 | desc->setmode(chip, V4L2_TUNER_MODE_LANG2); | ||
301 | else | ||
302 | desc->setmode(chip, V4L2_TUNER_MODE_MONO); | ||
286 | 303 | ||
287 | /* schedule next check */ | 304 | /* schedule next check */ |
288 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 305 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
@@ -292,29 +309,6 @@ static int chip_thread(void *data) | |||
292 | return 0; | 309 | return 0; |
293 | } | 310 | } |
294 | 311 | ||
295 | static void generic_checkmode(struct CHIPSTATE *chip) | ||
296 | { | ||
297 | struct CHIPDESC *desc = chiplist + chip->type; | ||
298 | int mode = desc->getmode(chip); | ||
299 | |||
300 | if (mode == chip->prevmode) | ||
301 | return; | ||
302 | |||
303 | v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name); | ||
304 | chip->prevmode = mode; | ||
305 | |||
306 | if (mode & V4L2_TUNER_MODE_STEREO) | ||
307 | desc->setmode(chip,V4L2_TUNER_MODE_STEREO); | ||
308 | if (mode & V4L2_TUNER_MODE_LANG1_LANG2) | ||
309 | desc->setmode(chip,V4L2_TUNER_MODE_STEREO); | ||
310 | else if (mode & V4L2_TUNER_MODE_LANG1) | ||
311 | desc->setmode(chip,V4L2_TUNER_MODE_LANG1); | ||
312 | else if (mode & V4L2_TUNER_MODE_LANG2) | ||
313 | desc->setmode(chip,V4L2_TUNER_MODE_LANG2); | ||
314 | else | ||
315 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); | ||
316 | } | ||
317 | |||
318 | /* ---------------------------------------------------------------------- */ | 312 | /* ---------------------------------------------------------------------- */ |
319 | /* audio chip descriptions - defines+functions for tda9840 */ | 313 | /* audio chip descriptions - defines+functions for tda9840 */ |
320 | 314 | ||
@@ -1259,12 +1253,12 @@ static struct CHIPDESC chiplist[] = { | |||
1259 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1253 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
1260 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1254 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
1261 | .registers = 5, | 1255 | .registers = 5, |
1256 | .flags = CHIP_NEED_CHECKMODE, | ||
1262 | 1257 | ||
1263 | /* callbacks */ | 1258 | /* callbacks */ |
1264 | .checkit = tda9840_checkit, | 1259 | .checkit = tda9840_checkit, |
1265 | .getmode = tda9840_getmode, | 1260 | .getmode = tda9840_getmode, |
1266 | .setmode = tda9840_setmode, | 1261 | .setmode = tda9840_setmode, |
1267 | .checkmode = generic_checkmode, | ||
1268 | 1262 | ||
1269 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN | 1263 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN |
1270 | /* ,TDA9840_SW, TDA9840_MONO */} } | 1264 | /* ,TDA9840_SW, TDA9840_MONO */} } |
@@ -1275,13 +1269,12 @@ static struct CHIPDESC chiplist[] = { | |||
1275 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, | 1269 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, |
1276 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, | 1270 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, |
1277 | .registers = 3, | 1271 | .registers = 3, |
1278 | .flags = CHIP_HAS_INPUTSEL, | 1272 | .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE, |
1279 | 1273 | ||
1280 | /* callbacks */ | 1274 | /* callbacks */ |
1281 | .checkit = tda9873_checkit, | 1275 | .checkit = tda9873_checkit, |
1282 | .getmode = tda9873_getmode, | 1276 | .getmode = tda9873_getmode, |
1283 | .setmode = tda9873_setmode, | 1277 | .setmode = tda9873_setmode, |
1284 | .checkmode = generic_checkmode, | ||
1285 | 1278 | ||
1286 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, | 1279 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, |
1287 | .inputreg = TDA9873_SW, | 1280 | .inputreg = TDA9873_SW, |
@@ -1295,13 +1288,13 @@ static struct CHIPDESC chiplist[] = { | |||
1295 | .insmodopt = &tda9874a, | 1288 | .insmodopt = &tda9874a, |
1296 | .addr_lo = I2C_ADDR_TDA9874 >> 1, | 1289 | .addr_lo = I2C_ADDR_TDA9874 >> 1, |
1297 | .addr_hi = I2C_ADDR_TDA9874 >> 1, | 1290 | .addr_hi = I2C_ADDR_TDA9874 >> 1, |
1291 | .flags = CHIP_NEED_CHECKMODE, | ||
1298 | 1292 | ||
1299 | /* callbacks */ | 1293 | /* callbacks */ |
1300 | .initialize = tda9874a_initialize, | 1294 | .initialize = tda9874a_initialize, |
1301 | .checkit = tda9874a_checkit, | 1295 | .checkit = tda9874a_checkit, |
1302 | .getmode = tda9874a_getmode, | 1296 | .getmode = tda9874a_getmode, |
1303 | .setmode = tda9874a_setmode, | 1297 | .setmode = tda9874a_setmode, |
1304 | .checkmode = generic_checkmode, | ||
1305 | }, | 1298 | }, |
1306 | { | 1299 | { |
1307 | .name = "tda9850", | 1300 | .name = "tda9850", |
@@ -1444,11 +1437,11 @@ static struct CHIPDESC chiplist[] = { | |||
1444 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1437 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
1445 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1438 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
1446 | .registers = 2, | 1439 | .registers = 2, |
1440 | .flags = CHIP_NEED_CHECKMODE, | ||
1447 | 1441 | ||
1448 | /* callbacks */ | 1442 | /* callbacks */ |
1449 | .getmode = ta8874z_getmode, | 1443 | .getmode = ta8874z_getmode, |
1450 | .setmode = ta8874z_setmode, | 1444 | .setmode = ta8874z_setmode, |
1451 | .checkmode = generic_checkmode, | ||
1452 | 1445 | ||
1453 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, | 1446 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, |
1454 | }, | 1447 | }, |
@@ -1531,7 +1524,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1531 | } | 1524 | } |
1532 | 1525 | ||
1533 | chip->thread = NULL; | 1526 | chip->thread = NULL; |
1534 | if (desc->checkmode) { | 1527 | if (desc->flags & CHIP_NEED_CHECKMODE) { |
1535 | /* start async thread */ | 1528 | /* start async thread */ |
1536 | init_timer(&chip->wt); | 1529 | init_timer(&chip->wt); |
1537 | chip->wt.function = chip_thread_wake; | 1530 | chip->wt.function = chip_thread_wake; |
@@ -1804,12 +1797,18 @@ static int chip_command(struct i2c_client *client, | |||
1804 | break; | 1797 | break; |
1805 | case VIDIOC_S_FREQUENCY: | 1798 | case VIDIOC_S_FREQUENCY: |
1806 | chip->mode = 0; /* automatic */ | 1799 | chip->mode = 0; /* automatic */ |
1807 | if (desc->checkmode && desc->setmode) { | 1800 | |
1801 | /* For chips that provide getmode, setmode and checkmode, | ||
1802 | a kthread is created to automatically to set the audio | ||
1803 | standard. In this case, start with MONO and wait 2 seconds | ||
1804 | for the decoding to stablize. Then, run kthread to change | ||
1805 | to stereo, if carrier detected. | ||
1806 | */ | ||
1807 | if (chip->thread) { | ||
1808 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); | 1808 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); |
1809 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) | 1809 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) |
1810 | chip->prevmode = -1; /* reset previous mode */ | 1810 | chip->prevmode = -1; /* reset previous mode */ |
1811 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 1811 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
1812 | /* the thread will call checkmode() later */ | ||
1813 | } | 1812 | } |
1814 | break; | 1813 | break; |
1815 | 1814 | ||