@@ -34,6 +34,11 @@ static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
3434 return cdev_to_lp55xx_led (dev_get_drvdata (dev ));
3535}
3636
37+ static struct lp55xx_led * mcled_cdev_to_led (struct led_classdev_mc * mc_cdev )
38+ {
39+ return container_of (mc_cdev , struct lp55xx_led , mc_cdev );
40+ }
41+
3742static void lp55xx_reset_device (struct lp55xx_chip * chip )
3843{
3944 struct lp55xx_device_config * cfg = chip -> cfg ;
@@ -129,6 +134,18 @@ static struct attribute *lp55xx_led_attrs[] = {
129134};
130135ATTRIBUTE_GROUPS (lp55xx_led );
131136
137+ static int lp55xx_set_mc_brightness (struct led_classdev * cdev ,
138+ enum led_brightness brightness )
139+ {
140+ struct led_classdev_mc * mc_dev = lcdev_to_mccdev (cdev );
141+ struct lp55xx_led * led = mcled_cdev_to_led (mc_dev );
142+ struct lp55xx_device_config * cfg = led -> chip -> cfg ;
143+
144+ led_mc_calc_color_components (& led -> mc_cdev , brightness );
145+ return cfg -> multicolor_brightness_fn (led );
146+
147+ }
148+
132149static int lp55xx_set_brightness (struct led_classdev * cdev ,
133150 enum led_brightness brightness )
134151{
@@ -145,9 +162,12 @@ static int lp55xx_init_led(struct lp55xx_led *led,
145162 struct lp55xx_platform_data * pdata = chip -> pdata ;
146163 struct lp55xx_device_config * cfg = chip -> cfg ;
147164 struct device * dev = & chip -> cl -> dev ;
165+ int max_channel = cfg -> max_channel ;
166+ struct mc_subled * mc_led_info ;
167+ struct led_classdev * led_cdev ;
148168 char name [32 ];
169+ int i , j = 0 ;
149170 int ret ;
150- int max_channel = cfg -> max_channel ;
151171
152172 if (chan >= max_channel ) {
153173 dev_err (dev , "invalid channel: %d / %d\n" , chan , max_channel );
@@ -157,29 +177,55 @@ static int lp55xx_init_led(struct lp55xx_led *led,
157177 if (pdata -> led_config [chan ].led_current == 0 )
158178 return 0 ;
159179
180+ if (pdata -> led_config [chan ].name ) {
181+ led -> cdev .name = pdata -> led_config [chan ].name ;
182+ } else {
183+ snprintf (name , sizeof (name ), "%s:channel%d" ,
184+ pdata -> label ? : chip -> cl -> name , chan );
185+ led -> cdev .name = name ;
186+ }
187+
188+ if (pdata -> led_config [chan ].num_colors > 1 ) {
189+ mc_led_info = devm_kcalloc (dev ,
190+ pdata -> led_config [chan ].num_colors ,
191+ sizeof (* mc_led_info ), GFP_KERNEL );
192+ if (!mc_led_info )
193+ return - ENOMEM ;
194+
195+ led_cdev = & led -> mc_cdev .led_cdev ;
196+ led_cdev -> name = led -> cdev .name ;
197+ led_cdev -> brightness_set_blocking = lp55xx_set_mc_brightness ;
198+ led -> mc_cdev .num_colors = pdata -> led_config [chan ].num_colors ;
199+ for (i = 0 ; i < led -> mc_cdev .num_colors ; i ++ ) {
200+ mc_led_info [i ].color_index =
201+ pdata -> led_config [chan ].color_id [i ];
202+ mc_led_info [i ].channel =
203+ pdata -> led_config [chan ].output_num [i ];
204+ j ++ ;
205+ }
206+
207+ led -> mc_cdev .subled_info = mc_led_info ;
208+ } else {
209+ led -> cdev .brightness_set_blocking = lp55xx_set_brightness ;
210+ }
211+
212+ led -> cdev .groups = lp55xx_led_groups ;
213+ led -> cdev .default_trigger = pdata -> led_config [chan ].default_trigger ;
160214 led -> led_current = pdata -> led_config [chan ].led_current ;
161215 led -> max_current = pdata -> led_config [chan ].max_current ;
162216 led -> chan_nr = pdata -> led_config [chan ].chan_nr ;
163- led -> cdev .default_trigger = pdata -> led_config [chan ].default_trigger ;
164217
165218 if (led -> chan_nr >= max_channel ) {
166219 dev_err (dev , "Use channel numbers between 0 and %d\n" ,
167220 max_channel - 1 );
168221 return - EINVAL ;
169222 }
170223
171- led -> cdev .brightness_set_blocking = lp55xx_set_brightness ;
172- led -> cdev .groups = lp55xx_led_groups ;
173-
174- if (pdata -> led_config [chan ].name ) {
175- led -> cdev .name = pdata -> led_config [chan ].name ;
176- } else {
177- snprintf (name , sizeof (name ), "%s:channel%d" ,
178- pdata -> label ? : chip -> cl -> name , chan );
179- led -> cdev .name = name ;
180- }
224+ if (pdata -> led_config [chan ].num_colors > 1 )
225+ ret = devm_led_classdev_multicolor_register (dev , & led -> mc_cdev );
226+ else
227+ ret = devm_led_classdev_register (dev , & led -> cdev );
181228
182- ret = devm_led_classdev_register (dev , & led -> cdev );
183229 if (ret ) {
184230 dev_err (dev , "led register err: %d\n" , ret );
185231 return ret ;
@@ -515,14 +561,105 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
515561}
516562EXPORT_SYMBOL_GPL (lp55xx_unregister_sysfs );
517563
564+ static int lp55xx_parse_common_child (struct device_node * np ,
565+ struct lp55xx_led_config * cfg ,
566+ int led_number , int * chan_nr )
567+ {
568+ int ret ;
569+
570+ of_property_read_string (np , "chan-name" ,
571+ & cfg [led_number ].name );
572+ of_property_read_u8 (np , "led-cur" ,
573+ & cfg [led_number ].led_current );
574+ of_property_read_u8 (np , "max-cur" ,
575+ & cfg [led_number ].max_current );
576+
577+ ret = of_property_read_u32 (np , "reg" , chan_nr );
578+ if (ret )
579+ return ret ;
580+
581+ if (* chan_nr < 0 || * chan_nr > cfg -> max_channel )
582+ return - EINVAL ;
583+
584+ return 0 ;
585+ }
586+
587+ static int lp55xx_parse_multi_led_child (struct device_node * child ,
588+ struct lp55xx_led_config * cfg ,
589+ int child_number , int color_number )
590+ {
591+ int chan_nr , color_id , ret ;
592+
593+ ret = lp55xx_parse_common_child (child , cfg , child_number , & chan_nr );
594+ if (ret )
595+ return ret ;
596+
597+ ret = of_property_read_u32 (child , "color" , & color_id );
598+ if (ret )
599+ return ret ;
600+
601+ cfg [child_number ].color_id [color_number ] = color_id ;
602+ cfg [child_number ].output_num [color_number ] = chan_nr ;
603+
604+ return 0 ;
605+ }
606+
607+ static int lp55xx_parse_multi_led (struct device_node * np ,
608+ struct lp55xx_led_config * cfg ,
609+ int child_number )
610+ {
611+ struct device_node * child ;
612+ int num_colors = 0 , ret ;
613+
614+ for_each_child_of_node (np , child ) {
615+ ret = lp55xx_parse_multi_led_child (child , cfg , child_number ,
616+ num_colors );
617+ if (ret )
618+ return ret ;
619+ num_colors ++ ;
620+ }
621+
622+ cfg [child_number ].num_colors = num_colors ;
623+
624+ return 0 ;
625+ }
626+
627+ static int lp55xx_parse_logical_led (struct device_node * np ,
628+ struct lp55xx_led_config * cfg ,
629+ int child_number )
630+ {
631+ int led_color , ret ;
632+ int chan_nr = 0 ;
633+
634+ cfg [child_number ].default_trigger =
635+ of_get_property (np , "linux,default-trigger" , NULL );
636+
637+ ret = of_property_read_u32 (np , "color" , & led_color );
638+ if (ret )
639+ return ret ;
640+
641+ if (led_color == LED_COLOR_ID_MULTI )
642+ return lp55xx_parse_multi_led (np , cfg , child_number );
643+
644+ ret = lp55xx_parse_common_child (np , cfg , child_number , & chan_nr );
645+ if (ret < 0 )
646+ return ret ;
647+
648+ cfg [child_number ].chan_nr = chan_nr ;
649+
650+ return ret ;
651+ }
652+
518653struct lp55xx_platform_data * lp55xx_of_populate_pdata (struct device * dev ,
519- struct device_node * np )
654+ struct device_node * np ,
655+ struct lp55xx_chip * chip )
520656{
521657 struct device_node * child ;
522658 struct lp55xx_platform_data * pdata ;
523659 struct lp55xx_led_config * cfg ;
524660 int num_channels ;
525661 int i = 0 ;
662+ int ret ;
526663
527664 pdata = devm_kzalloc (dev , sizeof (* pdata ), GFP_KERNEL );
528665 if (!pdata )
@@ -540,16 +677,12 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
540677
541678 pdata -> led_config = & cfg [0 ];
542679 pdata -> num_channels = num_channels ;
680+ cfg -> max_channel = chip -> cfg -> max_channel ;
543681
544682 for_each_child_of_node (np , child ) {
545- cfg [i ].chan_nr = i ;
546-
547- of_property_read_string (child , "chan-name" , & cfg [i ].name );
548- of_property_read_u8 (child , "led-cur" , & cfg [i ].led_current );
549- of_property_read_u8 (child , "max-cur" , & cfg [i ].max_current );
550- cfg [i ].default_trigger =
551- of_get_property (child , "linux,default-trigger" , NULL );
552-
683+ ret = lp55xx_parse_logical_led (child , cfg , i );
684+ if (ret )
685+ return ERR_PTR (- EINVAL );
553686 i ++ ;
554687 }
555688
0 commit comments