summaryrefslogtreecommitdiff
path: root/drivers/input/keyboard/tegra-kbc.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-01-06 18:32:22 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-01-17 00:28:00 -0800
commit88390243a9937f9831aeba5113a8b59bb1d4411a (patch)
tree3fd73c6fc87b0c43290a4d49ee2895c8fdbeeaca /drivers/input/keyboard/tegra-kbc.c
parent00eb81e56a38ffb7839e0e6262e26c20c617d2ab (diff)
Input: tegra-kbc - add support for rows/columns configuration from dt
The NVIDIA's Tegra KBC has maximum 24 pins to make matrix keypad. Any pin can be configured as row or column. The maximum column pin can be 8 and maximum row pin can be 16. Remove the assumption that all first 16 pins will be used as row and remaining as columns and Add the property for configuring pins to either row or column from DT. Update the devicetree binding document accordingly. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/keyboard/tegra-kbc.c')
-rw-r--r--drivers/input/keyboard/tegra-kbc.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index f79993679070..39ef663bb38f 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -614,13 +614,21 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
struct device_node *np = pdev->dev.of_node;
u32 prop;
int i;
-
- if (!np)
- return NULL;
+ u32 num_rows = 0;
+ u32 num_cols = 0;
+ u32 cols_cfg[KBC_MAX_GPIO];
+ u32 rows_cfg[KBC_MAX_GPIO];
+ int proplen;
+ int ret;
+
+ if (!np) {
+ dev_err(&pdev->dev, "device tree data is missing\n");
+ return ERR_PTR(-ENOENT);
+ }
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
- return NULL;
+ return ERR_PTR(-ENOMEM);
if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop))
pdata->debounce_cnt = prop;
@@ -634,18 +642,55 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
if (of_find_property(np, "nvidia,wakeup-source", NULL))
pdata->wakeup = true;
- /*
- * All currently known keymaps with device tree support use the same
- * pin_cfg, so set it up here.
- */
- for (i = 0; i < KBC_MAX_ROW; i++) {
- pdata->pin_cfg[i].num = i;
- pdata->pin_cfg[i].type = PIN_CFG_ROW;
+ if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) {
+ dev_err(&pdev->dev, "property nvidia,kbc-row-pins not found\n");
+ return ERR_PTR(-ENOENT);
+ }
+ num_rows = proplen / sizeof(u32);
+
+ if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) {
+ dev_err(&pdev->dev, "property nvidia,kbc-col-pins not found\n");
+ return ERR_PTR(-ENOENT);
+ }
+ num_cols = proplen / sizeof(u32);
+
+ if (!of_get_property(np, "linux,keymap", &proplen)) {
+ dev_err(&pdev->dev, "property linux,keymap not found\n");
+ return ERR_PTR(-ENOENT);
}
- for (i = 0; i < KBC_MAX_COL; i++) {
- pdata->pin_cfg[KBC_MAX_ROW + i].num = i;
- pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL;
+ if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) {
+ dev_err(&pdev->dev,
+ "keypad rows/columns not porperly specified\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Set all pins as non-configured */
+ for (i = 0; i < KBC_MAX_GPIO; i++)
+ pdata->pin_cfg[i].type = PIN_CFG_IGNORE;
+
+ ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins",
+ rows_cfg, num_rows);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Rows configurations are not proper\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins",
+ cols_cfg, num_cols);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Cols configurations are not proper\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (i = 0; i < num_rows; i++) {
+ pdata->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW;
+ pdata->pin_cfg[rows_cfg[i]].num = i;
+ }
+
+ for (i = 0; i < num_cols; i++) {
+ pdata->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL;
+ pdata->pin_cfg[cols_cfg[i]].num = i;
}
return pdata;
@@ -654,7 +699,8 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
struct platform_device *pdev)
{
- return NULL;
+ dev_err(&pdev->dev, "platform data is missing\n");
+ return ERR_PTR(-EINVAL);
}
#endif
@@ -700,10 +746,8 @@ static int tegra_kbc_probe(struct platform_device *pdev)
if (!pdata)
pdata = tegra_kbc_dt_parse_pdata(pdev);
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data missing\n");
- return -EINVAL;
- }
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows))
return -EINVAL;