[go: nahoru, domu]

1bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil/* cx25840 audio functions
2bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil *
3bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * This program is free software; you can redistribute it and/or
4bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * modify it under the terms of the GNU General Public License
5bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * as published by the Free Software Foundation; either version 2
6bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * of the License, or (at your option) any later version.
7bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil *
8bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * This program is distributed in the hope that it will be useful,
9bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of
10bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * GNU General Public License for more details.
12bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil *
13bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * You should have received a copy of the GNU General Public License
14bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * along with this program; if not, write to the Free Software
15bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil */
17bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
18bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
19bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil#include <linux/videodev2.h>
20bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil#include <linux/i2c.h>
21bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil#include <media/v4l2-common.h>
2231bc09b579f31331545e694d0a49ec4e6b380989Hans Verkuil#include <media/cx25840.h>
23bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2431bc09b579f31331545e694d0a49ec4e6b380989Hans Verkuil#include "cx25840-core.h"
25bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
269eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls/*
279eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * Note: The PLL and SRC parameters are based on a reference frequency that
289eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * would ideally be:
299eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *
309eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
319eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *
329eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * However, it's not the exact reference frequency that matters, only that the
339eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * firmware and modules that comprise the driver for a particular board all
349eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * use the same value (close to the ideal value).
359eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *
369eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * Comments below will note which reference frequency is assumed for various
379eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls * parameters.  They will usually be one of
389eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *
399eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *	ref_freq = 28.636360 MHz
409eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *		or
419eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls *	ref_freq = 28.636363 MHz
429eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls */
439eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
449eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Wallsstatic int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq)
45bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil{
469357b31c6cbd3d1c279fb161b3bf179c53062365Hans Verkuil	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
47bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
48a8bbf12ad8a8ad532cea0b67f0127ad90d336b04Hans Verkuil	if (state->aud_input != CX25840_AUDIO_SERIAL) {
49bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		switch (freq) {
503578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 32000:
519eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
529eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
539eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10
549eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
559eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x1006040f);
569eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
579eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
589eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
599eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
609eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
619eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
629eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
639eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
649eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x1bb39ee
659eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0x6.dd9cf70/0x10 = 32000 * 384
669eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 196.6 MHz pre-postdivide
679eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME < 200 MHz is out of specified valid range
689eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
699eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
709eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x01bb39ee);
719eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
729eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
739eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
749eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
759eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
769eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x50);
77bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
782a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
79e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
80e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
819eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
829eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
834a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x900, 0x0801f77f);
844a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x904, 0x0801f77f);
854a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x90c, 0x0801f77f);
86bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
87bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
883578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 44100:
899eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
909eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
919eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10
929eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
939eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x1009040f);
949eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
959eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
969eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
979eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
989eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
999eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1009eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1019eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1029eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x0ec6bd6
1039eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0x9.7635eb0/0x10 = 44100 * 384
1049eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 271 MHz pre-postdivide
1059eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
1069eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1079eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x00ec6bd6);
1089eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1099eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1109eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
1119eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
1129eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1139eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x50);
114bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
1152a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
116e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
117e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
1189eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
1199eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
1204a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x900, 0x08016d59);
1214a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x904, 0x08016d59);
1224a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x90c, 0x08016d59);
123bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
124bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
1253578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 48000:
1269eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1279eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
1289eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10
1299eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1309eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x100a040f);
1319eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1329eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1339eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
1349eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
1359eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
1369eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1379eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1389eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1399eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x098d6e5
1409eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0xa.4c6b728/0x10 = 48000 * 384
1419eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 295 MHz pre-postdivide
1429eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
1439eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1449eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x0098d6e5);
1459eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1469eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1479eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
1489eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
1499eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1509eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x50);
151bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
1522a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
153e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
154e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
1559eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
1569eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
1574a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x900, 0x08014faa);
1584a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x904, 0x08014faa);
1594a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x90c, 0x08014faa);
160bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
161bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		}
162a8bbf12ad8a8ad532cea0b67f0127ad90d336b04Hans Verkuil	} else {
163bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		switch (freq) {
1643578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 32000:
1659eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1669eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
1679eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e
1689eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1699eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x1e08040f);
1709eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1719eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1729eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
1739eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
1749eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
1759eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1769eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1779eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1789eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x12a0869
1799eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0x8.9504348/0x1e = 32000 * 256
1809eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 246 MHz pre-postdivide
1819eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
1829eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1839eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x012a0869);
1849eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
1859eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
1869eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
1879eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider
1889eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
1899eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x54);
190bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
1912a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
192e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
193e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
1949eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
1959eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.0000 = 32000/32000 */
1964a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x8f8, 0x08010000);
197bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
1989eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
1999eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x2.0000 = 2 * (32000/32000) */
2004a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x900, 0x08020000);
2014a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x904, 0x08020000);
2024a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x90c, 0x08020000);
203bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
204bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2053578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 44100:
2069eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2079eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
2089eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18
2099eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2109eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x1809040f);
2119eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2129eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2139eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
2149eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
2159eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
2169eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2179eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2189eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2199eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x0ec6bd6
2209eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0x9.7635eb0/0x18 = 44100 * 256
2219eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 271 MHz pre-postdivide
2229eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
2239eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2249eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x00ec6bd6);
2259eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2269eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2279eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
2289eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
2299eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2309eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x50);
231bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2322a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
233e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
234e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
2359eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
2369eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.60cd = 44100/32000 */
2374a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x8f8, 0x080160cd);
238bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2399eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
2409eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.7385 = 2 * (32000/44100) */
2414a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x900, 0x08017385);
2424a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x904, 0x08017385);
2434a56eb3f535f92b0585aa01dba05b3f17a547df0Hans Verkuil			cx25840_write4(client, 0x90c, 0x08017385);
244bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
245bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2463578d3dd0b1e468a44a76a83efe90476a854625dHans Verkuil		case 48000:
2479eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2489eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
2499eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18
2509eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2519eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x108, 0x180a040f);
2529eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2539eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2549eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
2559eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
2569eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 432 MHz pre-postdivide
2579eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2589eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2599eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2609eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * AUX_PLL Fraction = 0x098d6e5
2619eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 28636363 * 0xa.4c6b728/0x18 = 48000 * 256
2629eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * 295 MHz pre-postdivide
2639eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
2649eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2659eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x110, 0x0098d6e5);
2669eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2679eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/*
2689eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_SEL = 1
2699eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
2709eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 */
2719eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write(client, 0x127, 0x50);
272bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2732a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls			if (is_cx2583x(state))
274e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil				break;
275e2b8cf4ced47465b24d6fe911714827475fb0412Hans Verkuil
2769eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
2779eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.8000 = 48000/32000 */
2789eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x8f8, 0x08018000);
279bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
2809eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
2819eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.5555 = 2 * (32000/48000) */
2829eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08015555);
2839eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08015555);
2849eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08015555);
2859eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
2869eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		}
2879eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	}
2889eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2899eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	state->audclk_freq = freq;
2909eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2919eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	return 0;
2929eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls}
2939eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2949eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Wallsstatic inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq)
2959eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls{
2969eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	return cx25840_set_audclk_freq(client, freq);
2979eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls}
2989eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
2999eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Wallsstatic int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq)
3009eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls{
3019eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
3029eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3039eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (state->aud_input != CX25840_AUDIO_SERIAL) {
3049eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		switch (freq) {
3059eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 32000:
3069eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 44100:
3079eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 48000:
3089eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* We don't have register values
3099eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * so avoid destroying registers. */
3109eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* FIXME return -EINVAL; */
3119eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3129eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		}
3139eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	} else {
3149eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		switch (freq) {
3159eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 32000:
3169eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 44100:
3179eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* We don't have register values
3189eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			 * so avoid destroying registers. */
3199eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* FIXME return -EINVAL; */
3209eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
321f234081bc564c69eb0e2cd4e957ad1cbae4a6144Steven Toth
3229eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 48000:
3239eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
3249eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
3259eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x8f8, 0x0801867c);
326f234081bc564c69eb0e2cd4e957ad1cbae4a6144Steven Toth
3279eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3289eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
3299eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08014faa);
3309eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08014faa);
3319eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08014faa);
332bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil			break;
333bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		}
334bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	}
335bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
336bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	state->audclk_freq = freq;
337bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
338bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	return 0;
339bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil}
340bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
3419eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Wallsstatic int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq)
3429eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls{
3439eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
3449eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3459eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (state->aud_input != CX25840_AUDIO_SERIAL) {
3469eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		switch (freq) {
3479eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 32000:
3489eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3499eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
3509eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x0801f77f);
3519eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x0801f77f);
3529eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x0801f77f);
3539eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3549eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3559eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 44100:
3569eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3579eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
3589eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08016d59);
3599eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08016d59);
3609eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08016d59);
3619eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3629eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3639eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 48000:
3649eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3659eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
3669eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08014faa);
3679eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08014faa);
3689eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08014faa);
3699eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3709eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		}
3719eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	} else {
3729eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		switch (freq) {
3739eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		/* FIXME These cases make different assumptions about audclk */
3749eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 32000:
3759eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
3769eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.0000 = 32000/32000 */
3779eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x8f8, 0x08010000);
3789eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3799eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3809eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x2.0000 = 2 * (32000/32000) */
3819eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08020000);
3829eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08020000);
3839eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08020000);
3849eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3859eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3869eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 44100:
3879eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
3889eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.60cd = 44100/32000 */
3899eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x8f8, 0x080160cd);
3909eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3919eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
3929eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.7385 = 2 * (32000/44100) */
3939eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08017385);
3949eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08017385);
3959eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08017385);
3969eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
3979eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
3989eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		case 48000:
3999eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src1_ctl */
4009eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
4019eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x8f8, 0x0801867c);
4029eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4039eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* src3/4/6_ctl */
4049eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
4059eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x900, 0x08014faa);
4069eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x904, 0x08014faa);
4079eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			cx25840_write4(client, 0x90c, 0x08014faa);
4089eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls			break;
4099eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		}
4109eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	}
4119eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4129eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	state->audclk_freq = freq;
4139eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4149eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	return 0;
4159eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls}
4169eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4179eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Wallsstatic int set_audclk_freq(struct i2c_client *client, u32 freq)
4189eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls{
4199eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
4209eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4219eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (freq != 32000 && freq != 44100 && freq != 48000)
4229eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		return -EINVAL;
4239eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4249eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (is_cx231xx(state))
4259eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		return cx231xx_set_audclk_freq(client, freq);
4269eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4279eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (is_cx2388x(state))
4289eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		return cx23885_set_audclk_freq(client, freq);
4299eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4309eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	if (is_cx2583x(state))
4319eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls		return cx25836_set_audclk_freq(client, freq);
4329eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
4339eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls	return cx25840_set_audclk_freq(client, freq);
4349eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls}
4359eef550a9a98c1e3d15aaf490812949fdeb01c7cAndy Walls
436a8bbf12ad8a8ad532cea0b67f0127ad90d336b04Hans Verkuilvoid cx25840_audio_set_path(struct i2c_client *client)
437bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil{
4389357b31c6cbd3d1c279fb161b3bf179c53062365Hans Verkuil	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
439bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
4405af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth	if (!is_cx2583x(state)) {
4415af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		/* assert soft reset */
4425af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		cx25840_and_or(client, 0x810, ~0x1, 0x01);
4435af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth
4445af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		/* stop microcontroller */
4455af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		cx25840_and_or(client, 0x803, ~0x10, 0);
4465af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth
4475af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		/* Mute everything to prevent the PFFT! */
4485af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		cx25840_write(client, 0x8d3, 0x1f);
4495af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth
4505af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		if (state->aud_input == CX25840_AUDIO_SERIAL) {
4515af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			/* Set Path1 to Serial Audio Input */
4525af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			cx25840_write4(client, 0x8d0, 0x01011012);
4535af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth
4545af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			/* The microcontroller should not be started for the
4555af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			 * non-tuner inputs: autodetection is specific for
4565af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			 * TV audio. */
4575af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		} else {
4585af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			/* Set Path1 to Analog Demod Main Channel */
4595af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			cx25840_write4(client, 0x8d0, 0x1f063870);
4605af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		}
461c0c044a71f3d0a0a73c954b389cbc4b55ed4c2baHans Verkuil	}
462c0c044a71f3d0a0a73c954b389cbc4b55ed4c2baHans Verkuil
463c0c044a71f3d0a0a73c954b389cbc4b55ed4c2baHans Verkuil	set_audclk_freq(client, state->audclk_freq);
464bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
4655af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth	if (!is_cx2583x(state)) {
4665af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		if (state->aud_input != CX25840_AUDIO_SERIAL) {
4675af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			/* When the microcontroller detects the
4685af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			 * audio format, it will unmute the lines */
4695af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			cx25840_and_or(client, 0x803, ~0x10, 0x10);
4705af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		}
4718267761881d6bb91c168ba4d629b778cf106c485Hans Verkuil
4725af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		/* deassert soft reset */
4735af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		cx25840_and_or(client, 0x810, ~0x1, 0x00);
474f234081bc564c69eb0e2cd4e957ad1cbae4a6144Steven Toth
4755af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		/* Ensure the controller is running when we exit */
4765af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth		if (is_cx2388x(state) || is_cx231xx(state))
4775af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth			cx25840_and_or(client, 0x803, ~0x10, 0x10);
4785af79f86db6a29a158510b5dc255d8844d95c4e9Sven Barth	}
479bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil}
480bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
481d92c20e0a5b560bbe46d7e68bb47df2366cddf8fHans Verkuilstatic void set_volume(struct i2c_client *client, int volume)
482bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil{
48387410dab1238623e082e9a78a62f1bbeb6c475e3Hans Verkuil	int vol;
48487410dab1238623e082e9a78a62f1bbeb6c475e3Hans Verkuil
48587410dab1238623e082e9a78a62f1bbeb6c475e3Hans Verkuil	/* Convert the volume to msp3400 values (0-127) */
48687410dab1238623e082e9a78a62f1bbeb6c475e3Hans Verkuil	vol = volume >> 9;
48787410dab1238623e082e9a78a62f1bbeb6c475e3Hans Verkuil
488bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	/* now scale it up to cx25840 values
489bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	 * -114dB to -96dB maps to 0
490bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	 * this should be 19, but in my testing that was 4dB too loud */
491bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	if (vol <= 23) {
492bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		vol = 0;
493bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	} else {
494bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		vol -= 23;
495bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	}
496bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
497bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	/* PATH1_VOLUME */
4984c3764d15050f91a76cede6f24402cd2701e73efSteven Toth	cx25840_write(client, 0x8d4, 228 - (vol * 2));
499bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil}
500bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
501d92c20e0a5b560bbe46d7e68bb47df2366cddf8fHans Verkuilstatic void set_balance(struct i2c_client *client, int balance)
502bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil{
503bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	int bal = balance >> 8;
504bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	if (bal > 0x80) {
505bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		/* PATH1_BAL_LEFT */
506bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
507bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		/* PATH1_BAL_LEVEL */
508bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
509bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	} else {
510bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		/* PATH1_BAL_LEFT */
511bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
512bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		/* PATH1_BAL_LEVEL */
513bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
514bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	}
515bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil}
516bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
517df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuilint cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
518bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil{
519df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
520df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	struct cx25840_state *state = to_state(sd);
521c0c044a71f3d0a0a73c954b389cbc4b55ed4c2baHans Verkuil	int retval;
522bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
5232a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls	if (!is_cx2583x(state))
524df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		cx25840_and_or(client, 0x810, ~0x1, 1);
525df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	if (state->aud_input != CX25840_AUDIO_SERIAL) {
526df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		cx25840_and_or(client, 0x803, ~0x10, 0);
527df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		cx25840_write(client, 0x8d3, 0x1f);
528df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	}
529df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	retval = set_audclk_freq(client, freq);
530df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	if (state->aud_input != CX25840_AUDIO_SERIAL)
531df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		cx25840_and_or(client, 0x803, ~0x10, 0x10);
5322a03f03471d3232037e656570ccaf3ff2ffd01e8Andy Walls	if (!is_cx2583x(state))
533df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		cx25840_and_or(client, 0x810, ~0x1, 0);
534df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	return retval;
535df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil}
536a8bbf12ad8a8ad532cea0b67f0127ad90d336b04Hans Verkuil
537e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuilstatic int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl)
538df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil{
539e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil	struct v4l2_subdev *sd = to_sd(ctrl);
540e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil	struct cx25840_state *state = to_state(sd);
541df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
542a8bbf12ad8a8ad532cea0b67f0127ad90d336b04Hans Verkuil
543df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	switch (ctrl->id) {
544df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	case V4L2_CID_AUDIO_VOLUME:
545e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		if (state->mute->val)
546e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil			set_volume(client, 0);
547e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		else
548e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil			set_volume(client, state->volume->val);
549df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		break;
550df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	case V4L2_CID_AUDIO_BASS:
551e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		/* PATH1_EQ_BASS_VOL */
552e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		cx25840_and_or(client, 0x8d9, ~0x3f,
553e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil					48 - (ctrl->val * 48 / 0xffff));
554df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		break;
555df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	case V4L2_CID_AUDIO_TREBLE:
556e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		/* PATH1_EQ_TREBLE_VOL */
557e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		cx25840_and_or(client, 0x8db, ~0x3f,
558e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil					48 - (ctrl->val * 48 / 0xffff));
559df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		break;
560df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	case V4L2_CID_AUDIO_BALANCE:
561e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil		set_balance(client, ctrl->val);
562df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil		break;
563bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	default:
564bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil		return -EINVAL;
565bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil	}
566df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil	return 0;
567df1d5ed8a81565b78d45fbdffb6561c75c75ec0dHans Verkuil}
568bd985160a9f4623fdb24fcfeb36fe59e1b8f7b57Hans Verkuil
569e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuilconst struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
570e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil	.s_ctrl = cx25840_audio_s_ctrl,
571e34e658b5a42fb1a12fda2112f0b556cf5d1f1c4Hans Verkuil};
572