msp3400-kthreads.c revision d312a46e5340be6a89c662ac483230c0737148c9
17e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 27e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * Programming the mspx4xx sound processor family 37e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 47e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> 57e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 67e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * This program is free software; you can redistribute it and/or 77e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * modify it under the terms of the GNU General Public License 87e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * as published by the Free Software Foundation; either version 2 97e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * of the License, or (at your option) any later version. 107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * This program is distributed in the hope that it will be useful, 127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * GNU General Public License for more details. 157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * You should have received a copy of the GNU General Public License 177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * along with this program; if not, write to the Free Software 187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kernel.h> 237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/module.h> 247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/slab.h> 257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/i2c.h> 267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/videodev.h> 277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/videodev2.h> 287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <media/v4l2-common.h> 297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <media/audiochip.h> 307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kthread.h> 317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/suspend.h> 327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include "msp3400.h" 337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* this one uses the automatic sound standard detection of newer msp34xx 357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil chip versions */ 367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct { 377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int retval; 387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int main, second; 397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} msp_modelist[] = { 417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0000, 0, 0, "could not detect sound standard" }, 427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0001, 0, 0, "autodetect start" }, 437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, 447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, 457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, 467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, 477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, 487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, 497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, 507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, 517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, 527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, 537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, 547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, 557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, 567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, 577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, 587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, 597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, 607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { -1, 0, 0, NULL }, /* EOF */ 617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_init_data_dem { 647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir1[6]; 657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir2[6]; 667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo1; 677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo2; 687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int ad_cv; 697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int mode_reg; 707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_src; 717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_matrix; 727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} msp3400c_init_data[] = { 737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { /* AM (for carrier detect / msp3400) */ 747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0500, 0x0020, 0x3000 787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* AM (for carrier detect / msp3410) */ 797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0100, 0x0020, 0x3000 837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* FM Radio */ 847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7), MSP_CARRIER(10.7), 877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0020, 0x3000 887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Terrestial FM-mono + FM-stereo */ 897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0030, 0x3000 937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Sat FM-mono */ 947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 1, 9, 14, 24, 33, 37}, 957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 3, 18, 27, 48, 66, 72}, 967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00c6, 0x0480, 0x0000, 0x3000 987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ 997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- I (6.0/6.552) */ 1047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {2, 4, -6, -4, 40, 94}, 1057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.0), MSP_CARRIER(6.0), 1077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/AM -- L (6.5/5.85) */ 1097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-4, -12, -9, 23, 79, 126}, 1117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 1127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00c6, 0x0140, 0x0120, 0x7c03 1137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil }, 1147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstruct msp3400c_carrier_detect { 1177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo; 1187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 1197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = { 1227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* main carrier */ 1237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(4.5), "4.5 NTSC" }, 1247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.5), "5.5 PAL B/G" }, 1257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.0), "6.0 PAL I" }, 1267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } 1277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = { 1307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL B/G */ 1317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, 1327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } 1337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = { 1367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL SAT / SECAM */ 1377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, 1387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, 1397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, 1407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, 1417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, 1427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, 1437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ------------------------------------------------------------------------ */ 1467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilconst char *msp_standard_mode_name(int mode) 1487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; msp_modelist[i].name != NULL; i++) 1527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_modelist[i].retval == mode) 1537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return msp_modelist[i].name; 1547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return "unknown"; 1557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilvoid msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) 1587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0093, cdo1 & 0xfff); 1607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x009b, cdo1 >> 12); 1617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00a3, cdo2 & 0xfff); 1627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00ab, cdo2 >> 12); 1637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ 1647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilvoid msp3400c_setmode(struct i2c_client *client, int type) 1677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 1697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "setmode: %d\n", type); 1727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = type; 1737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->audmode = V4L2_TUNER_MODE_MONO; 1747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 1757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv); 1777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) /* fir 1 */ 1797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]); 1807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ 1827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0040); 1837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0000); 1847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) 1857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]); 1867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg); 1887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1, 1907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_init_data[type].cdo2); 1917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ 1937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (dolby) { 1957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ 1967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ 1977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); 1987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 1997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src); 2007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src); 2017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); 2027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src); 2047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix); 2057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2067560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->has_nicam) { 2077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam prescale */ 2087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ 2097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 2117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* turn on/off nicam + stereo */ 2137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilvoid msp3400c_setstereo(struct i2c_client *client, int mode) 2147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 215d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; 2167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 2177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int nicam = 0; /* channel source: FM/AM or nicam */ 2187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int src = 0; 2197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->opmode == OPMODE_AUTOSELECT) { 2217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* this method would break everything, let's make sure 2227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * it's never called 2237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 2247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "setstereo called with mode=%d instead of set_source (ignored)\n", 2257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil mode); 2267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch demodulator */ 2307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 2317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 2327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "FM setstereo: %s\n", strmode[mode]); 233d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 2347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (mode) { 2357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3001); 2377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3000); 2427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_SAT: 2467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "SAT setstereo: %s\n", strmode[mode]); 2477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (mode) { 2487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); 2507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); 2537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 2637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 2647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 2657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "NICAM setstereo: %s\n",strmode[mode]); 2667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client,state->second,state->main); 2677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->nicam_on) 2687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil nicam=0x0100; 2697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 2717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "BTSC setstereo: %s\n",strmode[mode]); 2727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil nicam=0x0300; 2737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_EXTERN: 2757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "extern setstereo: %s\n",strmode[mode]); 2767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil nicam = 0x0200; 2777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_RADIO: 2797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "FM-Radio setstereo: %s\n",strmode[mode]); 2807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 2827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "mono setstereo\n"); 2837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch audio */ 287d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil switch (mode) { 2887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0020 | nicam; 2907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) { 2937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "switching to AM mono\n"); 2947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM mono decoding is handled by tuner, not MSP chip */ 2957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART switching control register */ 2967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client, SCART_MONO, 0); 2977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0200; 2987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0000 | nicam; 3027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0010 | nicam; 3057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "setstereo final source/matrix = 0x%x\n", src); 3087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (dolby) { 3107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0008, 0x0520); 3117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0009, 0x0620); 3127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000a, src); 3137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000b, src); 3147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0008, src); 3167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0009, src); 3177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000a, src); 3187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000b, src); 319d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil msp_write_dsp(client, 0x000c, src); 320d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (state->has_scart23_in_scart2_out) 321d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil msp_write_dsp(client, 0x0041, src); 3227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp3400c_print_mode(struct i2c_client *client) 3267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->main == state->second) { 3307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "mono sound carrier: %d.%03d MHz\n", 3317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "main sound carrier: %d.%03d MHz\n", 3347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) 3377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "NICAM/FM carrier : %d.%03d MHz\n", 3387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second/910) % 1000); 3397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) 3407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "NICAM/AM carrier : %d.%03d MHz\n", 3417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { 3437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "FM-stereo carrier : %d.%03d MHz\n", 3447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 3497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint autodetect_stereo(struct i2c_client *client) 3517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val; 3547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int rxsubchans = state->rxsubchans; 3557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int newnicam = state->nicam_on; 3567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int update = 0; 3577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 3597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 3607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x18); 3617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 3627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 3637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "stereo detect register: %d\n", val); 3647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 4096) { 3657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; 3667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else if (val < -4096) { 3677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 3687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 3727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 3747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 3757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 3767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x23); 3777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "nicam sync=%d, mode=%d\n", 3787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val & 1, (val & 0x1e) >> 1); 3797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 1) { 3817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam synced */ 3827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch ((val & 0x1e) >> 1) { 3837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: 3847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 8: 3857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 3867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: 3887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 9: 3897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO 3907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil | V4L2_TUNER_SUB_LANG1; 3917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: 3937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 10: 3947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO 3957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil | V4L2_TUNER_SUB_LANG1 3967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil | V4L2_TUNER_SUB_LANG2; 3977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 3997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 1; 4037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 4097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x200); 4107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n", 4117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val, 4127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil (val & 0x0002) ? "no" : "yes", 4137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil (val & 0x0004) ? "no" : "yes", 4147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil (val & 0x0040) ? "stereo" : "mono", 4157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil (val & 0x0080) ? ", nicam 2nd mono" : "", 4167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil (val & 0x0100) ? ", bilingual/SAP" : ""); 4177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; 4197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; 4207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (rxsubchans != state->rxsubchans) { 4237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 4247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "watch: rxsubchans %d => %d\n", 4257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans,rxsubchans); 4267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = rxsubchans; 4277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (newnicam != state->nicam_on) { 4297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 4307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "watch: nicam %d => %d\n", 4317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on,newnicam); 4327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = newnicam; 4337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return update; 4357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 4387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * A kernel thread for msp3400 control -- we don't want to block the 4397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * in the ioctl while doing the sound carrier & stereo detect 4407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 4417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* stereo/multilang monitoring */ 4427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void watch_stereo(struct i2c_client *client) 4437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (autodetect_stereo(client)) { 447d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 4487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); 449d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1) 4507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); 4517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 4527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); 4537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (once) 4567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3400c_thread(void *data) 4607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 4627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp3400c_carrier_detect *cd; 4647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int count, max1,max2,val1,val2, val,this; 4657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "msp3400 daemon started\n"); 4687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 4697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp3400 thread: sleep\n"); 4707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 4717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp3400 thread: wakeup\n"); 4727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 4747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: restart scan\n"); 4757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 4767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 4777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4797560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio || MSP_MODE_EXTERN == state->mode) { 4807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan, just unmute */ 4817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: no carrier scan\n"); 4827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 4837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 4847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* mute */ 4877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_mute(client); 4887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); 4897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val2 = 0; 4907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = max2 = -1; 4917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* some time for the tuner to sync */ 4947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,200)) 4957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 4967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #1 -- main carrier */ 4987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_main; 4997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_main); 5007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5017560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (amsound && (state->std & V4L2_STD_SECAM)) { 5027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = 3; 5047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "AM sound override\n"); 5067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); 5107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val1 < val) 5167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val, max1 = this; 5177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "carrier1 val: %5d / %s\n", val,cd[this].name); 5187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #2 -- second (stereo) carrier */ 5217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_55; 5247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_55); 5257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_65; 5287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_65); 5297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5387560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (amsound && (state->std & V4L2_STD_SECAM)) { 5397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max2 = 0; 5437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); 5467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val2 < val) 5527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val2 = val, max2 = this; 5537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "carrier2 val: %5d / %s\n", val,cd[this].name); 5547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* program the msp3400 according to the results */ 5577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main = msp3400c_carrier_detect_main[max1].cdo; 5587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 0) { 5617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G FM-stereo */ 5627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_TERRA); 5647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 5657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); 5667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5677560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 1 && state->has_nicam) { 5687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G NICAM */ 5697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_NICAM1); 5717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 5737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 5757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 5767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL I NICAM */ 5807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = MSP_CARRIER(6.552); 5817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_NICAM2); 5827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 5847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 1 || max2 == 2) { 5887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K FM-stereo */ 5897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_TERRA); 5917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 5927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); 5937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5947560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && (state->std & V4L2_STD_SECAM)) { 5957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* L NICAM or AM-mono */ 5967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_AM_NICAM); 5987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 5997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); 6007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 6017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* volume prescale for SCART (AM mono input) */ 6027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000d, 0x1900); 6037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6047560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && state->has_nicam) { 6057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K NICAM */ 6067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_NICAM1); 6087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 6107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 6137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 6167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 6177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil no_second: 6187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_main[max1].cdo; 6197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client, MSP_MODE_FM_TERRA); 6207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 6217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, state->second, state->main); 6227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 6237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); 6247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute */ 6287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (debug) 6317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_print_mode(client); 6327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* monitor tv audio mode */ 6347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 6357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,5000)) 6367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil watch_stereo(client); 6387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: exit\n"); 6417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 6427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 6437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3410d_thread(void *data) 6467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 6477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 6487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 649d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil int val, i, std; 6507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "msp3410 daemon started\n"); 6527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 6547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp3410 thread: sleep\n"); 6557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state,-1); 6567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp3410 thread: wakeup\n"); 6577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 6597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: restart scan\n"); 6607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 6617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 6627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 6657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan needed, just unmute */ 6667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: no carrier scan\n"); 6677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 6697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* put into sane state (and mute) */ 6727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_reset(client); 6737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* some time for the tuner to sync */ 6757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,200)) 6767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* start autodetect */ 679d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil std = 1; 680d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (state->std & V4L2_STD_NTSC) 681d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil std = 0x20; 682d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else 683d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil msp_write_dem(client, 0x20, std); 6847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 6857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (debug) 6877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "setting mode: %s (0x%04x)\n", 6887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_standard_mode_name(std), std); 6897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 1) { 6917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* programmed some specific mode */ 6927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = std; 6937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* triggered autodetect */ 6957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 696d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (msp_sleep(state, 100)) 6977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 7007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 7017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) 7027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "detection still in progress\n"); 7047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; msp_modelist[i].name != NULL; i++) 7077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_modelist[i].retval == val) 7087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "current mode: %s (0x%04x)\n", 7107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_standard_mode_name(val), val); 7117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main = msp_modelist[i].main; 7127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp_modelist[i].second; 7137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7147560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (amsound && (state->std & V4L2_STD_SECAM) && (val != 0x0009)) { 7157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetection has failed, let backup */ 7167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "autodetection failed," 7177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil " switching to backup mode: %s (0x%04x)\n", 7187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_modelist[8].name ? msp_modelist[8].name : "unknown",val); 7197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = 0x0009; 7207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x20, val); 7217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set various prescales */ 7247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 7257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0e, 0x2403); /* FM */ 7267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 7277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set stereo */ 7297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (val) { 7307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0008: /* B/G NICAM */ 7317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x000a: /* I NICAM */ 7327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val == 0x0008) 7337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM1; 7347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 7357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM2; 7367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); 7417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0009: 7437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_AM_NICAM; 7447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); 7477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0020: /* BTSC */ 7507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_BTSC; 7527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 7547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); 7567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0040: /* FM radio */ 7587560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil state->mode = MSP_MODE_FM_RADIO; 7597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->audmode = V4L2_TUNER_MODE_STEREO; 7617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 7627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 7637560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* not needed in theory if we have radio, but 7647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil short programming enables carrier mute */ 7657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setmode(client,MSP_MODE_FM_RADIO); 7667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_setcarrier(client, MSP_CARRIER(10.7), 7677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7)); 7687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* scart routing */ 7697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client,SCART_IN2,0); 7707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* msp34xx does radio decoding */ 7717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x08, 0x0020); 7727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x09, 0x0020); 7737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0b, 0x0020); 7747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0003: 7767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0004: 7777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0005: 7787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_TERRA; 7797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->audmode = V4L2_TUNER_MODE_MONO; 7817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 0; 7827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute, restore misc registers */ 7877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 7887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x13, state->acb); 7897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 7907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* monitor tv audio mode */ 7927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 7937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,5000)) 7947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 7957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil watch_stereo(client); 7967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: exit\n"); 7997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 8007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 8037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* msp34xxG + (autoselect no-thread) */ 8057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* this one uses both automatic standard detection and automatic sound */ 8067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* select which are available in the newer G versions */ 8077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* struct msp: only norm, acb and source are really used in this mode */ 8087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* set the same 'source' for the loudspeaker, scart and quasi-peak detector 8107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * the value for source is the same as bit 15:8 of DSP registers 0x08, 8117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B 8127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 8137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * this function replaces msp3400c_setstereo 8147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp34xxg_set_source(struct i2c_client *client, int source) 8167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* fix matrix mode to stereo and let the msp choose what 8207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * to output according to 'source', as recommended 8217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * for MONO (source==0) downmixing set bit[7:0] to 0x30 8227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); 8247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "set source to %d (0x%x)\n", source, value); 8267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* Loudspeaker Output */ 8277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x08, value); 8287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART1 DA Output */ 8297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0a, value); 8307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* Quasi-peak detector */ 8317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0c, value); 8327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* 8337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * set identification threshold. Personally, I 8347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * I set it to a higher value that the default 8357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * of 0x190 to ignore noisy stereo signals. 8367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * this needs tuning. (recommended range 0x00a0-0x03c0) 8377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 0x7f0 = forced mono mode 8387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* a2 threshold for stereo/bilingual */ 8407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x22, stereo_threshold); 8417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->source = source; 8427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* (re-)initialize the msp34xxg, according to the current norm in state->norm 8457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * return 0 if it worked, -1 if it failed 8467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic int msp34xxg_reset(struct i2c_client *client) 8487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int modus, std; 8517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_reset(client)) 8537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* make sure that input/output is muted (paranoid mode) */ 8567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* ACB, mute DSP input, mute SCART 1 */ 8577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, 0x0f20)) 8587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 8617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* step-by-step initialisation, as described in the manual */ 8637560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil modus = msp_modus(client); 8647560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio) 8657560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil std = 0x40; 8667560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil else 8677560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil std = (state->std & V4L2_STD_NTSC) ? 0x20 : 1; 8687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil modus &= ~0x03; /* STATUS_CHANGE = 0 */ 8697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */ 8707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dem(client, 0x30, modus)) 8717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dem(client, 0x20, std)) 8737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* write the dsps that may have an influence on 8767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil standard/audio autodetection right now */ 8777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_set_source(client, state->source); 8787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM/FM Prescale [15:8] 75khz deviation */ 8807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x0e, 0x3000)) 8817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* NICAM Prescale 9db gain (as recommended) */ 8847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x10, 0x5a00)) 8857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 8887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp34xxg_thread(void *data) 8917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 8937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val, std, i; 8957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "msp34xxg daemon started\n"); 8977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->source = 1; /* default */ 8997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 9007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp34xxg thread: sleep\n"); 9017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 9027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "msp34xxg thread: wakeup\n"); 9037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 9057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: restart scan\n"); 9067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 9077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 9087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* setup the chip*/ 9117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_reset(client); 9127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil std = standard; 9137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 0x01) 9147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto unmute; 9157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* watch autodetect */ 9177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "triggered autodetect, waiting for result\n"); 9187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; i < 10; i++) { 9197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state, 100)) 9207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 9217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 9237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 9247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) { 9257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil std = val; 9267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(2, client, "detection still in progress\n"); 9297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std == 1) { 9317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "detection still in progress after 10 tries. giving up.\n"); 9327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 9337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil unmute: 9367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = std; 9377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "current mode: %s (0x%04x)\n", 9387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_standard_mode_name(std), std); 9397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute: dispatch sound to scart output, set scart volume */ 9417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 9427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* restore ACB */ 9447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, state->acb)) 9457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 9467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 9487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "thread: exit\n"); 9507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 9517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilvoid msp34xxg_detect_stereo(struct i2c_client *client) 9547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int status = msp_read_dem(client, 0x0200); 9587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_bilingual = status & 0x100; 9597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_stereo = status & 0x40; 9607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = 0; 9627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_stereo) 9637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_STEREO; 9647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 9657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_MONO; 9667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_bilingual) { 9677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 9687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* I'm supposed to check whether it's SAP or not 9697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * and set only LANG2/SAP in this case. Yet, the MSP 9707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * does a lot of work to hide this and handle everything 9717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * the same way. I don't want to work around it so unless 9727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * this is a problem, I'll handle SAP just like lang1/lang2. 9737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 9747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_dbg(1, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", 9767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil status, is_stereo, is_bilingual, state->rxsubchans); 9777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilvoid msp34xxg_set_audmode(struct i2c_client *client, int audmode) 9807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int source; 9837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (audmode) { 9857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 9867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 0; /* mono only */ 9877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 9897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ 9907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* problem: that could also mean 2 (scart input) */ 9917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 9937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 3; /* stereo or A */ 9947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 9967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 4; /* stereo or B */ 9977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 9997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil audmode = 0; 10007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 1; 10017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 10027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 10037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->audmode = audmode; 10047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_set_source(client, source); 10057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1007