aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tvaudio.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-11-13 11:55:39 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-11-14 11:24:44 -0500
commitdd03e970a18f266faf120e47355349d224f64e3f (patch)
treeb4cc3088f239eaa60c58826f532505178358a339 /drivers/media/video/tvaudio.c
parentaf1a9951fc5c89518c25c4d9f2c4b391b2e72b83 (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.c71
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*);
58typedef int (*initialize)(struct CHIPSTATE*); 58typedef int (*initialize)(struct CHIPSTATE*);
59typedef int (*getmode)(struct CHIPSTATE*); 59typedef int (*getmode)(struct CHIPSTATE*);
60typedef void (*setmode)(struct CHIPSTATE*, int mode); 60typedef void (*setmode)(struct CHIPSTATE*, int mode);
61typedef void (*checkmode)(struct CHIPSTATE*);
62 61
63/* i2c command */ 62/* i2c command */
64typedef struct AUDIOCMD { 63typedef 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
295static 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