brintos

brintos / linux-shallow public Read only

0
0
Text · 32.6 KiB · e509fdc Raw
1344 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Greybus Lights protocol driver.4 *5 * Copyright 2015 Google Inc.6 * Copyright 2015 Linaro Ltd.7 */8 9#include <linux/kernel.h>10#include <linux/leds.h>11#include <linux/led-class-flash.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/greybus.h>15#include <media/v4l2-flash-led-class.h>16 17#define NAMES_MAX	3218 19struct gb_channel {20	u8				id;21	u32				flags;22	u32				color;23	char				*color_name;24	u8				fade_in;25	u8				fade_out;26	u32				mode;27	char				*mode_name;28	struct attribute		**attrs;29	struct attribute_group		*attr_group;30	const struct attribute_group	**attr_groups;31	struct led_classdev		*led;32	struct led_classdev_flash	fled;33	struct led_flash_setting	intensity_uA;34	struct led_flash_setting	timeout_us;35	struct gb_light			*light;36	bool				is_registered;37	bool				releasing;38	bool				strobe_state;39	bool				active;40	struct mutex			lock;41};42 43struct gb_light {44	u8			id;45	char			*name;46	struct gb_lights	*glights;47	u32			flags;48	u8			channels_count;49	struct gb_channel	*channels;50	bool			has_flash;51	bool			ready;52#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS)53	struct v4l2_flash	*v4l2_flash;54	struct v4l2_flash	*v4l2_flash_ind;55#endif56};57 58struct gb_lights {59	struct gb_connection	*connection;60	u8			lights_count;61	struct gb_light		*lights;62	struct mutex		lights_lock;63};64 65static void gb_lights_channel_free(struct gb_channel *channel);66 67static struct gb_connection *get_conn_from_channel(struct gb_channel *channel)68{69	return channel->light->glights->connection;70}71 72static struct gb_connection *get_conn_from_light(struct gb_light *light)73{74	return light->glights->connection;75}76 77static bool is_channel_flash(struct gb_channel *channel)78{79	return !!(channel->mode & (GB_CHANNEL_MODE_FLASH | GB_CHANNEL_MODE_TORCH80				   | GB_CHANNEL_MODE_INDICATOR));81}82 83static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev)84{85	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev);86 87	return container_of(fled_cdev, struct gb_channel, fled);88}89 90static struct led_classdev *get_channel_cdev(struct gb_channel *channel)91{92	return &channel->fled.led_cdev;93}94 95static struct gb_channel *get_channel_from_mode(struct gb_light *light,96						u32 mode)97{98	struct gb_channel *channel;99	int i;100 101	for (i = 0; i < light->channels_count; i++) {102		channel = &light->channels[i];103		if (channel->mode == mode)104			return channel;105	}106	return NULL;107}108 109static int __gb_lights_flash_intensity_set(struct gb_channel *channel,110					   u32 intensity)111{112	struct gb_connection *connection = get_conn_from_channel(channel);113	struct gb_bundle *bundle = connection->bundle;114	struct gb_lights_set_flash_intensity_request req;115	int ret;116 117	if (channel->releasing)118		return -ESHUTDOWN;119 120	ret = gb_pm_runtime_get_sync(bundle);121	if (ret < 0)122		return ret;123 124	req.light_id = channel->light->id;125	req.channel_id = channel->id;126	req.intensity_uA = cpu_to_le32(intensity);127 128	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY,129				&req, sizeof(req), NULL, 0);130 131	gb_pm_runtime_put_autosuspend(bundle);132 133	return ret;134}135 136static int __gb_lights_flash_brightness_set(struct gb_channel *channel)137{138	u32 intensity;139 140	/* If the channel is flash we need to get the attached torch channel */141	if (channel->mode & GB_CHANNEL_MODE_FLASH)142		channel = get_channel_from_mode(channel->light,143						GB_CHANNEL_MODE_TORCH);144 145	if (!channel)146		return -EINVAL;147 148	/* For not flash we need to convert brightness to intensity */149	intensity = channel->intensity_uA.min +150			(channel->intensity_uA.step * channel->led->brightness);151 152	return __gb_lights_flash_intensity_set(channel, intensity);153}154 155static int gb_lights_color_set(struct gb_channel *channel, u32 color);156static int gb_lights_fade_set(struct gb_channel *channel);157 158static void led_lock(struct led_classdev *cdev)159{160	mutex_lock(&cdev->led_access);161}162 163static void led_unlock(struct led_classdev *cdev)164{165	mutex_unlock(&cdev->led_access);166}167 168#define gb_lights_fade_attr(__dir)					\169static ssize_t fade_##__dir##_show(struct device *dev,			\170				   struct device_attribute *attr,	\171				   char *buf)				\172{									\173	struct led_classdev *cdev = dev_get_drvdata(dev);		\174	struct gb_channel *channel = get_channel_from_cdev(cdev);	\175									\176	return sprintf(buf, "%u\n", channel->fade_##__dir);		\177}									\178									\179static ssize_t fade_##__dir##_store(struct device *dev,			\180				    struct device_attribute *attr,	\181				    const char *buf, size_t size)	\182{									\183	struct led_classdev *cdev = dev_get_drvdata(dev);		\184	struct gb_channel *channel = get_channel_from_cdev(cdev);	\185	u8 fade;							\186	int ret;							\187									\188	led_lock(cdev);							\189	if (led_sysfs_is_disabled(cdev)) {				\190		ret = -EBUSY;						\191		goto unlock;						\192	}								\193									\194	ret = kstrtou8(buf, 0, &fade);					\195	if (ret < 0) {							\196		dev_err(dev, "could not parse fade value %d\n", ret);	\197		goto unlock;						\198	}								\199	if (channel->fade_##__dir == fade)				\200		goto unlock;						\201	channel->fade_##__dir = fade;					\202									\203	ret = gb_lights_fade_set(channel);				\204	if (ret < 0)							\205		goto unlock;						\206									\207	ret = size;							\208unlock:									\209	led_unlock(cdev);						\210	return ret;							\211}									\212static DEVICE_ATTR_RW(fade_##__dir)213 214gb_lights_fade_attr(in);215gb_lights_fade_attr(out);216 217static ssize_t color_show(struct device *dev, struct device_attribute *attr,218			  char *buf)219{220	struct led_classdev *cdev = dev_get_drvdata(dev);221	struct gb_channel *channel = get_channel_from_cdev(cdev);222 223	return sprintf(buf, "0x%08x\n", channel->color);224}225 226static ssize_t color_store(struct device *dev, struct device_attribute *attr,227			   const char *buf, size_t size)228{229	struct led_classdev *cdev = dev_get_drvdata(dev);230	struct gb_channel *channel = get_channel_from_cdev(cdev);231	u32 color;232	int ret;233 234	led_lock(cdev);235	if (led_sysfs_is_disabled(cdev)) {236		ret = -EBUSY;237		goto unlock;238	}239	ret = kstrtou32(buf, 0, &color);240	if (ret < 0) {241		dev_err(dev, "could not parse color value %d\n", ret);242		goto unlock;243	}244 245	ret = gb_lights_color_set(channel, color);246	if (ret < 0)247		goto unlock;248 249	channel->color = color;250	ret = size;251unlock:252	led_unlock(cdev);253	return ret;254}255static DEVICE_ATTR_RW(color);256 257static int channel_attr_groups_set(struct gb_channel *channel,258				   struct led_classdev *cdev)259{260	int attr = 0;261	int size = 0;262 263	if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR)264		size++;265	if (channel->flags & GB_LIGHT_CHANNEL_FADER)266		size += 2;267 268	if (!size)269		return 0;270 271	/* Set attributes based in the channel flags */272	channel->attrs = kcalloc(size + 1, sizeof(*channel->attrs), GFP_KERNEL);273	if (!channel->attrs)274		return -ENOMEM;275	channel->attr_group = kzalloc(sizeof(*channel->attr_group), GFP_KERNEL);276	if (!channel->attr_group)277		return -ENOMEM;278	channel->attr_groups = kcalloc(2, sizeof(*channel->attr_groups),279				       GFP_KERNEL);280	if (!channel->attr_groups)281		return -ENOMEM;282 283	if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR)284		channel->attrs[attr++] = &dev_attr_color.attr;285	if (channel->flags & GB_LIGHT_CHANNEL_FADER) {286		channel->attrs[attr++] = &dev_attr_fade_in.attr;287		channel->attrs[attr++] = &dev_attr_fade_out.attr;288	}289 290	channel->attr_group->attrs = channel->attrs;291 292	channel->attr_groups[0] = channel->attr_group;293 294	cdev->groups = channel->attr_groups;295 296	return 0;297}298 299static int gb_lights_fade_set(struct gb_channel *channel)300{301	struct gb_connection *connection = get_conn_from_channel(channel);302	struct gb_bundle *bundle = connection->bundle;303	struct gb_lights_set_fade_request req;304	int ret;305 306	if (channel->releasing)307		return -ESHUTDOWN;308 309	ret = gb_pm_runtime_get_sync(bundle);310	if (ret < 0)311		return ret;312 313	req.light_id = channel->light->id;314	req.channel_id = channel->id;315	req.fade_in = channel->fade_in;316	req.fade_out = channel->fade_out;317	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE,318				&req, sizeof(req), NULL, 0);319 320	gb_pm_runtime_put_autosuspend(bundle);321 322	return ret;323}324 325static int gb_lights_color_set(struct gb_channel *channel, u32 color)326{327	struct gb_connection *connection = get_conn_from_channel(channel);328	struct gb_bundle *bundle = connection->bundle;329	struct gb_lights_set_color_request req;330	int ret;331 332	if (channel->releasing)333		return -ESHUTDOWN;334 335	ret = gb_pm_runtime_get_sync(bundle);336	if (ret < 0)337		return ret;338 339	req.light_id = channel->light->id;340	req.channel_id = channel->id;341	req.color = cpu_to_le32(color);342	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR,343				&req, sizeof(req), NULL, 0);344 345	gb_pm_runtime_put_autosuspend(bundle);346 347	return ret;348}349 350static int __gb_lights_led_brightness_set(struct gb_channel *channel)351{352	struct gb_lights_set_brightness_request req;353	struct gb_connection *connection = get_conn_from_channel(channel);354	struct gb_bundle *bundle = connection->bundle;355	bool old_active;356	int ret;357 358	mutex_lock(&channel->lock);359	ret = gb_pm_runtime_get_sync(bundle);360	if (ret < 0)361		goto out_unlock;362 363	old_active = channel->active;364 365	req.light_id = channel->light->id;366	req.channel_id = channel->id;367	req.brightness = (u8)channel->led->brightness;368 369	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS,370				&req, sizeof(req), NULL, 0);371	if (ret < 0)372		goto out_pm_put;373 374	if (channel->led->brightness)375		channel->active = true;376	else377		channel->active = false;378 379	/* we need to keep module alive when turning to active state */380	if (!old_active && channel->active)381		goto out_unlock;382 383	/*384	 * on the other hand if going to inactive we still hold a reference and385	 * need to put it, so we could go to suspend.386	 */387	if (old_active && !channel->active)388		gb_pm_runtime_put_autosuspend(bundle);389 390out_pm_put:391	gb_pm_runtime_put_autosuspend(bundle);392out_unlock:393	mutex_unlock(&channel->lock);394 395	return ret;396}397 398static int __gb_lights_brightness_set(struct gb_channel *channel)399{400	int ret;401 402	if (channel->releasing)403		return 0;404 405	if (is_channel_flash(channel))406		ret = __gb_lights_flash_brightness_set(channel);407	else408		ret = __gb_lights_led_brightness_set(channel);409 410	return ret;411}412 413static int gb_brightness_set(struct led_classdev *cdev,414			     enum led_brightness value)415{416	struct gb_channel *channel = get_channel_from_cdev(cdev);417 418	channel->led->brightness = value;419 420	return __gb_lights_brightness_set(channel);421}422 423static enum led_brightness gb_brightness_get(struct led_classdev *cdev)424 425{426	struct gb_channel *channel = get_channel_from_cdev(cdev);427 428	return channel->led->brightness;429}430 431static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on,432			unsigned long *delay_off)433{434	struct gb_channel *channel = get_channel_from_cdev(cdev);435	struct gb_connection *connection = get_conn_from_channel(channel);436	struct gb_bundle *bundle = connection->bundle;437	struct gb_lights_blink_request req;438	bool old_active;439	int ret;440 441	if (channel->releasing)442		return -ESHUTDOWN;443 444	if (!delay_on || !delay_off)445		return -EINVAL;446 447	mutex_lock(&channel->lock);448	ret = gb_pm_runtime_get_sync(bundle);449	if (ret < 0)450		goto out_unlock;451 452	old_active = channel->active;453 454	req.light_id = channel->light->id;455	req.channel_id = channel->id;456	req.time_on_ms = cpu_to_le16(*delay_on);457	req.time_off_ms = cpu_to_le16(*delay_off);458 459	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req,460				sizeof(req), NULL, 0);461	if (ret < 0)462		goto out_pm_put;463 464	if (*delay_on)465		channel->active = true;466	else467		channel->active = false;468 469	/* we need to keep module alive when turning to active state */470	if (!old_active && channel->active)471		goto out_unlock;472 473	/*474	 * on the other hand if going to inactive we still hold a reference and475	 * need to put it, so we could go to suspend.476	 */477	if (old_active && !channel->active)478		gb_pm_runtime_put_autosuspend(bundle);479 480out_pm_put:481	gb_pm_runtime_put_autosuspend(bundle);482out_unlock:483	mutex_unlock(&channel->lock);484 485	return ret;486}487 488static void gb_lights_led_operations_set(struct gb_channel *channel,489					 struct led_classdev *cdev)490{491	cdev->brightness_get = gb_brightness_get;492	cdev->brightness_set_blocking = gb_brightness_set;493 494	if (channel->flags & GB_LIGHT_CHANNEL_BLINK)495		cdev->blink_set = gb_blink_set;496}497 498#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS)499/* V4L2 specific helpers */500static const struct v4l2_flash_ops v4l2_flash_ops;501 502static void __gb_lights_channel_v4l2_config(struct led_flash_setting *channel_s,503					    struct led_flash_setting *v4l2_s)504{505	v4l2_s->min = channel_s->min;506	v4l2_s->max = channel_s->max;507	v4l2_s->step = channel_s->step;508	/* For v4l2 val is the default value */509	v4l2_s->val = channel_s->max;510}511 512static int gb_lights_light_v4l2_register(struct gb_light *light)513{514	struct gb_connection *connection = get_conn_from_light(light);515	struct device *dev = &connection->bundle->dev;516	struct v4l2_flash_config sd_cfg = { {0} }, sd_cfg_ind = { {0} };517	struct led_classdev_flash *fled;518	struct led_classdev *iled = NULL;519	struct gb_channel *channel_torch, *channel_ind, *channel_flash;520 521	channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH);522	if (channel_torch)523		__gb_lights_channel_v4l2_config(&channel_torch->intensity_uA,524						&sd_cfg.intensity);525 526	channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR);527	if (channel_ind) {528		__gb_lights_channel_v4l2_config(&channel_ind->intensity_uA,529						&sd_cfg_ind.intensity);530		iled = &channel_ind->fled.led_cdev;531	}532 533	channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH);534	if (!channel_flash) {535		dev_err(dev, "failed to get flash channel from mode\n");536		return -EINVAL;537	}538 539	fled = &channel_flash->fled;540 541	snprintf(sd_cfg.dev_name, sizeof(sd_cfg.dev_name), "%s", light->name);542	snprintf(sd_cfg_ind.dev_name, sizeof(sd_cfg_ind.dev_name),543		 "%s indicator", light->name);544 545	/* Set the possible values to faults, in our case all faults */546	sd_cfg.flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT |547		LED_FAULT_OVER_TEMPERATURE | LED_FAULT_SHORT_CIRCUIT |548		LED_FAULT_OVER_CURRENT | LED_FAULT_INDICATOR |549		LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE |550		LED_FAULT_LED_OVER_TEMPERATURE;551 552	light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, &v4l2_flash_ops,553					    &sd_cfg);554	if (IS_ERR(light->v4l2_flash))555		return PTR_ERR(light->v4l2_flash);556 557	if (channel_ind) {558		light->v4l2_flash_ind =559			v4l2_flash_indicator_init(dev, NULL, iled, &sd_cfg_ind);560		if (IS_ERR(light->v4l2_flash_ind)) {561			v4l2_flash_release(light->v4l2_flash);562			return PTR_ERR(light->v4l2_flash_ind);563		}564	}565 566	return 0;567}568 569static void gb_lights_light_v4l2_unregister(struct gb_light *light)570{571	v4l2_flash_release(light->v4l2_flash_ind);572	v4l2_flash_release(light->v4l2_flash);573}574#else575static int gb_lights_light_v4l2_register(struct gb_light *light)576{577	struct gb_connection *connection = get_conn_from_light(light);578 579	dev_err(&connection->bundle->dev, "no support for v4l2 subdevices\n");580	return 0;581}582 583static void gb_lights_light_v4l2_unregister(struct gb_light *light)584{585}586#endif587 588#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH)589/* Flash specific operations */590static int gb_lights_flash_intensity_set(struct led_classdev_flash *fcdev,591					 u32 brightness)592{593	struct gb_channel *channel = container_of(fcdev, struct gb_channel,594						  fled);595	int ret;596 597	ret = __gb_lights_flash_intensity_set(channel, brightness);598	if (ret < 0)599		return ret;600 601	fcdev->brightness.val = brightness;602 603	return 0;604}605 606static int gb_lights_flash_intensity_get(struct led_classdev_flash *fcdev,607					 u32 *brightness)608{609	*brightness = fcdev->brightness.val;610 611	return 0;612}613 614static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev,615				      bool state)616{617	struct gb_channel *channel = container_of(fcdev, struct gb_channel,618						  fled);619	struct gb_connection *connection = get_conn_from_channel(channel);620	struct gb_bundle *bundle = connection->bundle;621	struct gb_lights_set_flash_strobe_request req;622	int ret;623 624	if (channel->releasing)625		return -ESHUTDOWN;626 627	ret = gb_pm_runtime_get_sync(bundle);628	if (ret < 0)629		return ret;630 631	req.light_id = channel->light->id;632	req.channel_id = channel->id;633	req.state = state ? 1 : 0;634 635	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE,636				&req, sizeof(req), NULL, 0);637	if (!ret)638		channel->strobe_state = state;639 640	gb_pm_runtime_put_autosuspend(bundle);641 642	return ret;643}644 645static int gb_lights_flash_strobe_get(struct led_classdev_flash *fcdev,646				      bool *state)647{648	struct gb_channel *channel = container_of(fcdev, struct gb_channel,649						  fled);650 651	*state = channel->strobe_state;652	return 0;653}654 655static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev,656				       u32 timeout)657{658	struct gb_channel *channel = container_of(fcdev, struct gb_channel,659						  fled);660	struct gb_connection *connection = get_conn_from_channel(channel);661	struct gb_bundle *bundle = connection->bundle;662	struct gb_lights_set_flash_timeout_request req;663	int ret;664 665	if (channel->releasing)666		return -ESHUTDOWN;667 668	ret = gb_pm_runtime_get_sync(bundle);669	if (ret < 0)670		return ret;671 672	req.light_id = channel->light->id;673	req.channel_id = channel->id;674	req.timeout_us = cpu_to_le32(timeout);675 676	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT,677				&req, sizeof(req), NULL, 0);678	if (!ret)679		fcdev->timeout.val = timeout;680 681	gb_pm_runtime_put_autosuspend(bundle);682 683	return ret;684}685 686static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev,687				     u32 *fault)688{689	struct gb_channel *channel = container_of(fcdev, struct gb_channel,690						  fled);691	struct gb_connection *connection = get_conn_from_channel(channel);692	struct gb_bundle *bundle = connection->bundle;693	struct gb_lights_get_flash_fault_request req;694	struct gb_lights_get_flash_fault_response resp;695	int ret;696 697	if (channel->releasing)698		return -ESHUTDOWN;699 700	ret = gb_pm_runtime_get_sync(bundle);701	if (ret < 0)702		return ret;703 704	req.light_id = channel->light->id;705	req.channel_id = channel->id;706 707	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT,708				&req, sizeof(req), &resp, sizeof(resp));709	if (!ret)710		*fault = le32_to_cpu(resp.fault);711 712	gb_pm_runtime_put_autosuspend(bundle);713 714	return ret;715}716 717static const struct led_flash_ops gb_lights_flash_ops = {718	.flash_brightness_set	= gb_lights_flash_intensity_set,719	.flash_brightness_get	= gb_lights_flash_intensity_get,720	.strobe_set		= gb_lights_flash_strobe_set,721	.strobe_get		= gb_lights_flash_strobe_get,722	.timeout_set		= gb_lights_flash_timeout_set,723	.fault_get		= gb_lights_flash_fault_get,724};725 726static int __gb_lights_channel_torch_attach(struct gb_channel *channel,727					    struct gb_channel *channel_torch)728{729	char *name;730 731	/* we can only attach torch to a flash channel */732	if (!(channel->mode & GB_CHANNEL_MODE_FLASH))733		return 0;734 735	/* Move torch brightness to the destination */736	channel->led->max_brightness = channel_torch->led->max_brightness;737 738	/* append mode name to flash name */739	name = kasprintf(GFP_KERNEL, "%s_%s", channel->led->name,740			 channel_torch->mode_name);741	if (!name)742		return -ENOMEM;743	kfree(channel->led->name);744	channel->led->name = name;745 746	channel_torch->led = channel->led;747 748	return 0;749}750 751static int __gb_lights_flash_led_register(struct gb_channel *channel)752{753	struct gb_connection *connection = get_conn_from_channel(channel);754	struct led_classdev_flash *fled = &channel->fled;755	struct led_flash_setting *fset;756	struct gb_channel *channel_torch;757	int ret;758 759	fled->ops = &gb_lights_flash_ops;760 761	fled->led_cdev.flags |= LED_DEV_CAP_FLASH;762 763	fset = &fled->brightness;764	fset->min = channel->intensity_uA.min;765	fset->max = channel->intensity_uA.max;766	fset->step = channel->intensity_uA.step;767	fset->val = channel->intensity_uA.max;768 769	/* Only the flash mode have the timeout constraints settings */770	if (channel->mode & GB_CHANNEL_MODE_FLASH) {771		fset = &fled->timeout;772		fset->min = channel->timeout_us.min;773		fset->max = channel->timeout_us.max;774		fset->step = channel->timeout_us.step;775		fset->val = channel->timeout_us.max;776	}777 778	/*779	 * If light have torch mode channel, this channel will be the led780	 * classdev of the registered above flash classdev781	 */782	channel_torch = get_channel_from_mode(channel->light,783					      GB_CHANNEL_MODE_TORCH);784	if (channel_torch) {785		ret = __gb_lights_channel_torch_attach(channel, channel_torch);786		if (ret < 0)787			goto fail;788	}789 790	ret = led_classdev_flash_register(&connection->bundle->dev, fled);791	if (ret < 0)792		goto fail;793 794	channel->is_registered = true;795	return 0;796fail:797	channel->led = NULL;798	return ret;799}800 801static void __gb_lights_flash_led_unregister(struct gb_channel *channel)802{803	if (!channel->is_registered)804		return;805 806	led_classdev_flash_unregister(&channel->fled);807}808 809static int gb_lights_channel_flash_config(struct gb_channel *channel)810{811	struct gb_connection *connection = get_conn_from_channel(channel);812	struct gb_lights_get_channel_flash_config_request req;813	struct gb_lights_get_channel_flash_config_response conf;814	struct led_flash_setting *fset;815	int ret;816 817	req.light_id = channel->light->id;818	req.channel_id = channel->id;819 820	ret = gb_operation_sync(connection,821				GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG,822				&req, sizeof(req), &conf, sizeof(conf));823	if (ret < 0)824		return ret;825 826	/*827	 * Intensity constraints for flash related modes: flash, torch,828	 * indicator.  They will be needed for v4l2 registration.829	 */830	fset = &channel->intensity_uA;831	fset->min = le32_to_cpu(conf.intensity_min_uA);832	fset->max = le32_to_cpu(conf.intensity_max_uA);833	fset->step = le32_to_cpu(conf.intensity_step_uA);834 835	/*836	 * On flash type, max brightness is set as the number of intensity steps837	 * available.838	 */839	channel->led->max_brightness = (fset->max - fset->min) / fset->step;840 841	/* Only the flash mode have the timeout constraints settings */842	if (channel->mode & GB_CHANNEL_MODE_FLASH) {843		fset = &channel->timeout_us;844		fset->min = le32_to_cpu(conf.timeout_min_us);845		fset->max = le32_to_cpu(conf.timeout_max_us);846		fset->step = le32_to_cpu(conf.timeout_step_us);847	}848 849	return 0;850}851#else852static int gb_lights_channel_flash_config(struct gb_channel *channel)853{854	struct gb_connection *connection = get_conn_from_channel(channel);855 856	dev_err(&connection->bundle->dev, "no support for flash devices\n");857	return 0;858}859 860static int __gb_lights_flash_led_register(struct gb_channel *channel)861{862	return 0;863}864 865static void __gb_lights_flash_led_unregister(struct gb_channel *channel)866{867}868 869#endif870 871static int __gb_lights_led_register(struct gb_channel *channel)872{873	struct gb_connection *connection = get_conn_from_channel(channel);874	struct led_classdev *cdev = get_channel_cdev(channel);875	int ret;876 877	ret = led_classdev_register(&connection->bundle->dev, cdev);878	if (ret < 0)879		channel->led = NULL;880	else881		channel->is_registered = true;882	return ret;883}884 885static int gb_lights_channel_register(struct gb_channel *channel)886{887	/* Normal LED channel, just register in led classdev and we are done */888	if (!is_channel_flash(channel))889		return __gb_lights_led_register(channel);890 891	/*892	 * Flash Type need more work, register flash classdev, indicator as893	 * flash classdev, torch will be led classdev of the flash classdev.894	 */895	if (!(channel->mode & GB_CHANNEL_MODE_TORCH))896		return __gb_lights_flash_led_register(channel);897 898	return 0;899}900 901static void __gb_lights_led_unregister(struct gb_channel *channel)902{903	struct led_classdev *cdev = get_channel_cdev(channel);904 905	if (!channel->is_registered)906		return;907 908	led_classdev_unregister(cdev);909	kfree(cdev->name);910	cdev->name = NULL;911	channel->led = NULL;912}913 914static void gb_lights_channel_unregister(struct gb_channel *channel)915{916	/* The same as register, handle channels differently */917	if (!is_channel_flash(channel)) {918		__gb_lights_led_unregister(channel);919		return;920	}921 922	if (channel->mode & GB_CHANNEL_MODE_TORCH)923		__gb_lights_led_unregister(channel);924	else925		__gb_lights_flash_led_unregister(channel);926}927 928static int gb_lights_channel_config(struct gb_light *light,929				    struct gb_channel *channel)930{931	struct gb_lights_get_channel_config_response conf;932	struct gb_lights_get_channel_config_request req;933	struct gb_connection *connection = get_conn_from_light(light);934	struct led_classdev *cdev = get_channel_cdev(channel);935	char *name;936	int ret;937 938	req.light_id = light->id;939	req.channel_id = channel->id;940 941	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG,942				&req, sizeof(req), &conf, sizeof(conf));943	if (ret < 0)944		return ret;945 946	channel->light = light;947	channel->mode = le32_to_cpu(conf.mode);948	channel->flags = le32_to_cpu(conf.flags);949	channel->color = le32_to_cpu(conf.color);950	channel->color_name = kstrndup(conf.color_name, NAMES_MAX, GFP_KERNEL);951	if (!channel->color_name)952		return -ENOMEM;953	channel->mode_name = kstrndup(conf.mode_name, NAMES_MAX, GFP_KERNEL);954	if (!channel->mode_name)955		return -ENOMEM;956 957	channel->led = cdev;958 959	name = kasprintf(GFP_KERNEL, "%s:%s:%s", light->name,960			 channel->color_name, channel->mode_name);961	if (!name)962		return -ENOMEM;963 964	cdev->name = name;965 966	cdev->max_brightness = conf.max_brightness;967 968	ret = channel_attr_groups_set(channel, cdev);969	if (ret < 0)970		return ret;971 972	gb_lights_led_operations_set(channel, cdev);973 974	/*975	 * If it is not a flash related channel (flash, torch or indicator) we976	 * are done here. If not, continue and fetch flash related977	 * configurations.978	 */979	if (!is_channel_flash(channel))980		return ret;981 982	light->has_flash = true;983 984	return gb_lights_channel_flash_config(channel);985}986 987static int gb_lights_light_config(struct gb_lights *glights, u8 id)988{989	struct gb_light *light = &glights->lights[id];990	struct gb_lights_get_light_config_request req;991	struct gb_lights_get_light_config_response conf;992	int ret;993	int i;994 995	light->glights = glights;996	light->id = id;997 998	req.id = id;999 1000	ret = gb_operation_sync(glights->connection,1001				GB_LIGHTS_TYPE_GET_LIGHT_CONFIG,1002				&req, sizeof(req), &conf, sizeof(conf));1003	if (ret < 0)1004		return ret;1005 1006	if (!conf.channel_count)1007		return -EINVAL;1008	if (!strlen(conf.name))1009		return -EINVAL;1010 1011	light->channels_count = conf.channel_count;1012	light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL);1013	if (!light->name)1014		return -ENOMEM;1015	light->channels = kcalloc(light->channels_count,1016				  sizeof(struct gb_channel), GFP_KERNEL);1017	if (!light->channels)1018		return -ENOMEM;1019 1020	/* First we collect all the configurations for all channels */1021	for (i = 0; i < light->channels_count; i++) {1022		light->channels[i].id = i;1023		ret = gb_lights_channel_config(light, &light->channels[i]);1024		if (ret < 0)1025			return ret;1026	}1027 1028	return 0;1029}1030 1031static int gb_lights_light_register(struct gb_light *light)1032{1033	int ret;1034	int i;1035 1036	/*1037	 * Then, if everything went ok in getting configurations, we register1038	 * the classdev, flash classdev and v4l2 subsystem, if a flash device is1039	 * found.1040	 */1041	for (i = 0; i < light->channels_count; i++) {1042		ret = gb_lights_channel_register(&light->channels[i]);1043		if (ret < 0)1044			return ret;1045 1046		mutex_init(&light->channels[i].lock);1047	}1048 1049	light->ready = true;1050 1051	if (light->has_flash) {1052		ret = gb_lights_light_v4l2_register(light);1053		if (ret < 0) {1054			light->has_flash = false;1055			return ret;1056		}1057	}1058 1059	return 0;1060}1061 1062static void gb_lights_channel_free(struct gb_channel *channel)1063{1064	kfree(channel->attrs);1065	kfree(channel->attr_group);1066	kfree(channel->attr_groups);1067	kfree(channel->color_name);1068	kfree(channel->mode_name);1069	mutex_destroy(&channel->lock);1070}1071 1072static void gb_lights_channel_release(struct gb_channel *channel)1073{1074	channel->releasing = true;1075 1076	gb_lights_channel_unregister(channel);1077 1078	gb_lights_channel_free(channel);1079}1080 1081static void gb_lights_light_release(struct gb_light *light)1082{1083	int i;1084 1085	light->ready = false;1086 1087	if (light->has_flash)1088		gb_lights_light_v4l2_unregister(light);1089	light->has_flash = false;1090 1091	for (i = 0; i < light->channels_count; i++)1092		gb_lights_channel_release(&light->channels[i]);1093	light->channels_count = 0;1094 1095	kfree(light->channels);1096	light->channels = NULL;1097	kfree(light->name);1098	light->name = NULL;1099}1100 1101static void gb_lights_release(struct gb_lights *glights)1102{1103	int i;1104 1105	if (!glights)1106		return;1107 1108	mutex_lock(&glights->lights_lock);1109	if (!glights->lights)1110		goto free_glights;1111 1112	for (i = 0; i < glights->lights_count; i++)1113		gb_lights_light_release(&glights->lights[i]);1114 1115	kfree(glights->lights);1116 1117free_glights:1118	mutex_unlock(&glights->lights_lock);1119	mutex_destroy(&glights->lights_lock);1120	kfree(glights);1121}1122 1123static int gb_lights_get_count(struct gb_lights *glights)1124{1125	struct gb_lights_get_lights_response resp;1126	int ret;1127 1128	ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHTS,1129				NULL, 0, &resp, sizeof(resp));1130	if (ret < 0)1131		return ret;1132 1133	if (!resp.lights_count)1134		return -EINVAL;1135 1136	glights->lights_count = resp.lights_count;1137 1138	return 0;1139}1140 1141static int gb_lights_create_all(struct gb_lights *glights)1142{1143	struct gb_connection *connection = glights->connection;1144	int ret;1145	int i;1146 1147	mutex_lock(&glights->lights_lock);1148	ret = gb_lights_get_count(glights);1149	if (ret < 0)1150		goto out;1151 1152	glights->lights = kcalloc(glights->lights_count,1153				  sizeof(struct gb_light), GFP_KERNEL);1154	if (!glights->lights) {1155		ret = -ENOMEM;1156		goto out;1157	}1158 1159	for (i = 0; i < glights->lights_count; i++) {1160		ret = gb_lights_light_config(glights, i);1161		if (ret < 0) {1162			dev_err(&connection->bundle->dev,1163				"Fail to configure lights device\n");1164			goto out;1165		}1166	}1167 1168out:1169	mutex_unlock(&glights->lights_lock);1170	return ret;1171}1172 1173static int gb_lights_register_all(struct gb_lights *glights)1174{1175	struct gb_connection *connection = glights->connection;1176	int ret = 0;1177	int i;1178 1179	mutex_lock(&glights->lights_lock);1180	for (i = 0; i < glights->lights_count; i++) {1181		ret = gb_lights_light_register(&glights->lights[i]);1182		if (ret < 0) {1183			dev_err(&connection->bundle->dev,1184				"Fail to enable lights device\n");1185			break;1186		}1187	}1188 1189	mutex_unlock(&glights->lights_lock);1190	return ret;1191}1192 1193static int gb_lights_request_handler(struct gb_operation *op)1194{1195	struct gb_connection *connection = op->connection;1196	struct device *dev = &connection->bundle->dev;1197	struct gb_lights *glights = gb_connection_get_data(connection);1198	struct gb_light *light;1199	struct gb_message *request;1200	struct gb_lights_event_request *payload;1201	int ret =  0;1202	u8 light_id;1203	u8 event;1204 1205	if (op->type != GB_LIGHTS_TYPE_EVENT) {1206		dev_err(dev, "Unsupported unsolicited event: %u\n", op->type);1207		return -EINVAL;1208	}1209 1210	request = op->request;1211 1212	if (request->payload_size < sizeof(*payload)) {1213		dev_err(dev, "Wrong event size received (%zu < %zu)\n",1214			request->payload_size, sizeof(*payload));1215		return -EINVAL;1216	}1217 1218	payload = request->payload;1219	light_id = payload->light_id;1220 1221	if (light_id >= glights->lights_count ||1222	    !glights->lights[light_id].ready) {1223		dev_err(dev, "Event received for unconfigured light id: %d\n",1224			light_id);1225		return -EINVAL;1226	}1227 1228	event = payload->event;1229 1230	if (event & GB_LIGHTS_LIGHT_CONFIG) {1231		light = &glights->lights[light_id];1232 1233		mutex_lock(&glights->lights_lock);1234		gb_lights_light_release(light);1235		ret = gb_lights_light_config(glights, light_id);1236		if (!ret)1237			ret = gb_lights_light_register(light);1238		if (ret < 0)1239			gb_lights_light_release(light);1240		mutex_unlock(&glights->lights_lock);1241	}1242 1243	return ret;1244}1245 1246static int gb_lights_probe(struct gb_bundle *bundle,1247			   const struct greybus_bundle_id *id)1248{1249	struct greybus_descriptor_cport *cport_desc;1250	struct gb_connection *connection;1251	struct gb_lights *glights;1252	int ret;1253 1254	if (bundle->num_cports != 1)1255		return -ENODEV;1256 1257	cport_desc = &bundle->cport_desc[0];1258	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LIGHTS)1259		return -ENODEV;1260 1261	glights = kzalloc(sizeof(*glights), GFP_KERNEL);1262	if (!glights)1263		return -ENOMEM;1264 1265	mutex_init(&glights->lights_lock);1266 1267	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),1268					  gb_lights_request_handler);1269	if (IS_ERR(connection)) {1270		ret = PTR_ERR(connection);1271		goto out;1272	}1273 1274	glights->connection = connection;1275	gb_connection_set_data(connection, glights);1276 1277	greybus_set_drvdata(bundle, glights);1278 1279	/* We aren't ready to receive an incoming request yet */1280	ret = gb_connection_enable_tx(connection);1281	if (ret)1282		goto error_connection_destroy;1283 1284	/*1285	 * Setup all the lights devices over this connection, if anything goes1286	 * wrong tear down all lights1287	 */1288	ret = gb_lights_create_all(glights);1289	if (ret < 0)1290		goto error_connection_disable;1291 1292	/* We are ready to receive an incoming request now, enable RX as well */1293	ret = gb_connection_enable(connection);1294	if (ret)1295		goto error_connection_disable;1296 1297	/* Enable & register lights */1298	ret = gb_lights_register_all(glights);1299	if (ret < 0)1300		goto error_connection_disable;1301 1302	gb_pm_runtime_put_autosuspend(bundle);1303 1304	return 0;1305 1306error_connection_disable:1307	gb_connection_disable(connection);1308error_connection_destroy:1309	gb_connection_destroy(connection);1310out:1311	gb_lights_release(glights);1312	return ret;1313}1314 1315static void gb_lights_disconnect(struct gb_bundle *bundle)1316{1317	struct gb_lights *glights = greybus_get_drvdata(bundle);1318 1319	if (gb_pm_runtime_get_sync(bundle))1320		gb_pm_runtime_get_noresume(bundle);1321 1322	gb_connection_disable(glights->connection);1323	gb_connection_destroy(glights->connection);1324 1325	gb_lights_release(glights);1326}1327 1328static const struct greybus_bundle_id gb_lights_id_table[] = {1329	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) },1330	{ }1331};1332MODULE_DEVICE_TABLE(greybus, gb_lights_id_table);1333 1334static struct greybus_driver gb_lights_driver = {1335	.name		= "lights",1336	.probe		= gb_lights_probe,1337	.disconnect	= gb_lights_disconnect,1338	.id_table	= gb_lights_id_table,1339};1340module_greybus_driver(gb_lights_driver);1341 1342MODULE_DESCRIPTION("Greybus Lights protocol driver");1343MODULE_LICENSE("GPL v2");1344