xref: /linux/drivers/dpll/zl3073x/synth.c (revision 84318277d6334c6981ab326d4acc87c6a6ddc9b8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/bitfield.h>
4 #include <linux/cleanup.h>
5 #include <linux/dev_printk.h>
6 #include <linux/string.h>
7 #include <linux/string_choices.h>
8 #include <linux/types.h>
9 
10 #include "core.h"
11 #include "synth.h"
12 
13 /**
14  * zl3073x_synth_state_fetch - fetch synth state from hardware
15  * @zldev: pointer to zl3073x_dev structure
16  * @index: synth index to fetch state for
17  *
18  * Function fetches state of the given synthesizer from the hardware and
19  * stores it for later use.
20  *
21  * Return: 0 on success, <0 on error
22  */
23 int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index)
24 {
25 	struct zl3073x_synth *synth = &zldev->synth[index];
26 	int rc;
27 
28 	/* Read synth control register */
29 	rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth->ctrl);
30 	if (rc)
31 		return rc;
32 
33 	guard(mutex)(&zldev->multiop_lock);
34 
35 	/* Read synth configuration */
36 	rc = zl3073x_mb_op(zldev, ZL_REG_SYNTH_MB_SEM, ZL_SYNTH_MB_SEM_RD,
37 			   ZL_REG_SYNTH_MB_MASK, BIT(index));
38 	if (rc)
39 		return rc;
40 
41 	/* The output frequency is determined by the following formula:
42 	 * base * multiplier * numerator / denominator
43 	 *
44 	 * Read registers with these values
45 	 */
46 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &synth->freq_base);
47 	if (rc)
48 		return rc;
49 
50 	rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &synth->freq_mult);
51 	if (rc)
52 		return rc;
53 
54 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &synth->freq_m);
55 	if (rc)
56 		return rc;
57 
58 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &synth->freq_n);
59 	if (rc)
60 		return rc;
61 
62 	/* Check denominator for zero to avoid div by 0 */
63 	if (!synth->freq_n) {
64 		dev_err(zldev->dev,
65 			"Zero divisor for SYNTH%u retrieved from device\n",
66 			index);
67 		return -EINVAL;
68 	}
69 
70 	dev_dbg(zldev->dev, "SYNTH%u frequency: %u Hz\n", index,
71 		zl3073x_synth_freq_get(synth));
72 
73 	return rc;
74 }
75 
76 /**
77  * zl3073x_synth_state_get - get current synth state
78  * @zldev: pointer to zl3073x_dev structure
79  * @index: synth index to get state for
80  *
81  * Return: pointer to given synth state
82  */
83 const struct zl3073x_synth *zl3073x_synth_state_get(struct zl3073x_dev *zldev,
84 						    u8 index)
85 {
86 	return &zldev->synth[index];
87 }
88