xref: /openbmc/linux/drivers/video/backlight/pwm_bl.c (revision 22d55f02)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * linux/drivers/video/backlight/pwm_bl.c
4  *
5  * simple PWM based backlight control, board code has to setup
6  * 1) pin configuration so PWM waveforms can output
7  * 2) platform_data being correctly configured
8  */
9 
10 #include <linux/delay.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/gpio.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/platform_device.h>
17 #include <linux/fb.h>
18 #include <linux/backlight.h>
19 #include <linux/err.h>
20 #include <linux/pwm.h>
21 #include <linux/pwm_backlight.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/slab.h>
24 
25 struct pwm_bl_data {
26 	struct pwm_device	*pwm;
27 	struct device		*dev;
28 	unsigned int		lth_brightness;
29 	unsigned int		*levels;
30 	bool			enabled;
31 	struct regulator	*power_supply;
32 	struct gpio_desc	*enable_gpio;
33 	unsigned int		scale;
34 	bool			legacy;
35 	unsigned int		post_pwm_on_delay;
36 	unsigned int		pwm_off_delay;
37 	int			(*notify)(struct device *,
38 					  int brightness);
39 	void			(*notify_after)(struct device *,
40 					int brightness);
41 	int			(*check_fb)(struct device *, struct fb_info *);
42 	void			(*exit)(struct device *);
43 };
44 
45 static void pwm_backlight_power_on(struct pwm_bl_data *pb)
46 {
47 	struct pwm_state state;
48 	int err;
49 
50 	pwm_get_state(pb->pwm, &state);
51 	if (pb->enabled)
52 		return;
53 
54 	err = regulator_enable(pb->power_supply);
55 	if (err < 0)
56 		dev_err(pb->dev, "failed to enable power supply\n");
57 
58 	state.enabled = true;
59 	pwm_apply_state(pb->pwm, &state);
60 
61 	if (pb->post_pwm_on_delay)
62 		msleep(pb->post_pwm_on_delay);
63 
64 	if (pb->enable_gpio)
65 		gpiod_set_value_cansleep(pb->enable_gpio, 1);
66 
67 	pb->enabled = true;
68 }
69 
70 static void pwm_backlight_power_off(struct pwm_bl_data *pb)
71 {
72 	struct pwm_state state;
73 
74 	pwm_get_state(pb->pwm, &state);
75 	if (!pb->enabled)
76 		return;
77 
78 	if (pb->enable_gpio)
79 		gpiod_set_value_cansleep(pb->enable_gpio, 0);
80 
81 	if (pb->pwm_off_delay)
82 		msleep(pb->pwm_off_delay);
83 
84 	state.enabled = false;
85 	state.duty_cycle = 0;
86 	pwm_apply_state(pb->pwm, &state);
87 
88 	regulator_disable(pb->power_supply);
89 	pb->enabled = false;
90 }
91 
92 static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
93 {
94 	unsigned int lth = pb->lth_brightness;
95 	struct pwm_state state;
96 	u64 duty_cycle;
97 
98 	pwm_get_state(pb->pwm, &state);
99 
100 	if (pb->levels)
101 		duty_cycle = pb->levels[brightness];
102 	else
103 		duty_cycle = brightness;
104 
105 	duty_cycle *= state.period - lth;
106 	do_div(duty_cycle, pb->scale);
107 
108 	return duty_cycle + lth;
109 }
110 
111 static int pwm_backlight_update_status(struct backlight_device *bl)
112 {
113 	struct pwm_bl_data *pb = bl_get_data(bl);
114 	int brightness = bl->props.brightness;
115 	struct pwm_state state;
116 
117 	if (bl->props.power != FB_BLANK_UNBLANK ||
118 	    bl->props.fb_blank != FB_BLANK_UNBLANK ||
119 	    bl->props.state & BL_CORE_FBBLANK)
120 		brightness = 0;
121 
122 	if (pb->notify)
123 		brightness = pb->notify(pb->dev, brightness);
124 
125 	if (brightness > 0) {
126 		pwm_get_state(pb->pwm, &state);
127 		state.duty_cycle = compute_duty_cycle(pb, brightness);
128 		pwm_apply_state(pb->pwm, &state);
129 		pwm_backlight_power_on(pb);
130 	} else
131 		pwm_backlight_power_off(pb);
132 
133 	if (pb->notify_after)
134 		pb->notify_after(pb->dev, brightness);
135 
136 	return 0;
137 }
138 
139 static int pwm_backlight_check_fb(struct backlight_device *bl,
140 				  struct fb_info *info)
141 {
142 	struct pwm_bl_data *pb = bl_get_data(bl);
143 
144 	return !pb->check_fb || pb->check_fb(pb->dev, info);
145 }
146 
147 static const struct backlight_ops pwm_backlight_ops = {
148 	.update_status	= pwm_backlight_update_status,
149 	.check_fb	= pwm_backlight_check_fb,
150 };
151 
152 #ifdef CONFIG_OF
153 #define PWM_LUMINANCE_SCALE	10000 /* luminance scale */
154 
155 /*
156  * CIE lightness to PWM conversion.
157  *
158  * The CIE 1931 lightness formula is what actually describes how we perceive
159  * light:
160  *          Y = (L* / 902.3)           if L* ≤ 0.08856
161  *          Y = ((L* + 16) / 116)^3    if L* > 0.08856
162  *
163  * Where Y is the luminance, the amount of light coming out of the screen, and
164  * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
165  * perceives the screen to be, and is a number between 0 and 100.
166  *
167  * The following function does the fixed point maths needed to implement the
168  * above formula.
169  */
170 static u64 cie1931(unsigned int lightness, unsigned int scale)
171 {
172 	u64 retval;
173 
174 	lightness *= 100;
175 	if (lightness <= (8 * scale)) {
176 		retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
177 	} else {
178 		retval = int_pow((lightness + (16 * scale)) / 116, 3);
179 		retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
180 	}
181 
182 	return retval;
183 }
184 
185 /*
186  * Create a default correction table for PWM values to create linear brightness
187  * for LED based backlights using the CIE1931 algorithm.
188  */
189 static
190 int pwm_backlight_brightness_default(struct device *dev,
191 				     struct platform_pwm_backlight_data *data,
192 				     unsigned int period)
193 {
194 	unsigned int counter = 0;
195 	unsigned int i, n;
196 	u64 retval;
197 
198 	/*
199 	 * Count the number of bits needed to represent the period number. The
200 	 * number of bits is used to calculate the number of levels used for the
201 	 * brightness-levels table, the purpose of this calculation is have a
202 	 * pre-computed table with enough levels to get linear brightness
203 	 * perception. The period is divided by the number of bits so for a
204 	 * 8-bit PWM we have 255 / 8 = 32 brightness levels or for a 16-bit PWM
205 	 * we have 65535 / 16 = 4096 brightness levels.
206 	 *
207 	 * Note that this method is based on empirical testing on different
208 	 * devices with PWM of 8 and 16 bits of resolution.
209 	 */
210 	n = period;
211 	while (n) {
212 		counter += n % 2;
213 		n >>= 1;
214 	}
215 
216 	data->max_brightness = DIV_ROUND_UP(period, counter);
217 	data->levels = devm_kcalloc(dev, data->max_brightness,
218 				    sizeof(*data->levels), GFP_KERNEL);
219 	if (!data->levels)
220 		return -ENOMEM;
221 
222 	/* Fill the table using the cie1931 algorithm */
223 	for (i = 0; i < data->max_brightness; i++) {
224 		retval = cie1931((i * PWM_LUMINANCE_SCALE) /
225 				 data->max_brightness, PWM_LUMINANCE_SCALE) *
226 				 period;
227 		retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
228 		if (retval > UINT_MAX)
229 			return -EINVAL;
230 		data->levels[i] = (unsigned int)retval;
231 	}
232 
233 	data->dft_brightness = data->max_brightness / 2;
234 	data->max_brightness--;
235 
236 	return 0;
237 }
238 
239 static int pwm_backlight_parse_dt(struct device *dev,
240 				  struct platform_pwm_backlight_data *data)
241 {
242 	struct device_node *node = dev->of_node;
243 	unsigned int num_levels = 0;
244 	unsigned int levels_count;
245 	unsigned int num_steps = 0;
246 	struct property *prop;
247 	unsigned int *table;
248 	int length;
249 	u32 value;
250 	int ret;
251 
252 	if (!node)
253 		return -ENODEV;
254 
255 	memset(data, 0, sizeof(*data));
256 
257 	/*
258 	 * These values are optional and set as 0 by default, the out values
259 	 * are modified only if a valid u32 value can be decoded.
260 	 */
261 	of_property_read_u32(node, "post-pwm-on-delay-ms",
262 			     &data->post_pwm_on_delay);
263 	of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
264 
265 	data->enable_gpio = -EINVAL;
266 
267 	/*
268 	 * Determine the number of brightness levels, if this property is not
269 	 * set a default table of brightness levels will be used.
270 	 */
271 	prop = of_find_property(node, "brightness-levels", &length);
272 	if (!prop)
273 		return 0;
274 
275 	data->max_brightness = length / sizeof(u32);
276 
277 	/* read brightness levels from DT property */
278 	if (data->max_brightness > 0) {
279 		size_t size = sizeof(*data->levels) * data->max_brightness;
280 		unsigned int i, j, n = 0;
281 
282 		data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
283 		if (!data->levels)
284 			return -ENOMEM;
285 
286 		ret = of_property_read_u32_array(node, "brightness-levels",
287 						 data->levels,
288 						 data->max_brightness);
289 		if (ret < 0)
290 			return ret;
291 
292 		ret = of_property_read_u32(node, "default-brightness-level",
293 					   &value);
294 		if (ret < 0)
295 			return ret;
296 
297 		data->dft_brightness = value;
298 
299 		/*
300 		 * This property is optional, if is set enables linear
301 		 * interpolation between each of the values of brightness levels
302 		 * and creates a new pre-computed table.
303 		 */
304 		of_property_read_u32(node, "num-interpolated-steps",
305 				     &num_steps);
306 
307 		/*
308 		 * Make sure that there is at least two entries in the
309 		 * brightness-levels table, otherwise we can't interpolate
310 		 * between two points.
311 		 */
312 		if (num_steps) {
313 			if (data->max_brightness < 2) {
314 				dev_err(dev, "can't interpolate\n");
315 				return -EINVAL;
316 			}
317 
318 			/*
319 			 * Recalculate the number of brightness levels, now
320 			 * taking in consideration the number of interpolated
321 			 * steps between two levels.
322 			 */
323 			for (i = 0; i < data->max_brightness - 1; i++) {
324 				if ((data->levels[i + 1] - data->levels[i]) /
325 				   num_steps)
326 					num_levels += num_steps;
327 				else
328 					num_levels++;
329 			}
330 			num_levels++;
331 			dev_dbg(dev, "new number of brightness levels: %d\n",
332 				num_levels);
333 
334 			/*
335 			 * Create a new table of brightness levels with all the
336 			 * interpolated steps.
337 			 */
338 			size = sizeof(*table) * num_levels;
339 			table = devm_kzalloc(dev, size, GFP_KERNEL);
340 			if (!table)
341 				return -ENOMEM;
342 
343 			/* Fill the interpolated table. */
344 			levels_count = 0;
345 			for (i = 0; i < data->max_brightness - 1; i++) {
346 				value = data->levels[i];
347 				n = (data->levels[i + 1] - value) / num_steps;
348 				if (n > 0) {
349 					for (j = 0; j < num_steps; j++) {
350 						table[levels_count] = value;
351 						value += n;
352 						levels_count++;
353 					}
354 				} else {
355 					table[levels_count] = data->levels[i];
356 					levels_count++;
357 				}
358 			}
359 			table[levels_count] = data->levels[i];
360 
361 			/*
362 			 * As we use interpolation lets remove current
363 			 * brightness levels table and replace for the
364 			 * new interpolated table.
365 			 */
366 			devm_kfree(dev, data->levels);
367 			data->levels = table;
368 
369 			/*
370 			 * Reassign max_brightness value to the new total number
371 			 * of brightness levels.
372 			 */
373 			data->max_brightness = num_levels;
374 		}
375 
376 		data->max_brightness--;
377 	}
378 
379 	return 0;
380 }
381 
382 static const struct of_device_id pwm_backlight_of_match[] = {
383 	{ .compatible = "pwm-backlight" },
384 	{ }
385 };
386 
387 MODULE_DEVICE_TABLE(of, pwm_backlight_of_match);
388 #else
389 static int pwm_backlight_parse_dt(struct device *dev,
390 				  struct platform_pwm_backlight_data *data)
391 {
392 	return -ENODEV;
393 }
394 
395 static
396 int pwm_backlight_brightness_default(struct device *dev,
397 				     struct platform_pwm_backlight_data *data,
398 				     unsigned int period)
399 {
400 	return -ENODEV;
401 }
402 #endif
403 
404 static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
405 {
406 	struct device_node *node = pb->dev->of_node;
407 
408 	/* Not booted with device tree or no phandle link to the node */
409 	if (!node || !node->phandle)
410 		return FB_BLANK_UNBLANK;
411 
412 	/*
413 	 * If the driver is probed from the device tree and there is a
414 	 * phandle link pointing to the backlight node, it is safe to
415 	 * assume that another driver will enable the backlight at the
416 	 * appropriate time. Therefore, if it is disabled, keep it so.
417 	 */
418 
419 	/* if the enable GPIO is disabled, do not enable the backlight */
420 	if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
421 		return FB_BLANK_POWERDOWN;
422 
423 	/* The regulator is disabled, do not enable the backlight */
424 	if (!regulator_is_enabled(pb->power_supply))
425 		return FB_BLANK_POWERDOWN;
426 
427 	/* The PWM is disabled, keep it like this */
428 	if (!pwm_is_enabled(pb->pwm))
429 		return FB_BLANK_POWERDOWN;
430 
431 	return FB_BLANK_UNBLANK;
432 }
433 
434 static int pwm_backlight_probe(struct platform_device *pdev)
435 {
436 	struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
437 	struct platform_pwm_backlight_data defdata;
438 	struct backlight_properties props;
439 	struct backlight_device *bl;
440 	struct device_node *node = pdev->dev.of_node;
441 	struct pwm_bl_data *pb;
442 	struct pwm_state state;
443 	unsigned int i;
444 	int ret;
445 
446 	if (!data) {
447 		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
448 		if (ret < 0) {
449 			dev_err(&pdev->dev, "failed to find platform data\n");
450 			return ret;
451 		}
452 
453 		data = &defdata;
454 	}
455 
456 	if (data->init) {
457 		ret = data->init(&pdev->dev);
458 		if (ret < 0)
459 			return ret;
460 	}
461 
462 	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
463 	if (!pb) {
464 		ret = -ENOMEM;
465 		goto err_alloc;
466 	}
467 
468 	pb->notify = data->notify;
469 	pb->notify_after = data->notify_after;
470 	pb->check_fb = data->check_fb;
471 	pb->exit = data->exit;
472 	pb->dev = &pdev->dev;
473 	pb->enabled = false;
474 	pb->post_pwm_on_delay = data->post_pwm_on_delay;
475 	pb->pwm_off_delay = data->pwm_off_delay;
476 
477 	pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
478 						  GPIOD_ASIS);
479 	if (IS_ERR(pb->enable_gpio)) {
480 		ret = PTR_ERR(pb->enable_gpio);
481 		goto err_alloc;
482 	}
483 
484 	/*
485 	 * Compatibility fallback for drivers still using the integer GPIO
486 	 * platform data. Must go away soon.
487 	 */
488 	if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) {
489 		ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio,
490 					    GPIOF_OUT_INIT_HIGH, "enable");
491 		if (ret < 0) {
492 			dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
493 				data->enable_gpio, ret);
494 			goto err_alloc;
495 		}
496 
497 		pb->enable_gpio = gpio_to_desc(data->enable_gpio);
498 	}
499 
500 	/*
501 	 * If the GPIO is not known to be already configured as output, that
502 	 * is, if gpiod_get_direction returns either 1 or -EINVAL, change the
503 	 * direction to output and set the GPIO as active.
504 	 * Do not force the GPIO to active when it was already output as it
505 	 * could cause backlight flickering or we would enable the backlight too
506 	 * early. Leave the decision of the initial backlight state for later.
507 	 */
508 	if (pb->enable_gpio &&
509 	    gpiod_get_direction(pb->enable_gpio) != 0)
510 		gpiod_direction_output(pb->enable_gpio, 1);
511 
512 	pb->power_supply = devm_regulator_get(&pdev->dev, "power");
513 	if (IS_ERR(pb->power_supply)) {
514 		ret = PTR_ERR(pb->power_supply);
515 		goto err_alloc;
516 	}
517 
518 	pb->pwm = devm_pwm_get(&pdev->dev, NULL);
519 	if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {
520 		dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
521 		pb->legacy = true;
522 		pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
523 	}
524 
525 	if (IS_ERR(pb->pwm)) {
526 		ret = PTR_ERR(pb->pwm);
527 		if (ret != -EPROBE_DEFER)
528 			dev_err(&pdev->dev, "unable to request PWM\n");
529 		goto err_alloc;
530 	}
531 
532 	dev_dbg(&pdev->dev, "got pwm for backlight\n");
533 
534 	/* Sync up PWM state. */
535 	pwm_init_state(pb->pwm, &state);
536 
537 	/*
538 	 * The DT case will set the pwm_period_ns field to 0 and store the
539 	 * period, parsed from the DT, in the PWM device. For the non-DT case,
540 	 * set the period from platform data if it has not already been set
541 	 * via the PWM lookup table.
542 	 */
543 	if (!state.period && (data->pwm_period_ns > 0))
544 		state.period = data->pwm_period_ns;
545 
546 	ret = pwm_apply_state(pb->pwm, &state);
547 	if (ret) {
548 		dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
549 			ret);
550 		goto err_alloc;
551 	}
552 
553 	if (data->levels) {
554 		/*
555 		 * For the DT case, only when brightness levels is defined
556 		 * data->levels is filled. For the non-DT case, data->levels
557 		 * can come from platform data, however is not usual.
558 		 */
559 		for (i = 0; i <= data->max_brightness; i++) {
560 			if (data->levels[i] > pb->scale)
561 				pb->scale = data->levels[i];
562 
563 			pb->levels = data->levels;
564 		}
565 	} else if (!data->max_brightness) {
566 		/*
567 		 * If no brightness levels are provided and max_brightness is
568 		 * not set, use the default brightness table. For the DT case,
569 		 * max_brightness is set to 0 when brightness levels is not
570 		 * specified. For the non-DT case, max_brightness is usually
571 		 * set to some value.
572 		 */
573 
574 		/* Get the PWM period (in nanoseconds) */
575 		pwm_get_state(pb->pwm, &state);
576 
577 		ret = pwm_backlight_brightness_default(&pdev->dev, data,
578 						       state.period);
579 		if (ret < 0) {
580 			dev_err(&pdev->dev,
581 				"failed to setup default brightness table\n");
582 			goto err_alloc;
583 		}
584 
585 		for (i = 0; i <= data->max_brightness; i++) {
586 			if (data->levels[i] > pb->scale)
587 				pb->scale = data->levels[i];
588 
589 			pb->levels = data->levels;
590 		}
591 	} else {
592 		/*
593 		 * That only happens for the non-DT case, where platform data
594 		 * sets the max_brightness value.
595 		 */
596 		pb->scale = data->max_brightness;
597 	}
598 
599 	pb->lth_brightness = data->lth_brightness * (state.period / pb->scale);
600 
601 	memset(&props, 0, sizeof(struct backlight_properties));
602 	props.type = BACKLIGHT_RAW;
603 	props.max_brightness = data->max_brightness;
604 	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
605 				       &pwm_backlight_ops, &props);
606 	if (IS_ERR(bl)) {
607 		dev_err(&pdev->dev, "failed to register backlight\n");
608 		ret = PTR_ERR(bl);
609 		if (pb->legacy)
610 			pwm_free(pb->pwm);
611 		goto err_alloc;
612 	}
613 
614 	if (data->dft_brightness > data->max_brightness) {
615 		dev_warn(&pdev->dev,
616 			 "invalid default brightness level: %u, using %u\n",
617 			 data->dft_brightness, data->max_brightness);
618 		data->dft_brightness = data->max_brightness;
619 	}
620 
621 	bl->props.brightness = data->dft_brightness;
622 	bl->props.power = pwm_backlight_initial_power_state(pb);
623 	backlight_update_status(bl);
624 
625 	platform_set_drvdata(pdev, bl);
626 	return 0;
627 
628 err_alloc:
629 	if (data->exit)
630 		data->exit(&pdev->dev);
631 	return ret;
632 }
633 
634 static int pwm_backlight_remove(struct platform_device *pdev)
635 {
636 	struct backlight_device *bl = platform_get_drvdata(pdev);
637 	struct pwm_bl_data *pb = bl_get_data(bl);
638 
639 	backlight_device_unregister(bl);
640 	pwm_backlight_power_off(pb);
641 
642 	if (pb->exit)
643 		pb->exit(&pdev->dev);
644 	if (pb->legacy)
645 		pwm_free(pb->pwm);
646 
647 	return 0;
648 }
649 
650 static void pwm_backlight_shutdown(struct platform_device *pdev)
651 {
652 	struct backlight_device *bl = platform_get_drvdata(pdev);
653 	struct pwm_bl_data *pb = bl_get_data(bl);
654 
655 	pwm_backlight_power_off(pb);
656 }
657 
658 #ifdef CONFIG_PM_SLEEP
659 static int pwm_backlight_suspend(struct device *dev)
660 {
661 	struct backlight_device *bl = dev_get_drvdata(dev);
662 	struct pwm_bl_data *pb = bl_get_data(bl);
663 
664 	if (pb->notify)
665 		pb->notify(pb->dev, 0);
666 
667 	pwm_backlight_power_off(pb);
668 
669 	if (pb->notify_after)
670 		pb->notify_after(pb->dev, 0);
671 
672 	return 0;
673 }
674 
675 static int pwm_backlight_resume(struct device *dev)
676 {
677 	struct backlight_device *bl = dev_get_drvdata(dev);
678 
679 	backlight_update_status(bl);
680 
681 	return 0;
682 }
683 #endif
684 
685 static const struct dev_pm_ops pwm_backlight_pm_ops = {
686 #ifdef CONFIG_PM_SLEEP
687 	.suspend = pwm_backlight_suspend,
688 	.resume = pwm_backlight_resume,
689 	.poweroff = pwm_backlight_suspend,
690 	.restore = pwm_backlight_resume,
691 #endif
692 };
693 
694 static struct platform_driver pwm_backlight_driver = {
695 	.driver		= {
696 		.name		= "pwm-backlight",
697 		.pm		= &pwm_backlight_pm_ops,
698 		.of_match_table	= of_match_ptr(pwm_backlight_of_match),
699 	},
700 	.probe		= pwm_backlight_probe,
701 	.remove		= pwm_backlight_remove,
702 	.shutdown	= pwm_backlight_shutdown,
703 };
704 
705 module_platform_driver(pwm_backlight_driver);
706 
707 MODULE_DESCRIPTION("PWM based Backlight Driver");
708 MODULE_LICENSE("GPL");
709 MODULE_ALIAS("platform:pwm-backlight");
710