1*80503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20eadaa9cSLars-Peter Clausen /*
30eadaa9cSLars-Peter Clausen * Shared helper functions for devices from the ADAU family
40eadaa9cSLars-Peter Clausen *
50eadaa9cSLars-Peter Clausen * Copyright 2011-2016 Analog Devices Inc.
60eadaa9cSLars-Peter Clausen * Author: Lars-Peter Clausen <lars@metafoo.de>
70eadaa9cSLars-Peter Clausen */
80eadaa9cSLars-Peter Clausen
90eadaa9cSLars-Peter Clausen #include <linux/gcd.h>
100eadaa9cSLars-Peter Clausen #include <linux/kernel.h>
110eadaa9cSLars-Peter Clausen #include <linux/module.h>
120eadaa9cSLars-Peter Clausen
130eadaa9cSLars-Peter Clausen #include "adau-utils.h"
140eadaa9cSLars-Peter Clausen
adau_calc_pll_cfg(unsigned int freq_in,unsigned int freq_out,uint8_t regs[5])150eadaa9cSLars-Peter Clausen int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out,
160eadaa9cSLars-Peter Clausen uint8_t regs[5])
170eadaa9cSLars-Peter Clausen {
180eadaa9cSLars-Peter Clausen unsigned int r, n, m, i, j;
190eadaa9cSLars-Peter Clausen unsigned int div;
200eadaa9cSLars-Peter Clausen
210eadaa9cSLars-Peter Clausen if (!freq_out) {
220eadaa9cSLars-Peter Clausen r = 0;
230eadaa9cSLars-Peter Clausen n = 0;
240eadaa9cSLars-Peter Clausen m = 0;
250eadaa9cSLars-Peter Clausen div = 0;
260eadaa9cSLars-Peter Clausen } else {
270eadaa9cSLars-Peter Clausen if (freq_out % freq_in != 0) {
280eadaa9cSLars-Peter Clausen div = DIV_ROUND_UP(freq_in, 13500000);
290eadaa9cSLars-Peter Clausen freq_in /= div;
300eadaa9cSLars-Peter Clausen r = freq_out / freq_in;
310eadaa9cSLars-Peter Clausen i = freq_out % freq_in;
320eadaa9cSLars-Peter Clausen j = gcd(i, freq_in);
330eadaa9cSLars-Peter Clausen n = i / j;
340eadaa9cSLars-Peter Clausen m = freq_in / j;
350eadaa9cSLars-Peter Clausen div--;
360eadaa9cSLars-Peter Clausen } else {
370eadaa9cSLars-Peter Clausen r = freq_out / freq_in;
380eadaa9cSLars-Peter Clausen n = 0;
390eadaa9cSLars-Peter Clausen m = 0;
400eadaa9cSLars-Peter Clausen div = 0;
410eadaa9cSLars-Peter Clausen }
420eadaa9cSLars-Peter Clausen if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
430eadaa9cSLars-Peter Clausen return -EINVAL;
440eadaa9cSLars-Peter Clausen }
450eadaa9cSLars-Peter Clausen
460eadaa9cSLars-Peter Clausen regs[0] = m >> 8;
470eadaa9cSLars-Peter Clausen regs[1] = m & 0xff;
480eadaa9cSLars-Peter Clausen regs[2] = n >> 8;
490eadaa9cSLars-Peter Clausen regs[3] = n & 0xff;
500eadaa9cSLars-Peter Clausen regs[4] = (r << 3) | (div << 1);
510eadaa9cSLars-Peter Clausen if (m != 0)
520eadaa9cSLars-Peter Clausen regs[4] |= 1; /* Fractional mode */
530eadaa9cSLars-Peter Clausen
540eadaa9cSLars-Peter Clausen return 0;
550eadaa9cSLars-Peter Clausen }
560eadaa9cSLars-Peter Clausen EXPORT_SYMBOL_GPL(adau_calc_pll_cfg);
570eadaa9cSLars-Peter Clausen
580eadaa9cSLars-Peter Clausen MODULE_DESCRIPTION("ASoC ADAU audio CODECs shared helper functions");
590eadaa9cSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
600eadaa9cSLars-Peter Clausen MODULE_LICENSE("GPL v2");
61