1 /******************************************************************************
5 / Description: Philips Desktop TV Tuners interface.
7 / Copyright 2001, Carlos Hasan
9 *******************************************************************************/
14 enum tuner_control_bits
{
15 CHANGE_PUMP
= 0x40, /* change pump settings */
16 CHANGE_PUMP_FAST
= 0x00, /* for fast tuning */
17 CHANGE_PUMP_SLOW
= 0x40, /* for moderate speed tuning */
19 TEST_MODE
= 0x38, /* test mode settings */
20 TEST_MODE_NORMAL
= 0x08, /* for normal operation */
22 RATIO_SELECT
= 0x06, /* ratio select */
23 RATIO_SELECT_FAST
= 0x00, /* fast picture search */
24 RATIO_SELECT_SLOW
= 0x02, /* slow picture search */
25 RATIO_SELECT_NORMAL
= 0x06, /* normal picture search */
27 OS_MODE
= 0x01, /* PLL disabling */
28 OS_MODE_NORMAL
= 0x00, /* for normal operation */
29 OS_MODE_SWITCH
= 0x01 /* change pump to high impedance */
32 enum tuner_status_bits
{
33 STB_POR
= 0x80, /* power on reset */
34 STB_FL
= 0x40, /* in-lock flag */
35 STB_INF
= 0x38, /* digital information */
36 STB_ADC
= 0x07 /* A/D converter */
39 /*****************************************************************************
41 / Tuner Parameters and Frequencies for TV Antenna and Cable Channels
43 ******************************************************************************/
45 static const int kBandsPerTuner
= 5;
52 float minFrequency
, maxFrequency
;
53 } bands
[kBandsPerTuner
];
55 /* Philips FI1236 NTSC M/N */
56 { C_TUNER_FI1236
, "FI1236 NTSC",
57 { { 0xa2, 54.00, 157.25 },
58 { 0x94, 162.00, 451.25 },
59 { 0x34, 451.25, 463.25 },
60 { 0x31, 463.25, 801.25 },
61 { 0x00, 0.00, 0.00 } } },
63 /* Philips FI1236J NTSC Japan */
64 { C_TUNER_FI1236J
, "FI1236J NTSC Japan",
65 { { 0xa2, 54.00, 157.25 },
66 { 0x94, 162.00, 451.25 },
67 { 0x34, 451.25, 463.25 },
68 { 0x31, 463.25, 801.25 },
69 { 0x00, 0.00, 0.00 } } },
71 /* Philips FI1236MK2 NTSC M/N */
72 { C_TUNER_FI1236MK2
, "FI1236MK2 NTSC",
73 { { 0xa0, 55.25, 160.00 },
74 { 0x90, 160.00, 454.00 },
75 { 0x30, 454.00, 855.25 },
77 { 0x00, 0.00, 0.00 } } },
79 /* Philips FI1216 PAL B/G */
80 { C_TUNER_FI1216
, "FI1216 PAL",
81 { { 0xa2, 45.00, 140.25 },
82 { 0xa4, 140.25, 168.25 },
83 { 0x94, 168.25, 447.25 },
84 { 0x34, 447.25, 463.25 },
85 { 0x31, 463.25, 855.25 } } },
87 /* Philips FI1216MK2 PAL B/G */
88 { C_TUNER_FI1216MK2
, "FI1216MK2 PAL",
89 { { 0xa0, 48.25, 170.00 },
90 { 0x90, 170.00, 450.00 },
91 { 0x30, 450.00, 855.25 },
93 { 0x00, 0.00, 0.00 } } },
95 /* Philips FI1216MF PAL B/G, SECAM L/L' */
96 { C_TUNER_FI1216MF
, "FI1216MF PAL/SECAM",
97 { { 0xa1, 45.00, 168.25 },
98 { 0x91, 168.25, 447.25 },
99 { 0x31, 447.25, 855.25 },
100 { 0x00, 0.00, 0.00 },
101 { 0x00, 0.00, 0.00 } } },
103 /* Philips FI1246 PAL I */
104 { C_TUNER_FI1246
, "FI1246 PAL I",
105 { { 0xa2, 45.00, 140.25 },
106 { 0xa4, 140.25, 168.25 },
107 { 0x94, 168.25, 447.25 },
108 { 0x34, 447.25, 463.25 },
109 { 0x31, 463.25, 855.25 } } },
111 /* Philips FI1256 SECAM D/K */
112 { C_TUNER_FI1256
, "FI1256 SECAM",
113 { { 0xa0, 48.25, 168.25 },
114 { 0x90, 175.25, 455.25 },
115 { 0x30, 463.25, 863.25 },
116 { 0x00, 0.00, 0.00 },
117 { 0x00, 0.00, 0.00 } } },
119 /* Temic FN5AL PAL I/B/G/DK, SECAM DK */
120 { C_TUNER_TEMIC_FN5AL_PAL
, "Temic FN5AL PAL",
121 { { 0xa2, 45.00, 140.25 },
122 { 0xa4, 140.25, 168.25 },
123 { 0x94, 168.25, 447.25 },
124 { 0x31, 447.25, 855.25 },
125 { 0x00, 0.00, 0.00 } } },
127 /* Temic FN5AL PAL I/B/G/DK, SECAM DK */
128 { C_TUNER_TEMIC_FN5AL_SECAM
, "Temic FN5AL SECAM",
129 { { 0xa0, 48.25, 168.25 },
130 { 0x90, 175.25, 455.25 },
131 { 0x30, 463.25, 863.25 },
132 { 0x00, 0.00, 0.00 },
133 { 0x00, 0.00, 0.00 } } } };
135 static const int kNumTuners
= sizeof(kTunerTable
) / sizeof(kTunerTable
[0]);
138 CTuner::CTuner(CI2CPort
& port
)
144 PRINT(("CTuner::CTuner()\n"));
146 if( fPort
.InitCheck() == B_OK
) {
147 radeon_video_tuner tuner
;
148 radeon_video_decoder video
;
149 radeon_video_clock clock
;
152 fPort
.Radeon().GetMMParameters(tuner
, video
, clock
, dummy
, dummy
, dummy
);
154 case C_RADEON_NO_TUNER
:
155 fType
= C_TUNER_NONE
;
157 case C_RADEON_FI1236_MK1_NTSC
:
158 fType
= C_TUNER_FI1236
;
160 case C_RADEON_FI1236_MK2_NTSC_JAPAN
:
161 fType
= C_TUNER_FI1236J
;
163 case C_RADEON_FI1216_MK2_PAL_BG
:
164 fType
= C_TUNER_FI1216
;
166 case C_RADEON_FI1246_MK2_PAL_I
:
167 fType
= C_TUNER_FI1246
;
169 case C_RADEON_FI1216_MF_MK2_PAL_BG_SECAM_L
:
170 fType
= C_TUNER_FI1216MF
;
172 case C_RADEON_FI1236_MK2_NTSC
:
173 fType
= C_TUNER_FI1236MK2
;
175 case C_RADEON_FI1256_MK2_SECAM_DK
:
176 fType
= C_TUNER_FI1256
;
178 case C_RADEON_FI1216_MK2_PAL_BG_SECAM_L
:
179 fType
= C_TUNER_FI1216MK2
;
181 case C_RADEON_TEMIC_FN5AL_PAL_IBGDK_SECAM_DK
:
182 fType
= C_TUNER_TEMIC_FN5AL_PAL
;
185 fType
= C_TUNER_FI1236
;
189 for (fAddress
= 0xc0; fAddress
<= 0xc6; fAddress
+= 0x02) {
190 if (fPort
.Probe(fAddress
)) {
191 PRINT(("CTuner::CTuner() - TV Tuner found at I2C port 0x%02x\n", fAddress
));
196 if( InitCheck() != B_OK
)
197 PRINT(("CTuner::CTuner() - TV Tuner not found!\n"));
202 PRINT(("CTuner::~CTuner()\n"));
205 status_t
CTuner::InitCheck() const
207 return (fType
!= C_TUNER_NONE
&& fAddress
>= 0xc0 && fAddress
<= 0xc6) ?
211 bool CTuner::SetFrequency(float frequency
, float picture
)
213 //PRINT(("CTuner::SetFrequency(%g, %g)\n", frequency, picture));
215 for (int index
= 0; index
< kNumTuners
; index
++) {
216 if (kTunerTable
[index
].brand
== fType
) {
217 for (int band
= 0; band
< kBandsPerTuner
; band
++) {
218 if (frequency
>= kTunerTable
[index
].bands
[band
].minFrequency
&&
219 frequency
<= kTunerTable
[index
].bands
[band
].maxFrequency
) {
221 (int) (16.0 * (frequency
+ picture
)),
222 CHANGE_PUMP_FAST
| RATIO_SELECT_NORMAL
|
223 TEST_MODE_NORMAL
| OS_MODE_NORMAL
,
224 kTunerTable
[index
].bands
[band
].pll
|
225 ((Status() & STB_INF
) >> 3));
234 bool CTuner::SweepFrequency(float frequency
, float picture
)
236 PRINT(("CTuner::SweepFrequency(%g, %g)\n", frequency
, picture
));
238 float centerFrequency
= frequency
;
242 SetFrequency(frequency
, picture
);
243 for (int timeout
= 0; timeout
< 10; timeout
++) {
248 } while (ADC() == 0 &&
249 (frequency
-= 0.5000) > centerFrequency
- 3.000);
253 SetFrequency(frequency
, picture
);
254 for (int timeout
= 0; timeout
< 10; timeout
++) {
259 } while (ADC() != 0 &&
260 (frequency
+= 0.0625) < centerFrequency
+ 0.500);
265 const char * CTuner::Name() const
267 for (int index
= 0; index
< kNumTuners
; index
++) {
268 if (kTunerTable
[index
].brand
== fType
)
269 return kTunerTable
[index
].name
;
274 tuner_type
CTuner::Type() const
279 bool CTuner::HasSignal(void)
281 return (IsLocked() && ADC() <= 2);
284 int CTuner::Status(void)
287 fPort
.Read(fAddress
, buffer
, sizeof(buffer
));
288 return buffer
[0] & 0xff;
291 int CTuner::ADC(void)
293 return Status() & STB_ADC
;
296 bool CTuner::IsLocked(void)
298 return (Status() & STB_FL
) != 0;
301 void CTuner::SetParameters(int divider
, int control
, int band
)
305 if (divider
> fDivider
) {
306 buffer
[0] = (divider
>> 8) & 0x7f;
307 buffer
[1] = (divider
>> 0) & 0xff;
309 buffer
[2] = (control
| 0x80);
310 buffer
[3] = (band
& 0xff);
313 buffer
[0] = (control
| 0x80);
314 buffer
[1] = (band
& 0xff);
316 buffer
[2] = (divider
>> 8) & 0x7f;
317 buffer
[3] = (divider
>> 0) & 0xff;
322 fPort
.Write(fAddress
, buffer
, sizeof(buffer
));