diff options
| -rw-r--r-- | drivers/input/misc/winbond-cir.c | 213 |
1 files changed, 104 insertions, 109 deletions
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index c8f5a9a3fa14..cbec3dfdd42b 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c | |||
| @@ -538,6 +538,7 @@ wbcir_reset_irdata(struct wbcir_data *data) | |||
| 538 | data->irdata_count = 0; | 538 | data->irdata_count = 0; |
| 539 | data->irdata_off = 0; | 539 | data->irdata_off = 0; |
| 540 | data->irdata_error = 0; | 540 | data->irdata_error = 0; |
| 541 | data->idle_count = 0; | ||
| 541 | } | 542 | } |
| 542 | 543 | ||
| 543 | /* Adds one bit of irdata */ | 544 | /* Adds one bit of irdata */ |
| @@ -1006,7 +1007,6 @@ wbcir_irq_handler(int irqno, void *cookie) | |||
| 1006 | } | 1007 | } |
| 1007 | 1008 | ||
| 1008 | wbcir_reset_irdata(data); | 1009 | wbcir_reset_irdata(data); |
| 1009 | data->idle_count = 0; | ||
| 1010 | } | 1010 | } |
| 1011 | 1011 | ||
| 1012 | out: | 1012 | out: |
| @@ -1018,7 +1018,7 @@ out: | |||
| 1018 | 1018 | ||
| 1019 | /***************************************************************************** | 1019 | /***************************************************************************** |
| 1020 | * | 1020 | * |
| 1021 | * SUSPEND/RESUME FUNCTIONS | 1021 | * SETUP/INIT/SUSPEND/RESUME FUNCTIONS |
| 1022 | * | 1022 | * |
| 1023 | *****************************************************************************/ | 1023 | *****************************************************************************/ |
| 1024 | 1024 | ||
| @@ -1197,7 +1197,16 @@ finish: | |||
| 1197 | } | 1197 | } |
| 1198 | 1198 | ||
| 1199 | /* Disable interrupts */ | 1199 | /* Disable interrupts */ |
| 1200 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1200 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | 1201 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); |
| 1202 | |||
| 1203 | /* | ||
| 1204 | * ACPI will set the HW disable bit for SP3 which means that the | ||
| 1205 | * output signals are left in an undefined state which may cause | ||
| 1206 | * spurious interrupts which we need to ignore until the hardware | ||
| 1207 | * is reinitialized. | ||
| 1208 | */ | ||
| 1209 | disable_irq(data->irq); | ||
| 1201 | } | 1210 | } |
| 1202 | 1211 | ||
| 1203 | static int | 1212 | static int |
| @@ -1207,37 +1216,15 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state) | |||
| 1207 | return 0; | 1216 | return 0; |
| 1208 | } | 1217 | } |
| 1209 | 1218 | ||
| 1210 | static int | ||
| 1211 | wbcir_resume(struct pnp_dev *device) | ||
| 1212 | { | ||
| 1213 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
| 1214 | |||
| 1215 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
| 1216 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
| 1217 | |||
| 1218 | /* Clear CEIR_EN */ | ||
| 1219 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
| 1220 | |||
| 1221 | /* Enable interrupts */ | ||
| 1222 | wbcir_reset_irdata(data); | ||
| 1223 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1224 | |||
| 1225 | return 0; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | |||
| 1229 | |||
| 1230 | /***************************************************************************** | ||
| 1231 | * | ||
| 1232 | * SETUP/INIT FUNCTIONS | ||
| 1233 | * | ||
| 1234 | *****************************************************************************/ | ||
| 1235 | |||
| 1236 | static void | 1219 | static void |
| 1237 | wbcir_cfg_ceir(struct wbcir_data *data) | 1220 | wbcir_init_hw(struct wbcir_data *data) |
| 1238 | { | 1221 | { |
| 1239 | u8 tmp; | 1222 | u8 tmp; |
| 1240 | 1223 | ||
| 1224 | /* Disable interrupts */ | ||
| 1225 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1226 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1227 | |||
| 1241 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ | 1228 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ |
| 1242 | tmp = protocol << 4; | 1229 | tmp = protocol << 4; |
| 1243 | if (invert) | 1230 | if (invert) |
| @@ -1264,6 +1251,93 @@ wbcir_cfg_ceir(struct wbcir_data *data) | |||
| 1264 | * set SP3_IRRX_SW to binary 01, helpfully not documented | 1251 | * set SP3_IRRX_SW to binary 01, helpfully not documented |
| 1265 | */ | 1252 | */ |
| 1266 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); | 1253 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); |
| 1254 | |||
| 1255 | /* Enable extended mode */ | ||
| 1256 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
| 1257 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
| 1258 | |||
| 1259 | /* | ||
| 1260 | * Configure baud generator, IR data will be sampled at | ||
| 1261 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
| 1262 | * | ||
| 1263 | * The ECIR registers include a flag to change the | ||
| 1264 | * 24Mhz clock freq to 48Mhz. | ||
| 1265 | * | ||
| 1266 | * It's not documented in the specs, but fifo levels | ||
| 1267 | * other than 16 seems to be unsupported. | ||
| 1268 | */ | ||
| 1269 | |||
| 1270 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
| 1271 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
| 1272 | |||
| 1273 | /* Set baud divisor to generate one byte per bit/cell */ | ||
| 1274 | switch (protocol) { | ||
| 1275 | case IR_PROTOCOL_RC5: | ||
| 1276 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1277 | break; | ||
| 1278 | case IR_PROTOCOL_RC6: | ||
| 1279 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1280 | break; | ||
| 1281 | case IR_PROTOCOL_NEC: | ||
| 1282 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1283 | break; | ||
| 1284 | } | ||
| 1285 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
| 1286 | |||
| 1287 | /* Set CEIR mode */ | ||
| 1288 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1289 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
| 1290 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
| 1291 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
| 1292 | |||
| 1293 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
| 1294 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1295 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
| 1296 | |||
| 1297 | /* Disable timer */ | ||
| 1298 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
| 1299 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
| 1300 | |||
| 1301 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
| 1302 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
| 1303 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
| 1304 | |||
| 1305 | /* Disable CRC */ | ||
| 1306 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
| 1307 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
| 1308 | |||
| 1309 | /* Set RX/TX (de)modulation freq, not really used */ | ||
| 1310 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1311 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
| 1312 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
| 1313 | |||
| 1314 | /* Set invert and pin direction */ | ||
| 1315 | if (invert) | ||
| 1316 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1317 | else | ||
| 1318 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1319 | |||
| 1320 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
| 1321 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1322 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
| 1323 | |||
| 1324 | /* Clear AUX status bits */ | ||
| 1325 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 1326 | |||
| 1327 | /* Enable interrupts */ | ||
| 1328 | wbcir_reset_irdata(data); | ||
| 1329 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | static int | ||
| 1333 | wbcir_resume(struct pnp_dev *device) | ||
| 1334 | { | ||
| 1335 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
| 1336 | |||
| 1337 | wbcir_init_hw(data); | ||
| 1338 | enable_irq(data->irq); | ||
| 1339 | |||
| 1340 | return 0; | ||
| 1267 | } | 1341 | } |
| 1268 | 1342 | ||
| 1269 | static int __devinit | 1343 | static int __devinit |
| @@ -1393,86 +1467,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
| 1393 | 1467 | ||
| 1394 | device_init_wakeup(&device->dev, 1); | 1468 | device_init_wakeup(&device->dev, 1); |
| 1395 | 1469 | ||
| 1396 | wbcir_cfg_ceir(data); | 1470 | wbcir_init_hw(data); |
| 1397 | |||
| 1398 | /* Disable interrupts */ | ||
| 1399 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1400 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1401 | |||
| 1402 | /* Enable extended mode */ | ||
| 1403 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
| 1404 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
| 1405 | |||
| 1406 | /* | ||
| 1407 | * Configure baud generator, IR data will be sampled at | ||
| 1408 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
| 1409 | * | ||
| 1410 | * The ECIR registers include a flag to change the | ||
| 1411 | * 24Mhz clock freq to 48Mhz. | ||
| 1412 | * | ||
| 1413 | * It's not documented in the specs, but fifo levels | ||
| 1414 | * other than 16 seems to be unsupported. | ||
| 1415 | */ | ||
| 1416 | |||
| 1417 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
| 1418 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
| 1419 | |||
| 1420 | /* Set baud divisor to generate one byte per bit/cell */ | ||
| 1421 | switch (protocol) { | ||
| 1422 | case IR_PROTOCOL_RC5: | ||
| 1423 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1424 | break; | ||
| 1425 | case IR_PROTOCOL_RC6: | ||
| 1426 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1427 | break; | ||
| 1428 | case IR_PROTOCOL_NEC: | ||
| 1429 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1430 | break; | ||
| 1431 | } | ||
| 1432 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
| 1433 | |||
| 1434 | /* Set CEIR mode */ | ||
| 1435 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1436 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
| 1437 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
| 1438 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
| 1439 | |||
| 1440 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
| 1441 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1442 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
| 1443 | |||
| 1444 | /* Disable timer */ | ||
| 1445 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
| 1446 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
| 1447 | |||
| 1448 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
| 1449 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
| 1450 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
| 1451 | |||
| 1452 | /* Disable CRC */ | ||
| 1453 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
| 1454 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
| 1455 | |||
| 1456 | /* Set RX/TX (de)modulation freq, not really used */ | ||
| 1457 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1458 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
| 1459 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
| 1460 | |||
| 1461 | /* Set invert and pin direction */ | ||
| 1462 | if (invert) | ||
| 1463 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1464 | else | ||
| 1465 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1466 | |||
| 1467 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
| 1468 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1469 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
| 1470 | |||
| 1471 | /* Clear AUX status bits */ | ||
| 1472 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 1473 | |||
| 1474 | /* Enable interrupts */ | ||
| 1475 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1476 | 1471 | ||
| 1477 | return 0; | 1472 | return 0; |
| 1478 | 1473 | ||
