commit c79729c84cbdde766517a863ade907d8e9a830d6 Author: Simon Budig Date: Thu Apr 5 14:43:18 2012 +0200 rework attribute handling. Not sure if this improves things diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index d96eb8f..9e5900c 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -35,7 +35,7 @@ #include -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.6" #define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_REPORT_RATE 0x08 @@ -47,6 +47,14 @@ #define WORK_REGISTER_OPMODE 0x3c #define FACTORY_REGISTER_OPMODE 0x01 +enum edt_ft5x06_setting { + SETTING_THRESHOLD, + SETTING_GAIN, + SETTING_OFFSET, + SETTING_REPORT_RATE, + N_SETTINGS, /* must be last entry */ +}; + struct edt_ft5x06_i2c_ts_data { struct i2c_client *client; struct input_dev *input; @@ -58,13 +66,69 @@ struct edt_ft5x06_i2c_ts_data { struct mutex mutex; bool factory_mode; - int threshold; - int gain; - int offset; - int report_rate; + int settings[N_SETTINGS]; char name[24]; }; +struct edt_ft5x06_settings_data_entry { + u8 addr; + u8 min; + u8 max; +}; + +static const struct edt_ft5x06_settings_data_entry +edt_ft5x06_settings_data[N_SETTINGS] = { + [SETTING_THRESHOLD] = { WORK_REGISTER_THRESHOLD, 20, 80 }, + [SETTING_GAIN] = { WORK_REGISTER_GAIN, 0, 31 }, + [SETTING_OFFSET] = { WORK_REGISTER_OFFSET, 0, 31 }, + [SETTING_REPORT_RATE] = { WORK_REGISTER_REPORT_RATE, 3, 14 }, +}; + + +static ssize_t edt_ft5x06_i2c_setting_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t edt_ft5x06_i2c_setting_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static ssize_t edt_ft5x06_i2c_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t edt_ft5x06_i2c_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static ssize_t edt_ft5x06_i2c_raw_data_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static DEVICE_ATTR(gain, 0664, + edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); +static DEVICE_ATTR(offset, 0664, + edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); +static DEVICE_ATTR(threshold, 0664, + edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); +static DEVICE_ATTR(report_rate, 0664, + edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); +static DEVICE_ATTR(mode, 0664, + edt_ft5x06_i2c_mode_show, edt_ft5x06_i2c_mode_store); +static DEVICE_ATTR(raw_data, 0444, + edt_ft5x06_i2c_raw_data_show, NULL); + +static struct attribute *edt_ft5x06_i2c_attrs[] = { + [SETTING_GAIN] = &dev_attr_gain.attr, + [SETTING_OFFSET] = &dev_attr_offset.attr, + [SETTING_THRESHOLD] = &dev_attr_threshold.attr, + [SETTING_REPORT_RATE] = &dev_attr_report_rate.attr, + &dev_attr_mode.attr, + &dev_attr_raw_data.attr, + NULL +}; + +static const struct attribute_group edt_ft5x06_i2c_attr_group = { + .attrs = edt_ft5x06_i2c_attrs, +}; + + static int edt_ft5x06_ts_readwrite(struct i2c_client *client, u16 wr_len, u8 *wr_buf, u16 rd_len, u8 *rd_buf) @@ -217,27 +281,14 @@ static ssize_t edt_ft5x06_i2c_setting_show(struct device *dev, struct edt_ft5x06_i2c_ts_data *tsdata = dev_get_drvdata(dev); struct i2c_client *client = tsdata->client; int ret = 0; - int *value; - u8 addr; + int i; - switch (attr->attr.name[0]) { - case 't': /* threshold */ - addr = WORK_REGISTER_THRESHOLD; - value = &tsdata->threshold; - break; - case 'g': /* gain */ - addr = WORK_REGISTER_GAIN; - value = &tsdata->gain; - break; - case 'o': /* offset */ - addr = WORK_REGISTER_OFFSET; - value = &tsdata->offset; - break; - case 'r': /* report rate */ - addr = WORK_REGISTER_REPORT_RATE; - value = &tsdata->report_rate; - break; - default: + for (i = 0; i < N_SETTINGS; i++) { + if (edt_ft5x06_i2c_attrs[i] == &attr->attr) + break; + } + + if (i == N_SETTINGS) { dev_err(&client->dev, "unknown attribute for edt_ft5x06_i2c_setting_show: %s\n", attr->attr.name); @@ -253,20 +304,21 @@ static ssize_t edt_ft5x06_i2c_setting_show(struct device *dev, return -EIO; } - ret = edt_ft5x06_i2c_register_read(tsdata, addr); + ret = edt_ft5x06_i2c_register_read(tsdata, + edt_ft5x06_settings_data[i].addr); if (ret < 0) { dev_err(&tsdata->client->dev, - "Unable to write to i2c touchscreen!\n"); + "Unable to read from i2c touchscreen!\n"); mutex_unlock(&tsdata->mutex); return ret; } mutex_unlock(&tsdata->mutex); - if (ret != *value) { + if (ret != tsdata->settings[i]) { dev_info(&tsdata->client->dev, "i2c read (%d) and stored value (%d) differ. Huh?\n", - ret, *value); - *value = ret; + ret, tsdata->settings[i]); + tsdata->settings[i] = ret; } return sprintf(buf, "%d\n", ret); @@ -278,10 +330,21 @@ static ssize_t edt_ft5x06_i2c_setting_store(struct device *dev, { struct edt_ft5x06_i2c_ts_data *tsdata = dev_get_drvdata(dev); struct i2c_client *client = tsdata->client; - int ret = 0; - u8 addr; + int i, ret = 0; unsigned int val; + for (i = 0; i < N_SETTINGS; i++) { + if (edt_ft5x06_i2c_attrs[i] == &attr->attr) + break; + } + + if (i == N_SETTINGS) { + dev_err(&client->dev, + "unknown attribute for edt_ft5x06_i2c_setting_show: %s\n", + attr->attr.name); + return -EINVAL; + } + mutex_lock(&tsdata->mutex); if (tsdata->factory_mode) { @@ -298,36 +361,14 @@ static ssize_t edt_ft5x06_i2c_setting_store(struct device *dev, goto out; } - switch (attr->attr.name[0]) { - case 't': /* threshold */ - addr = WORK_REGISTER_THRESHOLD; - val = val < 20 ? 20 : val > 80 ? 80 : val; - tsdata->threshold = val; - break; - case 'g': /* gain */ - addr = WORK_REGISTER_GAIN; - val = val < 0 ? 0 : val > 31 ? 31 : val; - tsdata->gain = val; - break; - case 'o': /* offset */ - addr = WORK_REGISTER_OFFSET; - val = val < 0 ? 0 : val > 31 ? 31 : val; - tsdata->offset = val; - break; - case 'r': /* report rate */ - addr = WORK_REGISTER_REPORT_RATE; - val = val < 3 ? 3 : val > 14 ? 14 : val; - tsdata->report_rate = val; - break; - default: - dev_err(&client->dev, - "unknown attribute for edt_ft5x06_i2c_setting_show: %s\n", - attr->attr.name); - ret = -EINVAL; - goto out; - } - - ret = edt_ft5x06_i2c_register_write(tsdata, addr, val); + if (val < edt_ft5x06_settings_data[i].min) + val = edt_ft5x06_settings_data[i].min; + else if (val > edt_ft5x06_settings_data[i].max) + val = edt_ft5x06_settings_data[i].max; + tsdata->settings[i] = val; + ret = edt_ft5x06_i2c_register_write(tsdata, + edt_ft5x06_settings_data[i].addr, + val); if (ret < 0) { dev_err(&tsdata->client->dev, @@ -411,18 +452,11 @@ static ssize_t edt_ft5x06_i2c_mode_store(struct device *dev, i*5); /* restore parameters */ - edt_ft5x06_i2c_register_write(tsdata, - WORK_REGISTER_THRESHOLD, - tsdata->threshold); - edt_ft5x06_i2c_register_write(tsdata, - WORK_REGISTER_GAIN, - tsdata->gain); - edt_ft5x06_i2c_register_write(tsdata, - WORK_REGISTER_OFFSET, - tsdata->offset); - edt_ft5x06_i2c_register_write(tsdata, - WORK_REGISTER_REPORT_RATE, - tsdata->report_rate); + for (i = 0; i < N_SETTINGS; i++) { + edt_ft5x06_i2c_register_write(tsdata, + edt_ft5x06_settings_data[i].addr, + tsdata->settings[i]); + } enable_irq(tsdata->irq); } @@ -482,33 +516,6 @@ static ssize_t edt_ft5x06_i2c_raw_data_show(struct device *dev, } -static DEVICE_ATTR(gain, 0664, - edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); -static DEVICE_ATTR(offset, 0664, - edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); -static DEVICE_ATTR(threshold, 0664, - edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); -static DEVICE_ATTR(report_rate, 0664, - edt_ft5x06_i2c_setting_show, edt_ft5x06_i2c_setting_store); -static DEVICE_ATTR(mode, 0664, - edt_ft5x06_i2c_mode_show, edt_ft5x06_i2c_mode_store); -static DEVICE_ATTR(raw_data, 0444, - edt_ft5x06_i2c_raw_data_show, NULL); - -static struct attribute *edt_ft5x06_i2c_attrs[] = { - &dev_attr_gain.attr, - &dev_attr_offset.attr, - &dev_attr_threshold.attr, - &dev_attr_report_rate.attr, - &dev_attr_mode.attr, - &dev_attr_raw_data.attr, - NULL -}; - -static const struct attribute_group edt_ft5x06_i2c_attr_group = { - .attrs = edt_ft5x06_i2c_attrs, -}; - static int edt_ft5x06_i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -516,7 +523,7 @@ static int edt_ft5x06_i2c_ts_probe(struct i2c_client *client, const struct edt_ft5x06_platform_data *pdata = client->dev.platform_data; struct edt_ft5x06_i2c_ts_data *tsdata; struct input_dev *input; - int error; + int i, error; u8 rdbuf[23]; char *model_name, *fw_version; @@ -586,14 +593,10 @@ static int edt_ft5x06_i2c_ts_probe(struct i2c_client *client, goto err_free_irq_pin; } - tsdata->threshold = edt_ft5x06_i2c_register_read(tsdata, - WORK_REGISTER_THRESHOLD); - tsdata->gain = edt_ft5x06_i2c_register_read(tsdata, - WORK_REGISTER_GAIN); - tsdata->offset = edt_ft5x06_i2c_register_read(tsdata, - WORK_REGISTER_OFFSET); - tsdata->report_rate = edt_ft5x06_i2c_register_read(tsdata, - WORK_REGISTER_REPORT_RATE); + for (i = 0; i < N_SETTINGS; i++) { + tsdata->settings[i] = edt_ft5x06_i2c_register_read(tsdata, + edt_ft5x06_settings_data[i].addr); + } tsdata->num_x = edt_ft5x06_i2c_register_read(tsdata, WORK_REGISTER_NUM_X); tsdata->num_y = edt_ft5x06_i2c_register_read(tsdata,