Exemplo n.º 1
0
static int __maybe_unused gsl_ts_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct gsl_ts_data *ts = i2c_get_clientdata(client);

	dev_warn(&client->dev, "%s: suspending device\n", __func__);

	disable_irq(client->irq);

	gsl_ts_reset_chip(client);
	usleep_range(10000, 20000);

	gsl_ts_power(client, true);

	if (device_may_wakeup(dev)) {
		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
	}

	ts->state = GSL_TS_SHUTDOWN;

	return 0;
}
Exemplo n.º 2
0
static int __maybe_unused gsl_ts_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct gsl_ts_data *ts = i2c_get_clientdata(client);

	dev_warn(&client->dev, "%s: resuming device\n", __func__);

	if (device_may_wakeup(dev) && ts->wake_irq_enabled) {
		disable_irq_wake(client->irq);
	}

	gsl_ts_power(client, false);

	gsl_ts_reset_chip(client);
	gsl_ts_startup_chip(client);

	enable_irq(client->irq);

	ts->state = GSL_TS_GREEN;

	return 0;
}
Exemplo n.º 3
0
static int __maybe_unused gsl_ts_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct gsl_ts_data *ts = i2c_get_clientdata(client);

	dev_warn(&client->dev, "%s: suspending device\n", __func__);

	disable_irq(client->irq);

	gsl_ts_reset_chip(client);
	usleep_range(10000, 20000);

	/* Do we need to do this ourselves? */
	acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D3);

	if (device_may_wakeup(dev)) {
		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
	}

	ts->state = GSL_TS_SHUTDOWN;

	return 0;
}
Exemplo n.º 4
0
static int __maybe_unused gsl_ts_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct gsl_ts_data *ts = i2c_get_clientdata(client);

	dev_warn(&client->dev, "%s: resuming device\n", __func__);

	if (device_may_wakeup(dev) && ts->wake_irq_enabled) {
		disable_irq_wake(client->irq);
	}

	/* Do we need to do this ourselves? */
	acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D0);
	usleep_range(20000, 50000);

	gsl_ts_reset_chip(client);
	gsl_ts_startup_chip(client);

	enable_irq(client->irq);

	ts->state = GSL_TS_GREEN;

	return 0;
}
Exemplo n.º 5
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 = 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;
}
Exemplo n.º 6
0
static irqreturn_t gsl_ts_irq(int irq, void *arg)
{
	int rc;
	struct gsl_ts_data *ts = (struct gsl_ts_data *) arg;
	struct i2c_client *client = ts->client;
	struct device *dev = &client->dev;
	u8 status[4] = { 0, 0, 0, 0 };
	u8 event[GSL_PACKET_SIZE];

	dev_dbg(&client->dev, "%s: IRQ received\n", __func__);

	if (ts->state == GSL_TS_SHUTDOWN) {
		dev_warn(&client->dev, "%s: device supended, not handling interrupt\n", __func__);
		return IRQ_HANDLED;
	}

	rc = gsl_ts_read(client, GSL_STATUS_REG, status, sizeof(status));
	if (rc < 0) {
		dev_err(dev, "%s: error reading chip status\n", __func__);
		return IRQ_HANDLED;
	}

	if (status[0] == GSL_STATUS_FW) {
		/* TODO: Send firmware here instead of during init */
		dev_info(dev, "%s: device waiting for firmware\n", __func__);

	} else if (status[0] == GSL_STATUS_TOUCH) {
		dev_vdbg(dev, "%s: touch event\n", __func__);

		rc = gsl_ts_read(client, GSL_DATA_REG, event, sizeof(event));
		if (rc < 0) {
			dev_err(dev, "%s: touch data read failed\n", __func__);
			return IRQ_HANDLED;
		}
		if (event[0] == 0xff) {
			dev_warn(dev, "%s: ignoring invalid touch record (0xff)\n", __func__);
			return IRQ_HANDLED;
		}

		rc = gsl_ts_read(client, GSL_TOUCH_STATUS_REG, status, sizeof(status));
		if (rc < 0) {
			dev_err(dev, "%s: reading touch status register failed\n", __func__);
			return IRQ_HANDLED;
		}

		if ((status[0] | status[1] | status[2] | status[3]) == 0) {
			gsl_ts_mt_event(ts, event);

		} else {
			dev_warn(dev, "%s: device seems to be stuck, resetting\n", __func__);

			rc = gsl_ts_reset_chip(ts->client);
			if (rc < 0) {
				dev_err(dev, "%s: reset_chip failed\n", __func__);
				return IRQ_HANDLED;
			}
			rc = gsl_ts_startup_chip(ts->client);
			if (rc < 0) {
				dev_err(dev, "%s: startup_chip failed\n", __func__);
				return IRQ_HANDLED;
			}
		}
	} else {
		dev_warn(&client->dev, "%s: IRQ received, unknown status 0x%02x\n", __func__, status[0]);
	}

	return IRQ_HANDLED;
}
Exemplo n.º 7
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;
}