pwm_bl.c 18 KB

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