11
11
#include <linux/err.h>
12
12
#include <linux/i2c.h>
13
13
#include <linux/iio/iio.h>
14
+ #include <linux/iio/iio-gts-helper.h>
14
15
#include <linux/module.h>
15
16
#include <linux/pm_runtime.h>
16
17
#include <linux/regmap.h>
@@ -35,17 +36,33 @@ struct veml3235_data {
35
36
struct device * dev ;
36
37
struct regmap * regmap ;
37
38
struct veml3235_rf rf ;
39
+ struct iio_gts gts ;
38
40
};
39
41
40
- static const int veml3235_it_times [][ 2 ] = {
41
- { 0 , 50000 } ,
42
- { 0 , 100000 } ,
43
- { 0 , 200000 } ,
44
- { 0 , 400000 } ,
45
- { 0 , 800000 } ,
42
+ static const struct iio_itime_sel_mul veml3235_it_sel [ ] = {
43
+ GAIN_SCALE_ITIME_US ( 50000 , 0 , 1 ) ,
44
+ GAIN_SCALE_ITIME_US ( 100000 , 1 , 2 ) ,
45
+ GAIN_SCALE_ITIME_US ( 200000 , 2 , 4 ) ,
46
+ GAIN_SCALE_ITIME_US ( 400000 , 3 , 8 ) ,
47
+ GAIN_SCALE_ITIME_US ( 800000 , 4 , 16 ) ,
46
48
};
47
49
48
- static const int veml3235_scale_vals [] = { 1 , 2 , 4 , 8 };
50
+ /*
51
+ * The MSB (DG) doubles the value of the rest of the field, which leads to
52
+ * two possible combinations to obtain gain = 2 and gain = 4. The gain
53
+ * handling can be simplified by restricting DG = 1 to the only gain that
54
+ * really requires it, gain = 8. Note that "X10" is a reserved value.
55
+ */
56
+ #define VEML3235_SEL_GAIN_X1 0
57
+ #define VEML3235_SEL_GAIN_X2 1
58
+ #define VEML3235_SEL_GAIN_X4 3
59
+ #define VEML3235_SEL_GAIN_X8 7
60
+ static const struct iio_gain_sel_pair veml3235_gain_sel [] = {
61
+ GAIN_SCALE_GAIN (1 , VEML3235_SEL_GAIN_X1 ),
62
+ GAIN_SCALE_GAIN (2 , VEML3235_SEL_GAIN_X2 ),
63
+ GAIN_SCALE_GAIN (4 , VEML3235_SEL_GAIN_X4 ),
64
+ GAIN_SCALE_GAIN (8 , VEML3235_SEL_GAIN_X8 ),
65
+ };
49
66
50
67
static int veml3235_power_on (struct veml3235_data * data )
51
68
{
@@ -142,32 +159,17 @@ static const struct regmap_config veml3235_regmap_config = {
142
159
143
160
static int veml3235_get_it (struct veml3235_data * data , int * val , int * val2 )
144
161
{
145
- int ret , reg ;
162
+ int ret , it_idx ;
146
163
147
- ret = regmap_field_read (data -> rf .it , & reg );
164
+ ret = regmap_field_read (data -> rf .it , & it_idx );
148
165
if (ret )
149
166
return ret ;
150
167
151
- switch (reg ) {
152
- case 0 :
153
- * val2 = 50000 ;
154
- break ;
155
- case 1 :
156
- * val2 = 100000 ;
157
- break ;
158
- case 2 :
159
- * val2 = 200000 ;
160
- break ;
161
- case 3 :
162
- * val2 = 400000 ;
163
- break ;
164
- case 4 :
165
- * val2 = 800000 ;
166
- break ;
167
- default :
168
- return - EINVAL ;
169
- }
168
+ ret = iio_gts_find_int_time_by_sel (& data -> gts , it_idx );
169
+ if (ret < 0 )
170
+ return ret ;
170
171
172
+ * val2 = ret ;
171
173
* val = 0 ;
172
174
173
175
return IIO_VAL_INT_PLUS_MICRO ;
@@ -176,104 +178,104 @@ static int veml3235_get_it(struct veml3235_data *data, int *val, int *val2)
176
178
static int veml3235_set_it (struct iio_dev * indio_dev , int val , int val2 )
177
179
{
178
180
struct veml3235_data * data = iio_priv (indio_dev );
179
- int ret , new_it ;
181
+ int ret , gain_idx , it_idx , new_gain , prev_gain , prev_it ;
182
+ bool in_range ;
180
183
181
- if (val )
184
+ if (val || ! iio_gts_valid_time ( & data -> gts , val2 ) )
182
185
return - EINVAL ;
183
186
184
- switch (val2 ) {
185
- case 50000 :
186
- new_it = 0x00 ;
187
- break ;
188
- case 100000 :
189
- new_it = 0x01 ;
190
- break ;
191
- case 200000 :
192
- new_it = 0x02 ;
193
- break ;
194
- case 400000 :
195
- new_it = 0x03 ;
196
- break ;
197
- case 800000 :
198
- new_it = 0x04 ;
199
- break ;
200
- default :
201
- return - EINVAL ;
202
- }
187
+ ret = regmap_field_read (data -> rf .it , & it_idx );
188
+ if (ret )
189
+ return ret ;
203
190
204
- ret = regmap_field_write (data -> rf .it , new_it );
205
- if (ret ) {
206
- dev_err (data -> dev ,
207
- "failed to update integration time: %d\n" , ret );
191
+ ret = regmap_field_read (data -> rf .gain , & gain_idx );
192
+ if (ret )
208
193
return ret ;
209
- }
210
194
211
- return 0 ;
195
+ prev_it = iio_gts_find_int_time_by_sel (& data -> gts , it_idx );
196
+ if (prev_it < 0 )
197
+ return prev_it ;
198
+
199
+ if (prev_it == val2 )
200
+ return 0 ;
201
+
202
+ prev_gain = iio_gts_find_gain_by_sel (& data -> gts , gain_idx );
203
+ if (prev_gain < 0 )
204
+ return prev_gain ;
205
+
206
+ ret = iio_gts_find_new_gain_by_gain_time_min (& data -> gts , prev_gain , prev_it ,
207
+ val2 , & new_gain , & in_range );
208
+ if (ret )
209
+ return ret ;
210
+
211
+ if (!in_range )
212
+ dev_dbg (data -> dev , "Optimal gain out of range\n" );
213
+
214
+ ret = iio_gts_find_sel_by_int_time (& data -> gts , val2 );
215
+ if (ret < 0 )
216
+ return ret ;
217
+
218
+ ret = regmap_field_write (data -> rf .it , ret );
219
+ if (ret )
220
+ return ret ;
221
+
222
+ ret = iio_gts_find_sel_by_gain (& data -> gts , new_gain );
223
+ if (ret < 0 )
224
+ return ret ;
225
+
226
+ return regmap_field_write (data -> rf .gain , ret );
212
227
}
213
228
214
- static int veml3235_set_gain (struct iio_dev * indio_dev , int val , int val2 )
229
+ static int veml3235_set_scale (struct iio_dev * indio_dev , int val , int val2 )
215
230
{
216
231
struct veml3235_data * data = iio_priv (indio_dev );
217
- int ret , new_gain ;
232
+ int ret , it_idx , gain_sel , time_sel ;
218
233
219
- if (val2 != 0 )
220
- return - EINVAL ;
234
+ ret = regmap_field_read (data -> rf .it , & it_idx );
235
+ if (ret )
236
+ return ret ;
221
237
222
- switch (val ) {
223
- case 1 :
224
- new_gain = 0x00 ;
225
- break ;
226
- case 2 :
227
- new_gain = 0x01 ;
228
- break ;
229
- case 4 :
230
- new_gain = 0x03 ;
231
- break ;
232
- case 8 :
233
- new_gain = 0x07 ;
234
- break ;
235
- default :
236
- return - EINVAL ;
237
- }
238
+ ret = iio_gts_find_gain_time_sel_for_scale (& data -> gts , val , val2 ,
239
+ & gain_sel , & time_sel );
240
+ if (ret )
241
+ return ret ;
238
242
239
- ret = regmap_field_write (data -> rf .gain , new_gain );
240
- if (ret ) {
241
- dev_err (data -> dev , "failed to set gain: %d\n" , ret );
243
+ ret = regmap_field_write (data -> rf .it , time_sel );
244
+ if (ret )
242
245
return ret ;
243
- }
244
246
245
- return 0 ;
247
+ return regmap_field_write ( data -> rf . gain , gain_sel ) ;
246
248
}
247
249
248
- static int veml3235_get_gain (struct veml3235_data * data , int * val )
250
+ static int veml3235_get_scale (struct veml3235_data * data , int * val , int * val2 )
249
251
{
250
- int ret , reg ;
252
+ int gain , it , reg , ret ;
251
253
252
254
ret = regmap_field_read (data -> rf .gain , & reg );
253
255
if (ret ) {
254
256
dev_err (data -> dev , "failed to read gain %d\n" , ret );
255
257
return ret ;
256
258
}
257
259
258
- switch (reg & 0x03 ) {
259
- case 0 :
260
- * val = 1 ;
261
- break ;
262
- case 1 :
263
- * val = 2 ;
264
- break ;
265
- case 3 :
266
- * val = 4 ;
267
- break ;
268
- default :
269
- return - EINVAL ;
260
+ gain = iio_gts_find_gain_by_sel (& data -> gts , reg );
261
+ if (gain < 0 )
262
+ return gain ;
263
+
264
+ ret = regmap_field_read (data -> rf .it , & reg );
265
+ if (ret ) {
266
+ dev_err (data -> dev , "failed to read integration time %d\n" , ret );
267
+ return ret ;
270
268
}
271
269
272
- /* Double gain */
273
- if (reg & 0x04 )
274
- * val *= 2 ;
270
+ it = iio_gts_find_int_time_by_sel ( & data -> gts , reg );
271
+ if (it < 0 )
272
+ return it ;
275
273
276
- return IIO_VAL_INT ;
274
+ ret = iio_gts_get_scale (& data -> gts , gain , it , val , val2 );
275
+ if (ret )
276
+ return ret ;
277
+
278
+ return IIO_VAL_INT_PLUS_NANO ;
277
279
}
278
280
279
281
static int veml3235_read_raw (struct iio_dev * indio_dev ,
@@ -307,7 +309,7 @@ static int veml3235_read_raw(struct iio_dev *indio_dev,
307
309
case IIO_CHAN_INFO_INT_TIME :
308
310
return veml3235_get_it (data , val , val2 );
309
311
case IIO_CHAN_INFO_SCALE :
310
- return veml3235_get_gain (data , val );
312
+ return veml3235_get_scale (data , val , val2 );
311
313
default :
312
314
return - EINVAL ;
313
315
}
@@ -318,17 +320,27 @@ static int veml3235_read_avail(struct iio_dev *indio_dev,
318
320
const int * * vals , int * type , int * length ,
319
321
long mask )
320
322
{
323
+ struct veml3235_data * data = iio_priv (indio_dev );
324
+
321
325
switch (mask ) {
322
326
case IIO_CHAN_INFO_INT_TIME :
323
- * vals = (int * )& veml3235_it_times ;
324
- * length = 2 * ARRAY_SIZE (veml3235_it_times );
325
- * type = IIO_VAL_INT_PLUS_MICRO ;
326
- return IIO_AVAIL_LIST ;
327
+ return iio_gts_avail_times (& data -> gts , vals , type , length );
327
328
case IIO_CHAN_INFO_SCALE :
328
- * vals = (int * )& veml3235_scale_vals ;
329
- * length = ARRAY_SIZE (veml3235_scale_vals );
330
- * type = IIO_VAL_INT ;
331
- return IIO_AVAIL_LIST ;
329
+ return iio_gts_all_avail_scales (& data -> gts , vals , type , length );
330
+ default :
331
+ return - EINVAL ;
332
+ }
333
+ }
334
+
335
+ static int veml3235_write_raw_get_fmt (struct iio_dev * indio_dev ,
336
+ struct iio_chan_spec const * chan ,
337
+ long mask )
338
+ {
339
+ switch (mask ) {
340
+ case IIO_CHAN_INFO_SCALE :
341
+ return IIO_VAL_INT_PLUS_NANO ;
342
+ case IIO_CHAN_INFO_INT_TIME :
343
+ return IIO_VAL_INT_PLUS_MICRO ;
332
344
default :
333
345
return - EINVAL ;
334
346
}
@@ -342,7 +354,7 @@ static int veml3235_write_raw(struct iio_dev *indio_dev,
342
354
case IIO_CHAN_INFO_INT_TIME :
343
355
return veml3235_set_it (indio_dev , val , val2 );
344
356
case IIO_CHAN_INFO_SCALE :
345
- return veml3235_set_gain (indio_dev , val , val2 );
357
+ return veml3235_set_scale (indio_dev , val , val2 );
346
358
}
347
359
348
360
return - EINVAL ;
@@ -402,6 +414,13 @@ static int veml3235_hw_init(struct iio_dev *indio_dev)
402
414
struct device * dev = data -> dev ;
403
415
int ret ;
404
416
417
+ ret = devm_iio_init_iio_gts (data -> dev , 0 , 272640000 ,
418
+ veml3235_gain_sel , ARRAY_SIZE (veml3235_gain_sel ),
419
+ veml3235_it_sel , ARRAY_SIZE (veml3235_it_sel ),
420
+ & data -> gts );
421
+ if (ret )
422
+ return dev_err_probe (data -> dev , ret , "failed to init iio gts\n" );
423
+
405
424
/* Set gain to 1 and integration time to 100 ms */
406
425
ret = regmap_field_write (data -> rf .gain , 0x00 );
407
426
if (ret )
@@ -423,6 +442,7 @@ static const struct iio_info veml3235_info = {
423
442
.read_raw = veml3235_read_raw ,
424
443
.read_avail = veml3235_read_avail ,
425
444
.write_raw = veml3235_write_raw ,
445
+ .write_raw_get_fmt = veml3235_write_raw_get_fmt ,
426
446
};
427
447
428
448
static int veml3235_probe (struct i2c_client * client )
@@ -524,3 +544,4 @@ module_i2c_driver(veml3235_driver);
524
544
MODULE_AUTHOR (
"Javier Carrasco <[email protected] >" );
525
545
MODULE_DESCRIPTION ("VEML3235 Ambient Light Sensor" );
526
546
MODULE_LICENSE ("GPL" );
547
+ MODULE_IMPORT_NS ("IIO_GTS_HELPER" );
0 commit comments