^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Programming the mspx4xx sound processor family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <media/drv-intf/msp3400.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "msp3400-driver.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* this one uses the automatic sound standard detection of newer msp34xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) chip versions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int main, second;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) v4l2_std_id std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) } msp_stdlist[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) "4.5/4.72 M Dual FM-Stereo", V4L2_STD_MN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) "5.5/5.74 B/G Dual FM-Stereo", V4L2_STD_BG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "6.5/6.25 D/K1 Dual FM-Stereo", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "6.5/6.74 D/K2 Dual FM-Stereo", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "6.5 D/K FM-Mono (HDEV3)", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "6.5/5.74 D/K3 Dual FM-Stereo", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) "5.5/5.85 B/G NICAM FM", V4L2_STD_BG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "6.5/5.85 L NICAM AM", V4L2_STD_L },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "6.0/6.55 I NICAM FM", V4L2_STD_PAL_I },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "6.5/5.85 D/K NICAM FM", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "6.5/5.85 D/K NICAM FM (HDEV2)", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) "6.5/5.85 D/K NICAM FM (HDEV3)", V4L2_STD_DK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "4.5 M BTSC-Stereo", V4L2_STD_MTS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) "4.5 M BTSC-Mono + SAP", V4L2_STD_MTS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) "4.5 M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) "10.7 FM-Stereo Radio", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "6.5 SAT-Mono", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "7.02/7.20 SAT-Stereo", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "7.2 SAT ADR", V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { -1, 0, 0, NULL, 0 }, /* EOF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static struct msp3400c_init_data_dem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int fir1[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int fir2[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int cdo1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int cdo2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int ad_cv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int mode_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int dsp_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int dsp_matrix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) } msp3400c_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { /* AM (for carrier detect / msp3400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {75, 19, 36, 35, 39, 40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {75, 19, 36, 35, 39, 40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) MSP_CARRIER(5.5), MSP_CARRIER(5.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 0x00d0, 0x0500, 0x0020, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }, { /* AM (for carrier detect / msp3410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {-1, -1, -8, 2, 59, 126},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {-1, -1, -8, 2, 59, 126},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MSP_CARRIER(5.5), MSP_CARRIER(5.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 0x00d0, 0x0100, 0x0020, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }, { /* FM Radio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {-8, -8, 4, 6, 78, 107},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {-8, -8, 4, 6, 78, 107},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) MSP_CARRIER(10.7), MSP_CARRIER(10.7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) 0x00d0, 0x0480, 0x0020, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }, { /* Terrestrial FM-mono + FM-stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {3, 18, 27, 48, 66, 72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {3, 18, 27, 48, 66, 72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) MSP_CARRIER(5.5), MSP_CARRIER(5.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 0x00d0, 0x0480, 0x0030, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }, { /* Sat FM-mono */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { 1, 9, 14, 24, 33, 37},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { 3, 18, 27, 48, 66, 72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) MSP_CARRIER(6.5), MSP_CARRIER(6.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 0x00c6, 0x0480, 0x0000, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }, { /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {-2, -8, -10, 10, 50, 86},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {3, 18, 27, 48, 66, 72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) MSP_CARRIER(5.5), MSP_CARRIER(5.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 0x00d0, 0x0040, 0x0120, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }, { /* NICAM/FM -- I (6.0/6.552) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {2, 4, -6, -4, 40, 94},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {3, 18, 27, 48, 66, 72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) MSP_CARRIER(6.0), MSP_CARRIER(6.0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 0x00d0, 0x0040, 0x0120, 0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }, { /* NICAM/AM -- L (6.5/5.85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {-2, -8, -10, 10, 50, 86},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {-4, -12, -9, 23, 79, 126},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) MSP_CARRIER(6.5), MSP_CARRIER(6.5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 0x00c6, 0x0140, 0x0120, 0x7c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct msp3400c_carrier_detect {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* main carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { MSP_CARRIER(4.5), "4.5 NTSC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { MSP_CARRIER(5.5), "5.5 PAL B/G" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { MSP_CARRIER(6.0), "6.0 PAL I" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* PAL B/G */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* PAL SAT / SECAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) const char *msp_standard_std_name(int std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; msp_stdlist[i].name != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (msp_stdlist[i].retval == std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return msp_stdlist[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static v4l2_std_id msp_standard_std(int std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; msp_stdlist[i].name != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (msp_stdlist[i].retval == std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return msp_stdlist[i].std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void msp_set_source(struct i2c_client *client, u16 src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (msp_dolby) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) msp_write_dsp(client, 0x0008, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) msp_write_dsp(client, 0x0009, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) msp_write_dsp(client, 0x000a, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) msp_write_dsp(client, 0x000b, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) msp_write_dsp(client, 0x000c, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (state->has_scart2_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) msp_write_dsp(client, 0x0041, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) msp_write_dem(client, 0x0093, cdo1 & 0xfff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) msp_write_dem(client, 0x009b, cdo1 >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) msp_write_dem(client, 0x00a3, cdo2 & 0xfff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) msp_write_dem(client, 0x00ab, cdo2 >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) void msp3400c_set_mode(struct i2c_client *client, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int tuner = (state->route_in >> 3) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dev_dbg_lvl(&client->dev, 1, msp_debug, "set_mode: %d\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) state->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) state->rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (i = 5; i >= 0; i--) /* fir 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) msp_write_dem(client, 0x0001, data->fir1[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) msp_write_dem(client, 0x0005, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) msp_write_dem(client, 0x0005, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for (i = 5; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) msp_write_dem(client, 0x0005, data->fir2[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) msp_write_dem(client, 0x0083, data->mode_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) msp3400c_set_carrier(client, data->cdo1, data->cdo2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) msp_set_source(client, data->dsp_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* set prescales */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* volume prescale for SCART (AM mono input) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) msp_write_dsp(client, 0x000d, 0x1900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) msp_write_dsp(client, 0x000e, data->dsp_matrix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (state->has_nicam) /* nicam prescale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) msp_write_dsp(client, 0x0010, 0x5a00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) nor do they support stereo BTSC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void msp3400c_set_audmode(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static char *strmode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) "mono", "stereo", "lang2", "lang1", "lang1+lang2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) strmode[state->audmode] : "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int src = 0; /* channel source: FM/AM, nicam or SCART */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int audmode = state->audmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (state->opmode == OPMODE_AUTOSELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* this method would break everything, let's make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * it's never called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) "set_audmode called with mode=%d instead of set_source (ignored)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) state->audmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Note: for the C and D revs no NTSC stereo + SAP is possible as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) the hardware does not support SAP. So the rxsubchans combination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) of STEREO | LANG2 does not occur. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (state->mode != MSP_MODE_EXTERN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* switch to mono if only mono is available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) audmode = V4L2_TUNER_MODE_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* if bilingual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* and mono or stereo, then fallback to lang1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (audmode == V4L2_TUNER_MODE_MONO ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) audmode == V4L2_TUNER_MODE_STEREO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) audmode = V4L2_TUNER_MODE_LANG1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* if stereo, and audmode is not mono, then switch to stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else if (audmode != V4L2_TUNER_MODE_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) audmode = V4L2_TUNER_MODE_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* switch demodulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) switch (state->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case MSP_MODE_FM_TERRA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dev_dbg_lvl(&client->dev, 1, msp_debug, "FM set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) switch (audmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case V4L2_TUNER_MODE_STEREO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) msp_write_dsp(client, 0x000e, 0x3001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case V4L2_TUNER_MODE_MONO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case V4L2_TUNER_MODE_LANG1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case V4L2_TUNER_MODE_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case V4L2_TUNER_MODE_LANG1_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msp_write_dsp(client, 0x000e, 0x3000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case MSP_MODE_FM_SAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dev_dbg_lvl(&client->dev, 1, msp_debug, "SAT set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) switch (audmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case V4L2_TUNER_MODE_MONO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case V4L2_TUNER_MODE_STEREO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case V4L2_TUNER_MODE_LANG1_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case V4L2_TUNER_MODE_LANG1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case V4L2_TUNER_MODE_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case MSP_MODE_FM_NICAM1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case MSP_MODE_FM_NICAM2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) case MSP_MODE_AM_NICAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) "NICAM set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (state->nicam_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) src = 0x0100; /* NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case MSP_MODE_BTSC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "BTSC set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case MSP_MODE_EXTERN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) "extern set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) src = 0x0200; /* SCART */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case MSP_MODE_FM_RADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "FM-Radio set_audmode: %s\n", modestr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dev_dbg_lvl(&client->dev, 1, msp_debug, "mono set_audmode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* switch audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) dev_dbg_lvl(&client->dev, 1, msp_debug, "set audmode %d\n", audmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) switch (audmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case V4L2_TUNER_MODE_STEREO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case V4L2_TUNER_MODE_LANG1_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) src |= 0x0020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case V4L2_TUNER_MODE_MONO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (state->mode == MSP_MODE_AM_NICAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_dbg_lvl(&client->dev, 1, msp_debug, "switching to AM mono\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* AM mono decoding is handled by tuner, not MSP chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* SCART switching control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) msp_set_scart(client, SCART_MONO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) src = 0x0200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) src = 0x0030;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case V4L2_TUNER_MODE_LANG1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case V4L2_TUNER_MODE_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) src |= 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "set_audmode final source/matrix = 0x%x\n", src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) msp_set_source(client, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static void msp3400c_print_mode(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (state->main == state->second)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) "mono sound carrier: %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) state->main / 910000, (state->main / 910) % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) "main sound carrier: %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) state->main / 910000, (state->main / 910) % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) "NICAM/FM carrier : %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) state->second / 910000, (state->second/910) % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (state->mode == MSP_MODE_AM_NICAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) "NICAM/AM carrier : %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) state->second / 910000, (state->second / 910) % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) "FM-stereo carrier : %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) state->second / 910000, (state->second / 910) % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int msp3400c_detect_stereo(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int rxsubchans = state->rxsubchans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int newnicam = state->nicam_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int update = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) switch (state->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case MSP_MODE_FM_TERRA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) val = msp_read_dsp(client, 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (val > 32767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) val -= 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dev_dbg_lvl(&client->dev, 2, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) "stereo detect register: %d\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (val > 8192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else if (val < -4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) newnicam = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case MSP_MODE_FM_NICAM1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) case MSP_MODE_FM_NICAM2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case MSP_MODE_AM_NICAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) val = msp_read_dem(client, 0x23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) dev_dbg_lvl(&client->dev, 2, msp_debug, "nicam sync=%d, mode=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) val & 1, (val & 0x1e) >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (val & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* nicam synced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) switch ((val & 0x1e) >> 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) newnicam = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) newnicam = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (rxsubchans != state->rxsubchans) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) "watch: rxsubchans %02x => %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) state->rxsubchans, rxsubchans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) state->rxsubchans = rxsubchans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (newnicam != state->nicam_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) dev_dbg_lvl(&client->dev, 1, msp_debug, "watch: nicam %d => %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) state->nicam_on, newnicam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) state->nicam_on = newnicam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * A kernel thread for msp3400 control -- we don't want to block the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * in the ioctl while doing the sound carrier & stereo detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* stereo/multilang monitoring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static void watch_stereo(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (msp_detect_stereo(client))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) msp_set_audmode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (msp_once)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) state->watch_stereo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int msp3400c_thread(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct i2c_client *client = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct msp3400c_carrier_detect *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int count, max1, max2, val1, val2, val, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3400 daemon started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) state->detected_std = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3400 thread: sleep\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) msp_sleep(state, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3400 thread: wakeup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) dev_dbg_lvl(&client->dev, 2, msp_debug, "thread: restart scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) state->restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (state->radio || MSP_MODE_EXTERN == state->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* no carrier scan, just unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) "thread: no carrier scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) state->scan_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* mute audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) state->scan_in_progress = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) val1 = val2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) max1 = max2 = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) state->watch_stereo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) state->nicam_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* wait for tuner to settle down after a channel change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (msp_sleep(state, 200))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* carrier detect pass #1 -- main carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) cd = msp3400c_carrier_detect_main;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) count = ARRAY_SIZE(msp3400c_carrier_detect_main);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* autodetect doesn't work well with AM ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) max1 = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dev_dbg_lvl(&client->dev, 1, msp_debug, "AM sound override\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (msp_sleep(state, 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) val = msp_read_dsp(client, 0x1b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (val > 32767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) val -= 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (val1 < val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) val1 = val, max1 = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) "carrier1 val: %5d / %s\n", val, cd[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* carrier detect pass #2 -- second (stereo) carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) switch (max1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case 1: /* 5.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) cd = msp3400c_carrier_detect_55;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) count = ARRAY_SIZE(msp3400c_carrier_detect_55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) case 3: /* 6.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cd = msp3400c_carrier_detect_65;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) count = ARRAY_SIZE(msp3400c_carrier_detect_65);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case 0: /* 4.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case 2: /* 6.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) cd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* autodetect doesn't work well with AM ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) cd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) max2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (msp_sleep(state, 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) val = msp_read_dsp(client, 0x1b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (val > 32767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) val -= 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (val2 < val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) val2 = val, max2 = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) "carrier2 val: %5d / %s\n", val, cd[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* program the msp3400 according to the results */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) state->main = msp3400c_carrier_detect_main[max1].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) switch (max1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case 1: /* 5.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (max2 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* B/G FM-stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) state->second = msp3400c_carrier_detect_55[max2].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else if (max2 == 1 && state->has_nicam) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* B/G NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) state->second = msp3400c_carrier_detect_55[max2].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) state->nicam_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) goto no_second;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case 2: /* 6.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* PAL I NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) state->detected_std = V4L2_STD_PAL_I;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) state->second = MSP_CARRIER(6.552);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) state->nicam_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) case 3: /* 6.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (max2 == 1 || max2 == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* D/K FM-stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) state->second = msp3400c_carrier_detect_65[max2].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) state->detected_std = V4L2_STD_DK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* L NICAM or AM-mono */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) state->second = msp3400c_carrier_detect_65[max2].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) state->detected_std = V4L2_STD_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) } else if (max2 == 0 && state->has_nicam) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* D/K NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) state->second = msp3400c_carrier_detect_65[max2].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) state->nicam_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) state->detected_std = V4L2_STD_DK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) goto no_second;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case 0: /* 4.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) state->detected_std = V4L2_STD_MN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) no_second:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) state->second = msp3400c_carrier_detect_main[max1].cdo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) msp3400c_set_carrier(client, state->second, state->main);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /* unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) state->scan_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) msp3400c_set_audmode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (msp_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) msp3400c_print_mode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* monitor tv audio mode, the first time don't wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) so long to get a quick stereo/bilingual result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) count = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) while (state->watch_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (msp_sleep(state, count ? 1000 : 5000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) watch_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int msp3410d_thread(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct i2c_client *client = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int val, i, std, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3410 daemon started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) state->detected_std = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3410 thread: sleep\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) msp_sleep(state, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3410 thread: wakeup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dev_dbg_lvl(&client->dev, 2, msp_debug, "thread: restart scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) state->restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (state->mode == MSP_MODE_EXTERN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* no carrier scan needed, just unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) "thread: no carrier scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) state->scan_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* mute audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) state->scan_in_progress = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* start autodetect. Note: autodetect is not supported for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) NTSC-M and radio, hence we force the standard in those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) cases. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (state->radio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) std = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) state->watch_stereo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) state->nicam_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* wait for tuner to settle down after a channel change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (msp_sleep(state, 200))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (msp_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dev_dbg_lvl(&client->dev, 2, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) "setting standard: %s (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) msp_standard_std_name(std), std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (std != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* programmed some specific mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) val = std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* triggered autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) msp_write_dem(client, 0x20, std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (msp_sleep(state, 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* check results */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) val = msp_read_dem(client, 0x7e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (val < 0x07ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) dev_dbg_lvl(&client->dev, 2, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) "detection still in progress\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) for (i = 0; msp_stdlist[i].name != NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (msp_stdlist[i].retval == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) dev_dbg_lvl(&client->dev, 1, msp_debug, "current standard: %s (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) msp_standard_std_name(val), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) state->main = msp_stdlist[i].main;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) state->second = msp_stdlist[i].second;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) state->std = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) state->rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (msp_amsound && !state->radio &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) (state->v4l2_std & V4L2_STD_SECAM) && (val != 0x0009)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* autodetection has failed, let backup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) dev_dbg_lvl(&client->dev, 1, msp_debug, "autodetection failed, switching to backup standard: %s (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) msp_stdlist[8].name ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) msp_stdlist[8].name : "unknown", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) state->std = val = 0x0009;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) msp_write_dem(client, 0x20, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) state->detected_std = msp_standard_std(state->std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* set stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case 0x0008: /* B/G NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case 0x000a: /* I NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case 0x000b: /* D/K NICAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (val == 0x000a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) state->mode = MSP_MODE_FM_NICAM2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) state->mode = MSP_MODE_FM_NICAM1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* just turn on stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) state->nicam_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) case 0x0009:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) state->mode = MSP_MODE_AM_NICAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) state->nicam_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case 0x0020: /* BTSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* The pre-'G' models only have BTSC-mono */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) state->mode = MSP_MODE_BTSC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) case 0x0040: /* FM radio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) state->mode = MSP_MODE_FM_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) state->rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* not needed in theory if we have radio, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) short programming enables carrier mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) msp3400c_set_carrier(client, MSP_CARRIER(10.7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) MSP_CARRIER(10.7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case 0x0002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case 0x0003:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) case 0x0004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case 0x0005:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) state->mode = MSP_MODE_FM_TERRA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* set various prescales */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) msp_write_dsp(client, 0x0d, 0x1900); /* scart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) msp_write_dsp(client, 0x0e, 0x3000); /* FM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (state->has_nicam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (state->has_i2s_conf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) msp_write_dem(client, 0x40, state->i2s_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) msp3400c_set_audmode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) state->scan_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* monitor tv audio mode, the first time don't wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) so long to get a quick stereo/bilingual result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) count = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) while (state->watch_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (msp_sleep(state, count ? 1000 : 5000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) watch_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* msp34xxG + (autoselect no-thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * this one uses both automatic standard detection and automatic sound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * select which are available in the newer G versions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * struct msp: only norm, acb and source are really used in this mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int msp34xxg_modus(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (state->radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) dev_dbg_lvl(&client->dev, 1, msp_debug, "selected radio modus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (EIA-J) modus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return 0x4001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (A2) modus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (state->v4l2_std == V4L2_STD_SECAM_L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) dev_dbg_lvl(&client->dev, 1, msp_debug, "selected SECAM-L modus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0x6001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (state->v4l2_std & V4L2_STD_MN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (BTSC) modus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return 0x2001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return 0x7001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int source, matrix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) switch (state->audmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case V4L2_TUNER_MODE_MONO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) source = 0; /* mono only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) matrix = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) case V4L2_TUNER_MODE_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) source = 4; /* stereo or B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) matrix = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) case V4L2_TUNER_MODE_LANG1_LANG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) source = 1; /* stereo or A|B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) matrix = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case V4L2_TUNER_MODE_LANG1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) source = 3; /* stereo or A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) matrix = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case V4L2_TUNER_MODE_STEREO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) source = 3; /* stereo or A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) matrix = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (in == MSP_DSP_IN_TUNER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) source = (source << 8) | 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) instead of 11, 12, 13. So we add one for that msp version. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) source = ((in + 1) << 8) | matrix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) source = (in << 8) | matrix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) "set source to %d (0x%x) for output %02x\n", in, source, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) msp_write_dsp(client, reg, source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static void msp34xxg_set_sources(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) u32 in = state->route_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (state->has_scart2_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* (re-)initialize the msp34xxg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static void msp34xxg_reset(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) int tuner = (state->route_in >> 3) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int modus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* initialize std to 1 (autodetect) to signal that no standard is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) selected yet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) state->std = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) msp_reset(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (state->has_i2s_conf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) msp_write_dem(client, 0x40, state->i2s_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /* step-by-step initialisation, as described in the manual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) modus = msp34xxg_modus(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) modus |= tuner ? 0x100 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) msp_write_dem(client, 0x30, modus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* write the dsps that may have an influence on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) standard/audio autodetection right now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) msp34xxg_set_sources(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) msp_write_dsp(client, 0x0d, 0x1900); /* scart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) msp_write_dsp(client, 0x0e, 0x3000); /* FM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (state->has_nicam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* set identification threshold. Personally, I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * I set it to a higher value than the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * of 0x190 to ignore noisy stereo signals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * this needs tuning. (recommended range 0x00a0-0x03c0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * 0x7f0 = forced mono mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * a2 threshold for stereo/bilingual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * Note: this register is part of the Manual/Compatibility mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * It is supported by all 'G'-family chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) msp_write_dem(client, 0x22, msp_stereo_thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int msp34xxg_thread(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct i2c_client *client = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) int val, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) dev_dbg_lvl(&client->dev, 1, msp_debug, "msp34xxg daemon started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) state->detected_std = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp34xxg thread: sleep\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) msp_sleep(state, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dev_dbg_lvl(&client->dev, 2, msp_debug, "msp34xxg thread: wakeup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: restart scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) state->restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (state->mode == MSP_MODE_EXTERN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /* no carrier scan needed, just unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) "thread: no carrier scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) state->scan_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /* setup the chip*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) msp34xxg_reset(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) state->std = state->radio ? 0x40 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) (state->force_btsc && msp_standard == 1) ? 32 : msp_standard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) msp_write_dem(client, 0x20, state->std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /* start autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (state->std != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) goto unmute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /* watch autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) "started autodetect, waiting for result\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) for (i = 0; i < 10; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (msp_sleep(state, 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /* check results */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) val = msp_read_dem(client, 0x7e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (val < 0x07ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) state->std = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) dev_dbg_lvl(&client->dev, 2, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) "detection still in progress\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (state->std == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) "detection still in progress after 10 tries. giving up.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) unmute:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) "detected standard: %s (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) msp_standard_std_name(state->std), state->std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) state->detected_std = msp_standard_std(state->std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (state->std == 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /* AM NICAM mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) msp_write_dsp(client, 0x0e, 0x7c00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /* unmute: dispatch sound to scart output, set scart volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) msp_update_volume(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* restore ACB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (msp_write_dsp(client, 0x13, state->acb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* the periodic stereo/SAP check is only relevant for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) the 0x20 standard (BTSC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (state->std != 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) state->watch_stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /* monitor tv audio mode, the first time don't wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) in order to get a quick stereo/SAP update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) watch_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) while (state->watch_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) watch_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (msp_sleep(state, 5000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static int msp34xxg_detect_stereo(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) int status = msp_read_dem(client, 0x0200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) int is_bilingual = status & 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) int is_stereo = status & 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) int oldrx = state->rxsubchans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (state->mode == MSP_MODE_EXTERN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) state->rxsubchans = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (is_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) state->rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) state->rxsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (is_bilingual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (state->std == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) state->rxsubchans |= V4L2_TUNER_SUB_SAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) state->rxsubchans =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) dev_dbg_lvl(&client->dev, 1, msp_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) status, is_stereo, is_bilingual, state->rxsubchans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return (oldrx != state->rxsubchans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static void msp34xxg_set_audmode(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (state->std == 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) state->audmode == V4L2_TUNER_MODE_LANG2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) msp_write_dem(client, 0x20, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) msp_write_dem(client, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) msp34xxg_set_sources(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) void msp_set_audmode(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) switch (state->opmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) case OPMODE_MANUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) case OPMODE_AUTODETECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) msp3400c_set_audmode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) case OPMODE_AUTOSELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) msp34xxg_set_audmode(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int msp_detect_stereo(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct msp_state *state = to_state(i2c_get_clientdata(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) switch (state->opmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case OPMODE_MANUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) case OPMODE_AUTODETECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return msp3400c_detect_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) case OPMODE_AUTOSELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return msp34xxg_detect_stereo(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)