diff options
Diffstat (limited to 'drivers/input/misc/winbond-cir.c')
-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 | ||