From patchwork Wed Feb 10 09:26:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 78354 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1A9S5qN012007 for ; Wed, 10 Feb 2010 09:28:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755153Ab0BJJ1C (ORCPT ); Wed, 10 Feb 2010 04:27:02 -0500 Received: from mail-yw0-f173.google.com ([209.85.211.173]:50296 "EHLO mail-yw0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753536Ab0BJJ05 (ORCPT ); Wed, 10 Feb 2010 04:26:57 -0500 Received: by ywh3 with SMTP id 3so7519352ywh.22 for ; Wed, 10 Feb 2010 01:26:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:references:mime-version:content-type:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=CPJM358y4x91M7/72wJO7UuOxtgmRDQT5ocl8Fw1iJ4=; b=B+Jzp65i53BLVE2XxS5UWrQs/mo0os5IyNV9OxDle2X8VtGtmlXa4EbKZN3iPIPU02 CeWMZIvb0YpDyhgg+OAwx0E9xJKXLg6FOwx4VKFHW2ROmY+0k3O6FirAujnCOCc/IqRO fFXrzfRHb2A28YjXIlJ5PgdFI/lPDN7Pt/f3k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:content-transfer-encoding :in-reply-to:user-agent; b=cbF+WYHSM1ZZE0lu8t1QOeWXinAFQzxpJaaQ+RKxTnrJA1wdMj8ZgrJupoE1irTaw2 JBXRAF/eTOzhsWLVkSjq4yZdelNN/gdvAGf+bn/HhjdWsbWKAYT2cvwvruEBrH6IzVlb Ag1+QZDpdsLJe4L3NzungFYO2SC5cdW1SyVfc= Received: by 10.151.19.34 with SMTP id w34mr1898246ybi.99.1265794015636; Wed, 10 Feb 2010 01:26:55 -0800 (PST) Received: from mailhub.coreip.homeip.net (c-24-6-153-206.hsd1.ca.comcast.net [24.6.153.206]) by mx.google.com with ESMTPS id 8sm379945yxb.61.2010.02.10.01.26.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 10 Feb 2010 01:26:54 -0800 (PST) Date: Wed, 10 Feb 2010 01:26:50 -0800 From: Dmitry Torokhov To: Magnus Damm Cc: linux-input@vger.kernel.org, lethal@linux-sh.org, linux-sh@vger.kernel.org Subject: Re: [PATCH] input: bitmap update for sh_keysc V2 Message-ID: <20100210092650.GA28229@core.coreip.homeip.net> References: <20100209091609.1262.66929.sendpatchset@rxone.opensource.se> <20100209093954.GC12642@core.coreip.homeip.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-08-17) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 10 Feb 2010 09:28:12 +0000 (UTC) diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 6218b2f..c2fc977 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ static const struct { struct sh_keysc_priv { void __iomem *iomem_base; struct clk *clk; - unsigned long last_keys; + DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS); struct input_dev *input; struct sh_keysc_info pdata; }; @@ -71,69 +72,87 @@ static void sh_keysc_level_mode(struct sh_keysc_priv *p, udelay(pdata->kycr2_delay); } +static void sh_keysc_map_dbg(struct device *dev, unsigned long *map, + const char *str) +{ + int k; + + for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++) + dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]); +} + static irqreturn_t sh_keysc_isr(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct sh_keysc_priv *priv = platform_get_drvdata(pdev); struct sh_keysc_info *pdata = &priv->pdata; - unsigned long keys, keys1, keys0, mask; + int keyout_nr = sh_keysc_mode[pdata->mode].keyout; + int keyin_nr = sh_keysc_mode[pdata->mode].keyin; + DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS); + DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS); + DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS); unsigned char keyin_set, tmp; - int i, k; + int i, k, n; dev_dbg(&pdev->dev, "isr!\n"); - keys1 = ~0; - keys0 = 0; + bitmap_fill(keys1, SH_KEYSC_MAXKEYS); + bitmap_zero(keys0, SH_KEYSC_MAXKEYS); do { - keys = 0; + bitmap_zero(keys, SH_KEYSC_MAXKEYS); keyin_set = 0; sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); - for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { + for (i = 0; i < keyout_nr; i++) { + n = keyin_nr * i; + + /* drive one KEYOUT pin low, read KEYIN pins */ sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2))); udelay(pdata->delay); tmp = sh_keysc_read(priv, KYINDR); - keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); - tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; - keyin_set |= tmp; + /* set bit if key press has been detected */ + for (k = 0; k < keyin_nr; k++) { + if (tmp & (1 << k)) + __set_bit(n + k, keys); + } + + /* keep track of which KEYIN bits that have been set */ + keyin_set |= tmp ^ ((1 << keyin_nr) - 1); } sh_keysc_level_mode(priv, keyin_set); - keys ^= ~0; - keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * - sh_keysc_mode[pdata->mode].keyout)) - 1; - keys1 &= keys; - keys0 |= keys; + bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS); + bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS); + bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS); - dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); + sh_keysc_map_dbg(&pdev->dev, keys, "keys"); } while (sh_keysc_read(priv, KYCR2) & 0x01); - dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", - priv->last_keys, keys0, keys1); + sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys"); + sh_keysc_map_dbg(&pdev->dev, keys0, "keys0"); + sh_keysc_map_dbg(&pdev->dev, keys1, "keys1"); for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { k = pdata->keycodes[i]; if (!k) continue; - mask = 1 << i; - - if (!((priv->last_keys ^ keys0) & mask)) + if (test_bit(i, keys0) == test_bit(i, priv->last_keys)) continue; - if ((keys1 | keys0) & mask) { + if (test_bit(i, keys1) || test_bit(i, keys0)) { input_event(priv->input, EV_KEY, k, 1); - priv->last_keys |= mask; + __set_bit(i, priv->last_keys); } - if (!(keys1 & mask)) { + if (!test_bit(i, keys1)) { input_event(priv->input, EV_KEY, k, 0); - priv->last_keys &= ~mask; + __clear_bit(i, priv->last_keys); } }