From 9d40ac5867b9aefe0722bc1f110b965ff294d30d Mon Sep 17 00:00:00 2001
From: Kevin
Date: Sat, 15 Nov 2014 10:00:36 +0800
Subject: add via modify part source code for wm8880 4.4 kitkat
---
ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c | 466 ++++++++++++++++++++++++
1 file changed, 466 insertions(+)
create mode 100755 ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c
(limited to 'ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c')
diff --git a/ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c b/ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c
new file mode 100755
index 00000000..cf50cf1c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/keyboard/wmt_kpad.c
@@ -0,0 +1,466 @@
+/*++
+linux/drivers/input/keyboard/wmt_kpad.c
+
+Some descriptions of such software. Copyright (c) 2008 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software Foundation,
+either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+/* Debug macros */
+#if 0
+#define DPRINTK(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __func__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+//#define USE_HOME
+#define wmt_kpad_timeout (HZ/50)
+
+#define WMT_KPAD_FUNCTION_NUM 7
+
+
+static unsigned int wmt_kpad_codes[WMT_KPAD_FUNCTION_NUM] = {
+ [0] = KEY_VOLUMEUP,
+ [1] = KEY_VOLUMEDOWN,
+ [2] = KEY_BACK,
+ [3] = KEY_HOME,
+ [4] = KEY_MENU,
+ [5] = KEY_CAMERA,
+ [6] = KEY_PLAYPAUSE,
+};
+
+
+enum {
+ KEY_ST_up,
+ KEY_ST_down,
+ KEY_ST_debounce,
+};
+
+static struct input_dev *kpad_dev;
+
+int key_num = 0;
+
+struct wmt_key{
+ int gpio;
+ int keycode;
+
+ int status;
+ int debounce;
+ struct timer_list timer;
+} ;
+struct wmt_key gpio_key[5];
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Well, the debounce time is not very critical while zac2_clk
+ * rescaling, but we still do it.
+ */
+
+/* kpad_clock_notifier()
+ *
+ * When changing the processor core clock frequency, it is necessary
+ * to adjust the KPMIR register.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int kpad_clock_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ return 0;
+}
+
+/*
+ * Notify callback while issusing zac2_clk rescale.
+ */
+static struct notifier_block kpad_clock_nblock = {
+ .notifier_call = kpad_clock_notifier,
+ .priority = 1
+};
+#endif
+
+static int wmt_kpad_gpio_requst(void)
+{
+ int i,j,ret;
+ DPRINTK("Start\n");
+ for(i=0; i< key_num; i++){
+ ret = gpio_request(gpio_key[i].gpio,"kpad");
+ if(ret)
+ goto exit;
+ }
+
+ DPRINTK("End\n");
+ return ret;
+exit:
+ for(j=0; j < i; j++)
+ gpio_free(gpio_key[j].gpio);
+ return ret;
+}
+
+static int wmt_kpad_gpio_init(void)
+{
+ int i;
+ for(i=0; igpio) == 0) { /*Active Low*/
+ if(gpk->status == KEY_ST_up){
+ gpk->debounce = 5;
+ gpk->status = KEY_ST_debounce;
+ DPRINTK("vd down to debounce\n");
+ }
+
+ if(gpk->status == KEY_ST_debounce){
+ if(--gpk->debounce == 0){
+ gpk->status = KEY_ST_down;
+ /* report volume down key down */
+ input_report_key(kpad_dev, gpk->keycode, 1);
+ input_sync(kpad_dev);
+ DPRINTK("WMT Volume up keep press\n");
+ }
+ }
+ //DPRINTK("vd level is low,status=%d\n",vu_status);
+
+ }
+ else {/* Level High */
+ if(gpk->status == KEY_ST_down){
+ gpk->status = KEY_ST_up;
+ /*Volume down release*/
+ input_report_key(kpad_dev, gpk->keycode, 0); /*row4 key is release*/
+ input_sync(kpad_dev);
+ DPRINTK("WMT_Volume down release key = %d \n", gpk->keycode);
+ }
+
+ if(gpk->status == KEY_ST_debounce){
+ if(--gpk->debounce == 0){
+ gpk->status = KEY_ST_up;
+ }
+ }
+
+ //DPRINTK("vd level is high,status=%d\n",vu_status);
+
+ }
+
+ mod_timer(&gpk->timer, jiffies + wmt_kpad_timeout);
+ //DPRINTK("End\n");
+
+ return;
+}
+
+static int init_key_timer(void)
+{
+ int i;
+ for(i=0; inum_resources = 0x%x\n",pdev->num_resources);
+ if (pdev->num_resources < 0 || pdev->num_resources > 2) {
+ ret = -ENODEV;
+ goto kpad_probe_out;
+ }
+
+ /* Register an input event device. */
+ kpad_dev->name = "keypad",
+ kpad_dev->phys = "keypad",
+
+ /*
+ * Let kpad to implement key repeat.
+ */
+
+ set_bit(EV_KEY, kpad_dev->evbit);
+
+ for (i = 0; i < WMT_KPAD_FUNCTION_NUM; i++)
+ set_bit(wmt_kpad_codes[i], kpad_dev->keybit);
+
+ kpad_dev->keycode = wmt_kpad_codes;
+ kpad_dev->keycodesize = sizeof(unsigned int);
+ kpad_dev->keycodemax = WMT_KPAD_FUNCTION_NUM;
+
+ /*
+ * For better view of /proc/bus/input/devices
+ */
+ kpad_dev->id.bustype = 0;
+ kpad_dev->id.vendor = 0;
+ kpad_dev->id.product = 0;
+ kpad_dev->id.version = 0;
+
+ input_register_device(kpad_dev);
+ kpad_open(kpad_dev);
+ DPRINTK("End2\n");
+kpad_probe_out:
+
+#ifndef CONFIG_SKIP_DRIVER_MSG
+ printk(KERN_INFO "WMT keypad driver initialized: %s\n",
+ (ret == 0) ? "ok" : "failed");
+#endif
+ DPRINTK("End3\n");
+ return ret;
+}
+
+static int wmt_kpad_remove(struct platform_device *pdev)
+{
+ int ret;
+ DPRINTK("Start\n");
+ kpad_close(kpad_dev);
+ wmt_kpad_gpio_free();
+ DPRINTK("End\n");
+#ifdef CONFIG_CPU_FREQ
+ ret = cpufreq_unregister_notifier(&kpad_clock_nblock, \
+ CPUFREQ_TRANSITION_NOTIFIER);
+
+ if (ret) {
+ printk(KERN_ERR "Unable to unregister CPU frequency " \
+ "change notifier (%d)\n", ret);
+ }
+#endif
+ return 0;
+}
+
+static int wmt_kpad_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ DPRINTK("Start\n");
+
+ switch (state.event) {
+ case PM_EVENT_SUSPEND:
+ del_key_timer();
+ break;
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_PRETHAW:
+
+ default:
+ break;
+ }
+
+ DPRINTK("End2\n");
+ return 0;
+}
+
+static int wmt_kpad_resume(struct platform_device *pdev)
+{
+ DPRINTK("Start\n");
+ wmt_kpad_gpio_init();
+ start_key_timer();
+ DPRINTK("End\n");
+ return 0;
+}
+
+static void wmt_kpad_release(struct device *dev)
+{
+ return ;
+}
+
+static struct platform_driver wmt_kpad_driver = {
+ .driver.name = "wmt-kpad",
+ .probe = &wmt_kpad_probe,
+ .remove = &wmt_kpad_remove,
+ .suspend = &wmt_kpad_suspend,
+ .resume = &wmt_kpad_resume
+};
+
+static struct resource wmt_kpad_resources[] = {
+ [0] = {
+ .start = IRQ_GPIO,
+ .end = IRQ_GPIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device wmt_kpad_device = {
+ .name = "wmt-kpad",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(wmt_kpad_resources),
+ .resource = wmt_kpad_resources,
+ .dev = {
+ .release = wmt_kpad_release,
+ }
+};
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+static int __init kpad_init(void)
+{
+ int i,ret;
+ int retval;
+ unsigned char buf[80];
+ int varlen = 80;
+ char *varname = "wmt.io.kpad";
+ char *p=NULL;
+ int gpio,code;
+
+ DPRINTK(KERN_ALERT "Start\n");
+ retval = wmt_getsyspara(varname, buf, &varlen);
+ if (retval == 0) {
+ sscanf(buf,"%d:", &key_num);
+ if (key_num <= 0)
+ return -ENODEV;
+ p = buf;
+ for(i=0; i