Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lm3533-als.c
Go to the documentation of this file.
1 /*
2  * lm3533-als.c -- LM3533 Ambient Light Sensor driver
3  *
4  * Copyright (C) 2011-2012 Texas Instruments
5  *
6  * Author: Johan Hovold <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  */
13 
14 #include <linux/atomic.h>
15 #include <linux/fs.h>
16 #include <linux/interrupt.h>
17 #include <linux/io.h>
18 #include <linux/iio/events.h>
19 #include <linux/iio/iio.h>
20 #include <linux/module.h>
21 #include <linux/mutex.h>
22 #include <linux/mfd/core.h>
23 #include <linux/platform_device.h>
24 #include <linux/slab.h>
25 #include <linux/uaccess.h>
26 
27 #include <linux/mfd/lm3533.h>
28 
29 
30 #define LM3533_ALS_RESISTOR_MIN 1
31 #define LM3533_ALS_RESISTOR_MAX 127
32 #define LM3533_ALS_CHANNEL_CURRENT_MAX 2
33 #define LM3533_ALS_THRESH_MAX 3
34 #define LM3533_ALS_ZONE_MAX 4
35 
36 #define LM3533_REG_ALS_RESISTOR_SELECT 0x30
37 #define LM3533_REG_ALS_CONF 0x31
38 #define LM3533_REG_ALS_ZONE_INFO 0x34
39 #define LM3533_REG_ALS_READ_ADC_RAW 0x37
40 #define LM3533_REG_ALS_READ_ADC_AVERAGE 0x38
41 #define LM3533_REG_ALS_BOUNDARY_BASE 0x50
42 #define LM3533_REG_ALS_TARGET_BASE 0x60
43 
44 #define LM3533_ALS_ENABLE_MASK 0x01
45 #define LM3533_ALS_INPUT_MODE_MASK 0x02
46 #define LM3533_ALS_INT_ENABLE_MASK 0x01
47 
48 #define LM3533_ALS_ZONE_SHIFT 2
49 #define LM3533_ALS_ZONE_MASK 0x1c
50 
51 #define LM3533_ALS_FLAG_INT_ENABLED 1
52 
53 
54 struct lm3533_als {
55  struct lm3533 *lm3533;
57 
58  unsigned long flags;
59  int irq;
60 
63 };
64 
65 
66 static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average,
67  int *adc)
68 {
69  struct lm3533_als *als = iio_priv(indio_dev);
70  u8 reg;
71  u8 val;
72  int ret;
73 
74  if (average)
76  else
78 
79  ret = lm3533_read(als->lm3533, reg, &val);
80  if (ret) {
81  dev_err(&indio_dev->dev, "failed to read adc\n");
82  return ret;
83  }
84 
85  *adc = val;
86 
87  return 0;
88 }
89 
90 static int _lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone)
91 {
92  struct lm3533_als *als = iio_priv(indio_dev);
93  u8 val;
94  int ret;
95 
96  ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
97  if (ret) {
98  dev_err(&indio_dev->dev, "failed to read zone\n");
99  return ret;
100  }
101 
103  *zone = min_t(u8, val, LM3533_ALS_ZONE_MAX);
104 
105  return 0;
106 }
107 
108 static int lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone)
109 {
110  struct lm3533_als *als = iio_priv(indio_dev);
111  int ret;
112 
114  *zone = atomic_read(&als->zone);
115  } else {
116  ret = _lm3533_als_get_zone(indio_dev, zone);
117  if (ret)
118  return ret;
119  }
120 
121  return 0;
122 }
123 
124 /*
125  * channel output channel 0..2
126  * zone zone 0..4
127  */
128 static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone)
129 {
130  return LM3533_REG_ALS_TARGET_BASE + 5 * channel + zone;
131 }
132 
133 static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel,
134  unsigned zone, u8 *val)
135 {
136  struct lm3533_als *als = iio_priv(indio_dev);
137  u8 reg;
138  int ret;
139 
140  if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX)
141  return -EINVAL;
142 
143  if (zone > LM3533_ALS_ZONE_MAX)
144  return -EINVAL;
145 
146  reg = lm3533_als_get_target_reg(channel, zone);
147  ret = lm3533_read(als->lm3533, reg, val);
148  if (ret)
149  dev_err(&indio_dev->dev, "failed to get target current\n");
150 
151  return ret;
152 }
153 
154 static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel,
155  unsigned zone, u8 val)
156 {
157  struct lm3533_als *als = iio_priv(indio_dev);
158  u8 reg;
159  int ret;
160 
161  if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX)
162  return -EINVAL;
163 
164  if (zone > LM3533_ALS_ZONE_MAX)
165  return -EINVAL;
166 
167  reg = lm3533_als_get_target_reg(channel, zone);
168  ret = lm3533_write(als->lm3533, reg, val);
169  if (ret)
170  dev_err(&indio_dev->dev, "failed to set target current\n");
171 
172  return ret;
173 }
174 
175 static int lm3533_als_get_current(struct iio_dev *indio_dev, unsigned channel,
176  int *val)
177 {
178  u8 zone;
179  u8 target;
180  int ret;
181 
182  ret = lm3533_als_get_zone(indio_dev, &zone);
183  if (ret)
184  return ret;
185 
186  ret = lm3533_als_get_target(indio_dev, channel, zone, &target);
187  if (ret)
188  return ret;
189 
190  *val = target;
191 
192  return 0;
193 }
194 
195 static int lm3533_als_read_raw(struct iio_dev *indio_dev,
196  struct iio_chan_spec const *chan,
197  int *val, int *val2, long mask)
198 {
199  int ret;
200 
201  switch (mask) {
202  case 0:
203  switch (chan->type) {
204  case IIO_LIGHT:
205  ret = lm3533_als_get_adc(indio_dev, false, val);
206  break;
207  case IIO_CURRENT:
208  ret = lm3533_als_get_current(indio_dev, chan->channel,
209  val);
210  break;
211  default:
212  return -EINVAL;
213  }
214  break;
216  ret = lm3533_als_get_adc(indio_dev, true, val);
217  break;
218  default:
219  return -EINVAL;
220  }
221 
222  if (ret)
223  return ret;
224 
225  return IIO_VAL_INT;
226 }
227 
228 #define CHANNEL_CURRENT(_channel) \
229  { \
230  .type = IIO_CURRENT, \
231  .channel = _channel, \
232  .indexed = true, \
233  .output = true, \
234  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
235  }
236 
237 static const struct iio_chan_spec lm3533_als_channels[] = {
238  {
239  .type = IIO_LIGHT,
240  .channel = 0,
241  .indexed = true,
244  },
245  CHANNEL_CURRENT(0),
246  CHANNEL_CURRENT(1),
247  CHANNEL_CURRENT(2),
248 };
249 
250 static irqreturn_t lm3533_als_isr(int irq, void *dev_id)
251 {
252 
253  struct iio_dev *indio_dev = dev_id;
254  struct lm3533_als *als = iio_priv(indio_dev);
255  u8 zone;
256  int ret;
257 
258  /* Clear interrupt by reading the ALS zone register. */
259  ret = _lm3533_als_get_zone(indio_dev, &zone);
260  if (ret)
261  goto out;
262 
263  atomic_set(&als->zone, zone);
264 
265  iio_push_event(indio_dev,
267  0,
270  iio_get_time_ns());
271 out:
272  return IRQ_HANDLED;
273 }
274 
275 static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable)
276 {
277  struct lm3533_als *als = iio_priv(indio_dev);
279  u8 val;
280  int ret;
281 
282  if (enable)
283  val = mask;
284  else
285  val = 0;
286 
287  ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask);
288  if (ret) {
289  dev_err(&indio_dev->dev, "failed to set int mode %d\n",
290  enable);
291  return ret;
292  }
293 
294  return 0;
295 }
296 
297 static int lm3533_als_get_int_mode(struct iio_dev *indio_dev, int *enable)
298 {
299  struct lm3533_als *als = iio_priv(indio_dev);
301  u8 val;
302  int ret;
303 
304  ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
305  if (ret) {
306  dev_err(&indio_dev->dev, "failed to get int mode\n");
307  return ret;
308  }
309 
310  *enable = !!(val & mask);
311 
312  return 0;
313 }
314 
315 static inline u8 lm3533_als_get_threshold_reg(unsigned nr, bool raising)
316 {
317  u8 offset = !raising;
318 
319  return LM3533_REG_ALS_BOUNDARY_BASE + 2 * nr + offset;
320 }
321 
322 static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr,
323  bool raising, u8 *val)
324 {
325  struct lm3533_als *als = iio_priv(indio_dev);
326  u8 reg;
327  int ret;
328 
329  if (nr > LM3533_ALS_THRESH_MAX)
330  return -EINVAL;
331 
332  reg = lm3533_als_get_threshold_reg(nr, raising);
333  ret = lm3533_read(als->lm3533, reg, val);
334  if (ret)
335  dev_err(&indio_dev->dev, "failed to get threshold\n");
336 
337  return ret;
338 }
339 
340 static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
341  bool raising, u8 val)
342 {
343  struct lm3533_als *als = iio_priv(indio_dev);
344  u8 val2;
345  u8 reg, reg2;
346  int ret;
347 
348  if (nr > LM3533_ALS_THRESH_MAX)
349  return -EINVAL;
350 
351  reg = lm3533_als_get_threshold_reg(nr, raising);
352  reg2 = lm3533_als_get_threshold_reg(nr, !raising);
353 
354  mutex_lock(&als->thresh_mutex);
355  ret = lm3533_read(als->lm3533, reg2, &val2);
356  if (ret) {
357  dev_err(&indio_dev->dev, "failed to get threshold\n");
358  goto out;
359  }
360  /*
361  * This device does not allow negative hysteresis (in fact, it uses
362  * whichever value is smaller as the lower bound) so we need to make
363  * sure that thresh_falling <= thresh_raising.
364  */
365  if ((raising && (val < val2)) || (!raising && (val > val2))) {
366  ret = -EINVAL;
367  goto out;
368  }
369 
370  ret = lm3533_write(als->lm3533, reg, val);
371  if (ret) {
372  dev_err(&indio_dev->dev, "failed to set threshold\n");
373  goto out;
374  }
375 out:
376  mutex_unlock(&als->thresh_mutex);
377 
378  return ret;
379 }
380 
381 static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr,
382  u8 *val)
383 {
384  struct lm3533_als *als = iio_priv(indio_dev);
385  u8 falling;
386  u8 raising;
387  int ret;
388 
389  if (nr > LM3533_ALS_THRESH_MAX)
390  return -EINVAL;
391 
392  mutex_lock(&als->thresh_mutex);
393  ret = lm3533_als_get_threshold(indio_dev, nr, false, &falling);
394  if (ret)
395  goto out;
396  ret = lm3533_als_get_threshold(indio_dev, nr, true, &raising);
397  if (ret)
398  goto out;
399 
400  *val = raising - falling;
401 out:
402  mutex_unlock(&als->thresh_mutex);
403 
404  return ret;
405 }
406 
407 static ssize_t show_thresh_either_en(struct device *dev,
408  struct device_attribute *attr,
409  char *buf)
410 {
411  struct iio_dev *indio_dev = dev_to_iio_dev(dev);
412  struct lm3533_als *als = iio_priv(indio_dev);
413  int enable;
414  int ret;
415 
416  if (als->irq) {
417  ret = lm3533_als_get_int_mode(indio_dev, &enable);
418  if (ret)
419  return ret;
420  } else {
421  enable = 0;
422  }
423 
424  return scnprintf(buf, PAGE_SIZE, "%u\n", enable);
425 }
426 
427 static ssize_t store_thresh_either_en(struct device *dev,
428  struct device_attribute *attr,
429  const char *buf, size_t len)
430 {
431  struct iio_dev *indio_dev = dev_to_iio_dev(dev);
432  struct lm3533_als *als = iio_priv(indio_dev);
433  unsigned long enable;
434  bool int_enabled;
435  u8 zone;
436  int ret;
437 
438  if (!als->irq)
439  return -EBUSY;
440 
441  if (kstrtoul(buf, 0, &enable))
442  return -EINVAL;
443 
444  int_enabled = test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags);
445 
446  if (enable && !int_enabled) {
447  ret = lm3533_als_get_zone(indio_dev, &zone);
448  if (ret)
449  return ret;
450 
451  atomic_set(&als->zone, zone);
452 
454  }
455 
456  ret = lm3533_als_set_int_mode(indio_dev, enable);
457  if (ret) {
458  if (!int_enabled)
460 
461  return ret;
462  }
463 
464  if (!enable)
466 
467  return len;
468 }
469 
470 static ssize_t show_zone(struct device *dev,
471  struct device_attribute *attr, char *buf)
472 {
473  struct iio_dev *indio_dev = dev_to_iio_dev(dev);
474  u8 zone;
475  int ret;
476 
477  ret = lm3533_als_get_zone(indio_dev, &zone);
478  if (ret)
479  return ret;
480 
481  return scnprintf(buf, PAGE_SIZE, "%u\n", zone);
482 }
483 
489 };
490 
496 };
497 
498 static inline struct lm3533_als_attribute *
499 to_lm3533_als_attr(struct device_attribute *attr)
500 {
501  return container_of(attr, struct lm3533_als_attribute, dev_attr);
502 }
503 
504 static ssize_t show_als_attr(struct device *dev,
505  struct device_attribute *attr,
506  char *buf)
507 {
508  struct iio_dev *indio_dev = dev_to_iio_dev(dev);
509  struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr);
510  u8 val;
511  int ret;
512 
513  switch (als_attr->type) {
515  ret = lm3533_als_get_hysteresis(indio_dev, als_attr->val1,
516  &val);
517  break;
519  ret = lm3533_als_get_target(indio_dev, als_attr->val1,
520  als_attr->val2, &val);
521  break;
523  ret = lm3533_als_get_threshold(indio_dev, als_attr->val1,
524  false, &val);
525  break;
527  ret = lm3533_als_get_threshold(indio_dev, als_attr->val1,
528  true, &val);
529  break;
530  default:
531  ret = -ENXIO;
532  }
533 
534  if (ret)
535  return ret;
536 
537  return scnprintf(buf, PAGE_SIZE, "%u\n", val);
538 }
539 
540 static ssize_t store_als_attr(struct device *dev,
541  struct device_attribute *attr,
542  const char *buf, size_t len)
543 {
544  struct iio_dev *indio_dev = dev_to_iio_dev(dev);
545  struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr);
546  u8 val;
547  int ret;
548 
549  if (kstrtou8(buf, 0, &val))
550  return -EINVAL;
551 
552  switch (als_attr->type) {
554  ret = lm3533_als_set_target(indio_dev, als_attr->val1,
555  als_attr->val2, val);
556  break;
558  ret = lm3533_als_set_threshold(indio_dev, als_attr->val1,
559  false, val);
560  break;
562  ret = lm3533_als_set_threshold(indio_dev, als_attr->val1,
563  true, val);
564  break;
565  default:
566  ret = -ENXIO;
567  }
568 
569  if (ret)
570  return ret;
571 
572  return len;
573 }
574 
575 #define ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \
576  { .dev_attr = __ATTR(_name, _mode, _show, _store), \
577  .type = _type, \
578  .val1 = _val1, \
579  .val2 = _val2 }
580 
581 #define LM3533_ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \
582  struct lm3533_als_attribute lm3533_als_attr_##_name = \
583  ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2)
584 
585 #define ALS_TARGET_ATTR_RW(_channel, _zone) \
586  LM3533_ALS_ATTR(out_current##_channel##_current##_zone##_raw, \
587  S_IRUGO | S_IWUSR, \
588  show_als_attr, store_als_attr, \
589  LM3533_ATTR_TYPE_TARGET, _channel, _zone)
590 /*
591  * ALS output current values (ALS mapper targets)
592  *
593  * out_current[0-2]_current[0-4]_raw 0-255
594  */
595 static ALS_TARGET_ATTR_RW(0, 0);
596 static ALS_TARGET_ATTR_RW(0, 1);
597 static ALS_TARGET_ATTR_RW(0, 2);
598 static ALS_TARGET_ATTR_RW(0, 3);
599 static ALS_TARGET_ATTR_RW(0, 4);
600 
601 static ALS_TARGET_ATTR_RW(1, 0);
602 static ALS_TARGET_ATTR_RW(1, 1);
603 static ALS_TARGET_ATTR_RW(1, 2);
604 static ALS_TARGET_ATTR_RW(1, 3);
605 static ALS_TARGET_ATTR_RW(1, 4);
606 
607 static ALS_TARGET_ATTR_RW(2, 0);
608 static ALS_TARGET_ATTR_RW(2, 1);
609 static ALS_TARGET_ATTR_RW(2, 2);
610 static ALS_TARGET_ATTR_RW(2, 3);
611 static ALS_TARGET_ATTR_RW(2, 4);
612 
613 #define ALS_THRESH_FALLING_ATTR_RW(_nr) \
614  LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_falling_value, \
615  S_IRUGO | S_IWUSR, \
616  show_als_attr, store_als_attr, \
617  LM3533_ATTR_TYPE_THRESH_FALLING, _nr, 0)
618 
619 #define ALS_THRESH_RAISING_ATTR_RW(_nr) \
620  LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_raising_value, \
621  S_IRUGO | S_IWUSR, \
622  show_als_attr, store_als_attr, \
623  LM3533_ATTR_TYPE_THRESH_RAISING, _nr, 0)
624 /*
625  * ALS Zone thresholds (boundaries)
626  *
627  * in_illuminance0_thresh[0-3]_falling_value 0-255
628  * in_illuminance0_thresh[0-3]_raising_value 0-255
629  */
634 
639 
640 #define ALS_HYSTERESIS_ATTR_RO(_nr) \
641  LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_hysteresis, \
642  S_IRUGO, show_als_attr, NULL, \
643  LM3533_ATTR_TYPE_HYSTERESIS, _nr, 0)
644 /*
645  * ALS Zone threshold hysteresis
646  *
647  * threshY_hysteresis = threshY_raising - threshY_falling
648  *
649  * in_illuminance0_thresh[0-3]_hysteresis 0-255
650  * in_illuminance0_thresh[0-3]_hysteresis 0-255
651  */
652 static ALS_HYSTERESIS_ATTR_RO(0);
653 static ALS_HYSTERESIS_ATTR_RO(1);
654 static ALS_HYSTERESIS_ATTR_RO(2);
655 static ALS_HYSTERESIS_ATTR_RO(3);
656 
657 #define ILLUMINANCE_ATTR_RO(_name) \
658  DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL)
659 #define ILLUMINANCE_ATTR_RW(_name) \
660  DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \
661  show_##_name, store_##_name)
662 /*
663  * ALS Zone threshold-event enable
664  *
665  * in_illuminance0_thresh_either_en 0,1
666  */
667 static ILLUMINANCE_ATTR_RW(thresh_either_en);
668 
669 /*
670  * ALS Current Zone
671  *
672  * in_illuminance0_zone 0-4
673  */
674 static ILLUMINANCE_ATTR_RO(zone);
675 
676 static struct attribute *lm3533_als_event_attributes[] = {
677  &dev_attr_in_illuminance0_thresh_either_en.attr,
678  &lm3533_als_attr_in_illuminance0_thresh0_falling_value.dev_attr.attr,
679  &lm3533_als_attr_in_illuminance0_thresh0_hysteresis.dev_attr.attr,
680  &lm3533_als_attr_in_illuminance0_thresh0_raising_value.dev_attr.attr,
681  &lm3533_als_attr_in_illuminance0_thresh1_falling_value.dev_attr.attr,
682  &lm3533_als_attr_in_illuminance0_thresh1_hysteresis.dev_attr.attr,
683  &lm3533_als_attr_in_illuminance0_thresh1_raising_value.dev_attr.attr,
684  &lm3533_als_attr_in_illuminance0_thresh2_falling_value.dev_attr.attr,
685  &lm3533_als_attr_in_illuminance0_thresh2_hysteresis.dev_attr.attr,
686  &lm3533_als_attr_in_illuminance0_thresh2_raising_value.dev_attr.attr,
687  &lm3533_als_attr_in_illuminance0_thresh3_falling_value.dev_attr.attr,
688  &lm3533_als_attr_in_illuminance0_thresh3_hysteresis.dev_attr.attr,
689  &lm3533_als_attr_in_illuminance0_thresh3_raising_value.dev_attr.attr,
690  NULL
691 };
692 
693 static struct attribute_group lm3533_als_event_attribute_group = {
694  .attrs = lm3533_als_event_attributes
695 };
696 
697 static struct attribute *lm3533_als_attributes[] = {
698  &dev_attr_in_illuminance0_zone.attr,
699  &lm3533_als_attr_out_current0_current0_raw.dev_attr.attr,
700  &lm3533_als_attr_out_current0_current1_raw.dev_attr.attr,
701  &lm3533_als_attr_out_current0_current2_raw.dev_attr.attr,
702  &lm3533_als_attr_out_current0_current3_raw.dev_attr.attr,
703  &lm3533_als_attr_out_current0_current4_raw.dev_attr.attr,
704  &lm3533_als_attr_out_current1_current0_raw.dev_attr.attr,
705  &lm3533_als_attr_out_current1_current1_raw.dev_attr.attr,
706  &lm3533_als_attr_out_current1_current2_raw.dev_attr.attr,
707  &lm3533_als_attr_out_current1_current3_raw.dev_attr.attr,
708  &lm3533_als_attr_out_current1_current4_raw.dev_attr.attr,
709  &lm3533_als_attr_out_current2_current0_raw.dev_attr.attr,
710  &lm3533_als_attr_out_current2_current1_raw.dev_attr.attr,
711  &lm3533_als_attr_out_current2_current2_raw.dev_attr.attr,
712  &lm3533_als_attr_out_current2_current3_raw.dev_attr.attr,
713  &lm3533_als_attr_out_current2_current4_raw.dev_attr.attr,
714  NULL
715 };
716 
717 static struct attribute_group lm3533_als_attribute_group = {
718  .attrs = lm3533_als_attributes
719 };
720 
721 static int __devinit lm3533_als_set_input_mode(struct lm3533_als *als,
722  bool pwm_mode)
723 {
725  u8 val;
726  int ret;
727 
728  if (pwm_mode)
729  val = mask; /* pwm input */
730  else
731  val = 0; /* analog input */
732 
733  ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, val, mask);
734  if (ret) {
735  dev_err(&als->pdev->dev, "failed to set input mode %d\n",
736  pwm_mode);
737  return ret;
738  }
739 
740  return 0;
741 }
742 
743 static int __devinit lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
744 {
745  int ret;
746 
747  if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX)
748  return -EINVAL;
749 
751  if (ret) {
752  dev_err(&als->pdev->dev, "failed to set resistor\n");
753  return ret;
754  }
755 
756  return 0;
757 }
758 
759 static int __devinit lm3533_als_setup(struct lm3533_als *als,
761 {
762  int ret;
763 
764  ret = lm3533_als_set_input_mode(als, pdata->pwm_mode);
765  if (ret)
766  return ret;
767 
768  /* ALS input is always high impedance in PWM-mode. */
769  if (!pdata->pwm_mode) {
770  ret = lm3533_als_set_resistor(als, pdata->r_select);
771  if (ret)
772  return ret;
773  }
774 
775  return 0;
776 }
777 
778 static int __devinit lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
779 {
781  int ret;
782 
783  /* Make sure interrupts are disabled. */
784  ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask);
785  if (ret) {
786  dev_err(&als->pdev->dev, "failed to disable interrupts\n");
787  return ret;
788  }
789 
790  ret = request_threaded_irq(als->irq, NULL, lm3533_als_isr,
792  dev_name(&als->pdev->dev), dev);
793  if (ret) {
794  dev_err(&als->pdev->dev, "failed to request irq %d\n",
795  als->irq);
796  return ret;
797  }
798 
799  return 0;
800 }
801 
802 static int __devinit lm3533_als_enable(struct lm3533_als *als)
803 {
804  u8 mask = LM3533_ALS_ENABLE_MASK;
805  int ret;
806 
807  ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask);
808  if (ret)
809  dev_err(&als->pdev->dev, "failed to enable ALS\n");
810 
811  return ret;
812 }
813 
814 static int lm3533_als_disable(struct lm3533_als *als)
815 {
816  u8 mask = LM3533_ALS_ENABLE_MASK;
817  int ret;
818 
819  ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask);
820  if (ret)
821  dev_err(&als->pdev->dev, "failed to disable ALS\n");
822 
823  return ret;
824 }
825 
826 static const struct iio_info lm3533_als_info = {
827  .attrs = &lm3533_als_attribute_group,
828  .event_attrs = &lm3533_als_event_attribute_group,
829  .driver_module = THIS_MODULE,
830  .read_raw = &lm3533_als_read_raw,
831 };
832 
833 static int __devinit lm3533_als_probe(struct platform_device *pdev)
834 {
835  struct lm3533 *lm3533;
837  struct lm3533_als *als;
838  struct iio_dev *indio_dev;
839  int ret;
840 
841  lm3533 = dev_get_drvdata(pdev->dev.parent);
842  if (!lm3533)
843  return -EINVAL;
844 
845  pdata = pdev->dev.platform_data;
846  if (!pdata) {
847  dev_err(&pdev->dev, "no platform data\n");
848  return -EINVAL;
849  }
850 
851  indio_dev = iio_device_alloc(sizeof(*als));
852  if (!indio_dev)
853  return -ENOMEM;
854 
855  indio_dev->info = &lm3533_als_info;
856  indio_dev->channels = lm3533_als_channels;
857  indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels);
858  indio_dev->name = dev_name(&pdev->dev);
859  indio_dev->dev.parent = pdev->dev.parent;
860  indio_dev->modes = INDIO_DIRECT_MODE;
861 
862  als = iio_priv(indio_dev);
863  als->lm3533 = lm3533;
864  als->pdev = pdev;
865  als->irq = lm3533->irq;
866  atomic_set(&als->zone, 0);
867  mutex_init(&als->thresh_mutex);
868 
869  platform_set_drvdata(pdev, indio_dev);
870 
871  if (als->irq) {
872  ret = lm3533_als_setup_irq(als, indio_dev);
873  if (ret)
874  goto err_free_dev;
875  }
876 
877  ret = lm3533_als_setup(als, pdata);
878  if (ret)
879  goto err_free_irq;
880 
881  ret = lm3533_als_enable(als);
882  if (ret)
883  goto err_free_irq;
884 
885  ret = iio_device_register(indio_dev);
886  if (ret) {
887  dev_err(&pdev->dev, "failed to register ALS\n");
888  goto err_disable;
889  }
890 
891  return 0;
892 
893 err_disable:
894  lm3533_als_disable(als);
895 err_free_irq:
896  if (als->irq)
897  free_irq(als->irq, indio_dev);
898 err_free_dev:
899  iio_device_free(indio_dev);
900 
901  return ret;
902 }
903 
904 static int __devexit lm3533_als_remove(struct platform_device *pdev)
905 {
906  struct iio_dev *indio_dev = platform_get_drvdata(pdev);
907  struct lm3533_als *als = iio_priv(indio_dev);
908 
909  lm3533_als_set_int_mode(indio_dev, false);
910  iio_device_unregister(indio_dev);
911  lm3533_als_disable(als);
912  if (als->irq)
913  free_irq(als->irq, indio_dev);
914  iio_device_free(indio_dev);
915 
916  return 0;
917 }
918 
919 static struct platform_driver lm3533_als_driver = {
920  .driver = {
921  .name = "lm3533-als",
922  .owner = THIS_MODULE,
923  },
924  .probe = lm3533_als_probe,
925  .remove = __devexit_p(lm3533_als_remove),
926 };
927 module_platform_driver(lm3533_als_driver);
928 
929 MODULE_AUTHOR("Johan Hovold <[email protected]>");
930 MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver");
931 MODULE_LICENSE("GPL");
932 MODULE_ALIAS("platform:lm3533-als");