123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- /*
- * pt_devtree.c
- * Parade TrueTouch(TM) Standard Product Device Tree Support Module.
- * For use with Parade touchscreen controllers.
- * Supported parts include:
- * TMA5XX
- * TMA448
- * TMA445A
- * TT21XXX
- * TT31XXX
- * TT4XXXX
- * TT7XXX
- * TC3XXX
- *
- * Copyright (C) 2015-2020 Parade Technologies
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2, and only version 2, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Contact Parade Technologies at www.paradetech.com <[email protected]>
- */
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/of_device.h>
- #include <linux/slab.h>
- #include "pt_platform.h"
- #include "pt_regs.h"
- #define MAX_NAME_LENGTH 64
- static bool is_create_and_get_pdata;
- enum pt_device_type {
- DEVICE_MT,
- DEVICE_BTN,
- DEVICE_PROXIMITY,
- DEVICE_TYPE_MAX,
- };
- struct pt_device_pdata_func {
- void * (*create_and_get_pdata)(struct device_node *dn);
- void (*free_pdata)(void *ptr);
- };
- struct pt_pdata_ptr {
- void **pdata;
- };
- #ifdef ENABLE_VIRTUAL_KEYS
- static struct kobject *board_properties_kobj;
- struct pt_virtual_keys {
- struct kobj_attribute kobj_attr;
- u16 *data;
- int size;
- };
- #endif
- struct pt_extended_mt_platform_data {
- struct pt_mt_platform_data pdata;
- #ifdef ENABLE_VIRTUAL_KEYS
- struct pt_virtual_keys vkeys;
- #endif
- };
- /*******************************************************************************
- * FUNCTION: get_inp_dev_name
- *
- * SUMMARY: Get the name of input device from dts.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- * **inp_dev_name - double pointer to the name of input device
- ******************************************************************************/
- static inline int get_inp_dev_name(struct device_node *dev_node,
- const char **inp_dev_name)
- {
- return of_property_read_string(dev_node, "parade,inp_dev_name",
- inp_dev_name);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_u16_array
- *
- * SUMMARY: Create and get u16 array from dts.
- *
- * RETURN:
- * success: the pointer of the created array
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- * *name - name of device node
- * size - number of u16 array elements
- ******************************************************************************/
- static s16 *create_and_get_u16_array(struct device_node *dev_node,
- const char *name, int *size)
- {
- const __be32 *values;
- s16 *val_array;
- int len;
- int sz;
- int rc;
- int i;
- values = of_get_property(dev_node, name, &len);
- if (values == NULL)
- return NULL;
- sz = len / sizeof(u32);
- pr_debug("%s: %s size:%d\n", __func__, name, sz);
- val_array = kcalloc(sz, sizeof(s16), GFP_KERNEL);
- if (!val_array) {
- rc = -ENOMEM;
- goto fail;
- }
- for (i = 0; i < sz; i++)
- val_array[i] = (s16)be32_to_cpup(values++);
- *size = sz;
- return val_array;
- fail:
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_touch_framework
- *
- * SUMMARY: Create and get touch framework structure from dts.
- *
- * RETURN:
- * success: the pointer of the touch framework data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- ******************************************************************************/
- static struct touch_framework *create_and_get_touch_framework(
- struct device_node *dev_node)
- {
- struct touch_framework *frmwrk;
- s16 *abs;
- int size;
- int rc;
- abs = create_and_get_u16_array(dev_node, "parade,abs", &size);
- if (IS_ERR_OR_NULL(abs))
- return (void *)abs;
- /* Check for valid abs size */
- if (size % PT_NUM_ABS_SET) {
- rc = -EINVAL;
- goto fail_free_abs;
- }
- frmwrk = kzalloc(sizeof(*frmwrk), GFP_KERNEL);
- if (!frmwrk) {
- rc = -ENOMEM;
- goto fail_free_abs;
- }
- frmwrk->abs = abs;
- frmwrk->size = size;
- return frmwrk;
- fail_free_abs:
- kfree(abs);
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_touch_framework
- *
- * SUMMARY: Free all the pointer of touch framework structure.
- *
- * PARAMETERS:
- * *frmwrk - pointer to touch framework structure
- ******************************************************************************/
- static void free_touch_framework(struct touch_framework *frmwrk)
- {
- kfree(frmwrk->abs);
- kfree(frmwrk);
- }
- #ifdef ENABLE_VIRTUAL_KEYS
- #define VIRTUAL_KEY_ELEMENT_SIZE 5
- /*******************************************************************************
- * FUNCTION: virtual_keys_show
- *
- * SUMMARY: Show method for the board_properties sysfs node that will show the
- * information for all virtual keys
- *
- * RETURN: size of data written to sysfs node
- *
- * PARAMETERS:
- * *kobj - pointer to kobject structure
- * *attr - pointer to kobject attributes
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t virtual_keys_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
- {
- struct pt_virtual_keys *vkeys = container_of(attr,
- struct pt_virtual_keys, kobj_attr);
- u16 *data = vkeys->data;
- int size = vkeys->size;
- int index;
- int i;
- index = 0;
- for (i = 0; i < size; i += VIRTUAL_KEY_ELEMENT_SIZE)
- index += scnprintf(buf + index, PT_MAX_PRBUF_SIZE - index,
- "0x01:%d:%d:%d:%d:%d\n",
- data[i], data[i+1], data[i+2], data[i+3], data[i+4]);
- return index;
- }
- /*******************************************************************************
- * FUNCTION: setup_virtual_keys
- *
- * SUMMARY: Create virtual key data array from dts and set up dynamic sysfs for
- * board_properties node.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- * **inp_dev_name - double pointer to the name of input device
- * *vkeys - pointer to virtual key structure
- ******************************************************************************/
- static int setup_virtual_keys(struct device_node *dev_node,
- const char *inp_dev_name, struct pt_virtual_keys *vkeys)
- {
- char *name;
- u16 *data;
- int size;
- int rc;
- data = create_and_get_u16_array(dev_node, "parade,virtual_keys", &size);
- if (data == NULL)
- return 0;
- else if (IS_ERR(data)) {
- rc = PTR_ERR(data);
- goto fail;
- }
- /* Check for valid virtual keys size */
- if (size % VIRTUAL_KEY_ELEMENT_SIZE) {
- rc = -EINVAL;
- goto fail_free_data;
- }
- name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
- if (!name) {
- rc = -ENOMEM;
- goto fail_free_data;
- }
- snprintf(name, MAX_NAME_LENGTH, "virtualkeys.%s", inp_dev_name);
- vkeys->data = data;
- vkeys->size = size;
- /* TODO: Instantiate in board file and export it */
- if (board_properties_kobj == NULL)
- board_properties_kobj =
- kobject_create_and_add("board_properties", NULL);
- if (board_properties_kobj == NULL) {
- pr_err("%s: Cannot get board_properties kobject!\n", __func__);
- rc = -EINVAL;
- goto fail_free_name;
- }
- /* Initialize dynamic SysFs attribute */
- sysfs_attr_init(&vkeys->kobj_attr.attr);
- vkeys->kobj_attr.attr.name = name;
- vkeys->kobj_attr.attr.mode = 0444;
- vkeys->kobj_attr.show = virtual_keys_show;
- rc = sysfs_create_file(board_properties_kobj, &vkeys->kobj_attr.attr);
- if (rc)
- goto fail_del_kobj;
- return 0;
- fail_del_kobj:
- kobject_del(board_properties_kobj);
- fail_free_name:
- kfree(name);
- vkeys->kobj_attr.attr.name = NULL;
- fail_free_data:
- kfree(data);
- vkeys->data = NULL;
- fail:
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: free_virtual_keys
- *
- * SUMMARY: Remove board_properties node and free all pointers.
- *
- * PARAMETERS:
- * *vkeys - pointer to virtual key structure
- ******************************************************************************/
- static void free_virtual_keys(struct pt_virtual_keys *vkeys)
- {
- if (board_properties_kobj)
- sysfs_remove_file(board_properties_kobj,
- &vkeys->kobj_attr.attr);
- kobject_del(board_properties_kobj);
- board_properties_kobj = NULL;
- kfree(vkeys->data);
- kfree(vkeys->kobj_attr.attr.name);
- }
- #endif
- /*******************************************************************************
- * FUNCTION: create_and_get_mt_pdata
- *
- * SUMMARY: Create and get touch platform data from dts.Touch framework and
- * virtual keys are set up in this function.
- *
- * RETURN:
- * success: the pointer of the platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- ******************************************************************************/
- static void *create_and_get_mt_pdata(struct device_node *dev_node)
- {
- struct pt_extended_mt_platform_data *ext_pdata;
- struct pt_mt_platform_data *pdata;
- u32 value;
- int rc;
- ext_pdata = kzalloc(sizeof(*ext_pdata), GFP_KERNEL);
- if (!ext_pdata) {
- rc = -ENOMEM;
- goto fail;
- }
- pdata = &ext_pdata->pdata;
- rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
- if (rc)
- goto fail_free_pdata;
- /* Optional fields */
- rc = of_property_read_u32(dev_node, "parade,flags", &value);
- if (!rc)
- pdata->flags = value;
- rc = of_property_read_u32(dev_node, "parade,vkeys_x", &value);
- if (!rc)
- pdata->vkeys_x = value;
- rc = of_property_read_u32(dev_node, "parade,vkeys_y", &value);
- if (!rc)
- pdata->vkeys_y = value;
- /* Required fields */
- pdata->frmwrk = create_and_get_touch_framework(dev_node);
- if (pdata->frmwrk == NULL) {
- rc = -EINVAL;
- goto fail_free_pdata;
- } else if (IS_ERR(pdata->frmwrk)) {
- rc = PTR_ERR(pdata->frmwrk);
- goto fail_free_pdata;
- }
- #ifdef ENABLE_VIRTUAL_KEYS
- rc = setup_virtual_keys(dev_node, pdata->inp_dev_name,
- &ext_pdata->vkeys);
- if (rc) {
- pr_err("%s: Cannot setup virtual keys!\n", __func__);
- goto fail_free_pdata;
- }
- #endif
- return pdata;
- fail_free_pdata:
- kfree(ext_pdata);
- fail:
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_mt_pdata
- *
- * SUMMARY: Free all pointers that include touch framework, virtual keys and
- * touch data.
- *
- * PARAMETERS:
- * *vkeys - pointer to virtual key structure
- ******************************************************************************/
- static void free_mt_pdata(void *pdata)
- {
- struct pt_mt_platform_data *mt_pdata =
- (struct pt_mt_platform_data *)pdata;
- struct pt_extended_mt_platform_data *ext_mt_pdata =
- container_of(mt_pdata,
- struct pt_extended_mt_platform_data, pdata);
- free_touch_framework(mt_pdata->frmwrk);
- #ifdef ENABLE_VIRTUAL_KEYS
- free_virtual_keys(&ext_mt_pdata->vkeys);
- #endif
- kfree(ext_mt_pdata);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_btn_pdata
- *
- * SUMMARY: Create and get button platform data from dts.
- *
- * RETURN:
- * success: the pointer of the platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- ******************************************************************************/
- static void *create_and_get_btn_pdata(struct device_node *dev_node)
- {
- struct pt_btn_platform_data *pdata;
- int rc;
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- rc = -ENOMEM;
- goto fail;
- }
- rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
- if (rc)
- goto fail_free_pdata;
- return pdata;
- fail_free_pdata:
- kfree(pdata);
- fail:
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_btn_pdata
- *
- * SUMMARY: Free all pointers for button platform data.
- *
- * PARAMETERS:
- * *vkeys - pointer to virtual key structure
- ******************************************************************************/
- static void free_btn_pdata(void *pdata)
- {
- struct pt_btn_platform_data *btn_pdata =
- (struct pt_btn_platform_data *)pdata;
- kfree(btn_pdata);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_proximity_pdata
- *
- * SUMMARY: Create and get proximity platform data from dts.
- *
- * RETURN:
- * success: the pointer of the proximity platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- ******************************************************************************/
- static void *create_and_get_proximity_pdata(struct device_node *dev_node)
- {
- struct pt_proximity_platform_data *pdata;
- int rc;
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- rc = -ENOMEM;
- goto fail;
- }
- rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
- if (rc)
- goto fail_free_pdata;
- pdata->frmwrk = create_and_get_touch_framework(dev_node);
- if (pdata->frmwrk == NULL) {
- rc = -EINVAL;
- goto fail_free_pdata;
- } else if (IS_ERR(pdata->frmwrk)) {
- rc = PTR_ERR(pdata->frmwrk);
- goto fail_free_pdata;
- }
- return pdata;
- fail_free_pdata:
- kfree(pdata);
- fail:
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_proximity_pdata
- *
- * SUMMARY: Free all pointers for proximity platform data.
- *
- * PARAMETERS:
- * *vkeys - pointer to virtual key structure
- ******************************************************************************/
- static void free_proximity_pdata(void *pdata)
- {
- struct pt_proximity_platform_data *proximity_pdata =
- (struct pt_proximity_platform_data *)pdata;
- free_touch_framework(proximity_pdata->frmwrk);
- kfree(proximity_pdata);
- }
- static struct pt_device_pdata_func device_pdata_funcs[DEVICE_TYPE_MAX] = {
- [DEVICE_MT] = {
- .create_and_get_pdata = create_and_get_mt_pdata,
- .free_pdata = free_mt_pdata,
- },
- [DEVICE_BTN] = {
- .create_and_get_pdata = create_and_get_btn_pdata,
- .free_pdata = free_btn_pdata,
- },
- [DEVICE_PROXIMITY] = {
- .create_and_get_pdata = create_and_get_proximity_pdata,
- .free_pdata = free_proximity_pdata,
- },
- };
- static struct pt_pdata_ptr pdata_ptr[DEVICE_TYPE_MAX];
- static const char *device_names[DEVICE_TYPE_MAX] = {
- [DEVICE_MT] = "parade,mt",
- [DEVICE_BTN] = "parade,btn",
- [DEVICE_PROXIMITY] = "parade,proximity",
- };
- /*******************************************************************************
- * FUNCTION: set_pdata_ptr
- *
- * SUMMARY: Set platform data pointer for touch, button, proximity module.
- *
- * PARAMETERS:
- * *pdata - pointer to platform data structure
- ******************************************************************************/
- static void set_pdata_ptr(struct pt_platform_data *pdata)
- {
- pdata_ptr[DEVICE_MT].pdata = (void **)&pdata->mt_pdata;
- pdata_ptr[DEVICE_BTN].pdata = (void **)&pdata->btn_pdata;
- pdata_ptr[DEVICE_PROXIMITY].pdata = (void **)&pdata->prox_pdata;
- }
- /*******************************************************************************
- * FUNCTION: get_device_type
- *
- * SUMMARY: Determine the device type[mt,btn,proximity] from dts.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- * *type - pointer to store the device type
- ******************************************************************************/
- static int get_device_type(struct device_node *dev_node,
- enum pt_device_type *type)
- {
- const char *name;
- enum pt_device_type t;
- int rc;
- rc = of_property_read_string(dev_node, "name", &name);
- if (rc)
- return rc;
- for (t = 0; t < DEVICE_TYPE_MAX; t++)
- if (!strncmp(name, device_names[t], MAX_NAME_LENGTH)) {
- *type = t;
- return 0;
- }
- return -EINVAL;
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_device_pdata
- *
- * SUMMARY: Create platform data for mt, btn, proximity module.
- *
- * RETURN:
- * success: the pointer of the platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *dev_node - pointer to device_node structure
- * type - determine the device type
- ******************************************************************************/
- static inline void *create_and_get_device_pdata(struct device_node *dev_node,
- enum pt_device_type type)
- {
- return device_pdata_funcs[type].create_and_get_pdata(dev_node);
- }
- /*******************************************************************************
- * FUNCTION: free_device_pdata
- *
- * SUMMARY: Free platform data for mt, btn, proximity module.
- *
- * PARAMETERS:
- * type - determine the device type
- ******************************************************************************/
- static inline void free_device_pdata(enum pt_device_type type)
- {
- device_pdata_funcs[type].free_pdata(*pdata_ptr[type].pdata);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_touch_setting
- *
- * SUMMARY: Create and get touch settings from dts.
- *
- * RETURN:
- * success: the pointer of touch settings
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *core_node - pointer to device_node structure
- * name - name of touch setting
- ******************************************************************************/
- static struct touch_settings *create_and_get_touch_setting(
- struct device_node *core_node, const char *name)
- {
- struct touch_settings *setting;
- char *tag_name;
- u32 tag_value;
- u16 *data;
- int size;
- int rc;
- data = create_and_get_u16_array(core_node, name, &size);
- if (IS_ERR_OR_NULL(data))
- return (void *)data;
- pr_debug("%s: Touch setting:'%s' size:%d\n", __func__, name, size);
- setting = kzalloc(sizeof(*setting), GFP_KERNEL);
- if (!setting) {
- rc = -ENOMEM;
- goto fail_free_data;
- }
- setting->data = (u8 *)data;
- setting->size = size;
- tag_name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
- if (!tag_name) {
- rc = -ENOMEM;
- goto fail_free_setting;
- }
- snprintf(tag_name, MAX_NAME_LENGTH, "%s-tag", name);
- rc = of_property_read_u32(core_node, tag_name, &tag_value);
- if (!rc)
- setting->tag = tag_value;
- kfree(tag_name);
- return setting;
- fail_free_setting:
- kfree(setting);
- fail_free_data:
- kfree(data);
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_touch_setting
- *
- * SUMMARY: Free touch setting data.
- *
- * PARAMETERS:
- * setting - pointer to touch setting
- ******************************************************************************/
- static void free_touch_setting(struct touch_settings *setting)
- {
- if (setting) {
- kfree(setting->data);
- kfree(setting);
- }
- }
- static char *touch_setting_names[PT_IC_GRPNUM_NUM] = {
- NULL, /* PT_IC_GRPNUM_RESERVED */
- "parade,cmd_regs", /* PT_IC_GRPNUM_CMD_REGS */
- "parade,tch_rep", /* PT_IC_GRPNUM_TCH_REP */
- "parade,data_rec", /* PT_IC_GRPNUM_DATA_REC */
- "parade,test_rec", /* PT_IC_GRPNUM_TEST_REC */
- "parade,pcfg_rec", /* PT_IC_GRPNUM_PCFG_REC */
- "parade,tch_parm_val", /* PT_IC_GRPNUM_TCH_PARM_VAL */
- "parade,tch_parm_size", /* PT_IC_GRPNUM_TCH_PARM_SIZE */
- NULL, /* PT_IC_GRPNUM_RESERVED1 */
- NULL, /* PT_IC_GRPNUM_RESERVED2 */
- "parade,opcfg_rec", /* PT_IC_GRPNUM_OPCFG_REC */
- "parade,ddata_rec", /* PT_IC_GRPNUM_DDATA_REC */
- "parade,mdata_rec", /* PT_IC_GRPNUM_MDATA_REC */
- "parade,test_regs", /* PT_IC_GRPNUM_TEST_REGS */
- "parade,btn_keys", /* PT_IC_GRPNUM_BTN_KEYS */
- NULL, /* PT_IC_GRPNUM_TTHE_REGS */
- };
- /*******************************************************************************
- * FUNCTION: pt_check_dsi_panel_dt
- *
- * SUMMARY: Get the DSI active panel information from dtsi
- *
- * RETURN:
- * 0 = success
- * !0 = fail
- *
- * PARAMETERS:
- * np - pointer to device_node structure
- * active_panel - name of active DSI panel
- ******************************************************************************/
- static int pt_check_dsi_panel_dt(struct device_node *np, struct drm_panel **active_panel)
- {
- int i;
- int count;
- struct device_node *node;
- struct drm_panel *panel;
- count = of_count_phandle_with_args(np, "panel", NULL);
- pr_info("%s: Active panel count: %d\n", __func__, count);
- if (count <= 0)
- return 0;
- for (i = 0; i < count; i++) {
- node = of_parse_phandle(np, "panel", i);
- if (node != NULL)
- pr_info("%s: Node handle successfully parsed !\n", __func__);
- panel = of_drm_find_panel(node);
- of_node_put(node);
- if (!IS_ERR(panel)) {
- pr_info("%s: Active panel selected !\n", __func__);
- *active_panel = panel;
- return 0;
- }
- }
- pr_err("%s: Active panel NOT selected !\n", __func__);
- return PTR_ERR(panel);
- }
- /*******************************************************************************
- * FUNCTION: create_and_get_core_pdata
- *
- * SUMMARY: Create and get core module platform data from dts.
- *
- * RETURN:
- * success: the pointer of core platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *core_node - pointer to device_node structure
- ******************************************************************************/
- static struct pt_core_platform_data *create_and_get_core_pdata(
- struct device_node *core_node)
- {
- struct pt_core_platform_data *pdata;
- u32 value;
- int rc;
- int i;
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- rc = -ENOMEM;
- goto fail;
- }
- /* Required fields */
- value = of_get_named_gpio_flags(core_node, "parade,irq_gpio", 0, &pdata->irq_gpio_flags);
- pdata->irq_gpio = value;
- rc = of_property_read_u32(core_node, "parade,hid_desc_register",
- &value);
- if (rc)
- goto fail_free;
- pdata->hid_desc_register = value;
- /* Optional fields */
- /* rst_gpio is optional since a platform may use
- * power cycling instead of using the XRES pin
- */
- value = of_get_named_gpio_flags(core_node, "parade,rst_gpio", 0, &pdata->rst_gpio_flags);
- pdata->rst_gpio = value;
- rc = of_property_read_u32(core_node, "parade,ddi_rst_gpio", &value);
- if (!rc)
- pdata->ddi_rst_gpio = value;
- rc = of_property_read_u32(core_node, "parade,vddi_gpio", &value);
- if (!rc)
- pdata->vddi_gpio = value;
- rc = of_property_read_u32(core_node, "parade,vcc_gpio", &value);
- if (!rc)
- pdata->vcc_gpio = value;
- rc = of_property_read_u32(core_node, "parade,avdd_gpio", &value);
- if (!rc)
- pdata->avdd_gpio = value;
- rc = of_property_read_u32(core_node, "parade,avee_gpio", &value);
- if (!rc)
- pdata->avee_gpio = value;
- rc = of_property_read_u32(core_node, "parade,level_irq_udelay", &value);
- if (!rc)
- pdata->level_irq_udelay = value;
- rc = of_property_read_u32(core_node, "parade,vendor_id", &value);
- if (!rc)
- pdata->vendor_id = value;
- rc = of_property_read_u32(core_node, "parade,product_id", &value);
- if (!rc)
- pdata->product_id = value;
- rc = of_property_read_u32(core_node, "parade,flags", &value);
- if (!rc)
- pdata->flags = value;
- rc = of_property_read_u32(core_node, "parade,easy_wakeup_gesture",
- &value);
- if (!rc)
- pdata->easy_wakeup_gesture = (u8)value;
- rc = of_property_read_u32(core_node, "parade,config_dut_generation",
- &value);
- if (!rc)
- pdata->config_dut_generation = (u8)value;
- else {
- pr_err("%s: dut_generation is not configured, set default: DUT_PIP2_CAPABLE!\n",
- __func__);
- pdata->config_dut_generation = CONFIG_DUT_PIP2_CAPABLE;
- }
- rc = of_property_read_u32(core_node, "parade,watchdog_force_stop",
- &value);
- if (!rc) {
- if (value)
- pdata->watchdog_force_stop = true;
- else
- pdata->watchdog_force_stop = false;
- } else {
- pr_err("%s: watchdog_force_stop is not configured, set default: false!\n",
- __func__);
- pdata->watchdog_force_stop = false;
- }
- rc = of_property_read_u32(core_node, "parade,panel_id_support",
- &value);
- if (!rc) {
- pdata->panel_id_support = (u8)value;
- } else {
- pr_err("%s: panel_id_support is not configured, set default: PT_PANEL_ID_DISABLE\n",
- __func__);
- pdata->panel_id_support = PT_PANEL_ID_DISABLE;
- }
- for (i = 0; (unsigned int)i < ARRAY_SIZE(touch_setting_names); i++) {
- if (touch_setting_names[i] == NULL)
- continue;
- pdata->sett[i] = create_and_get_touch_setting(core_node,
- touch_setting_names[i]);
- if (IS_ERR(pdata->sett[i])) {
- rc = PTR_ERR(pdata->sett[i]);
- goto fail_free_sett;
- } else if (pdata->sett[i] == NULL)
- pr_debug("%s: No data for setting '%s'\n", __func__,
- touch_setting_names[i]);
- }
- pr_debug("%s: irq_gpio:%d rst_gpio:%d\n"
- "hid_desc_reg:%d level_irq_udelay:%d vendor_id:%d prod_id:%d\n"
- "flags:%d easy_wakeup_gesture:%d\n", __func__,
- pdata->irq_gpio, pdata->rst_gpio,
- pdata->hid_desc_register,
- pdata->level_irq_udelay, pdata->vendor_id, pdata->product_id,
- pdata->flags, pdata->easy_wakeup_gesture);
- pdata->xres = pt_xres;
- pdata->init = pt_init;
- pdata->power = pt_power;
- pdata->detect = pt_detect;
- pdata->irq_stat = pt_irq_stat;
- pdata->setup_power = pt_setup_power;
- pdata->setup_irq = pt_setup_irq;
- return pdata;
- fail_free_sett:
- for (i--; i >= 0; i--)
- free_touch_setting(pdata->sett[i]);
- fail_free:
- kfree(pdata);
- fail:
- return ERR_PTR(rc);
- }
- /*******************************************************************************
- * FUNCTION: free_core_pdata
- *
- * SUMMARY: Free the core module platform data and touch settings data.
- *
- * RETURN:
- * success: the pointer of core platform data
- * fail : error code with type of error pointer
- *
- * PARAMETERS:
- * *core_node - pointer to device_node structure
- ******************************************************************************/
- static void free_core_pdata(void *pdata)
- {
- struct pt_core_platform_data *core_pdata = pdata;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(touch_setting_names); i++)
- free_touch_setting(core_pdata->sett[i]);
- kfree(core_pdata);
- }
- /*******************************************************************************
- * FUNCTION: pt_devtree_create_and_get_pdata
- *
- * SUMMARY: Parse dts and set up platform data for core module, multi-touch(mt)
- * module, button(btn) module, proximity module.And Assign platform data
- * pointer for loader module.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *adap_dev - pointer to device structure
- ******************************************************************************/
- int pt_devtree_create_and_get_pdata(struct device *adap_dev)
- {
- struct pt_platform_data *pdata;
- struct device_node *core_node, *dev_node, *dev_node_fail;
- struct drm_panel *active_panel = NULL;
- enum pt_device_type type;
- int count = 0;
- int rc = 0;
- pr_info("%s: Start of fetch dtsi..\n", __func__);
- if (is_create_and_get_pdata == true)
- return 0;
- if (!adap_dev->of_node)
- return 0;
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
- adap_dev->platform_data = pdata;
- set_pdata_ptr(pdata);
- /* There should be only one core node */
- for_each_child_of_node(adap_dev->of_node, core_node) {
- const char *name;
- rc = of_property_read_string(core_node, "name", &name);
- if (!rc)
- pr_debug("%s: name:%s\n", __func__, name);
- rc = pt_check_dsi_panel_dt(core_node, &active_panel);
- if (rc) {
- pr_err("%s: Panel not selected, rc=%d\n", __func__, rc);
- if (rc == -EPROBE_DEFER) {
- pr_err("%s: Probe defer selected, rc=%d\n", __func__, rc);
- kfree(pdata);
- return rc;
- }
- }
- pdata->core_pdata = create_and_get_core_pdata(core_node);
- if (IS_ERR(pdata->core_pdata)) {
- pr_err("%s: Error in fetch dtsi..\n", __func__);
- rc = PTR_ERR(pdata->core_pdata);
- break;
- }
- pr_info("%s: End of fetch dtsi..\n", __func__);
- pdata->core_pdata->active_panel = active_panel;
- pr_info("%s: Successful insert of active panel in core data\n",
- __func__);
- /* Increment reference count */
- of_node_get(core_node);
- for_each_child_of_node(core_node, dev_node) {
- count++;
- rc = get_device_type(dev_node, &type);
- if (rc)
- break;
- *pdata_ptr[type].pdata
- = create_and_get_device_pdata(dev_node, type);
- if (IS_ERR(*pdata_ptr[type].pdata))
- rc = PTR_ERR(*pdata_ptr[type].pdata);
- if (rc)
- break;
- /* Increment reference count */
- of_node_get(dev_node);
- }
- if (rc) {
- free_core_pdata(pdata->core_pdata);
- of_node_put(core_node);
- for_each_child_of_node(core_node, dev_node_fail) {
- if (dev_node == dev_node_fail)
- break;
- rc = get_device_type(dev_node, &type);
- if (rc)
- break;
- free_device_pdata(type);
- of_node_put(dev_node);
- }
- break;
- }
- pdata->loader_pdata = &_pt_loader_platform_data;
- }
- is_create_and_get_pdata = true;
- pr_debug("%s: %d child node(s) found\n", __func__, count);
- return rc;
- }
- EXPORT_SYMBOL_GPL(pt_devtree_create_and_get_pdata);
- /*******************************************************************************
- * FUNCTION: pt_devtree_clean_pdata
- *
- * SUMMARY: Free all platform data for core module, multi-touch(mt) module,
- * button(btn) module, proximity module.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *adap_dev - pointer to device structure
- ******************************************************************************/
- int pt_devtree_clean_pdata(struct device *adap_dev)
- {
- struct pt_platform_data *pdata;
- struct device_node *core_node, *dev_node;
- enum pt_device_type type;
- int rc = 0;
- if (is_create_and_get_pdata == false)
- return 0;
- if (!adap_dev->of_node)
- return 0;
- pdata = dev_get_platdata(adap_dev);
- set_pdata_ptr(pdata);
- free_core_pdata(pdata->core_pdata);
- for_each_child_of_node(adap_dev->of_node, core_node) {
- of_node_put(core_node);
- for_each_child_of_node(core_node, dev_node) {
- rc = get_device_type(dev_node, &type);
- if (rc)
- break;
- free_device_pdata(type);
- of_node_put(dev_node);
- }
- }
- is_create_and_get_pdata = false;
- return rc;
- }
- EXPORT_SYMBOL_GPL(pt_devtree_clean_pdata);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product DeviceTree Driver");
- MODULE_AUTHOR("Parade Technologies <[email protected]>");
|