static int gsl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct gsl_ts_data *ts; const struct firmware *fw = NULL; unsigned long irqflags; int error; bool acpipower; dev_warn(&client->dev, "%s: got a device named %s at address 0x%x, IRQ %d, flags 0x%x\n", __func__, client->name, client->addr, client->irq, client->flags); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "%s: i2c check functionality error\n", __func__); error = -ENXIO; goto release; } if (client->irq <= 0) { dev_err(&client->dev, "%s: missing IRQ configuration\n", __func__); error = -ENODEV; goto release; } ts = devm_kzalloc(&client->dev, sizeof(struct gsl_ts_data), GFP_KERNEL); if (!ts) { error = -ENOMEM; goto release; } ts->client = client; i2c_set_clientdata(client, ts); if (gsl_fw_name != NULL) { strncpy(ts->fw_name, gsl_fw_name, sizeof(ts->fw_name)); } else { strncpy(ts->fw_name, GSL_FW_NAME_DEFAULT, sizeof(ts->fw_name)); } error = request_firmware(&fw, ts->fw_name, &ts->client->dev); if (error < 0) { dev_err(&client->dev, "%s: failed to load firmware: %d\n", __func__, error); goto release; } error = gsl_ts_init(ts, fw); if (error < 0) { dev_err(&client->dev, "%s: failed to initialize: %d\n", __func__, error); goto release; } ts->input = devm_input_allocate_device(&client->dev); if (!ts->input) { dev_err(&client->dev, "%s: failed to allocate input device\n", __func__); error = -ENOMEM; goto release; } ts->input->name = "Silead GSLx680 Touchscreen"; ts->input->id.bustype = BUS_I2C; ts->input->phys = "input/ts"; input_set_capability(ts->input, EV_ABS, ABS_X); input_set_capability(ts->input, EV_ABS, ABS_Y); input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, ts->jitter, ts->deadzone); input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, ts->jitter, ts->deadzone); input_mt_init_slots(ts->input, ts->multi_touches, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); input_set_drvdata(ts->input, ts); error = input_register_device(ts->input); if (error) { dev_err(&client->dev, "%s: unable to register input device: %d\n", __func__, error); goto release; } /* Try to use ACPI power methods first */ acpipower = false; #ifdef CONFIG_ACPI if (ACPI_COMPANION(&client->dev)) { /* Wake the device up with a power on reset */ if (acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D3)) { dev_warn(&client->dev, "%s: failed to wake up device through ACPI: %d, using GPIO controls instead\n", __func__, error); } else { acpipower = true; } } #endif /* Not available, use GPIO settings from DSDT/DT instead */ if (!acpipower) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ts->gpio = devm_gpiod_get_index(&client->dev, GSL_PWR_GPIO, 0); #else ts->gpio = devm_gpiod_get_index(&client->dev, GSL_PWR_GPIO, 0, GPIOD_OUT_LOW); #endif if (IS_ERR(ts->gpio)) { dev_err(&client->dev, "%s: error obtaining power pin GPIO resource\n", __func__); error = PTR_ERR(ts->gpio); goto release; } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) error = gpiod_direction_output(ts->gpio, 0); if (error < 0) { dev_err(&client->dev, "%s: error setting GPIO pin direction\n", __func__); goto release; } #endif } else { ts->gpio = NULL; } /* Enable power */ gsl_ts_power(client, false); /* Execute the controller startup sequence */ error = gsl_ts_reset_chip(client); if (error < 0) { dev_err(&client->dev, "%s: chip reset failed\n", __func__); goto release; } error = gsl_ts_write_fw(ts, fw); if (error < 0) { dev_err(&client->dev, "%s: firmware transfer failed\n", __func__); goto release; } error = gsl_ts_startup_chip(client); if (error < 0) { dev_err(&client->dev, "%s: chip startup failed\n", __func__); goto release; } /* * Systems using device tree should set up interrupt via DTS, * the rest will use the default falling edge interrupts. */ irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING; /* Set up interrupt handler - do we still need to account for shared interrupts? */ error = devm_request_threaded_irq( &client->dev, client->irq, NULL, gsl_ts_irq, irqflags | IRQF_ONESHOT, client->name, ts ); if (error) { dev_err(&client->dev, "%s: failed to register interrupt\n", __func__); goto release; } /* * Systems using device tree should set up wakeup via DTS, * the rest will configure device as wakeup source by default. */ if (!client->dev.of_node) { device_init_wakeup(&client->dev, true); } ts->state = GSL_TS_GREEN; release: if (fw) { release_firmware(fw); } if (error < 0) { return error; } return 0; }
static int gsl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct gsl_ts_data *ts; const struct firmware *fw; unsigned long irqflags; int error; dev_warn(&client->dev, "%s: got a device named %s at address 0x%x, IRQ %d, flags 0x%x\n", __func__, client->name, client->addr, client->irq, client->flags); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "%s: i2c check functionality error\n", __func__); return -ENXIO; } if (client->irq <= 0) { dev_err(&client->dev, "%s: missing IRQ configuration\n", __func__); return -ENODEV; } ts = devm_kzalloc(&client->dev, sizeof(struct gsl_ts_data), GFP_KERNEL); if (!ts) { return -ENOMEM; } ts->client = client; i2c_set_clientdata(client, ts); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* Set up ACPI device descriptor GPIO name mappings. * This is a fallback, it will only be used if the system does not * provide a corresponding _DSD entry. */ error = acpi_dev_add_driver_gpios(ACPI_COMPANION(&client->dev), gsl_ts_acpi_gpios); if (error < 0) { dev_warn(&client->dev, "%s: failed to register GPIO names, continuing anyway\n", __func__); } #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ts->gpio = devm_gpiod_get(&client->dev, GSL_PWR_GPIO); #else ts->gpio = devm_gpiod_get(&client->dev, GSL_PWR_GPIO, GPIOD_OUT_LOW); #endif if (IS_ERR(ts->gpio)) { dev_err(&client->dev, "%s: error obtaining power pin GPIO resource\n", __func__); error = PTR_ERR(ts->gpio); goto release_gpios; } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) error = gpiod_direction_output(ts->gpio, 0); if (error < 0) { dev_err(&client->dev, "%s: error setting GPIO pin direction\n", __func__); goto release_gpios; } #endif if (ACPI_COMPANION(&client->dev)) { /* Wake the device up with a power on reset */ error = acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D3); if (error == 0) { error = acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D0); } if (error) { dev_err(&client->dev, "%s: failed to wake up device through ACPI: %d, continuting anyway\n", __func__, error); } } error = request_firmware(&fw, GSL_FW_NAME, &ts->client->dev); if (error < 0) { dev_err(&client->dev, "%s: failed to load firmware: %d\n", __func__, error); goto release_gpios; } error = gsl_ts_init(ts, fw); if (error < 0) { dev_err(&client->dev, "%s: failed to initialize: %d\n", __func__, error); goto release_fw; } ts->input = devm_input_allocate_device(&client->dev); if (!ts->input) { dev_err(&client->dev, "%s: failed to allocate input device\n", __func__); error = -ENOMEM; goto release_fw; } ts->input->name = "Silead GSLx680 Touchscreen"; ts->input->id.bustype = BUS_I2C; ts->input->phys = "input/ts"; input_set_capability(ts->input, EV_ABS, ABS_X); input_set_capability(ts->input, EV_ABS, ABS_Y); input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, ts->jitter, ts->deadzone); input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, ts->jitter, ts->deadzone); input_mt_init_slots(ts->input, ts->multi_touches, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); input_set_drvdata(ts->input, ts); error = input_register_device(ts->input); if (error) { dev_err(&client->dev, "%s: unable to register input device: %d\n", __func__, error); goto release_fw; } /* * Systems using device tree should set up interrupt via DTS, * the rest will use the default falling edge interrupts. */ irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING; /* Set up interrupt handler - do we still need to account for shared interrupts? */ error = devm_request_threaded_irq( &client->dev, client->irq, NULL, gsl_ts_irq, irqflags | IRQF_ONESHOT, client->name, ts ); if (error) { dev_err(&client->dev, "%s: failed to register interrupt\n", __func__); goto release_fw; } /* Execute the controller startup sequence */ error = gsl_ts_reset_chip(client); if (error < 0) { dev_err(&client->dev, "%s: chip reset failed\n", __func__); goto release_fw; } error = gsl_ts_write_fw(ts, fw); if (error < 0) { dev_err(&client->dev, "%s: firmware transfer failed\n", __func__); goto release_fw; } error = gsl_ts_startup_chip(client); if (error < 0) { dev_err(&client->dev, "%s: chip startup failed\n", __func__); goto release_fw; } /* * Systems using device tree should set up wakeup via DTS, * the rest will configure device as wakeup source by default. */ if (!client->dev.of_node) { device_init_wakeup(&client->dev, true); } ts->state = GSL_TS_GREEN; release_fw: if (fw) { release_firmware(fw); } release_gpios: if (error < 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev)); #endif return error; } return 0; }