static ssize_t touchkey_idac1_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cptk_data *tkey_i2c = dev_get_drvdata(dev); u8 data = -1; cptk_i2c_read(tkey_i2c, IDAC_REG+1, &data, sizeof(data)); return sprintf(buf, "%d\n", data); }
static ssize_t touchkey_threshold_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cptk_data *tkey_i2c = dev_get_drvdata(dev); u8 data; int ret; ret = cptk_i2c_read(tkey_i2c, THRESHOLD_REG, &data, sizeof(data)); return sprintf(buf, "%d\n", data); }
static ssize_t touchkey_raw_data1_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cptk_data *tkey_i2c = dev_get_drvdata(dev); u8 data[2]; u16 raw_data1 = 0; if (cptk_i2c_read(tkey_i2c, RAW_DATA_REG + 2, data, sizeof(data)) >= 0) raw_data1 = ((0x00FF & data[0]) << 8) | data[1]; return sprintf(buf, "%d\n", raw_data1); }
static ssize_t touchkey_autocal_status_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cptk_data *tkey_i2c = dev_get_drvdata(dev); u8 data; int ret; ret = cptk_i2c_read(tkey_i2c, AUTOCAL_REG, &data, sizeof(data)); if (data & TK_BIT_AUTOCAL) return sprintf(buf, "Enabled\n"); return sprintf(buf, "Disabled\n"); }
static void cptk_update_firmware_cb(const struct firmware *fw, void *context) { int ret; struct cptk_data *cptk = context; struct device *dev = &cptk->input_dev->dev; int retries = 3; pr_info("cptk: firware download start\n"); if (fw->size != FW_SIZE) { dev_err(dev, "%s: Firmware file size invalid size:%d\n", __func__, fw->size); return; } mutex_lock(&cptk->lock); disable_irq(cptk->client->irq); /* Lock the i2c bus since the firmware updater accesses it */ i2c_lock_adapter(cptk->client->adapter); while (retries--) { ret = touchkey_flash_firmware(cptk->pdata, fw->data); if (!ret) break; } if (ret) { cptk->touchkey_update_status = -1; dev_err(dev, "%s: Firmware update failed\n", __func__); } else { cptk->touchkey_update_status = 0; pr_info("cptk: firware download finished\n"); } i2c_unlock_adapter(cptk->client->adapter); enable_irq(cptk->client->irq); release_firmware(fw); mutex_unlock(&cptk->lock); cptk_i2c_read(cptk, KEYCODE_REG, cptk->cur_firm_ver, sizeof(cptk->cur_firm_ver)); pr_info("cptk: current firm ver = 0x%.2x, latest firm ver = 0x%.2x\n", cptk->cur_firm_ver[1], cptk->pdata->firm_ver); return; }
static ssize_t touchkey_menu_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cptk_data *cptk = dev_get_drvdata(dev); u8 data[2]; int menu_sensitivity = 0; mutex_lock(&cptk->lock); if (cptk_i2c_read(cptk, DIFF_DATA_REG, data, sizeof(data)) >= 0) menu_sensitivity = ((0x00FF&data[0])<<8)|data[1]; pr_debug("cptk: menu_sensitivity = %d\n", menu_sensitivity); mutex_unlock(&cptk->lock); return sprintf(buf, "%d\n", menu_sensitivity); }
static ssize_t touchkey_back_show(struct device *dev, struct device_attribute *attr, char *buf) { u8 data[2]; int ret; int back_sensitivity; struct cptk_data *cptk = dev_get_drvdata(dev); mutex_lock(&cptk->lock); ret = cptk_i2c_read(cptk, DIFF_DATA_REG + 2, data, sizeof(data)); back_sensitivity = ((0x00FF&data[0])<<8)|data[1]; pr_debug("cptk : back_sensitivity = %d\n", back_sensitivity); mutex_unlock(&cptk->lock); return sprintf(buf, "%d\n", back_sensitivity); }
static ssize_t set_touchkey_firm_version_read_show (struct device *dev, struct device_attribute *attr, char *buf) { char data[3] = { 0, }; int count, ret; struct cptk_data *cptk = dev_get_drvdata(dev); mutex_lock(&cptk->lock); ret = cptk_i2c_read(cptk, KEYCODE_REG, data, 3); if (ret) { pr_err("cptk : %s: error in cptk_i2c_read\n" , __func__); mutex_unlock(&cptk->lock); return ret; } mutex_unlock(&cptk->lock); count = sprintf(buf, "0x%X\n", data[1]); pr_debug("cptk :touch_version_read 0x%X\n", data[1]); return count; }
static irqreturn_t cptk_irq_thread(int irq, void *data) { struct cptk_data *cptk = data; int ret; u8 keycode; mutex_lock(&cptk->lock); if (!gpio_get_value(cptk->pdata->gpio)) { ret = cptk_i2c_read(cptk, KEYCODE_REG, &keycode, 1); if (keycode & UPDOWN_EVENT_BIT) input_report_key(cptk->input_dev, cptk->pdata->keymap[keycode & KEYCODE_BIT], 0); else input_report_key(cptk->input_dev, cptk->pdata->keymap[keycode & KEYCODE_BIT], 1); input_sync(cptk->input_dev); } mutex_unlock(&cptk->lock); return IRQ_HANDLED; }
static int __init cptk_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cptk_data *cptk; struct cptk_platform_data *pdata = client->dev.platform_data; struct device_node *np = client->dev.of_node; int ret = -ENODEV; int i; if (IS_ENABLED(CONFIG_OF)) { if (!pdata) { pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (unlikely(!pdata)) return -ENOMEM; } ret = cptk_probe_dt(np, &client->dev, pdata); if (ret) goto err_exit1; } else if (!pdata) { dev_err(&client->dev, "%s: missing pdata\n", __func__); return ret; } cptk = kzalloc(sizeof(struct cptk_data), GFP_KERNEL); if (unlikely(!cptk)) { dev_err(&client->dev, "failed to allocate driver data\n"); ret = -ENOMEM; goto err_exit1; } cptk->pdata = pdata; ret = gpio_request(pdata->gpio, "TOUCHKEY_INT"); if (ret < 0) { pr_err("%s: gpio request touchkey interrupt failed!, ret = %d\n", __func__, ret); goto err_exit2; } ret = gpio_request(pdata->en_pin, "TOUCHKEY_EN"); if (ret < 0) { pr_err("%s: gpio request for touchkey ldo failed!, ret = %d\n", __func__, ret); goto err_exit3; } gpio_direction_output(pdata->en_pin, GPIOF_INIT_LOW); cptk->input_dev = input_allocate_device(); if (unlikely(!cptk->input_dev)) { dev_err(&client->dev, "failed to allocate memory\n"); ret = -ENOMEM; goto err_exit4; } cptk->client = client; strlcpy(cptk->client->name, "cypress-touchkey", I2C_NAME_SIZE); cptk->client->dev.init_name = DEVICE_NAME; i2c_set_clientdata(client, cptk); cptk->input_dev->name = DEVICE_NAME; cptk->input_dev->phys = "cypress-touchkey/input0"; cptk->input_dev->id.bustype = BUS_HOST; cptk->input_dev->dev.parent = &client->dev; set_bit(EV_SYN, cptk->input_dev->evbit); set_bit(EV_KEY, cptk->input_dev->evbit); set_bit(EV_LED, cptk->input_dev->evbit); set_bit(LED_MISC, cptk->input_dev->ledbit); for (i = 1; i < cptk->pdata->keymap_size; i++) set_bit(cptk->pdata->keymap[i], cptk->input_dev->keybit); ret = input_register_device(cptk->input_dev); if (ret) { input_free_device(cptk->input_dev); goto err_exit4; } mutex_init(&cptk->i2c_lock); mutex_init(&cptk->lock); if (cptk->pdata->power) cptk->pdata->power(1); cptk->enable = true; /* Check Touch Key IC connect properly && read IC fw. version */ ret = cptk_i2c_read(cptk, KEYCODE_REG, cptk->cur_firm_ver, sizeof(cptk->cur_firm_ver)); if (ret < 0) { pr_err("cptk: %s: touch key IC is not connected.\n", __func__); goto err_exit5; } pr_info("cptk: module ver = 0x%.2x, IC firm ver = 0x%.2x, binary firm ver = 0x%.2x\n", cptk->cur_firm_ver[2], cptk->cur_firm_ver[1], cptk->pdata->firm_ver); if (cptk->cur_firm_ver[2] == cptk->pdata->mod_ver) { if (cptk->cur_firm_ver[1] < cptk->pdata->firm_ver) { pr_info("cptk: force firmware update\n"); ret = cptk_update_firmware(cptk); if (ret) goto err_exit5; } } #ifdef CONFIG_PM_RUNTIME pm_runtime_enable(&client->dev); #endif cptk_i2c_write(cptk, KEYCODE_REG, AUTO_CAL_MODE_CMD); cptk_i2c_write(cptk, CMD_REG, AUTO_CAL_EN_CMD); ret = request_threaded_irq(client->irq, NULL, cptk_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DEVICE_NAME, cptk); if (ret < 0) { dev_err(&client->dev, "failed to register interrupt\n"); goto err_exit5; } #ifdef CONFIG_MACH_PXA_SAMSUNG ret = cptk_create_sec_touchkey(cptk); if (ret < 0) goto err_exit6; #endif return 0; err_exit6: free_irq(client->irq, cptk); err_exit5: input_unregister_device(cptk->input_dev); err_exit4: gpio_free(pdata->en_pin); err_exit3: gpio_free(pdata->gpio); err_exit2: kfree(cptk); err_exit1: if(IS_ENABLED(CONFIG_OF) && pdata) { if(pdata->keymap) devm_kfree(&client->dev, (void *)pdata->keymap); devm_kfree(&client->dev, (void *)pdata); } return ret; }
static int __devinit cptk_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cptk_data *cptk; int ret; int i; cptk = kzalloc(sizeof(struct cptk_data), GFP_KERNEL); if (!cptk) { dev_err(&client->dev, "failed to allocate driver data\n"); return -ENOMEM; } cptk->input_dev = input_allocate_device(); if (!cptk->input_dev) return -ENOMEM; cptk->pdata = client->dev.platform_data; if (!cptk->pdata) { ret = -EINVAL; goto err_exit1; } cptk->client = client; strlcpy(cptk->client->name, "melfas-touchkey", I2C_NAME_SIZE); cptk->client->dev.init_name = DEVICE_NAME; i2c_set_clientdata(client, cptk); cptk->input_dev->name = DEVICE_NAME; cptk->input_dev->phys = "melfas-touchkey/input0"; cptk->input_dev->id.bustype = BUS_HOST; set_bit(EV_SYN, cptk->input_dev->evbit); set_bit(EV_KEY, cptk->input_dev->evbit); set_bit(EV_LED, cptk->input_dev->evbit); set_bit(LED_MISC, cptk->input_dev->ledbit); for (i = 1; i < cptk->pdata->keymap_size; i++) set_bit(cptk->pdata->keymap[i], cptk->input_dev->keybit); ret = input_register_device(cptk->input_dev); if (ret) { input_free_device(cptk->input_dev); return ret; } mutex_init(&cptk->i2c_lock); mutex_init(&cptk->lock); if (cptk->pdata->power) cptk->pdata->power(1); cptk->enable = true; cptk_i2c_read(cptk, KEYCODE_REG, cptk->cur_firm_ver, sizeof(cptk->cur_firm_ver)); pr_info("cptk :firm ver = 0x%x, mod ver = 0x%x\n", cptk->cur_firm_ver[1], cptk->cur_firm_ver[2]); if (cptk->cur_firm_ver[1] < cptk->pdata->firm_ver) { pr_info("cptk: force firmware update\n"); cptk_update_firmware(cptk); } #ifdef CONFIG_HAS_EARLYSUSPEND cptk->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 2; cptk->early_suspend.suspend = (void *) cptk_early_suspend; cptk->early_suspend.resume = (void *) cptk_late_resume; register_early_suspend(&cptk->early_suspend); #endif cptk_i2c_write(cptk, KEYCODE_REG, AUTO_CAL_MODE_CMD); cptk_i2c_write(cptk, CMD_REG, AUTO_CAL_EN_CMD); ret = request_threaded_irq(client->irq, NULL, cptk_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, DEVICE_NAME, cptk); if (ret < 0) goto err_exit2; ret = cptk_create_sec_touchkey(cptk); if (ret < 0) goto err_exit2; return 0; err_exit2: err_exit1: kfree(cptk); return ret; }