Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <media/tuner.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "tuner-i2c.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "tda9887.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /* Chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)    TDA9885 (PAL, NTSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)    TDA9886 (PAL, SECAM, NTSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)    TDA9887 (PAL, SECAM, NTSC, FM Radio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)    Used as part of several tuners
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) MODULE_PARM_DESC(debug, "enable verbose debug messages");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static DEFINE_MUTEX(tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static LIST_HEAD(hybrid_tuner_instance_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) struct tda9887_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct tuner_i2c_props i2c_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	struct list_head hybrid_tuner_instance_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	unsigned char	   data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	unsigned int       config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	unsigned int       mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	unsigned int       audmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	v4l2_std_id        std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	bool               standby;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* ---------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define UNSET       (-1U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) struct tvnorm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	v4l2_std_id       std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	char              *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned char     b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	unsigned char     c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	unsigned char     e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) /* ---------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) // TDA defines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) //// first reg (b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define cVideoTrapBypassOFF     0x00    // bit b0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #define cVideoTrapBypassON      0x01    // bit b0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define cAutoMuteFmInactive     0x00    // bit b1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define cAutoMuteFmActive       0x02    // bit b1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define cIntercarrier           0x00    // bit b2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define cQSS                    0x04    // bit b2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) #define cPositiveAmTV           0x00    // bit b3:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #define cFmRadio                0x08    // bit b3:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #define cNegativeFmTV           0x10    // bit b3:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define cForcedMuteAudioON      0x20    // bit b5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #define cForcedMuteAudioOFF     0x00    // bit b5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #define cOutputPort1Active      0x00    // bit b6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define cOutputPort1Inactive    0x40    // bit b6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #define cOutputPort2Active      0x00    // bit b7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) #define cOutputPort2Inactive    0x80    // bit b7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) //// second reg (c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) #define cDeemphasisOFF          0x00    // bit c5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #define cDeemphasisON           0x20    // bit c5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define cDeemphasis75           0x00    // bit c6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define cDeemphasis50           0x40    // bit c6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define cAudioGain0             0x00    // bit c7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define cAudioGain6             0x80    // bit c7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define cTopMask                0x1f    // bit c0:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #define cTopDefault		0x10	// bit c0:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) //// third reg (e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define cAudioIF_4_5             0x00    // bit e0:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define cAudioIF_5_5             0x01    // bit e0:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define cAudioIF_6_0             0x02    // bit e0:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define cAudioIF_6_5             0x03    // bit e0:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define cVideoIFMask		0x1c	// bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Video IF selection in TV Mode (bit B3=0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define cVideoIF_58_75           0x00    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define cVideoIF_45_75           0x04    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define cVideoIF_38_90           0x08    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define cVideoIF_38_00           0x0C    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define cVideoIF_33_90           0x10    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define cVideoIF_33_40           0x14    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define cRadioIF_45_75           0x18    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define cRadioIF_38_90           0x1C    // bit e2:4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* IF1 selection in Radio Mode (bit B3=1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define cRadioIF_33_30		0x00	// bit e2,4 (also 0x10,0x14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define cRadioIF_41_30		0x04	// bit e2,4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Output of AFC pin in radio mode when bit E7=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define cRadioAGC_SIF		0x00	// bit e3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define cRadioAGC_FM		0x08	// bit e3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define cTunerGainNormal         0x00    // bit e5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define cTunerGainLow            0x20    // bit e5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define cGating_18               0x00    // bit e6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define cGating_36               0x40    // bit e6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define cAgcOutON                0x80    // bit e7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define cAgcOutOFF               0x00    // bit e7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^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 tvnorm tvnorms[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		.std   = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		.name  = "PAL-BGHN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			   cDeemphasis50  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			   cAudioIF_5_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		.std   = V4L2_STD_PAL_I,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		.name  = "PAL-I",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			   cDeemphasis50  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			   cAudioIF_6_0   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		.std   = V4L2_STD_PAL_DK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		.name  = "PAL-DK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			   cDeemphasis50  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			   cAudioIF_6_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		.std   = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		.name  = "PAL-M/Nc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			   cDeemphasis75  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			   cAudioIF_4_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			   cVideoIF_45_75 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		.std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		.name  = "SECAM-BGH",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		.c     = ( cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		.e     = ( cAudioIF_5_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		.std   = V4L2_STD_SECAM_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.name  = "SECAM-L",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		.b     = ( cPositiveAmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		.c     = ( cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.e     = ( cGating_36	  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			   cAudioIF_6_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		.std   = V4L2_STD_SECAM_LC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		.name  = "SECAM-L'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		.b     = ( cOutputPort2Inactive |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			   cPositiveAmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		.c     = ( cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		.e     = ( cGating_36	  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			   cAudioIF_6_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			   cVideoIF_33_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		.std   = V4L2_STD_SECAM_DK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		.name  = "SECAM-DK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			   cDeemphasis50  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			   cAudioIF_6_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			   cVideoIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		.std   = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.name  = "NTSC-M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			   cDeemphasis75  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			   cAudioIF_4_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			   cVideoIF_45_75 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	},{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		.std   = V4L2_STD_NTSC_M_JP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		.name  = "NTSC-M-JP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		.b     = ( cNegativeFmTV  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			   cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		.c     = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			   cDeemphasis50  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			   cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		.e     = ( cGating_36     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			   cAudioIF_4_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			   cVideoIF_58_75 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static struct tvnorm radio_stereo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	.name = "Radio Stereo",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	.b    = ( cFmRadio       |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		  cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	.c    = ( cDeemphasisOFF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		  cAudioGain6    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		  cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	.e    = ( cTunerGainLow  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		  cAudioIF_5_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		  cRadioIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static struct tvnorm radio_mono = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	.name = "Radio Mono",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	.b    = ( cFmRadio       |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		  cQSS           ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	.c    = ( cDeemphasisON  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		  cDeemphasis75  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		  cTopDefault),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	.e    = ( cTunerGainLow  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		  cAudioIF_5_5   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		  cRadioIF_38_90 ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* ---------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	static char *afc[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		"- 12.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		"- 37.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		"- 62.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		"- 87.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		"-112.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		"-137.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		"-162.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		"-187.5 kHz [min]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		"+187.5 kHz [max]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		"+162.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		"+137.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		"+112.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		"+ 87.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		"+ 62.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		"+ 37.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		"+ 12.5 kHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	tuner_info("read: 0x%2x\n", buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	tuner_info("  after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	tuner_info("  afc            : %s\n", afc[(buf[0] >> 1) & 0x0f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	tuner_info("  fmif level     : %s\n", (buf[0] & 0x20) ? "high" : "low");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	tuner_info("  afc window     : %s\n", (buf[0] & 0x40) ? "in" : "out");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	tuner_info("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	static char *sound[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		"AM/TV",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		"FM/radio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		"FM/TV",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		"FM/radio"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	static char *adjust[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		"-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		"-8",  "-7",  "-6",  "-5",  "-4",  "-3",  "-2",  "-1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		"0",   "+1",  "+2",  "+3",  "+4",  "+5",  "+6",  "+7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		"+8",  "+9",  "+10", "+11", "+12", "+13", "+14", "+15"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	static char *deemph[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		"no", "no", "75", "50"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	static char *carrier[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		"4.5 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		"5.5 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		"6.0 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		"6.5 MHz / AM"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	static char *vif[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		"58.75 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		"45.75 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		"38.9 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		"38.0 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		"33.9 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		"33.4 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		"45.75 MHz + pin13",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		"38.9 MHz + pin13",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	static char *rif[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		"44 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		"52 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		"52 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		"44 MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	tuner_info("write: byte B 0x%02x\n", buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	tuner_info("  B0   video mode      : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		   (buf[1] & 0x01) ? "video trap" : "sound trap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	tuner_info("  B1   auto mute fm    : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		   (buf[1] & 0x02) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	tuner_info("  B2   carrier mode    : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		   (buf[1] & 0x04) ? "QSS" : "Intercarrier");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	tuner_info("  B3-4 tv sound/radio  : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		   sound[(buf[1] & 0x18) >> 3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	tuner_info("  B5   force mute audio: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		   (buf[1] & 0x20) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	tuner_info("  B6   output port 1   : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		   (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	tuner_info("  B7   output port 2   : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		   (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	tuner_info("write: byte C 0x%02x\n", buf[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	tuner_info("  C0-4 top adjustment  : %s dB\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		   adjust[buf[2] & 0x1f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	tuner_info("  C5-6 de-emphasis     : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		   deemph[(buf[2] & 0x60) >> 5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	tuner_info("  C7   audio gain      : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		   (buf[2] & 0x80) ? "-6" : "0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	tuner_info("write: byte E 0x%02x\n", buf[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	tuner_info("  E0-1 sound carrier   : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		   carrier[(buf[3] & 0x03)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	tuner_info("  E6   l pll gating   : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		   (buf[3] & 0x40) ? "36" : "13");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (buf[1] & 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		/* radio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		tuner_info("  E2-4 video if        : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			   rif[(buf[3] & 0x0c) >> 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		tuner_info("  E7   vif agc output  : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 			   (buf[3] & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 			   ? ((buf[3] & 0x10) ? "fm-agc radio" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 						"sif-agc radio")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			   : "fm radio carrier afc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		/* video */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		tuner_info("  E2-4 video if        : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 			   vif[(buf[3] & 0x1c) >> 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		tuner_info("  E5   tuner gain      : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 			   (buf[3] & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 			   ? ((buf[3] & 0x20) ? "external" : "normal")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			   : ((buf[3] & 0x20) ? "minimum"  : "normal"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		tuner_info("  E7   vif agc output  : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			   (buf[3] & 0x80) ? ((buf[3] & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				? "pin3 port, pin22 vif agc out"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 				: "pin22 port, pin3 vif acg ext in")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 				: "pin3+pin22 port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	tuner_info("--\n");
^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 tda9887_set_tvnorm(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	struct tvnorm *norm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	char *buf = priv->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	if (priv->mode == V4L2_TUNER_RADIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		if (priv->audmode == V4L2_TUNER_MODE_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 			norm = &radio_mono;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 			norm = &radio_stereo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			if (tvnorms[i].std & priv->std) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				norm = tvnorms+i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	if (NULL == norm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		tuner_dbg("Unsupported tvnorm entry - audio muted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	tuner_dbg("configure for: %s\n", norm->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	buf[1] = norm->b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	buf[2] = norm->c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	buf[3] = norm->e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static unsigned int port1  = UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static unsigned int port2  = UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static unsigned int qss    = UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static unsigned int adjust = UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) module_param(port1, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) module_param(port2, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) module_param(qss, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) module_param(adjust, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int tda9887_set_insmod(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	char *buf = priv->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	if (UNSET != port1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		if (port1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			buf[1] |= cOutputPort1Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 			buf[1] &= ~cOutputPort1Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	if (UNSET != port2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		if (port2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			buf[1] |= cOutputPort2Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 			buf[1] &= ~cOutputPort2Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	if (UNSET != qss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		if (qss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			buf[1] |= cQSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			buf[1] &= ~cQSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	if (adjust < 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		buf[2] &= ~cTopMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		buf[2] |= adjust;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	return 0;
^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) static int tda9887_do_config(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	char *buf = priv->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	if (priv->config & TDA9887_PORT1_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		buf[1] &= ~cOutputPort1Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	if (priv->config & TDA9887_PORT1_INACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		buf[1] |= cOutputPort1Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (priv->config & TDA9887_PORT2_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		buf[1] &= ~cOutputPort2Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	if (priv->config & TDA9887_PORT2_INACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		buf[1] |= cOutputPort2Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	if (priv->config & TDA9887_QSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		buf[1] |= cQSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	if (priv->config & TDA9887_INTERCARRIER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		buf[1] &= ~cQSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (priv->config & TDA9887_AUTOMUTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		buf[1] |= cAutoMuteFmActive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	if (priv->config & TDA9887_DEEMPHASIS_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		buf[2] &= ~0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		case TDA9887_DEEMPHASIS_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 			buf[2] |= cDeemphasisOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		case TDA9887_DEEMPHASIS_50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			buf[2] |= cDeemphasisON | cDeemphasis50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		case TDA9887_DEEMPHASIS_75:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			buf[2] |= cDeemphasisON | cDeemphasis75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (priv->config & TDA9887_TOP_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		buf[2] &= ~cTopMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		buf[2] |= (priv->config >> 8) & cTopMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	    (priv->std & V4L2_STD_NTSC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		buf[1] &= ~cQSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	if (priv->config & TDA9887_GATING_18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		buf[3] &= ~cGating_36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (priv->mode == V4L2_TUNER_RADIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		if (priv->config & TDA9887_RIF_41_3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 			buf[3] &= ~cVideoIFMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 			buf[3] |= cRadioIF_41_30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		if (priv->config & TDA9887_GAIN_NORMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 			buf[3] &= ~cTunerGainLow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /* ---------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static int tda9887_status(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	unsigned char buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	if (rc != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	dump_read_message(fe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static void tda9887_configure(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	memset(priv->data,0,sizeof(priv->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	tda9887_set_tvnorm(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	/* A note on the port settings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	   These settings tend to depend on the specifics of the board.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	   By default they are set to inactive (bit value 1) by this driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	   overwriting any changes made by the tvnorm. This means that it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	   is the responsibility of the module using the tda9887 to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	   these values in case of changes in the tvnorm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	   In many cases port 2 should be made active (0) when selecting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	   SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	   For the other standards the tda9887 application note says that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	   the ports should be set to active (0), but, again, that may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	   differ depending on the precise hardware configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	priv->data[1] |= cOutputPort1Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	priv->data[1] |= cOutputPort2Inactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	tda9887_do_config(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	tda9887_set_insmod(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (priv->standby)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		priv->data[1] |= cForcedMuteAudioON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		  priv->data[1], priv->data[2], priv->data[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		dump_write_message(fe, priv->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	if (debug > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		msleep_interruptible(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		tda9887_status(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* ---------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static void tda9887_tuner_status(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		   priv->data[1], priv->data[2], priv->data[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static int tda9887_get_afc(struct dvb_frontend *fe, s32 *afc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	static const int AFC_BITS_2_kHz[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		-12500,  -37500,  -62500,  -97500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 		-112500, -137500, -162500, -187500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 		187500,  162500,  137500,  112500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		97500 ,  62500,   37500 ,  12500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	__u8 reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	if (priv->mode != V4L2_TUNER_RADIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, &reg, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		*afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static void tda9887_standby(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	priv->standby = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	tda9887_configure(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static void tda9887_set_params(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 			       struct analog_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	priv->standby = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	priv->mode    = params->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	priv->audmode = params->audmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	priv->std     = params->std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	tda9887_configure(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	priv->config = *(unsigned int *)priv_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	tda9887_configure(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static void tda9887_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	struct tda9887_priv *priv = fe->analog_demod_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	mutex_lock(&tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	if (priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 		hybrid_tuner_release_state(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	mutex_unlock(&tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	fe->analog_demod_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static const struct analog_demod_ops tda9887_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	.info		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		.name	= "tda9887",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	.set_params     = tda9887_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	.standby        = tda9887_standby,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	.tuner_status   = tda9887_tuner_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	.get_afc        = tda9887_get_afc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	.release        = tda9887_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	.set_config     = tda9887_set_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 				    struct i2c_adapter *i2c_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 				    u8 i2c_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	struct tda9887_priv *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	int instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	mutex_lock(&tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 					      hybrid_tuner_instance_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 					      i2c_adap, i2c_addr, "tda9887");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	switch (instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		mutex_unlock(&tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 		fe->analog_demod_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		priv->standby = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 		tuner_info("tda988[5/6/7] found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		fe->analog_demod_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	mutex_unlock(&tda9887_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	memcpy(&fe->ops.analog_ops, &tda9887_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	       sizeof(struct analog_demod_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) EXPORT_SYMBOL_GPL(tda9887_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) MODULE_LICENSE("GPL");