Skip to content

Commit efbd347

Browse files
Henrik Rydbergdtor
authored andcommitted
Input: bcm5974 - prepare for a new trackpad generation
With the advent of the Macbook Pro 12, we see a new generation of trackpads, capable of force sensoring and haptic feedback. This patch prepares for the new device by adding configuration data for the code paths that would otherwise look different. Tested-by: John Horan <knasher@gmail.com> Tested-by: Jochen Radmacher <jradmacher@gmx.de> Tested-by: Yang Hongyang <burnef@gmail.com> Tested-by: Yen-Chin, Lee <coldnew.tw@gmail.com> Tested-by: George Hilios <ghilios@gmail.com> Tested-by: Janez Urevc <janez@janezurevc.name> Signed-off-by: Henrik Rydberg <rydberg@bitmath.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent ab80ee3 commit efbd347

File tree

1 file changed

+81
-51
lines changed

1 file changed

+81
-51
lines changed

drivers/input/mouse/bcm5974.c

Lines changed: 81 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,37 @@ enum tp_type {
184184
};
185185

186186
/* trackpad finger data offsets, le16-aligned */
187-
#define FINGER_TYPE1 (13 * sizeof(__le16))
188-
#define FINGER_TYPE2 (15 * sizeof(__le16))
189-
#define FINGER_TYPE3 (19 * sizeof(__le16))
187+
#define HEADER_TYPE1 (13 * sizeof(__le16))
188+
#define HEADER_TYPE2 (15 * sizeof(__le16))
189+
#define HEADER_TYPE3 (19 * sizeof(__le16))
190190

191191
/* trackpad button data offsets */
192+
#define BUTTON_TYPE1 0
192193
#define BUTTON_TYPE2 15
193194
#define BUTTON_TYPE3 23
194195

195196
/* list of device capability bits */
196197
#define HAS_INTEGRATED_BUTTON 1
197198

199+
/* trackpad finger data block size */
200+
#define FSIZE_TYPE1 (14 * sizeof(__le16))
201+
#define FSIZE_TYPE2 (14 * sizeof(__le16))
202+
#define FSIZE_TYPE3 (14 * sizeof(__le16))
203+
204+
/* offset from header to finger struct */
205+
#define DELTA_TYPE1 (0 * sizeof(__le16))
206+
#define DELTA_TYPE2 (0 * sizeof(__le16))
207+
#define DELTA_TYPE3 (0 * sizeof(__le16))
208+
209+
/* usb control message mode switch data */
210+
#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8
211+
#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8
212+
#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8
213+
214+
/* Wellspring initialization constants */
215+
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
216+
#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
217+
198218
/* trackpad finger structure, le16-aligned */
199219
struct tp_finger {
200220
__le16 origin; /* zero when switching track finger */
@@ -213,8 +233,6 @@ struct tp_finger {
213233

214234
/* trackpad finger data size, empirically at least ten fingers */
215235
#define MAX_FINGERS 16
216-
#define SIZEOF_FINGER sizeof(struct tp_finger)
217-
#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER)
218236
#define MAX_FINGER_ORIENTATION 16384
219237

220238
/* device-specific parameters */
@@ -232,8 +250,17 @@ struct bcm5974_config {
232250
int bt_datalen; /* data length of the button interface */
233251
int tp_ep; /* the endpoint of the trackpad interface */
234252
enum tp_type tp_type; /* type of trackpad interface */
235-
int tp_offset; /* offset to trackpad finger data */
253+
int tp_header; /* bytes in header block */
236254
int tp_datalen; /* data length of the trackpad interface */
255+
int tp_button; /* offset to button data */
256+
int tp_fsize; /* bytes in single finger block */
257+
int tp_delta; /* offset from header to finger struct */
258+
int um_size; /* usb control message length */
259+
int um_req_val; /* usb control message value */
260+
int um_req_idx; /* usb control message index */
261+
int um_switch_idx; /* usb control message mode switch index */
262+
int um_switch_on; /* usb control message mode switch on */
263+
int um_switch_off; /* usb control message mode switch off */
237264
struct bcm5974_param p; /* finger pressure limits */
238265
struct bcm5974_param w; /* finger width limits */
239266
struct bcm5974_param x; /* horizontal limits */
@@ -259,6 +286,24 @@ struct bcm5974 {
259286
int slots[MAX_FINGERS]; /* slot assignments */
260287
};
261288

289+
/* trackpad finger block data, le16-aligned */
290+
static const struct tp_finger *get_tp_finger(const struct bcm5974 *dev, int i)
291+
{
292+
const struct bcm5974_config *c = &dev->cfg;
293+
u8 *f_base = dev->tp_data + c->tp_header + c->tp_delta;
294+
295+
return (const struct tp_finger *)(f_base + i * c->tp_fsize);
296+
}
297+
298+
#define DATAFORMAT(type) \
299+
type, \
300+
HEADER_##type, \
301+
HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \
302+
BUTTON_##type, \
303+
FSIZE_##type, \
304+
DELTA_##type, \
305+
USBMSG_##type
306+
262307
/* logical signal quality */
263308
#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
264309
#define SN_WIDTH 25 /* width signal-to-noise ratio */
@@ -273,7 +318,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
273318
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
274319
0,
275320
0x84, sizeof(struct bt_data),
276-
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
321+
0x81, DATAFORMAT(TYPE1),
277322
{ SN_PRESSURE, 0, 256 },
278323
{ SN_WIDTH, 0, 2048 },
279324
{ SN_COORD, -4824, 5342 },
@@ -286,7 +331,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
286331
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
287332
0,
288333
0x84, sizeof(struct bt_data),
289-
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
334+
0x81, DATAFORMAT(TYPE1),
290335
{ SN_PRESSURE, 0, 256 },
291336
{ SN_WIDTH, 0, 2048 },
292337
{ SN_COORD, -4824, 4824 },
@@ -299,7 +344,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
299344
USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
300345
HAS_INTEGRATED_BUTTON,
301346
0x84, sizeof(struct bt_data),
302-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
347+
0x81, DATAFORMAT(TYPE2),
303348
{ SN_PRESSURE, 0, 300 },
304349
{ SN_WIDTH, 0, 2048 },
305350
{ SN_COORD, -4460, 5166 },
@@ -312,7 +357,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
312357
USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
313358
HAS_INTEGRATED_BUTTON,
314359
0x84, sizeof(struct bt_data),
315-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
360+
0x81, DATAFORMAT(TYPE2),
316361
{ SN_PRESSURE, 0, 300 },
317362
{ SN_WIDTH, 0, 2048 },
318363
{ SN_COORD, -4620, 5140 },
@@ -325,7 +370,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
325370
USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
326371
HAS_INTEGRATED_BUTTON,
327372
0x84, sizeof(struct bt_data),
328-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
373+
0x81, DATAFORMAT(TYPE2),
329374
{ SN_PRESSURE, 0, 300 },
330375
{ SN_WIDTH, 0, 2048 },
331376
{ SN_COORD, -4616, 5112 },
@@ -338,7 +383,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
338383
USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
339384
HAS_INTEGRATED_BUTTON,
340385
0x84, sizeof(struct bt_data),
341-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
386+
0x81, DATAFORMAT(TYPE2),
342387
{ SN_PRESSURE, 0, 300 },
343388
{ SN_WIDTH, 0, 2048 },
344389
{ SN_COORD, -4415, 5050 },
@@ -351,7 +396,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
351396
USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
352397
HAS_INTEGRATED_BUTTON,
353398
0x84, sizeof(struct bt_data),
354-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
399+
0x81, DATAFORMAT(TYPE2),
355400
{ SN_PRESSURE, 0, 300 },
356401
{ SN_WIDTH, 0, 2048 },
357402
{ SN_COORD, -4620, 5140 },
@@ -364,7 +409,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
364409
USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
365410
HAS_INTEGRATED_BUTTON,
366411
0x84, sizeof(struct bt_data),
367-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
412+
0x81, DATAFORMAT(TYPE2),
368413
{ SN_PRESSURE, 0, 300 },
369414
{ SN_WIDTH, 0, 2048 },
370415
{ SN_COORD, -4750, 5280 },
@@ -377,7 +422,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
377422
USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS,
378423
HAS_INTEGRATED_BUTTON,
379424
0x84, sizeof(struct bt_data),
380-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
425+
0x81, DATAFORMAT(TYPE2),
381426
{ SN_PRESSURE, 0, 300 },
382427
{ SN_WIDTH, 0, 2048 },
383428
{ SN_COORD, -4620, 5140 },
@@ -390,7 +435,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
390435
USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
391436
HAS_INTEGRATED_BUTTON,
392437
0x84, sizeof(struct bt_data),
393-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
438+
0x81, DATAFORMAT(TYPE2),
394439
{ SN_PRESSURE, 0, 300 },
395440
{ SN_WIDTH, 0, 2048 },
396441
{ SN_COORD, -4750, 5280 },
@@ -403,7 +448,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
403448
USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
404449
HAS_INTEGRATED_BUTTON,
405450
0x84, sizeof(struct bt_data),
406-
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
451+
0x81, DATAFORMAT(TYPE2),
407452
{ SN_PRESSURE, 0, 300 },
408453
{ SN_WIDTH, 0, 2048 },
409454
{ SN_COORD, -4750, 5280 },
@@ -416,7 +461,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
416461
USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
417462
HAS_INTEGRATED_BUTTON,
418463
0, sizeof(struct bt_data),
419-
0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS,
464+
0x83, DATAFORMAT(TYPE3),
420465
{ SN_PRESSURE, 0, 300 },
421466
{ SN_WIDTH, 0, 2048 },
422467
{ SN_COORD, -4620, 5140 },
@@ -549,19 +594,18 @@ static int report_tp_state(struct bcm5974 *dev, int size)
549594
struct input_dev *input = dev->input;
550595
int raw_n, i, n = 0;
551596

552-
if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
597+
if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0)
553598
return -EIO;
554599

555-
/* finger data, le16-aligned */
556-
f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
557-
raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
600+
raw_n = (size - c->tp_header) / c->tp_fsize;
558601

559602
for (i = 0; i < raw_n; i++) {
560-
if (raw2int(f[i].touch_major) == 0)
603+
f = get_tp_finger(dev, i);
604+
if (raw2int(f->touch_major) == 0)
561605
continue;
562-
dev->pos[n].x = raw2int(f[i].abs_x);
563-
dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
564-
dev->index[n++] = &f[i];
606+
dev->pos[n].x = raw2int(f->abs_x);
607+
dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y);
608+
dev->index[n++] = f;
565609
}
566610

567611
input_mt_assign_slots(input, dev->slots, dev->pos, n, 0);
@@ -572,40 +616,30 @@ static int report_tp_state(struct bcm5974 *dev, int size)
572616

573617
input_mt_sync_frame(input);
574618

575-
report_synaptics_data(input, c, f, raw_n);
619+
report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n);
576620

577-
/* type 2 reports button events via ibt only */
578-
if (c->tp_type == TYPE2) {
579-
int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
621+
/* later types report button events via integrated button only */
622+
if (c->caps & HAS_INTEGRATED_BUTTON) {
623+
int ibt = raw2int(dev->tp_data[c->tp_button]);
580624
input_report_key(input, BTN_LEFT, ibt);
581625
}
582626

583-
if (c->tp_type == TYPE3)
584-
input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]);
585-
586627
input_sync(input);
587628

588629
return 0;
589630
}
590631

591-
/* Wellspring initialization constants */
592-
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
593-
#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
594-
#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
595-
#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
596-
#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
597-
#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08
598-
599632
static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
600633
{
634+
const struct bcm5974_config *c = &dev->cfg;
601635
int retval = 0, size;
602636
char *data;
603637

604638
/* Type 3 does not require a mode switch */
605639
if (dev->cfg.tp_type == TYPE3)
606640
return 0;
607641

608-
data = kmalloc(8, GFP_KERNEL);
642+
data = kmalloc(c->um_size, GFP_KERNEL);
609643
if (!data) {
610644
dev_err(&dev->intf->dev, "out of memory\n");
611645
retval = -ENOMEM;
@@ -616,28 +650,24 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
616650
size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
617651
BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
618652
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
619-
BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
620-
BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
653+
c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
621654

622-
if (size != 8) {
655+
if (size != c->um_size) {
623656
dev_err(&dev->intf->dev, "could not read from device\n");
624657
retval = -EIO;
625658
goto out;
626659
}
627660

628661
/* apply the mode switch */
629-
data[0] = on ?
630-
BCM5974_WELLSPRING_MODE_VENDOR_VALUE :
631-
BCM5974_WELLSPRING_MODE_NORMAL_VALUE;
662+
data[c->um_switch_idx] = on ? c->um_switch_on : c->um_switch_off;
632663

633664
/* write configuration */
634665
size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
635666
BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
636667
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
637-
BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
638-
BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
668+
c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
639669

640-
if (size != 8) {
670+
if (size != c->um_size) {
641671
dev_err(&dev->intf->dev, "could not write to device\n");
642672
retval = -EIO;
643673
goto out;

0 commit comments

Comments
 (0)