Mercurial > pt1.oyama
comparison driver/pt1_tuner.c @ 0:67e8eca28a80
initial import
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 16 Feb 2009 15:41:49 +0900 |
parents | |
children | 07b2fc07ff48 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:67e8eca28a80 |
---|---|
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 |