1 /* SPDX-License-Identifier: GPL-2.0-only */ 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* gain-time-scale conversion helpers for IIO 2 /* gain-time-scale conversion helpers for IIO light sensors 3 * 3 * 4 * Copyright (c) 2023 Matti Vaittinen <mazzies 4 * Copyright (c) 2023 Matti Vaittinen <mazziesaccount@gmail.com> 5 */ 5 */ 6 6 7 #ifndef __IIO_GTS_HELPER__ 7 #ifndef __IIO_GTS_HELPER__ 8 #define __IIO_GTS_HELPER__ 8 #define __IIO_GTS_HELPER__ 9 9 10 #include <linux/types.h> 10 #include <linux/types.h> 11 11 12 struct device; 12 struct device; 13 13 14 /** 14 /** 15 * struct iio_gain_sel_pair - gain - selector 15 * struct iio_gain_sel_pair - gain - selector values 16 * 16 * 17 * In many cases devices like light sensors al 17 * In many cases devices like light sensors allow setting signal amplification 18 * (gain) using a register interface. This str 18 * (gain) using a register interface. This structure describes amplification 19 * and corresponding selector (register value) 19 * and corresponding selector (register value) 20 * 20 * 21 * @gain: Gain (multiplication) value. G 21 * @gain: Gain (multiplication) value. Gain must be positive, negative 22 * values are reserved for error 22 * values are reserved for error handling. 23 * @sel: Selector (usually register val 23 * @sel: Selector (usually register value) used to indicate this gain. 24 * NOTE: Only selectors >= 0 supp 24 * NOTE: Only selectors >= 0 supported. 25 */ 25 */ 26 struct iio_gain_sel_pair { 26 struct iio_gain_sel_pair { 27 int gain; 27 int gain; 28 int sel; 28 int sel; 29 }; 29 }; 30 30 31 /** 31 /** 32 * struct iio_itime_sel_mul - integration time 32 * struct iio_itime_sel_mul - integration time description 33 * 33 * 34 * In many cases devices like light sensors al 34 * In many cases devices like light sensors allow setting the duration of 35 * collecting data. Typically this duration ha 35 * collecting data. Typically this duration has also an impact to the magnitude 36 * of measured values (gain). This structure d 36 * of measured values (gain). This structure describes the relation of 37 * integration time and amplification as well 37 * integration time and amplification as well as corresponding selector 38 * (register value). 38 * (register value). 39 * 39 * 40 * An example could be a sensor allowing 50, 1 40 * An example could be a sensor allowing 50, 100, 200 and 400 mS times. The 41 * respective multiplication values could be 5 41 * respective multiplication values could be 50 mS => 1, 100 mS => 2, 42 * 200 mS => 4 and 400 mS => 8 assuming the im 42 * 200 mS => 4 and 400 mS => 8 assuming the impact of integration time would be 43 * linear in a way that when collecting data f 43 * linear in a way that when collecting data for 50 mS caused value X, doubling 44 * the data collection time caused value 2X et 44 * the data collection time caused value 2X etc. 45 * 45 * 46 * @time_us: Integration time in microsecon 46 * @time_us: Integration time in microseconds. Time values must be positive, 47 * negative values are reserved f 47 * negative values are reserved for error handling. 48 * @sel: Selector (usually register val 48 * @sel: Selector (usually register value) used to indicate this time 49 * NOTE: Only selectors >= 0 supp 49 * NOTE: Only selectors >= 0 supported. 50 * @mul: Multiplication to the values c 50 * @mul: Multiplication to the values caused by this time. 51 * NOTE: Only multipliers > 0 sup 51 * NOTE: Only multipliers > 0 supported. 52 */ 52 */ 53 struct iio_itime_sel_mul { 53 struct iio_itime_sel_mul { 54 int time_us; 54 int time_us; 55 int sel; 55 int sel; 56 int mul; 56 int mul; 57 }; 57 }; 58 58 59 struct iio_gts { 59 struct iio_gts { 60 u64 max_scale; 60 u64 max_scale; 61 const struct iio_gain_sel_pair *hwgain 61 const struct iio_gain_sel_pair *hwgain_table; 62 int num_hwgain; 62 int num_hwgain; 63 const struct iio_itime_sel_mul *itime_ 63 const struct iio_itime_sel_mul *itime_table; 64 int num_itime; 64 int num_itime; 65 int **per_time_avail_scale_tables; 65 int **per_time_avail_scale_tables; 66 int *avail_all_scales_table; 66 int *avail_all_scales_table; 67 int num_avail_all_scales; 67 int num_avail_all_scales; 68 int *avail_time_tables; 68 int *avail_time_tables; 69 int num_avail_time_tables; 69 int num_avail_time_tables; 70 }; 70 }; 71 71 72 #define GAIN_SCALE_GAIN(_gain, _sel) 72 #define GAIN_SCALE_GAIN(_gain, _sel) \ 73 { 73 { \ 74 .gain = (_gain), 74 .gain = (_gain), \ 75 .sel = (_sel), 75 .sel = (_sel), \ 76 } 76 } 77 77 78 #define GAIN_SCALE_ITIME_US(_itime, _sel, _mul 78 #define GAIN_SCALE_ITIME_US(_itime, _sel, _mul) \ 79 { 79 { \ 80 .time_us = (_itime), 80 .time_us = (_itime), \ 81 .sel = (_sel), 81 .sel = (_sel), \ 82 .mul = (_mul), 82 .mul = (_mul), \ 83 } 83 } 84 84 85 static inline const struct iio_itime_sel_mul * 85 static inline const struct iio_itime_sel_mul * 86 iio_gts_find_itime_by_time(struct iio_gts *gts 86 iio_gts_find_itime_by_time(struct iio_gts *gts, int time) 87 { 87 { 88 int i; 88 int i; 89 89 90 if (!gts->num_itime) 90 if (!gts->num_itime) 91 return NULL; 91 return NULL; 92 92 93 for (i = 0; i < gts->num_itime; i++) 93 for (i = 0; i < gts->num_itime; i++) 94 if (gts->itime_table[i].time_u 94 if (gts->itime_table[i].time_us == time) 95 return >s->itime_tab 95 return >s->itime_table[i]; 96 96 97 return NULL; 97 return NULL; 98 } 98 } 99 99 100 static inline const struct iio_itime_sel_mul * 100 static inline const struct iio_itime_sel_mul * 101 iio_gts_find_itime_by_sel(struct iio_gts *gts, 101 iio_gts_find_itime_by_sel(struct iio_gts *gts, int sel) 102 { 102 { 103 int i; 103 int i; 104 104 105 for (i = 0; i < gts->num_itime; i++) 105 for (i = 0; i < gts->num_itime; i++) 106 if (gts->itime_table[i].sel == 106 if (gts->itime_table[i].sel == sel) 107 return >s->itime_tab 107 return >s->itime_table[i]; 108 108 109 return NULL; 109 return NULL; 110 } 110 } 111 111 112 int devm_iio_init_iio_gts(struct device *dev, 112 int devm_iio_init_iio_gts(struct device *dev, int max_scale_int, int max_scale_nano, 113 const struct iio_gai 113 const struct iio_gain_sel_pair *gain_tbl, int num_gain, 114 const struct iio_iti 114 const struct iio_itime_sel_mul *tim_tbl, int num_times, 115 struct iio_gts *gts) 115 struct iio_gts *gts); 116 /** 116 /** 117 * iio_gts_find_int_time_by_sel - find integra 117 * iio_gts_find_int_time_by_sel - find integration time matching a selector 118 * @gts: Gain time scale descriptor 118 * @gts: Gain time scale descriptor 119 * @sel: selector for which matching in 119 * @sel: selector for which matching integration time is searched for 120 * 120 * 121 * Return: integration time matching give 121 * Return: integration time matching given selector or -EINVAL if 122 * integration time was not found 122 * integration time was not found. 123 */ 123 */ 124 static inline int iio_gts_find_int_time_by_sel 124 static inline int iio_gts_find_int_time_by_sel(struct iio_gts *gts, int sel) 125 { 125 { 126 const struct iio_itime_sel_mul *itime; 126 const struct iio_itime_sel_mul *itime; 127 127 128 itime = iio_gts_find_itime_by_sel(gts, 128 itime = iio_gts_find_itime_by_sel(gts, sel); 129 if (!itime) 129 if (!itime) 130 return -EINVAL; 130 return -EINVAL; 131 131 132 return itime->time_us; 132 return itime->time_us; 133 } 133 } 134 134 135 /** 135 /** 136 * iio_gts_find_sel_by_int_time - find selecto 136 * iio_gts_find_sel_by_int_time - find selector matching integration time 137 * @gts: Gain time scale descriptor 137 * @gts: Gain time scale descriptor 138 * @time: Integration time for which mat 138 * @time: Integration time for which matching selector is searched for 139 * 139 * 140 * Return: a selector matching given inte 140 * Return: a selector matching given integration time or -EINVAL if 141 * selector was not found. 141 * selector was not found. 142 */ 142 */ 143 static inline int iio_gts_find_sel_by_int_time 143 static inline int iio_gts_find_sel_by_int_time(struct iio_gts *gts, int time) 144 { 144 { 145 const struct iio_itime_sel_mul *itime; 145 const struct iio_itime_sel_mul *itime; 146 146 147 itime = iio_gts_find_itime_by_time(gts 147 itime = iio_gts_find_itime_by_time(gts, time); 148 if (!itime) 148 if (!itime) 149 return -EINVAL; 149 return -EINVAL; 150 150 151 return itime->sel; 151 return itime->sel; 152 } 152 } 153 153 154 /** 154 /** 155 * iio_gts_valid_time - check if given integra 155 * iio_gts_valid_time - check if given integration time is valid 156 * @gts: Gain time scale descriptor 156 * @gts: Gain time scale descriptor 157 * @time_us: Integration time to check 157 * @time_us: Integration time to check 158 * 158 * 159 * Return: True if given time is supporte 159 * Return: True if given time is supported by device. False if not. 160 */ 160 */ 161 static inline bool iio_gts_valid_time(struct i 161 static inline bool iio_gts_valid_time(struct iio_gts *gts, int time_us) 162 { 162 { 163 return iio_gts_find_itime_by_time(gts, 163 return iio_gts_find_itime_by_time(gts, time_us) != NULL; 164 } 164 } 165 165 166 int iio_gts_find_sel_by_gain(struct iio_gts *g 166 int iio_gts_find_sel_by_gain(struct iio_gts *gts, int gain); 167 167 168 /** 168 /** 169 * iio_gts_valid_gain - check if given HW-gain 169 * iio_gts_valid_gain - check if given HW-gain is valid 170 * @gts: Gain time scale descriptor 170 * @gts: Gain time scale descriptor 171 * @gain: HW-gain to check 171 * @gain: HW-gain to check 172 * 172 * 173 * Return: True if given time is supporte 173 * Return: True if given time is supported by device. False if not. 174 */ 174 */ 175 static inline bool iio_gts_valid_gain(struct i 175 static inline bool iio_gts_valid_gain(struct iio_gts *gts, int gain) 176 { 176 { 177 return iio_gts_find_sel_by_gain(gts, g 177 return iio_gts_find_sel_by_gain(gts, gain) >= 0; 178 } 178 } 179 179 180 int iio_find_closest_gain_low(struct iio_gts * 180 int iio_find_closest_gain_low(struct iio_gts *gts, int gain, bool *in_range); 181 int iio_gts_find_gain_by_sel(struct iio_gts *g 181 int iio_gts_find_gain_by_sel(struct iio_gts *gts, int sel); 182 int iio_gts_get_min_gain(struct iio_gts *gts); 182 int iio_gts_get_min_gain(struct iio_gts *gts); 183 int iio_gts_find_int_time_by_sel(struct iio_gt 183 int iio_gts_find_int_time_by_sel(struct iio_gts *gts, int sel); 184 int iio_gts_find_sel_by_int_time(struct iio_gt 184 int iio_gts_find_sel_by_int_time(struct iio_gts *gts, int time); 185 185 186 int iio_gts_total_gain_to_scale(struct iio_gts 186 int iio_gts_total_gain_to_scale(struct iio_gts *gts, int total_gain, 187 int *scale_int 187 int *scale_int, int *scale_nano); 188 int iio_gts_find_gain_sel_for_scale_using_time 188 int iio_gts_find_gain_sel_for_scale_using_time(struct iio_gts *gts, int time_sel, 189 189 int scale_int, int scale_nano, 190 190 int *gain_sel); 191 int iio_gts_get_scale(struct iio_gts *gts, int 191 int iio_gts_get_scale(struct iio_gts *gts, int gain, int time, int *scale_int, 192 int *scale_nano); 192 int *scale_nano); 193 int iio_gts_find_new_gain_sel_by_old_gain_time 193 int iio_gts_find_new_gain_sel_by_old_gain_time(struct iio_gts *gts, 194 194 int old_gain, int old_time_sel, 195 195 int new_time_sel, int *new_gain); 196 int iio_gts_find_new_gain_by_old_gain_time(str 196 int iio_gts_find_new_gain_by_old_gain_time(struct iio_gts *gts, int old_gain, 197 int 197 int old_time, int new_time, 198 int 198 int *new_gain); 199 int iio_gts_avail_times(struct iio_gts *gts, 199 int iio_gts_avail_times(struct iio_gts *gts, const int **vals, int *type, 200 int *length); 200 int *length); 201 int iio_gts_all_avail_scales(struct iio_gts *g 201 int iio_gts_all_avail_scales(struct iio_gts *gts, const int **vals, int *type, 202 int *length); 202 int *length); 203 int iio_gts_avail_scales_for_time(struct iio_g 203 int iio_gts_avail_scales_for_time(struct iio_gts *gts, int time, 204 const int ** 204 const int **vals, int *type, int *length); 205 205 206 #endif 206 #endif 207 207
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.