diff options
author | Matthias Benesch <twoof7@freenet.de> | 2009-12-18 20:13:26 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:10:53 -0500 |
commit | dae52d009fc950b5c209260d50fcc000f5becd3c (patch) | |
tree | bc871578fd78a0a23c1613dec21c2eb4853c6346 /drivers/media/dvb | |
parent | c22425ffa10792e2e8aba321dded98a5867d2a86 (diff) |
V4L/DVB: ngene: Initial check-in
Add Micronas nGene PCIe bridge driver.
The source code was provided by Micronas / Ralph Metzler,
and has been reformatted to comply with Linux Codingstyle.
Signed-off-by: Matthias Benesch <twoof7@freenet.de>
Signed-off-by: Ralph Metzler <rjkm@metzlerbros.de>
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/ngene/ngene-core.c | 4062 | ||||
-rw-r--r-- | drivers/media/dvb/ngene/ngene-ioctls.h | 216 | ||||
-rw-r--r-- | drivers/media/dvb/ngene/ngene-snd.c | 421 | ||||
-rw-r--r-- | drivers/media/dvb/ngene/ngene-v4l2.c | 1937 | ||||
-rw-r--r-- | drivers/media/dvb/ngene/ngene.h | 948 |
5 files changed, 7584 insertions, 0 deletions
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c new file mode 100644 index 000000000000..744a232bd100 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-core.c | |||
@@ -0,0 +1,4062 @@ | |||
1 | /* | ||
2 | * ngene.c: nGene PCIe bridge driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * Modifications for new nGene firmware, | ||
8 | * support for EEPROM-copying, | ||
9 | * support for new dual DVB-S2 card prototype | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 only, as published by the Free Software Foundation. | ||
15 | * | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
26 | * 02110-1301, USA | ||
27 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/div64.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/pci_ids.h> | ||
39 | #include <linux/smp_lock.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <linux/version.h> | ||
42 | #include <linux/byteorder/generic.h> | ||
43 | #include <linux/firmware.h> | ||
44 | |||
45 | #include "ngene.h" | ||
46 | |||
47 | #ifdef NGENE_COMMAND_API | ||
48 | #include "ngene-ioctls.h" | ||
49 | #endif | ||
50 | |||
51 | #define FW_INC 1 | ||
52 | #ifdef FW_INC | ||
53 | #include "ngene_fw_15.h" | ||
54 | #include "ngene_fw_16.h" | ||
55 | #include "ngene_fw_17.h" | ||
56 | |||
57 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
58 | |||
59 | static int load_firmware; | ||
60 | module_param(load_firmware, int, 0444); | ||
61 | MODULE_PARM_DESC(load_firmware, "Try to load firmware from file."); | ||
62 | #endif | ||
63 | |||
64 | static int copy_eeprom; | ||
65 | module_param(copy_eeprom, int, 0444); | ||
66 | MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); | ||
67 | |||
68 | static int ngene_fw_debug; | ||
69 | module_param(ngene_fw_debug, int, 0444); | ||
70 | MODULE_PARM_DESC(ngene_fw_debug, "Debug firmware."); | ||
71 | |||
72 | static int debug; | ||
73 | module_param(debug, int, 0444); | ||
74 | MODULE_PARM_DESC(debug, "Print debugging information."); | ||
75 | |||
76 | #define dprintk if (debug) printk | ||
77 | |||
78 | #define DEVICE_NAME "ngene" | ||
79 | |||
80 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | ||
81 | #define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) | ||
82 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | ||
83 | #define ngreadl(adr) readl(dev->iomem + (adr)) | ||
84 | #define ngreadb(adr) readb(dev->iomem + (adr)) | ||
85 | #define ngcpyto(adr, src, count) memcpy_toio((char *) \ | ||
86 | (dev->iomem + (adr)), (src), (count)) | ||
87 | #define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ | ||
88 | (dev->iomem + (adr)), (count)) | ||
89 | |||
90 | /****************************************************************************/ | ||
91 | /* Functions with missing kernel exports ************************************/ | ||
92 | /****************************************************************************/ | ||
93 | |||
94 | /* yeah, let's throw out all exports which are not used in kernel ... */ | ||
95 | |||
96 | void my_dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) | ||
97 | { | ||
98 | rbuf->pread = rbuf->pwrite; | ||
99 | rbuf->error = 0; | ||
100 | } | ||
101 | |||
102 | /****************************************************************************/ | ||
103 | /* nGene interrupt handler **************************************************/ | ||
104 | /****************************************************************************/ | ||
105 | |||
106 | static void event_tasklet(unsigned long data) | ||
107 | { | ||
108 | struct ngene *dev = (struct ngene *)data; | ||
109 | |||
110 | while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) { | ||
111 | struct EVENT_BUFFER Event = | ||
112 | dev->EventQueue[dev->EventQueueReadIndex]; | ||
113 | dev->EventQueueReadIndex = | ||
114 | (dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1); | ||
115 | |||
116 | if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify)) | ||
117 | dev->TxEventNotify(dev, Event.TimeStamp); | ||
118 | if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) | ||
119 | dev->RxEventNotify(dev, Event.TimeStamp, | ||
120 | Event.RXCharacter); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void demux_tasklet(unsigned long data) | ||
125 | { | ||
126 | struct ngene_channel *chan = (struct ngene_channel *)data; | ||
127 | struct SBufferHeader *Cur = chan->nextBuffer; | ||
128 | |||
129 | spin_lock_irq(&chan->state_lock); | ||
130 | |||
131 | while (Cur->ngeneBuffer.SR.Flags & 0x80) { | ||
132 | if (chan->mode & NGENE_IO_TSOUT) { | ||
133 | u32 Flags = chan->DataFormatFlags; | ||
134 | if (Cur->ngeneBuffer.SR.Flags & 0x20) | ||
135 | Flags |= BEF_OVERFLOW; | ||
136 | if (chan->pBufferExchange) { | ||
137 | if (!chan->pBufferExchange(chan, | ||
138 | Cur->Buffer1, | ||
139 | chan->Capture1Length, | ||
140 | Cur->ngeneBuffer.SR. | ||
141 | Clock, Flags)) { | ||
142 | /* | ||
143 | We didn't get data | ||
144 | Clear in service flag to make sure we | ||
145 | get called on next interrupt again. | ||
146 | leave fill/empty (0x80) flag alone | ||
147 | to avoid hardware running out of | ||
148 | buffers during startup, we hold only | ||
149 | in run state ( the source may be late | ||
150 | delivering data ) | ||
151 | */ | ||
152 | |||
153 | if (chan->HWState == HWSTATE_RUN) { | ||
154 | Cur->ngeneBuffer.SR.Flags &= | ||
155 | ~0x40; | ||
156 | break; | ||
157 | /* Stop proccessing stream */ | ||
158 | } | ||
159 | } else { | ||
160 | /* We got a valid buffer, | ||
161 | so switch to run state */ | ||
162 | chan->HWState = HWSTATE_RUN; | ||
163 | } | ||
164 | } else { | ||
165 | printk(KERN_ERR DEVICE_NAME ": OOPS\n"); | ||
166 | if (chan->HWState == HWSTATE_RUN) { | ||
167 | Cur->ngeneBuffer.SR.Flags &= ~0x40; | ||
168 | break; /* Stop proccessing stream */ | ||
169 | } | ||
170 | } | ||
171 | if (chan->AudioDTOUpdated) { | ||
172 | printk(KERN_INFO DEVICE_NAME | ||
173 | ": Update AudioDTO = %d\n", | ||
174 | chan->AudioDTOValue); | ||
175 | Cur->ngeneBuffer.SR.DTOUpdate = | ||
176 | chan->AudioDTOValue; | ||
177 | chan->AudioDTOUpdated = 0; | ||
178 | } | ||
179 | } else { | ||
180 | if (chan->HWState == HWSTATE_RUN) { | ||
181 | u32 Flags = 0; | ||
182 | if (Cur->ngeneBuffer.SR.Flags & 0x01) | ||
183 | Flags |= BEF_EVEN_FIELD; | ||
184 | if (Cur->ngeneBuffer.SR.Flags & 0x20) | ||
185 | Flags |= BEF_OVERFLOW; | ||
186 | if (chan->pBufferExchange) | ||
187 | chan->pBufferExchange(chan, | ||
188 | Cur->Buffer1, | ||
189 | chan-> | ||
190 | Capture1Length, | ||
191 | Cur->ngeneBuffer. | ||
192 | SR.Clock, Flags); | ||
193 | if (chan->pBufferExchange2) | ||
194 | chan->pBufferExchange2(chan, | ||
195 | Cur->Buffer2, | ||
196 | chan-> | ||
197 | Capture2Length, | ||
198 | Cur->ngeneBuffer. | ||
199 | SR.Clock, Flags); | ||
200 | } else if (chan->HWState != HWSTATE_STOP) | ||
201 | chan->HWState = HWSTATE_RUN; | ||
202 | } | ||
203 | Cur->ngeneBuffer.SR.Flags = 0x00; | ||
204 | Cur = Cur->Next; | ||
205 | } | ||
206 | chan->nextBuffer = Cur; | ||
207 | |||
208 | spin_unlock_irq(&chan->state_lock); | ||
209 | } | ||
210 | |||
211 | static irqreturn_t irq_handler(int irq, void *dev_id) | ||
212 | { | ||
213 | struct ngene *dev = (struct ngene *)dev_id; | ||
214 | u32 icounts = 0; | ||
215 | irqreturn_t rc = IRQ_NONE; | ||
216 | u32 i = MAX_STREAM; | ||
217 | u8 *tmpCmdDoneByte; | ||
218 | |||
219 | if (dev->BootFirmware) { | ||
220 | icounts = ngreadl(NGENE_INT_COUNTS); | ||
221 | if (icounts != dev->icounts) { | ||
222 | ngwritel(0, FORCE_NMI); | ||
223 | dev->cmd_done = 1; | ||
224 | wake_up(&dev->cmd_wq); | ||
225 | dev->icounts = icounts; | ||
226 | rc = IRQ_HANDLED; | ||
227 | } | ||
228 | return rc; | ||
229 | } | ||
230 | |||
231 | ngwritel(0, FORCE_NMI); | ||
232 | |||
233 | spin_lock(&dev->cmd_lock); | ||
234 | tmpCmdDoneByte = dev->CmdDoneByte; | ||
235 | if (tmpCmdDoneByte && | ||
236 | (*tmpCmdDoneByte || | ||
237 | (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) { | ||
238 | dev->CmdDoneByte = NULL; | ||
239 | dev->cmd_done = 1; | ||
240 | wake_up(&dev->cmd_wq); | ||
241 | rc = IRQ_HANDLED; | ||
242 | } | ||
243 | spin_unlock(&dev->cmd_lock); | ||
244 | |||
245 | if (dev->EventBuffer->EventStatus & 0x80) { | ||
246 | u8 nextWriteIndex = | ||
247 | (dev->EventQueueWriteIndex + 1) & | ||
248 | (EVENT_QUEUE_SIZE - 1); | ||
249 | if (nextWriteIndex != dev->EventQueueReadIndex) { | ||
250 | dev->EventQueue[dev->EventQueueWriteIndex] = | ||
251 | *(dev->EventBuffer); | ||
252 | dev->EventQueueWriteIndex = nextWriteIndex; | ||
253 | } else { | ||
254 | printk(KERN_ERR DEVICE_NAME ": event overflow\n"); | ||
255 | dev->EventQueueOverflowCount += 1; | ||
256 | dev->EventQueueOverflowFlag = 1; | ||
257 | } | ||
258 | dev->EventBuffer->EventStatus &= ~0x80; | ||
259 | tasklet_schedule(&dev->event_tasklet); | ||
260 | rc = IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | while (i > 0) { | ||
264 | i--; | ||
265 | spin_lock(&dev->channel[i].state_lock); | ||
266 | /* if (dev->channel[i].State>=KSSTATE_RUN) { */ | ||
267 | if (dev->channel[i].nextBuffer) { | ||
268 | if ((dev->channel[i].nextBuffer-> | ||
269 | ngeneBuffer.SR.Flags & 0xC0) == 0x80) { | ||
270 | dev->channel[i].nextBuffer-> | ||
271 | ngeneBuffer.SR.Flags |= 0x40; | ||
272 | tasklet_schedule( | ||
273 | &dev->channel[i].demux_tasklet); | ||
274 | rc = IRQ_HANDLED; | ||
275 | } | ||
276 | } | ||
277 | spin_unlock(&dev->channel[i].state_lock); | ||
278 | } | ||
279 | |||
280 | return rc; | ||
281 | } | ||
282 | |||
283 | /****************************************************************************/ | ||
284 | /* nGene command interface **************************************************/ | ||
285 | /****************************************************************************/ | ||
286 | |||
287 | static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) | ||
288 | { | ||
289 | int ret; | ||
290 | u8 *tmpCmdDoneByte; | ||
291 | |||
292 | dev->cmd_done = 0; | ||
293 | |||
294 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) { | ||
295 | dev->BootFirmware = 1; | ||
296 | dev->icounts = ngreadl(NGENE_INT_COUNTS); | ||
297 | ngwritel(0, NGENE_COMMAND); | ||
298 | ngwritel(0, NGENE_COMMAND_HI); | ||
299 | ngwritel(0, NGENE_STATUS); | ||
300 | ngwritel(0, NGENE_STATUS_HI); | ||
301 | ngwritel(0, NGENE_EVENT); | ||
302 | ngwritel(0, NGENE_EVENT_HI); | ||
303 | } else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) { | ||
304 | u64 fwio = dev->PAFWInterfaceBuffer; | ||
305 | |||
306 | ngwritel(fwio & 0xffffffff, NGENE_COMMAND); | ||
307 | ngwritel(fwio >> 32, NGENE_COMMAND_HI); | ||
308 | ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS); | ||
309 | ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI); | ||
310 | ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT); | ||
311 | ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI); | ||
312 | } | ||
313 | |||
314 | memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2); | ||
315 | |||
316 | if (dev->BootFirmware) | ||
317 | ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2); | ||
318 | |||
319 | spin_lock_irq(&dev->cmd_lock); | ||
320 | tmpCmdDoneByte = dev->ngenetohost + com->out_len; | ||
321 | if (!com->out_len) | ||
322 | tmpCmdDoneByte++; | ||
323 | *tmpCmdDoneByte = 0; | ||
324 | dev->ngenetohost[0] = 0; | ||
325 | dev->ngenetohost[1] = 0; | ||
326 | dev->CmdDoneByte = tmpCmdDoneByte; | ||
327 | spin_unlock_irq(&dev->cmd_lock); | ||
328 | |||
329 | /* Notify 8051. */ | ||
330 | ngwritel(1, FORCE_INT); | ||
331 | |||
332 | ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); | ||
333 | if (!ret) { | ||
334 | /*ngwritel(0, FORCE_NMI);*/ | ||
335 | |||
336 | printk(KERN_ERR DEVICE_NAME | ||
337 | ": Command timeout cmd=%02x prev=%02x\n", | ||
338 | com->cmd.hdr.Opcode, dev->prev_cmd); | ||
339 | return -1; | ||
340 | } | ||
341 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) | ||
342 | dev->BootFirmware = 0; | ||
343 | |||
344 | dev->prev_cmd = com->cmd.hdr.Opcode; | ||
345 | msleep(10); | ||
346 | |||
347 | if (!com->out_len) | ||
348 | return 0; | ||
349 | |||
350 | memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int ngene_command(struct ngene *dev, struct ngene_command *com) | ||
356 | { | ||
357 | int result; | ||
358 | |||
359 | down(&dev->cmd_mutex); | ||
360 | result = ngene_command_mutex(dev, com); | ||
361 | up(&dev->cmd_mutex); | ||
362 | return result; | ||
363 | } | ||
364 | |||
365 | int ngene_command_nop(struct ngene *dev) | ||
366 | { | ||
367 | struct ngene_command com; | ||
368 | |||
369 | com.cmd.hdr.Opcode = CMD_NOP; | ||
370 | com.cmd.hdr.Length = 0; | ||
371 | com.in_len = 0; | ||
372 | com.out_len = 0; | ||
373 | |||
374 | return ngene_command(dev, &com); | ||
375 | } | ||
376 | |||
377 | int ngene_command_i2c_read(struct ngene *dev, u8 adr, | ||
378 | u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) | ||
379 | { | ||
380 | struct ngene_command com; | ||
381 | |||
382 | com.cmd.hdr.Opcode = CMD_I2C_READ; | ||
383 | com.cmd.hdr.Length = outlen + 3; | ||
384 | com.cmd.I2CRead.Device = adr << 1; | ||
385 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
386 | com.cmd.I2CRead.Data[outlen] = inlen; | ||
387 | com.cmd.I2CRead.Data[outlen + 1] = 0; | ||
388 | com.in_len = outlen + 3; | ||
389 | com.out_len = inlen + 1; | ||
390 | |||
391 | if (ngene_command(dev, &com) < 0) | ||
392 | return -EIO; | ||
393 | |||
394 | if ((com.cmd.raw8[0] >> 1) != adr) | ||
395 | return -EIO; | ||
396 | |||
397 | if (flag) | ||
398 | memcpy(in, com.cmd.raw8, inlen + 1); | ||
399 | else | ||
400 | memcpy(in, com.cmd.raw8 + 1, inlen); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen) | ||
405 | { | ||
406 | struct ngene_command com; | ||
407 | |||
408 | |||
409 | com.cmd.hdr.Opcode = CMD_I2C_WRITE; | ||
410 | com.cmd.hdr.Length = outlen + 1; | ||
411 | com.cmd.I2CRead.Device = adr << 1; | ||
412 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
413 | com.in_len = outlen + 1; | ||
414 | com.out_len = 1; | ||
415 | |||
416 | if (ngene_command(dev, &com) < 0) | ||
417 | return -EIO; | ||
418 | |||
419 | if (com.cmd.raw8[0] == 1) | ||
420 | return -EIO; | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int ngene_command_load_firmware(struct ngene *dev, | ||
426 | u8 *ngene_fw, u32 size) | ||
427 | { | ||
428 | #define FIRSTCHUNK (1024) | ||
429 | u32 cleft; | ||
430 | struct ngene_command com; | ||
431 | |||
432 | com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE; | ||
433 | com.cmd.hdr.Length = 0; | ||
434 | com.in_len = 0; | ||
435 | com.out_len = 0; | ||
436 | |||
437 | ngene_command(dev, &com); | ||
438 | |||
439 | cleft = (size + 3) & ~3; | ||
440 | if (cleft > FIRSTCHUNK) { | ||
441 | ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK, | ||
442 | cleft - FIRSTCHUNK); | ||
443 | cleft = FIRSTCHUNK; | ||
444 | } | ||
445 | ngene_fw[FW_DEBUG_DEFAULT - PROGRAM_SRAM] = ngene_fw_debug; | ||
446 | ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft); | ||
447 | |||
448 | memset(&com, 0, sizeof(struct ngene_command)); | ||
449 | com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH; | ||
450 | com.cmd.hdr.Length = 4; | ||
451 | com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA; | ||
452 | com.cmd.FWLoadFinish.Length = (unsigned short)cleft; | ||
453 | com.in_len = 4; | ||
454 | com.out_len = 0; | ||
455 | |||
456 | return ngene_command(dev, &com); | ||
457 | } | ||
458 | |||
459 | int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) | ||
460 | { | ||
461 | struct ngene_command com; | ||
462 | |||
463 | com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; | ||
464 | com.cmd.hdr.Length = 1; | ||
465 | com.cmd.SfrIramRead.address = adr; | ||
466 | com.in_len = 1; | ||
467 | com.out_len = 2; | ||
468 | |||
469 | if (ngene_command(dev, &com) < 0) | ||
470 | return -EIO; | ||
471 | |||
472 | *data = com.cmd.raw8[1]; | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) | ||
477 | { | ||
478 | struct ngene_command com; | ||
479 | |||
480 | com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; | ||
481 | com.cmd.hdr.Length = 2; | ||
482 | com.cmd.SfrIramWrite.address = adr; | ||
483 | com.cmd.SfrIramWrite.data = data; | ||
484 | com.in_len = 2; | ||
485 | com.out_len = 1; | ||
486 | |||
487 | if (ngene_command(dev, &com) < 0) | ||
488 | return -EIO; | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int ngene_command_config_uart(struct ngene *dev, u8 config, | ||
494 | tx_cb_t *tx_cb, rx_cb_t *rx_cb) | ||
495 | { | ||
496 | struct ngene_command com; | ||
497 | |||
498 | com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; | ||
499 | com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; | ||
500 | com.cmd.ConfigureUart.UartControl = config; | ||
501 | com.in_len = sizeof(struct FW_CONFIGURE_UART); | ||
502 | com.out_len = 0; | ||
503 | |||
504 | if (ngene_command(dev, &com) < 0) | ||
505 | return -EIO; | ||
506 | |||
507 | dev->TxEventNotify = tx_cb; | ||
508 | dev->RxEventNotify = rx_cb; | ||
509 | |||
510 | dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static void tx_cb(struct ngene *dev, u32 ts) | ||
516 | { | ||
517 | dev->tx_busy = 0; | ||
518 | wake_up_interruptible(&dev->tx_wq); | ||
519 | } | ||
520 | |||
521 | static void rx_cb(struct ngene *dev, u32 ts, u8 c) | ||
522 | { | ||
523 | int rp = dev->uart_rp; | ||
524 | int nwp, wp = dev->uart_wp; | ||
525 | |||
526 | /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ | ||
527 | nwp = (wp + 1) % (UART_RBUF_LEN); | ||
528 | if (nwp == rp) | ||
529 | return; | ||
530 | dev->uart_rbuf[wp] = c; | ||
531 | dev->uart_wp = nwp; | ||
532 | wake_up_interruptible(&dev->rx_wq); | ||
533 | } | ||
534 | |||
535 | static int ngene_command_config_buf(struct ngene *dev, u8 config) | ||
536 | { | ||
537 | struct ngene_command com; | ||
538 | |||
539 | com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER; | ||
540 | com.cmd.hdr.Length = 1; | ||
541 | com.cmd.ConfigureBuffers.config = config; | ||
542 | com.in_len = 1; | ||
543 | com.out_len = 0; | ||
544 | |||
545 | if (ngene_command(dev, &com) < 0) | ||
546 | return -EIO; | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) | ||
551 | { | ||
552 | struct ngene_command com; | ||
553 | |||
554 | com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER; | ||
555 | com.cmd.hdr.Length = 6; | ||
556 | memcpy(&com.cmd.ConfigureBuffers.config, config, 6); | ||
557 | com.in_len = 6; | ||
558 | com.out_len = 0; | ||
559 | |||
560 | if (ngene_command(dev, &com) < 0) | ||
561 | return -EIO; | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) | ||
567 | { | ||
568 | struct ngene_command com; | ||
569 | |||
570 | com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN; | ||
571 | com.cmd.hdr.Length = 1; | ||
572 | com.cmd.SetGpioPin.select = select | (level << 7); | ||
573 | com.in_len = 1; | ||
574 | com.out_len = 0; | ||
575 | |||
576 | return ngene_command(dev, &com); | ||
577 | } | ||
578 | |||
579 | /* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! | ||
580 | Also better set bootdelay to 1 in nvram or less. */ | ||
581 | static void ngene_reset_decypher(struct ngene *dev) | ||
582 | { | ||
583 | printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); | ||
584 | ngene_command_gpio_set(dev, 4, 0); | ||
585 | msleep(1); | ||
586 | ngene_command_gpio_set(dev, 4, 1); | ||
587 | msleep(2000); | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | 02000640 is sample on rising edge. | ||
592 | 02000740 is sample on falling edge. | ||
593 | 02000040 is ignore "valid" signal | ||
594 | |||
595 | 0: FD_CTL1 Bit 7,6 must be 0,1 | ||
596 | 7 disable(fw controlled) | ||
597 | 6 0-AUX,1-TS | ||
598 | 5 0-par,1-ser | ||
599 | 4 0-lsb/1-msb | ||
600 | 3,2 reserved | ||
601 | 1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both | ||
602 | 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge | ||
603 | 2: FD_STA is read-only. 0-sync | ||
604 | 3: FD_INSYNC is number of 47s to trigger "in sync". | ||
605 | 4: FD_OUTSYNC is number of 47s to trigger "out of sync". | ||
606 | 5: FD_MAXBYTE1 is low-order of bytes per packet. | ||
607 | 6: FD_MAXBYTE2 is high-order of bytes per packet. | ||
608 | 7: Top byte is unused. | ||
609 | */ | ||
610 | |||
611 | /****************************************************************************/ | ||
612 | |||
613 | static u8 TSFeatureDecoderSetup[8 * 4] = { | ||
614 | 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, | ||
615 | 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ | ||
616 | 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ | ||
617 | 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ | ||
618 | }; | ||
619 | |||
620 | /* Set NGENE I2S Config to 16 bit packed */ | ||
621 | static u8 I2SConfiguration[] = { | ||
622 | 0x00, 0x10, 0x00, 0x00, | ||
623 | 0x80, 0x10, 0x00, 0x00, | ||
624 | }; | ||
625 | |||
626 | static u8 SPDIFConfiguration[10] = { | ||
627 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
628 | }; | ||
629 | |||
630 | /* Set NGENE I2S Config to transport stream compatible mode */ | ||
631 | |||
632 | static u8 TS_I2SConfiguration[4] = { 0x3E, 0x1A, 0x00, 0x00 }; /*3e 18 00 00 ?*/ | ||
633 | |||
634 | static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x20, 0x00, 0x00 }; | ||
635 | |||
636 | static u8 ITUDecoderSetup[4][16] = { | ||
637 | {0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20, /* SDTV */ | ||
638 | 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00}, | ||
639 | {0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, | ||
640 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
641 | {0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00, /* HDTV 1080i50 */ | ||
642 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
643 | {0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, /* HDTV 1080i60 */ | ||
644 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
645 | }; | ||
646 | |||
647 | /* | ||
648 | * 50 48 60 gleich | ||
649 | * 27p50 9f 00 22 80 42 69 18 ... | ||
650 | * 27p60 93 00 22 80 82 69 1c ... | ||
651 | */ | ||
652 | |||
653 | /* Maxbyte to 1144 (for raw data) */ | ||
654 | static u8 ITUFeatureDecoderSetup[8] = { | ||
655 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 | ||
656 | }; | ||
657 | |||
658 | static void FillTSBuffer(void *Buffer, int Length, u32 Flags) | ||
659 | { | ||
660 | u32 *ptr = Buffer; | ||
661 | |||
662 | memset(Buffer, Length, 0xff); | ||
663 | while (Length > 0) { | ||
664 | if (Flags & DF_SWAP32) | ||
665 | *ptr = 0x471FFF10; | ||
666 | else | ||
667 | *ptr = 0x10FF1F47; | ||
668 | ptr += (188 / 4); | ||
669 | Length -= 188; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | static void clear_tsin(struct ngene_channel *chan) | ||
674 | { | ||
675 | struct SBufferHeader *Cur = chan->nextBuffer; | ||
676 | |||
677 | do { | ||
678 | memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); | ||
679 | Cur = Cur->Next; | ||
680 | } while (Cur != chan->nextBuffer); | ||
681 | } | ||
682 | |||
683 | static void flush_buffers(struct ngene_channel *chan) | ||
684 | { | ||
685 | u8 val; | ||
686 | |||
687 | do { | ||
688 | msleep(1); | ||
689 | spin_lock_irq(&chan->state_lock); | ||
690 | val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80; | ||
691 | spin_unlock_irq(&chan->state_lock); | ||
692 | } while (val); | ||
693 | } | ||
694 | |||
695 | static void clear_buffers(struct ngene_channel *chan) | ||
696 | { | ||
697 | struct SBufferHeader *Cur = chan->nextBuffer; | ||
698 | |||
699 | do { | ||
700 | memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); | ||
701 | if (chan->mode & NGENE_IO_TSOUT) | ||
702 | FillTSBuffer(Cur->Buffer1, | ||
703 | chan->Capture1Length, | ||
704 | chan->DataFormatFlags); | ||
705 | Cur = Cur->Next; | ||
706 | } while (Cur != chan->nextBuffer); | ||
707 | |||
708 | if (chan->mode & NGENE_IO_TSOUT) { | ||
709 | chan->nextBuffer->ngeneBuffer.SR.DTOUpdate = | ||
710 | chan->AudioDTOValue; | ||
711 | chan->AudioDTOUpdated = 0; | ||
712 | |||
713 | Cur = chan->TSIdleBuffer.Head; | ||
714 | |||
715 | do { | ||
716 | memset(&Cur->ngeneBuffer.SR, 0, | ||
717 | sizeof(Cur->ngeneBuffer.SR)); | ||
718 | FillTSBuffer(Cur->Buffer1, | ||
719 | chan->Capture1Length, | ||
720 | chan->DataFormatFlags); | ||
721 | Cur = Cur->Next; | ||
722 | } while (Cur != chan->TSIdleBuffer.Head); | ||
723 | } | ||
724 | } | ||
725 | |||
726 | int ngene_command_stream_control(struct ngene *dev, u8 stream, u8 control, | ||
727 | u8 mode, u8 flags) | ||
728 | { | ||
729 | struct ngene_channel *chan = &dev->channel[stream]; | ||
730 | struct ngene_command com; | ||
731 | u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300); | ||
732 | u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500); | ||
733 | u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); | ||
734 | u16 BsSDO = 0x9B00; | ||
735 | |||
736 | /* down(&dev->stream_mutex); */ | ||
737 | while (down_trylock(&dev->stream_mutex)) { | ||
738 | printk(KERN_INFO DEVICE_NAME ": SC locked\n"); | ||
739 | msleep(1); | ||
740 | } | ||
741 | memset(&com, 0, sizeof(com)); | ||
742 | com.cmd.hdr.Opcode = CMD_CONTROL; | ||
743 | com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; | ||
744 | com.cmd.StreamControl.Stream = stream | (control ? 8 : 0); | ||
745 | if (chan->mode & NGENE_IO_TSOUT) | ||
746 | com.cmd.StreamControl.Stream |= 0x07; | ||
747 | com.cmd.StreamControl.Control = control | | ||
748 | (flags & SFLAG_ORDER_LUMA_CHROMA); | ||
749 | com.cmd.StreamControl.Mode = mode; | ||
750 | com.in_len = sizeof(struct FW_STREAM_CONTROL); | ||
751 | com.out_len = 0; | ||
752 | |||
753 | printk(KERN_INFO DEVICE_NAME ": Stream=%02x, Control=%02x, Mode=%02x\n", | ||
754 | com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, | ||
755 | com.cmd.StreamControl.Mode); | ||
756 | chan->Mode = mode; | ||
757 | |||
758 | if (!(control & 0x80)) { | ||
759 | spin_lock_irq(&chan->state_lock); | ||
760 | if (chan->State == KSSTATE_RUN) { | ||
761 | chan->State = KSSTATE_ACQUIRE; | ||
762 | chan->HWState = HWSTATE_STOP; | ||
763 | spin_unlock_irq(&chan->state_lock); | ||
764 | if (ngene_command(dev, &com) < 0) { | ||
765 | up(&dev->stream_mutex); | ||
766 | return -1; | ||
767 | } | ||
768 | /* clear_buffers(chan); */ | ||
769 | flush_buffers(chan); | ||
770 | up(&dev->stream_mutex); | ||
771 | return 0; | ||
772 | } | ||
773 | spin_unlock_irq(&chan->state_lock); | ||
774 | up(&dev->stream_mutex); | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | if (mode & SMODE_AUDIO_CAPTURE) { | ||
779 | com.cmd.StreamControl.CaptureBlockCount = | ||
780 | chan->Capture1Length / AUDIO_BLOCK_SIZE; | ||
781 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; | ||
782 | } else if (mode & SMODE_TRANSPORT_STREAM) { | ||
783 | com.cmd.StreamControl.CaptureBlockCount = | ||
784 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
785 | com.cmd.StreamControl.MaxLinesPerField = | ||
786 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
787 | com.cmd.StreamControl.Buffer_Address = | ||
788 | chan->TSRingBuffer.PAHead; | ||
789 | if (chan->mode & NGENE_IO_TSOUT) { | ||
790 | com.cmd.StreamControl.BytesPerVBILine = | ||
791 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
792 | com.cmd.StreamControl.Stream |= 0x07; | ||
793 | } | ||
794 | } else { | ||
795 | com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine; | ||
796 | com.cmd.StreamControl.MaxLinesPerField = chan->nLines; | ||
797 | com.cmd.StreamControl.MinLinesPerField = 100; | ||
798 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; | ||
799 | |||
800 | if (mode & SMODE_VBI_CAPTURE) { | ||
801 | com.cmd.StreamControl.MaxVBILinesPerField = | ||
802 | chan->nVBILines; | ||
803 | com.cmd.StreamControl.MinVBILinesPerField = 0; | ||
804 | com.cmd.StreamControl.BytesPerVBILine = | ||
805 | chan->nBytesPerVBILine; | ||
806 | } | ||
807 | if (flags & SFLAG_COLORBAR) | ||
808 | com.cmd.StreamControl.Stream |= 0x04; | ||
809 | } | ||
810 | |||
811 | spin_lock_irq(&chan->state_lock); | ||
812 | if (mode & SMODE_AUDIO_CAPTURE) { | ||
813 | chan->nextBuffer = chan->RingBuffer.Head; | ||
814 | if (mode & SMODE_AUDIO_SPDIF) { | ||
815 | com.cmd.StreamControl.SetupDataLen = | ||
816 | sizeof(SPDIFConfiguration); | ||
817 | com.cmd.StreamControl.SetupDataAddr = BsSPI; | ||
818 | memcpy(com.cmd.StreamControl.SetupData, | ||
819 | SPDIFConfiguration, sizeof(SPDIFConfiguration)); | ||
820 | } else { | ||
821 | com.cmd.StreamControl.SetupDataLen = 4; | ||
822 | com.cmd.StreamControl.SetupDataAddr = BsSDI; | ||
823 | memcpy(com.cmd.StreamControl.SetupData, | ||
824 | I2SConfiguration + | ||
825 | 4 * dev->card_info->i2s[stream], 4); | ||
826 | } | ||
827 | } else if (mode & SMODE_TRANSPORT_STREAM) { | ||
828 | chan->nextBuffer = chan->TSRingBuffer.Head; | ||
829 | if (stream >= STREAM_AUDIOIN1) { | ||
830 | if (chan->mode & NGENE_IO_TSOUT) { | ||
831 | com.cmd.StreamControl.SetupDataLen = | ||
832 | sizeof(TS_I2SOutConfiguration); | ||
833 | com.cmd.StreamControl.SetupDataAddr = BsSDO; | ||
834 | memcpy(com.cmd.StreamControl.SetupData, | ||
835 | TS_I2SOutConfiguration, | ||
836 | sizeof(TS_I2SOutConfiguration)); | ||
837 | } else { | ||
838 | com.cmd.StreamControl.SetupDataLen = | ||
839 | sizeof(TS_I2SConfiguration); | ||
840 | com.cmd.StreamControl.SetupDataAddr = BsSDI; | ||
841 | memcpy(com.cmd.StreamControl.SetupData, | ||
842 | TS_I2SConfiguration, | ||
843 | sizeof(TS_I2SConfiguration)); | ||
844 | } | ||
845 | } else { | ||
846 | com.cmd.StreamControl.SetupDataLen = 8; | ||
847 | com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10; | ||
848 | memcpy(com.cmd.StreamControl.SetupData, | ||
849 | TSFeatureDecoderSetup + | ||
850 | 8 * dev->card_info->tsf[stream], 8); | ||
851 | } | ||
852 | } else { | ||
853 | chan->nextBuffer = chan->RingBuffer.Head; | ||
854 | com.cmd.StreamControl.SetupDataLen = | ||
855 | 16 + sizeof(ITUFeatureDecoderSetup); | ||
856 | com.cmd.StreamControl.SetupDataAddr = BsUVI; | ||
857 | memcpy(com.cmd.StreamControl.SetupData, | ||
858 | ITUDecoderSetup[chan->itumode], 16); | ||
859 | memcpy(com.cmd.StreamControl.SetupData + 16, | ||
860 | ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup)); | ||
861 | } | ||
862 | clear_buffers(chan); | ||
863 | chan->State = KSSTATE_RUN; | ||
864 | if (mode & SMODE_TRANSPORT_STREAM) | ||
865 | chan->HWState = HWSTATE_RUN; | ||
866 | else | ||
867 | chan->HWState = HWSTATE_STARTUP; | ||
868 | spin_unlock_irq(&chan->state_lock); | ||
869 | |||
870 | if (ngene_command(dev, &com) < 0) { | ||
871 | up(&dev->stream_mutex); | ||
872 | return -1; | ||
873 | } | ||
874 | up(&dev->stream_mutex); | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, | ||
879 | u16 lines, u16 bpl, u16 vblines, u16 vbibpl) | ||
880 | { | ||
881 | if (!(mode & SMODE_TRANSPORT_STREAM)) | ||
882 | return -EINVAL; | ||
883 | |||
884 | if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) | ||
885 | return -EINVAL; | ||
886 | |||
887 | if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) | ||
888 | return -EINVAL; | ||
889 | |||
890 | if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) | ||
891 | return -EINVAL; | ||
892 | |||
893 | return ngene_command_stream_control(dev, stream, control, mode, 0); | ||
894 | } | ||
895 | |||
896 | /****************************************************************************/ | ||
897 | /* I2C **********************************************************************/ | ||
898 | /****************************************************************************/ | ||
899 | |||
900 | static void ngene_i2c_set_bus(struct ngene *dev, int bus) | ||
901 | { | ||
902 | if (!(dev->card_info->i2c_access & 2)) | ||
903 | return; | ||
904 | if (dev->i2c_current_bus == bus) | ||
905 | return; | ||
906 | |||
907 | switch (bus) { | ||
908 | case 0: | ||
909 | ngene_command_gpio_set(dev, 3, 0); | ||
910 | ngene_command_gpio_set(dev, 2, 1); | ||
911 | break; | ||
912 | |||
913 | case 1: | ||
914 | ngene_command_gpio_set(dev, 2, 0); | ||
915 | ngene_command_gpio_set(dev, 3, 1); | ||
916 | break; | ||
917 | } | ||
918 | dev->i2c_current_bus = bus; | ||
919 | } | ||
920 | |||
921 | static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, | ||
922 | struct i2c_msg msg[], int num) | ||
923 | { | ||
924 | struct ngene_channel *chan = | ||
925 | (struct ngene_channel *)i2c_get_adapdata(adapter); | ||
926 | struct ngene *dev = chan->dev; | ||
927 | |||
928 | down(&dev->i2c_switch_mutex); | ||
929 | ngene_i2c_set_bus(dev, chan->number); | ||
930 | |||
931 | if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) | ||
932 | if (!ngene_command_i2c_read(dev, msg[0].addr, | ||
933 | msg[0].buf, msg[0].len, | ||
934 | msg[1].buf, msg[1].len, 0)) | ||
935 | goto done; | ||
936 | |||
937 | if (num == 1 && !(msg[0].flags & I2C_M_RD)) | ||
938 | if (!ngene_command_i2c_write(dev, msg[0].addr, | ||
939 | msg[0].buf, msg[0].len)) | ||
940 | goto done; | ||
941 | if (num == 1 && (msg[0].flags & I2C_M_RD)) | ||
942 | if (!ngene_command_i2c_read(dev, msg[0].addr, 0, 0, | ||
943 | msg[0].buf, msg[0].len, 0)) | ||
944 | goto done; | ||
945 | |||
946 | up(&dev->i2c_switch_mutex); | ||
947 | return -EIO; | ||
948 | |||
949 | done: | ||
950 | up(&dev->i2c_switch_mutex); | ||
951 | return num; | ||
952 | } | ||
953 | |||
954 | |||
955 | static int ngene_i2c_algo_control(struct i2c_adapter *adap, | ||
956 | unsigned int cmd, unsigned long arg) | ||
957 | { | ||
958 | struct ngene_channel *chan = | ||
959 | (struct ngene_channel *)i2c_get_adapdata(adap); | ||
960 | |||
961 | switch (cmd) { | ||
962 | case IOCTL_MIC_TUN_RDY: | ||
963 | chan->tun_rdy = 1; | ||
964 | if (chan->dec_rdy == 1) | ||
965 | chan->tun_dec_rdy = 1; | ||
966 | break; | ||
967 | |||
968 | case IOCTL_MIC_DEC_RDY: | ||
969 | chan->dec_rdy = 1; | ||
970 | if (chan->tun_rdy == 1) | ||
971 | chan->tun_dec_rdy = 1; | ||
972 | break; | ||
973 | |||
974 | case IOCTL_MIC_TUN_DETECT: | ||
975 | { | ||
976 | int *palorbtsc = (int *)arg; | ||
977 | *palorbtsc = chan->dev->card_info->ntsc; | ||
978 | break; | ||
979 | } | ||
980 | |||
981 | default: | ||
982 | break; | ||
983 | } | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static u32 ngene_i2c_functionality(struct i2c_adapter *adap) | ||
988 | { | ||
989 | return I2C_FUNC_SMBUS_EMUL; | ||
990 | } | ||
991 | |||
992 | struct i2c_algorithm ngene_i2c_algo = { | ||
993 | .master_xfer = ngene_i2c_master_xfer, | ||
994 | .functionality = ngene_i2c_functionality, | ||
995 | }; | ||
996 | |||
997 | static int ngene_i2c_attach(struct i2c_client *client) | ||
998 | { | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static int ngene_i2c_detach(struct i2c_client *client) | ||
1003 | { | ||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int ngene_i2c_init(struct ngene *dev, int dev_nr) | ||
1008 | { | ||
1009 | struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); | ||
1010 | |||
1011 | i2c_set_adapdata(adap, &(dev->channel[dev_nr])); | ||
1012 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
1013 | adap->class = I2C_ADAP_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; | ||
1014 | #else | ||
1015 | adap->class = I2C_CLASS_TV_ANALOG; | ||
1016 | #endif | ||
1017 | |||
1018 | strcpy(adap->name, "nGene"); | ||
1019 | |||
1020 | adap->id = I2C_HW_SAA7146; | ||
1021 | adap->client_register = ngene_i2c_attach; | ||
1022 | adap->client_unregister = ngene_i2c_detach; | ||
1023 | adap->algo = &ngene_i2c_algo; | ||
1024 | adap->algo_data = (void *)&(dev->channel[dev_nr]); | ||
1025 | |||
1026 | mutex_init(&adap->bus_lock); | ||
1027 | return i2c_add_adapter(adap); | ||
1028 | } | ||
1029 | |||
1030 | int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) | ||
1031 | { | ||
1032 | u8 m[1] = {data}; | ||
1033 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; | ||
1034 | |||
1035 | if (i2c_transfer(adapter, &msg, 1) != 1) { | ||
1036 | printk(KERN_ERR DEVICE_NAME | ||
1037 | ": Failed to write to I2C adr %02x!\n", adr); | ||
1038 | return -1; | ||
1039 | } | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | static int i2c_write_register(struct i2c_adapter *adapter, | ||
1044 | u8 adr, u8 reg, u8 data) | ||
1045 | { | ||
1046 | u8 m[2] = {reg, data}; | ||
1047 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; | ||
1048 | |||
1049 | if (i2c_transfer(adapter, &msg, 1) != 1) { | ||
1050 | printk(KERN_ERR DEVICE_NAME | ||
1051 | ": Failed to write to I2C register %02x@%02x!\n", | ||
1052 | reg, adr); | ||
1053 | return -1; | ||
1054 | } | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | static int i2c_write_read(struct i2c_adapter *adapter, | ||
1059 | u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) | ||
1060 | { | ||
1061 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, | ||
1062 | .buf = w, .len = wlen}, | ||
1063 | {.addr = adr, .flags = I2C_M_RD, | ||
1064 | .buf = r, .len = rlen} }; | ||
1065 | |||
1066 | if (i2c_transfer(adapter, msgs, 2) != 2) { | ||
1067 | printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); | ||
1068 | return -1; | ||
1069 | } | ||
1070 | return 0; | ||
1071 | } | ||
1072 | |||
1073 | static int test_dec_i2c(struct i2c_adapter *adapter, int reg) | ||
1074 | { | ||
1075 | u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; | ||
1076 | u8 data2[256]; | ||
1077 | int i; | ||
1078 | |||
1079 | memset(data2, 0, 256); | ||
1080 | i2c_write_read(adapter, 0x66, data, 2, data2, 4); | ||
1081 | for (i = 0; i < 4; i++) | ||
1082 | printk("%02x ", data2[i]); | ||
1083 | printk("\n"); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | /****************************************************************************/ | ||
1090 | /* EEPROM TAGS **************************************************************/ | ||
1091 | /****************************************************************************/ | ||
1092 | |||
1093 | #define MICNG_EE_START 0x0100 | ||
1094 | #define MICNG_EE_END 0x0FF0 | ||
1095 | |||
1096 | #define MICNG_EETAG_END0 0x0000 | ||
1097 | #define MICNG_EETAG_END1 0xFFFF | ||
1098 | |||
1099 | /* 0x0001 - 0x000F reserved for housekeeping */ | ||
1100 | /* 0xFFFF - 0xFFFE reserved for housekeeping */ | ||
1101 | |||
1102 | /* Micronas assigned tags | ||
1103 | EEProm tags for hardware support */ | ||
1104 | |||
1105 | #define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ | ||
1106 | #define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ | ||
1107 | |||
1108 | #define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ | ||
1109 | #define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ | ||
1110 | |||
1111 | /* Tag range for OEMs */ | ||
1112 | |||
1113 | #define MICNG_EETAG_OEM_FIRST 0xC000 | ||
1114 | #define MICNG_EETAG_OEM_LAST 0xFFEF | ||
1115 | |||
1116 | static int i2c_write_eeprom(struct i2c_adapter *adapter, | ||
1117 | u8 adr, u16 reg, u8 data) | ||
1118 | { | ||
1119 | u8 m[3] = {(reg >> 8), (reg & 0xff), data}; | ||
1120 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, | ||
1121 | .len = sizeof(m)}; | ||
1122 | |||
1123 | if (i2c_transfer(adapter, &msg, 1) != 1) { | ||
1124 | dprintk(KERN_DEBUG DEVICE_NAME ": Error writing EEPROM!\n"); | ||
1125 | return -EIO; | ||
1126 | } | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int i2c_read_eeprom(struct i2c_adapter *adapter, | ||
1131 | u8 adr, u16 reg, u8 *data, int len) | ||
1132 | { | ||
1133 | u8 msg[2] = {(reg >> 8), (reg & 0xff)}; | ||
1134 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, | ||
1135 | .buf = msg, .len = 2 }, | ||
1136 | {.addr = adr, .flags = I2C_M_RD, | ||
1137 | .buf = data, .len = len} }; | ||
1138 | |||
1139 | if (i2c_transfer(adapter, msgs, 2) != 2) { | ||
1140 | dprintk(KERN_DEBUG DEVICE_NAME ": Error reading EEPROM\n"); | ||
1141 | return -EIO; | ||
1142 | } | ||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | static int ReadEEProm(struct i2c_adapter *adapter, | ||
1147 | u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) | ||
1148 | { | ||
1149 | int status = 0; | ||
1150 | u16 Addr = MICNG_EE_START, Length, tag = 0; | ||
1151 | u8 EETag[3]; | ||
1152 | |||
1153 | while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { | ||
1154 | if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) | ||
1155 | return -1; | ||
1156 | tag = (EETag[0] << 8) | EETag[1]; | ||
1157 | if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) | ||
1158 | return -1; | ||
1159 | if (tag == Tag) | ||
1160 | break; | ||
1161 | Addr += sizeof(u16) + 1 + EETag[2]; | ||
1162 | } | ||
1163 | if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { | ||
1164 | printk(KERN_ERR DEVICE_NAME | ||
1165 | ": Reached EOEE @ Tag = %04x Length = %3d\n", | ||
1166 | tag, EETag[2]); | ||
1167 | return -1; | ||
1168 | } | ||
1169 | Length = EETag[2]; | ||
1170 | if (Length > MaxLen) | ||
1171 | Length = (u16) MaxLen; | ||
1172 | if (Length > 0) { | ||
1173 | Addr += sizeof(u16) + 1; | ||
1174 | status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); | ||
1175 | if (!status) { | ||
1176 | *pLength = EETag[2]; | ||
1177 | if (Length < EETag[2]) | ||
1178 | ; /*status=STATUS_BUFFER_OVERFLOW; */ | ||
1179 | } | ||
1180 | } | ||
1181 | return status; | ||
1182 | } | ||
1183 | |||
1184 | static int WriteEEProm(struct i2c_adapter *adapter, | ||
1185 | u16 Tag, u32 Length, u8 *data) | ||
1186 | { | ||
1187 | int status = 0; | ||
1188 | u16 Addr = MICNG_EE_START; | ||
1189 | u8 EETag[3]; | ||
1190 | u16 tag = 0; | ||
1191 | int retry, i; | ||
1192 | |||
1193 | while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { | ||
1194 | if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) | ||
1195 | return -1; | ||
1196 | tag = (EETag[0] << 8) | EETag[1]; | ||
1197 | if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) | ||
1198 | return -1; | ||
1199 | if (tag == Tag) | ||
1200 | break; | ||
1201 | Addr += sizeof(u16) + 1 + EETag[2]; | ||
1202 | } | ||
1203 | if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { | ||
1204 | printk(KERN_ERR DEVICE_NAME | ||
1205 | ": Reached EOEE @ Tag = %04x Length = %3d\n", | ||
1206 | tag, EETag[2]); | ||
1207 | return -1; | ||
1208 | } | ||
1209 | |||
1210 | if (Length > EETag[2]) | ||
1211 | return -EINVAL; | ||
1212 | /* Note: We write the data one byte at a time to avoid | ||
1213 | issues with page sizes. (which are different for | ||
1214 | each manufacture and eeprom size) | ||
1215 | */ | ||
1216 | Addr += sizeof(u16) + 1; | ||
1217 | for (i = 0; i < Length; i++, Addr++) { | ||
1218 | status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); | ||
1219 | |||
1220 | if (status) | ||
1221 | break; | ||
1222 | |||
1223 | /* Poll for finishing write cycle */ | ||
1224 | retry = 10; | ||
1225 | while (retry) { | ||
1226 | u8 Tmp; | ||
1227 | |||
1228 | msleep(50); | ||
1229 | status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); | ||
1230 | if (status) | ||
1231 | break; | ||
1232 | if (Tmp != data[i]) | ||
1233 | printk(KERN_ERR DEVICE_NAME | ||
1234 | "eeprom write error\n"); | ||
1235 | retry -= 1; | ||
1236 | } | ||
1237 | if (status) { | ||
1238 | printk(KERN_ERR DEVICE_NAME | ||
1239 | ": Timeout polling eeprom\n"); | ||
1240 | break; | ||
1241 | } | ||
1242 | } | ||
1243 | return status; | ||
1244 | } | ||
1245 | |||
1246 | static void i2c_init_eeprom(struct i2c_adapter *adapter) | ||
1247 | { | ||
1248 | u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, | ||
1249 | 0x10, 0x01, 0x02, 0x00, 0x00, | ||
1250 | 0x00, 0x00, 0x00}; | ||
1251 | |||
1252 | int i; | ||
1253 | |||
1254 | for (i = 0; i < sizeof(tags); i++) | ||
1255 | i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); | ||
1256 | } | ||
1257 | |||
1258 | static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) | ||
1259 | { | ||
1260 | int stat; | ||
1261 | u8 buf[2]; | ||
1262 | u32 len = 0; | ||
1263 | |||
1264 | stat = ReadEEProm(adapter, tag, 2, buf, &len); | ||
1265 | if (stat) | ||
1266 | return stat; | ||
1267 | if (len != 2) | ||
1268 | return -EINVAL; | ||
1269 | |||
1270 | *data = (buf[0] << 8) | buf[1]; | ||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) | ||
1275 | { | ||
1276 | int stat; | ||
1277 | u8 buf[2]; | ||
1278 | |||
1279 | buf[0] = data >> 8; | ||
1280 | buf[1] = data & 0xff; | ||
1281 | stat = WriteEEProm(adapter, tag, 2, buf); | ||
1282 | if (stat) | ||
1283 | return stat; | ||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | static int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) | ||
1288 | { | ||
1289 | u8 buf[64]; | ||
1290 | int i; | ||
1291 | |||
1292 | if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { | ||
1293 | printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); | ||
1294 | return -1; | ||
1295 | } | ||
1296 | for (i = 0; i < sizeof(buf); i++) { | ||
1297 | if (!(i & 15)) | ||
1298 | printk("\n"); | ||
1299 | printk("%02x ", buf[i]); | ||
1300 | } | ||
1301 | printk("\n"); | ||
1302 | |||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | static int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) | ||
1307 | { | ||
1308 | u8 buf[64]; | ||
1309 | int i; | ||
1310 | |||
1311 | if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { | ||
1312 | printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); | ||
1313 | return -1; | ||
1314 | } | ||
1315 | buf[36] = 0xc3; | ||
1316 | buf[39] = 0xab; | ||
1317 | for (i = 0; i < sizeof(buf); i++) { | ||
1318 | i2c_write_eeprom(adapter, adr2, i, buf[i]); | ||
1319 | msleep(10); | ||
1320 | } | ||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | |||
1325 | /****************************************************************************/ | ||
1326 | /* COMMAND API interface ****************************************************/ | ||
1327 | /****************************************************************************/ | ||
1328 | |||
1329 | #ifdef NGENE_COMMAND_API | ||
1330 | |||
1331 | static int command_do_ioctl(struct inode *inode, struct file *file, | ||
1332 | unsigned int cmd, void *parg) | ||
1333 | { | ||
1334 | struct dvb_device *dvbdev = file->private_data; | ||
1335 | struct ngene_channel *chan = dvbdev->priv; | ||
1336 | struct ngene *dev = chan->dev; | ||
1337 | int err = 0; | ||
1338 | |||
1339 | switch (cmd) { | ||
1340 | case IOCTL_MIC_NO_OP: | ||
1341 | err = ngene_command_nop(dev); | ||
1342 | break; | ||
1343 | |||
1344 | case IOCTL_MIC_DOWNLOAD_FIRMWARE: | ||
1345 | break; | ||
1346 | |||
1347 | case IOCTL_MIC_I2C_READ: | ||
1348 | { | ||
1349 | MIC_I2C_READ *msg = parg; | ||
1350 | |||
1351 | err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, | ||
1352 | msg->OutData, msg->OutLength, | ||
1353 | msg->OutData, msg->InLength, 1); | ||
1354 | break; | ||
1355 | } | ||
1356 | |||
1357 | case IOCTL_MIC_I2C_WRITE: | ||
1358 | { | ||
1359 | MIC_I2C_WRITE *msg = parg; | ||
1360 | |||
1361 | err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, | ||
1362 | msg->Data, msg->Length); | ||
1363 | break; | ||
1364 | } | ||
1365 | |||
1366 | case IOCTL_MIC_TEST_GETMEM: | ||
1367 | { | ||
1368 | MIC_MEM *m = parg; | ||
1369 | |||
1370 | if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) | ||
1371 | return -EINVAL; | ||
1372 | |||
1373 | /* WARNING, only use this on x86, | ||
1374 | other archs may not swallow this */ | ||
1375 | err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); | ||
1376 | break; | ||
1377 | } | ||
1378 | |||
1379 | case IOCTL_MIC_TEST_SETMEM: | ||
1380 | { | ||
1381 | MIC_MEM *m = parg; | ||
1382 | |||
1383 | if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) | ||
1384 | return -EINVAL; | ||
1385 | |||
1386 | err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); | ||
1387 | break; | ||
1388 | } | ||
1389 | |||
1390 | case IOCTL_MIC_SFR_READ: | ||
1391 | { | ||
1392 | MIC_IMEM *m = parg; | ||
1393 | |||
1394 | err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); | ||
1395 | break; | ||
1396 | } | ||
1397 | |||
1398 | case IOCTL_MIC_SFR_WRITE: | ||
1399 | { | ||
1400 | MIC_IMEM *m = parg; | ||
1401 | |||
1402 | err = ngene_command_imem_write(dev, m->Address, m->Data, 1); | ||
1403 | break; | ||
1404 | } | ||
1405 | |||
1406 | case IOCTL_MIC_IRAM_READ: | ||
1407 | { | ||
1408 | MIC_IMEM *m = parg; | ||
1409 | |||
1410 | err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); | ||
1411 | break; | ||
1412 | } | ||
1413 | |||
1414 | case IOCTL_MIC_IRAM_WRITE: | ||
1415 | { | ||
1416 | MIC_IMEM *m = parg; | ||
1417 | |||
1418 | err = ngene_command_imem_write(dev, m->Address, m->Data, 0); | ||
1419 | break; | ||
1420 | } | ||
1421 | |||
1422 | case IOCTL_MIC_STREAM_CONTROL: | ||
1423 | { | ||
1424 | MIC_STREAM_CONTROL *m = parg; | ||
1425 | |||
1426 | err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, | ||
1427 | m->nLines, m->nBytesPerLine, | ||
1428 | m->nVBILines, m->nBytesPerVBILine); | ||
1429 | break; | ||
1430 | } | ||
1431 | |||
1432 | default: | ||
1433 | err = -EINVAL; | ||
1434 | break; | ||
1435 | } | ||
1436 | return err; | ||
1437 | } | ||
1438 | |||
1439 | static int command_ioctl(struct inode *inode, struct file *file, | ||
1440 | unsigned int cmd, unsigned long arg) | ||
1441 | { | ||
1442 | void *parg = (void *)arg, *pbuf = NULL; | ||
1443 | char buf[64]; | ||
1444 | int res = -EFAULT; | ||
1445 | |||
1446 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
1447 | parg = buf; | ||
1448 | if (_IOC_SIZE(cmd) > sizeof(buf)) { | ||
1449 | pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); | ||
1450 | if (!pbuf) | ||
1451 | return -ENOMEM; | ||
1452 | parg = pbuf; | ||
1453 | } | ||
1454 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
1455 | goto error; | ||
1456 | } | ||
1457 | res = command_do_ioctl(inode, file, cmd, parg); | ||
1458 | if (res < 0) | ||
1459 | goto error; | ||
1460 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
1461 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
1462 | res = -EFAULT; | ||
1463 | error: | ||
1464 | kfree(pbuf); | ||
1465 | return res; | ||
1466 | } | ||
1467 | |||
1468 | struct page *ngene_nopage(struct vm_area_struct *vma, | ||
1469 | unsigned long address, int *type) | ||
1470 | { | ||
1471 | return 0; | ||
1472 | } | ||
1473 | |||
1474 | static int ngene_mmap(struct file *file, struct vm_area_struct *vma) | ||
1475 | { | ||
1476 | struct dvb_device *dvbdev = file->private_data; | ||
1477 | struct ngene_channel *chan = dvbdev->priv; | ||
1478 | struct ngene *dev = chan->dev; | ||
1479 | |||
1480 | unsigned long size = vma->vm_end - vma->vm_start; | ||
1481 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | ||
1482 | unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; | ||
1483 | unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; | ||
1484 | |||
1485 | if (size > psize) | ||
1486 | return -EINVAL; | ||
1487 | |||
1488 | if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, | ||
1489 | vma->vm_page_prot)) | ||
1490 | return -EAGAIN; | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | static int write_uart(struct ngene *dev, u8 *data, int len) | ||
1495 | { | ||
1496 | struct ngene_command com; | ||
1497 | |||
1498 | com.cmd.hdr.Opcode = CMD_WRITE_UART; | ||
1499 | com.cmd.hdr.Length = len; | ||
1500 | memcpy(com.cmd.WriteUart.Data, data, len); | ||
1501 | com.cmd.WriteUart.Data[len] = 0; | ||
1502 | com.cmd.WriteUart.Data[len + 1] = 0; | ||
1503 | com.in_len = len; | ||
1504 | com.out_len = 0; | ||
1505 | |||
1506 | if (ngene_command(dev, &com) < 0) | ||
1507 | return -EIO; | ||
1508 | |||
1509 | return 0; | ||
1510 | } | ||
1511 | |||
1512 | static int send_cli(struct ngene *dev, char *cmd) | ||
1513 | { | ||
1514 | /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ | ||
1515 | return write_uart(dev, cmd, strlen(cmd)); | ||
1516 | } | ||
1517 | |||
1518 | static int send_cli_val(struct ngene *dev, char *cmd, u32 val) | ||
1519 | { | ||
1520 | char s[32]; | ||
1521 | |||
1522 | snprintf(s, 32, "%s %d\n", cmd, val); | ||
1523 | /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ | ||
1524 | return write_uart(dev, s, strlen(s)); | ||
1525 | } | ||
1526 | |||
1527 | static int ngene_command_write_uart_user(struct ngene *dev, | ||
1528 | const u8 *data, int len) | ||
1529 | { | ||
1530 | struct ngene_command com; | ||
1531 | |||
1532 | dev->tx_busy = 1; | ||
1533 | com.cmd.hdr.Opcode = CMD_WRITE_UART; | ||
1534 | com.cmd.hdr.Length = len; | ||
1535 | |||
1536 | if (copy_from_user(com.cmd.WriteUart.Data, data, len)) | ||
1537 | return -EFAULT; | ||
1538 | com.in_len = len; | ||
1539 | com.out_len = 0; | ||
1540 | |||
1541 | if (ngene_command(dev, &com) < 0) | ||
1542 | return -EIO; | ||
1543 | |||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | static ssize_t uart_write(struct file *file, const char *buf, | ||
1548 | size_t count, loff_t *ppos) | ||
1549 | { | ||
1550 | struct dvb_device *dvbdev = file->private_data; | ||
1551 | struct ngene_channel *chan = dvbdev->priv; | ||
1552 | struct ngene *dev = chan->dev; | ||
1553 | int len, ret = 0; | ||
1554 | size_t left = count; | ||
1555 | |||
1556 | while (left) { | ||
1557 | len = left; | ||
1558 | if (len > 250) | ||
1559 | len = 250; | ||
1560 | ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); | ||
1561 | if (ret < 0) | ||
1562 | return ret; | ||
1563 | ngene_command_write_uart_user(dev, buf, len); | ||
1564 | left -= len; | ||
1565 | buf += len; | ||
1566 | } | ||
1567 | return count; | ||
1568 | } | ||
1569 | |||
1570 | static ssize_t ts_write(struct file *file, const char *buf, | ||
1571 | size_t count, loff_t *ppos) | ||
1572 | { | ||
1573 | struct dvb_device *dvbdev = file->private_data; | ||
1574 | struct ngene_channel *chan = dvbdev->priv; | ||
1575 | struct ngene *dev = chan->dev; | ||
1576 | |||
1577 | if (wait_event_interruptible(dev->tsout_rbuf.queue, | ||
1578 | dvb_ringbuffer_free | ||
1579 | (&dev->tsout_rbuf) >= count) < 0) | ||
1580 | return 0; | ||
1581 | |||
1582 | dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); | ||
1583 | |||
1584 | return count; | ||
1585 | } | ||
1586 | |||
1587 | static ssize_t uart_read(struct file *file, char *buf, | ||
1588 | size_t count, loff_t *ppos) | ||
1589 | { | ||
1590 | struct dvb_device *dvbdev = file->private_data; | ||
1591 | struct ngene_channel *chan = dvbdev->priv; | ||
1592 | struct ngene *dev = chan->dev; | ||
1593 | int left; | ||
1594 | int wp, rp, avail, len; | ||
1595 | |||
1596 | if (!dev->uart_rbuf) | ||
1597 | return -EINVAL; | ||
1598 | if (count > 128) | ||
1599 | count = 128; | ||
1600 | left = count; | ||
1601 | while (left) { | ||
1602 | if (wait_event_interruptible(dev->rx_wq, | ||
1603 | dev->uart_wp != dev->uart_rp) < 0) | ||
1604 | return -EAGAIN; | ||
1605 | wp = dev->uart_wp; | ||
1606 | rp = dev->uart_rp; | ||
1607 | avail = (wp - rp); | ||
1608 | |||
1609 | if (avail < 0) | ||
1610 | avail += UART_RBUF_LEN; | ||
1611 | if (avail > left) | ||
1612 | avail = left; | ||
1613 | if (wp < rp) { | ||
1614 | len = UART_RBUF_LEN - rp; | ||
1615 | if (len > avail) | ||
1616 | len = avail; | ||
1617 | if (copy_to_user(buf, dev->uart_rbuf + rp, len)) | ||
1618 | return -EFAULT; | ||
1619 | if (len < avail) | ||
1620 | if (copy_to_user(buf + len, dev->uart_rbuf, | ||
1621 | avail - len)) | ||
1622 | return -EFAULT; | ||
1623 | } else { | ||
1624 | if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) | ||
1625 | return -EFAULT; | ||
1626 | } | ||
1627 | dev->uart_rp = (rp + avail) % UART_RBUF_LEN; | ||
1628 | left -= avail; | ||
1629 | buf += avail; | ||
1630 | } | ||
1631 | return count; | ||
1632 | } | ||
1633 | |||
1634 | static const struct file_operations command_fops = { | ||
1635 | .owner = THIS_MODULE, | ||
1636 | .read = uart_read, | ||
1637 | .write = ts_write, | ||
1638 | .ioctl = command_ioctl, | ||
1639 | .open = dvb_generic_open, | ||
1640 | .release = dvb_generic_release, | ||
1641 | .poll = 0, | ||
1642 | .mmap = ngene_mmap, | ||
1643 | }; | ||
1644 | |||
1645 | static struct dvb_device dvbdev_command = { | ||
1646 | .priv = 0, | ||
1647 | .readers = -1, | ||
1648 | .writers = -1, | ||
1649 | .users = -1, | ||
1650 | .fops = &command_fops, | ||
1651 | }; | ||
1652 | |||
1653 | #endif | ||
1654 | |||
1655 | /****************************************************************************/ | ||
1656 | /* DVB functions and API interface ******************************************/ | ||
1657 | /****************************************************************************/ | ||
1658 | |||
1659 | static void swap_buffer(u32 *p, u32 len) | ||
1660 | { | ||
1661 | while (len) { | ||
1662 | *p = swab32(*p); | ||
1663 | p++; | ||
1664 | len -= 4; | ||
1665 | } | ||
1666 | } | ||
1667 | |||
1668 | static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
1669 | { | ||
1670 | struct ngene_channel *chan = priv; | ||
1671 | struct ngene *dev = chan->dev; | ||
1672 | |||
1673 | if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { | ||
1674 | dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); | ||
1675 | wake_up_interruptible(&dev->ain_rbuf.queue); | ||
1676 | } else | ||
1677 | printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); | ||
1678 | |||
1679 | return 0; | ||
1680 | } | ||
1681 | |||
1682 | static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
1683 | { | ||
1684 | |||
1685 | struct ngene_channel *chan = priv; | ||
1686 | struct ngene *dev = chan->dev; | ||
1687 | |||
1688 | if (len >= 1920 * 1080) | ||
1689 | len = 1920 * 1080; | ||
1690 | if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { | ||
1691 | dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); | ||
1692 | wake_up_interruptible(&dev->vin_rbuf.queue); | ||
1693 | } else { | ||
1694 | ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ | ||
1695 | } | ||
1696 | return 0; | ||
1697 | } | ||
1698 | |||
1699 | static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
1700 | { | ||
1701 | struct ngene_channel *chan = priv; | ||
1702 | |||
1703 | |||
1704 | dvb_dmx_swfilter(&chan->demux, buf, len); | ||
1705 | return 0; | ||
1706 | } | ||
1707 | |||
1708 | u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; | ||
1709 | |||
1710 | static void *tsout_exchange(void *priv, void *buf, u32 len, | ||
1711 | u32 clock, u32 flags) | ||
1712 | { | ||
1713 | struct ngene_channel *chan = priv; | ||
1714 | struct ngene *dev = chan->dev; | ||
1715 | u32 alen; | ||
1716 | |||
1717 | alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); | ||
1718 | alen -= alen % 188; | ||
1719 | |||
1720 | if (alen < len) | ||
1721 | FillTSBuffer(buf + alen, len - alen, flags); | ||
1722 | else | ||
1723 | alen = len; | ||
1724 | dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); | ||
1725 | if (flags & DF_SWAP32) | ||
1726 | swap_buffer((u32 *)buf, alen); | ||
1727 | wake_up_interruptible(&dev->tsout_rbuf.queue); | ||
1728 | return buf; | ||
1729 | } | ||
1730 | |||
1731 | static void set_dto(struct ngene_channel *chan, u32 rate) | ||
1732 | { | ||
1733 | u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ | ||
1734 | |||
1735 | val = ((val >> 25) + 1) >> 1; | ||
1736 | chan->AudioDTOValue = (u32) val; | ||
1737 | /* chan->AudioDTOUpdated=1; */ | ||
1738 | /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ | ||
1739 | } | ||
1740 | |||
1741 | static void set_transfer(struct ngene_channel *chan, int state) | ||
1742 | { | ||
1743 | u8 control = 0, mode = 0, flags = 0; | ||
1744 | struct ngene *dev = chan->dev; | ||
1745 | int ret; | ||
1746 | |||
1747 | /* | ||
1748 | if (chan->running) | ||
1749 | return; | ||
1750 | */ | ||
1751 | |||
1752 | /* | ||
1753 | printk(KERN_INFO DEVICE_NAME ": st %d\n", state); | ||
1754 | msleep(100); | ||
1755 | */ | ||
1756 | |||
1757 | if (state) { | ||
1758 | if (chan->running) { | ||
1759 | printk(KERN_INFO DEVICE_NAME ": already running\n"); | ||
1760 | return; | ||
1761 | } | ||
1762 | } else { | ||
1763 | if (!chan->running) { | ||
1764 | printk(KERN_INFO DEVICE_NAME ": already stopped\n"); | ||
1765 | return; | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | if (dev->card_info->switch_ctrl) | ||
1770 | dev->card_info->switch_ctrl(chan, 1, state ^ 1); | ||
1771 | |||
1772 | if (state) { | ||
1773 | spin_lock_irq(&chan->state_lock); | ||
1774 | |||
1775 | /* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", | ||
1776 | ngreadl(0x9310)); */ | ||
1777 | my_dvb_ringbuffer_flush(&dev->tsout_rbuf); | ||
1778 | control = 0x80; | ||
1779 | if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
1780 | chan->Capture1Length = 512 * 188; | ||
1781 | mode = SMODE_TRANSPORT_STREAM; | ||
1782 | } | ||
1783 | if (chan->mode & NGENE_IO_TSOUT) { | ||
1784 | chan->pBufferExchange = tsout_exchange; | ||
1785 | /* 0x66666666 = 50MHz *2^33 /250MHz */ | ||
1786 | chan->AudioDTOValue = 0x66666666; | ||
1787 | /* set_dto(chan, 38810700+1000); */ | ||
1788 | /* set_dto(chan, 19392658); */ | ||
1789 | } | ||
1790 | if (chan->mode & NGENE_IO_TSIN) | ||
1791 | chan->pBufferExchange = tsin_exchange; | ||
1792 | /* ngwritel(0, 0x9310); */ | ||
1793 | spin_unlock_irq(&chan->state_lock); | ||
1794 | } else | ||
1795 | ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", | ||
1796 | ngreadl(0x9310)); */ | ||
1797 | |||
1798 | ret = ngene_command_stream_control(dev, chan->number, | ||
1799 | control, mode, flags); | ||
1800 | if (!ret) | ||
1801 | chan->running = state; | ||
1802 | else | ||
1803 | printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n", | ||
1804 | state); | ||
1805 | if (!state) { | ||
1806 | spin_lock_irq(&chan->state_lock); | ||
1807 | chan->pBufferExchange = 0; | ||
1808 | my_dvb_ringbuffer_flush(&dev->tsout_rbuf); | ||
1809 | spin_unlock_irq(&chan->state_lock); | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1813 | static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1814 | { | ||
1815 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
1816 | struct ngene_channel *chan = dvbdmx->priv; | ||
1817 | struct ngene *dev = chan->dev; | ||
1818 | |||
1819 | if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { | ||
1820 | switch (dvbdmxfeed->pes_type) { | ||
1821 | case DMX_TS_PES_VIDEO: | ||
1822 | send_cli_val(dev, "vpid", dvbdmxfeed->pid); | ||
1823 | send_cli(dev, "res 1080i50\n"); | ||
1824 | /* send_cli(dev, "vdec mpeg2\n"); */ | ||
1825 | break; | ||
1826 | |||
1827 | case DMX_TS_PES_AUDIO: | ||
1828 | send_cli_val(dev, "apid", dvbdmxfeed->pid); | ||
1829 | send_cli(dev, "start\n"); | ||
1830 | break; | ||
1831 | |||
1832 | case DMX_TS_PES_PCR: | ||
1833 | send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); | ||
1834 | break; | ||
1835 | |||
1836 | default: | ||
1837 | break; | ||
1838 | } | ||
1839 | |||
1840 | } | ||
1841 | |||
1842 | if (chan->users == 0) { | ||
1843 | set_transfer(chan, 1); | ||
1844 | /* msleep(10); */ | ||
1845 | } | ||
1846 | |||
1847 | return ++chan->users; | ||
1848 | } | ||
1849 | |||
1850 | static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1851 | { | ||
1852 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
1853 | struct ngene_channel *chan = dvbdmx->priv; | ||
1854 | struct ngene *dev = chan->dev; | ||
1855 | |||
1856 | if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { | ||
1857 | switch (dvbdmxfeed->pes_type) { | ||
1858 | case DMX_TS_PES_VIDEO: | ||
1859 | send_cli(dev, "stop\n"); | ||
1860 | break; | ||
1861 | |||
1862 | case DMX_TS_PES_AUDIO: | ||
1863 | break; | ||
1864 | |||
1865 | case DMX_TS_PES_PCR: | ||
1866 | break; | ||
1867 | |||
1868 | default: | ||
1869 | break; | ||
1870 | } | ||
1871 | |||
1872 | } | ||
1873 | |||
1874 | if (--chan->users) | ||
1875 | return chan->users; | ||
1876 | |||
1877 | set_transfer(chan, 0); | ||
1878 | |||
1879 | return 0; | ||
1880 | } | ||
1881 | |||
1882 | static int write_demod(struct i2c_adapter *adapter, u8 adr, u16 reg, u16 data) | ||
1883 | { | ||
1884 | u8 mm[5] = { 0x10, (reg >> 8) & 0xff, reg & 0xff, | ||
1885 | (data >> 8) & 0xff, data & 0xff}; | ||
1886 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = mm, .len = 5 }; | ||
1887 | |||
1888 | if (i2c_transfer(adapter, &msg, 1) != 1) { | ||
1889 | printk(KERN_ERR DEVICE_NAME ": error in write_demod\n"); | ||
1890 | return -1; | ||
1891 | } | ||
1892 | return 0; | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | static int ngene_drxd_pll_set(struct ngene_channel *chan, | ||
1897 | u8 *pll, u8 *aux, u8 plladr) | ||
1898 | { | ||
1899 | struct i2c_adapter *adap = &chan->i2c_adapter; | ||
1900 | struct i2c_msg msg_pll = {.addr = plladr, .flags = 0, .buf = pll, | ||
1901 | .len = 4}; | ||
1902 | struct i2c_msg msg_aux = {.addr = plladr, .flags = 0, .buf = aux, | ||
1903 | .len = 2}; | ||
1904 | int err = 0; | ||
1905 | |||
1906 | if (chan->dev->card_info->i2c_access & 1) | ||
1907 | down(&chan->dev->pll_mutex); | ||
1908 | |||
1909 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); | ||
1910 | err = i2c_transfer(adap, &msg_pll, 1); | ||
1911 | if (err != 1) | ||
1912 | goto error; | ||
1913 | if (aux) | ||
1914 | err = i2c_transfer(adap, &msg_aux, 1); | ||
1915 | error: | ||
1916 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); | ||
1917 | if (chan->dev->card_info->i2c_access & 1) | ||
1918 | up(&chan->dev->pll_mutex); | ||
1919 | return err; | ||
1920 | } | ||
1921 | |||
1922 | static int ngene_pll_set_th_dtt7520x(void *priv, void *priv_params, | ||
1923 | u8 plladr, u8 dadr, s32 *off) | ||
1924 | { | ||
1925 | struct dvb_frontend_parameters *params = priv_params; | ||
1926 | struct ngene_channel *chan = priv; | ||
1927 | |||
1928 | u32 freq = params->frequency; | ||
1929 | u8 pll[4], aux[2]; | ||
1930 | u8 c1, c2; | ||
1931 | u32 div; | ||
1932 | |||
1933 | if (freq < 185000000 || freq > 900000000) | ||
1934 | return -EINVAL; | ||
1935 | |||
1936 | if (freq < 465000000) | ||
1937 | c2 = 0x12; | ||
1938 | else | ||
1939 | c2 = 0x18; | ||
1940 | |||
1941 | if (freq < 305000000) | ||
1942 | c1 = 0xb4; | ||
1943 | else if (freq < 405000000) | ||
1944 | c1 = 0xbc; | ||
1945 | else if (freq < 445000000) | ||
1946 | c1 = 0xf4; | ||
1947 | else if (freq < 465000000) | ||
1948 | c1 = 0xfc; | ||
1949 | else if (freq < 735000000) | ||
1950 | c1 = 0xbc; | ||
1951 | else if (freq < 835000000) | ||
1952 | c1 = 0xf4; | ||
1953 | else | ||
1954 | c1 = 0xfc; | ||
1955 | |||
1956 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | ||
1957 | c2 ^= 0x10; | ||
1958 | |||
1959 | div = (freq + 36000000 + 166667 / 2) / 166667; | ||
1960 | *off = ((s32) div) * 166667 - (s32) freq - 36000000; | ||
1961 | |||
1962 | pll[0] = (div >> 8) & 0x7f; | ||
1963 | pll[1] = div & 0xff; | ||
1964 | pll[2] = c1; | ||
1965 | pll[3] = c2; | ||
1966 | |||
1967 | aux[0] = (c1 & 0xc7) | 0x98; | ||
1968 | aux[1] = 0x30; | ||
1969 | |||
1970 | return ngene_drxd_pll_set(chan, pll, aux, plladr); | ||
1971 | } | ||
1972 | |||
1973 | static int ngene_pll_set_mt_3x0823(void *priv, | ||
1974 | void *priv_params, | ||
1975 | u8 plladr, u8 dadr, s32 *off) | ||
1976 | { | ||
1977 | struct dvb_frontend_parameters *params = priv_params; | ||
1978 | struct ngene_channel *chan = priv; | ||
1979 | struct i2c_adapter *adap = &chan->i2c_adapter; | ||
1980 | u32 freq = params->frequency; | ||
1981 | u8 pll[4]; | ||
1982 | u8 aux[2]; | ||
1983 | u8 c1, c2; | ||
1984 | u32 div; | ||
1985 | |||
1986 | if (freq < 47125000 || freq > 855250000) | ||
1987 | return -EINVAL; | ||
1988 | else if (freq < 120000000) { | ||
1989 | c1 = 0xcc; | ||
1990 | c2 = 0x01; | ||
1991 | } else if (freq < 155500000) { | ||
1992 | c1 = 0xfc; | ||
1993 | c2 = 0x01; | ||
1994 | } else if (freq < 300000000) { | ||
1995 | c1 = 0xbc; | ||
1996 | c2 = 0x02; | ||
1997 | } else if (freq < 467000000) { | ||
1998 | c1 = 0xcc; | ||
1999 | c2 = 0x02; | ||
2000 | } else { | ||
2001 | c1 = 0xcc; | ||
2002 | c2 = 0x04; | ||
2003 | } | ||
2004 | |||
2005 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | ||
2006 | c2 |= 0x08; | ||
2007 | |||
2008 | #define INTERFREQ (36000000) | ||
2009 | |||
2010 | div = (freq + INTERFREQ + 166667 / 2) / 166667; | ||
2011 | |||
2012 | *off = ((s32) div) * 166667 - (s32) freq - INTERFREQ; | ||
2013 | |||
2014 | pll[0] = (div >> 8) & 0x7f; | ||
2015 | pll[1] = div & 0xff; | ||
2016 | pll[2] = c1; | ||
2017 | pll[3] = c2; | ||
2018 | |||
2019 | aux[0] = (c1 & 0xc7) | 0x98; | ||
2020 | aux[1] = 0x20; | ||
2021 | |||
2022 | write_demod(adap, dadr, 0x1007, 0xc27); | ||
2023 | |||
2024 | switch (params->u.ofdm.bandwidth) { | ||
2025 | case BANDWIDTH_7_MHZ: | ||
2026 | write_demod(adap, dadr, 0x0020, 0x103); | ||
2027 | break; | ||
2028 | case BANDWIDTH_AUTO: | ||
2029 | case BANDWIDTH_8_MHZ: | ||
2030 | write_demod(adap, dadr, 0x0020, 0x003); | ||
2031 | break; | ||
2032 | case BANDWIDTH_6_MHZ: | ||
2033 | write_demod(adap, dadr, 0x0020, 0x002); | ||
2034 | /*write_demod(adap, dadr, 0x1022, 397);*/ | ||
2035 | break; | ||
2036 | } | ||
2037 | |||
2038 | return ngene_drxd_pll_set(chan, pll, aux, plladr); | ||
2039 | |||
2040 | } | ||
2041 | |||
2042 | static s16 osc_deviation(void *priv, s16 deviation, int flag) | ||
2043 | { | ||
2044 | struct ngene_channel *chan = priv; | ||
2045 | struct i2c_adapter *adap = &chan->i2c_adapter; | ||
2046 | u16 data = 0; | ||
2047 | |||
2048 | if (flag) { | ||
2049 | data = (u16) deviation; | ||
2050 | printk(KERN_INFO DEVICE_NAME ": write deviation %d\n", | ||
2051 | deviation); | ||
2052 | eeprom_write_ushort(adap, 0x1000 + chan->number, data); | ||
2053 | } else { | ||
2054 | if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) | ||
2055 | data = 0; | ||
2056 | printk(KERN_INFO DEVICE_NAME ": read deviation %d\n", | ||
2057 | (s16) data); | ||
2058 | } | ||
2059 | |||
2060 | return (s16) data; | ||
2061 | } | ||
2062 | |||
2063 | static int write_to_decoder(struct dvb_demux_feed *feed, | ||
2064 | const u8 *buf, size_t len) | ||
2065 | { | ||
2066 | struct dvb_demux *dvbdmx = feed->demux; | ||
2067 | struct ngene_channel *chan = dvbdmx->priv; | ||
2068 | struct ngene *dev = chan->dev; | ||
2069 | |||
2070 | if (wait_event_interruptible(dev->tsout_rbuf.queue, | ||
2071 | dvb_ringbuffer_free | ||
2072 | (&dev->tsout_rbuf) >= len) < 0) | ||
2073 | return 0; | ||
2074 | |||
2075 | dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); | ||
2076 | |||
2077 | return len; | ||
2078 | } | ||
2079 | |||
2080 | static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, | ||
2081 | int (*start_feed)(struct dvb_demux_feed *), | ||
2082 | int (*stop_feed)(struct dvb_demux_feed *), | ||
2083 | void *priv) | ||
2084 | { | ||
2085 | dvbdemux->priv = priv; | ||
2086 | |||
2087 | dvbdemux->filternum = 256; | ||
2088 | dvbdemux->feednum = 256; | ||
2089 | dvbdemux->start_feed = start_feed; | ||
2090 | dvbdemux->stop_feed = stop_feed; | ||
2091 | dvbdemux->write_to_decoder = 0; | ||
2092 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | ||
2093 | DMX_SECTION_FILTERING | | ||
2094 | DMX_MEMORY_BASED_FILTERING); | ||
2095 | return dvb_dmx_init(dvbdemux); | ||
2096 | } | ||
2097 | |||
2098 | static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, | ||
2099 | struct dvb_demux *dvbdemux, | ||
2100 | struct dmx_frontend *hw_frontend, | ||
2101 | struct dmx_frontend *mem_frontend, | ||
2102 | struct dvb_adapter *dvb_adapter) | ||
2103 | { | ||
2104 | int ret; | ||
2105 | |||
2106 | dmxdev->filternum = 256; | ||
2107 | dmxdev->demux = &dvbdemux->dmx; | ||
2108 | dmxdev->capabilities = 0; | ||
2109 | ret = dvb_dmxdev_init(dmxdev, dvb_adapter); | ||
2110 | if (ret < 0) | ||
2111 | return ret; | ||
2112 | |||
2113 | hw_frontend->source = DMX_FRONTEND_0; | ||
2114 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); | ||
2115 | mem_frontend->source = DMX_MEMORY_FE; | ||
2116 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); | ||
2117 | return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); | ||
2118 | } | ||
2119 | |||
2120 | /****************************************************************************/ | ||
2121 | /* Decypher firmware loading ************************************************/ | ||
2122 | /****************************************************************************/ | ||
2123 | |||
2124 | #define DECYPHER_FW "decypher.fw" | ||
2125 | |||
2126 | static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) | ||
2127 | { | ||
2128 | while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) | ||
2129 | msleep(1); | ||
2130 | |||
2131 | |||
2132 | dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); | ||
2133 | |||
2134 | return len; | ||
2135 | } | ||
2136 | |||
2137 | u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; | ||
2138 | |||
2139 | int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) | ||
2140 | { | ||
2141 | struct ngene_channel *chan = &dev->channel[4]; | ||
2142 | u32 len = 180, cc = 0; | ||
2143 | u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; | ||
2144 | |||
2145 | set_transfer(chan, 1); | ||
2146 | msleep(100); | ||
2147 | while (size) { | ||
2148 | len = 180; | ||
2149 | if (len > size) | ||
2150 | len = size; | ||
2151 | buf[3] = 0x10 | (cc & 0x0f); | ||
2152 | buf[4] = (cc >> 8); | ||
2153 | buf[5] = cc & 0xff; | ||
2154 | buf[6] = len; | ||
2155 | |||
2156 | dec_ts_send(dev, buf, 8); | ||
2157 | dec_ts_send(dev, fw, len); | ||
2158 | if (len < 180) | ||
2159 | dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); | ||
2160 | cc++; | ||
2161 | size -= len; | ||
2162 | fw += len; | ||
2163 | } | ||
2164 | for (len = 0; len < 512; len++) | ||
2165 | dec_ts_send(dev, dec_fw_fill_ts, 188); | ||
2166 | while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) | ||
2167 | msleep(10); | ||
2168 | msleep(100); | ||
2169 | set_transfer(chan, 0); | ||
2170 | return 0; | ||
2171 | } | ||
2172 | |||
2173 | int dec_fw_boot(struct ngene *dev) | ||
2174 | { | ||
2175 | u32 size; | ||
2176 | const struct firmware *fw = NULL; | ||
2177 | u8 *dec_fw; | ||
2178 | char *fw_name; | ||
2179 | int err, version; | ||
2180 | |||
2181 | if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { | ||
2182 | printk(KERN_ERR DEVICE_NAME | ||
2183 | ": %s not found. Check hotplug directory.\n", | ||
2184 | DECYPHER_FW); | ||
2185 | return -1; | ||
2186 | } | ||
2187 | printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", | ||
2188 | DECYPHER_FW); | ||
2189 | |||
2190 | size = fw->size; | ||
2191 | dec_fw = fw->data; | ||
2192 | dec_fw_send(dev, dec_fw, size); | ||
2193 | release_firmware(fw); | ||
2194 | return 0; | ||
2195 | } | ||
2196 | |||
2197 | /****************************************************************************/ | ||
2198 | /* nGene hardware init and release functions ********************************/ | ||
2199 | /****************************************************************************/ | ||
2200 | |||
2201 | void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) | ||
2202 | { | ||
2203 | struct SBufferHeader *Cur = rb->Head; | ||
2204 | u32 j; | ||
2205 | |||
2206 | if (!Cur) | ||
2207 | return; | ||
2208 | |||
2209 | for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) { | ||
2210 | if (Cur->Buffer1) | ||
2211 | pci_free_consistent(dev->pci_dev, | ||
2212 | rb->Buffer1Length, | ||
2213 | Cur->Buffer1, | ||
2214 | Cur->scList1->Address); | ||
2215 | |||
2216 | if (Cur->Buffer2) | ||
2217 | pci_free_consistent(dev->pci_dev, | ||
2218 | rb->Buffer2Length, | ||
2219 | Cur->Buffer2, | ||
2220 | Cur->scList2->Address); | ||
2221 | } | ||
2222 | |||
2223 | if (rb->SCListMem) | ||
2224 | pci_free_consistent(dev->pci_dev, rb->SCListMemSize, | ||
2225 | rb->SCListMem, rb->PASCListMem); | ||
2226 | |||
2227 | pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead); | ||
2228 | } | ||
2229 | |||
2230 | void free_idlebuffer(struct ngene *dev, | ||
2231 | struct SRingBufferDescriptor *rb, | ||
2232 | struct SRingBufferDescriptor *tb) | ||
2233 | { | ||
2234 | int j; | ||
2235 | struct SBufferHeader *Cur = tb->Head; | ||
2236 | |||
2237 | if (!rb->Head) | ||
2238 | return; | ||
2239 | free_ringbuffer(dev, rb); | ||
2240 | for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { | ||
2241 | Cur->Buffer2 = 0; | ||
2242 | Cur->scList2 = 0; | ||
2243 | Cur->ngeneBuffer.Address_of_first_entry_2 = 0; | ||
2244 | Cur->ngeneBuffer.Number_of_entries_2 = 0; | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | void free_common_buffers(struct ngene *dev) | ||
2249 | { | ||
2250 | u32 i; | ||
2251 | struct ngene_channel *chan; | ||
2252 | |||
2253 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { | ||
2254 | chan = &dev->channel[i]; | ||
2255 | free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer); | ||
2256 | free_ringbuffer(dev, &chan->RingBuffer); | ||
2257 | free_ringbuffer(dev, &chan->TSRingBuffer); | ||
2258 | } | ||
2259 | |||
2260 | if (dev->OverflowBuffer) | ||
2261 | pci_free_consistent(dev->pci_dev, | ||
2262 | OVERFLOW_BUFFER_SIZE, | ||
2263 | dev->OverflowBuffer, dev->PAOverflowBuffer); | ||
2264 | |||
2265 | if (dev->FWInterfaceBuffer) | ||
2266 | pci_free_consistent(dev->pci_dev, | ||
2267 | 4096, | ||
2268 | dev->FWInterfaceBuffer, | ||
2269 | dev->PAFWInterfaceBuffer); | ||
2270 | } | ||
2271 | |||
2272 | /****************************************************************************/ | ||
2273 | /* Ring buffer handling *****************************************************/ | ||
2274 | /****************************************************************************/ | ||
2275 | |||
2276 | int create_ring_buffer(struct pci_dev *pci_dev, | ||
2277 | struct SRingBufferDescriptor *descr, u32 NumBuffers) | ||
2278 | { | ||
2279 | dma_addr_t tmp; | ||
2280 | struct SBufferHeader *Head; | ||
2281 | u32 i; | ||
2282 | u32 MemSize = SIZEOF_SBufferHeader * NumBuffers; | ||
2283 | u64 PARingBufferHead; | ||
2284 | u64 PARingBufferCur; | ||
2285 | u64 PARingBufferNext; | ||
2286 | struct SBufferHeader *Cur, *Next; | ||
2287 | |||
2288 | descr->Head = 0; | ||
2289 | descr->MemSize = 0; | ||
2290 | descr->PAHead = 0; | ||
2291 | descr->NumBuffers = 0; | ||
2292 | |||
2293 | if (MemSize < 4096) | ||
2294 | MemSize = 4096; | ||
2295 | |||
2296 | Head = pci_alloc_consistent(pci_dev, MemSize, &tmp); | ||
2297 | PARingBufferHead = tmp; | ||
2298 | |||
2299 | if (!Head) | ||
2300 | return -ENOMEM; | ||
2301 | |||
2302 | memset(Head, 0, MemSize); | ||
2303 | |||
2304 | PARingBufferCur = PARingBufferHead; | ||
2305 | Cur = Head; | ||
2306 | |||
2307 | for (i = 0; i < NumBuffers - 1; i++) { | ||
2308 | Next = (struct SBufferHeader *) | ||
2309 | (((u8 *) Cur) + SIZEOF_SBufferHeader); | ||
2310 | PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader; | ||
2311 | Cur->Next = Next; | ||
2312 | Cur->ngeneBuffer.Next = PARingBufferNext; | ||
2313 | Cur = Next; | ||
2314 | PARingBufferCur = PARingBufferNext; | ||
2315 | } | ||
2316 | /* Last Buffer points back to first one */ | ||
2317 | Cur->Next = Head; | ||
2318 | Cur->ngeneBuffer.Next = PARingBufferHead; | ||
2319 | |||
2320 | descr->Head = Head; | ||
2321 | descr->MemSize = MemSize; | ||
2322 | descr->PAHead = PARingBufferHead; | ||
2323 | descr->NumBuffers = NumBuffers; | ||
2324 | |||
2325 | return 0; | ||
2326 | } | ||
2327 | |||
2328 | static int AllocateRingBuffers(struct pci_dev *pci_dev, | ||
2329 | dma_addr_t of, | ||
2330 | struct SRingBufferDescriptor *pRingBuffer, | ||
2331 | u32 Buffer1Length, u32 Buffer2Length) | ||
2332 | { | ||
2333 | dma_addr_t tmp; | ||
2334 | u32 i, j; | ||
2335 | int status = 0; | ||
2336 | u32 SCListMemSize = pRingBuffer->NumBuffers | ||
2337 | * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : | ||
2338 | NUM_SCATTER_GATHER_ENTRIES) | ||
2339 | * sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
2340 | |||
2341 | u64 PASCListMem; | ||
2342 | PHW_SCATTER_GATHER_ELEMENT SCListEntry; | ||
2343 | u64 PASCListEntry; | ||
2344 | struct SBufferHeader *Cur; | ||
2345 | void *SCListMem; | ||
2346 | |||
2347 | if (SCListMemSize < 4096) | ||
2348 | SCListMemSize = 4096; | ||
2349 | |||
2350 | SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp); | ||
2351 | |||
2352 | PASCListMem = tmp; | ||
2353 | if (SCListMem == NULL) | ||
2354 | return -ENOMEM; | ||
2355 | |||
2356 | memset(SCListMem, 0, SCListMemSize); | ||
2357 | |||
2358 | pRingBuffer->SCListMem = SCListMem; | ||
2359 | pRingBuffer->PASCListMem = PASCListMem; | ||
2360 | pRingBuffer->SCListMemSize = SCListMemSize; | ||
2361 | pRingBuffer->Buffer1Length = Buffer1Length; | ||
2362 | pRingBuffer->Buffer2Length = Buffer2Length; | ||
2363 | |||
2364 | SCListEntry = (PHW_SCATTER_GATHER_ELEMENT) SCListMem; | ||
2365 | PASCListEntry = PASCListMem; | ||
2366 | Cur = pRingBuffer->Head; | ||
2367 | |||
2368 | for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) { | ||
2369 | u64 PABuffer; | ||
2370 | |||
2371 | void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length, | ||
2372 | &tmp); | ||
2373 | PABuffer = tmp; | ||
2374 | |||
2375 | if (Buffer == NULL) | ||
2376 | return -ENOMEM; | ||
2377 | |||
2378 | Cur->Buffer1 = Buffer; | ||
2379 | |||
2380 | SCListEntry->Address = PABuffer; | ||
2381 | SCListEntry->Length = Buffer1Length; | ||
2382 | |||
2383 | Cur->scList1 = SCListEntry; | ||
2384 | Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry; | ||
2385 | Cur->ngeneBuffer.Number_of_entries_1 = | ||
2386 | NUM_SCATTER_GATHER_ENTRIES; | ||
2387 | |||
2388 | SCListEntry += 1; | ||
2389 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
2390 | |||
2391 | #if NUM_SCATTER_GATHER_ENTRIES > 1 | ||
2392 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) { | ||
2393 | SCListEntry->Address = of; | ||
2394 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; | ||
2395 | SCListEntry += 1; | ||
2396 | PASCListEntry += | ||
2397 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
2398 | } | ||
2399 | #endif | ||
2400 | |||
2401 | if (!Buffer2Length) | ||
2402 | continue; | ||
2403 | |||
2404 | Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp); | ||
2405 | PABuffer = tmp; | ||
2406 | |||
2407 | if (Buffer == NULL) | ||
2408 | return -ENOMEM; | ||
2409 | |||
2410 | Cur->Buffer2 = Buffer; | ||
2411 | |||
2412 | SCListEntry->Address = PABuffer; | ||
2413 | SCListEntry->Length = Buffer2Length; | ||
2414 | |||
2415 | Cur->scList2 = SCListEntry; | ||
2416 | Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry; | ||
2417 | Cur->ngeneBuffer.Number_of_entries_2 = | ||
2418 | NUM_SCATTER_GATHER_ENTRIES; | ||
2419 | |||
2420 | SCListEntry += 1; | ||
2421 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
2422 | |||
2423 | #if NUM_SCATTER_GATHER_ENTRIES > 1 | ||
2424 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) { | ||
2425 | SCListEntry->Address = of; | ||
2426 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; | ||
2427 | SCListEntry += 1; | ||
2428 | PASCListEntry += | ||
2429 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
2430 | } | ||
2431 | #endif | ||
2432 | |||
2433 | } | ||
2434 | |||
2435 | return status; | ||
2436 | } | ||
2437 | |||
2438 | static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, | ||
2439 | struct SRingBufferDescriptor *pRingBuffer) | ||
2440 | { | ||
2441 | int status = 0; | ||
2442 | |||
2443 | /* Copy pointer to scatter gather list in TSRingbuffer | ||
2444 | structure for buffer 2 | ||
2445 | Load number of buffer | ||
2446 | */ | ||
2447 | u32 n = pRingBuffer->NumBuffers; | ||
2448 | |||
2449 | /* Point to first buffer entry */ | ||
2450 | struct SBufferHeader *Cur = pRingBuffer->Head; | ||
2451 | int i; | ||
2452 | /* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */ | ||
2453 | for (i = 0; i < n; i++) { | ||
2454 | Cur->Buffer2 = pIdleBuffer->Head->Buffer1; | ||
2455 | Cur->scList2 = pIdleBuffer->Head->scList1; | ||
2456 | Cur->ngeneBuffer.Address_of_first_entry_2 = | ||
2457 | pIdleBuffer->Head->ngeneBuffer. | ||
2458 | Address_of_first_entry_1; | ||
2459 | Cur->ngeneBuffer.Number_of_entries_2 = | ||
2460 | pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; | ||
2461 | Cur = Cur->Next; | ||
2462 | } | ||
2463 | return status; | ||
2464 | } | ||
2465 | |||
2466 | static u32 RingBufferSizes[MAX_STREAM] = { | ||
2467 | RING_SIZE_VIDEO, | ||
2468 | RING_SIZE_VIDEO, | ||
2469 | RING_SIZE_AUDIO, | ||
2470 | RING_SIZE_AUDIO, | ||
2471 | RING_SIZE_AUDIO, | ||
2472 | }; | ||
2473 | |||
2474 | static u32 Buffer1Sizes[MAX_STREAM] = { | ||
2475 | MAX_VIDEO_BUFFER_SIZE, | ||
2476 | MAX_VIDEO_BUFFER_SIZE, | ||
2477 | MAX_AUDIO_BUFFER_SIZE, | ||
2478 | MAX_AUDIO_BUFFER_SIZE, | ||
2479 | MAX_AUDIO_BUFFER_SIZE | ||
2480 | }; | ||
2481 | |||
2482 | static u32 Buffer2Sizes[MAX_STREAM] = { | ||
2483 | MAX_VBI_BUFFER_SIZE, | ||
2484 | MAX_VBI_BUFFER_SIZE, | ||
2485 | 0, | ||
2486 | 0, | ||
2487 | 0 | ||
2488 | }; | ||
2489 | |||
2490 | static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, | ||
2491 | struct SRingBufferDescriptor *rbuf, | ||
2492 | u32 entries, u32 size1, u32 size2) | ||
2493 | { | ||
2494 | if (create_ring_buffer(pci_dev, rbuf, entries) < 0) | ||
2495 | return -ENOMEM; | ||
2496 | |||
2497 | if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) | ||
2498 | return -ENOMEM; | ||
2499 | |||
2500 | return 0; | ||
2501 | } | ||
2502 | |||
2503 | static int channel_allocate_buffers(struct ngene_channel *chan) | ||
2504 | { | ||
2505 | struct ngene *dev = chan->dev; | ||
2506 | int type = dev->card_info->io_type[chan->number]; | ||
2507 | int status; | ||
2508 | |||
2509 | chan->State = KSSTATE_STOP; | ||
2510 | |||
2511 | if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { | ||
2512 | status = create_ring_buffer(dev->pci_dev, | ||
2513 | &chan->RingBuffer, | ||
2514 | RingBufferSizes[chan->number]); | ||
2515 | if (status < 0) | ||
2516 | return -ENOMEM; | ||
2517 | |||
2518 | if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { | ||
2519 | status = AllocateRingBuffers(dev->pci_dev, | ||
2520 | dev->PAOverflowBuffer, | ||
2521 | &chan->RingBuffer, | ||
2522 | Buffer1Sizes[chan->number], | ||
2523 | Buffer2Sizes[chan-> | ||
2524 | number]); | ||
2525 | if (status < 0) | ||
2526 | return -ENOMEM; | ||
2527 | } else if (type & NGENE_IO_HDTV) { | ||
2528 | status = AllocateRingBuffers(dev->pci_dev, | ||
2529 | dev->PAOverflowBuffer, | ||
2530 | &chan->RingBuffer, | ||
2531 | MAX_HDTV_BUFFER_SIZE, 0); | ||
2532 | if (status < 0) | ||
2533 | return -ENOMEM; | ||
2534 | } | ||
2535 | } | ||
2536 | |||
2537 | if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
2538 | |||
2539 | status = create_ring_buffer(dev->pci_dev, | ||
2540 | &chan->TSRingBuffer, RING_SIZE_TS); | ||
2541 | if (status < 0) | ||
2542 | return -ENOMEM; | ||
2543 | |||
2544 | status = AllocateRingBuffers(dev->pci_dev, | ||
2545 | dev->PAOverflowBuffer, | ||
2546 | &chan->TSRingBuffer, | ||
2547 | MAX_TS_BUFFER_SIZE, 0); | ||
2548 | if (status) | ||
2549 | return -ENOMEM; | ||
2550 | } | ||
2551 | |||
2552 | if (type & NGENE_IO_TSOUT) { | ||
2553 | status = create_ring_buffer(dev->pci_dev, | ||
2554 | &chan->TSIdleBuffer, 1); | ||
2555 | if (status < 0) | ||
2556 | return -ENOMEM; | ||
2557 | status = AllocateRingBuffers(dev->pci_dev, | ||
2558 | dev->PAOverflowBuffer, | ||
2559 | &chan->TSIdleBuffer, | ||
2560 | MAX_TS_BUFFER_SIZE, 0); | ||
2561 | if (status) | ||
2562 | return -ENOMEM; | ||
2563 | FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); | ||
2564 | } | ||
2565 | return 0; | ||
2566 | } | ||
2567 | |||
2568 | static int AllocCommonBuffers(struct ngene *dev) | ||
2569 | { | ||
2570 | int status = 0, i; | ||
2571 | |||
2572 | dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096, | ||
2573 | &dev->PAFWInterfaceBuffer); | ||
2574 | if (!dev->FWInterfaceBuffer) | ||
2575 | return -ENOMEM; | ||
2576 | dev->hosttongene = dev->FWInterfaceBuffer; | ||
2577 | dev->ngenetohost = dev->FWInterfaceBuffer + 256; | ||
2578 | dev->EventBuffer = dev->FWInterfaceBuffer + 512; | ||
2579 | |||
2580 | dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, | ||
2581 | OVERFLOW_BUFFER_SIZE, | ||
2582 | &dev->PAOverflowBuffer); | ||
2583 | if (!dev->OverflowBuffer) | ||
2584 | return -ENOMEM; | ||
2585 | memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); | ||
2586 | |||
2587 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { | ||
2588 | int type = dev->card_info->io_type[i]; | ||
2589 | |||
2590 | dev->channel[i].State = KSSTATE_STOP; | ||
2591 | |||
2592 | if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { | ||
2593 | status = create_ring_buffer(dev->pci_dev, | ||
2594 | &dev->channel[i].RingBuffer, | ||
2595 | RingBufferSizes[i]); | ||
2596 | if (status < 0) | ||
2597 | break; | ||
2598 | |||
2599 | if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { | ||
2600 | status = AllocateRingBuffers(dev->pci_dev, | ||
2601 | dev-> | ||
2602 | PAOverflowBuffer, | ||
2603 | &dev->channel[i]. | ||
2604 | RingBuffer, | ||
2605 | Buffer1Sizes[i], | ||
2606 | Buffer2Sizes[i]); | ||
2607 | if (status < 0) | ||
2608 | break; | ||
2609 | } else if (type & NGENE_IO_HDTV) { | ||
2610 | status = AllocateRingBuffers(dev->pci_dev, | ||
2611 | dev-> | ||
2612 | PAOverflowBuffer, | ||
2613 | &dev->channel[i]. | ||
2614 | RingBuffer, | ||
2615 | MAX_HDTV_BUFFER_SIZE, | ||
2616 | 0); | ||
2617 | if (status < 0) | ||
2618 | break; | ||
2619 | } | ||
2620 | } | ||
2621 | |||
2622 | if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
2623 | |||
2624 | status = create_ring_buffer(dev->pci_dev, | ||
2625 | &dev->channel[i]. | ||
2626 | TSRingBuffer, RING_SIZE_TS); | ||
2627 | if (status < 0) | ||
2628 | break; | ||
2629 | |||
2630 | status = AllocateRingBuffers(dev->pci_dev, | ||
2631 | dev->PAOverflowBuffer, | ||
2632 | &dev->channel[i]. | ||
2633 | TSRingBuffer, | ||
2634 | MAX_TS_BUFFER_SIZE, 0); | ||
2635 | if (status) | ||
2636 | break; | ||
2637 | } | ||
2638 | |||
2639 | if (type & NGENE_IO_TSOUT) { | ||
2640 | status = create_ring_buffer(dev->pci_dev, | ||
2641 | &dev->channel[i]. | ||
2642 | TSIdleBuffer, 1); | ||
2643 | if (status < 0) | ||
2644 | break; | ||
2645 | status = AllocateRingBuffers(dev->pci_dev, | ||
2646 | dev->PAOverflowBuffer, | ||
2647 | &dev->channel[i]. | ||
2648 | TSIdleBuffer, | ||
2649 | MAX_TS_BUFFER_SIZE, 0); | ||
2650 | if (status) | ||
2651 | break; | ||
2652 | FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer, | ||
2653 | &dev->channel[i].TSRingBuffer); | ||
2654 | } | ||
2655 | } | ||
2656 | return status; | ||
2657 | } | ||
2658 | |||
2659 | static void ngene_release_buffers(struct ngene *dev) | ||
2660 | { | ||
2661 | if (dev->iomem) | ||
2662 | iounmap(dev->iomem); | ||
2663 | free_common_buffers(dev); | ||
2664 | vfree(dev->tsout_buf); | ||
2665 | vfree(dev->ain_buf); | ||
2666 | vfree(dev->vin_buf); | ||
2667 | vfree(dev); | ||
2668 | } | ||
2669 | |||
2670 | static int ngene_get_buffers(struct ngene *dev) | ||
2671 | { | ||
2672 | if (AllocCommonBuffers(dev)) | ||
2673 | return -ENOMEM; | ||
2674 | if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) { | ||
2675 | dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE); | ||
2676 | if (!dev->tsout_buf) | ||
2677 | return -ENOMEM; | ||
2678 | dvb_ringbuffer_init(&dev->tsout_rbuf, | ||
2679 | dev->tsout_buf, TSOUT_BUF_SIZE); | ||
2680 | } | ||
2681 | if (dev->card_info->io_type[2] & NGENE_IO_AIN) { | ||
2682 | dev->ain_buf = vmalloc(AIN_BUF_SIZE); | ||
2683 | if (!dev->ain_buf) | ||
2684 | return -ENOMEM; | ||
2685 | dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE); | ||
2686 | } | ||
2687 | if (dev->card_info->io_type[0] & NGENE_IO_HDTV) { | ||
2688 | dev->vin_buf = vmalloc(VIN_BUF_SIZE); | ||
2689 | if (!dev->vin_buf) | ||
2690 | return -ENOMEM; | ||
2691 | dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE); | ||
2692 | } | ||
2693 | dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0), | ||
2694 | pci_resource_len(dev->pci_dev, 0)); | ||
2695 | if (!dev->iomem) | ||
2696 | return -ENOMEM; | ||
2697 | |||
2698 | return 0; | ||
2699 | } | ||
2700 | |||
2701 | static void ngene_init(struct ngene *dev) | ||
2702 | { | ||
2703 | int i; | ||
2704 | |||
2705 | tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev); | ||
2706 | |||
2707 | memset_io(dev->iomem + 0xc000, 0x00, 0x220); | ||
2708 | memset_io(dev->iomem + 0xc400, 0x00, 0x100); | ||
2709 | |||
2710 | for (i = 0; i < MAX_STREAM; i++) { | ||
2711 | dev->channel[i].dev = dev; | ||
2712 | dev->channel[i].number = i; | ||
2713 | } | ||
2714 | |||
2715 | dev->fw_interface_version = 0; | ||
2716 | |||
2717 | ngwritel(0, NGENE_INT_ENABLE); | ||
2718 | |||
2719 | dev->icounts = ngreadl(NGENE_INT_COUNTS); | ||
2720 | |||
2721 | dev->device_version = ngreadl(DEV_VER) & 0x0f; | ||
2722 | printk(KERN_INFO DEVICE_NAME ": Device version %d\n", | ||
2723 | dev->device_version); | ||
2724 | } | ||
2725 | |||
2726 | static int ngene_load_firm(struct ngene *dev) | ||
2727 | { | ||
2728 | u32 size; | ||
2729 | const struct firmware *fw = NULL; | ||
2730 | u8 *ngene_fw; | ||
2731 | char *fw_name; | ||
2732 | int err, version; | ||
2733 | |||
2734 | version = dev->card_info->fw_version; | ||
2735 | |||
2736 | switch (version) { | ||
2737 | default: | ||
2738 | case 15: | ||
2739 | version = 15; | ||
2740 | ngene_fw = FW15; | ||
2741 | size = sizeof(FW15); | ||
2742 | fw_name = "ngene_15.fw"; | ||
2743 | break; | ||
2744 | case 16: | ||
2745 | ngene_fw = FW16; | ||
2746 | size = sizeof(FW16); | ||
2747 | fw_name = "ngene_16.fw"; | ||
2748 | break; | ||
2749 | case 17: | ||
2750 | ngene_fw = FW17; | ||
2751 | size = sizeof(FW17); | ||
2752 | fw_name = "ngene_17.fw"; | ||
2753 | break; | ||
2754 | } | ||
2755 | #ifdef FW_INC | ||
2756 | if (load_firmware && | ||
2757 | request_firmware(&fw, fw_name, &dev->pci_dev->dev) >= 0) { | ||
2758 | printk(KERN_INFO DEVICE_NAME | ||
2759 | ": Loading firmware file %s.\n", fw_name); | ||
2760 | size = fw->size; | ||
2761 | ngene_fw = fw->data; | ||
2762 | } else | ||
2763 | printk(KERN_INFO DEVICE_NAME | ||
2764 | ": Loading built-in firmware version %d.\n", version); | ||
2765 | err = ngene_command_load_firmware(dev, ngene_fw, size); | ||
2766 | |||
2767 | if (fw) | ||
2768 | release_firmware(fw); | ||
2769 | #else | ||
2770 | if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) { | ||
2771 | printk(KERN_ERR DEVICE_NAME | ||
2772 | ": Could not load firmware file %s. \n", fw_name); | ||
2773 | printk(KERN_INFO DEVICE_NAME | ||
2774 | ": Copy %s to your hotplug directory!\n", fw_name); | ||
2775 | return -1; | ||
2776 | } | ||
2777 | printk(KERN_INFO DEVICE_NAME ": Loading firmware file %s.\n", fw_name); | ||
2778 | size = fw->size; | ||
2779 | ngene_fw = fw->data; | ||
2780 | err = ngene_command_load_firmware(dev, ngene_fw, size); | ||
2781 | release_firmware(fw); | ||
2782 | #endif | ||
2783 | return err; | ||
2784 | } | ||
2785 | |||
2786 | static void ngene_stop(struct ngene *dev) | ||
2787 | { | ||
2788 | down(&dev->cmd_mutex); | ||
2789 | i2c_del_adapter(&(dev->channel[0].i2c_adapter)); | ||
2790 | i2c_del_adapter(&(dev->channel[1].i2c_adapter)); | ||
2791 | ngwritel(0, NGENE_INT_ENABLE); | ||
2792 | ngwritel(0, NGENE_COMMAND); | ||
2793 | ngwritel(0, NGENE_COMMAND_HI); | ||
2794 | ngwritel(0, NGENE_STATUS); | ||
2795 | ngwritel(0, NGENE_STATUS_HI); | ||
2796 | ngwritel(0, NGENE_EVENT); | ||
2797 | ngwritel(0, NGENE_EVENT_HI); | ||
2798 | free_irq(dev->pci_dev->irq, dev); | ||
2799 | } | ||
2800 | |||
2801 | static int ngene_start(struct ngene *dev) | ||
2802 | { | ||
2803 | int stat; | ||
2804 | int i; | ||
2805 | |||
2806 | pci_set_master(dev->pci_dev); | ||
2807 | ngene_init(dev); | ||
2808 | |||
2809 | stat = request_irq(dev->pci_dev->irq, irq_handler, | ||
2810 | IRQF_SHARED, "nGene", | ||
2811 | (void *)dev); | ||
2812 | if (stat < 0) | ||
2813 | return stat; | ||
2814 | |||
2815 | init_waitqueue_head(&dev->cmd_wq); | ||
2816 | init_waitqueue_head(&dev->tx_wq); | ||
2817 | init_waitqueue_head(&dev->rx_wq); | ||
2818 | sema_init(&dev->cmd_mutex, 1); | ||
2819 | sema_init(&dev->stream_mutex, 1); | ||
2820 | sema_init(&dev->pll_mutex, 1); | ||
2821 | sema_init(&dev->i2c_switch_mutex, 1); | ||
2822 | spin_lock_init(&dev->cmd_lock); | ||
2823 | for (i = 0; i < MAX_STREAM; i++) | ||
2824 | spin_lock_init(&dev->channel[i].state_lock); | ||
2825 | ngwritel(1, TIMESTAMPS); | ||
2826 | |||
2827 | ngwritel(1, NGENE_INT_ENABLE); | ||
2828 | |||
2829 | stat = ngene_load_firm(dev); | ||
2830 | if (stat < 0) | ||
2831 | goto fail; | ||
2832 | |||
2833 | stat = ngene_i2c_init(dev, 0); | ||
2834 | if (stat < 0) | ||
2835 | goto fail; | ||
2836 | |||
2837 | stat = ngene_i2c_init(dev, 1); | ||
2838 | if (stat < 0) | ||
2839 | goto fail; | ||
2840 | |||
2841 | if (dev->card_info->fw_version == 17) { | ||
2842 | u8 hdtv_config[6] = | ||
2843 | {6144 / 64, 0, 0, 2048 / 64, 2048 / 64, 2048 / 64}; | ||
2844 | u8 tsin4_config[6] = | ||
2845 | {3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; | ||
2846 | u8 ts5_config[6] = | ||
2847 | {2048 / 64, 2048 / 64, 0, 2048 / 64, 2048 / 64, | ||
2848 | 2048 / 64}; | ||
2849 | u8 default_config[6] = | ||
2850 | {4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; | ||
2851 | u8 *bconf = default_config; | ||
2852 | |||
2853 | if (dev->card_info->io_type[3] == NGENE_IO_TSIN) | ||
2854 | bconf = tsin4_config; | ||
2855 | if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { | ||
2856 | bconf = hdtv_config; | ||
2857 | ngene_reset_decypher(dev); | ||
2858 | } | ||
2859 | printk(KERN_INFO DEVICE_NAME ": FW 17 buffer config\n"); | ||
2860 | stat = ngene_command_config_free_buf(dev, bconf); | ||
2861 | } else { | ||
2862 | int bconf = BUFFER_CONFIG_4422; | ||
2863 | |||
2864 | if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { | ||
2865 | bconf = BUFFER_CONFIG_8022; | ||
2866 | ngene_reset_decypher(dev); | ||
2867 | } | ||
2868 | if (dev->card_info->io_type[3] == NGENE_IO_TSIN) | ||
2869 | bconf = BUFFER_CONFIG_3333; | ||
2870 | stat = ngene_command_config_buf(dev, bconf); | ||
2871 | } | ||
2872 | |||
2873 | if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { | ||
2874 | ngene_command_config_uart(dev, 0xc1, tx_cb, rx_cb); | ||
2875 | test_dec_i2c(&dev->channel[0].i2c_adapter, 0); | ||
2876 | test_dec_i2c(&dev->channel[0].i2c_adapter, 1); | ||
2877 | } | ||
2878 | |||
2879 | return stat; | ||
2880 | fail: | ||
2881 | ngwritel(0, NGENE_INT_ENABLE); | ||
2882 | free_irq(dev->pci_dev->irq, dev); | ||
2883 | return stat; | ||
2884 | } | ||
2885 | |||
2886 | /****************************************************************************/ | ||
2887 | /* DVB audio/video device functions *****************************************/ | ||
2888 | /****************************************************************************/ | ||
2889 | |||
2890 | static ssize_t audio_write(struct file *file, | ||
2891 | const char *buf, size_t count, loff_t *ppos) | ||
2892 | { | ||
2893 | return -EINVAL; | ||
2894 | } | ||
2895 | |||
2896 | ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) | ||
2897 | { | ||
2898 | struct dvb_device *dvbdev = file->private_data; | ||
2899 | struct ngene_channel *chan = dvbdev->priv; | ||
2900 | struct ngene *dev = chan->dev; | ||
2901 | int left; | ||
2902 | int avail; | ||
2903 | |||
2904 | left = count; | ||
2905 | while (left) { | ||
2906 | if (wait_event_interruptible( | ||
2907 | dev->ain_rbuf.queue, | ||
2908 | dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) | ||
2909 | return -EAGAIN; | ||
2910 | avail = dvb_ringbuffer_avail(&dev->ain_rbuf); | ||
2911 | if (avail > left) | ||
2912 | avail = left; | ||
2913 | dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); | ||
2914 | left -= avail; | ||
2915 | buf += avail; | ||
2916 | } | ||
2917 | return count; | ||
2918 | } | ||
2919 | |||
2920 | static int audio_open(struct inode *inode, struct file *file) | ||
2921 | { | ||
2922 | struct dvb_device *dvbdev = file->private_data; | ||
2923 | struct ngene_channel *chan = dvbdev->priv; | ||
2924 | struct ngene *dev = chan->dev; | ||
2925 | struct ngene_channel *chan2 = &chan->dev->channel[2]; | ||
2926 | int ret; | ||
2927 | |||
2928 | ret = dvb_generic_open(inode, file); | ||
2929 | if (ret < 0) | ||
2930 | return ret; | ||
2931 | my_dvb_ringbuffer_flush(&dev->ain_rbuf); | ||
2932 | |||
2933 | chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; | ||
2934 | chan2->pBufferExchange = ain_exchange; | ||
2935 | ngene_command_stream_control(chan2->dev, chan2->number, 0x80, | ||
2936 | SMODE_AUDIO_CAPTURE, 0); | ||
2937 | return ret; | ||
2938 | } | ||
2939 | |||
2940 | static int audio_release(struct inode *inode, struct file *file) | ||
2941 | { | ||
2942 | struct dvb_device *dvbdev = file->private_data; | ||
2943 | struct ngene_channel *chan = dvbdev->priv; | ||
2944 | struct ngene *dev = chan->dev; | ||
2945 | struct ngene_channel *chan2 = &chan->dev->channel[2]; | ||
2946 | |||
2947 | ngene_command_stream_control(dev, 2, 0, 0, 0); | ||
2948 | chan2->pBufferExchange = 0; | ||
2949 | |||
2950 | return dvb_generic_release(inode, file); | ||
2951 | } | ||
2952 | |||
2953 | static const struct file_operations audio_fops = { | ||
2954 | .owner = THIS_MODULE, | ||
2955 | .read = audio_read, | ||
2956 | .write = audio_write, | ||
2957 | .open = audio_open, | ||
2958 | .release = audio_release, | ||
2959 | }; | ||
2960 | |||
2961 | static struct dvb_device dvbdev_audio = { | ||
2962 | .priv = 0, | ||
2963 | .readers = -1, | ||
2964 | .writers = 1, | ||
2965 | .users = 1, | ||
2966 | .fops = &audio_fops, | ||
2967 | }; | ||
2968 | |||
2969 | static int video_open(struct inode *inode, struct file *file) | ||
2970 | { | ||
2971 | struct dvb_device *dvbdev = file->private_data; | ||
2972 | struct ngene_channel *chan = dvbdev->priv; | ||
2973 | struct ngene *dev = chan->dev; | ||
2974 | struct ngene_channel *chan0 = &chan->dev->channel[0]; | ||
2975 | int ret; | ||
2976 | |||
2977 | ret = dvb_generic_open(inode, file); | ||
2978 | if (ret < 0) | ||
2979 | return ret; | ||
2980 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) | ||
2981 | return ret; | ||
2982 | my_dvb_ringbuffer_flush(&dev->vin_rbuf); | ||
2983 | |||
2984 | chan0->nBytesPerLine = 1920 * 2; | ||
2985 | chan0->nLines = 540; | ||
2986 | chan0->Capture1Length = 1920 * 2 * 540; | ||
2987 | chan0->pBufferExchange = vcap_exchange; | ||
2988 | chan0->itumode = 2; | ||
2989 | ngene_command_stream_control(chan0->dev, chan0->number, | ||
2990 | 0x80, SMODE_VIDEO_CAPTURE, 0); | ||
2991 | return ret; | ||
2992 | } | ||
2993 | |||
2994 | static int video_release(struct inode *inode, struct file *file) | ||
2995 | { | ||
2996 | struct dvb_device *dvbdev = file->private_data; | ||
2997 | struct ngene_channel *chan = dvbdev->priv; | ||
2998 | struct ngene *dev = chan->dev; | ||
2999 | struct ngene_channel *chan0 = &chan->dev->channel[0]; | ||
3000 | |||
3001 | ngene_command_stream_control(dev, 0, 0, 0, 0); | ||
3002 | chan0->pBufferExchange = 0; | ||
3003 | |||
3004 | return dvb_generic_release(inode, file); | ||
3005 | } | ||
3006 | |||
3007 | static ssize_t video_write(struct file *file, | ||
3008 | const char *buf, size_t count, loff_t *ppos) | ||
3009 | { | ||
3010 | return -EINVAL; | ||
3011 | } | ||
3012 | |||
3013 | ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) | ||
3014 | { | ||
3015 | struct dvb_device *dvbdev = file->private_data; | ||
3016 | struct ngene_channel *chan = dvbdev->priv; | ||
3017 | struct ngene *dev = chan->dev; | ||
3018 | int left, avail; | ||
3019 | |||
3020 | left = count; | ||
3021 | while (left) { | ||
3022 | if (wait_event_interruptible( | ||
3023 | dev->vin_rbuf.queue, | ||
3024 | dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) | ||
3025 | return -EAGAIN; | ||
3026 | avail = dvb_ringbuffer_avail(&dev->vin_rbuf); | ||
3027 | if (avail > left) | ||
3028 | avail = left; | ||
3029 | dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); | ||
3030 | left -= avail; | ||
3031 | buf += avail; | ||
3032 | } | ||
3033 | return count; | ||
3034 | } | ||
3035 | |||
3036 | /* Why is this not exported from dvb_core ?!?! */ | ||
3037 | |||
3038 | static int dvb_usercopy2(struct inode *inode, struct file *file, | ||
3039 | unsigned int cmd, unsigned long arg, | ||
3040 | int (*func)(struct inode *inode, struct file *file, | ||
3041 | unsigned int cmd, void *arg)) | ||
3042 | { | ||
3043 | char sbuf[128]; | ||
3044 | void *mbuf = NULL; | ||
3045 | void *parg = NULL; | ||
3046 | int err = -EINVAL; | ||
3047 | |||
3048 | /* Copy arguments into temp kernel buffer */ | ||
3049 | switch (_IOC_DIR(cmd)) { | ||
3050 | case _IOC_NONE: | ||
3051 | /* | ||
3052 | * For this command, the pointer is actually an integer | ||
3053 | * argument. | ||
3054 | */ | ||
3055 | parg = (void *)arg; | ||
3056 | break; | ||
3057 | case _IOC_READ: /* some v4l ioctls are marked wrong ... */ | ||
3058 | case _IOC_WRITE: | ||
3059 | case (_IOC_WRITE | _IOC_READ): | ||
3060 | if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { | ||
3061 | parg = sbuf; | ||
3062 | } else { | ||
3063 | /* too big to allocate from stack */ | ||
3064 | mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); | ||
3065 | if (NULL == mbuf) | ||
3066 | return -ENOMEM; | ||
3067 | parg = mbuf; | ||
3068 | } | ||
3069 | |||
3070 | err = -EFAULT; | ||
3071 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
3072 | goto out; | ||
3073 | break; | ||
3074 | } | ||
3075 | |||
3076 | /* call driver */ | ||
3077 | err = func(inode, file, cmd, parg); | ||
3078 | if (err == -ENOIOCTLCMD) | ||
3079 | err = -EINVAL; | ||
3080 | |||
3081 | if (err < 0) | ||
3082 | goto out; | ||
3083 | |||
3084 | /* Copy results into user buffer */ | ||
3085 | switch (_IOC_DIR(cmd)) { | ||
3086 | case _IOC_READ: | ||
3087 | case (_IOC_WRITE | _IOC_READ): | ||
3088 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
3089 | err = -EFAULT; | ||
3090 | break; | ||
3091 | } | ||
3092 | |||
3093 | out: | ||
3094 | kfree(mbuf); | ||
3095 | return err; | ||
3096 | } | ||
3097 | |||
3098 | static int video_do_ioctl(struct inode *inode, struct file *file, | ||
3099 | unsigned int cmd, void *parg) | ||
3100 | { | ||
3101 | struct dvb_device *dvbdev = file->private_data; | ||
3102 | struct ngene_channel *chan = dvbdev->priv; | ||
3103 | struct ngene *dev = chan->dev; | ||
3104 | int ret = 0; | ||
3105 | unsigned long arg = (unsigned long)parg; | ||
3106 | |||
3107 | switch (cmd) { | ||
3108 | case VIDEO_SET_STREAMTYPE: | ||
3109 | switch (arg) { | ||
3110 | case VIDEO_CAP_MPEG2: | ||
3111 | /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ | ||
3112 | send_cli(dev, "vdec mpeg2\n"); | ||
3113 | break; | ||
3114 | case VIDEO_CAP_AVC: | ||
3115 | /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ | ||
3116 | send_cli(dev, "vdec h264\n"); | ||
3117 | break; | ||
3118 | case VIDEO_CAP_VC1: | ||
3119 | /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ | ||
3120 | send_cli(dev, "vdec vc1\n"); | ||
3121 | break; | ||
3122 | default: | ||
3123 | ret = -EINVAL; | ||
3124 | break; | ||
3125 | } | ||
3126 | break; | ||
3127 | default: | ||
3128 | ret = -ENOIOCTLCMD; | ||
3129 | return -EINVAL; | ||
3130 | } | ||
3131 | return ret; | ||
3132 | } | ||
3133 | |||
3134 | static int video_ioctl(struct inode *inode, struct file *file, | ||
3135 | unsigned int cmd, unsigned long arg) | ||
3136 | { | ||
3137 | return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); | ||
3138 | } | ||
3139 | |||
3140 | static const struct file_operations video_fops = { | ||
3141 | .owner = THIS_MODULE, | ||
3142 | .read = video_read, | ||
3143 | .write = video_write, | ||
3144 | .open = video_open, | ||
3145 | .release = video_release, | ||
3146 | .ioctl = video_ioctl, | ||
3147 | }; | ||
3148 | |||
3149 | static struct dvb_device dvbdev_video = { | ||
3150 | .priv = 0, | ||
3151 | .readers = -1, | ||
3152 | .writers = 1, | ||
3153 | .users = -1, | ||
3154 | .fops = &video_fops, | ||
3155 | }; | ||
3156 | |||
3157 | /****************************************************************************/ | ||
3158 | /* LNBH21 *******************************************************************/ | ||
3159 | /****************************************************************************/ | ||
3160 | |||
3161 | static int lnbh21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
3162 | { | ||
3163 | struct ngene_channel *chan = | ||
3164 | *(struct ngene_channel **) fe->demodulator_priv; | ||
3165 | |||
3166 | switch (voltage) { | ||
3167 | case SEC_VOLTAGE_OFF: | ||
3168 | chan->lnbh &= 0xf3; | ||
3169 | break; | ||
3170 | case SEC_VOLTAGE_13: | ||
3171 | chan->lnbh |= 0x04; | ||
3172 | chan->lnbh &= ~0x08; | ||
3173 | break; | ||
3174 | case SEC_VOLTAGE_18: | ||
3175 | chan->lnbh |= 0x0c; | ||
3176 | break; | ||
3177 | default: | ||
3178 | return -EINVAL; | ||
3179 | }; | ||
3180 | chan->lnbh |= 0x10; | ||
3181 | return i2c_write(&chan->i2c_adapter, | ||
3182 | chan->dev->card_info->lnb[chan->number], chan->lnbh); | ||
3183 | } | ||
3184 | |||
3185 | static int lnbh21_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
3186 | { | ||
3187 | struct ngene_channel *chan = | ||
3188 | *(struct ngene_channel **)fe->demodulator_priv; | ||
3189 | |||
3190 | switch (tone) { | ||
3191 | case SEC_TONE_ON: | ||
3192 | chan->lnbh |= 0x20; | ||
3193 | break; | ||
3194 | case SEC_TONE_OFF: | ||
3195 | chan->lnbh &= 0xdf; | ||
3196 | break; | ||
3197 | default: | ||
3198 | return -EINVAL; | ||
3199 | } | ||
3200 | return i2c_write(&chan->i2c_adapter, | ||
3201 | chan->dev->card_info->lnb[chan->number], chan->lnbh); | ||
3202 | } | ||
3203 | |||
3204 | /****************************************************************************/ | ||
3205 | /* Switch control (I2C gates, etc.) *****************************************/ | ||
3206 | /****************************************************************************/ | ||
3207 | |||
3208 | static int avf_output(struct ngene_channel *chan, int state) | ||
3209 | { | ||
3210 | if (chan->dev->card_info->avf[chan->number]) | ||
3211 | i2c_write_register(&chan->i2c_adapter, | ||
3212 | chan->dev->card_info->avf[chan->number], | ||
3213 | 0xf2, state ? 0x89 : 0x80); | ||
3214 | return 0; | ||
3215 | } | ||
3216 | |||
3217 | /* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ | ||
3218 | |||
3219 | static int exp_set(struct ngene *dev) | ||
3220 | { | ||
3221 | return i2c_write(&dev->channel[0].i2c_adapter, | ||
3222 | dev->card_info->exp, dev->exp_val); | ||
3223 | } | ||
3224 | |||
3225 | static int exp_init(struct ngene *dev) | ||
3226 | { | ||
3227 | if (!dev->card_info->exp) | ||
3228 | return 0; | ||
3229 | dev->exp_val = dev->card_info->exp_init; | ||
3230 | return exp_set(dev); | ||
3231 | } | ||
3232 | |||
3233 | static int exp_set_bit(struct ngene *dev, int bit, int val) | ||
3234 | { | ||
3235 | if (val) | ||
3236 | set_bit(bit, &dev->exp_val); | ||
3237 | else | ||
3238 | clear_bit(bit, &dev->exp_val); | ||
3239 | return exp_set(dev); | ||
3240 | } | ||
3241 | |||
3242 | static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) | ||
3243 | { | ||
3244 | switch (type) { | ||
3245 | case 0: /* I2C tuner gate on/off */ | ||
3246 | return exp_set_bit(chan->dev, 4 + chan->number, val); | ||
3247 | case 1: /* Stream: 0=TS 1=ITU */ | ||
3248 | avf_output(chan, val); | ||
3249 | return exp_set_bit(chan->dev, 6 + chan->number, val); | ||
3250 | case 2: /* Input: 0=digital 1=analog antenna input */ | ||
3251 | exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); | ||
3252 | exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); | ||
3253 | break; | ||
3254 | } | ||
3255 | return 0; | ||
3256 | } | ||
3257 | |||
3258 | static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) | ||
3259 | { | ||
3260 | switch (type) { | ||
3261 | case 0: /* I2C tuner gate on/off */ | ||
3262 | return exp_set_bit(chan->dev, 4 + chan->number, val); | ||
3263 | case 1: /* Stream: 0=TS 1=ITU */ | ||
3264 | avf_output(chan, val); | ||
3265 | return exp_set_bit(chan->dev, 6 + chan->number, val); | ||
3266 | case 2: /* Input: 0=digital 1=analog antenna input */ | ||
3267 | exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); | ||
3268 | exp_set_bit(chan->dev, 1 + chan->number * 2, 0); | ||
3269 | break; | ||
3270 | } | ||
3271 | return 0; | ||
3272 | } | ||
3273 | |||
3274 | static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
3275 | { | ||
3276 | /* Well, just abuse sec :-) */ | ||
3277 | struct ngene_channel *chan = fe->sec_priv; | ||
3278 | struct ngene *dev = chan->dev; | ||
3279 | |||
3280 | return dev->card_info->switch_ctrl(chan, 0, enable); | ||
3281 | } | ||
3282 | |||
3283 | static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) | ||
3284 | { | ||
3285 | switch (type) { | ||
3286 | case 0: /* I2C tuner gate on/off */ | ||
3287 | if (chan->number > 1) | ||
3288 | return -EINVAL; | ||
3289 | return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); | ||
3290 | case 1: /* Stream: 0=TS 1=ITU */ | ||
3291 | avf_output(chan, val); | ||
3292 | return 0; | ||
3293 | } | ||
3294 | return 0; | ||
3295 | } | ||
3296 | |||
3297 | static int viper_reset_xc(struct dvb_frontend *fe) | ||
3298 | { | ||
3299 | struct ngene_channel *chan = fe->sec_priv; | ||
3300 | struct ngene *dev = chan->dev; | ||
3301 | |||
3302 | printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); | ||
3303 | |||
3304 | if (chan->number > 1) | ||
3305 | return -EINVAL; | ||
3306 | |||
3307 | ngene_command_gpio_set(dev, 3 + chan->number, 0); | ||
3308 | msleep(150); | ||
3309 | ngene_command_gpio_set(dev, 3 + chan->number, 1); | ||
3310 | return 0; | ||
3311 | } | ||
3312 | |||
3313 | static int python_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
3314 | { | ||
3315 | struct ngene_channel *chan = fe->sec_priv; | ||
3316 | struct ngene *dev = chan->dev; | ||
3317 | |||
3318 | if (chan->number == 0) | ||
3319 | return ngene_command_gpio_set(dev, 3, enable); | ||
3320 | if (chan->number == 1) | ||
3321 | return ngene_command_gpio_set(dev, 4, enable); | ||
3322 | return -EINVAL; | ||
3323 | } | ||
3324 | |||
3325 | /****************************************************************************/ | ||
3326 | /* Demod/tuner attachment ***************************************************/ | ||
3327 | /****************************************************************************/ | ||
3328 | |||
3329 | static int tuner_attach_mt2060(struct ngene_channel *chan) | ||
3330 | { | ||
3331 | struct ngene *dev = chan->dev; | ||
3332 | void *tconf = dev->card_info->tuner_config[chan->number]; | ||
3333 | u8 drxa = dev->card_info->demoda[chan->number]; | ||
3334 | struct dvb_frontend *fe = chan->fe, *fe2; | ||
3335 | |||
3336 | fe->sec_priv = chan; | ||
3337 | fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; | ||
3338 | |||
3339 | dev->card_info->gate_ctrl(fe, 1); | ||
3340 | fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); | ||
3341 | dev->card_info->gate_ctrl(fe, 0); | ||
3342 | |||
3343 | i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); | ||
3344 | write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); | ||
3345 | write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); | ||
3346 | write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); | ||
3347 | |||
3348 | return fe2 ? 0 : -ENODEV; | ||
3349 | } | ||
3350 | |||
3351 | static int tuner_attach_xc3028(struct ngene_channel *chan) | ||
3352 | { | ||
3353 | struct ngene *dev = chan->dev; | ||
3354 | void *tconf = dev->card_info->tuner_config[chan->number]; | ||
3355 | struct dvb_frontend *fe = chan->fe, *fe2; | ||
3356 | |||
3357 | fe->sec_priv = chan; | ||
3358 | fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; | ||
3359 | |||
3360 | dev->card_info->gate_ctrl(fe, 1); | ||
3361 | fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); | ||
3362 | dev->card_info->gate_ctrl(fe, 0); | ||
3363 | |||
3364 | /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ | ||
3365 | |||
3366 | return fe2 ? 0 : -ENODEV; | ||
3367 | } | ||
3368 | |||
3369 | static int demod_attach_drxd(struct ngene_channel *chan) | ||
3370 | { | ||
3371 | void *feconf = chan->dev->card_info->fe_config[chan->number]; | ||
3372 | |||
3373 | chan->fe = drxd_attach(feconf, | ||
3374 | chan, &chan->i2c_adapter, | ||
3375 | &chan->dev->pci_dev->dev); | ||
3376 | return (chan->fe) ? 0 : -ENODEV; | ||
3377 | } | ||
3378 | |||
3379 | static int demod_attach_drxh(struct ngene_channel *chan) | ||
3380 | { | ||
3381 | void *feconf = chan->dev->card_info->fe_config[chan->number]; | ||
3382 | |||
3383 | chan->fe = drxh_attach(feconf, chan, | ||
3384 | &chan->i2c_adapter, &chan->dev->pci_dev->dev); | ||
3385 | return (chan->fe) ? 0 : -ENODEV; | ||
3386 | } | ||
3387 | |||
3388 | static int demod_attach_stb0899(struct ngene_channel *chan) | ||
3389 | { | ||
3390 | void *feconf = chan->dev->card_info->fe_config[chan->number]; | ||
3391 | |||
3392 | chan->fe = stb0899_attach(feconf, | ||
3393 | chan, &chan->i2c_adapter, | ||
3394 | &chan->dev->pci_dev->dev); | ||
3395 | if (chan->fe) { | ||
3396 | chan->set_tone = chan->fe->ops.set_tone; | ||
3397 | chan->fe->ops.set_tone = lnbh21_set_tone; | ||
3398 | chan->fe->ops.set_voltage = lnbh21_set_voltage; | ||
3399 | } | ||
3400 | |||
3401 | return (chan->fe) ? 0 : -ENODEV; | ||
3402 | } | ||
3403 | |||
3404 | static int demod_attach_stv0900(struct ngene_channel *chan) | ||
3405 | { | ||
3406 | void *feconf = chan->dev->card_info->fe_config[chan->number]; | ||
3407 | |||
3408 | chan->fe = stv0900_attach(feconf, | ||
3409 | chan, &chan->i2c_adapter, | ||
3410 | &chan->dev->pci_dev->dev); | ||
3411 | |||
3412 | if (chan->fe) { | ||
3413 | chan->set_tone = chan->fe->ops.set_tone; | ||
3414 | chan->fe->ops.set_tone = lnbh21_set_tone; | ||
3415 | chan->fe->ops.set_voltage = lnbh21_set_voltage; | ||
3416 | } | ||
3417 | |||
3418 | return (chan->fe) ? 0 : -ENODEV; | ||
3419 | } | ||
3420 | |||
3421 | /****************************************************************************/ | ||
3422 | /****************************************************************************/ | ||
3423 | /****************************************************************************/ | ||
3424 | |||
3425 | static void release_channel(struct ngene_channel *chan) | ||
3426 | { | ||
3427 | struct dvb_demux *dvbdemux = &chan->demux; | ||
3428 | struct ngene *dev = chan->dev; | ||
3429 | struct ngene_info *ni = dev->card_info; | ||
3430 | int io = ni->io_type[chan->number]; | ||
3431 | |||
3432 | tasklet_kill(&chan->demux_tasklet); | ||
3433 | |||
3434 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
3435 | #ifdef NGENE_COMMAND_API | ||
3436 | if (chan->command_dev) | ||
3437 | dvb_unregister_device(chan->command_dev); | ||
3438 | #endif | ||
3439 | if (chan->audio_dev) | ||
3440 | dvb_unregister_device(chan->audio_dev); | ||
3441 | if (chan->video_dev) | ||
3442 | dvb_unregister_device(chan->video_dev); | ||
3443 | if (chan->fe) { | ||
3444 | dvb_unregister_frontend(chan->fe); | ||
3445 | /*dvb_frontend_detach(chan->fe); */ | ||
3446 | chan->fe = 0; | ||
3447 | } | ||
3448 | dvbdemux->dmx.close(&dvbdemux->dmx); | ||
3449 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, | ||
3450 | &chan->hw_frontend); | ||
3451 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, | ||
3452 | &chan->mem_frontend); | ||
3453 | dvb_dmxdev_release(&chan->dmxdev); | ||
3454 | dvb_dmx_release(&chan->demux); | ||
3455 | #ifndef ONE_ADAPTER | ||
3456 | dvb_unregister_adapter(&chan->dvb_adapter); | ||
3457 | #endif | ||
3458 | } | ||
3459 | |||
3460 | if (io & (NGENE_IO_AIN)) { | ||
3461 | ngene_snd_exit(chan); | ||
3462 | kfree(chan->soundbuffer); | ||
3463 | } | ||
3464 | } | ||
3465 | |||
3466 | static int init_channel(struct ngene_channel *chan) | ||
3467 | { | ||
3468 | int ret = 0, nr = chan->number; | ||
3469 | struct dvb_adapter *adapter = 0; | ||
3470 | struct dvb_demux *dvbdemux = &chan->demux; | ||
3471 | struct ngene *dev = chan->dev; | ||
3472 | struct ngene_info *ni = dev->card_info; | ||
3473 | int io = ni->io_type[nr]; | ||
3474 | |||
3475 | tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan); | ||
3476 | chan->users = 0; | ||
3477 | chan->type = io; | ||
3478 | chan->mode = chan->type; /* for now only one mode */ | ||
3479 | |||
3480 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
3481 | if (nr >= STREAM_AUDIOIN1) | ||
3482 | chan->DataFormatFlags = DF_SWAP32; | ||
3483 | |||
3484 | if (io & NGENE_IO_TSOUT) | ||
3485 | dec_fw_boot(dev); | ||
3486 | |||
3487 | #ifdef ONE_ADAPTER | ||
3488 | adapter = &chan->dev->dvb_adapter; | ||
3489 | #else | ||
3490 | ret = dvb_register_adapter(&chan->dvb_adapter, "nGene", | ||
3491 | THIS_MODULE, | ||
3492 | &chan->dev->pci_dev->dev); | ||
3493 | if (ret < 0) | ||
3494 | return ret; | ||
3495 | adapter = &chan->dvb_adapter; | ||
3496 | #endif | ||
3497 | ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", | ||
3498 | ngene_start_feed, | ||
3499 | ngene_stop_feed, chan); | ||
3500 | ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux, | ||
3501 | &chan->hw_frontend, | ||
3502 | &chan->mem_frontend, adapter); | ||
3503 | if (io & NGENE_IO_TSOUT) { | ||
3504 | dvbdemux->write_to_decoder = write_to_decoder; | ||
3505 | dvb_register_device(adapter, &chan->audio_dev, | ||
3506 | &dvbdev_audio, (void *)chan, | ||
3507 | DVB_DEVICE_AUDIO); | ||
3508 | dvb_register_device(adapter, &chan->video_dev, | ||
3509 | &dvbdev_video, (void *)chan, | ||
3510 | DVB_DEVICE_VIDEO); | ||
3511 | |||
3512 | } | ||
3513 | #ifdef NGENE_COMMAND_API | ||
3514 | dvb_register_device(adapter, &chan->command_dev, | ||
3515 | &dvbdev_command, (void *)chan, | ||
3516 | DVB_DEVICE_SEC); | ||
3517 | #endif | ||
3518 | } | ||
3519 | |||
3520 | if (io & NGENE_IO_TSIN) { | ||
3521 | chan->fe = NULL; | ||
3522 | if (ni->demod_attach[nr]) | ||
3523 | ni->demod_attach[nr](chan); | ||
3524 | if (chan->fe) { | ||
3525 | if (dvb_register_frontend(adapter, chan->fe) < 0) { | ||
3526 | if (chan->fe->ops.release) | ||
3527 | chan->fe->ops.release(chan->fe); | ||
3528 | chan->fe = NULL; | ||
3529 | } | ||
3530 | } | ||
3531 | if (chan->fe && ni->tuner_attach[nr]) | ||
3532 | if (ni->tuner_attach[nr] (chan) < 0) { | ||
3533 | printk(KERN_ERR DEVICE_NAME | ||
3534 | ": Tuner attach failed on channel %d!\n", | ||
3535 | nr); | ||
3536 | } | ||
3537 | } | ||
3538 | |||
3539 | if (io & (NGENE_IO_AIN)) { | ||
3540 | ngene_snd_init(chan); | ||
3541 | #ifdef NGENE_V4L | ||
3542 | spin_lock_init(&chan->s_lock); | ||
3543 | init_MUTEX(&chan->reslock); | ||
3544 | INIT_LIST_HEAD(&chan->capture); | ||
3545 | #endif | ||
3546 | |||
3547 | chan->soundbuffer = kmalloc(MAX_AUDIO_BUFFER_SIZE, GFP_KERNEL); | ||
3548 | if (!chan->soundbuffer) | ||
3549 | return -ENOMEM; | ||
3550 | memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); | ||
3551 | } | ||
3552 | return ret; | ||
3553 | } | ||
3554 | |||
3555 | static int init_channels(struct ngene *dev) | ||
3556 | { | ||
3557 | int i, j; | ||
3558 | |||
3559 | for (i = 0; i < MAX_STREAM; i++) { | ||
3560 | if (init_channel(&dev->channel[i]) < 0) { | ||
3561 | for (j = 0; j < i; j++) | ||
3562 | release_channel(&dev->channel[j]); | ||
3563 | return -1; | ||
3564 | } | ||
3565 | } | ||
3566 | return 0; | ||
3567 | } | ||
3568 | |||
3569 | /****************************************************************************/ | ||
3570 | /* device probe/remove calls ************************************************/ | ||
3571 | /****************************************************************************/ | ||
3572 | |||
3573 | static void __devexit ngene_remove(struct pci_dev *pdev) | ||
3574 | { | ||
3575 | struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); | ||
3576 | int i; | ||
3577 | |||
3578 | tasklet_kill(&dev->event_tasklet); | ||
3579 | for (i = 0; i < MAX_STREAM; i++) | ||
3580 | release_channel(&dev->channel[i]); | ||
3581 | #ifdef ONE_ADAPTER | ||
3582 | dvb_unregister_adapter(&dev->dvb_adapter); | ||
3583 | #endif | ||
3584 | ngene_stop(dev); | ||
3585 | ngene_release_buffers(dev); | ||
3586 | pci_set_drvdata(pdev, 0); | ||
3587 | pci_disable_device(pdev); | ||
3588 | } | ||
3589 | |||
3590 | static int __devinit ngene_probe(struct pci_dev *pci_dev, | ||
3591 | const struct pci_device_id *id) | ||
3592 | { | ||
3593 | struct ngene *dev; | ||
3594 | int stat = 0; | ||
3595 | |||
3596 | if (pci_enable_device(pci_dev) < 0) | ||
3597 | return -ENODEV; | ||
3598 | |||
3599 | dev = vmalloc(sizeof(struct ngene)); | ||
3600 | if (dev == NULL) | ||
3601 | return -ENOMEM; | ||
3602 | memset(dev, 0, sizeof(struct ngene)); | ||
3603 | |||
3604 | dev->pci_dev = pci_dev; | ||
3605 | dev->card_info = (struct ngene_info *)id->driver_data; | ||
3606 | printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name); | ||
3607 | |||
3608 | pci_set_drvdata(pci_dev, dev); | ||
3609 | |||
3610 | /* Alloc buffers and start nGene */ | ||
3611 | stat = ngene_get_buffers(dev); | ||
3612 | if (stat < 0) | ||
3613 | goto fail1; | ||
3614 | stat = ngene_start(dev); | ||
3615 | if (stat < 0) | ||
3616 | goto fail1; | ||
3617 | |||
3618 | dev->i2c_current_bus = -1; | ||
3619 | exp_init(dev); | ||
3620 | |||
3621 | /* Disable analog TV decoder chips if present */ | ||
3622 | if (copy_eeprom) { | ||
3623 | i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); | ||
3624 | i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); | ||
3625 | } | ||
3626 | /*i2c_check_eeprom(&dev->i2c_adapter);*/ | ||
3627 | |||
3628 | /* Register DVB adapters and devices for both channels */ | ||
3629 | #ifdef ONE_ADAPTER | ||
3630 | if (dvb_register_adapter(&dev->dvb_adapter, "nGene", THIS_MODULE, | ||
3631 | &dev->pci_dev->dev, adapter_nr) < 0) | ||
3632 | goto fail2; | ||
3633 | #endif | ||
3634 | if (init_channels(dev) < 0) | ||
3635 | goto fail2; | ||
3636 | |||
3637 | return 0; | ||
3638 | |||
3639 | fail2: | ||
3640 | ngene_stop(dev); | ||
3641 | fail1: | ||
3642 | ngene_release_buffers(dev); | ||
3643 | pci_set_drvdata(pci_dev, 0); | ||
3644 | return stat; | ||
3645 | } | ||
3646 | |||
3647 | /****************************************************************************/ | ||
3648 | /* Card configs *************************************************************/ | ||
3649 | /****************************************************************************/ | ||
3650 | |||
3651 | static struct drxd_config fe_terratec_dvbt_0 = { | ||
3652 | .index = 0, | ||
3653 | .demod_address = 0x70, | ||
3654 | .demod_revision = 0xa2, | ||
3655 | .demoda_address = 0x00, | ||
3656 | .pll_address = 0x60, | ||
3657 | .pll_type = DRXD_PLL_DTT7520X, | ||
3658 | .clock = 20000, | ||
3659 | .pll_set = ngene_pll_set_th_dtt7520x, | ||
3660 | .osc_deviation = osc_deviation, | ||
3661 | }; | ||
3662 | |||
3663 | static struct drxd_config fe_terratec_dvbt_1 = { | ||
3664 | .index = 1, | ||
3665 | .demod_address = 0x71, | ||
3666 | .demod_revision = 0xa2, | ||
3667 | .demoda_address = 0x00, | ||
3668 | .pll_address = 0x60, | ||
3669 | .pll_type = DRXD_PLL_DTT7520X, | ||
3670 | .clock = 20000, | ||
3671 | .pll_set = ngene_pll_set_th_dtt7520x, | ||
3672 | .osc_deviation = osc_deviation, | ||
3673 | }; | ||
3674 | |||
3675 | static struct ngene_info ngene_info_terratec = { | ||
3676 | .type = NGENE_TERRATEC, | ||
3677 | .name = "Terratec Integra/Cinergy2400i Dual DVB-T", | ||
3678 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3679 | .demod_attach = {demod_attach_drxd, demod_attach_drxd}, | ||
3680 | .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, | ||
3681 | .i2c_access = 1, | ||
3682 | }; | ||
3683 | |||
3684 | /****************************************************************************/ | ||
3685 | |||
3686 | static struct mt2060_config tuner_python_0 = { | ||
3687 | .i2c_address = 0x60, | ||
3688 | .clock_out = 3, | ||
3689 | .input = 0 | ||
3690 | }; | ||
3691 | |||
3692 | static struct mt2060_config tuner_python_1 = { | ||
3693 | .i2c_address = 0x61, | ||
3694 | .clock_out = 3, | ||
3695 | .input = 1 | ||
3696 | }; | ||
3697 | |||
3698 | static struct drxd_config fe_python_0 = { | ||
3699 | .index = 0, | ||
3700 | .demod_address = 0x71, | ||
3701 | .demod_revision = 0xb1, | ||
3702 | .demoda_address = 0x41, | ||
3703 | .clock = 16000, | ||
3704 | .osc_deviation = osc_deviation, | ||
3705 | }; | ||
3706 | |||
3707 | static struct drxd_config fe_python_1 = { | ||
3708 | .index = 1, | ||
3709 | .demod_address = 0x70, | ||
3710 | .demod_revision = 0xb1, | ||
3711 | .demoda_address = 0x45, | ||
3712 | .clock = 16000, | ||
3713 | .osc_deviation = osc_deviation, | ||
3714 | }; | ||
3715 | |||
3716 | static struct ngene_info ngene_info_python = { | ||
3717 | .type = NGENE_PYTHON, | ||
3718 | .name = "Micronas MicPython/Hedgehog Dual DVB-T", | ||
3719 | .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, | ||
3720 | NGENE_IO_TSIN | NGENE_IO_TV, | ||
3721 | NGENE_IO_AIN, NGENE_IO_AIN}, | ||
3722 | .demod_attach = {demod_attach_drxd, demod_attach_drxd}, | ||
3723 | .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, | ||
3724 | .fe_config = {&fe_python_0, &fe_python_1}, | ||
3725 | .tuner_config = {&tuner_python_0, &tuner_python_1}, | ||
3726 | .avf = {0x43, 0x47}, | ||
3727 | .msp = {0x40, 0x42}, | ||
3728 | .demoda = {0x41, 0x45}, | ||
3729 | .gate_ctrl = python_gate_ctrl, | ||
3730 | .switch_ctrl = python_switch_ctrl, | ||
3731 | }; | ||
3732 | |||
3733 | /****************************************************************************/ | ||
3734 | |||
3735 | static struct drxd_config fe_appb_dvbt_0 = { | ||
3736 | .index = 0, | ||
3737 | .demod_address = 0x71, | ||
3738 | .demod_revision = 0xa2, | ||
3739 | .demoda_address = 0x41, | ||
3740 | .pll_address = 0x63, | ||
3741 | .pll_type = DRXD_PLL_MT3X0823, | ||
3742 | .clock = 20000, | ||
3743 | .pll_set = ngene_pll_set_mt_3x0823, | ||
3744 | .osc_deviation = osc_deviation, | ||
3745 | }; | ||
3746 | |||
3747 | static struct drxd_config fe_appb_dvbt_1 = { | ||
3748 | .index = 1, | ||
3749 | .demod_address = 0x70, | ||
3750 | .demod_revision = 0xa2, | ||
3751 | .demoda_address = 0x45, | ||
3752 | .pll_address = 0x60, | ||
3753 | .pll_type = DRXD_PLL_MT3X0823, | ||
3754 | .clock = 20000, | ||
3755 | .pll_set = ngene_pll_set_mt_3x0823, | ||
3756 | .osc_deviation = osc_deviation, | ||
3757 | }; | ||
3758 | |||
3759 | static struct ngene_info ngene_info_appboard = { | ||
3760 | .type = NGENE_APP, | ||
3761 | .name = "Micronas Application Board Dual DVB-T", | ||
3762 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3763 | .demod_attach = {demod_attach_drxd, demod_attach_drxd}, | ||
3764 | .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, | ||
3765 | .avf = {0x43, 0x47}, | ||
3766 | }; | ||
3767 | |||
3768 | static struct ngene_info ngene_info_appboard_ntsc = { | ||
3769 | .type = NGENE_APP, | ||
3770 | .name = "Micronas Application Board Dual DVB-T", | ||
3771 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3772 | .demod_attach = {demod_attach_drxd, demod_attach_drxd}, | ||
3773 | .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, | ||
3774 | .avf = {0x43, 0x47}, | ||
3775 | .ntsc = 1, | ||
3776 | }; | ||
3777 | |||
3778 | /****************************************************************************/ | ||
3779 | |||
3780 | static struct stb0899_config fe_sidewinder_0 = { | ||
3781 | .demod_address = 0x68, | ||
3782 | .pll_address = 0x63, | ||
3783 | }; | ||
3784 | |||
3785 | static struct stb0899_config fe_sidewinder_1 = { | ||
3786 | .demod_address = 0x6b, | ||
3787 | .pll_address = 0x60, | ||
3788 | }; | ||
3789 | |||
3790 | static struct ngene_info ngene_info_sidewinder = { | ||
3791 | .type = NGENE_SIDEWINDER, | ||
3792 | .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", | ||
3793 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3794 | .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, | ||
3795 | .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, | ||
3796 | .lnb = {0x0b, 0x08}, | ||
3797 | }; | ||
3798 | |||
3799 | /****************************************************************************/ | ||
3800 | /* Yet unnamed S2 card with dual DVB-S2 demod */ | ||
3801 | /****************************************************************************/ | ||
3802 | |||
3803 | static struct stv0900_config fe_s2_0 = { | ||
3804 | .addr = 0x68, | ||
3805 | .pll = 0x63, | ||
3806 | .pll_type = 0, | ||
3807 | .nr = 0, | ||
3808 | }; | ||
3809 | |||
3810 | static struct stv0900_config fe_s2_1 = { | ||
3811 | .addr = 0x68, | ||
3812 | .pll = 0x60, | ||
3813 | .pll_type = 0, | ||
3814 | .nr = 1, | ||
3815 | }; | ||
3816 | |||
3817 | static struct ngene_info ngene_info_s2 = { | ||
3818 | .type = NGENE_SIDEWINDER, | ||
3819 | .name = "S2", | ||
3820 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, | ||
3821 | NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3822 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
3823 | .fe_config = {&fe_s2_0, &fe_s2_1}, | ||
3824 | .lnb = {0x0b, 0x08}, | ||
3825 | .tsf = {3, 3}, | ||
3826 | .fw_version = 15, | ||
3827 | }; | ||
3828 | |||
3829 | static struct stv0900_config fe_s2b_0 = { | ||
3830 | .addr = 0x68, | ||
3831 | .pll = 0x60, | ||
3832 | .pll_type = 0x10, | ||
3833 | .nr = 0, | ||
3834 | }; | ||
3835 | |||
3836 | static struct stv0900_config fe_s2b_1 = { | ||
3837 | .addr = 0x68, | ||
3838 | .pll = 0x63, | ||
3839 | .pll_type = 0x10, | ||
3840 | .nr = 1, | ||
3841 | }; | ||
3842 | |||
3843 | static struct ngene_info ngene_info_s2_b = { | ||
3844 | .type = NGENE_SIDEWINDER, | ||
3845 | .name = "S2 V2", | ||
3846 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, | ||
3847 | NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
3848 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
3849 | .fe_config = {&fe_s2b_0, &fe_s2b_1}, | ||
3850 | .lnb = {0x0b, 0x08}, | ||
3851 | .tsf = {3, 3}, | ||
3852 | .fw_version = 17, | ||
3853 | }; | ||
3854 | |||
3855 | /****************************************************************************/ | ||
3856 | |||
3857 | static struct xc3028_config tuner_viper_0 = { | ||
3858 | .adr = 0x61, | ||
3859 | .reset = viper_reset_xc | ||
3860 | }; | ||
3861 | |||
3862 | static struct xc3028_config tuner_viper_1 = { | ||
3863 | .adr = 0x64, | ||
3864 | .reset = viper_reset_xc | ||
3865 | }; | ||
3866 | |||
3867 | static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; | ||
3868 | |||
3869 | static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; | ||
3870 | |||
3871 | static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; | ||
3872 | |||
3873 | static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; | ||
3874 | |||
3875 | static struct ngene_info ngene_info_viper_v1 = { | ||
3876 | .type = NGENE_VIPER, | ||
3877 | .name = "Micronas MicViper Dual ATSC DRXH", | ||
3878 | .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, | ||
3879 | NGENE_IO_TSIN | NGENE_IO_TV, | ||
3880 | NGENE_IO_AIN, NGENE_IO_AIN}, | ||
3881 | .demod_attach = {demod_attach_drxh, demod_attach_drxh}, | ||
3882 | .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, | ||
3883 | .tuner_config = {&tuner_viper_0, &tuner_viper_1}, | ||
3884 | .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, | ||
3885 | .avf = {0x43, 0x47}, | ||
3886 | .msp = {0x40, 0x42}, | ||
3887 | .exp = 0x20, | ||
3888 | .exp_init = 0xf5, | ||
3889 | .gate_ctrl = viper_gate_ctrl, | ||
3890 | .switch_ctrl = viper_switch_ctrl, | ||
3891 | .tsf = {2, 2}, | ||
3892 | }; | ||
3893 | |||
3894 | static struct ngene_info ngene_info_viper_v2 = { | ||
3895 | .type = NGENE_VIPER, | ||
3896 | .name = "Micronas MicViper Dual ATSC DRXL", | ||
3897 | .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, | ||
3898 | NGENE_IO_TSIN | NGENE_IO_TV, | ||
3899 | NGENE_IO_AIN, NGENE_IO_AIN}, | ||
3900 | .demod_attach = {demod_attach_drxh, demod_attach_drxh}, | ||
3901 | .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, | ||
3902 | .tuner_config = {&tuner_viper_0, &tuner_viper_1}, | ||
3903 | .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, | ||
3904 | .avf = {0x43, 0x47}, | ||
3905 | .msp = {0x40, 0x42}, | ||
3906 | .exp = 0x38, | ||
3907 | .exp_init = 0xf5, | ||
3908 | .gate_ctrl = viper_gate_ctrl, | ||
3909 | .switch_ctrl = viper_switch_ctrl, | ||
3910 | .tsf = {2, 2}, | ||
3911 | }; | ||
3912 | |||
3913 | /****************************************************************************/ | ||
3914 | |||
3915 | static struct ngene_info ngene_info_vbox_v1 = { | ||
3916 | .type = NGENE_VBOX_V1, | ||
3917 | .name = "VBox Cat's Eye 164E", | ||
3918 | .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, | ||
3919 | NGENE_IO_TSIN | NGENE_IO_TV, | ||
3920 | NGENE_IO_AIN, NGENE_IO_AIN}, | ||
3921 | .demod_attach = {demod_attach_drxh, demod_attach_drxh}, | ||
3922 | .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, | ||
3923 | .tuner_config = {&tuner_viper_0, &tuner_viper_1}, | ||
3924 | .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, | ||
3925 | .avf = {0x43, 0x47}, | ||
3926 | .msp = {0x40, 0x42}, | ||
3927 | .exp = 0x20, | ||
3928 | .exp_init = 0xf5, | ||
3929 | .gate_ctrl = viper_gate_ctrl, | ||
3930 | .switch_ctrl = viper_switch_ctrl, | ||
3931 | .tsf = {2, 2}, | ||
3932 | }; | ||
3933 | |||
3934 | /****************************************************************************/ | ||
3935 | |||
3936 | static struct ngene_info ngene_info_vbox_v2 = { | ||
3937 | .type = NGENE_VBOX_V2, | ||
3938 | .name = "VBox Cat's Eye 164E", | ||
3939 | .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, | ||
3940 | NGENE_IO_TSIN | NGENE_IO_TV, | ||
3941 | NGENE_IO_AIN, NGENE_IO_AIN}, | ||
3942 | .demod_attach = {demod_attach_drxh, demod_attach_drxh}, | ||
3943 | .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, | ||
3944 | .tuner_config = {&tuner_viper_0, &tuner_viper_1}, | ||
3945 | .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, | ||
3946 | .avf = {0x43, 0x47}, | ||
3947 | .msp = {0x40, 0x42}, | ||
3948 | .exp = 0x20, | ||
3949 | .exp_init = 0xf5, | ||
3950 | .gate_ctrl = viper_gate_ctrl, | ||
3951 | .switch_ctrl = viper_switch_ctrl2, | ||
3952 | .tsf = {2, 2}, | ||
3953 | }; | ||
3954 | |||
3955 | /****************************************************************************/ | ||
3956 | |||
3957 | static struct ngene_info ngene_info_racer = { | ||
3958 | .type = NGENE_RACER, | ||
3959 | .name = "Micronas MicRacer HDTV Decoder Card", | ||
3960 | .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, | ||
3961 | NGENE_IO_AIN, NGENE_IO_NONE, | ||
3962 | NGENE_IO_TSOUT}, | ||
3963 | .i2s = {0, 0, 1, 0}, | ||
3964 | .fw_version = 17, | ||
3965 | }; | ||
3966 | |||
3967 | |||
3968 | /****************************************************************************/ | ||
3969 | /****************************************************************************/ | ||
3970 | /****************************************************************************/ | ||
3971 | |||
3972 | #define NGENE_ID(_subvend, _subdev, _driverdata) { \ | ||
3973 | .vendor = NGENE_VID, .device = NGENE_PID, \ | ||
3974 | .subvendor = _subvend, .subdevice = _subdev, \ | ||
3975 | .driver_data = (unsigned long) &_driverdata } | ||
3976 | |||
3977 | /****************************************************************************/ | ||
3978 | |||
3979 | static const struct pci_device_id ngene_id_tbl[] __devinitdata = { | ||
3980 | NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), | ||
3981 | NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), | ||
3982 | NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), | ||
3983 | NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), | ||
3984 | NGENE_ID(0x153b, 0x1167, ngene_info_terratec), | ||
3985 | NGENE_ID(0x18c3, 0x0030, ngene_info_python), | ||
3986 | NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), | ||
3987 | NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), | ||
3988 | NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), | ||
3989 | NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), | ||
3990 | NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), | ||
3991 | NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), | ||
3992 | NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), | ||
3993 | NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), | ||
3994 | NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), | ||
3995 | {0} | ||
3996 | }; | ||
3997 | |||
3998 | /****************************************************************************/ | ||
3999 | /* Init/Exit ****************************************************************/ | ||
4000 | /****************************************************************************/ | ||
4001 | |||
4002 | static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, | ||
4003 | enum pci_channel_state state) | ||
4004 | { | ||
4005 | printk(KERN_ERR DEVICE_NAME ": PCI error\n"); | ||
4006 | if (state == pci_channel_io_perm_failure) | ||
4007 | return PCI_ERS_RESULT_DISCONNECT; | ||
4008 | if (state == pci_channel_io_frozen) | ||
4009 | return PCI_ERS_RESULT_NEED_RESET; | ||
4010 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
4011 | } | ||
4012 | |||
4013 | static pci_ers_result_t ngene_link_reset(struct pci_dev *dev) | ||
4014 | { | ||
4015 | printk(KERN_INFO DEVICE_NAME ": link reset\n"); | ||
4016 | return 0; | ||
4017 | } | ||
4018 | |||
4019 | static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) | ||
4020 | { | ||
4021 | printk(KERN_INFO DEVICE_NAME ": slot reset\n"); | ||
4022 | return 0; | ||
4023 | } | ||
4024 | |||
4025 | static void ngene_resume(struct pci_dev *dev) | ||
4026 | { | ||
4027 | printk(KERN_INFO DEVICE_NAME ": resume\n"); | ||
4028 | } | ||
4029 | |||
4030 | static struct pci_error_handlers ngene_errors = { | ||
4031 | .error_detected = ngene_error_detected, | ||
4032 | .link_reset = ngene_link_reset, | ||
4033 | .slot_reset = ngene_slot_reset, | ||
4034 | .resume = ngene_resume, | ||
4035 | }; | ||
4036 | |||
4037 | static struct pci_driver ngene_pci_driver = { | ||
4038 | .name = "ngene", | ||
4039 | .id_table = ngene_id_tbl, | ||
4040 | .probe = ngene_probe, | ||
4041 | .remove = ngene_remove, | ||
4042 | .err_handler = &ngene_errors, | ||
4043 | }; | ||
4044 | |||
4045 | static __init int module_init_ngene(void) | ||
4046 | { | ||
4047 | printk(KERN_INFO | ||
4048 | "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); | ||
4049 | return pci_register_driver(&ngene_pci_driver); | ||
4050 | } | ||
4051 | |||
4052 | static __exit void module_exit_ngene(void) | ||
4053 | { | ||
4054 | pci_unregister_driver(&ngene_pci_driver); | ||
4055 | } | ||
4056 | |||
4057 | module_init(module_init_ngene); | ||
4058 | module_exit(module_exit_ngene); | ||
4059 | |||
4060 | MODULE_DESCRIPTION("nGene"); | ||
4061 | MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); | ||
4062 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/ngene/ngene-ioctls.h b/drivers/media/dvb/ngene/ngene-ioctls.h new file mode 100644 index 000000000000..4aa2f64a5314 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-ioctls.h | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2007 Micronas | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * version 2 only, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | * 02110-1301, USA | ||
19 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
20 | */ | ||
21 | |||
22 | #ifndef _NGENE_IOCTLS_H_ | ||
23 | #define _NGENE_IOCTLS_H_ | ||
24 | |||
25 | #include <linux/ioctl.h> | ||
26 | #include <linux/types.h> | ||
27 | |||
28 | #define NGENE_MAGIC 'n' | ||
29 | |||
30 | typedef struct { | ||
31 | unsigned char I2CAddress; | ||
32 | unsigned char OutLength; /* bytes to write first */ | ||
33 | unsigned char InLength; /* bytes to read */ | ||
34 | unsigned char OutData[256]; /* output data */ | ||
35 | unsigned char InData[256]; /* input data */ | ||
36 | } MIC_I2C_READ, *PMIC_I2C_READ; | ||
37 | |||
38 | #define IOCTL_MIC_I2C_READ _IOWR(NGENE_MAGIC, 0x00, MIC_I2C_READ) | ||
39 | |||
40 | |||
41 | typedef struct { | ||
42 | unsigned char I2CAddress; | ||
43 | unsigned char Length; | ||
44 | unsigned char Data[250]; | ||
45 | } MIC_I2C_WRITE, *PMIC_I2C_WRITE; | ||
46 | |||
47 | typedef struct { | ||
48 | unsigned char Length; | ||
49 | unsigned char Data[250]; | ||
50 | } MIC_I2C_CONTINUE_WRITE, *PMIC_I2C_CONTINUE_WRITE; | ||
51 | |||
52 | #define IOCTL_MIC_I2C_WRITE _IOW(NGENE_MAGIC, 0x01, \ | ||
53 | MIC_I2C_WRITE) | ||
54 | #define IOCTL_MIC_I2C_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0c, \ | ||
55 | MIC_I2C_WRITE) | ||
56 | #define IOCTL_MIC_I2C_CONTINUE_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0d, \ | ||
57 | MIC_I2C_CONTINUE_WRITE) | ||
58 | #define IOCTL_MIC_I2C_CONTINUE_WRITE _IOW(NGENE_MAGIC, 0x0e, \ | ||
59 | MIC_I2C_CONTINUE_WRITE) | ||
60 | |||
61 | typedef struct { | ||
62 | unsigned char ModeSelect; /* see bellow */ | ||
63 | unsigned char OutLength; /* bytes to write first */ | ||
64 | unsigned char InLength; /* bytes to read */ | ||
65 | unsigned char OutData[250]; /* output data */ | ||
66 | } MIC_SPI_READ, *PMIC_SPI_READ; | ||
67 | |||
68 | #define IOCTL_MIC_SPI_READ _IOWR(NGENE_MAGIC, 0x02, MIC_SPI_READ) | ||
69 | |||
70 | typedef struct { | ||
71 | unsigned char ModeSelect; /* see below */ | ||
72 | unsigned char Length; | ||
73 | unsigned char Data[250]; | ||
74 | } MIC_SPI_WRITE, *PMIC_SPI_WRITE; | ||
75 | |||
76 | #define IOCTL_MIC_SPI_WRITE _IOW(NGENE_MAGIC, 0x03, MIC_SPI_READ) | ||
77 | |||
78 | #define IOCTL_MIC_DOWNLOAD_FIRMWARE _IOW(NGENE_MAGIC, 0x06, unsigned char) | ||
79 | |||
80 | #define IOCTL_MIC_NO_OP _IO(NGENE_MAGIC, 0x18) | ||
81 | |||
82 | #define IOCTL_MIC_TUN_RDY _IO(NGENE_MAGIC, 0x07) | ||
83 | #define IOCTL_MIC_DEC_SRATE _IOW(NGENE_MAGIC, 0x0a, int) | ||
84 | #define IOCTL_MIC_DEC_RDY _IO(NGENE_MAGIC, 0x09) | ||
85 | #define IOCTL_MIC_DEC_FREESYNC _IOW(NGENE_MAGIC, 0x08, int) | ||
86 | #define IOCTL_MIC_TUN_DETECT _IOWR(NGENE_MAGIC, 0x0b, int) | ||
87 | |||
88 | typedef struct { | ||
89 | unsigned char Stream; /* < UVI1, UVI2, or TVOUT */ | ||
90 | unsigned char Control; | ||
91 | unsigned char Mode; | ||
92 | unsigned short nLines; | ||
93 | unsigned short nBytesPerLine; | ||
94 | unsigned short nVBILines; | ||
95 | unsigned short nBytesPerVBILine; | ||
96 | } MIC_STREAM_CONTROL, *PMIC_STREAM_CONTROL; | ||
97 | |||
98 | enum MIC_STREAM_CONTROL_MODE_BITS { | ||
99 | MSC_MODE_LOOPBACK = 0x80, | ||
100 | MSC_MODE_AVLOOP = 0x40, | ||
101 | MSC_MODE_AUDIO_SPDIF = 0x20, | ||
102 | MSC_MODE_AVSYNC = 0x10, | ||
103 | MSC_MODE_TRANSPORT_STREAM = 0x08, | ||
104 | MSC_MODE_AUDIO_CAPTURE = 0x04, | ||
105 | MSC_MODE_VBI_CAPTURE = 0x02, | ||
106 | MSC_MODE_VIDEO_CAPTURE = 0x01 | ||
107 | }; | ||
108 | |||
109 | #define IOCTL_MIC_STREAM_CONTROL _IOW(NGENE_MAGIC, 0x22, MIC_STREAM_CONTROL) | ||
110 | |||
111 | typedef struct { | ||
112 | unsigned char Stream; /* < UVI1, UVI2 */ | ||
113 | unsigned int Rate; /* < Rate in 100nsec to release the buffers | ||
114 | to the stream filters */ | ||
115 | } MIC_SIMULATE_CONTROL, *PMIC_SIMULATE_CONTROL; | ||
116 | |||
117 | #define IOCTL_MIC_SIMULATE_CONTROL _IOW(NGENE_MAGIC, 0x23, \ | ||
118 | MIC_SIMULATE_CONTROL) | ||
119 | |||
120 | /* | ||
121 | * IOCTL definitions for the test driver | ||
122 | * | ||
123 | * NOTE: the test driver also supports following IOCTL defined above: | ||
124 | * IOCTL_MIC_NO_OP: | ||
125 | * IOCTL_MIC_RECEIVE_BUFFER: | ||
126 | * IOCTL_MIC_STREAM_CONTROL: | ||
127 | * IOCTL_MIC_I2C_READ: | ||
128 | * IOCTL_MIC_I2C_WRITE: | ||
129 | * | ||
130 | * | ||
131 | * VI2C access to NGene memory (read) | ||
132 | * | ||
133 | * GETMEM in : ULONG start offset | ||
134 | * out : read data (length defined by size of output buffer) | ||
135 | * SETMEM in : ULONG start offset followed by data to be written | ||
136 | * (length defined by size of input buffer) | ||
137 | */ | ||
138 | |||
139 | typedef struct { | ||
140 | __u32 Start; | ||
141 | __u32 Length; | ||
142 | __u8 *Data; | ||
143 | } MIC_MEM; | ||
144 | |||
145 | #define IOCTL_MIC_TEST_GETMEM _IOWR(NGENE_MAGIC, 0x90, MIC_MEM) | ||
146 | #define IOCTL_MIC_TEST_SETMEM _IOW(NGENE_MAGIC, 0x91, MIC_MEM) | ||
147 | |||
148 | typedef struct { | ||
149 | __u8 Address; | ||
150 | __u8 Data; | ||
151 | } MIC_IMEM; | ||
152 | |||
153 | #define IOCTL_MIC_SFR_READ _IOWR(NGENE_MAGIC, 0xa2, MIC_IMEM) | ||
154 | #define IOCTL_MIC_SFR_WRITE _IOWR(NGENE_MAGIC, 0xa3, MIC_IMEM) | ||
155 | |||
156 | #define IOCTL_MIC_IRAM_READ _IOWR(NGENE_MAGIC, 0xa4, MIC_IMEM) | ||
157 | #define IOCTL_MIC_IRAM_WRITE _IOWR(NGENE_MAGIC, 0xa5, MIC_IMEM) | ||
158 | |||
159 | /* | ||
160 | * Set Ngene gpio bit | ||
161 | */ | ||
162 | typedef struct { | ||
163 | unsigned char Select; | ||
164 | unsigned char Level; | ||
165 | } MIC_SET_GPIO_PIN, *PMIC_SET_GPIO_PIN; | ||
166 | |||
167 | #define IOCTL_MIC_SET_GPIO_PIN _IOWR(NGENE_MAGIC, 0xa6, MIC_SET_GPIO_PIN) | ||
168 | |||
169 | /* | ||
170 | * Uart ioctls: | ||
171 | * These are implemented in the test driver. | ||
172 | * | ||
173 | * Enable UART | ||
174 | * | ||
175 | * In: 1 byte containing baud rate: 0 = 19200, 1 = 9600, 2 = 4800, 3 = 2400 | ||
176 | * Out: nothing | ||
177 | */ | ||
178 | #define IOCTL_MIC_UART_ENABLE _IOW(NGENE_MAGIC, 0xa9, unsigned char) | ||
179 | |||
180 | /* | ||
181 | * Enable UART | ||
182 | * | ||
183 | * In: nothing | ||
184 | * Out: nothing | ||
185 | */ | ||
186 | #define IOCTL_MIC_UART_DISABLE _IO(NGENE_MAGIC, 0xAA) | ||
187 | |||
188 | /* | ||
189 | * Write UART | ||
190 | * | ||
191 | * In: data to write | ||
192 | * Out: nothing | ||
193 | * Note: Call returns immediatly, data are send out asynchrounsly | ||
194 | */ | ||
195 | #define IOCTL_MIC_UART_WRITE _IOW(NGENE_MAGIC, 0xAB, unsigned char) | ||
196 | |||
197 | /* | ||
198 | * Read UART | ||
199 | * | ||
200 | * In: nothing | ||
201 | * Out: Data read (since last call) | ||
202 | * Note: Call returns immediatly | ||
203 | */ | ||
204 | #define IOCTL_MIC_UART_READ _IOR(NGENE_MAGIC, 0xAC, unsigned char) | ||
205 | |||
206 | /* | ||
207 | * UART Status | ||
208 | * | ||
209 | * In: nothing | ||
210 | * Out: Byte 0 : Transmitter busy, | ||
211 | * Byte 1 : Nbr of characters available for read. | ||
212 | * Note: Call returns immediatly | ||
213 | */ | ||
214 | #define IOCTL_MIC_UART_STATUS _IOR(NGENE_MAGIC, 0xAD, unsigned char) | ||
215 | |||
216 | #endif | ||
diff --git a/drivers/media/dvb/ngene/ngene-snd.c b/drivers/media/dvb/ngene/ngene-snd.c new file mode 100644 index 000000000000..1ca343236ffb --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-snd.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /* | ||
2 | * ngene_snd.c: nGene PCIe bridge driver ALSA support | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Based on the initial ALSA support port by Thomas Eschbach. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 only, as published by the Free Software Foundation. | ||
11 | * | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
22 | * 02110-1301, USA | ||
23 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
24 | */ | ||
25 | |||
26 | #include <linux/version.h> | ||
27 | #include <linux/module.h> | ||
28 | |||
29 | #include "ngene.h" | ||
30 | #include "ngene-ioctls.h" | ||
31 | |||
32 | static int sound_dev; | ||
33 | |||
34 | /* sound module parameters (see "Module Parameters") */ | ||
35 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
36 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
37 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; | ||
38 | |||
39 | /****************************************************************************/ | ||
40 | /* PCM Sound Funktions ******************************************************/ | ||
41 | /****************************************************************************/ | ||
42 | |||
43 | static struct snd_pcm_hardware snd_mychip_capture_hw = { | ||
44 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), | ||
45 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
46 | .rates = (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | ||
47 | | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | ||
48 | | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), | ||
49 | .rate_min = 11025, | ||
50 | .rate_max = 48000, | ||
51 | .channels_min = 2, | ||
52 | .channels_max = 2, | ||
53 | .buffer_bytes_max = 16384, | ||
54 | .period_bytes_min = 8192, | ||
55 | .period_bytes_max = 8192, | ||
56 | .periods_min = 1, | ||
57 | .periods_max = 2, | ||
58 | }; | ||
59 | |||
60 | /* open callback */ | ||
61 | static int snd_mychip_capture_open(struct snd_pcm_substream *substream) | ||
62 | { | ||
63 | |||
64 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
65 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
66 | |||
67 | runtime->hw = snd_mychip_capture_hw; | ||
68 | chip->substream = substream; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* close callback */ | ||
73 | static int snd_mychip_capture_close(struct snd_pcm_substream *substream) | ||
74 | { | ||
75 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
76 | chip->substream = NULL; | ||
77 | return 0; | ||
78 | |||
79 | } | ||
80 | |||
81 | /* hw_params callback */ | ||
82 | static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream, | ||
83 | struct snd_pcm_hw_params *hw_params) | ||
84 | { | ||
85 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
86 | struct ngene_channel *chan = chip->chan; | ||
87 | if (chan->soundbuffisallocated == 0) { | ||
88 | chan->soundbuffisallocated = 1; | ||
89 | return snd_pcm_lib_malloc_pages(substream, | ||
90 | params_buffer_bytes(hw_params)); | ||
91 | } | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | /* hw_free callback */ | ||
96 | static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream) | ||
97 | { | ||
98 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
99 | struct ngene_channel *chan = chip->chan; | ||
100 | int retval = 0; | ||
101 | if (chan->soundbuffisallocated == 1) { | ||
102 | chan->soundbuffisallocated = 0; | ||
103 | retval = snd_pcm_lib_free_pages(substream); | ||
104 | } | ||
105 | return retval; | ||
106 | } | ||
107 | |||
108 | /* prepare callback */ | ||
109 | static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream) | ||
110 | { | ||
111 | |||
112 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
113 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
114 | struct ngene_channel *chan = chip->chan; | ||
115 | struct ngene_channel *ch = &chan->dev->channel[chan->number - 2]; | ||
116 | struct i2c_adapter *adap = &ch->i2c_adapter; | ||
117 | |||
118 | if (ch->soundstreamon == 1) | ||
119 | ;/*ngene_command_stream_control_sound(chan->dev, chan->number, | ||
120 | 0x00, 0x00);*/ | ||
121 | i2c_clients_command(adap, IOCTL_MIC_DEC_SRATE, &(runtime->rate)); | ||
122 | mdelay(80); | ||
123 | if (ch->soundstreamon == 1) | ||
124 | ;/*ngene_command_stream_control_sound(chan->dev, chan->number, | ||
125 | 0x80, 0x04);*/ | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* trigger callback */ | ||
131 | static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
132 | { | ||
133 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
134 | struct ngene_channel *chan = chip->chan; | ||
135 | |||
136 | switch (cmd) { | ||
137 | case SNDRV_PCM_TRIGGER_START: | ||
138 | /* do something to start the PCM engine */ | ||
139 | chan->sndbuffflag = 0; | ||
140 | break; | ||
141 | case SNDRV_PCM_TRIGGER_STOP: | ||
142 | /* do something to stop the PCM engine */ | ||
143 | chip->substream = NULL; | ||
144 | chan->sndbuffflag = 0; | ||
145 | break; | ||
146 | default: | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /* pointer callback */ | ||
153 | static snd_pcm_uframes_t | ||
154 | snd_mychip_pcm_pointer(struct snd_pcm_substream *substream) | ||
155 | { | ||
156 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
157 | struct ngene_channel *chan = chip->chan; | ||
158 | unsigned int current_ptr; | ||
159 | |||
160 | if (chan->sndbuffflag == 0) { | ||
161 | current_ptr = (unsigned int) | ||
162 | bytes_to_frames(substream->runtime, 0); | ||
163 | } else { | ||
164 | current_ptr = (unsigned int) | ||
165 | bytes_to_frames(substream->runtime, 8192); | ||
166 | } | ||
167 | return current_ptr; | ||
168 | } | ||
169 | |||
170 | /*copy sound buffer to pcm middel layer*/ | ||
171 | static int snd_capture_copy(struct snd_pcm_substream *substream, int channel, | ||
172 | snd_pcm_uframes_t pos, void *dst, | ||
173 | snd_pcm_uframes_t count) | ||
174 | { | ||
175 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
176 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
177 | struct ngene_channel *chan = chip->chan; | ||
178 | |||
179 | memcpy(dst, chan->soundbuffer, frames_to_bytes(runtime, count)); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int snd_pcm_capture_silence(struct snd_pcm_substream *substream, | ||
184 | int channel, | ||
185 | snd_pcm_uframes_t pos, | ||
186 | snd_pcm_uframes_t count) | ||
187 | { | ||
188 | /* | ||
189 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
190 | struct mychip *chip = snd_pcm_substream_chip(substream); | ||
191 | struct ngene_channel *chan = chip->chan; | ||
192 | */ | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* operators */ | ||
197 | static struct snd_pcm_ops snd_mychip_capture_ops = { | ||
198 | .open = snd_mychip_capture_open, | ||
199 | .close = snd_mychip_capture_close, | ||
200 | .ioctl = snd_pcm_lib_ioctl, | ||
201 | .hw_params = snd_mychip_pcm_hw_params, | ||
202 | .hw_free = snd_mychip_pcm_hw_free, | ||
203 | .prepare = snd_mychip_pcm_prepare, | ||
204 | .trigger = snd_mychip_pcm_trigger, | ||
205 | .pointer = snd_mychip_pcm_pointer, | ||
206 | .copy = snd_capture_copy, | ||
207 | .silence = snd_pcm_capture_silence, | ||
208 | }; | ||
209 | |||
210 | static void mychip_pcm_free(struct snd_pcm *pcm) | ||
211 | { | ||
212 | pcm->private_data = NULL; | ||
213 | } | ||
214 | |||
215 | /* create a pcm device */ | ||
216 | static int snd_mychip_new_pcm(struct mychip *chip, struct ngene_channel *chan) | ||
217 | { | ||
218 | struct snd_pcm *pcm; | ||
219 | int err; | ||
220 | char gro[10]; | ||
221 | sprintf(gro, "PCM%d", chan->number); | ||
222 | |||
223 | err = snd_pcm_new(chip->card, gro, 0, 0, 1, &pcm); | ||
224 | if (err < 0) | ||
225 | return err; | ||
226 | |||
227 | pcm->private_data = chip; | ||
228 | pcm->private_free = mychip_pcm_free; | ||
229 | |||
230 | sprintf(pcm->name, "MyPCM_%d", chan->number); | ||
231 | |||
232 | chip->pcm = pcm; | ||
233 | /* set operators */ | ||
234 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); | ||
235 | /* pre-allocation of buffers */ | ||
236 | |||
237 | err = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
238 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
239 | snd_dma_continuous_data( | ||
240 | GFP_KERNEL), | ||
241 | 0, 16 * 1024); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | #define ngene_VOLUME(xname, xindex, addr) \ | ||
247 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | ||
248 | .info = snd_volume_info, \ | ||
249 | .get = snd_volume_get, .put = snd_volume_put, \ | ||
250 | .private_value = addr } | ||
251 | |||
252 | static int snd_volume_info(struct snd_kcontrol *kcontrol, | ||
253 | struct snd_ctl_elem_info *uinfo) | ||
254 | { | ||
255 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
256 | uinfo->count = 2; | ||
257 | uinfo->value.integer.min = 0; | ||
258 | uinfo->value.integer.max = 20; | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int snd_volume_get(struct snd_kcontrol *kcontrol, | ||
263 | struct snd_ctl_elem_value *ucontrol) | ||
264 | { | ||
265 | struct mychip *chip = snd_kcontrol_chip(kcontrol); | ||
266 | int addr = kcontrol->private_value; | ||
267 | |||
268 | ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0]; | ||
269 | ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1]; | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int snd_volume_put(struct snd_kcontrol *kcontrol, | ||
274 | struct snd_ctl_elem_value *ucontrol) | ||
275 | { | ||
276 | struct mychip *chip = snd_kcontrol_chip(kcontrol); | ||
277 | int change, addr = kcontrol->private_value; | ||
278 | int left, right; | ||
279 | |||
280 | left = ucontrol->value.integer.value[0]; | ||
281 | if (left < 0) | ||
282 | left = 0; | ||
283 | if (left > 20) | ||
284 | left = 20; | ||
285 | right = ucontrol->value.integer.value[1]; | ||
286 | if (right < 0) | ||
287 | right = 0; | ||
288 | if (right > 20) | ||
289 | right = 20; | ||
290 | spin_lock_irq(&chip->mixer_lock); | ||
291 | change = chip->mixer_volume[addr][0] != left || | ||
292 | chip->mixer_volume[addr][1] != right; | ||
293 | chip->mixer_volume[addr][0] = left; | ||
294 | chip->mixer_volume[addr][1] = right; | ||
295 | spin_unlock_irq(&chip->mixer_lock); | ||
296 | return change; | ||
297 | } | ||
298 | |||
299 | #define ngene_CAPSRC(xname, xindex, addr) \ | ||
300 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | ||
301 | .info = snd_capsrc_info, \ | ||
302 | .get = snd_capsrc_get, .put = snd_capsrc_put, \ | ||
303 | .private_value = addr } | ||
304 | |||
305 | static int snd_capsrc_info(struct snd_kcontrol *kcontrol, | ||
306 | struct snd_ctl_elem_info *uinfo) | ||
307 | { | ||
308 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
309 | uinfo->count = 2; | ||
310 | uinfo->value.integer.min = 0; | ||
311 | uinfo->value.integer.max = 1; | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int snd_capsrc_get(struct snd_kcontrol *kcontrol, | ||
316 | struct snd_ctl_elem_value *ucontrol) | ||
317 | { | ||
318 | struct mychip *chip = snd_kcontrol_chip(kcontrol); | ||
319 | int addr = kcontrol->private_value; | ||
320 | |||
321 | spin_lock_irq(&chip->mixer_lock); | ||
322 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; | ||
323 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; | ||
324 | spin_unlock_irq(&chip->mixer_lock); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int snd_capsrc_put(struct snd_kcontrol *kcontrol, | ||
330 | struct snd_ctl_elem_value *ucontrol) | ||
331 | { | ||
332 | struct mychip *chip = snd_kcontrol_chip(kcontrol); | ||
333 | int change, addr = kcontrol->private_value; | ||
334 | int left, right; | ||
335 | |||
336 | left = ucontrol->value.integer.value[0] & 1; | ||
337 | right = ucontrol->value.integer.value[1] & 1; | ||
338 | spin_lock_irq(&chip->mixer_lock); | ||
339 | |||
340 | change = chip->capture_source[addr][0] != left || | ||
341 | chip->capture_source[addr][1] != right; | ||
342 | chip->capture_source[addr][0] = left; | ||
343 | chip->capture_source[addr][1] = right; | ||
344 | |||
345 | spin_unlock_irq(&chip->mixer_lock); | ||
346 | |||
347 | if (change) | ||
348 | printk(KERN_INFO "snd_capsrc_put change\n"); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static struct snd_kcontrol_new snd_controls[] = { | ||
353 | ngene_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), | ||
354 | ngene_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), | ||
355 | }; | ||
356 | |||
357 | static int snd_card_new_mixer(struct mychip *chip) | ||
358 | { | ||
359 | struct snd_card *card = chip->card; | ||
360 | unsigned int idx; | ||
361 | int err; | ||
362 | |||
363 | strcpy(card->mixername, "NgeneMixer"); | ||
364 | |||
365 | for (idx = 0; idx < ARRAY_SIZE(snd_controls); idx++) { | ||
366 | err = snd_ctl_add(card, snd_ctl_new1(&snd_controls[idx], chip)); | ||
367 | if (err < 0) | ||
368 | return err; | ||
369 | } | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | int ngene_snd_init(struct ngene_channel *chan) | ||
374 | { | ||
375 | struct snd_card *card; | ||
376 | struct mychip *chip; | ||
377 | int err; | ||
378 | |||
379 | if (sound_dev >= SNDRV_CARDS) | ||
380 | return -ENODEV; | ||
381 | if (!enable[sound_dev]) { | ||
382 | sound_dev++; | ||
383 | return -ENOENT; | ||
384 | } | ||
385 | card = snd_card_new(index[sound_dev], id[sound_dev], | ||
386 | THIS_MODULE, sizeof(struct mychip)); | ||
387 | if (card == NULL) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | chip = card->private_data; | ||
391 | chip->card = card; | ||
392 | chip->irq = -1; | ||
393 | |||
394 | sprintf(card->shortname, "MyChip%d%d", chan->dev->nr, chan->number); | ||
395 | sprintf(card->shortname, "Myown%d%d", chan->dev->nr, chan->number); | ||
396 | sprintf(card->longname, "My first Own Chip on Card Nr.%d is %d", | ||
397 | chan->dev->nr, chan->number); | ||
398 | |||
399 | spin_lock_init(&chip->lock); | ||
400 | spin_lock_init(&chip->mixer_lock); | ||
401 | |||
402 | snd_card_new_mixer(chip); | ||
403 | |||
404 | snd_mychip_new_pcm(chip, chan); | ||
405 | err = snd_card_register(card); | ||
406 | if (err < 0) { | ||
407 | snd_card_free(card); | ||
408 | return err; | ||
409 | } | ||
410 | chan->soundcard = card; | ||
411 | chan->mychip = chip; | ||
412 | chip->chan = chan; | ||
413 | sound_dev++; | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | int ngene_snd_exit(struct ngene_channel *chan) | ||
418 | { | ||
419 | snd_card_free(chan->soundcard); | ||
420 | return 0; | ||
421 | } | ||
diff --git a/drivers/media/dvb/ngene/ngene-v4l2.c b/drivers/media/dvb/ngene/ngene-v4l2.c new file mode 100644 index 000000000000..c0a9147c44a5 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-v4l2.c | |||
@@ -0,0 +1,1937 @@ | |||
1 | /* | ||
2 | * ngene_v4l2.c: nGene PCIe bridge driver V4L2 support | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Based on the initial V4L2 support port by Thomas Eschbach. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 only, as published by the Free Software Foundation. | ||
11 | * | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
22 | * 02110-1301, USA | ||
23 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/spinlock.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/unistd.h> | ||
33 | #include <linux/time.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/vmalloc.h> | ||
36 | #include <linux/pagemap.h> | ||
37 | #include <linux/videodev2.h> | ||
38 | #include <linux/videodev.h> | ||
39 | #include <linux/version.h> | ||
40 | #include <asm/uaccess.h> | ||
41 | #include <asm/semaphore.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/kmap_types.h> | ||
45 | #include <linux/videodev.h> | ||
46 | |||
47 | #include <media/v4l2-dev.h> | ||
48 | |||
49 | #include "ngene.h" | ||
50 | #include "ngene-ioctls.h" | ||
51 | |||
52 | /****************************************************************************/ | ||
53 | |||
54 | static unsigned int gbuffers = 8; | ||
55 | static unsigned int gbufsize = 0x208000; | ||
56 | |||
57 | enum km_type ngene_km_types[] = { | ||
58 | KM_USER0, | ||
59 | KM_USER1, | ||
60 | KM_SOFTIRQ0, | ||
61 | KM_SOFTIRQ1, | ||
62 | }; | ||
63 | |||
64 | #define V4L2_STD_NTSC_M_KOREA ((v4l2_std_id)0x00004000) | ||
65 | #define V4L2_STD_SECAM_L1 ((v4l2_std_id)0x00008000) | ||
66 | |||
67 | static inline void *my_video_get_drvdata(struct video_device *vd) | ||
68 | { | ||
69 | return dev_get_drvdata(vd->dev); | ||
70 | } | ||
71 | |||
72 | static inline void my_video_set_drvdata(struct video_device *vd, void *d) | ||
73 | { | ||
74 | dev_set_drvdata(vd->dev, d); | ||
75 | } | ||
76 | |||
77 | static struct ngene_tvnorm ngene_tvnorms_hd[] = { | ||
78 | { | ||
79 | .v4l2_id = V4L2_STD_PAL_BG, | ||
80 | .name = "1080i50", | ||
81 | .swidth = 1920, | ||
82 | .sheight = 1080, | ||
83 | .tuner_norm = 1, | ||
84 | .soundstd = 1, | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | static struct ngene_tvnorm ngene_tvnorms_sd[] = { | ||
89 | /* PAL-BDGHI */ | ||
90 | /* max. active video is actually 922, but 924 is divisible by 4 & 3!*/ | ||
91 | /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ | ||
92 | { | ||
93 | .v4l2_id = V4L2_STD_PAL_BG, | ||
94 | .name = "PAL-BG", | ||
95 | .swidth = 720, | ||
96 | .sheight = 576, | ||
97 | .tuner_norm = 1, | ||
98 | .soundstd = 1, | ||
99 | }, { | ||
100 | .v4l2_id = V4L2_STD_PAL_DK, | ||
101 | .name = "PAL-DK", | ||
102 | .swidth = 720, | ||
103 | .sheight = 576, | ||
104 | .tuner_norm = 2, | ||
105 | .soundstd = 2, | ||
106 | }, { | ||
107 | .v4l2_id = V4L2_STD_PAL_H, | ||
108 | .name = "PAL-H", | ||
109 | .swidth = 720, | ||
110 | .sheight = 576, | ||
111 | .tuner_norm = 0, | ||
112 | .soundstd = 1, | ||
113 | }, { | ||
114 | .v4l2_id = V4L2_STD_PAL_I, | ||
115 | .name = "PAL-I", | ||
116 | .swidth = 720, | ||
117 | .sheight = 576, | ||
118 | .tuner_norm = 4, | ||
119 | .soundstd = 4, | ||
120 | }, { | ||
121 | .v4l2_id = V4L2_STD_PAL_M, | ||
122 | .name = "PAL_M", | ||
123 | .swidth = 720, | ||
124 | .sheight = 5760, | ||
125 | .tuner_norm = 7, | ||
126 | .soundstd = 5, | ||
127 | }, { | ||
128 | .v4l2_id = V4L2_STD_NTSC_M, | ||
129 | .name = "NTSC_M", | ||
130 | .swidth = 720, | ||
131 | .sheight = 480, | ||
132 | .tuner_norm = 7, | ||
133 | .soundstd = 5, | ||
134 | }, { | ||
135 | .v4l2_id = V4L2_STD_NTSC_M_JP, | ||
136 | .name = "NTSC_M_JP", | ||
137 | .swidth = 720, | ||
138 | .sheight = 480, | ||
139 | .tuner_norm = 7, | ||
140 | .soundstd = 6, | ||
141 | }, { | ||
142 | .v4l2_id = V4L2_STD_PAL_N, | ||
143 | .name = "PAL-N", | ||
144 | .swidth = 720, | ||
145 | .sheight = 576, | ||
146 | .tuner_norm = 7, | ||
147 | .soundstd = 5, | ||
148 | }, { | ||
149 | .v4l2_id = V4L2_STD_SECAM_B, | ||
150 | .name = "SECAM_B", | ||
151 | .swidth = 720, | ||
152 | .sheight = 576, | ||
153 | .tuner_norm = 1, | ||
154 | .soundstd = 1, | ||
155 | }, { | ||
156 | .v4l2_id = V4L2_STD_SECAM_D, | ||
157 | .name = "SECAM_D", | ||
158 | .swidth = 720, | ||
159 | .sheight = 576, | ||
160 | .tuner_norm = 2, | ||
161 | .soundstd = 2, | ||
162 | }, { | ||
163 | .v4l2_id = V4L2_STD_SECAM_G, | ||
164 | .name = "SECAM_G", | ||
165 | .swidth = 720, | ||
166 | .sheight = 576, | ||
167 | .tuner_norm = 3, | ||
168 | .soundstd = 1, | ||
169 | }, { | ||
170 | .v4l2_id = V4L2_STD_SECAM_H, | ||
171 | .name = "SECAM_H", | ||
172 | .swidth = 720, | ||
173 | .sheight = 576, | ||
174 | .tuner_norm = 3, | ||
175 | .soundstd = 1, | ||
176 | }, { | ||
177 | .v4l2_id = V4L2_STD_SECAM_K, | ||
178 | .name = "SECAM_K", | ||
179 | .swidth = 720, | ||
180 | .sheight = 576, | ||
181 | .tuner_norm = 2, | ||
182 | .soundstd = 2, | ||
183 | }, { | ||
184 | .v4l2_id = V4L2_STD_SECAM_K1, | ||
185 | .name = "SECAM_K1", | ||
186 | .swidth = 720, | ||
187 | .sheight = 576, | ||
188 | .tuner_norm = 2, | ||
189 | .soundstd = 2, | ||
190 | }, { | ||
191 | .v4l2_id = V4L2_STD_SECAM_L, | ||
192 | .name = "SECAM_L", | ||
193 | .swidth = 720, | ||
194 | .sheight = 576, | ||
195 | .tuner_norm = 5, | ||
196 | .soundstd = 3, | ||
197 | }, { | ||
198 | .v4l2_id = V4L2_STD_NTSC_M_KOREA, | ||
199 | .name = "NTSC_M_KOREA", | ||
200 | .swidth = 720, | ||
201 | .sheight = 480, | ||
202 | .tuner_norm = 7, | ||
203 | .soundstd = 7, | ||
204 | }, { | ||
205 | .v4l2_id = V4L2_STD_SECAM_L1, | ||
206 | .name = "SECAM_L1", | ||
207 | .swidth = 720, | ||
208 | .sheight = 576, | ||
209 | .tuner_norm = 6, | ||
210 | .soundstd = 3, | ||
211 | } | ||
212 | |||
213 | }; | ||
214 | |||
215 | static const int NGENE_TVNORMS = ARRAY_SIZE(ngene_tvnorms_sd); | ||
216 | |||
217 | static u8 BlackLine[1440] = { | ||
218 | /* 0x80, */ 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
219 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
220 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
221 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
222 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
223 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
224 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
225 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
226 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
227 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
228 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
229 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
230 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
231 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
232 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
233 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
234 | |||
235 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
236 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
237 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
238 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
239 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
240 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
241 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
242 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
243 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
244 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
245 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
246 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
247 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
248 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
249 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
250 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
251 | |||
252 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
253 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
254 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
255 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
256 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
257 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
258 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
259 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
260 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
261 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
262 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
263 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
264 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
265 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
266 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
267 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
268 | |||
269 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
270 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
271 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
272 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
273 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
274 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
275 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
276 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
277 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
278 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
279 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
280 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
281 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
282 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
283 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
284 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
285 | |||
286 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
287 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
288 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
289 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
290 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
291 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
292 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
293 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
294 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
295 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
296 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
297 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
298 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
299 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
300 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
301 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
302 | |||
303 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
304 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
305 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
306 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
307 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
308 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
309 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
310 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
311 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
312 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
313 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
314 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
315 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
316 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
317 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
318 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
319 | |||
320 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
321 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
322 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
323 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
324 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
325 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
326 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
327 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
328 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
329 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
330 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
331 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
332 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
333 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
334 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
335 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
336 | |||
337 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
338 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
339 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
340 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
341 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
342 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
343 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
344 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
345 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
346 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
347 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
348 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
349 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
350 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
351 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
352 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
353 | |||
354 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
355 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
356 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
357 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
358 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
359 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
360 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
361 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
362 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
363 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
364 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
365 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
366 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
367 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
368 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
369 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
370 | |||
371 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
372 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
373 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
374 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
375 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
376 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
377 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
378 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
379 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
380 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
381 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
382 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
383 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
384 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
385 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
386 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
387 | |||
388 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
389 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
390 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
391 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
392 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
393 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
394 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
395 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
396 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
397 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
398 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
399 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
400 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
401 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
402 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
403 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
404 | |||
405 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
406 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
407 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
408 | 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, | ||
409 | 0x80, | ||
410 | }; | ||
411 | |||
412 | #define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) | ||
413 | #define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 1) | ||
414 | |||
415 | static const struct v4l2_queryctrl no_ctl = { | ||
416 | .name = "no_ctl", | ||
417 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
418 | }; | ||
419 | |||
420 | static const struct v4l2_queryctrl ngene_ctls[] = { | ||
421 | /* --- video --- */ | ||
422 | { | ||
423 | .id = V4L2_CID_BRIGHTNESS, | ||
424 | .name = "Brightness", | ||
425 | .minimum = -127, | ||
426 | .maximum = 127, | ||
427 | .step = 1, | ||
428 | .default_value = 0, | ||
429 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
430 | }, { | ||
431 | .id = V4L2_CID_CONTRAST, | ||
432 | .name = "Contrast", | ||
433 | .minimum = 0, | ||
434 | .maximum = 63, | ||
435 | .step = 1, | ||
436 | .default_value = 30, | ||
437 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
438 | }, { | ||
439 | .id = V4L2_CID_SATURATION, | ||
440 | .name = "Saturation", | ||
441 | .minimum = 0, | ||
442 | .maximum = 4094, | ||
443 | .step = 1, | ||
444 | .default_value = 2000, | ||
445 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
446 | }, { | ||
447 | .id = V4L2_CID_HUE, | ||
448 | .name = "Hue", | ||
449 | .minimum = -2047, | ||
450 | .maximum = 2047, | ||
451 | .step = 1, | ||
452 | .default_value = 0, | ||
453 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
454 | }, | ||
455 | /* --- audio --- */ | ||
456 | { | ||
457 | .id = V4L2_CID_AUDIO_MUTE, | ||
458 | .name = "Mute", | ||
459 | .minimum = 0, | ||
460 | .maximum = 1, | ||
461 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
462 | }, { | ||
463 | .id = V4L2_CID_PRIVATE_SHARPNESS, | ||
464 | .name = "sharpness", | ||
465 | .minimum = 0, | ||
466 | .maximum = 100, | ||
467 | .step = 1, | ||
468 | .default_value = 50, | ||
469 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
470 | }, | ||
471 | |||
472 | }; | ||
473 | |||
474 | static const int NGENE_CTLS = ARRAY_SIZE(ngene_ctls); | ||
475 | |||
476 | static const struct ngene_format ngene_formats[] = { | ||
477 | { | ||
478 | .name = "4:2:2, packed, YUYV", | ||
479 | .palette = -1, | ||
480 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
481 | .format = V4L2_PIX_FMT_YUYV, | ||
482 | .palette = VIDEO_PALETTE_YUYV, | ||
483 | .depth = 16, | ||
484 | .flags = 0x02,/* FORMAT_FLAGS_PACKED, */ | ||
485 | } | ||
486 | }; | ||
487 | |||
488 | static const unsigned int NGENE_FORMATS = ARRAY_SIZE(ngene_formats); | ||
489 | |||
490 | /****************************************************************************/ | ||
491 | |||
492 | static struct videobuf_queue *ngene_queue(struct ngene_vopen *vopen) | ||
493 | { | ||
494 | struct videobuf_queue *q = NULL; | ||
495 | |||
496 | switch (vopen->type) { | ||
497 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
498 | q = &vopen->vbuf_q; | ||
499 | break; | ||
500 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
501 | q = &vopen->vbi; | ||
502 | break; | ||
503 | default: | ||
504 | break; | ||
505 | } | ||
506 | return q; | ||
507 | } | ||
508 | |||
509 | static int ngene_resource(struct ngene_vopen *vopen) | ||
510 | { | ||
511 | int res = 0; | ||
512 | |||
513 | switch (vopen->type) { | ||
514 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
515 | res = RESOURCE_VIDEO; | ||
516 | break; | ||
517 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
518 | res = RESOURCE_VBI; | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | return res; | ||
524 | } | ||
525 | |||
526 | static int ngene_try_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, | ||
527 | struct v4l2_format *f) | ||
528 | { | ||
529 | switch (f->type) { | ||
530 | |||
531 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
532 | { | ||
533 | const struct ngene_format *fmt; | ||
534 | enum v4l2_field field; | ||
535 | unsigned int maxw, maxh; | ||
536 | int maxLinesPerField; | ||
537 | |||
538 | fmt = ngene_formats; | ||
539 | if (NULL == fmt) | ||
540 | return -EINVAL; | ||
541 | |||
542 | /* fixup format */ | ||
543 | maxw = chan->tvnorms[chan->tvnorm].swidth; | ||
544 | maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; | ||
545 | maxh = maxLinesPerField; | ||
546 | field = f->fmt.pix.field; | ||
547 | |||
548 | if (V4L2_FIELD_ANY == field) | ||
549 | field = (f->fmt.pix.height > maxh / 2) | ||
550 | ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; | ||
551 | |||
552 | if (V4L2_FIELD_SEQ_BT == field) | ||
553 | field = V4L2_FIELD_SEQ_TB; | ||
554 | |||
555 | /* update data for the application */ | ||
556 | f->fmt.pix.field = field; | ||
557 | if (f->fmt.pix.width < 48) | ||
558 | f->fmt.pix.width = 48; | ||
559 | if (f->fmt.pix.height < 32) | ||
560 | f->fmt.pix.height = 32; | ||
561 | if (f->fmt.pix.width > maxw) | ||
562 | f->fmt.pix.width = maxw; | ||
563 | if (f->fmt.pix.height > maxh) | ||
564 | f->fmt.pix.height = maxh; | ||
565 | f->fmt.pix.width &= ~0x03; | ||
566 | f->fmt.pix.bytesperline = | ||
567 | (f->fmt.pix.width * fmt->depth) >> 3; | ||
568 | f->fmt.pix.sizeimage = | ||
569 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
575 | return -EINVAL; | ||
576 | |||
577 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
578 | return 0; | ||
579 | |||
580 | default: | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | /****************************************************************************/ | ||
586 | /* Analog driver stuff ******************************************************/ | ||
587 | /****************************************************************************/ | ||
588 | |||
589 | static int check_alloc_res(struct ngene_channel *channel, | ||
590 | struct ngene_vopen *vopen, int bit) | ||
591 | { | ||
592 | if (vopen->resources & bit) | ||
593 | /* have it already allocated */ | ||
594 | return 1; | ||
595 | |||
596 | /* is it free? */ | ||
597 | down(&channel->reslock); | ||
598 | if (channel->resources & bit) { | ||
599 | /* no, someone else uses it */ | ||
600 | up(&channel->reslock); | ||
601 | return 0; | ||
602 | } | ||
603 | /* it's free, grab it */ | ||
604 | vopen->resources |= bit; | ||
605 | channel->resources |= bit; | ||
606 | up(&channel->reslock); | ||
607 | return 1; | ||
608 | } | ||
609 | |||
610 | static int check_res(struct ngene_vopen *vopen, int bit) | ||
611 | { | ||
612 | return vopen->resources & bit; | ||
613 | } | ||
614 | |||
615 | static int locked_res(struct ngene_channel *chan, int bit) | ||
616 | { | ||
617 | return chan->resources & bit; | ||
618 | } | ||
619 | |||
620 | static void free_res(struct ngene_channel *channel, | ||
621 | struct ngene_vopen *vopen, int bits) | ||
622 | { | ||
623 | down(&channel->reslock); | ||
624 | vopen->resources &= ~bits; | ||
625 | channel->resources &= ~bits; | ||
626 | up(&channel->reslock); | ||
627 | } | ||
628 | |||
629 | /****************************************************************************/ | ||
630 | /* MISC HELPERS *************************************************************/ | ||
631 | /****************************************************************************/ | ||
632 | |||
633 | static int ngene_g_fmt(struct ngene_vopen *vopen, struct v4l2_format *f) | ||
634 | { | ||
635 | if (!vopen->fmt) | ||
636 | vopen->fmt = ngene_formats; | ||
637 | |||
638 | switch (f->type) { | ||
639 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
640 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); | ||
641 | f->fmt.pix.width = vopen->width; | ||
642 | f->fmt.pix.height = vopen->height; | ||
643 | f->fmt.pix.field = vopen->vbuf_q.field; | ||
644 | f->fmt.pix.pixelformat = vopen->fmt->fourcc; | ||
645 | f->fmt.pix.bytesperline = (f->fmt.pix.width * 16) >> 3; | ||
646 | f->fmt.pix.sizeimage = | ||
647 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
648 | return 0; | ||
649 | |||
650 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
651 | memset(&f->fmt.win, 0, sizeof(struct v4l2_window)); | ||
652 | return 0; | ||
653 | f->fmt.win.w = vopen->ov.w; | ||
654 | f->fmt.win.field = vopen->ov.field; | ||
655 | return 0; | ||
656 | |||
657 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
658 | return -EINVAL; | ||
659 | |||
660 | default: | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | static int ngene_switch_type(struct ngene_vopen *vopen, enum v4l2_buf_type type) | ||
666 | { | ||
667 | struct videobuf_queue *q = ngene_queue(vopen); | ||
668 | int res = ngene_resource(vopen); | ||
669 | |||
670 | if (check_res(vopen, res)) | ||
671 | return -EBUSY; | ||
672 | if (videobuf_queue_is_busy(q)) | ||
673 | return -EBUSY; | ||
674 | vopen->type = type; | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int ngene_s_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, | ||
679 | struct v4l2_format *f) | ||
680 | { | ||
681 | int retval; | ||
682 | |||
683 | switch (f->type) { | ||
684 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
685 | { | ||
686 | const struct ngene_format *fmt; | ||
687 | retval = ngene_try_fmt(vopen, chan, f); | ||
688 | if (0 != retval) | ||
689 | return retval; | ||
690 | |||
691 | retval = ngene_switch_type(vopen, f->type); | ||
692 | if (0 != retval) | ||
693 | return retval; | ||
694 | fmt = ngene_formats; | ||
695 | |||
696 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) | ||
697 | return -EINVAL; | ||
698 | /* update our state informations */ | ||
699 | mutex_lock(&vopen->vbuf_q.lock); | ||
700 | vopen->fmt = fmt; | ||
701 | vopen->vbuf_q.field = f->fmt.pix.field; | ||
702 | vopen->vbuf_q.last = V4L2_FIELD_INTERLACED; | ||
703 | vopen->width = f->fmt.pix.width; | ||
704 | vopen->height = f->fmt.pix.height; | ||
705 | chan->init.fmt = fmt; | ||
706 | chan->init.width = f->fmt.pix.width; | ||
707 | chan->init.height = f->fmt.pix.height; | ||
708 | mutex_unlock(&vopen->vbuf_q.lock); | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
713 | return -EINVAL; | ||
714 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
715 | return -EINVAL; | ||
716 | default: | ||
717 | return -EINVAL; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | /****************************************************************************/ | ||
722 | /* SG support ***************************************************************/ | ||
723 | /****************************************************************************/ | ||
724 | |||
725 | static inline enum km_type ngene_kmap_type(int out) | ||
726 | { | ||
727 | return ngene_km_types[(in_softirq() ? 2 : 0) + out]; | ||
728 | } | ||
729 | |||
730 | static inline void *ngene_kmap(struct page *page, int out) | ||
731 | { | ||
732 | return kmap_atomic(page, ngene_kmap_type(out)); | ||
733 | } | ||
734 | |||
735 | static inline void ngene_kunmap(void *vaddr, int out) | ||
736 | { | ||
737 | kunmap_atomic(vaddr, ngene_kmap_type(out)); | ||
738 | } | ||
739 | |||
740 | struct scatter_walk { | ||
741 | struct scatterlist *sg; | ||
742 | struct page *page; | ||
743 | void *data; | ||
744 | unsigned int len_this_page; | ||
745 | unsigned int len_this_segment; | ||
746 | unsigned int offset; | ||
747 | }; | ||
748 | |||
749 | static inline struct scatterlist *sg_next(struct scatterlist *sg) | ||
750 | { | ||
751 | return sg + 1; | ||
752 | } | ||
753 | |||
754 | void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes) | ||
755 | { | ||
756 | if (nbytes <= walk->len_this_page && | ||
757 | (((unsigned long)walk->data) & | ||
758 | (PAGE_CACHE_SIZE - 1)) + nbytes <= PAGE_CACHE_SIZE) | ||
759 | return walk->data; | ||
760 | else | ||
761 | return walk->data; | ||
762 | } | ||
763 | |||
764 | void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) | ||
765 | { | ||
766 | unsigned int rest_of_page; | ||
767 | |||
768 | walk->sg = sg; | ||
769 | walk->page = sg->page; | ||
770 | walk->len_this_segment = sg->length; | ||
771 | rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); | ||
772 | walk->len_this_page = min(sg->length, rest_of_page); | ||
773 | walk->offset = sg->offset; | ||
774 | } | ||
775 | |||
776 | void scatterwalk_map(struct scatter_walk *walk, int out) | ||
777 | { | ||
778 | walk->data = ngene_kmap(walk->page, out) + walk->offset; | ||
779 | } | ||
780 | |||
781 | static void scatterwalk_pagedone(struct scatter_walk *walk, int out, | ||
782 | unsigned int more) | ||
783 | { | ||
784 | /* walk->data may be pointing the first byte of the next page; | ||
785 | however, we know we transfered at least one byte. So, | ||
786 | walk->data - 1 will be a virtual address in the mapped page. */ | ||
787 | |||
788 | if (out) | ||
789 | flush_dcache_page(walk->page); | ||
790 | |||
791 | if (more) { | ||
792 | walk->len_this_segment -= walk->len_this_page; | ||
793 | |||
794 | if (walk->len_this_segment) { | ||
795 | walk->page++; | ||
796 | walk->len_this_page = min(walk->len_this_segment, | ||
797 | (unsigned)PAGE_CACHE_SIZE); | ||
798 | walk->offset = 0; | ||
799 | } else { | ||
800 | scatterwalk_start(walk, sg_next(walk->sg)); | ||
801 | } | ||
802 | } | ||
803 | } | ||
804 | |||
805 | void scatterwalk_done(struct scatter_walk *walk, int out, int more) | ||
806 | { | ||
807 | ngene_kunmap(walk->data, out); | ||
808 | if (walk->len_this_page == 0 || !more) | ||
809 | scatterwalk_pagedone(walk, out, more); | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * Do not call this unless the total length of all of the fragments | ||
814 | * has been verified as multiple of the block size. | ||
815 | */ | ||
816 | int scatterwalk_copychunks(struct scatter_walk *walk, size_t nbytes, int out) | ||
817 | { | ||
818 | walk->offset += nbytes; | ||
819 | walk->len_this_page -= nbytes; | ||
820 | walk->len_this_segment -= nbytes; | ||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | static void *vid_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
825 | { | ||
826 | struct ngene_channel *chan = priv; | ||
827 | struct ngene_buffer *item; | ||
828 | int wstrich, hstrich; | ||
829 | u8 *odd, *even; | ||
830 | u32 bpl = chan->tvnorms[chan->tvnorm].swidth * 2; | ||
831 | |||
832 | struct scatter_walk walk_out; | ||
833 | const unsigned int bsize = PAGE_SIZE; | ||
834 | unsigned int nbytes; | ||
835 | int rest_of_buffer, ah, rwstrich; | ||
836 | |||
837 | spin_lock(&chan->s_lock); | ||
838 | |||
839 | if (list_empty(&chan->capture)) { | ||
840 | chan->evenbuffer = NULL; | ||
841 | goto out; | ||
842 | } | ||
843 | item = list_entry(chan->capture.next, struct ngene_buffer, vb.queue); | ||
844 | |||
845 | if (chan->tvnorms[chan->tvnorm].sheight == 1080) | ||
846 | buf += 3840; | ||
847 | |||
848 | odd = buf; | ||
849 | |||
850 | hstrich = item->vb.height; | ||
851 | if (hstrich > chan->tvnorms[chan->tvnorm].sheight) | ||
852 | hstrich = chan->tvnorms[chan->tvnorm].sheight; | ||
853 | |||
854 | wstrich = item->vb.width; | ||
855 | if (wstrich > chan->tvnorms[chan->tvnorm].swidth) | ||
856 | wstrich = chan->tvnorms[chan->tvnorm].swidth; | ||
857 | wstrich <<= 1; | ||
858 | |||
859 | if (flags & BEF_EVEN_FIELD) { | ||
860 | chan->evenbuffer = buf; | ||
861 | if (chan->lastbufferflag) { | ||
862 | chan->lastbufferflag = 0; | ||
863 | if (chan->tvnorms[chan->tvnorm].sheight == 576) { | ||
864 | memcpy(buf + 413280, BlackLine, 1440); | ||
865 | memcpy(buf + 411840, BlackLine, 1440); | ||
866 | } | ||
867 | goto out; | ||
868 | } | ||
869 | } | ||
870 | chan->lastbufferflag = 1; | ||
871 | if (chan->evenbuffer) | ||
872 | even = chan->evenbuffer; | ||
873 | else | ||
874 | even = odd; | ||
875 | if (chan->tvnorms[chan->tvnorm].sheight == 576) { | ||
876 | memcpy(odd + 413280, BlackLine, 1440); | ||
877 | memcpy(odd + 411840, BlackLine, 1440); | ||
878 | } | ||
879 | nbytes = item->vb.dma.sglen * PAGE_SIZE; | ||
880 | scatterwalk_start(&walk_out, item->vb.dma.sglist); | ||
881 | ah = 0; | ||
882 | rwstrich = wstrich; | ||
883 | do { | ||
884 | u8 *dst_p; | ||
885 | |||
886 | rest_of_buffer = bsize; | ||
887 | scatterwalk_map(&walk_out, 1); | ||
888 | dst_p = scatterwalk_whichbuf(&walk_out, bsize); | ||
889 | nbytes -= bsize; | ||
890 | scatterwalk_copychunks(&walk_out, bsize, 1); | ||
891 | |||
892 | while (rest_of_buffer > 0 && ah < hstrich) { | ||
893 | if (rest_of_buffer >= rwstrich) { | ||
894 | if (ah % 2 == 0) { | ||
895 | memcpy(walk_out.data + | ||
896 | (bsize - rest_of_buffer), | ||
897 | odd, rwstrich); | ||
898 | odd += bpl - (wstrich - rwstrich); | ||
899 | } else { | ||
900 | memcpy(walk_out.data + | ||
901 | (bsize - rest_of_buffer), | ||
902 | even, rwstrich); | ||
903 | even += bpl - (wstrich - rwstrich); | ||
904 | } | ||
905 | rest_of_buffer -= rwstrich; | ||
906 | ah++; | ||
907 | rwstrich = wstrich; | ||
908 | } else { | ||
909 | if (ah % 2 == 0) { | ||
910 | memcpy(walk_out.data + | ||
911 | (bsize - rest_of_buffer), | ||
912 | odd, rest_of_buffer); | ||
913 | odd += rest_of_buffer; | ||
914 | } else { | ||
915 | memcpy(walk_out.data + | ||
916 | (bsize - rest_of_buffer), | ||
917 | even, rest_of_buffer); | ||
918 | even += rest_of_buffer; | ||
919 | } | ||
920 | rwstrich -= rest_of_buffer; | ||
921 | rest_of_buffer = 0; | ||
922 | } | ||
923 | } | ||
924 | scatterwalk_done(&walk_out, 1, nbytes); | ||
925 | } while (nbytes && ah < hstrich); | ||
926 | |||
927 | { | ||
928 | struct timeval ts; | ||
929 | do_gettimeofday(&ts); | ||
930 | list_del(&item->vb.queue); | ||
931 | item->vb.state = STATE_DONE; | ||
932 | item->vb.ts = ts; | ||
933 | wake_up(&item->vb.done); | ||
934 | chan->evenbuffer = NULL; | ||
935 | } | ||
936 | |||
937 | out: | ||
938 | spin_unlock(&chan->s_lock); | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static void *snd_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
943 | { | ||
944 | struct ngene_channel *chan = priv; | ||
945 | struct mychip *mychip = chan->mychip; | ||
946 | |||
947 | if (chan->audiomute == 0) | ||
948 | memcpy(chan->soundbuffer, (u8 *) buf, MAX_AUDIO_BUFFER_SIZE); | ||
949 | else | ||
950 | memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); | ||
951 | |||
952 | if (mychip->substream != NULL) { | ||
953 | if (chan->sndbuffflag == 0) | ||
954 | chan->sndbuffflag = 1; | ||
955 | else | ||
956 | chan->sndbuffflag = 0; | ||
957 | spin_unlock(&mychip->lock); | ||
958 | snd_pcm_period_elapsed(mychip->substream); | ||
959 | spin_lock(&mychip->lock); | ||
960 | } | ||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static void set_analog_transfer(struct ngene_channel *chan, int state) | ||
965 | { | ||
966 | struct ngene_channel *ch; | ||
967 | u8 flags = 0; | ||
968 | |||
969 | ch = &chan->dev->channel[chan->number + 2]; | ||
970 | /* printk(KERN_INFO "set_analog_transfer %d\n", state); */ | ||
971 | |||
972 | if (1) { /* chan->tun_dec_rdy == 1){ */ | ||
973 | if (state) { | ||
974 | |||
975 | chan->Capture1Length = | ||
976 | chan->tvnorms[chan->tvnorm].swidth * | ||
977 | chan->tvnorms[chan->tvnorm].sheight; | ||
978 | if (chan->tvnorms[chan->tvnorm].sheight == 576) | ||
979 | chan->nLines = 287; | ||
980 | else if (chan->tvnorms[chan->tvnorm].sheight == 1080) | ||
981 | chan->nLines = 541; | ||
982 | else | ||
983 | chan->nLines = | ||
984 | chan->tvnorms[chan->tvnorm].sheight / 2; | ||
985 | chan->nBytesPerLine = | ||
986 | chan->tvnorms[chan->tvnorm].swidth * 2; | ||
987 | if (chan->dev->card_info->io_type[chan->number] == | ||
988 | NGENE_IO_HDTV) { | ||
989 | chan->itumode = 2; | ||
990 | flags = SFLAG_ORDER_LUMA_CHROMA; | ||
991 | } else { | ||
992 | chan->itumode = 0; | ||
993 | flags = SFLAG_ORDER_LUMA_CHROMA; | ||
994 | } | ||
995 | chan->pBufferExchange = vid_exchange; | ||
996 | ngene_command_stream_control(chan->dev, chan->number, | ||
997 | 0x80, | ||
998 | SMODE_VIDEO_CAPTURE, | ||
999 | flags); | ||
1000 | |||
1001 | ch->Capture1Length = MAX_AUDIO_BUFFER_SIZE; | ||
1002 | ch->pBufferExchange = snd_exchange; | ||
1003 | ngene_command_stream_control(ch->dev, ch->number, | ||
1004 | 0x80, | ||
1005 | SMODE_AUDIO_CAPTURE, 0); | ||
1006 | ch->soundstreamon = 1; | ||
1007 | } else { | ||
1008 | ngene_command_stream_control(chan->dev, chan->number, | ||
1009 | 0, 0, 0); | ||
1010 | ngene_command_stream_control(ch->dev, ch->number, | ||
1011 | 0, 0, 0); | ||
1012 | ch->soundstreamon = 0; | ||
1013 | } | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | static int ngene_analog_start_feed(struct ngene_channel *chan) | ||
1018 | { | ||
1019 | int freerunmode = 1; | ||
1020 | struct i2c_adapter *adapter = &chan->i2c_adapter; | ||
1021 | |||
1022 | if (chan->users == 0 && chan->number < 2) { | ||
1023 | chan->evenbuffer = NULL; | ||
1024 | chan->users = 1; | ||
1025 | i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, | ||
1026 | &freerunmode); | ||
1027 | msleep(25); | ||
1028 | set_analog_transfer(chan, 1); | ||
1029 | msleep(25); | ||
1030 | freerunmode = 0; | ||
1031 | i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, | ||
1032 | &freerunmode); | ||
1033 | } | ||
1034 | return chan->users; | ||
1035 | } | ||
1036 | |||
1037 | static int ngene_analog_stop_feed(struct ngene_channel *chan) | ||
1038 | { | ||
1039 | int freerunmode = 1; | ||
1040 | struct i2c_adapter *adapter = &chan->i2c_adapter; | ||
1041 | if (chan->users == 1 && chan->number < 2) { | ||
1042 | chan->users = 0; | ||
1043 | i2c_clients_command(adapter, | ||
1044 | IOCTL_MIC_DEC_FREESYNC, &freerunmode); | ||
1045 | msleep(20); | ||
1046 | set_analog_transfer(chan, 0); | ||
1047 | } | ||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | /****************************************************************************/ | ||
1052 | /* V4L2 API interface *******************************************************/ | ||
1053 | /****************************************************************************/ | ||
1054 | |||
1055 | void ngene_dma_free(struct videobuf_queue *q, | ||
1056 | struct ngene_channel *chan, struct ngene_buffer *buf) | ||
1057 | { | ||
1058 | videobuf_waiton(&buf->vb, 0, 0); | ||
1059 | videobuf_dma_unmap(q, &buf->vb.dma); | ||
1060 | videobuf_dma_free(&buf->vb.dma); | ||
1061 | buf->vb.state = STATE_NEEDS_INIT; | ||
1062 | } | ||
1063 | |||
1064 | static int ngene_prepare_buffer(struct videobuf_queue *q, | ||
1065 | struct ngene_channel *chan, | ||
1066 | struct ngene_buffer *buf, | ||
1067 | const struct ngene_format *fmt, | ||
1068 | unsigned int width, unsigned int height, | ||
1069 | enum v4l2_field field) | ||
1070 | { | ||
1071 | int rc = 0; | ||
1072 | /* check settings */ | ||
1073 | if (NULL == fmt) | ||
1074 | return -EINVAL; | ||
1075 | |||
1076 | if (width < 48 || height < 32) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | buf->vb.size = (width * height * 16 /* fmt->depth */) >> 3; | ||
1080 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
1081 | return -EINVAL; | ||
1082 | |||
1083 | /* alloc + fill struct ngene_buffer (if changed) */ | ||
1084 | if (buf->vb.width != width || buf->vb.height != height || | ||
1085 | buf->vb.field != field || buf->fmt != fmt || | ||
1086 | buf->tvnorm != chan->tvnorm) { | ||
1087 | |||
1088 | buf->vb.width = width; | ||
1089 | buf->vb.height = height; | ||
1090 | buf->vb.field = field; | ||
1091 | buf->tvnorm = chan->tvnorm; | ||
1092 | buf->fmt = fmt; | ||
1093 | |||
1094 | ngene_dma_free(q, chan, buf); | ||
1095 | } | ||
1096 | |||
1097 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
1098 | return -EINVAL; | ||
1099 | |||
1100 | if (buf->vb.field == 0) | ||
1101 | buf->vb.field = V4L2_FIELD_INTERLACED; | ||
1102 | |||
1103 | if (STATE_NEEDS_INIT == buf->vb.state) { | ||
1104 | buf->vb.width = width; | ||
1105 | buf->vb.height = height; | ||
1106 | buf->vb.field = field; | ||
1107 | buf->tvnorm = chan->tvnorm; | ||
1108 | buf->fmt = fmt; | ||
1109 | |||
1110 | rc = videobuf_iolock(q, &buf->vb, &chan->fbuf); | ||
1111 | if (0 != rc) | ||
1112 | goto fail; | ||
1113 | } | ||
1114 | if (!buf->vb.dma.bus_addr) | ||
1115 | videobuf_dma_sync(q, &buf->vb.dma); | ||
1116 | buf->vb.state = STATE_PREPARED; | ||
1117 | return 0; | ||
1118 | |||
1119 | fail: | ||
1120 | ngene_dma_free(q, chan, buf); | ||
1121 | return rc; | ||
1122 | |||
1123 | } | ||
1124 | |||
1125 | static int buffer_setup(struct videobuf_queue *q, | ||
1126 | unsigned int *count, unsigned int *size) | ||
1127 | { | ||
1128 | struct ngene_vopen *vopen = q->priv_data; | ||
1129 | *size = 2 * vopen->width * vopen->height; | ||
1130 | if (0 == *count) | ||
1131 | *count = gbuffers; | ||
1132 | while (*size * *count > gbuffers * gbufsize) | ||
1133 | (*count)--; | ||
1134 | q->field = V4L2_FIELD_INTERLACED; | ||
1135 | q->last = V4L2_FIELD_INTERLACED; | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
1140 | enum v4l2_field field) | ||
1141 | { | ||
1142 | struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); | ||
1143 | struct ngene_vopen *vopen = q->priv_data; | ||
1144 | return ngene_prepare_buffer(q, vopen->ch, buf, vopen->fmt, | ||
1145 | vopen->width, vopen->height, field); | ||
1146 | } | ||
1147 | |||
1148 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
1149 | { | ||
1150 | struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); | ||
1151 | struct ngene_vopen *vopen = q->priv_data; | ||
1152 | ngene_dma_free(q, vopen->ch, buf); | ||
1153 | } | ||
1154 | |||
1155 | static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
1156 | { | ||
1157 | struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); | ||
1158 | struct ngene_vopen *vopen = q->priv_data; | ||
1159 | struct ngene_channel *chan = vopen->ch; | ||
1160 | |||
1161 | buf->vb.state = STATE_QUEUED; | ||
1162 | list_add_tail(&buf->vb.queue, &chan->capture); | ||
1163 | } | ||
1164 | |||
1165 | static struct videobuf_queue_ops ngene_video_qops = { | ||
1166 | .buf_setup = buffer_setup, | ||
1167 | .buf_prepare = buffer_prepare, | ||
1168 | .buf_queue = buffer_queue, | ||
1169 | .buf_release = buffer_release, | ||
1170 | }; | ||
1171 | |||
1172 | int video_open(struct inode *inode, struct file *flip) | ||
1173 | { | ||
1174 | struct ngene_vopen *vopen = NULL; | ||
1175 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1176 | struct video_device *vd = video_devdata(flip); | ||
1177 | struct ngene_channel *chan = my_video_get_drvdata(vd); | ||
1178 | |||
1179 | vopen = kmalloc(sizeof(*vopen), GFP_KERNEL); | ||
1180 | if (!vopen) | ||
1181 | return -ENOMEM; | ||
1182 | memset(vopen, 0, sizeof(*vopen)); | ||
1183 | flip->private_data = vopen; | ||
1184 | v4l2_prio_open(&chan->prio, &vopen->prio); | ||
1185 | vopen->ch = chan; | ||
1186 | vopen->picxcount = 0; | ||
1187 | vopen->type = type; | ||
1188 | videobuf_queue_init(&vopen->vbuf_q, &ngene_video_qops, | ||
1189 | chan->dev->pci_dev, &chan->s_lock, | ||
1190 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1191 | V4L2_FIELD_INTERLACED, | ||
1192 | sizeof(struct ngene_buffer), vopen); | ||
1193 | |||
1194 | vopen->ovfmt = ngene_formats; | ||
1195 | chan->videousers++; | ||
1196 | if (chan->dev->card_info->switch_ctrl) | ||
1197 | chan->dev->card_info->switch_ctrl(chan, 2, 1); | ||
1198 | return 0; | ||
1199 | } | ||
1200 | |||
1201 | int video_close(struct inode *inode, struct file *filp) | ||
1202 | { | ||
1203 | struct ngene_vopen *vopen = filp->private_data; | ||
1204 | struct ngene_channel *chan = vopen->ch; | ||
1205 | |||
1206 | chan->videousers--; | ||
1207 | if (!chan->videousers) { | ||
1208 | if (chan->dev->card_info->switch_ctrl) | ||
1209 | chan->dev->card_info->switch_ctrl(chan, 2, 0); | ||
1210 | ngene_analog_stop_feed(chan); | ||
1211 | } | ||
1212 | videobuf_mmap_free(&vopen->vbuf_q); | ||
1213 | v4l2_prio_close(&chan->prio, &vopen->prio); | ||
1214 | filp->private_data = NULL; | ||
1215 | kfree(vopen); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | /****************************************************************************/ | ||
1220 | |||
1221 | static int vid_do_ioctl(struct inode *inode, struct file *file, | ||
1222 | unsigned int cmd, void *parg) | ||
1223 | { | ||
1224 | struct ngene_vopen *vopen = file->private_data; | ||
1225 | struct ngene_channel *chan = vopen->ch; | ||
1226 | struct ngene *dev = chan->dev; | ||
1227 | struct i2c_adapter *adap = &chan->i2c_adapter; | ||
1228 | int retval = 0; | ||
1229 | int err = 0; | ||
1230 | |||
1231 | switch (cmd) { | ||
1232 | |||
1233 | case VIDIOC_S_CTRL: | ||
1234 | { | ||
1235 | struct v4l2_control *c = parg; | ||
1236 | |||
1237 | err = v4l2_prio_check(&chan->prio, &vopen->prio); | ||
1238 | if (err) | ||
1239 | return err; | ||
1240 | |||
1241 | if (c->id == V4L2_CID_AUDIO_MUTE) { | ||
1242 | if (c->value) | ||
1243 | (dev->channel[chan->number + 2]).audiomute = 1; | ||
1244 | else | ||
1245 | (dev->channel[chan->number + 2]).audiomute = 0; | ||
1246 | return 0; | ||
1247 | } | ||
1248 | if (c->value != V4L2_CID_AUDIO_MUTE) | ||
1249 | ngene_analog_stop_feed(chan); | ||
1250 | i2c_clients_command(adap, cmd, parg); | ||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | case VIDIOC_S_TUNER: | ||
1255 | { | ||
1256 | err = v4l2_prio_check(&chan->prio, &vopen->prio); | ||
1257 | if (err != 0) | ||
1258 | return err; | ||
1259 | i2c_clients_command(adap, cmd, parg); | ||
1260 | return 0; | ||
1261 | } | ||
1262 | |||
1263 | case VIDIOC_S_FREQUENCY: | ||
1264 | { | ||
1265 | struct v4l2_frequency *f = parg; | ||
1266 | u8 drxa = dev->card_info->demoda[chan->number]; | ||
1267 | |||
1268 | if (chan->fe && chan->fe->ops.tuner_ops.set_frequency) | ||
1269 | chan->fe->ops.tuner_ops. | ||
1270 | set_frequency(chan->fe, f->frequency * 62500); | ||
1271 | if (drxa) | ||
1272 | ; | ||
1273 | } | ||
1274 | |||
1275 | case VIDIOC_S_INPUT: | ||
1276 | { | ||
1277 | err = v4l2_prio_check(&chan->prio, &vopen->prio); | ||
1278 | if (err != 0) | ||
1279 | return err; | ||
1280 | i2c_clients_command(adap, cmd, parg); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | case VIDIOC_G_STD: | ||
1285 | { | ||
1286 | v4l2_std_id *id = parg; | ||
1287 | *id = chan->tvnorms[chan->tvnorm].v4l2_id; | ||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | case VIDIOC_S_STD: | ||
1292 | { | ||
1293 | v4l2_std_id *id = parg; | ||
1294 | unsigned int i; | ||
1295 | |||
1296 | err = v4l2_prio_check(&chan->prio, &vopen->prio); | ||
1297 | if (err != 0) | ||
1298 | return err; | ||
1299 | ngene_analog_stop_feed(chan); | ||
1300 | i2c_clients_command(adap, cmd, parg); | ||
1301 | for (i = 0; i < chan->tvnorm_num; i++) | ||
1302 | if (*id & chan->tvnorms[i].v4l2_id) | ||
1303 | break; | ||
1304 | if (i == chan->tvnorm_num) | ||
1305 | return -EINVAL; | ||
1306 | |||
1307 | chan->tvnorm = i; | ||
1308 | mdelay(50); | ||
1309 | ngene_analog_start_feed(chan); | ||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | case VIDIOC_G_FREQUENCY: | ||
1314 | case VIDIOC_G_INPUT: | ||
1315 | case VIDIOC_S_AUDIO: | ||
1316 | case VIDIOC_G_AUDIO: | ||
1317 | case VIDIOC_ENUMAUDIO: | ||
1318 | case VIDIOC_S_MODULATOR: | ||
1319 | case VIDIOC_G_MODULATOR: | ||
1320 | case VIDIOC_G_CTRL: | ||
1321 | { | ||
1322 | i2c_clients_command(adap, cmd, parg); | ||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | case VIDIOC_G_TUNER: | ||
1327 | { | ||
1328 | struct v4l2_tuner *tuner = parg; | ||
1329 | if (tuner->index != 0) | ||
1330 | return -EINVAL; | ||
1331 | i2c_clients_command(adap, cmd, parg); | ||
1332 | |||
1333 | if (chan->fe && chan->fe->ops.tuner_ops.get_status) { | ||
1334 | u32 status; | ||
1335 | |||
1336 | chan->fe->ops.tuner_ops.get_status(chan->fe, &status); | ||
1337 | tuner->signal = status; | ||
1338 | } | ||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | case VIDIOC_QUERYCTRL: | ||
1343 | { | ||
1344 | struct v4l2_queryctrl *c = parg; | ||
1345 | int i; | ||
1346 | |||
1347 | if ((c->id < V4L2_CID_BASE || | ||
1348 | c->id >= V4L2_CID_LASTP1) && | ||
1349 | (c->id < V4L2_CID_PRIVATE_BASE || | ||
1350 | c->id >= V4L2_CID_PRIVATE_LASTP1)) | ||
1351 | return -EINVAL; | ||
1352 | for (i = 0; i < NGENE_CTLS; i++) | ||
1353 | if (ngene_ctls[i].id == c->id) | ||
1354 | break; | ||
1355 | if (i == NGENE_CTLS) { | ||
1356 | *c = no_ctl; | ||
1357 | return 0; | ||
1358 | } | ||
1359 | *c = ngene_ctls[i]; | ||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | case VIDIOC_G_FMT: | ||
1364 | { | ||
1365 | struct v4l2_format *f = parg; | ||
1366 | ngene_g_fmt(vopen, f); | ||
1367 | } | ||
1368 | |||
1369 | case VIDIOC_S_FMT: | ||
1370 | { | ||
1371 | struct v4l2_format *f = parg; | ||
1372 | |||
1373 | ngene_analog_stop_feed(chan); | ||
1374 | return ngene_s_fmt(vopen, chan, f); | ||
1375 | } | ||
1376 | |||
1377 | case VIDIOC_ENUM_FMT: | ||
1378 | { | ||
1379 | struct v4l2_fmtdesc *f = parg; | ||
1380 | enum v4l2_buf_type type; | ||
1381 | unsigned int i; | ||
1382 | int index; | ||
1383 | |||
1384 | type = f->type; | ||
1385 | if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { | ||
1386 | /* vbi | ||
1387 | index = f->index; | ||
1388 | if (0 != index) | ||
1389 | return -EINVAL; | ||
1390 | memset(f, 0, sizeof(*f)); | ||
1391 | f->index = index; | ||
1392 | f->type = type; | ||
1393 | f->pixelformat = V4L2_PIX_FMT_GREY; | ||
1394 | strcpy(f->description, "vbi data"); */ | ||
1395 | return EINVAL; | ||
1396 | } | ||
1397 | |||
1398 | /* video capture + overlay */ | ||
1399 | index = -1; | ||
1400 | for (i = 0; i < NGENE_FORMATS; i++) { | ||
1401 | if (ngene_formats[i].fourcc != -1) | ||
1402 | index++; | ||
1403 | if ((unsigned int)index == f->index) | ||
1404 | break; | ||
1405 | } | ||
1406 | if (NGENE_FORMATS == i) | ||
1407 | return -EINVAL; | ||
1408 | |||
1409 | switch (f->type) { | ||
1410 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
1411 | break; | ||
1412 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
1413 | /* dprintk(KERN_DEBUG | ||
1414 | "Video Overlay not supported yet.\n"); */ | ||
1415 | return -EINVAL; | ||
1416 | break; | ||
1417 | default: | ||
1418 | return -EINVAL; | ||
1419 | } | ||
1420 | memset(f, 0, sizeof(*f)); | ||
1421 | f->index = index; | ||
1422 | f->type = type; | ||
1423 | f->pixelformat = ngene_formats[i].fourcc; | ||
1424 | strlcpy(f->description, ngene_formats[i].name, | ||
1425 | sizeof(f->description)); | ||
1426 | return 0; | ||
1427 | |||
1428 | } | ||
1429 | |||
1430 | case VIDIOC_QUERYSTD: | ||
1431 | { | ||
1432 | v4l2_std_id *id = parg; | ||
1433 | *id = V4L2_STD_625_50 | V4L2_STD_525_60; | ||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | case VIDIOC_ENUMSTD: | ||
1438 | { | ||
1439 | struct v4l2_standard *e = parg; | ||
1440 | unsigned int index = e->index; | ||
1441 | |||
1442 | if (index >= chan->tvnorm_num) | ||
1443 | return -EINVAL; | ||
1444 | v4l2_video_std_construct(e, chan->tvnorms[e->index].v4l2_id, | ||
1445 | chan->tvnorms[e->index].name); | ||
1446 | e->index = index; | ||
1447 | return 0; | ||
1448 | } | ||
1449 | |||
1450 | case VIDIOC_QUERYCAP: | ||
1451 | { | ||
1452 | static char driver[] = {'n', 'G', 'e', 'n', 'e', '\0'}; | ||
1453 | static char card[] = {'M', 'k', '4', 'x', 'x', '\0'}; | ||
1454 | struct v4l2_capability *cap = parg; | ||
1455 | |||
1456 | memset(cap, 0, sizeof(*cap)); | ||
1457 | if (dev->nr == 0) | ||
1458 | card[3] = '0'; | ||
1459 | else | ||
1460 | card[3] = '1'; | ||
1461 | if (chan->number) | ||
1462 | card[4] = 'a'; | ||
1463 | else | ||
1464 | card[4] = 'b'; | ||
1465 | strlcpy(cap->driver, driver, sizeof(cap->driver)); | ||
1466 | strlcpy(cap->card, card, sizeof(cap->card)); | ||
1467 | cap->bus_info[0] = 0; | ||
1468 | cap->version = KERNEL_VERSION(0, 8, 1); | ||
1469 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE| | ||
1470 | V4L2_CAP_TUNER|V4L2_CAP_AUDIO| | ||
1471 | V4L2_CAP_READWRITE|V4L2_CAP_STREAMING; | ||
1472 | return 0; | ||
1473 | } | ||
1474 | |||
1475 | case VIDIOC_ENUMINPUT: | ||
1476 | { | ||
1477 | static char *inputname[2] = { | ||
1478 | "AnalogTuner", | ||
1479 | "S-Video" | ||
1480 | }; | ||
1481 | |||
1482 | struct v4l2_input *i = parg; | ||
1483 | unsigned int index; | ||
1484 | index = i->index; | ||
1485 | |||
1486 | if (index > 1) | ||
1487 | return -EINVAL; | ||
1488 | |||
1489 | memset(i, 0, sizeof(*i)); | ||
1490 | i->index = index; | ||
1491 | strlcpy(i->name, inputname[index], sizeof(i->name)); | ||
1492 | |||
1493 | i->type = index ? V4L2_INPUT_TYPE_CAMERA : | ||
1494 | V4L2_INPUT_TYPE_TUNER; | ||
1495 | i->audioset = 0; | ||
1496 | i->tuner = 0; | ||
1497 | i->std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M; | ||
1498 | i->status = 0;/* V4L2_IN_ST_NO_H_LOCK; */ | ||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1502 | case VIDIOC_G_PARM: | ||
1503 | return -EINVAL; | ||
1504 | |||
1505 | case VIDIOC_S_PARM: | ||
1506 | return -EINVAL; | ||
1507 | |||
1508 | case VIDIOC_G_PRIORITY: | ||
1509 | { | ||
1510 | enum v4l2_priority *prio = parg; | ||
1511 | *prio = v4l2_prio_max(&chan->prio); | ||
1512 | return 0; | ||
1513 | } | ||
1514 | |||
1515 | case VIDIOC_S_PRIORITY: | ||
1516 | { | ||
1517 | enum v4l2_priority *prio = parg; | ||
1518 | return v4l2_prio_change(&chan->prio, &vopen->prio, *prio); | ||
1519 | return 0; | ||
1520 | } | ||
1521 | |||
1522 | case VIDIOC_CROPCAP: | ||
1523 | return -EINVAL; | ||
1524 | |||
1525 | case VIDIOC_G_CROP: | ||
1526 | return -EINVAL; | ||
1527 | |||
1528 | case VIDIOC_S_CROP: | ||
1529 | return -EINVAL; | ||
1530 | |||
1531 | case VIDIOC_G_FBUF: | ||
1532 | { | ||
1533 | struct v4l2_framebuffer *fb = parg; | ||
1534 | |||
1535 | *fb = chan->fbuf; | ||
1536 | fb->capability = 0; | ||
1537 | if (vopen->ovfmt) | ||
1538 | fb->fmt.pixelformat = vopen->ovfmt->fourcc; | ||
1539 | return 0; | ||
1540 | } | ||
1541 | |||
1542 | case VIDIOC_REQBUFS: | ||
1543 | return videobuf_reqbufs(ngene_queue(vopen), parg); | ||
1544 | |||
1545 | case VIDIOC_QUERYBUF: | ||
1546 | return videobuf_querybuf(ngene_queue(vopen), parg); | ||
1547 | |||
1548 | case VIDIOC_QBUF: | ||
1549 | return videobuf_qbuf(ngene_queue(vopen), parg); | ||
1550 | |||
1551 | case VIDIOC_DQBUF: | ||
1552 | return videobuf_dqbuf(ngene_queue(vopen), parg, | ||
1553 | file->f_flags & O_NONBLOCK); | ||
1554 | |||
1555 | case VIDIOC_S_FBUF: | ||
1556 | { | ||
1557 | /* ngene_analog_stop_feed(chan); */ | ||
1558 | struct v4l2_framebuffer *fb = parg; | ||
1559 | const struct ngene_format *fmt; | ||
1560 | |||
1561 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) | ||
1562 | return -EPERM; | ||
1563 | |||
1564 | /* check args */ | ||
1565 | fmt = ngene_formats; /*format_by_fourcc(fb->fmt.pixelformat);*/ | ||
1566 | if (NULL == fmt) | ||
1567 | return -EINVAL; | ||
1568 | |||
1569 | if (0 == (fmt->flags & 0x02 /*FORMAT_FLAGS_PACKED*/)) | ||
1570 | return -EINVAL; | ||
1571 | |||
1572 | mutex_lock(&vopen->vbuf_q.lock); | ||
1573 | retval = -EINVAL; | ||
1574 | |||
1575 | if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { | ||
1576 | int maxLinesPerField; | ||
1577 | |||
1578 | if (fb->fmt.width > | ||
1579 | chan->tvnorms[chan->tvnorm].swidth) | ||
1580 | goto vopen_unlock_and_return; | ||
1581 | maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; | ||
1582 | if (fb->fmt.height > maxLinesPerField) | ||
1583 | goto vopen_unlock_and_return; | ||
1584 | } | ||
1585 | |||
1586 | /* ok, accept it */ | ||
1587 | chan->fbuf.base = fb->base; | ||
1588 | chan->fbuf.fmt.width = fb->fmt.width; | ||
1589 | chan->fbuf.fmt.height = fb->fmt.height; | ||
1590 | if (0 != fb->fmt.bytesperline) | ||
1591 | chan->fbuf.fmt.bytesperline = fb->fmt.bytesperline; | ||
1592 | else | ||
1593 | chan->fbuf.fmt.bytesperline = | ||
1594 | chan->fbuf.fmt.width * fmt->depth / 8; | ||
1595 | |||
1596 | retval = 0; | ||
1597 | vopen->ovfmt = fmt; | ||
1598 | chan->init.ovfmt = fmt; | ||
1599 | |||
1600 | vopen_unlock_and_return: | ||
1601 | mutex_unlock(&vopen->vbuf_q.lock); | ||
1602 | return retval; | ||
1603 | |||
1604 | } | ||
1605 | |||
1606 | case VIDIOC_ENUMOUTPUT: | ||
1607 | return -EINVAL; | ||
1608 | |||
1609 | case VIDIOC_TRY_FMT: | ||
1610 | { | ||
1611 | struct v4l2_format *f = parg; | ||
1612 | return ngene_try_fmt(vopen, chan, f); | ||
1613 | |||
1614 | } | ||
1615 | |||
1616 | case VIDIOC_STREAMON: | ||
1617 | { | ||
1618 | int res = ngene_resource(vopen); | ||
1619 | if (!check_alloc_res(chan, vopen, res)) | ||
1620 | return -EBUSY; | ||
1621 | ngene_analog_start_feed(chan); | ||
1622 | return videobuf_streamon(ngene_queue(vopen)); | ||
1623 | } | ||
1624 | |||
1625 | case VIDIOC_STREAMOFF: | ||
1626 | { | ||
1627 | int res = ngene_resource(vopen); | ||
1628 | int retval = videobuf_streamoff(ngene_queue(vopen)); | ||
1629 | ngene_analog_stop_feed(chan); | ||
1630 | if (retval < 0) | ||
1631 | return retval; | ||
1632 | |||
1633 | free_res(chan, vopen, res); | ||
1634 | return 0; | ||
1635 | } | ||
1636 | |||
1637 | case VIDIOC_OVERLAY: | ||
1638 | return -EINVAL; | ||
1639 | |||
1640 | case VIDIOCGFBUF: | ||
1641 | { | ||
1642 | struct video_buffer *vb = parg; | ||
1643 | |||
1644 | memset(vb, 0, sizeof(*vb)); | ||
1645 | return 0; | ||
1646 | } | ||
1647 | |||
1648 | default: | ||
1649 | err = -EINVAL; | ||
1650 | break; | ||
1651 | } | ||
1652 | return err; | ||
1653 | } | ||
1654 | |||
1655 | /* | ||
1656 | static int vid_ioctl(struct inode *inode, struct file *file, | ||
1657 | unsigned int cmd, unsigned long arg) | ||
1658 | { | ||
1659 | return video_usercopy(inode, file, cmd, arg, vid_do_ioctl); | ||
1660 | } | ||
1661 | */ | ||
1662 | static unsigned int video_fix_command(unsigned int cmd) | ||
1663 | { | ||
1664 | switch (cmd) { | ||
1665 | } | ||
1666 | return cmd; | ||
1667 | } | ||
1668 | |||
1669 | static int vid_ioctl(struct inode *inode, struct file *file, | ||
1670 | unsigned int cmd, unsigned long arg) | ||
1671 | { | ||
1672 | void *parg = (void *)arg, *pbuf = NULL; | ||
1673 | char buf[64]; | ||
1674 | int res = -EFAULT; | ||
1675 | cmd = video_fix_command(cmd); | ||
1676 | |||
1677 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
1678 | parg = buf; | ||
1679 | if (_IOC_SIZE(cmd) > sizeof(buf)) { | ||
1680 | pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); | ||
1681 | if (!pbuf) | ||
1682 | return -ENOMEM; | ||
1683 | parg = pbuf; | ||
1684 | } | ||
1685 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
1686 | goto error; | ||
1687 | } | ||
1688 | res = vid_do_ioctl(inode, file, cmd, parg); | ||
1689 | if (res < 0) | ||
1690 | goto error; | ||
1691 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
1692 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
1693 | res = -EFAULT; | ||
1694 | error: | ||
1695 | kfree(pbuf); | ||
1696 | return res; | ||
1697 | } | ||
1698 | |||
1699 | static int ngene_mmap(struct file *file, struct vm_area_struct *vma) | ||
1700 | { | ||
1701 | struct ngene_vopen *vopen = file->private_data; | ||
1702 | return videobuf_mmap_mapper(ngene_queue(vopen), vma); | ||
1703 | } | ||
1704 | |||
1705 | #define MAGIC_BUFFER 0x20040302 | ||
1706 | void *my_videobuf_alloc(unsigned int size) | ||
1707 | { | ||
1708 | struct videobuf_buffer *vb; | ||
1709 | |||
1710 | vb = kmalloc(size, GFP_KERNEL); | ||
1711 | if (NULL != vb) { | ||
1712 | memset(vb, 0, size); | ||
1713 | videobuf_dma_init(&vb->dma); | ||
1714 | init_waitqueue_head(&vb->done); | ||
1715 | vb->magic = MAGIC_BUFFER; | ||
1716 | } | ||
1717 | return vb; | ||
1718 | } | ||
1719 | |||
1720 | static ssize_t driver_read(struct file *file, char *user, | ||
1721 | size_t count, loff_t *offset) | ||
1722 | { | ||
1723 | char __user *data = user; | ||
1724 | struct ngene_channel *chan; | ||
1725 | int retval = 0; | ||
1726 | struct videobuf_queue *q; | ||
1727 | struct ngene_vopen *vopen = file->private_data; | ||
1728 | int nonblocking = file->f_flags & O_NONBLOCK; | ||
1729 | enum v4l2_field field; | ||
1730 | unsigned long flags; | ||
1731 | unsigned size, nbufs, bytes; | ||
1732 | |||
1733 | if (!vopen) | ||
1734 | return 0; | ||
1735 | |||
1736 | chan = vopen->ch; | ||
1737 | q = &vopen->vbuf_q; | ||
1738 | |||
1739 | mutex_lock(&q->lock); | ||
1740 | nbufs = 1; | ||
1741 | size = 0; | ||
1742 | q->ops->buf_setup(q, &nbufs, &size); | ||
1743 | |||
1744 | if (NULL == q->read_buf) { | ||
1745 | /* need to capture a new frame */ | ||
1746 | retval = -ENOMEM; | ||
1747 | q->read_buf = my_videobuf_alloc(q->msize); | ||
1748 | if (NULL == q->read_buf) | ||
1749 | goto done; | ||
1750 | |||
1751 | q->read_buf->memory = V4L2_MEMORY_USERPTR; | ||
1752 | field = V4L2_FIELD_INTERLACED; | ||
1753 | retval = q->ops->buf_prepare(q, q->read_buf, field); | ||
1754 | if (0 != retval) { | ||
1755 | kfree(q->read_buf); | ||
1756 | q->read_buf = NULL; | ||
1757 | goto done; | ||
1758 | } | ||
1759 | |||
1760 | spin_lock_irqsave(q->irqlock, flags); | ||
1761 | q->ops->buf_queue(q, q->read_buf); | ||
1762 | spin_unlock_irqrestore(q->irqlock, flags); | ||
1763 | q->read_off = 0; | ||
1764 | } | ||
1765 | |||
1766 | ngene_analog_start_feed(chan); | ||
1767 | /* wait until capture is done */ | ||
1768 | retval = videobuf_waiton(q->read_buf, nonblocking, 1); | ||
1769 | if (0 != retval) | ||
1770 | goto done; | ||
1771 | videobuf_dma_sync(q, &q->read_buf->dma); | ||
1772 | |||
1773 | if (STATE_ERROR == q->read_buf->state) { | ||
1774 | /* catch I/O errors */ | ||
1775 | q->ops->buf_release(q, q->read_buf); | ||
1776 | kfree(q->read_buf); | ||
1777 | q->read_buf = NULL; | ||
1778 | retval = -EIO; | ||
1779 | goto done; | ||
1780 | } | ||
1781 | |||
1782 | /* copy to userspace */ | ||
1783 | bytes = count; | ||
1784 | if (bytes > q->read_buf->size - q->read_off) | ||
1785 | bytes = q->read_buf->size - q->read_off; | ||
1786 | retval = -EFAULT; | ||
1787 | |||
1788 | if (copy_to_user(data, q->read_buf->dma.vmalloc + q->read_off, bytes)) | ||
1789 | goto done; | ||
1790 | |||
1791 | retval = bytes; | ||
1792 | |||
1793 | q->read_off += bytes; | ||
1794 | if (q->read_off == q->read_buf->size) { | ||
1795 | /* all data copied, cleanup */ | ||
1796 | q->ops->buf_release(q, q->read_buf); | ||
1797 | kfree(q->read_buf); | ||
1798 | q->read_buf = NULL; | ||
1799 | } | ||
1800 | |||
1801 | done: | ||
1802 | mutex_unlock(&q->lock); | ||
1803 | |||
1804 | ngene_analog_stop_feed(chan); | ||
1805 | |||
1806 | return retval; | ||
1807 | } | ||
1808 | |||
1809 | static unsigned int ngene_poll(struct file *file, poll_table *wait) | ||
1810 | { | ||
1811 | struct ngene_vopen *vopen = file->private_data; | ||
1812 | struct ngene_buffer *buf; | ||
1813 | enum v4l2_field field; | ||
1814 | |||
1815 | if (check_res(vopen, RESOURCE_VIDEO)) { | ||
1816 | /* streaming capture */ | ||
1817 | if (list_empty(&vopen->vbuf_q.stream)) | ||
1818 | return POLLERR; | ||
1819 | buf = list_entry(vopen->vbuf_q.stream.next, | ||
1820 | struct ngene_buffer, vb.stream); | ||
1821 | } else { | ||
1822 | /* read() capture */ | ||
1823 | mutex_lock(&vopen->vbuf_q.lock); | ||
1824 | if (NULL == vopen->vbuf_q.read_buf) { | ||
1825 | /* need to capture a new frame */ | ||
1826 | if (locked_res(vopen->ch, RESOURCE_VIDEO)) { | ||
1827 | mutex_unlock(&vopen->vbuf_q.lock); | ||
1828 | return POLLERR; | ||
1829 | } | ||
1830 | vopen->vbuf_q.read_buf = | ||
1831 | videobuf_alloc(vopen->vbuf_q.msize); | ||
1832 | if (NULL == vopen->vbuf_q.read_buf) { | ||
1833 | mutex_unlock(&vopen->vbuf_q.lock); | ||
1834 | return POLLERR; | ||
1835 | } | ||
1836 | vopen->vbuf_q.read_buf->memory = V4L2_MEMORY_USERPTR; | ||
1837 | field = videobuf_next_field(&vopen->vbuf_q); | ||
1838 | if (0 != | ||
1839 | vopen->vbuf_q.ops-> | ||
1840 | buf_prepare(&vopen->vbuf_q, | ||
1841 | vopen->vbuf_q.read_buf, field)) { | ||
1842 | mutex_unlock(&vopen->vbuf_q.lock); | ||
1843 | return POLLERR; | ||
1844 | } | ||
1845 | vopen->vbuf_q.ops->buf_queue(&vopen->vbuf_q, | ||
1846 | vopen->vbuf_q.read_buf); | ||
1847 | vopen->vbuf_q.read_off = 0; | ||
1848 | } | ||
1849 | mutex_unlock(&vopen->vbuf_q.lock); | ||
1850 | buf = (struct ngene_buffer *)vopen->vbuf_q.read_buf; | ||
1851 | } | ||
1852 | |||
1853 | poll_wait(file, &buf->vb.done, wait); | ||
1854 | if (buf->vb.state == STATE_DONE || buf->vb.state == STATE_ERROR) | ||
1855 | return POLLIN | POLLRDNORM; | ||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | static const struct file_operations ngene_fops = { | ||
1860 | .owner = THIS_MODULE, | ||
1861 | .read = driver_read, | ||
1862 | .write = 0, | ||
1863 | .open = video_open, | ||
1864 | .release = video_close, | ||
1865 | .ioctl = vid_ioctl, | ||
1866 | .poll = ngene_poll, | ||
1867 | .mmap = ngene_mmap, | ||
1868 | }; | ||
1869 | |||
1870 | static struct video_device ngene_cinfo = { | ||
1871 | .name = "analog_Ngene", | ||
1872 | .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_SCALES, | ||
1873 | .fops = &ngene_fops, | ||
1874 | .minor = -1, | ||
1875 | }; | ||
1876 | |||
1877 | void ngene_v4l2_remove(struct ngene_channel *chan) | ||
1878 | { | ||
1879 | video_unregister_device(chan->v4l_dev); | ||
1880 | } | ||
1881 | |||
1882 | int ngene_v4l2_init(struct ngene_channel *chan) | ||
1883 | { | ||
1884 | int ret = 0; | ||
1885 | struct video_device *v_dev; | ||
1886 | |||
1887 | chan->evenbuffer = NULL; | ||
1888 | chan->dma_on = 0; | ||
1889 | |||
1890 | v_dev = video_device_alloc(); | ||
1891 | *v_dev = ngene_cinfo; | ||
1892 | /* v_dev->dev = &(chan->dev->pci_dev->dev); */ | ||
1893 | v_dev->release = video_device_release; | ||
1894 | v_dev->minor = -1; | ||
1895 | video_register_device(v_dev, VFL_TYPE_GRABBER, -1); | ||
1896 | snprintf(v_dev->name, sizeof(v_dev->name), "AnalognGene%d", | ||
1897 | v_dev->minor); | ||
1898 | chan->v4l_dev = v_dev; | ||
1899 | chan->minor = v_dev->minor; | ||
1900 | printk(KERN_INFO "nGene V4L2 device video%d registered.\n", | ||
1901 | v_dev->minor); | ||
1902 | |||
1903 | v_dev->dev = &chan->device; | ||
1904 | my_video_set_drvdata(chan->v4l_dev, chan); | ||
1905 | |||
1906 | v4l2_prio_init(&chan->prio); | ||
1907 | |||
1908 | if (chan->dev->card_info->io_type[chan->number] == NGENE_IO_HDTV) { | ||
1909 | chan->tvnorms = ngene_tvnorms_hd; | ||
1910 | chan->tvnorm_num = 1; | ||
1911 | } else { | ||
1912 | chan->tvnorms = ngene_tvnorms_sd; | ||
1913 | chan->tvnorm_num = NGENE_TVNORMS; | ||
1914 | } | ||
1915 | chan->tvnorm = 0; | ||
1916 | |||
1917 | spin_lock_init(&chan->s_lock); | ||
1918 | init_MUTEX(&chan->reslock); | ||
1919 | INIT_LIST_HEAD(&chan->capture); | ||
1920 | chan->users = 0; | ||
1921 | chan->videousers = 0; | ||
1922 | chan->init.ov.w.width = 384; | ||
1923 | chan->init.ov.w.height = 288; | ||
1924 | chan->init.fmt = ngene_formats; | ||
1925 | chan->init.width = 384; | ||
1926 | chan->init.height = 288; | ||
1927 | chan->tun_rdy = 0; | ||
1928 | chan->dec_rdy = 0; | ||
1929 | chan->tun_dec_rdy = 0; | ||
1930 | chan->lastbufferflag = -1; | ||
1931 | |||
1932 | if (chan->dev->card_info->avf[chan->number]) | ||
1933 | avf4910a_attach(&chan->i2c_adapter, | ||
1934 | chan->dev->card_info->avf[chan->number]); | ||
1935 | |||
1936 | return ret; | ||
1937 | } | ||
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h new file mode 100644 index 000000000000..9b48250fdbf8 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene.h | |||
@@ -0,0 +1,948 @@ | |||
1 | /* | ||
2 | * ngene.h: nGene PCIe bridge driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 only, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301, USA | ||
21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
22 | */ | ||
23 | |||
24 | #ifndef _NGENE_H_ | ||
25 | #define _NGENE_H_ | ||
26 | |||
27 | #define ONE_ADAPTER | ||
28 | #define NGENE_COMMAND_API | ||
29 | /*#define NGENE_V4L*/ | ||
30 | |||
31 | #include <linux/types.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/i2c.h> | ||
35 | #include <asm/dma.h> | ||
36 | #include <asm/scatterlist.h> | ||
37 | #include <sound/driver.h> | ||
38 | #include <sound/core.h> | ||
39 | #include <sound/initval.h> | ||
40 | #include <sound/control.h> | ||
41 | #include <sound/pcm.h> | ||
42 | #include <sound/pcm_params.h> | ||
43 | |||
44 | #include <linux/dvb/frontend.h> | ||
45 | #include <linux/dvb/ca.h> | ||
46 | #include <linux/dvb/video.h> | ||
47 | #include <linux/dvb/audio.h> | ||
48 | |||
49 | #include "dmxdev.h" | ||
50 | #include "dvbdev.h" | ||
51 | #include "dvb_demux.h" | ||
52 | #include "dvb_frontend.h" | ||
53 | #include "dvb_ringbuffer.h" | ||
54 | #include "drxd.h" | ||
55 | #include "drxh.h" | ||
56 | #include "xc3028.h" | ||
57 | #include "stb0899.h" | ||
58 | #include "stv0900.h" | ||
59 | #include "mt2060.h" | ||
60 | |||
61 | #ifdef NGENE_V4L | ||
62 | #include <media/v4l2-dev.h> | ||
63 | #include <media/videobuf-core.h> | ||
64 | #include <linux/videodev.h> | ||
65 | #endif | ||
66 | |||
67 | #define NGENE_VID 0x18c3 | ||
68 | #define NGENE_PID 0x0720 | ||
69 | |||
70 | #ifndef VIDEO_CAP_VC1 | ||
71 | #define VIDEO_CAP_AVC 128 | ||
72 | #define VIDEO_CAP_H264 128 | ||
73 | #define VIDEO_CAP_VC1 256 | ||
74 | #define VIDEO_CAP_WMV9 256 | ||
75 | #define VIDEO_CAP_MPEG4 512 | ||
76 | #endif | ||
77 | |||
78 | enum STREAM { | ||
79 | STREAM_VIDEOIN1 = 0, /* ITU656 or TS Input */ | ||
80 | STREAM_VIDEOIN2, | ||
81 | STREAM_AUDIOIN1, /* I2S or SPI Input */ | ||
82 | STREAM_AUDIOIN2, | ||
83 | STREAM_AUDIOOUT, | ||
84 | MAX_STREAM | ||
85 | }; | ||
86 | |||
87 | enum SMODE_BITS { | ||
88 | SMODE_AUDIO_SPDIF = 0x20, | ||
89 | SMODE_AVSYNC = 0x10, | ||
90 | SMODE_TRANSPORT_STREAM = 0x08, | ||
91 | SMODE_AUDIO_CAPTURE = 0x04, | ||
92 | SMODE_VBI_CAPTURE = 0x02, | ||
93 | SMODE_VIDEO_CAPTURE = 0x01 | ||
94 | }; | ||
95 | |||
96 | enum STREAM_FLAG_BITS { | ||
97 | SFLAG_CHROMA_FORMAT_2COMP = 0x01, /* Chroma Format : 2's complement */ | ||
98 | SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */ | ||
99 | SFLAG_ORDER_LUMA_CHROMA = 0x02, /* Byte order: Y,Cb,Y,Cr */ | ||
100 | SFLAG_ORDER_CHROMA_LUMA = 0x00, /* Byte order: Cb,Y,Cr,Y */ | ||
101 | SFLAG_COLORBAR = 0x04, /* Select colorbar */ | ||
102 | }; | ||
103 | |||
104 | #define PROGRAM_ROM 0x0000 | ||
105 | #define PROGRAM_SRAM 0x1000 | ||
106 | #define PERIPHERALS0 0x8000 | ||
107 | #define PERIPHERALS1 0x9000 | ||
108 | #define SHARED_BUFFER 0xC000 | ||
109 | |||
110 | #define HOST_TO_NGENE (SHARED_BUFFER+0x0000) | ||
111 | #define NGENE_TO_HOST (SHARED_BUFFER+0x0100) | ||
112 | #define NGENE_COMMAND (SHARED_BUFFER+0x0200) | ||
113 | #define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204) | ||
114 | #define NGENE_STATUS (SHARED_BUFFER+0x0208) | ||
115 | #define NGENE_STATUS_HI (SHARED_BUFFER+0x020C) | ||
116 | #define NGENE_EVENT (SHARED_BUFFER+0x0210) | ||
117 | #define NGENE_EVENT_HI (SHARED_BUFFER+0x0214) | ||
118 | #define VARIABLES (SHARED_BUFFER+0x0210) | ||
119 | |||
120 | #define NGENE_INT_COUNTS (SHARED_BUFFER+0x0260) | ||
121 | #define NGENE_INT_ENABLE (SHARED_BUFFER+0x0264) | ||
122 | #define NGENE_VBI_LINE_COUNT (SHARED_BUFFER+0x0268) | ||
123 | |||
124 | #define BUFFER_GP_XMIT (SHARED_BUFFER+0x0800) | ||
125 | #define BUFFER_GP_RECV (SHARED_BUFFER+0x0900) | ||
126 | #define EEPROM_AREA (SHARED_BUFFER+0x0A00) | ||
127 | |||
128 | #define SG_V_IN_1 (SHARED_BUFFER+0x0A80) | ||
129 | #define SG_VBI_1 (SHARED_BUFFER+0x0B00) | ||
130 | #define SG_A_IN_1 (SHARED_BUFFER+0x0B80) | ||
131 | #define SG_V_IN_2 (SHARED_BUFFER+0x0C00) | ||
132 | #define SG_VBI_2 (SHARED_BUFFER+0x0C80) | ||
133 | #define SG_A_IN_2 (SHARED_BUFFER+0x0D00) | ||
134 | #define SG_V_OUT (SHARED_BUFFER+0x0D80) | ||
135 | #define SG_A_OUT2 (SHARED_BUFFER+0x0E00) | ||
136 | |||
137 | #define DATA_A_IN_1 (SHARED_BUFFER+0x0E80) | ||
138 | #define DATA_A_IN_2 (SHARED_BUFFER+0x0F00) | ||
139 | #define DATA_A_OUT (SHARED_BUFFER+0x0F80) | ||
140 | #define DATA_V_IN_1 (SHARED_BUFFER+0x1000) | ||
141 | #define DATA_V_IN_2 (SHARED_BUFFER+0x2000) | ||
142 | #define DATA_V_OUT (SHARED_BUFFER+0x3000) | ||
143 | |||
144 | #define DATA_FIFO_AREA (SHARED_BUFFER+0x1000) | ||
145 | |||
146 | #define TIMESTAMPS 0xA000 | ||
147 | #define SCRATCHPAD 0xA080 | ||
148 | #define FORCE_INT 0xA088 | ||
149 | #define FORCE_NMI 0xA090 | ||
150 | #define INT_STATUS 0xA0A0 | ||
151 | |||
152 | #define DEV_VER 0x9004 | ||
153 | |||
154 | #define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF) | ||
155 | |||
156 | struct SG_ADDR { | ||
157 | u64 start; | ||
158 | u64 curr; | ||
159 | u16 curr_ptr; | ||
160 | u16 elements; | ||
161 | u32 pad[3]; | ||
162 | } __attribute__ ((__packed__)); | ||
163 | |||
164 | struct SHARED_MEMORY { | ||
165 | /* C000 */ | ||
166 | u32 HostToNgene[64]; | ||
167 | |||
168 | /* C100 */ | ||
169 | u32 NgeneToHost[64]; | ||
170 | |||
171 | /* C200 */ | ||
172 | u64 NgeneCommand; | ||
173 | u64 NgeneStatus; | ||
174 | u64 NgeneEvent; | ||
175 | |||
176 | /* C210 */ | ||
177 | u8 pad1[0xc260 - 0xc218]; | ||
178 | |||
179 | /* C260 */ | ||
180 | u32 IntCounts; | ||
181 | u32 IntEnable; | ||
182 | |||
183 | /* C268 */ | ||
184 | u8 pad2[0xd000 - 0xc268]; | ||
185 | |||
186 | } __attribute__ ((__packed__)); | ||
187 | |||
188 | struct BUFFER_STREAM_RESULTS { | ||
189 | u32 Clock; /* Stream time in 100ns units */ | ||
190 | u16 RemainingLines; /* Remaining lines in this field. | ||
191 | 0 for complete field */ | ||
192 | u8 FieldCount; /* Video field number */ | ||
193 | u8 Flags; /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow, | ||
194 | Bit 0 = FieldID */ | ||
195 | u16 BlockCount; /* Audio block count (unused) */ | ||
196 | u8 Reserved[2]; | ||
197 | u32 DTOUpdate; | ||
198 | } __attribute__ ((__packed__)); | ||
199 | |||
200 | struct HW_SCATTER_GATHER_ELEMENT { | ||
201 | u64 Address; | ||
202 | u32 Length; | ||
203 | u32 Reserved; | ||
204 | } __attribute__ ((__packed__)); | ||
205 | |||
206 | struct BUFFER_HEADER { | ||
207 | u64 Next; | ||
208 | struct BUFFER_STREAM_RESULTS SR; | ||
209 | |||
210 | u32 Number_of_entries_1; | ||
211 | u32 Reserved5; | ||
212 | u64 Address_of_first_entry_1; | ||
213 | |||
214 | u32 Number_of_entries_2; | ||
215 | u32 Reserved7; | ||
216 | u64 Address_of_first_entry_2; | ||
217 | } __attribute__ ((__packed__)); | ||
218 | |||
219 | struct EVENT_BUFFER { | ||
220 | u32 TimeStamp; | ||
221 | u8 GPIOStatus; | ||
222 | u8 UARTStatus; | ||
223 | u8 RXCharacter; | ||
224 | u8 EventStatus; | ||
225 | u32 Reserved[2]; | ||
226 | } __attribute__ ((__packed__)); | ||
227 | |||
228 | typedef struct EVENT_BUFFER *PEVENT_BUFFER; | ||
229 | |||
230 | /* Firmware commands. */ | ||
231 | |||
232 | enum OPCODES { | ||
233 | CMD_NOP = 0, | ||
234 | CMD_FWLOAD_PREPARE = 0x01, | ||
235 | CMD_FWLOAD_FINISH = 0x02, | ||
236 | CMD_I2C_READ = 0x03, | ||
237 | CMD_I2C_WRITE = 0x04, | ||
238 | |||
239 | CMD_I2C_WRITE_NOSTOP = 0x05, | ||
240 | CMD_I2C_CONTINUE_WRITE = 0x06, | ||
241 | CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07, | ||
242 | |||
243 | CMD_DEBUG_OUTPUT = 0x09, | ||
244 | |||
245 | CMD_CONTROL = 0x10, | ||
246 | CMD_CONFIGURE_BUFFER = 0x11, | ||
247 | CMD_CONFIGURE_FREE_BUFFER = 0x12, | ||
248 | |||
249 | CMD_SPI_READ = 0x13, | ||
250 | CMD_SPI_WRITE = 0x14, | ||
251 | |||
252 | CMD_MEM_READ = 0x20, | ||
253 | CMD_MEM_WRITE = 0x21, | ||
254 | CMD_SFR_READ = 0x22, | ||
255 | CMD_SFR_WRITE = 0x23, | ||
256 | CMD_IRAM_READ = 0x24, | ||
257 | CMD_IRAM_WRITE = 0x25, | ||
258 | CMD_SET_GPIO_PIN = 0x26, | ||
259 | CMD_SET_GPIO_INT = 0x27, | ||
260 | CMD_CONFIGURE_UART = 0x28, | ||
261 | CMD_WRITE_UART = 0x29, | ||
262 | MAX_CMD | ||
263 | }; | ||
264 | |||
265 | enum RESPONSES { | ||
266 | OK = 0, | ||
267 | ERROR = 1 | ||
268 | }; | ||
269 | |||
270 | struct FW_HEADER { | ||
271 | u8 Opcode; | ||
272 | u8 Length; | ||
273 | } __attribute__ ((__packed__)); | ||
274 | |||
275 | struct FW_I2C_WRITE { | ||
276 | struct FW_HEADER hdr; | ||
277 | u8 Device; | ||
278 | u8 Data[250]; | ||
279 | } __attribute__ ((__packed__)); | ||
280 | |||
281 | struct FW_I2C_CONTINUE_WRITE { | ||
282 | struct FW_HEADER hdr; | ||
283 | u8 Data[250]; | ||
284 | } __attribute__ ((__packed__)); | ||
285 | |||
286 | struct FW_I2C_READ { | ||
287 | struct FW_HEADER hdr; | ||
288 | u8 Device; | ||
289 | u8 Data[252]; /* followed by two bytes of read data count */ | ||
290 | } __attribute__ ((__packed__)); | ||
291 | |||
292 | struct FW_SPI_WRITE { | ||
293 | struct FW_HEADER hdr; | ||
294 | u8 ModeSelect; | ||
295 | u8 Data[250]; | ||
296 | } __attribute__ ((__packed__)); | ||
297 | |||
298 | struct FW_SPI_READ { | ||
299 | struct FW_HEADER hdr; | ||
300 | u8 ModeSelect; | ||
301 | u8 Data[252]; /* followed by two bytes of read data count */ | ||
302 | } __attribute__ ((__packed__)); | ||
303 | |||
304 | struct FW_FWLOAD_PREPARE { | ||
305 | struct FW_HEADER hdr; | ||
306 | } __attribute__ ((__packed__)); | ||
307 | |||
308 | struct FW_FWLOAD_FINISH { | ||
309 | struct FW_HEADER hdr; | ||
310 | u16 Address; /* address of final block */ | ||
311 | u16 Length; | ||
312 | } __attribute__ ((__packed__)); | ||
313 | |||
314 | /* | ||
315 | * Meaning of FW_STREAM_CONTROL::Mode bits: | ||
316 | * Bit 7: Loopback PEXin to PEXout using TVOut channel | ||
317 | * Bit 6: AVLOOP | ||
318 | * Bit 5: Audio select; 0=I2S, 1=SPDIF | ||
319 | * Bit 4: AVSYNC | ||
320 | * Bit 3: Enable transport stream | ||
321 | * Bit 2: Enable audio capture | ||
322 | * Bit 1: Enable ITU-Video VBI capture | ||
323 | * Bit 0: Enable ITU-Video capture | ||
324 | * | ||
325 | * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL) | ||
326 | * Bit 7: continuous capture | ||
327 | * Bit 6: capture one field | ||
328 | * Bit 5: capture one frame | ||
329 | * Bit 4: unused | ||
330 | * Bit 3: starting field; 0=odd, 1=even | ||
331 | * Bit 2: sample size; 0=8-bit, 1=10-bit | ||
332 | * Bit 1: data format; 0=UYVY, 1=YUY2 | ||
333 | * Bit 0: resets buffer pointers | ||
334 | */ | ||
335 | |||
336 | enum FSC_MODE_BITS { | ||
337 | SMODE_LOOPBACK = 0x80, | ||
338 | SMODE_AVLOOP = 0x40, | ||
339 | _SMODE_AUDIO_SPDIF = 0x20, | ||
340 | _SMODE_AVSYNC = 0x10, | ||
341 | _SMODE_TRANSPORT_STREAM = 0x08, | ||
342 | _SMODE_AUDIO_CAPTURE = 0x04, | ||
343 | _SMODE_VBI_CAPTURE = 0x02, | ||
344 | _SMODE_VIDEO_CAPTURE = 0x01 | ||
345 | }; | ||
346 | |||
347 | |||
348 | /* Meaning of FW_STREAM_CONTROL::Stream bits: | ||
349 | * Bit 3: Audio sample count: 0 = relative, 1 = absolute | ||
350 | * Bit 2: color bar select; 1=color bars, 0=CV3 decoder | ||
351 | * Bits 1-0: stream select, UVI1, UVI2, TVOUT | ||
352 | */ | ||
353 | |||
354 | struct FW_STREAM_CONTROL { | ||
355 | struct FW_HEADER hdr; | ||
356 | u8 Stream; /* Stream number (UVI1, UVI2, TVOUT) */ | ||
357 | u8 Control; /* Value written to UVI1_CTL */ | ||
358 | u8 Mode; /* Controls clock source */ | ||
359 | u8 SetupDataLen; /* Length of setup data, MSB=1 write | ||
360 | backwards */ | ||
361 | u16 CaptureBlockCount; /* Blocks (a 256 Bytes) to capture per buffer | ||
362 | for TS and Audio */ | ||
363 | u64 Buffer_Address; /* Address of first buffer header */ | ||
364 | u16 BytesPerVideoLine; | ||
365 | u16 MaxLinesPerField; | ||
366 | u16 MinLinesPerField; | ||
367 | u16 Reserved_1; | ||
368 | u16 BytesPerVBILine; | ||
369 | u16 MaxVBILinesPerField; | ||
370 | u16 MinVBILinesPerField; | ||
371 | u16 SetupDataAddr; /* ngene relative address of setup data */ | ||
372 | u8 SetupData[32]; /* setup data */ | ||
373 | } __attribute__((__packed__)); | ||
374 | |||
375 | #define AUDIO_BLOCK_SIZE 256 | ||
376 | #define TS_BLOCK_SIZE 256 | ||
377 | |||
378 | struct FW_MEM_READ { | ||
379 | struct FW_HEADER hdr; | ||
380 | u16 address; | ||
381 | } __attribute__ ((__packed__)); | ||
382 | |||
383 | struct FW_MEM_WRITE { | ||
384 | struct FW_HEADER hdr; | ||
385 | u16 address; | ||
386 | u8 data; | ||
387 | } __attribute__ ((__packed__)); | ||
388 | |||
389 | struct FW_SFR_IRAM_READ { | ||
390 | struct FW_HEADER hdr; | ||
391 | u8 address; | ||
392 | } __attribute__ ((__packed__)); | ||
393 | |||
394 | struct FW_SFR_IRAM_WRITE { | ||
395 | struct FW_HEADER hdr; | ||
396 | u8 address; | ||
397 | u8 data; | ||
398 | } __attribute__ ((__packed__)); | ||
399 | |||
400 | struct FW_SET_GPIO_PIN { | ||
401 | struct FW_HEADER hdr; | ||
402 | u8 select; | ||
403 | } __attribute__ ((__packed__)); | ||
404 | |||
405 | struct FW_SET_GPIO_INT { | ||
406 | struct FW_HEADER hdr; | ||
407 | u8 select; | ||
408 | } __attribute__ ((__packed__)); | ||
409 | |||
410 | struct FW_SET_DEBUGMODE { | ||
411 | struct FW_HEADER hdr; | ||
412 | u8 debug_flags; | ||
413 | } __attribute__ ((__packed__)); | ||
414 | |||
415 | struct FW_CONFIGURE_BUFFERS { | ||
416 | struct FW_HEADER hdr; | ||
417 | u8 config; | ||
418 | } __attribute__ ((__packed__)); | ||
419 | |||
420 | enum _BUFFER_CONFIGS { | ||
421 | /* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2 (standard usage) */ | ||
422 | BUFFER_CONFIG_4422 = 0, | ||
423 | /* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2 (4x TS input usage) */ | ||
424 | BUFFER_CONFIG_3333 = 1, | ||
425 | /* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut (HDTV decoder usage) */ | ||
426 | BUFFER_CONFIG_8022 = 2, | ||
427 | BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */ | ||
428 | }; | ||
429 | |||
430 | struct FW_CONFIGURE_FREE_BUFFERS { | ||
431 | struct FW_HEADER hdr; | ||
432 | u8 UVI1_BufferLength; | ||
433 | u8 UVI2_BufferLength; | ||
434 | u8 TVO_BufferLength; | ||
435 | u8 AUD1_BufferLength; | ||
436 | u8 AUD2_BufferLength; | ||
437 | u8 TVA_BufferLength; | ||
438 | } __attribute__ ((__packed__)); | ||
439 | |||
440 | struct FW_CONFIGURE_UART { | ||
441 | struct FW_HEADER hdr; | ||
442 | u8 UartControl; | ||
443 | } __attribute__ ((__packed__)); | ||
444 | |||
445 | enum _UART_CONFIG { | ||
446 | _UART_BAUDRATE_19200 = 0, | ||
447 | _UART_BAUDRATE_9600 = 1, | ||
448 | _UART_BAUDRATE_4800 = 2, | ||
449 | _UART_BAUDRATE_2400 = 3, | ||
450 | _UART_RX_ENABLE = 0x40, | ||
451 | _UART_TX_ENABLE = 0x80, | ||
452 | }; | ||
453 | |||
454 | struct FW_WRITE_UART { | ||
455 | struct FW_HEADER hdr; | ||
456 | u8 Data[252]; | ||
457 | } __attribute__ ((__packed__)); | ||
458 | |||
459 | |||
460 | struct ngene_command { | ||
461 | u32 in_len; | ||
462 | u32 out_len; | ||
463 | union { | ||
464 | u32 raw[64]; | ||
465 | u8 raw8[256]; | ||
466 | struct FW_HEADER hdr; | ||
467 | struct FW_I2C_WRITE I2CWrite; | ||
468 | struct FW_I2C_CONTINUE_WRITE I2CContinueWrite; | ||
469 | struct FW_I2C_READ I2CRead; | ||
470 | struct FW_STREAM_CONTROL StreamControl; | ||
471 | struct FW_FWLOAD_PREPARE FWLoadPrepare; | ||
472 | struct FW_FWLOAD_FINISH FWLoadFinish; | ||
473 | struct FW_MEM_READ MemoryRead; | ||
474 | struct FW_MEM_WRITE MemoryWrite; | ||
475 | struct FW_SFR_IRAM_READ SfrIramRead; | ||
476 | struct FW_SFR_IRAM_WRITE SfrIramWrite; | ||
477 | struct FW_SPI_WRITE SPIWrite; | ||
478 | struct FW_SPI_READ SPIRead; | ||
479 | struct FW_SET_GPIO_PIN SetGpioPin; | ||
480 | struct FW_SET_GPIO_INT SetGpioInt; | ||
481 | struct FW_SET_DEBUGMODE SetDebugMode; | ||
482 | struct FW_CONFIGURE_BUFFERS ConfigureBuffers; | ||
483 | struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers; | ||
484 | struct FW_CONFIGURE_UART ConfigureUart; | ||
485 | struct FW_WRITE_UART WriteUart; | ||
486 | } cmd; | ||
487 | } __attribute__ ((__packed__)); | ||
488 | |||
489 | #define NGENE_INTERFACE_VERSION 0x103 | ||
490 | #define MAX_VIDEO_BUFFER_SIZE (417792) /* 288*1440 rounded up to next page */ | ||
491 | #define MAX_AUDIO_BUFFER_SIZE (8192) /* Gives room for about 23msec@48KHz */ | ||
492 | #define MAX_VBI_BUFFER_SIZE (28672) /* 1144*18 rounded up to next page */ | ||
493 | #define MAX_TS_BUFFER_SIZE (98304) /* 512*188 rounded up to next page */ | ||
494 | #define MAX_HDTV_BUFFER_SIZE (2080768) /* 541*1920*2 rounded up to next page | ||
495 | Max: (1920x1080i60) */ | ||
496 | |||
497 | #define OVERFLOW_BUFFER_SIZE (8192) | ||
498 | |||
499 | #define RING_SIZE_VIDEO 4 | ||
500 | #define RING_SIZE_AUDIO 8 | ||
501 | #define RING_SIZE_TS 8 | ||
502 | |||
503 | #define NUM_SCATTER_GATHER_ENTRIES 8 | ||
504 | |||
505 | #define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \ | ||
506 | RING_SIZE_VIDEO * 2) + \ | ||
507 | (MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \ | ||
508 | (MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \ | ||
509 | (RING_SIZE_VIDEO * PAGE_SIZE * 2) + \ | ||
510 | (RING_SIZE_AUDIO * PAGE_SIZE * 2) + \ | ||
511 | (RING_SIZE_TS * PAGE_SIZE * 4) + \ | ||
512 | 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE) | ||
513 | |||
514 | #define EVENT_QUEUE_SIZE 16 | ||
515 | |||
516 | typedef struct HW_SCATTER_GATHER_ELEMENT *PHW_SCATTER_GATHER_ELEMENT; | ||
517 | typedef struct FWRB *PFWRB; | ||
518 | |||
519 | /* Gathers the current state of a single channel. */ | ||
520 | |||
521 | struct SBufferHeader { | ||
522 | struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */ | ||
523 | struct SBufferHeader *Next; | ||
524 | void *Buffer1; | ||
525 | PHW_SCATTER_GATHER_ELEMENT scList1; | ||
526 | void *Buffer2; | ||
527 | PHW_SCATTER_GATHER_ELEMENT scList2; | ||
528 | }; | ||
529 | |||
530 | /* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */ | ||
531 | #define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63) | ||
532 | |||
533 | enum HWSTATE { | ||
534 | HWSTATE_STOP, | ||
535 | HWSTATE_STARTUP, | ||
536 | HWSTATE_RUN, | ||
537 | HWSTATE_PAUSE, | ||
538 | }; | ||
539 | |||
540 | enum KSSTATE { | ||
541 | KSSTATE_STOP, | ||
542 | KSSTATE_ACQUIRE, | ||
543 | KSSTATE_PAUSE, | ||
544 | KSSTATE_RUN, | ||
545 | }; | ||
546 | |||
547 | struct SRingBufferDescriptor { | ||
548 | struct SBufferHeader *Head; /* Points to first buffer in ring buffer | ||
549 | structure*/ | ||
550 | u64 PAHead; /* Physical address of first buffer */ | ||
551 | u32 MemSize; /* Memory size of allocated ring buffers | ||
552 | (needed for freeing) */ | ||
553 | u32 NumBuffers; /* Number of buffers in the ring */ | ||
554 | u32 Buffer1Length; /* Allocated length of Buffer 1 */ | ||
555 | u32 Buffer2Length; /* Allocated length of Buffer 2 */ | ||
556 | void *SCListMem; /* Memory to hold scatter gather lists for this | ||
557 | ring */ | ||
558 | u64 PASCListMem; /* Physical address .. */ | ||
559 | u32 SCListMemSize; /* Size of this memory */ | ||
560 | }; | ||
561 | |||
562 | enum STREAMMODEFLAGS { | ||
563 | StreamMode_NONE = 0, /* Stream not used */ | ||
564 | StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */ | ||
565 | StreamMode_TSIN = 2, /* Transport stream input (all) */ | ||
566 | StreamMode_HDTV = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60 | ||
567 | (only stream 0) */ | ||
568 | StreamMode_TSOUT = 8, /* Transport stream output (only stream 3) */ | ||
569 | }; | ||
570 | |||
571 | |||
572 | enum BufferExchangeFlags { | ||
573 | BEF_EVEN_FIELD = 0x00000001, | ||
574 | BEF_CONTINUATION = 0x00000002, | ||
575 | BEF_MORE_DATA = 0x00000004, | ||
576 | BEF_OVERFLOW = 0x00000008, | ||
577 | DF_SWAP32 = 0x00010000, | ||
578 | }; | ||
579 | |||
580 | typedef void *(IBufferExchange)(void *, void *, u32, u32, u32); | ||
581 | |||
582 | typedef struct { | ||
583 | IBufferExchange *pExchange; | ||
584 | IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */ | ||
585 | u8 Stream; | ||
586 | u8 Flags; | ||
587 | u8 Mode; | ||
588 | u8 Reserved; | ||
589 | u16 nLinesVideo; | ||
590 | u16 nBytesPerLineVideo; | ||
591 | u16 nLinesVBI; | ||
592 | u16 nBytesPerLineVBI; | ||
593 | u32 CaptureLength; /* Used for audio and transport stream */ | ||
594 | } MICI_STREAMINFO, *PMICI_STREAMINFO; | ||
595 | |||
596 | /****************************************************************************/ | ||
597 | /* STRUCTS ******************************************************************/ | ||
598 | /****************************************************************************/ | ||
599 | |||
600 | /* sound hardware definition */ | ||
601 | #define MIXER_ADDR_TVTUNER 0 | ||
602 | #define MIXER_ADDR_LAST 0 | ||
603 | |||
604 | struct ngene_channel; | ||
605 | |||
606 | /*struct sound chip*/ | ||
607 | |||
608 | struct mychip { | ||
609 | struct ngene_channel *chan; | ||
610 | struct snd_card *card; | ||
611 | struct pci_dev *pci; | ||
612 | struct snd_pcm_substream *substream; | ||
613 | struct snd_pcm *pcm; | ||
614 | unsigned long port; | ||
615 | int irq; | ||
616 | spinlock_t mixer_lock; | ||
617 | spinlock_t lock; | ||
618 | int mixer_volume[MIXER_ADDR_LAST + 1][2]; | ||
619 | int capture_source[MIXER_ADDR_LAST + 1][2]; | ||
620 | }; | ||
621 | |||
622 | #ifdef NGENE_V4L | ||
623 | struct ngene_overlay { | ||
624 | int tvnorm; | ||
625 | struct v4l2_rect w; | ||
626 | enum v4l2_field field; | ||
627 | struct v4l2_clip *clips; | ||
628 | int nclips; | ||
629 | int setup_ok; | ||
630 | }; | ||
631 | |||
632 | struct ngene_tvnorm { | ||
633 | int v4l2_id; | ||
634 | char *name; | ||
635 | u16 swidth, sheight; /* scaled standard width, height */ | ||
636 | int tuner_norm; | ||
637 | int soundstd; | ||
638 | }; | ||
639 | |||
640 | struct ngene_vopen { | ||
641 | struct ngene_channel *ch; | ||
642 | enum v4l2_priority prio; | ||
643 | int width; | ||
644 | int height; | ||
645 | int depth; | ||
646 | struct videobuf_queue vbuf_q; | ||
647 | struct videobuf_queue vbi; | ||
648 | int fourcc; | ||
649 | int picxcount; | ||
650 | int resources; | ||
651 | enum v4l2_buf_type type; | ||
652 | const struct ngene_format *fmt; | ||
653 | |||
654 | const struct ngene_format *ovfmt; | ||
655 | struct ngene_overlay ov; | ||
656 | }; | ||
657 | #endif | ||
658 | |||
659 | struct ngene_channel { | ||
660 | struct device device; | ||
661 | struct i2c_adapter i2c_adapter; | ||
662 | |||
663 | struct ngene *dev; | ||
664 | int number; | ||
665 | int type; | ||
666 | int mode; | ||
667 | |||
668 | struct dvb_frontend *fe; | ||
669 | struct dmxdev dmxdev; | ||
670 | struct dvb_demux demux; | ||
671 | struct dmx_frontend hw_frontend; | ||
672 | struct dmx_frontend mem_frontend; | ||
673 | int users; | ||
674 | struct video_device *v4l_dev; | ||
675 | #ifndef ONE_ADAPTER | ||
676 | struct dvb_adapter dvb_adapter; | ||
677 | #endif | ||
678 | struct dvb_device *command_dev; | ||
679 | struct dvb_device *audio_dev; | ||
680 | struct dvb_device *video_dev; | ||
681 | struct tasklet_struct demux_tasklet; | ||
682 | |||
683 | struct SBufferHeader *nextBuffer; | ||
684 | enum KSSTATE State; | ||
685 | enum HWSTATE HWState; | ||
686 | u8 Stream; | ||
687 | u8 Flags; | ||
688 | u8 Mode; | ||
689 | IBufferExchange *pBufferExchange; | ||
690 | IBufferExchange *pBufferExchange2; | ||
691 | |||
692 | spinlock_t state_lock; | ||
693 | u16 nLines; | ||
694 | u16 nBytesPerLine; | ||
695 | u16 nVBILines; | ||
696 | u16 nBytesPerVBILine; | ||
697 | u16 itumode; | ||
698 | u32 Capture1Length; | ||
699 | u32 Capture2Length; | ||
700 | struct SRingBufferDescriptor RingBuffer; | ||
701 | struct SRingBufferDescriptor TSRingBuffer; | ||
702 | struct SRingBufferDescriptor TSIdleBuffer; | ||
703 | |||
704 | u32 DataFormatFlags; | ||
705 | |||
706 | int AudioDTOUpdated; | ||
707 | u32 AudioDTOValue; | ||
708 | |||
709 | int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t); | ||
710 | u8 lnbh; | ||
711 | |||
712 | /* stuff from analog driver */ | ||
713 | |||
714 | int minor; | ||
715 | struct mychip *mychip; | ||
716 | struct snd_card *soundcard; | ||
717 | u8 *evenbuffer; | ||
718 | u8 *soundbuffer; | ||
719 | u8 dma_on; | ||
720 | int soundstreamon; | ||
721 | int audiomute; | ||
722 | int soundbuffisallocated; | ||
723 | int sndbuffflag; | ||
724 | int tun_rdy; | ||
725 | int dec_rdy; | ||
726 | int tun_dec_rdy; | ||
727 | int lastbufferflag; | ||
728 | |||
729 | struct ngene_tvnorm *tvnorms; | ||
730 | int tvnorm_num; | ||
731 | int tvnorm; | ||
732 | |||
733 | #ifdef NGENE_V4L | ||
734 | int videousers; | ||
735 | struct v4l2_prio_state prio; | ||
736 | struct ngene_vopen init; | ||
737 | int resources; | ||
738 | struct v4l2_framebuffer fbuf; | ||
739 | struct ngene_buffer *screen; /* overlay */ | ||
740 | struct list_head capture; /* video capture queue */ | ||
741 | spinlock_t s_lock; | ||
742 | struct semaphore reslock; | ||
743 | #endif | ||
744 | |||
745 | int running; | ||
746 | }; | ||
747 | |||
748 | struct ngene; | ||
749 | |||
750 | typedef void (rx_cb_t)(struct ngene *, u32, u8); | ||
751 | typedef void (tx_cb_t)(struct ngene *, u32); | ||
752 | |||
753 | struct ngene { | ||
754 | int nr; | ||
755 | struct pci_dev *pci_dev; | ||
756 | unsigned char *iomem; | ||
757 | |||
758 | #ifdef ONE_ADAPTER | ||
759 | struct dvb_adapter dvb_adapter; | ||
760 | #endif | ||
761 | /*struct i2c_adapter i2c_adapter;*/ | ||
762 | |||
763 | u32 device_version; | ||
764 | u32 fw_interface_version; | ||
765 | u32 icounts; | ||
766 | |||
767 | u8 *CmdDoneByte; | ||
768 | int BootFirmware; | ||
769 | void *OverflowBuffer; | ||
770 | dma_addr_t PAOverflowBuffer; | ||
771 | void *FWInterfaceBuffer; | ||
772 | dma_addr_t PAFWInterfaceBuffer; | ||
773 | u8 *ngenetohost; | ||
774 | u8 *hosttongene; | ||
775 | |||
776 | struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE]; | ||
777 | int EventQueueOverflowCount; | ||
778 | int EventQueueOverflowFlag; | ||
779 | struct tasklet_struct event_tasklet; | ||
780 | struct EVENT_BUFFER *EventBuffer; | ||
781 | int EventQueueWriteIndex; | ||
782 | int EventQueueReadIndex; | ||
783 | |||
784 | wait_queue_head_t cmd_wq; | ||
785 | int cmd_done; | ||
786 | struct semaphore cmd_mutex; | ||
787 | struct semaphore stream_mutex; | ||
788 | struct semaphore pll_mutex; | ||
789 | struct semaphore i2c_switch_mutex; | ||
790 | int i2c_current_channel; | ||
791 | int i2c_current_bus; | ||
792 | spinlock_t cmd_lock; | ||
793 | |||
794 | struct ngene_channel channel[MAX_STREAM]; | ||
795 | |||
796 | struct ngene_info *card_info; | ||
797 | |||
798 | tx_cb_t *TxEventNotify; | ||
799 | rx_cb_t *RxEventNotify; | ||
800 | int tx_busy; | ||
801 | wait_queue_head_t tx_wq; | ||
802 | wait_queue_head_t rx_wq; | ||
803 | #define UART_RBUF_LEN 4096 | ||
804 | u8 uart_rbuf[UART_RBUF_LEN]; | ||
805 | int uart_rp, uart_wp; | ||
806 | |||
807 | u8 *tsout_buf; | ||
808 | #define TSOUT_BUF_SIZE (512*188*8) | ||
809 | struct dvb_ringbuffer tsout_rbuf; | ||
810 | |||
811 | u8 *ain_buf; | ||
812 | #define AIN_BUF_SIZE (128*1024) | ||
813 | struct dvb_ringbuffer ain_rbuf; | ||
814 | |||
815 | |||
816 | u8 *vin_buf; | ||
817 | #define VIN_BUF_SIZE (4*1920*1080) | ||
818 | struct dvb_ringbuffer vin_rbuf; | ||
819 | |||
820 | unsigned long exp_val; | ||
821 | int prev_cmd; | ||
822 | }; | ||
823 | |||
824 | struct channel_info { | ||
825 | int io_type; | ||
826 | #define NGENE_IO_NONE 0 | ||
827 | #define NGENE_IO_TV 1 | ||
828 | #define NGENE_IO_HDTV 2 | ||
829 | #define NGENE_IO_TSIN 4 | ||
830 | #define NGENE_IO_TSOUT 8 | ||
831 | #define NGENE_IO_AIN 16 | ||
832 | |||
833 | void *fe_config; | ||
834 | void *tuner_config; | ||
835 | |||
836 | int (*demod_attach)(struct ngene_channel *); | ||
837 | int demod_type; | ||
838 | #define NGENE_DEMOD_NONE 0 | ||
839 | #define NGENE_DEMOD_DRXD 1 | ||
840 | #define NGENE_DEMOD_STB0899 2 | ||
841 | #define NGENE_DEMOD_DRXH 3 | ||
842 | |||
843 | int (*tuner_attach)(struct ngene_channel *); | ||
844 | int tuner_type; | ||
845 | #define NGENE_TUNER_NONE 0 | ||
846 | #define NGENE_TUNER_MT2060 1 | ||
847 | |||
848 | u8 demod; | ||
849 | u8 tuner; | ||
850 | u8 lnb; | ||
851 | u8 demoda; | ||
852 | u8 avf; | ||
853 | u8 msp; | ||
854 | }; | ||
855 | |||
856 | struct ngene_info { | ||
857 | int type; | ||
858 | #define NGENE_APP 0 | ||
859 | #define NGENE_TERRATEC 1 | ||
860 | #define NGENE_SIDEWINDER 2 | ||
861 | #define NGENE_RACER 3 | ||
862 | #define NGENE_VIPER 4 | ||
863 | #define NGENE_PYTHON 5 | ||
864 | #define NGENE_VBOX_V1 6 | ||
865 | #define NGENE_VBOX_V2 7 | ||
866 | |||
867 | int fw_version; | ||
868 | char *name; | ||
869 | |||
870 | int io_type[MAX_STREAM]; | ||
871 | #define NGENE_IO_NONE 0 | ||
872 | #define NGENE_IO_TV 1 | ||
873 | #define NGENE_IO_HDTV 2 | ||
874 | #define NGENE_IO_TSIN 4 | ||
875 | #define NGENE_IO_TSOUT 8 | ||
876 | #define NGENE_IO_AIN 16 | ||
877 | |||
878 | void *fe_config[4]; | ||
879 | void *tuner_config[4]; | ||
880 | |||
881 | int (*demod_attach[4])(struct ngene_channel *); | ||
882 | int (*tuner_attach[4])(struct ngene_channel *); | ||
883 | |||
884 | u8 avf[4]; | ||
885 | u8 msp[4]; | ||
886 | u8 demoda[4]; | ||
887 | u8 lnb[4]; | ||
888 | int i2c_access; | ||
889 | u8 ntsc; | ||
890 | u8 exp; | ||
891 | u8 exp_init; | ||
892 | u8 tsf[4]; | ||
893 | u8 i2s[4]; | ||
894 | |||
895 | int (*gate_ctrl)(struct dvb_frontend *, int); | ||
896 | int (*switch_ctrl)(struct ngene_channel *, int, int); | ||
897 | }; | ||
898 | |||
899 | #ifdef NGENE_V4L | ||
900 | struct ngene_format{ | ||
901 | char *name; | ||
902 | int fourcc; /* video4linux 2 */ | ||
903 | int btformat; /* BT848_COLOR_FMT_* */ | ||
904 | int format; | ||
905 | int btswap; /* BT848_COLOR_CTL_* */ | ||
906 | int depth; /* bit/pixel */ | ||
907 | int flags; | ||
908 | int hshift, vshift; /* for planar modes */ | ||
909 | int palette; | ||
910 | }; | ||
911 | |||
912 | #define RESOURCE_OVERLAY 1 | ||
913 | #define RESOURCE_VIDEO 2 | ||
914 | #define RESOURCE_VBI 4 | ||
915 | |||
916 | struct ngene_buffer { | ||
917 | /* common v4l buffer stuff -- must be first */ | ||
918 | struct videobuf_buffer vb; | ||
919 | |||
920 | /* ngene specific */ | ||
921 | const struct ngene_format *fmt; | ||
922 | int tvnorm; | ||
923 | int btformat; | ||
924 | int btswap; | ||
925 | }; | ||
926 | #endif | ||
927 | |||
928 | int ngene_command_stream_control(struct ngene *dev, | ||
929 | u8 stream, u8 control, u8 mode, u8 flags); | ||
930 | int ngene_command_nop(struct ngene *dev); | ||
931 | int ngene_command_i2c_read(struct ngene *dev, u8 adr, | ||
932 | u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); | ||
933 | int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); | ||
934 | int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); | ||
935 | int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); | ||
936 | int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, | ||
937 | u16 lines, u16 bpl, u16 vblines, u16 vbibpl); | ||
938 | int ngene_v4l2_init(struct ngene_channel *chan); | ||
939 | void ngene_v4l2_remove(struct ngene_channel *chan); | ||
940 | int ngene_snd_exit(struct ngene_channel *chan); | ||
941 | int ngene_snd_init(struct ngene_channel *chan); | ||
942 | |||
943 | struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); | ||
944 | |||
945 | #endif | ||
946 | |||
947 | /* LocalWords: Endif | ||
948 | */ | ||