diff options
Diffstat (limited to 'drivers/input/touchscreen/auo-pixcir-ts.c')
-rw-r--r-- | drivers/input/touchscreen/auo-pixcir-ts.c | 226 |
1 files changed, 144 insertions, 82 deletions
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index c6e19a96348e..d3f9f6b0f9b7 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/input/auo-pixcir-ts.h> | 33 | #include <linux/input/auo-pixcir-ts.h> |
34 | #include <linux/of.h> | ||
35 | #include <linux/of_gpio.h> | ||
34 | 36 | ||
35 | /* | 37 | /* |
36 | * Coordinate calculation: | 38 | * Coordinate calculation: |
@@ -111,6 +113,7 @@ | |||
111 | struct auo_pixcir_ts { | 113 | struct auo_pixcir_ts { |
112 | struct i2c_client *client; | 114 | struct i2c_client *client; |
113 | struct input_dev *input; | 115 | struct input_dev *input; |
116 | const struct auo_pixcir_ts_platdata *pdata; | ||
114 | char phys[32]; | 117 | char phys[32]; |
115 | 118 | ||
116 | /* special handling for touch_indicate interupt mode */ | 119 | /* special handling for touch_indicate interupt mode */ |
@@ -132,7 +135,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, | |||
132 | struct auo_point_t *point) | 135 | struct auo_point_t *point) |
133 | { | 136 | { |
134 | struct i2c_client *client = ts->client; | 137 | struct i2c_client *client = ts->client; |
135 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | 138 | const struct auo_pixcir_ts_platdata *pdata = ts->pdata; |
136 | uint8_t raw_coord[8]; | 139 | uint8_t raw_coord[8]; |
137 | uint8_t raw_area[4]; | 140 | uint8_t raw_area[4]; |
138 | int i, ret; | 141 | int i, ret; |
@@ -178,8 +181,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, | |||
178 | static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) | 181 | static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) |
179 | { | 182 | { |
180 | struct auo_pixcir_ts *ts = dev_id; | 183 | struct auo_pixcir_ts *ts = dev_id; |
181 | struct i2c_client *client = ts->client; | 184 | const struct auo_pixcir_ts_platdata *pdata = ts->pdata; |
182 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
183 | struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; | 185 | struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; |
184 | int i; | 186 | int i; |
185 | int ret; | 187 | int ret; |
@@ -290,7 +292,7 @@ static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, | |||
290 | int int_setting) | 292 | int int_setting) |
291 | { | 293 | { |
292 | struct i2c_client *client = ts->client; | 294 | struct i2c_client *client = ts->client; |
293 | struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | 295 | const struct auo_pixcir_ts_platdata *pdata = ts->pdata; |
294 | int ret; | 296 | int ret; |
295 | 297 | ||
296 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); | 298 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); |
@@ -479,53 +481,105 @@ unlock: | |||
479 | } | 481 | } |
480 | #endif | 482 | #endif |
481 | 483 | ||
482 | static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend, | 484 | static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, |
483 | auo_pixcir_resume); | 485 | auo_pixcir_suspend, auo_pixcir_resume); |
486 | |||
487 | #ifdef CONFIG_OF | ||
488 | static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) | ||
489 | { | ||
490 | struct auo_pixcir_ts_platdata *pdata; | ||
491 | struct device_node *np = dev->of_node; | ||
492 | |||
493 | if (!np) | ||
494 | return ERR_PTR(-ENOENT); | ||
495 | |||
496 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
497 | if (!pdata) { | ||
498 | dev_err(dev, "failed to allocate platform data\n"); | ||
499 | return ERR_PTR(-ENOMEM); | ||
500 | } | ||
501 | |||
502 | pdata->gpio_int = of_get_gpio(np, 0); | ||
503 | if (!gpio_is_valid(pdata->gpio_int)) { | ||
504 | dev_err(dev, "failed to get interrupt gpio\n"); | ||
505 | return ERR_PTR(-EINVAL); | ||
506 | } | ||
507 | |||
508 | pdata->gpio_rst = of_get_gpio(np, 1); | ||
509 | if (!gpio_is_valid(pdata->gpio_rst)) { | ||
510 | dev_err(dev, "failed to get reset gpio\n"); | ||
511 | return ERR_PTR(-EINVAL); | ||
512 | } | ||
513 | |||
514 | if (of_property_read_u32(np, "x-size", &pdata->x_max)) { | ||
515 | dev_err(dev, "failed to get x-size property\n"); | ||
516 | return ERR_PTR(-EINVAL); | ||
517 | } | ||
518 | |||
519 | if (of_property_read_u32(np, "y-size", &pdata->y_max)) { | ||
520 | dev_err(dev, "failed to get y-size property\n"); | ||
521 | return ERR_PTR(-EINVAL); | ||
522 | } | ||
523 | |||
524 | /* default to asserting the interrupt when the screen is touched */ | ||
525 | pdata->int_setting = AUO_PIXCIR_INT_TOUCH_IND; | ||
526 | |||
527 | return pdata; | ||
528 | } | ||
529 | #else | ||
530 | static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) | ||
531 | { | ||
532 | return ERR_PTR(-EINVAL); | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | static void auo_pixcir_reset(void *data) | ||
537 | { | ||
538 | struct auo_pixcir_ts *ts = data; | ||
539 | |||
540 | gpio_set_value(ts->pdata->gpio_rst, 0); | ||
541 | } | ||
484 | 542 | ||
485 | static int auo_pixcir_probe(struct i2c_client *client, | 543 | static int auo_pixcir_probe(struct i2c_client *client, |
486 | const struct i2c_device_id *id) | 544 | const struct i2c_device_id *id) |
487 | { | 545 | { |
488 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | 546 | const struct auo_pixcir_ts_platdata *pdata; |
489 | struct auo_pixcir_ts *ts; | 547 | struct auo_pixcir_ts *ts; |
490 | struct input_dev *input_dev; | 548 | struct input_dev *input_dev; |
491 | int ret; | 549 | int version; |
492 | 550 | int error; | |
493 | if (!pdata) | 551 | |
494 | return -EINVAL; | 552 | pdata = dev_get_platdata(&client->dev); |
553 | if (!pdata) { | ||
554 | pdata = auo_pixcir_parse_dt(&client->dev); | ||
555 | if (IS_ERR(pdata)) | ||
556 | return PTR_ERR(pdata); | ||
557 | } | ||
495 | 558 | ||
496 | ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL); | 559 | ts = devm_kzalloc(&client->dev, |
560 | sizeof(struct auo_pixcir_ts), GFP_KERNEL); | ||
497 | if (!ts) | 561 | if (!ts) |
498 | return -ENOMEM; | 562 | return -ENOMEM; |
499 | 563 | ||
500 | ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int"); | 564 | input_dev = devm_input_allocate_device(&client->dev); |
501 | if (ret) { | 565 | if (!input_dev) { |
502 | dev_err(&client->dev, "request of gpio %d failed, %d\n", | 566 | dev_err(&client->dev, "could not allocate input device\n"); |
503 | pdata->gpio_int, ret); | 567 | return -ENOMEM; |
504 | goto err_gpio_int; | ||
505 | } | 568 | } |
506 | 569 | ||
507 | if (pdata->init_hw) | 570 | ts->pdata = pdata; |
508 | pdata->init_hw(client); | ||
509 | |||
510 | ts->client = client; | 571 | ts->client = client; |
572 | ts->input = input_dev; | ||
511 | ts->touch_ind_mode = 0; | 573 | ts->touch_ind_mode = 0; |
574 | ts->stopped = true; | ||
512 | init_waitqueue_head(&ts->wait); | 575 | init_waitqueue_head(&ts->wait); |
513 | 576 | ||
514 | snprintf(ts->phys, sizeof(ts->phys), | 577 | snprintf(ts->phys, sizeof(ts->phys), |
515 | "%s/input0", dev_name(&client->dev)); | 578 | "%s/input0", dev_name(&client->dev)); |
516 | 579 | ||
517 | input_dev = input_allocate_device(); | ||
518 | if (!input_dev) { | ||
519 | dev_err(&client->dev, "could not allocate input device\n"); | ||
520 | goto err_input_alloc; | ||
521 | } | ||
522 | |||
523 | ts->input = input_dev; | ||
524 | |||
525 | input_dev->name = "AUO-Pixcir touchscreen"; | 580 | input_dev->name = "AUO-Pixcir touchscreen"; |
526 | input_dev->phys = ts->phys; | 581 | input_dev->phys = ts->phys; |
527 | input_dev->id.bustype = BUS_I2C; | 582 | input_dev->id.bustype = BUS_I2C; |
528 | input_dev->dev.parent = &client->dev; | ||
529 | 583 | ||
530 | input_dev->open = auo_pixcir_input_open; | 584 | input_dev->open = auo_pixcir_input_open; |
531 | input_dev->close = auo_pixcir_input_close; | 585 | input_dev->close = auo_pixcir_input_close; |
@@ -550,70 +604,70 @@ static int auo_pixcir_probe(struct i2c_client *client, | |||
550 | AUO_PIXCIR_MAX_AREA, 0, 0); | 604 | AUO_PIXCIR_MAX_AREA, 0, 0); |
551 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); | 605 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); |
552 | 606 | ||
553 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); | ||
554 | if (ret < 0) | ||
555 | goto err_fw_vers; | ||
556 | dev_info(&client->dev, "firmware version 0x%X\n", ret); | ||
557 | |||
558 | ret = auo_pixcir_int_config(ts, pdata->int_setting); | ||
559 | if (ret) | ||
560 | goto err_fw_vers; | ||
561 | |||
562 | input_set_drvdata(ts->input, ts); | 607 | input_set_drvdata(ts->input, ts); |
563 | ts->stopped = true; | ||
564 | 608 | ||
565 | ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt, | 609 | error = devm_gpio_request_one(&client->dev, pdata->gpio_int, |
566 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 610 | GPIOF_DIR_IN, "auo_pixcir_ts_int"); |
567 | input_dev->name, ts); | 611 | if (error) { |
568 | if (ret) { | 612 | dev_err(&client->dev, "request of gpio %d failed, %d\n", |
569 | dev_err(&client->dev, "irq %d requested failed\n", client->irq); | 613 | pdata->gpio_int, error); |
570 | goto err_fw_vers; | 614 | return error; |
571 | } | 615 | } |
572 | 616 | ||
573 | /* stop device and put it into deep sleep until it is opened */ | 617 | error = devm_gpio_request_one(&client->dev, pdata->gpio_rst, |
574 | ret = auo_pixcir_stop(ts); | 618 | GPIOF_DIR_OUT | GPIOF_INIT_HIGH, |
575 | if (ret < 0) | 619 | "auo_pixcir_ts_rst"); |
576 | goto err_input_register; | 620 | if (error) { |
577 | 621 | dev_err(&client->dev, "request of gpio %d failed, %d\n", | |
578 | ret = input_register_device(input_dev); | 622 | pdata->gpio_rst, error); |
579 | if (ret) { | 623 | return error; |
580 | dev_err(&client->dev, "could not register input device\n"); | ||
581 | goto err_input_register; | ||
582 | } | 624 | } |
583 | 625 | ||
584 | i2c_set_clientdata(client, ts); | 626 | error = devm_add_action(&client->dev, auo_pixcir_reset, ts); |
585 | 627 | if (error) { | |
586 | return 0; | 628 | auo_pixcir_reset(ts); |
629 | dev_err(&client->dev, "failed to register reset action, %d\n", | ||
630 | error); | ||
631 | return error; | ||
632 | } | ||
587 | 633 | ||
588 | err_input_register: | 634 | msleep(200); |
589 | free_irq(client->irq, ts); | ||
590 | err_fw_vers: | ||
591 | input_free_device(input_dev); | ||
592 | err_input_alloc: | ||
593 | if (pdata->exit_hw) | ||
594 | pdata->exit_hw(client); | ||
595 | gpio_free(pdata->gpio_int); | ||
596 | err_gpio_int: | ||
597 | kfree(ts); | ||
598 | 635 | ||
599 | return ret; | 636 | version = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); |
600 | } | 637 | if (version < 0) { |
601 | 638 | error = version; | |
602 | static int auo_pixcir_remove(struct i2c_client *client) | 639 | return error; |
603 | { | 640 | } |
604 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | ||
605 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
606 | 641 | ||
607 | free_irq(client->irq, ts); | 642 | dev_info(&client->dev, "firmware version 0x%X\n", version); |
608 | 643 | ||
609 | input_unregister_device(ts->input); | 644 | error = auo_pixcir_int_config(ts, pdata->int_setting); |
645 | if (error) | ||
646 | return error; | ||
610 | 647 | ||
611 | if (pdata->exit_hw) | 648 | error = devm_request_threaded_irq(&client->dev, client->irq, |
612 | pdata->exit_hw(client); | 649 | NULL, auo_pixcir_interrupt, |
650 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
651 | input_dev->name, ts); | ||
652 | if (error) { | ||
653 | dev_err(&client->dev, "irq %d requested failed, %d\n", | ||
654 | client->irq, error); | ||
655 | return error; | ||
656 | } | ||
613 | 657 | ||
614 | gpio_free(pdata->gpio_int); | 658 | /* stop device and put it into deep sleep until it is opened */ |
659 | error = auo_pixcir_stop(ts); | ||
660 | if (error) | ||
661 | return error; | ||
662 | |||
663 | error = input_register_device(input_dev); | ||
664 | if (error) { | ||
665 | dev_err(&client->dev, "could not register input device, %d\n", | ||
666 | error); | ||
667 | return error; | ||
668 | } | ||
615 | 669 | ||
616 | kfree(ts); | 670 | i2c_set_clientdata(client, ts); |
617 | 671 | ||
618 | return 0; | 672 | return 0; |
619 | } | 673 | } |
@@ -624,14 +678,22 @@ static const struct i2c_device_id auo_pixcir_idtable[] = { | |||
624 | }; | 678 | }; |
625 | MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); | 679 | MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); |
626 | 680 | ||
681 | #ifdef CONFIG_OF | ||
682 | static struct of_device_id auo_pixcir_ts_dt_idtable[] = { | ||
683 | { .compatible = "auo,auo_pixcir_ts" }, | ||
684 | {}, | ||
685 | }; | ||
686 | MODULE_DEVICE_TABLE(of, auo_pixcir_ts_dt_idtable); | ||
687 | #endif | ||
688 | |||
627 | static struct i2c_driver auo_pixcir_driver = { | 689 | static struct i2c_driver auo_pixcir_driver = { |
628 | .driver = { | 690 | .driver = { |
629 | .owner = THIS_MODULE, | 691 | .owner = THIS_MODULE, |
630 | .name = "auo_pixcir_ts", | 692 | .name = "auo_pixcir_ts", |
631 | .pm = &auo_pixcir_pm_ops, | 693 | .pm = &auo_pixcir_pm_ops, |
694 | .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), | ||
632 | }, | 695 | }, |
633 | .probe = auo_pixcir_probe, | 696 | .probe = auo_pixcir_probe, |
634 | .remove = auo_pixcir_remove, | ||
635 | .id_table = auo_pixcir_idtable, | 697 | .id_table = auo_pixcir_idtable, |
636 | }; | 698 | }; |
637 | 699 | ||