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