Lines Matching +full:calibration +full:- +full:data
1 // SPDX-License-Identifier: GPL-2.0-only
7 * YAS530 MS-3E (2011 Samsung Galaxy S Advance)
8 * YAS532 MS-3R (2011 Samsung Galaxy S4)
9 * YAS533 MS-3F (Vivo 1633, 1707, V3, Y21L)
11 * YAS535 MS-6C
12 * YAS536 MS-3W
13 * YAS537 MS-3T (2015 Samsung Galaxy S6, Note 5, Xiaomi)
14 * YAS539 MS-3S (2018 Samsung Galaxy A7 SM-A750FN)
49 #define YAS5XX_OFFSET_X 0x85 /* [-31 .. 31] */
50 #define YAS5XX_OFFSET_Y1 0x86 /* [-31 .. 31] */
51 #define YAS5XX_OFFSET_Y2 0x87 /* [-31 .. 31] */
69 /* Bits in the measure data register */
72 #define YAS530_DEVICE_ID 0x01 /* YAS530 (MS-3E) */
73 #define YAS530_VERSION_A 0 /* YAS530 (MS-3E A) */
74 #define YAS530_VERSION_B 1 /* YAS530B (MS-3E B) */
78 #define YAS530_DATA_CENTER BIT(YAS530_DATA_BITS - 1)
79 #define YAS530_DATA_OVERFLOW (BIT(YAS530_DATA_BITS) - 1)
81 #define YAS532_DEVICE_ID 0x02 /* YAS532/YAS533 (MS-3R/F) */
82 #define YAS532_VERSION_AB 0 /* YAS532/533 AB (MS-3R/F AB) */
83 #define YAS532_VERSION_AC 1 /* YAS532/533 AC (MS-3R/F AC) */
89 #define YAS532_DATA_CENTER BIT(YAS532_DATA_BITS - 1)
90 #define YAS532_DATA_OVERFLOW (BIT(YAS532_DATA_BITS) - 1)
94 #define YAS537_DEVICE_ID 0x07 /* YAS537 (MS-3T) */
95 #define YAS539_DEVICE_ID 0x08 /* YAS539 (MS-3S) */
101 /* Linearization calibration x, y1, y2 */
104 /* Temperature compensation calibration */
106 /* Misc calibration coefficients */
113 * struct yas5xx - state container for the YAS5xx driver
118 * @calibration: calibration settings from the OTP storage
126 * so that measurements get serialized in a first-come-first serve manner
134 struct yas5xx_calibration calibration; member
152 static u16 yas530_extract_axis(u8 *data) in yas530_extract_axis() argument
161 val = get_unaligned_be16(&data[0]); in yas530_extract_axis()
167 static u16 yas532_extract_axis(u8 *data) in yas532_extract_axis() argument
176 val = get_unaligned_be16(&data[0]); in yas532_extract_axis()
182 * yas5xx_measure() - Make a measure from the hardware
193 u8 data[8]; in yas5xx_measure() local
197 mutex_lock(&yas5xx->lock); in yas5xx_measure()
198 ret = regmap_write(yas5xx->map, YAS5XX_MEASURE, YAS5XX_MEASURE_START); in yas5xx_measure()
207 ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA, busy, in yas5xx_measure()
211 dev_err(yas5xx->dev, "timeout waiting for measurement\n"); in yas5xx_measure()
215 ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA, in yas5xx_measure()
216 data, sizeof(data)); in yas5xx_measure()
220 mutex_unlock(&yas5xx->lock); in yas5xx_measure()
222 switch (yas5xx->devid) { in yas5xx_measure()
230 val = get_unaligned_be16(&data[0]); in yas5xx_measure()
233 *x = yas530_extract_axis(&data[2]); in yas5xx_measure()
234 *y1 = yas530_extract_axis(&data[4]); in yas5xx_measure()
235 *y2 = yas530_extract_axis(&data[6]); in yas5xx_measure()
244 val = get_unaligned_be16(&data[0]); in yas5xx_measure()
247 *x = yas532_extract_axis(&data[2]); in yas5xx_measure()
248 *y1 = yas532_extract_axis(&data[4]); in yas5xx_measure()
249 *y2 = yas532_extract_axis(&data[6]); in yas5xx_measure()
252 dev_err(yas5xx->dev, "unknown data format\n"); in yas5xx_measure()
253 ret = -EINVAL; in yas5xx_measure()
260 mutex_unlock(&yas5xx->lock); in yas5xx_measure()
266 struct yas5xx_calibration *c = &yas5xx->calibration; in yas5xx_linearize()
275 switch (yas5xx->devid) { in yas5xx_linearize()
277 if (yas5xx->version == YAS530_VERSION_A) in yas5xx_linearize()
283 if (yas5xx->version == YAS532_VERSION_AB) in yas5xx_linearize()
290 dev_err(yas5xx->dev, "unknown device type\n"); in yas5xx_linearize()
296 * x' = x - (3721 + 50 * f) + (xoffset - r) * c in yas5xx_linearize()
298 * Where f and r are calibration values, c is a per-device in yas5xx_linearize()
299 * and sometimes per-axis coefficient. in yas5xx_linearize()
301 return val - (3721 + 50 * c->f[axis]) + in yas5xx_linearize()
302 (yas5xx->hard_offsets[axis] - c->r[axis]) * coef; in yas5xx_linearize()
306 * yas5xx_get_measure() - Measure a sample of all axis and process
318 struct yas5xx_calibration *c = &yas5xx->calibration; in yas5xx_get_measure()
324 /* We first get raw data that needs to be translated to [x,y,z] */ in yas5xx_get_measure()
338 * x' = x - ------ in yas5xx_get_measure()
341 sx = sx - (c->Cx * t) / 100; in yas5xx_get_measure()
342 sy1 = sy1 - (c->Cy1 * t) / 100; in yas5xx_get_measure()
343 sy2 = sy2 - (c->Cy2 * t) / 100; in yas5xx_get_measure()
349 sy = sy1 - sy2; in yas5xx_get_measure()
350 sz = -sy1 - sy2; in yas5xx_get_measure()
361 * x' = k * --------------------------- in yas5xx_get_measure()
365 * y' = k * --------------------------- in yas5xx_get_measure()
369 * z' = k * --------------------------- in yas5xx_get_measure()
372 *xo = c->k * ((100 * sx + c->a2 * sy + c->a3 * sz) / 10); in yas5xx_get_measure()
373 *yo = c->k * ((c->a4 * sx + c->a5 * sy + c->a6 * sz) / 10); in yas5xx_get_measure()
374 *zo = c->k * ((c->a7 * sx + c->a8 * sy + c->a9 * sz) / 10); in yas5xx_get_measure()
390 pm_runtime_get_sync(yas5xx->dev); in yas5xx_read_raw()
392 pm_runtime_mark_last_busy(yas5xx->dev); in yas5xx_read_raw()
393 pm_runtime_put_autosuspend(yas5xx->dev); in yas5xx_read_raw()
396 switch (chan->address) { in yas5xx_read_raw()
410 dev_err(yas5xx->dev, "unknown channel\n"); in yas5xx_read_raw()
411 return -EINVAL; in yas5xx_read_raw()
415 if (chan->address == 0) { in yas5xx_read_raw()
431 return -EINVAL; in yas5xx_read_raw()
441 pm_runtime_get_sync(yas5xx->dev); in yas5xx_fill_buffer()
443 pm_runtime_mark_last_busy(yas5xx->dev); in yas5xx_fill_buffer()
444 pm_runtime_put_autosuspend(yas5xx->dev); in yas5xx_fill_buffer()
446 dev_err(yas5xx->dev, "error refilling buffer\n"); in yas5xx_fill_buffer()
449 yas5xx->scan.channels[0] = t; in yas5xx_fill_buffer()
450 yas5xx->scan.channels[1] = x; in yas5xx_fill_buffer()
451 yas5xx->scan.channels[2] = y; in yas5xx_fill_buffer()
452 yas5xx->scan.channels[3] = z; in yas5xx_fill_buffer()
453 iio_push_to_buffers_with_timestamp(indio_dev, &yas5xx->scan, in yas5xx_fill_buffer()
460 struct iio_dev *indio_dev = pf->indio_dev; in yas5xx_handle_trigger()
463 iio_trigger_notify_done(indio_dev->trig); in yas5xx_handle_trigger()
475 return &yas5xx->orientation; in yas5xx_get_mount_matrix()
542 * yas53x_extract_calibration() - extracts the a2-a9 and k calibration
543 * @data: the bitfield to use
544 * @c: the calibration to populate
546 static void yas53x_extract_calibration(u8 *data, struct yas5xx_calibration *c) in yas53x_extract_calibration() argument
548 u64 val = get_unaligned_be64(data); in yas53x_extract_calibration()
551 * Bitfield layout for the axis calibration data, for factor in yas53x_extract_calibration()
564 c->a2 = FIELD_GET(GENMASK_ULL(63, 58), val) - 32; in yas53x_extract_calibration()
565 c->a3 = FIELD_GET(GENMASK_ULL(57, 54), val) - 8; in yas53x_extract_calibration()
566 c->a4 = FIELD_GET(GENMASK_ULL(53, 48), val) - 32; in yas53x_extract_calibration()
567 c->a5 = FIELD_GET(GENMASK_ULL(47, 42), val) + 38; in yas53x_extract_calibration()
568 c->a6 = FIELD_GET(GENMASK_ULL(41, 36), val) - 32; in yas53x_extract_calibration()
569 c->a7 = FIELD_GET(GENMASK_ULL(35, 29), val) - 64; in yas53x_extract_calibration()
570 c->a8 = FIELD_GET(GENMASK_ULL(28, 23), val) - 32; in yas53x_extract_calibration()
571 c->a9 = FIELD_GET(GENMASK_ULL(22, 15), val); in yas53x_extract_calibration()
572 c->k = FIELD_GET(GENMASK_ULL(14, 10), val) + 10; in yas53x_extract_calibration()
573 c->dck = FIELD_GET(GENMASK_ULL(9, 7), val); in yas53x_extract_calibration()
578 struct yas5xx_calibration *c = &yas5xx->calibration; in yas530_get_calibration_data()
579 u8 data[16]; in yas530_get_calibration_data() local
584 ret = regmap_bulk_read(yas5xx->map, YAS5XX_CAL, data, sizeof(data)); in yas530_get_calibration_data()
588 /* Actual calibration readout */ in yas530_get_calibration_data()
589 ret = regmap_bulk_read(yas5xx->map, YAS5XX_CAL, data, sizeof(data)); in yas530_get_calibration_data()
592 dev_dbg(yas5xx->dev, "calibration data: %*ph\n", 14, data); in yas530_get_calibration_data()
594 add_device_randomness(data, sizeof(data)); in yas530_get_calibration_data()
595 yas5xx->version = data[15] & GENMASK(1, 0); in yas530_get_calibration_data()
597 /* Extract the calibration from the bitfield */ in yas530_get_calibration_data()
598 c->Cx = data[0] * 6 - 768; in yas530_get_calibration_data()
599 c->Cy1 = data[1] * 6 - 768; in yas530_get_calibration_data()
600 c->Cy2 = data[2] * 6 - 768; in yas530_get_calibration_data()
601 yas53x_extract_calibration(&data[3], c); in yas530_get_calibration_data()
614 val = get_unaligned_be32(&data[11]); in yas530_get_calibration_data()
615 c->f[0] = FIELD_GET(GENMASK(22, 21), val); in yas530_get_calibration_data()
616 c->f[1] = FIELD_GET(GENMASK(14, 13), val); in yas530_get_calibration_data()
617 c->f[2] = FIELD_GET(GENMASK(6, 5), val); in yas530_get_calibration_data()
618 c->r[0] = sign_extend32(FIELD_GET(GENMASK(28, 23), val), 5); in yas530_get_calibration_data()
619 c->r[1] = sign_extend32(FIELD_GET(GENMASK(20, 15), val), 5); in yas530_get_calibration_data()
620 c->r[2] = sign_extend32(FIELD_GET(GENMASK(12, 7), val), 5); in yas530_get_calibration_data()
626 struct yas5xx_calibration *c = &yas5xx->calibration; in yas532_get_calibration_data()
627 u8 data[14]; in yas532_get_calibration_data() local
632 ret = regmap_bulk_read(yas5xx->map, YAS5XX_CAL, data, sizeof(data)); in yas532_get_calibration_data()
635 /* Actual calibration readout */ in yas532_get_calibration_data()
636 ret = regmap_bulk_read(yas5xx->map, YAS5XX_CAL, data, sizeof(data)); in yas532_get_calibration_data()
639 dev_dbg(yas5xx->dev, "calibration data: %*ph\n", 14, data); in yas532_get_calibration_data()
642 if (memchr_inv(data, 0x00, 13)) { in yas532_get_calibration_data()
643 if (!(data[13] & BIT(7))) in yas532_get_calibration_data()
644 dev_warn(yas5xx->dev, "calibration is blank!\n"); in yas532_get_calibration_data()
647 add_device_randomness(data, sizeof(data)); in yas532_get_calibration_data()
649 yas5xx->version = data[13] & BIT(0); in yas532_get_calibration_data()
651 /* Extract calibration from the bitfield */ in yas532_get_calibration_data()
652 c->Cx = data[0] * 10 - 1280; in yas532_get_calibration_data()
653 c->Cy1 = data[1] * 10 - 1280; in yas532_get_calibration_data()
654 c->Cy2 = data[2] * 10 - 1280; in yas532_get_calibration_data()
655 yas53x_extract_calibration(&data[3], c); in yas532_get_calibration_data()
667 val = get_unaligned_be32(&data[10]); in yas532_get_calibration_data()
668 c->f[0] = FIELD_GET(GENMASK(24, 23), val); in yas532_get_calibration_data()
669 c->f[1] = FIELD_GET(GENMASK(16, 15), val); in yas532_get_calibration_data()
670 c->f[2] = FIELD_GET(GENMASK(8, 7), val); in yas532_get_calibration_data()
671 c->r[0] = sign_extend32(FIELD_GET(GENMASK(30, 25), val), 5); in yas532_get_calibration_data()
672 c->r[1] = sign_extend32(FIELD_GET(GENMASK(22, 17), val), 5); in yas532_get_calibration_data()
673 c->r[2] = sign_extend32(FIELD_GET(GENMASK(14, 7), val), 5); in yas532_get_calibration_data()
680 struct yas5xx_calibration *c = &yas5xx->calibration; in yas5xx_dump_calibration()
682 dev_dbg(yas5xx->dev, "f[] = [%d, %d, %d]\n", in yas5xx_dump_calibration()
683 c->f[0], c->f[1], c->f[2]); in yas5xx_dump_calibration()
684 dev_dbg(yas5xx->dev, "r[] = [%d, %d, %d]\n", in yas5xx_dump_calibration()
685 c->r[0], c->r[1], c->r[2]); in yas5xx_dump_calibration()
686 dev_dbg(yas5xx->dev, "Cx = %d\n", c->Cx); in yas5xx_dump_calibration()
687 dev_dbg(yas5xx->dev, "Cy1 = %d\n", c->Cy1); in yas5xx_dump_calibration()
688 dev_dbg(yas5xx->dev, "Cy2 = %d\n", c->Cy2); in yas5xx_dump_calibration()
689 dev_dbg(yas5xx->dev, "a2 = %d\n", c->a2); in yas5xx_dump_calibration()
690 dev_dbg(yas5xx->dev, "a3 = %d\n", c->a3); in yas5xx_dump_calibration()
691 dev_dbg(yas5xx->dev, "a4 = %d\n", c->a4); in yas5xx_dump_calibration()
692 dev_dbg(yas5xx->dev, "a5 = %d\n", c->a5); in yas5xx_dump_calibration()
693 dev_dbg(yas5xx->dev, "a6 = %d\n", c->a6); in yas5xx_dump_calibration()
694 dev_dbg(yas5xx->dev, "a7 = %d\n", c->a7); in yas5xx_dump_calibration()
695 dev_dbg(yas5xx->dev, "a8 = %d\n", c->a8); in yas5xx_dump_calibration()
696 dev_dbg(yas5xx->dev, "a9 = %d\n", c->a9); in yas5xx_dump_calibration()
697 dev_dbg(yas5xx->dev, "k = %d\n", c->k); in yas5xx_dump_calibration()
698 dev_dbg(yas5xx->dev, "dck = %d\n", c->dck); in yas5xx_dump_calibration()
705 ret = regmap_write(yas5xx->map, YAS5XX_OFFSET_X, ox); in yas5xx_set_offsets()
708 ret = regmap_write(yas5xx->map, YAS5XX_OFFSET_Y1, oy1); in yas5xx_set_offsets()
711 return regmap_write(yas5xx->map, YAS5XX_OFFSET_Y2, oy2); in yas5xx_set_offsets()
719 return old - BIT(bit); in yas5xx_adjust_offset()
732 ret = regmap_write(yas5xx->map, YAS5XX_ACTUATE_INIT_COIL, 0); in yas5xx_meaure_offsets()
737 switch (yas5xx->devid) { in yas5xx_meaure_offsets()
745 dev_err(yas5xx->dev, "unknown device type\n"); in yas5xx_meaure_offsets()
746 return -EINVAL; in yas5xx_meaure_offsets()
750 * We set offsets in the interval +-31 by iterating in yas5xx_meaure_offsets()
751 * +-16, +-8, +-4, +-2, +-1 adjusting the offsets each in yas5xx_meaure_offsets()
756 * as the values for [x, y1, y2]. The value is +/-31 in yas5xx_meaure_offsets()
765 for (i = 4; i >= 0; i--) { in yas5xx_meaure_offsets()
773 dev_dbg(yas5xx->dev, "measurement %d: x=%d, y1=%d, y2=%d\n", in yas5xx_meaure_offsets()
774 5-i, x, y1, y2); in yas5xx_meaure_offsets()
781 /* Needed for calibration algorithm */ in yas5xx_meaure_offsets()
782 yas5xx->hard_offsets[0] = ox; in yas5xx_meaure_offsets()
783 yas5xx->hard_offsets[1] = oy1; in yas5xx_meaure_offsets()
784 yas5xx->hard_offsets[2] = oy2; in yas5xx_meaure_offsets()
789 dev_info(yas5xx->dev, "discovered hard offsets: x=%d, y1=%d, y2=%d\n", in yas5xx_meaure_offsets()
800 ret = regmap_write(yas5xx->map, YAS5XX_TEST1, 0); in yas5xx_power_on()
803 ret = regmap_write(yas5xx->map, YAS5XX_TEST2, 0); in yas5xx_power_on()
808 val = FIELD_PREP(YAS5XX_CONFIG_CCK_MASK, yas5xx->calibration.dck); in yas5xx_power_on()
809 ret = regmap_write(yas5xx->map, YAS5XX_CONFIG, val); in yas5xx_power_on()
813 /* Measure interval 0 (back-to-back?) */ in yas5xx_power_on()
814 return regmap_write(yas5xx->map, YAS5XX_MEASURE_INTERVAL, 0); in yas5xx_power_on()
821 struct device *dev = &i2c->dev; in yas5xx_probe()
827 return -ENOMEM; in yas5xx_probe()
831 yas5xx->dev = dev; in yas5xx_probe()
832 mutex_init(&yas5xx->lock); in yas5xx_probe()
834 ret = iio_read_mount_matrix(dev, &yas5xx->orientation); in yas5xx_probe()
838 yas5xx->regs[0].supply = "vdd"; in yas5xx_probe()
839 yas5xx->regs[1].supply = "iovdd"; in yas5xx_probe()
840 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(yas5xx->regs), in yas5xx_probe()
841 yas5xx->regs); in yas5xx_probe()
845 ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_probe()
855 yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); in yas5xx_probe()
856 if (IS_ERR(yas5xx->reset)) { in yas5xx_probe()
857 ret = dev_err_probe(dev, PTR_ERR(yas5xx->reset), in yas5xx_probe()
862 yas5xx->map = devm_regmap_init_i2c(i2c, &yas5xx_regmap_config); in yas5xx_probe()
863 if (IS_ERR(yas5xx->map)) { in yas5xx_probe()
865 ret = PTR_ERR(yas5xx->map); in yas5xx_probe()
869 ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &yas5xx->devid); in yas5xx_probe()
873 switch (yas5xx->devid) { in yas5xx_probe()
878 dev_info(dev, "detected YAS530 MS-3E %s", in yas5xx_probe()
879 yas5xx->version ? "B" : "A"); in yas5xx_probe()
880 strncpy(yas5xx->name, "yas530", sizeof(yas5xx->name)); in yas5xx_probe()
886 dev_info(dev, "detected YAS532/YAS533 MS-3R/F %s", in yas5xx_probe()
887 yas5xx->version ? "AC" : "AB"); in yas5xx_probe()
888 strncpy(yas5xx->name, "yas532", sizeof(yas5xx->name)); in yas5xx_probe()
891 ret = -ENODEV; in yas5xx_probe()
892 dev_err(dev, "unhandled device ID %02x\n", yas5xx->devid); in yas5xx_probe()
904 indio_dev->info = &yas5xx_info; in yas5xx_probe()
905 indio_dev->available_scan_masks = yas5xx_scan_masks; in yas5xx_probe()
906 indio_dev->modes = INDIO_DIRECT_MODE; in yas5xx_probe()
907 indio_dev->name = yas5xx->name; in yas5xx_probe()
908 indio_dev->channels = yas5xx_channels; in yas5xx_probe()
909 indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels); in yas5xx_probe()
939 gpiod_set_value_cansleep(yas5xx->reset, 1); in yas5xx_probe()
941 regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_probe()
950 struct device *dev = &i2c->dev; in yas5xx_remove()
962 gpiod_set_value_cansleep(yas5xx->reset, 1); in yas5xx_remove()
963 regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_remove()
973 gpiod_set_value_cansleep(yas5xx->reset, 1); in yas5xx_runtime_suspend()
974 regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_runtime_suspend()
985 ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_runtime_resume()
997 gpiod_set_value_cansleep(yas5xx->reset, 0); in yas5xx_runtime_resume()
1008 gpiod_set_value_cansleep(yas5xx->reset, 1); in yas5xx_runtime_resume()
1009 regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); in yas5xx_runtime_resume()
1049 MODULE_DESCRIPTION("Yamaha YAS53x 3-axis magnetometer driver");