Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: light: Add support for ROHM RPR0521 sensor

This patch adds support for ROHM RPR0521 ambient light and proximity
sensor. It offers raw readings for intensity and proximity.

Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Daniel Baluta and committed by
Jonathan Cameron
efa86e9f da8ef4e7

+627
+11
drivers/iio/light/Kconfig
··· 168 168 To compile this driver as a module, choose M here: 169 169 the module will be called jsa1212. 170 170 171 + config RPR0521 172 + tristate "ROHM RPR0521 ALS and proximity sensor driver" 173 + depends on I2C 174 + select REGMAP_I2C 175 + help 176 + Say Y here if you want to build support for ROHM's RPR0521 177 + ambient light and proximity sensor device. 178 + 179 + To compile this driver as a module, choose M here: 180 + the module will be called rpr0521. 181 + 171 182 config SENSORS_LM3533 172 183 tristate "LM3533 ambient light sensor" 173 184 depends on MFD_LM3533
+1
drivers/iio/light/Makefile
··· 19 19 obj-$(CONFIG_JSA1212) += jsa1212.o 20 20 obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o 21 21 obj-$(CONFIG_LTR501) += ltr501.o 22 + obj-$(CONFIG_RPR0521) += rpr0521.o 22 23 obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o 23 24 obj-$(CONFIG_STK3310) += stk3310.o 24 25 obj-$(CONFIG_TCS3414) += tcs3414.o
+615
drivers/iio/light/rpr0521.c
··· 1 + /* 2 + * RPR-0521 ROHM Ambient Light and Proximity Sensor 3 + * 4 + * Copyright (c) 2015, Intel Corporation. 5 + * 6 + * This file is subject to the terms and conditions of version 2 of 7 + * the GNU General Public License. See the file COPYING in the main 8 + * directory of this archive for more details. 9 + * 10 + * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38). 11 + * 12 + * TODO: illuminance channel, PM support, buffer 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/init.h> 17 + #include <linux/i2c.h> 18 + #include <linux/regmap.h> 19 + #include <linux/delay.h> 20 + #include <linux/acpi.h> 21 + 22 + #include <linux/iio/iio.h> 23 + #include <linux/iio/sysfs.h> 24 + #include <linux/pm_runtime.h> 25 + 26 + #define RPR0521_REG_SYSTEM_CTRL 0x40 27 + #define RPR0521_REG_MODE_CTRL 0x41 28 + #define RPR0521_REG_ALS_CTRL 0x42 29 + #define RPR0521_REG_PXS_CTRL 0x43 30 + #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */ 31 + #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */ 32 + #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */ 33 + #define RPR0521_REG_ID 0x92 34 + 35 + #define RPR0521_MODE_ALS_MASK BIT(7) 36 + #define RPR0521_MODE_PXS_MASK BIT(6) 37 + #define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0) 38 + #define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4) 39 + #define RPR0521_ALS_DATA0_GAIN_SHIFT 4 40 + #define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2) 41 + #define RPR0521_ALS_DATA1_GAIN_SHIFT 2 42 + #define RPR0521_PXS_GAIN_MASK GENMASK(5, 4) 43 + #define RPR0521_PXS_GAIN_SHIFT 4 44 + 45 + #define RPR0521_MODE_ALS_ENABLE BIT(7) 46 + #define RPR0521_MODE_ALS_DISABLE 0x00 47 + #define RPR0521_MODE_PXS_ENABLE BIT(6) 48 + #define RPR0521_MODE_PXS_DISABLE 0x00 49 + 50 + #define RPR0521_MANUFACT_ID 0xE0 51 + #define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */ 52 + 53 + #define RPR0521_DRV_NAME "RPR0521" 54 + #define RPR0521_REGMAP_NAME "rpr0521_regmap" 55 + 56 + #define RPR0521_SLEEP_DELAY_MS 2000 57 + 58 + #define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1" 59 + #define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1" 60 + 61 + struct rpr0521_gain { 62 + int scale; 63 + int uscale; 64 + }; 65 + 66 + static const struct rpr0521_gain rpr0521_als_gain[4] = { 67 + {1, 0}, /* x1 */ 68 + {0, 500000}, /* x2 */ 69 + {0, 15625}, /* x64 */ 70 + {0, 7812}, /* x128 */ 71 + }; 72 + 73 + static const struct rpr0521_gain rpr0521_pxs_gain[3] = { 74 + {1, 0}, /* x1 */ 75 + {0, 500000}, /* x2 */ 76 + {0, 125000}, /* x4 */ 77 + }; 78 + 79 + enum rpr0521_channel { 80 + RPR0521_CHAN_ALS_DATA0, 81 + RPR0521_CHAN_ALS_DATA1, 82 + RPR0521_CHAN_PXS, 83 + }; 84 + 85 + struct rpr0521_reg_desc { 86 + u8 address; 87 + u8 device_mask; 88 + }; 89 + 90 + static const struct rpr0521_reg_desc rpr0521_data_reg[] = { 91 + [RPR0521_CHAN_ALS_DATA0] = { 92 + .address = RPR0521_REG_ALS_DATA0, 93 + .device_mask = RPR0521_MODE_ALS_MASK, 94 + }, 95 + [RPR0521_CHAN_ALS_DATA1] = { 96 + .address = RPR0521_REG_ALS_DATA1, 97 + .device_mask = RPR0521_MODE_ALS_MASK, 98 + }, 99 + [RPR0521_CHAN_PXS] = { 100 + .address = RPR0521_REG_PXS_DATA, 101 + .device_mask = RPR0521_MODE_PXS_MASK, 102 + }, 103 + }; 104 + 105 + static const struct rpr0521_gain_info { 106 + u8 reg; 107 + u8 mask; 108 + u8 shift; 109 + const struct rpr0521_gain *gain; 110 + int size; 111 + } rpr0521_gain[] = { 112 + [RPR0521_CHAN_ALS_DATA0] = { 113 + .reg = RPR0521_REG_ALS_CTRL, 114 + .mask = RPR0521_ALS_DATA0_GAIN_MASK, 115 + .shift = RPR0521_ALS_DATA0_GAIN_SHIFT, 116 + .gain = rpr0521_als_gain, 117 + .size = ARRAY_SIZE(rpr0521_als_gain), 118 + }, 119 + [RPR0521_CHAN_ALS_DATA1] = { 120 + .reg = RPR0521_REG_ALS_CTRL, 121 + .mask = RPR0521_ALS_DATA1_GAIN_MASK, 122 + .shift = RPR0521_ALS_DATA1_GAIN_SHIFT, 123 + .gain = rpr0521_als_gain, 124 + .size = ARRAY_SIZE(rpr0521_als_gain), 125 + }, 126 + [RPR0521_CHAN_PXS] = { 127 + .reg = RPR0521_REG_PXS_CTRL, 128 + .mask = RPR0521_PXS_GAIN_MASK, 129 + .shift = RPR0521_PXS_GAIN_SHIFT, 130 + .gain = rpr0521_pxs_gain, 131 + .size = ARRAY_SIZE(rpr0521_pxs_gain), 132 + }, 133 + }; 134 + 135 + struct rpr0521_data { 136 + struct i2c_client *client; 137 + 138 + /* protect device params updates (e.g state, gain) */ 139 + struct mutex lock; 140 + 141 + /* device active status */ 142 + bool als_dev_en; 143 + bool pxs_dev_en; 144 + 145 + /* optimize runtime pm ops - enable device only if needed */ 146 + bool als_ps_need_en; 147 + bool pxs_ps_need_en; 148 + 149 + struct regmap *regmap; 150 + }; 151 + 152 + static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL); 153 + static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL); 154 + 155 + static struct attribute *rpr0521_attributes[] = { 156 + &iio_const_attr_in_intensity_scale_available.dev_attr.attr, 157 + &iio_const_attr_in_proximity_scale_available.dev_attr.attr, 158 + NULL, 159 + }; 160 + 161 + static const struct attribute_group rpr0521_attribute_group = { 162 + .attrs = rpr0521_attributes, 163 + }; 164 + 165 + static const struct iio_chan_spec rpr0521_channels[] = { 166 + { 167 + .type = IIO_INTENSITY, 168 + .modified = 1, 169 + .address = RPR0521_CHAN_ALS_DATA0, 170 + .channel2 = IIO_MOD_LIGHT_BOTH, 171 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 172 + BIT(IIO_CHAN_INFO_SCALE), 173 + }, 174 + { 175 + .type = IIO_INTENSITY, 176 + .modified = 1, 177 + .address = RPR0521_CHAN_ALS_DATA1, 178 + .channel2 = IIO_MOD_LIGHT_IR, 179 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 180 + BIT(IIO_CHAN_INFO_SCALE), 181 + }, 182 + { 183 + .type = IIO_PROXIMITY, 184 + .address = RPR0521_CHAN_PXS, 185 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 186 + BIT(IIO_CHAN_INFO_SCALE), 187 + } 188 + }; 189 + 190 + static int rpr0521_als_enable(struct rpr0521_data *data, u8 status) 191 + { 192 + int ret; 193 + 194 + ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 195 + RPR0521_MODE_ALS_MASK, 196 + status); 197 + if (ret < 0) 198 + return ret; 199 + 200 + data->als_dev_en = true; 201 + 202 + return 0; 203 + } 204 + 205 + static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status) 206 + { 207 + int ret; 208 + 209 + ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 210 + RPR0521_MODE_PXS_MASK, 211 + status); 212 + if (ret < 0) 213 + return ret; 214 + 215 + data->pxs_dev_en = true; 216 + 217 + return 0; 218 + } 219 + 220 + /** 221 + * rpr0521_set_power_state - handles runtime PM state and sensors enabled status 222 + * 223 + * @data: rpr0521 device private data 224 + * @on: state to be set for devices in @device_mask 225 + * @device_mask: bitmask specifying for which device we need to update @on state 226 + * 227 + * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but 228 + * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to 229 + * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable 230 + * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not 231 + * be called twice. 232 + */ 233 + static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, 234 + u8 device_mask) 235 + { 236 + #ifdef CONFIG_PM 237 + int ret; 238 + u8 update_mask = 0; 239 + 240 + if (device_mask & RPR0521_MODE_ALS_MASK) { 241 + if (on && !data->als_ps_need_en && data->pxs_dev_en) 242 + update_mask |= RPR0521_MODE_ALS_MASK; 243 + else 244 + data->als_ps_need_en = on; 245 + } 246 + 247 + if (device_mask & RPR0521_MODE_PXS_MASK) { 248 + if (on && !data->pxs_ps_need_en && data->als_dev_en) 249 + update_mask |= RPR0521_MODE_PXS_MASK; 250 + else 251 + data->pxs_ps_need_en = on; 252 + } 253 + 254 + if (update_mask) { 255 + ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 256 + update_mask, update_mask); 257 + if (ret < 0) 258 + return ret; 259 + } 260 + 261 + if (on) { 262 + ret = pm_runtime_get_sync(&data->client->dev); 263 + } else { 264 + pm_runtime_mark_last_busy(&data->client->dev); 265 + ret = pm_runtime_put_autosuspend(&data->client->dev); 266 + } 267 + if (ret < 0) { 268 + dev_err(&data->client->dev, 269 + "Failed: rpr0521_set_power_state for %d, ret %d\n", 270 + on, ret); 271 + if (on) 272 + pm_runtime_put_noidle(&data->client->dev); 273 + 274 + return ret; 275 + } 276 + #endif 277 + return 0; 278 + } 279 + 280 + static int rpr0521_get_gain(struct rpr0521_data *data, int chan, 281 + int *val, int *val2) 282 + { 283 + int ret, reg, idx; 284 + 285 + ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, &reg); 286 + if (ret < 0) 287 + return ret; 288 + 289 + idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift; 290 + *val = rpr0521_gain[chan].gain[idx].scale; 291 + *val2 = rpr0521_gain[chan].gain[idx].uscale; 292 + 293 + return 0; 294 + } 295 + 296 + static int rpr0521_set_gain(struct rpr0521_data *data, int chan, 297 + int val, int val2) 298 + { 299 + int i, idx = -EINVAL; 300 + 301 + /* get gain index */ 302 + for (i = 0; i < rpr0521_gain[chan].size; i++) 303 + if (val == rpr0521_gain[chan].gain[i].scale && 304 + val2 == rpr0521_gain[chan].gain[i].uscale) { 305 + idx = i; 306 + break; 307 + } 308 + 309 + if (idx < 0) 310 + return idx; 311 + 312 + return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg, 313 + rpr0521_gain[chan].mask, 314 + idx << rpr0521_gain[chan].shift); 315 + } 316 + 317 + static int rpr0521_read_raw(struct iio_dev *indio_dev, 318 + struct iio_chan_spec const *chan, int *val, 319 + int *val2, long mask) 320 + { 321 + struct rpr0521_data *data = iio_priv(indio_dev); 322 + int ret; 323 + u8 device_mask; 324 + __le16 raw_data; 325 + 326 + switch (mask) { 327 + case IIO_CHAN_INFO_RAW: 328 + if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY) 329 + return -EINVAL; 330 + 331 + device_mask = rpr0521_data_reg[chan->address].device_mask; 332 + 333 + mutex_lock(&data->lock); 334 + ret = rpr0521_set_power_state(data, true, device_mask); 335 + if (ret < 0) { 336 + mutex_unlock(&data->lock); 337 + return ret; 338 + } 339 + 340 + ret = regmap_bulk_read(data->regmap, 341 + rpr0521_data_reg[chan->address].address, 342 + &raw_data, 2); 343 + if (ret < 0) { 344 + rpr0521_set_power_state(data, false, device_mask); 345 + mutex_unlock(&data->lock); 346 + return ret; 347 + } 348 + 349 + ret = rpr0521_set_power_state(data, false, device_mask); 350 + mutex_unlock(&data->lock); 351 + if (ret < 0) 352 + return ret; 353 + 354 + *val = le16_to_cpu(raw_data); 355 + 356 + return IIO_VAL_INT; 357 + case IIO_CHAN_INFO_SCALE: 358 + mutex_lock(&data->lock); 359 + ret = rpr0521_get_gain(data, chan->address, val, val2); 360 + mutex_unlock(&data->lock); 361 + if (ret < 0) 362 + return ret; 363 + 364 + return IIO_VAL_INT_PLUS_MICRO; 365 + default: 366 + return -EINVAL; 367 + } 368 + } 369 + 370 + static int rpr0521_write_raw(struct iio_dev *indio_dev, 371 + struct iio_chan_spec const *chan, int val, 372 + int val2, long mask) 373 + { 374 + struct rpr0521_data *data = iio_priv(indio_dev); 375 + int ret; 376 + 377 + switch (mask) { 378 + case IIO_CHAN_INFO_SCALE: 379 + mutex_lock(&data->lock); 380 + ret = rpr0521_set_gain(data, chan->address, val, val2); 381 + mutex_unlock(&data->lock); 382 + 383 + return ret; 384 + default: 385 + return -EINVAL; 386 + } 387 + } 388 + 389 + static const struct iio_info rpr0521_info = { 390 + .driver_module = THIS_MODULE, 391 + .read_raw = rpr0521_read_raw, 392 + .write_raw = rpr0521_write_raw, 393 + .attrs = &rpr0521_attribute_group, 394 + }; 395 + 396 + static int rpr0521_init(struct rpr0521_data *data) 397 + { 398 + int ret; 399 + int id; 400 + 401 + ret = regmap_read(data->regmap, RPR0521_REG_ID, &id); 402 + if (ret < 0) { 403 + dev_err(&data->client->dev, "Failed to read REG_ID register\n"); 404 + return ret; 405 + } 406 + 407 + if (id != RPR0521_MANUFACT_ID) { 408 + dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n", 409 + id, RPR0521_MANUFACT_ID); 410 + return -ENODEV; 411 + } 412 + 413 + /* set default measurement time - 100 ms for both ALS and PS */ 414 + ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 415 + RPR0521_MODE_MEAS_TIME_MASK, 416 + RPR0521_DEFAULT_MEAS_TIME); 417 + if (ret) { 418 + pr_err("regmap_update_bits returned %d\n", ret); 419 + return ret; 420 + } 421 + 422 + ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); 423 + if (ret < 0) 424 + return ret; 425 + ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); 426 + if (ret < 0) 427 + return ret; 428 + 429 + return 0; 430 + } 431 + 432 + static int rpr0521_poweroff(struct rpr0521_data *data) 433 + { 434 + int ret; 435 + 436 + ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 437 + RPR0521_MODE_ALS_MASK | 438 + RPR0521_MODE_PXS_MASK, 439 + RPR0521_MODE_ALS_DISABLE | 440 + RPR0521_MODE_PXS_DISABLE); 441 + if (ret < 0) 442 + return ret; 443 + 444 + data->als_dev_en = false; 445 + data->pxs_dev_en = false; 446 + 447 + return 0; 448 + } 449 + 450 + static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg) 451 + { 452 + switch (reg) { 453 + case RPR0521_REG_MODE_CTRL: 454 + case RPR0521_REG_ALS_CTRL: 455 + case RPR0521_REG_PXS_CTRL: 456 + return false; 457 + default: 458 + return true; 459 + } 460 + } 461 + 462 + static const struct regmap_config rpr0521_regmap_config = { 463 + .name = RPR0521_REGMAP_NAME, 464 + 465 + .reg_bits = 8, 466 + .val_bits = 8, 467 + 468 + .max_register = RPR0521_REG_ID, 469 + .cache_type = REGCACHE_RBTREE, 470 + .volatile_reg = rpr0521_is_volatile_reg, 471 + }; 472 + 473 + static int rpr0521_probe(struct i2c_client *client, 474 + const struct i2c_device_id *id) 475 + { 476 + struct rpr0521_data *data; 477 + struct iio_dev *indio_dev; 478 + struct regmap *regmap; 479 + int ret; 480 + 481 + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 482 + if (!indio_dev) 483 + return -ENOMEM; 484 + 485 + regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config); 486 + if (IS_ERR(regmap)) { 487 + dev_err(&client->dev, "regmap_init failed!\n"); 488 + return PTR_ERR(regmap); 489 + } 490 + 491 + data = iio_priv(indio_dev); 492 + i2c_set_clientdata(client, indio_dev); 493 + data->client = client; 494 + data->regmap = regmap; 495 + 496 + mutex_init(&data->lock); 497 + 498 + indio_dev->dev.parent = &client->dev; 499 + indio_dev->info = &rpr0521_info; 500 + indio_dev->name = RPR0521_DRV_NAME; 501 + indio_dev->channels = rpr0521_channels; 502 + indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels); 503 + indio_dev->modes = INDIO_DIRECT_MODE; 504 + 505 + ret = rpr0521_init(data); 506 + if (ret < 0) { 507 + dev_err(&client->dev, "rpr0521 chip init failed\n"); 508 + return ret; 509 + } 510 + ret = iio_device_register(indio_dev); 511 + if (ret < 0) 512 + return ret; 513 + 514 + ret = pm_runtime_set_active(&client->dev); 515 + if (ret < 0) 516 + goto err_iio_unregister; 517 + 518 + pm_runtime_enable(&client->dev); 519 + pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); 520 + pm_runtime_use_autosuspend(&client->dev); 521 + 522 + return 0; 523 + 524 + err_iio_unregister: 525 + iio_device_unregister(indio_dev); 526 + return ret; 527 + } 528 + 529 + static int rpr0521_remove(struct i2c_client *client) 530 + { 531 + struct iio_dev *indio_dev = i2c_get_clientdata(client); 532 + 533 + pm_runtime_disable(&client->dev); 534 + pm_runtime_set_suspended(&client->dev); 535 + pm_runtime_put_noidle(&client->dev); 536 + 537 + iio_device_unregister(indio_dev); 538 + rpr0521_poweroff(iio_priv(indio_dev)); 539 + 540 + return 0; 541 + } 542 + 543 + #ifdef CONFIG_PM 544 + static int rpr0521_runtime_suspend(struct device *dev) 545 + { 546 + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 547 + struct rpr0521_data *data = iio_priv(indio_dev); 548 + int ret; 549 + 550 + /* disable channels and sets {als,pxs}_dev_en to false */ 551 + mutex_lock(&data->lock); 552 + ret = rpr0521_poweroff(data); 553 + mutex_unlock(&data->lock); 554 + 555 + return ret; 556 + } 557 + 558 + static int rpr0521_runtime_resume(struct device *dev) 559 + { 560 + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 561 + struct rpr0521_data *data = iio_priv(indio_dev); 562 + int ret; 563 + 564 + if (data->als_ps_need_en) { 565 + ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); 566 + if (ret < 0) 567 + return ret; 568 + data->als_ps_need_en = false; 569 + } 570 + 571 + if (data->pxs_ps_need_en) { 572 + ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); 573 + if (ret < 0) 574 + return ret; 575 + data->pxs_ps_need_en = false; 576 + } 577 + 578 + return 0; 579 + } 580 + #endif 581 + 582 + static const struct dev_pm_ops rpr0521_pm_ops = { 583 + SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend, 584 + rpr0521_runtime_resume, NULL) 585 + }; 586 + 587 + static const struct acpi_device_id rpr0521_acpi_match[] = { 588 + {"RPR0521", 0}, 589 + { } 590 + }; 591 + MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match); 592 + 593 + static const struct i2c_device_id rpr0521_id[] = { 594 + {"rpr0521", 0}, 595 + { } 596 + }; 597 + 598 + MODULE_DEVICE_TABLE(i2c, rpr0521_id); 599 + 600 + static struct i2c_driver rpr0521_driver = { 601 + .driver = { 602 + .name = RPR0521_DRV_NAME, 603 + .pm = &rpr0521_pm_ops, 604 + .acpi_match_table = ACPI_PTR(rpr0521_acpi_match), 605 + }, 606 + .probe = rpr0521_probe, 607 + .remove = rpr0521_remove, 608 + .id_table = rpr0521_id, 609 + }; 610 + 611 + module_i2c_driver(rpr0521_driver); 612 + 613 + MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 614 + MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver"); 615 + MODULE_LICENSE("GPL v2");