⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omap24xx-keypad.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
字号:
/* * linux/drivers/input/keyboard/omap24xx-keypad.c * * Copyright (C) 2004 Texas Instruments Inc * Author: TI * * Keypad driver for OMAP24xx * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/types.h>#include <linux/input.h>#include <linux/kernel.h>#include <linux/delay.h>#include <asm/arch/irqs.h>#include <asm/arch/hardware.h>#include <asm/io.h>#include <asm/errno.h>#include <asm/arch/mux.h>#include <asm/arch/gpio.h>#include <asm/arch/sys_info.h>#include <asm/irq.h>#include "omap24xx-keypad.h"#define INT_GPIO_IRQ_NO(n) (IH_GPIO_BASE+n)//#define DEBUG#if defined(CONFIG_MACH_OMAP_H4)/* values for 2420 IP board, init will update for 2422 and Menelaus */static unsigned int row_gpio_num[NUM_ROWS] = { 88, 89, 124, 11, 6, 96 };static unsigned int col_gpio_num[NUM_COLS] = { 90, 91, 100, 36, 12, 97, 98 };#else#error "Define a valid OMAP24xx platform"#endifstatic void omap_kp_tasklet(unsigned long);static void omap_kp_timer(unsigned long);static struct input_dev omap_kp_dev;static unsigned char previous_state[NUM_COLS];static struct timer_list kp_timer;DECLARE_TASKLET(kp_tasklet, omap_kp_tasklet, 0);#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))static int keymap[] = {	KEY(0, 0, KEY_LEFT),	KEY(0, 1, KEY_RIGHT),	KEY(0, 2, KEY_A),	KEY(0, 3, KEY_B),	KEY(0, 4, KEY_C),//      KEY(0, 5, KEY_D),	KEY(1, 0, KEY_DOWN),	KEY(1, 1, KEY_UP),	KEY(1, 2, KEY_E),	KEY(1, 3, KEY_F),	KEY(1, 4, KEY_G),//      KEY(1, 5, KEY_H),	KEY(2, 0, KEY_ENTER),	KEY(2, 1, KEY_I),	KEY(2, 2, KEY_J),	KEY(2, 3, KEY_K),	KEY(2, 4, KEY_3),//      KEY(2, 5, KEY_HOME),	KEY(3, 0, KEY_M),	KEY(3, 1, KEY_N),	KEY(3, 2, KEY_O),	KEY(3, 3, KEY_P),	KEY(3, 4, KEY_Q),//      KEY(3, 5, KEY_END),	KEY(4, 0, KEY_R),	KEY(4, 1, KEY_4),	KEY(4, 2, KEY_T),	KEY(4, 3, KEY_U),	KEY(4, 4, KEY_ENTER),//      KEY(4, 5, KEY_ESC),	KEY(5, 0, KEY_V),	KEY(5, 1, KEY_W),	KEY(5, 2, KEY_L),	KEY(5, 3, KEY_S),	KEY(5, 4, KEY_ENTER),//        KEY(5, 5, KEY_ESC),	KEY(6, 0, KEY_X),	KEY(6, 1, KEY_Y),	KEY(6, 2, KEY_Z),	KEY(6, 3, KEY_1),	KEY(6, 4, KEY_2),//        KEY(6, 5, KEY_ESC),	0};char *switch_name[NUM_ROWS][NUM_COLS] = {	{"S2_L", "S2_D", "S2_S", "S3", "S4", "S23", "NC"},	{"S2_R", "S2_U", "S5", "S6", "S7", "S24", "NC"},	{"S8", "S9", "S10", "S11", "S12", "S25", "NC"},	{"S13", "S14", "S15", "S16", "S17", "S26", "NC"},	{"S18", "S19", "S20", "S21", "S22", "S27", "NC"},	{"NC", "NC", "NC", "NC", "NC", "NC", "NC"},};static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,				     struct pt_regs *regs){	int i;	for (i = 0; i < NUM_ROWS; i++)		disable_irq(INT_GPIO_IRQ_NO(row_gpio_num[i]));	tasklet_schedule(&kp_tasklet);	return IRQ_HANDLED;}static void omap_kp_timer(unsigned long data){	tasklet_schedule(&kp_tasklet);}/* * this function configures the keypad column GPIO pins * to drive high or low * value - bit 0 of "value" corresponds to 1st keypad column GPIO pin level *         bit 1 of "value" corresponds to 2nd keypad column GPIO pin level **/static void set_col_gpio_val(u8 value){	int col;	for (col = 0; col < NUM_COLS; col++) {		if (value & (1 << col))			omap_set_gpio_dataout(col_gpio_num[col], 1);		else			omap_set_gpio_dataout(col_gpio_num[col], 0);	}}/* * this function returns the keypad row GPIO pin levels(high or low) * value - bit 0 of "value" corresponds to 1st keypad row GPIO pin level *         bit 1 of "value" corresponds to 2nd keypad row GPIO pin level **/static u8 get_row_gpio_val(void){	int row;	u8 value = 0;	for (row = 0; row < NUM_ROWS; row++) {		if (omap_get_gpio_datain(row_gpio_num[row]))			value |= (1 << row);	}	return value;}/* * this function reads the keypad row GPIO pin levels while driving the * keypad column GPIO pins * the column GPIO pins are driven with one column pin level low and others high * and for all the sequence */static void omap_kp_scan_keypad(unsigned char *state){	int col = 0;	/* read the keypad status */	for (col = 0; col < NUM_COLS; col++) {		set_col_gpio_val(~(1 << col));		state[col] = ~(get_row_gpio_val()) & ROW_MASK;	}	set_col_gpio_val(0);}static inline int omap_kp_find_key(int col, int row){	int i, key;	key = KEY(col, row, 0);	for (i = 0; keymap[i] != 0; i++) {		if ((keymap[i] & 0xff000000) == key) {			return keymap[i] & 0x00ffffff;		}	}	return -1;}static void omap_kp_tasklet(unsigned long data){	unsigned char present_state[NUM_COLS], changed, key_down = 0;	int i, col, row, key;	/* check for any changes */	omap_kp_scan_keypad(present_state);	/* check for changes and print those */	for (col = 0; col < NUM_COLS; col++) {		changed = present_state[col] ^ previous_state[col];		key_down |= present_state[col];		if (changed == 0)			continue;		for (row = 0; row < NUM_ROWS; row++) {			if (!(changed & (1 << row)))				continue;#ifdef DEBUG			printk(KERN_INFO "key %s %s\n", switch_name[row][col],			       (present_state[col] & (1 << row)) ? "press" :			       "release");#endif			key = omap_kp_find_key(col, row);			if (key < 0) {				printk(KERN_WARNING				       "omap-keypad: Spurious key event %d-%d\n",				       col, row);				continue;			}			input_report_key(&omap_kp_dev, key,					 present_state[col] & (1 << row));		}	}	memcpy(previous_state, present_state, sizeof(previous_state));	if (key_down) {		/* some key is pressed - keep irq disabled and use timer		 * to poll the keypad */		mod_timer(&kp_timer, jiffies + SCAN_RATE);	} else {		for (i = 0; i < NUM_ROWS; i++)			enable_irq(INT_GPIO_IRQ_NO(row_gpio_num[i]));	}}static void setup_kbd_pin_mux(void){	u32 cpu = get_cpu_type();	u32 board = get_board_type();	/*configure the mux registers, update any gpio numbers */	/* Row signals */	omap2_cfg_reg(T19_242X_IM_KBR0);    omap2_cfg_reg(R19_242X_IM_KBR1);    omap2_cfg_reg(V18_242X_IM_KBR2);    omap2_cfg_reg(M21_242X_IM_KBR3);    omap2_cfg_reg(E5__242X_IM_KBR4);	if((cpu == CPU_2420) && (board == BOARD_H4_MENELAUS)){		omap2_cfg_reg(B3__2420__M_KBR5);		row_gpio_num[5] = 0;	}else		omap2_cfg_reg(M18_2420_I__2422_IM_KBR5);	/* Column signals */    omap2_cfg_reg(R20_242X_IM_KBC0);    omap2_cfg_reg(M14_242X_IM_KBC1);	if(board == BOARD_H4_MENELAUS){		omap2_cfg_reg(AA4_242X__M_KBC2);		col_gpio_num[2] = 15;	}else		omap2_cfg_reg(H19_242X_I_KBC2);	omap2_cfg_reg(V17_242X_IM_KBC3);    omap2_cfg_reg(P21_242X_IM_KBC4);    omap2_cfg_reg(L14_242X_IM_KBC5);	if((cpu == CPU_2420) && (board == BOARD_H4_MENELAUS)){		omap2_cfg_reg(B13_2420_M_KBC6);		col_gpio_num[6] = 38;	}else		omap2_cfg_reg(N19_2420_I_2422_IM_KBC6);}static int init_kbd_pin_func(void){	int i;	/* Cols: outputs */	for (i = 0; i < NUM_COLS; i++)		omap_set_gpio_direction(col_gpio_num[i], 0);	/* Rows: inputs */	for (i = 0; i < NUM_ROWS; i++)		omap_set_gpio_direction(row_gpio_num[i], 1);	omap_kp_scan_keypad(previous_state);	for (i = 0; i < NUM_ROWS; i++) {		omap_set_gpio_edge_ctrl(row_gpio_num[i],					OMAP_GPIO_FALLING_EDGE);		if (request_irq		    (INT_GPIO_IRQ_NO(row_gpio_num[i]), omap_kp_interrupt, 0,		     "omap-keypad", NULL) < 0) {			printk(KERN_INFO "request_irq failed for irq no=%d\n",			       INT_GPIO_IRQ_NO(row_gpio_num[i]));			return -EINVAL;		}	}	return(0);}static int __init omap_kp_init(void){	int i, ret = 0;	printk(KERN_INFO "OMAP24xx Keypad Driver\n");	init_timer(&kp_timer);	kp_timer.function = omap_kp_timer;	/* setup input device */	set_bit(EV_KEY, omap_kp_dev.evbit);	/* setup for auto repeat feature */	set_bit(EV_REP, omap_kp_dev.evbit);	for (i = 0; keymap[i] != 0; i++)		set_bit(keymap[i] & 0x00ffffff, omap_kp_dev.keybit);	omap_kp_dev.name = "omap24xx-keypad";	input_register_device(&omap_kp_dev);	setup_kbd_pin_mux();	ret = init_kbd_pin_func();	return ret;}static void __exit omap_kp_exit(void){	int i;	for (i = 0; i < NUM_ROWS; i++)		free_irq(INT_GPIO_IRQ_NO(row_gpio_num[i]), NULL);	/* disable keypad interrupt handling */	tasklet_disable(&kp_tasklet);	del_timer_sync(&kp_timer);	/* unregister everything */	input_unregister_device(&omap_kp_dev);}module_init(omap_kp_init);module_exit(omap_kp_exit);MODULE_AUTHOR("TI");MODULE_DESCRIPTION("OMAP24XX Keypad Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -