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