Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Touchscreen driver for the tps6507x chip.
0003  *
0004  * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com)
0005  *
0006  * Credits:
0007  *
0008  *    Using code from tsc2007, MtekVision Co., Ltd.
0009  *
0010  * For licencing details see kernel-base/COPYING
0011  *
0012  * TPS65070, TPS65073, TPS650731, and TPS650732 support
0013  * 10 bit touch screen interface.
0014  */
0015 
0016 #include <linux/module.h>
0017 #include <linux/workqueue.h>
0018 #include <linux/slab.h>
0019 #include <linux/input.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/mfd/tps6507x.h>
0022 #include <linux/input/tps6507x-ts.h>
0023 #include <linux/delay.h>
0024 
0025 #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */
0026 #define TPS_DEFAULT_MIN_PRESSURE 0x30
0027 #define MAX_10BIT ((1 << 10) - 1)
0028 
0029 #define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \
0030                      TPS6507X_ADCONFIG_START_CONVERSION | \
0031                      TPS6507X_ADCONFIG_INPUT_REAL_TSC)
0032 #define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC)
0033 
0034 struct ts_event {
0035     u16 x;
0036     u16 y;
0037     u16 pressure;
0038 };
0039 
0040 struct tps6507x_ts {
0041     struct device       *dev;
0042     struct input_dev    *input;
0043     struct tps6507x_dev *mfd;
0044     char            phys[32];
0045     struct ts_event     tc;
0046     u16         min_pressure;
0047     bool            pendown;
0048 };
0049 
0050 static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
0051 {
0052     return tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
0053 }
0054 
0055 static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
0056 {
0057     return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data);
0058 }
0059 
0060 static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc,
0061                    u8 tsc_mode, u16 *value)
0062 {
0063     s32 ret;
0064     u8 adc_status;
0065     u8 result;
0066 
0067     /* Route input signal to A/D converter */
0068 
0069     ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode);
0070     if (ret) {
0071         dev_err(tsc->dev, "TSC mode read failed\n");
0072         goto err;
0073     }
0074 
0075     /* Start A/D conversion */
0076 
0077     ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG,
0078                 TPS6507X_ADCONFIG_CONVERT_TS);
0079     if (ret) {
0080         dev_err(tsc->dev, "ADC config write failed\n");
0081         return ret;
0082     }
0083 
0084     do {
0085         ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG,
0086                        &adc_status);
0087         if (ret) {
0088             dev_err(tsc->dev, "ADC config read failed\n");
0089             goto err;
0090         }
0091     } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION);
0092 
0093     ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result);
0094     if (ret) {
0095         dev_err(tsc->dev, "ADC result 2 read failed\n");
0096         goto err;
0097     }
0098 
0099     *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8;
0100 
0101     ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result);
0102     if (ret) {
0103         dev_err(tsc->dev, "ADC result 1 read failed\n");
0104         goto err;
0105     }
0106 
0107     *value |= result;
0108 
0109     dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value);
0110 
0111 err:
0112     return ret;
0113 }
0114 
0115 /* Need to call tps6507x_adc_standby() after using A/D converter for the
0116  * touch screen interrupt to work properly.
0117  */
0118 
0119 static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
0120 {
0121     s32 ret;
0122     s32 loops = 0;
0123     u8 val;
0124 
0125     ret = tps6507x_write_u8(tsc,  TPS6507X_REG_ADCONFIG,
0126                 TPS6507X_ADCONFIG_INPUT_TSC);
0127     if (ret)
0128         return ret;
0129 
0130     ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE,
0131                 TPS6507X_TSCMODE_STANDBY);
0132     if (ret)
0133         return ret;
0134 
0135     ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
0136     if (ret)
0137         return ret;
0138 
0139     while (val & TPS6507X_REG_TSC_INT) {
0140         mdelay(10);
0141         ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
0142         if (ret)
0143             return ret;
0144         loops++;
0145     }
0146 
0147     return ret;
0148 }
0149 
0150 static void tps6507x_ts_poll(struct input_dev *input_dev)
0151 {
0152     struct tps6507x_ts *tsc = input_get_drvdata(input_dev);
0153     bool pendown;
0154     s32 ret;
0155 
0156     ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
0157                       &tsc->tc.pressure);
0158     if (ret)
0159         goto done;
0160 
0161     pendown = tsc->tc.pressure > tsc->min_pressure;
0162 
0163     if (unlikely(!pendown && tsc->pendown)) {
0164         dev_dbg(tsc->dev, "UP\n");
0165         input_report_key(input_dev, BTN_TOUCH, 0);
0166         input_report_abs(input_dev, ABS_PRESSURE, 0);
0167         input_sync(input_dev);
0168         tsc->pendown = false;
0169     }
0170 
0171     if (pendown) {
0172 
0173         if (!tsc->pendown) {
0174             dev_dbg(tsc->dev, "DOWN\n");
0175             input_report_key(input_dev, BTN_TOUCH, 1);
0176         } else
0177             dev_dbg(tsc->dev, "still down\n");
0178 
0179         ret =  tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION,
0180                            &tsc->tc.x);
0181         if (ret)
0182             goto done;
0183 
0184         ret =  tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION,
0185                            &tsc->tc.y);
0186         if (ret)
0187             goto done;
0188 
0189         input_report_abs(input_dev, ABS_X, tsc->tc.x);
0190         input_report_abs(input_dev, ABS_Y, tsc->tc.y);
0191         input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure);
0192         input_sync(input_dev);
0193         tsc->pendown = true;
0194     }
0195 
0196 done:
0197     tps6507x_adc_standby(tsc);
0198 }
0199 
0200 static int tps6507x_ts_probe(struct platform_device *pdev)
0201 {
0202     struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
0203     const struct tps6507x_board *tps_board;
0204     const struct touchscreen_init_data *init_data;
0205     struct tps6507x_ts *tsc;
0206     struct input_dev *input_dev;
0207     int error;
0208 
0209     /*
0210      * tps_board points to pmic related constants
0211      * coming from the board-evm file.
0212      */
0213     tps_board = dev_get_platdata(tps6507x_dev->dev);
0214     if (!tps_board) {
0215         dev_err(tps6507x_dev->dev,
0216             "Could not find tps6507x platform data\n");
0217         return -ENODEV;
0218     }
0219 
0220     /*
0221      * init_data points to array of regulator_init structures
0222      * coming from the board-evm file.
0223      */
0224     init_data = tps_board->tps6507x_ts_init_data;
0225 
0226     tsc = devm_kzalloc(&pdev->dev, sizeof(struct tps6507x_ts), GFP_KERNEL);
0227     if (!tsc) {
0228         dev_err(tps6507x_dev->dev, "failed to allocate driver data\n");
0229         return -ENOMEM;
0230     }
0231 
0232     tsc->mfd = tps6507x_dev;
0233     tsc->dev = tps6507x_dev->dev;
0234     tsc->min_pressure = init_data ?
0235             init_data->min_pressure : TPS_DEFAULT_MIN_PRESSURE;
0236 
0237     snprintf(tsc->phys, sizeof(tsc->phys),
0238          "%s/input0", dev_name(tsc->dev));
0239 
0240     input_dev = devm_input_allocate_device(&pdev->dev);
0241     if (!input_dev) {
0242         dev_err(tsc->dev, "Failed to allocate polled input device.\n");
0243         return -ENOMEM;
0244     }
0245 
0246     tsc->input = input_dev;
0247     input_set_drvdata(input_dev, tsc);
0248 
0249     input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
0250     input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0);
0251     input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0);
0252     input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
0253 
0254     input_dev->name = "TPS6507x Touchscreen";
0255     input_dev->phys = tsc->phys;
0256     input_dev->dev.parent = tsc->dev;
0257     input_dev->id.bustype = BUS_I2C;
0258     if (init_data) {
0259         input_dev->id.vendor = init_data->vendor;
0260         input_dev->id.product = init_data->product;
0261         input_dev->id.version = init_data->version;
0262     }
0263 
0264     error = tps6507x_adc_standby(tsc);
0265     if (error)
0266         return error;
0267 
0268     error = input_setup_polling(input_dev, tps6507x_ts_poll);
0269     if (error)
0270         return error;
0271 
0272     input_set_poll_interval(input_dev,
0273                 init_data ? init_data->poll_period :
0274                         TSC_DEFAULT_POLL_PERIOD);
0275 
0276     error = input_register_device(input_dev);
0277     if (error)
0278         return error;
0279 
0280     return 0;
0281 }
0282 
0283 static struct platform_driver tps6507x_ts_driver = {
0284     .driver = {
0285         .name = "tps6507x-ts",
0286     },
0287     .probe = tps6507x_ts_probe,
0288 };
0289 module_platform_driver(tps6507x_ts_driver);
0290 
0291 MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>");
0292 MODULE_DESCRIPTION("TPS6507x - TouchScreen driver");
0293 MODULE_LICENSE("GPL v2");
0294 MODULE_ALIAS("platform:tps6507x-ts");