xref: /openbmc/linux/sound/soc/codecs/adau-utils.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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