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