pwm_bl.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Simple PWM based backlight control, board code has to setup
  4. * 1) pin configuration so PWM waveforms can output
  5. * 2) platform_data being correctly configured
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/gpio/consumer.h>
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/backlight.h>
  14. #include <linux/err.h>
  15. #include <linux/pwm.h>
  16. #include <linux/pwm_backlight.h>
  17. #include <linux/regulator/consumer.h>
  18. #include <linux/slab.h>
  19. struct pwm_bl_data {
  20. struct pwm_device *pwm;
  21. struct device *dev;
  22. unsigned int lth_brightness;
  23. unsigned int *levels;
  24. bool enabled;
  25. struct regulator *power_supply;
  26. struct gpio_desc *enable_gpio;
  27. unsigned int scale;
  28. unsigned int post_pwm_on_delay;
  29. unsigned int pwm_off_delay;
  30. int (*notify)(struct device *,
  31. int brightness);
  32. void (*notify_after)(struct device *,
  33. int brightness);
  34. void (*exit)(struct device *);
  35. };
  36. static void pwm_backlight_power_on(struct pwm_bl_data *pb)
  37. {
  38. int err;
  39. if (pb->enabled)
  40. return;
  41. if (pb->power_supply) {
  42. err = regulator_enable(pb->power_supply);
  43. if (err < 0)
  44. dev_err(pb->dev, "failed to enable power supply\n");
  45. }
  46. if (pb->post_pwm_on_delay)
  47. msleep(pb->post_pwm_on_delay);
  48. gpiod_set_value_cansleep(pb->enable_gpio, 1);
  49. pb->enabled = true;
  50. }
  51. static void pwm_backlight_power_off(struct pwm_bl_data *pb)
  52. {
  53. if (!pb->enabled)
  54. return;
  55. gpiod_set_value_cansleep(pb->enable_gpio, 0);
  56. if (pb->pwm_off_delay)
  57. msleep(pb->pwm_off_delay);
  58. if (pb->power_supply)
  59. regulator_disable(pb->power_supply);
  60. pb->enabled = false;
  61. }
  62. static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness, struct pwm_state *state)
  63. {
  64. unsigned int lth = pb->lth_brightness;
  65. u64 duty_cycle;
  66. if (pb->levels)
  67. duty_cycle = pb->levels[brightness];
  68. else
  69. duty_cycle = brightness;
  70. duty_cycle *= state->period - lth;
  71. do_div(duty_cycle, pb->scale);
  72. return duty_cycle + lth;
  73. }
  74. static int pwm_backlight_update_status(struct backlight_device *bl)
  75. {
  76. struct pwm_bl_data *pb = bl_get_data(bl);
  77. int brightness = backlight_get_brightness(bl);
  78. struct pwm_state state;
  79. if (pb->notify)
  80. brightness = pb->notify(pb->dev, brightness);
  81. if (brightness > 0) {
  82. pwm_get_state(pb->pwm, &state);
  83. state.duty_cycle = compute_duty_cycle(pb, brightness, &state);
  84. state.enabled = true;
  85. pwm_apply_might_sleep(pb->pwm, &state);
  86. pwm_backlight_power_on(pb);
  87. } else {
  88. pwm_backlight_power_off(pb);
  89. pwm_get_state(pb->pwm, &state);
  90. state.duty_cycle = 0;
  91. /*
  92. * We cannot assume a disabled PWM to drive its output to the
  93. * inactive state. If we have an enable GPIO and/or a regulator
  94. * we assume that this isn't relevant and we can disable the PWM
  95. * to save power. If however there is neither an enable GPIO nor
  96. * a regulator keep the PWM on be sure to get a constant
  97. * inactive output.
  98. */
  99. state.enabled = !pb->power_supply && !pb->enable_gpio;
  100. pwm_apply_might_sleep(pb->pwm, &state);
  101. }
  102. if (pb->notify_after)
  103. pb->notify_after(pb->dev, brightness);
  104. return 0;
  105. }
  106. static const struct backlight_ops pwm_backlight_ops = {
  107. .update_status = pwm_backlight_update_status,
  108. };
  109. #ifdef CONFIG_OF
  110. #define PWM_LUMINANCE_SHIFT 16
  111. #define PWM_LUMINANCE_SCALE (1 << PWM_LUMINANCE_SHIFT) /* luminance scale */
  112. /*
  113. * CIE lightness to PWM conversion.
  114. *
  115. * The CIE 1931 lightness formula is what actually describes how we perceive
  116. * light:
  117. * Y = (L* / 903.3) if L* ≤ 8
  118. * Y = ((L* + 16) / 116)^3 if L* > 8
  119. *
  120. * Where Y is the luminance, the amount of light coming out of the screen, and
  121. * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
  122. * perceives the screen to be, and is a number between 0 and 100.
  123. *
  124. * The following function does the fixed point maths needed to implement the
  125. * above formula.
  126. */
  127. static u64 cie1931(unsigned int lightness)
  128. {
  129. u64 retval;
  130. /*
  131. * @lightness is given as a number between 0 and 1, expressed
  132. * as a fixed-point number in scale
  133. * PWM_LUMINANCE_SCALE. Convert to a percentage, still
  134. * expressed as a fixed-point number, so the above formulas
  135. * can be applied.
  136. */
  137. lightness *= 100;
  138. if (lightness <= (8 * PWM_LUMINANCE_SCALE)) {
  139. retval = DIV_ROUND_CLOSEST(lightness * 10, 9033);
  140. } else {
  141. retval = (lightness + (16 * PWM_LUMINANCE_SCALE)) / 116;
  142. retval *= retval * retval;
  143. retval += 1ULL << (2*PWM_LUMINANCE_SHIFT - 1);
  144. retval >>= 2*PWM_LUMINANCE_SHIFT;
  145. }
  146. return retval;
  147. }
  148. /*
  149. * Create a default correction table for PWM values to create linear brightness
  150. * for LED based backlights using the CIE1931 algorithm.
  151. */
  152. static
  153. int pwm_backlight_brightness_default(struct device *dev,
  154. struct platform_pwm_backlight_data *data,
  155. unsigned int period)
  156. {
  157. unsigned int i;
  158. u64 retval;
  159. /*
  160. * Once we have 4096 levels there's little point going much higher...
  161. * neither interactive sliders nor animation benefits from having
  162. * more values in the table.
  163. */
  164. data->max_brightness =
  165. min((int)DIV_ROUND_UP(period, fls(period)), 4096);
  166. data->levels = devm_kcalloc(dev, data->max_brightness,
  167. sizeof(*data->levels), GFP_KERNEL);
  168. if (!data->levels)
  169. return -ENOMEM;
  170. /* Fill the table using the cie1931 algorithm */
  171. for (i = 0; i < data->max_brightness; i++) {
  172. retval = cie1931((i * PWM_LUMINANCE_SCALE) /
  173. data->max_brightness) * period;
  174. retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
  175. if (retval > UINT_MAX)
  176. return -EINVAL;
  177. data->levels[i] = (unsigned int)retval;
  178. }
  179. data->dft_brightness = data->max_brightness / 2;
  180. data->max_brightness--;
  181. return 0;
  182. }
  183. static int pwm_backlight_parse_dt(struct device *dev,
  184. struct platform_pwm_backlight_data *data)
  185. {
  186. struct device_node *node = dev->of_node;
  187. unsigned int num_levels;
  188. unsigned int num_steps = 0;
  189. struct property *prop;
  190. unsigned int *table;
  191. int length;
  192. u32 value;
  193. int ret;
  194. if (!node)
  195. return -ENODEV;
  196. memset(data, 0, sizeof(*data));
  197. /*
  198. * These values are optional and set as 0 by default, the out values
  199. * are modified only if a valid u32 value can be decoded.
  200. */
  201. of_property_read_u32(node, "post-pwm-on-delay-ms",
  202. &data->post_pwm_on_delay);
  203. of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
  204. /*
  205. * Determine the number of brightness levels, if this property is not
  206. * set a default table of brightness levels will be used.
  207. */
  208. prop = of_find_property(node, "brightness-levels", &length);
  209. if (!prop)
  210. return 0;
  211. num_levels = length / sizeof(u32);
  212. /* read brightness levels from DT property */
  213. if (num_levels > 0) {
  214. data->levels = devm_kcalloc(dev, num_levels,
  215. sizeof(*data->levels), GFP_KERNEL);
  216. if (!data->levels)
  217. return -ENOMEM;
  218. ret = of_property_read_u32_array(node, "brightness-levels",
  219. data->levels,
  220. num_levels);
  221. if (ret < 0)
  222. return ret;
  223. ret = of_property_read_u32(node, "default-brightness-level",
  224. &value);
  225. if (ret < 0)
  226. return ret;
  227. data->dft_brightness = value;
  228. /*
  229. * This property is optional, if is set enables linear
  230. * interpolation between each of the values of brightness levels
  231. * and creates a new pre-computed table.
  232. */
  233. of_property_read_u32(node, "num-interpolated-steps",
  234. &num_steps);
  235. /*
  236. * Make sure that there is at least two entries in the
  237. * brightness-levels table, otherwise we can't interpolate
  238. * between two points.
  239. */
  240. if (num_steps) {
  241. unsigned int num_input_levels = num_levels;
  242. unsigned int i;
  243. u32 x1, x2, x, dx;
  244. u32 y1, y2;
  245. s64 dy;
  246. if (num_input_levels < 2) {
  247. dev_err(dev, "can't interpolate\n");
  248. return -EINVAL;
  249. }
  250. /*
  251. * Recalculate the number of brightness levels, now
  252. * taking in consideration the number of interpolated
  253. * steps between two levels.
  254. */
  255. num_levels = (num_input_levels - 1) * num_steps + 1;
  256. dev_dbg(dev, "new number of brightness levels: %d\n",
  257. num_levels);
  258. /*
  259. * Create a new table of brightness levels with all the
  260. * interpolated steps.
  261. */
  262. table = devm_kcalloc(dev, num_levels, sizeof(*table),
  263. GFP_KERNEL);
  264. if (!table)
  265. return -ENOMEM;
  266. /*
  267. * Fill the interpolated table[x] = y
  268. * by draw lines between each (x1, y1) to (x2, y2).
  269. */
  270. dx = num_steps;
  271. for (i = 0; i < num_input_levels - 1; i++) {
  272. x1 = i * dx;
  273. x2 = x1 + dx;
  274. y1 = data->levels[i];
  275. y2 = data->levels[i + 1];
  276. dy = (s64)y2 - y1;
  277. for (x = x1; x < x2; x++) {
  278. table[x] = y1 +
  279. div_s64(dy * (x - x1), dx);
  280. }
  281. }
  282. /* Fill in the last point, since no line starts here. */
  283. table[x2] = y2;
  284. /*
  285. * As we use interpolation lets remove current
  286. * brightness levels table and replace for the
  287. * new interpolated table.
  288. */
  289. devm_kfree(dev, data->levels);
  290. data->levels = table;
  291. }
  292. data->max_brightness = num_levels - 1;
  293. }
  294. return 0;
  295. }
  296. static const struct of_device_id pwm_backlight_of_match[] = {
  297. { .compatible = "pwm-backlight" },
  298. { }
  299. };
  300. MODULE_DEVICE_TABLE(of, pwm_backlight_of_match);
  301. #else
  302. static int pwm_backlight_parse_dt(struct device *dev,
  303. struct platform_pwm_backlight_data *data)
  304. {
  305. return -ENODEV;
  306. }
  307. static
  308. int pwm_backlight_brightness_default(struct device *dev,
  309. struct platform_pwm_backlight_data *data,
  310. unsigned int period)
  311. {
  312. return -ENODEV;
  313. }
  314. #endif
  315. static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data)
  316. {
  317. unsigned int nlevels = data->max_brightness + 1;
  318. unsigned int min_val = data->levels[0];
  319. unsigned int max_val = data->levels[nlevels - 1];
  320. /*
  321. * Multiplying by 128 means that even in pathological cases such
  322. * as (max_val - min_val) == nlevels the error at max_val is less
  323. * than 1%.
  324. */
  325. unsigned int slope = (128 * (max_val - min_val)) / nlevels;
  326. unsigned int margin = (max_val - min_val) / 20; /* 5% */
  327. int i;
  328. for (i = 1; i < nlevels; i++) {
  329. unsigned int linear_value = min_val + ((i * slope) / 128);
  330. unsigned int delta = abs(linear_value - data->levels[i]);
  331. if (delta > margin)
  332. return false;
  333. }
  334. return true;
  335. }
  336. static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
  337. {
  338. struct device_node *node = pb->dev->of_node;
  339. bool active = true;
  340. /*
  341. * If the enable GPIO is present, observable (either as input
  342. * or output) and off then the backlight is not currently active.
  343. * */
  344. if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
  345. active = false;
  346. if (pb->power_supply && !regulator_is_enabled(pb->power_supply))
  347. active = false;
  348. if (!pwm_is_enabled(pb->pwm))
  349. active = false;
  350. /*
  351. * Synchronize the enable_gpio with the observed state of the
  352. * hardware.
  353. */
  354. gpiod_direction_output(pb->enable_gpio, active);
  355. /*
  356. * Do not change pb->enabled here! pb->enabled essentially
  357. * tells us if we own one of the regulator's use counts and
  358. * right now we do not.
  359. */
  360. /* Not booted with device tree or no phandle link to the node */
  361. if (!node || !node->phandle)
  362. return BACKLIGHT_POWER_ON;
  363. /*
  364. * If the driver is probed from the device tree and there is a
  365. * phandle link pointing to the backlight node, it is safe to
  366. * assume that another driver will enable the backlight at the
  367. * appropriate time. Therefore, if it is disabled, keep it so.
  368. */
  369. return active ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF;
  370. }
  371. static int pwm_backlight_probe(struct platform_device *pdev)
  372. {
  373. struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
  374. struct platform_pwm_backlight_data defdata;
  375. struct backlight_properties props;
  376. struct backlight_device *bl;
  377. struct pwm_bl_data *pb;
  378. struct pwm_state state;
  379. unsigned int i;
  380. int ret;
  381. if (!data) {
  382. ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
  383. if (ret < 0)
  384. return dev_err_probe(&pdev->dev, ret,
  385. "failed to find platform data\n");
  386. data = &defdata;
  387. }
  388. if (data->init) {
  389. ret = data->init(&pdev->dev);
  390. if (ret < 0)
  391. return ret;
  392. }
  393. pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
  394. if (!pb) {
  395. ret = -ENOMEM;
  396. goto err_alloc;
  397. }
  398. pb->notify = data->notify;
  399. pb->notify_after = data->notify_after;
  400. pb->exit = data->exit;
  401. pb->dev = &pdev->dev;
  402. pb->enabled = false;
  403. pb->post_pwm_on_delay = data->post_pwm_on_delay;
  404. pb->pwm_off_delay = data->pwm_off_delay;
  405. pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
  406. GPIOD_ASIS);
  407. if (IS_ERR(pb->enable_gpio)) {
  408. ret = dev_err_probe(&pdev->dev, PTR_ERR(pb->enable_gpio),
  409. "failed to acquire enable GPIO\n");
  410. goto err_alloc;
  411. }
  412. pb->power_supply = devm_regulator_get_optional(&pdev->dev, "power");
  413. if (IS_ERR(pb->power_supply)) {
  414. ret = PTR_ERR(pb->power_supply);
  415. if (ret == -ENODEV) {
  416. pb->power_supply = NULL;
  417. } else {
  418. dev_err_probe(&pdev->dev, ret,
  419. "failed to acquire power regulator\n");
  420. goto err_alloc;
  421. }
  422. }
  423. pb->pwm = devm_pwm_get(&pdev->dev, NULL);
  424. if (IS_ERR(pb->pwm)) {
  425. ret = dev_err_probe(&pdev->dev, PTR_ERR(pb->pwm),
  426. "unable to request PWM\n");
  427. goto err_alloc;
  428. }
  429. dev_dbg(&pdev->dev, "got pwm for backlight\n");
  430. /* Sync up PWM state. */
  431. pwm_init_state(pb->pwm, &state);
  432. /*
  433. * The DT case will set the pwm_period_ns field to 0 and store the
  434. * period, parsed from the DT, in the PWM device. For the non-DT case,
  435. * set the period from platform data if it has not already been set
  436. * via the PWM lookup table.
  437. */
  438. if (!state.period && (data->pwm_period_ns > 0))
  439. state.period = data->pwm_period_ns;
  440. ret = pwm_apply_might_sleep(pb->pwm, &state);
  441. if (ret) {
  442. dev_err_probe(&pdev->dev, ret,
  443. "failed to apply initial PWM state");
  444. goto err_alloc;
  445. }
  446. memset(&props, 0, sizeof(struct backlight_properties));
  447. if (data->levels) {
  448. pb->levels = data->levels;
  449. /*
  450. * For the DT case, only when brightness levels is defined
  451. * data->levels is filled. For the non-DT case, data->levels
  452. * can come from platform data, however is not usual.
  453. */
  454. for (i = 0; i <= data->max_brightness; i++)
  455. if (data->levels[i] > pb->scale)
  456. pb->scale = data->levels[i];
  457. if (pwm_backlight_is_linear(data))
  458. props.scale = BACKLIGHT_SCALE_LINEAR;
  459. else
  460. props.scale = BACKLIGHT_SCALE_NON_LINEAR;
  461. } else if (!data->max_brightness) {
  462. /*
  463. * If no brightness levels are provided and max_brightness is
  464. * not set, use the default brightness table. For the DT case,
  465. * max_brightness is set to 0 when brightness levels is not
  466. * specified. For the non-DT case, max_brightness is usually
  467. * set to some value.
  468. */
  469. /* Get the PWM period (in nanoseconds) */
  470. pwm_get_state(pb->pwm, &state);
  471. ret = pwm_backlight_brightness_default(&pdev->dev, data,
  472. state.period);
  473. if (ret < 0) {
  474. dev_err_probe(&pdev->dev, ret,
  475. "failed to setup default brightness table\n");
  476. goto err_alloc;
  477. }
  478. for (i = 0; i <= data->max_brightness; i++) {
  479. if (data->levels[i] > pb->scale)
  480. pb->scale = data->levels[i];
  481. pb->levels = data->levels;
  482. }
  483. props.scale = BACKLIGHT_SCALE_NON_LINEAR;
  484. } else {
  485. /*
  486. * That only happens for the non-DT case, where platform data
  487. * sets the max_brightness value.
  488. */
  489. pb->scale = data->max_brightness;
  490. }
  491. pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
  492. pb->scale));
  493. props.type = BACKLIGHT_RAW;
  494. props.max_brightness = data->max_brightness;
  495. bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
  496. &pwm_backlight_ops, &props);
  497. if (IS_ERR(bl)) {
  498. ret = dev_err_probe(&pdev->dev, PTR_ERR(bl),
  499. "failed to register backlight\n");
  500. goto err_alloc;
  501. }
  502. if (data->dft_brightness > data->max_brightness) {
  503. dev_warn(&pdev->dev,
  504. "invalid default brightness level: %u, using %u\n",
  505. data->dft_brightness, data->max_brightness);
  506. data->dft_brightness = data->max_brightness;
  507. }
  508. bl->props.brightness = data->dft_brightness;
  509. bl->props.power = pwm_backlight_initial_power_state(pb);
  510. backlight_update_status(bl);
  511. platform_set_drvdata(pdev, bl);
  512. return 0;
  513. err_alloc:
  514. if (data->exit)
  515. data->exit(&pdev->dev);
  516. return ret;
  517. }
  518. static void pwm_backlight_remove(struct platform_device *pdev)
  519. {
  520. struct backlight_device *bl = platform_get_drvdata(pdev);
  521. struct pwm_bl_data *pb = bl_get_data(bl);
  522. struct pwm_state state;
  523. backlight_device_unregister(bl);
  524. pwm_backlight_power_off(pb);
  525. pwm_get_state(pb->pwm, &state);
  526. state.duty_cycle = 0;
  527. state.enabled = false;
  528. pwm_apply_might_sleep(pb->pwm, &state);
  529. if (pb->exit)
  530. pb->exit(&pdev->dev);
  531. }
  532. static void pwm_backlight_shutdown(struct platform_device *pdev)
  533. {
  534. struct backlight_device *bl = platform_get_drvdata(pdev);
  535. struct pwm_bl_data *pb = bl_get_data(bl);
  536. struct pwm_state state;
  537. pwm_backlight_power_off(pb);
  538. pwm_get_state(pb->pwm, &state);
  539. state.duty_cycle = 0;
  540. state.enabled = false;
  541. pwm_apply_might_sleep(pb->pwm, &state);
  542. }
  543. #ifdef CONFIG_PM_SLEEP
  544. static int pwm_backlight_suspend(struct device *dev)
  545. {
  546. struct backlight_device *bl = dev_get_drvdata(dev);
  547. struct pwm_bl_data *pb = bl_get_data(bl);
  548. struct pwm_state state;
  549. if (pb->notify)
  550. pb->notify(pb->dev, 0);
  551. pwm_backlight_power_off(pb);
  552. /*
  553. * Note that disabling the PWM doesn't guarantee that the output stays
  554. * at its inactive state. However without the PWM disabled, the PWM
  555. * driver refuses to suspend. So disable here even though this might
  556. * enable the backlight on poorly designed boards.
  557. */
  558. pwm_get_state(pb->pwm, &state);
  559. state.duty_cycle = 0;
  560. state.enabled = false;
  561. pwm_apply_might_sleep(pb->pwm, &state);
  562. if (pb->notify_after)
  563. pb->notify_after(pb->dev, 0);
  564. return 0;
  565. }
  566. static int pwm_backlight_resume(struct device *dev)
  567. {
  568. struct backlight_device *bl = dev_get_drvdata(dev);
  569. backlight_update_status(bl);
  570. return 0;
  571. }
  572. #endif
  573. static const struct dev_pm_ops pwm_backlight_pm_ops = {
  574. #ifdef CONFIG_PM_SLEEP
  575. .suspend = pwm_backlight_suspend,
  576. .resume = pwm_backlight_resume,
  577. .poweroff = pwm_backlight_suspend,
  578. .restore = pwm_backlight_resume,
  579. #endif
  580. };
  581. static struct platform_driver pwm_backlight_driver = {
  582. .driver = {
  583. .name = "pwm-backlight",
  584. .pm = &pwm_backlight_pm_ops,
  585. .of_match_table = of_match_ptr(pwm_backlight_of_match),
  586. },
  587. .probe = pwm_backlight_probe,
  588. .remove_new = pwm_backlight_remove,
  589. .shutdown = pwm_backlight_shutdown,
  590. };
  591. module_platform_driver(pwm_backlight_driver);
  592. MODULE_DESCRIPTION("PWM based Backlight Driver");
  593. MODULE_LICENSE("GPL v2");
  594. MODULE_ALIAS("platform:pwm-backlight");