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