diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/input/touchscreen/ads7846.c | 115 |
1 files changed, 104 insertions, 11 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 5ff041995198..ea195360747e 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -27,6 +27,9 @@ | |||
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
| 30 | #include <linux/of.h> | ||
| 31 | #include <linux/of_gpio.h> | ||
| 32 | #include <linux/of_device.h> | ||
| 30 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 31 | #include <linux/spi/spi.h> | 34 | #include <linux/spi/spi.h> |
| 32 | #include <linux/spi/ads7846.h> | 35 | #include <linux/spi/ads7846.h> |
| @@ -1201,9 +1204,87 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, | |||
| 1201 | spi_message_add_tail(x, m); | 1204 | spi_message_add_tail(x, m); |
| 1202 | } | 1205 | } |
| 1203 | 1206 | ||
| 1207 | #ifdef CONFIG_OF | ||
| 1208 | static const struct of_device_id ads7846_dt_ids[] = { | ||
| 1209 | { .compatible = "ti,tsc2046", .data = (void *) 7846 }, | ||
| 1210 | { .compatible = "ti,ads7843", .data = (void *) 7843 }, | ||
| 1211 | { .compatible = "ti,ads7845", .data = (void *) 7845 }, | ||
| 1212 | { .compatible = "ti,ads7846", .data = (void *) 7846 }, | ||
| 1213 | { .compatible = "ti,ads7873", .data = (void *) 7873 }, | ||
| 1214 | { } | ||
| 1215 | }; | ||
| 1216 | MODULE_DEVICE_TABLE(of, ads7846_dt_ids); | ||
| 1217 | |||
| 1218 | static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) | ||
| 1219 | { | ||
| 1220 | struct ads7846_platform_data *pdata; | ||
| 1221 | struct device_node *node = dev->of_node; | ||
| 1222 | const struct of_device_id *match; | ||
| 1223 | |||
| 1224 | if (!node) { | ||
| 1225 | dev_err(dev, "Device does not have associated DT data\n"); | ||
| 1226 | return ERR_PTR(-EINVAL); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | match = of_match_device(ads7846_dt_ids, dev); | ||
| 1230 | if (!match) { | ||
| 1231 | dev_err(dev, "Unknown device model\n"); | ||
| 1232 | return ERR_PTR(-EINVAL); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
| 1236 | if (!pdata) | ||
| 1237 | return ERR_PTR(-ENOMEM); | ||
| 1238 | |||
| 1239 | pdata->model = (unsigned long)match->data; | ||
| 1240 | |||
| 1241 | of_property_read_u16(node, "ti,vref-delay-usecs", | ||
| 1242 | &pdata->vref_delay_usecs); | ||
| 1243 | of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv); | ||
| 1244 | pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on"); | ||
| 1245 | |||
| 1246 | pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy"); | ||
| 1247 | |||
| 1248 | of_property_read_u16(node, "ti,settle-delay-usec", | ||
| 1249 | &pdata->settle_delay_usecs); | ||
| 1250 | of_property_read_u16(node, "ti,penirq-recheck-delay-usecs", | ||
| 1251 | &pdata->penirq_recheck_delay_usecs); | ||
| 1252 | |||
| 1253 | of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms); | ||
| 1254 | of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms); | ||
| 1255 | |||
| 1256 | of_property_read_u16(node, "ti,x-min", &pdata->x_min); | ||
| 1257 | of_property_read_u16(node, "ti,y-min", &pdata->y_min); | ||
| 1258 | of_property_read_u16(node, "ti,x-max", &pdata->x_max); | ||
| 1259 | of_property_read_u16(node, "ti,y-max", &pdata->y_max); | ||
| 1260 | |||
| 1261 | of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); | ||
| 1262 | of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); | ||
| 1263 | |||
| 1264 | of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); | ||
| 1265 | of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); | ||
| 1266 | of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); | ||
| 1267 | |||
| 1268 | of_property_read_u32(node, "ti,pendown-gpio-debounce", | ||
| 1269 | &pdata->gpio_pendown_debounce); | ||
| 1270 | |||
| 1271 | pdata->wakeup = of_property_read_bool(node, "linux,wakeup"); | ||
| 1272 | |||
| 1273 | pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0); | ||
| 1274 | |||
| 1275 | return pdata; | ||
| 1276 | } | ||
| 1277 | #else | ||
| 1278 | static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) | ||
| 1279 | { | ||
| 1280 | dev_err(dev, "no platform data defined\n"); | ||
| 1281 | return ERR_PTR(-EINVAL); | ||
| 1282 | } | ||
| 1283 | #endif | ||
| 1284 | |||
| 1204 | static int ads7846_probe(struct spi_device *spi) | 1285 | static int ads7846_probe(struct spi_device *spi) |
| 1205 | { | 1286 | { |
| 1206 | const struct ads7846_platform_data *pdata = dev_get_platdata(&spi->dev); | 1287 | const struct ads7846_platform_data *pdata; |
| 1207 | struct ads7846 *ts; | 1288 | struct ads7846 *ts; |
| 1208 | struct ads7846_packet *packet; | 1289 | struct ads7846_packet *packet; |
| 1209 | struct input_dev *input_dev; | 1290 | struct input_dev *input_dev; |
| @@ -1212,22 +1293,18 @@ static int ads7846_probe(struct spi_device *spi) | |||
| 1212 | 1293 | ||
| 1213 | if (!spi->irq) { | 1294 | if (!spi->irq) { |
| 1214 | dev_dbg(&spi->dev, "no IRQ?\n"); | 1295 | dev_dbg(&spi->dev, "no IRQ?\n"); |
| 1215 | return -ENODEV; | 1296 | return -EINVAL; |
| 1216 | } | ||
| 1217 | |||
| 1218 | if (!pdata) { | ||
| 1219 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
| 1220 | return -ENODEV; | ||
| 1221 | } | 1297 | } |
| 1222 | 1298 | ||
| 1223 | /* don't exceed max specified sample rate */ | 1299 | /* don't exceed max specified sample rate */ |
| 1224 | if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { | 1300 | if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { |
| 1225 | dev_dbg(&spi->dev, "f(sample) %d KHz?\n", | 1301 | dev_err(&spi->dev, "f(sample) %d KHz?\n", |
| 1226 | (spi->max_speed_hz/SAMPLE_BITS)/1000); | 1302 | (spi->max_speed_hz/SAMPLE_BITS)/1000); |
| 1227 | return -EINVAL; | 1303 | return -EINVAL; |
| 1228 | } | 1304 | } |
| 1229 | 1305 | ||
| 1230 | /* We'd set TX word size 8 bits and RX word size to 13 bits ... except | 1306 | /* |
| 1307 | * We'd set TX word size 8 bits and RX word size to 13 bits ... except | ||
| 1231 | * that even if the hardware can do that, the SPI controller driver | 1308 | * that even if the hardware can do that, the SPI controller driver |
| 1232 | * may not. So we stick to very-portable 8 bit words, both RX and TX. | 1309 | * may not. So we stick to very-portable 8 bit words, both RX and TX. |
| 1233 | */ | 1310 | */ |
| @@ -1250,17 +1327,25 @@ static int ads7846_probe(struct spi_device *spi) | |||
| 1250 | ts->packet = packet; | 1327 | ts->packet = packet; |
| 1251 | ts->spi = spi; | 1328 | ts->spi = spi; |
| 1252 | ts->input = input_dev; | 1329 | ts->input = input_dev; |
| 1253 | ts->vref_mv = pdata->vref_mv; | ||
| 1254 | ts->swap_xy = pdata->swap_xy; | ||
| 1255 | 1330 | ||
| 1256 | mutex_init(&ts->lock); | 1331 | mutex_init(&ts->lock); |
| 1257 | init_waitqueue_head(&ts->wait); | 1332 | init_waitqueue_head(&ts->wait); |
| 1258 | 1333 | ||
| 1334 | pdata = dev_get_platdata(&spi->dev); | ||
| 1335 | if (!pdata) { | ||
| 1336 | pdata = ads7846_probe_dt(&spi->dev); | ||
| 1337 | if (IS_ERR(pdata)) | ||
| 1338 | return PTR_ERR(pdata); | ||
| 1339 | } | ||
| 1340 | |||
| 1259 | ts->model = pdata->model ? : 7846; | 1341 | ts->model = pdata->model ? : 7846; |
| 1260 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | 1342 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; |
| 1261 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | 1343 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; |
| 1262 | ts->pressure_max = pdata->pressure_max ? : ~0; | 1344 | ts->pressure_max = pdata->pressure_max ? : ~0; |
| 1263 | 1345 | ||
| 1346 | ts->vref_mv = pdata->vref_mv; | ||
| 1347 | ts->swap_xy = pdata->swap_xy; | ||
| 1348 | |||
| 1264 | if (pdata->filter != NULL) { | 1349 | if (pdata->filter != NULL) { |
| 1265 | if (pdata->filter_init != NULL) { | 1350 | if (pdata->filter_init != NULL) { |
| 1266 | err = pdata->filter_init(pdata, &ts->filter_data); | 1351 | err = pdata->filter_init(pdata, &ts->filter_data); |
| @@ -1370,6 +1455,13 @@ static int ads7846_probe(struct spi_device *spi) | |||
| 1370 | 1455 | ||
| 1371 | device_init_wakeup(&spi->dev, pdata->wakeup); | 1456 | device_init_wakeup(&spi->dev, pdata->wakeup); |
| 1372 | 1457 | ||
| 1458 | /* | ||
| 1459 | * If device does not carry platform data we must have allocated it | ||
| 1460 | * when parsing DT data. | ||
| 1461 | */ | ||
| 1462 | if (!dev_get_platdata(&spi->dev)) | ||
| 1463 | devm_kfree(&spi->dev, (void *)pdata); | ||
| 1464 | |||
| 1373 | return 0; | 1465 | return 0; |
| 1374 | 1466 | ||
| 1375 | err_remove_attr_group: | 1467 | err_remove_attr_group: |
| @@ -1437,6 +1529,7 @@ static struct spi_driver ads7846_driver = { | |||
| 1437 | .name = "ads7846", | 1529 | .name = "ads7846", |
| 1438 | .owner = THIS_MODULE, | 1530 | .owner = THIS_MODULE, |
| 1439 | .pm = &ads7846_pm, | 1531 | .pm = &ads7846_pm, |
| 1532 | .of_match_table = of_match_ptr(ads7846_dt_ids), | ||
| 1440 | }, | 1533 | }, |
| 1441 | .probe = ads7846_probe, | 1534 | .probe = ads7846_probe, |
| 1442 | .remove = ads7846_remove, | 1535 | .remove = ads7846_remove, |
