blob: 67f689de4daada8a8d110c9377ce65e62f6efc60 [file] [log] [blame]
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001/*
2 * Driver for the Conexant CX25821 PCIe bridge
3 *
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03004 * Copyright (C) 2009 Conexant Systems Inc.
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03005 * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
6 * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 *
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/i2c.h>
25#include "cx25821.h"
26#include "cx25821-sram.h"
27#include "cx25821-video.h"
28
29MODULE_DESCRIPTION("Driver for Athena cards");
30MODULE_AUTHOR("Shu Lin - Hiep Huynh");
31MODULE_LICENSE("GPL");
32
33struct list_head cx25821_devlist;
34
35static unsigned int debug;
36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "enable debug messages");
38
Mauro Carvalho Chehab53e712d2009-09-13 11:39:12 -030039static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030040module_param_array(card, int, NULL, 0444);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -030041MODULE_PARM_DESC(card, "card type");
42
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -030043static unsigned int cx25821_devcount = 0;
44
45static DEFINE_MUTEX(devlist);
46LIST_HEAD(cx25821_devlist);
47
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -030048struct sram_channel cx25821_sram_channels[] = {
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030049 [SRAM_CH00] = {
50 .i = SRAM_CH00,
51 .name = "VID A",
52 .cmds_start = VID_A_DOWN_CMDS,
53 .ctrl_start = VID_A_IQ,
54 .cdt = VID_A_CDT,
55 .fifo_start = VID_A_DOWN_CLUSTER_1,
56 .fifo_size = (VID_CLUSTER_SIZE << 2),
57 .ptr1_reg = DMA1_PTR1,
58 .ptr2_reg = DMA1_PTR2,
59 .cnt1_reg = DMA1_CNT1,
60 .cnt2_reg = DMA1_CNT2,
61 .int_msk = VID_A_INT_MSK,
62 .int_stat = VID_A_INT_STAT,
63 .int_mstat = VID_A_INT_MSTAT,
64 .dma_ctl = VID_DST_A_DMA_CTL,
65 .gpcnt_ctl = VID_DST_A_GPCNT_CTL,
66 .gpcnt = VID_DST_A_GPCNT,
67 .vip_ctl = VID_DST_A_VIP_CTL,
68 .pix_frmt = VID_DST_A_PIX_FRMT,
69 },
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -030070
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030071 [SRAM_CH01] = {
72 .i = SRAM_CH01,
73 .name = "VID B",
74 .cmds_start = VID_B_DOWN_CMDS,
75 .ctrl_start = VID_B_IQ,
76 .cdt = VID_B_CDT,
77 .fifo_start = VID_B_DOWN_CLUSTER_1,
78 .fifo_size = (VID_CLUSTER_SIZE << 2),
79 .ptr1_reg = DMA2_PTR1,
80 .ptr2_reg = DMA2_PTR2,
81 .cnt1_reg = DMA2_CNT1,
82 .cnt2_reg = DMA2_CNT2,
83 .int_msk = VID_B_INT_MSK,
84 .int_stat = VID_B_INT_STAT,
85 .int_mstat = VID_B_INT_MSTAT,
86 .dma_ctl = VID_DST_B_DMA_CTL,
87 .gpcnt_ctl = VID_DST_B_GPCNT_CTL,
88 .gpcnt = VID_DST_B_GPCNT,
89 .vip_ctl = VID_DST_B_VIP_CTL,
90 .pix_frmt = VID_DST_B_PIX_FRMT,
91 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -030092
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030093 [SRAM_CH02] = {
94 .i = SRAM_CH02,
95 .name = "VID C",
96 .cmds_start = VID_C_DOWN_CMDS,
97 .ctrl_start = VID_C_IQ,
98 .cdt = VID_C_CDT,
99 .fifo_start = VID_C_DOWN_CLUSTER_1,
100 .fifo_size = (VID_CLUSTER_SIZE << 2),
101 .ptr1_reg = DMA3_PTR1,
102 .ptr2_reg = DMA3_PTR2,
103 .cnt1_reg = DMA3_CNT1,
104 .cnt2_reg = DMA3_CNT2,
105 .int_msk = VID_C_INT_MSK,
106 .int_stat = VID_C_INT_STAT,
107 .int_mstat = VID_C_INT_MSTAT,
108 .dma_ctl = VID_DST_C_DMA_CTL,
109 .gpcnt_ctl = VID_DST_C_GPCNT_CTL,
110 .gpcnt = VID_DST_C_GPCNT,
111 .vip_ctl = VID_DST_C_VIP_CTL,
112 .pix_frmt = VID_DST_C_PIX_FRMT,
113 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300114
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300115 [SRAM_CH03] = {
116 .i = SRAM_CH03,
117 .name = "VID D",
118 .cmds_start = VID_D_DOWN_CMDS,
119 .ctrl_start = VID_D_IQ,
120 .cdt = VID_D_CDT,
121 .fifo_start = VID_D_DOWN_CLUSTER_1,
122 .fifo_size = (VID_CLUSTER_SIZE << 2),
123 .ptr1_reg = DMA4_PTR1,
124 .ptr2_reg = DMA4_PTR2,
125 .cnt1_reg = DMA4_CNT1,
126 .cnt2_reg = DMA4_CNT2,
127 .int_msk = VID_D_INT_MSK,
128 .int_stat = VID_D_INT_STAT,
129 .int_mstat = VID_D_INT_MSTAT,
130 .dma_ctl = VID_DST_D_DMA_CTL,
131 .gpcnt_ctl = VID_DST_D_GPCNT_CTL,
132 .gpcnt = VID_DST_D_GPCNT,
133 .vip_ctl = VID_DST_D_VIP_CTL,
134 .pix_frmt = VID_DST_D_PIX_FRMT,
135 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300136
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300137 [SRAM_CH04] = {
138 .i = SRAM_CH04,
139 .name = "VID E",
140 .cmds_start = VID_E_DOWN_CMDS,
141 .ctrl_start = VID_E_IQ,
142 .cdt = VID_E_CDT,
143 .fifo_start = VID_E_DOWN_CLUSTER_1,
144 .fifo_size = (VID_CLUSTER_SIZE << 2),
145 .ptr1_reg = DMA5_PTR1,
146 .ptr2_reg = DMA5_PTR2,
147 .cnt1_reg = DMA5_CNT1,
148 .cnt2_reg = DMA5_CNT2,
149 .int_msk = VID_E_INT_MSK,
150 .int_stat = VID_E_INT_STAT,
151 .int_mstat = VID_E_INT_MSTAT,
152 .dma_ctl = VID_DST_E_DMA_CTL,
153 .gpcnt_ctl = VID_DST_E_GPCNT_CTL,
154 .gpcnt = VID_DST_E_GPCNT,
155 .vip_ctl = VID_DST_E_VIP_CTL,
156 .pix_frmt = VID_DST_E_PIX_FRMT,
157 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300158
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300159 [SRAM_CH05] = {
160 .i = SRAM_CH05,
161 .name = "VID F",
162 .cmds_start = VID_F_DOWN_CMDS,
163 .ctrl_start = VID_F_IQ,
164 .cdt = VID_F_CDT,
165 .fifo_start = VID_F_DOWN_CLUSTER_1,
166 .fifo_size = (VID_CLUSTER_SIZE << 2),
167 .ptr1_reg = DMA6_PTR1,
168 .ptr2_reg = DMA6_PTR2,
169 .cnt1_reg = DMA6_CNT1,
170 .cnt2_reg = DMA6_CNT2,
171 .int_msk = VID_F_INT_MSK,
172 .int_stat = VID_F_INT_STAT,
173 .int_mstat = VID_F_INT_MSTAT,
174 .dma_ctl = VID_DST_F_DMA_CTL,
175 .gpcnt_ctl = VID_DST_F_GPCNT_CTL,
176 .gpcnt = VID_DST_F_GPCNT,
177 .vip_ctl = VID_DST_F_VIP_CTL,
178 .pix_frmt = VID_DST_F_PIX_FRMT,
179 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300180
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300181 [SRAM_CH06] = {
182 .i = SRAM_CH06,
183 .name = "VID G",
184 .cmds_start = VID_G_DOWN_CMDS,
185 .ctrl_start = VID_G_IQ,
186 .cdt = VID_G_CDT,
187 .fifo_start = VID_G_DOWN_CLUSTER_1,
188 .fifo_size = (VID_CLUSTER_SIZE << 2),
189 .ptr1_reg = DMA7_PTR1,
190 .ptr2_reg = DMA7_PTR2,
191 .cnt1_reg = DMA7_CNT1,
192 .cnt2_reg = DMA7_CNT2,
193 .int_msk = VID_G_INT_MSK,
194 .int_stat = VID_G_INT_STAT,
195 .int_mstat = VID_G_INT_MSTAT,
196 .dma_ctl = VID_DST_G_DMA_CTL,
197 .gpcnt_ctl = VID_DST_G_GPCNT_CTL,
198 .gpcnt = VID_DST_G_GPCNT,
199 .vip_ctl = VID_DST_G_VIP_CTL,
200 .pix_frmt = VID_DST_G_PIX_FRMT,
201 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300202
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300203 [SRAM_CH07] = {
204 .i = SRAM_CH07,
205 .name = "VID H",
206 .cmds_start = VID_H_DOWN_CMDS,
207 .ctrl_start = VID_H_IQ,
208 .cdt = VID_H_CDT,
209 .fifo_start = VID_H_DOWN_CLUSTER_1,
210 .fifo_size = (VID_CLUSTER_SIZE << 2),
211 .ptr1_reg = DMA8_PTR1,
212 .ptr2_reg = DMA8_PTR2,
213 .cnt1_reg = DMA8_CNT1,
214 .cnt2_reg = DMA8_CNT2,
215 .int_msk = VID_H_INT_MSK,
216 .int_stat = VID_H_INT_STAT,
217 .int_mstat = VID_H_INT_MSTAT,
218 .dma_ctl = VID_DST_H_DMA_CTL,
219 .gpcnt_ctl = VID_DST_H_GPCNT_CTL,
220 .gpcnt = VID_DST_H_GPCNT,
221 .vip_ctl = VID_DST_H_VIP_CTL,
222 .pix_frmt = VID_DST_H_PIX_FRMT,
223 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300224
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300225 [SRAM_CH08] = {
226 .name = "audio from",
227 .cmds_start = AUD_A_DOWN_CMDS,
228 .ctrl_start = AUD_A_IQ,
229 .cdt = AUD_A_CDT,
230 .fifo_start = AUD_A_DOWN_CLUSTER_1,
231 .fifo_size = AUDIO_CLUSTER_SIZE * 3,
232 .ptr1_reg = DMA17_PTR1,
233 .ptr2_reg = DMA17_PTR2,
234 .cnt1_reg = DMA17_CNT1,
235 .cnt2_reg = DMA17_CNT2,
236 },
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300237
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300238 [SRAM_CH09] = {
239 .i = SRAM_CH09,
240 .name = "VID Upstream I",
241 .cmds_start = VID_I_UP_CMDS,
242 .ctrl_start = VID_I_IQ,
243 .cdt = VID_I_CDT,
244 .fifo_start = VID_I_UP_CLUSTER_1,
245 .fifo_size = (VID_CLUSTER_SIZE << 2),
246 .ptr1_reg = DMA15_PTR1,
247 .ptr2_reg = DMA15_PTR2,
248 .cnt1_reg = DMA15_CNT1,
249 .cnt2_reg = DMA15_CNT2,
250 .int_msk = VID_I_INT_MSK,
251 .int_stat = VID_I_INT_STAT,
252 .int_mstat = VID_I_INT_MSTAT,
253 .dma_ctl = VID_SRC_I_DMA_CTL,
254 .gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
255 .gpcnt = VID_SRC_I_GPCNT,
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300256
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300257 .vid_fmt_ctl = VID_SRC_I_FMT_CTL,
258 .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
259 .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
260 .vid_cdt_size = VID_SRC_I_CDT_SZ,
261 .irq_bit = 8,
262 },
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300263
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300264 [SRAM_CH10] = {
265 .i = SRAM_CH10,
266 .name = "VID Upstream J",
267 .cmds_start = VID_J_UP_CMDS,
268 .ctrl_start = VID_J_IQ,
269 .cdt = VID_J_CDT,
270 .fifo_start = VID_J_UP_CLUSTER_1,
271 .fifo_size = (VID_CLUSTER_SIZE << 2),
272 .ptr1_reg = DMA16_PTR1,
273 .ptr2_reg = DMA16_PTR2,
274 .cnt1_reg = DMA16_CNT1,
275 .cnt2_reg = DMA16_CNT2,
276 .int_msk = VID_J_INT_MSK,
277 .int_stat = VID_J_INT_STAT,
278 .int_mstat = VID_J_INT_MSTAT,
279 .dma_ctl = VID_SRC_J_DMA_CTL,
280 .gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
281 .gpcnt = VID_SRC_J_GPCNT,
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300282
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300283 .vid_fmt_ctl = VID_SRC_J_FMT_CTL,
284 .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
285 .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
286 .vid_cdt_size = VID_SRC_J_CDT_SZ,
287 .irq_bit = 9,
288 },
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300289
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300290 [SRAM_CH11] = {
291 .i = SRAM_CH11,
292 .name = "Audio Upstream Channel B",
293 .cmds_start = AUD_B_UP_CMDS,
294 .ctrl_start = AUD_B_IQ,
295 .cdt = AUD_B_CDT,
296 .fifo_start = AUD_B_UP_CLUSTER_1,
297 .fifo_size = (AUDIO_CLUSTER_SIZE * 3),
298 .ptr1_reg = DMA22_PTR1,
299 .ptr2_reg = DMA22_PTR2,
300 .cnt1_reg = DMA22_CNT1,
301 .cnt2_reg = DMA22_CNT2,
302 .int_msk = AUD_B_INT_MSK,
303 .int_stat = AUD_B_INT_STAT,
304 .int_mstat = AUD_B_INT_MSTAT,
305 .dma_ctl = AUD_INT_DMA_CTL,
306 .gpcnt_ctl = AUD_B_GPCNT_CTL,
307 .gpcnt = AUD_B_GPCNT,
308 .aud_length = AUD_B_LNGTH,
309 .aud_cfg = AUD_B_CFG,
310 .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
311 .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
312 .irq_bit = 11,
313 },
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300314};
315
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300316struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
317struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
318struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
319struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
320struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
321struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
322struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
323struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300324struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300325struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
326struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
327
328struct cx25821_dmaqueue mpegq;
329
330static int cx25821_risc_decode(u32 risc)
331{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300332 static char *instr[16] = {
333 [RISC_SYNC >> 28] = "sync",
334 [RISC_WRITE >> 28] = "write",
335 [RISC_WRITEC >> 28] = "writec",
336 [RISC_READ >> 28] = "read",
337 [RISC_READC >> 28] = "readc",
338 [RISC_JUMP >> 28] = "jump",
339 [RISC_SKIP >> 28] = "skip",
340 [RISC_WRITERM >> 28] = "writerm",
341 [RISC_WRITECM >> 28] = "writecm",
342 [RISC_WRITECR >> 28] = "writecr",
343 };
344 static int incr[16] = {
345 [RISC_WRITE >> 28] = 3,
346 [RISC_JUMP >> 28] = 3,
347 [RISC_SKIP >> 28] = 1,
348 [RISC_SYNC >> 28] = 1,
349 [RISC_WRITERM >> 28] = 3,
350 [RISC_WRITECM >> 28] = 3,
351 [RISC_WRITECR >> 28] = 4,
352 };
353 static char *bits[] = {
354 "12", "13", "14", "resync",
355 "cnt0", "cnt1", "18", "19",
356 "20", "21", "22", "23",
357 "irq1", "irq2", "eol", "sol",
358 };
359 int i;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300360
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300361 printk("0x%08x [ %s", risc,
362 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
363 for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
364 if (risc & (1 << (i + 12)))
365 printk(" %s", bits[i]);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300366 }
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300367 printk(" count=%d ]\n", risc & 0xfff);
368 return incr[risc >> 28] ? incr[risc >> 28] : 1;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300369}
370
371static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
372{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300373 struct cx25821_i2c *bus = i2c_adap->algo_data;
374 struct cx25821_dev *dev = bus->dev;
375 return cx_read(bus->reg_stat) & 0x01;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300376}
377
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300378void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300379{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300380 int tmp = 0;
381 u32 value = 0;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300382
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300383 value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300384}
385
386static void cx25821_registers_init(struct cx25821_dev *dev)
387{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300388 u32 tmp;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300389
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300390 // enable RUN_RISC in Pecos
391 cx_write(DEV_CNTRL2, 0x20);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300392
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300393 // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts
394 // I2C interrupt masking is handled by the I2C objects themselves.
395 cx_write(PCI_INT_MSK, 0x2001FFFF);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300396
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300397 tmp = cx_read(RDR_TLCTL0);
398 tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit
399 cx_write(RDR_TLCTL0, tmp);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300400
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300401 // PLL-A setting for the Audio Master Clock
402 cx_write(PLL_A_INT_FRAC, 0x9807A58B);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300403
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300404 // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1
405 cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300406
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300407 // clear reset bit [31]
408 tmp = cx_read(PLL_A_INT_FRAC);
409 cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300410
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300411 // PLL-B setting for Mobilygen Host Bus Interface
412 cx_write(PLL_B_INT_FRAC, 0x9883A86F);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300413
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300414 // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0
415 cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300416
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300417 // clear reset bit [31]
418 tmp = cx_read(PLL_B_INT_FRAC);
419 cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300420
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300421 // PLL-C setting for video upstream channel
422 cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300423
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300424 // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0
425 cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300426
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300427 // clear reset bit [31]
428 tmp = cx_read(PLL_C_INT_FRAC);
429 cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300430
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300431 // PLL-D setting for audio upstream channel
432 cx_write(PLL_D_INT_FRAC, 0x98757F5B);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300433
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300434 // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0
435 cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300436
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300437 // clear reset bit [31]
438 tmp = cx_read(PLL_D_INT_FRAC);
439 cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300440
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300441 // This selects the PLL C clock source for the video upstream channel I and J
442 tmp = cx_read(VID_CH_CLK_SEL);
443 cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300444
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300445 // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
446 //select 656/VIP DST for downstream Channel A - C
447 tmp = cx_read(VID_CH_MODE_SEL);
448 //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);
449 cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300450
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300451 // enables 656 port I and J as output
452 tmp = cx_read(CLK_RST);
453 tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead
454 cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300455
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300456 mdelay(100);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300457}
458
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300459int cx25821_sram_channel_setup(struct cx25821_dev *dev,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300460 struct sram_channel *ch,
461 unsigned int bpl, u32 risc)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300462{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300463 unsigned int i, lines;
464 u32 cdt;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300465
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300466 if (ch->cmds_start == 0) {
467 cx_write(ch->ptr1_reg, 0);
468 cx_write(ch->ptr2_reg, 0);
469 cx_write(ch->cnt2_reg, 0);
470 cx_write(ch->cnt1_reg, 0);
471 return 0;
472 }
473
474 bpl = (bpl + 7) & ~7; /* alignment */
475 cdt = ch->cdt;
476 lines = ch->fifo_size / bpl;
477
478 if (lines > 4) {
479 lines = 4;
480 }
481
482 BUG_ON(lines < 2);
483
484 cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
485 cx_write(8 + 4, 8);
486 cx_write(8 + 8, 0);
487
488 /* write CDT */
489 for (i = 0; i < lines; i++) {
490 cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
491 cx_write(cdt + 16 * i + 4, 0);
492 cx_write(cdt + 16 * i + 8, 0);
493 cx_write(cdt + 16 * i + 12, 0);
494 }
495
496 //init the first cdt buffer
497 for (i = 0; i < 128; i++)
498 cx_write(ch->fifo_start + 4 * i, i);
499
500 /* write CMDS */
501 if (ch->jumponly) {
502 cx_write(ch->cmds_start + 0, 8);
503 } else {
504 cx_write(ch->cmds_start + 0, risc);
505 }
506
507 cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
508 cx_write(ch->cmds_start + 8, cdt);
509 cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
510 cx_write(ch->cmds_start + 16, ch->ctrl_start);
511
512 if (ch->jumponly)
513 cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
514 else
515 cx_write(ch->cmds_start + 20, 64 >> 2);
516
517 for (i = 24; i < 80; i += 4)
518 cx_write(ch->cmds_start + i, 0);
519
520 /* fill registers */
521 cx_write(ch->ptr1_reg, ch->fifo_start);
522 cx_write(ch->ptr2_reg, cdt);
523 cx_write(ch->cnt2_reg, (lines * 16) >> 3);
524 cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
525
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300526 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300527}
528
529int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300530 struct sram_channel *ch,
531 unsigned int bpl, u32 risc)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300532{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300533 unsigned int i, lines;
534 u32 cdt;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300535
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300536 if (ch->cmds_start == 0) {
537 cx_write(ch->ptr1_reg, 0);
538 cx_write(ch->ptr2_reg, 0);
539 cx_write(ch->cnt2_reg, 0);
540 cx_write(ch->cnt1_reg, 0);
541 return 0;
542 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300543
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300544 bpl = (bpl + 7) & ~7; /* alignment */
545 cdt = ch->cdt;
546 lines = ch->fifo_size / bpl;
547
548 if (lines > 3) {
549 lines = 3; //for AUDIO
550 }
551
552 BUG_ON(lines < 2);
553
554 cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
555 cx_write(8 + 4, 8);
556 cx_write(8 + 8, 0);
557
558 /* write CDT */
559 for (i = 0; i < lines; i++) {
560 cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
561 cx_write(cdt + 16 * i + 4, 0);
562 cx_write(cdt + 16 * i + 8, 0);
563 cx_write(cdt + 16 * i + 12, 0);
564 }
565
566 /* write CMDS */
567 if (ch->jumponly) {
568 cx_write(ch->cmds_start + 0, 8);
569 } else {
570 cx_write(ch->cmds_start + 0, risc);
571 }
572
573 cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
574 cx_write(ch->cmds_start + 8, cdt);
575 cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
576 cx_write(ch->cmds_start + 16, ch->ctrl_start);
577
578 //IQ size
579 if (ch->jumponly) {
580 cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
581 } else {
582 cx_write(ch->cmds_start + 20, 64 >> 2);
583 }
584
585 //zero out
586 for (i = 24; i < 80; i += 4)
587 cx_write(ch->cmds_start + i, 0);
588
589 /* fill registers */
590 cx_write(ch->ptr1_reg, ch->fifo_start);
591 cx_write(ch->ptr2_reg, cdt);
592 cx_write(ch->cnt2_reg, (lines * 16) >> 3);
593 cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
594
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300595 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300596}
597
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300598void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
599{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300600 static char *name[] = {
601 "init risc lo",
602 "init risc hi",
603 "cdt base",
604 "cdt size",
605 "iq base",
606 "iq size",
607 "risc pc lo",
608 "risc pc hi",
609 "iq wr ptr",
610 "iq rd ptr",
611 "cdt current",
612 "pci target lo",
613 "pci target hi",
614 "line / byte",
615 };
616 u32 risc;
617 unsigned int i, j, n;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300618
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300619 printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name,
620 ch->name);
621 for (i = 0; i < ARRAY_SIZE(name); i++)
622 printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i * 4,
623 name[i], cx_read(ch->cmds_start + 4 * i));
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300624
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300625 j = i * 4;
626 for (i = 0; i < 4;) {
627 risc = cx_read(ch->cmds_start + 4 * (i + 14));
628 printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i);
629 i += cx25821_risc_decode(risc);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300630 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300631
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300632 for (i = 0; i < (64 >> 2); i += n) {
633 risc = cx_read(ch->ctrl_start + 4 * i);
634 /* No consideration for bits 63-32 */
635
636 printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
637 ch->ctrl_start + 4 * i, i);
638 n = cx25821_risc_decode(risc);
639 for (j = 1; j < n; j++) {
640 risc = cx_read(ch->ctrl_start + 4 * (i + j));
641 printk(KERN_WARNING
642 "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
643 4 * (i + j), i + j, risc, j);
644 }
645 }
646
647 printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n",
648 ch->fifo_start, ch->fifo_start + ch->fifo_size);
649 printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n",
650 ch->ctrl_start, ch->ctrl_start + 6 * 16);
651 printk(KERN_WARNING " : ptr1_reg: 0x%08x\n",
652 cx_read(ch->ptr1_reg));
653 printk(KERN_WARNING " : ptr2_reg: 0x%08x\n",
654 cx_read(ch->ptr2_reg));
655 printk(KERN_WARNING " : cnt1_reg: 0x%08x\n",
656 cx_read(ch->cnt1_reg));
657 printk(KERN_WARNING " : cnt2_reg: 0x%08x\n",
658 cx_read(ch->cnt2_reg));
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300659}
660
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300661void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
662 struct sram_channel *ch)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300663{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300664 static char *name[] = {
665 "init risc lo",
666 "init risc hi",
667 "cdt base",
668 "cdt size",
669 "iq base",
670 "iq size",
671 "risc pc lo",
672 "risc pc hi",
673 "iq wr ptr",
674 "iq rd ptr",
675 "cdt current",
676 "pci target lo",
677 "pci target hi",
678 "line / byte",
679 };
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300680
681 u32 risc, value, tmp;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300682 unsigned int i, j, n;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300683
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300684 printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n",
685 dev->name, ch->name);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300686
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300687 for (i = 0; i < ARRAY_SIZE(name); i++)
688 printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n",
689 dev->name, i * 4, name[i],
690 cx_read(ch->cmds_start + 4 * i));
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300691
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300692 j = i * 4;
693 for (i = 0; i < 4;) {
694 risc = cx_read(ch->cmds_start + 4 * (i + 14));
695 printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i);
696 i += cx25821_risc_decode(risc);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300697 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300698
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300699 for (i = 0; i < (64 >> 2); i += n) {
700 risc = cx_read(ch->ctrl_start + 4 * i);
701 /* No consideration for bits 63-32 */
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300702
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300703 printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
704 ch->ctrl_start + 4 * i, i);
705 n = cx25821_risc_decode(risc);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300706
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300707 for (j = 1; j < n; j++) {
708 risc = cx_read(ch->ctrl_start + 4 * (i + j));
709 printk(KERN_WARNING
710 "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
711 4 * (i + j), i + j, risc, j);
712 }
713 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300714
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300715 printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n",
716 ch->fifo_start, ch->fifo_start + ch->fifo_size);
717 printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n",
718 ch->ctrl_start, ch->ctrl_start + 6 * 16);
719 printk(KERN_WARNING " : ptr1_reg: 0x%08x\n",
720 cx_read(ch->ptr1_reg));
721 printk(KERN_WARNING " : ptr2_reg: 0x%08x\n",
722 cx_read(ch->ptr2_reg));
723 printk(KERN_WARNING " : cnt1_reg: 0x%08x\n",
724 cx_read(ch->cnt1_reg));
725 printk(KERN_WARNING " : cnt2_reg: 0x%08x\n",
726 cx_read(ch->cnt2_reg));
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300727
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300728 for (i = 0; i < 4; i++) {
729 risc = cx_read(ch->cmds_start + 56 + (i * 4));
730 printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc);
731 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300732
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300733 //read data from the first cdt buffer
734 risc = cx_read(AUD_A_CDT);
735 printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc);
736 for (i = 0; i < 8; i++) {
737 n = cx_read(risc + i * 4);
738 printk(KERN_WARNING "0x%x ", n);
739 }
740 printk(KERN_WARNING "\n\n");
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300741
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300742 value = cx_read(CLK_RST);
743 CX25821_INFO(" CLK_RST = 0x%x \n\n", value);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300744
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300745 value = cx_read(PLL_A_POST_STAT_BIST);
746 CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value);
747 value = cx_read(PLL_A_INT_FRAC);
748 CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300749
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300750 value = cx_read(PLL_B_POST_STAT_BIST);
751 CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value);
752 value = cx_read(PLL_B_INT_FRAC);
753 CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300754
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300755 value = cx_read(PLL_C_POST_STAT_BIST);
756 CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value);
757 value = cx_read(PLL_C_INT_FRAC);
758 CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value);
759
760 value = cx_read(PLL_D_POST_STAT_BIST);
761 CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value);
762 value = cx_read(PLL_D_INT_FRAC);
763 CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value);
764
765 value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
766 CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300767}
768
769static void cx25821_shutdown(struct cx25821_dev *dev)
770{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300771 int i;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300772
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300773 /* disable RISC controller */
774 cx_write(DEV_CNTRL2, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300775
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300776 /* Disable Video A/B activity */
777 for (i = 0; i < VID_CHANNEL_NUM; i++) {
778 cx_write(dev->sram_channels[i].dma_ctl, 0);
779 cx_write(dev->sram_channels[i].int_msk, 0);
780 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300781
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300782 for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J;
783 i++) {
784 cx_write(dev->sram_channels[i].dma_ctl, 0);
785 cx_write(dev->sram_channels[i].int_msk, 0);
786 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300787
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300788 /* Disable Audio activity */
789 cx_write(AUD_INT_DMA_CTL, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300790
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300791 /* Disable Serial port */
792 cx_write(UART_CTL, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300793
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300794 /* Disable Interrupts */
795 cx_write(PCI_INT_MSK, 0);
796 cx_write(AUD_A_INT_MSK, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300797}
798
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300799void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
800 u32 format)
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300801{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300802 struct sram_channel *ch;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300803
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300804 if (channel_select <= 7 && channel_select >= 0) {
805 ch = &cx25821_sram_channels[channel_select];
806 cx_write(ch->pix_frmt, format);
807 dev->pixel_formats[channel_select] = format;
808 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300809}
810
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300811static void cx25821_set_vip_mode(struct cx25821_dev *dev,
812 struct sram_channel *ch)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300813{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300814 cx_write(ch->pix_frmt, PIXEL_FRMT_422);
815 cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300816}
817
818static void cx25821_initialize(struct cx25821_dev *dev)
819{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300820 int i;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300821
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300822 dprintk(1, "%s()\n", __func__);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300823
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300824 cx25821_shutdown(dev);
825 cx_write(PCI_INT_STAT, 0xffffffff);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300826
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300827 for (i = 0; i < VID_CHANNEL_NUM; i++)
828 cx_write(dev->sram_channels[i].int_stat, 0xffffffff);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300829
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300830 cx_write(AUD_A_INT_STAT, 0xffffffff);
831 cx_write(AUD_B_INT_STAT, 0xffffffff);
832 cx_write(AUD_C_INT_STAT, 0xffffffff);
833 cx_write(AUD_D_INT_STAT, 0xffffffff);
834 cx_write(AUD_E_INT_STAT, 0xffffffff);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300835
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300836 cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
837 cx_write(PAD_CTRL, 0x12); //for I2C
838 cx25821_registers_init(dev); //init Pecos registers
839 mdelay(100);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300840
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300841 for (i = 0; i < VID_CHANNEL_NUM; i++) {
842 cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
843 cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440,
844 0);
845 dev->pixel_formats[i] = PIXEL_FRMT_422;
846 dev->use_cif_resolution[i] = FALSE;
847 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300848
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300849 //Probably only affect Downstream
850 for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J;
851 i++) {
852 cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
853 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300854
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300855 cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08],
856 128, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300857
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300858 cx25821_gpio_init(dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300859}
860
861static int get_resources(struct cx25821_dev *dev)
862{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300863 if (request_mem_region
864 (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
865 dev->name))
866 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300867
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300868 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
869 dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300870
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300871 return -EBUSY;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300872}
873
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300874static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
875{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300876 dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300877
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300878 printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__,
879 dev->hwrevision);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300880}
881
882static void cx25821_iounmap(struct cx25821_dev *dev)
883{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300884 if (dev == NULL)
885 return;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300886
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300887 /* Releasing IO memory */
888 if (dev->lmmio != NULL) {
889 CX25821_INFO("Releasing lmmio.\n");
890 iounmap(dev->lmmio);
891 dev->lmmio = NULL;
892 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300893}
894
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300895static int cx25821_dev_setup(struct cx25821_dev *dev)
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300896{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300897 int io_size = 0, i;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300898
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300899 struct video_device *video_template[] = {
900 &cx25821_video_template0,
901 &cx25821_video_template1,
902 &cx25821_video_template2,
903 &cx25821_video_template3,
904 &cx25821_video_template4,
905 &cx25821_video_template5,
906 &cx25821_video_template6,
907 &cx25821_video_template7,
908 &cx25821_video_template9,
909 &cx25821_video_template10,
910 &cx25821_video_template11,
911 &cx25821_videoioctl_template,
912 };
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300913
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300914 printk(KERN_INFO "\n***********************************\n");
915 printk(KERN_INFO "cx25821 set up\n");
916 printk(KERN_INFO "***********************************\n\n");
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300917
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300918 mutex_init(&dev->lock);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300919
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300920 atomic_inc(&dev->refcount);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300921
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300922 dev->nr = ++cx25821_devcount;
923 sprintf(dev->name, "cx25821[%d]", dev->nr);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300924
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300925 mutex_lock(&devlist);
926 list_add_tail(&dev->devlist, &cx25821_devlist);
927 mutex_unlock(&devlist);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300928
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300929 strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
930 strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
931
932 if (dev->pci->device != 0x8210) {
933 printk(KERN_INFO
934 "%s() Exiting. Incorrect Hardware device = 0x%02x\n",
935 __func__, dev->pci->device);
936 return -1;
937 } else {
938 printk(KERN_INFO "Athena Hardware device = 0x%02x\n",
939 dev->pci->device);
940 }
941
942 /* Apply a sensible clock frequency for the PCIe bridge */
943 dev->clk_freq = 28000000;
944 dev->sram_channels = cx25821_sram_channels;
945
946 if (dev->nr > 1) {
947 CX25821_INFO("dev->nr > 1!");
948 }
949
950 /* board config */
951 dev->board = 1; //card[dev->nr];
952 dev->_max_num_decoders = MAX_DECODERS;
953
954 dev->pci_bus = dev->pci->bus->number;
955 dev->pci_slot = PCI_SLOT(dev->pci->devfn);
956 dev->pci_irqmask = 0x001f00;
957
958 /* External Master 1 Bus */
959 dev->i2c_bus[0].nr = 0;
960 dev->i2c_bus[0].dev = dev;
961 dev->i2c_bus[0].reg_stat = I2C1_STAT;
962 dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
963 dev->i2c_bus[0].reg_addr = I2C1_ADDR;
964 dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
965 dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
966 dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300967
968
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300969 if (get_resources(dev) < 0) {
970 printk(KERN_ERR "%s No more PCIe resources for "
971 "subsystem: %04x:%04x\n",
972 dev->name, dev->pci->subsystem_vendor,
973 dev->pci->subsystem_device);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -0300974
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300975 cx25821_devcount--;
976 return -ENODEV;
977 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300978
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300979 /* PCIe stuff */
980 dev->base_io_addr = pci_resource_start(dev->pci, 0);
981 io_size = pci_resource_len(dev->pci, 0);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300982
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300983 if (!dev->base_io_addr) {
984 CX25821_ERR("No PCI Memory resources, exiting!\n");
985 return -ENODEV;
986 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300987
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300988 dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300989
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300990 if (!dev->lmmio) {
991 CX25821_ERR
992 ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
993 cx25821_iounmap(dev);
994 return -ENOMEM;
995 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300996
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300997 dev->bmmio = (u8 __iomem *) dev->lmmio;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -0300998
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300999 printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001000 dev->name, dev->pci->subsystem_vendor,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001001 dev->pci->subsystem_device, cx25821_boards[dev->board].name,
1002 dev->board, card[dev->nr] == dev->board ?
1003 "insmod option" : "autodetected");
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001004
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001005 /* init hardware */
1006 cx25821_initialize(dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001007
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001008 cx25821_i2c_register(&dev->i2c_bus[0]);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001009// cx25821_i2c_register(&dev->i2c_bus[1]);
1010// cx25821_i2c_register(&dev->i2c_bus[2]);
1011
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001012 CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
1013 dev->i2c_bus[0].i2c_rc);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001014
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001015 cx25821_card_setup(dev);
1016 medusa_video_init(dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001017
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001018 for (i = 0; i < VID_CHANNEL_NUM; i++) {
1019 if (cx25821_video_register(dev, i, video_template[i]) < 0) {
1020 printk(KERN_ERR
1021 "%s() Failed to register analog video adapters on VID channel %d\n",
1022 __func__, i);
1023 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001024 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001025
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001026 for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
1027 i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
1028 //Since we don't have template8 for Audio Downstream
1029 if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) {
1030 printk(KERN_ERR
1031 "%s() Failed to register analog video adapters for Upstream channel %d.\n",
1032 __func__, i);
1033 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001034 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001035
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001036 // register IOCTL device
1037 dev->ioctl_dev =
1038 cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH],
1039 "video");
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001040
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001041 if (video_register_device
1042 (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
1043 cx25821_videoioctl_unregister(dev);
1044 printk(KERN_ERR
1045 "%s() Failed to register video adapter for IOCTL so releasing.\n",
1046 __func__);
1047 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001048
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001049 cx25821_dev_checkrevision(dev);
1050 CX25821_INFO("cx25821 setup done!\n");
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001051
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001052 return 0;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001053}
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001054
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001055void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
1056 struct upstream_user_struct *up_data)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001057{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001058 dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001059
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001060 dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
1061 medusa_set_videostandard(dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001062
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001063 cx25821_vidupstream_init_ch1(dev, dev->channel_select,
1064 dev->pixel_format);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001065}
1066
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001067void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
1068 struct upstream_user_struct *up_data)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001069{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001070 dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001071
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001072 dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
1073 medusa_set_videostandard(dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001074
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001075 cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
1076 dev->pixel_format_ch2);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001077}
1078
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001079void cx25821_start_upstream_audio(struct cx25821_dev *dev,
1080 struct upstream_user_struct *up_data)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001081{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001082 cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001083}
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001084
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001085void cx25821_dev_unregister(struct cx25821_dev *dev)
1086{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001087 int i;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001088
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001089 if (!dev->base_io_addr)
1090 return;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001091
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001092 cx25821_free_mem_upstream_ch1(dev);
1093 cx25821_free_mem_upstream_ch2(dev);
1094 cx25821_free_mem_upstream_audio(dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001095
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001096 release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001097
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001098 if (!atomic_dec_and_test(&dev->refcount))
1099 return;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001100
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001101 for (i = 0; i < VID_CHANNEL_NUM; i++)
1102 cx25821_video_unregister(dev, i);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001103
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001104 for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
1105 i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
1106 cx25821_video_unregister(dev, i);
1107 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001108
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001109 cx25821_videoioctl_unregister(dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001110
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001111 cx25821_i2c_unregister(&dev->i2c_bus[0]);
1112 cx25821_iounmap(dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001113}
1114
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001115static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
1116 unsigned int offset, u32 sync_line,
1117 unsigned int bpl, unsigned int padding,
1118 unsigned int lines)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001119{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001120 struct scatterlist *sg;
1121 unsigned int line, todo;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001122
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001123 /* sync instruction */
1124 if (sync_line != NO_SYNC_LINE) {
1125 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001126 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001127
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001128 /* scan lines */
1129 sg = sglist;
1130 for (line = 0; line < lines; line++) {
1131 while (offset && offset >= sg_dma_len(sg)) {
1132 offset -= sg_dma_len(sg);
1133 sg++;
1134 }
1135 if (bpl <= sg_dma_len(sg) - offset) {
1136 /* fits into current chunk */
1137 *(rp++) =
1138 cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
1139 *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
1140 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1141 offset += bpl;
1142 } else {
1143 /* scanline needs to be split */
1144 todo = bpl;
1145 *(rp++) =
1146 cpu_to_le32(RISC_WRITE | RISC_SOL |
1147 (sg_dma_len(sg) - offset));
1148 *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
1149 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1150 todo -= (sg_dma_len(sg) - offset);
1151 offset = 0;
1152 sg++;
1153 while (todo > sg_dma_len(sg)) {
1154 *(rp++) =
1155 cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
1156 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1157 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1158 todo -= sg_dma_len(sg);
1159 sg++;
1160 }
1161 *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
1162 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1163 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1164 offset += todo;
1165 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001166
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001167 offset += padding;
1168 }
1169
1170 return rp;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001171}
1172
1173int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001174 struct scatterlist *sglist, unsigned int top_offset,
1175 unsigned int bottom_offset, unsigned int bpl,
1176 unsigned int padding, unsigned int lines)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001177{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001178 u32 instructions;
1179 u32 fields;
1180 __le32 *rp;
1181 int rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001182
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001183 fields = 0;
1184 if (UNSET != top_offset)
1185 fields++;
1186 if (UNSET != bottom_offset)
1187 fields++;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001188
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001189 /* estimate risc mem: worst case is one write per page border +
1190 one write per scan line + syncs + jump (all 2 dwords). Padding
1191 can cause next bpl to start close to a page border. First DMA
1192 region may be smaller than PAGE_SIZE */
1193 /* write and jump need and extra dword */
1194 instructions =
1195 fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
1196 instructions += 2;
1197 rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001198
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001199 if (rc < 0)
1200 return rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001201
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001202 /* write risc instructions */
1203 rp = risc->cpu;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001204
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001205 if (UNSET != top_offset) {
1206 rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
1207 lines);
1208 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001209
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001210 if (UNSET != bottom_offset) {
1211 rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
1212 padding, lines);
1213 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001214
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001215 /* save pointer to jmp instruction address */
1216 risc->jmp = rp;
1217 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001218
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001219 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001220}
1221
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001222static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
1223 unsigned int offset, u32 sync_line,
1224 unsigned int bpl, unsigned int padding,
1225 unsigned int lines, unsigned int lpi)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001226{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001227 struct scatterlist *sg;
1228 unsigned int line, todo, sol;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001229
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001230 /* sync instruction */
1231 if (sync_line != NO_SYNC_LINE)
1232 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001233
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001234 /* scan lines */
1235 sg = sglist;
1236 for (line = 0; line < lines; line++) {
1237 while (offset && offset >= sg_dma_len(sg)) {
1238 offset -= sg_dma_len(sg);
1239 sg++;
1240 }
1241
1242 if (lpi && line > 0 && !(line % lpi))
1243 sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
1244 else
1245 sol = RISC_SOL;
1246
1247 if (bpl <= sg_dma_len(sg) - offset) {
1248 /* fits into current chunk */
1249 *(rp++) =
1250 cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
1251 *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
1252 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1253 offset += bpl;
1254 } else {
1255 /* scanline needs to be split */
1256 todo = bpl;
1257 *(rp++) = cpu_to_le32(RISC_WRITE | sol |
1258 (sg_dma_len(sg) - offset));
1259 *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
1260 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1261 todo -= (sg_dma_len(sg) - offset);
1262 offset = 0;
1263 sg++;
1264 while (todo > sg_dma_len(sg)) {
1265 *(rp++) = cpu_to_le32(RISC_WRITE |
1266 sg_dma_len(sg));
1267 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1268 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1269 todo -= sg_dma_len(sg);
1270 sg++;
1271 }
1272 *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
1273 *(rp++) = cpu_to_le32(sg_dma_address(sg));
1274 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1275 offset += todo;
1276 }
1277 offset += padding;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001278 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001279
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001280 return rp;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001281}
1282
1283int cx25821_risc_databuffer_audio(struct pci_dev *pci,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001284 struct btcx_riscmem *risc,
1285 struct scatterlist *sglist,
1286 unsigned int bpl,
1287 unsigned int lines, unsigned int lpi)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001288{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001289 u32 instructions;
1290 __le32 *rp;
1291 int rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001292
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001293 /* estimate risc mem: worst case is one write per page border +
1294 one write per scan line + syncs + jump (all 2 dwords). Here
1295 there is no padding and no sync. First DMA region may be smaller
1296 than PAGE_SIZE */
1297 /* Jump and write need an extra dword */
1298 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
1299 instructions += 1;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001300
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001301 if ((rc = btcx_riscmem_alloc(pci, risc, instructions * 12)) < 0)
1302 return rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001303
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001304 /* write risc instructions */
1305 rp = risc->cpu;
1306 rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
1307 lines, lpi);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001308
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001309 /* save pointer to jmp instruction address */
1310 risc->jmp = rp;
1311 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
1312 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001313}
1314
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001315int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
1316 u32 reg, u32 mask, u32 value)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001317{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001318 __le32 *rp;
1319 int rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001320
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001321 rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001322
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001323 if (rc < 0)
1324 return rc;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001325
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001326 /* write risc instructions */
1327 rp = risc->cpu;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001328
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001329 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
1330 *(rp++) = cpu_to_le32(reg);
1331 *(rp++) = cpu_to_le32(value);
1332 *(rp++) = cpu_to_le32(mask);
1333 *(rp++) = cpu_to_le32(RISC_JUMP);
1334 *(rp++) = cpu_to_le32(risc->dma);
1335 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1336 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001337}
1338
1339void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
1340{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001341 struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001342
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001343 BUG_ON(in_interrupt());
1344 videobuf_waiton(&buf->vb, 0, 0);
1345 videobuf_dma_unmap(q, dma);
1346 videobuf_dma_free(dma);
1347 btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
1348 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001349}
1350
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001351static irqreturn_t cx25821_irq(int irq, void *dev_id)
1352{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001353 struct cx25821_dev *dev = dev_id;
1354 u32 pci_status, pci_mask;
1355 u32 vid_status;
1356 int i, handled = 0;
1357 u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001358
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001359 pci_status = cx_read(PCI_INT_STAT);
1360 pci_mask = cx_read(PCI_INT_MSK);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001361
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001362 if (pci_status == 0)
1363 goto out;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001364
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001365 for (i = 0; i < VID_CHANNEL_NUM; i++) {
1366 if (pci_status & mask[i]) {
1367 vid_status = cx_read(dev->sram_channels[i].int_stat);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001368
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001369 if (vid_status)
1370 handled +=
1371 cx25821_video_irq(dev, i, vid_status);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001372
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001373 cx_write(PCI_INT_STAT, mask[i]);
1374 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001375 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001376
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001377 out:
1378 return IRQ_RETVAL(handled);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001379}
1380
1381void cx25821_print_irqbits(char *name, char *tag, char **strings,
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001382 int len, u32 bits, u32 mask)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001383{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001384 unsigned int i;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001385
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001386 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001387
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001388 for (i = 0; i < len; i++) {
1389 if (!(bits & (1 << i)))
1390 continue;
1391 if (strings[i])
1392 printk(" %s", strings[i]);
1393 else
1394 printk(" %d", i);
1395 if (!(mask & (1 << i)))
1396 continue;
1397 printk("*");
1398 }
1399 printk("\n");
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001400}
1401
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001402struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001403{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001404 struct cx25821_dev *dev = pci_get_drvdata(pci);
1405 return dev;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001406}
1407
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001408static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
1409 const struct pci_device_id *pci_id)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001410{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001411 struct cx25821_dev *dev;
1412 int err = 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001413
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001414 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1415 if (NULL == dev)
1416 return -ENOMEM;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001417
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001418 err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
1419 if (err < 0)
1420 goto fail_free;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001421
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001422 /* pci init */
1423 dev->pci = pci_dev;
1424 if (pci_enable_device(pci_dev)) {
1425 err = -EIO;
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001426
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001427 printk(KERN_INFO "pci enable failed! ");
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001428
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001429 goto fail_unregister_device;
1430 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001431
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001432 printk(KERN_INFO "cx25821 Athena pci enable ! \n");
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001433
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001434 if (cx25821_dev_setup(dev) < 0) {
1435 err = -EINVAL;
1436 goto fail_unregister_device;
1437 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001438
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001439 /* print pci info */
1440 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
1441 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
1442 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
1443 "latency: %d, mmio: 0x%llx\n", dev->name,
1444 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
1445 dev->pci_lat, (unsigned long long)dev->base_io_addr);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001446
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001447 pci_set_master(pci_dev);
1448 if (!pci_dma_supported(pci_dev, 0xffffffff)) {
1449 printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
1450 err = -EIO;
1451 goto fail_irq;
1452 }
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001453
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001454 err =
1455 request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED,
1456 dev->name, dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001457
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001458 if (err < 0) {
1459 printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
1460 pci_dev->irq);
1461 goto fail_irq;
1462 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001463
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001464 return 0;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001465
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001466 fail_irq:
1467 printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n");
1468 cx25821_dev_unregister(dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001469
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001470 fail_unregister_device:
1471 v4l2_device_unregister(&dev->v4l2_dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001472
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001473 fail_free:
1474 kfree(dev);
1475 return err;
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001476}
1477
1478static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
1479{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001480 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
1481 struct cx25821_dev *dev = get_cx25821(v4l2_dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001482
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001483 cx25821_shutdown(dev);
1484 pci_disable_device(pci_dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001485
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001486 /* unregister stuff */
1487 if (pci_dev->irq)
1488 free_irq(pci_dev->irq, dev);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001489
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001490 mutex_lock(&devlist);
1491 list_del(&dev->devlist);
1492 mutex_unlock(&devlist);
Mauro Carvalho Chehabbb4c9a72009-09-13 11:25:45 -03001493
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001494 cx25821_dev_unregister(dev);
1495 v4l2_device_unregister(v4l2_dev);
1496 kfree(dev);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001497}
1498
1499static struct pci_device_id cx25821_pci_tbl[] = {
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001500 {
1501 /* CX25821 Athena */
1502 .vendor = 0x14f1,
1503 .device = 0x8210,
1504 .subvendor = 0x14f1,
1505 .subdevice = 0x0920,
1506 },
1507 {
1508 /* --- end of list --- */
1509 }
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001510};
1511
1512MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
1513
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001514static struct pci_driver cx25821_pci_driver = {
1515 .name = "cx25821",
1516 .id_table = cx25821_pci_tbl,
1517 .probe = cx25821_initdev,
1518 .remove = __devexit_p(cx25821_finidev),
1519 /* TODO */
1520 .suspend = NULL,
1521 .resume = NULL,
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001522};
1523
Peter Huewe64ed20162009-09-29 01:40:59 +02001524static int __init cx25821_init(void)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001525{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001526 INIT_LIST_HEAD(&cx25821_devlist);
1527 printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n",
1528 (CX25821_VERSION_CODE >> 16) & 0xff,
1529 (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff);
1530 return pci_register_driver(&cx25821_pci_driver);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001531}
1532
Peter Huewe64ed20162009-09-29 01:40:59 +02001533static void __exit cx25821_fini(void)
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001534{
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001535 pci_unregister_driver(&cx25821_pci_driver);
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001536}
1537
Mauro Carvalho Chehab02b20b02009-09-15 11:33:54 -03001538EXPORT_SYMBOL(cx25821_devlist);
1539EXPORT_SYMBOL(cx25821_sram_channels);
1540EXPORT_SYMBOL(cx25821_print_irqbits);
1541EXPORT_SYMBOL(cx25821_dev_get);
1542EXPORT_SYMBOL(cx25821_dev_unregister);
1543EXPORT_SYMBOL(cx25821_sram_channel_setup);
1544EXPORT_SYMBOL(cx25821_sram_channel_dump);
1545EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
1546EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
1547EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
1548EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
1549
1550module_init(cx25821_init);
1551module_exit(cx25821_fini);