^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, ®, 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");