1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ngene.c: nGene PCIe bridge driver |
4 | * |
5 | * Copyright (C) 2005-2007 Micronas |
6 | * |
7 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> |
8 | * Modifications for new nGene firmware, |
9 | * support for EEPROM-copying, |
10 | * support for new dual DVB-S2 card prototype |
11 | */ |
12 | |
13 | #include <linux/module.h> |
14 | #include <linux/init.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/poll.h> |
17 | #include <linux/io.h> |
18 | #include <asm/div64.h> |
19 | #include <linux/pci.h> |
20 | #include <linux/timer.h> |
21 | #include <linux/byteorder/generic.h> |
22 | #include <linux/firmware.h> |
23 | #include <linux/vmalloc.h> |
24 | |
25 | #include "ngene.h" |
26 | |
27 | static int one_adapter; |
28 | module_param(one_adapter, int, 0444); |
29 | MODULE_PARM_DESC(one_adapter, "Use only one adapter." ); |
30 | |
31 | static int shutdown_workaround; |
32 | module_param(shutdown_workaround, int, 0644); |
33 | MODULE_PARM_DESC(shutdown_workaround, "Activate workaround for shutdown problem with some chipsets." ); |
34 | |
35 | static int debug; |
36 | module_param(debug, int, 0444); |
37 | MODULE_PARM_DESC(debug, "Print debugging information." ); |
38 | |
39 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
40 | |
41 | #define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) |
42 | #define ngwritel(dat, adr) writel((dat), dev->iomem + (adr)) |
43 | #define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) |
44 | #define ngreadl(adr) readl(dev->iomem + (adr)) |
45 | #define ngreadb(adr) readb(dev->iomem + (adr)) |
46 | #define ngcpyto(adr, src, count) memcpy_toio(dev->iomem + (adr), (src), (count)) |
47 | #define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), dev->iomem + (adr), (count)) |
48 | |
49 | /****************************************************************************/ |
50 | /* nGene interrupt handler **************************************************/ |
51 | /****************************************************************************/ |
52 | |
53 | static void event_tasklet(struct tasklet_struct *t) |
54 | { |
55 | struct ngene *dev = from_tasklet(dev, t, event_tasklet); |
56 | |
57 | while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) { |
58 | struct EVENT_BUFFER Event = |
59 | dev->EventQueue[dev->EventQueueReadIndex]; |
60 | dev->EventQueueReadIndex = |
61 | (dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1); |
62 | |
63 | if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify)) |
64 | dev->TxEventNotify(dev, Event.TimeStamp); |
65 | if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) |
66 | dev->RxEventNotify(dev, Event.TimeStamp, |
67 | Event.RXCharacter); |
68 | } |
69 | } |
70 | |
71 | static void demux_tasklet(struct tasklet_struct *t) |
72 | { |
73 | struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet); |
74 | struct device *pdev = &chan->dev->pci_dev->dev; |
75 | struct SBufferHeader *Cur = chan->nextBuffer; |
76 | |
77 | spin_lock_irq(lock: &chan->state_lock); |
78 | |
79 | while (Cur->ngeneBuffer.SR.Flags & 0x80) { |
80 | if (chan->mode & NGENE_IO_TSOUT) { |
81 | u32 Flags = chan->DataFormatFlags; |
82 | if (Cur->ngeneBuffer.SR.Flags & 0x20) |
83 | Flags |= BEF_OVERFLOW; |
84 | if (chan->pBufferExchange) { |
85 | if (!chan->pBufferExchange(chan, |
86 | Cur->Buffer1, |
87 | chan->Capture1Length, |
88 | Cur->ngeneBuffer.SR. |
89 | Clock, Flags)) { |
90 | /* |
91 | We didn't get data |
92 | Clear in service flag to make sure we |
93 | get called on next interrupt again. |
94 | leave fill/empty (0x80) flag alone |
95 | to avoid hardware running out of |
96 | buffers during startup, we hold only |
97 | in run state ( the source may be late |
98 | delivering data ) |
99 | */ |
100 | |
101 | if (chan->HWState == HWSTATE_RUN) { |
102 | Cur->ngeneBuffer.SR.Flags &= |
103 | ~0x40; |
104 | break; |
105 | /* Stop processing stream */ |
106 | } |
107 | } else { |
108 | /* We got a valid buffer, |
109 | so switch to run state */ |
110 | chan->HWState = HWSTATE_RUN; |
111 | } |
112 | } else { |
113 | dev_err(pdev, "OOPS\n" ); |
114 | if (chan->HWState == HWSTATE_RUN) { |
115 | Cur->ngeneBuffer.SR.Flags &= ~0x40; |
116 | break; /* Stop processing stream */ |
117 | } |
118 | } |
119 | if (chan->AudioDTOUpdated) { |
120 | dev_info(pdev, "Update AudioDTO = %d\n" , |
121 | chan->AudioDTOValue); |
122 | Cur->ngeneBuffer.SR.DTOUpdate = |
123 | chan->AudioDTOValue; |
124 | chan->AudioDTOUpdated = 0; |
125 | } |
126 | } else { |
127 | if (chan->HWState == HWSTATE_RUN) { |
128 | u32 Flags = chan->DataFormatFlags; |
129 | IBufferExchange *exch1 = chan->pBufferExchange; |
130 | IBufferExchange *exch2 = chan->pBufferExchange2; |
131 | if (Cur->ngeneBuffer.SR.Flags & 0x01) |
132 | Flags |= BEF_EVEN_FIELD; |
133 | if (Cur->ngeneBuffer.SR.Flags & 0x20) |
134 | Flags |= BEF_OVERFLOW; |
135 | spin_unlock_irq(lock: &chan->state_lock); |
136 | if (exch1) |
137 | exch1(chan, Cur->Buffer1, |
138 | chan->Capture1Length, |
139 | Cur->ngeneBuffer.SR.Clock, |
140 | Flags); |
141 | if (exch2) |
142 | exch2(chan, Cur->Buffer2, |
143 | chan->Capture2Length, |
144 | Cur->ngeneBuffer.SR.Clock, |
145 | Flags); |
146 | spin_lock_irq(lock: &chan->state_lock); |
147 | } else if (chan->HWState != HWSTATE_STOP) |
148 | chan->HWState = HWSTATE_RUN; |
149 | } |
150 | Cur->ngeneBuffer.SR.Flags = 0x00; |
151 | Cur = Cur->Next; |
152 | } |
153 | chan->nextBuffer = Cur; |
154 | |
155 | spin_unlock_irq(lock: &chan->state_lock); |
156 | } |
157 | |
158 | static irqreturn_t irq_handler(int irq, void *dev_id) |
159 | { |
160 | struct ngene *dev = (struct ngene *)dev_id; |
161 | struct device *pdev = &dev->pci_dev->dev; |
162 | u32 icounts = 0; |
163 | irqreturn_t rc = IRQ_NONE; |
164 | u32 i = MAX_STREAM; |
165 | u8 *tmpCmdDoneByte; |
166 | |
167 | if (dev->BootFirmware) { |
168 | icounts = ngreadl(NGENE_INT_COUNTS); |
169 | if (icounts != dev->icounts) { |
170 | ngwritel(0, FORCE_NMI); |
171 | dev->cmd_done = 1; |
172 | wake_up(&dev->cmd_wq); |
173 | dev->icounts = icounts; |
174 | rc = IRQ_HANDLED; |
175 | } |
176 | return rc; |
177 | } |
178 | |
179 | ngwritel(0, FORCE_NMI); |
180 | |
181 | spin_lock(lock: &dev->cmd_lock); |
182 | tmpCmdDoneByte = dev->CmdDoneByte; |
183 | if (tmpCmdDoneByte && |
184 | (*tmpCmdDoneByte || |
185 | (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) { |
186 | dev->CmdDoneByte = NULL; |
187 | dev->cmd_done = 1; |
188 | wake_up(&dev->cmd_wq); |
189 | rc = IRQ_HANDLED; |
190 | } |
191 | spin_unlock(lock: &dev->cmd_lock); |
192 | |
193 | if (dev->EventBuffer->EventStatus & 0x80) { |
194 | u8 nextWriteIndex = |
195 | (dev->EventQueueWriteIndex + 1) & |
196 | (EVENT_QUEUE_SIZE - 1); |
197 | if (nextWriteIndex != dev->EventQueueReadIndex) { |
198 | dev->EventQueue[dev->EventQueueWriteIndex] = |
199 | *(dev->EventBuffer); |
200 | dev->EventQueueWriteIndex = nextWriteIndex; |
201 | } else { |
202 | dev_err(pdev, "event overflow\n" ); |
203 | dev->EventQueueOverflowCount += 1; |
204 | dev->EventQueueOverflowFlag = 1; |
205 | } |
206 | dev->EventBuffer->EventStatus &= ~0x80; |
207 | tasklet_schedule(t: &dev->event_tasklet); |
208 | rc = IRQ_HANDLED; |
209 | } |
210 | |
211 | while (i > 0) { |
212 | i--; |
213 | spin_lock(lock: &dev->channel[i].state_lock); |
214 | /* if (dev->channel[i].State>=KSSTATE_RUN) { */ |
215 | if (dev->channel[i].nextBuffer) { |
216 | if ((dev->channel[i].nextBuffer-> |
217 | ngeneBuffer.SR.Flags & 0xC0) == 0x80) { |
218 | dev->channel[i].nextBuffer-> |
219 | ngeneBuffer.SR.Flags |= 0x40; |
220 | tasklet_schedule( |
221 | t: &dev->channel[i].demux_tasklet); |
222 | rc = IRQ_HANDLED; |
223 | } |
224 | } |
225 | spin_unlock(lock: &dev->channel[i].state_lock); |
226 | } |
227 | |
228 | /* Request might have been processed by a previous call. */ |
229 | return IRQ_HANDLED; |
230 | } |
231 | |
232 | /****************************************************************************/ |
233 | /* nGene command interface **************************************************/ |
234 | /****************************************************************************/ |
235 | |
236 | static void dump_command_io(struct ngene *dev) |
237 | { |
238 | struct device *pdev = &dev->pci_dev->dev; |
239 | u8 buf[8], *b; |
240 | |
241 | ngcpyfrom(buf, HOST_TO_NGENE, 8); |
242 | dev_err(pdev, "host_to_ngene (%04x): %*ph\n" , HOST_TO_NGENE, 8, buf); |
243 | |
244 | ngcpyfrom(buf, NGENE_TO_HOST, 8); |
245 | dev_err(pdev, "ngene_to_host (%04x): %*ph\n" , NGENE_TO_HOST, 8, buf); |
246 | |
247 | b = dev->hosttongene; |
248 | dev_err(pdev, "dev->hosttongene (%p): %*ph\n" , b, 8, b); |
249 | |
250 | b = dev->ngenetohost; |
251 | dev_err(pdev, "dev->ngenetohost (%p): %*ph\n" , b, 8, b); |
252 | } |
253 | |
254 | static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) |
255 | { |
256 | struct device *pdev = &dev->pci_dev->dev; |
257 | int ret; |
258 | u8 *tmpCmdDoneByte; |
259 | |
260 | dev->cmd_done = 0; |
261 | |
262 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) { |
263 | dev->BootFirmware = 1; |
264 | dev->icounts = ngreadl(NGENE_INT_COUNTS); |
265 | ngwritel(0, NGENE_COMMAND); |
266 | ngwritel(0, NGENE_COMMAND_HI); |
267 | ngwritel(0, NGENE_STATUS); |
268 | ngwritel(0, NGENE_STATUS_HI); |
269 | ngwritel(0, NGENE_EVENT); |
270 | ngwritel(0, NGENE_EVENT_HI); |
271 | } else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) { |
272 | u64 fwio = dev->PAFWInterfaceBuffer; |
273 | |
274 | ngwritel(fwio & 0xffffffff, NGENE_COMMAND); |
275 | ngwritel(fwio >> 32, NGENE_COMMAND_HI); |
276 | ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS); |
277 | ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI); |
278 | ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT); |
279 | ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI); |
280 | } |
281 | |
282 | memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2); |
283 | |
284 | if (dev->BootFirmware) |
285 | ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2); |
286 | |
287 | spin_lock_irq(lock: &dev->cmd_lock); |
288 | tmpCmdDoneByte = dev->ngenetohost + com->out_len; |
289 | if (!com->out_len) |
290 | tmpCmdDoneByte++; |
291 | *tmpCmdDoneByte = 0; |
292 | dev->ngenetohost[0] = 0; |
293 | dev->ngenetohost[1] = 0; |
294 | dev->CmdDoneByte = tmpCmdDoneByte; |
295 | spin_unlock_irq(lock: &dev->cmd_lock); |
296 | |
297 | /* Notify 8051. */ |
298 | ngwritel(1, FORCE_INT); |
299 | |
300 | ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); |
301 | if (!ret) { |
302 | /*ngwritel(0, FORCE_NMI);*/ |
303 | |
304 | dev_err(pdev, "Command timeout cmd=%02x prev=%02x\n" , |
305 | com->cmd.hdr.Opcode, dev->prev_cmd); |
306 | dump_command_io(dev); |
307 | return -1; |
308 | } |
309 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) |
310 | dev->BootFirmware = 0; |
311 | |
312 | dev->prev_cmd = com->cmd.hdr.Opcode; |
313 | |
314 | if (!com->out_len) |
315 | return 0; |
316 | |
317 | memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len); |
318 | |
319 | return 0; |
320 | } |
321 | |
322 | int ngene_command(struct ngene *dev, struct ngene_command *com) |
323 | { |
324 | int result; |
325 | |
326 | mutex_lock(&dev->cmd_mutex); |
327 | result = ngene_command_mutex(dev, com); |
328 | mutex_unlock(lock: &dev->cmd_mutex); |
329 | return result; |
330 | } |
331 | |
332 | |
333 | static int ngene_command_load_firmware(struct ngene *dev, |
334 | u8 *ngene_fw, u32 size) |
335 | { |
336 | #define FIRSTCHUNK (1024) |
337 | u32 cleft; |
338 | struct ngene_command com; |
339 | |
340 | com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE; |
341 | com.cmd.hdr.Length = 0; |
342 | com.in_len = 0; |
343 | com.out_len = 0; |
344 | |
345 | ngene_command(dev, com: &com); |
346 | |
347 | cleft = (size + 3) & ~3; |
348 | if (cleft > FIRSTCHUNK) { |
349 | ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK, |
350 | cleft - FIRSTCHUNK); |
351 | cleft = FIRSTCHUNK; |
352 | } |
353 | ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft); |
354 | |
355 | memset(&com, 0, sizeof(struct ngene_command)); |
356 | com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH; |
357 | com.cmd.hdr.Length = 4; |
358 | com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA; |
359 | com.cmd.FWLoadFinish.Length = (unsigned short)cleft; |
360 | com.in_len = 4; |
361 | com.out_len = 0; |
362 | |
363 | return ngene_command(dev, com: &com); |
364 | } |
365 | |
366 | |
367 | static int ngene_command_config_buf(struct ngene *dev, u8 config) |
368 | { |
369 | struct ngene_command com; |
370 | |
371 | com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER; |
372 | com.cmd.hdr.Length = 1; |
373 | com.cmd.ConfigureBuffers.config = config; |
374 | com.in_len = 1; |
375 | com.out_len = 0; |
376 | |
377 | if (ngene_command(dev, com: &com) < 0) |
378 | return -EIO; |
379 | return 0; |
380 | } |
381 | |
382 | static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) |
383 | { |
384 | struct ngene_command com; |
385 | |
386 | com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER; |
387 | com.cmd.hdr.Length = 6; |
388 | memcpy(&com.cmd.ConfigureFreeBuffers.config, config, 6); |
389 | com.in_len = 6; |
390 | com.out_len = 0; |
391 | |
392 | if (ngene_command(dev, com: &com) < 0) |
393 | return -EIO; |
394 | |
395 | return 0; |
396 | } |
397 | |
398 | int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) |
399 | { |
400 | struct ngene_command com; |
401 | |
402 | com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN; |
403 | com.cmd.hdr.Length = 1; |
404 | com.cmd.SetGpioPin.select = select | (level << 7); |
405 | com.in_len = 1; |
406 | com.out_len = 0; |
407 | |
408 | return ngene_command(dev, com: &com); |
409 | } |
410 | |
411 | |
412 | /* |
413 | 02000640 is sample on rising edge. |
414 | 02000740 is sample on falling edge. |
415 | 02000040 is ignore "valid" signal |
416 | |
417 | 0: FD_CTL1 Bit 7,6 must be 0,1 |
418 | 7 disable(fw controlled) |
419 | 6 0-AUX,1-TS |
420 | 5 0-par,1-ser |
421 | 4 0-lsb/1-msb |
422 | 3,2 reserved |
423 | 1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both |
424 | 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge |
425 | 2: FD_STA is read-only. 0-sync |
426 | 3: FD_INSYNC is number of 47s to trigger "in sync". |
427 | 4: FD_OUTSYNC is number of 47s to trigger "out of sync". |
428 | 5: FD_MAXBYTE1 is low-order of bytes per packet. |
429 | 6: FD_MAXBYTE2 is high-order of bytes per packet. |
430 | 7: Top byte is unused. |
431 | */ |
432 | |
433 | /****************************************************************************/ |
434 | |
435 | static u8 TSFeatureDecoderSetup[8 * 5] = { |
436 | 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, |
437 | 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ |
438 | 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ |
439 | 0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ |
440 | 0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */ |
441 | }; |
442 | |
443 | /* Set NGENE I2S Config to 16 bit packed */ |
444 | static u8 I2SConfiguration[] = { |
445 | 0x00, 0x10, 0x00, 0x00, |
446 | 0x80, 0x10, 0x00, 0x00, |
447 | }; |
448 | |
449 | static u8 SPDIFConfiguration[10] = { |
450 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
451 | }; |
452 | |
453 | /* Set NGENE I2S Config to transport stream compatible mode */ |
454 | |
455 | static u8 TS_I2SConfiguration[4] = { 0x3E, 0x18, 0x00, 0x00 }; |
456 | |
457 | static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x04, 0x00, 0x00 }; |
458 | |
459 | static u8 ITUDecoderSetup[4][16] = { |
460 | {0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20, /* SDTV */ |
461 | 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00}, |
462 | {0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, |
463 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, |
464 | {0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00, /* HDTV 1080i50 */ |
465 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, |
466 | {0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, /* HDTV 1080i60 */ |
467 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, |
468 | }; |
469 | |
470 | /* |
471 | * 50 48 60 gleich |
472 | * 27p50 9f 00 22 80 42 69 18 ... |
473 | * 27p60 93 00 22 80 82 69 1c ... |
474 | */ |
475 | |
476 | /* Maxbyte to 1144 (for raw data) */ |
477 | static u8 ITUFeatureDecoderSetup[8] = { |
478 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 |
479 | }; |
480 | |
481 | void FillTSBuffer(void *Buffer, int Length, u32 Flags) |
482 | { |
483 | u32 *ptr = Buffer; |
484 | |
485 | memset(Buffer, TS_FILLER, Length); |
486 | while (Length > 0) { |
487 | if (Flags & DF_SWAP32) |
488 | *ptr = 0x471FFF10; |
489 | else |
490 | *ptr = 0x10FF1F47; |
491 | ptr += (188 / 4); |
492 | Length -= 188; |
493 | } |
494 | } |
495 | |
496 | |
497 | static void flush_buffers(struct ngene_channel *chan) |
498 | { |
499 | u8 val; |
500 | |
501 | do { |
502 | msleep(msecs: 1); |
503 | spin_lock_irq(lock: &chan->state_lock); |
504 | val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80; |
505 | spin_unlock_irq(lock: &chan->state_lock); |
506 | } while (val); |
507 | } |
508 | |
509 | static void clear_buffers(struct ngene_channel *chan) |
510 | { |
511 | struct SBufferHeader *Cur = chan->nextBuffer; |
512 | |
513 | do { |
514 | memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); |
515 | if (chan->mode & NGENE_IO_TSOUT) |
516 | FillTSBuffer(Buffer: Cur->Buffer1, |
517 | Length: chan->Capture1Length, |
518 | Flags: chan->DataFormatFlags); |
519 | Cur = Cur->Next; |
520 | } while (Cur != chan->nextBuffer); |
521 | |
522 | if (chan->mode & NGENE_IO_TSOUT) { |
523 | chan->nextBuffer->ngeneBuffer.SR.DTOUpdate = |
524 | chan->AudioDTOValue; |
525 | chan->AudioDTOUpdated = 0; |
526 | |
527 | Cur = chan->TSIdleBuffer.Head; |
528 | |
529 | do { |
530 | memset(&Cur->ngeneBuffer.SR, 0, |
531 | sizeof(Cur->ngeneBuffer.SR)); |
532 | FillTSBuffer(Buffer: Cur->Buffer1, |
533 | Length: chan->Capture1Length, |
534 | Flags: chan->DataFormatFlags); |
535 | Cur = Cur->Next; |
536 | } while (Cur != chan->TSIdleBuffer.Head); |
537 | } |
538 | } |
539 | |
540 | static int ngene_command_stream_control(struct ngene *dev, u8 stream, |
541 | u8 control, u8 mode, u8 flags) |
542 | { |
543 | struct device *pdev = &dev->pci_dev->dev; |
544 | struct ngene_channel *chan = &dev->channel[stream]; |
545 | struct ngene_command com; |
546 | u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300); |
547 | u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500); |
548 | u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); |
549 | u16 BsSDO = 0x9B00; |
550 | |
551 | memset(&com, 0, sizeof(com)); |
552 | com.cmd.hdr.Opcode = CMD_CONTROL; |
553 | com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; |
554 | com.cmd.StreamControl.Stream = stream | (control ? 8 : 0); |
555 | if (chan->mode & NGENE_IO_TSOUT) |
556 | com.cmd.StreamControl.Stream |= 0x07; |
557 | com.cmd.StreamControl.Control = control | |
558 | (flags & SFLAG_ORDER_LUMA_CHROMA); |
559 | com.cmd.StreamControl.Mode = mode; |
560 | com.in_len = sizeof(struct FW_STREAM_CONTROL); |
561 | com.out_len = 0; |
562 | |
563 | dev_dbg(pdev, "Stream=%02x, Control=%02x, Mode=%02x\n" , |
564 | com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, |
565 | com.cmd.StreamControl.Mode); |
566 | |
567 | chan->Mode = mode; |
568 | |
569 | if (!(control & 0x80)) { |
570 | spin_lock_irq(lock: &chan->state_lock); |
571 | if (chan->State == KSSTATE_RUN) { |
572 | chan->State = KSSTATE_ACQUIRE; |
573 | chan->HWState = HWSTATE_STOP; |
574 | spin_unlock_irq(lock: &chan->state_lock); |
575 | if (ngene_command(dev, com: &com) < 0) |
576 | return -1; |
577 | /* clear_buffers(chan); */ |
578 | flush_buffers(chan); |
579 | return 0; |
580 | } |
581 | spin_unlock_irq(lock: &chan->state_lock); |
582 | return 0; |
583 | } |
584 | |
585 | if (mode & SMODE_AUDIO_CAPTURE) { |
586 | com.cmd.StreamControl.CaptureBlockCount = |
587 | chan->Capture1Length / AUDIO_BLOCK_SIZE; |
588 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; |
589 | } else if (mode & SMODE_TRANSPORT_STREAM) { |
590 | com.cmd.StreamControl.CaptureBlockCount = |
591 | chan->Capture1Length / TS_BLOCK_SIZE; |
592 | com.cmd.StreamControl.MaxLinesPerField = |
593 | chan->Capture1Length / TS_BLOCK_SIZE; |
594 | com.cmd.StreamControl.Buffer_Address = |
595 | chan->TSRingBuffer.PAHead; |
596 | if (chan->mode & NGENE_IO_TSOUT) { |
597 | com.cmd.StreamControl.BytesPerVBILine = |
598 | chan->Capture1Length / TS_BLOCK_SIZE; |
599 | com.cmd.StreamControl.Stream |= 0x07; |
600 | } |
601 | } else { |
602 | com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine; |
603 | com.cmd.StreamControl.MaxLinesPerField = chan->nLines; |
604 | com.cmd.StreamControl.MinLinesPerField = 100; |
605 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; |
606 | |
607 | if (mode & SMODE_VBI_CAPTURE) { |
608 | com.cmd.StreamControl.MaxVBILinesPerField = |
609 | chan->nVBILines; |
610 | com.cmd.StreamControl.MinVBILinesPerField = 0; |
611 | com.cmd.StreamControl.BytesPerVBILine = |
612 | chan->nBytesPerVBILine; |
613 | } |
614 | if (flags & SFLAG_COLORBAR) |
615 | com.cmd.StreamControl.Stream |= 0x04; |
616 | } |
617 | |
618 | spin_lock_irq(lock: &chan->state_lock); |
619 | if (mode & SMODE_AUDIO_CAPTURE) { |
620 | chan->nextBuffer = chan->RingBuffer.Head; |
621 | if (mode & SMODE_AUDIO_SPDIF) { |
622 | com.cmd.StreamControl.SetupDataLen = |
623 | sizeof(SPDIFConfiguration); |
624 | com.cmd.StreamControl.SetupDataAddr = BsSPI; |
625 | memcpy(com.cmd.StreamControl.SetupData, |
626 | SPDIFConfiguration, sizeof(SPDIFConfiguration)); |
627 | } else { |
628 | com.cmd.StreamControl.SetupDataLen = 4; |
629 | com.cmd.StreamControl.SetupDataAddr = BsSDI; |
630 | memcpy(com.cmd.StreamControl.SetupData, |
631 | I2SConfiguration + |
632 | 4 * dev->card_info->i2s[stream], 4); |
633 | } |
634 | } else if (mode & SMODE_TRANSPORT_STREAM) { |
635 | chan->nextBuffer = chan->TSRingBuffer.Head; |
636 | if (stream >= STREAM_AUDIOIN1) { |
637 | if (chan->mode & NGENE_IO_TSOUT) { |
638 | com.cmd.StreamControl.SetupDataLen = |
639 | sizeof(TS_I2SOutConfiguration); |
640 | com.cmd.StreamControl.SetupDataAddr = BsSDO; |
641 | memcpy(com.cmd.StreamControl.SetupData, |
642 | TS_I2SOutConfiguration, |
643 | sizeof(TS_I2SOutConfiguration)); |
644 | } else { |
645 | com.cmd.StreamControl.SetupDataLen = |
646 | sizeof(TS_I2SConfiguration); |
647 | com.cmd.StreamControl.SetupDataAddr = BsSDI; |
648 | memcpy(com.cmd.StreamControl.SetupData, |
649 | TS_I2SConfiguration, |
650 | sizeof(TS_I2SConfiguration)); |
651 | } |
652 | } else { |
653 | com.cmd.StreamControl.SetupDataLen = 8; |
654 | com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10; |
655 | memcpy(com.cmd.StreamControl.SetupData, |
656 | TSFeatureDecoderSetup + |
657 | 8 * dev->card_info->tsf[stream], 8); |
658 | } |
659 | } else { |
660 | chan->nextBuffer = chan->RingBuffer.Head; |
661 | com.cmd.StreamControl.SetupDataLen = |
662 | 16 + sizeof(ITUFeatureDecoderSetup); |
663 | com.cmd.StreamControl.SetupDataAddr = BsUVI; |
664 | memcpy(com.cmd.StreamControl.SetupData, |
665 | ITUDecoderSetup[chan->itumode], 16); |
666 | memcpy(com.cmd.StreamControl.SetupData + 16, |
667 | ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup)); |
668 | } |
669 | clear_buffers(chan); |
670 | chan->State = KSSTATE_RUN; |
671 | if (mode & SMODE_TRANSPORT_STREAM) |
672 | chan->HWState = HWSTATE_RUN; |
673 | else |
674 | chan->HWState = HWSTATE_STARTUP; |
675 | spin_unlock_irq(lock: &chan->state_lock); |
676 | |
677 | if (ngene_command(dev, com: &com) < 0) |
678 | return -1; |
679 | |
680 | return 0; |
681 | } |
682 | |
683 | void set_transfer(struct ngene_channel *chan, int state) |
684 | { |
685 | struct device *pdev = &chan->dev->pci_dev->dev; |
686 | u8 control = 0, mode = 0, flags = 0; |
687 | struct ngene *dev = chan->dev; |
688 | int ret; |
689 | |
690 | /* |
691 | dev_info(pdev, "st %d\n", state); |
692 | msleep(100); |
693 | */ |
694 | |
695 | if (state) { |
696 | if (chan->running) { |
697 | dev_info(pdev, "already running\n" ); |
698 | return; |
699 | } |
700 | } else { |
701 | if (!chan->running) { |
702 | dev_info(pdev, "already stopped\n" ); |
703 | return; |
704 | } |
705 | } |
706 | |
707 | if (dev->card_info->switch_ctrl) |
708 | dev->card_info->switch_ctrl(chan, 1, state ^ 1); |
709 | |
710 | if (state) { |
711 | spin_lock_irq(lock: &chan->state_lock); |
712 | |
713 | /* dev_info(pdev, "lock=%08x\n", |
714 | ngreadl(0x9310)); */ |
715 | dvb_ringbuffer_flush(rbuf: &dev->tsout_rbuf); |
716 | control = 0x80; |
717 | if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { |
718 | chan->Capture1Length = 512 * 188; |
719 | mode = SMODE_TRANSPORT_STREAM; |
720 | } |
721 | if (chan->mode & NGENE_IO_TSOUT) { |
722 | chan->pBufferExchange = tsout_exchange; |
723 | /* 0x66666666 = 50MHz *2^33 /250MHz */ |
724 | chan->AudioDTOValue = 0x80000000; |
725 | chan->AudioDTOUpdated = 1; |
726 | } |
727 | if (chan->mode & NGENE_IO_TSIN) |
728 | chan->pBufferExchange = tsin_exchange; |
729 | spin_unlock_irq(lock: &chan->state_lock); |
730 | } |
731 | /* else dev_info(pdev, "lock=%08x\n", |
732 | ngreadl(0x9310)); */ |
733 | |
734 | mutex_lock(&dev->stream_mutex); |
735 | ret = ngene_command_stream_control(dev, stream: chan->number, |
736 | control, mode, flags); |
737 | mutex_unlock(lock: &dev->stream_mutex); |
738 | |
739 | if (!ret) |
740 | chan->running = state; |
741 | else |
742 | dev_err(pdev, "%s %d failed\n" , __func__, state); |
743 | if (!state) { |
744 | spin_lock_irq(lock: &chan->state_lock); |
745 | chan->pBufferExchange = NULL; |
746 | dvb_ringbuffer_flush(rbuf: &dev->tsout_rbuf); |
747 | spin_unlock_irq(lock: &chan->state_lock); |
748 | } |
749 | } |
750 | |
751 | |
752 | /****************************************************************************/ |
753 | /* nGene hardware init and release functions ********************************/ |
754 | /****************************************************************************/ |
755 | |
756 | static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) |
757 | { |
758 | struct SBufferHeader *Cur = rb->Head; |
759 | u32 j; |
760 | |
761 | if (!Cur) |
762 | return; |
763 | |
764 | for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) { |
765 | if (Cur->Buffer1) |
766 | dma_free_coherent(dev: &dev->pci_dev->dev, |
767 | size: rb->Buffer1Length, cpu_addr: Cur->Buffer1, |
768 | dma_handle: Cur->scList1->Address); |
769 | |
770 | if (Cur->Buffer2) |
771 | dma_free_coherent(dev: &dev->pci_dev->dev, |
772 | size: rb->Buffer2Length, cpu_addr: Cur->Buffer2, |
773 | dma_handle: Cur->scList2->Address); |
774 | } |
775 | |
776 | if (rb->SCListMem) |
777 | dma_free_coherent(dev: &dev->pci_dev->dev, size: rb->SCListMemSize, |
778 | cpu_addr: rb->SCListMem, dma_handle: rb->PASCListMem); |
779 | |
780 | dma_free_coherent(dev: &dev->pci_dev->dev, size: rb->MemSize, cpu_addr: rb->Head, |
781 | dma_handle: rb->PAHead); |
782 | } |
783 | |
784 | static void free_idlebuffer(struct ngene *dev, |
785 | struct SRingBufferDescriptor *rb, |
786 | struct SRingBufferDescriptor *tb) |
787 | { |
788 | int j; |
789 | struct SBufferHeader *Cur = tb->Head; |
790 | |
791 | if (!rb->Head) |
792 | return; |
793 | free_ringbuffer(dev, rb); |
794 | for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { |
795 | Cur->Buffer2 = NULL; |
796 | Cur->scList2 = NULL; |
797 | Cur->ngeneBuffer.Address_of_first_entry_2 = 0; |
798 | Cur->ngeneBuffer.Number_of_entries_2 = 0; |
799 | } |
800 | } |
801 | |
802 | static void free_common_buffers(struct ngene *dev) |
803 | { |
804 | u32 i; |
805 | struct ngene_channel *chan; |
806 | |
807 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { |
808 | chan = &dev->channel[i]; |
809 | free_idlebuffer(dev, rb: &chan->TSIdleBuffer, tb: &chan->TSRingBuffer); |
810 | free_ringbuffer(dev, rb: &chan->RingBuffer); |
811 | free_ringbuffer(dev, rb: &chan->TSRingBuffer); |
812 | } |
813 | |
814 | if (dev->OverflowBuffer) |
815 | dma_free_coherent(dev: &dev->pci_dev->dev, OVERFLOW_BUFFER_SIZE, |
816 | cpu_addr: dev->OverflowBuffer, dma_handle: dev->PAOverflowBuffer); |
817 | |
818 | if (dev->FWInterfaceBuffer) |
819 | dma_free_coherent(dev: &dev->pci_dev->dev, size: 4096, |
820 | cpu_addr: dev->FWInterfaceBuffer, |
821 | dma_handle: dev->PAFWInterfaceBuffer); |
822 | } |
823 | |
824 | /****************************************************************************/ |
825 | /* Ring buffer handling *****************************************************/ |
826 | /****************************************************************************/ |
827 | |
828 | static int create_ring_buffer(struct pci_dev *pci_dev, |
829 | struct SRingBufferDescriptor *descr, u32 NumBuffers) |
830 | { |
831 | dma_addr_t tmp; |
832 | struct SBufferHeader *Head; |
833 | u32 i; |
834 | u32 MemSize = SIZEOF_SBufferHeader * NumBuffers; |
835 | u64 PARingBufferHead; |
836 | u64 PARingBufferCur; |
837 | u64 PARingBufferNext; |
838 | struct SBufferHeader *Cur, *Next; |
839 | |
840 | descr->Head = NULL; |
841 | descr->MemSize = 0; |
842 | descr->PAHead = 0; |
843 | descr->NumBuffers = 0; |
844 | |
845 | if (MemSize < 4096) |
846 | MemSize = 4096; |
847 | |
848 | Head = dma_alloc_coherent(dev: &pci_dev->dev, size: MemSize, dma_handle: &tmp, GFP_KERNEL); |
849 | PARingBufferHead = tmp; |
850 | |
851 | if (!Head) |
852 | return -ENOMEM; |
853 | |
854 | PARingBufferCur = PARingBufferHead; |
855 | Cur = Head; |
856 | |
857 | for (i = 0; i < NumBuffers - 1; i++) { |
858 | Next = (struct SBufferHeader *) |
859 | (((u8 *) Cur) + SIZEOF_SBufferHeader); |
860 | PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader; |
861 | Cur->Next = Next; |
862 | Cur->ngeneBuffer.Next = PARingBufferNext; |
863 | Cur = Next; |
864 | PARingBufferCur = PARingBufferNext; |
865 | } |
866 | /* Last Buffer points back to first one */ |
867 | Cur->Next = Head; |
868 | Cur->ngeneBuffer.Next = PARingBufferHead; |
869 | |
870 | descr->Head = Head; |
871 | descr->MemSize = MemSize; |
872 | descr->PAHead = PARingBufferHead; |
873 | descr->NumBuffers = NumBuffers; |
874 | |
875 | return 0; |
876 | } |
877 | |
878 | static int AllocateRingBuffers(struct pci_dev *pci_dev, |
879 | dma_addr_t of, |
880 | struct SRingBufferDescriptor *pRingBuffer, |
881 | u32 Buffer1Length, u32 Buffer2Length) |
882 | { |
883 | dma_addr_t tmp; |
884 | u32 i, j; |
885 | u32 SCListMemSize = pRingBuffer->NumBuffers |
886 | * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : |
887 | NUM_SCATTER_GATHER_ENTRIES) |
888 | * sizeof(struct HW_SCATTER_GATHER_ELEMENT); |
889 | |
890 | u64 PASCListMem; |
891 | struct HW_SCATTER_GATHER_ELEMENT *SCListEntry; |
892 | u64 PASCListEntry; |
893 | struct SBufferHeader *Cur; |
894 | void *SCListMem; |
895 | |
896 | if (SCListMemSize < 4096) |
897 | SCListMemSize = 4096; |
898 | |
899 | SCListMem = dma_alloc_coherent(dev: &pci_dev->dev, size: SCListMemSize, dma_handle: &tmp, |
900 | GFP_KERNEL); |
901 | |
902 | PASCListMem = tmp; |
903 | if (SCListMem == NULL) |
904 | return -ENOMEM; |
905 | |
906 | pRingBuffer->SCListMem = SCListMem; |
907 | pRingBuffer->PASCListMem = PASCListMem; |
908 | pRingBuffer->SCListMemSize = SCListMemSize; |
909 | pRingBuffer->Buffer1Length = Buffer1Length; |
910 | pRingBuffer->Buffer2Length = Buffer2Length; |
911 | |
912 | SCListEntry = SCListMem; |
913 | PASCListEntry = PASCListMem; |
914 | Cur = pRingBuffer->Head; |
915 | |
916 | for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) { |
917 | u64 PABuffer; |
918 | |
919 | void *Buffer = dma_alloc_coherent(dev: &pci_dev->dev, |
920 | size: Buffer1Length, dma_handle: &tmp, GFP_KERNEL); |
921 | PABuffer = tmp; |
922 | |
923 | if (Buffer == NULL) |
924 | return -ENOMEM; |
925 | |
926 | Cur->Buffer1 = Buffer; |
927 | |
928 | SCListEntry->Address = PABuffer; |
929 | SCListEntry->Length = Buffer1Length; |
930 | |
931 | Cur->scList1 = SCListEntry; |
932 | Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry; |
933 | Cur->ngeneBuffer.Number_of_entries_1 = |
934 | NUM_SCATTER_GATHER_ENTRIES; |
935 | |
936 | SCListEntry += 1; |
937 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); |
938 | |
939 | #if NUM_SCATTER_GATHER_ENTRIES > 1 |
940 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) { |
941 | SCListEntry->Address = of; |
942 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; |
943 | SCListEntry += 1; |
944 | PASCListEntry += |
945 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); |
946 | } |
947 | #endif |
948 | |
949 | if (!Buffer2Length) |
950 | continue; |
951 | |
952 | Buffer = dma_alloc_coherent(dev: &pci_dev->dev, size: Buffer2Length, |
953 | dma_handle: &tmp, GFP_KERNEL); |
954 | PABuffer = tmp; |
955 | |
956 | if (Buffer == NULL) |
957 | return -ENOMEM; |
958 | |
959 | Cur->Buffer2 = Buffer; |
960 | |
961 | SCListEntry->Address = PABuffer; |
962 | SCListEntry->Length = Buffer2Length; |
963 | |
964 | Cur->scList2 = SCListEntry; |
965 | Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry; |
966 | Cur->ngeneBuffer.Number_of_entries_2 = |
967 | NUM_SCATTER_GATHER_ENTRIES; |
968 | |
969 | SCListEntry += 1; |
970 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); |
971 | |
972 | #if NUM_SCATTER_GATHER_ENTRIES > 1 |
973 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) { |
974 | SCListEntry->Address = of; |
975 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; |
976 | SCListEntry += 1; |
977 | PASCListEntry += |
978 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); |
979 | } |
980 | #endif |
981 | |
982 | } |
983 | |
984 | return 0; |
985 | } |
986 | |
987 | static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, |
988 | struct SRingBufferDescriptor *pRingBuffer) |
989 | { |
990 | /* Copy pointer to scatter gather list in TSRingbuffer |
991 | structure for buffer 2 |
992 | Load number of buffer |
993 | */ |
994 | u32 n = pRingBuffer->NumBuffers; |
995 | |
996 | /* Point to first buffer entry */ |
997 | struct SBufferHeader *Cur = pRingBuffer->Head; |
998 | int i; |
999 | /* Loop through all buffer and set Buffer 2 pointers to TSIdlebuffer */ |
1000 | for (i = 0; i < n; i++) { |
1001 | Cur->Buffer2 = pIdleBuffer->Head->Buffer1; |
1002 | Cur->scList2 = pIdleBuffer->Head->scList1; |
1003 | Cur->ngeneBuffer.Address_of_first_entry_2 = |
1004 | pIdleBuffer->Head->ngeneBuffer. |
1005 | Address_of_first_entry_1; |
1006 | Cur->ngeneBuffer.Number_of_entries_2 = |
1007 | pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; |
1008 | Cur = Cur->Next; |
1009 | } |
1010 | return 0; |
1011 | } |
1012 | |
1013 | static u32 RingBufferSizes[MAX_STREAM] = { |
1014 | RING_SIZE_VIDEO, |
1015 | RING_SIZE_VIDEO, |
1016 | RING_SIZE_AUDIO, |
1017 | RING_SIZE_AUDIO, |
1018 | RING_SIZE_AUDIO, |
1019 | }; |
1020 | |
1021 | static u32 Buffer1Sizes[MAX_STREAM] = { |
1022 | MAX_VIDEO_BUFFER_SIZE, |
1023 | MAX_VIDEO_BUFFER_SIZE, |
1024 | MAX_AUDIO_BUFFER_SIZE, |
1025 | MAX_AUDIO_BUFFER_SIZE, |
1026 | MAX_AUDIO_BUFFER_SIZE |
1027 | }; |
1028 | |
1029 | static u32 Buffer2Sizes[MAX_STREAM] = { |
1030 | MAX_VBI_BUFFER_SIZE, |
1031 | MAX_VBI_BUFFER_SIZE, |
1032 | 0, |
1033 | 0, |
1034 | 0 |
1035 | }; |
1036 | |
1037 | |
1038 | static int AllocCommonBuffers(struct ngene *dev) |
1039 | { |
1040 | int status = 0, i; |
1041 | |
1042 | dev->FWInterfaceBuffer = dma_alloc_coherent(dev: &dev->pci_dev->dev, size: 4096, |
1043 | dma_handle: &dev->PAFWInterfaceBuffer, |
1044 | GFP_KERNEL); |
1045 | if (!dev->FWInterfaceBuffer) |
1046 | return -ENOMEM; |
1047 | dev->hosttongene = dev->FWInterfaceBuffer; |
1048 | dev->ngenetohost = dev->FWInterfaceBuffer + 256; |
1049 | dev->EventBuffer = dev->FWInterfaceBuffer + 512; |
1050 | |
1051 | dev->OverflowBuffer = dma_alloc_coherent(dev: &dev->pci_dev->dev, |
1052 | OVERFLOW_BUFFER_SIZE, |
1053 | dma_handle: &dev->PAOverflowBuffer, GFP_KERNEL); |
1054 | if (!dev->OverflowBuffer) |
1055 | return -ENOMEM; |
1056 | |
1057 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { |
1058 | int type = dev->card_info->io_type[i]; |
1059 | |
1060 | dev->channel[i].State = KSSTATE_STOP; |
1061 | |
1062 | if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { |
1063 | status = create_ring_buffer(pci_dev: dev->pci_dev, |
1064 | descr: &dev->channel[i].RingBuffer, |
1065 | NumBuffers: RingBufferSizes[i]); |
1066 | if (status < 0) |
1067 | break; |
1068 | |
1069 | if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { |
1070 | status = AllocateRingBuffers(pci_dev: dev->pci_dev, |
1071 | of: dev-> |
1072 | PAOverflowBuffer, |
1073 | pRingBuffer: &dev->channel[i]. |
1074 | RingBuffer, |
1075 | Buffer1Length: Buffer1Sizes[i], |
1076 | Buffer2Length: Buffer2Sizes[i]); |
1077 | if (status < 0) |
1078 | break; |
1079 | } else if (type & NGENE_IO_HDTV) { |
1080 | status = AllocateRingBuffers(pci_dev: dev->pci_dev, |
1081 | of: dev-> |
1082 | PAOverflowBuffer, |
1083 | pRingBuffer: &dev->channel[i]. |
1084 | RingBuffer, |
1085 | MAX_HDTV_BUFFER_SIZE, |
1086 | Buffer2Length: 0); |
1087 | if (status < 0) |
1088 | break; |
1089 | } |
1090 | } |
1091 | |
1092 | if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { |
1093 | |
1094 | status = create_ring_buffer(pci_dev: dev->pci_dev, |
1095 | descr: &dev->channel[i]. |
1096 | TSRingBuffer, RING_SIZE_TS); |
1097 | if (status < 0) |
1098 | break; |
1099 | |
1100 | status = AllocateRingBuffers(pci_dev: dev->pci_dev, |
1101 | of: dev->PAOverflowBuffer, |
1102 | pRingBuffer: &dev->channel[i]. |
1103 | TSRingBuffer, |
1104 | MAX_TS_BUFFER_SIZE, Buffer2Length: 0); |
1105 | if (status) |
1106 | break; |
1107 | } |
1108 | |
1109 | if (type & NGENE_IO_TSOUT) { |
1110 | status = create_ring_buffer(pci_dev: dev->pci_dev, |
1111 | descr: &dev->channel[i]. |
1112 | TSIdleBuffer, NumBuffers: 1); |
1113 | if (status < 0) |
1114 | break; |
1115 | status = AllocateRingBuffers(pci_dev: dev->pci_dev, |
1116 | of: dev->PAOverflowBuffer, |
1117 | pRingBuffer: &dev->channel[i]. |
1118 | TSIdleBuffer, |
1119 | MAX_TS_BUFFER_SIZE, Buffer2Length: 0); |
1120 | if (status) |
1121 | break; |
1122 | FillTSIdleBuffer(pIdleBuffer: &dev->channel[i].TSIdleBuffer, |
1123 | pRingBuffer: &dev->channel[i].TSRingBuffer); |
1124 | } |
1125 | } |
1126 | return status; |
1127 | } |
1128 | |
1129 | static void ngene_release_buffers(struct ngene *dev) |
1130 | { |
1131 | if (dev->iomem) |
1132 | iounmap(addr: dev->iomem); |
1133 | free_common_buffers(dev); |
1134 | vfree(addr: dev->tsout_buf); |
1135 | vfree(addr: dev->tsin_buf); |
1136 | vfree(addr: dev->ain_buf); |
1137 | vfree(addr: dev->vin_buf); |
1138 | vfree(addr: dev); |
1139 | } |
1140 | |
1141 | static int ngene_get_buffers(struct ngene *dev) |
1142 | { |
1143 | if (AllocCommonBuffers(dev)) |
1144 | return -ENOMEM; |
1145 | if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) { |
1146 | dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE); |
1147 | if (!dev->tsout_buf) |
1148 | return -ENOMEM; |
1149 | dvb_ringbuffer_init(rbuf: &dev->tsout_rbuf, |
1150 | data: dev->tsout_buf, TSOUT_BUF_SIZE); |
1151 | } |
1152 | if (dev->card_info->io_type[2]&NGENE_IO_TSIN) { |
1153 | dev->tsin_buf = vmalloc(TSIN_BUF_SIZE); |
1154 | if (!dev->tsin_buf) |
1155 | return -ENOMEM; |
1156 | dvb_ringbuffer_init(rbuf: &dev->tsin_rbuf, |
1157 | data: dev->tsin_buf, TSIN_BUF_SIZE); |
1158 | } |
1159 | if (dev->card_info->io_type[2] & NGENE_IO_AIN) { |
1160 | dev->ain_buf = vmalloc(AIN_BUF_SIZE); |
1161 | if (!dev->ain_buf) |
1162 | return -ENOMEM; |
1163 | dvb_ringbuffer_init(rbuf: &dev->ain_rbuf, data: dev->ain_buf, AIN_BUF_SIZE); |
1164 | } |
1165 | if (dev->card_info->io_type[0] & NGENE_IO_HDTV) { |
1166 | dev->vin_buf = vmalloc(VIN_BUF_SIZE); |
1167 | if (!dev->vin_buf) |
1168 | return -ENOMEM; |
1169 | dvb_ringbuffer_init(rbuf: &dev->vin_rbuf, data: dev->vin_buf, VIN_BUF_SIZE); |
1170 | } |
1171 | dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0), |
1172 | pci_resource_len(dev->pci_dev, 0)); |
1173 | if (!dev->iomem) |
1174 | return -ENOMEM; |
1175 | |
1176 | return 0; |
1177 | } |
1178 | |
1179 | static void ngene_init(struct ngene *dev) |
1180 | { |
1181 | struct device *pdev = &dev->pci_dev->dev; |
1182 | int i; |
1183 | |
1184 | tasklet_setup(t: &dev->event_tasklet, callback: event_tasklet); |
1185 | |
1186 | memset_io(dev->iomem + 0xc000, 0x00, 0x220); |
1187 | memset_io(dev->iomem + 0xc400, 0x00, 0x100); |
1188 | |
1189 | for (i = 0; i < MAX_STREAM; i++) { |
1190 | dev->channel[i].dev = dev; |
1191 | dev->channel[i].number = i; |
1192 | } |
1193 | |
1194 | dev->fw_interface_version = 0; |
1195 | |
1196 | ngwritel(0, NGENE_INT_ENABLE); |
1197 | |
1198 | dev->icounts = ngreadl(NGENE_INT_COUNTS); |
1199 | |
1200 | dev->device_version = ngreadl(DEV_VER) & 0x0f; |
1201 | dev_info(pdev, "Device version %d\n" , dev->device_version); |
1202 | } |
1203 | |
1204 | static int ngene_load_firm(struct ngene *dev) |
1205 | { |
1206 | struct device *pdev = &dev->pci_dev->dev; |
1207 | u32 size; |
1208 | const struct firmware *fw = NULL; |
1209 | u8 *ngene_fw; |
1210 | char *fw_name; |
1211 | int err, version; |
1212 | |
1213 | version = dev->card_info->fw_version; |
1214 | |
1215 | switch (version) { |
1216 | default: |
1217 | case 15: |
1218 | version = 15; |
1219 | size = 23466; |
1220 | fw_name = "ngene_15.fw" ; |
1221 | dev->cmd_timeout_workaround = true; |
1222 | break; |
1223 | case 16: |
1224 | size = 23498; |
1225 | fw_name = "ngene_16.fw" ; |
1226 | dev->cmd_timeout_workaround = true; |
1227 | break; |
1228 | case 17: |
1229 | size = 24446; |
1230 | fw_name = "ngene_17.fw" ; |
1231 | dev->cmd_timeout_workaround = true; |
1232 | break; |
1233 | case 18: |
1234 | size = 0; |
1235 | fw_name = "ngene_18.fw" ; |
1236 | break; |
1237 | } |
1238 | |
1239 | if (request_firmware(fw: &fw, name: fw_name, device: &dev->pci_dev->dev) < 0) { |
1240 | dev_err(pdev, "Could not load firmware file %s.\n" , fw_name); |
1241 | dev_info(pdev, "Copy %s to your hotplug directory!\n" , |
1242 | fw_name); |
1243 | return -1; |
1244 | } |
1245 | if (size == 0) |
1246 | size = fw->size; |
1247 | if (size != fw->size) { |
1248 | dev_err(pdev, "Firmware %s has invalid size!" , fw_name); |
1249 | err = -1; |
1250 | } else { |
1251 | dev_info(pdev, "Loading firmware file %s.\n" , fw_name); |
1252 | ngene_fw = (u8 *) fw->data; |
1253 | err = ngene_command_load_firmware(dev, ngene_fw, size); |
1254 | } |
1255 | |
1256 | release_firmware(fw); |
1257 | |
1258 | return err; |
1259 | } |
1260 | |
1261 | static void ngene_stop(struct ngene *dev) |
1262 | { |
1263 | mutex_destroy(lock: &dev->cmd_mutex); |
1264 | i2c_del_adapter(adap: &(dev->channel[0].i2c_adapter)); |
1265 | i2c_del_adapter(adap: &(dev->channel[1].i2c_adapter)); |
1266 | ngwritel(0, NGENE_INT_ENABLE); |
1267 | ngwritel(0, NGENE_COMMAND); |
1268 | ngwritel(0, NGENE_COMMAND_HI); |
1269 | ngwritel(0, NGENE_STATUS); |
1270 | ngwritel(0, NGENE_STATUS_HI); |
1271 | ngwritel(0, NGENE_EVENT); |
1272 | ngwritel(0, NGENE_EVENT_HI); |
1273 | free_irq(dev->pci_dev->irq, dev); |
1274 | #ifdef CONFIG_PCI_MSI |
1275 | if (dev->msi_enabled) |
1276 | pci_disable_msi(dev: dev->pci_dev); |
1277 | #endif |
1278 | } |
1279 | |
1280 | static int ngene_buffer_config(struct ngene *dev) |
1281 | { |
1282 | int stat; |
1283 | |
1284 | if (dev->card_info->fw_version >= 17) { |
1285 | u8 tsin12_config[6] = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 }; |
1286 | u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 }; |
1287 | u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 }; |
1288 | u8 *bconf = tsin12_config; |
1289 | |
1290 | if (dev->card_info->io_type[2]&NGENE_IO_TSIN && |
1291 | dev->card_info->io_type[3]&NGENE_IO_TSIN) { |
1292 | bconf = tsin1234_config; |
1293 | if (dev->card_info->io_type[4]&NGENE_IO_TSOUT && |
1294 | dev->ci.en) |
1295 | bconf = tsio1235_config; |
1296 | } |
1297 | stat = ngene_command_config_free_buf(dev, config: bconf); |
1298 | } else { |
1299 | int bconf = BUFFER_CONFIG_4422; |
1300 | |
1301 | if (dev->card_info->io_type[3] == NGENE_IO_TSIN) |
1302 | bconf = BUFFER_CONFIG_3333; |
1303 | stat = ngene_command_config_buf(dev, config: bconf); |
1304 | } |
1305 | return stat; |
1306 | } |
1307 | |
1308 | |
1309 | static int ngene_start(struct ngene *dev) |
1310 | { |
1311 | int stat; |
1312 | int i; |
1313 | |
1314 | pci_set_master(dev: dev->pci_dev); |
1315 | ngene_init(dev); |
1316 | |
1317 | stat = request_irq(irq: dev->pci_dev->irq, handler: irq_handler, |
1318 | IRQF_SHARED, name: "nGene" , |
1319 | dev: (void *)dev); |
1320 | if (stat < 0) |
1321 | return stat; |
1322 | |
1323 | init_waitqueue_head(&dev->cmd_wq); |
1324 | init_waitqueue_head(&dev->tx_wq); |
1325 | init_waitqueue_head(&dev->rx_wq); |
1326 | mutex_init(&dev->cmd_mutex); |
1327 | mutex_init(&dev->stream_mutex); |
1328 | sema_init(sem: &dev->pll_mutex, val: 1); |
1329 | mutex_init(&dev->i2c_switch_mutex); |
1330 | spin_lock_init(&dev->cmd_lock); |
1331 | for (i = 0; i < MAX_STREAM; i++) |
1332 | spin_lock_init(&dev->channel[i].state_lock); |
1333 | ngwritel(1, TIMESTAMPS); |
1334 | |
1335 | ngwritel(1, NGENE_INT_ENABLE); |
1336 | |
1337 | stat = ngene_load_firm(dev); |
1338 | if (stat < 0) |
1339 | goto fail; |
1340 | |
1341 | #ifdef CONFIG_PCI_MSI |
1342 | /* enable MSI if kernel and card support it */ |
1343 | if (pci_msi_enabled() && dev->card_info->msi_supported) { |
1344 | struct device *pdev = &dev->pci_dev->dev; |
1345 | unsigned long flags; |
1346 | |
1347 | ngwritel(0, NGENE_INT_ENABLE); |
1348 | free_irq(dev->pci_dev->irq, dev); |
1349 | stat = pci_enable_msi(dev: dev->pci_dev); |
1350 | if (stat) { |
1351 | dev_info(pdev, "MSI not available\n" ); |
1352 | flags = IRQF_SHARED; |
1353 | } else { |
1354 | flags = 0; |
1355 | dev->msi_enabled = true; |
1356 | } |
1357 | stat = request_irq(irq: dev->pci_dev->irq, handler: irq_handler, |
1358 | flags, name: "nGene" , dev); |
1359 | if (stat < 0) |
1360 | goto fail2; |
1361 | ngwritel(1, NGENE_INT_ENABLE); |
1362 | } |
1363 | #endif |
1364 | |
1365 | stat = ngene_i2c_init(dev, dev_nr: 0); |
1366 | if (stat < 0) |
1367 | goto fail; |
1368 | |
1369 | stat = ngene_i2c_init(dev, dev_nr: 1); |
1370 | if (stat < 0) |
1371 | goto fail; |
1372 | |
1373 | return 0; |
1374 | |
1375 | fail: |
1376 | ngwritel(0, NGENE_INT_ENABLE); |
1377 | free_irq(dev->pci_dev->irq, dev); |
1378 | #ifdef CONFIG_PCI_MSI |
1379 | fail2: |
1380 | if (dev->msi_enabled) |
1381 | pci_disable_msi(dev: dev->pci_dev); |
1382 | #endif |
1383 | return stat; |
1384 | } |
1385 | |
1386 | /****************************************************************************/ |
1387 | /****************************************************************************/ |
1388 | /****************************************************************************/ |
1389 | |
1390 | static void release_channel(struct ngene_channel *chan) |
1391 | { |
1392 | struct dvb_demux *dvbdemux = &chan->demux; |
1393 | struct ngene *dev = chan->dev; |
1394 | |
1395 | if (chan->running) |
1396 | set_transfer(chan, state: 0); |
1397 | |
1398 | tasklet_kill(t: &chan->demux_tasklet); |
1399 | |
1400 | if (chan->ci_dev) { |
1401 | dvb_unregister_device(dvbdev: chan->ci_dev); |
1402 | chan->ci_dev = NULL; |
1403 | } |
1404 | |
1405 | if (chan->fe2) |
1406 | dvb_unregister_frontend(fe: chan->fe2); |
1407 | |
1408 | if (chan->fe) { |
1409 | dvb_unregister_frontend(fe: chan->fe); |
1410 | |
1411 | /* release I2C client (tuner) if needed */ |
1412 | if (chan->i2c_client_fe) { |
1413 | dvb_module_release(client: chan->i2c_client[0]); |
1414 | chan->i2c_client[0] = NULL; |
1415 | } |
1416 | |
1417 | dvb_frontend_detach(fe: chan->fe); |
1418 | chan->fe = NULL; |
1419 | } |
1420 | |
1421 | if (chan->has_demux) { |
1422 | dvb_net_release(dvbnet: &chan->dvbnet); |
1423 | dvbdemux->dmx.close(&dvbdemux->dmx); |
1424 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, |
1425 | &chan->hw_frontend); |
1426 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, |
1427 | &chan->mem_frontend); |
1428 | dvb_dmxdev_release(dmxdev: &chan->dmxdev); |
1429 | dvb_dmx_release(demux: &chan->demux); |
1430 | chan->has_demux = false; |
1431 | } |
1432 | |
1433 | if (chan->has_adapter) { |
1434 | dvb_unregister_adapter(adap: &dev->adapter[chan->number]); |
1435 | chan->has_adapter = false; |
1436 | } |
1437 | } |
1438 | |
1439 | static int init_channel(struct ngene_channel *chan) |
1440 | { |
1441 | int ret = 0, nr = chan->number; |
1442 | struct dvb_adapter *adapter = NULL; |
1443 | struct dvb_demux *dvbdemux = &chan->demux; |
1444 | struct ngene *dev = chan->dev; |
1445 | struct ngene_info *ni = dev->card_info; |
1446 | int io = ni->io_type[nr]; |
1447 | |
1448 | tasklet_setup(t: &chan->demux_tasklet, callback: demux_tasklet); |
1449 | chan->users = 0; |
1450 | chan->type = io; |
1451 | chan->mode = chan->type; /* for now only one mode */ |
1452 | chan->i2c_client_fe = 0; /* be sure this is set to zero */ |
1453 | |
1454 | if (io & NGENE_IO_TSIN) { |
1455 | chan->fe = NULL; |
1456 | if (ni->demod_attach[nr]) { |
1457 | ret = ni->demod_attach[nr](chan); |
1458 | if (ret < 0) |
1459 | goto err; |
1460 | } |
1461 | if (chan->fe && ni->tuner_attach[nr]) { |
1462 | ret = ni->tuner_attach[nr](chan); |
1463 | if (ret < 0) |
1464 | goto err; |
1465 | } |
1466 | } |
1467 | |
1468 | if (!dev->ci.en && (io & NGENE_IO_TSOUT)) |
1469 | return 0; |
1470 | |
1471 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { |
1472 | if (nr >= STREAM_AUDIOIN1) |
1473 | chan->DataFormatFlags = DF_SWAP32; |
1474 | |
1475 | if (nr == 0 || !one_adapter || dev->first_adapter == NULL) { |
1476 | adapter = &dev->adapter[nr]; |
1477 | ret = dvb_register_adapter(adap: adapter, name: "nGene" , |
1478 | THIS_MODULE, |
1479 | device: &chan->dev->pci_dev->dev, |
1480 | adapter_nums: adapter_nr); |
1481 | if (ret < 0) |
1482 | goto err; |
1483 | if (dev->first_adapter == NULL) |
1484 | dev->first_adapter = adapter; |
1485 | chan->has_adapter = true; |
1486 | } else |
1487 | adapter = dev->first_adapter; |
1488 | } |
1489 | |
1490 | if (dev->ci.en && (io & NGENE_IO_TSOUT)) { |
1491 | dvb_ca_en50221_init(dvb_adapter: adapter, ca: dev->ci.en, flags: 0, slot_count: 1); |
1492 | set_transfer(chan, state: 1); |
1493 | chan->dev->channel[2].DataFormatFlags = DF_SWAP32; |
1494 | set_transfer(chan: &chan->dev->channel[2], state: 1); |
1495 | dvb_register_device(adap: adapter, pdvbdev: &chan->ci_dev, |
1496 | template: &ngene_dvbdev_ci, priv: (void *) chan, |
1497 | type: DVB_DEVICE_SEC, demux_sink_pads: 0); |
1498 | if (!chan->ci_dev) |
1499 | goto err; |
1500 | } |
1501 | |
1502 | if (chan->fe) { |
1503 | if (dvb_register_frontend(dvb: adapter, fe: chan->fe) < 0) |
1504 | goto err; |
1505 | chan->has_demux = true; |
1506 | } |
1507 | if (chan->fe2) { |
1508 | if (dvb_register_frontend(dvb: adapter, fe: chan->fe2) < 0) |
1509 | goto err; |
1510 | if (chan->fe) { |
1511 | chan->fe2->tuner_priv = chan->fe->tuner_priv; |
1512 | memcpy(&chan->fe2->ops.tuner_ops, |
1513 | &chan->fe->ops.tuner_ops, |
1514 | sizeof(struct dvb_tuner_ops)); |
1515 | } |
1516 | } |
1517 | |
1518 | if (chan->has_demux) { |
1519 | ret = my_dvb_dmx_ts_card_init(dvbdemux, id: "SW demux" , |
1520 | start_feed: ngene_start_feed, |
1521 | stop_feed: ngene_stop_feed, priv: chan); |
1522 | ret = my_dvb_dmxdev_ts_card_init(dmxdev: &chan->dmxdev, dvbdemux: &chan->demux, |
1523 | hw_frontend: &chan->hw_frontend, |
1524 | mem_frontend: &chan->mem_frontend, dvb_adapter: adapter); |
1525 | ret = dvb_net_init(adap: adapter, dvbnet: &chan->dvbnet, dmxdemux: &chan->demux.dmx); |
1526 | } |
1527 | |
1528 | return ret; |
1529 | |
1530 | err: |
1531 | if (chan->fe) { |
1532 | dvb_frontend_detach(fe: chan->fe); |
1533 | chan->fe = NULL; |
1534 | } |
1535 | release_channel(chan); |
1536 | return 0; |
1537 | } |
1538 | |
1539 | static int init_channels(struct ngene *dev) |
1540 | { |
1541 | int i, j; |
1542 | |
1543 | for (i = 0; i < MAX_STREAM; i++) { |
1544 | dev->channel[i].number = i; |
1545 | if (init_channel(chan: &dev->channel[i]) < 0) { |
1546 | for (j = i - 1; j >= 0; j--) |
1547 | release_channel(chan: &dev->channel[j]); |
1548 | return -1; |
1549 | } |
1550 | } |
1551 | return 0; |
1552 | } |
1553 | |
1554 | static const struct cxd2099_cfg cxd_cfgtmpl = { |
1555 | .bitrate = 62000, |
1556 | .polarity = 0, |
1557 | .clock_mode = 0, |
1558 | }; |
1559 | |
1560 | static void cxd_attach(struct ngene *dev) |
1561 | { |
1562 | struct device *pdev = &dev->pci_dev->dev; |
1563 | struct ngene_ci *ci = &dev->ci; |
1564 | struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl; |
1565 | struct i2c_client *client; |
1566 | int ret; |
1567 | u8 type; |
1568 | |
1569 | /* check for CXD2099AR presence before attaching */ |
1570 | ret = ngene_port_has_cxd2099(i2c: &dev->channel[0].i2c_adapter, type: &type); |
1571 | if (!ret) { |
1572 | dev_dbg(pdev, "No CXD2099AR found\n" ); |
1573 | return; |
1574 | } |
1575 | |
1576 | if (type != 1) { |
1577 | dev_warn(pdev, "CXD2099AR is uninitialized!\n" ); |
1578 | return; |
1579 | } |
1580 | |
1581 | cxd_cfg.en = &ci->en; |
1582 | client = dvb_module_probe(module_name: "cxd2099" , NULL, |
1583 | adap: &dev->channel[0].i2c_adapter, |
1584 | addr: 0x40, platform_data: &cxd_cfg); |
1585 | if (!client) |
1586 | goto err; |
1587 | |
1588 | ci->dev = dev; |
1589 | dev->channel[0].i2c_client[0] = client; |
1590 | return; |
1591 | |
1592 | err: |
1593 | dev_err(pdev, "CXD2099AR attach failed\n" ); |
1594 | return; |
1595 | } |
1596 | |
1597 | static void cxd_detach(struct ngene *dev) |
1598 | { |
1599 | struct ngene_ci *ci = &dev->ci; |
1600 | |
1601 | dvb_ca_en50221_release(ca: ci->en); |
1602 | |
1603 | dvb_module_release(client: dev->channel[0].i2c_client[0]); |
1604 | dev->channel[0].i2c_client[0] = NULL; |
1605 | ci->en = NULL; |
1606 | } |
1607 | |
1608 | /***********************************/ |
1609 | /* workaround for shutdown failure */ |
1610 | /***********************************/ |
1611 | |
1612 | static void ngene_unlink(struct ngene *dev) |
1613 | { |
1614 | struct ngene_command com; |
1615 | |
1616 | com.cmd.hdr.Opcode = CMD_MEM_WRITE; |
1617 | com.cmd.hdr.Length = 3; |
1618 | com.cmd.MemoryWrite.address = 0x910c; |
1619 | com.cmd.MemoryWrite.data = 0xff; |
1620 | com.in_len = 3; |
1621 | com.out_len = 1; |
1622 | |
1623 | mutex_lock(&dev->cmd_mutex); |
1624 | ngwritel(0, NGENE_INT_ENABLE); |
1625 | ngene_command_mutex(dev, com: &com); |
1626 | mutex_unlock(lock: &dev->cmd_mutex); |
1627 | } |
1628 | |
1629 | void ngene_shutdown(struct pci_dev *pdev) |
1630 | { |
1631 | struct ngene *dev = pci_get_drvdata(pdev); |
1632 | |
1633 | if (!dev || !shutdown_workaround) |
1634 | return; |
1635 | |
1636 | dev_info(&pdev->dev, "shutdown workaround...\n" ); |
1637 | ngene_unlink(dev); |
1638 | pci_disable_device(dev: pdev); |
1639 | } |
1640 | |
1641 | /****************************************************************************/ |
1642 | /* device probe/remove calls ************************************************/ |
1643 | /****************************************************************************/ |
1644 | |
1645 | void ngene_remove(struct pci_dev *pdev) |
1646 | { |
1647 | struct ngene *dev = pci_get_drvdata(pdev); |
1648 | int i; |
1649 | |
1650 | tasklet_kill(t: &dev->event_tasklet); |
1651 | for (i = MAX_STREAM - 1; i >= 0; i--) |
1652 | release_channel(chan: &dev->channel[i]); |
1653 | if (dev->ci.en) |
1654 | cxd_detach(dev); |
1655 | ngene_stop(dev); |
1656 | ngene_release_buffers(dev); |
1657 | pci_disable_device(dev: pdev); |
1658 | } |
1659 | |
1660 | int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) |
1661 | { |
1662 | struct ngene *dev; |
1663 | int stat = 0; |
1664 | |
1665 | if (pci_enable_device(dev: pci_dev) < 0) |
1666 | return -ENODEV; |
1667 | |
1668 | dev = vzalloc(size: sizeof(struct ngene)); |
1669 | if (dev == NULL) { |
1670 | stat = -ENOMEM; |
1671 | goto fail0; |
1672 | } |
1673 | |
1674 | dev->pci_dev = pci_dev; |
1675 | dev->card_info = (struct ngene_info *)id->driver_data; |
1676 | dev_info(&pci_dev->dev, "Found %s\n" , dev->card_info->name); |
1677 | |
1678 | pci_set_drvdata(pdev: pci_dev, data: dev); |
1679 | |
1680 | /* Alloc buffers and start nGene */ |
1681 | stat = ngene_get_buffers(dev); |
1682 | if (stat < 0) |
1683 | goto fail1; |
1684 | stat = ngene_start(dev); |
1685 | if (stat < 0) |
1686 | goto fail1; |
1687 | |
1688 | cxd_attach(dev); |
1689 | |
1690 | stat = ngene_buffer_config(dev); |
1691 | if (stat < 0) |
1692 | goto fail1; |
1693 | |
1694 | |
1695 | dev->i2c_current_bus = -1; |
1696 | |
1697 | /* Register DVB adapters and devices for both channels */ |
1698 | stat = init_channels(dev); |
1699 | if (stat < 0) |
1700 | goto fail2; |
1701 | |
1702 | return 0; |
1703 | |
1704 | fail2: |
1705 | ngene_stop(dev); |
1706 | fail1: |
1707 | ngene_release_buffers(dev); |
1708 | fail0: |
1709 | pci_disable_device(dev: pci_dev); |
1710 | return stat; |
1711 | } |
1712 | |