diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt new file mode 100644 index 00000000000000..d3149e16e488b3 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt @@ -0,0 +1,51 @@ +* Atmel maXtouch touchscreen controller + +Required properties: +- compatible: must be "atmel,maxtouch" +- reg: I2C address of the chip +- interrupt-parent: interrupt controller which provides the interrupt +- interrupts: interrupt signal to which the chip is connected +- atmel,x-line: horizonal line +- atmel,y-line: vertical line +- atmel,x-size: horizontal resolution of touchscreen +- atmel,y-size: vertical resolution of touchscreen +- atmel,burst-length: burst length +- atmel,threshold: threshold +- atmel,orientation: touchscreen orientation, must be one of following: + - 0: normal + - 1: diagonal + - 2: horizonally flipped + - 3: rotated by 90 degrees counter-clockwise + - 4: vertically flipped + - 5: rotated by 90 degress clockwise + - 6: rotated by 180 degrees + - 7: diagonal counter + +Optional properties: +- vdd-supply: voltage regulator used for power control and reading + operating voltage + +Example: + + i2c@00000000 { + /* ... */ + + tsp@4a { + compatible = "atmel,maxtouch"; + reg = <0x4a>; + interrupt-parent = <&gpe1>; + interrupts = <7 2>; + + atmel,x-line = <19>; + atmel,y-line = <11>; + atmel,x-size = <800>; + atmel,y-size = <480>; + atmel,burst-length = <0x11>; + atmel,threshold = <0x28>; + atmel,orientation = <1>; + + vdd-supply = <&tsp_reg>; + }; + + /* ... */ + }; diff --git a/arch/arm/boot/dts/s5p6442-apollo.dts b/arch/arm/boot/dts/s5p6442-apollo.dts index 108b230eefb099..4c5cb5bbb6caac 100644 --- a/arch/arm/boot/dts/s5p6442-apollo.dts +++ b/arch/arm/boot/dts/s5p6442-apollo.dts @@ -532,12 +532,21 @@ status = "okay"; touchscreen@4a { - compatible = "atmel,qt602240_ts"; + compatible = "atmel,maxtouch"; reg = <0x4a>; interrupt-parent = <&gpg0>; - interrupts = <2>; + interrupts = <2 8>; gpios = <&gpe1 4 0>; - // TODO + + atmel,x-line = <18>; + atmel,y-line = <11>; + atmel,x-size = <400>; + atmel,y-size = <240>; + atmel,burst-length = <0x11>; + atmel,threshold = <0x28>; + atmel,orientation = <1>; + + vdd-supply = <&ldo13_reg>; }; }; diff --git a/arch/arm/configs/s5p6442_defconfig b/arch/arm/configs/s5p6442_defconfig index 425d2d19e72236..448ed2d28be785 100644 --- a/arch/arm/configs/s5p6442_defconfig +++ b/arch/arm/configs/s5p6442_defconfig @@ -1015,7 +1015,47 @@ CONFIG_INPUT_LEDS=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_BMA150 is not set diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index a8a8a326ca6251..801fccfd9f4854 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -238,6 +238,32 @@ static void __init goni_radio_init(void) } /* TSP */ +static struct regulator_consumer_supply tsp_fixed_consumer = + REGULATOR_SUPPLY("vdd", "2-004a"); + +static struct regulator_init_data tsp_fixed_voltage_init_data = { + .constraints = { + .name = "TSP_2.8V", + }, + .num_consumer_supplies = 1, + .consumer_supplies = &tsp_fixed_consumer, +}; + +static struct fixed_voltage_config tsp_fixed_voltage_config = { + .supply_name = "TSP_VDD", + .microvolts = 2800000, + .gpio = -EINVAL, + .init_data = &tsp_fixed_voltage_init_data, +}; + +static struct platform_device tsp_fixed_voltage = { + .name = "reg-fixed-voltage", + .id = 3, + .dev = { + .platform_data = &tsp_fixed_voltage_config, + }, +}; + static struct mxt_platform_data qt602240_platform_data = { .x_line = 17, .y_line = 11, @@ -245,7 +271,6 @@ static struct mxt_platform_data qt602240_platform_data = { .y_size = 480, .blen = 0x21, .threshold = 0x28, - .voltage = 2800000, /* 2.8V */ .orient = MXT_DIAGONAL, .irqflags = IRQF_TRIGGER_FALLING, }; @@ -885,6 +910,7 @@ static struct platform_device *goni_devices[] __initdata = { &s3c_device_usb_hsotg, &samsung_device_keypad, &s3c_device_i2c1, + &tsp_fixed_voltage, &s3c_device_i2c2, &wm8994_fixed_voltage0, &wm8994_fixed_voltage1, diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 37ea05741d209a..771028bd236741 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* Version */ @@ -247,6 +248,7 @@ struct mxt_message { struct mxt_data { struct i2c_client *client; struct input_dev *input_dev; + struct regulator *regulator; char phys[64]; /* device physical location */ const struct mxt_platform_data *pdata; struct mxt_object *object_table; @@ -720,13 +722,14 @@ static void mxt_handle_pdata(struct mxt_data *data) MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); /* Set touchscreen voltage */ - if (pdata->voltage) { - if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { - voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / + if (!IS_ERR(data->regulator)) { + int reg_voltage = regulator_get_voltage(data->regulator); + if (reg_voltage < MXT_VOLTAGE_DEFAULT) { + voltage = (MXT_VOLTAGE_DEFAULT - reg_voltage) / MXT_VOLTAGE_STEP; voltage = 0xff - voltage + 1; } else - voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / + voltage = (reg_voltage - MXT_VOLTAGE_DEFAULT) / MXT_VOLTAGE_STEP; mxt_write_object(data, MXT_SPT_CTECONFIG_T28, @@ -1127,6 +1130,74 @@ static void mxt_input_close(struct input_dev *dev) mxt_stop(data); } +#ifdef CONFIG_OF +static struct of_device_id mxt_dt_match[] = { + { .compatible = "atmel,maxtouch" }, + {} +}; +MODULE_DEVICE_TABLE(of, mxt_dt_match); + +static struct mxt_platform_data *mxt_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct mxt_platform_data *pd; + u32 val; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + dev_err(dev, "Failed to allocate platform data\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,x-line", &pd->x_line)) { + dev_err(dev, "failed to get atmel,x-line property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,y-line", &pd->y_line)) { + dev_err(dev, "failed to get atmel,y-line property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,x-size", &pd->x_size)) { + dev_err(dev, "failed to get atmel,x-size property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,y-size", &pd->y_size)) { + dev_err(dev, "failed to get atmel,y-size property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,burst-length", &pd->blen)) { + dev_err(dev, "failed to get atmel,burst-length property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,threshold", &pd->threshold)) { + dev_err(dev, "failed to get atmel,threshold property\n"); + return NULL; + } + + if (of_property_read_u32(np, "atmel,orientation", &val)) { + dev_err(dev, "failed to get atmel,orientation property\n"); + return NULL; + } + if (val > MXT_DIAGONAL_COUNTER) { + dev_err(dev, "invalid value for atmel-orientation property\n"); + return NULL; + } + pd->orient = val; + + return pd; +} +#else +static struct mxt_platform_data *mxt_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1136,6 +1207,9 @@ static int mxt_probe(struct i2c_client *client, int error; unsigned int num_mt_slots; + if (!pdata && client->dev.of_node) + pdata = mxt_parse_dt(&client->dev); + if (!pdata) return -EINVAL; @@ -1151,6 +1225,13 @@ static int mxt_probe(struct i2c_client *client, input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" : "Atmel maXTouch Touchscreen"; + + data->regulator = devm_regulator_get(&client->dev, "vdd"); + if (!IS_ERR(data->regulator)) { + regulator_enable(data->regulator); + msleep(100); + } + snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", client->adapter->nr, client->addr); @@ -1170,7 +1251,7 @@ static int mxt_probe(struct i2c_client *client, error = mxt_initialize(data); if (error) - goto err_free_mem; + goto err_disable_regulator; __set_bit(EV_ABS, input_dev->evbit); __set_bit(EV_KEY, input_dev->evbit); @@ -1253,6 +1334,9 @@ static int mxt_probe(struct i2c_client *client, free_irq(client->irq, data); err_free_object: kfree(data->object_table); +err_disable_regulator: + if (!IS_ERR(data->regulator)) + regulator_disable(data->regulator); err_free_mem: input_free_device(input_dev); kfree(data); @@ -1267,6 +1351,8 @@ static int mxt_remove(struct i2c_client *client) free_irq(data->irq, data); input_unregister_device(data->input_dev); kfree(data->object_table); + if (!IS_ERR(data->regulator)) + regulator_disable(data->regulator); kfree(data); return 0; @@ -1328,6 +1414,7 @@ static struct i2c_driver mxt_driver = { .name = "atmel_mxt_ts", .owner = THIS_MODULE, .pm = &mxt_pm_ops, + .of_match_table = of_match_ptr(mxt_dt_match), }, .probe = mxt_probe, .remove = mxt_remove, diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index 99e379b74398e6..03cb0c74235b21 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -39,7 +39,6 @@ struct mxt_platform_data { unsigned int y_size; unsigned int blen; unsigned int threshold; - unsigned int voltage; unsigned char orient; unsigned long irqflags; bool is_tp;