1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/video/backlight/aat2870_bl.c
5 * Copyright (c) 2011, NVIDIA Corporation.
6 * Author: Jin Park <jinyoungp@nvidia.com>
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/platform_device.h>
13 #include <linux/mutex.h>
14 #include <linux/delay.h>
15 #include <linux/backlight.h>
16 #include <linux/mfd/aat2870.h>
18 struct aat2870_bl_driver_data
{
19 struct platform_device
*pdev
;
20 struct backlight_device
*bd
;
24 int brightness
; /* current brightness */
27 static inline int aat2870_brightness(struct aat2870_bl_driver_data
*aat2870_bl
,
30 struct backlight_device
*bd
= aat2870_bl
->bd
;
33 val
= brightness
* (aat2870_bl
->max_current
- 1);
34 val
/= bd
->props
.max_brightness
;
39 static inline int aat2870_bl_enable(struct aat2870_bl_driver_data
*aat2870_bl
)
41 struct aat2870_data
*aat2870
42 = dev_get_drvdata(aat2870_bl
->pdev
->dev
.parent
);
44 return aat2870
->write(aat2870
, AAT2870_BL_CH_EN
,
45 (u8
)aat2870_bl
->channels
);
48 static inline int aat2870_bl_disable(struct aat2870_bl_driver_data
*aat2870_bl
)
50 struct aat2870_data
*aat2870
51 = dev_get_drvdata(aat2870_bl
->pdev
->dev
.parent
);
53 return aat2870
->write(aat2870
, AAT2870_BL_CH_EN
, 0x0);
56 static int aat2870_bl_update_status(struct backlight_device
*bd
)
58 struct aat2870_bl_driver_data
*aat2870_bl
= bl_get_data(bd
);
59 struct aat2870_data
*aat2870
=
60 dev_get_drvdata(aat2870_bl
->pdev
->dev
.parent
);
61 int brightness
= backlight_get_brightness(bd
);
64 if ((brightness
< 0) || (bd
->props
.max_brightness
< brightness
)) {
65 dev_err(&bd
->dev
, "invalid brightness, %d\n", brightness
);
69 dev_dbg(&bd
->dev
, "brightness=%d, power=%d, state=%d\n",
70 bd
->props
.brightness
, bd
->props
.power
, bd
->props
.state
);
72 ret
= aat2870
->write(aat2870
, AAT2870_BLM
,
73 (u8
)aat2870_brightness(aat2870_bl
, brightness
));
77 if (brightness
== 0) {
78 ret
= aat2870_bl_disable(aat2870_bl
);
81 } else if (aat2870_bl
->brightness
== 0) {
82 ret
= aat2870_bl_enable(aat2870_bl
);
87 aat2870_bl
->brightness
= brightness
;
92 static const struct backlight_ops aat2870_bl_ops
= {
93 .options
= BL_CORE_SUSPENDRESUME
,
94 .update_status
= aat2870_bl_update_status
,
97 static int aat2870_bl_probe(struct platform_device
*pdev
)
99 struct aat2870_bl_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
100 struct aat2870_bl_driver_data
*aat2870_bl
;
101 struct backlight_device
*bd
;
102 struct backlight_properties props
;
106 dev_err(&pdev
->dev
, "No platform data\n");
111 if (pdev
->id
!= AAT2870_ID_BL
) {
112 dev_err(&pdev
->dev
, "Invalid device ID, %d\n", pdev
->id
);
117 aat2870_bl
= devm_kzalloc(&pdev
->dev
,
118 sizeof(struct aat2870_bl_driver_data
),
125 memset(&props
, 0, sizeof(struct backlight_properties
));
127 props
.type
= BACKLIGHT_RAW
;
128 bd
= devm_backlight_device_register(&pdev
->dev
, "aat2870-backlight",
129 &pdev
->dev
, aat2870_bl
, &aat2870_bl_ops
,
133 "Failed allocate memory for backlight device\n");
138 aat2870_bl
->pdev
= pdev
;
139 platform_set_drvdata(pdev
, aat2870_bl
);
143 if (pdata
->channels
> 0)
144 aat2870_bl
->channels
= pdata
->channels
;
146 aat2870_bl
->channels
= AAT2870_BL_CH_ALL
;
148 if (pdata
->max_current
> 0)
149 aat2870_bl
->max_current
= pdata
->max_current
;
151 aat2870_bl
->max_current
= AAT2870_CURRENT_27_9
;
153 if (pdata
->max_brightness
> 0)
154 bd
->props
.max_brightness
= pdata
->max_brightness
;
156 bd
->props
.max_brightness
= 255;
158 aat2870_bl
->brightness
= 0;
159 bd
->props
.power
= BACKLIGHT_POWER_ON
;
160 bd
->props
.brightness
= bd
->props
.max_brightness
;
162 ret
= aat2870_bl_update_status(bd
);
164 dev_err(&pdev
->dev
, "Failed to initialize\n");
174 static void aat2870_bl_remove(struct platform_device
*pdev
)
176 struct aat2870_bl_driver_data
*aat2870_bl
= platform_get_drvdata(pdev
);
177 struct backlight_device
*bd
= aat2870_bl
->bd
;
179 bd
->props
.power
= BACKLIGHT_POWER_OFF
;
180 bd
->props
.brightness
= 0;
181 backlight_update_status(bd
);
184 static struct platform_driver aat2870_bl_driver
= {
186 .name
= "aat2870-backlight",
188 .probe
= aat2870_bl_probe
,
189 .remove_new
= aat2870_bl_remove
,
192 static int __init
aat2870_bl_init(void)
194 return platform_driver_register(&aat2870_bl_driver
);
196 subsys_initcall(aat2870_bl_init
);
198 static void __exit
aat2870_bl_exit(void)
200 platform_driver_unregister(&aat2870_bl_driver
);
202 module_exit(aat2870_bl_exit
);
204 MODULE_DESCRIPTION("AnalogicTech AAT2870 Backlight");
205 MODULE_LICENSE("GPL");
206 MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");