aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenson Leung <bleung@chromium.org>2018-04-10 02:00:04 -0400
committerBenson Leung <bleung@chromium.org>2018-04-10 02:00:04 -0400
commit72655f6cf7fe04b867776bb7120fbdb84dee4f61 (patch)
tree000347fc0721362eb43b0449f1b3484f2696ad3b
parentf56db262e46d3368ee4e5c9e19797853cab382cd (diff)
parent96a938aa214e965d5b4a2f10443b29cad14289b9 (diff)
Merge remote-tracking branch 'chrome-platform-stop-being-a-platform-driver-plus-atmel_mxt_ts-for-v4.17' into working-branch-for-4.17
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c231
-rw-r--r--drivers/platform/chrome/chromeos_laptop.c896
-rw-r--r--include/linux/platform_data/atmel_mxt_ts.h31
4 files changed, 579 insertions, 580 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 73c0cdabf755..d4b0b09d2e3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2394,7 +2394,6 @@ T: git git://github.com/ndyer/linux.git
2394S: Maintained 2394S: Maintained
2395F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt 2395F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt
2396F: drivers/input/touchscreen/atmel_mxt_ts.c 2396F: drivers/input/touchscreen/atmel_mxt_ts.c
2397F: include/linux/platform_data/atmel_mxt_ts.h
2398 2397
2399ATMEL SAMA5D2 ADC DRIVER 2398ATMEL SAMA5D2 ADC DRIVER
2400M: Ludovic Desroches <ludovic.desroches@microchip.com> 2399M: Ludovic Desroches <ludovic.desroches@microchip.com>
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 7659bc48f1db..5d9699fe1b55 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -23,12 +23,13 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/firmware.h> 24#include <linux/firmware.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/platform_data/atmel_mxt_ts.h>
27#include <linux/input/mt.h> 26#include <linux/input/mt.h>
28#include <linux/interrupt.h> 27#include <linux/interrupt.h>
29#include <linux/of.h> 28#include <linux/of.h>
29#include <linux/property.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/gpio/consumer.h> 31#include <linux/gpio/consumer.h>
32#include <linux/property.h>
32#include <asm/unaligned.h> 33#include <asm/unaligned.h>
33#include <media/v4l2-device.h> 34#include <media/v4l2-device.h>
34#include <media/v4l2-ioctl.h> 35#include <media/v4l2-ioctl.h>
@@ -268,12 +269,16 @@ static const struct v4l2_file_operations mxt_video_fops = {
268 .poll = vb2_fop_poll, 269 .poll = vb2_fop_poll,
269}; 270};
270 271
272enum mxt_suspend_mode {
273 MXT_SUSPEND_DEEP_SLEEP = 0,
274 MXT_SUSPEND_T9_CTRL = 1,
275};
276
271/* Each client has this additional data */ 277/* Each client has this additional data */
272struct mxt_data { 278struct mxt_data {
273 struct i2c_client *client; 279 struct i2c_client *client;
274 struct input_dev *input_dev; 280 struct input_dev *input_dev;
275 char phys[64]; /* device physical location */ 281 char phys[64]; /* device physical location */
276 const struct mxt_platform_data *pdata;
277 struct mxt_object *object_table; 282 struct mxt_object *object_table;
278 struct mxt_info info; 283 struct mxt_info info;
279 unsigned int irq; 284 unsigned int irq;
@@ -324,6 +329,11 @@ struct mxt_data {
324 329
325 /* for config update handling */ 330 /* for config update handling */
326 struct completion crc_completion; 331 struct completion crc_completion;
332
333 u32 *t19_keymap;
334 unsigned int t19_num_keys;
335
336 enum mxt_suspend_mode suspend_mode;
327}; 337};
328 338
329struct mxt_vb2_buffer { 339struct mxt_vb2_buffer {
@@ -742,15 +752,14 @@ static int mxt_write_object(struct mxt_data *data,
742static void mxt_input_button(struct mxt_data *data, u8 *message) 752static void mxt_input_button(struct mxt_data *data, u8 *message)
743{ 753{
744 struct input_dev *input = data->input_dev; 754 struct input_dev *input = data->input_dev;
745 const struct mxt_platform_data *pdata = data->pdata;
746 int i; 755 int i;
747 756
748 for (i = 0; i < pdata->t19_num_keys; i++) { 757 for (i = 0; i < data->t19_num_keys; i++) {
749 if (pdata->t19_keymap[i] == KEY_RESERVED) 758 if (data->t19_keymap[i] == KEY_RESERVED)
750 continue; 759 continue;
751 760
752 /* Active-low switch */ 761 /* Active-low switch */
753 input_report_key(input, pdata->t19_keymap[i], 762 input_report_key(input, data->t19_keymap[i],
754 !(message[1] & BIT(i))); 763 !(message[1] & BIT(i)));
755 } 764 }
756} 765}
@@ -758,7 +767,7 @@ static void mxt_input_button(struct mxt_data *data, u8 *message)
758static void mxt_input_sync(struct mxt_data *data) 767static void mxt_input_sync(struct mxt_data *data)
759{ 768{
760 input_mt_report_pointer_emulation(data->input_dev, 769 input_mt_report_pointer_emulation(data->input_dev,
761 data->pdata->t19_num_keys); 770 data->t19_num_keys);
762 input_sync(data->input_dev); 771 input_sync(data->input_dev);
763} 772}
764 773
@@ -1858,7 +1867,6 @@ static void mxt_input_close(struct input_dev *dev);
1858static void mxt_set_up_as_touchpad(struct input_dev *input_dev, 1867static void mxt_set_up_as_touchpad(struct input_dev *input_dev,
1859 struct mxt_data *data) 1868 struct mxt_data *data)
1860{ 1869{
1861 const struct mxt_platform_data *pdata = data->pdata;
1862 int i; 1870 int i;
1863 1871
1864 input_dev->name = "Atmel maXTouch Touchpad"; 1872 input_dev->name = "Atmel maXTouch Touchpad";
@@ -1872,15 +1880,14 @@ static void mxt_set_up_as_touchpad(struct input_dev *input_dev,
1872 input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 1880 input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
1873 MXT_PIXELS_PER_MM); 1881 MXT_PIXELS_PER_MM);
1874 1882
1875 for (i = 0; i < pdata->t19_num_keys; i++) 1883 for (i = 0; i < data->t19_num_keys; i++)
1876 if (pdata->t19_keymap[i] != KEY_RESERVED) 1884 if (data->t19_keymap[i] != KEY_RESERVED)
1877 input_set_capability(input_dev, EV_KEY, 1885 input_set_capability(input_dev, EV_KEY,
1878 pdata->t19_keymap[i]); 1886 data->t19_keymap[i]);
1879} 1887}
1880 1888
1881static int mxt_initialize_input_device(struct mxt_data *data) 1889static int mxt_initialize_input_device(struct mxt_data *data)
1882{ 1890{
1883 const struct mxt_platform_data *pdata = data->pdata;
1884 struct device *dev = &data->client->dev; 1891 struct device *dev = &data->client->dev;
1885 struct input_dev *input_dev; 1892 struct input_dev *input_dev;
1886 int error; 1893 int error;
@@ -1946,7 +1953,7 @@ static int mxt_initialize_input_device(struct mxt_data *data)
1946 } 1953 }
1947 1954
1948 /* If device has buttons we assume it is a touchpad */ 1955 /* If device has buttons we assume it is a touchpad */
1949 if (pdata->t19_num_keys) { 1956 if (data->t19_num_keys) {
1950 mxt_set_up_as_touchpad(input_dev, data); 1957 mxt_set_up_as_touchpad(input_dev, data);
1951 mt_flags |= INPUT_MT_POINTER; 1958 mt_flags |= INPUT_MT_POINTER;
1952 } else { 1959 } else {
@@ -2868,7 +2875,7 @@ static const struct attribute_group mxt_attr_group = {
2868 2875
2869static void mxt_start(struct mxt_data *data) 2876static void mxt_start(struct mxt_data *data)
2870{ 2877{
2871 switch (data->pdata->suspend_mode) { 2878 switch (data->suspend_mode) {
2872 case MXT_SUSPEND_T9_CTRL: 2879 case MXT_SUSPEND_T9_CTRL:
2873 mxt_soft_reset(data); 2880 mxt_soft_reset(data);
2874 2881
@@ -2886,12 +2893,11 @@ static void mxt_start(struct mxt_data *data)
2886 mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); 2893 mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
2887 break; 2894 break;
2888 } 2895 }
2889
2890} 2896}
2891 2897
2892static void mxt_stop(struct mxt_data *data) 2898static void mxt_stop(struct mxt_data *data)
2893{ 2899{
2894 switch (data->pdata->suspend_mode) { 2900 switch (data->suspend_mode) {
2895 case MXT_SUSPEND_T9_CTRL: 2901 case MXT_SUSPEND_T9_CTRL:
2896 /* Touch disable */ 2902 /* Touch disable */
2897 mxt_write_object(data, 2903 mxt_write_object(data,
@@ -2921,55 +2927,49 @@ static void mxt_input_close(struct input_dev *dev)
2921 mxt_stop(data); 2927 mxt_stop(data);
2922} 2928}
2923 2929
2924#ifdef CONFIG_OF 2930static int mxt_parse_device_properties(struct mxt_data *data)
2925static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2926{ 2931{
2927 struct mxt_platform_data *pdata; 2932 static const char keymap_property[] = "linux,gpio-keymap";
2928 struct device_node *np = client->dev.of_node; 2933 struct device *dev = &data->client->dev;
2929 u32 *keymap; 2934 u32 *keymap;
2930 int proplen, ret; 2935 int n_keys;
2931 2936 int error;
2932 if (!np)
2933 return ERR_PTR(-ENOENT);
2934
2935 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
2936 if (!pdata)
2937 return ERR_PTR(-ENOMEM);
2938 2937
2939 if (of_find_property(np, "linux,gpio-keymap", &proplen)) { 2938 if (device_property_present(dev, keymap_property)) {
2940 pdata->t19_num_keys = proplen / sizeof(u32); 2939 n_keys = device_property_read_u32_array(dev, keymap_property,
2940 NULL, 0);
2941 if (n_keys <= 0) {
2942 error = n_keys < 0 ? n_keys : -EINVAL;
2943 dev_err(dev, "invalid/malformed '%s' property: %d\n",
2944 keymap_property, error);
2945 return error;
2946 }
2941 2947
2942 keymap = devm_kzalloc(&client->dev, 2948 keymap = devm_kmalloc_array(dev, n_keys, sizeof(*keymap),
2943 pdata->t19_num_keys * sizeof(keymap[0]), 2949 GFP_KERNEL);
2944 GFP_KERNEL);
2945 if (!keymap) 2950 if (!keymap)
2946 return ERR_PTR(-ENOMEM); 2951 return -ENOMEM;
2947 2952
2948 ret = of_property_read_u32_array(np, "linux,gpio-keymap", 2953 error = device_property_read_u32_array(dev, keymap_property,
2949 keymap, pdata->t19_num_keys); 2954 keymap, n_keys);
2950 if (ret) 2955 if (error) {
2951 dev_warn(&client->dev, 2956 dev_err(dev, "failed to parse '%s' property: %d\n",
2952 "Couldn't read linux,gpio-keymap: %d\n", ret); 2957 keymap_property, error);
2958 return error;
2959 }
2953 2960
2954 pdata->t19_keymap = keymap; 2961 data->t19_keymap = keymap;
2962 data->t19_num_keys = n_keys;
2955 } 2963 }
2956 2964
2957 pdata->suspend_mode = MXT_SUSPEND_DEEP_SLEEP; 2965 return 0;
2958
2959 return pdata;
2960}
2961#else
2962static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2963{
2964 return ERR_PTR(-ENOENT);
2965} 2966}
2966#endif
2967 2967
2968#ifdef CONFIG_ACPI 2968#ifdef CONFIG_ACPI
2969 2969
2970struct mxt_acpi_platform_data { 2970struct mxt_acpi_platform_data {
2971 const char *hid; 2971 const char *hid;
2972 struct mxt_platform_data pdata; 2972 const struct property_entry *props;
2973}; 2973};
2974 2974
2975static unsigned int samus_touchpad_buttons[] = { 2975static unsigned int samus_touchpad_buttons[] = {
@@ -2979,14 +2979,16 @@ static unsigned int samus_touchpad_buttons[] = {
2979 BTN_LEFT 2979 BTN_LEFT
2980}; 2980};
2981 2981
2982static const struct property_entry samus_touchpad_props[] = {
2983 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons),
2984 { }
2985};
2986
2982static struct mxt_acpi_platform_data samus_platform_data[] = { 2987static struct mxt_acpi_platform_data samus_platform_data[] = {
2983 { 2988 {
2984 /* Touchpad */ 2989 /* Touchpad */
2985 .hid = "ATML0000", 2990 .hid = "ATML0000",
2986 .pdata = { 2991 .props = samus_touchpad_props,
2987 .t19_num_keys = ARRAY_SIZE(samus_touchpad_buttons),
2988 .t19_keymap = samus_touchpad_buttons,
2989 },
2990 }, 2992 },
2991 { 2993 {
2992 /* Touchscreen */ 2994 /* Touchscreen */
@@ -3004,14 +3006,16 @@ static unsigned int chromebook_tp_buttons[] = {
3004 BTN_LEFT 3006 BTN_LEFT
3005}; 3007};
3006 3008
3009static const struct property_entry chromebook_tp_props[] = {
3010 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_tp_buttons),
3011 { }
3012};
3013
3007static struct mxt_acpi_platform_data chromebook_platform_data[] = { 3014static struct mxt_acpi_platform_data chromebook_platform_data[] = {
3008 { 3015 {
3009 /* Touchpad */ 3016 /* Touchpad */
3010 .hid = "ATML0000", 3017 .hid = "ATML0000",
3011 .pdata = { 3018 .props = chromebook_tp_props,
3012 .t19_num_keys = ARRAY_SIZE(chromebook_tp_buttons),
3013 .t19_keymap = chromebook_tp_buttons,
3014 },
3015 }, 3019 },
3016 { 3020 {
3017 /* Touchscreen */ 3021 /* Touchscreen */
@@ -3041,83 +3045,85 @@ static const struct dmi_system_id mxt_dmi_table[] = {
3041 { } 3045 { }
3042}; 3046};
3043 3047
3044static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) 3048static int mxt_prepare_acpi_properties(struct i2c_client *client)
3045{ 3049{
3046 struct acpi_device *adev; 3050 struct acpi_device *adev;
3047 const struct dmi_system_id *system_id; 3051 const struct dmi_system_id *system_id;
3048 const struct mxt_acpi_platform_data *acpi_pdata; 3052 const struct mxt_acpi_platform_data *acpi_pdata;
3049 3053
3050 /*
3051 * Ignore ACPI devices representing bootloader mode.
3052 *
3053 * This is a bit of a hack: Google Chromebook BIOS creates ACPI
3054 * devices for both application and bootloader modes, but we are
3055 * interested in application mode only (if device is in bootloader
3056 * mode we'll end up switching into application anyway). So far
3057 * application mode addresses were all above 0x40, so we'll use it
3058 * as a threshold.
3059 */
3060 if (client->addr < 0x40)
3061 return ERR_PTR(-ENXIO);
3062
3063 adev = ACPI_COMPANION(&client->dev); 3054 adev = ACPI_COMPANION(&client->dev);
3064 if (!adev) 3055 if (!adev)
3065 return ERR_PTR(-ENOENT); 3056 return -ENOENT;
3066 3057
3067 system_id = dmi_first_match(mxt_dmi_table); 3058 system_id = dmi_first_match(mxt_dmi_table);
3068 if (!system_id) 3059 if (!system_id)
3069 return ERR_PTR(-ENOENT); 3060 return -ENOENT;
3070 3061
3071 acpi_pdata = system_id->driver_data; 3062 acpi_pdata = system_id->driver_data;
3072 if (!acpi_pdata) 3063 if (!acpi_pdata)
3073 return ERR_PTR(-ENOENT); 3064 return -ENOENT;
3074 3065
3075 while (acpi_pdata->hid) { 3066 while (acpi_pdata->hid) {
3076 if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) 3067 if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) {
3077 return &acpi_pdata->pdata; 3068 /*
3069 * Remove previously installed properties if we
3070 * are probing this device not for the very first
3071 * time.
3072 */
3073 device_remove_properties(&client->dev);
3074
3075 /*
3076 * Now install the platform-specific properties
3077 * that are missing from ACPI.
3078 */
3079 device_add_properties(&client->dev, acpi_pdata->props);
3080 break;
3081 }
3078 3082
3079 acpi_pdata++; 3083 acpi_pdata++;
3080 } 3084 }
3081 3085
3082 return ERR_PTR(-ENOENT); 3086 return 0;
3083} 3087}
3084#else 3088#else
3085static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) 3089static int mxt_prepare_acpi_properties(struct i2c_client *client)
3086{ 3090{
3087 return ERR_PTR(-ENOENT); 3091 return -ENOENT;
3088} 3092}
3089#endif 3093#endif
3090 3094
3091static const struct mxt_platform_data * 3095static const struct dmi_system_id chromebook_T9_suspend_dmi[] = {
3092mxt_get_platform_data(struct i2c_client *client) 3096 {
3093{ 3097 .matches = {
3094 const struct mxt_platform_data *pdata; 3098 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
3095 3099 DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
3096 pdata = dev_get_platdata(&client->dev); 3100 },
3097 if (pdata) 3101 },
3098 return pdata; 3102 {
3099 3103 .matches = {
3100 pdata = mxt_parse_dt(client); 3104 DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
3101 if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT) 3105 },
3102 return pdata; 3106 },
3103 3107 { }
3104 pdata = mxt_parse_acpi(client); 3108};
3105 if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
3106 return pdata;
3107
3108 dev_err(&client->dev, "No platform data specified\n");
3109 return ERR_PTR(-EINVAL);
3110}
3111 3109
3112static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) 3110static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
3113{ 3111{
3114 struct mxt_data *data; 3112 struct mxt_data *data;
3115 const struct mxt_platform_data *pdata;
3116 int error; 3113 int error;
3117 3114
3118 pdata = mxt_get_platform_data(client); 3115 /*
3119 if (IS_ERR(pdata)) 3116 * Ignore ACPI devices representing bootloader mode.
3120 return PTR_ERR(pdata); 3117 *
3118 * This is a bit of a hack: Google Chromebook BIOS creates ACPI
3119 * devices for both application and bootloader modes, but we are
3120 * interested in application mode only (if device is in bootloader
3121 * mode we'll end up switching into application anyway). So far
3122 * application mode addresses were all above 0x40, so we'll use it
3123 * as a threshold.
3124 */
3125 if (ACPI_COMPANION(&client->dev) && client->addr < 0x40)
3126 return -ENXIO;
3121 3127
3122 data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL); 3128 data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
3123 if (!data) 3129 if (!data)
@@ -3127,7 +3133,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
3127 client->adapter->nr, client->addr); 3133 client->adapter->nr, client->addr);
3128 3134
3129 data->client = client; 3135 data->client = client;
3130 data->pdata = pdata;
3131 data->irq = client->irq; 3136 data->irq = client->irq;
3132 i2c_set_clientdata(client, data); 3137 i2c_set_clientdata(client, data);
3133 3138
@@ -3135,6 +3140,17 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
3135 init_completion(&data->reset_completion); 3140 init_completion(&data->reset_completion);
3136 init_completion(&data->crc_completion); 3141 init_completion(&data->crc_completion);
3137 3142
3143 data->suspend_mode = dmi_check_system(chromebook_T9_suspend_dmi) ?
3144 MXT_SUSPEND_T9_CTRL : MXT_SUSPEND_DEEP_SLEEP;
3145
3146 error = mxt_prepare_acpi_properties(client);
3147 if (error && error != -ENOENT)
3148 return error;
3149
3150 error = mxt_parse_device_properties(data);
3151 if (error)
3152 return error;
3153
3138 data->reset_gpio = devm_gpiod_get_optional(&client->dev, 3154 data->reset_gpio = devm_gpiod_get_optional(&client->dev,
3139 "reset", GPIOD_OUT_LOW); 3155 "reset", GPIOD_OUT_LOW);
3140 if (IS_ERR(data->reset_gpio)) { 3156 if (IS_ERR(data->reset_gpio)) {
@@ -3144,8 +3160,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
3144 } 3160 }
3145 3161
3146 error = devm_request_threaded_irq(&client->dev, client->irq, 3162 error = devm_request_threaded_irq(&client->dev, client->irq,
3147 NULL, mxt_interrupt, 3163 NULL, mxt_interrupt, IRQF_ONESHOT,
3148 pdata->irqflags | IRQF_ONESHOT,
3149 client->name, data); 3164 client->name, data);
3150 if (error) { 3165 if (error) {
3151 dev_err(&client->dev, "Failed to register interrupt\n"); 3166 dev_err(&client->dev, "Failed to register interrupt\n");
@@ -3265,7 +3280,7 @@ MODULE_DEVICE_TABLE(i2c, mxt_id);
3265static struct i2c_driver mxt_driver = { 3280static struct i2c_driver mxt_driver = {
3266 .driver = { 3281 .driver = {
3267 .name = "atmel_mxt_ts", 3282 .name = "atmel_mxt_ts",
3268 .of_match_table = of_match_ptr(mxt_of_match), 3283 .of_match_table = mxt_of_match,
3269 .acpi_match_table = ACPI_PTR(mxt_acpi_id), 3284 .acpi_match_table = ACPI_PTR(mxt_acpi_id),
3270 .pm = &mxt_pm_ops, 3285 .pm = &mxt_pm_ops,
3271 }, 3286 },
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index d8599736a41a..5c47f451e43b 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -1,33 +1,20 @@
1/* 1// SPDX-License-Identifier: GPL-2.0+
2 * chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices. 2// Driver to instantiate Chromebook i2c/smbus devices.
3 * 3//
4 * Author : Benson Leung <bleung@chromium.org> 4// Copyright (C) 2012 Google, Inc.
5 * 5// Author: Benson Leung <bleung@chromium.org>
6 * Copyright (C) 2012 Google, Inc. 6
7 * 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23 8
24#include <linux/dmi.h> 9#include <linux/dmi.h>
25#include <linux/i2c.h> 10#include <linux/i2c.h>
26#include <linux/platform_data/atmel_mxt_ts.h>
27#include <linux/input.h> 11#include <linux/input.h>
28#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/ioport.h>
29#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/pci.h>
30#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/property.h>
31 18
32#define ATMEL_TP_I2C_ADDR 0x4b 19#define ATMEL_TP_I2C_ADDR 0x4b
33#define ATMEL_TP_I2C_BL_ADDR 0x25 20#define ATMEL_TP_I2C_BL_ADDR 0x25
@@ -38,18 +25,11 @@
38#define ISL_ALS_I2C_ADDR 0x44 25#define ISL_ALS_I2C_ADDR 0x44
39#define TAOS_ALS_I2C_ADDR 0x29 26#define TAOS_ALS_I2C_ADDR 0x29
40 27
41#define MAX_I2C_DEVICE_DEFERRALS 5
42
43static struct i2c_client *als;
44static struct i2c_client *tp;
45static struct i2c_client *ts;
46
47static const char *i2c_adapter_names[] = { 28static const char *i2c_adapter_names[] = {
48 "SMBus I801 adapter", 29 "SMBus I801 adapter",
49 "i915 gmbus vga", 30 "i915 gmbus vga",
50 "i915 gmbus panel", 31 "i915 gmbus panel",
51 "Synopsys DesignWare I2C adapter", 32 "Synopsys DesignWare I2C adapter",
52 "Synopsys DesignWare I2C adapter",
53}; 33};
54 34
55/* Keep this enum consistent with i2c_adapter_names */ 35/* Keep this enum consistent with i2c_adapter_names */
@@ -57,126 +37,41 @@ enum i2c_adapter_type {
57 I2C_ADAPTER_SMBUS = 0, 37 I2C_ADAPTER_SMBUS = 0,
58 I2C_ADAPTER_VGADDC, 38 I2C_ADAPTER_VGADDC,
59 I2C_ADAPTER_PANEL, 39 I2C_ADAPTER_PANEL,
60 I2C_ADAPTER_DESIGNWARE_0, 40 I2C_ADAPTER_DESIGNWARE,
61 I2C_ADAPTER_DESIGNWARE_1,
62};
63
64enum i2c_peripheral_state {
65 UNPROBED = 0,
66 PROBED,
67 TIMEDOUT,
68}; 41};
69 42
70struct i2c_peripheral { 43struct i2c_peripheral {
71 int (*add)(enum i2c_adapter_type type); 44 struct i2c_board_info board_info;
72 enum i2c_adapter_type type; 45 unsigned short alt_addr;
73 enum i2c_peripheral_state state;
74 int tries;
75};
76
77#define MAX_I2C_PERIPHERALS 4
78 46
79struct chromeos_laptop { 47 const char *dmi_name;
80 struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS]; 48 unsigned long irqflags;
81}; 49 struct resource irq_resource;
82
83static struct chromeos_laptop *cros_laptop;
84
85static struct i2c_board_info cyapa_device = {
86 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
87 .flags = I2C_CLIENT_WAKE,
88};
89 50
90static struct i2c_board_info elantech_device = { 51 enum i2c_adapter_type type;
91 I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), 52 u32 pci_devid;
92 .flags = I2C_CLIENT_WAKE,
93};
94
95static struct i2c_board_info isl_als_device = {
96 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
97};
98
99static struct i2c_board_info tsl2583_als_device = {
100 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
101};
102
103static struct i2c_board_info tsl2563_als_device = {
104 I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
105};
106
107static int mxt_t19_keys[] = {
108 KEY_RESERVED,
109 KEY_RESERVED,
110 KEY_RESERVED,
111 KEY_RESERVED,
112 KEY_RESERVED,
113 BTN_LEFT
114};
115
116static struct mxt_platform_data atmel_224s_tp_platform_data = {
117 .irqflags = IRQF_TRIGGER_FALLING,
118 .t19_num_keys = ARRAY_SIZE(mxt_t19_keys),
119 .t19_keymap = mxt_t19_keys,
120 .suspend_mode = MXT_SUSPEND_T9_CTRL,
121};
122 53
123static struct i2c_board_info atmel_224s_tp_device = { 54 struct i2c_client *client;
124 I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR),
125 .platform_data = &atmel_224s_tp_platform_data,
126 .flags = I2C_CLIENT_WAKE,
127}; 55};
128 56
129static struct mxt_platform_data atmel_1664s_platform_data = { 57struct chromeos_laptop {
130 .irqflags = IRQF_TRIGGER_FALLING, 58 /*
131 .suspend_mode = MXT_SUSPEND_T9_CTRL, 59 * Note that we can't mark this pointer as const because
60 * i2c_new_probed_device() changes passed in I2C board info, so.
61 */
62 struct i2c_peripheral *i2c_peripherals;
63 unsigned int num_i2c_peripherals;
132}; 64};
133 65
134static struct i2c_board_info atmel_1664s_device = { 66static const struct chromeos_laptop *cros_laptop;
135 I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR),
136 .platform_data = &atmel_1664s_platform_data,
137 .flags = I2C_CLIENT_WAKE,
138};
139 67
140static struct i2c_client *__add_probed_i2c_device( 68static struct i2c_client *
141 const char *name, 69chromes_laptop_instantiate_i2c_device(struct i2c_adapter *adapter,
142 int bus, 70 struct i2c_board_info *info,
143 struct i2c_board_info *info, 71 unsigned short alt_addr)
144 const unsigned short *alt_addr_list)
145{ 72{
146 const struct dmi_device *dmi_dev;
147 const struct dmi_dev_onboard *dev_data;
148 struct i2c_adapter *adapter;
149 struct i2c_client *client = NULL;
150 const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; 73 const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
151 74 struct i2c_client *client;
152 if (bus < 0)
153 return NULL;
154 /*
155 * If a name is specified, look for irq platform information stashed
156 * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware.
157 */
158 if (name) {
159 dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL);
160 if (!dmi_dev) {
161 pr_err("%s failed to dmi find device %s.\n",
162 __func__,
163 name);
164 return NULL;
165 }
166 dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data;
167 if (!dev_data) {
168 pr_err("%s failed to get data from dmi for %s.\n",
169 __func__, name);
170 return NULL;
171 }
172 info->irq = dev_data->instance;
173 }
174
175 adapter = i2c_get_adapter(bus);
176 if (!adapter) {
177 pr_err("%s failed to get i2c adapter %d.\n", __func__, bus);
178 return NULL;
179 }
180 75
181 /* 76 /*
182 * Add the i2c device. If we can't detect it at the primary 77 * Add the i2c device. If we can't detect it at the primary
@@ -184,339 +79,345 @@ static struct i2c_client *__add_probed_i2c_device(
184 * structure gets assigned primary address. 79 * structure gets assigned primary address.
185 */ 80 */
186 client = i2c_new_probed_device(adapter, info, addr_list, NULL); 81 client = i2c_new_probed_device(adapter, info, addr_list, NULL);
187 if (!client && alt_addr_list) { 82 if (!client && alt_addr) {
188 struct i2c_board_info dummy_info = { 83 struct i2c_board_info dummy_info = {
189 I2C_BOARD_INFO("dummy", info->addr), 84 I2C_BOARD_INFO("dummy", info->addr),
190 }; 85 };
86 const unsigned short alt_addr_list[] = {
87 alt_addr, I2C_CLIENT_END
88 };
191 struct i2c_client *dummy; 89 struct i2c_client *dummy;
192 90
193 dummy = i2c_new_probed_device(adapter, &dummy_info, 91 dummy = i2c_new_probed_device(adapter, &dummy_info,
194 alt_addr_list, NULL); 92 alt_addr_list, NULL);
195 if (dummy) { 93 if (dummy) {
196 pr_debug("%s %d-%02x is probed at %02x\n", 94 pr_debug("%d-%02x is probed at %02x\n",
197 __func__, bus, info->addr, dummy->addr); 95 adapter->nr, info->addr, dummy->addr);
198 i2c_unregister_device(dummy); 96 i2c_unregister_device(dummy);
199 client = i2c_new_device(adapter, info); 97 client = i2c_new_device(adapter, info);
200 } 98 }
201 } 99 }
202 100
203 if (!client) 101 if (!client)
204 pr_notice("%s failed to register device %d-%02x\n", 102 pr_debug("failed to register device %d-%02x\n",
205 __func__, bus, info->addr); 103 adapter->nr, info->addr);
206 else 104 else
207 pr_debug("%s added i2c device %d-%02x\n", 105 pr_debug("added i2c device %d-%02x\n",
208 __func__, bus, info->addr); 106 adapter->nr, info->addr);
209 107
210 i2c_put_adapter(adapter);
211 return client; 108 return client;
212} 109}
213 110
214struct i2c_lookup { 111static bool chromeos_laptop_match_adapter_devid(struct device *dev, u32 devid)
215 const char *name;
216 int instance;
217 int n;
218};
219
220static int __find_i2c_adap(struct device *dev, void *data)
221{
222 struct i2c_lookup *lookup = data;
223 static const char *prefix = "i2c-";
224 struct i2c_adapter *adapter;
225
226 if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
227 return 0;
228 adapter = to_i2c_adapter(dev);
229 if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 &&
230 lookup->n++ == lookup->instance)
231 return 1;
232 return 0;
233}
234
235static int find_i2c_adapter_num(enum i2c_adapter_type type)
236{
237 struct device *dev = NULL;
238 struct i2c_adapter *adapter;
239 struct i2c_lookup lookup;
240
241 memset(&lookup, 0, sizeof(lookup));
242 lookup.name = i2c_adapter_names[type];
243 lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0;
244
245 /* find the adapter by name */
246 dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap);
247 if (!dev) {
248 /* Adapters may appear later. Deferred probing will retry */
249 pr_notice("%s: i2c adapter %s not found on system.\n", __func__,
250 lookup.name);
251 return -ENODEV;
252 }
253 adapter = to_i2c_adapter(dev);
254 return adapter->nr;
255}
256
257/*
258 * Takes a list of addresses in addrs as such :
259 * { addr1, ... , addrn, I2C_CLIENT_END };
260 * add_probed_i2c_device will use i2c_new_probed_device
261 * and probe for devices at all of the addresses listed.
262 * Returns NULL if no devices found.
263 * See Documentation/i2c/instantiating-devices for more information.
264 */
265static struct i2c_client *add_probed_i2c_device(
266 const char *name,
267 enum i2c_adapter_type type,
268 struct i2c_board_info *info,
269 const unsigned short *addrs)
270{ 112{
271 return __add_probed_i2c_device(name, 113 struct pci_dev *pdev;
272 find_i2c_adapter_num(type),
273 info,
274 addrs);
275}
276 114
277/* 115 if (!dev_is_pci(dev))
278 * Probes for a device at a single address, the one provided by 116 return false;
279 * info->addr.
280 * Returns NULL if no device found.
281 */
282static struct i2c_client *add_i2c_device(const char *name,
283 enum i2c_adapter_type type,
284 struct i2c_board_info *info)
285{
286 return __add_probed_i2c_device(name,
287 find_i2c_adapter_num(type),
288 info,
289 NULL);
290}
291
292static int setup_cyapa_tp(enum i2c_adapter_type type)
293{
294 if (tp)
295 return 0;
296 117
297 /* add cyapa touchpad */ 118 pdev = to_pci_dev(dev);
298 tp = add_i2c_device("trackpad", type, &cyapa_device); 119 return devid == PCI_DEVID(pdev->bus->number, pdev->devfn);
299 return (!tp) ? -EAGAIN : 0;
300} 120}
301 121
302static int setup_atmel_224s_tp(enum i2c_adapter_type type) 122static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter)
303{ 123{
304 const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, 124 struct i2c_peripheral *i2c_dev;
305 I2C_CLIENT_END }; 125 int i;
306 if (tp)
307 return 0;
308
309 /* add atmel mxt touchpad */
310 tp = add_probed_i2c_device("trackpad", type,
311 &atmel_224s_tp_device, addr_list);
312 return (!tp) ? -EAGAIN : 0;
313}
314 126
315static int setup_elantech_tp(enum i2c_adapter_type type) 127 for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
316{ 128 i2c_dev = &cros_laptop->i2c_peripherals[i];
317 if (tp)
318 return 0;
319 129
320 /* add elantech touchpad */ 130 /* Skip devices already created */
321 tp = add_i2c_device("trackpad", type, &elantech_device); 131 if (i2c_dev->client)
322 return (!tp) ? -EAGAIN : 0; 132 continue;
323}
324 133
325static int setup_atmel_1664s_ts(enum i2c_adapter_type type) 134 if (strncmp(adapter->name, i2c_adapter_names[i2c_dev->type],
326{ 135 strlen(i2c_adapter_names[i2c_dev->type])))
327 const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, 136 continue;
328 I2C_CLIENT_END };
329 if (ts)
330 return 0;
331
332 /* add atmel mxt touch device */
333 ts = add_probed_i2c_device("touchscreen", type,
334 &atmel_1664s_device, addr_list);
335 return (!ts) ? -EAGAIN : 0;
336}
337 137
338static int setup_isl29018_als(enum i2c_adapter_type type) 138 if (i2c_dev->pci_devid &&
339{ 139 !chromeos_laptop_match_adapter_devid(adapter->dev.parent,
340 if (als) 140 i2c_dev->pci_devid)) {
341 return 0; 141 continue;
142 }
342 143
343 /* add isl29018 light sensor */ 144 i2c_dev->client =
344 als = add_i2c_device("lightsensor", type, &isl_als_device); 145 chromes_laptop_instantiate_i2c_device(adapter,
345 return (!als) ? -EAGAIN : 0; 146 &i2c_dev->board_info,
147 i2c_dev->alt_addr);
148 }
346} 149}
347 150
348static int setup_tsl2583_als(enum i2c_adapter_type type) 151static void chromeos_laptop_detach_i2c_client(struct i2c_client *client)
349{ 152{
350 if (als) 153 struct i2c_peripheral *i2c_dev;
351 return 0; 154 int i;
352
353 /* add tsl2583 light sensor */
354 als = add_i2c_device(NULL, type, &tsl2583_als_device);
355 return (!als) ? -EAGAIN : 0;
356}
357 155
358static int setup_tsl2563_als(enum i2c_adapter_type type) 156 for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
359{ 157 i2c_dev = &cros_laptop->i2c_peripherals[i];
360 if (als)
361 return 0;
362 158
363 /* add tsl2563 light sensor */ 159 if (i2c_dev->client == client)
364 als = add_i2c_device(NULL, type, &tsl2563_als_device); 160 i2c_dev->client = NULL;
365 return (!als) ? -EAGAIN : 0; 161 }
366} 162}
367 163
368static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) 164static int chromeos_laptop_i2c_notifier_call(struct notifier_block *nb,
165 unsigned long action, void *data)
369{ 166{
370 cros_laptop = (void *)id->driver_data; 167 struct device *dev = data;
371 pr_debug("DMI Matched %s.\n", id->ident); 168
169 switch (action) {
170 case BUS_NOTIFY_ADD_DEVICE:
171 if (dev->type == &i2c_adapter_type)
172 chromeos_laptop_check_adapter(to_i2c_adapter(dev));
173 break;
174
175 case BUS_NOTIFY_REMOVED_DEVICE:
176 if (dev->type == &i2c_client_type)
177 chromeos_laptop_detach_i2c_client(to_i2c_client(dev));
178 break;
179 }
372 180
373 /* Indicate to dmi_scan that processing is done. */ 181 return 0;
374 return 1;
375} 182}
376 183
377static int chromeos_laptop_probe(struct platform_device *pdev) 184static struct notifier_block chromeos_laptop_i2c_notifier = {
378{ 185 .notifier_call = chromeos_laptop_i2c_notifier_call,
379 int i; 186};
380 int ret = 0;
381
382 for (i = 0; i < MAX_I2C_PERIPHERALS; i++) {
383 struct i2c_peripheral *i2c_dev;
384
385 i2c_dev = &cros_laptop->i2c_peripherals[i];
386
387 /* No more peripherals. */
388 if (i2c_dev->add == NULL)
389 break;
390
391 if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED)
392 continue;
393
394 /*
395 * Check that the i2c adapter is present.
396 * -EPROBE_DEFER if missing as the adapter may appear much
397 * later.
398 */
399 if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) {
400 ret = -EPROBE_DEFER;
401 continue;
402 }
403
404 /* Add the device. */
405 if (i2c_dev->add(i2c_dev->type) == -EAGAIN) {
406 /*
407 * Set -EPROBE_DEFER a limited num of times
408 * if device is not successfully added.
409 */
410 if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) {
411 ret = -EPROBE_DEFER;
412 } else {
413 /* Ran out of tries. */
414 pr_notice("%s: Ran out of tries for device.\n",
415 __func__);
416 i2c_dev->state = TIMEDOUT;
417 }
418 } else {
419 i2c_dev->state = PROBED;
420 }
421 }
422 187
423 return ret; 188#define DECLARE_CROS_LAPTOP(_name) \
189static const struct chromeos_laptop _name __initconst = { \
190 .i2c_peripherals = _name##_peripherals, \
191 .num_i2c_peripherals = ARRAY_SIZE(_name##_peripherals), \
424} 192}
425 193
426static struct chromeos_laptop samsung_series_5_550 = { 194static struct i2c_peripheral samsung_series_5_550_peripherals[] __initdata = {
427 .i2c_peripherals = { 195 /* Touchpad. */
428 /* Touchpad. */ 196 {
429 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, 197 .board_info = {
430 /* Light Sensor. */ 198 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
431 { .add = setup_isl29018_als, I2C_ADAPTER_SMBUS }, 199 .flags = I2C_CLIENT_WAKE,
200 },
201 .dmi_name = "trackpad",
202 .type = I2C_ADAPTER_SMBUS,
203 },
204 /* Light Sensor. */
205 {
206 .board_info = {
207 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
208 },
209 .dmi_name = "lightsensor",
210 .type = I2C_ADAPTER_SMBUS,
432 }, 211 },
433}; 212};
213DECLARE_CROS_LAPTOP(samsung_series_5_550);
434 214
435static struct chromeos_laptop samsung_series_5 = { 215static struct i2c_peripheral samsung_series_5_peripherals[] __initdata = {
436 .i2c_peripherals = { 216 /* Light Sensor. */
437 /* Light Sensor. */ 217 {
438 { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS }, 218 .board_info = {
219 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
220 },
221 .type = I2C_ADAPTER_SMBUS,
439 }, 222 },
440}; 223};
224DECLARE_CROS_LAPTOP(samsung_series_5);
441 225
442static struct chromeos_laptop chromebook_pixel = { 226static const int chromebook_pixel_tp_keys[] __initconst = {
443 .i2c_peripherals = { 227 KEY_RESERVED,
444 /* Touch Screen. */ 228 KEY_RESERVED,
445 { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL }, 229 KEY_RESERVED,
446 /* Touchpad. */ 230 KEY_RESERVED,
447 { .add = setup_atmel_224s_tp, I2C_ADAPTER_VGADDC }, 231 KEY_RESERVED,
448 /* Light Sensor. */ 232 BTN_LEFT
449 { .add = setup_isl29018_als, I2C_ADAPTER_PANEL },
450 },
451}; 233};
452 234
453static struct chromeos_laptop hp_chromebook_14 = { 235static const struct property_entry
454 .i2c_peripherals = { 236chromebook_pixel_trackpad_props[] __initconst = {
455 /* Touchpad. */ 237 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys),
456 { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, 238 { }
239};
240
241static struct i2c_peripheral chromebook_pixel_peripherals[] __initdata = {
242 /* Touch Screen. */
243 {
244 .board_info = {
245 I2C_BOARD_INFO("atmel_mxt_ts",
246 ATMEL_TS_I2C_ADDR),
247 .flags = I2C_CLIENT_WAKE,
248 },
249 .dmi_name = "touchscreen",
250 .irqflags = IRQF_TRIGGER_FALLING,
251 .type = I2C_ADAPTER_PANEL,
252 .alt_addr = ATMEL_TS_I2C_BL_ADDR,
253 },
254 /* Touchpad. */
255 {
256 .board_info = {
257 I2C_BOARD_INFO("atmel_mxt_tp",
258 ATMEL_TP_I2C_ADDR),
259 .properties =
260 chromebook_pixel_trackpad_props,
261 .flags = I2C_CLIENT_WAKE,
262 },
263 .dmi_name = "trackpad",
264 .irqflags = IRQF_TRIGGER_FALLING,
265 .type = I2C_ADAPTER_VGADDC,
266 .alt_addr = ATMEL_TP_I2C_BL_ADDR,
267 },
268 /* Light Sensor. */
269 {
270 .board_info = {
271 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
272 },
273 .dmi_name = "lightsensor",
274 .type = I2C_ADAPTER_PANEL,
457 }, 275 },
458}; 276};
277DECLARE_CROS_LAPTOP(chromebook_pixel);
459 278
460static struct chromeos_laptop dell_chromebook_11 = { 279static struct i2c_peripheral hp_chromebook_14_peripherals[] __initdata = {
461 .i2c_peripherals = { 280 /* Touchpad. */
462 /* Touchpad. */ 281 {
463 { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, 282 .board_info = {
464 /* Elan Touchpad option. */ 283 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
465 { .add = setup_elantech_tp, I2C_ADAPTER_DESIGNWARE_0 }, 284 .flags = I2C_CLIENT_WAKE,
285 },
286 .dmi_name = "trackpad",
287 .type = I2C_ADAPTER_DESIGNWARE,
466 }, 288 },
467}; 289};
290DECLARE_CROS_LAPTOP(hp_chromebook_14);
468 291
469static struct chromeos_laptop toshiba_cb35 = { 292static struct i2c_peripheral dell_chromebook_11_peripherals[] __initdata = {
470 .i2c_peripherals = { 293 /* Touchpad. */
471 /* Touchpad. */ 294 {
472 { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, 295 .board_info = {
296 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
297 .flags = I2C_CLIENT_WAKE,
298 },
299 .dmi_name = "trackpad",
300 .type = I2C_ADAPTER_DESIGNWARE,
301 },
302 /* Elan Touchpad option. */
303 {
304 .board_info = {
305 I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR),
306 .flags = I2C_CLIENT_WAKE,
307 },
308 .dmi_name = "trackpad",
309 .type = I2C_ADAPTER_DESIGNWARE,
473 }, 310 },
474}; 311};
312DECLARE_CROS_LAPTOP(dell_chromebook_11);
475 313
476static struct chromeos_laptop acer_c7_chromebook = { 314static struct i2c_peripheral toshiba_cb35_peripherals[] __initdata = {
477 .i2c_peripherals = { 315 /* Touchpad. */
478 /* Touchpad. */ 316 {
479 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, 317 .board_info = {
318 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
319 .flags = I2C_CLIENT_WAKE,
320 },
321 .dmi_name = "trackpad",
322 .type = I2C_ADAPTER_DESIGNWARE,
480 }, 323 },
481}; 324};
325DECLARE_CROS_LAPTOP(toshiba_cb35);
482 326
483static struct chromeos_laptop acer_ac700 = { 327static struct i2c_peripheral acer_c7_chromebook_peripherals[] __initdata = {
484 .i2c_peripherals = { 328 /* Touchpad. */
485 /* Light Sensor. */ 329 {
486 { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, 330 .board_info = {
331 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
332 .flags = I2C_CLIENT_WAKE,
333 },
334 .dmi_name = "trackpad",
335 .type = I2C_ADAPTER_SMBUS,
487 }, 336 },
488}; 337};
338DECLARE_CROS_LAPTOP(acer_c7_chromebook);
489 339
490static struct chromeos_laptop acer_c720 = { 340static struct i2c_peripheral acer_ac700_peripherals[] __initdata = {
491 .i2c_peripherals = { 341 /* Light Sensor. */
492 /* Touchscreen. */ 342 {
493 { .add = setup_atmel_1664s_ts, I2C_ADAPTER_DESIGNWARE_1 }, 343 .board_info = {
494 /* Touchpad. */ 344 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
495 { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, 345 },
496 /* Elan Touchpad option. */ 346 .type = I2C_ADAPTER_SMBUS,
497 { .add = setup_elantech_tp, I2C_ADAPTER_DESIGNWARE_0 },
498 /* Light Sensor. */
499 { .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 },
500 }, 347 },
501}; 348};
349DECLARE_CROS_LAPTOP(acer_ac700);
502 350
503static struct chromeos_laptop hp_pavilion_14_chromebook = { 351static struct i2c_peripheral acer_c720_peripherals[] __initdata = {
504 .i2c_peripherals = { 352 /* Touchscreen. */
505 /* Touchpad. */ 353 {
506 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, 354 .board_info = {
355 I2C_BOARD_INFO("atmel_mxt_ts",
356 ATMEL_TS_I2C_ADDR),
357 .flags = I2C_CLIENT_WAKE,
358 },
359 .dmi_name = "touchscreen",
360 .irqflags = IRQF_TRIGGER_FALLING,
361 .type = I2C_ADAPTER_DESIGNWARE,
362 .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
363 .alt_addr = ATMEL_TS_I2C_BL_ADDR,
364 },
365 /* Touchpad. */
366 {
367 .board_info = {
368 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
369 .flags = I2C_CLIENT_WAKE,
370 },
371 .dmi_name = "trackpad",
372 .type = I2C_ADAPTER_DESIGNWARE,
373 .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
374 },
375 /* Elan Touchpad option. */
376 {
377 .board_info = {
378 I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR),
379 .flags = I2C_CLIENT_WAKE,
380 },
381 .dmi_name = "trackpad",
382 .type = I2C_ADAPTER_DESIGNWARE,
383 .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
384 },
385 /* Light Sensor. */
386 {
387 .board_info = {
388 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
389 },
390 .dmi_name = "lightsensor",
391 .type = I2C_ADAPTER_DESIGNWARE,
392 .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
507 }, 393 },
508}; 394};
395DECLARE_CROS_LAPTOP(acer_c720);
509 396
510static struct chromeos_laptop cr48 = { 397static struct i2c_peripheral
511 .i2c_peripherals = { 398hp_pavilion_14_chromebook_peripherals[] __initdata = {
512 /* Light Sensor. */ 399 /* Touchpad. */
513 { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, 400 {
401 .board_info = {
402 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
403 .flags = I2C_CLIENT_WAKE,
404 },
405 .dmi_name = "trackpad",
406 .type = I2C_ADAPTER_SMBUS,
514 }, 407 },
515}; 408};
409DECLARE_CROS_LAPTOP(hp_pavilion_14_chromebook);
516 410
517#define _CBDD(board_) \ 411static struct i2c_peripheral cr48_peripherals[] __initdata = {
518 .callback = chromeos_laptop_dmi_matched, \ 412 /* Light Sensor. */
519 .driver_data = (void *)&board_ 413 {
414 .board_info = {
415 I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
416 },
417 .type = I2C_ADAPTER_SMBUS,
418 },
419};
420DECLARE_CROS_LAPTOP(cr48);
520 421
521static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { 422static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
522 { 423 {
@@ -525,14 +426,14 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
525 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), 426 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
526 DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), 427 DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
527 }, 428 },
528 _CBDD(samsung_series_5_550), 429 .driver_data = (void *)&samsung_series_5_550,
529 }, 430 },
530 { 431 {
531 .ident = "Samsung Series 5", 432 .ident = "Samsung Series 5",
532 .matches = { 433 .matches = {
533 DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), 434 DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
534 }, 435 },
535 _CBDD(samsung_series_5), 436 .driver_data = (void *)&samsung_series_5,
536 }, 437 },
537 { 438 {
538 .ident = "Chromebook Pixel", 439 .ident = "Chromebook Pixel",
@@ -540,7 +441,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
540 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 441 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
541 DMI_MATCH(DMI_PRODUCT_NAME, "Link"), 442 DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
542 }, 443 },
543 _CBDD(chromebook_pixel), 444 .driver_data = (void *)&chromebook_pixel,
544 }, 445 },
545 { 446 {
546 .ident = "Wolf", 447 .ident = "Wolf",
@@ -548,7 +449,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
548 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), 449 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
549 DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"), 450 DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"),
550 }, 451 },
551 _CBDD(dell_chromebook_11), 452 .driver_data = (void *)&dell_chromebook_11,
552 }, 453 },
553 { 454 {
554 .ident = "HP Chromebook 14", 455 .ident = "HP Chromebook 14",
@@ -556,7 +457,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
556 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), 457 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
557 DMI_MATCH(DMI_PRODUCT_NAME, "Falco"), 458 DMI_MATCH(DMI_PRODUCT_NAME, "Falco"),
558 }, 459 },
559 _CBDD(hp_chromebook_14), 460 .driver_data = (void *)&hp_chromebook_14,
560 }, 461 },
561 { 462 {
562 .ident = "Toshiba CB35", 463 .ident = "Toshiba CB35",
@@ -564,99 +465,214 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
564 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), 465 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
565 DMI_MATCH(DMI_PRODUCT_NAME, "Leon"), 466 DMI_MATCH(DMI_PRODUCT_NAME, "Leon"),
566 }, 467 },
567 _CBDD(toshiba_cb35), 468 .driver_data = (void *)&toshiba_cb35,
568 }, 469 },
569 { 470 {
570 .ident = "Acer C7 Chromebook", 471 .ident = "Acer C7 Chromebook",
571 .matches = { 472 .matches = {
572 DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), 473 DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
573 }, 474 },
574 _CBDD(acer_c7_chromebook), 475 .driver_data = (void *)&acer_c7_chromebook,
575 }, 476 },
576 { 477 {
577 .ident = "Acer AC700", 478 .ident = "Acer AC700",
578 .matches = { 479 .matches = {
579 DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), 480 DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
580 }, 481 },
581 _CBDD(acer_ac700), 482 .driver_data = (void *)&acer_ac700,
582 }, 483 },
583 { 484 {
584 .ident = "Acer C720", 485 .ident = "Acer C720",
585 .matches = { 486 .matches = {
586 DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"), 487 DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
587 }, 488 },
588 _CBDD(acer_c720), 489 .driver_data = (void *)&acer_c720,
589 }, 490 },
590 { 491 {
591 .ident = "HP Pavilion 14 Chromebook", 492 .ident = "HP Pavilion 14 Chromebook",
592 .matches = { 493 .matches = {
593 DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), 494 DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
594 }, 495 },
595 _CBDD(hp_pavilion_14_chromebook), 496 .driver_data = (void *)&hp_pavilion_14_chromebook,
596 }, 497 },
597 { 498 {
598 .ident = "Cr-48", 499 .ident = "Cr-48",
599 .matches = { 500 .matches = {
600 DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), 501 DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
601 }, 502 },
602 _CBDD(cr48), 503 .driver_data = (void *)&cr48,
603 }, 504 },
604 { } 505 { }
605}; 506};
606MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); 507MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
607 508
608static struct platform_device *cros_platform_device; 509static int __init chromeos_laptop_scan_adapter(struct device *dev, void *data)
510{
511 struct i2c_adapter *adapter;
609 512
610static struct platform_driver cros_platform_driver = { 513 adapter = i2c_verify_adapter(dev);
611 .driver = { 514 if (adapter)
612 .name = "chromeos_laptop", 515 chromeos_laptop_check_adapter(adapter);
613 }, 516
614 .probe = chromeos_laptop_probe, 517 return 0;
615}; 518}
519
520static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name)
521{
522 const struct dmi_device *dmi_dev;
523 const struct dmi_dev_onboard *dev_data;
524
525 dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, dmi_name, NULL);
526 if (!dmi_dev) {
527 pr_err("failed to find DMI device '%s'\n", dmi_name);
528 return -ENOENT;
529 }
530
531 dev_data = dmi_dev->device_data;
532 if (!dev_data) {
533 pr_err("failed to get data from DMI for '%s'\n", dmi_name);
534 return -EINVAL;
535 }
536
537 return dev_data->instance;
538}
539
540static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev)
541{
542 int irq;
543
544 if (i2c_dev->dmi_name) {
545 irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name);
546 if (irq < 0)
547 return irq;
548
549 i2c_dev->irq_resource = (struct resource)
550 DEFINE_RES_NAMED(irq, 1, NULL,
551 IORESOURCE_IRQ | i2c_dev->irqflags);
552 i2c_dev->board_info.resources = &i2c_dev->irq_resource;
553 i2c_dev->board_info.num_resources = 1;
554 }
555
556 return 0;
557}
558
559static struct chromeos_laptop * __init
560chromeos_laptop_prepare(const struct chromeos_laptop *src)
561{
562 struct chromeos_laptop *cros_laptop;
563 struct i2c_peripheral *i2c_dev;
564 struct i2c_board_info *info;
565 int error;
566 int i;
567
568 cros_laptop = kzalloc(sizeof(*cros_laptop), GFP_KERNEL);
569 if (!cros_laptop)
570 return ERR_PTR(-ENOMEM);
571
572 cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals,
573 src->num_i2c_peripherals *
574 sizeof(*src->i2c_peripherals),
575 GFP_KERNEL);
576 if (!cros_laptop->i2c_peripherals) {
577 error = -ENOMEM;
578 goto err_free_cros_laptop;
579 }
580
581 cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;
582
583 for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
584 i2c_dev = &cros_laptop->i2c_peripherals[i];
585 info = &i2c_dev->board_info;
586
587 error = chromeos_laptop_setup_irq(i2c_dev);
588 if (error)
589 goto err_destroy_cros_peripherals;
590
591 /* We need to deep-copy properties */
592 if (info->properties) {
593 info->properties =
594 property_entries_dup(info->properties);
595 if (IS_ERR(info->properties)) {
596 error = PTR_ERR(info->properties);
597 goto err_destroy_cros_peripherals;
598 }
599 }
600 }
601
602 return cros_laptop;
603
604err_destroy_cros_peripherals:
605 while (--i >= 0) {
606 i2c_dev = &cros_laptop->i2c_peripherals[i];
607 info = &i2c_dev->board_info;
608 if (info->properties)
609 property_entries_free(info->properties);
610 }
611 kfree(cros_laptop->i2c_peripherals);
612err_free_cros_laptop:
613 kfree(cros_laptop);
614 return ERR_PTR(error);
615}
616
617static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop)
618{
619 struct i2c_peripheral *i2c_dev;
620 struct i2c_board_info *info;
621 int i;
622
623 for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
624 i2c_dev = &cros_laptop->i2c_peripherals[i];
625 info = &i2c_dev->board_info;
626
627 if (i2c_dev->client)
628 i2c_unregister_device(i2c_dev->client);
629
630 if (info->properties)
631 property_entries_free(info->properties);
632 }
633
634 kfree(cros_laptop->i2c_peripherals);
635 kfree(cros_laptop);
636}
616 637
617static int __init chromeos_laptop_init(void) 638static int __init chromeos_laptop_init(void)
618{ 639{
619 int ret; 640 const struct dmi_system_id *dmi_id;
641 int error;
620 642
621 if (!dmi_check_system(chromeos_laptop_dmi_table)) { 643 dmi_id = dmi_first_match(chromeos_laptop_dmi_table);
622 pr_debug("%s unsupported system.\n", __func__); 644 if (!dmi_id) {
645 pr_debug("unsupported system\n");
623 return -ENODEV; 646 return -ENODEV;
624 } 647 }
625 648
626 ret = platform_driver_register(&cros_platform_driver); 649 pr_debug("DMI Matched %s\n", dmi_id->ident);
627 if (ret) 650
628 return ret; 651 cros_laptop = chromeos_laptop_prepare((void *)dmi_id->driver_data);
652 if (IS_ERR(cros_laptop))
653 return PTR_ERR(cros_laptop);
629 654
630 cros_platform_device = platform_device_alloc("chromeos_laptop", -1); 655 error = bus_register_notifier(&i2c_bus_type,
631 if (!cros_platform_device) { 656 &chromeos_laptop_i2c_notifier);
632 ret = -ENOMEM; 657 if (error) {
633 goto fail_platform_device1; 658 pr_err("failed to register i2c bus notifier: %d\n", error);
659 chromeos_laptop_destroy(cros_laptop);
660 return error;
634 } 661 }
635 662
636 ret = platform_device_add(cros_platform_device); 663 /*
637 if (ret) 664 * Scan adapters that have been registered before we installed
638 goto fail_platform_device2; 665 * the notifier to make sure we do not miss any devices.
666 */
667 i2c_for_each_dev(NULL, chromeos_laptop_scan_adapter);
639 668
640 return 0; 669 return 0;
641
642fail_platform_device2:
643 platform_device_put(cros_platform_device);
644fail_platform_device1:
645 platform_driver_unregister(&cros_platform_driver);
646 return ret;
647} 670}
648 671
649static void __exit chromeos_laptop_exit(void) 672static void __exit chromeos_laptop_exit(void)
650{ 673{
651 if (als) 674 bus_unregister_notifier(&i2c_bus_type, &chromeos_laptop_i2c_notifier);
652 i2c_unregister_device(als); 675 chromeos_laptop_destroy(cros_laptop);
653 if (tp)
654 i2c_unregister_device(tp);
655 if (ts)
656 i2c_unregister_device(ts);
657
658 platform_device_unregister(cros_platform_device);
659 platform_driver_unregister(&cros_platform_driver);
660} 676}
661 677
662module_init(chromeos_laptop_init); 678module_init(chromeos_laptop_init);
diff --git a/include/linux/platform_data/atmel_mxt_ts.h b/include/linux/platform_data/atmel_mxt_ts.h
deleted file mode 100644
index 695035a8d7fb..000000000000
--- a/include/linux/platform_data/atmel_mxt_ts.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2 * Atmel maXTouch Touchscreen driver
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H
14#define __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H
15
16#include <linux/types.h>
17
18enum mxt_suspend_mode {
19 MXT_SUSPEND_DEEP_SLEEP = 0,
20 MXT_SUSPEND_T9_CTRL = 1,
21};
22
23/* The platform data for the Atmel maXTouch touchscreen driver */
24struct mxt_platform_data {
25 unsigned long irqflags;
26 u8 t19_num_keys;
27 const unsigned int *t19_keymap;
28 enum mxt_suspend_mode suspend_mode;
29};
30
31#endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */