Lines Matching +full:touchscreen +full:- +full:min +full:- +full:x

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
15 * - supports WM9705, WM9712, WM9713
16 * - polling mode
17 * - continuous mode (arch-dependent)
18 * - adjustable rpu/dpp settings
19 * - adjustable pressure current
20 * - adjustable sample settle delay
21 * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
22 * - pen down detection
23 * - battery monitor
24 * - sample AUX adcs
25 * - power management
26 * - codec GPIO
27 * - codec event notification
29 * - Support for async sampling control for noisy LCDs.
55 * Touchscreen absolute values
60 * o min, max:- indicate the min and max values your touch screen returns
61 * o fuzz:- use a higher number to reduce jitter
66 * Documentation/input/input-programming.rst for more details.
71 MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
75 MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
79 MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
86 if (wm->ac97) in wm97xx_reg_read()
87 return wm->ac97->bus->ops->read(wm->ac97, reg); in wm97xx_reg_read()
89 return -1; in wm97xx_reg_read()
97 wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val; in wm97xx_reg_write()
101 wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val; in wm97xx_reg_write()
105 wm->misc = val; in wm97xx_reg_write()
107 if (wm->ac97) in wm97xx_reg_write()
108 wm->ac97->bus->ops->write(wm->ac97, reg, val); in wm97xx_reg_write()
113 * wm97xx_read_aux_adc - Read the aux adc.
128 mutex_lock(&wm->codec_mutex); in wm97xx_read_aux_adc()
130 /* When the touchscreen is not in use, we may have to power up in wm97xx_read_aux_adc()
131 * the AUX ADC before we can use sample the AUX inputs-> in wm97xx_read_aux_adc()
133 if (wm->id == WM9713_ID2 && in wm97xx_read_aux_adc()
140 wm->codec->aux_prepare(wm); in wm97xx_read_aux_adc()
143 wm->pen_probably_down = 1; in wm97xx_read_aux_adc()
146 rc = wm->codec->poll_sample(wm, adcsel, &auxval); in wm97xx_read_aux_adc()
151 wm->codec->dig_restore(wm); in wm97xx_read_aux_adc()
153 wm->pen_probably_down = 0; in wm97xx_read_aux_adc()
156 dev_err(wm->dev, in wm97xx_read_aux_adc()
159 wm->codec->dig_enable(wm, false); in wm97xx_read_aux_adc()
162 mutex_unlock(&wm->codec_mutex); in wm97xx_read_aux_adc()
163 return (rc == RC_VALID ? auxval & 0xfff : -EBUSY); in wm97xx_read_aux_adc()
168 * wm97xx_get_gpio - Get the status of a codec GPIO.
180 mutex_lock(&wm->codec_mutex); in wm97xx_get_gpio()
188 mutex_unlock(&wm->codec_mutex); in wm97xx_get_gpio()
194 * wm97xx_set_gpio - Set the status of a codec GPIO.
207 mutex_lock(&wm->codec_mutex); in wm97xx_set_gpio()
215 if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) in wm97xx_set_gpio()
219 mutex_unlock(&wm->codec_mutex); in wm97xx_set_gpio()
233 mutex_lock(&wm->codec_mutex); in wm97xx_config_gpio()
266 mutex_unlock(&wm->codec_mutex); in wm97xx_config_gpio()
282 wm->suspend_mode = mode; in wm97xx_set_suspend_mode()
283 device_init_wakeup(&wm->input_dev->dev, mode != 0); in wm97xx_set_suspend_mode()
293 int pen_was_down = wm->pen_is_down; in wm97xx_pen_irq_worker()
296 if (wm->id == WM9705_ID2) { in wm97xx_pen_irq_worker()
299 wm->pen_is_down = 1; in wm97xx_pen_irq_worker()
301 wm->pen_is_down = 0; in wm97xx_pen_irq_worker()
304 mutex_lock(&wm->codec_mutex); in wm97xx_pen_irq_worker()
309 wm->pen_is_down = 1; in wm97xx_pen_irq_worker()
313 wm->pen_is_down = 0; in wm97xx_pen_irq_worker()
318 if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) in wm97xx_pen_irq_worker()
324 mutex_unlock(&wm->codec_mutex); in wm97xx_pen_irq_worker()
332 if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) { in wm97xx_pen_irq_worker()
333 if (wm->pen_is_down && !pen_was_down) { in wm97xx_pen_irq_worker()
335 queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1); in wm97xx_pen_irq_worker()
339 if (!wm->pen_is_down && pen_was_down) in wm97xx_pen_irq_worker()
340 wm->pen_is_down = 1; in wm97xx_pen_irq_worker()
343 if (!wm->pen_is_down && wm->mach_ops->acc_enabled) in wm97xx_pen_irq_worker()
344 wm->mach_ops->acc_pen_up(wm); in wm97xx_pen_irq_worker()
346 wm->mach_ops->irq_enable(wm, 1); in wm97xx_pen_irq_worker()
362 if (!work_pending(&wm->pen_event_work)) { in wm97xx_pen_interrupt()
363 wm->mach_ops->irq_enable(wm, 0); in wm97xx_pen_interrupt()
364 queue_work(wm->ts_workq, &wm->pen_event_work); in wm97xx_pen_interrupt()
379 BUG_ON(!wm->mach_ops->irq_enable); in wm97xx_init_pen_irq()
381 if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED, in wm97xx_init_pen_irq()
382 "wm97xx-pen", wm)) { in wm97xx_init_pen_irq()
383 dev_err(wm->dev, in wm97xx_init_pen_irq()
385 wm->pen_irq = 0; in wm97xx_init_pen_irq()
386 return -EINVAL; in wm97xx_init_pen_irq()
390 if (wm->id != WM9705_ID2) { in wm97xx_init_pen_irq()
391 BUG_ON(!wm->mach_ops->irq_gpio); in wm97xx_init_pen_irq()
394 reg & ~(wm->mach_ops->irq_gpio)); in wm97xx_init_pen_irq()
407 mutex_lock(&wm->codec_mutex); in wm97xx_read_samples()
409 if (wm->mach_ops && wm->mach_ops->acc_enabled) in wm97xx_read_samples()
410 rc = wm->mach_ops->acc_pen_down(wm); in wm97xx_read_samples()
412 rc = wm->codec->poll_touch(wm, &data); in wm97xx_read_samples()
415 if (wm->pen_is_down) { in wm97xx_read_samples()
416 wm->pen_is_down = 0; in wm97xx_read_samples()
417 dev_dbg(wm->dev, "pen up\n"); in wm97xx_read_samples()
418 input_report_abs(wm->input_dev, ABS_PRESSURE, 0); in wm97xx_read_samples()
419 input_report_key(wm->input_dev, BTN_TOUCH, 0); in wm97xx_read_samples()
420 input_sync(wm->input_dev); in wm97xx_read_samples()
426 * is actively working with the touchscreen we in wm97xx_read_samples()
432 if (wm->ts_reader_interval < HZ / 10) in wm97xx_read_samples()
433 wm->ts_reader_interval++; in wm97xx_read_samples()
437 dev_dbg(wm->dev, in wm97xx_read_samples()
438 "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n", in wm97xx_read_samples()
439 data.x >> 12, data.x & 0xfff, data.y >> 12, in wm97xx_read_samples()
442 if (abs_x[0] > (data.x & 0xfff) || in wm97xx_read_samples()
443 abs_x[1] < (data.x & 0xfff) || in wm97xx_read_samples()
446 dev_dbg(wm->dev, "Measurement out of range, dropping it\n"); in wm97xx_read_samples()
451 input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); in wm97xx_read_samples()
452 input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); in wm97xx_read_samples()
453 input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); in wm97xx_read_samples()
454 input_report_key(wm->input_dev, BTN_TOUCH, 1); in wm97xx_read_samples()
455 input_sync(wm->input_dev); in wm97xx_read_samples()
456 wm->pen_is_down = 1; in wm97xx_read_samples()
457 wm->ts_reader_interval = wm->ts_reader_min_interval; in wm97xx_read_samples()
459 dev_dbg(wm->dev, "pen down\n"); in wm97xx_read_samples()
460 wm->pen_is_down = 1; in wm97xx_read_samples()
461 wm->ts_reader_interval = wm->ts_reader_min_interval; in wm97xx_read_samples()
465 mutex_unlock(&wm->codec_mutex); in wm97xx_read_samples()
470 * The touchscreen sample reader.
477 BUG_ON(!wm->codec); in wm97xx_ts_reader()
483 if (wm->pen_is_down || !wm->pen_irq) in wm97xx_ts_reader()
484 queue_delayed_work(wm->ts_workq, &wm->ts_reader, in wm97xx_ts_reader()
485 wm->ts_reader_interval); in wm97xx_ts_reader()
489 * wm97xx_ts_input_open - Open the touch screen input device.
492 * Called by the input sub system to open a wm97xx touchscreen device.
493 * Starts the touchscreen thread and touch digitiser.
499 wm->ts_workq = alloc_ordered_workqueue("kwm97xx", 0); in wm97xx_ts_input_open()
500 if (wm->ts_workq == NULL) { in wm97xx_ts_input_open()
501 dev_err(wm->dev, in wm97xx_ts_input_open()
503 return -EINVAL; in wm97xx_ts_input_open()
507 if (wm->mach_ops && wm->mach_ops->acc_enabled) in wm97xx_ts_input_open()
508 wm->codec->acc_enable(wm, 1); in wm97xx_ts_input_open()
509 wm->codec->dig_enable(wm, 1); in wm97xx_ts_input_open()
511 INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader); in wm97xx_ts_input_open()
512 INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker); in wm97xx_ts_input_open()
514 wm->ts_reader_min_interval = HZ >= 100 ? HZ / 100 : 1; in wm97xx_ts_input_open()
515 if (wm->ts_reader_min_interval < 1) in wm97xx_ts_input_open()
516 wm->ts_reader_min_interval = 1; in wm97xx_ts_input_open()
517 wm->ts_reader_interval = wm->ts_reader_min_interval; in wm97xx_ts_input_open()
519 wm->pen_is_down = 0; in wm97xx_ts_input_open()
520 if (wm->pen_irq) in wm97xx_ts_input_open()
523 dev_err(wm->dev, "No IRQ specified\n"); in wm97xx_ts_input_open()
528 if (wm->pen_irq == 0) in wm97xx_ts_input_open()
529 queue_delayed_work(wm->ts_workq, &wm->ts_reader, in wm97xx_ts_input_open()
530 wm->ts_reader_interval); in wm97xx_ts_input_open()
536 * wm97xx_ts_input_close - Close the touch screen input device.
539 * Called by the input sub system to close a wm97xx touchscreen
540 * device. Kills the touchscreen thread and stops the touch
549 if (wm->pen_irq) { in wm97xx_ts_input_close()
551 if (wm->id != WM9705_ID2) { in wm97xx_ts_input_close()
552 BUG_ON(!wm->mach_ops->irq_gpio); in wm97xx_ts_input_close()
555 reg | wm->mach_ops->irq_gpio); in wm97xx_ts_input_close()
558 free_irq(wm->pen_irq, wm); in wm97xx_ts_input_close()
561 wm->pen_is_down = 0; in wm97xx_ts_input_close()
564 if (cancel_work_sync(&wm->pen_event_work)) in wm97xx_ts_input_close()
565 wm->mach_ops->irq_enable(wm, 1); in wm97xx_ts_input_close()
570 cancel_delayed_work_sync(&wm->ts_reader); in wm97xx_ts_input_close()
572 destroy_workqueue(wm->ts_workq); in wm97xx_ts_input_close()
575 wm->codec->dig_enable(wm, 0); in wm97xx_ts_input_close()
576 if (wm->mach_ops && wm->mach_ops->acc_enabled) in wm97xx_ts_input_close()
577 wm->codec->acc_enable(wm, 0); in wm97xx_ts_input_close()
582 struct wm97xx_pdata *pdata = dev_get_platdata(wm->dev); in wm97xx_register_touch()
585 wm->input_dev = devm_input_allocate_device(wm->dev); in wm97xx_register_touch()
586 if (wm->input_dev == NULL) in wm97xx_register_touch()
587 return -ENOMEM; in wm97xx_register_touch()
590 wm->input_dev->name = "wm97xx touchscreen"; in wm97xx_register_touch()
591 wm->input_dev->phys = "wm97xx"; in wm97xx_register_touch()
592 wm->input_dev->open = wm97xx_ts_input_open; in wm97xx_register_touch()
593 wm->input_dev->close = wm97xx_ts_input_close; in wm97xx_register_touch()
595 __set_bit(EV_ABS, wm->input_dev->evbit); in wm97xx_register_touch()
596 __set_bit(EV_KEY, wm->input_dev->evbit); in wm97xx_register_touch()
597 __set_bit(BTN_TOUCH, wm->input_dev->keybit); in wm97xx_register_touch()
599 input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1], in wm97xx_register_touch()
601 input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1], in wm97xx_register_touch()
603 input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1], in wm97xx_register_touch()
606 input_set_drvdata(wm->input_dev, wm); in wm97xx_register_touch()
607 wm->input_dev->dev.parent = wm->dev; in wm97xx_register_touch()
609 ret = input_register_device(wm->input_dev); in wm97xx_register_touch()
617 wm->touch_dev = platform_device_alloc("wm97xx-touch", -1); in wm97xx_register_touch()
618 if (!wm->touch_dev) { in wm97xx_register_touch()
619 ret = -ENOMEM; in wm97xx_register_touch()
622 platform_set_drvdata(wm->touch_dev, wm); in wm97xx_register_touch()
623 wm->touch_dev->dev.parent = wm->dev; in wm97xx_register_touch()
624 wm->touch_dev->dev.platform_data = pdata; in wm97xx_register_touch()
625 ret = platform_device_add(wm->touch_dev); in wm97xx_register_touch()
631 platform_device_put(wm->touch_dev); in wm97xx_register_touch()
633 input_unregister_device(wm->input_dev); in wm97xx_register_touch()
634 wm->input_dev = NULL; in wm97xx_register_touch()
641 platform_device_unregister(wm->touch_dev); in wm97xx_unregister_touch()
642 input_unregister_device(wm->input_dev); in wm97xx_unregister_touch()
643 wm->input_dev = NULL; in wm97xx_unregister_touch()
650 mutex_init(&wm->codec_mutex); in _wm97xx_probe()
651 dev_set_drvdata(wm->dev, wm); in _wm97xx_probe()
656 dev_err(wm->dev, in _wm97xx_probe()
657 "Device with vendor %04x is not a wm97xx\n", id); in _wm97xx_probe()
658 return -ENODEV; in _wm97xx_probe()
661 wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); in _wm97xx_probe()
663 wm->variant = WM97xx_GENERIC; in _wm97xx_probe()
665 dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); in _wm97xx_probe()
667 switch (wm->id & 0xff) { in _wm97xx_probe()
670 wm->codec = &wm9705_codec; in _wm97xx_probe()
675 wm->codec = &wm9712_codec; in _wm97xx_probe()
680 wm->codec = &wm9713_codec; in _wm97xx_probe()
684 dev_err(wm->dev, "Support for wm97%02x not compiled in.\n", in _wm97xx_probe()
685 wm->id & 0xff); in _wm97xx_probe()
686 return -ENODEV; in _wm97xx_probe()
690 wm->codec->phy_init(wm); in _wm97xx_probe()
693 wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG); in _wm97xx_probe()
694 wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); in _wm97xx_probe()
695 wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY); in _wm97xx_probe()
696 wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP); in _wm97xx_probe()
697 wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS); in _wm97xx_probe()
698 wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE); in _wm97xx_probe()
705 platform_device_unregister(wm->battery_dev); in wm97xx_remove_battery()
713 wm->battery_dev = platform_device_alloc("wm97xx-battery", -1); in wm97xx_add_battery()
714 if (!wm->battery_dev) in wm97xx_add_battery()
715 return -ENOMEM; in wm97xx_add_battery()
717 platform_set_drvdata(wm->battery_dev, wm); in wm97xx_add_battery()
718 wm->battery_dev->dev.parent = wm->dev; in wm97xx_add_battery()
719 wm->battery_dev->dev.platform_data = pdata; in wm97xx_add_battery()
720 ret = platform_device_add(wm->battery_dev); in wm97xx_add_battery()
722 platform_device_put(wm->battery_dev); in wm97xx_add_battery()
735 return -ENOMEM; in wm97xx_probe()
737 wm->dev = dev; in wm97xx_probe()
738 wm->ac97 = to_ac97_t(dev); in wm97xx_probe()
744 ret = wm97xx_add_battery(wm, pdata ? pdata->batt_pdata : NULL); in wm97xx_probe()
768 struct wm97xx_platform_data *mfd_pdata = dev_get_platdata(&pdev->dev); in wm97xx_mfd_probe()
771 wm = devm_kzalloc(&pdev->dev, sizeof(struct wm97xx), GFP_KERNEL); in wm97xx_mfd_probe()
773 return -ENOMEM; in wm97xx_mfd_probe()
775 wm->dev = &pdev->dev; in wm97xx_mfd_probe()
776 wm->ac97 = mfd_pdata->ac97; in wm97xx_mfd_probe()
782 ret = wm97xx_add_battery(wm, mfd_pdata->batt_pdata); in wm97xx_mfd_probe()
795 return wm97xx_remove(&pdev->dev); in wm97xx_mfd_remove()
804 if (device_may_wakeup(&wm->input_dev->dev)) in wm97xx_suspend()
805 suspend_mode = wm->suspend_mode; in wm97xx_suspend()
809 if (wm->input_dev->users) in wm97xx_suspend()
810 cancel_delayed_work_sync(&wm->ts_reader); in wm97xx_suspend()
815 if (wm->input_dev->users) in wm97xx_suspend()
817 wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg); in wm97xx_suspend()
819 /* WM9713 has an additional power bit - turn it off if there in wm97xx_suspend()
821 if (wm->id == WM9713_ID2 && in wm97xx_suspend()
822 (!wm->input_dev->users || !suspend_mode)) { in wm97xx_suspend()
835 if (wm->id == WM9713_ID2) { in wm97xx_resume()
836 wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]); in wm97xx_resume()
837 wm97xx_reg_write(wm, 0x5a, wm->misc); in wm97xx_resume()
838 if (wm->input_dev->users) { in wm97xx_resume()
845 wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]); in wm97xx_resume()
846 wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]); in wm97xx_resume()
848 wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]); in wm97xx_resume()
849 wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]); in wm97xx_resume()
850 wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]); in wm97xx_resume()
851 wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]); in wm97xx_resume()
852 wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]); in wm97xx_resume()
853 wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]); in wm97xx_resume()
855 if (wm->input_dev->users && !wm->pen_irq) { in wm97xx_resume()
856 wm->ts_reader_interval = wm->ts_reader_min_interval; in wm97xx_resume()
857 queue_delayed_work(wm->ts_workq, &wm->ts_reader, in wm97xx_resume()
858 wm->ts_reader_interval); in wm97xx_resume()
872 mutex_lock(&wm->codec_mutex); in wm97xx_register_mach_ops()
873 if (wm->mach_ops) { in wm97xx_register_mach_ops()
874 mutex_unlock(&wm->codec_mutex); in wm97xx_register_mach_ops()
875 return -EINVAL; in wm97xx_register_mach_ops()
877 wm->mach_ops = mach_ops; in wm97xx_register_mach_ops()
878 mutex_unlock(&wm->codec_mutex); in wm97xx_register_mach_ops()
886 mutex_lock(&wm->codec_mutex); in wm97xx_unregister_mach_ops()
887 wm->mach_ops = NULL; in wm97xx_unregister_mach_ops()
888 mutex_unlock(&wm->codec_mutex); in wm97xx_unregister_mach_ops()
893 .name = "wm97xx-ts",
905 .name = "wm97xx-ts",
937 MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");