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