void __init input_wacom_init(void) { pr_info("[WACOM] init........\n"); wacom_request_gpio(); wacom_power_on(1); wacom_pdata.gpio_pendct = GPIO_PEN_PDCT; wacom_pdata.gpio_pen_insert = GPIO_PEN_DETECT; wacom_pdata.gpio_pen_fwe1 = GPIO_PEN_FWE1; i2c_register_board_info(MSM_8960_GSBI11_QUP_I2C_BUS_ID, wacom_boardinfo, ARRAY_SIZE(wacom_boardinfo)); platform_add_devices(input_wacom_devices, ARRAY_SIZE(input_wacom_devices)); }
static int wacom_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wacom_g5_platform_data *pdata; struct wacom_i2c *wac_i2c; struct input_dev *input; int ret = 0; int error; int fw_ver; /*Check I2C functionality */ ret = i2c_check_functionality(client->adapter, I2C_FUNC_I2C); if (!ret) { printk(KERN_ERR "%s: No I2C functionality found\n", __func__); ret = -ENODEV; goto err_i2c_fail; } /*Obtain kernel memory space for wacom i2c */ if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct wacom_g5_platform_data), GFP_KERNEL); if (!pdata) { dev_err(&client->dev, "%s: Failed to allocate memory\n", __func__); return -ENOMEM; } error = wacom_parse_dt(&client->dev, pdata); if (error) return error; } else { pdata = client->dev.platform_data; if (pdata == NULL) { dev_err(&client->dev, "%s: no pdata\n", __func__); ret = -ENODEV; goto err_i2c_fail; } } wacom_connect_platform_data(pdata); wacom_request_gpio(pdata); wac_i2c = kzalloc(sizeof(struct wacom_i2c), GFP_KERNEL); if (NULL == wac_i2c) { dev_err(&client->dev, "%s: failed to allocate wac_i2c.\n", __func__); ret = -ENOMEM; goto err_i2c_fail; } wac_i2c->client_boot = i2c_new_dummy(client->adapter, WACOM_I2C_BOOT); if (!wac_i2c->client_boot) { dev_err(&client->dev, "Fail to register sub client[0x%x]\n", WACOM_I2C_BOOT); } input = input_allocate_device(); if (NULL == input) { dev_err(&client->dev, "%s: failed to allocate input device.\n", __func__); ret = -ENOMEM; goto err_freemem; } wacom_i2c_set_input_values(client, wac_i2c, input); wac_i2c->wac_feature = &wacom_feature_EMR; wac_i2c->wac_pdata = pdata; wac_i2c->input_dev = input; wac_i2c->client = client; client->irq = gpio_to_irq(pdata->gpio_int); printk(KERN_ERR "%s: wacom : gpio_to_irq : %d\n", __func__, client->irq); wac_i2c->irq = client->irq; /*Set client data */ i2c_set_clientdata(client, wac_i2c); i2c_set_clientdata(wac_i2c->client_boot, wac_i2c); #ifdef WACOM_PDCT_WORK_AROUND wac_i2c->irq_pdct = gpio_to_irq(pdata->gpio_pen_pdct); wac_i2c->pen_pdct = PDCT_NOSIGNAL; #endif #ifdef WACOM_PEN_DETECT wac_i2c->gpio_pen_insert = pdata->gpio_pen_insert; wac_i2c->irq_pen_insert = gpio_to_irq(wac_i2c->gpio_pen_insert); #endif #ifdef WACOM_IMPORT_FW_ALGO wac_i2c->use_offset_table = true; wac_i2c->use_aveTransition = false; #endif #ifdef USE_WACOM_CALLBACK /*Register callbacks */ wac_i2c->callbacks.check_prox = wacom_check_emr_prox; if (wac_i2c->wac_pdata->register_cb) wac_i2c->wac_pdata->register_cb(&wac_i2c->callbacks); #endif #ifdef CONFIG_SEC_VIENNA_PROJECT if (system_rev >= WACOM_BOOT_REVISION) { wac_i2c->wac_pdata->ic_mpu_ver = MPU_W9007; wac_i2c->boot_ver = 0x92; } #endif #ifdef CONFIG_SEC_LT03_PROJECT wac_i2c->boot_ver = 0x92; #endif if (wac_i2c->wac_pdata->ic_mpu_ver > 0) { wac_i2c->ic_mpu_ver = wac_i2c->wac_pdata->ic_mpu_ver; wac_i2c->wac_pdata->compulsory_flash_mode(wac_i2c, false); wac_i2c->wac_pdata->wacom_start(wac_i2c); msleep(200); } else { wac_i2c->wac_pdata->compulsory_flash_mode(wac_i2c, true); /*Reset */ wac_i2c->wac_pdata->wacom_start(wac_i2c); msleep(200); ret = wacom_check_mpu_version(wac_i2c); if (ret == -ETIMEDOUT) #if defined(CONFIG_SEC_H_PROJECT) || defined(CONFIG_SEC_FRESCO_PROJECT) goto err_wacom_i2c_send_timeout; #else pr_err("[E-PEN] wacom_i2c_send failed.\n"); #endif wac_i2c->ic_mpu_ver = wacom_check_flash_mode(wac_i2c, BOOT_MPU); dev_info(&wac_i2c->client->dev, "%s: mpu version: %x\n", __func__, ret); if (wac_i2c->ic_mpu_ver == MPU_W9001) wac_i2c->client_boot = i2c_new_dummy(client->adapter, WACOM_I2C_9001_BOOT); else if (wac_i2c->ic_mpu_ver == MPU_W9007) { ret = wacom_enter_bootloader(wac_i2c); if (ret < 0) { dev_info(&wac_i2c->client->dev, "%s: failed to get BootLoader version, %d\n", __func__, ret); goto err_wacom_i2c_bootloader_ver; } else { dev_info(&wac_i2c->client->dev, "%s: BootLoader version: %x\n", __func__, ret); } } wac_i2c->wac_pdata->compulsory_flash_mode(wac_i2c, false); wac_i2c->wac_pdata->reset_platform_hw(wac_i2c); wac_i2c->power_enable = true; } /* Firmware Feature */ wacom_i2c_init_firm_data(); pr_err("%s: wacon ic turn on\n", __func__); fw_ver = wacom_i2c_query(wac_i2c); wacom_init_abs_params(wac_i2c); input_set_drvdata(input, wac_i2c); /*Initializing for semaphor */ mutex_init(&wac_i2c->lock); #if defined(CONFIG_SEC_LT03_PROJECT) || defined(CONFIG_SEC_VIENNA_PROJECT) mutex_init(&wac_i2c->irq_lock); #endif #ifdef WACOM_BOOSTER wacom_init_dvfs(wac_i2c); #endif INIT_DELAYED_WORK(&wac_i2c->resume_work, wacom_i2c_resume_work); #ifdef USE_WACOM_BLOCK_KEYEVENT INIT_DELAYED_WORK(&wac_i2c->touch_pressed_work, wacom_i2c_touch_pressed_work); wac_i2c->key_delay_time = 100; #endif #ifdef USE_WACOM_LCD_WORKAROUND wac_i2c->wait_done = true; wac_i2c->delay_time = 5; INIT_DELAYED_WORK(&wac_i2c->read_vsync_work, wacom_i2c_read_vsync_work); wac_i2c->boot_done = false; INIT_DELAYED_WORK(&wac_i2c->boot_done_work, wacom_i2c_boot_done_work); #endif #ifdef WACOM_PEN_DETECT INIT_DELAYED_WORK(&wac_i2c->pen_insert_dwork, pen_insert_work); #endif #ifdef WACOM_RESETPIN_DELAY INIT_DELAYED_WORK(&wac_i2c->work_wacom_reset, wacom_reset); #endif /*Before registering input device, data in each input_dev must be set */ ret = input_register_device(input); if (ret) { pr_err("[E-PEN] failed to register input device.\n"); goto err_input_allocate_device; } #ifdef CONFIG_HAS_EARLYSUSPEND wac_i2c->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; wac_i2c->early_suspend.suspend = wacom_i2c_early_suspend; wac_i2c->early_suspend.resume = wacom_i2c_late_resume; register_early_suspend(&wac_i2c->early_suspend); #endif wac_i2c->dev = device_create(sec_class, NULL, 0, NULL, "sec_epen"); if (IS_ERR(wac_i2c->dev)) { dev_err(&wac_i2c->client->dev, "%s: Failed to create device(wac_i2c->dev)!\n", __func__); goto err_sysfs_create_group; } dev_set_drvdata(wac_i2c->dev, wac_i2c); ret = sysfs_create_group(&wac_i2c->dev->kobj, &epen_attr_group); if (ret) { dev_err(&wac_i2c->client->dev, "%s: failed to create sysfs group\n", __func__); goto err_sysfs_create_group; } ret = wacom_firmware_update(wac_i2c); if (ret) { dev_err(&wac_i2c->client->dev, "%s: firmware update failed.\n", __func__); if (fw_ver > 0 && wac_i2c->ic_mpu_ver < 0) dev_err(&wac_i2c->client->dev, "%s: read query but not enter boot mode[%x,%x]\n", __func__, fw_ver, wac_i2c->ic_mpu_ver); else goto err_fw_update; } /*Request IRQ */ if (pdata->irq_flags) { ret = request_threaded_irq(wac_i2c->irq, NULL, wacom_interrupt, IRQF_DISABLED | pdata->irq_flags | IRQF_ONESHOT, wac_i2c->name, wac_i2c); if (ret < 0) { dev_err(&wac_i2c->client->dev, "%s: failed to request irq(%d) - %d\n", __func__, wac_i2c->irq, ret); goto err_fw_update; } #if defined(WACOM_PDCT_WORK_AROUND) ret = request_threaded_irq(wac_i2c->irq_pdct, NULL, wacom_interrupt_pdct, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, wac_i2c->name, wac_i2c); if (ret < 0) { dev_err(&wac_i2c->client->dev, "%s: failed to request irq(%d) - %d\n", __func__, wac_i2c->irq_pdct, ret); goto err_request_irq_pdct; } #endif #ifdef WACOM_PEN_DETECT ret = request_threaded_irq( wac_i2c->irq_pen_insert, NULL, wacom_pen_detect, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "pen_insert", wac_i2c); if (ret < 0) { dev_err(&wac_i2c->client->dev, "%s: failed to request irq(%d) - %d\n", __func__, wac_i2c->irq_pen_insert, ret); goto err_request_irq_pen_inster; } enable_irq_wake(wac_i2c->irq_pen_insert); /* update the current status */ schedule_delayed_work(&wac_i2c->pen_insert_dwork, HZ / 2); #endif } #ifdef USE_WACOM_LCD_WORKAROUND schedule_delayed_work(&wac_i2c->boot_done_work, msecs_to_jiffies(20 * 1000)); #endif #ifdef WACOM_RESETPIN_DELAY schedule_delayed_work(&wac_i2c->work_wacom_reset, msecs_to_jiffies(5000)); #endif return 0; err_request_irq_pen_inster: #ifdef WACOM_PDCT_WORK_AROUND free_irq(wac_i2c->irq_pdct, wac_i2c); err_request_irq_pdct: #endif free_irq(wac_i2c->irq, wac_i2c); err_fw_update: sysfs_remove_group(&wac_i2c->dev->kobj, &epen_attr_group); err_sysfs_create_group: wac_i2c->init_fail = true; input_unregister_device(input); err_input_allocate_device: cancel_delayed_work_sync(&wac_i2c->resume_work); cancel_delayed_work_sync(&wac_i2c->touch_pressed_work); #ifdef USE_WACOM_LCD_WORKAROUND cancel_delayed_work_sync(&wac_i2c->read_vsync_work); cancel_delayed_work_sync(&wac_i2c->boot_done_work); #endif cancel_delayed_work_sync(&wac_i2c->pen_insert_dwork); #ifdef WACOM_RESETPIN_DELAY cancel_delayed_work_sync(&wac_i2c->work_wacom_reset); #endif #ifdef WACOM_BOOSTER cancel_delayed_work_sync(&wac_i2c->work_dvfs_off); cancel_delayed_work_sync(&wac_i2c->work_dvfs_chg); mutex_destroy(&wac_i2c->dvfs_lock); #endif wac_i2c->wac_pdata->wacom_stop(wac_i2c); mutex_destroy(&wac_i2c->lock); err_wacom_i2c_bootloader_ver: #if defined(CONFIG_SEC_H_PROJECT) || defined(CONFIG_SEC_FRESCO_PROJECT) err_wacom_i2c_send_timeout: #endif input_free_device(input); err_freemem: kfree(wac_i2c); err_i2c_fail: return ret; }