diff options
Diffstat (limited to 'drivers/media/video/tvaudio.c')
| -rw-r--r-- | drivers/media/video/tvaudio.c | 231 |
1 files changed, 149 insertions, 82 deletions
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index b59e47272ab..3720f0e03a1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * experimental driver for simple i2c audio chips. | 2 | * Driver for simple i2c audio chips. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000 Gerd Knorr | 4 | * Copyright (c) 2000 Gerd Knorr |
| 5 | * based on code by: | 5 | * based on code by: |
| @@ -7,6 +7,10 @@ | |||
| 7 | * Steve VanDeBogart (vandebo@uclink.berkeley.edu) | 7 | * Steve VanDeBogart (vandebo@uclink.berkeley.edu) |
| 8 | * Greg Alexander (galexand@acm.org) | 8 | * Greg Alexander (galexand@acm.org) |
| 9 | * | 9 | * |
| 10 | * Copyright(c) 2005-2008 Mauro Carvalho Chehab | ||
| 11 | * - Some cleanups, code fixes, etc | ||
| 12 | * - Convert it to V4L2 API | ||
| 13 | * | ||
| 10 | * This code is placed under the terms of the GNU General Public License | 14 | * This code is placed under the terms of the GNU General Public License |
| 11 | * | 15 | * |
| 12 | * OPTIONS: | 16 | * OPTIONS: |
| @@ -30,6 +34,7 @@ | |||
| 30 | 34 | ||
| 31 | #include <media/tvaudio.h> | 35 | #include <media/tvaudio.h> |
| 32 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 37 | #include <media/v4l2-ioctl.h> | ||
| 33 | #include <media/v4l2-chip-ident.h> | 38 | #include <media/v4l2-chip-ident.h> |
| 34 | #include <media/v4l2-i2c-drv-legacy.h> | 39 | #include <media/v4l2-i2c-drv-legacy.h> |
| 35 | 40 | ||
| @@ -58,7 +63,6 @@ typedef int (*checkit)(struct CHIPSTATE*); | |||
| 58 | typedef int (*initialize)(struct CHIPSTATE*); | 63 | typedef int (*initialize)(struct CHIPSTATE*); |
| 59 | typedef int (*getmode)(struct CHIPSTATE*); | 64 | typedef int (*getmode)(struct CHIPSTATE*); |
| 60 | typedef void (*setmode)(struct CHIPSTATE*, int mode); | 65 | typedef void (*setmode)(struct CHIPSTATE*, int mode); |
| 61 | typedef void (*checkmode)(struct CHIPSTATE*); | ||
| 62 | 66 | ||
| 63 | /* i2c command */ | 67 | /* i2c command */ |
| 64 | typedef struct AUDIOCMD { | 68 | typedef struct AUDIOCMD { |
| @@ -79,6 +83,7 @@ struct CHIPDESC { | |||
| 79 | #define CHIP_HAS_VOLUME 1 | 83 | #define CHIP_HAS_VOLUME 1 |
| 80 | #define CHIP_HAS_BASSTREBLE 2 | 84 | #define CHIP_HAS_BASSTREBLE 2 |
| 81 | #define CHIP_HAS_INPUTSEL 4 | 85 | #define CHIP_HAS_INPUTSEL 4 |
| 86 | #define CHIP_NEED_CHECKMODE 8 | ||
| 82 | 87 | ||
| 83 | /* various i2c command sequences */ | 88 | /* various i2c command sequences */ |
| 84 | audiocmd init; | 89 | audiocmd init; |
| @@ -96,23 +101,20 @@ struct CHIPDESC { | |||
| 96 | getmode getmode; | 101 | getmode getmode; |
| 97 | setmode setmode; | 102 | setmode setmode; |
| 98 | 103 | ||
| 99 | /* check / autoswitch audio after channel switches */ | ||
| 100 | checkmode checkmode; | ||
| 101 | |||
| 102 | /* input switch register + values for v4l inputs */ | 104 | /* input switch register + values for v4l inputs */ |
| 103 | int inputreg; | 105 | int inputreg; |
| 104 | int inputmap[4]; | 106 | int inputmap[4]; |
| 105 | int inputmute; | 107 | int inputmute; |
| 106 | int inputmask; | 108 | int inputmask; |
| 107 | }; | 109 | }; |
| 108 | static struct CHIPDESC chiplist[]; | ||
| 109 | 110 | ||
| 110 | /* current state of the chip */ | 111 | /* current state of the chip */ |
| 111 | struct CHIPSTATE { | 112 | struct CHIPSTATE { |
| 112 | struct i2c_client *c; | 113 | struct i2c_client *c; |
| 113 | 114 | ||
| 114 | /* index into CHIPDESC array */ | 115 | /* chip-specific description - should point to |
| 115 | int type; | 116 | an entry at CHIPDESC table */ |
| 117 | struct CHIPDESC *desc; | ||
| 116 | 118 | ||
| 117 | /* shadow register set */ | 119 | /* shadow register set */ |
| 118 | audiocmd shadow; | 120 | audiocmd shadow; |
| @@ -152,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 152 | { | 154 | { |
| 153 | unsigned char buffer[2]; | 155 | unsigned char buffer[2]; |
| 154 | 156 | ||
| 155 | if (-1 == subaddr) { | 157 | if (subaddr < 0) { |
| 156 | v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", | 158 | v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", |
| 157 | chip->c->name, val); | 159 | chip->c->name, val); |
| 158 | chip->shadow.bytes[1] = val; | 160 | chip->shadow.bytes[1] = val; |
| @@ -163,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 163 | return -1; | 165 | return -1; |
| 164 | } | 166 | } |
| 165 | } else { | 167 | } else { |
| 168 | if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 169 | v4l_info(chip->c, | ||
| 170 | "Tried to access a non-existent register: %d\n", | ||
| 171 | subaddr); | ||
| 172 | return -EINVAL; | ||
| 173 | } | ||
| 174 | |||
| 166 | v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", | 175 | v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", |
| 167 | chip->c->name, subaddr, val); | 176 | chip->c->name, subaddr, val); |
| 168 | chip->shadow.bytes[subaddr+1] = val; | 177 | chip->shadow.bytes[subaddr+1] = val; |
| @@ -177,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 177 | return 0; | 186 | return 0; |
| 178 | } | 187 | } |
| 179 | 188 | ||
| 180 | static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) | 189 | static int chip_write_masked(struct CHIPSTATE *chip, |
| 190 | int subaddr, int val, int mask) | ||
| 181 | { | 191 | { |
| 182 | if (mask != 0) { | 192 | if (mask != 0) { |
| 183 | if (-1 == subaddr) { | 193 | if (subaddr < 0) { |
| 184 | val = (chip->shadow.bytes[1] & ~mask) | (val & mask); | 194 | val = (chip->shadow.bytes[1] & ~mask) | (val & mask); |
| 185 | } else { | 195 | } else { |
| 196 | if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 197 | v4l_info(chip->c, | ||
| 198 | "Tried to access a non-existent register: %d\n", | ||
| 199 | subaddr); | ||
| 200 | return -EINVAL; | ||
| 201 | } | ||
| 202 | |||
| 186 | val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); | 203 | val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); |
| 187 | } | 204 | } |
| 188 | } | 205 | } |
| @@ -228,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) | |||
| 228 | if (0 == cmd->count) | 245 | if (0 == cmd->count) |
| 229 | return 0; | 246 | return 0; |
| 230 | 247 | ||
| 248 | if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 249 | v4l_info(chip->c, | ||
| 250 | "Tried to access a non-existent register range: %d to %d\n", | ||
| 251 | cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* FIXME: it seems that the shadow bytes are wrong bellow !*/ | ||
| 256 | |||
| 231 | /* update our shadow register set; print bytes if (debug > 0) */ | 257 | /* update our shadow register set; print bytes if (debug > 0) */ |
| 232 | v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", | 258 | v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", |
| 233 | chip->c->name, name,cmd->bytes[0]); | 259 | chip->c->name, name,cmd->bytes[0]); |
| @@ -263,7 +289,8 @@ static void chip_thread_wake(unsigned long data) | |||
| 263 | static int chip_thread(void *data) | 289 | static int chip_thread(void *data) |
| 264 | { | 290 | { |
| 265 | struct CHIPSTATE *chip = data; | 291 | struct CHIPSTATE *chip = data; |
| 266 | struct CHIPDESC *desc = chiplist + chip->type; | 292 | struct CHIPDESC *desc = chip->desc; |
| 293 | int mode; | ||
| 267 | 294 | ||
| 268 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); | 295 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); |
| 269 | set_freezable(); | 296 | set_freezable(); |
| @@ -282,7 +309,26 @@ static int chip_thread(void *data) | |||
| 282 | continue; | 309 | continue; |
| 283 | 310 | ||
| 284 | /* have a look what's going on */ | 311 | /* have a look what's going on */ |
| 285 | desc->checkmode(chip); | 312 | mode = desc->getmode(chip); |
| 313 | if (mode == chip->prevmode) | ||
| 314 | continue; | ||
| 315 | |||
| 316 | /* chip detected a new audio mode - set it */ | ||
| 317 | v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", | ||
| 318 | chip->c->name); | ||
| 319 | |||
| 320 | chip->prevmode = mode; | ||
| 321 | |||
| 322 | if (mode & V4L2_TUNER_MODE_STEREO) | ||
| 323 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
| 324 | if (mode & V4L2_TUNER_MODE_LANG1_LANG2) | ||
| 325 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
| 326 | else if (mode & V4L2_TUNER_MODE_LANG1) | ||
| 327 | desc->setmode(chip, V4L2_TUNER_MODE_LANG1); | ||
| 328 | else if (mode & V4L2_TUNER_MODE_LANG2) | ||
| 329 | desc->setmode(chip, V4L2_TUNER_MODE_LANG2); | ||
| 330 | else | ||
| 331 | desc->setmode(chip, V4L2_TUNER_MODE_MONO); | ||
| 286 | 332 | ||
| 287 | /* schedule next check */ | 333 | /* schedule next check */ |
| 288 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 334 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
| @@ -292,29 +338,6 @@ static int chip_thread(void *data) | |||
| 292 | return 0; | 338 | return 0; |
| 293 | } | 339 | } |
| 294 | 340 | ||
| 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 | /* ---------------------------------------------------------------------- */ | 341 | /* ---------------------------------------------------------------------- */ |
| 319 | /* audio chip descriptions - defines+functions for tda9840 */ | 342 | /* audio chip descriptions - defines+functions for tda9840 */ |
| 320 | 343 | ||
| @@ -777,7 +800,7 @@ static struct tda9874a_MODES { | |||
| 777 | char *name; | 800 | char *name; |
| 778 | audiocmd cmd; | 801 | audiocmd cmd; |
| 779 | } tda9874a_modelist[9] = { | 802 | } tda9874a_modelist[9] = { |
| 780 | { "A2, B/G", | 803 | { "A2, B/G", /* default */ |
| 781 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, | 804 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, |
| 782 | { "A2, M (Korea)", | 805 | { "A2, M (Korea)", |
| 783 | { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, | 806 | { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, |
| @@ -791,7 +814,7 @@ static struct tda9874a_MODES { | |||
| 791 | { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, | 814 | { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, |
| 792 | { "NICAM, B/G", | 815 | { "NICAM, B/G", |
| 793 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, | 816 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, |
| 794 | { "NICAM, D/K", /* default */ | 817 | { "NICAM, D/K", |
| 795 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, | 818 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, |
| 796 | { "NICAM, L", | 819 | { "NICAM, L", |
| 797 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } | 820 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } |
| @@ -981,7 +1004,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) | |||
| 981 | { | 1004 | { |
| 982 | if (tda9874a_SIF > 2) | 1005 | if (tda9874a_SIF > 2) |
| 983 | tda9874a_SIF = 1; | 1006 | tda9874a_SIF = 1; |
| 984 | if (tda9874a_STD > 8) | 1007 | if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist)) |
| 985 | tda9874a_STD = 0; | 1008 | tda9874a_STD = 0; |
| 986 | if(tda9874a_AMSEL > 1) | 1009 | if(tda9874a_AMSEL > 1) |
| 987 | tda9874a_AMSEL = 0; | 1010 | tda9874a_AMSEL = 0; |
| @@ -1089,7 +1112,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } | |||
| 1089 | 1112 | ||
| 1090 | static int tda8425_initialize(struct CHIPSTATE *chip) | 1113 | static int tda8425_initialize(struct CHIPSTATE *chip) |
| 1091 | { | 1114 | { |
| 1092 | struct CHIPDESC *desc = chiplist + chip->type; | 1115 | struct CHIPDESC *desc = chip->desc; |
| 1093 | int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, | 1116 | int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, |
| 1094 | /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; | 1117 | /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; |
| 1095 | 1118 | ||
| @@ -1259,27 +1282,28 @@ static struct CHIPDESC chiplist[] = { | |||
| 1259 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1282 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
| 1260 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1283 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
| 1261 | .registers = 5, | 1284 | .registers = 5, |
| 1285 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1262 | 1286 | ||
| 1287 | /* callbacks */ | ||
| 1263 | .checkit = tda9840_checkit, | 1288 | .checkit = tda9840_checkit, |
| 1264 | .getmode = tda9840_getmode, | 1289 | .getmode = tda9840_getmode, |
| 1265 | .setmode = tda9840_setmode, | 1290 | .setmode = tda9840_setmode, |
| 1266 | .checkmode = generic_checkmode, | ||
| 1267 | 1291 | ||
| 1268 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN | 1292 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN |
| 1269 | /* ,TDA9840_SW, TDA9840_MONO */} } | 1293 | /* ,TDA9840_SW, TDA9840_MONO */} } |
| 1270 | }, | 1294 | }, |
| 1271 | { | 1295 | { |
| 1272 | .name = "tda9873h", | 1296 | .name = "tda9873h", |
| 1273 | .checkit = tda9873_checkit, | ||
| 1274 | .insmodopt = &tda9873, | 1297 | .insmodopt = &tda9873, |
| 1275 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, | 1298 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, |
| 1276 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, | 1299 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, |
| 1277 | .registers = 3, | 1300 | .registers = 3, |
| 1278 | .flags = CHIP_HAS_INPUTSEL, | 1301 | .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE, |
| 1279 | 1302 | ||
| 1303 | /* callbacks */ | ||
| 1304 | .checkit = tda9873_checkit, | ||
| 1280 | .getmode = tda9873_getmode, | 1305 | .getmode = tda9873_getmode, |
| 1281 | .setmode = tda9873_setmode, | 1306 | .setmode = tda9873_setmode, |
| 1282 | .checkmode = generic_checkmode, | ||
| 1283 | 1307 | ||
| 1284 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, | 1308 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, |
| 1285 | .inputreg = TDA9873_SW, | 1309 | .inputreg = TDA9873_SW, |
| @@ -1290,15 +1314,16 @@ static struct CHIPDESC chiplist[] = { | |||
| 1290 | }, | 1314 | }, |
| 1291 | { | 1315 | { |
| 1292 | .name = "tda9874h/a", | 1316 | .name = "tda9874h/a", |
| 1293 | .checkit = tda9874a_checkit, | ||
| 1294 | .initialize = tda9874a_initialize, | ||
| 1295 | .insmodopt = &tda9874a, | 1317 | .insmodopt = &tda9874a, |
| 1296 | .addr_lo = I2C_ADDR_TDA9874 >> 1, | 1318 | .addr_lo = I2C_ADDR_TDA9874 >> 1, |
| 1297 | .addr_hi = I2C_ADDR_TDA9874 >> 1, | 1319 | .addr_hi = I2C_ADDR_TDA9874 >> 1, |
| 1320 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1298 | 1321 | ||
| 1322 | /* callbacks */ | ||
| 1323 | .initialize = tda9874a_initialize, | ||
| 1324 | .checkit = tda9874a_checkit, | ||
| 1299 | .getmode = tda9874a_getmode, | 1325 | .getmode = tda9874a_getmode, |
| 1300 | .setmode = tda9874a_setmode, | 1326 | .setmode = tda9874a_setmode, |
| 1301 | .checkmode = generic_checkmode, | ||
| 1302 | }, | 1327 | }, |
| 1303 | { | 1328 | { |
| 1304 | .name = "tda9850", | 1329 | .name = "tda9850", |
| @@ -1324,10 +1349,11 @@ static struct CHIPDESC chiplist[] = { | |||
| 1324 | .rightreg = TDA9855_VR, | 1349 | .rightreg = TDA9855_VR, |
| 1325 | .bassreg = TDA9855_BA, | 1350 | .bassreg = TDA9855_BA, |
| 1326 | .treblereg = TDA9855_TR, | 1351 | .treblereg = TDA9855_TR, |
| 1352 | |||
| 1353 | /* callbacks */ | ||
| 1327 | .volfunc = tda9855_volume, | 1354 | .volfunc = tda9855_volume, |
| 1328 | .bassfunc = tda9855_bass, | 1355 | .bassfunc = tda9855_bass, |
| 1329 | .treblefunc = tda9855_treble, | 1356 | .treblefunc = tda9855_treble, |
| 1330 | |||
| 1331 | .getmode = tda985x_getmode, | 1357 | .getmode = tda985x_getmode, |
| 1332 | .setmode = tda985x_setmode, | 1358 | .setmode = tda985x_setmode, |
| 1333 | 1359 | ||
| @@ -1348,6 +1374,8 @@ static struct CHIPDESC chiplist[] = { | |||
| 1348 | .rightreg = TEA6300_VL, | 1374 | .rightreg = TEA6300_VL, |
| 1349 | .bassreg = TEA6300_BA, | 1375 | .bassreg = TEA6300_BA, |
| 1350 | .treblereg = TEA6300_TR, | 1376 | .treblereg = TEA6300_TR, |
| 1377 | |||
| 1378 | /* callbacks */ | ||
| 1351 | .volfunc = tea6300_shift10, | 1379 | .volfunc = tea6300_shift10, |
| 1352 | .bassfunc = tea6300_shift12, | 1380 | .bassfunc = tea6300_shift12, |
| 1353 | .treblefunc = tea6300_shift12, | 1381 | .treblefunc = tea6300_shift12, |
| @@ -1358,7 +1386,6 @@ static struct CHIPDESC chiplist[] = { | |||
| 1358 | }, | 1386 | }, |
| 1359 | { | 1387 | { |
| 1360 | .name = "tea6320", | 1388 | .name = "tea6320", |
| 1361 | .initialize = tea6320_initialize, | ||
| 1362 | .insmodopt = &tea6320, | 1389 | .insmodopt = &tea6320, |
| 1363 | .addr_lo = I2C_ADDR_TEA6300 >> 1, | 1390 | .addr_lo = I2C_ADDR_TEA6300 >> 1, |
| 1364 | .addr_hi = I2C_ADDR_TEA6300 >> 1, | 1391 | .addr_hi = I2C_ADDR_TEA6300 >> 1, |
| @@ -1369,6 +1396,9 @@ static struct CHIPDESC chiplist[] = { | |||
| 1369 | .rightreg = TEA6320_V, | 1396 | .rightreg = TEA6320_V, |
| 1370 | .bassreg = TEA6320_BA, | 1397 | .bassreg = TEA6320_BA, |
| 1371 | .treblereg = TEA6320_TR, | 1398 | .treblereg = TEA6320_TR, |
| 1399 | |||
| 1400 | /* callbacks */ | ||
| 1401 | .initialize = tea6320_initialize, | ||
| 1372 | .volfunc = tea6320_volume, | 1402 | .volfunc = tea6320_volume, |
| 1373 | .bassfunc = tea6320_shift11, | 1403 | .bassfunc = tea6320_shift11, |
| 1374 | .treblefunc = tea6320_shift11, | 1404 | .treblefunc = tea6320_shift11, |
| @@ -1401,16 +1431,18 @@ static struct CHIPDESC chiplist[] = { | |||
| 1401 | .rightreg = TDA8425_VR, | 1431 | .rightreg = TDA8425_VR, |
| 1402 | .bassreg = TDA8425_BA, | 1432 | .bassreg = TDA8425_BA, |
| 1403 | .treblereg = TDA8425_TR, | 1433 | .treblereg = TDA8425_TR, |
| 1434 | |||
| 1435 | /* callbacks */ | ||
| 1436 | .initialize = tda8425_initialize, | ||
| 1404 | .volfunc = tda8425_shift10, | 1437 | .volfunc = tda8425_shift10, |
| 1405 | .bassfunc = tda8425_shift12, | 1438 | .bassfunc = tda8425_shift12, |
| 1406 | .treblefunc = tda8425_shift12, | 1439 | .treblefunc = tda8425_shift12, |
| 1440 | .setmode = tda8425_setmode, | ||
| 1407 | 1441 | ||
| 1408 | .inputreg = TDA8425_S1, | 1442 | .inputreg = TDA8425_S1, |
| 1409 | .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, | 1443 | .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, |
| 1410 | .inputmute = TDA8425_S1_OFF, | 1444 | .inputmute = TDA8425_S1_OFF, |
| 1411 | 1445 | ||
| 1412 | .setmode = tda8425_setmode, | ||
| 1413 | .initialize = tda8425_initialize, | ||
| 1414 | }, | 1446 | }, |
| 1415 | { | 1447 | { |
| 1416 | .name = "pic16c54 (PV951)", | 1448 | .name = "pic16c54 (PV951)", |
| @@ -1434,10 +1466,11 @@ static struct CHIPDESC chiplist[] = { | |||
| 1434 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1466 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
| 1435 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1467 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
| 1436 | .registers = 2, | 1468 | .registers = 2, |
| 1469 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1437 | 1470 | ||
| 1471 | /* callbacks */ | ||
| 1438 | .getmode = ta8874z_getmode, | 1472 | .getmode = ta8874z_getmode, |
| 1439 | .setmode = ta8874z_setmode, | 1473 | .setmode = ta8874z_setmode, |
| 1440 | .checkmode = generic_checkmode, | ||
| 1441 | 1474 | ||
| 1442 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, | 1475 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, |
| 1443 | }, | 1476 | }, |
| @@ -1481,6 +1514,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1481 | } | 1514 | } |
| 1482 | if (desc->name == NULL) { | 1515 | if (desc->name == NULL) { |
| 1483 | v4l_dbg(1, debug, client, "no matching chip description found\n"); | 1516 | v4l_dbg(1, debug, client, "no matching chip description found\n"); |
| 1517 | kfree(chip); | ||
| 1484 | return -EIO; | 1518 | return -EIO; |
| 1485 | } | 1519 | } |
| 1486 | v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); | 1520 | v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); |
| @@ -1494,7 +1528,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1494 | /* fill required data structures */ | 1528 | /* fill required data structures */ |
| 1495 | if (!id) | 1529 | if (!id) |
| 1496 | strlcpy(client->name, desc->name, I2C_NAME_SIZE); | 1530 | strlcpy(client->name, desc->name, I2C_NAME_SIZE); |
| 1497 | chip->type = desc-chiplist; | 1531 | chip->desc = desc; |
| 1498 | chip->shadow.count = desc->registers+1; | 1532 | chip->shadow.count = desc->registers+1; |
| 1499 | chip->prevmode = -1; | 1533 | chip->prevmode = -1; |
| 1500 | chip->audmode = V4L2_TUNER_MODE_LANG1; | 1534 | chip->audmode = V4L2_TUNER_MODE_LANG1; |
| @@ -1506,20 +1540,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1506 | chip_cmd(chip,"init",&desc->init); | 1540 | chip_cmd(chip,"init",&desc->init); |
| 1507 | 1541 | ||
| 1508 | if (desc->flags & CHIP_HAS_VOLUME) { | 1542 | if (desc->flags & CHIP_HAS_VOLUME) { |
| 1509 | chip->left = desc->leftinit ? desc->leftinit : 65535; | 1543 | if (!desc->volfunc) { |
| 1510 | chip->right = desc->rightinit ? desc->rightinit : 65535; | 1544 | /* This shouldn't be happen. Warn user, but keep working |
| 1511 | chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); | 1545 | without volume controls |
| 1512 | chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); | 1546 | */ |
| 1547 | v4l_info(chip->c, "volume callback undefined!\n"); | ||
| 1548 | desc->flags &= ~CHIP_HAS_VOLUME; | ||
| 1549 | } else { | ||
| 1550 | chip->left = desc->leftinit ? desc->leftinit : 65535; | ||
| 1551 | chip->right = desc->rightinit ? desc->rightinit : 65535; | ||
| 1552 | chip_write(chip, desc->leftreg, | ||
| 1553 | desc->volfunc(chip->left)); | ||
| 1554 | chip_write(chip, desc->rightreg, | ||
| 1555 | desc->volfunc(chip->right)); | ||
| 1556 | } | ||
| 1513 | } | 1557 | } |
| 1514 | if (desc->flags & CHIP_HAS_BASSTREBLE) { | 1558 | if (desc->flags & CHIP_HAS_BASSTREBLE) { |
| 1515 | chip->treble = desc->trebleinit ? desc->trebleinit : 32768; | 1559 | if (!desc->bassfunc || !desc->treblefunc) { |
| 1516 | chip->bass = desc->bassinit ? desc->bassinit : 32768; | 1560 | /* This shouldn't be happen. Warn user, but keep working |
| 1517 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); | 1561 | without bass/treble controls |
| 1518 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); | 1562 | */ |
| 1563 | v4l_info(chip->c, "bass/treble callbacks undefined!\n"); | ||
| 1564 | desc->flags &= ~CHIP_HAS_BASSTREBLE; | ||
| 1565 | } else { | ||
| 1566 | chip->treble = desc->trebleinit ? | ||
| 1567 | desc->trebleinit : 32768; | ||
| 1568 | chip->bass = desc->bassinit ? | ||
| 1569 | desc->bassinit : 32768; | ||
| 1570 | chip_write(chip, desc->bassreg, | ||
| 1571 | desc->bassfunc(chip->bass)); | ||
| 1572 | chip_write(chip, desc->treblereg, | ||
| 1573 | desc->treblefunc(chip->treble)); | ||
| 1574 | } | ||
| 1519 | } | 1575 | } |
| 1520 | 1576 | ||
| 1521 | chip->thread = NULL; | 1577 | chip->thread = NULL; |
| 1522 | if (desc->checkmode) { | 1578 | if (desc->flags & CHIP_NEED_CHECKMODE) { |
| 1579 | if (!desc->getmode || !desc->setmode) { | ||
| 1580 | /* This shouldn't be happen. Warn user, but keep working | ||
| 1581 | without kthread | ||
| 1582 | */ | ||
| 1583 | v4l_info(chip->c, "set/get mode callbacks undefined!\n"); | ||
| 1584 | return 0; | ||
| 1585 | } | ||
| 1523 | /* start async thread */ | 1586 | /* start async thread */ |
| 1524 | init_timer(&chip->wt); | 1587 | init_timer(&chip->wt); |
| 1525 | chip->wt.function = chip_thread_wake; | 1588 | chip->wt.function = chip_thread_wake; |
| @@ -1552,7 +1615,7 @@ static int chip_remove(struct i2c_client *client) | |||
| 1552 | static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | 1615 | static int tvaudio_get_ctrl(struct CHIPSTATE *chip, |
| 1553 | struct v4l2_control *ctrl) | 1616 | struct v4l2_control *ctrl) |
| 1554 | { | 1617 | { |
| 1555 | struct CHIPDESC *desc = chiplist + chip->type; | 1618 | struct CHIPDESC *desc = chip->desc; |
| 1556 | 1619 | ||
| 1557 | switch (ctrl->id) { | 1620 | switch (ctrl->id) { |
| 1558 | case V4L2_CID_AUDIO_MUTE: | 1621 | case V4L2_CID_AUDIO_MUTE: |
| @@ -1576,13 +1639,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | |||
| 1576 | return 0; | 1639 | return 0; |
| 1577 | } | 1640 | } |
| 1578 | case V4L2_CID_AUDIO_BASS: | 1641 | case V4L2_CID_AUDIO_BASS: |
| 1579 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1642 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1580 | break; | 1643 | break; |
| 1581 | ctrl->value = chip->bass; | 1644 | ctrl->value = chip->bass; |
| 1582 | return 0; | 1645 | return 0; |
| 1583 | case V4L2_CID_AUDIO_TREBLE: | 1646 | case V4L2_CID_AUDIO_TREBLE: |
| 1584 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1647 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1585 | return -EINVAL; | 1648 | break; |
| 1586 | ctrl->value = chip->treble; | 1649 | ctrl->value = chip->treble; |
| 1587 | return 0; | 1650 | return 0; |
| 1588 | } | 1651 | } |
| @@ -1592,7 +1655,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | |||
| 1592 | static int tvaudio_set_ctrl(struct CHIPSTATE *chip, | 1655 | static int tvaudio_set_ctrl(struct CHIPSTATE *chip, |
| 1593 | struct v4l2_control *ctrl) | 1656 | struct v4l2_control *ctrl) |
| 1594 | { | 1657 | { |
| 1595 | struct CHIPDESC *desc = chiplist + chip->type; | 1658 | struct CHIPDESC *desc = chip->desc; |
| 1596 | 1659 | ||
| 1597 | switch (ctrl->id) { | 1660 | switch (ctrl->id) { |
| 1598 | case V4L2_CID_AUDIO_MUTE: | 1661 | case V4L2_CID_AUDIO_MUTE: |
| @@ -1642,16 +1705,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, | |||
| 1642 | return 0; | 1705 | return 0; |
| 1643 | } | 1706 | } |
| 1644 | case V4L2_CID_AUDIO_BASS: | 1707 | case V4L2_CID_AUDIO_BASS: |
| 1645 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1708 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1646 | break; | 1709 | break; |
| 1647 | chip->bass = ctrl->value; | 1710 | chip->bass = ctrl->value; |
| 1648 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); | 1711 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); |
| 1649 | 1712 | ||
| 1650 | return 0; | 1713 | return 0; |
| 1651 | case V4L2_CID_AUDIO_TREBLE: | 1714 | case V4L2_CID_AUDIO_TREBLE: |
| 1652 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1715 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1653 | return -EINVAL; | 1716 | break; |
| 1654 | |||
| 1655 | chip->treble = ctrl->value; | 1717 | chip->treble = ctrl->value; |
| 1656 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); | 1718 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); |
| 1657 | 1719 | ||
| @@ -1668,9 +1730,12 @@ static int chip_command(struct i2c_client *client, | |||
| 1668 | unsigned int cmd, void *arg) | 1730 | unsigned int cmd, void *arg) |
| 1669 | { | 1731 | { |
| 1670 | struct CHIPSTATE *chip = i2c_get_clientdata(client); | 1732 | struct CHIPSTATE *chip = i2c_get_clientdata(client); |
| 1671 | struct CHIPDESC *desc = chiplist + chip->type; | 1733 | struct CHIPDESC *desc = chip->desc; |
| 1672 | 1734 | ||
| 1673 | v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); | 1735 | if (debug > 0) { |
| 1736 | v4l_i2c_print_ioctl(chip->c, cmd); | ||
| 1737 | printk("\n"); | ||
| 1738 | } | ||
| 1674 | 1739 | ||
| 1675 | switch (cmd) { | 1740 | switch (cmd) { |
| 1676 | case AUDC_SET_RADIO: | 1741 | case AUDC_SET_RADIO: |
| @@ -1695,7 +1760,7 @@ static int chip_command(struct i2c_client *client, | |||
| 1695 | break; | 1760 | break; |
| 1696 | case V4L2_CID_AUDIO_BASS: | 1761 | case V4L2_CID_AUDIO_BASS: |
| 1697 | case V4L2_CID_AUDIO_TREBLE: | 1762 | case V4L2_CID_AUDIO_TREBLE: |
| 1698 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1763 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1699 | return -EINVAL; | 1764 | return -EINVAL; |
| 1700 | break; | 1765 | break; |
| 1701 | default: | 1766 | default: |
| @@ -1792,12 +1857,20 @@ static int chip_command(struct i2c_client *client, | |||
| 1792 | break; | 1857 | break; |
| 1793 | case VIDIOC_S_FREQUENCY: | 1858 | case VIDIOC_S_FREQUENCY: |
| 1794 | chip->mode = 0; /* automatic */ | 1859 | chip->mode = 0; /* automatic */ |
| 1795 | if (desc->checkmode && desc->setmode) { | 1860 | |
| 1861 | /* For chips that provide getmode and setmode, and doesn't | ||
| 1862 | automatically follows the stereo carrier, a kthread is | ||
| 1863 | created to set the audio standard. In this case, when then | ||
| 1864 | the video channel is changed, tvaudio starts on MONO mode. | ||
| 1865 | After waiting for 2 seconds, the kernel thread is called, | ||
| 1866 | to follow whatever audio standard is pointed by the | ||
| 1867 | audio carrier. | ||
| 1868 | */ | ||
| 1869 | if (chip->thread) { | ||
| 1796 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); | 1870 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); |
| 1797 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) | 1871 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) |
| 1798 | chip->prevmode = -1; /* reset previous mode */ | 1872 | chip->prevmode = -1; /* reset previous mode */ |
| 1799 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 1873 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
| 1800 | /* the thread will call checkmode() later */ | ||
| 1801 | } | 1874 | } |
| 1802 | break; | 1875 | break; |
| 1803 | 1876 | ||
| @@ -1836,9 +1909,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
| 1836 | .legacy_probe = chip_legacy_probe, | 1909 | .legacy_probe = chip_legacy_probe, |
| 1837 | .id_table = chip_id, | 1910 | .id_table = chip_id, |
| 1838 | }; | 1911 | }; |
| 1839 | |||
| 1840 | /* | ||
| 1841 | * Local variables: | ||
| 1842 | * c-basic-offset: 8 | ||
| 1843 | * End: | ||
| 1844 | */ | ||
