From patchwork Mon Aug 5 01:47:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 13753062 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F07F3C3DA7F for ; Mon, 5 Aug 2024 01:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=3W9Xny5Oe2jyjvAS76xpniX/sLkXGO8PpSiALjSSUIs=; b=aekNlFHvLeFDslYK+r0gM9uck7 eBhYIwVFYKj8zuIqVpHMAZLtoNm3ajPBAyG6tJxyoOAkyPVRNsDTVTcmTpixGQkyOE2KTjTpgBFYD UD4Y6oYDhN0jEG2+wtnkvUZIWTvPjwGTC3t64qPu+kh9T7xCjR9/ANAfibNOClfGS5nuaotVBwrVt I989zcdOw9hSnaPnmHI5qT9fhQZk130ukJeYOeAsfX3Vn/4L1aA8XRf6CTkPLcJ+1MTtQVFAffNgn qXGiZlzM/dPWzVckL6ke+UGyDF7fnUMs0uBDYKvmBOOWvQd4koiFmrxZ/dMGyRgi0g5BCox0kC1AG fKGPUOYw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1samqR-0000000EKoN-3E08; Mon, 05 Aug 2024 01:49:07 +0000 Received: from mail-pl1-x635.google.com ([2607:f8b0:4864:20::635]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1samon-0000000EKHQ-0YK4 for linux-arm-kernel@lists.infradead.org; Mon, 05 Aug 2024 01:47:26 +0000 Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1fc60c3ead4so68971975ad.0 for ; Sun, 04 Aug 2024 18:47:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1722822444; x=1723427244; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3W9Xny5Oe2jyjvAS76xpniX/sLkXGO8PpSiALjSSUIs=; b=hSDd+PcMukYJkwZvbwdmPbL68+SymOB1P6PdBywCl02lO6KAHjsomG1I/LLqqr2sg0 tXuMfdfVVMa1ZvlQb6TEB98hKdMN8ZDmIEZv1FkZU/mDcmIAFNeWh4Z3ke6aBOPOXhCg ZbLTAYYFWi8Nl6hxzG+PjiY3jaEQ5Oy5P0QcbKLnxmNN+xgEW8FwSMiZlx+pxlf+DVuh YPrEPpG56pGOJIrpZSuvCbkSW4aw2136pMEqSeVB9tzxEwUOrT0T4xuNvOEdZbvdMgSI 9D62E7BBdrgrogG2LPikHgRveYbkXInrnbKtLkU/RqV1LNsD65JNx2aBVhD0IU3vsjxa EUFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722822444; x=1723427244; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3W9Xny5Oe2jyjvAS76xpniX/sLkXGO8PpSiALjSSUIs=; b=VJfEhoLlDP4w7p3dkOONDpP+VynqJKptI/+nnpEAxNewe52Y/L0QqNzuDfaLEAf4A7 iGuR3OShT8oxWaFTnN7AEOV/GjtoklIkhCKCv5BOLcZdEF0f7UErffo30V+Bf200Y+o8 5LtrRNcOZ1TSne5pIviARmYbIAOcH2UUM80ogIKSblb1DnbPMujlUdFUj9kLFmu0yhjt hsA8y4in74om2AyeUvdJpcxsee27fIrrZlXTnd9bfumtYpYV5CzBVQ6t5JlhLfpxuF1V US9LwGIY3UTqvth2oG6xtY0gWduSXtno/iBSd3SQ86sjQbux5IvkU31bqPo1RI1LANKT fXcw== X-Gm-Message-State: AOJu0Yx1KcvwlRtNCYQt5CR41zKrxgt2JLsa+ZhmctQu9TC+kJiR0f1/ bX2alX25Xz81t1IWu9sDCB85S+Yqiz7PmgwM3LuFRAkBpcZxMf2D X-Google-Smtp-Source: AGHT+IG2qk2UX76WiKnUEfoLNtj9w3mHbdNpAlFnbpU8lmTUrz8S1fXH3OJw5hl3xcahnItIgN3FOQ== X-Received: by 2002:a17:902:b70d:b0:1ff:3b0f:d5e2 with SMTP id d9443c01a7336-1ff5737e3abmr89071635ad.32.1722822443699; Sun, 04 Aug 2024 18:47:23 -0700 (PDT) Received: from dtor-ws.sjc.corp.google.com ([2620:15c:9d:2:22e4:17a:28a:7497]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1ff59295790sm55836015ad.261.2024.08.04.18.47.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 04 Aug 2024 18:47:23 -0700 (PDT) From: Dmitry Torokhov To: Haojian Zhuang , Daniel Mack , Robert Jarzmik , Arnd Bergmann , Linus Walleij , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-input@vger.kernel.org Subject: [PATCH 2/5] Input: matrix_keypad - switch to gpiod API and generic device properties Date: Sun, 4 Aug 2024 18:47:05 -0700 Message-ID: <20240805014710.1961677-3-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.46.0.rc2.264.g509ed76dc8-goog In-Reply-To: <20240805014710.1961677-1-dmitry.torokhov@gmail.com> References: <20240805014710.1961677-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240804_184725_211758_4460D799 X-CRM114-Status: GOOD ( 27.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org gpiod API and generic device properties work with software nodes and static properties, which will allow removing platform data support from the driver, simplifying and streamlining the code. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/matrix_keypad.c | 341 ++++++++++++++----------- 1 file changed, 185 insertions(+), 156 deletions(-) diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 604e90d13ed0..5f7e6f27e9c5 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -17,17 +17,26 @@ #include #include #include +#include #include #include #include -#include -#include struct matrix_keypad { - const struct matrix_keypad_platform_data *pdata; struct input_dev *input_dev; unsigned int row_shift; + unsigned int col_scan_delay_us; + /* key debounce interval in milli-second */ + unsigned int debounce_ms; + bool drive_inactive_cols; + + struct gpio_desc *row_gpios[MATRIX_MAX_ROWS]; + unsigned int num_row_gpios; + + struct gpio_desc *col_gpios[MATRIX_MAX_ROWS]; + unsigned int num_col_gpios; + unsigned int row_irqs[MATRIX_MAX_ROWS]; DECLARE_BITMAP(wakeup_enabled_irqs, MATRIX_MAX_ROWS); @@ -44,50 +53,43 @@ struct matrix_keypad { * columns. In that case it is configured here to be input, otherwise it is * driven with the inactive value. */ -static void __activate_col(const struct matrix_keypad_platform_data *pdata, - int col, bool on) +static void __activate_col(struct matrix_keypad *keypad, int col, bool on) { - bool level_on = !pdata->active_low; - if (on) { - gpio_direction_output(pdata->col_gpios[col], level_on); + gpiod_direction_output(keypad->col_gpios[col], 1); } else { - gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); - if (!pdata->drive_inactive_cols) - gpio_direction_input(pdata->col_gpios[col]); + gpiod_set_value_cansleep(keypad->col_gpios[col], 0); + if (!keypad->drive_inactive_cols) + gpiod_direction_input(keypad->col_gpios[col]); } } -static void activate_col(const struct matrix_keypad_platform_data *pdata, - int col, bool on) +static void activate_col(struct matrix_keypad *keypad, int col, bool on) { - __activate_col(pdata, col, on); + __activate_col(keypad, col, on); - if (on && pdata->col_scan_delay_us) - udelay(pdata->col_scan_delay_us); + if (on && keypad->col_scan_delay_us) + udelay(keypad->col_scan_delay_us); } -static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, - bool on) +static void activate_all_cols(struct matrix_keypad *keypad, bool on) { int col; - for (col = 0; col < pdata->num_col_gpios; col++) - __activate_col(pdata, col, on); + for (col = 0; col < keypad->num_col_gpios; col++) + __activate_col(keypad, col, on); } -static bool row_asserted(const struct matrix_keypad_platform_data *pdata, - int row) +static bool row_asserted(struct matrix_keypad *keypad, int row) { - return gpio_get_value_cansleep(pdata->row_gpios[row]) ? - !pdata->active_low : pdata->active_low; + return gpiod_get_value_cansleep(keypad->row_gpios[row]); } static void enable_row_irqs(struct matrix_keypad *keypad) { int i; - for (i = 0; i < keypad->pdata->num_row_gpios; i++) + for (i = 0; i < keypad->num_row_gpios; i++) enable_irq(keypad->row_irqs[i]); } @@ -95,7 +97,7 @@ static void disable_row_irqs(struct matrix_keypad *keypad) { int i; - for (i = 0; i < keypad->pdata->num_row_gpios; i++) + for (i = 0; i < keypad->num_row_gpios; i++) disable_irq_nosync(keypad->row_irqs[i]); } @@ -108,39 +110,38 @@ static void matrix_keypad_scan(struct work_struct *work) container_of(work, struct matrix_keypad, work.work); struct input_dev *input_dev = keypad->input_dev; const unsigned short *keycodes = input_dev->keycode; - const struct matrix_keypad_platform_data *pdata = keypad->pdata; uint32_t new_state[MATRIX_MAX_COLS]; int row, col, code; /* de-activate all columns for scanning */ - activate_all_cols(pdata, false); + activate_all_cols(keypad, false); memset(new_state, 0, sizeof(new_state)); - for (row = 0; row < pdata->num_row_gpios; row++) - gpio_direction_input(pdata->row_gpios[row]); + for (row = 0; row < keypad->num_row_gpios; row++) + gpiod_direction_input(keypad->row_gpios[row]); /* assert each column and read the row status out */ - for (col = 0; col < pdata->num_col_gpios; col++) { + for (col = 0; col < keypad->num_col_gpios; col++) { - activate_col(pdata, col, true); + activate_col(keypad, col, true); - for (row = 0; row < pdata->num_row_gpios; row++) + for (row = 0; row < keypad->num_row_gpios; row++) new_state[col] |= - row_asserted(pdata, row) ? (1 << row) : 0; + row_asserted(keypad, row) ? BIT(row) : 0; - activate_col(pdata, col, false); + activate_col(keypad, col, false); } - for (col = 0; col < pdata->num_col_gpios; col++) { + for (col = 0; col < keypad->num_col_gpios; col++) { uint32_t bits_changed; bits_changed = keypad->last_key_state[col] ^ new_state[col]; if (bits_changed == 0) continue; - for (row = 0; row < pdata->num_row_gpios; row++) { - if ((bits_changed & (1 << row)) == 0) + for (row = 0; row < keypad->num_row_gpios; row++) { + if (!(bits_changed & BIT(row))) continue; code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); @@ -154,7 +155,7 @@ static void matrix_keypad_scan(struct work_struct *work) memcpy(keypad->last_key_state, new_state, sizeof(new_state)); - activate_all_cols(pdata, true); + activate_all_cols(keypad, true); /* Enable IRQs again */ spin_lock_irq(&keypad->lock); @@ -181,7 +182,7 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id) disable_row_irqs(keypad); keypad->scan_pending = true; schedule_delayed_work(&keypad->work, - msecs_to_jiffies(keypad->pdata->debounce_ms)); + msecs_to_jiffies(keypad->debounce_ms)); out: spin_unlock_irqrestore(&keypad->lock, flags); @@ -225,7 +226,7 @@ static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) int i; for_each_clear_bit(i, keypad->wakeup_enabled_irqs, - keypad->pdata->num_row_gpios) + keypad->num_row_gpios) if (enable_irq_wake(keypad->row_irqs[i]) == 0) __set_bit(i, keypad->wakeup_enabled_irqs); } @@ -235,7 +236,7 @@ static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad) int i; for_each_set_bit(i, keypad->wakeup_enabled_irqs, - keypad->pdata->num_row_gpios) { + keypad->num_row_gpios) { disable_irq_wake(keypad->row_irqs[i]); __clear_bit(i, keypad->wakeup_enabled_irqs); } @@ -270,11 +271,14 @@ static int matrix_keypad_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, matrix_keypad_suspend, matrix_keypad_resume); -static int matrix_keypad_init_gpio(struct platform_device *pdev, - struct matrix_keypad *keypad) +static int matrix_keypad_init_pdata_gpio(struct platform_device *pdev, + const struct matrix_keypad_platform_data *pdata, + struct matrix_keypad *keypad) { - const struct matrix_keypad_platform_data *pdata = keypad->pdata; - int i, irq, err; + int i, err; + + keypad->num_col_gpios = pdata->num_col_gpios; + keypad->num_row_gpios = pdata->num_row_gpios; /* initialized strobe lines as outputs, activated */ for (i = 0; i < pdata->num_col_gpios; i++) { @@ -287,7 +291,12 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev, return err; } - gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); + keypad->col_gpios[i] = gpio_to_desc(pdata->col_gpios[i]); + + if (pdata->active_low ^ gpiod_is_active_low(keypad->col_gpios[i])) + gpiod_toggle_active_low(keypad->col_gpios[i]); + + gpiod_direction_output(keypad->col_gpios[i], 1); } for (i = 0; i < pdata->num_row_gpios; i++) { @@ -300,137 +309,125 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev, return err; } - gpio_direction_input(pdata->row_gpios[i]); - } - - for (i = 0; i < pdata->num_row_gpios; i++) { - irq = gpio_to_irq(pdata->row_gpios[i]); - if (irq < 0) { - err = irq; - dev_err(&pdev->dev, - "Unable to convert GPIO line %i to irq: %d\n", - pdata->row_gpios[i], err); - return err; - } + keypad->row_gpios[i] = gpio_to_desc(pdata->row_gpios[i]); - err = devm_request_any_context_irq(&pdev->dev, - irq, - matrix_keypad_interrupt, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, - "matrix-keypad", keypad); - if (err < 0) { - dev_err(&pdev->dev, - "Unable to acquire interrupt for GPIO line %i\n", - pdata->row_gpios[i]); - return err; - } + if (pdata->active_low ^ gpiod_is_active_low(keypad->row_gpios[i])) + gpiod_toggle_active_low(keypad->row_gpios[i]); - keypad->row_irqs[i] = irq; + gpiod_direction_input(keypad->row_gpios[i]); } - /* initialized as disabled - enabled by input->open */ - disable_row_irqs(keypad); - return 0; } -#ifdef CONFIG_OF -static struct matrix_keypad_platform_data * -matrix_keypad_parse_dt(struct device *dev) +static int matrix_keypad_init_gpio(struct platform_device *pdev, + struct matrix_keypad *keypad) { - struct matrix_keypad_platform_data *pdata; - struct device_node *np = dev->of_node; - unsigned int *gpios; - int ret, i, nrow, ncol; - - if (!np) { - dev_err(dev, "device lacks DT data\n"); - return ERR_PTR(-ENODEV); - } - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "could not allocate memory for platform data\n"); - return ERR_PTR(-ENOMEM); - } + bool active_low; + int nrow, ncol; + int err; + int i; - pdata->num_row_gpios = nrow = gpiod_count(dev, "row"); - pdata->num_col_gpios = ncol = gpiod_count(dev, "col"); + nrow = gpiod_count(&pdev->dev, "row"); + ncol = gpiod_count(&pdev->dev, "col"); if (nrow < 0 || ncol < 0) { - dev_err(dev, "number of keypad rows/columns not specified\n"); - return ERR_PTR(-EINVAL); + dev_err(&pdev->dev, "missing row or column GPIOs\n"); + return -EINVAL; } - pdata->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat"); + keypad->num_row_gpios = nrow; + keypad->num_col_gpios = ncol; - pdata->wakeup = of_property_read_bool(np, "wakeup-source") || - of_property_read_bool(np, "linux,wakeup"); /* legacy */ + active_low = device_property_read_bool(&pdev->dev, "gpio-activelow"); - pdata->active_low = of_property_read_bool(np, "gpio-activelow"); + /* initialize strobe lines as outputs, activated */ + for (i = 0; i < keypad->num_col_gpios; i++) { + keypad->col_gpios[i] = devm_gpiod_get_index(&pdev->dev, "col", + i, GPIOD_ASIS); + err = PTR_ERR_OR_ZERO(keypad->col_gpios[i]); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO for COL%d: %d\n", + i, err); + return err; + } - pdata->drive_inactive_cols = - of_property_read_bool(np, "drive-inactive-cols"); + gpiod_set_consumer_name(keypad->col_gpios[i], "matrix_kbd_col"); - of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms); - of_property_read_u32(np, "col-scan-delay-us", - &pdata->col_scan_delay_us); + if (active_low ^ gpiod_is_active_low(keypad->col_gpios[i])) + gpiod_toggle_active_low(keypad->col_gpios[i]); - gpios = devm_kcalloc(dev, - pdata->num_row_gpios + pdata->num_col_gpios, - sizeof(unsigned int), - GFP_KERNEL); - if (!gpios) { - dev_err(dev, "could not allocate memory for gpios\n"); - return ERR_PTR(-ENOMEM); + gpiod_direction_output(keypad->col_gpios[i], 1); } - for (i = 0; i < nrow; i++) { - ret = of_get_named_gpio(np, "row-gpios", i); - if (ret < 0) - return ERR_PTR(ret); - gpios[i] = ret; - } + for (i = 0; i < keypad->num_row_gpios; i++) { + keypad->row_gpios[i] = devm_gpiod_get_index(&pdev->dev, "row", + i, GPIOD_IN); + err = PTR_ERR_OR_ZERO(keypad->row_gpios[i]); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO for ROW%d: %d\n", + i, err); + return err; + } - for (i = 0; i < ncol; i++) { - ret = of_get_named_gpio(np, "col-gpios", i); - if (ret < 0) - return ERR_PTR(ret); - gpios[nrow + i] = ret; - } + gpiod_set_consumer_name(keypad->row_gpios[i], "matrix_kbd_row"); - pdata->row_gpios = gpios; - pdata->col_gpios = &gpios[pdata->num_row_gpios]; + if (active_low ^ gpiod_is_active_low(keypad->row_gpios[i])) + gpiod_toggle_active_low(keypad->row_gpios[i]); + } - return pdata; + return 0; } -#else -static inline struct matrix_keypad_platform_data * -matrix_keypad_parse_dt(struct device *dev) + +static int matrix_keypad_setup_interrupts(struct platform_device *pdev, + struct matrix_keypad *keypad) { - dev_err(dev, "no platform data defined\n"); + int err; + int irq; + int i; + + for (i = 0; i < keypad->num_row_gpios; i++) { + irq = gpiod_to_irq(keypad->row_gpios[i]); + if (irq < 0) { + err = irq; + dev_err(&pdev->dev, + "Unable to convert GPIO line %i to irq: %d\n", + i, err); + return err; + } + + err = devm_request_any_context_irq(&pdev->dev, irq, + matrix_keypad_interrupt, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "matrix-keypad", keypad); + if (err < 0) { + dev_err(&pdev->dev, + "Unable to acquire interrupt for row %i: %d\n", + i, err); + return err; + } + + keypad->row_irqs[i] = irq; + } - return ERR_PTR(-EINVAL); + /* initialized as disabled - enabled by input->open */ + disable_row_irqs(keypad); + + return 0; } -#endif static int matrix_keypad_probe(struct platform_device *pdev) { - const struct matrix_keypad_platform_data *pdata; + const struct matrix_keypad_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct matrix_keypad *keypad; struct input_dev *input_dev; + bool autorepeat; + bool wakeup; int err; - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - pdata = matrix_keypad_parse_dt(&pdev->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } else if (!pdata->keymap_data) { - dev_err(&pdev->dev, "no keymap data defined\n"); - return -EINVAL; - } - keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); if (!keypad) return -ENOMEM; @@ -440,40 +437,72 @@ static int matrix_keypad_probe(struct platform_device *pdev) return -ENOMEM; keypad->input_dev = input_dev; - keypad->pdata = pdata; - keypad->row_shift = get_count_order(pdata->num_col_gpios); keypad->stopped = true; INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); spin_lock_init(&keypad->lock); + keypad->drive_inactive_cols = + device_property_read_bool(&pdev->dev, "drive-inactive-cols"); + device_property_read_u32(&pdev->dev, "debounce-delay-ms", + &keypad->debounce_ms); + device_property_read_u32(&pdev->dev, "col-scan-delay-us", + &keypad->col_scan_delay_us); + + if (pdata) { + keypad->col_scan_delay_us = pdata->col_scan_delay_us; + keypad->debounce_ms = pdata->debounce_ms; + keypad->drive_inactive_cols = pdata->drive_inactive_cols; + } + + if (pdata) + err = matrix_keypad_init_pdata_gpio(pdev, pdata, keypad); + else + err = matrix_keypad_init_gpio(pdev, keypad); + if (err) + return err; + + keypad->row_shift = get_count_order(keypad->num_col_gpios); + + err = matrix_keypad_setup_interrupts(pdev, keypad); + if (err) + return err; + input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; - err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, - pdata->num_row_gpios, - pdata->num_col_gpios, + err = matrix_keypad_build_keymap(pdata ? pdata->keymap_data : NULL, + NULL, + keypad->num_row_gpios, + keypad->num_col_gpios, NULL, input_dev); if (err) { dev_err(&pdev->dev, "failed to build keymap\n"); return -ENOMEM; } - if (!pdata->no_autorepeat) + autorepeat = !device_property_read_bool(&pdev->dev, + "linux,no-autorepeat"); + if (autorepeat && pdata->no_autorepeat) + autorepeat = false; + if (autorepeat) __set_bit(EV_REP, input_dev->evbit); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); - err = matrix_keypad_init_gpio(pdev, keypad); - if (err) - return err; - err = input_register_device(keypad->input_dev); if (err) return err; - device_init_wakeup(&pdev->dev, pdata->wakeup); + wakeup = device_property_read_bool(&pdev->dev, "wakeup-source") || + /* legacy */ + device_property_read_bool(&pdev->dev, "linux,wakeup"); + if (!wakeup && pdata) + wakeup = pdata->wakeup; + device_init_wakeup(&pdev->dev, wakeup); + platform_set_drvdata(pdev, keypad); return 0;