Beispiel #1
0
static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on,
			unsigned long *delay_off)
{
	struct gb_channel *channel = get_channel_from_cdev(cdev);
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_blink_request req;
	bool old_active;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	mutex_lock(&channel->lock);
	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		goto out_unlock;

	old_active = channel->active;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.time_on_ms = cpu_to_le16(*delay_on);
	req.time_off_ms = cpu_to_le16(*delay_off);

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req,
				sizeof(req), NULL, 0);
	if (ret < 0)
		goto out_pm_put;

	if (delay_on)
		channel->active = true;
	else
		channel->active = false;

	/* we need to keep module alive when turning to active state */
	if (!old_active && channel->active)
		goto out_unlock;

	/*
	 * on the other hand if going to inactive we still hold a reference and
	 * need to put it, so we could go to suspend.
	 */
	if (old_active && !channel->active)
		gb_pm_runtime_put_autosuspend(bundle);

out_pm_put:
	gb_pm_runtime_put_autosuspend(bundle);
out_unlock:
	mutex_unlock(&channel->lock);

	return ret;
}
Beispiel #2
0
static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev,
				     u32 *fault)
{
	struct gb_channel *channel = container_of(fcdev, struct gb_channel,
						  fled);
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_get_flash_fault_request req;
	struct gb_lights_get_flash_fault_response resp;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT,
				&req, sizeof(req), &resp, sizeof(resp));
	if (!ret)
		*fault = le32_to_cpu(resp.fault);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #3
0
static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev,
				       u32 timeout)
{
	struct gb_channel *channel = container_of(fcdev, struct gb_channel,
						  fled);
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_flash_timeout_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.timeout_us = cpu_to_le32(timeout);

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT,
				&req, sizeof(req), NULL, 0);
	if (!ret)
		fcdev->timeout.val = timeout;

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #4
0
static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev,
				      bool state)
{
	struct gb_channel *channel = container_of(fcdev, struct gb_channel,
						  fled);
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_flash_strobe_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.state = state ? 1 : 0;

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE,
				&req, sizeof(req), NULL, 0);
	if (!ret)
		channel->strobe_state = state;

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #5
0
static int gb_lights_fade_set(struct gb_channel *channel)
{
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_fade_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.fade_in = channel->fade_in;
	req.fade_out = channel->fade_out;
	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE,
				&req, sizeof(req), NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #6
0
static int __gb_lights_flash_intensity_set(struct gb_channel *channel,
					   u32 intensity)
{
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_flash_intensity_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.intensity_uA = cpu_to_le32(intensity);

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY,
				&req, sizeof(req), NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #7
0
static int __gb_lights_led_brightness_set(struct gb_channel *channel)
{
	struct gb_lights_set_brightness_request req;
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	bool old_active;
	int ret;

	mutex_lock(&channel->lock);
	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		goto out_unlock;

	old_active = channel->active;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.brightness = (u8)channel->led->brightness;

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS,
				&req, sizeof(req), NULL, 0);
	if (ret < 0)
		goto out_pm_put;

	if (channel->led->brightness)
		channel->active = true;
	else
		channel->active = false;

	/* we need to keep module alive when turning to active state */
	if (!old_active && channel->active)
		goto out_unlock;

	/*
	 * on the other hand if going to inactive we still hold a reference and
	 * need to put it, so we could go to suspend.
	 */
	if (old_active && !channel->active)
		gb_pm_runtime_put_autosuspend(bundle);

out_pm_put:
	gb_pm_runtime_put_autosuspend(bundle);
out_unlock:
	mutex_unlock(&channel->lock);

	return ret;
}
Beispiel #8
0
static int turn_off(struct gb_vibrator_device *vib)
{
	struct gb_bundle *bundle = vib->connection->bundle;
	int ret;

	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
			NULL, 0, NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #9
0
static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
{
	struct gb_bundle *bundle = vib->connection->bundle;
	int ret;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret)
		return ret;

	/* Vibrator was switched ON earlier */
	if (cancel_delayed_work_sync(&vib->delayed_work))
		turn_off(vib);

	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
			NULL, 0, NULL, 0);
	if (ret) {
		gb_pm_runtime_put_autosuspend(bundle);
		return ret;
	}

	schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));

	return 0;
}
Beispiel #10
0
static int gb_lights_color_set(struct gb_channel *channel, u32 color)
{
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_color_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.color = cpu_to_le32(color);
	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR,
				&req, sizeof(req), NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Beispiel #11
0
static int gb_vibrator_probe(struct gb_bundle *bundle,
					const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct gb_connection *connection;
	struct gb_vibrator_device *vib;
	struct device *dev;
	int retval;

	if (bundle->num_cports != 1)
		return -ENODEV;

	cport_desc = &bundle->cport_desc[0];
	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
		return -ENODEV;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
						NULL);
	if (IS_ERR(connection)) {
		retval = PTR_ERR(connection);
		goto err_free_vib;
	}
	gb_connection_set_data(connection, vib);

	vib->connection = connection;

	greybus_set_drvdata(bundle, vib);

	retval = gb_connection_enable(connection);
	if (retval)
		goto err_connection_destroy;

	/*
	 * For now we create a device in sysfs for the vibrator, but odds are
	 * there is a "real" device somewhere in the kernel for this, but I
	 * can't find it at the moment...
	 */
	vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
	if (vib->minor < 0) {
		retval = vib->minor;
		goto err_connection_disable;
	}
	dev = device_create(&vibrator_class, &bundle->dev,
			    MKDEV(0, 0), vib, "vibrator%d", vib->minor);
	if (IS_ERR(dev)) {
		retval = -EINVAL;
		goto err_ida_remove;
	}
	vib->dev = dev;

	INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);

	gb_pm_runtime_put_autosuspend(bundle);

	return 0;

err_ida_remove:
	ida_simple_remove(&minors, vib->minor);
err_connection_disable:
	gb_connection_disable(connection);
err_connection_destroy:
	gb_connection_destroy(connection);
err_free_vib:
	kfree(vib);

	return retval;
}
Beispiel #12
0
static int gb_lights_probe(struct gb_bundle *bundle,
			   const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct gb_connection *connection;
	struct gb_lights *glights;
	int ret;

	if (bundle->num_cports != 1)
		return -ENODEV;

	cport_desc = &bundle->cport_desc[0];
	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LIGHTS)
		return -ENODEV;

	glights = kzalloc(sizeof(*glights), GFP_KERNEL);
	if (!glights)
		return -ENOMEM;

	mutex_init(&glights->lights_lock);

	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
					  gb_lights_request_handler);
	if (IS_ERR(connection)) {
		ret = PTR_ERR(connection);
		goto out;
	}

	glights->connection = connection;
	gb_connection_set_data(connection, glights);

	greybus_set_drvdata(bundle, glights);

	/* We aren't ready to receive an incoming request yet */
	ret = gb_connection_enable_tx(connection);
	if (ret)
		goto error_connection_destroy;

	/*
	 * Setup all the lights devices over this connection, if anything goes
	 * wrong tear down all lights
	 */
	ret = gb_lights_create_all(glights);
	if (ret < 0)
		goto error_connection_disable;

	/* We are ready to receive an incoming request now, enable RX as well */
	ret = gb_connection_enable(connection);
	if (ret)
		goto error_connection_disable;

	/* Enable & register lights */
	ret = gb_lights_register_all(glights);
	if (ret < 0)
		goto error_connection_disable;

	gb_pm_runtime_put_autosuspend(bundle);

	return 0;

error_connection_disable:
	gb_connection_disable(connection);
error_connection_destroy:
	gb_connection_destroy(connection);
out:
	gb_lights_release(glights);
	return ret;
}