Keyboard: zipit2-keyboard.patch

File zipit2-keyboard.patch, 12.6 kB (added by ethicalclone, 1 year ago)

Zipit2 Keyboard kernel patch

  • a/drivers/input/keyboard/Kconfig

    old new  
    229229          To compile this driver as a module, choose M here: the 
    230230          module will be called gpio-keys. 
    231231 
     232config KEYBOARD_ZIPIT2 
     233        tristate "Zipit2 Keyboard Helper" 
     234        depends on PXA27x 
     235        select KEYBOARD_PXA27x 
     236        help 
     237          Adds the missing devices needed to use the PXA27x 
     238          keyboard driver with the default Zipit2 kernel. 
     239 
     240config KEYBOARD_PXA27x 
     241       tristate "PXA27x keyboard support" 
     242       depends on PXA27x 
     243       help 
     244         Enable support for PXA27x matrix keyboard controller 
     245 
     246         To compile this driver as a module, choose M here: the 
     247         module will be called pxa27x_keyboard. 
     248 
    232249endif 
  • a/drivers/input/keyboard/Makefile

    old new  
    1919obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o 
    2020obj-$(CONFIG_KEYBOARD_AAED2000)         += aaed2000_kbd.o 
    2121obj-$(CONFIG_KEYBOARD_GPIO)             += gpio_keys.o 
     22obj-$(CONFIG_KEYBOARD_PXA27x)           += pxa27x_keyboard.o 
     23obj-$(CONFIG_KEYBOARD_ZIPIT2)           += zipit2_kbd_helper.o 
    2224 
  • /dev/null

    old new  
     1/* 
     2 * linux/drivers/input/keyboard/pxa27x_keyboard.c 
     3 * 
     4 * Driver for the pxa27x matrix keyboard controller. 
     5 * 
     6 * Created:     Feb 22, 2007 
     7 * Author:      Rodolfo Giometti <giometti@linux.it> 
     8 * 
     9 * Based on a previous implementations by Kevin O'Connor 
     10 * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and 
     11 * on some suggestions by Nicolas Pitre <nico@cam.org>. 
     12 * 
     13 * This program is free software; you can redistribute it and/or modify 
     14 * it under the terms of the GNU General Public License version 2 as 
     15 * published by the Free Software Foundation. 
     16 */ 
     17 
     18 
     19#include <linux/kernel.h> 
     20#include <linux/module.h> 
     21#include <linux/init.h> 
     22#include <linux/interrupt.h> 
     23#include <linux/input.h> 
     24#include <linux/device.h> 
     25#include <linux/platform_device.h> 
     26#include <linux/clk.h> 
     27#include <linux/err.h> 
     28 
     29#include <asm/mach-types.h> 
     30#include <asm/mach/arch.h> 
     31#include <asm/mach/map.h> 
     32 
     33#include <asm/arch/hardware.h> 
     34#include <asm/arch/pxa-regs.h> 
     35#include <asm/arch/irqs.h> 
     36#include <asm/arch/pxa27x_keyboard.h> 
     37 
     38#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG)) 
     39#define BIT_WORD(nr)            ((nr) / BITS_PER_LONG) 
     40#define BITS_PER_BYTE           8 
     41 
     42#define DRIVER_NAME             "pxa27x-keyboard" 
     43 
     44#define KPASMKP(col)            (col/2 == 0 ? KPASMKP0 : \ 
     45                                 col/2 == 1 ? KPASMKP1 : \ 
     46                                 col/2 == 2 ? KPASMKP2 : KPASMKP3) 
     47#define KPASMKPx_MKC(row, col)  (1 << (row + 16 * (col % 2))) 
     48 
     49static struct clk *pxakbd_clk; 
     50 
     51static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id) 
     52{ 
     53        struct platform_device *pdev = dev_id; 
     54        struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; 
     55        struct input_dev *input_dev = platform_get_drvdata(pdev); 
     56        unsigned long kpc = KPC; 
     57        int p, row, col, rel; 
     58 
     59        if (kpc & KPC_DI) { 
     60                unsigned long kpdk = KPDK; 
     61 
     62                if (!(kpdk & KPDK_DKP)) { 
     63                        /* better luck next time */ 
     64                } else if (kpc & KPC_REE0) { 
     65                        unsigned long kprec = KPREC; 
     66                        KPREC = 0x7f; 
     67 
     68                        if (kprec & KPREC_OF0) 
     69                                rel = (kprec & 0xff) + 0x7f; 
     70                        else if (kprec & KPREC_UF0) 
     71                                rel = (kprec & 0xff) - 0x7f - 0xff; 
     72                        else 
     73                                rel = (kprec & 0xff) - 0x7f; 
     74 
     75                        if (rel) { 
     76                                input_report_rel(input_dev, REL_WHEEL, rel); 
     77                                input_sync(input_dev); 
     78                        } 
     79                } 
     80        } 
     81 
     82        if (kpc & KPC_MI) { 
     83                /* report the status of every button */ 
     84                for (row = 0; row < pdata->nr_rows; row++) { 
     85                        for (col = 0; col < pdata->nr_cols; col++) { 
     86                                p = KPASMKP(col) & KPASMKPx_MKC(row, col) ? 
     87                                        1 : 0; 
     88                                //printk(KERN_INFO "keycode %x - pressed %x\n", pdata->keycodes[row][col],p); 
     89                                input_report_key(input_dev, 
     90                                                pdata->keycodes[row][col], p); 
     91                        } 
     92                } 
     93                input_sync(input_dev); 
     94        } 
     95 
     96        return IRQ_HANDLED; 
     97} 
     98 
     99static int pxakbd_open(struct input_dev *dev) 
     100{ 
     101        /* Set keypad control register */ 
     102        KPC |= (KPC_ASACT | 
     103                KPC_MS_ALL | 
     104                (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL | 
     105                KPC_ME | KPC_MIE | KPC_DE | KPC_DIE); 
     106 
     107        KPC &= ~KPC_AS;         /* disable automatic scan */ 
     108        KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */ 
     109 
     110        /* Set rotary count to mid-point value */ 
     111        KPREC = 0x7F; 
     112 
     113        /* Enable unit clock */ 
     114        clk_enable(pxakbd_clk); 
     115 
     116        return 0; 
     117} 
     118 
     119static void pxakbd_close(struct input_dev *dev) 
     120{ 
     121        /* Disable clock unit */ 
     122        clk_disable(pxakbd_clk); 
     123} 
     124 
     125#ifdef CONFIG_PM 
     126static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state) 
     127{ 
     128        struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; 
     129 
     130        /* Save controller status */ 
     131        pdata->reg_kpc = KPC; 
     132        pdata->reg_kprec = KPREC; 
     133 
     134        return 0; 
     135} 
     136 
     137static int pxakbd_resume(struct platform_device *pdev) 
     138{ 
     139        struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; 
     140        struct input_dev *input_dev = platform_get_drvdata(pdev); 
     141 
     142        mutex_lock(&input_dev->mutex); 
     143 
     144        if (input_dev->users) { 
     145                /* Restore controller status */ 
     146                KPC = pdata->reg_kpc; 
     147                KPREC = pdata->reg_kprec; 
     148 
     149                /* Enable unit clock */ 
     150                clk_disable(pxakbd_clk); 
     151                clk_enable(pxakbd_clk); 
     152        } 
     153 
     154        mutex_unlock(&input_dev->mutex); 
     155 
     156        return 0; 
     157} 
     158#else 
     159#define pxakbd_suspend  NULL 
     160#define pxakbd_resume   NULL 
     161#endif 
     162 
     163static int __devinit pxakbd_probe(struct platform_device *pdev) 
     164{ 
     165        struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; 
     166        struct input_dev *input_dev; 
     167        int i, row, col, error; 
     168 
     169        pxakbd_clk = clk_get(&pdev->dev, "KBDCLK"); 
     170        if (IS_ERR(pxakbd_clk)) { 
     171                error = PTR_ERR(pxakbd_clk); 
     172                goto err_clk; 
     173        } 
     174 
     175        /* Create and register the input driver. */ 
     176        input_dev = input_allocate_device(); 
     177        if (!input_dev) { 
     178                printk(KERN_ERR "Cannot request keypad device\n"); 
     179                error = -ENOMEM; 
     180                goto err_alloc; 
     181        } 
     182 
     183        input_dev->name = DRIVER_NAME; 
     184        input_dev->id.bustype = BUS_HOST; 
     185        input_dev->open = pxakbd_open; 
     186        input_dev->close = pxakbd_close; 
     187        // input_dev->dev.parent = &pdev->dev; 
     188 
     189        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | 
     190                BIT_MASK(EV_REL); 
     191        input_dev->relbit[BIT_WORD(REL_WHEEL)] = BIT_MASK(REL_WHEEL); 
     192        for (row = 0; row < pdata->nr_rows; row++) { 
     193                for (col = 0; col < pdata->nr_cols; col++) { 
     194                        int code = pdata->keycodes[row][col]; 
     195                        if (code > 0) 
     196                                set_bit(code, input_dev->keybit); 
     197                } 
     198        } 
     199 
     200        error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED, 
     201                            DRIVER_NAME, pdev); 
     202        if (error) { 
     203                printk(KERN_ERR "Cannot request keypad IRQ\n"); 
     204                goto err_free_dev; 
     205        } 
     206 
     207        platform_set_drvdata(pdev, input_dev); 
     208 
     209        /* Register the input device */ 
     210        error = input_register_device(input_dev); 
     211        if (error) 
     212                goto err_free_irq; 
     213 
     214        /* Setup GPIOs. */ 
     215        for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++) 
     216                pxa_gpio_mode(pdata->gpio_modes[i]); 
     217 
     218        /* 
     219         * Store rows/cols info into keyboard registers. 
     220         */ 
     221 
     222        KPC |= (pdata->nr_rows - 1) << 26; 
     223        KPC |= (pdata->nr_cols - 1) << 23; 
     224 
     225        for (col = 0; col < pdata->nr_cols; col++) 
     226                KPC |= KPC_MS0 << col; 
     227 
     228        return 0; 
     229 
     230 err_free_irq: 
     231        platform_set_drvdata(pdev, NULL); 
     232        free_irq(IRQ_KEYPAD, pdev); 
     233 err_free_dev: 
     234        input_free_device(input_dev); 
     235 err_alloc: 
     236        clk_put(pxakbd_clk); 
     237 err_clk: 
     238        return error; 
     239} 
     240 
     241static int __devexit pxakbd_remove(struct platform_device *pdev) 
     242{ 
     243        struct input_dev *input_dev = platform_get_drvdata(pdev); 
     244 
     245        input_unregister_device(input_dev); 
     246        free_irq(IRQ_KEYPAD, pdev); 
     247        clk_put(pxakbd_clk); 
     248        platform_set_drvdata(pdev, NULL); 
     249 
     250        return 0; 
     251} 
     252 
     253static struct platform_driver pxakbd_driver = { 
     254        .probe          = pxakbd_probe, 
     255        .remove         = __devexit_p(pxakbd_remove), 
     256        .suspend        = pxakbd_suspend, 
     257        .resume         = pxakbd_resume, 
     258        .driver         = { 
     259                .name   = DRIVER_NAME, 
     260        }, 
     261}; 
     262 
     263static int __init pxakbd_init(void) 
     264{ 
     265        return platform_driver_register(&pxakbd_driver); 
     266} 
     267 
     268static void __exit pxakbd_exit(void) 
     269{ 
     270        platform_driver_unregister(&pxakbd_driver); 
     271} 
     272 
     273module_init(pxakbd_init); 
     274module_exit(pxakbd_exit); 
     275 
     276MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver"); 
     277MODULE_LICENSE("GPL"); 
  • /dev/null

    old new  
     1/* 
     2 * linux/drivers/input/keyboard/zipit2_kbd_helper.c 
     3 * 
     4 * This helper module adds the missing devices to 
     5 * the Zipit2's built-in kernel so that the pxa27x_keyboard driver 
     6 * works. The platform_device stuff should be move to the proper place in 
     7 * the future. The clock stuff is not need in newer versions of the kernel. 
     8 * 
     9 * Wayne LaBelle <ethicalclone@gmail.com> 
     10 * 
     11 * This program is free software; you can redistribute it and/or modify 
     12 * it under the terms of the GNU General Public License version 2 as 
     13 * published by the Free Software Foundation. 
     14 */ 
     15 
     16 
     17#include <linux/kernel.h> 
     18#include <linux/module.h> 
     19#include <linux/init.h> 
     20#include <linux/input.h> 
     21#include <linux/device.h> 
     22#include <linux/platform_device.h> 
     23#include <linux/clk.h> 
     24#include <linux/err.h> 
     25 
     26#include <asm/mach-types.h> 
     27#include <asm/mach/arch.h> 
     28#include <asm/mach/map.h> 
     29#include <asm/arch/hardware.h> 
     30 
     31#include <asm/arch/pxa-regs.h> 
     32#include <asm/arch/pxa27x_keyboard.h> 
     33 
     34struct clk { 
     35        struct list_head        node; 
     36        unsigned long           rate; 
     37        struct module           *owner; 
     38        const char              *name; 
     39        unsigned int            enabled; 
     40        void                    (*enable)(void); 
     41        void                    (*disable)(void); 
     42}; 
     43 
     44static void clk_keypad_enable(void) 
     45{ 
     46        CKEN |= CKEN19_KEYPAD; 
     47} 
     48 
     49static void clk_keypad_disable(void) 
     50{ 
     51        CKEN &= ~CKEN19_KEYPAD; 
     52} 
     53 
     54static struct clk clk_keypad = { 
     55        .name = "KBDCLK", 
     56        .rate = 32768, 
     57        .enable = clk_keypad_enable, 
     58        .disable = clk_keypad_disable 
     59}; 
     60 
     61struct pxa27x_keyboard_platform_data zipit2_kbd_pdata = { 
     62        .nr_rows = 7, 
     63        .nr_cols = 8, 
     64        .keycodes = 
     65/*         103  104  105  106  107  108   35   41 */ 
     66/*    100  opt home prev next face  zip stop play */ 
     67/*    101   up    q    w    e    r    t    y    u */ 
     68/*    102 down    i    o    p    a    s    d    f */ 
     69/*     34 left    g    h    j    k    l   bs    z */ 
     70/*     38 rigt    x    c    v    b    n    m    ; */ 
     71/*     16  btn  ent  alt shft  ...   sp    ,    . */ 
     72/*     17    +    -                               */ 
     73        {{ KEY_OPTION, KEY_HOME, KEY_PAGEUP, KEY_PAGEDOWN, KEY_ESC, KEY_TAB, KEY_STOPCD, KEY_PLAYCD }, 
     74         { KEY_UP, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U }, 
     75         { KEY_DOWN, KEY_I, KEY_O, KEY_P, KEY_A, KEY_S, KEY_D, KEY_F }, 
     76         { KEY_LEFT, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_BACKSPACE, KEY_Z }, 
     77         { KEY_RIGHT,  KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_SEMICOLON }, 
     78         { KEY_END, KEY_ENTER, KEY_LEFTMETA, KEY_LEFTSHIFT, KEY_LEFTCTRL, KEY_SPACE, KEY_COMMA, KEY_DOT }, 
     79         { KEY_KPPLUS, KEY_KPMINUS,   0,   0,   0,   0,   0,   0 }}, 
     80 
     81        .gpio_modes = { (16 | GPIO_ALT_FN_1_IN), // KP_MKIN<5> 
     82                        (17 | GPIO_ALT_FN_1_IN), // KP_MKIN<6> 
     83                        (34 | GPIO_ALT_FN_2_IN), // KP_MKIN<3> 
     84                        (38 | GPIO_ALT_FN_2_IN), // KP_MKIN<4> 
     85                        (100 | GPIO_ALT_FN_1_IN),// KP_MKIN<0> 
     86                        (101 | GPIO_ALT_FN_1_IN),// KP_MKIN<1> 
     87                        (102 | GPIO_ALT_FN_1_IN),// KP_MKIN<2> 
     88                        (103 | GPIO_ALT_FN_2_OUT), 
     89                        (104 | GPIO_ALT_FN_2_OUT), 
     90                        (105 | GPIO_ALT_FN_2_OUT), 
     91                        (106 | GPIO_ALT_FN_2_OUT), 
     92                        (107 | GPIO_ALT_FN_2_OUT), 
     93                        (108 | GPIO_ALT_FN_2_OUT), 
     94                        (35 | GPIO_ALT_FN_2_OUT), 
     95                        (41 | GPIO_ALT_FN_1_OUT) 
     96        } 
     97}; 
     98 
     99static struct platform_device zipit2_kbd_device = { 
     100        .name           = "pxa27x-keyboard", 
     101        .id             = -1, 
     102        .dev            = { 
     103                .platform_data = &zipit2_kbd_pdata 
     104        } 
     105 }; 
     106 
     107static int __init zipit2_kbd_init(void) 
     108{ 
     109 
     110        clk_register(&clk_keypad); 
     111        return platform_device_register(&zipit2_kbd_device); 
     112} 
     113 
     114static void __exit zipit2_kbd_exit(void) 
     115{ 
     116        clk_unregister(&clk_keypad); 
     117        platform_device_unregister(&zipit2_kbd_device); 
     118} 
     119 
     120module_init(zipit2_kbd_init); 
     121module_exit(zipit2_kbd_exit); 
     122 
     123MODULE_DESCRIPTION("ZIPIT2 Keyboard Helper"); 
     124MODULE_LICENSE("GPL"); 
  • /dev/null

    old new  
     1#define PXAKBD_MAXROW           8 
     2#define PXAKBD_MAXCOL           8 
     3 
     4struct pxa27x_keyboard_platform_data { 
     5        int nr_rows, nr_cols; 
     6        int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL]; 
     7        int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL]; 
     8 
     9#ifdef CONFIG_PM 
     10        u32 reg_kpc; 
     11        u32 reg_kprec; 
     12#endif 
     13};