diff options
author | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-08-08 11:17:27 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-11 05:38:09 -0400 |
commit | 894fc8f2c295373e6c73943d8bc2023cc49b9bb0 (patch) | |
tree | cdb7484175436b0737596bbebf427363a641f49a /drivers/leds | |
parent | a6ccdcd98c39ac13508570dbd943a1cf1b569f55 (diff) |
mfd: 88pm860x: Use REG in leds resource
Since the resources of 88pm860x leds are changed from IORESOURCE_IO
to IORESOURCE_REG that is register offset, change the original
self-defined IORESOURCE_IO to register offset.
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/leds-88pm860x.c | 176 |
1 files changed, 69 insertions, 107 deletions
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index ea2615b25082..70232b1756f9 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -20,18 +20,12 @@ | |||
20 | #include <linux/mfd/88pm860x.h> | 20 | #include <linux/mfd/88pm860x.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | 22 | ||
23 | #define LED_PWM_SHIFT (3) | ||
24 | #define LED_PWM_MASK (0x1F) | 23 | #define LED_PWM_MASK (0x1F) |
25 | #define LED_CURRENT_MASK (0x07 << 5) | 24 | #define LED_CURRENT_MASK (0x07 << 5) |
26 | 25 | ||
27 | #define LED_BLINK_ON_MASK (0x07) | ||
28 | #define LED_BLINK_MASK (0x7F) | 26 | #define LED_BLINK_MASK (0x7F) |
29 | 27 | ||
30 | #define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66) | ||
31 | #define LED_BLINK_ON_MIN LED_BLINK_ON(0) | ||
32 | #define LED_BLINK_ON_MAX LED_BLINK_ON(0x7) | ||
33 | #define LED_ON_CONTINUOUS (0x0F << 3) | 28 | #define LED_ON_CONTINUOUS (0x0F << 3) |
34 | #define LED_TO_ON(x) ((x - 66) / 66) | ||
35 | 29 | ||
36 | #define LED1_BLINK_EN (1 << 1) | 30 | #define LED1_BLINK_EN (1 << 1) |
37 | #define LED2_BLINK_EN (1 << 2) | 31 | #define LED2_BLINK_EN (1 << 2) |
@@ -49,85 +43,25 @@ struct pm860x_led { | |||
49 | unsigned char brightness; | 43 | unsigned char brightness; |
50 | unsigned char current_brightness; | 44 | unsigned char current_brightness; |
51 | 45 | ||
52 | int blink_data; | 46 | int reg_control; |
53 | int blink_time; | 47 | int reg_blink; |
54 | int blink_on; | 48 | int blink_mask; |
55 | int blink_off; | ||
56 | }; | 49 | }; |
57 | 50 | ||
58 | /* return offset of color register */ | ||
59 | static inline int __led_off(int port) | ||
60 | { | ||
61 | int ret = -EINVAL; | ||
62 | |||
63 | switch (port) { | ||
64 | case PM8606_LED1_RED: | ||
65 | case PM8606_LED1_GREEN: | ||
66 | case PM8606_LED1_BLUE: | ||
67 | ret = port - PM8606_LED1_RED + PM8606_RGB1B; | ||
68 | break; | ||
69 | case PM8606_LED2_RED: | ||
70 | case PM8606_LED2_GREEN: | ||
71 | case PM8606_LED2_BLUE: | ||
72 | ret = port - PM8606_LED2_RED + PM8606_RGB2B; | ||
73 | break; | ||
74 | } | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | /* return offset of blink register */ | ||
79 | static inline int __blink_off(int port) | ||
80 | { | ||
81 | int ret = -EINVAL; | ||
82 | |||
83 | switch (port) { | ||
84 | case PM8606_LED1_RED: | ||
85 | case PM8606_LED1_GREEN: | ||
86 | case PM8606_LED1_BLUE: | ||
87 | ret = PM8606_RGB1A; | ||
88 | break; | ||
89 | case PM8606_LED2_RED: | ||
90 | case PM8606_LED2_GREEN: | ||
91 | case PM8606_LED2_BLUE: | ||
92 | ret = PM8606_RGB2A; | ||
93 | break; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static inline int __blink_ctl_mask(int port) | ||
99 | { | ||
100 | int ret = -EINVAL; | ||
101 | |||
102 | switch (port) { | ||
103 | case PM8606_LED1_RED: | ||
104 | case PM8606_LED1_GREEN: | ||
105 | case PM8606_LED1_BLUE: | ||
106 | ret = LED1_BLINK_EN; | ||
107 | break; | ||
108 | case PM8606_LED2_RED: | ||
109 | case PM8606_LED2_GREEN: | ||
110 | case PM8606_LED2_BLUE: | ||
111 | ret = LED2_BLINK_EN; | ||
112 | break; | ||
113 | } | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int led_power_set(struct pm860x_chip *chip, int port, int on) | 51 | static int led_power_set(struct pm860x_chip *chip, int port, int on) |
118 | { | 52 | { |
119 | int ret = -EINVAL; | 53 | int ret = -EINVAL; |
120 | 54 | ||
121 | switch (port) { | 55 | switch (port) { |
122 | case PM8606_LED1_RED: | 56 | case 0: |
123 | case PM8606_LED1_GREEN: | 57 | case 1: |
124 | case PM8606_LED1_BLUE: | 58 | case 2: |
125 | ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) : | 59 | ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) : |
126 | pm8606_osc_disable(chip, RGB1_ENABLE); | 60 | pm8606_osc_disable(chip, RGB1_ENABLE); |
127 | break; | 61 | break; |
128 | case PM8606_LED2_RED: | 62 | case 3: |
129 | case PM8606_LED2_GREEN: | 63 | case 4: |
130 | case PM8606_LED2_BLUE: | 64 | case 5: |
131 | ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) : | 65 | ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) : |
132 | pm8606_osc_disable(chip, RGB2_ENABLE); | 66 | pm8606_osc_disable(chip, RGB2_ENABLE); |
133 | break; | 67 | break; |
@@ -141,7 +75,7 @@ static void pm860x_led_work(struct work_struct *work) | |||
141 | struct pm860x_led *led; | 75 | struct pm860x_led *led; |
142 | struct pm860x_chip *chip; | 76 | struct pm860x_chip *chip; |
143 | unsigned char buf[3]; | 77 | unsigned char buf[3]; |
144 | int mask, ret; | 78 | int ret; |
145 | 79 | ||
146 | led = container_of(work, struct pm860x_led, work); | 80 | led = container_of(work, struct pm860x_led, work); |
147 | chip = led->chip; | 81 | chip = led->chip; |
@@ -149,34 +83,34 @@ static void pm860x_led_work(struct work_struct *work) | |||
149 | if ((led->current_brightness == 0) && led->brightness) { | 83 | if ((led->current_brightness == 0) && led->brightness) { |
150 | led_power_set(chip, led->port, 1); | 84 | led_power_set(chip, led->port, 1); |
151 | if (led->iset) { | 85 | if (led->iset) { |
152 | pm860x_set_bits(led->i2c, __led_off(led->port), | 86 | pm860x_set_bits(led->i2c, led->reg_control, |
153 | LED_CURRENT_MASK, led->iset); | 87 | LED_CURRENT_MASK, led->iset); |
154 | } | 88 | } |
155 | pm860x_set_bits(led->i2c, __blink_off(led->port), | 89 | pm860x_set_bits(led->i2c, led->reg_blink, |
156 | LED_BLINK_MASK, LED_ON_CONTINUOUS); | 90 | LED_BLINK_MASK, LED_ON_CONTINUOUS); |
157 | mask = __blink_ctl_mask(led->port); | 91 | pm860x_set_bits(led->i2c, PM8606_WLED3B, led->blink_mask, |
158 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); | 92 | led->blink_mask); |
159 | } | 93 | } |
160 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, | 94 | pm860x_set_bits(led->i2c, led->reg_control, LED_PWM_MASK, |
161 | led->brightness); | 95 | led->brightness); |
162 | 96 | ||
163 | if (led->brightness == 0) { | 97 | if (led->brightness == 0) { |
164 | pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf); | 98 | pm860x_bulk_read(led->i2c, led->reg_control, 3, buf); |
165 | ret = buf[0] & LED_PWM_MASK; | 99 | ret = buf[0] & LED_PWM_MASK; |
166 | ret |= buf[1] & LED_PWM_MASK; | 100 | ret |= buf[1] & LED_PWM_MASK; |
167 | ret |= buf[2] & LED_PWM_MASK; | 101 | ret |= buf[2] & LED_PWM_MASK; |
168 | if (ret == 0) { | 102 | if (ret == 0) { |
169 | /* unset current since no led is lighting */ | 103 | /* unset current since no led is lighting */ |
170 | pm860x_set_bits(led->i2c, __led_off(led->port), | 104 | pm860x_set_bits(led->i2c, led->reg_control, |
171 | LED_CURRENT_MASK, 0); | 105 | LED_CURRENT_MASK, 0); |
172 | mask = __blink_ctl_mask(led->port); | 106 | pm860x_set_bits(led->i2c, PM8606_WLED3B, |
173 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | 107 | led->blink_mask, 0); |
174 | led_power_set(chip, led->port, 0); | 108 | led_power_set(chip, led->port, 0); |
175 | } | 109 | } |
176 | } | 110 | } |
177 | led->current_brightness = led->brightness; | 111 | led->current_brightness = led->brightness; |
178 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | 112 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", |
179 | __led_off(led->port), led->brightness); | 113 | led->reg_control, led->brightness); |
180 | mutex_unlock(&led->lock); | 114 | mutex_unlock(&led->lock); |
181 | } | 115 | } |
182 | 116 | ||
@@ -192,36 +126,61 @@ static void pm860x_led_set(struct led_classdev *cdev, | |||
192 | static int pm860x_led_probe(struct platform_device *pdev) | 126 | static int pm860x_led_probe(struct platform_device *pdev) |
193 | { | 127 | { |
194 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 128 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
195 | struct pm860x_led_pdata *pdata; | 129 | struct pm860x_led_pdata *pdata = pdev->dev.platform_data; |
196 | struct pm860x_led *data; | 130 | struct pm860x_led *data; |
197 | struct resource *res; | 131 | struct resource *res; |
198 | int ret; | 132 | int ret = 0; |
199 | |||
200 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); | ||
201 | if (res == NULL) { | ||
202 | dev_err(&pdev->dev, "No I/O resource!\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | pdata = pdev->dev.platform_data; | ||
207 | if (pdata == NULL) { | ||
208 | dev_err(&pdev->dev, "No platform data!\n"); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 133 | ||
212 | data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL); | 134 | data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL); |
213 | if (data == NULL) | 135 | if (data == NULL) |
214 | return -ENOMEM; | 136 | return -ENOMEM; |
215 | strncpy(data->name, res->name, MFD_NAME_SIZE - 1); | 137 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control"); |
138 | if (!res) { | ||
139 | dev_err(&pdev->dev, "No REG resource for control\n"); | ||
140 | ret = -ENXIO; | ||
141 | goto out; | ||
142 | } | ||
143 | data->reg_control = res->start; | ||
144 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink"); | ||
145 | if (!res) { | ||
146 | dev_err(&pdev->dev, "No REG resource for blink\n"); | ||
147 | ret = -ENXIO; | ||
148 | goto out; | ||
149 | } | ||
150 | data->reg_blink = res->start; | ||
151 | memset(data->name, 0, MFD_NAME_SIZE); | ||
152 | switch (pdev->id) { | ||
153 | case 0: | ||
154 | data->blink_mask = LED1_BLINK_EN; | ||
155 | sprintf(data->name, "led0-red"); | ||
156 | break; | ||
157 | case 1: | ||
158 | data->blink_mask = LED1_BLINK_EN; | ||
159 | sprintf(data->name, "led0-green"); | ||
160 | break; | ||
161 | case 2: | ||
162 | data->blink_mask = LED1_BLINK_EN; | ||
163 | sprintf(data->name, "led0-blue"); | ||
164 | break; | ||
165 | case 3: | ||
166 | data->blink_mask = LED2_BLINK_EN; | ||
167 | sprintf(data->name, "led1-red"); | ||
168 | break; | ||
169 | case 4: | ||
170 | data->blink_mask = LED2_BLINK_EN; | ||
171 | sprintf(data->name, "led1-green"); | ||
172 | break; | ||
173 | case 5: | ||
174 | data->blink_mask = LED2_BLINK_EN; | ||
175 | sprintf(data->name, "led1-blue"); | ||
176 | break; | ||
177 | } | ||
216 | dev_set_drvdata(&pdev->dev, data); | 178 | dev_set_drvdata(&pdev->dev, data); |
217 | data->chip = chip; | 179 | data->chip = chip; |
218 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; | 180 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
219 | data->iset = pdata->iset; | 181 | data->port = pdev->id; |
220 | data->port = pdata->flags; | 182 | if (pdata && pdata->iset) |
221 | if (data->port < 0) { | 183 | data->iset = pdata->iset; |
222 | dev_err(&pdev->dev, "check device failed\n"); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | 184 | ||
226 | data->current_brightness = 0; | 185 | data->current_brightness = 0; |
227 | data->cdev.name = data->name; | 186 | data->cdev.name = data->name; |
@@ -236,6 +195,9 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
236 | } | 195 | } |
237 | pm860x_led_set(&data->cdev, 0); | 196 | pm860x_led_set(&data->cdev, 0); |
238 | return 0; | 197 | return 0; |
198 | out: | ||
199 | devm_kfree(&pdev->dev, data); | ||
200 | return ret; | ||
239 | } | 201 | } |
240 | 202 | ||
241 | static int pm860x_led_remove(struct platform_device *pdev) | 203 | static int pm860x_led_remove(struct platform_device *pdev) |