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

Configure Feed

Select the types of activity you want to include in your feed.

iio: light: ltrf216a: Add LTR-308 support

Add LiteOn LTR-308 support into LTR-F216A kernel driver.

The two devices seem to have almost identical register map, except that
the LTR-308 does not have three CLEAR_DATA registers, which are unused
by this driver. Furthermore, LTR-308 and LTR-F216A use different lux
calculation constants, 0.6 and 0.45 respectively. Both differences are
handled using chip info data.

https://optoelectronics.liteon.com/upload/download/DS86-2016-0027/LTR-308ALS_Final_%20DS_V1%201.pdf
https://optoelectronics.liteon.com/upload/download/DS86-2019-0016/LTR-F216A_Final_DS_V1.4.PDF

Signed-off-by: Marek Vasut <marex@denx.de>
Link: https://patch.msgid.link/20240708114227.18283-2-marex@denx.de
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Marek Vasut and committed by
Jonathan Cameron
7c7d9170 14c09562

+43 -10
+43 -10
drivers/iio/light/ltrf216a.c
··· 68 68 { 25, 0x40 }, 69 69 }; 70 70 71 + struct ltr_chip_info { 72 + /* Chip contains CLEAR_DATA_0/1/2 registers at offset 0xa..0xc */ 73 + bool has_clear_data; 74 + /* Lux calculation multiplier for ALS data */ 75 + int lux_multiplier; 76 + }; 77 + 71 78 /* 72 79 * Window Factor is needed when the device is under Window glass 73 80 * with coated tinted ink. This is to compensate for the light loss ··· 86 79 struct ltrf216a_data { 87 80 struct regmap *regmap; 88 81 struct i2c_client *client; 82 + const struct ltr_chip_info *info; 89 83 u32 int_time; 90 84 u16 int_time_fac; 91 85 u8 als_gain_fac; ··· 254 246 255 247 ltrf216a_set_power_state(data, false); 256 248 257 - lux = greendata * 45 * LTRF216A_WIN_FAC; 249 + lux = greendata * data->info->lux_multiplier * LTRF216A_WIN_FAC; 258 250 259 251 return lux; 260 252 } ··· 342 334 343 335 static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg) 344 336 { 337 + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 338 + struct ltrf216a_data *data = iio_priv(indio_dev); 339 + 345 340 switch (reg) { 346 341 case LTRF216A_MAIN_CTRL: 347 342 case LTRF216A_ALS_MEAS_RES: 348 343 case LTRF216A_ALS_GAIN: 349 344 case LTRF216A_PART_ID: 350 345 case LTRF216A_MAIN_STATUS: 351 - case LTRF216A_ALS_CLEAR_DATA_0: 352 - case LTRF216A_ALS_CLEAR_DATA_1: 353 - case LTRF216A_ALS_CLEAR_DATA_2: 354 346 case LTRF216A_ALS_DATA_0: 355 347 case LTRF216A_ALS_DATA_1: 356 348 case LTRF216A_ALS_DATA_2: ··· 363 355 case LTRF216A_ALS_THRES_LOW_1: 364 356 case LTRF216A_ALS_THRES_LOW_2: 365 357 return true; 358 + case LTRF216A_ALS_CLEAR_DATA_0: 359 + case LTRF216A_ALS_CLEAR_DATA_1: 360 + case LTRF216A_ALS_CLEAR_DATA_2: 361 + return data->info->has_clear_data; 366 362 default: 367 363 return false; 368 364 } ··· 394 382 395 383 static bool ltrf216a_volatile_reg(struct device *dev, unsigned int reg) 396 384 { 385 + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 386 + struct ltrf216a_data *data = iio_priv(indio_dev); 387 + 397 388 switch (reg) { 398 389 case LTRF216A_MAIN_STATUS: 399 - case LTRF216A_ALS_CLEAR_DATA_0: 400 - case LTRF216A_ALS_CLEAR_DATA_1: 401 - case LTRF216A_ALS_CLEAR_DATA_2: 402 390 case LTRF216A_ALS_DATA_0: 403 391 case LTRF216A_ALS_DATA_1: 404 392 case LTRF216A_ALS_DATA_2: 405 393 return true; 394 + /* 395 + * If these registers are not present on a chip (like LTR-308), 396 + * the missing registers are not considered volatile. 397 + */ 398 + case LTRF216A_ALS_CLEAR_DATA_0: 399 + case LTRF216A_ALS_CLEAR_DATA_1: 400 + case LTRF216A_ALS_CLEAR_DATA_2: 401 + return data->info->has_clear_data; 406 402 default: 407 403 return false; 408 404 } ··· 453 433 454 434 i2c_set_clientdata(client, indio_dev); 455 435 data->client = client; 436 + data->info = i2c_get_match_data(client); 456 437 457 438 mutex_init(&data->lock); 458 439 ··· 541 520 static DEFINE_RUNTIME_DEV_PM_OPS(ltrf216a_pm_ops, ltrf216a_runtime_suspend, 542 521 ltrf216a_runtime_resume, NULL); 543 522 523 + static const struct ltr_chip_info ltr308_chip_info = { 524 + .has_clear_data = false, 525 + .lux_multiplier = 60, 526 + }; 527 + 528 + static const struct ltr_chip_info ltrf216a_chip_info = { 529 + .has_clear_data = true, 530 + .lux_multiplier = 45, 531 + }; 532 + 544 533 static const struct i2c_device_id ltrf216a_id[] = { 545 - { "ltrf216a" }, 534 + { "ltr308", .driver_data = (kernel_ulong_t)&ltr308_chip_info }, 535 + { "ltrf216a", .driver_data = (kernel_ulong_t)&ltrf216a_chip_info }, 546 536 {} 547 537 }; 548 538 MODULE_DEVICE_TABLE(i2c, ltrf216a_id); 549 539 550 540 static const struct of_device_id ltrf216a_of_match[] = { 551 - { .compatible = "liteon,ltrf216a" }, 552 - { .compatible = "ltr,ltrf216a" }, 541 + { .compatible = "liteon,ltr308", .data = &ltr308_chip_info }, 542 + { .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info }, 543 + { .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info }, 553 544 {} 554 545 }; 555 546 MODULE_DEVICE_TABLE(of, ltrf216a_of_match);