Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
leds
leds-pca9633.c
Go to the documentation of this file.
1
/*
2
* Copyright 2011 bct electronic GmbH
3
*
4
* Author: Peter Meerwald <
[email protected]
>
5
*
6
* Based on leds-pca955x.c
7
*
8
* This file is subject to the terms and conditions of version 2 of
9
* the GNU General Public License. See the file COPYING in the main
10
* directory of this archive for more details.
11
*
12
* LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
13
*
14
*/
15
16
#include <linux/module.h>
17
#include <
linux/delay.h
>
18
#include <linux/string.h>
19
#include <linux/ctype.h>
20
#include <
linux/leds.h
>
21
#include <
linux/err.h
>
22
#include <linux/i2c.h>
23
#include <
linux/workqueue.h
>
24
#include <linux/slab.h>
25
#include <
linux/platform_data/leds-pca9633.h
>
26
27
/* LED select registers determine the source that drives LED outputs */
28
#define PCA9633_LED_OFF 0x0
/* LED driver off */
29
#define PCA9633_LED_ON 0x1
/* LED driver on */
30
#define PCA9633_LED_PWM 0x2
/* Controlled through PWM */
31
#define PCA9633_LED_GRP_PWM 0x3
/* Controlled through PWM/GRPPWM */
32
33
#define PCA9633_MODE1 0x00
34
#define PCA9633_MODE2 0x01
35
#define PCA9633_PWM_BASE 0x02
36
#define PCA9633_LEDOUT 0x08
37
38
static
const
struct
i2c_device_id
pca9633_id[] = {
39
{
"pca9633"
, 0 },
40
{ }
41
};
42
MODULE_DEVICE_TABLE
(i2c, pca9633_id);
43
44
struct
pca9633_led
{
45
struct
i2c_client
*
client
;
46
struct
work_struct
work
;
47
enum
led_brightness
brightness
;
48
struct
led_classdev
led_cdev
;
49
int
led_num
;
/* 0 .. 3 potentially */
50
char
name
[32];
51
};
52
53
static
void
pca9633_led_work(
struct
work_struct
*
work
)
54
{
55
struct
pca9633_led
*pca9633 =
container_of
(work,
56
struct
pca9633_led
, work);
57
u8
ledout =
i2c_smbus_read_byte_data
(pca9633->
client
,
PCA9633_LEDOUT
);
58
int
shift = 2 * pca9633->
led_num
;
59
u8
mask
= 0x3 << shift;
60
61
switch
(pca9633->
brightness
) {
62
case
LED_FULL
:
63
i2c_smbus_write_byte_data
(pca9633->
client
,
PCA9633_LEDOUT
,
64
(ledout & ~mask) | (
PCA9633_LED_ON
<< shift));
65
break
;
66
case
LED_OFF
:
67
i2c_smbus_write_byte_data
(pca9633->
client
,
PCA9633_LEDOUT
,
68
ledout & ~mask);
69
break
;
70
default
:
71
i2c_smbus_write_byte_data
(pca9633->
client
,
72
PCA9633_PWM_BASE
+ pca9633->
led_num
,
73
pca9633->
brightness
);
74
i2c_smbus_write_byte_data
(pca9633->
client
,
PCA9633_LEDOUT
,
75
(ledout & ~mask) | (
PCA9633_LED_PWM
<< shift));
76
break
;
77
}
78
}
79
80
static
void
pca9633_led_set(
struct
led_classdev
*
led_cdev
,
81
enum
led_brightness
value
)
82
{
83
struct
pca9633_led
*pca9633;
84
85
pca9633 =
container_of
(led_cdev,
struct
pca9633_led
, led_cdev);
86
87
pca9633->
brightness
=
value
;
88
89
/*
90
* Must use workqueue for the actual I/O since I2C operations
91
* can sleep.
92
*/
93
schedule_work
(&pca9633->
work
);
94
}
95
96
static
int
__devinit
pca9633_probe(
struct
i2c_client
*
client
,
97
const
struct
i2c_device_id
*
id
)
98
{
99
struct
pca9633_led
*pca9633;
100
struct
pca9633_platform_data
*
pdata
;
101
int
i
,
err
;
102
103
pdata = client->
dev
.platform_data;
104
105
if
(pdata) {
106
if
(pdata->
leds
.num_leds <= 0 || pdata->
leds
.num_leds > 4) {
107
dev_err
(&client->
dev
,
"board info must claim at most 4 LEDs"
);
108
return
-
EINVAL
;
109
}
110
}
111
112
pca9633 =
devm_kzalloc
(&client->
dev
, 4 *
sizeof
(*pca9633),
GFP_KERNEL
);
113
if
(!pca9633)
114
return
-
ENOMEM
;
115
116
i2c_set_clientdata(client, pca9633);
117
118
for
(i = 0; i < 4; i++) {
119
pca9633[
i
].
client
=
client
;
120
pca9633[
i
].
led_num
=
i
;
121
122
/* Platform data can specify LED names and default triggers */
123
if
(pdata && i < pdata->
leds
.num_leds) {
124
if
(pdata->
leds
.leds[i].name)
125
snprintf
(pca9633[i].
name
,
126
sizeof
(pca9633[i].name),
"pca9633:%s"
,
127
pdata->
leds
.leds[i].name);
128
if
(pdata->
leds
.leds[i].default_trigger)
129
pca9633[
i
].
led_cdev
.default_trigger =
130
pdata->
leds
.leds[
i
].default_trigger;
131
}
else
{
132
snprintf
(pca9633[i].name,
sizeof
(pca9633[i].name),
133
"pca9633:%d"
, i);
134
}
135
136
pca9633[
i
].
led_cdev
.name = pca9633[
i
].
name
;
137
pca9633[
i
].
led_cdev
.brightness_set = pca9633_led_set;
138
139
INIT_WORK
(&pca9633[i].
work
, pca9633_led_work);
140
141
err =
led_classdev_register
(&client->
dev
, &pca9633[i].
led_cdev
);
142
if
(err < 0)
143
goto
exit
;
144
}
145
146
/* Disable LED all-call address and set normal mode */
147
i2c_smbus_write_byte_data
(client,
PCA9633_MODE1
, 0x00);
148
149
/* Configure output: open-drain or totem pole (push-pull) */
150
if
(pdata && pdata->
outdrv
==
PCA9633_OPEN_DRAIN
)
151
i2c_smbus_write_byte_data
(client,
PCA9633_MODE2
, 0x01);
152
153
/* Turn off LEDs */
154
i2c_smbus_write_byte_data
(client,
PCA9633_LEDOUT
, 0x00);
155
156
return
0;
157
158
exit
:
159
while
(i--) {
160
led_classdev_unregister
(&pca9633[i].led_cdev);
161
cancel_work_sync
(&pca9633[i].
work
);
162
}
163
164
return
err
;
165
}
166
167
static
int
__devexit
pca9633_remove(
struct
i2c_client
*client)
168
{
169
struct
pca9633_led
*pca9633 = i2c_get_clientdata(client);
170
int
i
;
171
172
for
(i = 0; i < 4; i++) {
173
led_classdev_unregister
(&pca9633[i].
led_cdev
);
174
cancel_work_sync
(&pca9633[i].
work
);
175
}
176
177
return
0;
178
}
179
180
static
struct
i2c_driver
pca9633_driver = {
181
.driver = {
182
.name =
"leds-pca9633"
,
183
.owner =
THIS_MODULE
,
184
},
185
.probe = pca9633_probe,
186
.remove =
__devexit_p
(pca9633_remove),
187
.id_table = pca9633_id,
188
};
189
190
module_i2c_driver
(pca9633_driver);
191
192
MODULE_AUTHOR
(
"Peter Meerwald <
[email protected]
>"
);
193
MODULE_DESCRIPTION
(
"PCA9633 LED driver"
);
194
MODULE_LICENSE
(
"GPL v2"
);
Generated on Thu Jan 10 2013 13:43:03 for Linux Kernel by
1.8.2