pwm_bl.c 17.3 KB
Newer Older
1 2 3 4 5
/*
 * linux/drivers/video/backlight/pwm_bl.c
 *
 * simple PWM based backlight control, board code has to setup
 * 1) pin configuration so PWM waveforms can output
6
 * 2) platform_data being correctly configured
7 8 9 10 11 12
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

13
#include <linux/delay.h>
14
#include <linux/gpio/consumer.h>
15
#include <linux/gpio.h>
16 17 18 19 20 21 22 23 24
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
25
#include <linux/regulator/consumer.h>
26
#include <linux/slab.h>
27 28 29

struct pwm_bl_data {
	struct pwm_device	*pwm;
30
	struct device		*dev;
31
	unsigned int		period;
32
	unsigned int		lth_brightness;
33
	unsigned int		*levels;
T
Thierry Reding 已提交
34
	bool			enabled;
35
	struct regulator	*power_supply;
36
	struct gpio_desc	*enable_gpio;
37
	unsigned int		scale;
38
	bool			legacy;
39 40
	unsigned int		post_pwm_on_delay;
	unsigned int		pwm_off_delay;
41 42
	int			(*notify)(struct device *,
					  int brightness);
43 44
	void			(*notify_after)(struct device *,
					int brightness);
45
	int			(*check_fb)(struct device *, struct fb_info *);
46
	void			(*exit)(struct device *);
47 48
};

49
static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
50
{
51
	int err;
52

T
Thierry Reding 已提交
53 54 55
	if (pb->enabled)
		return;

56 57 58 59
	err = regulator_enable(pb->power_supply);
	if (err < 0)
		dev_err(pb->dev, "failed to enable power supply\n");

60 61
	pwm_enable(pb->pwm);

62 63 64
	if (pb->post_pwm_on_delay)
		msleep(pb->post_pwm_on_delay);

65
	if (pb->enable_gpio)
66
		gpiod_set_value_cansleep(pb->enable_gpio, 1);
67

T
Thierry Reding 已提交
68
	pb->enabled = true;
69 70 71 72
}

static void pwm_backlight_power_off(struct pwm_bl_data *pb)
{
T
Thierry Reding 已提交
73 74 75
	if (!pb->enabled)
		return;

76
	if (pb->enable_gpio)
77
		gpiod_set_value_cansleep(pb->enable_gpio, 0);
78

79 80 81
	if (pb->pwm_off_delay)
		msleep(pb->pwm_off_delay);

82 83 84
	pwm_config(pb->pwm, 0, pb->period);
	pwm_disable(pb->pwm);

85
	regulator_disable(pb->power_supply);
T
Thierry Reding 已提交
86
	pb->enabled = false;
87 88
}

89 90 91
static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
{
	unsigned int lth = pb->lth_brightness;
92
	u64 duty_cycle;
93 94 95 96 97 98

	if (pb->levels)
		duty_cycle = pb->levels[brightness];
	else
		duty_cycle = brightness;

99 100 101 102
	duty_cycle *= pb->period - lth;
	do_div(duty_cycle, pb->scale);

	return duty_cycle + lth;
103 104
}

105 106
static int pwm_backlight_update_status(struct backlight_device *bl)
{
107
	struct pwm_bl_data *pb = bl_get_data(bl);
108
	int brightness = bl->props.brightness;
109
	int duty_cycle;
110

111 112 113
	if (bl->props.power != FB_BLANK_UNBLANK ||
	    bl->props.fb_blank != FB_BLANK_UNBLANK ||
	    bl->props.state & BL_CORE_FBBLANK)
114 115
		brightness = 0;

116
	if (pb->notify)
117
		brightness = pb->notify(pb->dev, brightness);
118

119 120
	if (brightness > 0) {
		duty_cycle = compute_duty_cycle(pb, brightness);
121
		pwm_config(pb->pwm, duty_cycle, pb->period);
122
		pwm_backlight_power_on(pb, brightness);
123
	} else
124
		pwm_backlight_power_off(pb);
125 126 127 128

	if (pb->notify_after)
		pb->notify_after(pb->dev, brightness);

129 130 131
	return 0;
}

132 133 134
static int pwm_backlight_check_fb(struct backlight_device *bl,
				  struct fb_info *info)
{
135
	struct pwm_bl_data *pb = bl_get_data(bl);
136 137 138 139

	return !pb->check_fb || pb->check_fb(pb->dev, info);
}

140
static const struct backlight_ops pwm_backlight_ops = {
141
	.update_status	= pwm_backlight_update_status,
142
	.check_fb	= pwm_backlight_check_fb,
143 144
};

145
#ifdef CONFIG_OF
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
#define PWM_LUMINANCE_SCALE	10000 /* luminance scale */

/* An integer based power function */
static u64 int_pow(u64 base, int exp)
{
	u64 result = 1;

	while (exp) {
		if (exp & 1)
			result *= base;
		exp >>= 1;
		base *= base;
	}

	return result;
}

/*
 * CIE lightness to PWM conversion.
 *
 * The CIE 1931 lightness formula is what actually describes how we perceive
 * light:
 *          Y = (L* / 902.3)           if L* ≤ 0.08856
 *          Y = ((L* + 16) / 116)^3    if L* > 0.08856
 *
 * Where Y is the luminance, the amount of light coming out of the screen, and
 * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
 * perceives the screen to be, and is a number between 0 and 100.
 *
 * The following function does the fixed point maths needed to implement the
 * above formula.
 */
static u64 cie1931(unsigned int lightness, unsigned int scale)
{
	u64 retval;

	lightness *= 100;
	if (lightness <= (8 * scale)) {
		retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
	} else {
		retval = int_pow((lightness + (16 * scale)) / 116, 3);
		retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
	}

	return retval;
}

/*
 * Create a default correction table for PWM values to create linear brightness
 * for LED based backlights using the CIE1931 algorithm.
 */
static
int pwm_backlight_brightness_default(struct device *dev,
				     struct platform_pwm_backlight_data *data,
				     unsigned int period)
{
	unsigned int counter = 0;
	unsigned int i, n;
	u64 retval;

	/*
	 * Count the number of bits needed to represent the period number. The
	 * number of bits is used to calculate the number of levels used for the
	 * brightness-levels table, the purpose of this calculation is have a
	 * pre-computed table with enough levels to get linear brightness
	 * perception. The period is divided by the number of bits so for a
	 * 8-bit PWM we have 255 / 8 = 32 brightness levels or for a 16-bit PWM
	 * we have 65535 / 16 = 4096 brightness levels.
	 *
	 * Note that this method is based on empirical testing on different
	 * devices with PWM of 8 and 16 bits of resolution.
	 */
	n = period;
	while (n) {
		counter += n % 2;
		n >>= 1;
	}

	data->max_brightness = DIV_ROUND_UP(period, counter);
	data->levels = devm_kcalloc(dev, data->max_brightness,
				    sizeof(*data->levels), GFP_KERNEL);
	if (!data->levels)
		return -ENOMEM;

	/* Fill the table using the cie1931 algorithm */
	for (i = 0; i < data->max_brightness; i++) {
		retval = cie1931((i * PWM_LUMINANCE_SCALE) /
				 data->max_brightness, PWM_LUMINANCE_SCALE) *
				 period;
		retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
		if (retval > UINT_MAX)
			return -EINVAL;
		data->levels[i] = (unsigned int)retval;
	}

	data->dft_brightness = data->max_brightness / 2;
	data->max_brightness--;

	return 0;
}

247 248 249 250
static int pwm_backlight_parse_dt(struct device *dev,
				  struct platform_pwm_backlight_data *data)
{
	struct device_node *node = dev->of_node;
251 252
	unsigned int num_levels = 0;
	unsigned int levels_count;
253
	unsigned int num_steps = 0;
254
	struct property *prop;
255
	unsigned int *table;
256 257 258 259 260 261 262 263 264
	int length;
	u32 value;
	int ret;

	if (!node)
		return -ENODEV;

	memset(data, 0, sizeof(*data));

265 266 267 268
	/*
	 * Determine the number of brightness levels, if this property is not
	 * set a default table of brightness levels will be used.
	 */
269 270
	prop = of_find_property(node, "brightness-levels", &length);
	if (!prop)
271
		return 0;
272 273 274 275 276 277

	data->max_brightness = length / sizeof(u32);

	/* read brightness levels from DT property */
	if (data->max_brightness > 0) {
		size_t size = sizeof(*data->levels) * data->max_brightness;
278
		unsigned int i, j, n = 0;
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295

		data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
		if (!data->levels)
			return -ENOMEM;

		ret = of_property_read_u32_array(node, "brightness-levels",
						 data->levels,
						 data->max_brightness);
		if (ret < 0)
			return ret;

		ret = of_property_read_u32(node, "default-brightness-level",
					   &value);
		if (ret < 0)
			return ret;

		data->dft_brightness = value;
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373

		/*
		 * This property is optional, if is set enables linear
		 * interpolation between each of the values of brightness levels
		 * and creates a new pre-computed table.
		 */
		of_property_read_u32(node, "num-interpolated-steps",
				     &num_steps);

		/*
		 * Make sure that there is at least two entries in the
		 * brightness-levels table, otherwise we can't interpolate
		 * between two points.
		 */
		if (num_steps) {
			if (data->max_brightness < 2) {
				dev_err(dev, "can't interpolate\n");
				return -EINVAL;
			}

			/*
			 * Recalculate the number of brightness levels, now
			 * taking in consideration the number of interpolated
			 * steps between two levels.
			 */
			for (i = 0; i < data->max_brightness - 1; i++) {
				if ((data->levels[i + 1] - data->levels[i]) /
				   num_steps)
					num_levels += num_steps;
				else
					num_levels++;
			}
			num_levels++;
			dev_dbg(dev, "new number of brightness levels: %d\n",
				num_levels);

			/*
			 * Create a new table of brightness levels with all the
			 * interpolated steps.
			 */
			size = sizeof(*table) * num_levels;
			table = devm_kzalloc(dev, size, GFP_KERNEL);
			if (!table)
				return -ENOMEM;

			/* Fill the interpolated table. */
			levels_count = 0;
			for (i = 0; i < data->max_brightness - 1; i++) {
				value = data->levels[i];
				n = (data->levels[i + 1] - value) / num_steps;
				if (n > 0) {
					for (j = 0; j < num_steps; j++) {
						table[levels_count] = value;
						value += n;
						levels_count++;
					}
				} else {
					table[levels_count] = data->levels[i];
					levels_count++;
				}
			}
			table[levels_count] = data->levels[i];

			/*
			 * As we use interpolation lets remove current
			 * brightness levels table and replace for the
			 * new interpolated table.
			 */
			devm_kfree(dev, data->levels);
			data->levels = table;

			/*
			 * Reassign max_brightness value to the new total number
			 * of brightness levels.
			 */
			data->max_brightness = num_levels;
		}

374 375 376
		data->max_brightness--;
	}

377 378 379 380 381 382 383 384
	/*
	 * These values are optional and set as 0 by default, the out values
	 * are modified only if a valid u32 value can be decoded.
	 */
	of_property_read_u32(node, "post-pwm-on-delay-ms",
			     &data->post_pwm_on_delay);
	of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);

385
	data->enable_gpio = -EINVAL;
386 387 388
	return 0;
}

389
static const struct of_device_id pwm_backlight_of_match[] = {
390 391 392 393 394 395 396 397 398 399 400
	{ .compatible = "pwm-backlight" },
	{ }
};

MODULE_DEVICE_TABLE(of, pwm_backlight_of_match);
#else
static int pwm_backlight_parse_dt(struct device *dev,
				  struct platform_pwm_backlight_data *data)
{
	return -ENODEV;
}
401 402 403 404 405 406 407 408

static
int pwm_backlight_brightness_default(struct device *dev,
				     struct platform_pwm_backlight_data *data,
				     unsigned int period)
{
	return -ENODEV;
}
409 410
#endif

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
{
	struct device_node *node = pb->dev->of_node;

	/* Not booted with device tree or no phandle link to the node */
	if (!node || !node->phandle)
		return FB_BLANK_UNBLANK;

	/*
	 * If the driver is probed from the device tree and there is a
	 * phandle link pointing to the backlight node, it is safe to
	 * assume that another driver will enable the backlight at the
	 * appropriate time. Therefore, if it is disabled, keep it so.
	 */

	/* if the enable GPIO is disabled, do not enable the backlight */
	if (pb->enable_gpio && gpiod_get_value(pb->enable_gpio) == 0)
		return FB_BLANK_POWERDOWN;

	/* The regulator is disabled, do not enable the backlight */
	if (!regulator_is_enabled(pb->power_supply))
		return FB_BLANK_POWERDOWN;

434 435 436 437
	/* The PWM is disabled, keep it like this */
	if (!pwm_is_enabled(pb->pwm))
		return FB_BLANK_POWERDOWN;

438 439 440
	return FB_BLANK_UNBLANK;
}

441 442
static int pwm_backlight_probe(struct platform_device *pdev)
{
J
Jingoo Han 已提交
443
	struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
444 445
	struct platform_pwm_backlight_data defdata;
	struct backlight_properties props;
446
	struct backlight_device *bl;
447
	struct device_node *node = pdev->dev.of_node;
448
	struct pwm_bl_data *pb;
449
	struct pwm_state state;
450
	struct pwm_args pargs;
451
	unsigned int i;
452
	int ret;
453

454
	if (!data) {
455 456 457 458 459 460 461
		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to find platform data\n");
			return ret;
		}

		data = &defdata;
462
	}
463

464 465 466 467 468 469
	if (data->init) {
		ret = data->init(&pdev->dev);
		if (ret < 0)
			return ret;
	}

470
	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
471 472 473 474
	if (!pb) {
		ret = -ENOMEM;
		goto err_alloc;
	}
475

476
	pb->notify = data->notify;
477
	pb->notify_after = data->notify_after;
478
	pb->check_fb = data->check_fb;
479
	pb->exit = data->exit;
480
	pb->dev = &pdev->dev;
T
Thierry Reding 已提交
481
	pb->enabled = false;
482 483
	pb->post_pwm_on_delay = data->post_pwm_on_delay;
	pb->pwm_off_delay = data->pwm_off_delay;
484

485
	pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
486
						  GPIOD_ASIS);
487 488
	if (IS_ERR(pb->enable_gpio)) {
		ret = PTR_ERR(pb->enable_gpio);
489
		goto err_alloc;
490
	}
491

492 493 494 495 496 497 498
	/*
	 * Compatibility fallback for drivers still using the integer GPIO
	 * platform data. Must go away soon.
	 */
	if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) {
		ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio,
					    GPIOF_OUT_INIT_HIGH, "enable");
499 500
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
501
				data->enable_gpio, ret);
502 503
			goto err_alloc;
		}
504 505

		pb->enable_gpio = gpio_to_desc(data->enable_gpio);
506 507
	}

508
	/*
509
	 * If the GPIO is not known to be already configured as output, that
510 511
	 * is, if gpiod_get_direction returns either 1 or -EINVAL, change the
	 * direction to output and set the GPIO as active.
512 513 514 515 516
	 * Do not force the GPIO to active when it was already output as it
	 * could cause backlight flickering or we would enable the backlight too
	 * early. Leave the decision of the initial backlight state for later.
	 */
	if (pb->enable_gpio &&
517
	    gpiod_get_direction(pb->enable_gpio) != 0)
518
		gpiod_direction_output(pb->enable_gpio, 1);
519

520 521 522
	pb->power_supply = devm_regulator_get(&pdev->dev, "power");
	if (IS_ERR(pb->power_supply)) {
		ret = PTR_ERR(pb->power_supply);
523
		goto err_alloc;
524
	}
525

526
	pb->pwm = devm_pwm_get(&pdev->dev, NULL);
527
	if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {
528
		dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
529
		pb->legacy = true;
530
		pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
531 532 533 534 535 536 537
	}

	if (IS_ERR(pb->pwm)) {
		ret = PTR_ERR(pb->pwm);
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev, "unable to request PWM\n");
		goto err_alloc;
538 539 540 541
	}

	dev_dbg(&pdev->dev, "got pwm for backlight\n");

542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
	if (!data->levels) {
		/* Get the PWM period (in nanoseconds) */
		pwm_get_state(pb->pwm, &state);

		ret = pwm_backlight_brightness_default(&pdev->dev, data,
						       state.period);
		if (ret < 0) {
			dev_err(&pdev->dev,
				"failed to setup default brightness table\n");
			goto err_alloc;
		}
	}

	for (i = 0; i <= data->max_brightness; i++) {
		if (data->levels[i] > pb->scale)
			pb->scale = data->levels[i];

		pb->levels = data->levels;
	}

562 563 564 565 566 567
	/*
	 * FIXME: pwm_apply_args() should be removed when switching to
	 * the atomic PWM API.
	 */
	pwm_apply_args(pb->pwm);

568 569 570
	/*
	 * The DT case will set the pwm_period_ns field to 0 and store the
	 * period, parsed from the DT, in the PWM device. For the non-DT case,
571 572
	 * set the period from platform data if it has not already been set
	 * via the PWM lookup table.
573
	 */
574 575
	pwm_get_args(pb->pwm, &pargs);
	pb->period = pargs.period;
576
	if (!pb->period && (data->pwm_period_ns > 0))
577
		pb->period = data->pwm_period_ns;
578

579
	pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);
580

581
	memset(&props, 0, sizeof(struct backlight_properties));
M
Matthew Garrett 已提交
582
	props.type = BACKLIGHT_RAW;
583 584 585
	props.max_brightness = data->max_brightness;
	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
				       &pwm_backlight_ops, &props);
586 587
	if (IS_ERR(bl)) {
		dev_err(&pdev->dev, "failed to register backlight\n");
588
		ret = PTR_ERR(bl);
589 590
		if (pb->legacy)
			pwm_free(pb->pwm);
591
		goto err_alloc;
592 593
	}

594 595 596 597 598 599 600
	if (data->dft_brightness > data->max_brightness) {
		dev_warn(&pdev->dev,
			 "invalid default brightness level: %u, using %u\n",
			 data->dft_brightness, data->max_brightness);
		data->dft_brightness = data->max_brightness;
	}

601
	bl->props.brightness = data->dft_brightness;
602
	bl->props.power = pwm_backlight_initial_power_state(pb);
603 604 605 606
	backlight_update_status(bl);

	platform_set_drvdata(pdev, bl);
	return 0;
607 608 609 610 611

err_alloc:
	if (data->exit)
		data->exit(&pdev->dev);
	return ret;
612 613 614 615 616
}

static int pwm_backlight_remove(struct platform_device *pdev)
{
	struct backlight_device *bl = platform_get_drvdata(pdev);
617
	struct pwm_bl_data *pb = bl_get_data(bl);
618 619

	backlight_device_unregister(bl);
620
	pwm_backlight_power_off(pb);
621

622 623
	if (pb->exit)
		pb->exit(&pdev->dev);
624 625
	if (pb->legacy)
		pwm_free(pb->pwm);
626

627 628 629
	return 0;
}

630 631 632 633 634 635 636 637
static void pwm_backlight_shutdown(struct platform_device *pdev)
{
	struct backlight_device *bl = platform_get_drvdata(pdev);
	struct pwm_bl_data *pb = bl_get_data(bl);

	pwm_backlight_power_off(pb);
}

638
#ifdef CONFIG_PM_SLEEP
639
static int pwm_backlight_suspend(struct device *dev)
640
{
641
	struct backlight_device *bl = dev_get_drvdata(dev);
642
	struct pwm_bl_data *pb = bl_get_data(bl);
643

644
	if (pb->notify)
645
		pb->notify(pb->dev, 0);
646

647
	pwm_backlight_power_off(pb);
648

649 650
	if (pb->notify_after)
		pb->notify_after(pb->dev, 0);
651

652 653 654
	return 0;
}

655
static int pwm_backlight_resume(struct device *dev)
656
{
657
	struct backlight_device *bl = dev_get_drvdata(dev);
658 659

	backlight_update_status(bl);
660

661 662
	return 0;
}
663
#endif
664

665 666 667 668 669 670 671 672
static const struct dev_pm_ops pwm_backlight_pm_ops = {
#ifdef CONFIG_PM_SLEEP
	.suspend = pwm_backlight_suspend,
	.resume = pwm_backlight_resume,
	.poweroff = pwm_backlight_suspend,
	.restore = pwm_backlight_resume,
#endif
};
673

674 675
static struct platform_driver pwm_backlight_driver = {
	.driver		= {
676 677 678
		.name		= "pwm-backlight",
		.pm		= &pwm_backlight_pm_ops,
		.of_match_table	= of_match_ptr(pwm_backlight_of_match),
679 680 681
	},
	.probe		= pwm_backlight_probe,
	.remove		= pwm_backlight_remove,
682
	.shutdown	= pwm_backlight_shutdown,
683 684
};

685
module_platform_driver(pwm_backlight_driver);
686 687 688

MODULE_DESCRIPTION("PWM based Backlight Driver");
MODULE_LICENSE("GPL");
689
MODULE_ALIAS("platform:pwm-backlight");