0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/module.h>
0017 #include <linux/moduleparam.h>
0018 #include <linux/kernel.h>
0019 #include <linux/delay.h>
0020 #include <linux/gpio/consumer.h>
0021 #include <linux/irq.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/io.h>
0024 #include <linux/soc/pxa/cpu.h>
0025 #include <linux/wm97xx.h>
0026
0027 #include <sound/pxa2xx-lib.h>
0028
0029 struct continuous {
0030 u16 id;
0031 u8 code;
0032 u8 reads;
0033 u32 speed;
0034 };
0035
0036 #define WM_READS(sp) ((sp / HZ) + 1)
0037
0038 static const struct continuous cinfo[] = {
0039 { WM9713_ID2, 0, WM_READS(94), 94 },
0040 { WM9713_ID2, 1, WM_READS(120), 120 },
0041 { WM9713_ID2, 2, WM_READS(154), 154 },
0042 { WM9713_ID2, 3, WM_READS(188), 188 },
0043 };
0044
0045
0046 static int sp_idx;
0047
0048
0049
0050
0051 static int cont_rate = 200;
0052 module_param(cont_rate, int, 0);
0053 MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
0054
0055
0056
0057
0058
0059
0060 static int pressure;
0061 module_param(pressure, int, 0);
0062 MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
0063
0064
0065
0066
0067
0068
0069 static int ac97_touch_slot = 5;
0070 module_param(ac97_touch_slot, int, 0);
0071 MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
0072
0073
0074
0075 static void wm97xx_acc_pen_up(struct wm97xx *wm)
0076 {
0077 int i;
0078
0079 msleep(1);
0080
0081 for (i = 0; i < 16; i++)
0082 pxa2xx_ac97_read_modr();
0083 }
0084
0085 static int wm97xx_acc_pen_down(struct wm97xx *wm)
0086 {
0087 u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
0088 int reads = 0;
0089 static u16 last, tries;
0090
0091
0092
0093
0094
0095
0096 msleep(1);
0097
0098 if (tries > 5) {
0099 tries = 0;
0100 return RC_PENUP;
0101 }
0102
0103 x = pxa2xx_ac97_read_modr();
0104 if (x == last) {
0105 tries++;
0106 return RC_AGAIN;
0107 }
0108 last = x;
0109 do {
0110 if (reads)
0111 x = pxa2xx_ac97_read_modr();
0112 y = pxa2xx_ac97_read_modr();
0113 if (pressure)
0114 p = pxa2xx_ac97_read_modr();
0115
0116 dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
0117 x, y, p);
0118
0119
0120 if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
0121 (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
0122 (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
0123 goto up;
0124
0125
0126 tries = 0;
0127 input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
0128 input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
0129 input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
0130 input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
0131 input_sync(wm->input_dev);
0132 reads++;
0133 } while (reads < cinfo[sp_idx].reads);
0134 up:
0135 return RC_PENDOWN | RC_AGAIN;
0136 }
0137
0138 static int wm97xx_acc_startup(struct wm97xx *wm)
0139 {
0140 int idx;
0141
0142
0143 if (wm->ac97 == NULL)
0144 return -ENODEV;
0145
0146
0147 for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
0148 if (wm->id != cinfo[idx].id)
0149 continue;
0150 sp_idx = idx;
0151 if (cont_rate <= cinfo[idx].speed)
0152 break;
0153 }
0154 wm->acc_rate = cinfo[sp_idx].code;
0155 wm->acc_slot = ac97_touch_slot;
0156 dev_info(wm->dev,
0157 "zylonite accelerated touchscreen driver, %d samples/sec\n",
0158 cinfo[sp_idx].speed);
0159
0160 return 0;
0161 }
0162
0163 static struct wm97xx_mach_ops zylonite_mach_ops = {
0164 .acc_enabled = 1,
0165 .acc_pen_up = wm97xx_acc_pen_up,
0166 .acc_pen_down = wm97xx_acc_pen_down,
0167 .acc_startup = wm97xx_acc_startup,
0168 .irq_gpio = WM97XX_GPIO_2,
0169 };
0170
0171 static int zylonite_wm97xx_probe(struct platform_device *pdev)
0172 {
0173 struct wm97xx *wm = platform_get_drvdata(pdev);
0174 struct gpio_desc *gpio_touch_irq;
0175 int err;
0176
0177 gpio_touch_irq = devm_gpiod_get(&pdev->dev, "touch", GPIOD_IN);
0178 err = PTR_ERR_OR_ZERO(gpio_touch_irq);
0179 if (err) {
0180 dev_err(&pdev->dev, "Cannot get irq gpio: %d\n", err);
0181 return err;
0182 }
0183
0184 wm->pen_irq = gpiod_to_irq(gpio_touch_irq);
0185 irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
0186
0187 wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
0188 WM97XX_GPIO_POL_HIGH,
0189 WM97XX_GPIO_STICKY,
0190 WM97XX_GPIO_WAKE);
0191 wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
0192 WM97XX_GPIO_POL_HIGH,
0193 WM97XX_GPIO_NOTSTICKY,
0194 WM97XX_GPIO_NOWAKE);
0195
0196 return wm97xx_register_mach_ops(wm, &zylonite_mach_ops);
0197 }
0198
0199 static int zylonite_wm97xx_remove(struct platform_device *pdev)
0200 {
0201 struct wm97xx *wm = platform_get_drvdata(pdev);
0202
0203 wm97xx_unregister_mach_ops(wm);
0204
0205 return 0;
0206 }
0207
0208 static struct platform_driver zylonite_wm97xx_driver = {
0209 .probe = zylonite_wm97xx_probe,
0210 .remove = zylonite_wm97xx_remove,
0211 .driver = {
0212 .name = "wm97xx-touch",
0213 },
0214 };
0215 module_platform_driver(zylonite_wm97xx_driver);
0216
0217
0218 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0219 MODULE_DESCRIPTION("wm97xx continuous touch driver for Zylonite");
0220 MODULE_LICENSE("GPL");