diff options
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 56 | ||||
-rw-r--r-- | drivers/input/matrix-keymap.c | 175 | ||||
-rw-r--r-- | include/linux/input/matrix_keypad.h | 18 |
3 files changed, 130 insertions, 119 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 6722d376e898..4ffe64d53107 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -619,8 +619,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, | |||
619 | } | 619 | } |
620 | 620 | ||
621 | #ifdef CONFIG_OF | 621 | #ifdef CONFIG_OF |
622 | static struct tegra_kbc_platform_data * __devinit | 622 | static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata( |
623 | tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | 623 | struct platform_device *pdev) |
624 | { | 624 | { |
625 | struct tegra_kbc_platform_data *pdata; | 625 | struct tegra_kbc_platform_data *pdata; |
626 | struct device_node *np = pdev->dev.of_node; | 626 | struct device_node *np = pdev->dev.of_node; |
@@ -660,10 +660,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | |||
660 | pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; | 660 | pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; |
661 | } | 661 | } |
662 | 662 | ||
663 | pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap"); | ||
664 | |||
665 | /* FIXME: Add handling of linux,fn-keymap here */ | ||
666 | |||
667 | return pdata; | 663 | return pdata; |
668 | } | 664 | } |
669 | #else | 665 | #else |
@@ -674,10 +670,36 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( | |||
674 | } | 670 | } |
675 | #endif | 671 | #endif |
676 | 672 | ||
673 | static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc) | ||
674 | { | ||
675 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | ||
676 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
677 | unsigned int keymap_rows = KBC_MAX_KEY; | ||
678 | int retval; | ||
679 | |||
680 | if (keymap_data && pdata->use_fn_map) | ||
681 | keymap_rows *= 2; | ||
682 | |||
683 | retval = matrix_keypad_build_keymap(keymap_data, NULL, | ||
684 | keymap_rows, KBC_MAX_COL, | ||
685 | kbc->keycode, kbc->idev); | ||
686 | if (retval == -ENOSYS || retval == -ENOENT) { | ||
687 | /* | ||
688 | * If there is no OF support in kernel or keymap | ||
689 | * property is missing, use default keymap. | ||
690 | */ | ||
691 | retval = matrix_keypad_build_keymap( | ||
692 | &tegra_kbc_default_keymap_data, NULL, | ||
693 | keymap_rows, KBC_MAX_COL, | ||
694 | kbc->keycode, kbc->idev); | ||
695 | } | ||
696 | |||
697 | return retval; | ||
698 | } | ||
699 | |||
677 | static int __devinit tegra_kbc_probe(struct platform_device *pdev) | 700 | static int __devinit tegra_kbc_probe(struct platform_device *pdev) |
678 | { | 701 | { |
679 | const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; | 702 | const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; |
680 | const struct matrix_keymap_data *keymap_data; | ||
681 | struct tegra_kbc *kbc; | 703 | struct tegra_kbc *kbc; |
682 | struct input_dev *input_dev; | 704 | struct input_dev *input_dev; |
683 | struct resource *res; | 705 | struct resource *res; |
@@ -686,7 +708,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
686 | int num_rows = 0; | 708 | int num_rows = 0; |
687 | unsigned int debounce_cnt; | 709 | unsigned int debounce_cnt; |
688 | unsigned int scan_time_rows; | 710 | unsigned int scan_time_rows; |
689 | unsigned int keymap_rows; | ||
690 | 711 | ||
691 | if (!pdata) | 712 | if (!pdata) |
692 | pdata = tegra_kbc_dt_parse_pdata(pdev); | 713 | pdata = tegra_kbc_dt_parse_pdata(pdev); |
@@ -768,17 +789,9 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
768 | input_dev->open = tegra_kbc_open; | 789 | input_dev->open = tegra_kbc_open; |
769 | input_dev->close = tegra_kbc_close; | 790 | input_dev->close = tegra_kbc_close; |
770 | 791 | ||
771 | keymap_rows = KBC_MAX_KEY; | 792 | err = tegra_kbd_setup_keymap(kbc); |
772 | if (pdata->use_fn_map) | ||
773 | keymap_rows *= 2; | ||
774 | |||
775 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | ||
776 | |||
777 | err = matrix_keypad_build_keymap(keymap_data, NULL, | ||
778 | keymap_rows, KBC_MAX_COL, | ||
779 | kbc->keycode, input_dev); | ||
780 | if (err) { | 793 | if (err) { |
781 | dev_err(&pdev->dev, "failed to build keymap\n"); | 794 | dev_err(&pdev->dev, "failed to setup keymap\n"); |
782 | goto err_put_clk; | 795 | goto err_put_clk; |
783 | } | 796 | } |
784 | 797 | ||
@@ -805,9 +818,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
805 | platform_set_drvdata(pdev, kbc); | 818 | platform_set_drvdata(pdev, kbc); |
806 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 819 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
807 | 820 | ||
808 | if (!pdev->dev.platform_data) | ||
809 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
810 | |||
811 | return 0; | 821 | return 0; |
812 | 822 | ||
813 | err_free_irq: | 823 | err_free_irq: |
@@ -822,10 +832,8 @@ err_free_mem: | |||
822 | input_free_device(input_dev); | 832 | input_free_device(input_dev); |
823 | kfree(kbc); | 833 | kfree(kbc); |
824 | err_free_pdata: | 834 | err_free_pdata: |
825 | if (!pdev->dev.platform_data) { | 835 | if (!pdev->dev.platform_data) |
826 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
827 | kfree(pdata); | 836 | kfree(pdata); |
828 | } | ||
829 | 837 | ||
830 | return err; | 838 | return err; |
831 | } | 839 | } |
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index de7992d55da2..db92c1ebfc59 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c | |||
@@ -17,15 +17,91 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/device.h> | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/types.h> | 22 | #include <linux/types.h> |
22 | #include <linux/input.h> | 23 | #include <linux/input.h> |
23 | #include <linux/of.h> | 24 | #include <linux/of.h> |
24 | #include <linux/export.h> | 25 | #include <linux/export.h> |
25 | #include <linux/gfp.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/input/matrix_keypad.h> | 26 | #include <linux/input/matrix_keypad.h> |
28 | 27 | ||
28 | static bool matrix_keypad_map_key(struct input_dev *input_dev, | ||
29 | unsigned int rows, unsigned int cols, | ||
30 | unsigned int row_shift, unsigned int key) | ||
31 | { | ||
32 | unsigned char *keymap = input_dev->keycode; | ||
33 | unsigned int row = KEY_ROW(key); | ||
34 | unsigned int col = KEY_COL(key); | ||
35 | unsigned short code = KEY_VAL(key); | ||
36 | |||
37 | if (row >= rows || col >= cols) { | ||
38 | dev_err(input_dev->dev.parent, | ||
39 | "%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n", | ||
40 | __func__, key, row, col, rows, cols); | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | ||
45 | __set_bit(code, input_dev->keybit); | ||
46 | |||
47 | return true; | ||
48 | } | ||
49 | |||
50 | #ifdef CONFIG_OF | ||
51 | static int matrix_keypad_parse_of_keymap(const char *propname, | ||
52 | unsigned int rows, unsigned int cols, | ||
53 | struct input_dev *input_dev) | ||
54 | { | ||
55 | struct device *dev = input_dev->dev.parent; | ||
56 | struct device_node *np = dev->of_node; | ||
57 | unsigned int row_shift = get_count_order(cols); | ||
58 | unsigned int max_keys = rows << row_shift; | ||
59 | unsigned int proplen, i, size; | ||
60 | const __be32 *prop; | ||
61 | |||
62 | if (!np) | ||
63 | return -ENOENT; | ||
64 | |||
65 | if (!propname) | ||
66 | propname = "linux,keymap"; | ||
67 | |||
68 | prop = of_get_property(np, propname, &proplen); | ||
69 | if (!prop) { | ||
70 | dev_err(dev, "OF: %s property not defined in %s\n", | ||
71 | propname, np->full_name); | ||
72 | return -ENOENT; | ||
73 | } | ||
74 | |||
75 | if (proplen % sizeof(u32)) { | ||
76 | dev_err(dev, "OF: Malformed keycode property %s in %s\n", | ||
77 | propname, np->full_name); | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | size = proplen / sizeof(u32); | ||
82 | if (size > max_keys) { | ||
83 | dev_err(dev, "OF: %s size overflow\n", propname); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | for (i = 0; i < size; i++) { | ||
88 | unsigned int key = be32_to_cpup(prop + i); | ||
89 | |||
90 | if (!matrix_keypad_map_key(input_dev, rows, cols, | ||
91 | row_shift, key)) | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | #else | ||
98 | static int matrix_keypad_parse_of_keymap(const char *propname, | ||
99 | unsigned int rows, unsigned int cols, | ||
100 | struct input_dev *input_dev) | ||
101 | { | ||
102 | return -ENOSYS; | ||
103 | } | ||
104 | #endif | ||
29 | 105 | ||
30 | /** | 106 | /** |
31 | * matrix_keypad_build_keymap - convert platform keymap into matrix keymap | 107 | * matrix_keypad_build_keymap - convert platform keymap into matrix keymap |
@@ -41,6 +117,13 @@ | |||
41 | * This function converts platform keymap (encoded with KEY() macro) into | 117 | * This function converts platform keymap (encoded with KEY() macro) into |
42 | * an array of keycodes that is suitable for using in a standard matrix | 118 | * an array of keycodes that is suitable for using in a standard matrix |
43 | * keyboard driver that uses row and col as indices. | 119 | * keyboard driver that uses row and col as indices. |
120 | * | ||
121 | * If @keymap_data is not supplied and device tree support is enabled | ||
122 | * it will attempt load the keymap from property specified by @keymap_name | ||
123 | * argument (or "linux,keymap" if @keymap_name is %NULL). | ||
124 | * | ||
125 | * Callers are expected to set up input_dev->dev.parent before calling this | ||
126 | * function. | ||
44 | */ | 127 | */ |
45 | int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | 128 | int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, |
46 | const char *keymap_name, | 129 | const char *keymap_name, |
@@ -50,6 +133,7 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | |||
50 | { | 133 | { |
51 | unsigned int row_shift = get_count_order(cols); | 134 | unsigned int row_shift = get_count_order(cols); |
52 | int i; | 135 | int i; |
136 | int error; | ||
53 | 137 | ||
54 | input_dev->keycode = keymap; | 138 | input_dev->keycode = keymap; |
55 | input_dev->keycodesize = sizeof(*keymap); | 139 | input_dev->keycodesize = sizeof(*keymap); |
@@ -57,86 +141,23 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | |||
57 | 141 | ||
58 | __set_bit(EV_KEY, input_dev->evbit); | 142 | __set_bit(EV_KEY, input_dev->evbit); |
59 | 143 | ||
60 | for (i = 0; i < keymap_data->keymap_size; i++) { | 144 | if (keymap_data) { |
61 | unsigned int key = keymap_data->keymap[i]; | 145 | for (i = 0; i < keymap_data->keymap_size; i++) { |
62 | unsigned int row = KEY_ROW(key); | 146 | unsigned int key = keymap_data->keymap[i]; |
63 | unsigned int col = KEY_COL(key); | ||
64 | unsigned short code = KEY_VAL(key); | ||
65 | 147 | ||
66 | if (row >= rows || col >= cols) { | 148 | if (!matrix_keypad_map_key(input_dev, rows, cols, |
67 | dev_err(input_dev->dev.parent, | 149 | row_shift, key)) |
68 | "%s: invalid keymap entry %d (row: %d, col: %d, rows: %d, cols: %d)\n", | 150 | return -EINVAL; |
69 | __func__, i, row, col, rows, cols); | ||
70 | return -EINVAL; | ||
71 | } | 151 | } |
72 | 152 | } else { | |
73 | keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | 153 | error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols, |
74 | __set_bit(code, input_dev->keybit); | 154 | input_dev); |
155 | if (error) | ||
156 | return error; | ||
75 | } | 157 | } |
158 | |||
76 | __clear_bit(KEY_RESERVED, input_dev->keybit); | 159 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
77 | 160 | ||
78 | return 0; | 161 | return 0; |
79 | } | 162 | } |
80 | EXPORT_SYMBOL(matrix_keypad_build_keymap); | 163 | EXPORT_SYMBOL(matrix_keypad_build_keymap); |
81 | |||
82 | #ifdef CONFIG_OF | ||
83 | struct matrix_keymap_data * | ||
84 | matrix_keyboard_of_fill_keymap(struct device_node *np, | ||
85 | const char *propname) | ||
86 | { | ||
87 | struct matrix_keymap_data *kd; | ||
88 | u32 *keymap; | ||
89 | int proplen, i; | ||
90 | const __be32 *prop; | ||
91 | |||
92 | if (!np) | ||
93 | return NULL; | ||
94 | |||
95 | if (!propname) | ||
96 | propname = "linux,keymap"; | ||
97 | |||
98 | prop = of_get_property(np, propname, &proplen); | ||
99 | if (!prop) | ||
100 | return NULL; | ||
101 | |||
102 | if (proplen % sizeof(u32)) { | ||
103 | pr_warn("Malformed keymap property %s in %s\n", | ||
104 | propname, np->full_name); | ||
105 | return NULL; | ||
106 | } | ||
107 | |||
108 | kd = kzalloc(sizeof(*kd), GFP_KERNEL); | ||
109 | if (!kd) | ||
110 | return NULL; | ||
111 | |||
112 | kd->keymap = keymap = kzalloc(proplen, GFP_KERNEL); | ||
113 | if (!kd->keymap) { | ||
114 | kfree(kd); | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | kd->keymap_size = proplen / sizeof(u32); | ||
119 | |||
120 | for (i = 0; i < kd->keymap_size; i++) { | ||
121 | u32 tmp = be32_to_cpup(prop + i); | ||
122 | int key_code, row, col; | ||
123 | |||
124 | row = (tmp >> 24) & 0xff; | ||
125 | col = (tmp >> 16) & 0xff; | ||
126 | key_code = tmp & 0xffff; | ||
127 | keymap[i] = KEY(row, col, key_code); | ||
128 | } | ||
129 | |||
130 | return kd; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_fill_keymap); | ||
133 | |||
134 | void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd) | ||
135 | { | ||
136 | if (kd) { | ||
137 | kfree(kd->keymap); | ||
138 | kfree(kd); | ||
139 | } | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_free_keymap); | ||
142 | #endif | ||
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h index e8fe08ebc245..5f3aa6b11bfa 100644 --- a/include/linux/input/matrix_keypad.h +++ b/include/linux/input/matrix_keypad.h | |||
@@ -81,22 +81,4 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | |||
81 | unsigned short *keymap, | 81 | unsigned short *keymap, |
82 | struct input_dev *input_dev); | 82 | struct input_dev *input_dev); |
83 | 83 | ||
84 | #ifdef CONFIG_OF | ||
85 | struct matrix_keymap_data * | ||
86 | matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname); | ||
87 | |||
88 | void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd); | ||
89 | #else | ||
90 | static inline struct matrix_keymap_data * | ||
91 | matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname) | ||
92 | { | ||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | static inline void | ||
97 | matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd) | ||
98 | { | ||
99 | } | ||
100 | #endif | ||
101 | |||
102 | #endif /* _MATRIX_KEYPAD_H */ | 84 | #endif /* _MATRIX_KEYPAD_H */ |