root/drivers/iio/light/us5182d.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. us5182d_oneshot_en
  2. us5182d_set_opmode
  3. us5182d_als_enable
  4. us5182d_px_enable
  5. us5182d_get_als
  6. us5182d_get_px
  7. us5182d_shutdown_en
  8. us5182d_set_power_state
  9. us5182d_read_value
  10. us5182d_read_raw
  11. us5182d_update_dark_th
  12. us5182d_apply_scale
  13. us5182d_write_raw
  14. us5182d_setup_prox
  15. us5182d_read_thresh
  16. us5182d_write_thresh
  17. us5182d_read_event_config
  18. us5182d_write_event_config
  19. us5182d_reset
  20. us5182d_init
  21. us5182d_get_platform_data
  22. us5182d_dark_gain_config
  23. us5182d_irq_thread_handler
  24. us5182d_probe
  25. us5182d_remove
  26. us5182d_suspend
  27. us5182d_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2015 Intel Corporation
   4  *
   5  * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor.
   6  *
   7  * To do: Interrupt support.
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/acpi.h>
  13 #include <linux/delay.h>
  14 #include <linux/i2c.h>
  15 #include <linux/iio/events.h>
  16 #include <linux/iio/iio.h>
  17 #include <linux/interrupt.h>
  18 #include <linux/irq.h>
  19 #include <linux/iio/sysfs.h>
  20 #include <linux/mutex.h>
  21 #include <linux/pm.h>
  22 #include <linux/pm_runtime.h>
  23 
  24 #define US5182D_REG_CFG0                                0x00
  25 #define US5182D_CFG0_ONESHOT_EN                         BIT(6)
  26 #define US5182D_CFG0_SHUTDOWN_EN                        BIT(7)
  27 #define US5182D_CFG0_WORD_ENABLE                        BIT(0)
  28 #define US5182D_CFG0_PROX                               BIT(3)
  29 #define US5182D_CFG0_PX_IRQ                             BIT(2)
  30 
  31 #define US5182D_REG_CFG1                                0x01
  32 #define US5182D_CFG1_ALS_RES16                          BIT(4)
  33 #define US5182D_CFG1_AGAIN_DEFAULT                      0x00
  34 
  35 #define US5182D_REG_CFG2                                0x02
  36 #define US5182D_CFG2_PX_RES16                           BIT(4)
  37 #define US5182D_CFG2_PXGAIN_DEFAULT                     BIT(2)
  38 
  39 #define US5182D_REG_CFG3                                0x03
  40 #define US5182D_CFG3_LED_CURRENT100                     (BIT(4) | BIT(5))
  41 #define US5182D_CFG3_INT_SOURCE_PX                      BIT(3)
  42 
  43 #define US5182D_REG_CFG4                                0x10
  44 
  45 /*
  46  * Registers for tuning the auto dark current cancelling feature.
  47  * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling.
  48  * when ALS  > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark
  49  * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark
  50  */
  51 #define US5182D_REG_UDARK_TH                    0x27
  52 #define US5182D_REG_DARK_AUTO_EN                0x2b
  53 #define US5182D_REG_AUTO_LDARK_GAIN             0x29
  54 #define US5182D_REG_AUTO_HDARK_GAIN             0x2a
  55 
  56 /* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */
  57 #define US5182D_REG_PXL_TH                      0x08
  58 #define US5182D_REG_PXH_TH                      0x0a
  59 
  60 #define US5182D_REG_PXL_TH_DEFAULT              1000
  61 #define US5182D_REG_PXH_TH_DEFAULT              30000
  62 
  63 #define US5182D_OPMODE_ALS                      0x01
  64 #define US5182D_OPMODE_PX                       0x02
  65 #define US5182D_OPMODE_SHIFT                    4
  66 
  67 #define US5182D_REG_DARK_AUTO_EN_DEFAULT        0x80
  68 #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT     0x16
  69 #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT     0x00
  70 
  71 #define US5182D_REG_ADL                         0x0c
  72 #define US5182D_REG_PDL                         0x0e
  73 
  74 #define US5182D_REG_MODE_STORE                  0x21
  75 #define US5182D_STORE_MODE                      0x01
  76 
  77 #define US5182D_REG_CHIPID                      0xb2
  78 
  79 #define US5182D_OPMODE_MASK                     GENMASK(5, 4)
  80 #define US5182D_AGAIN_MASK                      0x07
  81 #define US5182D_RESET_CHIP                      0x01
  82 
  83 #define US5182D_CHIPID                          0x26
  84 #define US5182D_DRV_NAME                        "us5182d"
  85 
  86 #define US5182D_GA_RESOLUTION                   1000
  87 
  88 #define US5182D_READ_BYTE                       1
  89 #define US5182D_READ_WORD                       2
  90 #define US5182D_OPSTORE_SLEEP_TIME              20 /* ms */
  91 #define US5182D_SLEEP_MS                        3000 /* ms */
  92 #define US5182D_PXH_TH_DISABLE                  0xffff
  93 #define US5182D_PXL_TH_DISABLE                  0x0000
  94 
  95 /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
  96 static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
  97                                      3900, 2100};
  98 
  99 /*
 100  * Experimental thresholds that work with US5182D sensor on evaluation board
 101  * roughly between 12-32 lux
 102  */
 103 static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000,
 104                                       8000};
 105 
 106 enum mode {
 107         US5182D_ALS_PX,
 108         US5182D_ALS_ONLY,
 109         US5182D_PX_ONLY
 110 };
 111 
 112 enum pmode {
 113         US5182D_CONTINUOUS,
 114         US5182D_ONESHOT
 115 };
 116 
 117 struct us5182d_data {
 118         struct i2c_client *client;
 119         struct mutex lock;
 120 
 121         /* Glass attenuation factor */
 122         u32 ga;
 123 
 124         /* Dark gain tuning */
 125         u8 lower_dark_gain;
 126         u8 upper_dark_gain;
 127         u16 *us5182d_dark_ths;
 128 
 129         u16 px_low_th;
 130         u16 px_high_th;
 131 
 132         int rising_en;
 133         int falling_en;
 134 
 135         u8 opmode;
 136         u8 power_mode;
 137 
 138         bool als_enabled;
 139         bool px_enabled;
 140 
 141         bool default_continuous;
 142 };
 143 
 144 static IIO_CONST_ATTR(in_illuminance_scale_available,
 145                       "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885");
 146 
 147 static struct attribute *us5182d_attrs[] = {
 148         &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
 149         NULL
 150 };
 151 
 152 static const struct attribute_group us5182d_attr_group = {
 153         .attrs = us5182d_attrs,
 154 };
 155 
 156 static const struct {
 157         u8 reg;
 158         u8 val;
 159 } us5182d_regvals[] = {
 160         {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE},
 161         {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},
 162         {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |
 163                             US5182D_CFG2_PXGAIN_DEFAULT)},
 164         {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 |
 165                            US5182D_CFG3_INT_SOURCE_PX},
 166         {US5182D_REG_CFG4, 0x00},
 167 };
 168 
 169 static const struct iio_event_spec us5182d_events[] = {
 170         {
 171                 .type = IIO_EV_TYPE_THRESH,
 172                 .dir = IIO_EV_DIR_RISING,
 173                 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
 174                                 BIT(IIO_EV_INFO_ENABLE),
 175         },
 176         {
 177                 .type = IIO_EV_TYPE_THRESH,
 178                 .dir = IIO_EV_DIR_FALLING,
 179                 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
 180                                 BIT(IIO_EV_INFO_ENABLE),
 181         },
 182 };
 183 
 184 static const struct iio_chan_spec us5182d_channels[] = {
 185         {
 186                 .type = IIO_LIGHT,
 187                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 188                                       BIT(IIO_CHAN_INFO_SCALE),
 189         },
 190         {
 191                 .type = IIO_PROXIMITY,
 192                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 193                 .event_spec = us5182d_events,
 194                 .num_event_specs = ARRAY_SIZE(us5182d_events),
 195         }
 196 };
 197 
 198 static int us5182d_oneshot_en(struct us5182d_data *data)
 199 {
 200         int ret;
 201 
 202         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
 203         if (ret < 0)
 204                 return ret;
 205 
 206         /*
 207          * In oneshot mode the chip will power itself down after taking the
 208          * required measurement.
 209          */
 210         ret = ret | US5182D_CFG0_ONESHOT_EN;
 211 
 212         return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
 213 }
 214 
 215 static int us5182d_set_opmode(struct us5182d_data *data, u8 mode)
 216 {
 217         int ret;
 218 
 219         if (mode == data->opmode)
 220                 return 0;
 221 
 222         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
 223         if (ret < 0)
 224                 return ret;
 225 
 226         /* update mode */
 227         ret = ret & ~US5182D_OPMODE_MASK;
 228         ret = ret | (mode << US5182D_OPMODE_SHIFT);
 229 
 230         /*
 231          * After updating the operating mode, the chip requires that
 232          * the operation is stored, by writing 1 in the STORE_MODE
 233          * register (auto-clearing).
 234          */
 235         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
 236         if (ret < 0)
 237                 return ret;
 238 
 239         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE,
 240                                         US5182D_STORE_MODE);
 241         if (ret < 0)
 242                 return ret;
 243 
 244         data->opmode = mode;
 245         msleep(US5182D_OPSTORE_SLEEP_TIME);
 246 
 247         return 0;
 248 }
 249 
 250 static int us5182d_als_enable(struct us5182d_data *data)
 251 {
 252         int ret;
 253         u8 mode;
 254 
 255         if (data->power_mode == US5182D_ONESHOT) {
 256                 ret = us5182d_set_opmode(data, US5182D_ALS_ONLY);
 257                 if (ret < 0)
 258                         return ret;
 259                 data->px_enabled = false;
 260         }
 261 
 262         if (data->als_enabled)
 263                 return 0;
 264 
 265         mode = data->px_enabled ? US5182D_ALS_PX : US5182D_ALS_ONLY;
 266 
 267         ret = us5182d_set_opmode(data, mode);
 268         if (ret < 0)
 269                 return ret;
 270 
 271         data->als_enabled = true;
 272 
 273         return 0;
 274 }
 275 
 276 static int us5182d_px_enable(struct us5182d_data *data)
 277 {
 278         int ret;
 279         u8 mode;
 280 
 281         if (data->power_mode == US5182D_ONESHOT) {
 282                 ret = us5182d_set_opmode(data, US5182D_PX_ONLY);
 283                 if (ret < 0)
 284                         return ret;
 285                 data->als_enabled = false;
 286         }
 287 
 288         if (data->px_enabled)
 289                 return 0;
 290 
 291         mode = data->als_enabled ? US5182D_ALS_PX : US5182D_PX_ONLY;
 292 
 293         ret = us5182d_set_opmode(data, mode);
 294         if (ret < 0)
 295                 return ret;
 296 
 297         data->px_enabled = true;
 298 
 299         return 0;
 300 }
 301 
 302 static int us5182d_get_als(struct us5182d_data *data)
 303 {
 304         int ret;
 305         unsigned long result;
 306 
 307         ret = us5182d_als_enable(data);
 308         if (ret < 0)
 309                 return ret;
 310 
 311         ret = i2c_smbus_read_word_data(data->client,
 312                                        US5182D_REG_ADL);
 313         if (ret < 0)
 314                 return ret;
 315 
 316         result = ret * data->ga / US5182D_GA_RESOLUTION;
 317         if (result > 0xffff)
 318                 result = 0xffff;
 319 
 320         return result;
 321 }
 322 
 323 static int us5182d_get_px(struct us5182d_data *data)
 324 {
 325         int ret;
 326 
 327         ret = us5182d_px_enable(data);
 328         if (ret < 0)
 329                 return ret;
 330 
 331         return i2c_smbus_read_word_data(data->client,
 332                                         US5182D_REG_PDL);
 333 }
 334 
 335 static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)
 336 {
 337         int ret;
 338 
 339         if (data->power_mode == US5182D_ONESHOT)
 340                 return 0;
 341 
 342         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
 343         if (ret < 0)
 344                 return ret;
 345 
 346         ret = ret & ~US5182D_CFG0_SHUTDOWN_EN;
 347         ret = ret | state;
 348 
 349         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
 350         if (ret < 0)
 351                 return ret;
 352 
 353         if (state & US5182D_CFG0_SHUTDOWN_EN) {
 354                 data->als_enabled = false;
 355                 data->px_enabled = false;
 356         }
 357 
 358         return ret;
 359 }
 360 
 361 
 362 static int us5182d_set_power_state(struct us5182d_data *data, bool on)
 363 {
 364         int ret;
 365 
 366         if (data->power_mode == US5182D_ONESHOT)
 367                 return 0;
 368 
 369         if (on) {
 370                 ret = pm_runtime_get_sync(&data->client->dev);
 371                 if (ret < 0)
 372                         pm_runtime_put_noidle(&data->client->dev);
 373         } else {
 374                 pm_runtime_mark_last_busy(&data->client->dev);
 375                 ret = pm_runtime_put_autosuspend(&data->client->dev);
 376         }
 377 
 378         return ret;
 379 }
 380 
 381 static int us5182d_read_value(struct us5182d_data *data,
 382                               struct iio_chan_spec const *chan)
 383 {
 384         int ret, value;
 385 
 386         mutex_lock(&data->lock);
 387 
 388         if (data->power_mode == US5182D_ONESHOT) {
 389                 ret = us5182d_oneshot_en(data);
 390                 if (ret < 0)
 391                         goto out_err;
 392         }
 393 
 394         ret = us5182d_set_power_state(data, true);
 395         if (ret < 0)
 396                 goto out_err;
 397 
 398         if (chan->type == IIO_LIGHT)
 399                 ret = us5182d_get_als(data);
 400         else
 401                 ret = us5182d_get_px(data);
 402         if (ret < 0)
 403                 goto out_poweroff;
 404 
 405         value = ret;
 406 
 407         ret = us5182d_set_power_state(data, false);
 408         if (ret < 0)
 409                 goto out_err;
 410 
 411         mutex_unlock(&data->lock);
 412         return value;
 413 
 414 out_poweroff:
 415         us5182d_set_power_state(data, false);
 416 out_err:
 417         mutex_unlock(&data->lock);
 418         return ret;
 419 }
 420 
 421 static int us5182d_read_raw(struct iio_dev *indio_dev,
 422                             struct iio_chan_spec const *chan, int *val,
 423                             int *val2, long mask)
 424 {
 425         struct us5182d_data *data = iio_priv(indio_dev);
 426         int ret;
 427 
 428         switch (mask) {
 429         case IIO_CHAN_INFO_RAW:
 430                 ret = us5182d_read_value(data, chan);
 431                 if (ret < 0)
 432                         return ret;
 433                 *val = ret;
 434                 return IIO_VAL_INT;
 435         case IIO_CHAN_INFO_SCALE:
 436                 ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
 437                 if (ret < 0)
 438                         return ret;
 439                 *val = 0;
 440                 *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];
 441                 return IIO_VAL_INT_PLUS_MICRO;
 442         default:
 443                 return -EINVAL;
 444         }
 445 }
 446 
 447 /**
 448  * us5182d_update_dark_th - update Darh_Th registers
 449  * @data        us5182d_data structure
 450  * @index       index in us5182d_dark_ths array to use for the updated value
 451  *
 452  * Function needs to be called with a lock held because it needs two i2c write
 453  * byte operations as these registers (0x27 0x28) don't work in word mode
 454  * accessing.
 455  */
 456 static int us5182d_update_dark_th(struct us5182d_data *data, int index)
 457 {
 458         __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]);
 459         int ret;
 460 
 461         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH,
 462                                         ((u8 *)&dark_th)[0]);
 463         if (ret < 0)
 464                 return ret;
 465 
 466         return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1,
 467                                         ((u8 *)&dark_th)[1]);
 468 }
 469 
 470 /**
 471  * us5182d_apply_scale - update the ALS scale
 472  * @data        us5182d_data structure
 473  * @index       index in us5182d_scales array to use for the updated value
 474  *
 475  * Function needs to be called with a lock held as we're having more than one
 476  * i2c operation.
 477  */
 478 static int us5182d_apply_scale(struct us5182d_data *data, int index)
 479 {
 480         int ret;
 481 
 482         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
 483         if (ret < 0)
 484                 return ret;
 485 
 486         ret = ret & (~US5182D_AGAIN_MASK);
 487         ret |= index;
 488 
 489         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret);
 490         if (ret < 0)
 491                 return ret;
 492 
 493         return us5182d_update_dark_th(data, index);
 494 }
 495 
 496 static int us5182d_write_raw(struct iio_dev *indio_dev,
 497                              struct iio_chan_spec const *chan, int val,
 498                              int val2, long mask)
 499 {
 500         struct us5182d_data *data = iio_priv(indio_dev);
 501         int ret, i;
 502 
 503         switch (mask) {
 504         case IIO_CHAN_INFO_SCALE:
 505                 if (val != 0)
 506                         return -EINVAL;
 507                 for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++)
 508                         if (val2 == us5182d_scales[i]) {
 509                                 mutex_lock(&data->lock);
 510                                 ret = us5182d_apply_scale(data, i);
 511                                 mutex_unlock(&data->lock);
 512                                 return ret;
 513                         }
 514                 break;
 515         default:
 516                 return -EINVAL;
 517         }
 518 
 519         return -EINVAL;
 520 }
 521 
 522 static int us5182d_setup_prox(struct iio_dev *indio_dev,
 523                               enum iio_event_direction dir, u16 val)
 524 {
 525         struct us5182d_data *data = iio_priv(indio_dev);
 526 
 527         if (dir == IIO_EV_DIR_FALLING)
 528                 return i2c_smbus_write_word_data(data->client,
 529                                                  US5182D_REG_PXL_TH, val);
 530         else if (dir == IIO_EV_DIR_RISING)
 531                 return i2c_smbus_write_word_data(data->client,
 532                                                  US5182D_REG_PXH_TH, val);
 533 
 534         return 0;
 535 }
 536 
 537 static int us5182d_read_thresh(struct iio_dev *indio_dev,
 538         const struct iio_chan_spec *chan, enum iio_event_type type,
 539         enum iio_event_direction dir, enum iio_event_info info, int *val,
 540         int *val2)
 541 {
 542         struct us5182d_data *data = iio_priv(indio_dev);
 543 
 544         switch (dir) {
 545         case IIO_EV_DIR_RISING:
 546                 mutex_lock(&data->lock);
 547                 *val = data->px_high_th;
 548                 mutex_unlock(&data->lock);
 549                 break;
 550         case IIO_EV_DIR_FALLING:
 551                 mutex_lock(&data->lock);
 552                 *val = data->px_low_th;
 553                 mutex_unlock(&data->lock);
 554                 break;
 555         default:
 556                 return -EINVAL;
 557         }
 558 
 559         return IIO_VAL_INT;
 560 }
 561 
 562 static int us5182d_write_thresh(struct iio_dev *indio_dev,
 563         const struct iio_chan_spec *chan, enum iio_event_type type,
 564         enum iio_event_direction dir, enum iio_event_info info, int val,
 565         int val2)
 566 {
 567         struct us5182d_data *data = iio_priv(indio_dev);
 568         int ret;
 569 
 570         if (val < 0 || val > USHRT_MAX || val2 != 0)
 571                 return -EINVAL;
 572 
 573         switch (dir) {
 574         case IIO_EV_DIR_RISING:
 575                 mutex_lock(&data->lock);
 576                 if (data->rising_en) {
 577                         ret = us5182d_setup_prox(indio_dev, dir, val);
 578                         if (ret < 0)
 579                                 goto err;
 580                 }
 581                 data->px_high_th = val;
 582                 mutex_unlock(&data->lock);
 583                 break;
 584         case IIO_EV_DIR_FALLING:
 585                 mutex_lock(&data->lock);
 586                 if (data->falling_en) {
 587                         ret = us5182d_setup_prox(indio_dev, dir, val);
 588                         if (ret < 0)
 589                                 goto err;
 590                 }
 591                 data->px_low_th = val;
 592                 mutex_unlock(&data->lock);
 593                 break;
 594         default:
 595                 return -EINVAL;
 596         }
 597 
 598         return 0;
 599 err:
 600         mutex_unlock(&data->lock);
 601         return ret;
 602 }
 603 
 604 static int us5182d_read_event_config(struct iio_dev *indio_dev,
 605         const struct iio_chan_spec *chan, enum iio_event_type type,
 606         enum iio_event_direction dir)
 607 {
 608         struct us5182d_data *data = iio_priv(indio_dev);
 609         int ret;
 610 
 611         switch (dir) {
 612         case IIO_EV_DIR_RISING:
 613                 mutex_lock(&data->lock);
 614                 ret = data->rising_en;
 615                 mutex_unlock(&data->lock);
 616                 break;
 617         case IIO_EV_DIR_FALLING:
 618                 mutex_lock(&data->lock);
 619                 ret = data->falling_en;
 620                 mutex_unlock(&data->lock);
 621                 break;
 622         default:
 623                 ret = -EINVAL;
 624                 break;
 625         }
 626 
 627         return ret;
 628 }
 629 
 630 static int us5182d_write_event_config(struct iio_dev *indio_dev,
 631         const struct iio_chan_spec *chan, enum iio_event_type type,
 632         enum iio_event_direction dir, int state)
 633 {
 634         struct us5182d_data *data = iio_priv(indio_dev);
 635         int ret;
 636         u16 new_th;
 637 
 638         mutex_lock(&data->lock);
 639 
 640         switch (dir) {
 641         case IIO_EV_DIR_RISING:
 642                 if (data->rising_en == state) {
 643                         mutex_unlock(&data->lock);
 644                         return 0;
 645                 }
 646                 new_th = US5182D_PXH_TH_DISABLE;
 647                 if (state) {
 648                         data->power_mode = US5182D_CONTINUOUS;
 649                         ret = us5182d_set_power_state(data, true);
 650                         if (ret < 0)
 651                                 goto err;
 652                         ret = us5182d_px_enable(data);
 653                         if (ret < 0)
 654                                 goto err_poweroff;
 655                         new_th = data->px_high_th;
 656                 }
 657                 ret = us5182d_setup_prox(indio_dev, dir, new_th);
 658                 if (ret < 0)
 659                         goto err_poweroff;
 660                 data->rising_en = state;
 661                 break;
 662         case IIO_EV_DIR_FALLING:
 663                 if (data->falling_en == state) {
 664                         mutex_unlock(&data->lock);
 665                         return 0;
 666                 }
 667                 new_th =  US5182D_PXL_TH_DISABLE;
 668                 if (state) {
 669                         data->power_mode = US5182D_CONTINUOUS;
 670                         ret = us5182d_set_power_state(data, true);
 671                         if (ret < 0)
 672                                 goto err;
 673                         ret = us5182d_px_enable(data);
 674                         if (ret < 0)
 675                                 goto err_poweroff;
 676                         new_th = data->px_low_th;
 677                 }
 678                 ret = us5182d_setup_prox(indio_dev, dir, new_th);
 679                 if (ret < 0)
 680                         goto err_poweroff;
 681                 data->falling_en = state;
 682                 break;
 683         default:
 684                 ret = -EINVAL;
 685                 goto err;
 686         }
 687 
 688         if (!state) {
 689                 ret = us5182d_set_power_state(data, false);
 690                 if (ret < 0)
 691                         goto err;
 692         }
 693 
 694         if (!data->falling_en && !data->rising_en && !data->default_continuous)
 695                 data->power_mode = US5182D_ONESHOT;
 696 
 697         mutex_unlock(&data->lock);
 698         return 0;
 699 
 700 err_poweroff:
 701         if (state)
 702                 us5182d_set_power_state(data, false);
 703 err:
 704         mutex_unlock(&data->lock);
 705         return ret;
 706 }
 707 
 708 static const struct iio_info us5182d_info = {
 709         .read_raw = us5182d_read_raw,
 710         .write_raw = us5182d_write_raw,
 711         .attrs = &us5182d_attr_group,
 712         .read_event_value = &us5182d_read_thresh,
 713         .write_event_value = &us5182d_write_thresh,
 714         .read_event_config = &us5182d_read_event_config,
 715         .write_event_config = &us5182d_write_event_config,
 716 };
 717 
 718 static int us5182d_reset(struct iio_dev *indio_dev)
 719 {
 720         struct us5182d_data *data = iio_priv(indio_dev);
 721 
 722         return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3,
 723                                          US5182D_RESET_CHIP);
 724 }
 725 
 726 static int us5182d_init(struct iio_dev *indio_dev)
 727 {
 728         struct us5182d_data *data = iio_priv(indio_dev);
 729         int i, ret;
 730 
 731         ret = us5182d_reset(indio_dev);
 732         if (ret < 0)
 733                 return ret;
 734 
 735         data->opmode = 0;
 736         data->power_mode = US5182D_CONTINUOUS;
 737         data->px_low_th = US5182D_REG_PXL_TH_DEFAULT;
 738         data->px_high_th = US5182D_REG_PXH_TH_DEFAULT;
 739 
 740         for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {
 741                 ret = i2c_smbus_write_byte_data(data->client,
 742                                                 us5182d_regvals[i].reg,
 743                                                 us5182d_regvals[i].val);
 744                 if (ret < 0)
 745                         return ret;
 746         }
 747 
 748         data->als_enabled = true;
 749         data->px_enabled = true;
 750 
 751         if (!data->default_continuous) {
 752                 ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
 753                 if (ret < 0)
 754                         return ret;
 755                 data->power_mode = US5182D_ONESHOT;
 756         }
 757 
 758         return ret;
 759 }
 760 
 761 static void us5182d_get_platform_data(struct iio_dev *indio_dev)
 762 {
 763         struct us5182d_data *data = iio_priv(indio_dev);
 764 
 765         if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef",
 766                                      &data->ga))
 767                 data->ga = US5182D_GA_RESOLUTION;
 768         if (device_property_read_u16_array(&data->client->dev,
 769                                            "upisemi,dark-ths",
 770                                            data->us5182d_dark_ths,
 771                                            ARRAY_SIZE(us5182d_dark_ths_vals)))
 772                 data->us5182d_dark_ths = us5182d_dark_ths_vals;
 773         if (device_property_read_u8(&data->client->dev,
 774                                     "upisemi,upper-dark-gain",
 775                                     &data->upper_dark_gain))
 776                 data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT;
 777         if (device_property_read_u8(&data->client->dev,
 778                                     "upisemi,lower-dark-gain",
 779                                     &data->lower_dark_gain))
 780                 data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT;
 781         data->default_continuous = device_property_read_bool(&data->client->dev,
 782                                                              "upisemi,continuous");
 783 }
 784 
 785 static int  us5182d_dark_gain_config(struct iio_dev *indio_dev)
 786 {
 787         struct us5182d_data *data = iio_priv(indio_dev);
 788         int ret;
 789 
 790         ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT);
 791         if (ret < 0)
 792                 return ret;
 793 
 794         ret = i2c_smbus_write_byte_data(data->client,
 795                                         US5182D_REG_AUTO_LDARK_GAIN,
 796                                         data->lower_dark_gain);
 797         if (ret < 0)
 798                 return ret;
 799 
 800         ret = i2c_smbus_write_byte_data(data->client,
 801                                         US5182D_REG_AUTO_HDARK_GAIN,
 802                                         data->upper_dark_gain);
 803         if (ret < 0)
 804                 return ret;
 805 
 806         return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN,
 807                                          US5182D_REG_DARK_AUTO_EN_DEFAULT);
 808 }
 809 
 810 static irqreturn_t us5182d_irq_thread_handler(int irq, void *private)
 811 {
 812         struct iio_dev *indio_dev = private;
 813         struct us5182d_data *data = iio_priv(indio_dev);
 814         enum iio_event_direction dir;
 815         int ret;
 816         u64 ev;
 817 
 818         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
 819         if (ret < 0) {
 820                 dev_err(&data->client->dev, "i2c transfer error in irq\n");
 821                 return IRQ_HANDLED;
 822         }
 823 
 824         dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
 825         ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir);
 826 
 827         iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));
 828 
 829         ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0,
 830                                         ret & ~US5182D_CFG0_PX_IRQ);
 831         if (ret < 0)
 832                 dev_err(&data->client->dev, "i2c transfer error in irq\n");
 833 
 834         return IRQ_HANDLED;
 835 }
 836 
 837 static int us5182d_probe(struct i2c_client *client,
 838                          const struct i2c_device_id *id)
 839 {
 840         struct us5182d_data *data;
 841         struct iio_dev *indio_dev;
 842         int ret;
 843 
 844         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 845         if (!indio_dev)
 846                 return -ENOMEM;
 847 
 848         data = iio_priv(indio_dev);
 849         i2c_set_clientdata(client, indio_dev);
 850         data->client = client;
 851 
 852         mutex_init(&data->lock);
 853 
 854         indio_dev->dev.parent = &client->dev;
 855         indio_dev->info = &us5182d_info;
 856         indio_dev->name = US5182D_DRV_NAME;
 857         indio_dev->channels = us5182d_channels;
 858         indio_dev->num_channels = ARRAY_SIZE(us5182d_channels);
 859         indio_dev->modes = INDIO_DIRECT_MODE;
 860 
 861         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID);
 862         if (ret != US5182D_CHIPID) {
 863                 dev_err(&data->client->dev,
 864                         "Failed to detect US5182 light chip\n");
 865                 return (ret < 0) ? ret : -ENODEV;
 866         }
 867 
 868         if (client->irq > 0) {
 869                 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 870                                                 us5182d_irq_thread_handler,
 871                                                 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 872                                                 "us5182d-irq", indio_dev);
 873                 if (ret < 0)
 874                         return ret;
 875         } else
 876                 dev_warn(&client->dev, "no valid irq found\n");
 877 
 878         us5182d_get_platform_data(indio_dev);
 879         ret = us5182d_init(indio_dev);
 880         if (ret < 0)
 881                 return ret;
 882 
 883         ret = us5182d_dark_gain_config(indio_dev);
 884         if (ret < 0)
 885                 goto out_err;
 886 
 887         if (data->default_continuous) {
 888                 ret = pm_runtime_set_active(&client->dev);
 889                 if (ret < 0)
 890                         goto out_err;
 891         }
 892 
 893         pm_runtime_enable(&client->dev);
 894         pm_runtime_set_autosuspend_delay(&client->dev,
 895                                          US5182D_SLEEP_MS);
 896         pm_runtime_use_autosuspend(&client->dev);
 897 
 898         ret = iio_device_register(indio_dev);
 899         if (ret < 0)
 900                 goto out_err;
 901 
 902         return 0;
 903 
 904 out_err:
 905         us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
 906         return ret;
 907 
 908 }
 909 
 910 static int us5182d_remove(struct i2c_client *client)
 911 {
 912         struct us5182d_data *data = iio_priv(i2c_get_clientdata(client));
 913 
 914         iio_device_unregister(i2c_get_clientdata(client));
 915 
 916         pm_runtime_disable(&client->dev);
 917         pm_runtime_set_suspended(&client->dev);
 918 
 919         return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
 920 }
 921 
 922 #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
 923 static int us5182d_suspend(struct device *dev)
 924 {
 925         struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 926         struct us5182d_data *data = iio_priv(indio_dev);
 927 
 928         if (data->power_mode == US5182D_CONTINUOUS)
 929                 return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
 930 
 931         return 0;
 932 }
 933 
 934 static int us5182d_resume(struct device *dev)
 935 {
 936         struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 937         struct us5182d_data *data = iio_priv(indio_dev);
 938 
 939         if (data->power_mode == US5182D_CONTINUOUS)
 940                 return us5182d_shutdown_en(data,
 941                                            ~US5182D_CFG0_SHUTDOWN_EN & 0xff);
 942 
 943         return 0;
 944 }
 945 #endif
 946 
 947 static const struct dev_pm_ops us5182d_pm_ops = {
 948         SET_SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume)
 949         SET_RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL)
 950 };
 951 
 952 static const struct acpi_device_id us5182d_acpi_match[] = {
 953         { "USD5182", 0},
 954         {}
 955 };
 956 
 957 MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match);
 958 
 959 static const struct i2c_device_id us5182d_id[] = {
 960                 {"usd5182", 0},
 961                 {}
 962 };
 963 
 964 MODULE_DEVICE_TABLE(i2c, us5182d_id);
 965 
 966 static const struct of_device_id us5182d_of_match[] = {
 967         { .compatible = "upisemi,usd5182" },
 968         {}
 969 };
 970 MODULE_DEVICE_TABLE(of, us5182d_of_match);
 971 
 972 static struct i2c_driver us5182d_driver = {
 973         .driver = {
 974                 .name = US5182D_DRV_NAME,
 975                 .pm = &us5182d_pm_ops,
 976                 .of_match_table = us5182d_of_match,
 977                 .acpi_match_table = ACPI_PTR(us5182d_acpi_match),
 978         },
 979         .probe = us5182d_probe,
 980         .remove = us5182d_remove,
 981         .id_table = us5182d_id,
 982 
 983 };
 984 module_i2c_driver(us5182d_driver);
 985 
 986 MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
 987 MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor");
 988 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */