@@ -148,7 +148,7 @@ struct tsl2X7X_chip {
148
148
struct tsl2x7x_als_info als_cur_info ;
149
149
struct tsl2x7x_settings settings ;
150
150
struct tsl2X7X_platform_data * pdata ;
151
- int als_time_scale ;
151
+ int als_gain_time_scale ;
152
152
int als_saturation ;
153
153
int tsl2x7x_chip_status ;
154
154
u8 tsl2x7x_config [TSL2X7X_MAX_CONFIG_REG ];
@@ -163,29 +163,36 @@ struct tsl2X7X_chip {
163
163
struct tsl2x7x_lux tsl2x7x_device_lux [TSL2X7X_MAX_LUX_TABLE_SIZE ];
164
164
};
165
165
166
- /* Different devices require different coefficents */
166
+ /*
167
+ * Different devices require different coefficents, and these numbers were
168
+ * derived from the 'Lux Equation' section of the various device datasheets.
169
+ * All of these coefficients assume a Glass Attenuation (GA) factor of 1.
170
+ * The coefficients are multiplied by 1000 to avoid floating point operations.
171
+ * The two rows in each table correspond to the Lux1 and Lux2 equations from
172
+ * the datasheets.
173
+ */
167
174
static const struct tsl2x7x_lux tsl2x71_lux_table [TSL2X7X_DEF_LUX_TABLE_SZ ] = {
168
- { 14461 , 611 , 1211 },
169
- { 18540 , 352 , 623 },
170
- { 0 , 0 , 0 },
175
+ { 53000 , 106000 },
176
+ { 31800 , 53000 },
177
+ { 0 , 0 },
171
178
};
172
179
173
180
static const struct tsl2x7x_lux tmd2x71_lux_table [TSL2X7X_DEF_LUX_TABLE_SZ ] = {
174
- { 11635 , 115 , 256 },
175
- { 15536 , 87 , 179 },
176
- { 0 , 0 , 0 },
181
+ { 24000 , 48000 },
182
+ { 14400 , 24000 },
183
+ { 0 , 0 },
177
184
};
178
185
179
186
static const struct tsl2x7x_lux tsl2x72_lux_table [TSL2X7X_DEF_LUX_TABLE_SZ ] = {
180
- { 14013 , 466 , 917 },
181
- { 18222 , 310 , 552 },
182
- { 0 , 0 , 0 },
187
+ { 60000 , 112200 },
188
+ { 37800 , 60000 },
189
+ { 0 , 0 },
183
190
};
184
191
185
192
static const struct tsl2x7x_lux tmd2x72_lux_table [TSL2X7X_DEF_LUX_TABLE_SZ ] = {
186
- { 13218 , 130 , 262 },
187
- { 17592 , 92 , 169 },
188
- { 0 , 0 , 0 },
193
+ { 20000 , 35000 },
194
+ { 12600 , 20000 },
195
+ { 0 , 0 },
189
196
};
190
197
191
198
static const struct tsl2x7x_lux * tsl2x7x_default_lux_table_group [] = {
@@ -343,22 +350,18 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg,
343
350
* @indio_dev: pointer to IIO device
344
351
*
345
352
* The raw ch0 and ch1 values of the ambient light sensed in the last
346
- * integration cycle are read from the device. Time scale factor array values
347
- * are adjusted based on the integration time. The raw values are multiplied
348
- * by a scale factor, and device gain is obtained using gain index. Limit
349
- * checks are done next, then the ratio of a multiple of ch1 value, to the
350
- * ch0 value, is calculated. Array tsl2x7x_device_lux[] is then scanned to
351
- * find the first ratio value that is just above the ratio we just calculated.
352
- * The ch0 and ch1 multiplier constants in the array are then used along with
353
- * the time scale factor array values, to calculate the lux.
353
+ * integration cycle are read from the device. The raw values are multiplied
354
+ * by a device-specific scale factor, and divided by the integration time and
355
+ * device gain. The code supports multiple lux equations through the lux table
356
+ * coefficients. A lux gain trim is applied to each lux equation, and then the
357
+ * maximum lux within the interval 0..65535 is selected.
354
358
*/
355
359
static int tsl2x7x_get_lux (struct iio_dev * indio_dev )
356
360
{
357
361
struct tsl2X7X_chip * chip = iio_priv (indio_dev );
358
362
struct tsl2x7x_lux * p ;
359
- u32 lux , ratio ;
360
- u64 lux64 ;
361
- int ret ;
363
+ int max_lux , ret ;
364
+ bool overflow ;
362
365
363
366
mutex_lock (& chip -> als_mutex );
364
367
@@ -392,10 +395,9 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
392
395
goto out_unlock ;
393
396
chip -> als_cur_info .als_ch1 = ret ;
394
397
395
- if (chip -> als_cur_info .als_ch0 >= chip -> als_saturation ||
396
- chip -> als_cur_info .als_ch1 >= chip -> als_saturation ) {
397
- lux = TSL2X7X_LUX_CALC_OVER_FLOW ;
398
- goto return_max ;
398
+ if (chip -> als_cur_info .als_ch0 >= chip -> als_saturation ) {
399
+ max_lux = TSL2X7X_LUX_CALC_OVER_FLOW ;
400
+ goto update_struct_with_max_lux ;
399
401
}
400
402
401
403
if (!chip -> als_cur_info .als_ch0 ) {
@@ -404,51 +406,38 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
404
406
goto out_unlock ;
405
407
}
406
408
407
- /* calculate ratio */
408
- ratio = (chip -> als_cur_info .als_ch1 << 15 ) / chip -> als_cur_info .als_ch0 ;
409
-
410
- /* convert to unscaled lux using the pointer to the table */
411
- p = (struct tsl2x7x_lux * )chip -> tsl2x7x_device_lux ;
412
- while (p -> ratio != 0 && p -> ratio < ratio )
413
- p ++ ;
409
+ max_lux = 0 ;
410
+ overflow = false;
411
+ for (p = (struct tsl2x7x_lux * )chip -> tsl2x7x_device_lux ; p -> ch0 != 0 ;
412
+ p ++ ) {
413
+ int lux ;
414
+
415
+ lux = ((chip -> als_cur_info .als_ch0 * p -> ch0 ) -
416
+ (chip -> als_cur_info .als_ch1 * p -> ch1 )) /
417
+ chip -> als_gain_time_scale ;
418
+
419
+ /*
420
+ * The als_gain_trim can have a value within the range 250..4000
421
+ * and is a multiplier for the lux. A trim of 1000 makes no
422
+ * changes to the lux, less than 1000 scales it down, and
423
+ * greater than 1000 scales it up.
424
+ */
425
+ lux = (lux * chip -> settings .als_gain_trim ) / 1000 ;
426
+
427
+ if (lux > TSL2X7X_LUX_CALC_OVER_FLOW ) {
428
+ overflow = true;
429
+ continue ;
430
+ }
414
431
415
- if (p -> ratio == 0 ) {
416
- lux = 0 ;
417
- } else {
418
- lux = DIV_ROUND_UP (chip -> als_cur_info .als_ch0 * p -> ch0 ,
419
- tsl2x7x_als_gain [chip -> settings .als_gain ]) -
420
- DIV_ROUND_UP (chip -> als_cur_info .als_ch1 * p -> ch1 ,
421
- tsl2x7x_als_gain [chip -> settings .als_gain ]);
432
+ max_lux = max (max_lux , lux );
422
433
}
423
434
424
- /* adjust for active time scale */
425
- if (chip -> als_time_scale == 0 )
426
- lux = 0 ;
427
- else
428
- lux = (lux + (chip -> als_time_scale >> 1 )) /
429
- chip -> als_time_scale ;
430
-
431
- /*
432
- * adjust for active gain scale. The tsl2x7x_device_lux tables have a
433
- * factor of 256 built-in. User-specified gain provides a multiplier.
434
- * Apply user-specified gain before shifting right to retain precision.
435
- * Use 64 bits to avoid overflow on multiplication. Then go back to
436
- * 32 bits before division to avoid using div_u64().
437
- */
438
-
439
- lux64 = lux ;
440
- lux64 = lux64 * chip -> settings .als_gain_trim ;
441
- lux64 >>= 8 ;
442
- lux = lux64 ;
443
- lux = (lux + 500 ) / 1000 ;
435
+ if (overflow && max_lux == 0 )
436
+ max_lux = TSL2X7X_LUX_CALC_OVER_FLOW ;
444
437
445
- if (lux > TSL2X7X_LUX_CALC_OVER_FLOW ) /* check for overflow */
446
- lux = TSL2X7X_LUX_CALC_OVER_FLOW ;
447
-
448
- /* Update the structure with the latest lux. */
449
- return_max :
450
- chip -> als_cur_info .lux = lux ;
451
- ret = lux ;
438
+ update_struct_with_max_lux :
439
+ chip -> als_cur_info .lux = max_lux ;
440
+ ret = max_lux ;
452
441
453
442
out_unlock :
454
443
mutex_unlock (& chip -> als_mutex );
@@ -525,7 +514,7 @@ static void tsl2x7x_defaults(struct tsl2X7X_chip *chip)
525
514
sizeof (tsl2x7x_default_settings ));
526
515
527
516
/* Load up the proper lux table. */
528
- if (chip -> pdata && chip -> pdata -> platform_lux_table [0 ].ratio != 0 )
517
+ if (chip -> pdata && chip -> pdata -> platform_lux_table [0 ].ch0 != 0 )
529
518
memcpy (chip -> tsl2x7x_device_lux ,
530
519
chip -> pdata -> platform_lux_table ,
531
520
sizeof (chip -> pdata -> platform_lux_table ));
@@ -588,10 +577,11 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
588
577
static int tsl2x7x_chip_on (struct iio_dev * indio_dev )
589
578
{
590
579
struct tsl2X7X_chip * chip = iio_priv (indio_dev );
591
- int ret , i , als_count , als_time ;
580
+ int ret , i , als_count , als_time_us ;
592
581
u8 * dev_reg , reg_val ;
593
582
594
583
/* Non calculated parameters */
584
+ chip -> tsl2x7x_config [TSL2X7X_ALS_TIME ] = chip -> settings .als_time ;
595
585
chip -> tsl2x7x_config [TSL2X7X_PRX_TIME ] = chip -> settings .prox_time ;
596
586
chip -> tsl2x7x_config [TSL2X7X_WAIT_TIME ] = chip -> settings .wait_time ;
597
587
chip -> tsl2x7x_config [TSL2X7X_ALS_PRX_CONFIG ] =
@@ -627,25 +617,19 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev)
627
617
return - EINVAL ;
628
618
}
629
619
630
- /* determine als integration register */
631
- als_count = (chip -> settings .als_time * 100 + 135 ) / 270 ;
632
- if (!als_count )
633
- als_count = 1 ; /* ensure at least one cycle */
634
-
635
- /* convert back to time (encompasses overrides) */
636
- als_time = (als_count * 27 + 5 ) / 10 ;
637
- chip -> tsl2x7x_config [TSL2X7X_ALS_TIME ] = 256 - als_count ;
638
-
639
620
/* Set the gain based on tsl2x7x_settings struct */
640
621
chip -> tsl2x7x_config [TSL2X7X_GAIN ] =
641
622
(chip -> settings .als_gain & 0xFF ) |
642
623
((chip -> settings .prox_gain & 0xFF ) << 2 ) |
643
624
(chip -> settings .prox_diode << 4 ) |
644
625
(chip -> settings .prox_power << 6 );
645
626
646
- /* set chip struct re scaling and saturation */
647
- chip -> als_saturation = als_count * 922 ; /* 90% of full scale */
648
- chip -> als_time_scale = (als_time + 25 ) / 50 ;
627
+ /* set chip time scaling and saturation */
628
+ als_count = 256 - chip -> settings .als_time ;
629
+ als_time_us = als_count * 2720 ;
630
+ chip -> als_saturation = als_count * 768 ; /* 75% of full scale */
631
+ chip -> als_gain_time_scale = als_time_us *
632
+ tsl2x7x_als_gain [chip -> settings .als_gain ];
649
633
650
634
/*
651
635
* TSL2X7X Specific power-on / adc enable sequence
@@ -843,11 +827,10 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev,
843
827
int offset = 0 ;
844
828
845
829
while (i < TSL2X7X_MAX_LUX_TABLE_SIZE ) {
846
- offset += snprintf (buf + offset , PAGE_SIZE , "%u,%u,%u," ,
847
- chip -> tsl2x7x_device_lux [i ].ratio ,
830
+ offset += snprintf (buf + offset , PAGE_SIZE , "%u,%u," ,
848
831
chip -> tsl2x7x_device_lux [i ].ch0 ,
849
832
chip -> tsl2x7x_device_lux [i ].ch1 );
850
- if (chip -> tsl2x7x_device_lux [i ].ratio == 0 ) {
833
+ if (chip -> tsl2x7x_device_lux [i ].ch0 == 0 ) {
851
834
/*
852
835
* We just printed the first "0" entry.
853
836
* Now get rid of the extra "," and break.
@@ -868,23 +851,23 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev,
868
851
{
869
852
struct iio_dev * indio_dev = dev_to_iio_dev (dev );
870
853
struct tsl2X7X_chip * chip = iio_priv (indio_dev );
871
- int value [ARRAY_SIZE (chip -> tsl2x7x_device_lux ) * 3 + 1 ];
854
+ int value [ARRAY_SIZE (chip -> tsl2x7x_device_lux ) * 2 + 1 ];
872
855
int n , ret ;
873
856
874
857
get_options (buf , ARRAY_SIZE (value ), value );
875
858
876
859
/*
877
860
* We now have an array of ints starting at value[1], and
878
861
* enumerated by value[0].
879
- * We expect each group of three ints is one table entry,
862
+ * We expect each group of two ints to be one table entry,
880
863
* and the last table entry is all 0.
881
864
*/
882
865
n = value [0 ];
883
- if ((n % 3 ) || n < 6 ||
884
- n > ((ARRAY_SIZE (chip -> tsl2x7x_device_lux ) - 1 ) * 3 ))
866
+ if ((n % 2 ) || n < 4 ||
867
+ n > ((ARRAY_SIZE (chip -> tsl2x7x_device_lux ) - 1 ) * 2 ))
885
868
return - EINVAL ;
886
869
887
- if ((value [(n - 2 )] | value [( n - 1 )] | value [n ]) != 0 )
870
+ if ((value [(n - 1 )] | value [n ]) != 0 )
888
871
return - EINVAL ;
889
872
890
873
if (chip -> tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING ) {
@@ -1140,8 +1123,8 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
1140
1123
ret = IIO_VAL_INT ;
1141
1124
break ;
1142
1125
case IIO_CHAN_INFO_INT_TIME :
1143
- * val = ( TSL2X7X_MAX_TIMER_CNT - chip -> settings . als_time ) + 1 ;
1144
- * val2 = (( * val * TSL2X7X_MIN_ITIME ) % 1000 ) / 1000 ;
1126
+ * val = 0 ;
1127
+ * val2 = (256 - chip -> settings . als_time ) * 2720 ;
1145
1128
ret = IIO_VAL_INT_PLUS_MICRO ;
1146
1129
break ;
1147
1130
default :
@@ -1201,8 +1184,7 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
1201
1184
chip -> settings .als_gain_trim = val ;
1202
1185
break ;
1203
1186
case IIO_CHAN_INFO_INT_TIME :
1204
- chip -> settings .als_time =
1205
- TSL2X7X_MAX_TIMER_CNT - (val2 / TSL2X7X_MIN_ITIME );
1187
+ chip -> settings .als_time = 256 - (val2 / 2720 );
1206
1188
break ;
1207
1189
default :
1208
1190
return - EINVAL ;
0 commit comments