xref: /linux/drivers/iio/test/iio-test-gts.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1cf996f03SMatti Vaittinen // SPDX-License-Identifier: GPL-2.0-only
2cf996f03SMatti Vaittinen /* Unit tests for IIO light sensor gain-time-scale helpers
3cf996f03SMatti Vaittinen  *
4cf996f03SMatti Vaittinen  * Copyright (c) 2023 Matti Vaittinen <mazziesaccount@gmail.com>
5cf996f03SMatti Vaittinen  */
6cf996f03SMatti Vaittinen 
7cf996f03SMatti Vaittinen #include <kunit/device.h>
8cf996f03SMatti Vaittinen #include <kunit/test.h>
9cf996f03SMatti Vaittinen #include <linux/device.h>
10cf996f03SMatti Vaittinen #include <linux/iio/iio-gts-helper.h>
11cf996f03SMatti Vaittinen #include <linux/iio/types.h>
12cf996f03SMatti Vaittinen 
13cf996f03SMatti Vaittinen /*
14cf996f03SMatti Vaittinen  * Please, read the "rant" from the top of the lib/test_linear_ranges.c if
15cf996f03SMatti Vaittinen  * you see a line of helper code which is not being tested.
16cf996f03SMatti Vaittinen  *
17cf996f03SMatti Vaittinen  * Then, please look at the line which is not being tested. Is this line
18cf996f03SMatti Vaittinen  * somehow unusually complex? If answer is "no", then chances are that the
19cf996f03SMatti Vaittinen  * "development inertia" caused by adding a test exceeds the benefits.
20cf996f03SMatti Vaittinen  *
21cf996f03SMatti Vaittinen  * If yes, then adding a test is probably a good idea but please stop for a
22cf996f03SMatti Vaittinen  * moment and consider the effort of changing all the tests when code gets
23cf996f03SMatti Vaittinen  * refactored. Eventually it neeeds to be.
24cf996f03SMatti Vaittinen  */
25cf996f03SMatti Vaittinen 
26cf996f03SMatti Vaittinen #define TEST_TSEL_50		1
27cf996f03SMatti Vaittinen #define TEST_TSEL_X_MIN		TEST_TSEL_50
28cf996f03SMatti Vaittinen #define TEST_TSEL_100		0
29cf996f03SMatti Vaittinen #define TEST_TSEL_200		2
30cf996f03SMatti Vaittinen #define TEST_TSEL_400		4
31cf996f03SMatti Vaittinen #define TEST_TSEL_X_MAX		TEST_TSEL_400
32cf996f03SMatti Vaittinen 
33cf996f03SMatti Vaittinen #define TEST_GSEL_1		0x00
34cf996f03SMatti Vaittinen #define TEST_GSEL_X_MIN		TEST_GSEL_1
35cf996f03SMatti Vaittinen #define TEST_GSEL_4		0x08
36cf996f03SMatti Vaittinen #define TEST_GSEL_16		0x0a
37cf996f03SMatti Vaittinen #define TEST_GSEL_32		0x0b
38cf996f03SMatti Vaittinen #define TEST_GSEL_64		0x0c
39cf996f03SMatti Vaittinen #define TEST_GSEL_256		0x18
40cf996f03SMatti Vaittinen #define TEST_GSEL_512		0x19
41cf996f03SMatti Vaittinen #define TEST_GSEL_1024		0x1a
42cf996f03SMatti Vaittinen #define TEST_GSEL_2048		0x1b
43cf996f03SMatti Vaittinen #define TEST_GSEL_4096		0x1c
44cf996f03SMatti Vaittinen #define TEST_GSEL_X_MAX		TEST_GSEL_4096
45cf996f03SMatti Vaittinen 
46cf996f03SMatti Vaittinen #define TEST_SCALE_1X		64
47cf996f03SMatti Vaittinen #define TEST_SCALE_MIN_X	TEST_SCALE_1X
48cf996f03SMatti Vaittinen #define TEST_SCALE_2X		32
49cf996f03SMatti Vaittinen #define TEST_SCALE_4X		16
50cf996f03SMatti Vaittinen #define TEST_SCALE_8X		8
51cf996f03SMatti Vaittinen #define TEST_SCALE_16X		4
52cf996f03SMatti Vaittinen #define TEST_SCALE_32X		2
53cf996f03SMatti Vaittinen #define TEST_SCALE_64X		1
54cf996f03SMatti Vaittinen 
55cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_128X	500000000
56cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_256X	250000000
57cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_512X	125000000
58cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_1024X	62500000
59cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_2048X	31250000
60cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_4096X	15625000
61cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_4096X2	7812500
62cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_4096X4	3906250
63cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_4096X8	1953125
64cf996f03SMatti Vaittinen 
65cf996f03SMatti Vaittinen #define TEST_SCALE_NANO_MAX_X TEST_SCALE_NANO_4096X8
66cf996f03SMatti Vaittinen 
67cf996f03SMatti Vaittinen /*
68cf996f03SMatti Vaittinen  * Can't have this allocated from stack because the kunit clean-up will
69cf996f03SMatti Vaittinen  * happen only after the test function has already gone
70cf996f03SMatti Vaittinen  */
71cf996f03SMatti Vaittinen static struct iio_gts gts;
72cf996f03SMatti Vaittinen 
73*6de2f3a1SMatti Vaittinen /* Keep the gain and time tables unsorted to test the sorting */
74cf996f03SMatti Vaittinen static const struct iio_gain_sel_pair gts_test_gains[] = {
75cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(1, TEST_GSEL_1),
76cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(4, TEST_GSEL_4),
77cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(16, TEST_GSEL_16),
78cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(32, TEST_GSEL_32),
79cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(64, TEST_GSEL_64),
80cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(256, TEST_GSEL_256),
81cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(512, TEST_GSEL_512),
82cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(1024, TEST_GSEL_1024),
83cf996f03SMatti Vaittinen 	GAIN_SCALE_GAIN(4096, TEST_GSEL_4096),
84*6de2f3a1SMatti Vaittinen 	GAIN_SCALE_GAIN(2048, TEST_GSEL_2048),
85cf996f03SMatti Vaittinen #define HWGAIN_MAX 4096
86cf996f03SMatti Vaittinen };
87cf996f03SMatti Vaittinen 
88cf996f03SMatti Vaittinen static const struct iio_itime_sel_mul gts_test_itimes[] = {
89cf996f03SMatti Vaittinen 	GAIN_SCALE_ITIME_US(100 * 1000, TEST_TSEL_100, 2),
90*6de2f3a1SMatti Vaittinen 	GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8),
91*6de2f3a1SMatti Vaittinen 	GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8),
92cf996f03SMatti Vaittinen 	GAIN_SCALE_ITIME_US(50 * 1000, TEST_TSEL_50, 1),
93*6de2f3a1SMatti Vaittinen 	GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
94cf996f03SMatti Vaittinen #define TIMEGAIN_MAX 8
95cf996f03SMatti Vaittinen };
96cf996f03SMatti Vaittinen #define TOTAL_GAIN_MAX	(HWGAIN_MAX * TIMEGAIN_MAX)
97cf996f03SMatti Vaittinen #define IIO_GTS_TEST_DEV "iio-gts-test-dev"
98cf996f03SMatti Vaittinen 
__test_init_iio_gain_scale(struct kunit * test,struct iio_gts * gts,const struct iio_gain_sel_pair * g_table,int num_g,const struct iio_itime_sel_mul * i_table,int num_i)99cf996f03SMatti Vaittinen static struct device *__test_init_iio_gain_scale(struct kunit *test,
100cf996f03SMatti Vaittinen 		struct iio_gts *gts, const struct iio_gain_sel_pair *g_table,
101cf996f03SMatti Vaittinen 		int num_g, const struct iio_itime_sel_mul *i_table, int num_i)
102cf996f03SMatti Vaittinen {
103cf996f03SMatti Vaittinen 	struct device *dev;
104cf996f03SMatti Vaittinen 	int ret;
105cf996f03SMatti Vaittinen 
106cf996f03SMatti Vaittinen 	dev = kunit_device_register(test, IIO_GTS_TEST_DEV);
107cf996f03SMatti Vaittinen 
108cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
109cf996f03SMatti Vaittinen 	if (IS_ERR_OR_NULL(dev))
110cf996f03SMatti Vaittinen 		return NULL;
111cf996f03SMatti Vaittinen 
112cf996f03SMatti Vaittinen 	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, g_table, num_g,
113cf996f03SMatti Vaittinen 				    i_table, num_i, gts);
114cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
115cf996f03SMatti Vaittinen 	if (ret)
116cf996f03SMatti Vaittinen 		return NULL;
117cf996f03SMatti Vaittinen 
118cf996f03SMatti Vaittinen 	return dev;
119cf996f03SMatti Vaittinen }
120cf996f03SMatti Vaittinen 
121cf996f03SMatti Vaittinen #define test_init_iio_gain_scale(test, gts)	\
122cf996f03SMatti Vaittinen 	__test_init_iio_gain_scale(test, gts, gts_test_gains, \
123cf996f03SMatti Vaittinen 				   ARRAY_SIZE(gts_test_gains), gts_test_itimes, \
124cf996f03SMatti Vaittinen 				   ARRAY_SIZE(gts_test_itimes))
125cf996f03SMatti Vaittinen 
test_init_iio_gts_invalid(struct kunit * test)126cf996f03SMatti Vaittinen static void test_init_iio_gts_invalid(struct kunit *test)
127cf996f03SMatti Vaittinen {
128cf996f03SMatti Vaittinen 	struct device *dev;
129cf996f03SMatti Vaittinen 	int ret;
130cf996f03SMatti Vaittinen 	const struct iio_itime_sel_mul itimes_neg[] = {
131cf996f03SMatti Vaittinen 		GAIN_SCALE_ITIME_US(-10, TEST_TSEL_400, 8),
132cf996f03SMatti Vaittinen 		GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
133cf996f03SMatti Vaittinen 	};
134cf996f03SMatti Vaittinen 	const struct iio_gain_sel_pair gains_neg[] = {
135cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(1, TEST_GSEL_1),
136cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(2, TEST_GSEL_4),
137cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(-2, TEST_GSEL_16),
138cf996f03SMatti Vaittinen 	};
139cf996f03SMatti Vaittinen 	/* 55555 * 38656 = 2147534080 => overflows 32bit int */
140cf996f03SMatti Vaittinen 	const struct iio_itime_sel_mul itimes_overflow[] = {
141cf996f03SMatti Vaittinen 		GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 55555),
142cf996f03SMatti Vaittinen 		GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
143cf996f03SMatti Vaittinen 	};
144cf996f03SMatti Vaittinen 	const struct iio_gain_sel_pair gains_overflow[] = {
145cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(1, TEST_GSEL_1),
146cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(2, TEST_GSEL_4),
147cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(38656, TEST_GSEL_16),
148cf996f03SMatti Vaittinen 	};
149cf996f03SMatti Vaittinen 
150cf996f03SMatti Vaittinen 	dev = kunit_device_register(test, IIO_GTS_TEST_DEV);
151cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
152cf996f03SMatti Vaittinen 	if (!dev)
153cf996f03SMatti Vaittinen 		return;
154cf996f03SMatti Vaittinen 
155cf996f03SMatti Vaittinen 	/* Ok gains, negative time */
156cf996f03SMatti Vaittinen 	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gts_test_gains,
157cf996f03SMatti Vaittinen 				    ARRAY_SIZE(gts_test_gains), itimes_neg,
158cf996f03SMatti Vaittinen 				    ARRAY_SIZE(itimes_neg), &gts);
159cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, -EINVAL, ret);
160cf996f03SMatti Vaittinen 
161cf996f03SMatti Vaittinen 	/* Ok times, negative gain */
162cf996f03SMatti Vaittinen 	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_neg,
163cf996f03SMatti Vaittinen 				    ARRAY_SIZE(gains_neg), gts_test_itimes,
164cf996f03SMatti Vaittinen 				    ARRAY_SIZE(gts_test_itimes), &gts);
165cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, -EINVAL, ret);
166cf996f03SMatti Vaittinen 
167cf996f03SMatti Vaittinen 	/* gain * time overflow int */
168cf996f03SMatti Vaittinen 	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_overflow,
169cf996f03SMatti Vaittinen 				    ARRAY_SIZE(gains_overflow), itimes_overflow,
170cf996f03SMatti Vaittinen 				    ARRAY_SIZE(itimes_overflow), &gts);
171cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, -EOVERFLOW, ret);
172cf996f03SMatti Vaittinen }
173cf996f03SMatti Vaittinen 
test_iio_gts_find_gain_for_scale_using_time(struct kunit * test)174cf996f03SMatti Vaittinen static void test_iio_gts_find_gain_for_scale_using_time(struct kunit *test)
175cf996f03SMatti Vaittinen {
176cf996f03SMatti Vaittinen 	struct device *dev;
177cf996f03SMatti Vaittinen 	int ret, gain_sel;
178cf996f03SMatti Vaittinen 
179cf996f03SMatti Vaittinen 	dev = test_init_iio_gain_scale(test, &gts);
180cf996f03SMatti Vaittinen 	if (!dev)
181cf996f03SMatti Vaittinen 		return;
182cf996f03SMatti Vaittinen 
183cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100,
184cf996f03SMatti Vaittinen 						TEST_SCALE_8X, 0, &gain_sel);
185cf996f03SMatti Vaittinen 	/*
186cf996f03SMatti Vaittinen 	 * Meas time 100 => gain by time 2x
187cf996f03SMatti Vaittinen 	 * TEST_SCALE_8X matches total gain 8x
188cf996f03SMatti Vaittinen 	 * => required HWGAIN 4x
189cf996f03SMatti Vaittinen 	 */
190cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
191cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_GSEL_4, gain_sel);
192cf996f03SMatti Vaittinen 
193cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,
194cf996f03SMatti Vaittinen 						TEST_SCALE_NANO_256X, &gain_sel);
195cf996f03SMatti Vaittinen 	/*
196cf996f03SMatti Vaittinen 	 * Meas time 200 => gain by time 4x
197cf996f03SMatti Vaittinen 	 * TEST_SCALE_256X matches total gain 256x
198cf996f03SMatti Vaittinen 	 * => required HWGAIN 256/4 => 64x
199cf996f03SMatti Vaittinen 	 */
200cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
201cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_GSEL_64, gain_sel);
202cf996f03SMatti Vaittinen 
203cf996f03SMatti Vaittinen 	/* Min time, Min gain */
204cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MIN,
205cf996f03SMatti Vaittinen 						TEST_SCALE_MIN_X, 0, &gain_sel);
206cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
207cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_GSEL_1, gain_sel);
208cf996f03SMatti Vaittinen 
209cf996f03SMatti Vaittinen 	/* Max time, Max gain */
210cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MAX,
211cf996f03SMatti Vaittinen 					0, TEST_SCALE_NANO_MAX_X, &gain_sel);
212cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
213cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_GSEL_4096, gain_sel);
214cf996f03SMatti Vaittinen 
215cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100, 0,
216cf996f03SMatti Vaittinen 						TEST_SCALE_NANO_256X, &gain_sel);
217cf996f03SMatti Vaittinen 	/*
218cf996f03SMatti Vaittinen 	 * Meas time 100 => gain by time 2x
219cf996f03SMatti Vaittinen 	 * TEST_SCALE_256X matches total gain 256x
220cf996f03SMatti Vaittinen 	 * => required HWGAIN 256/2 => 128x (not in gain-table - unsupported)
221cf996f03SMatti Vaittinen 	 */
222cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
223cf996f03SMatti Vaittinen 
224cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,
225cf996f03SMatti Vaittinen 						TEST_SCALE_NANO_MAX_X, &gain_sel);
226cf996f03SMatti Vaittinen 	/* We can't reach the max gain with integration time smaller than MAX */
227cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
228cf996f03SMatti Vaittinen 
229cf996f03SMatti Vaittinen 	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_50, 0,
230cf996f03SMatti Vaittinen 						TEST_SCALE_NANO_MAX_X, &gain_sel);
231cf996f03SMatti Vaittinen 	/* We can't reach the max gain with integration time smaller than MAX */
232cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
233cf996f03SMatti Vaittinen }
234cf996f03SMatti Vaittinen 
test_iio_gts_find_new_gain_sel_by_old_gain_time(struct kunit * test)235cf996f03SMatti Vaittinen static void test_iio_gts_find_new_gain_sel_by_old_gain_time(struct kunit *test)
236cf996f03SMatti Vaittinen {
237cf996f03SMatti Vaittinen 	struct device *dev;
238cf996f03SMatti Vaittinen 	int ret, old_gain, new_gain, old_time_sel, new_time_sel;
239cf996f03SMatti Vaittinen 
240cf996f03SMatti Vaittinen 	dev = test_init_iio_gain_scale(test, &gts);
241cf996f03SMatti Vaittinen 	if (!dev)
242cf996f03SMatti Vaittinen 		return;
243cf996f03SMatti Vaittinen 
244cf996f03SMatti Vaittinen 	old_gain = 32;
245cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_200;
246cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_400;
247cf996f03SMatti Vaittinen 
248cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
249cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
250cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
251cf996f03SMatti Vaittinen 	/*
252cf996f03SMatti Vaittinen 	 * Doubling the integration time doubles the total gain - so old
253cf996f03SMatti Vaittinen 	 * (hw)gain must be divided by two to compensate. => 32 / 2 => 16
254cf996f03SMatti Vaittinen 	 */
255cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 16, new_gain);
256cf996f03SMatti Vaittinen 
257cf996f03SMatti Vaittinen 	old_gain = 4;
258cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_50;
259cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_200;
260cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
261cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
262cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
263cf996f03SMatti Vaittinen 	/*
264cf996f03SMatti Vaittinen 	 * gain by time 1x => 4x - (hw)gain 4x => 1x
265cf996f03SMatti Vaittinen 	 */
266cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 1, new_gain);
267cf996f03SMatti Vaittinen 
268cf996f03SMatti Vaittinen 	old_gain = 512;
269cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_400;
270cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_50;
271cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
272cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
273cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
274cf996f03SMatti Vaittinen 	/*
275cf996f03SMatti Vaittinen 	 * gain by time 8x => 1x - (hw)gain 512x => 4096x)
276cf996f03SMatti Vaittinen 	 */
277cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 4096, new_gain);
278cf996f03SMatti Vaittinen 
279cf996f03SMatti Vaittinen 	/* Unsupported gain 2x */
280cf996f03SMatti Vaittinen 	old_gain = 4;
281cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_200;
282cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_400;
283cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
284cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
285cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
286cf996f03SMatti Vaittinen 
287cf996f03SMatti Vaittinen 	/* Too small gain */
288cf996f03SMatti Vaittinen 	old_gain = 4;
289cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_50;
290cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_400;
291cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
292cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
293cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
294cf996f03SMatti Vaittinen 
295cf996f03SMatti Vaittinen 	/* Too big gain */
296cf996f03SMatti Vaittinen 	old_gain = 1024;
297cf996f03SMatti Vaittinen 	old_time_sel = TEST_TSEL_400;
298cf996f03SMatti Vaittinen 	new_time_sel = TEST_TSEL_50;
299cf996f03SMatti Vaittinen 	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
300cf996f03SMatti Vaittinen 					old_time_sel, new_time_sel, &new_gain);
301cf996f03SMatti Vaittinen 	KUNIT_EXPECT_NE(test, 0, ret);
302cf996f03SMatti Vaittinen 
303cf996f03SMatti Vaittinen }
304cf996f03SMatti Vaittinen 
test_iio_find_closest_gain_low(struct kunit * test)305cf996f03SMatti Vaittinen static void test_iio_find_closest_gain_low(struct kunit *test)
306cf996f03SMatti Vaittinen {
307cf996f03SMatti Vaittinen 	struct device *dev;
308cf996f03SMatti Vaittinen 	bool in_range;
309cf996f03SMatti Vaittinen 	int ret;
310cf996f03SMatti Vaittinen 
311cf996f03SMatti Vaittinen 	const struct iio_gain_sel_pair gts_test_gains_gain_low[] = {
312cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(4, TEST_GSEL_4),
313cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(16, TEST_GSEL_16),
314cf996f03SMatti Vaittinen 		GAIN_SCALE_GAIN(32, TEST_GSEL_32),
315cf996f03SMatti Vaittinen 	};
316cf996f03SMatti Vaittinen 
317cf996f03SMatti Vaittinen 	dev = test_init_iio_gain_scale(test, &gts);
318cf996f03SMatti Vaittinen 	if (!dev)
319cf996f03SMatti Vaittinen 		return;
320cf996f03SMatti Vaittinen 
321cf996f03SMatti Vaittinen 	ret = iio_find_closest_gain_low(&gts, 2, &in_range);
322cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 1, ret);
323cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, true, in_range);
324cf996f03SMatti Vaittinen 
325cf996f03SMatti Vaittinen 	ret = iio_find_closest_gain_low(&gts, 1, &in_range);
326cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 1, ret);
327cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, true, in_range);
328cf996f03SMatti Vaittinen 
329cf996f03SMatti Vaittinen 	ret = iio_find_closest_gain_low(&gts, 4095, &in_range);
330cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 2048, ret);
331cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, true, in_range);
332cf996f03SMatti Vaittinen 
333cf996f03SMatti Vaittinen 	ret = iio_find_closest_gain_low(&gts, 4097, &in_range);
334cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 4096, ret);
335cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, false, in_range);
336cf996f03SMatti Vaittinen 
337cf996f03SMatti Vaittinen 	kunit_device_unregister(test, dev);
338cf996f03SMatti Vaittinen 
339cf996f03SMatti Vaittinen 	dev = __test_init_iio_gain_scale(test, &gts, gts_test_gains_gain_low,
340cf996f03SMatti Vaittinen 				ARRAY_SIZE(gts_test_gains_gain_low),
341cf996f03SMatti Vaittinen 				gts_test_itimes, ARRAY_SIZE(gts_test_itimes));
342cf996f03SMatti Vaittinen 	if (!dev)
343cf996f03SMatti Vaittinen 		return;
344cf996f03SMatti Vaittinen 
345cf996f03SMatti Vaittinen 	ret = iio_find_closest_gain_low(&gts, 3, &in_range);
346cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, -EINVAL, ret);
347cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, false, in_range);
348cf996f03SMatti Vaittinen }
349cf996f03SMatti Vaittinen 
test_iio_gts_total_gain_to_scale(struct kunit * test)350cf996f03SMatti Vaittinen static void test_iio_gts_total_gain_to_scale(struct kunit *test)
351cf996f03SMatti Vaittinen {
352cf996f03SMatti Vaittinen 	struct device *dev;
353cf996f03SMatti Vaittinen 	int ret, scale_int, scale_nano;
354cf996f03SMatti Vaittinen 
355cf996f03SMatti Vaittinen 	dev = test_init_iio_gain_scale(test, &gts);
356cf996f03SMatti Vaittinen 	if (!dev)
357cf996f03SMatti Vaittinen 		return;
358cf996f03SMatti Vaittinen 
359cf996f03SMatti Vaittinen 	ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);
360cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
361cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);
362cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, scale_nano);
363cf996f03SMatti Vaittinen 
364cf996f03SMatti Vaittinen 	ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);
365cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
366cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);
367cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, scale_nano);
368cf996f03SMatti Vaittinen 
369cf996f03SMatti Vaittinen 	ret = iio_gts_total_gain_to_scale(&gts, 4096 * 8, &scale_int,
370cf996f03SMatti Vaittinen 					  &scale_nano);
371cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, ret);
372cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 0, scale_int);
373cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, TEST_SCALE_NANO_4096X8, scale_nano);
374cf996f03SMatti Vaittinen }
375cf996f03SMatti Vaittinen 
test_iio_gts_chk_times(struct kunit * test,const int * vals)376cf996f03SMatti Vaittinen static void test_iio_gts_chk_times(struct kunit *test, const int *vals)
377cf996f03SMatti Vaittinen {
378cf996f03SMatti Vaittinen 	static const int expected[] = {0, 50000, 0, 100000, 0, 200000, 0, 400000};
379cf996f03SMatti Vaittinen 	int i;
380cf996f03SMatti Vaittinen 
381cf996f03SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(expected); i++)
382cf996f03SMatti Vaittinen 		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
383cf996f03SMatti Vaittinen }
384cf996f03SMatti Vaittinen 
test_iio_gts_chk_scales_all(struct kunit * test,struct iio_gts * gts,const int * vals,int len)385cf996f03SMatti Vaittinen static void test_iio_gts_chk_scales_all(struct kunit *test, struct iio_gts *gts,
386cf996f03SMatti Vaittinen 					const int *vals, int len)
387cf996f03SMatti Vaittinen {
388cf996f03SMatti Vaittinen 	static const int gains[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
389cf996f03SMatti Vaittinen 				    1024, 2048, 4096, 4096 * 2, 4096 * 4,
390cf996f03SMatti Vaittinen 				    4096 * 8};
391cf996f03SMatti Vaittinen 	int expected[ARRAY_SIZE(gains) * 2];
392cf996f03SMatti Vaittinen 	int i, ret;
393cf996f03SMatti Vaittinen 	int exp_len = ARRAY_SIZE(gains) * 2;
394cf996f03SMatti Vaittinen 
395cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, exp_len, len);
396cf996f03SMatti Vaittinen 	if (len != exp_len)
397cf996f03SMatti Vaittinen 		return;
398cf996f03SMatti Vaittinen 
399cf996f03SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(gains); i++) {
400cf996f03SMatti Vaittinen 		ret = iio_gts_total_gain_to_scale(gts, gains[i],
401cf996f03SMatti Vaittinen 						  &expected[2 * i],
402cf996f03SMatti Vaittinen 						  &expected[2 * i + 1]);
403cf996f03SMatti Vaittinen 		KUNIT_EXPECT_EQ(test, 0, ret);
404cf996f03SMatti Vaittinen 		if (ret)
405cf996f03SMatti Vaittinen 			return;
406cf996f03SMatti Vaittinen 	}
407cf996f03SMatti Vaittinen 
408cf996f03SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(expected); i++)
409cf996f03SMatti Vaittinen 		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
410cf996f03SMatti Vaittinen }
411cf996f03SMatti Vaittinen 
test_iio_gts_chk_scales_t200(struct kunit * test,struct iio_gts * gts,const int * vals,int len)412cf996f03SMatti Vaittinen static void test_iio_gts_chk_scales_t200(struct kunit *test, struct iio_gts *gts,
413cf996f03SMatti Vaittinen 					 const int *vals, int len)
414cf996f03SMatti Vaittinen {
415cf996f03SMatti Vaittinen 	/* The gain caused by time 200 is 4x */
416cf996f03SMatti Vaittinen 	static const int gains[] = {
417cf996f03SMatti Vaittinen 		1 * 4,
418cf996f03SMatti Vaittinen 		4 * 4,
419cf996f03SMatti Vaittinen 		16 * 4,
420cf996f03SMatti Vaittinen 		32 * 4,
421cf996f03SMatti Vaittinen 		64 * 4,
422cf996f03SMatti Vaittinen 		256 * 4,
423cf996f03SMatti Vaittinen 		512 * 4,
424cf996f03SMatti Vaittinen 		1024 * 4,
425cf996f03SMatti Vaittinen 		2048 * 4,
426cf996f03SMatti Vaittinen 		4096 * 4
427cf996f03SMatti Vaittinen 	};
428cf996f03SMatti Vaittinen 	int expected[ARRAY_SIZE(gains) * 2];
429cf996f03SMatti Vaittinen 	int i, ret;
430cf996f03SMatti Vaittinen 
431cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 2 * ARRAY_SIZE(gains), len);
432cf996f03SMatti Vaittinen 	if (len < 2 * ARRAY_SIZE(gains))
433cf996f03SMatti Vaittinen 		return;
434cf996f03SMatti Vaittinen 
435cf996f03SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(gains); i++) {
436cf996f03SMatti Vaittinen 		ret = iio_gts_total_gain_to_scale(gts, gains[i],
437cf996f03SMatti Vaittinen 						  &expected[2 * i],
438cf996f03SMatti Vaittinen 						  &expected[2 * i + 1]);
439cf996f03SMatti Vaittinen 		KUNIT_EXPECT_EQ(test, 0, ret);
440cf996f03SMatti Vaittinen 		if (ret)
441cf996f03SMatti Vaittinen 			return;
442cf996f03SMatti Vaittinen 	}
443cf996f03SMatti Vaittinen 
444cf996f03SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(expected); i++)
445cf996f03SMatti Vaittinen 		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
446cf996f03SMatti Vaittinen }
447cf996f03SMatti Vaittinen 
test_iio_gts_avail_test(struct kunit * test)448cf996f03SMatti Vaittinen static void test_iio_gts_avail_test(struct kunit *test)
449cf996f03SMatti Vaittinen {
450cf996f03SMatti Vaittinen 	struct device *dev;
451cf996f03SMatti Vaittinen 	int ret;
452cf996f03SMatti Vaittinen 	int type, len;
453cf996f03SMatti Vaittinen 	const int *vals;
454cf996f03SMatti Vaittinen 
455cf996f03SMatti Vaittinen 	dev = test_init_iio_gain_scale(test, &gts);
456cf996f03SMatti Vaittinen 	if (!dev)
457cf996f03SMatti Vaittinen 		return;
458cf996f03SMatti Vaittinen 
459cf996f03SMatti Vaittinen 	/* test table building for times and iio_gts_avail_times() */
460cf996f03SMatti Vaittinen 	ret = iio_gts_avail_times(&gts, &vals, &type, &len);
461cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
462cf996f03SMatti Vaittinen 	if (ret)
463cf996f03SMatti Vaittinen 		return;
464cf996f03SMatti Vaittinen 
465cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_MICRO, type);
466cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, 8, len);
467cf996f03SMatti Vaittinen 	if (len < 8)
468cf996f03SMatti Vaittinen 		return;
469cf996f03SMatti Vaittinen 
470cf996f03SMatti Vaittinen 	test_iio_gts_chk_times(test, vals);
471cf996f03SMatti Vaittinen 
472cf996f03SMatti Vaittinen 	/* Test table building for all scales and iio_gts_all_avail_scales() */
473cf996f03SMatti Vaittinen 	ret = iio_gts_all_avail_scales(&gts, &vals, &type, &len);
474cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
475cf996f03SMatti Vaittinen 	if (ret)
476cf996f03SMatti Vaittinen 		return;
477cf996f03SMatti Vaittinen 
478cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);
479cf996f03SMatti Vaittinen 
480cf996f03SMatti Vaittinen 	test_iio_gts_chk_scales_all(test, &gts, vals, len);
481cf996f03SMatti Vaittinen 
482cf996f03SMatti Vaittinen 	/*
483cf996f03SMatti Vaittinen 	 * Test table building for scales/time and
484cf996f03SMatti Vaittinen 	 * iio_gts_avail_scales_for_time()
485cf996f03SMatti Vaittinen 	 */
486cf996f03SMatti Vaittinen 	ret = iio_gts_avail_scales_for_time(&gts, 200000, &vals, &type, &len);
487cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
488cf996f03SMatti Vaittinen 	if (ret)
489cf996f03SMatti Vaittinen 		return;
490cf996f03SMatti Vaittinen 
491cf996f03SMatti Vaittinen 	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);
492cf996f03SMatti Vaittinen 	test_iio_gts_chk_scales_t200(test, &gts, vals, len);
493cf996f03SMatti Vaittinen }
494cf996f03SMatti Vaittinen 
495cf996f03SMatti Vaittinen static struct kunit_case iio_gts_test_cases[] = {
496cf996f03SMatti Vaittinen 	KUNIT_CASE(test_init_iio_gts_invalid),
497cf996f03SMatti Vaittinen 	KUNIT_CASE(test_iio_gts_find_gain_for_scale_using_time),
498cf996f03SMatti Vaittinen 	KUNIT_CASE(test_iio_gts_find_new_gain_sel_by_old_gain_time),
499cf996f03SMatti Vaittinen 	KUNIT_CASE(test_iio_find_closest_gain_low),
500cf996f03SMatti Vaittinen 	KUNIT_CASE(test_iio_gts_total_gain_to_scale),
501cf996f03SMatti Vaittinen 	KUNIT_CASE(test_iio_gts_avail_test),
502cf996f03SMatti Vaittinen 	{}
503cf996f03SMatti Vaittinen };
504cf996f03SMatti Vaittinen 
505cf996f03SMatti Vaittinen static struct kunit_suite iio_gts_test_suite = {
506cf996f03SMatti Vaittinen 	.name = "iio-gain-time-scale",
507cf996f03SMatti Vaittinen 	.test_cases = iio_gts_test_cases,
508cf996f03SMatti Vaittinen };
509cf996f03SMatti Vaittinen 
510cf996f03SMatti Vaittinen kunit_test_suite(iio_gts_test_suite);
511cf996f03SMatti Vaittinen 
512cf996f03SMatti Vaittinen MODULE_LICENSE("GPL");
513cf996f03SMatti Vaittinen MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
514cf996f03SMatti Vaittinen MODULE_DESCRIPTION("Test IIO light sensor gain-time-scale helpers");
515cf996f03SMatti Vaittinen MODULE_IMPORT_NS(IIO_GTS_HELPER);
516