Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dpll/zl3073x/synth.c
38189 views
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
89