88 lines
2.1 KiB
C
88 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
#include <linux/bitfield.h>
|
|
#include <linux/cleanup.h>
|
|
#include <linux/dev_printk.h>
|
|
#include <linux/string.h>
|
|
#include <linux/string_choices.h>
|
|
#include <linux/types.h>
|
|
|
|
#include "core.h"
|
|
#include "synth.h"
|
|
|
|
/**
|
|
* zl3073x_synth_state_fetch - fetch synth state from hardware
|
|
* @zldev: pointer to zl3073x_dev structure
|
|
* @index: synth index to fetch state for
|
|
*
|
|
* Function fetches state of the given synthesizer from the hardware and
|
|
* stores it for later use.
|
|
*
|
|
* Return: 0 on success, <0 on error
|
|
*/
|
|
int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index)
|
|
{
|
|
struct zl3073x_synth *synth = &zldev->synth[index];
|
|
int rc;
|
|
|
|
/* Read synth control register */
|
|
rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth->ctrl);
|
|
if (rc)
|
|
return rc;
|
|
|
|
guard(mutex)(&zldev->multiop_lock);
|
|
|
|
/* Read synth configuration */
|
|
rc = zl3073x_mb_op(zldev, ZL_REG_SYNTH_MB_SEM, ZL_SYNTH_MB_SEM_RD,
|
|
ZL_REG_SYNTH_MB_MASK, BIT(index));
|
|
if (rc)
|
|
return rc;
|
|
|
|
/* The output frequency is determined by the following formula:
|
|
* base * multiplier * numerator / denominator
|
|
*
|
|
* Read registers with these values
|
|
*/
|
|
rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &synth->freq_base);
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &synth->freq_mult);
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &synth->freq_m);
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &synth->freq_n);
|
|
if (rc)
|
|
return rc;
|
|
|
|
/* Check denominator for zero to avoid div by 0 */
|
|
if (!synth->freq_n) {
|
|
dev_err(zldev->dev,
|
|
"Zero divisor for SYNTH%u retrieved from device\n",
|
|
index);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev_dbg(zldev->dev, "SYNTH%u frequency: %u Hz\n", index,
|
|
zl3073x_synth_freq_get(synth));
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* zl3073x_synth_state_get - get current synth state
|
|
* @zldev: pointer to zl3073x_dev structure
|
|
* @index: synth index to get state for
|
|
*
|
|
* Return: pointer to given synth state
|
|
*/
|
|
const struct zl3073x_synth *zl3073x_synth_state_get(struct zl3073x_dev *zldev,
|
|
u8 index)
|
|
{
|
|
return &zldev->synth[index];
|
|
}
|