Root/
1 | /* |
2 | * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver. |
3 | * Chip is combined proximity and ambient light sensor. |
4 | * |
5 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
6 | * |
7 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> |
8 | * |
9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License |
11 | * version 2 as published by the Free Software Foundation. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
21 | * 02110-1301 USA |
22 | * |
23 | */ |
24 | |
25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> |
27 | #include <linux/i2c.h> |
28 | #include <linux/interrupt.h> |
29 | #include <linux/mutex.h> |
30 | #include <linux/i2c/bh1770glc.h> |
31 | #include <linux/regulator/consumer.h> |
32 | #include <linux/pm_runtime.h> |
33 | #include <linux/workqueue.h> |
34 | #include <linux/delay.h> |
35 | #include <linux/wait.h> |
36 | #include <linux/slab.h> |
37 | |
38 | #define BH1770_ALS_CONTROL 0x80 /* ALS operation mode control */ |
39 | #define BH1770_PS_CONTROL 0x81 /* PS operation mode control */ |
40 | #define BH1770_I_LED 0x82 /* active LED and LED1, LED2 current */ |
41 | #define BH1770_I_LED3 0x83 /* LED3 current setting */ |
42 | #define BH1770_ALS_PS_MEAS 0x84 /* Forced mode trigger */ |
43 | #define BH1770_PS_MEAS_RATE 0x85 /* PS meas. rate at stand alone mode */ |
44 | #define BH1770_ALS_MEAS_RATE 0x86 /* ALS meas. rate at stand alone mode */ |
45 | #define BH1770_PART_ID 0x8a /* Part number and revision ID */ |
46 | #define BH1770_MANUFACT_ID 0x8b /* Manufacturerer ID */ |
47 | #define BH1770_ALS_DATA_0 0x8c /* ALS DATA low byte */ |
48 | #define BH1770_ALS_DATA_1 0x8d /* ALS DATA high byte */ |
49 | #define BH1770_ALS_PS_STATUS 0x8e /* Measurement data and int status */ |
50 | #define BH1770_PS_DATA_LED1 0x8f /* PS data from LED1 */ |
51 | #define BH1770_PS_DATA_LED2 0x90 /* PS data from LED2 */ |
52 | #define BH1770_PS_DATA_LED3 0x91 /* PS data from LED3 */ |
53 | #define BH1770_INTERRUPT 0x92 /* Interrupt setting */ |
54 | #define BH1770_PS_TH_LED1 0x93 /* PS interrupt threshold for LED1 */ |
55 | #define BH1770_PS_TH_LED2 0x94 /* PS interrupt threshold for LED2 */ |
56 | #define BH1770_PS_TH_LED3 0x95 /* PS interrupt threshold for LED3 */ |
57 | #define BH1770_ALS_TH_UP_0 0x96 /* ALS upper threshold low byte */ |
58 | #define BH1770_ALS_TH_UP_1 0x97 /* ALS upper threshold high byte */ |
59 | #define BH1770_ALS_TH_LOW_0 0x98 /* ALS lower threshold low byte */ |
60 | #define BH1770_ALS_TH_LOW_1 0x99 /* ALS lower threshold high byte */ |
61 | |
62 | /* MANUFACT_ID */ |
63 | #define BH1770_MANUFACT_ROHM 0x01 |
64 | #define BH1770_MANUFACT_OSRAM 0x03 |
65 | |
66 | /* PART_ID */ |
67 | #define BH1770_PART 0x90 |
68 | #define BH1770_PART_MASK 0xf0 |
69 | #define BH1770_REV_MASK 0x0f |
70 | #define BH1770_REV_SHIFT 0 |
71 | #define BH1770_REV_0 0x00 |
72 | #define BH1770_REV_1 0x01 |
73 | |
74 | /* Operating modes for both */ |
75 | #define BH1770_STANDBY 0x00 |
76 | #define BH1770_FORCED 0x02 |
77 | #define BH1770_STANDALONE 0x03 |
78 | #define BH1770_SWRESET (0x01 << 2) |
79 | |
80 | #define BH1770_PS_TRIG_MEAS (1 << 0) |
81 | #define BH1770_ALS_TRIG_MEAS (1 << 1) |
82 | |
83 | /* Interrupt control */ |
84 | #define BH1770_INT_OUTPUT_MODE (1 << 3) /* 0 = latched */ |
85 | #define BH1770_INT_POLARITY (1 << 2) /* 1 = active high */ |
86 | #define BH1770_INT_ALS_ENA (1 << 1) |
87 | #define BH1770_INT_PS_ENA (1 << 0) |
88 | |
89 | /* Interrupt status */ |
90 | #define BH1770_INT_LED1_DATA (1 << 0) |
91 | #define BH1770_INT_LED1_INT (1 << 1) |
92 | #define BH1770_INT_LED2_DATA (1 << 2) |
93 | #define BH1770_INT_LED2_INT (1 << 3) |
94 | #define BH1770_INT_LED3_DATA (1 << 4) |
95 | #define BH1770_INT_LED3_INT (1 << 5) |
96 | #define BH1770_INT_LEDS_INT ((1 << 1) | (1 << 3) | (1 << 5)) |
97 | #define BH1770_INT_ALS_DATA (1 << 6) |
98 | #define BH1770_INT_ALS_INT (1 << 7) |
99 | |
100 | /* Led channels */ |
101 | #define BH1770_LED1 0x00 |
102 | |
103 | #define BH1770_DISABLE 0 |
104 | #define BH1770_ENABLE 1 |
105 | #define BH1770_PROX_CHANNELS 1 |
106 | |
107 | #define BH1770_LUX_DEFAULT_RATE 1 /* Index to lux rate table */ |
108 | #define BH1770_PROX_DEFAULT_RATE 1 /* Direct HW value =~ 50Hz */ |
109 | #define BH1770_PROX_DEF_RATE_THRESH 6 /* Direct HW value =~ 5 Hz */ |
110 | #define BH1770_STARTUP_DELAY 50 |
111 | #define BH1770_RESET_TIME 10 |
112 | #define BH1770_TIMEOUT 2100 /* Timeout in 2.1 seconds */ |
113 | |
114 | #define BH1770_LUX_RANGE 65535 |
115 | #define BH1770_PROX_RANGE 255 |
116 | #define BH1770_COEF_SCALER 1024 |
117 | #define BH1770_CALIB_SCALER 8192 |
118 | #define BH1770_LUX_NEUTRAL_CALIB_VALUE (1 * BH1770_CALIB_SCALER) |
119 | #define BH1770_LUX_DEF_THRES 1000 |
120 | #define BH1770_PROX_DEF_THRES 70 |
121 | #define BH1770_PROX_DEF_ABS_THRES 100 |
122 | #define BH1770_DEFAULT_PERSISTENCE 10 |
123 | #define BH1770_PROX_MAX_PERSISTENCE 50 |
124 | #define BH1770_LUX_GA_SCALE 16384 |
125 | #define BH1770_LUX_CF_SCALE 2048 /* CF ChipFactor */ |
126 | #define BH1770_NEUTRAL_CF BH1770_LUX_CF_SCALE |
127 | #define BH1770_LUX_CORR_SCALE 4096 |
128 | |
129 | #define PROX_ABOVE_THRESHOLD 1 |
130 | #define PROX_BELOW_THRESHOLD 0 |
131 | |
132 | #define PROX_IGNORE_LUX_LIMIT 500 |
133 | |
134 | struct bh1770_chip { |
135 | struct bh1770_platform_data *pdata; |
136 | char chipname[10]; |
137 | u8 revision; |
138 | struct i2c_client *client; |
139 | struct regulator_bulk_data regs[2]; |
140 | struct mutex mutex; /* avoid parallel access */ |
141 | wait_queue_head_t wait; |
142 | |
143 | bool int_mode_prox; |
144 | bool int_mode_lux; |
145 | struct delayed_work prox_work; |
146 | u32 lux_cf; /* Chip specific factor */ |
147 | u32 lux_ga; |
148 | u32 lux_calib; |
149 | int lux_rate_index; |
150 | u32 lux_corr; |
151 | u16 lux_data_raw; |
152 | u16 lux_threshold_hi; |
153 | u16 lux_threshold_lo; |
154 | u16 lux_thres_hi_onchip; |
155 | u16 lux_thres_lo_onchip; |
156 | bool lux_wait_result; |
157 | |
158 | int prox_enable_count; |
159 | u16 prox_coef; |
160 | u16 prox_const; |
161 | int prox_rate; |
162 | int prox_rate_threshold; |
163 | u8 prox_persistence; |
164 | u8 prox_persistence_counter; |
165 | u8 prox_data; |
166 | u8 prox_threshold; |
167 | u8 prox_threshold_hw; |
168 | bool prox_force_update; |
169 | u8 prox_abs_thres; |
170 | u8 prox_led; |
171 | }; |
172 | |
173 | static const char reg_vcc[] = "Vcc"; |
174 | static const char reg_vleds[] = "Vleds"; |
175 | |
176 | /* |
177 | * Supported stand alone rates in ms from chip data sheet |
178 | * {10, 20, 30, 40, 70, 100, 200, 500, 1000, 2000}; |
179 | */ |
180 | static const s16 prox_rates_hz[] = {100, 50, 33, 25, 14, 10, 5, 2}; |
181 | static const s16 prox_rates_ms[] = {10, 20, 30, 40, 70, 100, 200, 500}; |
182 | |
183 | /* Supported IR-led currents in mA */ |
184 | static const u8 prox_curr_ma[] = {5, 10, 20, 50, 100, 150, 200}; |
185 | |
186 | /* |
187 | * Supported stand alone rates in ms from chip data sheet |
188 | * {100, 200, 500, 1000, 2000}; |
189 | */ |
190 | static const s16 lux_rates_hz[] = {10, 5, 2, 1, 0}; |
191 | |
192 | /* |
193 | * interrupt control functions are called while keeping chip->mutex |
194 | * excluding module probe / remove |
195 | */ |
196 | static inline int bh1770_lux_interrupt_control(struct bh1770_chip *chip, |
197 | int lux) |
198 | { |
199 | chip->int_mode_lux = lux; |
200 | /* Set interrupt modes, interrupt active low, latched */ |
201 | return i2c_smbus_write_byte_data(chip->client, |
202 | BH1770_INTERRUPT, |
203 | (lux << 1) | chip->int_mode_prox); |
204 | } |
205 | |
206 | static inline int bh1770_prox_interrupt_control(struct bh1770_chip *chip, |
207 | int ps) |
208 | { |
209 | chip->int_mode_prox = ps; |
210 | return i2c_smbus_write_byte_data(chip->client, |
211 | BH1770_INTERRUPT, |
212 | (chip->int_mode_lux << 1) | (ps << 0)); |
213 | } |
214 | |
215 | /* chip->mutex is always kept here */ |
216 | static int bh1770_lux_rate(struct bh1770_chip *chip, int rate_index) |
217 | { |
218 | /* sysfs may call this when the chip is powered off */ |
219 | if (pm_runtime_suspended(&chip->client->dev)) |
220 | return 0; |
221 | |
222 | /* Proper proximity response needs fastest lux rate (100ms) */ |
223 | if (chip->prox_enable_count) |
224 | rate_index = 0; |
225 | |
226 | return i2c_smbus_write_byte_data(chip->client, |
227 | BH1770_ALS_MEAS_RATE, |
228 | rate_index); |
229 | } |
230 | |
231 | static int bh1770_prox_rate(struct bh1770_chip *chip, int mode) |
232 | { |
233 | int rate; |
234 | |
235 | rate = (mode == PROX_ABOVE_THRESHOLD) ? |
236 | chip->prox_rate_threshold : chip->prox_rate; |
237 | |
238 | return i2c_smbus_write_byte_data(chip->client, |
239 | BH1770_PS_MEAS_RATE, |
240 | rate); |
241 | } |
242 | |
243 | /* InfraredLED is controlled by the chip during proximity scanning */ |
244 | static inline int bh1770_led_cfg(struct bh1770_chip *chip) |
245 | { |
246 | /* LED cfg, current for leds 1 and 2 */ |
247 | return i2c_smbus_write_byte_data(chip->client, |
248 | BH1770_I_LED, |
249 | (BH1770_LED1 << 6) | |
250 | (BH1770_LED_5mA << 3) | |
251 | chip->prox_led); |
252 | } |
253 | |
254 | /* |
255 | * Following two functions converts raw ps values from HW to normalized |
256 | * values. Purpose is to compensate differences between different sensor |
257 | * versions and variants so that result means about the same between |
258 | * versions. |
259 | */ |
260 | static inline u8 bh1770_psraw_to_adjusted(struct bh1770_chip *chip, u8 psraw) |
261 | { |
262 | u16 adjusted; |
263 | adjusted = (u16)(((u32)(psraw + chip->prox_const) * chip->prox_coef) / |
264 | BH1770_COEF_SCALER); |
265 | if (adjusted > BH1770_PROX_RANGE) |
266 | adjusted = BH1770_PROX_RANGE; |
267 | return adjusted; |
268 | } |
269 | |
270 | static inline u8 bh1770_psadjusted_to_raw(struct bh1770_chip *chip, u8 ps) |
271 | { |
272 | u16 raw; |
273 | |
274 | raw = (((u32)ps * BH1770_COEF_SCALER) / chip->prox_coef); |
275 | if (raw > chip->prox_const) |
276 | raw = raw - chip->prox_const; |
277 | else |
278 | raw = 0; |
279 | return raw; |
280 | } |
281 | |
282 | /* |
283 | * Following two functions converts raw lux values from HW to normalized |
284 | * values. Purpose is to compensate differences between different sensor |
285 | * versions and variants so that result means about the same between |
286 | * versions. Chip->mutex is kept when this is called. |
287 | */ |
288 | static int bh1770_prox_set_threshold(struct bh1770_chip *chip) |
289 | { |
290 | u8 tmp = 0; |
291 | |
292 | /* sysfs may call this when the chip is powered off */ |
293 | if (pm_runtime_suspended(&chip->client->dev)) |
294 | return 0; |
295 | |
296 | tmp = bh1770_psadjusted_to_raw(chip, chip->prox_threshold); |
297 | chip->prox_threshold_hw = tmp; |
298 | |
299 | return i2c_smbus_write_byte_data(chip->client, BH1770_PS_TH_LED1, |
300 | tmp); |
301 | } |
302 | |
303 | static inline u16 bh1770_lux_raw_to_adjusted(struct bh1770_chip *chip, u16 raw) |
304 | { |
305 | u32 lux; |
306 | lux = ((u32)raw * chip->lux_corr) / BH1770_LUX_CORR_SCALE; |
307 | return min(lux, (u32)BH1770_LUX_RANGE); |
308 | } |
309 | |
310 | static inline u16 bh1770_lux_adjusted_to_raw(struct bh1770_chip *chip, |
311 | u16 adjusted) |
312 | { |
313 | return (u32)adjusted * BH1770_LUX_CORR_SCALE / chip->lux_corr; |
314 | } |
315 | |
316 | /* chip->mutex is kept when this is called */ |
317 | static int bh1770_lux_update_thresholds(struct bh1770_chip *chip, |
318 | u16 threshold_hi, u16 threshold_lo) |
319 | { |
320 | u8 data[4]; |
321 | int ret; |
322 | |
323 | /* sysfs may call this when the chip is powered off */ |
324 | if (pm_runtime_suspended(&chip->client->dev)) |
325 | return 0; |
326 | |
327 | /* |
328 | * Compensate threshold values with the correction factors if not |
329 | * set to minimum or maximum. |
330 | * Min & max values disables interrupts. |
331 | */ |
332 | if (threshold_hi != BH1770_LUX_RANGE && threshold_hi != 0) |
333 | threshold_hi = bh1770_lux_adjusted_to_raw(chip, threshold_hi); |
334 | |
335 | if (threshold_lo != BH1770_LUX_RANGE && threshold_lo != 0) |
336 | threshold_lo = bh1770_lux_adjusted_to_raw(chip, threshold_lo); |
337 | |
338 | if (chip->lux_thres_hi_onchip == threshold_hi && |
339 | chip->lux_thres_lo_onchip == threshold_lo) |
340 | return 0; |
341 | |
342 | chip->lux_thres_hi_onchip = threshold_hi; |
343 | chip->lux_thres_lo_onchip = threshold_lo; |
344 | |
345 | data[0] = threshold_hi; |
346 | data[1] = threshold_hi >> 8; |
347 | data[2] = threshold_lo; |
348 | data[3] = threshold_lo >> 8; |
349 | |
350 | ret = i2c_smbus_write_i2c_block_data(chip->client, |
351 | BH1770_ALS_TH_UP_0, |
352 | ARRAY_SIZE(data), |
353 | data); |
354 | return ret; |
355 | } |
356 | |
357 | static int bh1770_lux_get_result(struct bh1770_chip *chip) |
358 | { |
359 | u16 data; |
360 | int ret; |
361 | |
362 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_0); |
363 | if (ret < 0) |
364 | return ret; |
365 | |
366 | data = ret & 0xff; |
367 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_1); |
368 | if (ret < 0) |
369 | return ret; |
370 | |
371 | chip->lux_data_raw = data | ((ret & 0xff) << 8); |
372 | |
373 | return 0; |
374 | } |
375 | |
376 | /* Calculate correction value which contains chip and device specific parts */ |
377 | static u32 bh1770_get_corr_value(struct bh1770_chip *chip) |
378 | { |
379 | u32 tmp; |
380 | /* Impact of glass attenuation correction */ |
381 | tmp = (BH1770_LUX_CORR_SCALE * chip->lux_ga) / BH1770_LUX_GA_SCALE; |
382 | /* Impact of chip factor correction */ |
383 | tmp = (tmp * chip->lux_cf) / BH1770_LUX_CF_SCALE; |
384 | /* Impact of Device specific calibration correction */ |
385 | tmp = (tmp * chip->lux_calib) / BH1770_CALIB_SCALER; |
386 | return tmp; |
387 | } |
388 | |
389 | static int bh1770_lux_read_result(struct bh1770_chip *chip) |
390 | { |
391 | bh1770_lux_get_result(chip); |
392 | return bh1770_lux_raw_to_adjusted(chip, chip->lux_data_raw); |
393 | } |
394 | |
395 | /* |
396 | * Chip on / off functions are called while keeping mutex except probe |
397 | * or remove phase |
398 | */ |
399 | static int bh1770_chip_on(struct bh1770_chip *chip) |
400 | { |
401 | int ret = regulator_bulk_enable(ARRAY_SIZE(chip->regs), |
402 | chip->regs); |
403 | if (ret < 0) |
404 | return ret; |
405 | |
406 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); |
407 | |
408 | /* Reset the chip */ |
409 | i2c_smbus_write_byte_data(chip->client, BH1770_ALS_CONTROL, |
410 | BH1770_SWRESET); |
411 | usleep_range(BH1770_RESET_TIME, BH1770_RESET_TIME * 2); |
412 | |
413 | /* |
414 | * ALS is started always since proximity needs als results |
415 | * for realibility estimation. |
416 | * Let's assume dark until the first ALS measurement is ready. |
417 | */ |
418 | chip->lux_data_raw = 0; |
419 | chip->prox_data = 0; |
420 | ret = i2c_smbus_write_byte_data(chip->client, |
421 | BH1770_ALS_CONTROL, BH1770_STANDALONE); |
422 | |
423 | /* Assume reset defaults */ |
424 | chip->lux_thres_hi_onchip = BH1770_LUX_RANGE; |
425 | chip->lux_thres_lo_onchip = 0; |
426 | |
427 | return ret; |
428 | } |
429 | |
430 | static void bh1770_chip_off(struct bh1770_chip *chip) |
431 | { |
432 | i2c_smbus_write_byte_data(chip->client, |
433 | BH1770_INTERRUPT, BH1770_DISABLE); |
434 | i2c_smbus_write_byte_data(chip->client, |
435 | BH1770_ALS_CONTROL, BH1770_STANDBY); |
436 | i2c_smbus_write_byte_data(chip->client, |
437 | BH1770_PS_CONTROL, BH1770_STANDBY); |
438 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); |
439 | } |
440 | |
441 | /* chip->mutex is kept when this is called */ |
442 | static int bh1770_prox_mode_control(struct bh1770_chip *chip) |
443 | { |
444 | if (chip->prox_enable_count) { |
445 | chip->prox_force_update = true; /* Force immediate update */ |
446 | |
447 | bh1770_lux_rate(chip, chip->lux_rate_index); |
448 | bh1770_prox_set_threshold(chip); |
449 | bh1770_led_cfg(chip); |
450 | bh1770_prox_rate(chip, PROX_BELOW_THRESHOLD); |
451 | bh1770_prox_interrupt_control(chip, BH1770_ENABLE); |
452 | i2c_smbus_write_byte_data(chip->client, |
453 | BH1770_PS_CONTROL, BH1770_STANDALONE); |
454 | } else { |
455 | chip->prox_data = 0; |
456 | bh1770_lux_rate(chip, chip->lux_rate_index); |
457 | bh1770_prox_interrupt_control(chip, BH1770_DISABLE); |
458 | i2c_smbus_write_byte_data(chip->client, |
459 | BH1770_PS_CONTROL, BH1770_STANDBY); |
460 | } |
461 | return 0; |
462 | } |
463 | |
464 | /* chip->mutex is kept when this is called */ |
465 | static int bh1770_prox_read_result(struct bh1770_chip *chip) |
466 | { |
467 | int ret; |
468 | bool above; |
469 | u8 mode; |
470 | |
471 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_PS_DATA_LED1); |
472 | if (ret < 0) |
473 | goto out; |
474 | |
475 | if (ret > chip->prox_threshold_hw) |
476 | above = true; |
477 | else |
478 | above = false; |
479 | |
480 | /* |
481 | * when ALS levels goes above limit, proximity result may be |
482 | * false proximity. Thus ignore the result. With real proximity |
483 | * there is a shadow causing low als levels. |
484 | */ |
485 | if (chip->lux_data_raw > PROX_IGNORE_LUX_LIMIT) |
486 | ret = 0; |
487 | |
488 | chip->prox_data = bh1770_psraw_to_adjusted(chip, ret); |
489 | |
490 | /* Strong proximity level or force mode requires immediate response */ |
491 | if (chip->prox_data >= chip->prox_abs_thres || |
492 | chip->prox_force_update) |
493 | chip->prox_persistence_counter = chip->prox_persistence; |
494 | |
495 | chip->prox_force_update = false; |
496 | |
497 | /* Persistence filttering to reduce false proximity events */ |
498 | if (likely(above)) { |
499 | if (chip->prox_persistence_counter < chip->prox_persistence) { |
500 | chip->prox_persistence_counter++; |
501 | ret = -ENODATA; |
502 | } else { |
503 | mode = PROX_ABOVE_THRESHOLD; |
504 | ret = 0; |
505 | } |
506 | } else { |
507 | chip->prox_persistence_counter = 0; |
508 | mode = PROX_BELOW_THRESHOLD; |
509 | chip->prox_data = 0; |
510 | ret = 0; |
511 | } |
512 | |
513 | /* Set proximity detection rate based on above or below value */ |
514 | if (ret == 0) { |
515 | bh1770_prox_rate(chip, mode); |
516 | sysfs_notify(&chip->client->dev.kobj, NULL, "prox0_raw"); |
517 | } |
518 | out: |
519 | return ret; |
520 | } |
521 | |
522 | static int bh1770_detect(struct bh1770_chip *chip) |
523 | { |
524 | struct i2c_client *client = chip->client; |
525 | s32 ret; |
526 | u8 manu, part; |
527 | |
528 | ret = i2c_smbus_read_byte_data(client, BH1770_MANUFACT_ID); |
529 | if (ret < 0) |
530 | goto error; |
531 | manu = (u8)ret; |
532 | |
533 | ret = i2c_smbus_read_byte_data(client, BH1770_PART_ID); |
534 | if (ret < 0) |
535 | goto error; |
536 | part = (u8)ret; |
537 | |
538 | chip->revision = (part & BH1770_REV_MASK) >> BH1770_REV_SHIFT; |
539 | chip->prox_coef = BH1770_COEF_SCALER; |
540 | chip->prox_const = 0; |
541 | chip->lux_cf = BH1770_NEUTRAL_CF; |
542 | |
543 | if ((manu == BH1770_MANUFACT_ROHM) && |
544 | ((part & BH1770_PART_MASK) == BH1770_PART)) { |
545 | snprintf(chip->chipname, sizeof(chip->chipname), "BH1770GLC"); |
546 | return 0; |
547 | } |
548 | |
549 | if ((manu == BH1770_MANUFACT_OSRAM) && |
550 | ((part & BH1770_PART_MASK) == BH1770_PART)) { |
551 | snprintf(chip->chipname, sizeof(chip->chipname), "SFH7770"); |
552 | /* Values selected by comparing different versions */ |
553 | chip->prox_coef = 819; /* 0.8 * BH1770_COEF_SCALER */ |
554 | chip->prox_const = 40; |
555 | return 0; |
556 | } |
557 | |
558 | ret = -ENODEV; |
559 | error: |
560 | dev_dbg(&client->dev, "BH1770 or SFH7770 not found\n"); |
561 | |
562 | return ret; |
563 | } |
564 | |
565 | /* |
566 | * This work is re-scheduled at every proximity interrupt. |
567 | * If this work is running, it means that there hasn't been any |
568 | * proximity interrupt in time. Situation is handled as no-proximity. |
569 | * It would be nice to have low-threshold interrupt or interrupt |
570 | * when measurement and hi-threshold are both 0. But neither of those exists. |
571 | * This is a workaroud for missing HW feature. |
572 | */ |
573 | |
574 | static void bh1770_prox_work(struct work_struct *work) |
575 | { |
576 | struct bh1770_chip *chip = |
577 | container_of(work, struct bh1770_chip, prox_work.work); |
578 | |
579 | mutex_lock(&chip->mutex); |
580 | bh1770_prox_read_result(chip); |
581 | mutex_unlock(&chip->mutex); |
582 | } |
583 | |
584 | /* This is threaded irq handler */ |
585 | static irqreturn_t bh1770_irq(int irq, void *data) |
586 | { |
587 | struct bh1770_chip *chip = data; |
588 | int status; |
589 | int rate = 0; |
590 | |
591 | mutex_lock(&chip->mutex); |
592 | status = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_PS_STATUS); |
593 | |
594 | /* Acknowledge interrupt by reading this register */ |
595 | i2c_smbus_read_byte_data(chip->client, BH1770_INTERRUPT); |
596 | |
597 | /* |
598 | * Check if there is fresh data available for als. |
599 | * If this is the very first data, update thresholds after that. |
600 | */ |
601 | if (status & BH1770_INT_ALS_DATA) { |
602 | bh1770_lux_get_result(chip); |
603 | if (unlikely(chip->lux_wait_result)) { |
604 | chip->lux_wait_result = false; |
605 | wake_up(&chip->wait); |
606 | bh1770_lux_update_thresholds(chip, |
607 | chip->lux_threshold_hi, |
608 | chip->lux_threshold_lo); |
609 | } |
610 | } |
611 | |
612 | /* Disable interrupt logic to guarantee acknowledgement */ |
613 | i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT, |
614 | (0 << 1) | (0 << 0)); |
615 | |
616 | if ((status & BH1770_INT_ALS_INT)) |
617 | sysfs_notify(&chip->client->dev.kobj, NULL, "lux0_input"); |
618 | |
619 | if (chip->int_mode_prox && (status & BH1770_INT_LEDS_INT)) { |
620 | rate = prox_rates_ms[chip->prox_rate_threshold]; |
621 | bh1770_prox_read_result(chip); |
622 | } |
623 | |
624 | /* Re-enable interrupt logic */ |
625 | i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT, |
626 | (chip->int_mode_lux << 1) | |
627 | (chip->int_mode_prox << 0)); |
628 | mutex_unlock(&chip->mutex); |
629 | |
630 | /* |
631 | * Can't cancel work while keeping mutex since the work uses the |
632 | * same mutex. |
633 | */ |
634 | if (rate) { |
635 | /* |
636 | * Simulate missing no-proximity interrupt 50ms after the |
637 | * next expected interrupt time. |
638 | */ |
639 | cancel_delayed_work_sync(&chip->prox_work); |
640 | schedule_delayed_work(&chip->prox_work, |
641 | msecs_to_jiffies(rate + 50)); |
642 | } |
643 | return IRQ_HANDLED; |
644 | } |
645 | |
646 | static ssize_t bh1770_power_state_store(struct device *dev, |
647 | struct device_attribute *attr, |
648 | const char *buf, size_t count) |
649 | { |
650 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
651 | unsigned long value; |
652 | ssize_t ret; |
653 | |
654 | if (strict_strtoul(buf, 0, &value)) |
655 | return -EINVAL; |
656 | |
657 | mutex_lock(&chip->mutex); |
658 | if (value) { |
659 | pm_runtime_get_sync(dev); |
660 | |
661 | ret = bh1770_lux_rate(chip, chip->lux_rate_index); |
662 | if (ret < 0) { |
663 | pm_runtime_put(dev); |
664 | goto leave; |
665 | } |
666 | |
667 | ret = bh1770_lux_interrupt_control(chip, BH1770_ENABLE); |
668 | if (ret < 0) { |
669 | pm_runtime_put(dev); |
670 | goto leave; |
671 | } |
672 | |
673 | /* This causes interrupt after the next measurement cycle */ |
674 | bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES, |
675 | BH1770_LUX_DEF_THRES); |
676 | /* Inform that we are waiting for a result from ALS */ |
677 | chip->lux_wait_result = true; |
678 | bh1770_prox_mode_control(chip); |
679 | } else if (!pm_runtime_suspended(dev)) { |
680 | pm_runtime_put(dev); |
681 | } |
682 | ret = count; |
683 | leave: |
684 | mutex_unlock(&chip->mutex); |
685 | return ret; |
686 | } |
687 | |
688 | static ssize_t bh1770_power_state_show(struct device *dev, |
689 | struct device_attribute *attr, char *buf) |
690 | { |
691 | return sprintf(buf, "%d\n", !pm_runtime_suspended(dev)); |
692 | } |
693 | |
694 | static ssize_t bh1770_lux_result_show(struct device *dev, |
695 | struct device_attribute *attr, char *buf) |
696 | { |
697 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
698 | ssize_t ret; |
699 | long timeout; |
700 | |
701 | if (pm_runtime_suspended(dev)) |
702 | return -EIO; /* Chip is not enabled at all */ |
703 | |
704 | timeout = wait_event_interruptible_timeout(chip->wait, |
705 | !chip->lux_wait_result, |
706 | msecs_to_jiffies(BH1770_TIMEOUT)); |
707 | if (!timeout) |
708 | return -EIO; |
709 | |
710 | mutex_lock(&chip->mutex); |
711 | ret = sprintf(buf, "%d\n", bh1770_lux_read_result(chip)); |
712 | mutex_unlock(&chip->mutex); |
713 | |
714 | return ret; |
715 | } |
716 | |
717 | static ssize_t bh1770_lux_range_show(struct device *dev, |
718 | struct device_attribute *attr, char *buf) |
719 | { |
720 | return sprintf(buf, "%d\n", BH1770_LUX_RANGE); |
721 | } |
722 | |
723 | static ssize_t bh1770_prox_enable_store(struct device *dev, |
724 | struct device_attribute *attr, |
725 | const char *buf, size_t count) |
726 | { |
727 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
728 | unsigned long value; |
729 | |
730 | if (strict_strtoul(buf, 0, &value)) |
731 | return -EINVAL; |
732 | |
733 | mutex_lock(&chip->mutex); |
734 | /* Assume no proximity. Sensor will tell real state soon */ |
735 | if (!chip->prox_enable_count) |
736 | chip->prox_data = 0; |
737 | |
738 | if (value) |
739 | chip->prox_enable_count++; |
740 | else if (chip->prox_enable_count > 0) |
741 | chip->prox_enable_count--; |
742 | else |
743 | goto leave; |
744 | |
745 | /* Run control only when chip is powered on */ |
746 | if (!pm_runtime_suspended(dev)) |
747 | bh1770_prox_mode_control(chip); |
748 | leave: |
749 | mutex_unlock(&chip->mutex); |
750 | return count; |
751 | } |
752 | |
753 | static ssize_t bh1770_prox_enable_show(struct device *dev, |
754 | struct device_attribute *attr, char *buf) |
755 | { |
756 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
757 | ssize_t len; |
758 | |
759 | mutex_lock(&chip->mutex); |
760 | len = sprintf(buf, "%d\n", chip->prox_enable_count); |
761 | mutex_unlock(&chip->mutex); |
762 | return len; |
763 | } |
764 | |
765 | static ssize_t bh1770_prox_result_show(struct device *dev, |
766 | struct device_attribute *attr, char *buf) |
767 | { |
768 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
769 | ssize_t ret; |
770 | |
771 | mutex_lock(&chip->mutex); |
772 | if (chip->prox_enable_count && !pm_runtime_suspended(dev)) |
773 | ret = sprintf(buf, "%d\n", chip->prox_data); |
774 | else |
775 | ret = -EIO; |
776 | mutex_unlock(&chip->mutex); |
777 | return ret; |
778 | } |
779 | |
780 | static ssize_t bh1770_prox_range_show(struct device *dev, |
781 | struct device_attribute *attr, char *buf) |
782 | { |
783 | return sprintf(buf, "%d\n", BH1770_PROX_RANGE); |
784 | } |
785 | |
786 | static ssize_t bh1770_get_prox_rate_avail(struct device *dev, |
787 | struct device_attribute *attr, char *buf) |
788 | { |
789 | int i; |
790 | int pos = 0; |
791 | for (i = 0; i < ARRAY_SIZE(prox_rates_hz); i++) |
792 | pos += sprintf(buf + pos, "%d ", prox_rates_hz[i]); |
793 | sprintf(buf + pos - 1, "\n"); |
794 | return pos; |
795 | } |
796 | |
797 | static ssize_t bh1770_get_prox_rate_above(struct device *dev, |
798 | struct device_attribute *attr, char *buf) |
799 | { |
800 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
801 | return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate_threshold]); |
802 | } |
803 | |
804 | static ssize_t bh1770_get_prox_rate_below(struct device *dev, |
805 | struct device_attribute *attr, char *buf) |
806 | { |
807 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
808 | return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate]); |
809 | } |
810 | |
811 | static int bh1770_prox_rate_validate(int rate) |
812 | { |
813 | int i; |
814 | |
815 | for (i = 0; i < ARRAY_SIZE(prox_rates_hz) - 1; i++) |
816 | if (rate >= prox_rates_hz[i]) |
817 | break; |
818 | return i; |
819 | } |
820 | |
821 | static ssize_t bh1770_set_prox_rate_above(struct device *dev, |
822 | struct device_attribute *attr, |
823 | const char *buf, size_t count) |
824 | { |
825 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
826 | unsigned long value; |
827 | |
828 | if (strict_strtoul(buf, 0, &value)) |
829 | return -EINVAL; |
830 | |
831 | mutex_lock(&chip->mutex); |
832 | chip->prox_rate_threshold = bh1770_prox_rate_validate(value); |
833 | mutex_unlock(&chip->mutex); |
834 | return count; |
835 | } |
836 | |
837 | static ssize_t bh1770_set_prox_rate_below(struct device *dev, |
838 | struct device_attribute *attr, |
839 | const char *buf, size_t count) |
840 | { |
841 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
842 | unsigned long value; |
843 | |
844 | if (strict_strtoul(buf, 0, &value)) |
845 | return -EINVAL; |
846 | |
847 | mutex_lock(&chip->mutex); |
848 | chip->prox_rate = bh1770_prox_rate_validate(value); |
849 | mutex_unlock(&chip->mutex); |
850 | return count; |
851 | } |
852 | |
853 | static ssize_t bh1770_get_prox_thres(struct device *dev, |
854 | struct device_attribute *attr, char *buf) |
855 | { |
856 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
857 | return sprintf(buf, "%d\n", chip->prox_threshold); |
858 | } |
859 | |
860 | static ssize_t bh1770_set_prox_thres(struct device *dev, |
861 | struct device_attribute *attr, |
862 | const char *buf, size_t count) |
863 | { |
864 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
865 | unsigned long value; |
866 | int ret; |
867 | |
868 | if (strict_strtoul(buf, 0, &value)) |
869 | return -EINVAL; |
870 | if (value > BH1770_PROX_RANGE) |
871 | return -EINVAL; |
872 | |
873 | mutex_lock(&chip->mutex); |
874 | chip->prox_threshold = value; |
875 | ret = bh1770_prox_set_threshold(chip); |
876 | mutex_unlock(&chip->mutex); |
877 | if (ret < 0) |
878 | return ret; |
879 | return count; |
880 | } |
881 | |
882 | static ssize_t bh1770_prox_persistence_show(struct device *dev, |
883 | struct device_attribute *attr, char *buf) |
884 | { |
885 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
886 | |
887 | return sprintf(buf, "%u\n", chip->prox_persistence); |
888 | } |
889 | |
890 | static ssize_t bh1770_prox_persistence_store(struct device *dev, |
891 | struct device_attribute *attr, |
892 | const char *buf, size_t len) |
893 | { |
894 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
895 | unsigned long value; |
896 | |
897 | if (strict_strtoul(buf, 0, &value)) |
898 | return -EINVAL; |
899 | |
900 | if (value > BH1770_PROX_MAX_PERSISTENCE) |
901 | return -EINVAL; |
902 | |
903 | chip->prox_persistence = value; |
904 | |
905 | return len; |
906 | } |
907 | |
908 | static ssize_t bh1770_prox_abs_thres_show(struct device *dev, |
909 | struct device_attribute *attr, char *buf) |
910 | { |
911 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
912 | return sprintf(buf, "%u\n", chip->prox_abs_thres); |
913 | } |
914 | |
915 | static ssize_t bh1770_prox_abs_thres_store(struct device *dev, |
916 | struct device_attribute *attr, |
917 | const char *buf, size_t len) |
918 | { |
919 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
920 | unsigned long value; |
921 | |
922 | if (strict_strtoul(buf, 0, &value)) |
923 | return -EINVAL; |
924 | |
925 | if (value > BH1770_PROX_RANGE) |
926 | return -EINVAL; |
927 | |
928 | chip->prox_abs_thres = value; |
929 | |
930 | return len; |
931 | } |
932 | |
933 | static ssize_t bh1770_chip_id_show(struct device *dev, |
934 | struct device_attribute *attr, char *buf) |
935 | { |
936 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
937 | return sprintf(buf, "%s rev %d\n", chip->chipname, chip->revision); |
938 | } |
939 | |
940 | static ssize_t bh1770_lux_calib_default_show(struct device *dev, |
941 | struct device_attribute *attr, char *buf) |
942 | { |
943 | return sprintf(buf, "%u\n", BH1770_CALIB_SCALER); |
944 | } |
945 | |
946 | static ssize_t bh1770_lux_calib_show(struct device *dev, |
947 | struct device_attribute *attr, char *buf) |
948 | { |
949 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
950 | ssize_t len; |
951 | |
952 | mutex_lock(&chip->mutex); |
953 | len = sprintf(buf, "%u\n", chip->lux_calib); |
954 | mutex_unlock(&chip->mutex); |
955 | return len; |
956 | } |
957 | |
958 | static ssize_t bh1770_lux_calib_store(struct device *dev, |
959 | struct device_attribute *attr, |
960 | const char *buf, size_t len) |
961 | { |
962 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
963 | unsigned long value; |
964 | u32 old_calib; |
965 | u32 new_corr; |
966 | |
967 | if (strict_strtoul(buf, 0, &value)) |
968 | return -EINVAL; |
969 | |
970 | mutex_lock(&chip->mutex); |
971 | old_calib = chip->lux_calib; |
972 | chip->lux_calib = value; |
973 | new_corr = bh1770_get_corr_value(chip); |
974 | if (new_corr == 0) { |
975 | chip->lux_calib = old_calib; |
976 | mutex_unlock(&chip->mutex); |
977 | return -EINVAL; |
978 | } |
979 | chip->lux_corr = new_corr; |
980 | /* Refresh thresholds on HW after changing correction value */ |
981 | bh1770_lux_update_thresholds(chip, chip->lux_threshold_hi, |
982 | chip->lux_threshold_lo); |
983 | |
984 | mutex_unlock(&chip->mutex); |
985 | |
986 | return len; |
987 | } |
988 | |
989 | static ssize_t bh1770_get_lux_rate_avail(struct device *dev, |
990 | struct device_attribute *attr, char *buf) |
991 | { |
992 | int i; |
993 | int pos = 0; |
994 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz); i++) |
995 | pos += sprintf(buf + pos, "%d ", lux_rates_hz[i]); |
996 | sprintf(buf + pos - 1, "\n"); |
997 | return pos; |
998 | } |
999 | |
1000 | static ssize_t bh1770_get_lux_rate(struct device *dev, |
1001 | struct device_attribute *attr, char *buf) |
1002 | { |
1003 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1004 | return sprintf(buf, "%d\n", lux_rates_hz[chip->lux_rate_index]); |
1005 | } |
1006 | |
1007 | static ssize_t bh1770_set_lux_rate(struct device *dev, |
1008 | struct device_attribute *attr, |
1009 | const char *buf, size_t count) |
1010 | { |
1011 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1012 | unsigned long rate_hz; |
1013 | int ret, i; |
1014 | |
1015 | if (strict_strtoul(buf, 0, &rate_hz)) |
1016 | return -EINVAL; |
1017 | |
1018 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++) |
1019 | if (rate_hz >= lux_rates_hz[i]) |
1020 | break; |
1021 | |
1022 | mutex_lock(&chip->mutex); |
1023 | chip->lux_rate_index = i; |
1024 | ret = bh1770_lux_rate(chip, i); |
1025 | mutex_unlock(&chip->mutex); |
1026 | |
1027 | if (ret < 0) |
1028 | return ret; |
1029 | |
1030 | return count; |
1031 | } |
1032 | |
1033 | static ssize_t bh1770_get_lux_thresh_above(struct device *dev, |
1034 | struct device_attribute *attr, char *buf) |
1035 | { |
1036 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1037 | return sprintf(buf, "%d\n", chip->lux_threshold_hi); |
1038 | } |
1039 | |
1040 | static ssize_t bh1770_get_lux_thresh_below(struct device *dev, |
1041 | struct device_attribute *attr, char *buf) |
1042 | { |
1043 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1044 | return sprintf(buf, "%d\n", chip->lux_threshold_lo); |
1045 | } |
1046 | |
1047 | static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target, |
1048 | const char *buf) |
1049 | { |
1050 | int ret = 0; |
1051 | unsigned long thresh; |
1052 | |
1053 | if (strict_strtoul(buf, 0, &thresh)) |
1054 | return -EINVAL; |
1055 | |
1056 | if (thresh > BH1770_LUX_RANGE) |
1057 | return -EINVAL; |
1058 | |
1059 | mutex_lock(&chip->mutex); |
1060 | *target = thresh; |
1061 | /* |
1062 | * Don't update values in HW if we are still waiting for |
1063 | * first interrupt to come after device handle open call. |
1064 | */ |
1065 | if (!chip->lux_wait_result) |
1066 | ret = bh1770_lux_update_thresholds(chip, |
1067 | chip->lux_threshold_hi, |
1068 | chip->lux_threshold_lo); |
1069 | mutex_unlock(&chip->mutex); |
1070 | return ret; |
1071 | |
1072 | } |
1073 | |
1074 | static ssize_t bh1770_set_lux_thresh_above(struct device *dev, |
1075 | struct device_attribute *attr, |
1076 | const char *buf, size_t len) |
1077 | { |
1078 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1079 | int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_hi, buf); |
1080 | if (ret < 0) |
1081 | return ret; |
1082 | return len; |
1083 | } |
1084 | |
1085 | static ssize_t bh1770_set_lux_thresh_below(struct device *dev, |
1086 | struct device_attribute *attr, |
1087 | const char *buf, size_t len) |
1088 | { |
1089 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
1090 | int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_lo, buf); |
1091 | if (ret < 0) |
1092 | return ret; |
1093 | return len; |
1094 | } |
1095 | |
1096 | static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, bh1770_prox_enable_show, |
1097 | bh1770_prox_enable_store); |
1098 | static DEVICE_ATTR(prox0_thresh_above1_value, S_IRUGO | S_IWUSR, |
1099 | bh1770_prox_abs_thres_show, |
1100 | bh1770_prox_abs_thres_store); |
1101 | static DEVICE_ATTR(prox0_thresh_above0_value, S_IRUGO | S_IWUSR, |
1102 | bh1770_get_prox_thres, |
1103 | bh1770_set_prox_thres); |
1104 | static DEVICE_ATTR(prox0_raw, S_IRUGO, bh1770_prox_result_show, NULL); |
1105 | static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, bh1770_prox_range_show, NULL); |
1106 | static DEVICE_ATTR(prox0_thresh_above_count, S_IRUGO | S_IWUSR, |
1107 | bh1770_prox_persistence_show, |
1108 | bh1770_prox_persistence_store); |
1109 | static DEVICE_ATTR(prox0_rate_above, S_IRUGO | S_IWUSR, |
1110 | bh1770_get_prox_rate_above, |
1111 | bh1770_set_prox_rate_above); |
1112 | static DEVICE_ATTR(prox0_rate_below, S_IRUGO | S_IWUSR, |
1113 | bh1770_get_prox_rate_below, |
1114 | bh1770_set_prox_rate_below); |
1115 | static DEVICE_ATTR(prox0_rate_avail, S_IRUGO, bh1770_get_prox_rate_avail, NULL); |
1116 | |
1117 | static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, bh1770_lux_calib_show, |
1118 | bh1770_lux_calib_store); |
1119 | static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO, |
1120 | bh1770_lux_calib_default_show, |
1121 | NULL); |
1122 | static DEVICE_ATTR(lux0_input, S_IRUGO, bh1770_lux_result_show, NULL); |
1123 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, bh1770_lux_range_show, NULL); |
1124 | static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, bh1770_get_lux_rate, |
1125 | bh1770_set_lux_rate); |
1126 | static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, bh1770_get_lux_rate_avail, NULL); |
1127 | static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR, |
1128 | bh1770_get_lux_thresh_above, |
1129 | bh1770_set_lux_thresh_above); |
1130 | static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR, |
1131 | bh1770_get_lux_thresh_below, |
1132 | bh1770_set_lux_thresh_below); |
1133 | static DEVICE_ATTR(chip_id, S_IRUGO, bh1770_chip_id_show, NULL); |
1134 | static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, bh1770_power_state_show, |
1135 | bh1770_power_state_store); |
1136 | |
1137 | |
1138 | static struct attribute *sysfs_attrs[] = { |
1139 | &dev_attr_lux0_calibscale.attr, |
1140 | &dev_attr_lux0_calibscale_default.attr, |
1141 | &dev_attr_lux0_input.attr, |
1142 | &dev_attr_lux0_sensor_range.attr, |
1143 | &dev_attr_lux0_rate.attr, |
1144 | &dev_attr_lux0_rate_avail.attr, |
1145 | &dev_attr_lux0_thresh_above_value.attr, |
1146 | &dev_attr_lux0_thresh_below_value.attr, |
1147 | &dev_attr_prox0_raw.attr, |
1148 | &dev_attr_prox0_sensor_range.attr, |
1149 | &dev_attr_prox0_raw_en.attr, |
1150 | &dev_attr_prox0_thresh_above_count.attr, |
1151 | &dev_attr_prox0_rate_above.attr, |
1152 | &dev_attr_prox0_rate_below.attr, |
1153 | &dev_attr_prox0_rate_avail.attr, |
1154 | &dev_attr_prox0_thresh_above0_value.attr, |
1155 | &dev_attr_prox0_thresh_above1_value.attr, |
1156 | &dev_attr_chip_id.attr, |
1157 | &dev_attr_power_state.attr, |
1158 | NULL |
1159 | }; |
1160 | |
1161 | static struct attribute_group bh1770_attribute_group = { |
1162 | .attrs = sysfs_attrs |
1163 | }; |
1164 | |
1165 | static int __devinit bh1770_probe(struct i2c_client *client, |
1166 | const struct i2c_device_id *id) |
1167 | { |
1168 | struct bh1770_chip *chip; |
1169 | int err; |
1170 | |
1171 | chip = kzalloc(sizeof *chip, GFP_KERNEL); |
1172 | if (!chip) |
1173 | return -ENOMEM; |
1174 | |
1175 | i2c_set_clientdata(client, chip); |
1176 | chip->client = client; |
1177 | |
1178 | mutex_init(&chip->mutex); |
1179 | init_waitqueue_head(&chip->wait); |
1180 | INIT_DELAYED_WORK(&chip->prox_work, bh1770_prox_work); |
1181 | |
1182 | if (client->dev.platform_data == NULL) { |
1183 | dev_err(&client->dev, "platform data is mandatory\n"); |
1184 | err = -EINVAL; |
1185 | goto fail1; |
1186 | } |
1187 | |
1188 | chip->pdata = client->dev.platform_data; |
1189 | chip->lux_calib = BH1770_LUX_NEUTRAL_CALIB_VALUE; |
1190 | chip->lux_rate_index = BH1770_LUX_DEFAULT_RATE; |
1191 | chip->lux_threshold_lo = BH1770_LUX_DEF_THRES; |
1192 | chip->lux_threshold_hi = BH1770_LUX_DEF_THRES; |
1193 | |
1194 | if (chip->pdata->glass_attenuation == 0) |
1195 | chip->lux_ga = BH1770_NEUTRAL_GA; |
1196 | else |
1197 | chip->lux_ga = chip->pdata->glass_attenuation; |
1198 | |
1199 | chip->prox_threshold = BH1770_PROX_DEF_THRES; |
1200 | chip->prox_led = chip->pdata->led_def_curr; |
1201 | chip->prox_abs_thres = BH1770_PROX_DEF_ABS_THRES; |
1202 | chip->prox_persistence = BH1770_DEFAULT_PERSISTENCE; |
1203 | chip->prox_rate_threshold = BH1770_PROX_DEF_RATE_THRESH; |
1204 | chip->prox_rate = BH1770_PROX_DEFAULT_RATE; |
1205 | chip->prox_data = 0; |
1206 | |
1207 | chip->regs[0].supply = reg_vcc; |
1208 | chip->regs[1].supply = reg_vleds; |
1209 | |
1210 | err = regulator_bulk_get(&client->dev, |
1211 | ARRAY_SIZE(chip->regs), chip->regs); |
1212 | if (err < 0) { |
1213 | dev_err(&client->dev, "Cannot get regulators\n"); |
1214 | goto fail1; |
1215 | } |
1216 | |
1217 | err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), |
1218 | chip->regs); |
1219 | if (err < 0) { |
1220 | dev_err(&client->dev, "Cannot enable regulators\n"); |
1221 | goto fail2; |
1222 | } |
1223 | |
1224 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); |
1225 | err = bh1770_detect(chip); |
1226 | if (err < 0) |
1227 | goto fail3; |
1228 | |
1229 | /* Start chip */ |
1230 | bh1770_chip_on(chip); |
1231 | pm_runtime_set_active(&client->dev); |
1232 | pm_runtime_enable(&client->dev); |
1233 | |
1234 | chip->lux_corr = bh1770_get_corr_value(chip); |
1235 | if (chip->lux_corr == 0) { |
1236 | dev_err(&client->dev, "Improper correction values\n"); |
1237 | err = -EINVAL; |
1238 | goto fail3; |
1239 | } |
1240 | |
1241 | if (chip->pdata->setup_resources) { |
1242 | err = chip->pdata->setup_resources(); |
1243 | if (err) { |
1244 | err = -EINVAL; |
1245 | goto fail3; |
1246 | } |
1247 | } |
1248 | |
1249 | err = sysfs_create_group(&chip->client->dev.kobj, |
1250 | &bh1770_attribute_group); |
1251 | if (err < 0) { |
1252 | dev_err(&chip->client->dev, "Sysfs registration failed\n"); |
1253 | goto fail4; |
1254 | } |
1255 | |
1256 | /* |
1257 | * Chip needs level triggered interrupt to work. However, |
1258 | * level triggering doesn't work always correctly with power |
1259 | * management. Select both |
1260 | */ |
1261 | err = request_threaded_irq(client->irq, NULL, |
1262 | bh1770_irq, |
1263 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | |
1264 | IRQF_TRIGGER_LOW, |
1265 | "bh1770", chip); |
1266 | if (err) { |
1267 | dev_err(&client->dev, "could not get IRQ %d\n", |
1268 | client->irq); |
1269 | goto fail5; |
1270 | } |
1271 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); |
1272 | return err; |
1273 | fail5: |
1274 | sysfs_remove_group(&chip->client->dev.kobj, |
1275 | &bh1770_attribute_group); |
1276 | fail4: |
1277 | if (chip->pdata->release_resources) |
1278 | chip->pdata->release_resources(); |
1279 | fail3: |
1280 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); |
1281 | fail2: |
1282 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); |
1283 | fail1: |
1284 | kfree(chip); |
1285 | return err; |
1286 | } |
1287 | |
1288 | static int __devexit bh1770_remove(struct i2c_client *client) |
1289 | { |
1290 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1291 | |
1292 | free_irq(client->irq, chip); |
1293 | |
1294 | sysfs_remove_group(&chip->client->dev.kobj, |
1295 | &bh1770_attribute_group); |
1296 | |
1297 | if (chip->pdata->release_resources) |
1298 | chip->pdata->release_resources(); |
1299 | |
1300 | cancel_delayed_work_sync(&chip->prox_work); |
1301 | |
1302 | if (!pm_runtime_suspended(&client->dev)) |
1303 | bh1770_chip_off(chip); |
1304 | |
1305 | pm_runtime_disable(&client->dev); |
1306 | pm_runtime_set_suspended(&client->dev); |
1307 | |
1308 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); |
1309 | kfree(chip); |
1310 | return 0; |
1311 | } |
1312 | |
1313 | #ifdef CONFIG_PM |
1314 | static int bh1770_suspend(struct device *dev) |
1315 | { |
1316 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
1317 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1318 | |
1319 | bh1770_chip_off(chip); |
1320 | |
1321 | return 0; |
1322 | } |
1323 | |
1324 | static int bh1770_resume(struct device *dev) |
1325 | { |
1326 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
1327 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1328 | int ret = 0; |
1329 | |
1330 | bh1770_chip_on(chip); |
1331 | |
1332 | if (!pm_runtime_suspended(dev)) { |
1333 | /* |
1334 | * If we were enabled at suspend time, it is expected |
1335 | * everything works nice and smoothly |
1336 | */ |
1337 | ret = bh1770_lux_rate(chip, chip->lux_rate_index); |
1338 | ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE); |
1339 | |
1340 | /* This causes interrupt after the next measurement cycle */ |
1341 | bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES, |
1342 | BH1770_LUX_DEF_THRES); |
1343 | /* Inform that we are waiting for a result from ALS */ |
1344 | chip->lux_wait_result = true; |
1345 | bh1770_prox_mode_control(chip); |
1346 | } |
1347 | return ret; |
1348 | } |
1349 | |
1350 | #else |
1351 | #define bh1770_suspend NULL |
1352 | #define bh1770_shutdown NULL |
1353 | #define bh1770_resume NULL |
1354 | #endif |
1355 | |
1356 | #ifdef CONFIG_PM_RUNTIME |
1357 | static int bh1770_runtime_suspend(struct device *dev) |
1358 | { |
1359 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
1360 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1361 | |
1362 | bh1770_chip_off(chip); |
1363 | |
1364 | return 0; |
1365 | } |
1366 | |
1367 | static int bh1770_runtime_resume(struct device *dev) |
1368 | { |
1369 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
1370 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1371 | |
1372 | bh1770_chip_on(chip); |
1373 | |
1374 | return 0; |
1375 | } |
1376 | #endif |
1377 | |
1378 | static const struct i2c_device_id bh1770_id[] = { |
1379 | {"bh1770glc", 0 }, |
1380 | {"sfh7770", 0 }, |
1381 | {} |
1382 | }; |
1383 | |
1384 | MODULE_DEVICE_TABLE(i2c, bh1770_id); |
1385 | |
1386 | static const struct dev_pm_ops bh1770_pm_ops = { |
1387 | SET_SYSTEM_SLEEP_PM_OPS(bh1770_suspend, bh1770_resume) |
1388 | SET_RUNTIME_PM_OPS(bh1770_runtime_suspend, bh1770_runtime_resume, NULL) |
1389 | }; |
1390 | |
1391 | static struct i2c_driver bh1770_driver = { |
1392 | .driver = { |
1393 | .name = "bh1770glc", |
1394 | .owner = THIS_MODULE, |
1395 | .pm = &bh1770_pm_ops, |
1396 | }, |
1397 | .probe = bh1770_probe, |
1398 | .remove = __devexit_p(bh1770_remove), |
1399 | .id_table = bh1770_id, |
1400 | }; |
1401 | |
1402 | module_i2c_driver(bh1770_driver); |
1403 | |
1404 | MODULE_DESCRIPTION("BH1770GLC / SFH7770 combined ALS and proximity sensor"); |
1405 | MODULE_AUTHOR("Samu Onkalo, Nokia Corporation"); |
1406 | MODULE_LICENSE("GPL v2"); |
1407 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9