Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: max77693: add support for V4L2 Flash sub-device

Add support for V4L2 Flash sub-device to the max77693 LED Flash class
driver. The support allows for V4L2 Flash sub-device to take the control
of the LED Flash class device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Bryan Wu <cooloney@gmail.com>

authored by

Jacek Anaszewski and committed by
Bryan Wu
0b380186 42bd6f59

+123 -6
+123 -6
drivers/leds/leds-max77693.c
··· 20 20 #include <linux/regmap.h> 21 21 #include <linux/slab.h> 22 22 #include <linux/workqueue.h> 23 + #include <media/v4l2-flash-led-class.h> 23 24 24 25 #define MODE_OFF 0 25 26 #define MODE_FLASH(a) (1 << (a)) ··· 63 62 struct led_classdev_flash fled_cdev; 64 63 /* assures led-triggers compatibility */ 65 64 struct work_struct work_brightness_set; 65 + /* V4L2 Flash device */ 66 + struct v4l2_flash *v4l2_flash; 66 67 67 68 /* brightness cache */ 68 69 unsigned int torch_brightness; ··· 630 627 } 631 628 632 629 static int max77693_led_parse_dt(struct max77693_led_device *led, 633 - struct max77693_led_config_data *cfg) 630 + struct max77693_led_config_data *cfg, 631 + struct device_node **sub_nodes) 634 632 { 635 633 struct device *dev = &led->pdev->dev; 636 634 struct max77693_sub_led *sub_leds = led->sub_leds; ··· 678 674 return -EINVAL; 679 675 } 680 676 677 + if (sub_nodes[fled_id]) { 678 + dev_err(dev, 679 + "Conflicting \"led-sources\" DT properties\n"); 680 + return -EINVAL; 681 + } 682 + 683 + sub_nodes[fled_id] = child_node; 681 684 sub_leds[fled_id].fled_id = fled_id; 682 685 683 686 cfg->label[fled_id] = ··· 797 786 } 798 787 799 788 static int max77693_led_get_configuration(struct max77693_led_device *led, 800 - struct max77693_led_config_data *cfg) 789 + struct max77693_led_config_data *cfg, 790 + struct device_node **sub_nodes) 801 791 { 802 792 int ret; 803 793 804 - ret = max77693_led_parse_dt(led, cfg); 794 + ret = max77693_led_parse_dt(led, cfg, sub_nodes); 805 795 if (ret < 0) 806 796 return ret; 807 797 ··· 850 838 setting->val = setting->max; 851 839 } 852 840 841 + #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 842 + 843 + static int max77693_led_external_strobe_set( 844 + struct v4l2_flash *v4l2_flash, 845 + bool enable) 846 + { 847 + struct max77693_sub_led *sub_led = 848 + flcdev_to_sub_led(v4l2_flash->fled_cdev); 849 + struct max77693_led_device *led = sub_led_to_led(sub_led); 850 + int fled_id = sub_led->fled_id; 851 + int ret; 852 + 853 + mutex_lock(&led->lock); 854 + 855 + if (enable) 856 + ret = max77693_add_mode(led, MODE_FLASH_EXTERNAL(fled_id)); 857 + else 858 + ret = max77693_clear_mode(led, MODE_FLASH_EXTERNAL(fled_id)); 859 + 860 + mutex_unlock(&led->lock); 861 + 862 + return ret; 863 + } 864 + 865 + static void max77693_init_v4l2_flash_config(struct max77693_sub_led *sub_led, 866 + struct max77693_led_config_data *led_cfg, 867 + struct v4l2_flash_config *v4l2_sd_cfg) 868 + { 869 + struct max77693_led_device *led = sub_led_to_led(sub_led); 870 + struct device *dev = &led->pdev->dev; 871 + struct max77693_dev *iodev = dev_get_drvdata(dev->parent); 872 + struct i2c_client *i2c = iodev->i2c; 873 + struct led_flash_setting *s; 874 + 875 + snprintf(v4l2_sd_cfg->dev_name, sizeof(v4l2_sd_cfg->dev_name), 876 + "%s %d-%04x", sub_led->fled_cdev.led_cdev.name, 877 + i2c_adapter_id(i2c->adapter), i2c->addr); 878 + 879 + s = &v4l2_sd_cfg->torch_intensity; 880 + s->min = TORCH_IOUT_MIN; 881 + s->max = sub_led->fled_cdev.led_cdev.max_brightness * TORCH_IOUT_STEP; 882 + s->step = TORCH_IOUT_STEP; 883 + s->val = s->max; 884 + 885 + /* Init flash faults config */ 886 + v4l2_sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE | 887 + LED_FAULT_SHORT_CIRCUIT | 888 + LED_FAULT_OVER_CURRENT; 889 + 890 + v4l2_sd_cfg->has_external_strobe = true; 891 + } 892 + 893 + static const struct v4l2_flash_ops v4l2_flash_ops = { 894 + .external_strobe_set = max77693_led_external_strobe_set, 895 + }; 896 + #else 897 + static inline void max77693_init_v4l2_flash_config( 898 + struct max77693_sub_led *sub_led, 899 + struct max77693_led_config_data *led_cfg, 900 + struct v4l2_flash_config *v4l2_sd_cfg) 901 + { 902 + } 903 + static const struct v4l2_flash_ops v4l2_flash_ops; 904 + #endif 905 + 853 906 static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led, 854 907 struct max77693_led_config_data *led_cfg) 855 908 { ··· 947 870 sub_led->flash_timeout = fled_cdev->timeout.val; 948 871 } 949 872 873 + static int max77693_register_led(struct max77693_sub_led *sub_led, 874 + struct max77693_led_config_data *led_cfg, 875 + struct device_node *sub_node) 876 + { 877 + struct max77693_led_device *led = sub_led_to_led(sub_led); 878 + struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev; 879 + struct device *dev = &led->pdev->dev; 880 + struct v4l2_flash_config v4l2_sd_cfg = {}; 881 + int ret; 882 + 883 + /* Register in the LED subsystem */ 884 + ret = led_classdev_flash_register(dev, fled_cdev); 885 + if (ret < 0) 886 + return ret; 887 + 888 + max77693_init_v4l2_flash_config(sub_led, led_cfg, &v4l2_sd_cfg); 889 + 890 + /* Register in the V4L2 subsystem. */ 891 + sub_led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL, 892 + &v4l2_flash_ops, &v4l2_sd_cfg); 893 + if (IS_ERR(sub_led->v4l2_flash)) { 894 + ret = PTR_ERR(sub_led->v4l2_flash); 895 + goto err_v4l2_flash_init; 896 + } 897 + 898 + return 0; 899 + 900 + err_v4l2_flash_init: 901 + led_classdev_flash_unregister(fled_cdev); 902 + return ret; 903 + } 904 + 950 905 static int max77693_led_probe(struct platform_device *pdev) 951 906 { 952 907 struct device *dev = &pdev->dev; 953 908 struct max77693_dev *iodev = dev_get_drvdata(dev->parent); 954 909 struct max77693_led_device *led; 955 910 struct max77693_sub_led *sub_leds; 911 + struct device_node *sub_nodes[2] = {}; 956 912 struct max77693_led_config_data led_cfg = {}; 957 913 int init_fled_cdev[2], i, ret; 958 914 ··· 999 889 sub_leds = led->sub_leds; 1000 890 1001 891 platform_set_drvdata(pdev, led); 1002 - ret = max77693_led_get_configuration(led, &led_cfg); 892 + ret = max77693_led_get_configuration(led, &led_cfg, sub_nodes); 1003 893 if (ret < 0) 1004 894 return ret; 1005 895 ··· 1021 911 /* Initialize LED Flash class device */ 1022 912 max77693_init_fled_cdev(&sub_leds[i], &led_cfg); 1023 913 1024 - /* Register LED Flash class device */ 1025 - ret = led_classdev_flash_register(dev, &sub_leds[i].fled_cdev); 914 + /* 915 + * Register LED Flash class device and corresponding 916 + * V4L2 Flash device. 917 + */ 918 + ret = max77693_register_led(&sub_leds[i], &led_cfg, 919 + sub_nodes[i]); 1026 920 if (ret < 0) { 1027 921 /* 1028 922 * At this moment FLED1 might have been already ··· 1045 931 /* It is possible than only FLED2 was to be registered */ 1046 932 if (!init_fled_cdev[FLED1]) 1047 933 goto err_register_led1; 934 + v4l2_flash_release(sub_leds[FLED1].v4l2_flash); 1048 935 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev); 1049 936 err_register_led1: 1050 937 mutex_destroy(&led->lock); ··· 1059 944 struct max77693_sub_led *sub_leds = led->sub_leds; 1060 945 1061 946 if (led->iout_joint || max77693_fled_used(led, FLED1)) { 947 + v4l2_flash_release(sub_leds[FLED1].v4l2_flash); 1062 948 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev); 1063 949 cancel_work_sync(&sub_leds[FLED1].work_brightness_set); 1064 950 } 1065 951 1066 952 if (!led->iout_joint && max77693_fled_used(led, FLED2)) { 953 + v4l2_flash_release(sub_leds[FLED2].v4l2_flash); 1067 954 led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev); 1068 955 cancel_work_sync(&sub_leds[FLED2].work_brightness_set); 1069 956 }