Lines Matching +full:read +full:- +full:strobe +full:- +full:delay
1 // SPDX-License-Identifier: GPL-2.0-only
11 #include <linux/delay.h>
30 /* key debounce interval in milli-second */
52 * HiZ when de-activated to cause minmal side effect when scanning other
59 gpiod_direction_output(keypad->col_gpios[col], 1);
61 gpiod_set_value_cansleep(keypad->col_gpios[col], 0);
62 if (!keypad->drive_inactive_cols)
63 gpiod_direction_input(keypad->col_gpios[col]);
71 if (on && keypad->col_scan_delay_us)
72 fsleep(keypad->col_scan_delay_us);
79 for (col = 0; col < keypad->num_col_gpios; col++)
82 if (on && keypad->all_cols_on_delay_us)
83 fsleep(keypad->all_cols_on_delay_us);
88 return gpiod_get_value_cansleep(keypad->row_gpios[row]);
95 for (i = 0; i < keypad->num_row_gpios; i++)
96 enable_irq(keypad->row_irqs[i]);
103 for (i = 0; i < keypad->num_row_gpios; i++)
104 disable_irq_nosync(keypad->row_irqs[i]);
114 struct input_dev *input_dev = keypad->input_dev;
115 const unsigned short *keycodes = input_dev->keycode;
119 /* de-activate all columns for scanning */
124 for (row = 0; row < keypad->num_row_gpios; row++)
125 gpiod_direction_input(keypad->row_gpios[row]);
127 /* assert each column and read the row status out */
128 for (col = 0; col < keypad->num_col_gpios; col++) {
132 for (row = 0; row < keypad->num_row_gpios; row++)
139 for (col = 0; col < keypad->num_col_gpios; col++) {
142 bits_changed = keypad->last_key_state[col] ^ new_state[col];
146 for (row = 0; row < keypad->num_row_gpios; row++) {
150 code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
159 memcpy(keypad->last_key_state, new_state, sizeof(new_state));
164 scoped_guard(spinlock_irq, &keypad->lock) {
165 keypad->scan_pending = false;
174 guard(spinlock_irqsave)(&keypad->lock);
181 if (unlikely(keypad->scan_pending || keypad->stopped))
185 keypad->scan_pending = true;
186 schedule_delayed_work(&keypad->work,
187 msecs_to_jiffies(keypad->debounce_ms));
197 keypad->stopped = false;
204 schedule_delayed_work(&keypad->work, 0);
213 scoped_guard(spinlock_irq, &keypad->lock) {
214 keypad->stopped = true;
217 flush_delayed_work(&keypad->work);
229 for_each_clear_bit(i, keypad->wakeup_enabled_irqs,
230 keypad->num_row_gpios)
231 if (enable_irq_wake(keypad->row_irqs[i]) == 0)
232 __set_bit(i, keypad->wakeup_enabled_irqs);
239 for_each_set_bit(i, keypad->wakeup_enabled_irqs,
240 keypad->num_row_gpios) {
241 disable_irq_wake(keypad->row_irqs[i]);
242 __clear_bit(i, keypad->wakeup_enabled_irqs);
251 matrix_keypad_stop(keypad->input_dev);
253 if (device_may_wakeup(&pdev->dev))
264 if (device_may_wakeup(&pdev->dev))
267 matrix_keypad_start(keypad->input_dev);
283 nrow = gpiod_count(&pdev->dev, "row");
284 ncol = gpiod_count(&pdev->dev, "col");
286 dev_err(&pdev->dev, "missing row or column GPIOs\n");
287 return -EINVAL;
290 keypad->num_row_gpios = nrow;
291 keypad->num_col_gpios = ncol;
293 active_low = device_property_read_bool(&pdev->dev, "gpio-activelow");
295 /* initialize strobe lines as outputs, activated */
296 for (i = 0; i < keypad->num_col_gpios; i++) {
297 keypad->col_gpios[i] = devm_gpiod_get_index(&pdev->dev, "col",
299 err = PTR_ERR_OR_ZERO(keypad->col_gpios[i]);
301 dev_err(&pdev->dev,
307 gpiod_set_consumer_name(keypad->col_gpios[i], "matrix_kbd_col");
309 if (active_low ^ gpiod_is_active_low(keypad->col_gpios[i]))
310 gpiod_toggle_active_low(keypad->col_gpios[i]);
312 gpiod_direction_output(keypad->col_gpios[i], 1);
315 for (i = 0; i < keypad->num_row_gpios; i++) {
316 keypad->row_gpios[i] = devm_gpiod_get_index(&pdev->dev, "row",
318 err = PTR_ERR_OR_ZERO(keypad->row_gpios[i]);
320 dev_err(&pdev->dev,
326 gpiod_set_consumer_name(keypad->row_gpios[i], "matrix_kbd_row");
328 if (active_low ^ gpiod_is_active_low(keypad->row_gpios[i]))
329 gpiod_toggle_active_low(keypad->row_gpios[i]);
342 for (i = 0; i < keypad->num_row_gpios; i++) {
343 irq = gpiod_to_irq(keypad->row_gpios[i]);
346 dev_err(&pdev->dev,
352 err = devm_request_any_context_irq(&pdev->dev, irq,
356 "matrix-keypad", keypad);
358 dev_err(&pdev->dev,
364 keypad->row_irqs[i] = irq;
367 /* initialized as disabled - enabled by input->open */
380 keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
382 return -ENOMEM;
384 input_dev = devm_input_allocate_device(&pdev->dev);
386 return -ENOMEM;
388 keypad->input_dev = input_dev;
389 keypad->stopped = true;
390 INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
391 spin_lock_init(&keypad->lock);
393 keypad->drive_inactive_cols =
394 device_property_read_bool(&pdev->dev, "drive-inactive-cols");
395 device_property_read_u32(&pdev->dev, "debounce-delay-ms",
396 &keypad->debounce_ms);
397 device_property_read_u32(&pdev->dev, "col-scan-delay-us",
398 &keypad->col_scan_delay_us);
399 device_property_read_u32(&pdev->dev, "all-cols-on-delay-us",
400 &keypad->all_cols_on_delay_us);
406 keypad->row_shift = get_count_order(keypad->num_col_gpios);
412 input_dev->name = pdev->name;
413 input_dev->id.bustype = BUS_HOST;
414 input_dev->open = matrix_keypad_start;
415 input_dev->close = matrix_keypad_stop;
418 keypad->num_row_gpios,
419 keypad->num_col_gpios,
422 dev_err(&pdev->dev, "failed to build keymap\n");
423 return -ENOMEM;
426 if (!device_property_read_bool(&pdev->dev, "linux,no-autorepeat"))
427 __set_bit(EV_REP, input_dev->evbit);
432 err = input_register_device(keypad->input_dev);
436 wakeup = device_property_read_bool(&pdev->dev, "wakeup-source") ||
438 device_property_read_bool(&pdev->dev, "linux,wakeup");
439 device_init_wakeup(&pdev->dev, wakeup);
448 { .compatible = "gpio-matrix-keypad" },
457 .name = "matrix-keypad",
467 MODULE_ALIAS("platform:matrix-keypad");