0
|
1 /* pt1-tuner.c: A PT1 on Tuner driver for Linux. */
|
|
2
|
|
3 #include <linux/module.h>
|
|
4 #include <linux/kernel.h>
|
|
5 #include <linux/errno.h>
|
|
6 #include <linux/pci.h>
|
|
7 #include <linux/init.h>
|
|
8 #include <linux/interrupt.h>
|
|
9 #include <linux/mutex.h>
|
|
10
|
|
11 #include <asm/system.h>
|
|
12 #include <asm/io.h>
|
|
13 #include <asm/irq.h>
|
|
14 #include <asm/uaccess.h>
|
|
15
|
|
16 #include "pt1_com.h"
|
|
17 #include "pt1_pci.h"
|
|
18 #include "pt1_i2c.h"
|
|
19 #include "pt1_tuner.h"
|
|
20 #include "pt1_tuner_data.h"
|
|
21 /*
|
|
22 LNB : BIT 2 1
|
|
23 OFF : 0 0
|
|
24 +15V: 1 1
|
|
25 +11V: 1 0
|
|
26
|
|
27 TUNER: BIT 3 0
|
|
28 POWER-OFF : 0 0
|
|
29 POWER-ON RESET : 0 1
|
|
30 POWER-ON ONLY : 1 1
|
|
31 */
|
|
32 typedef struct _TUNER_INFO{
|
|
33 int isdb_s ;
|
|
34 int isdb_t ;
|
|
35 }TUNER_INFO;
|
|
36
|
|
37 TUNER_INFO tuner_info[2] = {
|
|
38 {T0_ISDB_S, T0_ISDB_T},
|
|
39 {T1_ISDB_S, T1_ISDB_T}
|
|
40 };
|
|
41
|
|
42 typedef struct _isdb_t_freq_add_table{
|
|
43 __u16 pos ; // 追加するチャンネルポジション
|
|
44 __u16 add_freq ; // 追加する値
|
|
45 }isdb_t_freq_add_table;
|
|
46
|
|
47 isdb_t_freq_add_table isdb_t_freq_add[10] = {
|
|
48 { 7, 0x8081}, // 0~7迄
|
|
49 { 12, 0x80A1}, // 8~12迄
|
|
50 { 21, 0x8062}, // 13~21迄
|
|
51 { 39, 0x80A2}, // 22~39迄
|
|
52 { 51, 0x80E2}, // 40~51迄
|
|
53 { 59, 0x8064}, // 52~59迄
|
|
54 { 75, 0x8084}, // 60~75迄
|
|
55 { 84, 0x80a4}, // 76~84迄
|
|
56 {100, 0x80C4}, // 85~100迄
|
|
57 {112, 0x80E4} // 101~112迄
|
|
58 };
|
|
59
|
|
60 void settuner_reset(void __iomem *regs, __u32 lnb, __u32 tuner)
|
|
61 {
|
|
62 __u32 val = 0;
|
|
63 switch(lnb){
|
|
64 case LNB_11V: val = (1 << BIT_LNB_DOWN); break ;
|
|
65 case LNB_15V: val = (1 << BIT_LNB_UP) | (1 << BIT_LNB_DOWN) ; break ;
|
|
66 }
|
|
67
|
|
68 switch(tuner){
|
|
69 case TUNER_POWER_ON_RESET_ENABLE: val |= (1 << BIT_TUNER) ; break ;
|
|
70 case TUNER_POWER_ON_RESET_DISABLE: val = (1 << BIT_TUNER) | (1 << BIT_RESET) ; break ;
|
|
71 }
|
|
72
|
|
73 writel(val, (regs + 4));
|
|
74 }
|
|
75 static int init_isdb_s(void __iomem *regs, struct mutex *lock, __u32 addr)
|
|
76 {
|
|
77
|
|
78 WBLOCK wk;
|
|
79 int lp ;
|
|
80 __u32 val ;
|
|
81
|
|
82 // ISDB-S/T初期化
|
|
83 memcpy(&wk, &com_initdata, sizeof(WBLOCK));
|
|
84
|
|
85 // 初期化1(なぜかREADなので)
|
|
86 memcpy(&wk, &isdb_s_init1, sizeof(WBLOCK));
|
|
87 wk.addr = addr;
|
|
88 val = i2c_read(regs, lock, &wk, 1);
|
|
89 if((val & 0xff) != 0x41){
|
|
90 printk(KERN_INFO "PT1:ISDB-S Read(%x)\n", val);
|
|
91 return -EIO ;
|
|
92 }
|
|
93 for(lp = 0 ; lp < MAX_ISDB_S_INIT ; lp++){
|
|
94 memcpy(&wk, isdb_s_initial[lp], sizeof(WBLOCK));
|
|
95 wk.addr = addr;
|
|
96 i2c_write(regs, lock, &wk);
|
|
97 }
|
|
98
|
|
99 return 0 ;
|
|
100 }
|
|
101 static void init_isdb_t(void __iomem *regs, struct mutex *lock, __u32 addr)
|
|
102 {
|
|
103 int lp ;
|
|
104 WBLOCK wk;
|
|
105
|
|
106 // ISDB-S/T初期化
|
|
107 for(lp = 0 ; lp < MAX_ISDB_T_INIT ; lp++){
|
|
108 memcpy(&wk, isdb_t_initial[lp], sizeof(WBLOCK));
|
|
109 wk.addr = addr;
|
|
110 i2c_write(regs, lock, &wk);
|
|
111 }
|
|
112
|
|
113
|
|
114 }
|
|
115 int tuner_init(void __iomem *regs, struct mutex *lock, int tuner_no)
|
|
116 {
|
|
117
|
|
118 int rc ;
|
|
119 WBLOCK wk;
|
|
120
|
|
121 // ISDB-S/T初期化
|
|
122 memcpy(&wk, &com_initdata, sizeof(WBLOCK));
|
|
123
|
|
124 // 初期化(共通)
|
|
125 wk.addr = tuner_info[tuner_no].isdb_t ;
|
|
126 i2c_write(regs, lock, &wk);
|
|
127 wk.addr = tuner_info[tuner_no].isdb_s ;
|
|
128 i2c_write(regs, lock, &wk);
|
|
129
|
|
130 rc = init_isdb_s(regs, lock, tuner_info[tuner_no].isdb_s);
|
|
131 if(rc < 0){
|
|
132 return rc ;
|
|
133 }
|
|
134 init_isdb_t(regs, lock, tuner_info[tuner_no].isdb_t);
|
|
135
|
|
136 memcpy(&wk, &isdb_s_init21, sizeof(WBLOCK));
|
|
137 wk.addr = tuner_info[tuner_no].isdb_s ;
|
|
138 i2c_write(regs, lock, &wk);
|
|
139
|
|
140 memcpy(&wk, &isdb_t_init17, sizeof(WBLOCK));
|
|
141 wk.addr = tuner_info[tuner_no].isdb_t ;
|
|
142 i2c_write(regs, lock, &wk);
|
|
143
|
|
144 return 0 ;
|
|
145 }
|
|
146 void set_sleepmode(void __iomem *regs, struct mutex *lock, int address, int tuner_type, int type)
|
|
147 {
|
|
148 WBLOCK wk;
|
|
149
|
|
150 if(type == TYPE_WAKEUP){
|
|
151 switch(tuner_type){
|
|
152 case CHANNEL_TYPE_ISDB_S:memcpy(&wk, &isdb_s_wake, sizeof(WBLOCK));break ;
|
|
153 case CHANNEL_TYPE_ISDB_T:memcpy(&wk, &isdb_t_wake, sizeof(WBLOCK));break ;
|
|
154 }
|
|
155 wk.addr = address ;
|
|
156 i2c_write(regs, lock, &wk);
|
|
157 }
|
|
158 switch(tuner_type){
|
|
159 case CHANNEL_TYPE_ISDB_S:
|
|
160 printk(KERN_INFO "PT1:ISDB-S Sleep\n");
|
|
161 memcpy(&wk, &isdb_s_sleep, sizeof(WBLOCK));
|
|
162 if(type == TYPE_WAKEUP){
|
|
163 wk.value[1] = 0x01 ;
|
|
164 }
|
|
165 break ;
|
|
166 case CHANNEL_TYPE_ISDB_T:
|
|
167 printk(KERN_INFO "PT1:ISDB-T Sleep\n");
|
|
168 memcpy(&wk, &isdb_t_sleep, sizeof(WBLOCK));
|
|
169 if(type == TYPE_WAKEUP){
|
|
170 wk.value[1] = 0x90 ;
|
|
171 }
|
|
172 break ;
|
|
173 }
|
|
174 wk.addr = address;
|
|
175 i2c_write(regs, lock, &wk);
|
|
176 }
|
|
177
|
|
178 int bs_frequency(void __iomem *regs, struct mutex *lock, int addr, int channel)
|
|
179 {
|
|
180 int lp ;
|
|
181 int tmcclock = FALSE ;
|
|
182 WBLOCK wk;
|
|
183 __u32 val ;
|
|
184
|
|
185 if(channel >= MAX_BS_CHANNEL){
|
|
186 return -EIO ;
|
|
187 }
|
|
188 // ISDB-S PLLロック
|
|
189 for(lp = 0 ; lp < MAX_BS_CHANNEL_PLL_COMMAND ; lp++){
|
|
190 memcpy(&wk, bs_pll[channel].wblock[lp], sizeof(WBLOCK));
|
|
191 wk.addr = addr ;
|
|
192 i2c_write(regs, lock, &wk);
|
|
193 }
|
|
194
|
|
195 // PLLロック確認
|
|
196 // チェック用
|
|
197 for(lp = 0 ; lp < 200 ; lp++){
|
|
198 memcpy(&wk, &bs_pll_lock, sizeof(WBLOCK));
|
|
199 wk.addr = addr;
|
|
200 val = i2c_read(regs, lock, &wk, 1);
|
|
201 if(((val & 0xFF) != 0) && ((val & 0XFF) != 0XFF)){
|
|
202 tmcclock = TRUE ;
|
|
203 break ;
|
|
204 }
|
|
205 }
|
|
206
|
|
207 if(tmcclock == FALSE){
|
|
208 printk(KERN_INFO "PLL LOCK ERROR\n");
|
|
209 return -EIO;
|
|
210 }
|
|
211
|
|
212 memcpy(&wk, &bs_tmcc_get_1, sizeof(WBLOCK));
|
|
213 wk.addr = addr;
|
|
214 i2c_write(regs, lock, &wk);
|
|
215
|
|
216 tmcclock = FALSE ;
|
|
217
|
|
218 for(lp = 0 ; lp < 200 ; lp++){
|
|
219 memcpy(&wk, &bs_tmcc_get_2, sizeof(WBLOCK));
|
|
220 wk.addr = addr;
|
|
221
|
|
222 val = i2c_read(regs, lock, &wk, 1);
|
|
223 if(((val & 0XFF) != 0XFF) && (!(val & 0x10))){
|
|
224 tmcclock = TRUE ;
|
|
225 break ;
|
|
226 }
|
|
227 }
|
|
228
|
|
229 if(tmcclock == FALSE){
|
|
230 printk(KERN_INFO "TMCC LOCK ERROR\n");
|
|
231 return -EIO;
|
|
232 }
|
|
233
|
|
234 return 0 ;
|
|
235 }
|
|
236 int ts_lock(void __iomem *regs, struct mutex *lock, int addr, __u16 ts_id)
|
|
237 {
|
|
238
|
|
239 int lp ;
|
|
240 WBLOCK wk;
|
|
241 __u32 val ;
|
|
242 union{
|
|
243 __u8 ts[2];
|
|
244 __u16 tsid;
|
|
245 }uts_id ;
|
|
246
|
|
247 uts_id.tsid = ts_id ;
|
|
248 memcpy(&wk, &bs_set_ts_lock, sizeof(WBLOCK));
|
|
249 wk.addr = addr;
|
|
250 // TS-ID設定
|
|
251 wk.value[1] = uts_id.ts[1];
|
|
252 wk.value[2] = uts_id.ts[0];
|
|
253 i2c_write(regs, lock, &wk);
|
|
254
|
|
255 for(lp = 0 ; lp < 100 ; lp++){
|
|
256 memcpy(&wk, &bs_get_ts_lock, sizeof(WBLOCK));
|
|
257 wk.addr = addr;
|
|
258 val = i2c_read(regs, lock, &wk, 2);
|
|
259 if((val & 0xFFFF) == ts_id){
|
|
260 return 0 ;
|
|
261 }
|
|
262 }
|
|
263 printk(KERN_INFO "PT1:ERROR TS-LOCK(%x)\n", ts_id);
|
|
264 return -EIO ;
|
|
265 }
|
|
266 int bs_tune(void __iomem *regs, struct mutex *lock, int addr, int channel, ISDB_S_TMCC *tmcc)
|
|
267 {
|
|
268
|
|
269 int lp ;
|
|
270 int lp2;
|
|
271 WBLOCK wk;
|
|
272 __u32 val ;
|
|
273 ISDB_S_TS_ID *tsid ;
|
|
274 union{
|
|
275 __u8 slot[4];
|
|
276 __u32 u32slot;
|
|
277 }ts_slot ;
|
|
278 union{
|
|
279 __u16 ts[2];
|
|
280 __u32 tsid;
|
|
281 }ts_id ;
|
|
282
|
|
283 if(channel >= MAX_BS_CHANNEL){
|
|
284 printk(KERN_INFO "Invalid Channel(%d)\n", channel);
|
|
285 return -EIO ;
|
|
286 }
|
|
287 val = bs_frequency(regs, lock, addr, channel);
|
|
288 if(val == -EIO){
|
|
289 return val ;
|
|
290 }
|
|
291
|
|
292 tsid = &tmcc->ts_id[0] ;
|
|
293 // 該当周波数のTS-IDを取得
|
|
294 for(lp = 0 ; lp < (MAX_BS_TS_ID / 2) ; lp++){
|
|
295 for(lp2 = 0 ; lp2 < 100 ; lp2++){
|
|
296 memcpy(&wk, bs_get_ts_id[lp], sizeof(WBLOCK));
|
|
297 wk.addr = addr;
|
|
298 ts_id.tsid = i2c_read(regs, lock, &wk, 4);
|
|
299 // TS-IDが0の場合は再取得する
|
|
300 if((ts_id.ts[0] != 0) && (ts_id.ts[1] != 0)){
|
|
301 break ;
|
|
302 }
|
|
303 }
|
|
304 tsid->ts_id = ts_id.ts[1] ;
|
|
305 tsid += 1;
|
|
306 tsid->ts_id = ts_id.ts[0] ;
|
|
307 tsid += 1;
|
|
308 }
|
|
309
|
|
310 memcpy(&wk, &bs_get_cn, sizeof(WBLOCK));
|
|
311 wk.addr = addr;
|
|
312 tmcc->cn[0] = i2c_read(regs, lock, &wk, 1);
|
|
313
|
|
314 memcpy(&wk, &bs_get_agc, sizeof(WBLOCK));
|
|
315 wk.addr = addr;
|
|
316 tmcc->cn[1] = i2c_read(regs, lock, &wk, 1);
|
|
317
|
|
318 memcpy(&wk, &bs_get_maxagc, sizeof(WBLOCK));
|
|
319 wk.addr = addr;
|
|
320 tmcc->agc = i2c_read(regs, lock, &wk, 1);
|
|
321
|
|
322 // TS-ID別の情報を取得
|
|
323 tsid = &tmcc->ts_id[0] ;
|
|
324 for(lp = 0 ; lp < MAX_BS_TS_ID ; lp++, tsid += 1){
|
|
325 // TS-IDなし=0XFFFF
|
|
326 if(tsid->ts_id == 0xFFFF){
|
|
327 continue ;
|
|
328 }
|
|
329 ts_lock(regs, lock, addr, tsid->ts_id);
|
|
330
|
|
331 //スロット取得
|
|
332 memcpy(&wk, &bs_get_slot, sizeof(WBLOCK));
|
|
333 wk.addr = addr;
|
|
334 ts_slot.u32slot = i2c_read(regs, lock, &wk, 3);
|
|
335 tsid->high_mode = 0;
|
|
336 tsid->low_slot = ts_slot.slot[0] ;
|
|
337 tsid->high_slot = ts_slot.slot[1] ;
|
|
338 tsid->low_mode = ts_slot.slot[2] ;
|
|
339 }
|
|
340
|
|
341 memcpy(&wk, &bs_get_clock, sizeof(WBLOCK));
|
|
342 wk.addr = addr;
|
|
343 tmcc->clockmargin = i2c_read(regs, lock, &wk, 1);
|
|
344
|
|
345 memcpy(&wk, &bs_get_carrir, sizeof(WBLOCK));
|
|
346 wk.addr = addr;
|
|
347 tmcc->carriermargin = i2c_read(regs, lock, &wk, 1);
|
|
348 return 0 ;
|
|
349 }
|
|
350 __u32 getfrequency_add(__u32 channel)
|
|
351 {
|
|
352 int lp ;
|
|
353
|
|
354 for(lp = 0 ; lp < 10 ; lp++){
|
|
355 if(channel <= isdb_t_freq_add[lp].pos){
|
|
356 return isdb_t_freq_add[lp].add_freq ;
|
|
357 }
|
|
358 }
|
|
359 return 0 ;
|
|
360 }
|
|
361 __u32 getfrequency(__u32 channel, int addfreq)
|
|
362 {
|
|
363 __u32 frequencyoffset = 0;
|
|
364 __u32 frequencyOffset = 0;
|
|
365
|
|
366 if (12 <= channel){
|
|
367 frequencyoffset += 2;
|
|
368 }else if (17 <= channel){
|
|
369 frequencyoffset = 0;
|
|
370 }else if (63 <= channel){
|
|
371 frequencyoffset += 2;
|
|
372 }
|
|
373 #if 0
|
|
374 return (((93 + channel * 6 + frequencyOffset) + addfreq) * 7) + 400;
|
|
375 #endif
|
|
376 frequencyOffset = 93 + channel * 6 + frequencyoffset;
|
|
377 frequencyOffset = 7 * (frequencyOffset + addfreq);
|
|
378 return frequencyOffset + 400;
|
|
379
|
|
380 }
|
|
381 int isdb_t_frequency(void __iomem *regs, struct mutex *lock, int addr, int channel, int addfreq)
|
|
382 {
|
|
383
|
|
384 int lp ;
|
|
385 WBLOCK wk;
|
|
386 __u32 val ;
|
|
387 int tmcclock = FALSE ;
|
|
388 union{
|
|
389 __u8 charfreq[2];
|
|
390 __u16 freq;
|
|
391 }freq[2] ;
|
|
392
|
|
393 if(channel >= MAX_ISDB_T_CHANNEL){
|
|
394 return -EIO ;
|
|
395 }
|
|
396
|
|
397 freq[0].freq = getfrequency(channel, addfreq);
|
|
398 freq[1].freq = getfrequency_add(channel);
|
|
399 //指定周波数
|
|
400 memcpy(&wk, &isdb_t_pll_base, sizeof(WBLOCK));
|
|
401 wk.addr = addr ;
|
|
402 // 計算した周波数を設定
|
|
403 wk.value[wk.count] = freq[0].charfreq[1];
|
|
404 wk.count += 1 ;
|
|
405 wk.value[wk.count] = freq[0].charfreq[0];
|
|
406 wk.count += 1 ;
|
|
407
|
|
408 // 計算した周波数付加情報を設定
|
|
409 wk.value[wk.count] = freq[1].charfreq[1];
|
|
410 wk.count += 1 ;
|
|
411 wk.value[wk.count] = freq[1].charfreq[0];
|
|
412 wk.count += 1 ;
|
|
413
|
|
414 i2c_write(regs, lock, &wk);
|
|
415
|
|
416 for(lp = 0 ; lp < 100 ; lp++){
|
|
417 memcpy(&wk, &isdb_t_pll_lock, sizeof(WBLOCK));
|
|
418 wk.addr = addr;
|
|
419 val = i2c_read(regs, lock, &wk, 1);
|
|
420 if(((val & 0xFF) != 0XFF) && ((val & 0X50) == 0x50)){
|
|
421 tmcclock = TRUE ;
|
|
422 break ;
|
|
423 }
|
|
424 }
|
|
425 if(tmcclock != TRUE){
|
|
426 printk(KERN_INFO "PT1:ISDB-T LOCK NG(%08x)\n", val);
|
|
427 return -EIO ;
|
|
428 }
|
|
429
|
|
430 memcpy(&wk, &isdb_t_check_tune, sizeof(WBLOCK));
|
|
431 wk.addr = addr ;
|
|
432 i2c_write(regs, lock, &wk);
|
|
433
|
|
434 tmcclock = FALSE ;
|
|
435 for(lp = 0 ; lp < 1000 ; lp++){
|
|
436 memcpy(&wk, &isdb_t_tune_read, sizeof(WBLOCK));
|
|
437 wk.addr = addr;
|
|
438 val = i2c_read(regs, lock, &wk, 1);
|
|
439 if(((val & 0xFF) != 0XFF) && ((val & 0X8) != 8)){
|
|
440 tmcclock = TRUE ;
|
|
441 break ;
|
|
442 }
|
|
443 }
|
|
444 if(tmcclock != TRUE){
|
|
445 return -EIO ;
|
|
446 }
|
|
447 return 0 ;
|
|
448 }
|
|
449 #if 0
|
|
450 int isdb_t_tune(void __iomem *regs, struct mutex *lock, int addr, int channel, ISDB_T_TMCC *tmcc)
|
|
451 {
|
|
452
|
|
453 int lp ;
|
|
454 int rc ;
|
|
455 int lp2 ;
|
|
456 WBLOCK wk;
|
|
457 __u32 val ;
|
|
458
|
|
459 printk(KERN_INFO "Channel(%d) Start\n", channel);
|
|
460 if(channel >= MAX_ISDB_T_CHANNEL){
|
|
461 return -EIO ;
|
|
462 }
|
|
463 rc = isdb_t_frequency(regs, lock, addr, channel);
|
|
464 if(rc < 0){
|
|
465 return -EIO ;
|
|
466 }
|
|
467 for(lp = 0 ; lp < 100 ; lp++){
|
|
468 memcpy(&wk, &isdb_t_tmcc_read_1, sizeof(WBLOCK));
|
|
469 wk.addr = addr;
|
|
470 val = i2c_read(regs, lock, &wk, 4);
|
|
471 if((val & 0xFF) != 0){
|
|
472 break ;
|
|
473 }
|
|
474 }
|
|
475 printk(KERN_INFO "TMCC(1)Val(%x)\n", val);
|
|
476
|
|
477 for(lp = 0 ; lp < 100 ; lp++){
|
|
478 memcpy(&wk, &isdb_t_tmcc_read_2, sizeof(WBLOCK));
|
|
479 wk.addr = addr;
|
|
480 val = i2c_read(regs, lock, &wk, 4);
|
|
481 if((val & 0xFF) != 0){
|
|
482 break ;
|
|
483 }
|
|
484 }
|
|
485 printk(KERN_INFO "TMCC(2)Val(%x)\n", val);
|
|
486
|
|
487 memcpy(&wk, &isdb_t_cn_1, sizeof(WBLOCK));
|
|
488 wk.addr = addr;
|
|
489 val = i2c_read(regs, lock, &wk, 1);
|
|
490 printk(KERN_INFO "CN(1)Val(%x)\n", val);
|
|
491
|
|
492 memcpy(&wk, &isdb_t_cn_2, sizeof(WBLOCK));
|
|
493 wk.addr = addr;
|
|
494 val = i2c_read(regs, lock, &wk, 1);
|
|
495 printk(KERN_INFO "CN(2)Val(%x)\n", val);
|
|
496
|
|
497 memcpy(&wk, &isdb_t_agc_1, sizeof(WBLOCK));
|
|
498 wk.addr = addr;
|
|
499 val = i2c_read(regs, lock, &wk, 1);
|
|
500 printk(KERN_INFO "AGC(1)Val(%x)\n", val);
|
|
501
|
|
502 memcpy(&wk, &isdb_t_agc_2, sizeof(WBLOCK));
|
|
503 wk.addr = addr;
|
|
504 val = i2c_read(regs, lock, &wk, 1);
|
|
505 printk(KERN_INFO "AGC(2)Val(%x)\n", val);
|
|
506 return 0;
|
|
507 }
|
|
508 #endif
|