Deleted Added
full compact
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, &reg },
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, &reg },
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 *)&regs, sizeof(regs), NULL);
1197 error = cyapa_read_bytes(sc->dev, CMD_DEV_STATUS,
1198 (void *)&regs, sizeof(regs));
1189 if (error == 0) {
1190 isidle = cyapa_raw_input(sc, &regs, 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, &regs, 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);