blob: ff76f64edac1e196f8c276e543fff216669cc445 [file] [log] [blame]
Steven Tothd19770e2007-03-11 20:44:05 -03001/*
2 * Driver for the Conexant CX23885 PCIe bridge
3 *
Steven Toth6d897612008-09-03 17:12:12 -03004 * Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
Steven Tothd19770e2007-03-11 20:44:05 -03005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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 *
15 * GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/init.h>
23#include <linux/list.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/kmod.h>
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <asm/div64.h>
32
33#include "cx23885.h"
Igor M. Liplianin5a23b0762009-03-03 12:06:09 -030034#include "cimax2.h"
Andy Walls29f8a0a2009-09-26 23:17:30 -030035#include "cx23888-ir.h"
Andy Wallsf59ad612009-09-27 19:51:50 -030036#include "cx23885-ir.h"
Andy Wallsdbda8f72009-09-27 20:55:41 -030037#include "cx23885-input.h"
Steven Tothd19770e2007-03-11 20:44:05 -030038
39MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
Steven Toth6d897612008-09-03 17:12:12 -030040MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
Steven Tothd19770e2007-03-11 20:44:05 -030041MODULE_LICENSE("GPL");
42
Steven Toth4513fc692008-01-12 11:36:36 -030043static unsigned int debug;
Steven Toth9c8ced52008-10-16 20:18:44 -030044module_param(debug, int, 0644);
45MODULE_PARM_DESC(debug, "enable debug messages");
Steven Tothd19770e2007-03-11 20:44:05 -030046
47static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
48module_param_array(card, int, NULL, 0444);
Steven Toth9c8ced52008-10-16 20:18:44 -030049MODULE_PARM_DESC(card, "card type");
Steven Tothd19770e2007-03-11 20:44:05 -030050
Steven Toth4513fc692008-01-12 11:36:36 -030051#define dprintk(level, fmt, arg...)\
52 do { if (debug >= level)\
53 printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
54 } while (0)
Steven Tothd19770e2007-03-11 20:44:05 -030055
56static unsigned int cx23885_devcount;
57
Steven Tothd19770e2007-03-11 20:44:05 -030058#define NO_SYNC_LINE (-1U)
59
Steven Tothd19770e2007-03-11 20:44:05 -030060/* FIXME, these allocations will change when
61 * analog arrives. The be reviewed.
62 * CX23887 Assumptions
63 * 1 line = 16 bytes of CDT
64 * cmds size = 80
65 * cdt size = 16 * linesize
66 * iqsize = 64
67 * maxlines = 6
68 *
69 * Address Space:
70 * 0x00000000 0x00008fff FIFO clusters
71 * 0x00010000 0x000104af Channel Management Data Structures
72 * 0x000104b0 0x000104ff Free
73 * 0x00010500 0x000108bf 15 channels * iqsize
74 * 0x000108c0 0x000108ff Free
75 * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables
76 * 15 channels * (iqsize + (maxlines * linesize))
77 * 0x00010ea0 0x00010xxx Free
78 */
79
Steven Toth7e994302008-07-01 21:18:00 -030080static struct sram_channel cx23885_sram_channels[] = {
Steven Tothd19770e2007-03-11 20:44:05 -030081 [SRAM_CH01] = {
Steven Toth69ad6e52008-01-10 02:16:41 -030082 .name = "VID A",
83 .cmds_start = 0x10000,
Steven Tothd8d12b42008-07-01 10:43:27 -030084 .ctrl_start = 0x10380,
85 .cdt = 0x104c0,
Steven Toth69ad6e52008-01-10 02:16:41 -030086 .fifo_start = 0x40,
87 .fifo_size = 0x2800,
Steven Tothd19770e2007-03-11 20:44:05 -030088 .ptr1_reg = DMA1_PTR1,
89 .ptr2_reg = DMA1_PTR2,
90 .cnt1_reg = DMA1_CNT1,
91 .cnt2_reg = DMA1_CNT2,
92 },
93 [SRAM_CH02] = {
94 .name = "ch2",
95 .cmds_start = 0x0,
96 .ctrl_start = 0x0,
97 .cdt = 0x0,
98 .fifo_start = 0x0,
99 .fifo_size = 0x0,
100 .ptr1_reg = DMA2_PTR1,
101 .ptr2_reg = DMA2_PTR2,
102 .cnt1_reg = DMA2_CNT1,
103 .cnt2_reg = DMA2_CNT2,
104 },
105 [SRAM_CH03] = {
Steven Toth69ad6e52008-01-10 02:16:41 -0300106 .name = "TS1 B",
107 .cmds_start = 0x100A0,
Steven Tothd8d12b42008-07-01 10:43:27 -0300108 .ctrl_start = 0x10400,
109 .cdt = 0x10580,
Steven Toth69ad6e52008-01-10 02:16:41 -0300110 .fifo_start = 0x5000,
111 .fifo_size = 0x1000,
Steven Tothd19770e2007-03-11 20:44:05 -0300112 .ptr1_reg = DMA3_PTR1,
113 .ptr2_reg = DMA3_PTR2,
114 .cnt1_reg = DMA3_CNT1,
115 .cnt2_reg = DMA3_CNT2,
116 },
117 [SRAM_CH04] = {
118 .name = "ch4",
119 .cmds_start = 0x0,
120 .ctrl_start = 0x0,
121 .cdt = 0x0,
122 .fifo_start = 0x0,
123 .fifo_size = 0x0,
124 .ptr1_reg = DMA4_PTR1,
125 .ptr2_reg = DMA4_PTR2,
126 .cnt1_reg = DMA4_CNT1,
127 .cnt2_reg = DMA4_CNT2,
128 },
129 [SRAM_CH05] = {
130 .name = "ch5",
131 .cmds_start = 0x0,
132 .ctrl_start = 0x0,
133 .cdt = 0x0,
134 .fifo_start = 0x0,
135 .fifo_size = 0x0,
136 .ptr1_reg = DMA5_PTR1,
137 .ptr2_reg = DMA5_PTR2,
138 .cnt1_reg = DMA5_CNT1,
139 .cnt2_reg = DMA5_CNT2,
140 },
141 [SRAM_CH06] = {
142 .name = "TS2 C",
143 .cmds_start = 0x10140,
Steven Tothd8d12b42008-07-01 10:43:27 -0300144 .ctrl_start = 0x10440,
145 .cdt = 0x105e0,
Steven Tothd19770e2007-03-11 20:44:05 -0300146 .fifo_start = 0x6000,
147 .fifo_size = 0x1000,
148 .ptr1_reg = DMA5_PTR1,
149 .ptr2_reg = DMA5_PTR2,
150 .cnt1_reg = DMA5_CNT1,
151 .cnt2_reg = DMA5_CNT2,
152 },
153 [SRAM_CH07] = {
154 .name = "ch7",
155 .cmds_start = 0x0,
156 .ctrl_start = 0x0,
157 .cdt = 0x0,
158 .fifo_start = 0x0,
159 .fifo_size = 0x0,
160 .ptr1_reg = DMA6_PTR1,
161 .ptr2_reg = DMA6_PTR2,
162 .cnt1_reg = DMA6_CNT1,
163 .cnt2_reg = DMA6_CNT2,
164 },
165 [SRAM_CH08] = {
166 .name = "ch8",
167 .cmds_start = 0x0,
168 .ctrl_start = 0x0,
169 .cdt = 0x0,
170 .fifo_start = 0x0,
171 .fifo_size = 0x0,
172 .ptr1_reg = DMA7_PTR1,
173 .ptr2_reg = DMA7_PTR2,
174 .cnt1_reg = DMA7_CNT1,
175 .cnt2_reg = DMA7_CNT2,
176 },
177 [SRAM_CH09] = {
178 .name = "ch9",
179 .cmds_start = 0x0,
180 .ctrl_start = 0x0,
181 .cdt = 0x0,
182 .fifo_start = 0x0,
183 .fifo_size = 0x0,
184 .ptr1_reg = DMA8_PTR1,
185 .ptr2_reg = DMA8_PTR2,
186 .cnt1_reg = DMA8_CNT1,
187 .cnt2_reg = DMA8_CNT2,
188 },
189};
190
Steven Toth7e994302008-07-01 21:18:00 -0300191static struct sram_channel cx23887_sram_channels[] = {
192 [SRAM_CH01] = {
193 .name = "VID A",
194 .cmds_start = 0x10000,
195 .ctrl_start = 0x105b0,
196 .cdt = 0x107b0,
197 .fifo_start = 0x40,
198 .fifo_size = 0x2800,
199 .ptr1_reg = DMA1_PTR1,
200 .ptr2_reg = DMA1_PTR2,
201 .cnt1_reg = DMA1_CNT1,
202 .cnt2_reg = DMA1_CNT2,
203 },
204 [SRAM_CH02] = {
205 .name = "ch2",
206 .cmds_start = 0x0,
207 .ctrl_start = 0x0,
208 .cdt = 0x0,
209 .fifo_start = 0x0,
210 .fifo_size = 0x0,
211 .ptr1_reg = DMA2_PTR1,
212 .ptr2_reg = DMA2_PTR2,
213 .cnt1_reg = DMA2_CNT1,
214 .cnt2_reg = DMA2_CNT2,
215 },
216 [SRAM_CH03] = {
217 .name = "TS1 B",
218 .cmds_start = 0x100A0,
219 .ctrl_start = 0x10630,
220 .cdt = 0x10870,
221 .fifo_start = 0x5000,
222 .fifo_size = 0x1000,
223 .ptr1_reg = DMA3_PTR1,
224 .ptr2_reg = DMA3_PTR2,
225 .cnt1_reg = DMA3_CNT1,
226 .cnt2_reg = DMA3_CNT2,
227 },
228 [SRAM_CH04] = {
229 .name = "ch4",
230 .cmds_start = 0x0,
231 .ctrl_start = 0x0,
232 .cdt = 0x0,
233 .fifo_start = 0x0,
234 .fifo_size = 0x0,
235 .ptr1_reg = DMA4_PTR1,
236 .ptr2_reg = DMA4_PTR2,
237 .cnt1_reg = DMA4_CNT1,
238 .cnt2_reg = DMA4_CNT2,
239 },
240 [SRAM_CH05] = {
241 .name = "ch5",
242 .cmds_start = 0x0,
243 .ctrl_start = 0x0,
244 .cdt = 0x0,
245 .fifo_start = 0x0,
246 .fifo_size = 0x0,
247 .ptr1_reg = DMA5_PTR1,
248 .ptr2_reg = DMA5_PTR2,
249 .cnt1_reg = DMA5_CNT1,
250 .cnt2_reg = DMA5_CNT2,
251 },
252 [SRAM_CH06] = {
253 .name = "TS2 C",
254 .cmds_start = 0x10140,
255 .ctrl_start = 0x10670,
256 .cdt = 0x108d0,
257 .fifo_start = 0x6000,
258 .fifo_size = 0x1000,
259 .ptr1_reg = DMA5_PTR1,
260 .ptr2_reg = DMA5_PTR2,
261 .cnt1_reg = DMA5_CNT1,
262 .cnt2_reg = DMA5_CNT2,
263 },
264 [SRAM_CH07] = {
265 .name = "ch7",
266 .cmds_start = 0x0,
267 .ctrl_start = 0x0,
268 .cdt = 0x0,
269 .fifo_start = 0x0,
270 .fifo_size = 0x0,
271 .ptr1_reg = DMA6_PTR1,
272 .ptr2_reg = DMA6_PTR2,
273 .cnt1_reg = DMA6_CNT1,
274 .cnt2_reg = DMA6_CNT2,
275 },
276 [SRAM_CH08] = {
277 .name = "ch8",
278 .cmds_start = 0x0,
279 .ctrl_start = 0x0,
280 .cdt = 0x0,
281 .fifo_start = 0x0,
282 .fifo_size = 0x0,
283 .ptr1_reg = DMA7_PTR1,
284 .ptr2_reg = DMA7_PTR2,
285 .cnt1_reg = DMA7_CNT1,
286 .cnt2_reg = DMA7_CNT2,
287 },
288 [SRAM_CH09] = {
289 .name = "ch9",
290 .cmds_start = 0x0,
291 .ctrl_start = 0x0,
292 .cdt = 0x0,
293 .fifo_start = 0x0,
294 .fifo_size = 0x0,
295 .ptr1_reg = DMA8_PTR1,
296 .ptr2_reg = DMA8_PTR2,
297 .cnt1_reg = DMA8_CNT1,
298 .cnt2_reg = DMA8_CNT2,
299 },
300};
301
Steven Tothd19770e2007-03-11 20:44:05 -0300302static int cx23885_risc_decode(u32 risc)
303{
304 static char *instr[16] = {
Steven Tothb1b81f12008-01-13 23:42:44 -0300305 [RISC_SYNC >> 28] = "sync",
306 [RISC_WRITE >> 28] = "write",
307 [RISC_WRITEC >> 28] = "writec",
308 [RISC_READ >> 28] = "read",
309 [RISC_READC >> 28] = "readc",
310 [RISC_JUMP >> 28] = "jump",
311 [RISC_SKIP >> 28] = "skip",
312 [RISC_WRITERM >> 28] = "writerm",
313 [RISC_WRITECM >> 28] = "writecm",
314 [RISC_WRITECR >> 28] = "writecr",
Steven Tothd19770e2007-03-11 20:44:05 -0300315 };
316 static int incr[16] = {
Steven Tothb1b81f12008-01-13 23:42:44 -0300317 [RISC_WRITE >> 28] = 3,
318 [RISC_JUMP >> 28] = 3,
319 [RISC_SKIP >> 28] = 1,
320 [RISC_SYNC >> 28] = 1,
321 [RISC_WRITERM >> 28] = 3,
322 [RISC_WRITECM >> 28] = 3,
323 [RISC_WRITECR >> 28] = 4,
Steven Tothd19770e2007-03-11 20:44:05 -0300324 };
325 static char *bits[] = {
326 "12", "13", "14", "resync",
327 "cnt0", "cnt1", "18", "19",
328 "20", "21", "22", "23",
329 "irq1", "irq2", "eol", "sol",
330 };
331 int i;
332
333 printk("0x%08x [ %s", risc,
334 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
Michael Krufky44a64812007-03-20 23:00:18 -0300335 for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
Steven Tothd19770e2007-03-11 20:44:05 -0300336 if (risc & (1 << (i + 12)))
Michael Krufky44a64812007-03-20 23:00:18 -0300337 printk(" %s", bits[i]);
Steven Tothd19770e2007-03-11 20:44:05 -0300338 printk(" count=%d ]\n", risc & 0xfff);
339 return incr[risc >> 28] ? incr[risc >> 28] : 1;
340}
341
Steven Toth7b888012008-01-10 03:40:49 -0300342void cx23885_wakeup(struct cx23885_tsport *port,
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300343 struct cx23885_dmaqueue *q, u32 count)
Steven Tothd19770e2007-03-11 20:44:05 -0300344{
345 struct cx23885_dev *dev = port->dev;
346 struct cx23885_buffer *buf;
347 int bc;
348
349 for (bc = 0;; bc++) {
350 if (list_empty(&q->active))
351 break;
352 buf = list_entry(q->active.next,
353 struct cx23885_buffer, vb.queue);
Steven Toth2e52f212007-09-04 21:32:41 -0300354
Steven Tothd19770e2007-03-11 20:44:05 -0300355 /* count comes from the hw and is is 16bit wide --
356 * this trick handles wrap-arounds correctly for
357 * up to 32767 buffers in flight... */
358 if ((s16) (count - buf->count) < 0)
359 break;
Steven Toth2e52f212007-09-04 21:32:41 -0300360
Steven Tothd19770e2007-03-11 20:44:05 -0300361 do_gettimeofday(&buf->vb.ts);
Michael Krufky44a64812007-03-20 23:00:18 -0300362 dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
Steven Tothd19770e2007-03-11 20:44:05 -0300363 count, buf->count);
Brandon Philips0fc06862007-11-06 20:02:36 -0300364 buf->vb.state = VIDEOBUF_DONE;
Steven Tothd19770e2007-03-11 20:44:05 -0300365 list_del(&buf->vb.queue);
366 wake_up(&buf->vb.done);
367 }
Steven Toth9c8ced52008-10-16 20:18:44 -0300368 if (list_empty(&q->active))
Steven Tothd19770e2007-03-11 20:44:05 -0300369 del_timer(&q->timeout);
Steven Toth9c8ced52008-10-16 20:18:44 -0300370 else
Michael Krufky44a64812007-03-20 23:00:18 -0300371 mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
Steven Tothd19770e2007-03-11 20:44:05 -0300372 if (bc != 1)
Steven Toth9c8ced52008-10-16 20:18:44 -0300373 printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300374 __func__, bc);
Steven Tothd19770e2007-03-11 20:44:05 -0300375}
Steven Tothd19770e2007-03-11 20:44:05 -0300376
Steven Toth7b888012008-01-10 03:40:49 -0300377int cx23885_sram_channel_setup(struct cx23885_dev *dev,
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300378 struct sram_channel *ch,
379 unsigned int bpl, u32 risc)
Steven Tothd19770e2007-03-11 20:44:05 -0300380{
Michael Krufky44a64812007-03-20 23:00:18 -0300381 unsigned int i, lines;
Steven Tothd19770e2007-03-11 20:44:05 -0300382 u32 cdt;
383
Steven Toth9c8ced52008-10-16 20:18:44 -0300384 if (ch->cmds_start == 0) {
Harvey Harrison22b4e642008-04-08 23:20:00 -0300385 dprintk(1, "%s() Erasing channel [%s]\n", __func__,
Michael Krufky44a64812007-03-20 23:00:18 -0300386 ch->name);
Steven Tothd19770e2007-03-11 20:44:05 -0300387 cx_write(ch->ptr1_reg, 0);
388 cx_write(ch->ptr2_reg, 0);
389 cx_write(ch->cnt2_reg, 0);
390 cx_write(ch->cnt1_reg, 0);
391 return 0;
392 } else {
Harvey Harrison22b4e642008-04-08 23:20:00 -0300393 dprintk(1, "%s() Configuring channel [%s]\n", __func__,
Michael Krufky44a64812007-03-20 23:00:18 -0300394 ch->name);
Steven Tothd19770e2007-03-11 20:44:05 -0300395 }
396
397 bpl = (bpl + 7) & ~7; /* alignment */
398 cdt = ch->cdt;
399 lines = ch->fifo_size / bpl;
400 if (lines > 6)
401 lines = 6;
402 BUG_ON(lines < 2);
403
Al Viro86ecc022008-06-22 14:19:59 -0300404 cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
405 cx_write(8 + 4, 8);
406 cx_write(8 + 8, 0);
Steven Tothd19770e2007-03-11 20:44:05 -0300407
408 /* write CDT */
409 for (i = 0; i < lines; i++) {
Harvey Harrison22b4e642008-04-08 23:20:00 -0300410 dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
Michael Krufky44a64812007-03-20 23:00:18 -0300411 ch->fifo_start + bpl*i);
Steven Tothd19770e2007-03-11 20:44:05 -0300412 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
413 cx_write(cdt + 16*i + 4, 0);
414 cx_write(cdt + 16*i + 8, 0);
415 cx_write(cdt + 16*i + 12, 0);
416 }
417
418 /* write CMDS */
419 if (ch->jumponly)
Steven Toth9c8ced52008-10-16 20:18:44 -0300420 cx_write(ch->cmds_start + 0, 8);
Steven Tothd19770e2007-03-11 20:44:05 -0300421 else
Steven Toth9c8ced52008-10-16 20:18:44 -0300422 cx_write(ch->cmds_start + 0, risc);
Steven Tothd19770e2007-03-11 20:44:05 -0300423 cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
424 cx_write(ch->cmds_start + 8, cdt);
425 cx_write(ch->cmds_start + 12, (lines*16) >> 3);
426 cx_write(ch->cmds_start + 16, ch->ctrl_start);
427 if (ch->jumponly)
Steven Toth9c8ced52008-10-16 20:18:44 -0300428 cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
Steven Tothd19770e2007-03-11 20:44:05 -0300429 else
430 cx_write(ch->cmds_start + 20, 64 >> 2);
431 for (i = 24; i < 80; i += 4)
432 cx_write(ch->cmds_start + i, 0);
433
434 /* fill registers */
435 cx_write(ch->ptr1_reg, ch->fifo_start);
436 cx_write(ch->ptr2_reg, cdt);
437 cx_write(ch->cnt2_reg, (lines*16) >> 3);
Steven Toth9c8ced52008-10-16 20:18:44 -0300438 cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
Steven Tothd19770e2007-03-11 20:44:05 -0300439
Steven Toth9c8ced52008-10-16 20:18:44 -0300440 dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
Steven Tothe133be02007-03-19 19:22:41 -0300441 dev->bridge,
Steven Tothd19770e2007-03-11 20:44:05 -0300442 ch->name,
443 bpl,
444 lines);
445
446 return 0;
447}
448
Steven Toth7b888012008-01-10 03:40:49 -0300449void cx23885_sram_channel_dump(struct cx23885_dev *dev,
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300450 struct sram_channel *ch)
Steven Tothd19770e2007-03-11 20:44:05 -0300451{
452 static char *name[] = {
453 "init risc lo",
454 "init risc hi",
455 "cdt base",
456 "cdt size",
457 "iq base",
458 "iq size",
459 "risc pc lo",
460 "risc pc hi",
461 "iq wr ptr",
462 "iq rd ptr",
463 "cdt current",
464 "pci target lo",
465 "pci target hi",
466 "line / byte",
467 };
468 u32 risc;
Michael Krufky44a64812007-03-20 23:00:18 -0300469 unsigned int i, j, n;
Steven Tothd19770e2007-03-11 20:44:05 -0300470
Steven Toth9c8ced52008-10-16 20:18:44 -0300471 printk(KERN_WARNING "%s: %s - dma channel status dump\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300472 dev->name, ch->name);
473 for (i = 0; i < ARRAY_SIZE(name); i++)
Steven Toth9c8ced52008-10-16 20:18:44 -0300474 printk(KERN_WARNING "%s: cmds: %-15s: 0x%08x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300475 dev->name, name[i],
476 cx_read(ch->cmds_start + 4*i));
477
478 for (i = 0; i < 4; i++) {
Michael Krufky44a64812007-03-20 23:00:18 -0300479 risc = cx_read(ch->cmds_start + 4 * (i + 14));
Steven Toth9c8ced52008-10-16 20:18:44 -0300480 printk(KERN_WARNING "%s: risc%d: ", dev->name, i);
Steven Tothd19770e2007-03-11 20:44:05 -0300481 cx23885_risc_decode(risc);
482 }
483 for (i = 0; i < (64 >> 2); i += n) {
Michael Krufky44a64812007-03-20 23:00:18 -0300484 risc = cx_read(ch->ctrl_start + 4 * i);
485 /* No consideration for bits 63-32 */
486
Steven Toth9c8ced52008-10-16 20:18:44 -0300487 printk(KERN_WARNING "%s: (0x%08x) iq %x: ", dev->name,
Michael Krufky44a64812007-03-20 23:00:18 -0300488 ch->ctrl_start + 4 * i, i);
Steven Tothd19770e2007-03-11 20:44:05 -0300489 n = cx23885_risc_decode(risc);
490 for (j = 1; j < n; j++) {
Michael Krufky44a64812007-03-20 23:00:18 -0300491 risc = cx_read(ch->ctrl_start + 4 * (i + j));
Steven Toth9c8ced52008-10-16 20:18:44 -0300492 printk(KERN_WARNING "%s: iq %x: 0x%08x [ arg #%d ]\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300493 dev->name, i+j, risc, j);
494 }
495 }
496
Steven Toth9c8ced52008-10-16 20:18:44 -0300497 printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300498 dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
Steven Toth9c8ced52008-10-16 20:18:44 -0300499 printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
Michael Krufky44a64812007-03-20 23:00:18 -0300500 dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
Steven Toth9c8ced52008-10-16 20:18:44 -0300501 printk(KERN_WARNING "%s: ptr1_reg: 0x%08x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300502 dev->name, cx_read(ch->ptr1_reg));
Steven Toth9c8ced52008-10-16 20:18:44 -0300503 printk(KERN_WARNING "%s: ptr2_reg: 0x%08x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300504 dev->name, cx_read(ch->ptr2_reg));
Steven Toth9c8ced52008-10-16 20:18:44 -0300505 printk(KERN_WARNING "%s: cnt1_reg: 0x%08x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300506 dev->name, cx_read(ch->cnt1_reg));
Steven Toth9c8ced52008-10-16 20:18:44 -0300507 printk(KERN_WARNING "%s: cnt2_reg: 0x%08x\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300508 dev->name, cx_read(ch->cnt2_reg));
509}
510
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300511static void cx23885_risc_disasm(struct cx23885_tsport *port,
512 struct btcx_riscmem *risc)
Steven Tothd19770e2007-03-11 20:44:05 -0300513{
514 struct cx23885_dev *dev = port->dev;
Michael Krufky44a64812007-03-20 23:00:18 -0300515 unsigned int i, j, n;
Steven Tothd19770e2007-03-11 20:44:05 -0300516
Steven Toth9c8ced52008-10-16 20:18:44 -0300517 printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
Steven Tothd19770e2007-03-11 20:44:05 -0300518 dev->name, risc->cpu, (unsigned long)risc->dma);
519 for (i = 0; i < (risc->size >> 2); i += n) {
Steven Toth9c8ced52008-10-16 20:18:44 -0300520 printk(KERN_INFO "%s: %04d: ", dev->name, i);
Al Viro86ecc022008-06-22 14:19:59 -0300521 n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
Steven Tothd19770e2007-03-11 20:44:05 -0300522 for (j = 1; j < n; j++)
Steven Toth9c8ced52008-10-16 20:18:44 -0300523 printk(KERN_INFO "%s: %04d: 0x%08x [ arg #%d ]\n",
Michael Krufky44a64812007-03-20 23:00:18 -0300524 dev->name, i + j, risc->cpu[i + j], j);
Al Viro86ecc022008-06-22 14:19:59 -0300525 if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
Steven Tothd19770e2007-03-11 20:44:05 -0300526 break;
527 }
528}
529
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300530static void cx23885_shutdown(struct cx23885_dev *dev)
Steven Tothd19770e2007-03-11 20:44:05 -0300531{
532 /* disable RISC controller */
533 cx_write(DEV_CNTRL2, 0);
534
535 /* Disable all IR activity */
536 cx_write(IR_CNTRL_REG, 0);
537
538 /* Disable Video A/B activity */
539 cx_write(VID_A_DMA_CTL, 0);
540 cx_write(VID_B_DMA_CTL, 0);
541 cx_write(VID_C_DMA_CTL, 0);
542
543 /* Disable Audio activity */
544 cx_write(AUD_INT_DMA_CTL, 0);
545 cx_write(AUD_EXT_DMA_CTL, 0);
546
547 /* Disable Serial port */
548 cx_write(UART_CTL, 0);
549
550 /* Disable Interrupts */
551 cx_write(PCI_INT_MSK, 0);
552 cx_write(VID_A_INT_MSK, 0);
553 cx_write(VID_B_INT_MSK, 0);
554 cx_write(VID_C_INT_MSK, 0);
555 cx_write(AUDIO_INT_INT_MSK, 0);
556 cx_write(AUDIO_EXT_INT_MSK, 0);
557
558}
559
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300560static void cx23885_reset(struct cx23885_dev *dev)
Steven Tothd19770e2007-03-11 20:44:05 -0300561{
Harvey Harrison22b4e642008-04-08 23:20:00 -0300562 dprintk(1, "%s()\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -0300563
564 cx23885_shutdown(dev);
565
566 cx_write(PCI_INT_STAT, 0xffffffff);
567 cx_write(VID_A_INT_STAT, 0xffffffff);
568 cx_write(VID_B_INT_STAT, 0xffffffff);
569 cx_write(VID_C_INT_STAT, 0xffffffff);
570 cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
571 cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
572 cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
Steven Tothecda5962008-06-28 00:52:45 -0300573 cx_write(PAD_CTRL, 0x00500300);
Steven Tothd19770e2007-03-11 20:44:05 -0300574
575 mdelay(100);
576
Steven Toth7b888012008-01-10 03:40:49 -0300577 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
578 720*4, 0);
579 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0);
580 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03],
581 188*4, 0);
582 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0);
583 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0);
584 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06],
585 188*4, 0);
586 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0);
587 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0);
588 cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
Steven Tothd19770e2007-03-11 20:44:05 -0300589
Steven Totha6a3f142007-09-08 21:31:56 -0300590 cx23885_gpio_setup(dev);
Steven Tothd19770e2007-03-11 20:44:05 -0300591}
592
593
594static int cx23885_pci_quirks(struct cx23885_dev *dev)
595{
Harvey Harrison22b4e642008-04-08 23:20:00 -0300596 dprintk(1, "%s()\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -0300597
Steven Toth2df9a4c2007-09-04 21:50:49 -0300598 /* The cx23885 bridge has a weird bug which causes NMI to be asserted
599 * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
600 * occur on the cx23887 bridge.
601 */
Steven Toth9c8ced52008-10-16 20:18:44 -0300602 if (dev->bridge == CX23885_BRIDGE_885)
Steven Tothd19770e2007-03-11 20:44:05 -0300603 cx_clear(RDR_TLCTL0, 1 << 4);
Steven Toth4823e9e2007-08-22 20:52:21 -0300604
Steven Tothd19770e2007-03-11 20:44:05 -0300605 return 0;
606}
607
608static int get_resources(struct cx23885_dev *dev)
609{
Steven Toth9c8ced52008-10-16 20:18:44 -0300610 if (request_mem_region(pci_resource_start(dev->pci, 0),
611 pci_resource_len(dev->pci, 0),
Michael Krufky44a64812007-03-20 23:00:18 -0300612 dev->name))
Steven Tothd19770e2007-03-11 20:44:05 -0300613 return 0;
614
615 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
Steven Toth9c8ced52008-10-16 20:18:44 -0300616 dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
Steven Tothd19770e2007-03-11 20:44:05 -0300617
618 return -EBUSY;
619}
620
621static void cx23885_timeout(unsigned long data);
Steven Toth7b888012008-01-10 03:40:49 -0300622int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300623 u32 reg, u32 mask, u32 value);
Steven Tothd19770e2007-03-11 20:44:05 -0300624
Steven Toth9c8ced52008-10-16 20:18:44 -0300625static int cx23885_init_tsport(struct cx23885_dev *dev,
626 struct cx23885_tsport *port, int portno)
Steven Tothd19770e2007-03-11 20:44:05 -0300627{
Harvey Harrison22b4e642008-04-08 23:20:00 -0300628 dprintk(1, "%s(portno=%d)\n", __func__, portno);
Steven Tothd19770e2007-03-11 20:44:05 -0300629
Steven Totha6a3f142007-09-08 21:31:56 -0300630 /* Transport bus init dma queue - Common settings */
631 port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */
632 port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */
Steven Tothb1b81f12008-01-13 23:42:44 -0300633 port->vld_misc_val = 0x0;
634 port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4);
Steven Totha6a3f142007-09-08 21:31:56 -0300635
636 spin_lock_init(&port->slock);
637 port->dev = dev;
638 port->nr = portno;
639
640 INIT_LIST_HEAD(&port->mpegq.active);
641 INIT_LIST_HEAD(&port->mpegq.queued);
642 port->mpegq.timeout.function = cx23885_timeout;
643 port->mpegq.timeout.data = (unsigned long)port;
644 init_timer(&port->mpegq.timeout);
645
Steven Tothd782ffa2008-10-11 12:25:25 -0300646 mutex_init(&port->frontends.lock);
Darron Broad7bdf84f2008-10-15 13:43:41 -0300647 INIT_LIST_HEAD(&port->frontends.felist);
Steven Tothd782ffa2008-10-11 12:25:25 -0300648 port->frontends.active_fe_id = 0;
649
Steven Totha739a7e2008-10-11 12:27:06 -0300650 /* This should be hardcoded allow a single frontend
651 * attachment to this tsport, keeping the -dvb.c
652 * code clean and safe.
653 */
Steven Toth9c8ced52008-10-16 20:18:44 -0300654 if (!port->num_frontends)
Steven Totha739a7e2008-10-11 12:27:06 -0300655 port->num_frontends = 1;
656
Steven Toth9c8ced52008-10-16 20:18:44 -0300657 switch (portno) {
Steven Totha6a3f142007-09-08 21:31:56 -0300658 case 1:
659 port->reg_gpcnt = VID_B_GPCNT;
660 port->reg_gpcnt_ctl = VID_B_GPCNT_CTL;
661 port->reg_dma_ctl = VID_B_DMA_CTL;
662 port->reg_lngth = VID_B_LNGTH;
663 port->reg_hw_sop_ctrl = VID_B_HW_SOP_CTL;
664 port->reg_gen_ctrl = VID_B_GEN_CTL;
665 port->reg_bd_pkt_status = VID_B_BD_PKT_STATUS;
666 port->reg_sop_status = VID_B_SOP_STATUS;
667 port->reg_fifo_ovfl_stat = VID_B_FIFO_OVFL_STAT;
668 port->reg_vld_misc = VID_B_VLD_MISC;
669 port->reg_ts_clk_en = VID_B_TS_CLK_EN;
670 port->reg_src_sel = VID_B_SRC_SEL;
671 port->reg_ts_int_msk = VID_B_INT_MSK;
Steven Tothb1b81f12008-01-13 23:42:44 -0300672 port->reg_ts_int_stat = VID_B_INT_STAT;
Steven Totha6a3f142007-09-08 21:31:56 -0300673 port->sram_chno = SRAM_CH03; /* VID_B */
674 port->pci_irqmask = 0x02; /* VID_B bit1 */
Steven Tothd19770e2007-03-11 20:44:05 -0300675 break;
Steven Totha6a3f142007-09-08 21:31:56 -0300676 case 2:
677 port->reg_gpcnt = VID_C_GPCNT;
678 port->reg_gpcnt_ctl = VID_C_GPCNT_CTL;
679 port->reg_dma_ctl = VID_C_DMA_CTL;
680 port->reg_lngth = VID_C_LNGTH;
681 port->reg_hw_sop_ctrl = VID_C_HW_SOP_CTL;
682 port->reg_gen_ctrl = VID_C_GEN_CTL;
683 port->reg_bd_pkt_status = VID_C_BD_PKT_STATUS;
684 port->reg_sop_status = VID_C_SOP_STATUS;
685 port->reg_fifo_ovfl_stat = VID_C_FIFO_OVFL_STAT;
686 port->reg_vld_misc = VID_C_VLD_MISC;
687 port->reg_ts_clk_en = VID_C_TS_CLK_EN;
688 port->reg_src_sel = 0;
689 port->reg_ts_int_msk = VID_C_INT_MSK;
690 port->reg_ts_int_stat = VID_C_INT_STAT;
691 port->sram_chno = SRAM_CH06; /* VID_C */
692 port->pci_irqmask = 0x04; /* VID_C bit2 */
693 break;
694 default:
695 BUG();
Steven Tothd19770e2007-03-11 20:44:05 -0300696 }
697
Steven Totha6a3f142007-09-08 21:31:56 -0300698 cx23885_risc_stopper(dev->pci, &port->mpegq.stopper,
699 port->reg_dma_ctl, port->dma_ctl_val, 0x00);
700
Steven Tothd19770e2007-03-11 20:44:05 -0300701 return 0;
702}
703
Steven Toth0ac58812008-01-10 02:06:35 -0300704static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
705{
706 switch (cx_read(RDR_CFG2) & 0xff) {
707 case 0x00:
708 /* cx23885 */
709 dev->hwrevision = 0xa0;
710 break;
711 case 0x01:
712 /* CX23885-12Z */
713 dev->hwrevision = 0xa1;
714 break;
715 case 0x02:
Steven Toth25ea66e2009-07-20 15:40:31 -0300716 /* CX23885-13Z/14Z */
Steven Toth0ac58812008-01-10 02:06:35 -0300717 dev->hwrevision = 0xb0;
718 break;
719 case 0x03:
Steven Toth25ea66e2009-07-20 15:40:31 -0300720 if (dev->pci->device == 0x8880) {
721 /* CX23888-21Z/22Z */
722 dev->hwrevision = 0xc0;
723 } else {
724 /* CX23885-14Z */
725 dev->hwrevision = 0xa4;
726 }
727 break;
728 case 0x04:
729 if (dev->pci->device == 0x8880) {
730 /* CX23888-31Z */
731 dev->hwrevision = 0xd0;
732 } else {
733 /* CX23885-15Z, CX23888-31Z */
734 dev->hwrevision = 0xa5;
735 }
Steven Toth0ac58812008-01-10 02:06:35 -0300736 break;
737 case 0x0e:
738 /* CX23887-15Z */
739 dev->hwrevision = 0xc0;
740 case 0x0f:
741 /* CX23887-14Z */
742 dev->hwrevision = 0xb1;
743 break;
744 default:
745 printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300746 __func__, dev->hwrevision);
Steven Toth0ac58812008-01-10 02:06:35 -0300747 }
748 if (dev->hwrevision)
749 printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300750 __func__, dev->hwrevision);
Steven Toth0ac58812008-01-10 02:06:35 -0300751 else
752 printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300753 __func__, dev->hwrevision);
Steven Toth0ac58812008-01-10 02:06:35 -0300754}
755
Andy Walls29f8a0a2009-09-26 23:17:30 -0300756/* Find the first v4l2_subdev member of the group id in hw */
757struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
758{
759 struct v4l2_subdev *result = NULL;
760 struct v4l2_subdev *sd;
761
762 spin_lock(&dev->v4l2_dev.lock);
763 v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
764 if (sd->grp_id == hw) {
765 result = sd;
766 break;
767 }
768 }
769 spin_unlock(&dev->v4l2_dev.lock);
770 return result;
771}
772
Steven Tothd19770e2007-03-11 20:44:05 -0300773static int cx23885_dev_setup(struct cx23885_dev *dev)
774{
775 int i;
776
777 mutex_init(&dev->lock);
Abylay Ospan8386c27f2009-09-16 13:08:06 -0300778 mutex_init(&dev->gpio_lock);
Steven Tothd19770e2007-03-11 20:44:05 -0300779
780 atomic_inc(&dev->refcount);
781
782 dev->nr = cx23885_devcount++;
Steven Toth579f1162007-09-08 15:07:02 -0300783 sprintf(dev->name, "cx23885[%d]", dev->nr);
784
Steven Toth579f1162007-09-08 15:07:02 -0300785 /* Configure the internal memory */
Steven Toth9c8ced52008-10-16 20:18:44 -0300786 if (dev->pci->device == 0x8880) {
Steven Toth25ea66e2009-07-20 15:40:31 -0300787 /* Could be 887 or 888, assume a default */
Steven Toth579f1162007-09-08 15:07:02 -0300788 dev->bridge = CX23885_BRIDGE_887;
Steven Tothc7712612008-01-10 02:24:27 -0300789 /* Apply a sensible clock frequency for the PCIe bridge */
790 dev->clk_freq = 25000000;
Steven Toth7e994302008-07-01 21:18:00 -0300791 dev->sram_channels = cx23887_sram_channels;
Steven Toth579f1162007-09-08 15:07:02 -0300792 } else
Steven Toth9c8ced52008-10-16 20:18:44 -0300793 if (dev->pci->device == 0x8852) {
Steven Toth579f1162007-09-08 15:07:02 -0300794 dev->bridge = CX23885_BRIDGE_885;
Steven Tothc7712612008-01-10 02:24:27 -0300795 /* Apply a sensible clock frequency for the PCIe bridge */
796 dev->clk_freq = 28000000;
Steven Toth7e994302008-07-01 21:18:00 -0300797 dev->sram_channels = cx23885_sram_channels;
Steven Toth579f1162007-09-08 15:07:02 -0300798 } else
799 BUG();
800
801 dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300802 __func__, dev->bridge);
Steven Toth579f1162007-09-08 15:07:02 -0300803
804 /* board config */
805 dev->board = UNSET;
806 if (card[dev->nr] < cx23885_bcount)
807 dev->board = card[dev->nr];
808 for (i = 0; UNSET == dev->board && i < cx23885_idcount; i++)
809 if (dev->pci->subsystem_vendor == cx23885_subids[i].subvendor &&
810 dev->pci->subsystem_device == cx23885_subids[i].subdevice)
811 dev->board = cx23885_subids[i].card;
812 if (UNSET == dev->board) {
813 dev->board = CX23885_BOARD_UNKNOWN;
814 cx23885_card_list(dev);
815 }
816
Steven Tothc7712612008-01-10 02:24:27 -0300817 /* If the user specific a clk freq override, apply it */
818 if (cx23885_boards[dev->board].clk_freq > 0)
819 dev->clk_freq = cx23885_boards[dev->board].clk_freq;
820
Steven Tothd19770e2007-03-11 20:44:05 -0300821 dev->pci_bus = dev->pci->bus->number;
822 dev->pci_slot = PCI_SLOT(dev->pci->devfn);
823 dev->pci_irqmask = 0x001f00;
Igor M. Liplianin5a23b0762009-03-03 12:06:09 -0300824 if (cx23885_boards[dev->board].cimax > 0)
825 dev->pci_irqmask |= 0x01800000; /* for CiMaxes */
Steven Tothd19770e2007-03-11 20:44:05 -0300826
827 /* External Master 1 Bus */
828 dev->i2c_bus[0].nr = 0;
829 dev->i2c_bus[0].dev = dev;
830 dev->i2c_bus[0].reg_stat = I2C1_STAT;
831 dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
832 dev->i2c_bus[0].reg_addr = I2C1_ADDR;
833 dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
834 dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
835 dev->i2c_bus[0].i2c_period = (0x9d << 24); /* 100kHz */
836
837 /* External Master 2 Bus */
838 dev->i2c_bus[1].nr = 1;
839 dev->i2c_bus[1].dev = dev;
840 dev->i2c_bus[1].reg_stat = I2C2_STAT;
841 dev->i2c_bus[1].reg_ctrl = I2C2_CTRL;
842 dev->i2c_bus[1].reg_addr = I2C2_ADDR;
843 dev->i2c_bus[1].reg_rdata = I2C2_RDATA;
844 dev->i2c_bus[1].reg_wdata = I2C2_WDATA;
845 dev->i2c_bus[1].i2c_period = (0x9d << 24); /* 100kHz */
846
847 /* Internal Master 3 Bus */
848 dev->i2c_bus[2].nr = 2;
849 dev->i2c_bus[2].dev = dev;
850 dev->i2c_bus[2].reg_stat = I2C3_STAT;
851 dev->i2c_bus[2].reg_ctrl = I2C3_CTRL;
Steven Totha2129af2007-03-16 11:48:33 -0300852 dev->i2c_bus[2].reg_addr = I2C3_ADDR;
Steven Tothd19770e2007-03-11 20:44:05 -0300853 dev->i2c_bus[2].reg_rdata = I2C3_RDATA;
854 dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
855 dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
856
Steven Tothb1b81f12008-01-13 23:42:44 -0300857 if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
858 (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
Steven Totha6a3f142007-09-08 21:31:56 -0300859 cx23885_init_tsport(dev, &dev->ts1, 1);
Steven Toth579f1162007-09-08 15:07:02 -0300860
Steven Tothb1b81f12008-01-13 23:42:44 -0300861 if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
862 (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
Steven Totha6a3f142007-09-08 21:31:56 -0300863 cx23885_init_tsport(dev, &dev->ts2, 2);
Steven Tothd19770e2007-03-11 20:44:05 -0300864
Steven Tothd19770e2007-03-11 20:44:05 -0300865 if (get_resources(dev) < 0) {
866 printk(KERN_ERR "CORE %s No more PCIe resources for "
Michael Krufky44a64812007-03-20 23:00:18 -0300867 "subsystem: %04x:%04x\n",
868 dev->name, dev->pci->subsystem_vendor,
869 dev->pci->subsystem_device);
Steven Tothd19770e2007-03-11 20:44:05 -0300870
871 cx23885_devcount--;
Florin Malitafcf94c82007-10-13 11:49:52 -0300872 return -ENODEV;
Steven Tothd19770e2007-03-11 20:44:05 -0300873 }
874
Steven Tothd19770e2007-03-11 20:44:05 -0300875 /* PCIe stuff */
Steven Toth9c8ced52008-10-16 20:18:44 -0300876 dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
877 pci_resource_len(dev->pci, 0));
Steven Tothd19770e2007-03-11 20:44:05 -0300878
879 dev->bmmio = (u8 __iomem *)dev->lmmio;
880
Steven Tothd19770e2007-03-11 20:44:05 -0300881 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
Michael Krufky44a64812007-03-20 23:00:18 -0300882 dev->name, dev->pci->subsystem_vendor,
883 dev->pci->subsystem_device, cx23885_boards[dev->board].name,
884 dev->board, card[dev->nr] == dev->board ?
885 "insmod option" : "autodetected");
Steven Tothd19770e2007-03-11 20:44:05 -0300886
Steven Toth4823e9e2007-08-22 20:52:21 -0300887 cx23885_pci_quirks(dev);
888
Steven Toth7b888012008-01-10 03:40:49 -0300889 /* Assume some sensible defaults */
890 dev->tuner_type = cx23885_boards[dev->board].tuner_type;
891 dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
892 dev->radio_type = cx23885_boards[dev->board].radio_type;
893 dev->radio_addr = cx23885_boards[dev->board].radio_addr;
894
895 dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300896 __func__, dev->tuner_type, dev->tuner_addr);
Steven Toth7b888012008-01-10 03:40:49 -0300897 dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300898 __func__, dev->radio_type, dev->radio_addr);
Steven Toth7b888012008-01-10 03:40:49 -0300899
Steven Tothf659c512009-06-25 23:43:31 -0300900 /* The cx23417 encoder has GPIO's that need to be initialised
901 * before DVB, so that demodulators and tuners are out of
902 * reset before DVB uses them.
903 */
904 if ((cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) ||
905 (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
906 cx23885_mc417_init(dev);
907
Steven Tothd19770e2007-03-11 20:44:05 -0300908 /* init hardware */
909 cx23885_reset(dev);
910
911 cx23885_i2c_register(&dev->i2c_bus[0]);
912 cx23885_i2c_register(&dev->i2c_bus[1]);
913 cx23885_i2c_register(&dev->i2c_bus[2]);
Steven Tothd19770e2007-03-11 20:44:05 -0300914 cx23885_card_setup(dev);
Laurent Pinchart622b8282009-10-05 10:48:17 -0300915 call_all(dev, core, s_power, 0);
Steven Tothd19770e2007-03-11 20:44:05 -0300916 cx23885_ir_init(dev);
917
Steven Toth7b888012008-01-10 03:40:49 -0300918 if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
919 if (cx23885_video_register(dev) < 0) {
920 printk(KERN_ERR "%s() Failed to register analog "
Harvey Harrison22b4e642008-04-08 23:20:00 -0300921 "video adapters on VID_A\n", __func__);
Steven Toth7b888012008-01-10 03:40:49 -0300922 }
923 }
924
925 if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
Steven Totha6a3f142007-09-08 21:31:56 -0300926 if (cx23885_dvb_register(&dev->ts1) < 0) {
927 printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300928 __func__);
Steven Totha6a3f142007-09-08 21:31:56 -0300929 }
Steven Tothb1b81f12008-01-13 23:42:44 -0300930 } else
931 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
932 if (cx23885_417_register(dev) < 0) {
933 printk(KERN_ERR
934 "%s() Failed to register 417 on VID_B\n",
935 __func__);
936 }
Steven Toth579f1162007-09-08 15:07:02 -0300937 }
938
Steven Toth7b888012008-01-10 03:40:49 -0300939 if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
Steven Totha6a3f142007-09-08 21:31:56 -0300940 if (cx23885_dvb_register(&dev->ts2) < 0) {
Steven Tothb1b81f12008-01-13 23:42:44 -0300941 printk(KERN_ERR
942 "%s() Failed to register dvb on VID_C\n",
943 __func__);
944 }
945 } else
946 if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
947 if (cx23885_417_register(dev) < 0) {
948 printk(KERN_ERR
949 "%s() Failed to register 417 on VID_C\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -0300950 __func__);
Steven Totha6a3f142007-09-08 21:31:56 -0300951 }
Steven Tothd19770e2007-03-11 20:44:05 -0300952 }
953
Steven Toth0ac58812008-01-10 02:06:35 -0300954 cx23885_dev_checkrevision(dev);
955
Steven Tothd19770e2007-03-11 20:44:05 -0300956 return 0;
Steven Tothd19770e2007-03-11 20:44:05 -0300957}
958
Adrian Bunk39e75cf2007-11-05 14:07:20 -0300959static void cx23885_dev_unregister(struct cx23885_dev *dev)
Steven Tothd19770e2007-03-11 20:44:05 -0300960{
Steven Toth9c8ced52008-10-16 20:18:44 -0300961 release_mem_region(pci_resource_start(dev->pci, 0),
962 pci_resource_len(dev->pci, 0));
Steven Tothd19770e2007-03-11 20:44:05 -0300963
964 if (!atomic_dec_and_test(&dev->refcount))
965 return;
966
Steven Toth7b888012008-01-10 03:40:49 -0300967 if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
968 cx23885_video_unregister(dev);
969
Steven Tothb1b81f12008-01-13 23:42:44 -0300970 if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
Steven Totha6a3f142007-09-08 21:31:56 -0300971 cx23885_dvb_unregister(&dev->ts1);
972
Steven Tothb1b81f12008-01-13 23:42:44 -0300973 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
974 cx23885_417_unregister(dev);
975
976 if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
Steven Totha6a3f142007-09-08 21:31:56 -0300977 cx23885_dvb_unregister(&dev->ts2);
978
Steven Tothb1b81f12008-01-13 23:42:44 -0300979 if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
980 cx23885_417_unregister(dev);
981
Steven Tothd19770e2007-03-11 20:44:05 -0300982 cx23885_i2c_unregister(&dev->i2c_bus[2]);
983 cx23885_i2c_unregister(&dev->i2c_bus[1]);
984 cx23885_i2c_unregister(&dev->i2c_bus[0]);
985
986 iounmap(dev->lmmio);
987}
988
Steven Toth9c8ced52008-10-16 20:18:44 -0300989static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
Michael Krufky44a64812007-03-20 23:00:18 -0300990 unsigned int offset, u32 sync_line,
991 unsigned int bpl, unsigned int padding,
992 unsigned int lines)
Steven Tothd19770e2007-03-11 20:44:05 -0300993{
994 struct scatterlist *sg;
Michael Krufky44a64812007-03-20 23:00:18 -0300995 unsigned int line, todo;
Steven Tothd19770e2007-03-11 20:44:05 -0300996
997 /* sync instruction */
998 if (sync_line != NO_SYNC_LINE)
999 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
1000
1001 /* scan lines */
1002 sg = sglist;
1003 for (line = 0; line < lines; line++) {
1004 while (offset && offset >= sg_dma_len(sg)) {
1005 offset -= sg_dma_len(sg);
1006 sg++;
1007 }
1008 if (bpl <= sg_dma_len(sg)-offset) {
1009 /* fits into current chunk */
Steven Toth9c8ced52008-10-16 20:18:44 -03001010 *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
1011 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
1012 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1013 offset += bpl;
Steven Tothd19770e2007-03-11 20:44:05 -03001014 } else {
1015 /* scanline needs to be split */
1016 todo = bpl;
Steven Toth9c8ced52008-10-16 20:18:44 -03001017 *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
Steven Tothd19770e2007-03-11 20:44:05 -03001018 (sg_dma_len(sg)-offset));
Steven Toth9c8ced52008-10-16 20:18:44 -03001019 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
1020 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
Steven Tothd19770e2007-03-11 20:44:05 -03001021 todo -= (sg_dma_len(sg)-offset);
1022 offset = 0;
1023 sg++;
1024 while (todo > sg_dma_len(sg)) {
Steven Toth9c8ced52008-10-16 20:18:44 -03001025 *(rp++) = cpu_to_le32(RISC_WRITE|
Steven Tothd19770e2007-03-11 20:44:05 -03001026 sg_dma_len(sg));
Steven Toth9c8ced52008-10-16 20:18:44 -03001027 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1028 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
Steven Tothd19770e2007-03-11 20:44:05 -03001029 todo -= sg_dma_len(sg);
1030 sg++;
1031 }
Steven Toth9c8ced52008-10-16 20:18:44 -03001032 *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
1033 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1034 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
Steven Tothd19770e2007-03-11 20:44:05 -03001035 offset += todo;
1036 }
1037 offset += padding;
1038 }
1039
1040 return rp;
1041}
1042
Steven Toth7b888012008-01-10 03:40:49 -03001043int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
1044 struct scatterlist *sglist, unsigned int top_offset,
1045 unsigned int bottom_offset, unsigned int bpl,
1046 unsigned int padding, unsigned int lines)
1047{
1048 u32 instructions, fields;
Al Virod8eaa582008-05-21 00:31:51 -03001049 __le32 *rp;
Steven Toth7b888012008-01-10 03:40:49 -03001050 int rc;
1051
1052 fields = 0;
1053 if (UNSET != top_offset)
1054 fields++;
1055 if (UNSET != bottom_offset)
1056 fields++;
1057
1058 /* estimate risc mem: worst case is one write per page border +
1059 one write per scan line + syncs + jump (all 2 dwords). Padding
1060 can cause next bpl to start close to a page border. First DMA
1061 region may be smaller than PAGE_SIZE */
1062 /* write and jump need and extra dword */
Steven Toth9c8ced52008-10-16 20:18:44 -03001063 instructions = fields * (1 + ((bpl + padding) * lines)
1064 / PAGE_SIZE + lines);
Steven Toth7b888012008-01-10 03:40:49 -03001065 instructions += 2;
Steven Toth9c8ced52008-10-16 20:18:44 -03001066 rc = btcx_riscmem_alloc(pci, risc, instructions*12);
1067 if (rc < 0)
Steven Toth7b888012008-01-10 03:40:49 -03001068 return rc;
1069
1070 /* write risc instructions */
1071 rp = risc->cpu;
1072 if (UNSET != top_offset)
1073 rp = cx23885_risc_field(rp, sglist, top_offset, 0,
1074 bpl, padding, lines);
1075 if (UNSET != bottom_offset)
1076 rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
1077 bpl, padding, lines);
1078
1079 /* save pointer to jmp instruction address */
1080 risc->jmp = rp;
Steven Toth9c8ced52008-10-16 20:18:44 -03001081 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
Steven Toth7b888012008-01-10 03:40:49 -03001082 return 0;
1083}
Steven Tothd19770e2007-03-11 20:44:05 -03001084
Adrian Bunk39e75cf2007-11-05 14:07:20 -03001085static int cx23885_risc_databuffer(struct pci_dev *pci,
1086 struct btcx_riscmem *risc,
1087 struct scatterlist *sglist,
1088 unsigned int bpl,
1089 unsigned int lines)
Steven Tothd19770e2007-03-11 20:44:05 -03001090{
1091 u32 instructions;
Al Virod8eaa582008-05-21 00:31:51 -03001092 __le32 *rp;
Steven Tothd19770e2007-03-11 20:44:05 -03001093 int rc;
1094
1095 /* estimate risc mem: worst case is one write per page border +
1096 one write per scan line + syncs + jump (all 2 dwords). Here
1097 there is no padding and no sync. First DMA region may be smaller
1098 than PAGE_SIZE */
1099 /* Jump and write need an extra dword */
1100 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
1101 instructions += 1;
1102
Steven Toth9c8ced52008-10-16 20:18:44 -03001103 rc = btcx_riscmem_alloc(pci, risc, instructions*12);
1104 if (rc < 0)
Steven Tothd19770e2007-03-11 20:44:05 -03001105 return rc;
1106
1107 /* write risc instructions */
1108 rp = risc->cpu;
1109 rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
1110
1111 /* save pointer to jmp instruction address */
1112 risc->jmp = rp;
Steven Toth9c8ced52008-10-16 20:18:44 -03001113 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
Steven Tothd19770e2007-03-11 20:44:05 -03001114 return 0;
1115}
1116
Steven Toth7b888012008-01-10 03:40:49 -03001117int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
Adrian Bunk39e75cf2007-11-05 14:07:20 -03001118 u32 reg, u32 mask, u32 value)
Steven Tothd19770e2007-03-11 20:44:05 -03001119{
Al Virod8eaa582008-05-21 00:31:51 -03001120 __le32 *rp;
Steven Tothd19770e2007-03-11 20:44:05 -03001121 int rc;
1122
Steven Toth9c8ced52008-10-16 20:18:44 -03001123 rc = btcx_riscmem_alloc(pci, risc, 4*16);
1124 if (rc < 0)
Steven Tothd19770e2007-03-11 20:44:05 -03001125 return rc;
1126
1127 /* write risc instructions */
1128 rp = risc->cpu;
Steven Tothd19770e2007-03-11 20:44:05 -03001129 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2);
1130 *(rp++) = cpu_to_le32(reg);
1131 *(rp++) = cpu_to_le32(value);
1132 *(rp++) = cpu_to_le32(mask);
1133 *(rp++) = cpu_to_le32(RISC_JUMP);
1134 *(rp++) = cpu_to_le32(risc->dma);
1135 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1136 return 0;
1137}
1138
1139void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
1140{
Trent Piepho409d84f2007-10-04 05:28:45 -03001141 struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
1142
Steven Tothd19770e2007-03-11 20:44:05 -03001143 BUG_ON(in_interrupt());
Michael Krufky44a64812007-03-20 23:00:18 -03001144 videobuf_waiton(&buf->vb, 0, 0);
Laurent Pinchart95268402010-05-11 10:36:30 -03001145 videobuf_dma_unmap(q->dev, dma);
Trent Piepho409d84f2007-10-04 05:28:45 -03001146 videobuf_dma_free(dma);
Guennadi Liakhovetskia920e422008-04-22 14:46:02 -03001147 btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
Brandon Philips0fc06862007-11-06 20:02:36 -03001148 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Steven Tothd19770e2007-03-11 20:44:05 -03001149}
1150
Steven Toth7b888012008-01-10 03:40:49 -03001151static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
1152{
1153 struct cx23885_dev *dev = port->dev;
1154
Harvey Harrison22b4e642008-04-08 23:20:00 -03001155 dprintk(1, "%s() Register Dump\n", __func__);
1156 dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001157 cx_read(DEV_CNTRL2));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001158 dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001159 cx_read(PCI_INT_MSK));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001160 dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001161 cx_read(AUDIO_INT_INT_MSK));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001162 dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001163 cx_read(AUD_INT_DMA_CTL));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001164 dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001165 cx_read(AUDIO_EXT_INT_MSK));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001166 dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001167 cx_read(AUD_EXT_DMA_CTL));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001168 dprintk(1, "%s() PAD_CTRL 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001169 cx_read(PAD_CTRL));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001170 dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001171 cx_read(ALT_PIN_OUT_SEL));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001172 dprintk(1, "%s() GPIO2 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001173 cx_read(GPIO2));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001174 dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001175 port->reg_gpcnt, cx_read(port->reg_gpcnt));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001176 dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001177 port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001178 dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001179 port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
Steven Toth7b913902008-06-30 20:54:34 -03001180 if (port->reg_src_sel)
1181 dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __func__,
1182 port->reg_src_sel, cx_read(port->reg_src_sel));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001183 dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001184 port->reg_lngth, cx_read(port->reg_lngth));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001185 dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001186 port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001187 dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001188 port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001189 dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001190 port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001191 dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001192 port->reg_sop_status, cx_read(port->reg_sop_status));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001193 dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001194 port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001195 dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001196 port->reg_vld_misc, cx_read(port->reg_vld_misc));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001197 dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001198 port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
Harvey Harrison22b4e642008-04-08 23:20:00 -03001199 dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __func__,
Steven Toth7b888012008-01-10 03:40:49 -03001200 port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
1201}
1202
Steven Tothd19770e2007-03-11 20:44:05 -03001203static int cx23885_start_dma(struct cx23885_tsport *port,
Michael Krufky44a64812007-03-20 23:00:18 -03001204 struct cx23885_dmaqueue *q,
1205 struct cx23885_buffer *buf)
Steven Tothd19770e2007-03-11 20:44:05 -03001206{
1207 struct cx23885_dev *dev = port->dev;
Steven Totha589b662008-01-13 23:44:47 -03001208 u32 reg;
Steven Tothd19770e2007-03-11 20:44:05 -03001209
Harvey Harrison22b4e642008-04-08 23:20:00 -03001210 dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
Michael Krufky44a64812007-03-20 23:00:18 -03001211 buf->vb.width, buf->vb.height, buf->vb.field);
Steven Tothd19770e2007-03-11 20:44:05 -03001212
Steven Tothd8d12b42008-07-01 10:43:27 -03001213 /* Stop the fifo and risc engine for this port */
1214 cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
1215
Steven Tothd19770e2007-03-11 20:44:05 -03001216 /* setup fifo + format */
1217 cx23885_sram_channel_setup(dev,
Steven Toth9c8ced52008-10-16 20:18:44 -03001218 &dev->sram_channels[port->sram_chno],
Michael Krufky44a64812007-03-20 23:00:18 -03001219 port->ts_packet_size, buf->risc.dma);
Steven Toth9c8ced52008-10-16 20:18:44 -03001220 if (debug > 5) {
1221 cx23885_sram_channel_dump(dev,
1222 &dev->sram_channels[port->sram_chno]);
Steven Tothd19770e2007-03-11 20:44:05 -03001223 cx23885_risc_disasm(port, &buf->risc);
Steven Toth3328e4f2007-03-19 18:01:07 -03001224 }
Steven Tothd19770e2007-03-11 20:44:05 -03001225
1226 /* write TS length to chip */
1227 cx_write(port->reg_lngth, buf->vb.width);
1228
Steven Toth9c8ced52008-10-16 20:18:44 -03001229 if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
1230 (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
1231 printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -03001232 __func__,
Steven Toth661c7e42007-09-06 16:07:49 -03001233 cx23885_boards[dev->board].portb,
Steven Toth9c8ced52008-10-16 20:18:44 -03001234 cx23885_boards[dev->board].portc);
Steven Tothd19770e2007-03-11 20:44:05 -03001235 return -EINVAL;
1236 }
1237
Steven Totha589b662008-01-13 23:44:47 -03001238 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
1239 cx23885_av_clk(dev, 0);
1240
Steven Tothd19770e2007-03-11 20:44:05 -03001241 udelay(100);
1242
Steven Toth579f1162007-09-08 15:07:02 -03001243 /* If the port supports SRC SELECT, configure it */
Steven Toth9c8ced52008-10-16 20:18:44 -03001244 if (port->reg_src_sel)
Steven Toth579f1162007-09-08 15:07:02 -03001245 cx_write(port->reg_src_sel, port->src_sel_val);
1246
Steven Tothb1b81f12008-01-13 23:42:44 -03001247 cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
Steven Tothd19770e2007-03-11 20:44:05 -03001248 cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
Steven Tothb1b81f12008-01-13 23:42:44 -03001249 cx_write(port->reg_vld_misc, port->vld_misc_val);
Steven Tothd19770e2007-03-11 20:44:05 -03001250 cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
1251 udelay(100);
1252
Steven Toth9c8ced52008-10-16 20:18:44 -03001253 /* NOTE: this is 2 (reserved) for portb, does it matter? */
Steven Tothd19770e2007-03-11 20:44:05 -03001254 /* reset counter to zero */
1255 cx_write(port->reg_gpcnt_ctl, 3);
1256 q->count = 1;
1257
Steven Toth52ce27b2008-06-28 00:58:35 -03001258 /* Set VIDB pins to input */
1259 if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
1260 reg = cx_read(PAD_CTRL);
1261 reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
1262 cx_write(PAD_CTRL, reg);
1263 }
1264
1265 /* Set VIDC pins to input */
1266 if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
1267 reg = cx_read(PAD_CTRL);
1268 reg &= ~0x4; /* Clear TS2_SOP_OE */
1269 cx_write(PAD_CTRL, reg);
1270 }
1271
1272 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
Steven Totha589b662008-01-13 23:44:47 -03001273
1274 reg = cx_read(PAD_CTRL);
1275 reg = reg & ~0x1; /* Clear TS1_OE */
1276
1277 /* FIXME, bit 2 writing here is questionable */
1278 /* set TS1_SOP_OE and TS1_OE_HI */
1279 reg = reg | 0xa;
1280 cx_write(PAD_CTRL, reg);
1281
1282 /* FIXME and these two registers should be documented. */
1283 cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
1284 cx_write(ALT_PIN_OUT_SEL, 0x10100045);
1285 }
1286
Steven Toth9c8ced52008-10-16 20:18:44 -03001287 switch (dev->bridge) {
Steven Tothd19770e2007-03-11 20:44:05 -03001288 case CX23885_BRIDGE_885:
Steven Toth3bd40652007-03-19 17:46:03 -03001289 case CX23885_BRIDGE_887:
Steven Toth25ea66e2009-07-20 15:40:31 -03001290 case CX23885_BRIDGE_888:
Steven Tothd19770e2007-03-11 20:44:05 -03001291 /* enable irqs */
Steven Toth9c8ced52008-10-16 20:18:44 -03001292 dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001293 cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
1294 cx_set(port->reg_dma_ctl, port->dma_ctl_val);
1295 cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
1296 break;
Steven Tothd19770e2007-03-11 20:44:05 -03001297 default:
Steven Toth579f1162007-09-08 15:07:02 -03001298 BUG();
Steven Tothd19770e2007-03-11 20:44:05 -03001299 }
1300
Steven Tothd19770e2007-03-11 20:44:05 -03001301 cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
1302
Steven Totha589b662008-01-13 23:44:47 -03001303 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
1304 cx23885_av_clk(dev, 1);
1305
Steven Toth7b888012008-01-10 03:40:49 -03001306 if (debug > 4)
1307 cx23885_tsport_reg_dump(port);
1308
Steven Tothd19770e2007-03-11 20:44:05 -03001309 return 0;
1310}
1311
1312static int cx23885_stop_dma(struct cx23885_tsport *port)
1313{
1314 struct cx23885_dev *dev = port->dev;
Steven Totha589b662008-01-13 23:44:47 -03001315 u32 reg;
1316
Harvey Harrison22b4e642008-04-08 23:20:00 -03001317 dprintk(1, "%s()\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001318
1319 /* Stop interrupts and DMA */
1320 cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
1321 cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
1322
Steven Toth52ce27b2008-06-28 00:58:35 -03001323 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
Steven Totha589b662008-01-13 23:44:47 -03001324
1325 reg = cx_read(PAD_CTRL);
1326
1327 /* Set TS1_OE */
1328 reg = reg | 0x1;
1329
1330 /* clear TS1_SOP_OE and TS1_OE_HI */
1331 reg = reg & ~0xa;
1332 cx_write(PAD_CTRL, reg);
1333 cx_write(port->reg_src_sel, 0);
1334 cx_write(port->reg_gen_ctrl, 8);
1335
1336 }
1337
1338 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
1339 cx23885_av_clk(dev, 0);
1340
Steven Tothd19770e2007-03-11 20:44:05 -03001341 return 0;
1342}
1343
Steven Toth7b888012008-01-10 03:40:49 -03001344int cx23885_restart_queue(struct cx23885_tsport *port,
Steven Tothd19770e2007-03-11 20:44:05 -03001345 struct cx23885_dmaqueue *q)
1346{
1347 struct cx23885_dev *dev = port->dev;
1348 struct cx23885_buffer *buf;
Steven Tothd19770e2007-03-11 20:44:05 -03001349
Harvey Harrison22b4e642008-04-08 23:20:00 -03001350 dprintk(5, "%s()\n", __func__);
Steven Toth9c8ced52008-10-16 20:18:44 -03001351 if (list_empty(&q->active)) {
Michael Krufky44a64812007-03-20 23:00:18 -03001352 struct cx23885_buffer *prev;
1353 prev = NULL;
Steven Tothd19770e2007-03-11 20:44:05 -03001354
Harvey Harrison22b4e642008-04-08 23:20:00 -03001355 dprintk(5, "%s() queue is empty\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001356
Michael Krufky44a64812007-03-20 23:00:18 -03001357 for (;;) {
1358 if (list_empty(&q->queued))
1359 return 0;
1360 buf = list_entry(q->queued.next, struct cx23885_buffer,
1361 vb.queue);
1362 if (NULL == prev) {
1363 list_del(&buf->vb.queue);
1364 list_add_tail(&buf->vb.queue, &q->active);
1365 cx23885_start_dma(port, q, buf);
Brandon Philips0fc06862007-11-06 20:02:36 -03001366 buf->vb.state = VIDEOBUF_ACTIVE;
Michael Krufky44a64812007-03-20 23:00:18 -03001367 buf->count = q->count++;
1368 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
Steven Toth9c8ced52008-10-16 20:18:44 -03001369 dprintk(5, "[%p/%d] restart_queue - f/active\n",
Michael Krufky44a64812007-03-20 23:00:18 -03001370 buf, buf->vb.i);
Steven Tothd19770e2007-03-11 20:44:05 -03001371
Michael Krufky44a64812007-03-20 23:00:18 -03001372 } else if (prev->vb.width == buf->vb.width &&
1373 prev->vb.height == buf->vb.height &&
1374 prev->fmt == buf->fmt) {
1375 list_del(&buf->vb.queue);
1376 list_add_tail(&buf->vb.queue, &q->active);
Brandon Philips0fc06862007-11-06 20:02:36 -03001377 buf->vb.state = VIDEOBUF_ACTIVE;
Michael Krufky44a64812007-03-20 23:00:18 -03001378 buf->count = q->count++;
1379 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
Steven Toth9c8ced52008-10-16 20:18:44 -03001380 /* 64 bit bits 63-32 */
1381 prev->risc.jmp[2] = cpu_to_le32(0);
1382 dprintk(5, "[%p/%d] restart_queue - m/active\n",
Michael Krufky44a64812007-03-20 23:00:18 -03001383 buf, buf->vb.i);
1384 } else {
1385 return 0;
1386 }
1387 prev = buf;
1388 }
Steven Tothd19770e2007-03-11 20:44:05 -03001389 return 0;
1390 }
1391
1392 buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
Michael Krufky44a64812007-03-20 23:00:18 -03001393 dprintk(2, "restart_queue [%p/%d]: restart dma\n",
Steven Tothd19770e2007-03-11 20:44:05 -03001394 buf, buf->vb.i);
1395 cx23885_start_dma(port, q, buf);
Trent Piephoa991f442007-10-10 05:37:43 -03001396 list_for_each_entry(buf, &q->active, vb.queue)
Steven Tothd19770e2007-03-11 20:44:05 -03001397 buf->count = q->count++;
Michael Krufky44a64812007-03-20 23:00:18 -03001398 mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
Steven Tothd19770e2007-03-11 20:44:05 -03001399 return 0;
1400}
1401
1402/* ------------------------------------------------------------------ */
1403
1404int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
1405 struct cx23885_buffer *buf, enum v4l2_field field)
1406{
1407 struct cx23885_dev *dev = port->dev;
1408 int size = port->ts_packet_size * port->ts_packet_count;
1409 int rc;
1410
Harvey Harrison22b4e642008-04-08 23:20:00 -03001411 dprintk(1, "%s: %p\n", __func__, buf);
Steven Tothd19770e2007-03-11 20:44:05 -03001412 if (0 != buf->vb.baddr && buf->vb.bsize < size)
1413 return -EINVAL;
1414
Brandon Philips0fc06862007-11-06 20:02:36 -03001415 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Steven Tothd19770e2007-03-11 20:44:05 -03001416 buf->vb.width = port->ts_packet_size;
1417 buf->vb.height = port->ts_packet_count;
1418 buf->vb.size = size;
1419 buf->vb.field = field /*V4L2_FIELD_TOP*/;
1420
Steven Toth9c8ced52008-10-16 20:18:44 -03001421 rc = videobuf_iolock(q, &buf->vb, NULL);
1422 if (0 != rc)
Steven Tothd19770e2007-03-11 20:44:05 -03001423 goto fail;
1424 cx23885_risc_databuffer(dev->pci, &buf->risc,
Trent Piepho409d84f2007-10-04 05:28:45 -03001425 videobuf_to_dma(&buf->vb)->sglist,
1426 buf->vb.width, buf->vb.height);
Steven Tothd19770e2007-03-11 20:44:05 -03001427 }
Brandon Philips0fc06862007-11-06 20:02:36 -03001428 buf->vb.state = VIDEOBUF_PREPARED;
Steven Tothd19770e2007-03-11 20:44:05 -03001429 return 0;
1430
1431 fail:
Michael Krufky44a64812007-03-20 23:00:18 -03001432 cx23885_free_buffer(q, buf);
Steven Tothd19770e2007-03-11 20:44:05 -03001433 return rc;
1434}
1435
1436void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
1437{
1438 struct cx23885_buffer *prev;
1439 struct cx23885_dev *dev = port->dev;
1440 struct cx23885_dmaqueue *cx88q = &port->mpegq;
1441
1442 /* add jump to stopper */
1443 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
1444 buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
1445 buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
1446
1447 if (list_empty(&cx88q->active)) {
Steven Toth9c8ced52008-10-16 20:18:44 -03001448 dprintk(1, "queue is empty - first active\n");
Michael Krufky44a64812007-03-20 23:00:18 -03001449 list_add_tail(&buf->vb.queue, &cx88q->active);
Steven Tothd19770e2007-03-11 20:44:05 -03001450 cx23885_start_dma(port, cx88q, buf);
Brandon Philips0fc06862007-11-06 20:02:36 -03001451 buf->vb.state = VIDEOBUF_ACTIVE;
Steven Tothd19770e2007-03-11 20:44:05 -03001452 buf->count = cx88q->count++;
Michael Krufky44a64812007-03-20 23:00:18 -03001453 mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
1454 dprintk(1, "[%p/%d] %s - first active\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -03001455 buf, buf->vb.i, __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001456 } else {
Steven Toth9c8ced52008-10-16 20:18:44 -03001457 dprintk(1, "queue is not empty - append to active\n");
Michael Krufky44a64812007-03-20 23:00:18 -03001458 prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
1459 vb.queue);
1460 list_add_tail(&buf->vb.queue, &cx88q->active);
Brandon Philips0fc06862007-11-06 20:02:36 -03001461 buf->vb.state = VIDEOBUF_ACTIVE;
Steven Tothd19770e2007-03-11 20:44:05 -03001462 buf->count = cx88q->count++;
1463 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
1464 prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
Steven Toth9c8ced52008-10-16 20:18:44 -03001465 dprintk(1, "[%p/%d] %s - append to active\n",
Harvey Harrison22b4e642008-04-08 23:20:00 -03001466 buf, buf->vb.i, __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001467 }
1468}
1469
1470/* ----------------------------------------------------------- */
1471
Michael Krufky44a64812007-03-20 23:00:18 -03001472static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
1473 int restart)
Steven Tothd19770e2007-03-11 20:44:05 -03001474{
1475 struct cx23885_dev *dev = port->dev;
1476 struct cx23885_dmaqueue *q = &port->mpegq;
1477 struct cx23885_buffer *buf;
1478 unsigned long flags;
1479
Michael Krufky44a64812007-03-20 23:00:18 -03001480 spin_lock_irqsave(&port->slock, flags);
Steven Tothd19770e2007-03-11 20:44:05 -03001481 while (!list_empty(&q->active)) {
Michael Krufky44a64812007-03-20 23:00:18 -03001482 buf = list_entry(q->active.next, struct cx23885_buffer,
1483 vb.queue);
Steven Tothd19770e2007-03-11 20:44:05 -03001484 list_del(&buf->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03001485 buf->vb.state = VIDEOBUF_ERROR;
Steven Tothd19770e2007-03-11 20:44:05 -03001486 wake_up(&buf->vb.done);
Michael Krufky44a64812007-03-20 23:00:18 -03001487 dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
Steven Tothd19770e2007-03-11 20:44:05 -03001488 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
1489 }
Michael Krufky44a64812007-03-20 23:00:18 -03001490 if (restart) {
Steven Toth9c8ced52008-10-16 20:18:44 -03001491 dprintk(1, "restarting queue\n");
Steven Tothd19770e2007-03-11 20:44:05 -03001492 cx23885_restart_queue(port, q);
1493 }
Michael Krufky44a64812007-03-20 23:00:18 -03001494 spin_unlock_irqrestore(&port->slock, flags);
Steven Tothd19770e2007-03-11 20:44:05 -03001495}
1496
Steven Tothb1b81f12008-01-13 23:42:44 -03001497void cx23885_cancel_buffers(struct cx23885_tsport *port)
1498{
1499 struct cx23885_dev *dev = port->dev;
1500 struct cx23885_dmaqueue *q = &port->mpegq;
1501
Alexander Beregalov26d2e852008-07-21 16:20:32 -03001502 dprintk(1, "%s()\n", __func__);
Steven Tothb1b81f12008-01-13 23:42:44 -03001503 del_timer_sync(&q->timeout);
1504 cx23885_stop_dma(port);
1505 do_cancel_buffers(port, "cancel", 0);
1506}
Steven Tothd19770e2007-03-11 20:44:05 -03001507
1508static void cx23885_timeout(unsigned long data)
1509{
1510 struct cx23885_tsport *port = (struct cx23885_tsport *)data;
1511 struct cx23885_dev *dev = port->dev;
1512
Steven Toth9c8ced52008-10-16 20:18:44 -03001513 dprintk(1, "%s()\n", __func__);
Steven Tothd19770e2007-03-11 20:44:05 -03001514
1515 if (debug > 5)
Steven Toth9c8ced52008-10-16 20:18:44 -03001516 cx23885_sram_channel_dump(dev,
1517 &dev->sram_channels[port->sram_chno]);
Steven Toth3328e4f2007-03-19 18:01:07 -03001518
Steven Tothd19770e2007-03-11 20:44:05 -03001519 cx23885_stop_dma(port);
1520 do_cancel_buffers(port, "timeout", 1);
1521}
1522
Steven Tothb1b81f12008-01-13 23:42:44 -03001523int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
1524{
1525 /* FIXME: port1 assumption here. */
1526 struct cx23885_tsport *port = &dev->ts1;
1527 int count = 0;
1528 int handled = 0;
1529
1530 if (status == 0)
1531 return handled;
1532
1533 count = cx_read(port->reg_gpcnt);
1534 dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n",
1535 status, cx_read(port->reg_ts_int_msk), count);
1536
1537 if ((status & VID_B_MSK_BAD_PKT) ||
1538 (status & VID_B_MSK_OPC_ERR) ||
1539 (status & VID_B_MSK_VBI_OPC_ERR) ||
1540 (status & VID_B_MSK_SYNC) ||
1541 (status & VID_B_MSK_VBI_SYNC) ||
1542 (status & VID_B_MSK_OF) ||
1543 (status & VID_B_MSK_VBI_OF)) {
1544 printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
1545 "= 0x%x\n", dev->name, status);
1546 if (status & VID_B_MSK_BAD_PKT)
1547 dprintk(1, " VID_B_MSK_BAD_PKT\n");
1548 if (status & VID_B_MSK_OPC_ERR)
1549 dprintk(1, " VID_B_MSK_OPC_ERR\n");
1550 if (status & VID_B_MSK_VBI_OPC_ERR)
1551 dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n");
1552 if (status & VID_B_MSK_SYNC)
1553 dprintk(1, " VID_B_MSK_SYNC\n");
1554 if (status & VID_B_MSK_VBI_SYNC)
1555 dprintk(1, " VID_B_MSK_VBI_SYNC\n");
1556 if (status & VID_B_MSK_OF)
1557 dprintk(1, " VID_B_MSK_OF\n");
1558 if (status & VID_B_MSK_VBI_OF)
1559 dprintk(1, " VID_B_MSK_VBI_OF\n");
1560
1561 cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
1562 cx23885_sram_channel_dump(dev,
1563 &dev->sram_channels[port->sram_chno]);
1564 cx23885_417_check_encoder(dev);
1565 } else if (status & VID_B_MSK_RISCI1) {
1566 dprintk(7, " VID_B_MSK_RISCI1\n");
1567 spin_lock(&port->slock);
1568 cx23885_wakeup(port, &port->mpegq, count);
1569 spin_unlock(&port->slock);
1570 } else if (status & VID_B_MSK_RISCI2) {
1571 dprintk(7, " VID_B_MSK_RISCI2\n");
1572 spin_lock(&port->slock);
1573 cx23885_restart_queue(port, &port->mpegq);
1574 spin_unlock(&port->slock);
1575 }
1576 if (status) {
1577 cx_write(port->reg_ts_int_stat, status);
1578 handled = 1;
1579 }
1580
1581 return handled;
1582}
1583
Steven Totha6a3f142007-09-08 21:31:56 -03001584static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
1585{
1586 struct cx23885_dev *dev = port->dev;
1587 int handled = 0;
1588 u32 count;
1589
Steven Tothb1b81f12008-01-13 23:42:44 -03001590 if ((status & VID_BC_MSK_OPC_ERR) ||
1591 (status & VID_BC_MSK_BAD_PKT) ||
1592 (status & VID_BC_MSK_SYNC) ||
Steven Toth9c8ced52008-10-16 20:18:44 -03001593 (status & VID_BC_MSK_OF)) {
1594
Steven Totha6a3f142007-09-08 21:31:56 -03001595 if (status & VID_BC_MSK_OPC_ERR)
Steven Toth9c8ced52008-10-16 20:18:44 -03001596 dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
1597 VID_BC_MSK_OPC_ERR);
1598
Steven Totha6a3f142007-09-08 21:31:56 -03001599 if (status & VID_BC_MSK_BAD_PKT)
Steven Toth9c8ced52008-10-16 20:18:44 -03001600 dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
1601 VID_BC_MSK_BAD_PKT);
1602
Steven Totha6a3f142007-09-08 21:31:56 -03001603 if (status & VID_BC_MSK_SYNC)
Steven Toth9c8ced52008-10-16 20:18:44 -03001604 dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n",
1605 VID_BC_MSK_SYNC);
1606
Steven Totha6a3f142007-09-08 21:31:56 -03001607 if (status & VID_BC_MSK_OF)
Steven Toth9c8ced52008-10-16 20:18:44 -03001608 dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n",
1609 VID_BC_MSK_OF);
Steven Totha6a3f142007-09-08 21:31:56 -03001610
1611 printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
1612
1613 cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
Steven Tothb1b81f12008-01-13 23:42:44 -03001614 cx23885_sram_channel_dump(dev,
1615 &dev->sram_channels[port->sram_chno]);
Steven Totha6a3f142007-09-08 21:31:56 -03001616
1617 } else if (status & VID_BC_MSK_RISCI1) {
1618
1619 dprintk(7, " (RISCI1 0x%08x)\n", VID_BC_MSK_RISCI1);
1620
1621 spin_lock(&port->slock);
1622 count = cx_read(port->reg_gpcnt);
1623 cx23885_wakeup(port, &port->mpegq, count);
1624 spin_unlock(&port->slock);
1625
1626 } else if (status & VID_BC_MSK_RISCI2) {
1627
1628 dprintk(7, " (RISCI2 0x%08x)\n", VID_BC_MSK_RISCI2);
1629
1630 spin_lock(&port->slock);
1631 cx23885_restart_queue(port, &port->mpegq);
1632 spin_unlock(&port->slock);
1633
1634 }
1635 if (status) {
1636 cx_write(port->reg_ts_int_stat, status);
1637 handled = 1;
1638 }
1639
1640 return handled;
1641}
1642
Michael Krufky03121f02007-03-11 20:57:52 -03001643static irqreturn_t cx23885_irq(int irq, void *dev_id)
Steven Tothd19770e2007-03-11 20:44:05 -03001644{
1645 struct cx23885_dev *dev = dev_id;
Steven Totha6a3f142007-09-08 21:31:56 -03001646 struct cx23885_tsport *ts1 = &dev->ts1;
1647 struct cx23885_tsport *ts2 = &dev->ts2;
Steven Tothd19770e2007-03-11 20:44:05 -03001648 u32 pci_status, pci_mask;
Steven Toth7b888012008-01-10 03:40:49 -03001649 u32 vida_status, vida_mask;
Steven Toth6f074ab2007-09-08 14:21:03 -03001650 u32 ts1_status, ts1_mask;
Steven Tothd19770e2007-03-11 20:44:05 -03001651 u32 ts2_status, ts2_mask;
Steven Toth7b888012008-01-10 03:40:49 -03001652 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
Andy Wallsf59ad612009-09-27 19:51:50 -03001653 bool ir_handled = false;
Steven Tothd19770e2007-03-11 20:44:05 -03001654
1655 pci_status = cx_read(PCI_INT_STAT);
1656 pci_mask = cx_read(PCI_INT_MSK);
Steven Toth7b888012008-01-10 03:40:49 -03001657 vida_status = cx_read(VID_A_INT_STAT);
1658 vida_mask = cx_read(VID_A_INT_MSK);
Steven Toth6f074ab2007-09-08 14:21:03 -03001659 ts1_status = cx_read(VID_B_INT_STAT);
1660 ts1_mask = cx_read(VID_B_INT_MSK);
Steven Tothd19770e2007-03-11 20:44:05 -03001661 ts2_status = cx_read(VID_C_INT_STAT);
1662 ts2_mask = cx_read(VID_C_INT_MSK);
1663
Steven Toth9c8ced52008-10-16 20:18:44 -03001664 if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
Steven Tothd19770e2007-03-11 20:44:05 -03001665 goto out;
1666
Steven Toth7b888012008-01-10 03:40:49 -03001667 vida_count = cx_read(VID_A_GPCNT);
Steven Totha6a3f142007-09-08 21:31:56 -03001668 ts1_count = cx_read(ts1->reg_gpcnt);
1669 ts2_count = cx_read(ts2->reg_gpcnt);
Steven Toth7b888012008-01-10 03:40:49 -03001670 dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n",
1671 pci_status, pci_mask);
1672 dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
1673 vida_status, vida_mask, vida_count);
1674 dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n",
1675 ts1_status, ts1_mask, ts1_count);
1676 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
1677 ts2_status, ts2_mask, ts2_count);
Steven Tothd19770e2007-03-11 20:44:05 -03001678
Andy Wallsf59ad612009-09-27 19:51:50 -03001679 if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
1680 PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA |
1681 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A |
1682 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
1683 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 |
1684 PCI_MSK_IR)) {
Steven Tothd19770e2007-03-11 20:44:05 -03001685
1686 if (pci_status & PCI_MSK_RISC_RD)
Steven Toth9c8ced52008-10-16 20:18:44 -03001687 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
1688 PCI_MSK_RISC_RD);
1689
Steven Tothd19770e2007-03-11 20:44:05 -03001690 if (pci_status & PCI_MSK_RISC_WR)
Steven Toth9c8ced52008-10-16 20:18:44 -03001691 dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n",
1692 PCI_MSK_RISC_WR);
1693
Steven Tothd19770e2007-03-11 20:44:05 -03001694 if (pci_status & PCI_MSK_AL_RD)
Steven Toth9c8ced52008-10-16 20:18:44 -03001695 dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n",
1696 PCI_MSK_AL_RD);
1697
Steven Tothd19770e2007-03-11 20:44:05 -03001698 if (pci_status & PCI_MSK_AL_WR)
Steven Toth9c8ced52008-10-16 20:18:44 -03001699 dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n",
1700 PCI_MSK_AL_WR);
1701
Steven Tothd19770e2007-03-11 20:44:05 -03001702 if (pci_status & PCI_MSK_APB_DMA)
Steven Toth9c8ced52008-10-16 20:18:44 -03001703 dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n",
1704 PCI_MSK_APB_DMA);
1705
Steven Tothd19770e2007-03-11 20:44:05 -03001706 if (pci_status & PCI_MSK_VID_C)
Steven Toth9c8ced52008-10-16 20:18:44 -03001707 dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n",
1708 PCI_MSK_VID_C);
1709
Steven Tothd19770e2007-03-11 20:44:05 -03001710 if (pci_status & PCI_MSK_VID_B)
Steven Toth9c8ced52008-10-16 20:18:44 -03001711 dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n",
1712 PCI_MSK_VID_B);
1713
Steven Tothd19770e2007-03-11 20:44:05 -03001714 if (pci_status & PCI_MSK_VID_A)
Steven Toth9c8ced52008-10-16 20:18:44 -03001715 dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n",
1716 PCI_MSK_VID_A);
1717
Steven Tothd19770e2007-03-11 20:44:05 -03001718 if (pci_status & PCI_MSK_AUD_INT)
Steven Toth9c8ced52008-10-16 20:18:44 -03001719 dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n",
1720 PCI_MSK_AUD_INT);
1721
Steven Tothd19770e2007-03-11 20:44:05 -03001722 if (pci_status & PCI_MSK_AUD_EXT)
Steven Toth9c8ced52008-10-16 20:18:44 -03001723 dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n",
1724 PCI_MSK_AUD_EXT);
Steven Tothd19770e2007-03-11 20:44:05 -03001725
Igor M. Liplianin5a23b0762009-03-03 12:06:09 -03001726 if (pci_status & PCI_MSK_GPIO0)
1727 dprintk(7, " (PCI_MSK_GPIO0 0x%08x)\n",
1728 PCI_MSK_GPIO0);
1729
1730 if (pci_status & PCI_MSK_GPIO1)
1731 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
1732 PCI_MSK_GPIO1);
Andy Wallsf59ad612009-09-27 19:51:50 -03001733
1734 if (pci_status & PCI_MSK_IR)
1735 dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
1736 PCI_MSK_IR);
Steven Tothd19770e2007-03-11 20:44:05 -03001737 }
1738
Hans Verkuilafd96662009-03-13 13:24:19 -03001739 if (cx23885_boards[dev->board].cimax > 0 &&
Steven Totha26ccc92009-04-29 20:49:12 -03001740 ((pci_status & PCI_MSK_GPIO0) ||
1741 (pci_status & PCI_MSK_GPIO1))) {
1742
1743 if (cx23885_boards[dev->board].cimax > 0)
1744 handled += netup_ci_slot_status(dev, pci_status);
1745
1746 }
Igor M. Liplianin5a23b0762009-03-03 12:06:09 -03001747
Steven Toth7b888012008-01-10 03:40:49 -03001748 if (ts1_status) {
1749 if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
1750 handled += cx23885_irq_ts(ts1, ts1_status);
Steven Tothb1b81f12008-01-13 23:42:44 -03001751 else
1752 if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
1753 handled += cx23885_irq_417(dev, ts1_status);
Steven Toth7b888012008-01-10 03:40:49 -03001754 }
Steven Toth6f074ab2007-09-08 14:21:03 -03001755
Steven Toth7b888012008-01-10 03:40:49 -03001756 if (ts2_status) {
1757 if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
1758 handled += cx23885_irq_ts(ts2, ts2_status);
Steven Tothb1b81f12008-01-13 23:42:44 -03001759 else
1760 if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
1761 handled += cx23885_irq_417(dev, ts2_status);
Steven Toth7b888012008-01-10 03:40:49 -03001762 }
1763
1764 if (vida_status)
1765 handled += cx23885_video_irq(dev, vida_status);
Steven Toth6f074ab2007-09-08 14:21:03 -03001766
Andy Wallsf59ad612009-09-27 19:51:50 -03001767 if (pci_status & PCI_MSK_IR) {
1768 v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine,
1769 pci_status, &ir_handled);
1770 if (ir_handled)
1771 handled++;
1772 }
1773
Steven Toth6f074ab2007-09-08 14:21:03 -03001774 if (handled)
1775 cx_write(PCI_INT_STAT, pci_status);
Steven Tothd19770e2007-03-11 20:44:05 -03001776out:
1777 return IRQ_RETVAL(handled);
1778}
1779
Andy Wallsf59ad612009-09-27 19:51:50 -03001780static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1781 unsigned int notification, void *arg)
1782{
1783 struct cx23885_dev *dev;
1784
1785 if (sd == NULL)
1786 return;
1787
1788 dev = to_cx23885(sd->v4l2_dev);
1789
1790 switch (notification) {
1791 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */
1792 if (sd == dev->sd_ir)
1793 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
1794 break;
1795 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */
1796 if (sd == dev->sd_ir)
1797 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
1798 break;
1799 }
1800}
1801
1802static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
1803{
1804 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
1805 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
1806 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
1807}
1808
Michael Krufky6de72bd2009-05-11 13:37:26 -03001809static inline int encoder_on_portb(struct cx23885_dev *dev)
Steven Toth6f8bee92009-05-02 11:29:50 -03001810{
1811 return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
1812}
1813
Michael Krufky6de72bd2009-05-11 13:37:26 -03001814static inline int encoder_on_portc(struct cx23885_dev *dev)
Steven Toth6f8bee92009-05-02 11:29:50 -03001815{
1816 return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER;
1817}
1818
1819/* Mask represents 32 different GPIOs, GPIO's are split into multiple
1820 * registers depending on the board configuration (and whether the
1821 * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will
1822 * be pushed into the correct hardware register, regardless of the
1823 * physical location. Certain registers are shared so we sanity check
1824 * and report errors if we think we're tampering with a GPIo that might
1825 * be assigned to the encoder (and used for the host bus).
1826 *
1827 * GPIO 2 thru 0 - On the cx23885 bridge
1828 * GPIO 18 thru 3 - On the cx23417 host bus interface
1829 * GPIO 23 thru 19 - On the cx25840 a/v core
1830 */
1831void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask)
1832{
1833 if (mask & 0x7)
1834 cx_set(GP0_IO, mask & 0x7);
1835
1836 if (mask & 0x0007fff8) {
1837 if (encoder_on_portb(dev) || encoder_on_portc(dev))
1838 printk(KERN_ERR
1839 "%s: Setting GPIO on encoder ports\n",
1840 dev->name);
1841 cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
1842 }
1843
1844 /* TODO: 23-19 */
1845 if (mask & 0x00f80000)
1846 printk(KERN_INFO "%s: Unsupported\n", dev->name);
1847}
1848
1849void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
1850{
1851 if (mask & 0x00000007)
1852 cx_clear(GP0_IO, mask & 0x7);
1853
1854 if (mask & 0x0007fff8) {
1855 if (encoder_on_portb(dev) || encoder_on_portc(dev))
1856 printk(KERN_ERR
1857 "%s: Clearing GPIO moving on encoder ports\n",
1858 dev->name);
1859 cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
1860 }
1861
1862 /* TODO: 23-19 */
1863 if (mask & 0x00f80000)
1864 printk(KERN_INFO "%s: Unsupported\n", dev->name);
1865}
1866
Igor M. Liplianin09ea33e2009-11-24 20:16:04 -03001867u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
1868{
1869 if (mask & 0x00000007)
1870 return (cx_read(GP0_IO) >> 8) & mask & 0x7;
1871
1872 if (mask & 0x0007fff8) {
1873 if (encoder_on_portb(dev) || encoder_on_portc(dev))
1874 printk(KERN_ERR
1875 "%s: Reading GPIO moving on encoder ports\n",
1876 dev->name);
1877 return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
1878 }
1879
1880 /* TODO: 23-19 */
1881 if (mask & 0x00f80000)
1882 printk(KERN_INFO "%s: Unsupported\n", dev->name);
1883
1884 return 0;
1885}
1886
Steven Toth6f8bee92009-05-02 11:29:50 -03001887void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
1888{
1889 if ((mask & 0x00000007) && asoutput)
1890 cx_set(GP0_IO, (mask & 0x7) << 16);
1891 else if ((mask & 0x00000007) && !asoutput)
1892 cx_clear(GP0_IO, (mask & 0x7) << 16);
1893
1894 if (mask & 0x0007fff8) {
1895 if (encoder_on_portb(dev) || encoder_on_portc(dev))
1896 printk(KERN_ERR
1897 "%s: Enabling GPIO on encoder ports\n",
1898 dev->name);
1899 }
1900
1901 /* MC417_OEN is active low for output, write 1 for an input */
1902 if ((mask & 0x0007fff8) && asoutput)
1903 cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3);
1904
1905 else if ((mask & 0x0007fff8) && !asoutput)
1906 cx_set(MC417_OEN, (mask & 0x7fff8) >> 3);
1907
1908 /* TODO: 23-19 */
1909}
1910
Steven Tothd19770e2007-03-11 20:44:05 -03001911static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
Michael Krufky44a64812007-03-20 23:00:18 -03001912 const struct pci_device_id *pci_id)
Steven Tothd19770e2007-03-11 20:44:05 -03001913{
1914 struct cx23885_dev *dev;
1915 int err;
1916
Michael Krufky44a64812007-03-20 23:00:18 -03001917 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
Steven Tothd19770e2007-03-11 20:44:05 -03001918 if (NULL == dev)
1919 return -ENOMEM;
1920
Hans Verkuilc0714f62009-03-13 08:02:43 -03001921 err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
1922 if (err < 0)
1923 goto fail_free;
1924
Andy Wallsf59ad612009-09-27 19:51:50 -03001925 /* Prepare to handle notifications from subdevices */
1926 cx23885_v4l2_dev_notify_init(dev);
1927
Steven Tothd19770e2007-03-11 20:44:05 -03001928 /* pci init */
1929 dev->pci = pci_dev;
1930 if (pci_enable_device(pci_dev)) {
1931 err = -EIO;
Hans Verkuilc0714f62009-03-13 08:02:43 -03001932 goto fail_unreg;
Steven Tothd19770e2007-03-11 20:44:05 -03001933 }
1934
1935 if (cx23885_dev_setup(dev) < 0) {
1936 err = -EINVAL;
Hans Verkuilc0714f62009-03-13 08:02:43 -03001937 goto fail_unreg;
Steven Tothd19770e2007-03-11 20:44:05 -03001938 }
1939
1940 /* print pci info */
1941 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
1942 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
1943 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
1944 "latency: %d, mmio: 0x%llx\n", dev->name,
1945 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
Steven Totha589b662008-01-13 23:44:47 -03001946 dev->pci_lat,
1947 (unsigned long long)pci_resource_start(pci_dev, 0));
Steven Tothd19770e2007-03-11 20:44:05 -03001948
1949 pci_set_master(pci_dev);
1950 if (!pci_dma_supported(pci_dev, 0xffffffff)) {
1951 printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
1952 err = -EIO;
1953 goto fail_irq;
1954 }
1955
Kusanagi Kouichie38030f2010-02-06 02:45:33 -03001956 if (!pci_enable_msi(pci_dev))
1957 err = request_irq(pci_dev->irq, cx23885_irq,
1958 IRQF_DISABLED, dev->name, dev);
1959 else
1960 err = request_irq(pci_dev->irq, cx23885_irq,
1961 IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
Steven Tothd19770e2007-03-11 20:44:05 -03001962 if (err < 0) {
1963 printk(KERN_ERR "%s: can't get IRQ %d\n",
1964 dev->name, pci_dev->irq);
1965 goto fail_irq;
1966 }
1967
Hans Verkuilafd96662009-03-13 13:24:19 -03001968 switch (dev->board) {
1969 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
1970 cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */
1971 break;
1972 }
Igor M. Liplianin5a23b0762009-03-03 12:06:09 -03001973
Andy Wallsf59ad612009-09-27 19:51:50 -03001974 /*
1975 * The CX2388[58] IR controller can start firing interrupts when
1976 * enabled, so these have to take place after the cx23885_irq() handler
1977 * is hooked up by the call to request_irq() above.
1978 */
1979 cx23885_ir_pci_int_enable(dev);
Andy Wallsdbda8f72009-09-27 20:55:41 -03001980 cx23885_input_init(dev);
Andy Wallsf59ad612009-09-27 19:51:50 -03001981
Steven Tothd19770e2007-03-11 20:44:05 -03001982 return 0;
1983
1984fail_irq:
1985 cx23885_dev_unregister(dev);
Hans Verkuilc0714f62009-03-13 08:02:43 -03001986fail_unreg:
1987 v4l2_device_unregister(&dev->v4l2_dev);
Steven Tothd19770e2007-03-11 20:44:05 -03001988fail_free:
1989 kfree(dev);
1990 return err;
1991}
1992
1993static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
1994{
Hans Verkuilc0714f62009-03-13 08:02:43 -03001995 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
1996 struct cx23885_dev *dev = to_cx23885(v4l2_dev);
Steven Tothd19770e2007-03-11 20:44:05 -03001997
Andy Wallsdbda8f72009-09-27 20:55:41 -03001998 cx23885_input_fini(dev);
Andy Wallsf59ad612009-09-27 19:51:50 -03001999 cx23885_ir_fini(dev);
Steven Tothd19770e2007-03-11 20:44:05 -03002000
Andy Wallsf59ad612009-09-27 19:51:50 -03002001 cx23885_shutdown(dev);
Andy Walls29f8a0a2009-09-26 23:17:30 -03002002
Steven Tothd19770e2007-03-11 20:44:05 -03002003 pci_disable_device(pci_dev);
2004
2005 /* unregister stuff */
2006 free_irq(pci_dev->irq, dev);
Kusanagi Kouichie38030f2010-02-06 02:45:33 -03002007 pci_disable_msi(pci_dev);
Steven Tothd19770e2007-03-11 20:44:05 -03002008
Steven Tothd19770e2007-03-11 20:44:05 -03002009 cx23885_dev_unregister(dev);
Hans Verkuilc0714f62009-03-13 08:02:43 -03002010 v4l2_device_unregister(v4l2_dev);
Steven Tothd19770e2007-03-11 20:44:05 -03002011 kfree(dev);
2012}
2013
2014static struct pci_device_id cx23885_pci_tbl[] = {
2015 {
2016 /* CX23885 */
2017 .vendor = 0x14f1,
2018 .device = 0x8852,
2019 .subvendor = PCI_ANY_ID,
2020 .subdevice = PCI_ANY_ID,
Steven Toth9c8ced52008-10-16 20:18:44 -03002021 }, {
Steven Tothd19770e2007-03-11 20:44:05 -03002022 /* CX23887 Rev 2 */
2023 .vendor = 0x14f1,
2024 .device = 0x8880,
2025 .subvendor = PCI_ANY_ID,
2026 .subdevice = PCI_ANY_ID,
Steven Toth9c8ced52008-10-16 20:18:44 -03002027 }, {
Steven Tothd19770e2007-03-11 20:44:05 -03002028 /* --- end of list --- */
2029 }
2030};
2031MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl);
2032
2033static struct pci_driver cx23885_pci_driver = {
2034 .name = "cx23885",
2035 .id_table = cx23885_pci_tbl,
2036 .probe = cx23885_initdev,
2037 .remove = __devexit_p(cx23885_finidev),
2038 /* TODO */
2039 .suspend = NULL,
2040 .resume = NULL,
2041};
2042
Peter Huewe9710e7a2009-11-04 15:28:33 -03002043static int __init cx23885_init(void)
Steven Tothd19770e2007-03-11 20:44:05 -03002044{
2045 printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n",
Steven Toth047646b2007-03-20 15:33:53 -03002046 (CX23885_VERSION_CODE >> 16) & 0xff,
2047 (CX23885_VERSION_CODE >> 8) & 0xff,
2048 CX23885_VERSION_CODE & 0xff);
Steven Tothd19770e2007-03-11 20:44:05 -03002049#ifdef SNAPSHOT
2050 printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n",
2051 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
2052#endif
2053 return pci_register_driver(&cx23885_pci_driver);
2054}
2055
Peter Huewe9710e7a2009-11-04 15:28:33 -03002056static void __exit cx23885_fini(void)
Steven Tothd19770e2007-03-11 20:44:05 -03002057{
2058 pci_unregister_driver(&cx23885_pci_driver);
2059}
2060
2061module_init(cx23885_init);
2062module_exit(cx23885_fini);
2063
2064/* ----------------------------------------------------------- */