1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * budget-av.c: driver for the SAA7146 based Budget DVB cards |
4 | * with analog video in |
5 | * |
6 | * Compiled from various sources by Michael Hunold <michael@mihu.de> |
7 | * |
8 | * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> & |
9 | * Andrew de Quincey <adq_dvb@lidskialf.net> |
10 | * |
11 | * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> |
12 | * |
13 | * Copyright (C) 1999-2002 Ralph Metzler |
14 | * & Marcus Metzler for convergence integrated media GmbH |
15 | * |
16 | * the project's page is at https://linuxtv.org |
17 | */ |
18 | |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | |
21 | #include "budget.h" |
22 | #include "stv0299.h" |
23 | #include "stb0899_drv.h" |
24 | #include "stb0899_reg.h" |
25 | #include "stb0899_cfg.h" |
26 | #include "tda8261.h" |
27 | #include "tda8261_cfg.h" |
28 | #include "tda1002x.h" |
29 | #include "tda1004x.h" |
30 | #include "tua6100.h" |
31 | #include "dvb-pll.h" |
32 | #include <media/drv-intf/saa7146_vv.h> |
33 | #include <linux/module.h> |
34 | #include <linux/etherdevice.h> |
35 | #include <linux/errno.h> |
36 | #include <linux/slab.h> |
37 | #include <linux/interrupt.h> |
38 | #include <linux/input.h> |
39 | #include <linux/spinlock.h> |
40 | |
41 | #include <media/dvb_ca_en50221.h> |
42 | |
43 | #define DEBICICAM 0x02420000 |
44 | |
45 | #define SLOTSTATUS_NONE 1 |
46 | #define SLOTSTATUS_PRESENT 2 |
47 | #define SLOTSTATUS_RESET 4 |
48 | #define SLOTSTATUS_READY 8 |
49 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
50 | |
51 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
52 | |
53 | struct budget_av { |
54 | struct budget budget; |
55 | struct video_device vd; |
56 | int cur_input; |
57 | int has_saa7113; |
58 | struct tasklet_struct ciintf_irq_tasklet; |
59 | int slot_status; |
60 | struct dvb_ca_en50221 ca; |
61 | u8 reinitialise_demod:1; |
62 | }; |
63 | |
64 | static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); |
65 | |
66 | |
67 | /* GPIO Connections: |
68 | * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*! |
69 | * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory |
70 | * 2 - CI Card Enable (Active Low) |
71 | * 3 - CI Card Detect |
72 | */ |
73 | |
74 | /**************************************************************************** |
75 | * INITIALIZATION |
76 | ****************************************************************************/ |
77 | |
78 | static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg) |
79 | { |
80 | u8 mm1[] = { 0x00 }; |
81 | u8 mm2[] = { 0x00 }; |
82 | struct i2c_msg msgs[2]; |
83 | |
84 | msgs[0].flags = 0; |
85 | msgs[1].flags = I2C_M_RD; |
86 | msgs[0].addr = msgs[1].addr = id / 2; |
87 | mm1[0] = reg; |
88 | msgs[0].len = 1; |
89 | msgs[1].len = 1; |
90 | msgs[0].buf = mm1; |
91 | msgs[1].buf = mm2; |
92 | |
93 | i2c_transfer(adap: i2c, msgs, num: 2); |
94 | |
95 | return mm2[0]; |
96 | } |
97 | |
98 | static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len) |
99 | { |
100 | u8 mm1[] = { reg }; |
101 | struct i2c_msg msgs[2] = { |
102 | {.addr = id / 2,.flags = 0,.buf = mm1,.len = 1}, |
103 | {.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len} |
104 | }; |
105 | |
106 | if (i2c_transfer(adap: i2c, msgs, num: 2) != 2) |
107 | return -EIO; |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val) |
113 | { |
114 | u8 msg[2] = { reg, val }; |
115 | struct i2c_msg msgs; |
116 | |
117 | msgs.flags = 0; |
118 | msgs.addr = id / 2; |
119 | msgs.len = 2; |
120 | msgs.buf = msg; |
121 | return i2c_transfer(adap: i2c, msgs: &msgs, num: 1); |
122 | } |
123 | |
124 | static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) |
125 | { |
126 | struct budget_av *budget_av = ca->data; |
127 | int result; |
128 | |
129 | if (slot != 0) |
130 | return -EINVAL; |
131 | |
132 | saa7146_setgpio(dev: budget_av->budget.dev, port: 1, SAA7146_GPIO_OUTHI); |
133 | udelay(1); |
134 | |
135 | result = ttpci_budget_debiread(budget: &budget_av->budget, DEBICICAM, addr: address & 0xfff, count: 1, uselocks: 0, nobusyloop: 1); |
136 | if (result == -ETIMEDOUT) { |
137 | ciintf_slot_shutdown(ca, slot); |
138 | pr_info("cam ejected 1\n" ); |
139 | } |
140 | return result; |
141 | } |
142 | |
143 | static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) |
144 | { |
145 | struct budget_av *budget_av = ca->data; |
146 | int result; |
147 | |
148 | if (slot != 0) |
149 | return -EINVAL; |
150 | |
151 | saa7146_setgpio(dev: budget_av->budget.dev, port: 1, SAA7146_GPIO_OUTHI); |
152 | udelay(1); |
153 | |
154 | result = ttpci_budget_debiwrite(budget: &budget_av->budget, DEBICICAM, addr: address & 0xfff, count: 1, value, uselocks: 0, nobusyloop: 1); |
155 | if (result == -ETIMEDOUT) { |
156 | ciintf_slot_shutdown(ca, slot); |
157 | pr_info("cam ejected 2\n" ); |
158 | } |
159 | return result; |
160 | } |
161 | |
162 | static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) |
163 | { |
164 | struct budget_av *budget_av = ca->data; |
165 | int result; |
166 | |
167 | if (slot != 0) |
168 | return -EINVAL; |
169 | |
170 | saa7146_setgpio(dev: budget_av->budget.dev, port: 1, SAA7146_GPIO_OUTLO); |
171 | udelay(1); |
172 | |
173 | result = ttpci_budget_debiread(budget: &budget_av->budget, DEBICICAM, addr: address & 3, count: 1, uselocks: 0, nobusyloop: 0); |
174 | if (result == -ETIMEDOUT) { |
175 | ciintf_slot_shutdown(ca, slot); |
176 | pr_info("cam ejected 3\n" ); |
177 | return -ETIMEDOUT; |
178 | } |
179 | return result; |
180 | } |
181 | |
182 | static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) |
183 | { |
184 | struct budget_av *budget_av = ca->data; |
185 | int result; |
186 | |
187 | if (slot != 0) |
188 | return -EINVAL; |
189 | |
190 | saa7146_setgpio(dev: budget_av->budget.dev, port: 1, SAA7146_GPIO_OUTLO); |
191 | udelay(1); |
192 | |
193 | result = ttpci_budget_debiwrite(budget: &budget_av->budget, DEBICICAM, addr: address & 3, count: 1, value, uselocks: 0, nobusyloop: 0); |
194 | if (result == -ETIMEDOUT) { |
195 | ciintf_slot_shutdown(ca, slot); |
196 | pr_info("cam ejected 5\n" ); |
197 | } |
198 | return result; |
199 | } |
200 | |
201 | static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) |
202 | { |
203 | struct budget_av *budget_av = ca->data; |
204 | struct saa7146_dev *saa = budget_av->budget.dev; |
205 | |
206 | if (slot != 0) |
207 | return -EINVAL; |
208 | |
209 | dprintk(1, "ciintf_slot_reset\n" ); |
210 | budget_av->slot_status = SLOTSTATUS_RESET; |
211 | |
212 | saa7146_setgpio(dev: saa, port: 2, SAA7146_GPIO_OUTHI); /* disable card */ |
213 | |
214 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_OUTHI); /* Vcc off */ |
215 | msleep(msecs: 2); |
216 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_OUTLO); /* Vcc on */ |
217 | msleep(msecs: 20); /* 20 ms Vcc settling time */ |
218 | |
219 | saa7146_setgpio(dev: saa, port: 2, SAA7146_GPIO_OUTLO); /* enable card */ |
220 | ttpci_budget_set_video_port(dev: saa, BUDGET_VIDEO_PORTB); |
221 | msleep(msecs: 20); |
222 | |
223 | /* reinitialise the frontend if necessary */ |
224 | if (budget_av->reinitialise_demod) |
225 | dvb_frontend_reinitialise(fe: budget_av->budget.dvb_frontend); |
226 | |
227 | return 0; |
228 | } |
229 | |
230 | static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) |
231 | { |
232 | struct budget_av *budget_av = ca->data; |
233 | struct saa7146_dev *saa = budget_av->budget.dev; |
234 | |
235 | if (slot != 0) |
236 | return -EINVAL; |
237 | |
238 | dprintk(1, "ciintf_slot_shutdown\n" ); |
239 | |
240 | ttpci_budget_set_video_port(dev: saa, BUDGET_VIDEO_PORTB); |
241 | budget_av->slot_status = SLOTSTATUS_NONE; |
242 | |
243 | return 0; |
244 | } |
245 | |
246 | static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) |
247 | { |
248 | struct budget_av *budget_av = ca->data; |
249 | struct saa7146_dev *saa = budget_av->budget.dev; |
250 | |
251 | if (slot != 0) |
252 | return -EINVAL; |
253 | |
254 | dprintk(1, "ciintf_slot_ts_enable: %d\n" , budget_av->slot_status); |
255 | |
256 | ttpci_budget_set_video_port(dev: saa, BUDGET_VIDEO_PORTA); |
257 | |
258 | return 0; |
259 | } |
260 | |
261 | static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) |
262 | { |
263 | struct budget_av *budget_av = ca->data; |
264 | struct saa7146_dev *saa = budget_av->budget.dev; |
265 | int result; |
266 | |
267 | if (slot != 0) |
268 | return -EINVAL; |
269 | |
270 | /* test the card detect line - needs to be done carefully |
271 | * since it never goes high for some CAMs on this interface (e.g. topuptv) */ |
272 | if (budget_av->slot_status == SLOTSTATUS_NONE) { |
273 | saa7146_setgpio(dev: saa, port: 3, SAA7146_GPIO_INPUT); |
274 | udelay(1); |
275 | if (saa7146_read(saa, PSR) & MASK_06) { |
276 | if (budget_av->slot_status == SLOTSTATUS_NONE) { |
277 | budget_av->slot_status = SLOTSTATUS_PRESENT; |
278 | pr_info("cam inserted A\n" ); |
279 | } |
280 | } |
281 | saa7146_setgpio(dev: saa, port: 3, SAA7146_GPIO_OUTLO); |
282 | } |
283 | |
284 | /* We also try and read from IO memory to work round the above detection bug. If |
285 | * there is no CAM, we will get a timeout. Only done if there is no cam |
286 | * present, since this test actually breaks some cams :( |
287 | * |
288 | * if the CI interface is not open, we also do the above test since we |
289 | * don't care if the cam has problems - we'll be resetting it on open() anyway */ |
290 | if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) { |
291 | saa7146_setgpio(dev: budget_av->budget.dev, port: 1, SAA7146_GPIO_OUTLO); |
292 | result = ttpci_budget_debiread(budget: &budget_av->budget, DEBICICAM, addr: 0, count: 1, uselocks: 0, nobusyloop: 1); |
293 | if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) { |
294 | budget_av->slot_status = SLOTSTATUS_PRESENT; |
295 | pr_info("cam inserted B\n" ); |
296 | } else if (result < 0) { |
297 | if (budget_av->slot_status != SLOTSTATUS_NONE) { |
298 | ciintf_slot_shutdown(ca, slot); |
299 | pr_info("cam ejected 5\n" ); |
300 | return 0; |
301 | } |
302 | } |
303 | } |
304 | |
305 | /* read from attribute memory in reset/ready state to know when the CAM is ready */ |
306 | if (budget_av->slot_status == SLOTSTATUS_RESET) { |
307 | result = ciintf_read_attribute_mem(ca, slot, address: 0); |
308 | if (result == 0x1d) { |
309 | budget_av->slot_status = SLOTSTATUS_READY; |
310 | } |
311 | } |
312 | |
313 | /* work out correct return code */ |
314 | if (budget_av->slot_status != SLOTSTATUS_NONE) { |
315 | if (budget_av->slot_status & SLOTSTATUS_READY) { |
316 | return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; |
317 | } |
318 | return DVB_CA_EN50221_POLL_CAM_PRESENT; |
319 | } |
320 | return 0; |
321 | } |
322 | |
323 | static int ciintf_init(struct budget_av *budget_av) |
324 | { |
325 | struct saa7146_dev *saa = budget_av->budget.dev; |
326 | int result; |
327 | |
328 | memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); |
329 | |
330 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_OUTLO); |
331 | saa7146_setgpio(dev: saa, port: 1, SAA7146_GPIO_OUTLO); |
332 | saa7146_setgpio(dev: saa, port: 2, SAA7146_GPIO_OUTLO); |
333 | saa7146_setgpio(dev: saa, port: 3, SAA7146_GPIO_OUTLO); |
334 | |
335 | /* Enable DEBI pins */ |
336 | saa7146_write(saa, MC1, MASK_27 | MASK_11); |
337 | |
338 | /* register CI interface */ |
339 | budget_av->ca.owner = THIS_MODULE; |
340 | budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem; |
341 | budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem; |
342 | budget_av->ca.read_cam_control = ciintf_read_cam_control; |
343 | budget_av->ca.write_cam_control = ciintf_write_cam_control; |
344 | budget_av->ca.slot_reset = ciintf_slot_reset; |
345 | budget_av->ca.slot_shutdown = ciintf_slot_shutdown; |
346 | budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; |
347 | budget_av->ca.poll_slot_status = ciintf_poll_slot_status; |
348 | budget_av->ca.data = budget_av; |
349 | budget_av->budget.ci_present = 1; |
350 | budget_av->slot_status = SLOTSTATUS_NONE; |
351 | |
352 | if ((result = dvb_ca_en50221_init(dvb_adapter: &budget_av->budget.dvb_adapter, |
353 | ca: &budget_av->ca, flags: 0, slot_count: 1)) != 0) { |
354 | pr_err("ci initialisation failed\n" ); |
355 | goto error; |
356 | } |
357 | |
358 | pr_info("ci interface initialised\n" ); |
359 | return 0; |
360 | |
361 | error: |
362 | saa7146_write(saa, MC1, MASK_27); |
363 | return result; |
364 | } |
365 | |
366 | static void ciintf_deinit(struct budget_av *budget_av) |
367 | { |
368 | struct saa7146_dev *saa = budget_av->budget.dev; |
369 | |
370 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_INPUT); |
371 | saa7146_setgpio(dev: saa, port: 1, SAA7146_GPIO_INPUT); |
372 | saa7146_setgpio(dev: saa, port: 2, SAA7146_GPIO_INPUT); |
373 | saa7146_setgpio(dev: saa, port: 3, SAA7146_GPIO_INPUT); |
374 | |
375 | /* release the CA device */ |
376 | dvb_ca_en50221_release(ca: &budget_av->ca); |
377 | |
378 | /* disable DEBI pins */ |
379 | saa7146_write(saa, MC1, MASK_27); |
380 | } |
381 | |
382 | |
383 | static const u8 saa7113_tab[] = { |
384 | 0x01, 0x08, |
385 | 0x02, 0xc0, |
386 | 0x03, 0x33, |
387 | 0x04, 0x00, |
388 | 0x05, 0x00, |
389 | 0x06, 0xeb, |
390 | 0x07, 0xe0, |
391 | 0x08, 0x28, |
392 | 0x09, 0x00, |
393 | 0x0a, 0x80, |
394 | 0x0b, 0x47, |
395 | 0x0c, 0x40, |
396 | 0x0d, 0x00, |
397 | 0x0e, 0x01, |
398 | 0x0f, 0x44, |
399 | |
400 | 0x10, 0x08, |
401 | 0x11, 0x0c, |
402 | 0x12, 0x7b, |
403 | 0x13, 0x00, |
404 | 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, |
405 | |
406 | 0x57, 0xff, |
407 | 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07, |
408 | 0x5b, 0x83, 0x5e, 0x00, |
409 | 0xff |
410 | }; |
411 | |
412 | static int saa7113_init(struct budget_av *budget_av) |
413 | { |
414 | struct budget *budget = &budget_av->budget; |
415 | struct saa7146_dev *saa = budget->dev; |
416 | const u8 *data = saa7113_tab; |
417 | |
418 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_OUTHI); |
419 | msleep(msecs: 200); |
420 | |
421 | if (i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: 0x01, val: 0x08) != 1) { |
422 | dprintk(1, "saa7113 not found on KNC card\n" ); |
423 | return -ENODEV; |
424 | } |
425 | |
426 | dprintk(1, "saa7113 detected and initializing\n" ); |
427 | |
428 | while (*data != 0xff) { |
429 | i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: *data, val: *(data + 1)); |
430 | data += 2; |
431 | } |
432 | |
433 | dprintk(1, "saa7113 status=%02x\n" , i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f)); |
434 | |
435 | return 0; |
436 | } |
437 | |
438 | static int saa7113_setinput(struct budget_av *budget_av, int input) |
439 | { |
440 | struct budget *budget = &budget_av->budget; |
441 | |
442 | if (1 != budget_av->has_saa7113) |
443 | return -ENODEV; |
444 | |
445 | if (input == 1) { |
446 | i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: 0x02, val: 0xc7); |
447 | i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: 0x09, val: 0x80); |
448 | } else if (input == 0) { |
449 | i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: 0x02, val: 0xc0); |
450 | i2c_writereg(i2c: &budget->i2c_adap, id: 0x4a, reg: 0x09, val: 0x00); |
451 | } else |
452 | return -EINVAL; |
453 | |
454 | budget_av->cur_input = input; |
455 | return 0; |
456 | } |
457 | |
458 | |
459 | static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) |
460 | { |
461 | u8 aclk = 0; |
462 | u8 bclk = 0; |
463 | u8 m1; |
464 | |
465 | aclk = 0xb5; |
466 | if (srate < 2000000) |
467 | bclk = 0x86; |
468 | else if (srate < 5000000) |
469 | bclk = 0x89; |
470 | else if (srate < 15000000) |
471 | bclk = 0x8f; |
472 | else if (srate < 45000000) |
473 | bclk = 0x95; |
474 | |
475 | m1 = 0x14; |
476 | if (srate < 4000000) |
477 | m1 = 0x10; |
478 | |
479 | stv0299_writereg(fe, 0x13, aclk); |
480 | stv0299_writereg(fe, 0x14, bclk); |
481 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); |
482 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); |
483 | stv0299_writereg(fe, 0x21, (ratio) & 0xf0); |
484 | stv0299_writereg(fe, 0x0f, 0x80 | m1); |
485 | |
486 | return 0; |
487 | } |
488 | |
489 | static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe) |
490 | { |
491 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
492 | u32 div; |
493 | u8 buf[4]; |
494 | struct budget *budget = fe->dvb->priv; |
495 | struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; |
496 | |
497 | if ((c->frequency < 950000) || (c->frequency > 2150000)) |
498 | return -EINVAL; |
499 | |
500 | div = (c->frequency + (125 - 1)) / 125; /* round correctly */ |
501 | buf[0] = (div >> 8) & 0x7f; |
502 | buf[1] = div & 0xff; |
503 | buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; |
504 | buf[3] = 0x20; |
505 | |
506 | if (c->symbol_rate < 4000000) |
507 | buf[3] |= 1; |
508 | |
509 | if (c->frequency < 1250000) |
510 | buf[3] |= 0; |
511 | else if (c->frequency < 1550000) |
512 | buf[3] |= 0x40; |
513 | else if (c->frequency < 2050000) |
514 | buf[3] |= 0x80; |
515 | else if (c->frequency < 2150000) |
516 | buf[3] |= 0xC0; |
517 | |
518 | if (fe->ops.i2c_gate_ctrl) |
519 | fe->ops.i2c_gate_ctrl(fe, 1); |
520 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &msg, num: 1) != 1) |
521 | return -EIO; |
522 | return 0; |
523 | } |
524 | |
525 | static u8 typhoon_cinergy1200s_inittab[] = { |
526 | 0x01, 0x15, |
527 | 0x02, 0x30, |
528 | 0x03, 0x00, |
529 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ |
530 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ |
531 | 0x06, 0x40, /* DAC not used, set to high impendance mode */ |
532 | 0x07, 0x00, /* DAC LSB */ |
533 | 0x08, 0x40, /* DiSEqC off */ |
534 | 0x09, 0x00, /* FIFO */ |
535 | 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ |
536 | 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ |
537 | 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ |
538 | 0x10, 0x3f, // AGC2 0x3d |
539 | 0x11, 0x84, |
540 | 0x12, 0xb9, |
541 | 0x15, 0xc9, // lock detector threshold |
542 | 0x16, 0x00, |
543 | 0x17, 0x00, |
544 | 0x18, 0x00, |
545 | 0x19, 0x00, |
546 | 0x1a, 0x00, |
547 | 0x1f, 0x50, |
548 | 0x20, 0x00, |
549 | 0x21, 0x00, |
550 | 0x22, 0x00, |
551 | 0x23, 0x00, |
552 | 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 |
553 | 0x29, 0x1e, // 1/2 threshold |
554 | 0x2a, 0x14, // 2/3 threshold |
555 | 0x2b, 0x0f, // 3/4 threshold |
556 | 0x2c, 0x09, // 5/6 threshold |
557 | 0x2d, 0x05, // 7/8 threshold |
558 | 0x2e, 0x01, |
559 | 0x31, 0x1f, // test all FECs |
560 | 0x32, 0x19, // viterbi and synchro search |
561 | 0x33, 0xfc, // rs control |
562 | 0x34, 0x93, // error control |
563 | 0x0f, 0x92, |
564 | 0xff, 0xff |
565 | }; |
566 | |
567 | static const struct stv0299_config typhoon_config = { |
568 | .demod_address = 0x68, |
569 | .inittab = typhoon_cinergy1200s_inittab, |
570 | .mclk = 88000000UL, |
571 | .invert = 0, |
572 | .skip_reinit = 0, |
573 | .lock_output = STV0299_LOCKOUTPUT_1, |
574 | .volt13_op0_op1 = STV0299_VOLT13_OP0, |
575 | .min_delay_ms = 100, |
576 | .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, |
577 | }; |
578 | |
579 | |
580 | static const struct stv0299_config cinergy_1200s_config = { |
581 | .demod_address = 0x68, |
582 | .inittab = typhoon_cinergy1200s_inittab, |
583 | .mclk = 88000000UL, |
584 | .invert = 0, |
585 | .skip_reinit = 0, |
586 | .lock_output = STV0299_LOCKOUTPUT_0, |
587 | .volt13_op0_op1 = STV0299_VOLT13_OP0, |
588 | .min_delay_ms = 100, |
589 | .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, |
590 | }; |
591 | |
592 | static const struct stv0299_config cinergy_1200s_1894_0010_config = { |
593 | .demod_address = 0x68, |
594 | .inittab = typhoon_cinergy1200s_inittab, |
595 | .mclk = 88000000UL, |
596 | .invert = 1, |
597 | .skip_reinit = 0, |
598 | .lock_output = STV0299_LOCKOUTPUT_1, |
599 | .volt13_op0_op1 = STV0299_VOLT13_OP0, |
600 | .min_delay_ms = 100, |
601 | .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, |
602 | }; |
603 | |
604 | static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe) |
605 | { |
606 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
607 | struct budget *budget = fe->dvb->priv; |
608 | u8 buf[6]; |
609 | struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; |
610 | int i; |
611 | |
612 | #define CU1216_IF 36125000 |
613 | #define TUNER_MUL 62500 |
614 | |
615 | u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; |
616 | |
617 | buf[0] = (div >> 8) & 0x7f; |
618 | buf[1] = div & 0xff; |
619 | buf[2] = 0xce; |
620 | buf[3] = (c->frequency < 150000000 ? 0x01 : |
621 | c->frequency < 445000000 ? 0x02 : 0x04); |
622 | buf[4] = 0xde; |
623 | buf[5] = 0x20; |
624 | |
625 | if (fe->ops.i2c_gate_ctrl) |
626 | fe->ops.i2c_gate_ctrl(fe, 1); |
627 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &msg, num: 1) != 1) |
628 | return -EIO; |
629 | |
630 | /* wait for the pll lock */ |
631 | msg.flags = I2C_M_RD; |
632 | msg.len = 1; |
633 | for (i = 0; i < 20; i++) { |
634 | if (fe->ops.i2c_gate_ctrl) |
635 | fe->ops.i2c_gate_ctrl(fe, 1); |
636 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &msg, num: 1) == 1 && (buf[0] & 0x40)) |
637 | break; |
638 | msleep(msecs: 10); |
639 | } |
640 | |
641 | /* switch the charge pump to the lower current */ |
642 | msg.flags = 0; |
643 | msg.len = 2; |
644 | msg.buf = &buf[2]; |
645 | buf[2] &= ~0x40; |
646 | if (fe->ops.i2c_gate_ctrl) |
647 | fe->ops.i2c_gate_ctrl(fe, 1); |
648 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &msg, num: 1) != 1) |
649 | return -EIO; |
650 | |
651 | return 0; |
652 | } |
653 | |
654 | static struct tda1002x_config philips_cu1216_config = { |
655 | .demod_address = 0x0c, |
656 | .invert = 1, |
657 | }; |
658 | |
659 | static struct tda1002x_config philips_cu1216_config_altaddress = { |
660 | .demod_address = 0x0d, |
661 | .invert = 0, |
662 | }; |
663 | |
664 | static struct tda10023_config philips_cu1216_tda10023_config = { |
665 | .demod_address = 0x0c, |
666 | .invert = 1, |
667 | }; |
668 | |
669 | static int philips_tu1216_tuner_init(struct dvb_frontend *fe) |
670 | { |
671 | struct budget *budget = fe->dvb->priv; |
672 | static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; |
673 | struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; |
674 | |
675 | // setup PLL configuration |
676 | if (fe->ops.i2c_gate_ctrl) |
677 | fe->ops.i2c_gate_ctrl(fe, 1); |
678 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &tuner_msg, num: 1) != 1) |
679 | return -EIO; |
680 | msleep(msecs: 1); |
681 | |
682 | return 0; |
683 | } |
684 | |
685 | static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe) |
686 | { |
687 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
688 | struct budget *budget = fe->dvb->priv; |
689 | u8 tuner_buf[4]; |
690 | struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = |
691 | sizeof(tuner_buf) }; |
692 | int tuner_frequency = 0; |
693 | u8 band, cp, filter; |
694 | |
695 | // determine charge pump |
696 | tuner_frequency = c->frequency + 36166000; |
697 | if (tuner_frequency < 87000000) |
698 | return -EINVAL; |
699 | else if (tuner_frequency < 130000000) |
700 | cp = 3; |
701 | else if (tuner_frequency < 160000000) |
702 | cp = 5; |
703 | else if (tuner_frequency < 200000000) |
704 | cp = 6; |
705 | else if (tuner_frequency < 290000000) |
706 | cp = 3; |
707 | else if (tuner_frequency < 420000000) |
708 | cp = 5; |
709 | else if (tuner_frequency < 480000000) |
710 | cp = 6; |
711 | else if (tuner_frequency < 620000000) |
712 | cp = 3; |
713 | else if (tuner_frequency < 830000000) |
714 | cp = 5; |
715 | else if (tuner_frequency < 895000000) |
716 | cp = 7; |
717 | else |
718 | return -EINVAL; |
719 | |
720 | // determine band |
721 | if (c->frequency < 49000000) |
722 | return -EINVAL; |
723 | else if (c->frequency < 161000000) |
724 | band = 1; |
725 | else if (c->frequency < 444000000) |
726 | band = 2; |
727 | else if (c->frequency < 861000000) |
728 | band = 4; |
729 | else |
730 | return -EINVAL; |
731 | |
732 | // setup PLL filter |
733 | switch (c->bandwidth_hz) { |
734 | case 6000000: |
735 | filter = 0; |
736 | break; |
737 | |
738 | case 7000000: |
739 | filter = 0; |
740 | break; |
741 | |
742 | case 8000000: |
743 | filter = 1; |
744 | break; |
745 | |
746 | default: |
747 | return -EINVAL; |
748 | } |
749 | |
750 | // calculate divisor |
751 | // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) |
752 | tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000; |
753 | |
754 | // setup tuner buffer |
755 | tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; |
756 | tuner_buf[1] = tuner_frequency & 0xff; |
757 | tuner_buf[2] = 0xca; |
758 | tuner_buf[3] = (cp << 5) | (filter << 3) | band; |
759 | |
760 | if (fe->ops.i2c_gate_ctrl) |
761 | fe->ops.i2c_gate_ctrl(fe, 1); |
762 | if (i2c_transfer(adap: &budget->i2c_adap, msgs: &tuner_msg, num: 1) != 1) |
763 | return -EIO; |
764 | |
765 | msleep(msecs: 1); |
766 | return 0; |
767 | } |
768 | |
769 | static int philips_tu1216_request_firmware(struct dvb_frontend *fe, |
770 | const struct firmware **fw, char *name) |
771 | { |
772 | struct budget *budget = fe->dvb->priv; |
773 | |
774 | return request_firmware(fw, name, &budget->dev->pci->dev); |
775 | } |
776 | |
777 | static struct tda1004x_config philips_tu1216_config = { |
778 | |
779 | .demod_address = 0x8, |
780 | .invert = 1, |
781 | .invert_oclk = 1, |
782 | .xtal_freq = TDA10046_XTAL_4M, |
783 | .agc_config = TDA10046_AGC_DEFAULT, |
784 | .if_freq = TDA10046_FREQ_3617, |
785 | .request_firmware = philips_tu1216_request_firmware, |
786 | }; |
787 | |
788 | static u8 philips_sd1878_inittab[] = { |
789 | 0x01, 0x15, |
790 | 0x02, 0x30, |
791 | 0x03, 0x00, |
792 | 0x04, 0x7d, |
793 | 0x05, 0x35, |
794 | 0x06, 0x40, |
795 | 0x07, 0x00, |
796 | 0x08, 0x43, |
797 | 0x09, 0x02, |
798 | 0x0C, 0x51, |
799 | 0x0D, 0x82, |
800 | 0x0E, 0x23, |
801 | 0x10, 0x3f, |
802 | 0x11, 0x84, |
803 | 0x12, 0xb9, |
804 | 0x15, 0xc9, |
805 | 0x16, 0x19, |
806 | 0x17, 0x8c, |
807 | 0x18, 0x59, |
808 | 0x19, 0xf8, |
809 | 0x1a, 0xfe, |
810 | 0x1c, 0x7f, |
811 | 0x1d, 0x00, |
812 | 0x1e, 0x00, |
813 | 0x1f, 0x50, |
814 | 0x20, 0x00, |
815 | 0x21, 0x00, |
816 | 0x22, 0x00, |
817 | 0x23, 0x00, |
818 | 0x28, 0x00, |
819 | 0x29, 0x28, |
820 | 0x2a, 0x14, |
821 | 0x2b, 0x0f, |
822 | 0x2c, 0x09, |
823 | 0x2d, 0x09, |
824 | 0x31, 0x1f, |
825 | 0x32, 0x19, |
826 | 0x33, 0xfc, |
827 | 0x34, 0x93, |
828 | 0xff, 0xff |
829 | }; |
830 | |
831 | static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe, |
832 | u32 srate, u32 ratio) |
833 | { |
834 | u8 aclk = 0; |
835 | u8 bclk = 0; |
836 | u8 m1; |
837 | |
838 | aclk = 0xb5; |
839 | if (srate < 2000000) |
840 | bclk = 0x86; |
841 | else if (srate < 5000000) |
842 | bclk = 0x89; |
843 | else if (srate < 15000000) |
844 | bclk = 0x8f; |
845 | else if (srate < 45000000) |
846 | bclk = 0x95; |
847 | |
848 | m1 = 0x14; |
849 | if (srate < 4000000) |
850 | m1 = 0x10; |
851 | |
852 | stv0299_writereg(fe, 0x0e, 0x23); |
853 | stv0299_writereg(fe, 0x0f, 0x94); |
854 | stv0299_writereg(fe, 0x10, 0x39); |
855 | stv0299_writereg(fe, 0x13, aclk); |
856 | stv0299_writereg(fe, 0x14, bclk); |
857 | stv0299_writereg(fe, 0x15, 0xc9); |
858 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); |
859 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); |
860 | stv0299_writereg(fe, 0x21, (ratio) & 0xf0); |
861 | stv0299_writereg(fe, 0x0f, 0x80 | m1); |
862 | |
863 | return 0; |
864 | } |
865 | |
866 | static const struct stv0299_config philips_sd1878_config = { |
867 | .demod_address = 0x68, |
868 | .inittab = philips_sd1878_inittab, |
869 | .mclk = 88000000UL, |
870 | .invert = 0, |
871 | .skip_reinit = 0, |
872 | .lock_output = STV0299_LOCKOUTPUT_1, |
873 | .volt13_op0_op1 = STV0299_VOLT13_OP0, |
874 | .min_delay_ms = 100, |
875 | .set_symbol_rate = philips_sd1878_ci_set_symbol_rate, |
876 | }; |
877 | |
878 | /* KNC1 DVB-S (STB0899) Inittab */ |
879 | static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = { |
880 | |
881 | { STB0899_DEV_ID , 0x81 }, |
882 | { STB0899_DISCNTRL1 , 0x32 }, |
883 | { STB0899_DISCNTRL2 , 0x80 }, |
884 | { STB0899_DISRX_ST0 , 0x04 }, |
885 | { STB0899_DISRX_ST1 , 0x00 }, |
886 | { STB0899_DISPARITY , 0x00 }, |
887 | { STB0899_DISSTATUS , 0x20 }, |
888 | { STB0899_DISF22 , 0x8c }, |
889 | { STB0899_DISF22RX , 0x9a }, |
890 | { STB0899_SYSREG , 0x0b }, |
891 | { STB0899_ACRPRESC , 0x11 }, |
892 | { STB0899_ACRDIV1 , 0x0a }, |
893 | { STB0899_ACRDIV2 , 0x05 }, |
894 | { STB0899_DACR1 , 0x00 }, |
895 | { STB0899_DACR2 , 0x00 }, |
896 | { STB0899_OUTCFG , 0x00 }, |
897 | { STB0899_MODECFG , 0x00 }, |
898 | { STB0899_IRQSTATUS_3 , 0x30 }, |
899 | { STB0899_IRQSTATUS_2 , 0x00 }, |
900 | { STB0899_IRQSTATUS_1 , 0x00 }, |
901 | { STB0899_IRQSTATUS_0 , 0x00 }, |
902 | { STB0899_IRQMSK_3 , 0xf3 }, |
903 | { STB0899_IRQMSK_2 , 0xfc }, |
904 | { STB0899_IRQMSK_1 , 0xff }, |
905 | { STB0899_IRQMSK_0 , 0xff }, |
906 | { STB0899_IRQCFG , 0x00 }, |
907 | { STB0899_I2CCFG , 0x88 }, |
908 | { STB0899_I2CRPT , 0x58 }, /* Repeater=8, Stop=disabled */ |
909 | { STB0899_IOPVALUE5 , 0x00 }, |
910 | { STB0899_IOPVALUE4 , 0x20 }, |
911 | { STB0899_IOPVALUE3 , 0xc9 }, |
912 | { STB0899_IOPVALUE2 , 0x90 }, |
913 | { STB0899_IOPVALUE1 , 0x40 }, |
914 | { STB0899_IOPVALUE0 , 0x00 }, |
915 | { STB0899_GPIO00CFG , 0x82 }, |
916 | { STB0899_GPIO01CFG , 0x82 }, |
917 | { STB0899_GPIO02CFG , 0x82 }, |
918 | { STB0899_GPIO03CFG , 0x82 }, |
919 | { STB0899_GPIO04CFG , 0x82 }, |
920 | { STB0899_GPIO05CFG , 0x82 }, |
921 | { STB0899_GPIO06CFG , 0x82 }, |
922 | { STB0899_GPIO07CFG , 0x82 }, |
923 | { STB0899_GPIO08CFG , 0x82 }, |
924 | { STB0899_GPIO09CFG , 0x82 }, |
925 | { STB0899_GPIO10CFG , 0x82 }, |
926 | { STB0899_GPIO11CFG , 0x82 }, |
927 | { STB0899_GPIO12CFG , 0x82 }, |
928 | { STB0899_GPIO13CFG , 0x82 }, |
929 | { STB0899_GPIO14CFG , 0x82 }, |
930 | { STB0899_GPIO15CFG , 0x82 }, |
931 | { STB0899_GPIO16CFG , 0x82 }, |
932 | { STB0899_GPIO17CFG , 0x82 }, |
933 | { STB0899_GPIO18CFG , 0x82 }, |
934 | { STB0899_GPIO19CFG , 0x82 }, |
935 | { STB0899_GPIO20CFG , 0x82 }, |
936 | { STB0899_SDATCFG , 0xb8 }, |
937 | { STB0899_SCLTCFG , 0xba }, |
938 | { STB0899_AGCRFCFG , 0x08 }, /* 0x1c */ |
939 | { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ |
940 | { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ |
941 | { STB0899_DIRCLKCFG , 0x82 }, |
942 | { STB0899_CLKOUT27CFG , 0x7e }, |
943 | { STB0899_STDBYCFG , 0x82 }, |
944 | { STB0899_CS0CFG , 0x82 }, |
945 | { STB0899_CS1CFG , 0x82 }, |
946 | { STB0899_DISEQCOCFG , 0x20 }, |
947 | { STB0899_GPIO32CFG , 0x82 }, |
948 | { STB0899_GPIO33CFG , 0x82 }, |
949 | { STB0899_GPIO34CFG , 0x82 }, |
950 | { STB0899_GPIO35CFG , 0x82 }, |
951 | { STB0899_GPIO36CFG , 0x82 }, |
952 | { STB0899_GPIO37CFG , 0x82 }, |
953 | { STB0899_GPIO38CFG , 0x82 }, |
954 | { STB0899_GPIO39CFG , 0x82 }, |
955 | { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ |
956 | { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ |
957 | { STB0899_FILTCTRL , 0x00 }, |
958 | { STB0899_SYSCTRL , 0x00 }, |
959 | { STB0899_STOPCLK1 , 0x20 }, |
960 | { STB0899_STOPCLK2 , 0x00 }, |
961 | { STB0899_INTBUFSTATUS , 0x00 }, |
962 | { STB0899_INTBUFCTRL , 0x0a }, |
963 | { 0xffff , 0xff }, |
964 | }; |
965 | |
966 | static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = { |
967 | { STB0899_DEMOD , 0x00 }, |
968 | { STB0899_RCOMPC , 0xc9 }, |
969 | { STB0899_AGC1CN , 0x41 }, |
970 | { STB0899_AGC1REF , 0x08 }, |
971 | { STB0899_RTC , 0x7a }, |
972 | { STB0899_TMGCFG , 0x4e }, |
973 | { STB0899_AGC2REF , 0x33 }, |
974 | { STB0899_TLSR , 0x84 }, |
975 | { STB0899_CFD , 0xee }, |
976 | { STB0899_ACLC , 0x87 }, |
977 | { STB0899_BCLC , 0x94 }, |
978 | { STB0899_EQON , 0x41 }, |
979 | { STB0899_LDT , 0xdd }, |
980 | { STB0899_LDT2 , 0xc9 }, |
981 | { STB0899_EQUALREF , 0xb4 }, |
982 | { STB0899_TMGRAMP , 0x10 }, |
983 | { STB0899_TMGTHD , 0x30 }, |
984 | { STB0899_IDCCOMP , 0xfb }, |
985 | { STB0899_QDCCOMP , 0x03 }, |
986 | { STB0899_POWERI , 0x3b }, |
987 | { STB0899_POWERQ , 0x3d }, |
988 | { STB0899_RCOMP , 0x81 }, |
989 | { STB0899_AGCIQIN , 0x80 }, |
990 | { STB0899_AGC2I1 , 0x04 }, |
991 | { STB0899_AGC2I2 , 0xf5 }, |
992 | { STB0899_TLIR , 0x25 }, |
993 | { STB0899_RTF , 0x80 }, |
994 | { STB0899_DSTATUS , 0x00 }, |
995 | { STB0899_LDI , 0xca }, |
996 | { STB0899_CFRM , 0xf1 }, |
997 | { STB0899_CFRL , 0xf3 }, |
998 | { STB0899_NIRM , 0x2a }, |
999 | { STB0899_NIRL , 0x05 }, |
1000 | { STB0899_ISYMB , 0x17 }, |
1001 | { STB0899_QSYMB , 0xfa }, |
1002 | { STB0899_SFRH , 0x2f }, |
1003 | { STB0899_SFRM , 0x68 }, |
1004 | { STB0899_SFRL , 0x40 }, |
1005 | { STB0899_SFRUPH , 0x2f }, |
1006 | { STB0899_SFRUPM , 0x68 }, |
1007 | { STB0899_SFRUPL , 0x40 }, |
1008 | { STB0899_EQUAI1 , 0xfd }, |
1009 | { STB0899_EQUAQ1 , 0x04 }, |
1010 | { STB0899_EQUAI2 , 0x0f }, |
1011 | { STB0899_EQUAQ2 , 0xff }, |
1012 | { STB0899_EQUAI3 , 0xdf }, |
1013 | { STB0899_EQUAQ3 , 0xfa }, |
1014 | { STB0899_EQUAI4 , 0x37 }, |
1015 | { STB0899_EQUAQ4 , 0x0d }, |
1016 | { STB0899_EQUAI5 , 0xbd }, |
1017 | { STB0899_EQUAQ5 , 0xf7 }, |
1018 | { STB0899_DSTATUS2 , 0x00 }, |
1019 | { STB0899_VSTATUS , 0x00 }, |
1020 | { STB0899_VERROR , 0xff }, |
1021 | { STB0899_IQSWAP , 0x2a }, |
1022 | { STB0899_ECNT1M , 0x00 }, |
1023 | { STB0899_ECNT1L , 0x00 }, |
1024 | { STB0899_ECNT2M , 0x00 }, |
1025 | { STB0899_ECNT2L , 0x00 }, |
1026 | { STB0899_ECNT3M , 0x00 }, |
1027 | { STB0899_ECNT3L , 0x00 }, |
1028 | { STB0899_FECAUTO1 , 0x06 }, |
1029 | { STB0899_FECM , 0x01 }, |
1030 | { STB0899_VTH12 , 0xf0 }, |
1031 | { STB0899_VTH23 , 0xa0 }, |
1032 | { STB0899_VTH34 , 0x78 }, |
1033 | { STB0899_VTH56 , 0x4e }, |
1034 | { STB0899_VTH67 , 0x48 }, |
1035 | { STB0899_VTH78 , 0x38 }, |
1036 | { STB0899_PRVIT , 0xff }, |
1037 | { STB0899_VITSYNC , 0x19 }, |
1038 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ |
1039 | { STB0899_TSULC , 0x42 }, |
1040 | { STB0899_RSLLC , 0x40 }, |
1041 | { STB0899_TSLPL , 0x12 }, |
1042 | { STB0899_TSCFGH , 0x0c }, |
1043 | { STB0899_TSCFGM , 0x00 }, |
1044 | { STB0899_TSCFGL , 0x0c }, |
1045 | { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */ |
1046 | { STB0899_RSSYNCDEL , 0x00 }, |
1047 | { STB0899_TSINHDELH , 0x02 }, |
1048 | { STB0899_TSINHDELM , 0x00 }, |
1049 | { STB0899_TSINHDELL , 0x00 }, |
1050 | { STB0899_TSLLSTKM , 0x00 }, |
1051 | { STB0899_TSLLSTKL , 0x00 }, |
1052 | { STB0899_TSULSTKM , 0x00 }, |
1053 | { STB0899_TSULSTKL , 0xab }, |
1054 | { STB0899_PCKLENUL , 0x00 }, |
1055 | { STB0899_PCKLENLL , 0xcc }, |
1056 | { STB0899_RSPCKLEN , 0xcc }, |
1057 | { STB0899_TSSTATUS , 0x80 }, |
1058 | { STB0899_ERRCTRL1 , 0xb6 }, |
1059 | { STB0899_ERRCTRL2 , 0x96 }, |
1060 | { STB0899_ERRCTRL3 , 0x89 }, |
1061 | { STB0899_DMONMSK1 , 0x27 }, |
1062 | { STB0899_DMONMSK0 , 0x03 }, |
1063 | { STB0899_DEMAPVIT , 0x5c }, |
1064 | { STB0899_PLPARM , 0x1f }, |
1065 | { STB0899_PDELCTRL , 0x48 }, |
1066 | { STB0899_PDELCTRL2 , 0x00 }, |
1067 | { STB0899_BBHCTRL1 , 0x00 }, |
1068 | { STB0899_BBHCTRL2 , 0x00 }, |
1069 | { STB0899_HYSTTHRESH , 0x77 }, |
1070 | { STB0899_MATCSTM , 0x00 }, |
1071 | { STB0899_MATCSTL , 0x00 }, |
1072 | { STB0899_UPLCSTM , 0x00 }, |
1073 | { STB0899_UPLCSTL , 0x00 }, |
1074 | { STB0899_DFLCSTM , 0x00 }, |
1075 | { STB0899_DFLCSTL , 0x00 }, |
1076 | { STB0899_SYNCCST , 0x00 }, |
1077 | { STB0899_SYNCDCSTM , 0x00 }, |
1078 | { STB0899_SYNCDCSTL , 0x00 }, |
1079 | { STB0899_ISI_ENTRY , 0x00 }, |
1080 | { STB0899_ISI_BIT_EN , 0x00 }, |
1081 | { STB0899_MATSTRM , 0x00 }, |
1082 | { STB0899_MATSTRL , 0x00 }, |
1083 | { STB0899_UPLSTRM , 0x00 }, |
1084 | { STB0899_UPLSTRL , 0x00 }, |
1085 | { STB0899_DFLSTRM , 0x00 }, |
1086 | { STB0899_DFLSTRL , 0x00 }, |
1087 | { STB0899_SYNCSTR , 0x00 }, |
1088 | { STB0899_SYNCDSTRM , 0x00 }, |
1089 | { STB0899_SYNCDSTRL , 0x00 }, |
1090 | { STB0899_CFGPDELSTATUS1 , 0x10 }, |
1091 | { STB0899_CFGPDELSTATUS2 , 0x00 }, |
1092 | { STB0899_BBFERRORM , 0x00 }, |
1093 | { STB0899_BBFERRORL , 0x00 }, |
1094 | { STB0899_UPKTERRORM , 0x00 }, |
1095 | { STB0899_UPKTERRORL , 0x00 }, |
1096 | { 0xffff , 0xff }, |
1097 | }; |
1098 | |
1099 | /* STB0899 demodulator config for the KNC1 and clones */ |
1100 | static struct stb0899_config knc1_dvbs2_config = { |
1101 | .init_dev = knc1_stb0899_s1_init_1, |
1102 | .init_s2_demod = stb0899_s2_init_2, |
1103 | .init_s1_demod = knc1_stb0899_s1_init_3, |
1104 | .init_s2_fec = stb0899_s2_init_4, |
1105 | .init_tst = stb0899_s1_init_5, |
1106 | |
1107 | .postproc = NULL, |
1108 | |
1109 | .demod_address = 0x68, |
1110 | // .ts_output_mode = STB0899_OUT_PARALLEL, /* types = SERIAL/PARALLEL */ |
1111 | .block_sync_mode = STB0899_SYNC_FORCED, /* DSS, SYNC_FORCED/UNSYNCED */ |
1112 | // .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */ |
1113 | |
1114 | .xtal_freq = 27000000, |
1115 | .inversion = IQ_SWAP_OFF, |
1116 | |
1117 | .lo_clk = 76500000, |
1118 | .hi_clk = 90000000, |
1119 | |
1120 | .esno_ave = STB0899_DVBS2_ESNO_AVE, |
1121 | .esno_quant = STB0899_DVBS2_ESNO_QUANT, |
1122 | .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, |
1123 | .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, |
1124 | .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, |
1125 | .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, |
1126 | .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, |
1127 | .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, |
1128 | .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, |
1129 | |
1130 | .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, |
1131 | .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, |
1132 | .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, |
1133 | .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, |
1134 | |
1135 | .tuner_get_frequency = tda8261_get_frequency, |
1136 | .tuner_set_frequency = tda8261_set_frequency, |
1137 | .tuner_set_bandwidth = NULL, |
1138 | .tuner_get_bandwidth = tda8261_get_bandwidth, |
1139 | .tuner_set_rfsiggain = NULL |
1140 | }; |
1141 | |
1142 | /* |
1143 | * SD1878/SHA tuner config |
1144 | * 1F, Single I/P, Horizontal mount, High Sensitivity |
1145 | */ |
1146 | static const struct tda8261_config sd1878c_config = { |
1147 | // .name = "SD1878/SHA", |
1148 | .addr = 0x60, |
1149 | .step_size = TDA8261_STEP_1000 /* kHz */ |
1150 | }; |
1151 | |
1152 | static u8 read_pwm(struct budget_av *budget_av) |
1153 | { |
1154 | u8 b = 0xff; |
1155 | u8 pwm; |
1156 | struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, |
1157 | {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} |
1158 | }; |
1159 | |
1160 | if ((i2c_transfer(adap: &budget_av->budget.i2c_adap, msgs: msg, num: 2) != 2) |
1161 | || (pwm == 0xff)) |
1162 | pwm = 0x48; |
1163 | |
1164 | return pwm; |
1165 | } |
1166 | |
1167 | #define SUBID_DVBS_KNC1 0x0010 |
1168 | #define SUBID_DVBS_KNC1_PLUS 0x0011 |
1169 | #define SUBID_DVBS_TYPHOON 0x4f56 |
1170 | #define SUBID_DVBS_CINERGY1200 0x1154 |
1171 | #define SUBID_DVBS_CYNERGY1200N 0x1155 |
1172 | #define SUBID_DVBS_TV_STAR 0x0014 |
1173 | #define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015 |
1174 | #define SUBID_DVBS_TV_STAR_CI 0x0016 |
1175 | #define SUBID_DVBS2_KNC1 0x0018 |
1176 | #define SUBID_DVBS2_KNC1_OEM 0x0019 |
1177 | #define SUBID_DVBS_EASYWATCH_1 0x001a |
1178 | #define SUBID_DVBS_EASYWATCH_2 0x001b |
1179 | #define SUBID_DVBS2_EASYWATCH 0x001d |
1180 | #define SUBID_DVBS_EASYWATCH 0x001e |
1181 | |
1182 | #define SUBID_DVBC_EASYWATCH 0x002a |
1183 | #define SUBID_DVBC_EASYWATCH_MK3 0x002c |
1184 | #define SUBID_DVBC_KNC1 0x0020 |
1185 | #define SUBID_DVBC_KNC1_PLUS 0x0021 |
1186 | #define SUBID_DVBC_KNC1_MK3 0x0022 |
1187 | #define SUBID_DVBC_KNC1_TDA10024 0x0028 |
1188 | #define SUBID_DVBC_KNC1_PLUS_MK3 0x0023 |
1189 | #define SUBID_DVBC_CINERGY1200 0x1156 |
1190 | #define SUBID_DVBC_CINERGY1200_MK3 0x1176 |
1191 | |
1192 | #define SUBID_DVBT_EASYWATCH 0x003a |
1193 | #define SUBID_DVBT_KNC1_PLUS 0x0031 |
1194 | #define SUBID_DVBT_KNC1 0x0030 |
1195 | #define SUBID_DVBT_CINERGY1200 0x1157 |
1196 | |
1197 | static void frontend_init(struct budget_av *budget_av) |
1198 | { |
1199 | struct saa7146_dev * saa = budget_av->budget.dev; |
1200 | struct dvb_frontend * fe = NULL; |
1201 | |
1202 | /* Enable / PowerON Frontend */ |
1203 | saa7146_setgpio(dev: saa, port: 0, SAA7146_GPIO_OUTLO); |
1204 | |
1205 | /* Wait for PowerON */ |
1206 | msleep(msecs: 100); |
1207 | |
1208 | /* additional setup necessary for the PLUS cards */ |
1209 | switch (saa->pci->subsystem_device) { |
1210 | case SUBID_DVBS_KNC1_PLUS: |
1211 | case SUBID_DVBC_KNC1_PLUS: |
1212 | case SUBID_DVBT_KNC1_PLUS: |
1213 | case SUBID_DVBC_EASYWATCH: |
1214 | case SUBID_DVBC_KNC1_PLUS_MK3: |
1215 | case SUBID_DVBS2_KNC1: |
1216 | case SUBID_DVBS2_KNC1_OEM: |
1217 | case SUBID_DVBS2_EASYWATCH: |
1218 | saa7146_setgpio(dev: saa, port: 3, SAA7146_GPIO_OUTHI); |
1219 | break; |
1220 | } |
1221 | |
1222 | switch (saa->pci->subsystem_device) { |
1223 | |
1224 | case SUBID_DVBS_KNC1: |
1225 | /* |
1226 | * maybe that setting is needed for other dvb-s cards as well, |
1227 | * but so far it has been only confirmed for this type |
1228 | */ |
1229 | budget_av->reinitialise_demod = 1; |
1230 | fallthrough; |
1231 | case SUBID_DVBS_KNC1_PLUS: |
1232 | case SUBID_DVBS_EASYWATCH_1: |
1233 | if (saa->pci->subsystem_vendor == 0x1894) { |
1234 | fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config, |
1235 | &budget_av->budget.i2c_adap); |
1236 | if (fe) { |
1237 | dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap); |
1238 | } |
1239 | } else { |
1240 | fe = dvb_attach(stv0299_attach, &typhoon_config, |
1241 | &budget_av->budget.i2c_adap); |
1242 | if (fe) { |
1243 | fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; |
1244 | } |
1245 | } |
1246 | break; |
1247 | |
1248 | case SUBID_DVBS_TV_STAR: |
1249 | case SUBID_DVBS_TV_STAR_PLUS_X4: |
1250 | case SUBID_DVBS_TV_STAR_CI: |
1251 | case SUBID_DVBS_CYNERGY1200N: |
1252 | case SUBID_DVBS_EASYWATCH: |
1253 | case SUBID_DVBS_EASYWATCH_2: |
1254 | fe = dvb_attach(stv0299_attach, &philips_sd1878_config, |
1255 | &budget_av->budget.i2c_adap); |
1256 | if (fe) { |
1257 | dvb_attach(dvb_pll_attach, fe, 0x60, |
1258 | &budget_av->budget.i2c_adap, |
1259 | DVB_PLL_PHILIPS_SD1878_TDA8261); |
1260 | } |
1261 | break; |
1262 | |
1263 | case SUBID_DVBS_TYPHOON: |
1264 | fe = dvb_attach(stv0299_attach, &typhoon_config, |
1265 | &budget_av->budget.i2c_adap); |
1266 | if (fe) { |
1267 | fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; |
1268 | } |
1269 | break; |
1270 | case SUBID_DVBS2_KNC1: |
1271 | case SUBID_DVBS2_KNC1_OEM: |
1272 | case SUBID_DVBS2_EASYWATCH: |
1273 | budget_av->reinitialise_demod = 1; |
1274 | if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap))) |
1275 | dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap); |
1276 | |
1277 | break; |
1278 | case SUBID_DVBS_CINERGY1200: |
1279 | fe = dvb_attach(stv0299_attach, &cinergy_1200s_config, |
1280 | &budget_av->budget.i2c_adap); |
1281 | if (fe) { |
1282 | fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; |
1283 | } |
1284 | break; |
1285 | |
1286 | case SUBID_DVBC_KNC1: |
1287 | case SUBID_DVBC_KNC1_PLUS: |
1288 | case SUBID_DVBC_CINERGY1200: |
1289 | case SUBID_DVBC_EASYWATCH: |
1290 | budget_av->reinitialise_demod = 1; |
1291 | budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; |
1292 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config, |
1293 | &budget_av->budget.i2c_adap, |
1294 | read_pwm(budget_av)); |
1295 | if (fe == NULL) |
1296 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress, |
1297 | &budget_av->budget.i2c_adap, |
1298 | read_pwm(budget_av)); |
1299 | if (fe) { |
1300 | fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; |
1301 | } |
1302 | break; |
1303 | |
1304 | case SUBID_DVBC_EASYWATCH_MK3: |
1305 | case SUBID_DVBC_CINERGY1200_MK3: |
1306 | case SUBID_DVBC_KNC1_MK3: |
1307 | case SUBID_DVBC_KNC1_TDA10024: |
1308 | case SUBID_DVBC_KNC1_PLUS_MK3: |
1309 | budget_av->reinitialise_demod = 1; |
1310 | budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; |
1311 | fe = dvb_attach(tda10023_attach, |
1312 | &philips_cu1216_tda10023_config, |
1313 | &budget_av->budget.i2c_adap, |
1314 | read_pwm(budget_av)); |
1315 | if (fe) { |
1316 | fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; |
1317 | } |
1318 | break; |
1319 | |
1320 | case SUBID_DVBT_EASYWATCH: |
1321 | case SUBID_DVBT_KNC1: |
1322 | case SUBID_DVBT_KNC1_PLUS: |
1323 | case SUBID_DVBT_CINERGY1200: |
1324 | budget_av->reinitialise_demod = 1; |
1325 | fe = dvb_attach(tda10046_attach, &philips_tu1216_config, |
1326 | &budget_av->budget.i2c_adap); |
1327 | if (fe) { |
1328 | fe->ops.tuner_ops.init = philips_tu1216_tuner_init; |
1329 | fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params; |
1330 | } |
1331 | break; |
1332 | } |
1333 | |
1334 | if (fe == NULL) { |
1335 | pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n" , |
1336 | saa->pci->vendor, |
1337 | saa->pci->device, |
1338 | saa->pci->subsystem_vendor, |
1339 | saa->pci->subsystem_device); |
1340 | return; |
1341 | } |
1342 | |
1343 | budget_av->budget.dvb_frontend = fe; |
1344 | |
1345 | if (dvb_register_frontend(dvb: &budget_av->budget.dvb_adapter, |
1346 | fe: budget_av->budget.dvb_frontend)) { |
1347 | pr_err("Frontend registration failed!\n" ); |
1348 | dvb_frontend_detach(fe: budget_av->budget.dvb_frontend); |
1349 | budget_av->budget.dvb_frontend = NULL; |
1350 | } |
1351 | } |
1352 | |
1353 | |
1354 | static void budget_av_irq(struct saa7146_dev *dev, u32 * isr) |
1355 | { |
1356 | struct budget_av *budget_av = dev->ext_priv; |
1357 | |
1358 | dprintk(8, "dev: %p, budget_av: %p\n" , dev, budget_av); |
1359 | |
1360 | if (*isr & MASK_10) |
1361 | ttpci_budget_irq10_handler(dev, isr); |
1362 | } |
1363 | |
1364 | static int budget_av_detach(struct saa7146_dev *dev) |
1365 | { |
1366 | struct budget_av *budget_av = dev->ext_priv; |
1367 | int err; |
1368 | |
1369 | dprintk(2, "dev: %p\n" , dev); |
1370 | |
1371 | if (1 == budget_av->has_saa7113) { |
1372 | saa7146_setgpio(dev, port: 0, SAA7146_GPIO_OUTLO); |
1373 | |
1374 | msleep(msecs: 200); |
1375 | |
1376 | saa7146_unregister_device(vid: &budget_av->vd, dev); |
1377 | |
1378 | saa7146_vv_release(dev); |
1379 | } |
1380 | |
1381 | if (budget_av->budget.ci_present) |
1382 | ciintf_deinit(budget_av); |
1383 | |
1384 | if (budget_av->budget.dvb_frontend != NULL) { |
1385 | dvb_unregister_frontend(fe: budget_av->budget.dvb_frontend); |
1386 | dvb_frontend_detach(fe: budget_av->budget.dvb_frontend); |
1387 | } |
1388 | err = ttpci_budget_deinit(budget: &budget_av->budget); |
1389 | |
1390 | kfree(objp: budget_av); |
1391 | |
1392 | return err; |
1393 | } |
1394 | |
1395 | #define KNC1_INPUTS 2 |
1396 | static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { |
1397 | { 0, "Composite" , V4L2_INPUT_TYPE_TUNER, 1, 0, |
1398 | V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
1399 | { 1, "S-Video" , V4L2_INPUT_TYPE_CAMERA, 2, 0, |
1400 | V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
1401 | }; |
1402 | |
1403 | static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) |
1404 | { |
1405 | dprintk(1, "VIDIOC_ENUMINPUT %d\n" , i->index); |
1406 | if (i->index >= KNC1_INPUTS) |
1407 | return -EINVAL; |
1408 | memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); |
1409 | return 0; |
1410 | } |
1411 | |
1412 | static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) |
1413 | { |
1414 | struct saa7146_dev *dev = video_drvdata(file); |
1415 | struct budget_av *budget_av = dev->ext_priv; |
1416 | |
1417 | *i = budget_av->cur_input; |
1418 | |
1419 | dprintk(1, "VIDIOC_G_INPUT %d\n" , *i); |
1420 | return 0; |
1421 | } |
1422 | |
1423 | static int vidioc_s_input(struct file *file, void *fh, unsigned int input) |
1424 | { |
1425 | struct saa7146_dev *dev = video_drvdata(file); |
1426 | struct budget_av *budget_av = dev->ext_priv; |
1427 | |
1428 | dprintk(1, "VIDIOC_S_INPUT %d\n" , input); |
1429 | return saa7113_setinput(budget_av, input); |
1430 | } |
1431 | |
1432 | static struct saa7146_ext_vv vv_data; |
1433 | |
1434 | static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
1435 | { |
1436 | struct budget_av *budget_av; |
1437 | u8 *mac; |
1438 | int err; |
1439 | |
1440 | dprintk(2, "dev: %p\n" , dev); |
1441 | |
1442 | if (!(budget_av = kzalloc(size: sizeof(struct budget_av), GFP_KERNEL))) |
1443 | return -ENOMEM; |
1444 | |
1445 | budget_av->has_saa7113 = 0; |
1446 | budget_av->budget.ci_present = 0; |
1447 | |
1448 | dev->ext_priv = budget_av; |
1449 | |
1450 | err = ttpci_budget_init(budget: &budget_av->budget, dev, info, THIS_MODULE, |
1451 | adapter_nums: adapter_nr); |
1452 | if (err) { |
1453 | kfree(objp: budget_av); |
1454 | return err; |
1455 | } |
1456 | |
1457 | /* knc1 initialization */ |
1458 | saa7146_write(dev, DD1_STREAM_B, 0x04000000); |
1459 | saa7146_write(dev, DD1_INIT, 0x07000600); |
1460 | saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); |
1461 | |
1462 | if (saa7113_init(budget_av) == 0) { |
1463 | budget_av->has_saa7113 = 1; |
1464 | err = saa7146_vv_init(dev, ext_vv: &vv_data); |
1465 | if (err != 0) { |
1466 | ttpci_budget_deinit(budget: &budget_av->budget); |
1467 | kfree(objp: budget_av); |
1468 | ERR("cannot init vv subsystem\n" ); |
1469 | return err; |
1470 | } |
1471 | vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input; |
1472 | vv_data.vid_ops.vidioc_g_input = vidioc_g_input; |
1473 | vv_data.vid_ops.vidioc_s_input = vidioc_s_input; |
1474 | |
1475 | if ((err = saa7146_register_device(vid: &budget_av->vd, dev, name: "knc1" , type: VFL_TYPE_VIDEO))) { |
1476 | saa7146_vv_release(dev); |
1477 | ttpci_budget_deinit(budget: &budget_av->budget); |
1478 | kfree(objp: budget_av); |
1479 | ERR("cannot register capture v4l2 device\n" ); |
1480 | return err; |
1481 | } |
1482 | |
1483 | /* beware: this modifies dev->vv ... */ |
1484 | saa7146_set_hps_source_and_sync(saa: dev, SAA7146_HPS_SOURCE_PORT_A, |
1485 | SAA7146_HPS_SYNC_PORT_A); |
1486 | |
1487 | saa7113_setinput(budget_av, input: 0); |
1488 | } |
1489 | |
1490 | /* fixme: find some sane values here... */ |
1491 | saa7146_write(dev, PCI_BT_V1, 0x1c00101f); |
1492 | |
1493 | mac = budget_av->budget.dvb_adapter.proposed_mac; |
1494 | if (i2c_readregs(i2c: &budget_av->budget.i2c_adap, id: 0xa0, reg: 0x30, buf: mac, len: 6)) { |
1495 | pr_err("KNC1-%d: Could not read MAC from KNC1 card\n" , |
1496 | budget_av->budget.dvb_adapter.num); |
1497 | eth_zero_addr(addr: mac); |
1498 | } else { |
1499 | pr_info("KNC1-%d: MAC addr = %pM\n" , |
1500 | budget_av->budget.dvb_adapter.num, mac); |
1501 | } |
1502 | |
1503 | budget_av->budget.dvb_adapter.priv = budget_av; |
1504 | frontend_init(budget_av); |
1505 | ciintf_init(budget_av); |
1506 | |
1507 | ttpci_budget_init_hooks(budget: &budget_av->budget); |
1508 | |
1509 | return 0; |
1510 | } |
1511 | |
1512 | static struct saa7146_standard standard[] = { |
1513 | {.name = "PAL" ,.id = V4L2_STD_PAL, |
1514 | .v_offset = 0x17,.v_field = 288, |
1515 | .h_offset = 0x14,.h_pixels = 680, |
1516 | .v_max_out = 576,.h_max_out = 768 }, |
1517 | |
1518 | {.name = "NTSC" ,.id = V4L2_STD_NTSC, |
1519 | .v_offset = 0x16,.v_field = 240, |
1520 | .h_offset = 0x06,.h_pixels = 708, |
1521 | .v_max_out = 480,.h_max_out = 640, }, |
1522 | }; |
1523 | |
1524 | static struct saa7146_ext_vv vv_data = { |
1525 | .inputs = 2, |
1526 | .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113 |
1527 | .flags = 0, |
1528 | .stds = &standard[0], |
1529 | .num_stds = ARRAY_SIZE(standard), |
1530 | }; |
1531 | |
1532 | static struct saa7146_extension budget_extension; |
1533 | |
1534 | MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S" , BUDGET_KNC1S); |
1535 | MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2" , BUDGET_KNC1S2); |
1536 | MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2" , BUDGET_KNC1S2); |
1537 | MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C" , BUDGET_KNC1C); |
1538 | MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T" , BUDGET_KNC1T); |
1539 | MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S" , BUDGET_TVSTAR); |
1540 | MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light" , BUDGET_TVSTAR); |
1541 | MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light" , BUDGET_KNC1S); |
1542 | MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S" , BUDGET_KNC1S); |
1543 | MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C" , BUDGET_KNC1CP); |
1544 | MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3" , BUDGET_KNC1C_MK3); |
1545 | MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T" , BUDGET_KNC1T); |
1546 | MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus" , BUDGET_KNC1SP); |
1547 | MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4" , BUDGET_KNC1SP); |
1548 | MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus" , BUDGET_KNC1CP); |
1549 | MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3" , BUDGET_KNC1C_MK3); |
1550 | MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024" , BUDGET_KNC1C_TDA10024); |
1551 | MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3" , BUDGET_KNC1CP_MK3); |
1552 | MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus" , BUDGET_KNC1TP); |
1553 | MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S" , BUDGET_CIN1200S); |
1554 | MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S" , BUDGET_CIN1200S); |
1555 | MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C" , BUDGET_CIN1200C); |
1556 | MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3" , BUDGET_CIN1200C_MK3); |
1557 | MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T" , BUDGET_CIN1200T); |
1558 | |
1559 | static const struct pci_device_id pci_tbl[] = { |
1560 | MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56), |
1561 | MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010), |
1562 | MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010), |
1563 | MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011), |
1564 | MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011), |
1565 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014), |
1566 | MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015), |
1567 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), |
1568 | MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018), |
1569 | MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019), |
1570 | MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d), |
1571 | MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), |
1572 | MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), |
1573 | MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b), |
1574 | MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), |
1575 | MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c), |
1576 | MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a), |
1577 | MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), |
1578 | MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), |
1579 | MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022), |
1580 | MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028), |
1581 | MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023), |
1582 | MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), |
1583 | MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031), |
1584 | MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154), |
1585 | MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155), |
1586 | MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156), |
1587 | MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176), |
1588 | MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157), |
1589 | { |
1590 | .vendor = 0, |
1591 | } |
1592 | }; |
1593 | |
1594 | MODULE_DEVICE_TABLE(pci, pci_tbl); |
1595 | |
1596 | static struct saa7146_extension budget_extension = { |
1597 | .name = "budget_av" , |
1598 | .flags = SAA7146_USE_I2C_IRQ, |
1599 | |
1600 | .pci_tbl = pci_tbl, |
1601 | |
1602 | .module = THIS_MODULE, |
1603 | .attach = budget_av_attach, |
1604 | .detach = budget_av_detach, |
1605 | |
1606 | .irq_mask = MASK_10, |
1607 | .irq_func = budget_av_irq, |
1608 | }; |
1609 | |
1610 | static int __init budget_av_init(void) |
1611 | { |
1612 | return saa7146_register_extension(&budget_extension); |
1613 | } |
1614 | |
1615 | static void __exit budget_av_exit(void) |
1616 | { |
1617 | saa7146_unregister_extension(&budget_extension); |
1618 | } |
1619 | |
1620 | module_init(budget_av_init); |
1621 | module_exit(budget_av_exit); |
1622 | |
1623 | MODULE_LICENSE("GPL" ); |
1624 | MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others" ); |
1625 | MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)" ); |
1626 | |