[PATCH v3 2/2] iio: proximity: hx9023s: Add performance tuning function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When hardware design introduces significant sensor data noise,
performance can be improved by adjusting register settings.

Signed-off-by: Yasin Lee <yasin.lee.x@xxxxxxxxx>
---
 drivers/iio/proximity/hx9023s.c | 234 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 234 insertions(+)

diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c
index 8b9f84400e00..5d0338588616 100644
--- a/drivers/iio/proximity/hx9023s.c
+++ b/drivers/iio/proximity/hx9023s.c
@@ -61,6 +61,7 @@
 #define HX9023S_OFFSET_DAC4_9_8                0x1E
 #define HX9023S_SAMPLE_NUM_7_0                 0x1F
 #define HX9023S_INTEGRATION_NUM_7_0            0x21
+#define HX9023S_GLOBAL_CTRL2                   0x23
 #define HX9023S_CH_NUM_CFG                     0x24
 #define HX9023S_LP_ALP_4_CFG                   0x29
 #define HX9023S_LP_ALP_1_0_CFG                 0x2A
@@ -623,6 +624,235 @@ static int hx9023s_property_get(struct hx9023s_data *data)
 	return 0;
 }
 
+static int hx9023s_performance_tuning(struct hx9023s_data *data)
+{
+	struct device *dev = regmap_get_device(data->regmap);
+	int ret;
+	bool dither;
+	bool chop;
+	u32 odr;
+	u32 range[HX9023S_CH_NUM];
+	u32 avg[HX9023S_CH_NUM];
+	u32 osr[HX9023S_CH_NUM];
+	u32 sample_time;
+	u32 integration_time;
+	u32 lp_alpha[HX9023S_CH_NUM];
+	u32 bl_up_alpha[HX9023S_CH_NUM];
+	u32 bl_down_alpha[HX9023S_CH_NUM];
+	u32 drdy_interrput;
+	u32 int_high_num;
+	u32 int_low_num;
+	u32 temp;
+
+	/* dither */
+	dither = device_property_read_bool(dev, "tyhx,dither");
+	if (dither)
+		ret = regmap_update_bits(data->regmap, HX9023S_GLOBAL_CTRL0, BIT(6), BIT(6));
+	else
+		ret = regmap_update_bits(data->regmap, HX9023S_GLOBAL_CTRL0, BIT(6), 0);
+
+	/* chop */
+	chop = device_property_read_bool(dev, "tyhx,chop");
+	if (chop)
+		ret = regmap_update_bits(data->regmap, HX9023S_GLOBAL_CTRL2, GENMASK(4, 0),
+					GENMASK(4, 0));
+	else
+		ret = regmap_update_bits(data->regmap, HX9023S_GLOBAL_CTRL2, GENMASK(4, 0), 0);
+
+	/* odr */
+	ret = device_property_read_u32(dev, "tyhx,odr", &odr);
+	if (!ret) {
+		ret = regmap_update_bits(data->regmap, HX9023S_PRF_CFG, GENMASK(4, 0),
+					FIELD_PREP(GENMASK(4, 0), odr));
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update odr\n");
+	}
+
+	/* range */
+	ret = device_property_read_u32_array(dev, "tyhx,range", range, ARRAY_SIZE(range));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(2, 0), range[0]) | FIELD_PREP(GENMASK(6, 4), range[1]);
+		ret = regmap_update_bits(data->regmap, HX9023S_RANGE_7_0, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update range for ch0 and ch1\n");
+
+		temp = FIELD_PREP(GENMASK(2, 0), range[2]) | FIELD_PREP(GENMASK(6, 4), range[3]);
+		ret = regmap_update_bits(data->regmap, HX9023S_RANGE_9_8, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update range for ch2 and ch3\n");
+
+		temp = FIELD_PREP(GENMASK(2, 0), range[4]);
+		ret = regmap_update_bits(data->regmap, HX9023S_RANGE_18_16, GENMASK(2, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update range for ch4\n");
+	}
+
+	/* avg */
+	ret = device_property_read_u32_array(dev, "tyhx,avg", avg, ARRAY_SIZE(avg));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(7, 5), avg[0]);
+		ret = regmap_update_bits(data->regmap, HX9023S_AVG0_NOSR0_CFG, GENMASK(7, 5),
+					temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update avg for ch0\n");
+
+		temp = FIELD_PREP(GENMASK(6, 4), avg[2]) | FIELD_PREP(GENMASK(2, 0), avg[1]);
+		ret = regmap_update_bits(data->regmap, HX9023S_AVG12_CFG, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update avg for ch1 and ch2\n");
+
+		temp = FIELD_PREP(GENMASK(6, 4), avg[4]) | FIELD_PREP(GENMASK(2, 0), avg[3]);
+		ret = regmap_update_bits(data->regmap, HX9023S_AVG34_CFG, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update avg for ch3 and ch4\n");
+	}
+
+	/* osr */
+	ret = device_property_read_u32_array(dev, "tyhx,osr", osr, ARRAY_SIZE(osr));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(4, 2), osr[0]);
+		ret = regmap_update_bits(data->regmap, HX9023S_AVG0_NOSR0_CFG, GENMASK(4, 2),
+					temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update osr for ch0\n");
+
+		temp = FIELD_PREP(GENMASK(6, 4), osr[2]) | FIELD_PREP(GENMASK(2, 0), osr[1]);
+		ret = regmap_update_bits(data->regmap, HX9023S_NOSR12_CFG, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update osr for ch1 and ch2\n");
+
+		temp = FIELD_PREP(GENMASK(6, 4), osr[4]) | FIELD_PREP(GENMASK(2, 0), osr[3]);
+		ret = regmap_update_bits(data->regmap, HX9023S_NOSR34_CFG, GENMASK(6, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update osr for ch3 and ch4\n");
+	}
+
+	/* sample time */
+	ret = device_property_read_u32(dev, "tyhx,sample-time", &sample_time);
+	if (!ret) {
+		ret = regmap_write(data->regmap, HX9023S_SAMPLE_NUM_7_0, sample_time);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update sample_time\n");
+	}
+
+	/* integration time */
+	ret = device_property_read_u32(dev, "tyhx,integration-time", &integration_time);
+	if (!ret) {
+		ret = regmap_write(data->regmap, HX9023S_INTEGRATION_NUM_7_0, integration_time);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update integration_time\n");
+	}
+
+	/* lp-alpha */
+	ret = device_property_read_u32_array(dev, "tyhx,lp-alpha", lp_alpha, ARRAY_SIZE(lp_alpha));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(6, 4), lp_alpha[1])
+			| FIELD_PREP(GENMASK(2, 0), lp_alpha[0]);
+		ret = regmap_write(data->regmap, HX9023S_LP_ALP_1_0_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update lp-alpha for ch0 and ch1\n");
+
+		temp = FIELD_PREP(GENMASK(6, 4), lp_alpha[3])
+			| FIELD_PREP(GENMASK(2, 0), lp_alpha[2]);
+		ret = regmap_write(data->regmap, HX9023S_LP_ALP_3_2_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update lp-alpha for ch2 and ch3\n");
+
+		temp = FIELD_PREP(GENMASK(2, 0), lp_alpha[4]);
+		ret = regmap_update_bits(data->regmap, HX9023S_LP_ALP_4_CFG, GENMASK(2, 0), temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update lp-alpha for ch4\n");
+	}
+
+	/* bl-up-alpha */
+	ret = device_property_read_u32_array(dev, "tyhx,bl-up-alpha",
+					bl_up_alpha, ARRAY_SIZE(bl_up_alpha));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(7, 4), bl_up_alpha[1])
+			| FIELD_PREP(GENMASK(3, 0), bl_up_alpha[0]);
+		ret = regmap_write(data->regmap, HX9023S_UP_ALP_1_0_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update bl-up-alpha for ch0 and ch1\n");
+
+		temp = FIELD_PREP(GENMASK(7, 4), bl_up_alpha[3])
+			| FIELD_PREP(GENMASK(3, 0), bl_up_alpha[2]);
+		ret = regmap_write(data->regmap, HX9023S_UP_ALP_3_2_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update bl-up-alpha for ch2 and ch3\n");
+
+		temp = FIELD_PREP(GENMASK(3, 0), bl_up_alpha[4]);
+		ret = regmap_update_bits(data->regmap, HX9023S_DN_UP_ALP_0_4_CFG, GENMASK(3, 0),
+					temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update bl-up-alpha for ch4\n");
+	}
+
+	/* bl-down-alpha */
+	ret = device_property_read_u32_array(dev, "tyhx,bl-down-alpha",
+					bl_down_alpha, ARRAY_SIZE(bl_down_alpha));
+	if (!ret) {
+		temp = FIELD_PREP(GENMASK(7, 4), bl_down_alpha[0]);
+		ret = regmap_update_bits(data->regmap, HX9023S_DN_UP_ALP_0_4_CFG, GENMASK(7, 4),
+					temp);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update bl-dn-alpha for ch0\n");
+
+		temp = FIELD_PREP(GENMASK(7, 4), bl_down_alpha[2])
+			| FIELD_PREP(GENMASK(3, 0), bl_down_alpha[1]);
+		ret = regmap_write(data->regmap, HX9023S_DN_ALP_2_1_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update bl-dn-alpha for ch1 and ch2\n");
+
+		temp = FIELD_PREP(GENMASK(7, 4), bl_down_alpha[4])
+			| FIELD_PREP(GENMASK(3, 0), bl_down_alpha[3]);
+		ret = regmap_write(data->regmap, HX9023S_DN_ALP_4_3_CFG, temp);
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update bl-dn-alpha for ch3 and ch4\n");
+	}
+
+	/* dydy-interrupt */
+	ret = device_property_read_u32(dev, "tyhx,drdy-interrupt", &drdy_interrput);
+	if (!ret) {
+		ret = regmap_update_bits(data->regmap, HX9023S_CALI_DIFF_CFG, GENMASK(7, 4),
+					FIELD_PREP(GENMASK(7, 4), drdy_interrput));
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update drdy-interrput for ch0~ch3\n");
+
+		ret = regmap_update_bits(data->regmap, HX9023S_DITHER_CFG, BIT(7),
+					FIELD_PREP(BIT(7), drdy_interrput >> 4));
+		if (ret)
+			return dev_err_probe(dev, ret,
+						"Failed to update drdy-interrput for ch4\n");
+	}
+
+	/* int-high-num */
+	ret = device_property_read_u32(dev, "tyhx,int-high-num", &int_high_num);
+	if (!ret) {
+		ret = regmap_update_bits(data->regmap, HX9023S_PROX_INT_HIGH_CFG, GENMASK(3, 0),
+					FIELD_PREP(GENMASK(3, 0), int_high_num));
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update int-high-num\n");
+	}
+
+	/* int-low-num */
+	ret = device_property_read_u32(dev, "tyhx,int-low-num", &int_low_num);
+	if (!ret) {
+		ret = regmap_update_bits(data->regmap, HX9023S_PROX_INT_LOW_CFG, GENMASK(3, 0),
+					FIELD_PREP(GENMASK(3, 0), int_low_num));
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to update int-low-num\n");
+	}
+
+	return 0;
+}
+
 static int hx9023s_update_chan_en(struct hx9023s_data *data,
 				  unsigned long chan_read,
 				  unsigned long chan_event)
@@ -1045,6 +1275,10 @@ static int hx9023s_probe(struct i2c_client *client)
 	if (ret)
 		return dev_err_probe(dev, ret, "channel config failed\n");
 
+	ret = hx9023s_performance_tuning(data);
+	if (ret)
+		return dev_err_probe(dev, ret, "performance tuning failed\n");
+
 	ret = regcache_sync(data->regmap);
 	if (ret)
 		return dev_err_probe(dev, ret, "regcache sync failed\n");

-- 
2.43.0





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux