cyapa.c (302408) | cyapa.c (310072) |
---|---|
1/* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> and was subsequently ported, 6 * modified and enhanced for FreeBSD by Michael Gmelin <freebsd@grem.de>. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> and was subsequently ported, 6 * modified and enhanced for FreeBSD by Michael Gmelin <freebsd@grem.de>. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: stable/11/sys/dev/cyapa/cyapa.c 286918 2015-08-19 09:49:29Z grembo $"); | 37__FBSDID("$FreeBSD: stable/11/sys/dev/cyapa/cyapa.c 310072 2016-12-14 16:27:28Z avg $"); |
38 39/* 40 * CYAPA - Cypress APA trackpad with I2C Interface driver 41 * 42 * Based on DragonFlyBSD's cyapa driver, which referenced the linux 43 * cyapa.c driver to figure out the bootstrapping and commands. 44 * 45 * Unable to locate any datasheet for the device. --- 71 unchanged lines hidden (view full) --- 117#include <sys/selinfo.h> 118#include <sys/sysctl.h> 119#include <sys/sysctl.h> 120#include <sys/systm.h> 121#include <sys/systm.h> 122#include <sys/uio.h> 123#include <sys/vnode.h> 124 | 38 39/* 40 * CYAPA - Cypress APA trackpad with I2C Interface driver 41 * 42 * Based on DragonFlyBSD's cyapa driver, which referenced the linux 43 * cyapa.c driver to figure out the bootstrapping and commands. 44 * 45 * Unable to locate any datasheet for the device. --- 71 unchanged lines hidden (view full) --- 117#include <sys/selinfo.h> 118#include <sys/sysctl.h> 119#include <sys/sysctl.h> 120#include <sys/systm.h> 121#include <sys/systm.h> 122#include <sys/uio.h> 123#include <sys/vnode.h> 124 |
125#include <dev/smbus/smbconf.h> 126#include <dev/smbus/smbus.h> | 125#include <dev/iicbus/iiconf.h> 126#include <dev/iicbus/iicbus.h> |
127#include <dev/cyapa/cyapa.h> 128 | 127#include <dev/cyapa/cyapa.h> 128 |
129#include "smbus_if.h" | 129#include "iicbus_if.h" |
130#include "bus_if.h" 131#include "device_if.h" 132 133#define CYAPA_BUFSIZE 128 /* power of 2 */ 134#define CYAPA_BUFMASK (CYAPA_BUFSIZE - 1) 135 136#define ZSCALE 15 137 --- 6 unchanged lines hidden (view full) --- 144 int rindex; 145 int windex; 146 char buf[CYAPA_BUFSIZE]; 147}; 148 149struct cyapa_softc { 150 device_t dev; 151 int count; /* >0 if device opened */ | 130#include "bus_if.h" 131#include "device_if.h" 132 133#define CYAPA_BUFSIZE 128 /* power of 2 */ 134#define CYAPA_BUFMASK (CYAPA_BUFSIZE - 1) 135 136#define ZSCALE 15 137 --- 6 unchanged lines hidden (view full) --- 144 int rindex; 145 int windex; 146 char buf[CYAPA_BUFSIZE]; 147}; 148 149struct cyapa_softc { 150 device_t dev; 151 int count; /* >0 if device opened */ |
152 int addr; | |
153 struct cdev *devnode; 154 struct selinfo selinfo; 155 struct mtx mutex; 156 157 int cap_resx; 158 int cap_resy; 159 int cap_phyx; 160 int cap_phyy; --- 107 unchanged lines hidden (view full) --- 268 269static int cyapa_debug = 0; 270SYSCTL_INT(_debug, OID_AUTO, cyapa_debug, CTLFLAG_RW, 271 &cyapa_debug, 0, "Enable debugging"); 272static int cyapa_reset = 0; 273SYSCTL_INT(_debug, OID_AUTO, cyapa_reset, CTLFLAG_RW, 274 &cyapa_reset, 0, "Reset track pad"); 275 | 152 struct cdev *devnode; 153 struct selinfo selinfo; 154 struct mtx mutex; 155 156 int cap_resx; 157 int cap_resy; 158 int cap_phyx; 159 int cap_phyy; --- 107 unchanged lines hidden (view full) --- 267 268static int cyapa_debug = 0; 269SYSCTL_INT(_debug, OID_AUTO, cyapa_debug, CTLFLAG_RW, 270 &cyapa_debug, 0, "Enable debugging"); 271static int cyapa_reset = 0; 272SYSCTL_INT(_debug, OID_AUTO, cyapa_reset, CTLFLAG_RW, 273 &cyapa_reset, 0, "Reset track pad"); 274 |
275static int 276cyapa_read_bytes(device_t dev, uint8_t reg, uint8_t *val, int cnt) 277{ 278 uint16_t addr = iicbus_get_addr(dev); 279 struct iic_msg msgs[] = { 280 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 281 { addr, IIC_M_RD, cnt, val }, 282 }; 283 284 return (iicbus_transfer(dev, msgs, nitems(msgs))); 285} 286 287static int 288cyapa_write_bytes(device_t dev, uint8_t reg, const uint8_t *val, int cnt) 289{ 290 uint16_t addr = iicbus_get_addr(dev); 291 struct iic_msg msgs[] = { 292 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 293 { addr, IIC_M_WR | IIC_M_NOSTART, cnt, __DECONST(uint8_t *, val) }, 294 }; 295 296 return (iicbus_transfer(dev, msgs, nitems(msgs))); 297} 298 |
|
276static void 277cyapa_lock(struct cyapa_softc *sc) 278{ 279 280 mtx_lock(&sc->mutex); 281} 282 283static void --- 29 unchanged lines hidden (view full) --- 313 } 314 } 315} 316 317/* 318 * Initialize the device 319 */ 320static int | 299static void 300cyapa_lock(struct cyapa_softc *sc) 301{ 302 303 mtx_lock(&sc->mutex); 304} 305 306static void --- 29 unchanged lines hidden (view full) --- 336 } 337 } 338} 339 340/* 341 * Initialize the device 342 */ 343static int |
321init_device(device_t dev, struct cyapa_cap *cap, int addr, int probe) | 344init_device(device_t dev, struct cyapa_cap *cap, int probe) |
322{ 323 static char bl_exit[] = { 324 0x00, 0xff, 0xa5, 0x00, 0x01, 325 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 326 static char bl_deactivate[] = { 327 0x00, 0xff, 0x3b, 0x00, 0x01, 328 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; | 345{ 346 static char bl_exit[] = { 347 0x00, 0xff, 0xa5, 0x00, 0x01, 348 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 349 static char bl_deactivate[] = { 350 0x00, 0xff, 0x3b, 0x00, 0x01, 351 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; |
329 device_t bus; | |
330 struct cyapa_boot_regs boot; 331 int error; 332 int retries; 333 | 352 struct cyapa_boot_regs boot; 353 int error; 354 int retries; 355 |
334 bus = device_get_parent(dev); /* smbus */ 335 | |
336 /* Get status */ | 356 /* Get status */ |
337 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 338 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 339 NULL, 0, (void *)&boot, sizeof(boot), NULL); | 357 error = cyapa_read_bytes(dev, CMD_BOOT_STATUS, 358 (void *)&boot, sizeof(boot)); |
340 if (error) 341 goto done; 342 343 /* 344 * Bootstrap the device if necessary. It can take up to 2 seconds 345 * for the device to fully initialize. 346 */ 347 retries = 20; 348 while ((boot.stat & CYAPA_STAT_RUNNING) == 0 && retries > 0) { 349 if (boot.boot & CYAPA_BOOT_BUSY) { 350 /* Busy, wait loop. */ 351 } else if (boot.error & CYAPA_ERROR_BOOTLOADER) { 352 /* Magic */ | 359 if (error) 360 goto done; 361 362 /* 363 * Bootstrap the device if necessary. It can take up to 2 seconds 364 * for the device to fully initialize. 365 */ 366 retries = 20; 367 while ((boot.stat & CYAPA_STAT_RUNNING) == 0 && retries > 0) { 368 if (boot.boot & CYAPA_BOOT_BUSY) { 369 /* Busy, wait loop. */ 370 } else if (boot.error & CYAPA_ERROR_BOOTLOADER) { 371 /* Magic */ |
353 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 354 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 355 bl_deactivate, sizeof(bl_deactivate), 356 NULL, 0, NULL); | 372 error = cyapa_write_bytes(dev, CMD_BOOT_STATUS, 373 bl_deactivate, sizeof(bl_deactivate)); |
357 if (error) 358 goto done; 359 } else { 360 /* Magic */ | 374 if (error) 375 goto done; 376 } else { 377 /* Magic */ |
361 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 362 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 363 bl_exit, sizeof(bl_exit), NULL, 0, NULL); | 378 error = cyapa_write_bytes(dev, CMD_BOOT_STATUS, 379 bl_exit, sizeof(bl_exit)); |
364 if (error) 365 goto done; 366 } 367 pause("cyapab1", (hz * 2) / 10); 368 --retries; | 380 if (error) 381 goto done; 382 } 383 pause("cyapab1", (hz * 2) / 10); 384 --retries; |
369 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 370 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 371 NULL, 0, (void *)&boot, sizeof(boot), NULL); | 385 error = cyapa_read_bytes(dev, CMD_BOOT_STATUS, 386 (void *)&boot, sizeof(boot)); |
372 if (error) 373 goto done; 374 } 375 376 if (retries == 0) { 377 device_printf(dev, "Unable to bring device out of bootstrap\n"); 378 error = ENXIO; 379 goto done; 380 } 381 382 /* Check identity */ 383 if (cap) { | 387 if (error) 388 goto done; 389 } 390 391 if (retries == 0) { 392 device_printf(dev, "Unable to bring device out of bootstrap\n"); 393 error = ENXIO; 394 goto done; 395 } 396 397 /* Check identity */ 398 if (cap) { |
384 error = smbus_trans(bus, addr, CMD_QUERY_CAPABILITIES, 385 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 386 NULL, 0, (void *)cap, sizeof(*cap), NULL); | 399 error = cyapa_read_bytes(dev, CMD_QUERY_CAPABILITIES, 400 (void *)cap, sizeof(*cap)); |
387 388 if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) { 389 device_printf(dev, "Product ID \"%5.5s\" mismatch\n", 390 cap->prod_ida); 391 error = ENXIO; 392 } 393 } | 401 402 if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) { 403 device_printf(dev, "Product ID \"%5.5s\" mismatch\n", 404 cap->prod_ida); 405 error = ENXIO; 406 } 407 } |
394 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 395 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 396 NULL, 0, (void *)&boot, sizeof(boot), NULL); | 408 error = cyapa_read_bytes(dev, CMD_BOOT_STATUS, 409 (void *)&boot, sizeof(boot)); |
397 398 if (probe == 0) /* official init */ 399 device_printf(dev, "cyapa init status %02x\n", boot.stat); 400 else if (probe == 2) 401 device_printf(dev, "cyapa reset status %02x\n", boot.stat); 402 403done: 404 if (error) --- 42 unchanged lines hidden (view full) --- 447 448static int 449cyapa_probe(device_t dev) 450{ 451 struct cyapa_cap cap; 452 int addr; 453 int error; 454 | 410 411 if (probe == 0) /* official init */ 412 device_printf(dev, "cyapa init status %02x\n", boot.stat); 413 else if (probe == 2) 414 device_printf(dev, "cyapa reset status %02x\n", boot.stat); 415 416done: 417 if (error) --- 42 unchanged lines hidden (view full) --- 460 461static int 462cyapa_probe(device_t dev) 463{ 464 struct cyapa_cap cap; 465 int addr; 466 int error; 467 |
455 addr = smbus_get_addr(dev); | 468 addr = iicbus_get_addr(dev); |
456 457 /* 458 * 0x67 - cypress trackpad on the acer c720 459 * (other devices might use other ids). 460 */ | 469 470 /* 471 * 0x67 - cypress trackpad on the acer c720 472 * (other devices might use other ids). 473 */ |
461 if (addr != 0x67) | 474 if (addr != 0xce) |
462 return (ENXIO); 463 | 475 return (ENXIO); 476 |
464 error = init_device(dev, &cap, addr, 1); | 477 error = init_device(dev, &cap, 1); |
465 if (error != 0) 466 return (ENXIO); 467 468 device_set_desc(dev, "Cypress APA I2C Trackpad"); 469 470 return (BUS_PROBE_VENDOR); 471} 472 --- 4 unchanged lines hidden (view full) --- 477 struct cyapa_cap cap; 478 int unit; 479 int addr; 480 481 sc = device_get_softc(dev); 482 sc->reporting_mode = 1; 483 484 unit = device_get_unit(dev); | 478 if (error != 0) 479 return (ENXIO); 480 481 device_set_desc(dev, "Cypress APA I2C Trackpad"); 482 483 return (BUS_PROBE_VENDOR); 484} 485 --- 4 unchanged lines hidden (view full) --- 490 struct cyapa_cap cap; 491 int unit; 492 int addr; 493 494 sc = device_get_softc(dev); 495 sc->reporting_mode = 1; 496 497 unit = device_get_unit(dev); |
485 addr = smbus_get_addr(dev); | 498 addr = iicbus_get_addr(dev); |
486 | 499 |
487 if (init_device(dev, &cap, addr, 0)) | 500 if (init_device(dev, &cap, 0)) |
488 return (ENXIO); 489 490 mtx_init(&sc->mutex, "cyapa", NULL, MTX_DEF); 491 492 sc->dev = dev; | 501 return (ENXIO); 502 503 mtx_init(&sc->mutex, "cyapa", NULL, MTX_DEF); 504 505 sc->dev = dev; |
493 sc->addr = addr; | |
494 495 knlist_init_mtx(&sc->selinfo.si_note, &sc->mutex); 496 497 sc->cap_resx = ((cap.max_abs_xy_high << 4) & 0x0F00) | 498 cap.max_abs_x_low; 499 sc->cap_resy = ((cap.max_abs_xy_high << 8) & 0x0F00) | 500 cap.max_abs_y_low; 501 sc->cap_phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) | --- 652 unchanged lines hidden (view full) --- 1154/* 1155 * MAJOR SUPPORT FUNCTIONS 1156 */ 1157static void 1158cyapa_poll_thread(void *arg) 1159{ 1160 struct cyapa_softc *sc; 1161 struct cyapa_regs regs; | 506 507 knlist_init_mtx(&sc->selinfo.si_note, &sc->mutex); 508 509 sc->cap_resx = ((cap.max_abs_xy_high << 4) & 0x0F00) | 510 cap.max_abs_x_low; 511 sc->cap_resy = ((cap.max_abs_xy_high << 8) & 0x0F00) | 512 cap.max_abs_y_low; 513 sc->cap_phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) | --- 652 unchanged lines hidden (view full) --- 1166/* 1167 * MAJOR SUPPORT FUNCTIONS 1168 */ 1169static void 1170cyapa_poll_thread(void *arg) 1171{ 1172 struct cyapa_softc *sc; 1173 struct cyapa_regs regs; |
1162 device_t bus; /* smbus */ | 1174 device_t bus; /* iicbus */ |
1163 int error; 1164 int freq; 1165 int isidle; 1166 int pstate; 1167 int npstate; 1168 int last_reset; 1169 1170 sc = arg; --- 4 unchanged lines hidden (view full) --- 1175 1176 bus = device_get_parent(sc->dev); 1177 1178 cyapa_lock(sc); 1179 sc->poll_thread_running = 1; 1180 1181 while (!sc->detaching) { 1182 cyapa_unlock(sc); | 1175 int error; 1176 int freq; 1177 int isidle; 1178 int pstate; 1179 int npstate; 1180 int last_reset; 1181 1182 sc = arg; --- 4 unchanged lines hidden (view full) --- 1187 1188 bus = device_get_parent(sc->dev); 1189 1190 cyapa_lock(sc); 1191 sc->poll_thread_running = 1; 1192 1193 while (!sc->detaching) { 1194 cyapa_unlock(sc); |
1183 error = smbus_request_bus(bus, sc->dev, SMB_WAIT); | 1195 error = iicbus_request_bus(bus, sc->dev, IIC_WAIT); |
1184 if (error == 0) { | 1196 if (error == 0) { |
1185 error = smbus_trans(bus, sc->addr, CMD_DEV_STATUS, 1186 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1187 NULL, 0, 1188 (void *)®s, sizeof(regs), NULL); | 1197 error = cyapa_read_bytes(sc->dev, CMD_DEV_STATUS, 1198 (void *)®s, sizeof(regs)); |
1189 if (error == 0) { 1190 isidle = cyapa_raw_input(sc, ®s, freq); 1191 } 1192 1193 /* 1194 * For some reason the device can crap-out. If it 1195 * drops back into bootstrap mode try to reinitialize 1196 * it. 1197 */ 1198 if (cyapa_reset || 1199 ((regs.stat & CYAPA_STAT_RUNNING) == 0 && 1200 (unsigned)(ticks - last_reset) > TIME_TO_RESET)) { 1201 cyapa_reset = 0; 1202 last_reset = ticks; | 1199 if (error == 0) { 1200 isidle = cyapa_raw_input(sc, ®s, freq); 1201 } 1202 1203 /* 1204 * For some reason the device can crap-out. If it 1205 * drops back into bootstrap mode try to reinitialize 1206 * it. 1207 */ 1208 if (cyapa_reset || 1209 ((regs.stat & CYAPA_STAT_RUNNING) == 0 && 1210 (unsigned)(ticks - last_reset) > TIME_TO_RESET)) { 1211 cyapa_reset = 0; 1212 last_reset = ticks; |
1203 init_device(sc->dev, NULL, sc->addr, 2); | 1213 init_device(sc->dev, NULL, 2); |
1204 } | 1214 } |
1205 smbus_release_bus(bus, sc->dev); | 1215 iicbus_release_bus(bus, sc->dev); |
1206 } 1207 pause("cyapw", hz / freq); 1208 ++sc->poll_ticks; 1209 1210 if (sc->count == 0) { 1211 freq = cyapa_idle_freq; 1212 npstate = CMD_POWER_MODE_IDLE; 1213 } else if (isidle) { --- 312 unchanged lines hidden (view full) --- 1526static void 1527cyapa_set_power_mode(struct cyapa_softc *sc, int mode) 1528{ 1529 uint8_t data; 1530 device_t bus; 1531 int error; 1532 1533 bus = device_get_parent(sc->dev); | 1216 } 1217 pause("cyapw", hz / freq); 1218 ++sc->poll_ticks; 1219 1220 if (sc->count == 0) { 1221 freq = cyapa_idle_freq; 1222 npstate = CMD_POWER_MODE_IDLE; 1223 } else if (isidle) { --- 312 unchanged lines hidden (view full) --- 1536static void 1537cyapa_set_power_mode(struct cyapa_softc *sc, int mode) 1538{ 1539 uint8_t data; 1540 device_t bus; 1541 int error; 1542 1543 bus = device_get_parent(sc->dev); |
1534 error = smbus_request_bus(bus, sc->dev, SMB_WAIT); | 1544 error = iicbus_request_bus(bus, sc->dev, IIC_WAIT); |
1535 if (error == 0) { | 1545 if (error == 0) { |
1536 error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, 1537 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1538 NULL, 0, (void *)&data, 1, NULL); | 1546 error = cyapa_read_bytes(sc->dev, CMD_POWER_MODE, 1547 &data, 1); |
1539 data = (data & ~0xFC) | mode; 1540 if (error == 0) { | 1548 data = (data & ~0xFC) | mode; 1549 if (error == 0) { |
1541 error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, 1542 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1543 (void *)&data, 1, NULL, 0, NULL); | 1550 error = cyapa_write_bytes(sc->dev, CMD_POWER_MODE, 1551 &data, 1); |
1544 } | 1552 } |
1545 smbus_release_bus(bus, sc->dev); | 1553 iicbus_release_bus(bus, sc->dev); |
1546 } 1547} 1548 1549/* 1550 * FIFO FUNCTIONS 1551 */ 1552 1553/* --- 138 unchanged lines hidden (view full) --- 1692 --delta; 1693 ++fuzz; 1694 } 1695 *fuzzp = fuzz; 1696 1697 return (delta); 1698} 1699 | 1554 } 1555} 1556 1557/* 1558 * FIFO FUNCTIONS 1559 */ 1560 1561/* --- 138 unchanged lines hidden (view full) --- 1700 --delta; 1701 ++fuzz; 1702 } 1703 *fuzzp = fuzz; 1704 1705 return (delta); 1706} 1707 |
1700DRIVER_MODULE(cyapa, smbus, cyapa_driver, cyapa_devclass, NULL, NULL); 1701MODULE_DEPEND(cyapa, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); | 1708DRIVER_MODULE(cyapa, iicbus, cyapa_driver, cyapa_devclass, NULL, NULL); 1709MODULE_DEPEND(cyapa, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); |
1702MODULE_VERSION(cyapa, 1); | 1710MODULE_VERSION(cyapa, 1); |