diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-15 10:33:54 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 22:47:36 -0400 |
commit | 02b20b0b4cde011f7ad6b5363fb88b93f7ad4e5b (patch) | |
tree | de8dbf798a2867a58d2108684e1aef76ec9bbfc0 /drivers/staging | |
parent | 78f28b7c555359c67c2a0d23f7436e915329421e (diff) |
V4L/DVB (12730): Add conexant cx25821 driver
GIT_BRANCH=devel
GIT_AUTHOR_DATE=1252851239
GIT_AUTHOR_NAME=Palash Bandyopadhyay
GIT_AUTHOR_EMAIL=Palash.Bandyopadhyay@conexant.com
Add conexant cx25821 driver release v106 of the Athena driver.
Signed-off-by: Palash Bandyopadhyay <palash.bandyopadhyay@conexant.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
37 files changed, 16790 insertions, 0 deletions
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig new file mode 100644 index 00000000000..88871156c0d --- /dev/null +++ b/drivers/staging/cx25821/Kconfig | |||
@@ -0,0 +1,34 @@ | |||
1 | config VIDEO_CX25821 | ||
2 | tristate "Conexant cx25821 support" | ||
3 | depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT | ||
4 | select I2C_ALGOBIT | ||
5 | select VIDEO_BTCX | ||
6 | select VIDEO_TVEEPROM | ||
7 | select VIDEO_IR | ||
8 | select VIDEOBUF_DVB | ||
9 | select VIDEOBUF_DMA_SG | ||
10 | select VIDEO_CX25840 | ||
11 | select VIDEO_CX2341X | ||
12 | ---help--- | ||
13 | This is a video4linux driver for Conexant 25821 based | ||
14 | TV cards. | ||
15 | |||
16 | To compile this driver as a module, choose M here: the | ||
17 | module will be called cx25821 | ||
18 | |||
19 | config VIDEO_CX25821_ALSA | ||
20 | tristate "Conexant 25821 DMA audio support" | ||
21 | depends on VIDEO_CX25821 && SND && EXPERIMENTAL | ||
22 | select SND_PCM | ||
23 | ---help--- | ||
24 | This is a video4linux driver for direct (DMA) audio on | ||
25 | Conexant 25821 based capture cards using ALSA. | ||
26 | |||
27 | It only works with boards with function 01 enabled. | ||
28 | To check if your board supports, use lspci -n. | ||
29 | If supported, you should see 14f1:8801 or 14f1:8811 | ||
30 | PCI device. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the | ||
33 | module will be called cx25821-alsa. | ||
34 | |||
diff --git a/drivers/staging/cx25821/Makefile b/drivers/staging/cx25821/Makefile new file mode 100644 index 00000000000..020d8440493 --- /dev/null +++ b/drivers/staging/cx25821/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o \ | ||
2 | cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o \ | ||
3 | cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o \ | ||
4 | cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o \ | ||
5 | cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o \ | ||
6 | cx25821-audio-upstream.o cx25821-videoioctl.o | ||
7 | |||
8 | obj-$(CONFIG_VIDEO_CX25821) += cx25821.o | ||
9 | obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o | ||
10 | |||
11 | EXTRA_CFLAGS += -Idrivers/media/video | ||
12 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
13 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
14 | |||
15 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | ||
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c new file mode 100644 index 00000000000..6b2e86acc12 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-alsa.c | |||
@@ -0,0 +1,791 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * Based on SAA713x ALSA driver and CX88 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, version 2 | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | #include <linux/dma-mapping.h> | ||
30 | #include <linux/pci.h> | ||
31 | |||
32 | #include <asm/delay.h> | ||
33 | #include <sound/core.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/control.h> | ||
37 | #include <sound/initval.h> | ||
38 | #include <sound/tlv.h> | ||
39 | |||
40 | |||
41 | #include "cx25821.h" | ||
42 | #include "cx25821-reg.h" | ||
43 | |||
44 | #define AUDIO_SRAM_CHANNEL SRAM_CH08 | ||
45 | |||
46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
47 | printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) | ||
48 | |||
49 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ | ||
50 | printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) | ||
51 | |||
52 | |||
53 | /**************************************************************************** | ||
54 | Data type declarations - Can be moded to a header file later | ||
55 | ****************************************************************************/ | ||
56 | |||
57 | |||
58 | static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; | ||
59 | static int devno; | ||
60 | |||
61 | struct cx25821_audio_dev { | ||
62 | struct cx25821_dev *dev; | ||
63 | struct cx25821_dmaqueue q; | ||
64 | |||
65 | /* pci i/o */ | ||
66 | struct pci_dev *pci; | ||
67 | |||
68 | /* audio controls */ | ||
69 | int irq; | ||
70 | |||
71 | struct snd_card *card; | ||
72 | |||
73 | unsigned long iobase; | ||
74 | spinlock_t reg_lock; | ||
75 | atomic_t count; | ||
76 | |||
77 | unsigned int dma_size; | ||
78 | unsigned int period_size; | ||
79 | unsigned int num_periods; | ||
80 | |||
81 | struct videobuf_dmabuf *dma_risc; | ||
82 | |||
83 | struct cx25821_buffer *buf; | ||
84 | |||
85 | struct snd_pcm_substream *substream; | ||
86 | }; | ||
87 | typedef struct cx25821_audio_dev snd_cx25821_card_t; | ||
88 | |||
89 | |||
90 | |||
91 | /**************************************************************************** | ||
92 | Module global static vars | ||
93 | ****************************************************************************/ | ||
94 | |||
95 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
96 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
97 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; | ||
98 | |||
99 | module_param_array(enable, bool, NULL, 0444); | ||
100 | MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); | ||
101 | |||
102 | module_param_array(index, int, NULL, 0444); | ||
103 | MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); | ||
104 | |||
105 | |||
106 | /**************************************************************************** | ||
107 | Module macros | ||
108 | ****************************************************************************/ | ||
109 | |||
110 | MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); | ||
111 | MODULE_AUTHOR("Hiep Huynh"); | ||
112 | MODULE_LICENSE("GPL"); | ||
113 | MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");//"{{Conexant,23881}," | ||
114 | |||
115 | static unsigned int debug; | ||
116 | module_param(debug,int,0644); | ||
117 | MODULE_PARM_DESC(debug,"enable debug messages"); | ||
118 | |||
119 | /**************************************************************************** | ||
120 | Module specific funtions | ||
121 | ****************************************************************************/ | ||
122 | /* Constants taken from cx88-reg.h */ | ||
123 | #define AUD_INT_DN_RISCI1 (1 << 0) | ||
124 | #define AUD_INT_UP_RISCI1 (1 << 1) | ||
125 | #define AUD_INT_RDS_DN_RISCI1 (1 << 2) | ||
126 | #define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ | ||
127 | #define AUD_INT_UP_RISCI2 (1 << 5) | ||
128 | #define AUD_INT_RDS_DN_RISCI2 (1 << 6) | ||
129 | #define AUD_INT_DN_SYNC (1 << 12) | ||
130 | #define AUD_INT_UP_SYNC (1 << 13) | ||
131 | #define AUD_INT_RDS_DN_SYNC (1 << 14) | ||
132 | #define AUD_INT_OPC_ERR (1 << 16) | ||
133 | #define AUD_INT_BER_IRQ (1 << 20) | ||
134 | #define AUD_INT_MCHG_IRQ (1 << 21) | ||
135 | #define GP_COUNT_CONTROL_RESET 0x3 | ||
136 | |||
137 | #define PCI_MSK_AUD_EXT (1 << 4) | ||
138 | #define PCI_MSK_AUD_INT (1 << 3) | ||
139 | /* | ||
140 | * BOARD Specific: Sets audio DMA | ||
141 | */ | ||
142 | |||
143 | static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip) | ||
144 | { | ||
145 | struct cx25821_buffer *buf = chip->buf; | ||
146 | struct cx25821_dev * dev = chip->dev; | ||
147 | struct sram_channel *audio_ch = &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; | ||
148 | u32 tmp = 0; | ||
149 | |||
150 | // enable output on the GPIO 0 for the MCLK ADC (Audio) | ||
151 | cx25821_set_gpiopin_direction( chip->dev, 0, 0 ); | ||
152 | |||
153 | /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ | ||
154 | cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); | ||
155 | |||
156 | /* setup fifo + format - out channel */ | ||
157 | cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, buf->risc.dma); | ||
158 | |||
159 | /* sets bpl size */ | ||
160 | cx_write(AUD_A_LNGTH, buf->bpl); | ||
161 | |||
162 | /* reset counter */ | ||
163 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 | ||
164 | atomic_set(&chip->count, 0); | ||
165 | |||
166 | //Set the input mode to 16-bit | ||
167 | tmp = cx_read(AUD_A_CFG); | ||
168 | cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE); | ||
169 | |||
170 | //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d " | ||
171 | // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, | ||
172 | // chip->num_periods, buf->bpl * chip->num_periods); | ||
173 | |||
174 | |||
175 | /* Enables corresponding bits at AUD_INT_STAT */ | ||
176 | cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR ); | ||
177 | |||
178 | /* Clean any pending interrupt bits already set */ | ||
179 | cx_write(AUD_A_INT_STAT, ~0); | ||
180 | |||
181 | /* enable audio irqs */ | ||
182 | cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); | ||
183 | |||
184 | // Turn on audio downstream fifo and risc enable 0x101 | ||
185 | tmp = cx_read(AUD_INT_DMA_CTL); | ||
186 | cx_set(AUD_INT_DMA_CTL, tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN) ); | ||
187 | |||
188 | mdelay(100); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * BOARD Specific: Resets audio DMA | ||
194 | */ | ||
195 | static int _cx25821_stop_audio_dma(snd_cx25821_card_t *chip) | ||
196 | { | ||
197 | struct cx25821_dev *dev = chip->dev; | ||
198 | |||
199 | /* stop dma */ | ||
200 | cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); | ||
201 | |||
202 | /* disable irqs */ | ||
203 | cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); | ||
204 | cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | #define MAX_IRQ_LOOP 50 | ||
210 | |||
211 | /* | ||
212 | * BOARD Specific: IRQ dma bits | ||
213 | */ | ||
214 | static char *cx25821_aud_irqs[32] = { | ||
215 | "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ | ||
216 | NULL, /* reserved */ | ||
217 | "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ | ||
218 | NULL, /* reserved */ | ||
219 | "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ | ||
220 | NULL, /* reserved */ | ||
221 | "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ | ||
222 | NULL, /* reserved */ | ||
223 | "opc_err", "par_err", "rip_err", /* 16-18 */ | ||
224 | "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * BOARD Specific: Threats IRQ audio specific calls | ||
229 | */ | ||
230 | static void cx25821_aud_irq(snd_cx25821_card_t *chip, u32 status, u32 mask) | ||
231 | { | ||
232 | struct cx25821_dev *dev = chip->dev; | ||
233 | |||
234 | if (0 == (status & mask)) | ||
235 | { | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | cx_write(AUD_A_INT_STAT, status); | ||
240 | if (debug > 1 || (status & mask & ~0xff)) | ||
241 | cx25821_print_irqbits(dev->name, "irq aud", | ||
242 | cx25821_aud_irqs, ARRAY_SIZE(cx25821_aud_irqs), | ||
243 | status, mask); | ||
244 | |||
245 | /* risc op code error */ | ||
246 | if (status & AUD_INT_OPC_ERR) { | ||
247 | printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",dev->name); | ||
248 | |||
249 | cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); | ||
250 | cx25821_sram_channel_dump_audio(dev, &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]); | ||
251 | } | ||
252 | if (status & AUD_INT_DN_SYNC) { | ||
253 | printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",dev->name); | ||
254 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); | ||
255 | return; | ||
256 | } | ||
257 | |||
258 | |||
259 | /* risc1 downstream */ | ||
260 | if (status & AUD_INT_DN_RISCI1) { | ||
261 | atomic_set(&chip->count, cx_read(AUD_A_GPCNT)); | ||
262 | snd_pcm_period_elapsed(chip->substream); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | |||
267 | /* | ||
268 | * BOARD Specific: Handles IRQ calls | ||
269 | */ | ||
270 | static irqreturn_t cx25821_irq(int irq, void *dev_id) | ||
271 | { | ||
272 | snd_cx25821_card_t *chip = dev_id; | ||
273 | struct cx25821_dev *dev = chip->dev; | ||
274 | u32 status, pci_status; | ||
275 | u32 audint_status, audint_mask; | ||
276 | int loop, handled = 0; | ||
277 | int audint_count = 0; | ||
278 | |||
279 | |||
280 | audint_status = cx_read(AUD_A_INT_STAT); | ||
281 | audint_mask = cx_read(AUD_A_INT_MSK); | ||
282 | audint_count = cx_read(AUD_A_GPCNT); | ||
283 | status = cx_read(PCI_INT_STAT); | ||
284 | |||
285 | for (loop = 0; loop < 1; loop++) | ||
286 | { | ||
287 | status = cx_read(PCI_INT_STAT); | ||
288 | if (0 == status) | ||
289 | { | ||
290 | status = cx_read(PCI_INT_STAT); | ||
291 | audint_status = cx_read(AUD_A_INT_STAT); | ||
292 | audint_mask = cx_read(AUD_A_INT_MSK); | ||
293 | |||
294 | if (status) | ||
295 | { | ||
296 | handled = 1; | ||
297 | cx_write(PCI_INT_STAT, status); | ||
298 | |||
299 | cx25821_aud_irq(chip, audint_status, audint_mask); | ||
300 | break; | ||
301 | } | ||
302 | else | ||
303 | goto out; | ||
304 | } | ||
305 | |||
306 | handled = 1; | ||
307 | cx_write(PCI_INT_STAT, status); | ||
308 | |||
309 | cx25821_aud_irq(chip, audint_status, audint_mask); | ||
310 | } | ||
311 | |||
312 | pci_status = cx_read(PCI_INT_STAT); | ||
313 | |||
314 | if (handled) | ||
315 | cx_write(PCI_INT_STAT, pci_status); | ||
316 | |||
317 | out: | ||
318 | return IRQ_RETVAL(handled); | ||
319 | } | ||
320 | |||
321 | |||
322 | static int dsp_buffer_free(snd_cx25821_card_t *chip) | ||
323 | { | ||
324 | BUG_ON(!chip->dma_size); | ||
325 | |||
326 | dprintk(2,"Freeing buffer\n"); | ||
327 | videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); | ||
328 | videobuf_dma_free(chip->dma_risc); | ||
329 | btcx_riscmem_free(chip->pci,&chip->buf->risc); | ||
330 | kfree(chip->buf); | ||
331 | |||
332 | chip->dma_risc = NULL; | ||
333 | chip->dma_size = 0; | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /**************************************************************************** | ||
339 | ALSA PCM Interface | ||
340 | ****************************************************************************/ | ||
341 | |||
342 | /* | ||
343 | * Digital hardware definition | ||
344 | */ | ||
345 | #define DEFAULT_FIFO_SIZE 384 | ||
346 | static struct snd_pcm_hardware snd_cx25821_digital_hw = { | ||
347 | .info = SNDRV_PCM_INFO_MMAP | | ||
348 | SNDRV_PCM_INFO_INTERLEAVED | | ||
349 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
350 | SNDRV_PCM_INFO_MMAP_VALID, | ||
351 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
352 | |||
353 | .rates = SNDRV_PCM_RATE_48000, | ||
354 | .rate_min = 48000, | ||
355 | .rate_max = 48000, | ||
356 | .channels_min = 2, | ||
357 | .channels_max = 2, | ||
358 | /* Analog audio output will be full of clicks and pops if there | ||
359 | are not exactly four lines in the SRAM FIFO buffer. */ | ||
360 | .period_bytes_min = DEFAULT_FIFO_SIZE/3, | ||
361 | .period_bytes_max = DEFAULT_FIFO_SIZE/3, | ||
362 | .periods_min = 1, | ||
363 | .periods_max = AUDIO_LINE_SIZE, | ||
364 | .buffer_bytes_max = (AUDIO_LINE_SIZE*AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 | ||
365 | }; | ||
366 | |||
367 | |||
368 | |||
369 | /* | ||
370 | * audio pcm capture open callback | ||
371 | */ | ||
372 | static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) | ||
373 | { | ||
374 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
375 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
376 | int err; | ||
377 | unsigned int bpl = 0; | ||
378 | |||
379 | if (!chip) { | ||
380 | printk(KERN_ERR "DEBUG: cx25821 can't find device struct." | ||
381 | " Can't proceed with open\n"); | ||
382 | return -ENODEV; | ||
383 | } | ||
384 | |||
385 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); | ||
386 | if (err < 0) | ||
387 | goto _error; | ||
388 | |||
389 | chip->substream = substream; | ||
390 | |||
391 | runtime->hw = snd_cx25821_digital_hw; | ||
392 | |||
393 | if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != DEFAULT_FIFO_SIZE) | ||
394 | { | ||
395 | bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters | ||
396 | bpl &= ~7; /* must be multiple of 8 */ | ||
397 | |||
398 | if( bpl > AUDIO_LINE_SIZE ) | ||
399 | { | ||
400 | bpl = AUDIO_LINE_SIZE; | ||
401 | } | ||
402 | runtime->hw.period_bytes_min = bpl; | ||
403 | runtime->hw.period_bytes_max = bpl; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | _error: | ||
408 | dprintk(1,"Error opening PCM!\n"); | ||
409 | return err; | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * audio close callback | ||
414 | */ | ||
415 | static int snd_cx25821_close(struct snd_pcm_substream *substream) | ||
416 | { | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * hw_params callback | ||
422 | */ | ||
423 | static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, | ||
424 | struct snd_pcm_hw_params * hw_params) | ||
425 | { | ||
426 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
427 | struct videobuf_dmabuf *dma; | ||
428 | |||
429 | struct cx25821_buffer *buf; | ||
430 | int ret; | ||
431 | |||
432 | if (substream->runtime->dma_area) { | ||
433 | dsp_buffer_free(chip); | ||
434 | substream->runtime->dma_area = NULL; | ||
435 | } | ||
436 | |||
437 | |||
438 | chip->period_size = params_period_bytes(hw_params); | ||
439 | chip->num_periods = params_periods(hw_params); | ||
440 | chip->dma_size = chip->period_size * params_periods(hw_params); | ||
441 | |||
442 | BUG_ON(!chip->dma_size); | ||
443 | BUG_ON(chip->num_periods & (chip->num_periods-1)); | ||
444 | |||
445 | buf = videobuf_sg_alloc(sizeof(*buf)); | ||
446 | if (NULL == buf) | ||
447 | return -ENOMEM; | ||
448 | |||
449 | |||
450 | if( chip->period_size > AUDIO_LINE_SIZE ) | ||
451 | { | ||
452 | chip->period_size = AUDIO_LINE_SIZE; | ||
453 | } | ||
454 | |||
455 | |||
456 | buf->vb.memory = V4L2_MEMORY_MMAP; | ||
457 | buf->vb.field = V4L2_FIELD_NONE; | ||
458 | buf->vb.width = chip->period_size; | ||
459 | buf->bpl = chip->period_size; | ||
460 | buf->vb.height = chip->num_periods; | ||
461 | buf->vb.size = chip->dma_size; | ||
462 | |||
463 | dma = videobuf_to_dma(&buf->vb); | ||
464 | videobuf_dma_init(dma); | ||
465 | |||
466 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | ||
467 | (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); | ||
468 | if (ret < 0) | ||
469 | goto error; | ||
470 | |||
471 | ret = videobuf_sg_dma_map(&chip->pci->dev, dma); | ||
472 | if (ret < 0) | ||
473 | goto error; | ||
474 | |||
475 | |||
476 | ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, buf->vb.width, buf->vb.height, 1); | ||
477 | if (ret < 0) | ||
478 | { | ||
479 | printk(KERN_INFO "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); | ||
480 | goto error; | ||
481 | } | ||
482 | |||
483 | |||
484 | /* Loop back to start of program */ | ||
485 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); | ||
486 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
487 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
488 | |||
489 | buf->vb.state = VIDEOBUF_PREPARED; | ||
490 | |||
491 | chip->buf = buf; | ||
492 | chip->dma_risc = dma; | ||
493 | |||
494 | substream->runtime->dma_area = chip->dma_risc->vmalloc; | ||
495 | substream->runtime->dma_bytes = chip->dma_size; | ||
496 | substream->runtime->dma_addr = 0; | ||
497 | |||
498 | return 0; | ||
499 | |||
500 | error: | ||
501 | kfree(buf); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * hw free callback | ||
507 | */ | ||
508 | static int snd_cx25821_hw_free(struct snd_pcm_substream * substream) | ||
509 | { | ||
510 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
511 | |||
512 | if (substream->runtime->dma_area) { | ||
513 | dsp_buffer_free(chip); | ||
514 | substream->runtime->dma_area = NULL; | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * prepare callback | ||
522 | */ | ||
523 | static int snd_cx25821_prepare(struct snd_pcm_substream *substream) | ||
524 | { | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * trigger callback | ||
530 | */ | ||
531 | static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd) | ||
532 | { | ||
533 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
534 | int err = 0; | ||
535 | |||
536 | /* Local interrupts are already disabled by ALSA */ | ||
537 | spin_lock(&chip->reg_lock); | ||
538 | |||
539 | switch (cmd) | ||
540 | { | ||
541 | case SNDRV_PCM_TRIGGER_START: | ||
542 | err = _cx25821_start_audio_dma(chip); | ||
543 | break; | ||
544 | case SNDRV_PCM_TRIGGER_STOP: | ||
545 | err = _cx25821_stop_audio_dma(chip); | ||
546 | break; | ||
547 | default: | ||
548 | err = -EINVAL; | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | spin_unlock(&chip->reg_lock); | ||
553 | |||
554 | return err; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * pointer callback | ||
559 | */ | ||
560 | static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream *substream) | ||
561 | { | ||
562 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
563 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
564 | u16 count; | ||
565 | |||
566 | count = atomic_read(&chip->count); | ||
567 | |||
568 | return runtime->period_size * (count & (runtime->periods-1)); | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * page callback (needed for mmap) | ||
573 | */ | ||
574 | static struct page *snd_cx25821_page(struct snd_pcm_substream *substream, | ||
575 | unsigned long offset) | ||
576 | { | ||
577 | void *pageptr = substream->runtime->dma_area + offset; | ||
578 | |||
579 | return vmalloc_to_page(pageptr); | ||
580 | } | ||
581 | |||
582 | /* | ||
583 | * operators | ||
584 | */ | ||
585 | static struct snd_pcm_ops snd_cx25821_pcm_ops = { | ||
586 | .open = snd_cx25821_pcm_open, | ||
587 | .close = snd_cx25821_close, | ||
588 | .ioctl = snd_pcm_lib_ioctl, | ||
589 | .hw_params = snd_cx25821_hw_params, | ||
590 | .hw_free = snd_cx25821_hw_free, | ||
591 | .prepare = snd_cx25821_prepare, | ||
592 | .trigger = snd_cx25821_card_trigger, | ||
593 | .pointer = snd_cx25821_pointer, | ||
594 | .page = snd_cx25821_page, | ||
595 | }; | ||
596 | |||
597 | |||
598 | /* | ||
599 | * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up | ||
600 | * the callbacks | ||
601 | */ | ||
602 | static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name) | ||
603 | { | ||
604 | struct snd_pcm *pcm; | ||
605 | int err; | ||
606 | |||
607 | err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); | ||
608 | if (err < 0) | ||
609 | { | ||
610 | printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", __func__); | ||
611 | return err; | ||
612 | } | ||
613 | pcm->private_data = chip; | ||
614 | pcm->info_flags = 0; | ||
615 | strcpy(pcm->name, name); | ||
616 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | |||
622 | /**************************************************************************** | ||
623 | Basic Flow for Sound Devices | ||
624 | ****************************************************************************/ | ||
625 | |||
626 | /* | ||
627 | * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio | ||
628 | * Only boards with eeprom and byte 1 at eeprom=1 have it | ||
629 | */ | ||
630 | |||
631 | static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = { | ||
632 | {0x14f1,0x0920,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | ||
633 | {0, } | ||
634 | }; | ||
635 | MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); | ||
636 | |||
637 | /* | ||
638 | * Not used in the function snd_cx25821_dev_free so removing | ||
639 | * from the file. | ||
640 | */ | ||
641 | /* | ||
642 | static int snd_cx25821_free(snd_cx25821_card_t *chip) | ||
643 | { | ||
644 | if (chip->irq >= 0) | ||
645 | free_irq(chip->irq, chip); | ||
646 | |||
647 | cx25821_dev_unregister(chip->dev); | ||
648 | pci_disable_device(chip->pci); | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | */ | ||
653 | |||
654 | /* | ||
655 | * Component Destructor | ||
656 | */ | ||
657 | static void snd_cx25821_dev_free(struct snd_card * card) | ||
658 | { | ||
659 | snd_cx25821_card_t *chip = card->private_data; | ||
660 | |||
661 | //snd_cx25821_free(chip); | ||
662 | snd_card_free(chip->card); | ||
663 | } | ||
664 | |||
665 | |||
666 | /* | ||
667 | * Alsa Constructor - Component probe | ||
668 | */ | ||
669 | static int cx25821_audio_initdev(struct cx25821_dev *dev) | ||
670 | { | ||
671 | struct snd_card *card; | ||
672 | snd_cx25821_card_t *chip; | ||
673 | int err; | ||
674 | |||
675 | if (devno >= SNDRV_CARDS) | ||
676 | { | ||
677 | printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__); | ||
678 | return (-ENODEV); | ||
679 | } | ||
680 | |||
681 | if (!enable[devno]) { | ||
682 | ++devno; | ||
683 | printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); | ||
684 | return (-ENOENT); | ||
685 | } | ||
686 | |||
687 | card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx25821_card_t)); | ||
688 | if (!card) | ||
689 | { | ||
690 | printk(KERN_INFO "DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); | ||
691 | return (-ENOMEM); | ||
692 | } | ||
693 | |||
694 | strcpy(card->driver, "cx25821"); | ||
695 | |||
696 | /* Card "creation" */ | ||
697 | card->private_free = snd_cx25821_dev_free; | ||
698 | chip = (snd_cx25821_card_t *) card->private_data; | ||
699 | spin_lock_init(&chip->reg_lock); | ||
700 | |||
701 | chip->dev = dev; | ||
702 | chip->card = card; | ||
703 | chip->pci = dev->pci; | ||
704 | chip->iobase = pci_resource_start(dev->pci, 0); | ||
705 | |||
706 | |||
707 | chip->irq = dev->pci->irq; | ||
708 | |||
709 | err = request_irq(dev->pci->irq, cx25821_irq, | ||
710 | IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip); | ||
711 | |||
712 | if (err < 0) { | ||
713 | printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, dev->pci->irq); | ||
714 | goto error; | ||
715 | } | ||
716 | |||
717 | |||
718 | if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) | ||
719 | { | ||
720 | printk(KERN_INFO "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", __func__); | ||
721 | goto error; | ||
722 | } | ||
723 | |||
724 | snd_card_set_dev(card, &chip->pci->dev); | ||
725 | |||
726 | |||
727 | strcpy(card->shortname, "cx25821"); | ||
728 | sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); | ||
729 | strcpy (card->mixername, "CX25821"); | ||
730 | |||
731 | printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", card->driver, devno); | ||
732 | |||
733 | err = snd_card_register(card); | ||
734 | if (err < 0) | ||
735 | { | ||
736 | printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", __func__); | ||
737 | goto error; | ||
738 | } | ||
739 | |||
740 | snd_cx25821_cards[devno] = card; | ||
741 | |||
742 | devno++; | ||
743 | return 0; | ||
744 | |||
745 | error: | ||
746 | snd_card_free(card); | ||
747 | return err; | ||
748 | } | ||
749 | |||
750 | |||
751 | /**************************************************************************** | ||
752 | LINUX MODULE INIT | ||
753 | ****************************************************************************/ | ||
754 | static void cx25821_audio_fini(void) | ||
755 | { | ||
756 | snd_card_free(snd_cx25821_cards[0]); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Module initializer | ||
761 | * | ||
762 | * Loops through present saa7134 cards, and assigns an ALSA device | ||
763 | * to each one | ||
764 | * | ||
765 | */ | ||
766 | static int cx25821_alsa_init(void) | ||
767 | { | ||
768 | struct cx25821_dev *dev = NULL; | ||
769 | struct list_head *list; | ||
770 | |||
771 | list_for_each(list,&cx25821_devlist) { | ||
772 | dev = list_entry(list, struct cx25821_dev, devlist); | ||
773 | cx25821_audio_initdev(dev); | ||
774 | } | ||
775 | |||
776 | if (dev == NULL) | ||
777 | printk(KERN_INFO "cx25821 ERROR ALSA: no cx25821 cards found\n"); | ||
778 | |||
779 | return 0; | ||
780 | |||
781 | } | ||
782 | |||
783 | late_initcall(cx25821_alsa_init); | ||
784 | module_exit(cx25821_audio_fini); | ||
785 | |||
786 | /* ----------------------------------------------------------- */ | ||
787 | /* | ||
788 | * Local variables: | ||
789 | * c-basic-offset: 8 | ||
790 | * End: | ||
791 | */ | ||
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c new file mode 100644 index 00000000000..9138767e4d7 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio-upstream.c | |||
@@ -0,0 +1,825 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include "cx25821-video.h" | ||
25 | #include "cx25821-audio-upstream.h" | ||
26 | |||
27 | #include <linux/fs.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/syscalls.h> | ||
33 | #include <linux/file.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | |||
39 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
40 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | |||
44 | static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; | ||
45 | |||
46 | |||
47 | int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, | ||
48 | struct sram_channel *ch, | ||
49 | unsigned int bpl, u32 risc) | ||
50 | { | ||
51 | unsigned int i, lines; | ||
52 | u32 cdt; | ||
53 | |||
54 | |||
55 | if (ch->cmds_start == 0) { | ||
56 | cx_write(ch->ptr1_reg, 0); | ||
57 | cx_write(ch->ptr2_reg, 0); | ||
58 | cx_write(ch->cnt2_reg, 0); | ||
59 | cx_write(ch->cnt1_reg, 0); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
64 | cdt = ch->cdt; | ||
65 | lines = ch->fifo_size / bpl; | ||
66 | |||
67 | if (lines > 3) | ||
68 | { | ||
69 | lines = 3; | ||
70 | } | ||
71 | |||
72 | BUG_ON(lines < 2); | ||
73 | |||
74 | |||
75 | /* write CDT */ | ||
76 | for (i = 0; i < lines; i++) { | ||
77 | cx_write(cdt + 16*i, ch->fifo_start + bpl*i); | ||
78 | cx_write(cdt + 16*i + 4, 0); | ||
79 | cx_write(cdt + 16*i + 8, 0); | ||
80 | cx_write(cdt + 16*i + 12, 0); | ||
81 | } | ||
82 | |||
83 | /* write CMDS */ | ||
84 | cx_write(ch->cmds_start + 0, risc); | ||
85 | |||
86 | cx_write(ch->cmds_start + 4, 0); | ||
87 | cx_write(ch->cmds_start + 8, cdt); | ||
88 | cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); | ||
89 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
90 | |||
91 | //IQ size | ||
92 | cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); | ||
93 | |||
94 | for (i = 24; i < 80; i += 4) | ||
95 | cx_write(ch->cmds_start + i, 0); | ||
96 | |||
97 | /* fill registers */ | ||
98 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
99 | cx_write(ch->ptr2_reg, cdt); | ||
100 | cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); | ||
101 | cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | static __le32 *cx25821_risc_field_upstream_audio( struct cx25821_dev *dev, __le32 *rp, | ||
108 | dma_addr_t databuf_phys_addr, | ||
109 | unsigned int bpl, int fifo_enable) | ||
110 | { | ||
111 | unsigned int line; | ||
112 | struct sram_channel *sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; | ||
113 | int offset = 0; | ||
114 | |||
115 | |||
116 | /* scan lines */ | ||
117 | for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) | ||
118 | { | ||
119 | *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); | ||
120 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | ||
121 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
122 | |||
123 | // Check if we need to enable the FIFO after the first 3 lines | ||
124 | // For the upstream audio channel, the risc engine will enable the FIFO. | ||
125 | if ( fifo_enable && line == 2 ) | ||
126 | { | ||
127 | *(rp++) = RISC_WRITECR; | ||
128 | *(rp++) = sram_ch->dma_ctl; | ||
129 | *(rp++) = sram_ch->fld_aud_fifo_en; | ||
130 | *(rp++) = 0x00000020; | ||
131 | } | ||
132 | |||
133 | offset += AUDIO_LINE_SIZE; | ||
134 | } | ||
135 | |||
136 | return rp; | ||
137 | } | ||
138 | |||
139 | int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, | ||
140 | struct pci_dev *pci, | ||
141 | unsigned int bpl, unsigned int lines) | ||
142 | { | ||
143 | __le32 *rp; | ||
144 | int fifo_enable = 0; | ||
145 | int frame = 0, i = 0; | ||
146 | int frame_size = AUDIO_DATA_BUF_SZ; | ||
147 | int databuf_offset = 0; | ||
148 | int risc_flag = RISC_CNT_INC; | ||
149 | dma_addr_t risc_phys_jump_addr; | ||
150 | |||
151 | |||
152 | /* Virtual address of Risc buffer program */ | ||
153 | rp = dev->_risc_virt_addr; | ||
154 | |||
155 | /* sync instruction */ | ||
156 | *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); | ||
157 | |||
158 | |||
159 | for( frame = 0; frame < NUM_AUDIO_FRAMES; frame++ ) | ||
160 | { | ||
161 | databuf_offset = frame_size * frame; | ||
162 | |||
163 | if( frame == 0 ) | ||
164 | { | ||
165 | fifo_enable = 1; | ||
166 | risc_flag = RISC_CNT_RESET; | ||
167 | } | ||
168 | else | ||
169 | { | ||
170 | fifo_enable = 0; | ||
171 | risc_flag = RISC_CNT_INC; | ||
172 | } | ||
173 | |||
174 | //Calculate physical jump address | ||
175 | if( (frame+1) == NUM_AUDIO_FRAMES ) | ||
176 | { | ||
177 | risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE; | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1); | ||
182 | } | ||
183 | |||
184 | rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable); | ||
185 | |||
186 | |||
187 | if( USE_RISC_NOOP_AUDIO ) | ||
188 | { | ||
189 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
190 | { | ||
191 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | |||
196 | // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ | ||
197 | *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); | ||
198 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
199 | *(rp++) = cpu_to_le32(0); | ||
200 | |||
201 | //Recalculate virtual address based on frame index | ||
202 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ; | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | |||
209 | void cx25821_free_memory_audio(struct cx25821_dev *dev) | ||
210 | { | ||
211 | if (dev->_risc_virt_addr) | ||
212 | { | ||
213 | pci_free_consistent(dev->pci, dev->_audiorisc_size, dev->_risc_virt_addr, dev->_risc_phys_addr); | ||
214 | dev->_risc_virt_addr = NULL; | ||
215 | } | ||
216 | |||
217 | if (dev->_audiodata_buf_virt_addr) | ||
218 | { | ||
219 | pci_free_consistent(dev->pci, dev->_audiodata_buf_size, dev->_audiodata_buf_virt_addr, dev->_audiodata_buf_phys_addr); | ||
220 | dev->_audiodata_buf_virt_addr = NULL; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | ||
225 | { | ||
226 | struct sram_channel *sram_ch = &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; | ||
227 | u32 tmp = 0; | ||
228 | |||
229 | if( !dev->_audio_is_running ) | ||
230 | { | ||
231 | printk("cx25821: No audio file is currently running so return!\n"); | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | //Disable RISC interrupts | ||
236 | cx_write( sram_ch->int_msk, 0 ); | ||
237 | |||
238 | //Turn OFF risc and fifo enable in AUD_DMA_CNTRL | ||
239 | tmp = cx_read( sram_ch->dma_ctl ); | ||
240 | cx_write( sram_ch->dma_ctl, tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en) ); | ||
241 | |||
242 | //Clear data buffer memory | ||
243 | if( dev->_audiodata_buf_virt_addr ) | ||
244 | memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); | ||
245 | |||
246 | dev->_audio_is_running = 0; | ||
247 | dev->_is_first_audio_frame = 0; | ||
248 | dev->_audioframe_count = 0; | ||
249 | dev->_audiofile_status = END_OF_FILE; | ||
250 | |||
251 | if( dev->_irq_audio_queues ) | ||
252 | { | ||
253 | kfree(dev->_irq_audio_queues); | ||
254 | dev->_irq_audio_queues = NULL; | ||
255 | } | ||
256 | |||
257 | if( dev->_audiofilename != NULL ) | ||
258 | kfree(dev->_audiofilename); | ||
259 | } | ||
260 | |||
261 | |||
262 | void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) | ||
263 | { | ||
264 | if( dev->_audio_is_running ) | ||
265 | { | ||
266 | cx25821_stop_upstream_audio(dev); | ||
267 | } | ||
268 | |||
269 | cx25821_free_memory_audio(dev); | ||
270 | } | ||
271 | |||
272 | |||
273 | int cx25821_get_audio_data(struct cx25821_dev *dev, struct sram_channel *sram_ch ) | ||
274 | { | ||
275 | struct file * myfile; | ||
276 | int frame_index_temp = dev->_audioframe_index; | ||
277 | int i = 0; | ||
278 | int line_size = AUDIO_LINE_SIZE; | ||
279 | int frame_size = AUDIO_DATA_BUF_SZ; | ||
280 | int frame_offset = frame_size * frame_index_temp; | ||
281 | ssize_t vfs_read_retval = 0; | ||
282 | char mybuf[line_size]; | ||
283 | loff_t file_offset = dev->_audioframe_count * frame_size; | ||
284 | loff_t pos; | ||
285 | mm_segment_t old_fs; | ||
286 | |||
287 | |||
288 | if( dev->_audiofile_status == END_OF_FILE ) | ||
289 | return 0; | ||
290 | |||
291 | myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); | ||
292 | |||
293 | |||
294 | if (IS_ERR(myfile)) | ||
295 | { | ||
296 | const int open_errno = -PTR_ERR(myfile); | ||
297 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); | ||
298 | return PTR_ERR(myfile); | ||
299 | } | ||
300 | else | ||
301 | { | ||
302 | if( !(myfile->f_op) ) | ||
303 | { | ||
304 | printk("%s: File has no file operations registered!\n", __func__); | ||
305 | filp_close(myfile, NULL); | ||
306 | return -EIO; | ||
307 | } | ||
308 | |||
309 | |||
310 | if( !myfile->f_op->read ) | ||
311 | { | ||
312 | printk("%s: File has no READ operations registered! \n", __func__); | ||
313 | filp_close(myfile, NULL); | ||
314 | return -EIO; | ||
315 | } | ||
316 | |||
317 | pos = myfile->f_pos; | ||
318 | old_fs = get_fs(); | ||
319 | set_fs(KERNEL_DS); | ||
320 | |||
321 | |||
322 | for( i = 0; i < dev->_audio_lines_count; i++ ) | ||
323 | { | ||
324 | pos = file_offset; | ||
325 | |||
326 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
327 | |||
328 | |||
329 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) | ||
330 | { | ||
331 | memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); | ||
332 | } | ||
333 | |||
334 | file_offset += vfs_read_retval; | ||
335 | frame_offset += vfs_read_retval; | ||
336 | |||
337 | if( vfs_read_retval < line_size ) | ||
338 | { | ||
339 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | if( i > 0 ) | ||
345 | dev->_audioframe_count++; | ||
346 | |||
347 | dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
348 | |||
349 | |||
350 | set_fs(old_fs); | ||
351 | filp_close(myfile, NULL); | ||
352 | } | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static void cx25821_audioups_handler(struct work_struct *work) | ||
358 | { | ||
359 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _audio_work_entry); | ||
360 | |||
361 | if( !dev ) | ||
362 | { | ||
363 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | cx25821_get_audio_data( dev, &dev->sram_channels[dev->_audio_upstream_channel_select] ); | ||
368 | } | ||
369 | |||
370 | int cx25821_openfile_audio(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
371 | { | ||
372 | struct file * myfile; | ||
373 | int i = 0, j = 0; | ||
374 | int line_size = AUDIO_LINE_SIZE; | ||
375 | ssize_t vfs_read_retval = 0; | ||
376 | char mybuf[line_size]; | ||
377 | loff_t pos; | ||
378 | loff_t offset = (unsigned long)0; | ||
379 | mm_segment_t old_fs; | ||
380 | |||
381 | |||
382 | myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); | ||
383 | |||
384 | |||
385 | if (IS_ERR(myfile)) | ||
386 | { | ||
387 | const int open_errno = -PTR_ERR(myfile); | ||
388 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); | ||
389 | return PTR_ERR(myfile); | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | if( !(myfile->f_op) ) | ||
394 | { | ||
395 | printk("%s: File has no file operations registered! \n", __func__); | ||
396 | filp_close(myfile, NULL); | ||
397 | return -EIO; | ||
398 | } | ||
399 | |||
400 | |||
401 | if( !myfile->f_op->read ) | ||
402 | { | ||
403 | printk("%s: File has no READ operations registered! \n", __func__); | ||
404 | filp_close(myfile, NULL); | ||
405 | return -EIO; | ||
406 | } | ||
407 | |||
408 | pos = myfile->f_pos; | ||
409 | old_fs = get_fs(); | ||
410 | set_fs(KERNEL_DS); | ||
411 | |||
412 | |||
413 | for( j = 0; j < NUM_AUDIO_FRAMES; j++ ) | ||
414 | { | ||
415 | for( i = 0; i < dev->_audio_lines_count; i++ ) | ||
416 | { | ||
417 | pos = offset; | ||
418 | |||
419 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
420 | |||
421 | |||
422 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) | ||
423 | { | ||
424 | memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval); | ||
425 | } | ||
426 | |||
427 | offset += vfs_read_retval; | ||
428 | |||
429 | if( vfs_read_retval < line_size ) | ||
430 | { | ||
431 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); | ||
432 | break; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | if( i > 0 ) | ||
437 | { | ||
438 | dev->_audioframe_count++; | ||
439 | } | ||
440 | |||
441 | if( vfs_read_retval < line_size ) | ||
442 | { | ||
443 | break; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
448 | |||
449 | set_fs(old_fs); | ||
450 | myfile->f_pos = 0; | ||
451 | filp_close(myfile, NULL); | ||
452 | } | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | ||
458 | struct sram_channel *sram_ch, | ||
459 | int bpl) | ||
460 | { | ||
461 | int ret = 0; | ||
462 | dma_addr_t dma_addr; | ||
463 | dma_addr_t data_dma_addr; | ||
464 | |||
465 | |||
466 | cx25821_free_memory_audio(dev); | ||
467 | |||
468 | dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, &dma_addr); | ||
469 | dev->_risc_virt_start_addr = dev->_risc_virt_addr; | ||
470 | dev->_risc_phys_start_addr = dma_addr; | ||
471 | dev->_risc_phys_addr = dma_addr; | ||
472 | dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; | ||
473 | |||
474 | |||
475 | if (!dev->_risc_virt_addr) | ||
476 | { | ||
477 | printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); | ||
478 | return -ENOMEM; | ||
479 | } | ||
480 | |||
481 | //Clear out memory at address | ||
482 | memset( dev->_risc_virt_addr, 0, dev->_audiorisc_size ); | ||
483 | |||
484 | |||
485 | //For Audio Data buffer allocation | ||
486 | dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, &data_dma_addr); | ||
487 | dev->_audiodata_buf_phys_addr = data_dma_addr; | ||
488 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; | ||
489 | |||
490 | if (!dev->_audiodata_buf_virt_addr) | ||
491 | { | ||
492 | printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); | ||
493 | return -ENOMEM; | ||
494 | } | ||
495 | |||
496 | //Clear out memory at address | ||
497 | memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); | ||
498 | |||
499 | |||
500 | ret = cx25821_openfile_audio(dev, sram_ch); | ||
501 | if( ret < 0 ) | ||
502 | return ret; | ||
503 | |||
504 | |||
505 | //Creating RISC programs | ||
506 | ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, dev->_audio_lines_count ); | ||
507 | if (ret < 0) | ||
508 | { | ||
509 | printk(KERN_DEBUG "cx25821 ERROR creating audio upstream RISC programs! \n"); | ||
510 | goto error; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | |||
515 | error: | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) | ||
520 | { | ||
521 | int i = 0; | ||
522 | u32 int_msk_tmp; | ||
523 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
524 | dma_addr_t risc_phys_jump_addr; | ||
525 | __le32 * rp; | ||
526 | |||
527 | |||
528 | if (status & FLD_AUD_SRC_RISCI1) | ||
529 | { | ||
530 | //Get interrupt_index of the program that interrupted | ||
531 | u32 prog_cnt = cx_read( channel->gpcnt ); | ||
532 | |||
533 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
534 | cx_write(channel->int_msk, 0); | ||
535 | cx_write(channel->int_stat, cx_read(channel->int_stat) ); | ||
536 | |||
537 | spin_lock(&dev->slock); | ||
538 | |||
539 | |||
540 | while(prog_cnt != dev->_last_index_irq) | ||
541 | { | ||
542 | //Update _last_index_irq | ||
543 | if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1)) | ||
544 | { | ||
545 | dev->_last_index_irq++; | ||
546 | } | ||
547 | else | ||
548 | { | ||
549 | dev->_last_index_irq = 0; | ||
550 | } | ||
551 | |||
552 | dev->_audioframe_index = dev->_last_index_irq; | ||
553 | |||
554 | queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry); | ||
555 | } | ||
556 | |||
557 | |||
558 | if ( dev->_is_first_audio_frame ) | ||
559 | { | ||
560 | dev->_is_first_audio_frame = 0; | ||
561 | |||
562 | if( dev->_risc_virt_start_addr != NULL ) | ||
563 | { | ||
564 | risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE; | ||
565 | |||
566 | rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE); | ||
567 | |||
568 | if( USE_RISC_NOOP_AUDIO ) | ||
569 | { | ||
570 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
571 | { | ||
572 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | // Jump to 2nd Audio Frame | ||
577 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET); | ||
578 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
579 | *(rp++) = cpu_to_le32(0); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | spin_unlock(&dev->slock); | ||
584 | } | ||
585 | else | ||
586 | { | ||
587 | if(status & FLD_AUD_SRC_OF) | ||
588 | printk("%s: Audio Received Overflow Error Interrupt!\n", __func__); | ||
589 | |||
590 | if(status & FLD_AUD_SRC_SYNC) | ||
591 | printk("%s: Audio Received Sync Error Interrupt!\n", __func__); | ||
592 | |||
593 | if(status & FLD_AUD_SRC_OPC_ERR) | ||
594 | printk("%s: Audio Received OpCode Error Interrupt!\n", __func__); | ||
595 | |||
596 | // Read and write back the interrupt status register to clear our bits | ||
597 | cx_write(channel->int_stat, cx_read(channel->int_stat) ); | ||
598 | } | ||
599 | |||
600 | |||
601 | if( dev->_audiofile_status == END_OF_FILE ) | ||
602 | { | ||
603 | printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count ); | ||
604 | return -1; | ||
605 | } | ||
606 | |||
607 | //ElSE, set the interrupt mask register, re-enable irq. | ||
608 | int_msk_tmp = cx_read( channel->int_msk ); | ||
609 | cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | ||
615 | { | ||
616 | struct cx25821_dev *dev = dev_id; | ||
617 | u32 msk_stat, audio_status; | ||
618 | int handled = 0; | ||
619 | struct sram_channel *sram_ch; | ||
620 | |||
621 | |||
622 | if( !dev ) | ||
623 | return -1; | ||
624 | |||
625 | |||
626 | sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; | ||
627 | |||
628 | msk_stat = cx_read(sram_ch->int_mstat); | ||
629 | audio_status = cx_read(sram_ch->int_stat); | ||
630 | |||
631 | // Only deal with our interrupt | ||
632 | if(audio_status) | ||
633 | { | ||
634 | handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status); | ||
635 | } | ||
636 | |||
637 | |||
638 | if( handled < 0 ) | ||
639 | { | ||
640 | cx25821_stop_upstream_audio(dev); | ||
641 | } | ||
642 | else | ||
643 | { | ||
644 | handled += handled; | ||
645 | } | ||
646 | |||
647 | return IRQ_RETVAL(handled); | ||
648 | } | ||
649 | |||
650 | |||
651 | static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
652 | { | ||
653 | int count = 0; | ||
654 | u32 tmp; | ||
655 | |||
656 | do | ||
657 | { | ||
658 | //Wait 10 microsecond before checking to see if the FIFO is turned ON. | ||
659 | udelay(10); | ||
660 | |||
661 | tmp = cx_read( sram_ch->dma_ctl ); | ||
662 | |||
663 | if(count++ > 1000) //10 millisecond timeout | ||
664 | { | ||
665 | printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); | ||
666 | return; | ||
667 | } | ||
668 | |||
669 | } while( !(tmp & sram_ch->fld_aud_fifo_en) ); | ||
670 | |||
671 | } | ||
672 | |||
673 | |||
674 | int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | ||
675 | struct sram_channel *sram_ch) | ||
676 | { | ||
677 | u32 tmp = 0; | ||
678 | int err = 0; | ||
679 | |||
680 | |||
681 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. | ||
682 | cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); | ||
683 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
684 | |||
685 | |||
686 | /* reset counter */ | ||
687 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
688 | |||
689 | //Set the line length (It looks like we do not need to set the line length) | ||
690 | cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); | ||
691 | |||
692 | //Set the input mode to 16-bit | ||
693 | tmp = cx_read( sram_ch->aud_cfg ); | ||
694 | tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; | ||
695 | cx_write( sram_ch->aud_cfg, tmp ); | ||
696 | |||
697 | // Read and write back the interrupt status register to clear it | ||
698 | tmp = cx_read( sram_ch->int_stat); | ||
699 | cx_write( sram_ch->int_stat, tmp); | ||
700 | |||
701 | // Clear our bits from the interrupt status register. | ||
702 | cx_write( sram_ch->int_stat, _intr_msk ); | ||
703 | |||
704 | |||
705 | //Set the interrupt mask register, enable irq. | ||
706 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
707 | tmp = cx_read( sram_ch->int_msk ); | ||
708 | cx_write( sram_ch->int_msk, tmp |= _intr_msk ); | ||
709 | |||
710 | |||
711 | err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
712 | if (err < 0) | ||
713 | { | ||
714 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); | ||
715 | goto fail_irq; | ||
716 | } | ||
717 | |||
718 | |||
719 | // Start the DMA engine | ||
720 | tmp = cx_read( sram_ch->dma_ctl ); | ||
721 | cx_set( sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en ); | ||
722 | |||
723 | dev->_audio_is_running = 1; | ||
724 | dev->_is_first_audio_frame = 1; | ||
725 | |||
726 | // The fifo_en bit turns on by the first Risc program | ||
727 | cx25821_wait_fifo_enable(dev, sram_ch); | ||
728 | |||
729 | return 0; | ||
730 | |||
731 | |||
732 | fail_irq: | ||
733 | cx25821_dev_unregister(dev); | ||
734 | return err; | ||
735 | } | ||
736 | |||
737 | |||
738 | int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | ||
739 | { | ||
740 | struct sram_channel *sram_ch; | ||
741 | int retval = 0; | ||
742 | int err = 0; | ||
743 | int str_length = 0; | ||
744 | |||
745 | if( dev->_audio_is_running ) | ||
746 | { | ||
747 | printk("Audio Channel is still running so return!\n"); | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | dev->_audio_upstream_channel_select = channel_select; | ||
752 | sram_ch = &dev->sram_channels[channel_select]; | ||
753 | |||
754 | //Work queue | ||
755 | INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); | ||
756 | dev->_irq_audio_queues = create_singlethread_workqueue("cx25821_audioworkqueue"); | ||
757 | |||
758 | if(!dev->_irq_audio_queues) | ||
759 | { | ||
760 | printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); | ||
761 | return -ENOMEM; | ||
762 | } | ||
763 | |||
764 | |||
765 | dev->_last_index_irq = 0; | ||
766 | dev->_audio_is_running = 0; | ||
767 | dev->_audioframe_count = 0; | ||
768 | dev->_audiofile_status = RESET_STATUS; | ||
769 | dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; | ||
770 | _line_size = AUDIO_LINE_SIZE; | ||
771 | |||
772 | |||
773 | if( dev->input_audiofilename ) | ||
774 | { | ||
775 | str_length = strlen(dev->input_audiofilename); | ||
776 | dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
777 | |||
778 | if( !dev->_audiofilename ) | ||
779 | goto error; | ||
780 | |||
781 | memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1); | ||
782 | |||
783 | //Default if filename is empty string | ||
784 | if( strcmp(dev->input_audiofilename,"") == 0) | ||
785 | { | ||
786 | dev->_audiofilename = "/root/audioGOOD.wav"; | ||
787 | } | ||
788 | } | ||
789 | else | ||
790 | { | ||
791 | str_length = strlen(_defaultAudioName); | ||
792 | dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
793 | |||
794 | if( !dev->_audiofilename ) | ||
795 | goto error; | ||
796 | |||
797 | memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); | ||
798 | } | ||
799 | |||
800 | |||
801 | retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, 0); | ||
802 | |||
803 | dev->audio_upstream_riscbuf_size = AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + RISC_SYNC_INSTRUCTION_SIZE; | ||
804 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; | ||
805 | |||
806 | |||
807 | //Allocating buffers and prepare RISC program | ||
808 | retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); | ||
809 | if (retval < 0) | ||
810 | { | ||
811 | printk(KERN_ERR "%s: Failed to set up Audio upstream buffers!\n", dev->name); | ||
812 | goto error; | ||
813 | } | ||
814 | |||
815 | //Start RISC engine | ||
816 | cx25821_start_audio_dma_upstream(dev, sram_ch); | ||
817 | |||
818 | return 0; | ||
819 | |||
820 | error: | ||
821 | cx25821_dev_unregister(dev); | ||
822 | |||
823 | return err; | ||
824 | } | ||
825 | |||
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.h b/drivers/staging/cx25821/cx25821-audio-upstream.h new file mode 100644 index 00000000000..7bb136b003b --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio-upstream.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | |||
27 | #define NUM_AUDIO_PROGS 8 | ||
28 | #define NUM_AUDIO_FRAMES 8 | ||
29 | #define END_OF_FILE 0 | ||
30 | #define IN_PROGRESS 1 | ||
31 | #define RESET_STATUS -1 | ||
32 | #define FIFO_DISABLE 0 | ||
33 | #define FIFO_ENABLE 1 | ||
34 | #define NUM_NO_OPS 4 | ||
35 | |||
36 | |||
37 | #define RISC_READ_INSTRUCTION_SIZE 12 | ||
38 | #define RISC_JUMP_INSTRUCTION_SIZE 12 | ||
39 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
40 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
41 | #define DWORD_SIZE 4 | ||
42 | #define AUDIO_SYNC_LINE 4 | ||
43 | |||
44 | |||
45 | #define LINES_PER_AUDIO_BUFFER 15 | ||
46 | #define AUDIO_LINE_SIZE 128 | ||
47 | #define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) | ||
48 | |||
49 | #define USE_RISC_NOOP_AUDIO 1 | ||
50 | |||
51 | #ifdef USE_RISC_NOOP_AUDIO | ||
52 | #define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE) | ||
53 | #endif | ||
54 | |||
55 | |||
56 | #ifndef USE_RISC_NOOP_AUDIO | ||
57 | #define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) | ||
58 | #endif | ||
59 | |||
60 | static int _line_size; | ||
61 | char * _defaultAudioName = "/root/audioGOOD.wav"; | ||
62 | |||
diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h new file mode 100644 index 00000000000..1e1351800ba --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef __CX25821_AUDIO_H__ | ||
24 | #define __CX25821_AUDIO_H__ | ||
25 | |||
26 | |||
27 | #define USE_RISC_NOOP 1 | ||
28 | #define LINES_PER_BUFFER 15 | ||
29 | #define AUDIO_LINE_SIZE 128 | ||
30 | |||
31 | //Number of buffer programs to use at once. | ||
32 | #define NUMBER_OF_PROGRAMS 8 | ||
33 | |||
34 | //Max size of the RISC program for a buffer. - worst case is 2 writes per line | ||
35 | // Space is also added for the 4 no-op instructions added on the end. | ||
36 | |||
37 | #ifndef USE_RISC_NOOP | ||
38 | #define MAX_BUFFER_PROGRAM_SIZE \ | ||
39 | (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) | ||
40 | #endif | ||
41 | |||
42 | // MAE 12 July 2005 Try to use NOOP RISC instruction instead | ||
43 | #ifdef USE_RISC_NOOP | ||
44 | #define MAX_BUFFER_PROGRAM_SIZE \ | ||
45 | (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) | ||
46 | #endif | ||
47 | |||
48 | |||
49 | //Sizes of various instructions in bytes. Used when adding instructions. | ||
50 | #define RISC_WRITE_INSTRUCTION_SIZE 12 | ||
51 | #define RISC_JUMP_INSTRUCTION_SIZE 12 | ||
52 | #define RISC_SKIP_INSTRUCTION_SIZE 4 | ||
53 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
54 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
55 | #define RISC_NOOP_INSTRUCTION_SIZE 4 | ||
56 | |||
57 | #define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) | ||
58 | |||
59 | #endif | ||
60 | |||
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c new file mode 100644 index 00000000000..a8e4dce88b9 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audups11.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | |||
99 | lock_kernel(); | ||
100 | list_for_each(list, &cx25821_devlist) | ||
101 | { | ||
102 | h = list_entry(list, struct cx25821_dev, devlist); | ||
103 | |||
104 | if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor) | ||
105 | { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | file->private_data = fh; | ||
126 | fh->dev = dev; | ||
127 | fh->type = type; | ||
128 | fh->width = 720; | ||
129 | |||
130 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
131 | fh->height = 576; | ||
132 | else | ||
133 | fh->height = 480; | ||
134 | |||
135 | dev->channel_opened = 10; | ||
136 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
137 | |||
138 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
139 | |||
140 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
141 | &dev->pci->dev, &dev->slock, | ||
142 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
143 | V4L2_FIELD_INTERLACED, | ||
144 | sizeof(struct cx25821_buffer), | ||
145 | fh); | ||
146 | |||
147 | dprintk(1, "post videobuf_queue_init()\n"); | ||
148 | unlock_kernel(); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
154 | { | ||
155 | struct cx25821_fh *fh = file->private_data; | ||
156 | |||
157 | switch (fh->type) | ||
158 | { | ||
159 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
160 | if (res_locked(fh->dev, RESOURCE_VIDEO11)) | ||
161 | return -EBUSY; | ||
162 | |||
163 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
164 | |||
165 | default: | ||
166 | BUG(); | ||
167 | return 0; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
172 | { | ||
173 | struct cx25821_fh *fh = file->private_data; | ||
174 | struct cx25821_buffer *buf; | ||
175 | |||
176 | if (res_check(fh, RESOURCE_VIDEO11)) { | ||
177 | /* streaming capture */ | ||
178 | if (list_empty(&fh->vidq.stream)) | ||
179 | return POLLERR; | ||
180 | buf = list_entry(fh->vidq.stream.next, | ||
181 | struct cx25821_buffer, vb.stream); | ||
182 | } else { | ||
183 | /* read() capture */ | ||
184 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
185 | if (NULL == buf) | ||
186 | return POLLERR; | ||
187 | } | ||
188 | |||
189 | poll_wait(file, &buf->vb.done, wait); | ||
190 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
191 | return POLLIN|POLLRDNORM; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | |||
196 | static int video_release(struct file *file) | ||
197 | { | ||
198 | struct cx25821_fh *fh = file->private_data; | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | //stop the risc engine and fifo | ||
202 | //cx_write(channel11->dma_ctl, 0); | ||
203 | |||
204 | /* stop video capture */ | ||
205 | if (res_check(fh, RESOURCE_VIDEO11)) { | ||
206 | videobuf_queue_cancel(&fh->vidq); | ||
207 | res_free(dev, fh, RESOURCE_VIDEO11); | ||
208 | } | ||
209 | |||
210 | if (fh->vidq.read_buf) { | ||
211 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
212 | kfree(fh->vidq.read_buf); | ||
213 | } | ||
214 | |||
215 | videobuf_mmap_free(&fh->vidq); | ||
216 | |||
217 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
218 | |||
219 | file->private_data = NULL; | ||
220 | kfree(fh); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
227 | { | ||
228 | struct cx25821_fh *fh = priv; | ||
229 | struct cx25821_dev *dev = fh->dev; | ||
230 | |||
231 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
232 | { | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | if (unlikely(i != fh->type)) | ||
237 | { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) | ||
242 | { | ||
243 | return -EBUSY; | ||
244 | } | ||
245 | |||
246 | return videobuf_streamon(get_queue(fh)); | ||
247 | } | ||
248 | |||
249 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
250 | { | ||
251 | struct cx25821_fh *fh = priv; | ||
252 | struct cx25821_dev *dev = fh->dev; | ||
253 | int err, res; | ||
254 | |||
255 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
256 | return -EINVAL; | ||
257 | if (i != fh->type) | ||
258 | return -EINVAL; | ||
259 | |||
260 | res = get_resource(fh, RESOURCE_VIDEO11); | ||
261 | err = videobuf_streamoff(get_queue(fh)); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | res_free(dev, fh, res); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | |||
269 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
270 | { | ||
271 | struct cx25821_fh *fh = priv; | ||
272 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
273 | int err; | ||
274 | |||
275 | if (fh) | ||
276 | { | ||
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
278 | if (0 != err) | ||
279 | return err; | ||
280 | } | ||
281 | |||
282 | dprintk(2, "%s()\n", __func__); | ||
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
284 | |||
285 | if (0 != err) | ||
286 | return err; | ||
287 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
288 | fh->width = f->fmt.pix.width; | ||
289 | fh->height = f->fmt.pix.height; | ||
290 | fh->vidq.field = f->fmt.pix.field; | ||
291 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
292 | cx25821_call_all(dev, video, s_fmt, f); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg) | ||
297 | { | ||
298 | struct cx25821_fh *fh = file->private_data; | ||
299 | struct cx25821_dev *dev = fh->dev; | ||
300 | int command = 0; | ||
301 | struct upstream_user_struct *data_from_user; | ||
302 | |||
303 | |||
304 | data_from_user = (struct upstream_user_struct *)arg; | ||
305 | |||
306 | if( !data_from_user ) | ||
307 | { | ||
308 | printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | command = data_from_user->command; | ||
313 | |||
314 | if( command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO ) | ||
315 | { | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | |||
320 | dev->input_filename = data_from_user->input_filename; | ||
321 | dev->input_audiofilename = data_from_user->input_filename; | ||
322 | dev->vid_stdname = data_from_user->vid_stdname; | ||
323 | dev->pixel_format = data_from_user->pixel_format; | ||
324 | dev->channel_select = data_from_user->channel_select; | ||
325 | dev->command = data_from_user->command; | ||
326 | |||
327 | |||
328 | switch(command) | ||
329 | { | ||
330 | case UPSTREAM_START_AUDIO: | ||
331 | cx25821_start_upstream_audio(dev, data_from_user); | ||
332 | break; | ||
333 | |||
334 | case UPSTREAM_STOP_AUDIO: | ||
335 | cx25821_stop_upstream_audio(dev); | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
343 | { | ||
344 | struct cx25821_fh *fh = priv; | ||
345 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
346 | } | ||
347 | |||
348 | static int vidioc_log_status (struct file *file, void *priv) | ||
349 | { | ||
350 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
351 | char name[32 + 2]; | ||
352 | |||
353 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
354 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
355 | dev->name); | ||
356 | cx25821_call_all(dev, core, log_status); | ||
357 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
358 | dev->name); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
363 | struct v4l2_control *ctl) | ||
364 | { | ||
365 | struct cx25821_fh *fh = priv; | ||
366 | struct cx25821_dev *dev = fh->dev; | ||
367 | int err; | ||
368 | |||
369 | if (fh) | ||
370 | { | ||
371 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
372 | if (0 != err) | ||
373 | return err; | ||
374 | } | ||
375 | return 0; | ||
376 | } | ||
377 | // exported stuff | ||
378 | static const struct v4l2_file_operations video_fops = { | ||
379 | .owner = THIS_MODULE, | ||
380 | .open = video_open, | ||
381 | .release = video_release, | ||
382 | .read = video_read, | ||
383 | .poll = video_poll, | ||
384 | .mmap = video_mmap, | ||
385 | .ioctl = video_ioctl_upstream11, | ||
386 | }; | ||
387 | |||
388 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
389 | .vidioc_querycap = vidioc_querycap, | ||
390 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
391 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
392 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
393 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
394 | .vidioc_reqbufs = vidioc_reqbufs, | ||
395 | .vidioc_querybuf = vidioc_querybuf, | ||
396 | .vidioc_qbuf = vidioc_qbuf, | ||
397 | .vidioc_dqbuf = vidioc_dqbuf, | ||
398 | #ifdef TUNER_FLAG | ||
399 | .vidioc_s_std = vidioc_s_std, | ||
400 | .vidioc_querystd = vidioc_querystd, | ||
401 | #endif | ||
402 | .vidioc_cropcap = vidioc_cropcap, | ||
403 | .vidioc_s_crop = vidioc_s_crop, | ||
404 | .vidioc_g_crop = vidioc_g_crop, | ||
405 | .vidioc_enum_input = vidioc_enum_input, | ||
406 | .vidioc_g_input = vidioc_g_input, | ||
407 | .vidioc_s_input = vidioc_s_input, | ||
408 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
409 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
410 | .vidioc_queryctrl = vidioc_queryctrl, | ||
411 | .vidioc_streamon = vidioc_streamon, | ||
412 | .vidioc_streamoff = vidioc_streamoff, | ||
413 | .vidioc_log_status = vidioc_log_status, | ||
414 | .vidioc_g_priority = vidioc_g_priority, | ||
415 | .vidioc_s_priority = vidioc_s_priority, | ||
416 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
417 | .vidiocgmbuf = vidiocgmbuf, | ||
418 | #endif | ||
419 | #ifdef TUNER_FLAG | ||
420 | .vidioc_g_tuner = vidioc_g_tuner, | ||
421 | .vidioc_s_tuner = vidioc_s_tuner, | ||
422 | .vidioc_g_frequency = vidioc_g_frequency, | ||
423 | .vidioc_s_frequency = vidioc_s_frequency, | ||
424 | #endif | ||
425 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
426 | .vidioc_g_register = vidioc_g_register, | ||
427 | .vidioc_s_register = vidioc_s_register, | ||
428 | #endif | ||
429 | }; | ||
430 | |||
431 | struct video_device cx25821_video_template11 = { | ||
432 | .name = "cx25821-audioupstream", | ||
433 | .fops = &video_fops, | ||
434 | .minor = -1, | ||
435 | .ioctl_ops = &video_ioctl_ops, | ||
436 | .tvnorms = CX25821_NORMS, | ||
437 | .current_norm = V4L2_STD_NTSC_M, | ||
438 | }; | ||
439 | |||
440 | |||
441 | |||
diff --git a/drivers/staging/cx25821/cx25821-biffuncs.h b/drivers/staging/cx25821/cx25821-biffuncs.h new file mode 100644 index 00000000000..a5c053507a4 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-biffuncs.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef _BITFUNCS_H | ||
24 | #define _BITFUNCS_H | ||
25 | |||
26 | #define SetBit(Bit) (1 << Bit) | ||
27 | |||
28 | inline u8 getBit(u32 sample, u8 index) | ||
29 | { | ||
30 | return (u8) ((sample >> index) & 1); | ||
31 | } | ||
32 | |||
33 | inline u32 clearBitAtPos(u32 value, u8 bit) | ||
34 | { | ||
35 | return value & ~(1 << bit); | ||
36 | } | ||
37 | |||
38 | inline u32 setBitAtPos(u32 sample, u8 bit) | ||
39 | { | ||
40 | sample |= (1 << bit); | ||
41 | return sample; | ||
42 | |||
43 | } | ||
44 | |||
45 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c new file mode 100644 index 00000000000..eaaa56707c1 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-cards.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <media/cx25840.h> | ||
29 | |||
30 | #include "cx25821.h" | ||
31 | #include "tuner-xc2028.h" | ||
32 | |||
33 | // board config info | ||
34 | |||
35 | struct cx25821_board cx25821_boards[] = { | ||
36 | [UNKNOWN_BOARD] = { | ||
37 | .name = "UNKNOWN/GENERIC", | ||
38 | // Ensure safe default for unknown boards | ||
39 | .clk_freq = 0, | ||
40 | }, | ||
41 | |||
42 | [CX25821_BOARD] = { | ||
43 | .name = "CX25821", | ||
44 | .portb = CX25821_RAW, | ||
45 | .portc = CX25821_264, | ||
46 | .input[0].type = CX25821_VMUX_COMPOSITE, | ||
47 | }, | ||
48 | |||
49 | }; | ||
50 | |||
51 | const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards); | ||
52 | |||
53 | struct cx25821_subid cx25821_subids[]={ | ||
54 | { | ||
55 | .subvendor = 0x14f1, | ||
56 | .subdevice = 0x0920, | ||
57 | .card = CX25821_BOARD, | ||
58 | }, | ||
59 | }; | ||
60 | |||
61 | |||
62 | void cx25821_card_setup(struct cx25821_dev *dev) | ||
63 | { | ||
64 | static u8 eeprom[256]; | ||
65 | |||
66 | if (dev->i2c_bus[0].i2c_rc == 0) | ||
67 | { | ||
68 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | ||
69 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); | ||
70 | } | ||
71 | } | ||
72 | |||
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c new file mode 100644 index 00000000000..adca7af1e50 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-core.c | |||
@@ -0,0 +1,1565 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 | |||
29 | MODULE_DESCRIPTION("Driver for Athena cards"); | ||
30 | MODULE_AUTHOR("Shu Lin - Hiep Huynh"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | struct list_head cx25821_devlist; | ||
34 | |||
35 | static unsigned int debug; | ||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "enable debug messages"); | ||
38 | |||
39 | static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | ||
40 | module_param_array(card, int, NULL, 0444); | ||
41 | MODULE_PARM_DESC(card, "card type"); | ||
42 | |||
43 | |||
44 | static unsigned int cx25821_devcount = 0; | ||
45 | |||
46 | static DEFINE_MUTEX(devlist); | ||
47 | LIST_HEAD(cx25821_devlist); | ||
48 | |||
49 | |||
50 | struct sram_channel cx25821_sram_channels[] = { | ||
51 | [SRAM_CH00] = { | ||
52 | .i = SRAM_CH00, | ||
53 | .name = "VID A", | ||
54 | .cmds_start = VID_A_DOWN_CMDS, | ||
55 | .ctrl_start = VID_A_IQ, | ||
56 | .cdt = VID_A_CDT, | ||
57 | .fifo_start = VID_A_DOWN_CLUSTER_1, | ||
58 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
59 | .ptr1_reg = DMA1_PTR1, | ||
60 | .ptr2_reg = DMA1_PTR2, | ||
61 | .cnt1_reg = DMA1_CNT1, | ||
62 | .cnt2_reg = DMA1_CNT2, | ||
63 | .int_msk = VID_A_INT_MSK, | ||
64 | .int_stat = VID_A_INT_STAT, | ||
65 | .int_mstat = VID_A_INT_MSTAT, | ||
66 | .dma_ctl = VID_DST_A_DMA_CTL, | ||
67 | .gpcnt_ctl = VID_DST_A_GPCNT_CTL, | ||
68 | .gpcnt = VID_DST_A_GPCNT, | ||
69 | .vip_ctl = VID_DST_A_VIP_CTL, | ||
70 | .pix_frmt = VID_DST_A_PIX_FRMT, | ||
71 | }, | ||
72 | |||
73 | [SRAM_CH01] = { | ||
74 | .i = SRAM_CH01, | ||
75 | .name = "VID B", | ||
76 | .cmds_start = VID_B_DOWN_CMDS, | ||
77 | .ctrl_start = VID_B_IQ, | ||
78 | .cdt = VID_B_CDT, | ||
79 | .fifo_start = VID_B_DOWN_CLUSTER_1, | ||
80 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
81 | .ptr1_reg = DMA2_PTR1, | ||
82 | .ptr2_reg = DMA2_PTR2, | ||
83 | .cnt1_reg = DMA2_CNT1, | ||
84 | .cnt2_reg = DMA2_CNT2, | ||
85 | .int_msk = VID_B_INT_MSK, | ||
86 | .int_stat = VID_B_INT_STAT, | ||
87 | .int_mstat = VID_B_INT_MSTAT, | ||
88 | .dma_ctl = VID_DST_B_DMA_CTL, | ||
89 | .gpcnt_ctl = VID_DST_B_GPCNT_CTL, | ||
90 | .gpcnt = VID_DST_B_GPCNT, | ||
91 | .vip_ctl = VID_DST_B_VIP_CTL, | ||
92 | .pix_frmt = VID_DST_B_PIX_FRMT, | ||
93 | }, | ||
94 | |||
95 | [SRAM_CH02] = { | ||
96 | .i = SRAM_CH02, | ||
97 | .name = "VID C", | ||
98 | .cmds_start = VID_C_DOWN_CMDS, | ||
99 | .ctrl_start = VID_C_IQ, | ||
100 | .cdt = VID_C_CDT, | ||
101 | .fifo_start = VID_C_DOWN_CLUSTER_1, | ||
102 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
103 | .ptr1_reg = DMA3_PTR1, | ||
104 | .ptr2_reg = DMA3_PTR2, | ||
105 | .cnt1_reg = DMA3_CNT1, | ||
106 | .cnt2_reg = DMA3_CNT2, | ||
107 | .int_msk = VID_C_INT_MSK, | ||
108 | .int_stat = VID_C_INT_STAT, | ||
109 | .int_mstat = VID_C_INT_MSTAT, | ||
110 | .dma_ctl = VID_DST_C_DMA_CTL, | ||
111 | .gpcnt_ctl = VID_DST_C_GPCNT_CTL, | ||
112 | .gpcnt = VID_DST_C_GPCNT, | ||
113 | .vip_ctl = VID_DST_C_VIP_CTL, | ||
114 | .pix_frmt = VID_DST_C_PIX_FRMT, | ||
115 | }, | ||
116 | |||
117 | [SRAM_CH03] = { | ||
118 | .i = SRAM_CH03, | ||
119 | .name = "VID D", | ||
120 | .cmds_start = VID_D_DOWN_CMDS, | ||
121 | .ctrl_start = VID_D_IQ, | ||
122 | .cdt = VID_D_CDT, | ||
123 | .fifo_start = VID_D_DOWN_CLUSTER_1, | ||
124 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
125 | .ptr1_reg = DMA4_PTR1, | ||
126 | .ptr2_reg = DMA4_PTR2, | ||
127 | .cnt1_reg = DMA4_CNT1, | ||
128 | .cnt2_reg = DMA4_CNT2, | ||
129 | .int_msk = VID_D_INT_MSK, | ||
130 | .int_stat = VID_D_INT_STAT, | ||
131 | .int_mstat = VID_D_INT_MSTAT, | ||
132 | .dma_ctl = VID_DST_D_DMA_CTL, | ||
133 | .gpcnt_ctl = VID_DST_D_GPCNT_CTL, | ||
134 | .gpcnt = VID_DST_D_GPCNT, | ||
135 | .vip_ctl = VID_DST_D_VIP_CTL, | ||
136 | .pix_frmt = VID_DST_D_PIX_FRMT, | ||
137 | }, | ||
138 | |||
139 | [SRAM_CH04] = { | ||
140 | .i = SRAM_CH04, | ||
141 | .name = "VID E", | ||
142 | .cmds_start = VID_E_DOWN_CMDS, | ||
143 | .ctrl_start = VID_E_IQ, | ||
144 | .cdt = VID_E_CDT, | ||
145 | .fifo_start = VID_E_DOWN_CLUSTER_1, | ||
146 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
147 | .ptr1_reg = DMA5_PTR1, | ||
148 | .ptr2_reg = DMA5_PTR2, | ||
149 | .cnt1_reg = DMA5_CNT1, | ||
150 | .cnt2_reg = DMA5_CNT2, | ||
151 | .int_msk = VID_E_INT_MSK, | ||
152 | .int_stat = VID_E_INT_STAT, | ||
153 | .int_mstat = VID_E_INT_MSTAT, | ||
154 | .dma_ctl = VID_DST_E_DMA_CTL, | ||
155 | .gpcnt_ctl = VID_DST_E_GPCNT_CTL, | ||
156 | .gpcnt = VID_DST_E_GPCNT, | ||
157 | .vip_ctl = VID_DST_E_VIP_CTL, | ||
158 | .pix_frmt = VID_DST_E_PIX_FRMT, | ||
159 | }, | ||
160 | |||
161 | [SRAM_CH05] = { | ||
162 | .i = SRAM_CH05, | ||
163 | .name = "VID F", | ||
164 | .cmds_start = VID_F_DOWN_CMDS, | ||
165 | .ctrl_start = VID_F_IQ, | ||
166 | .cdt = VID_F_CDT, | ||
167 | .fifo_start = VID_F_DOWN_CLUSTER_1, | ||
168 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
169 | .ptr1_reg = DMA6_PTR1, | ||
170 | .ptr2_reg = DMA6_PTR2, | ||
171 | .cnt1_reg = DMA6_CNT1, | ||
172 | .cnt2_reg = DMA6_CNT2, | ||
173 | .int_msk = VID_F_INT_MSK, | ||
174 | .int_stat = VID_F_INT_STAT, | ||
175 | .int_mstat = VID_F_INT_MSTAT, | ||
176 | .dma_ctl = VID_DST_F_DMA_CTL, | ||
177 | .gpcnt_ctl = VID_DST_F_GPCNT_CTL, | ||
178 | .gpcnt = VID_DST_F_GPCNT, | ||
179 | .vip_ctl = VID_DST_F_VIP_CTL, | ||
180 | .pix_frmt = VID_DST_F_PIX_FRMT, | ||
181 | }, | ||
182 | |||
183 | [SRAM_CH06] = { | ||
184 | .i = SRAM_CH06, | ||
185 | .name = "VID G", | ||
186 | .cmds_start = VID_G_DOWN_CMDS, | ||
187 | .ctrl_start = VID_G_IQ, | ||
188 | .cdt = VID_G_CDT, | ||
189 | .fifo_start = VID_G_DOWN_CLUSTER_1, | ||
190 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
191 | .ptr1_reg = DMA7_PTR1, | ||
192 | .ptr2_reg = DMA7_PTR2, | ||
193 | .cnt1_reg = DMA7_CNT1, | ||
194 | .cnt2_reg = DMA7_CNT2, | ||
195 | .int_msk = VID_G_INT_MSK, | ||
196 | .int_stat = VID_G_INT_STAT, | ||
197 | .int_mstat = VID_G_INT_MSTAT, | ||
198 | .dma_ctl = VID_DST_G_DMA_CTL, | ||
199 | .gpcnt_ctl = VID_DST_G_GPCNT_CTL, | ||
200 | .gpcnt = VID_DST_G_GPCNT, | ||
201 | .vip_ctl = VID_DST_G_VIP_CTL, | ||
202 | .pix_frmt = VID_DST_G_PIX_FRMT, | ||
203 | }, | ||
204 | |||
205 | [SRAM_CH07] = { | ||
206 | .i = SRAM_CH07, | ||
207 | .name = "VID H", | ||
208 | .cmds_start = VID_H_DOWN_CMDS, | ||
209 | .ctrl_start = VID_H_IQ, | ||
210 | .cdt = VID_H_CDT, | ||
211 | .fifo_start = VID_H_DOWN_CLUSTER_1, | ||
212 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
213 | .ptr1_reg = DMA8_PTR1, | ||
214 | .ptr2_reg = DMA8_PTR2, | ||
215 | .cnt1_reg = DMA8_CNT1, | ||
216 | .cnt2_reg = DMA8_CNT2, | ||
217 | .int_msk = VID_H_INT_MSK, | ||
218 | .int_stat = VID_H_INT_STAT, | ||
219 | .int_mstat = VID_H_INT_MSTAT, | ||
220 | .dma_ctl = VID_DST_H_DMA_CTL, | ||
221 | .gpcnt_ctl = VID_DST_H_GPCNT_CTL, | ||
222 | .gpcnt = VID_DST_H_GPCNT, | ||
223 | .vip_ctl = VID_DST_H_VIP_CTL, | ||
224 | .pix_frmt = VID_DST_H_PIX_FRMT, | ||
225 | }, | ||
226 | |||
227 | [SRAM_CH08] = { | ||
228 | .name = "audio from", | ||
229 | .cmds_start = AUD_A_DOWN_CMDS, | ||
230 | .ctrl_start = AUD_A_IQ, | ||
231 | .cdt = AUD_A_CDT, | ||
232 | .fifo_start = AUD_A_DOWN_CLUSTER_1, | ||
233 | .fifo_size = AUDIO_CLUSTER_SIZE * 3, | ||
234 | .ptr1_reg = DMA17_PTR1, | ||
235 | .ptr2_reg = DMA17_PTR2, | ||
236 | .cnt1_reg = DMA17_CNT1, | ||
237 | .cnt2_reg = DMA17_CNT2, | ||
238 | }, | ||
239 | |||
240 | [SRAM_CH09] = { | ||
241 | .i = SRAM_CH09, | ||
242 | .name = "VID Upstream I", | ||
243 | .cmds_start = VID_I_UP_CMDS, | ||
244 | .ctrl_start = VID_I_IQ, | ||
245 | .cdt = VID_I_CDT, | ||
246 | .fifo_start = VID_I_UP_CLUSTER_1, | ||
247 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
248 | .ptr1_reg = DMA15_PTR1, | ||
249 | .ptr2_reg = DMA15_PTR2, | ||
250 | .cnt1_reg = DMA15_CNT1, | ||
251 | .cnt2_reg = DMA15_CNT2, | ||
252 | .int_msk = VID_I_INT_MSK, | ||
253 | .int_stat = VID_I_INT_STAT, | ||
254 | .int_mstat = VID_I_INT_MSTAT, | ||
255 | .dma_ctl = VID_SRC_I_DMA_CTL, | ||
256 | .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, | ||
257 | .gpcnt = VID_SRC_I_GPCNT, | ||
258 | |||
259 | .vid_fmt_ctl = VID_SRC_I_FMT_CTL, | ||
260 | .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1, | ||
261 | .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2, | ||
262 | .vid_cdt_size = VID_SRC_I_CDT_SZ, | ||
263 | .irq_bit = 8, | ||
264 | }, | ||
265 | |||
266 | [SRAM_CH10] = { | ||
267 | .i = SRAM_CH10, | ||
268 | .name = "VID Upstream J", | ||
269 | .cmds_start = VID_J_UP_CMDS, | ||
270 | .ctrl_start = VID_J_IQ, | ||
271 | .cdt = VID_J_CDT, | ||
272 | .fifo_start = VID_J_UP_CLUSTER_1, | ||
273 | .fifo_size = (VID_CLUSTER_SIZE<<2), | ||
274 | .ptr1_reg = DMA16_PTR1, | ||
275 | .ptr2_reg = DMA16_PTR2, | ||
276 | .cnt1_reg = DMA16_CNT1, | ||
277 | .cnt2_reg = DMA16_CNT2, | ||
278 | .int_msk = VID_J_INT_MSK, | ||
279 | .int_stat = VID_J_INT_STAT, | ||
280 | .int_mstat = VID_J_INT_MSTAT, | ||
281 | .dma_ctl = VID_SRC_J_DMA_CTL, | ||
282 | .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, | ||
283 | .gpcnt = VID_SRC_J_GPCNT, | ||
284 | |||
285 | .vid_fmt_ctl = VID_SRC_J_FMT_CTL, | ||
286 | .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1, | ||
287 | .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2, | ||
288 | .vid_cdt_size = VID_SRC_J_CDT_SZ, | ||
289 | .irq_bit = 9, | ||
290 | }, | ||
291 | |||
292 | |||
293 | [SRAM_CH11] = { | ||
294 | .i = SRAM_CH11, | ||
295 | .name = "Audio Upstream Channel B", | ||
296 | .cmds_start = AUD_B_UP_CMDS, | ||
297 | .ctrl_start = AUD_B_IQ, | ||
298 | .cdt = AUD_B_CDT, | ||
299 | .fifo_start = AUD_B_UP_CLUSTER_1, | ||
300 | .fifo_size = (AUDIO_CLUSTER_SIZE*3), | ||
301 | .ptr1_reg = DMA22_PTR1, | ||
302 | .ptr2_reg = DMA22_PTR2, | ||
303 | .cnt1_reg = DMA22_CNT1, | ||
304 | .cnt2_reg = DMA22_CNT2, | ||
305 | .int_msk = AUD_B_INT_MSK, | ||
306 | .int_stat = AUD_B_INT_STAT, | ||
307 | .int_mstat = AUD_B_INT_MSTAT, | ||
308 | .dma_ctl = AUD_INT_DMA_CTL, | ||
309 | .gpcnt_ctl = AUD_B_GPCNT_CTL, | ||
310 | .gpcnt = AUD_B_GPCNT, | ||
311 | .aud_length = AUD_B_LNGTH, | ||
312 | .aud_cfg = AUD_B_CFG, | ||
313 | .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, | ||
314 | .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, | ||
315 | .irq_bit = 11, | ||
316 | }, | ||
317 | }; | ||
318 | |||
319 | |||
320 | struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; | ||
321 | struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; | ||
322 | struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02]; | ||
323 | struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03]; | ||
324 | struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04]; | ||
325 | struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05]; | ||
326 | struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06]; | ||
327 | struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07]; | ||
328 | struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; | ||
329 | struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10]; | ||
330 | struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11]; | ||
331 | |||
332 | struct cx25821_dmaqueue mpegq; | ||
333 | |||
334 | static int cx25821_risc_decode(u32 risc) | ||
335 | { | ||
336 | static char *instr[16] = { | ||
337 | [RISC_SYNC >> 28] = "sync", | ||
338 | [RISC_WRITE >> 28] = "write", | ||
339 | [RISC_WRITEC >> 28] = "writec", | ||
340 | [RISC_READ >> 28] = "read", | ||
341 | [RISC_READC >> 28] = "readc", | ||
342 | [RISC_JUMP >> 28] = "jump", | ||
343 | [RISC_SKIP >> 28] = "skip", | ||
344 | [RISC_WRITERM >> 28] = "writerm", | ||
345 | [RISC_WRITECM >> 28] = "writecm", | ||
346 | [RISC_WRITECR >> 28] = "writecr", | ||
347 | }; | ||
348 | static int incr[16] = { | ||
349 | [RISC_WRITE >> 28] = 3, | ||
350 | [RISC_JUMP >> 28] = 3, | ||
351 | [RISC_SKIP >> 28] = 1, | ||
352 | [RISC_SYNC >> 28] = 1, | ||
353 | [RISC_WRITERM >> 28] = 3, | ||
354 | [RISC_WRITECM >> 28] = 3, | ||
355 | [RISC_WRITECR >> 28] = 4, | ||
356 | }; | ||
357 | static char *bits[] = { | ||
358 | "12", "13", "14", "resync", | ||
359 | "cnt0", "cnt1", "18", "19", | ||
360 | "20", "21", "22", "23", | ||
361 | "irq1", "irq2", "eol", "sol", | ||
362 | }; | ||
363 | int i; | ||
364 | |||
365 | printk("0x%08x [ %s", risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); | ||
366 | for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) | ||
367 | { | ||
368 | if (risc & (1 << (i + 12))) | ||
369 | printk(" %s", bits[i]); | ||
370 | } | ||
371 | printk(" count=%d ]\n", risc & 0xfff); | ||
372 | return incr[risc >> 28] ? incr[risc >> 28] : 1; | ||
373 | } | ||
374 | |||
375 | static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) | ||
376 | { | ||
377 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
378 | struct cx25821_dev *dev = bus->dev; | ||
379 | return cx_read(bus->reg_stat) & 0x01; | ||
380 | } | ||
381 | |||
382 | |||
383 | void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char* reg_string) | ||
384 | { | ||
385 | int tmp = 0; | ||
386 | u32 value = 0; | ||
387 | |||
388 | value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); | ||
389 | } | ||
390 | |||
391 | static void cx25821_registers_init(struct cx25821_dev *dev) | ||
392 | { | ||
393 | u32 tmp; | ||
394 | |||
395 | // enable RUN_RISC in Pecos | ||
396 | cx_write( DEV_CNTRL2, 0x20 ); | ||
397 | |||
398 | // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts | ||
399 | // I2C interrupt masking is handled by the I2C objects themselves. | ||
400 | cx_write( PCI_INT_MSK, 0x2001FFFF ); | ||
401 | |||
402 | tmp = cx_read( RDR_TLCTL0 ); | ||
403 | tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit | ||
404 | cx_write( RDR_TLCTL0, tmp); | ||
405 | |||
406 | // PLL-A setting for the Audio Master Clock | ||
407 | cx_write( PLL_A_INT_FRAC, 0x9807A58B ); | ||
408 | |||
409 | // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 | ||
410 | cx_write( PLL_A_POST_STAT_BIST, 0x8000019C); | ||
411 | |||
412 | // clear reset bit [31] | ||
413 | tmp = cx_read( PLL_A_INT_FRAC ); | ||
414 | cx_write( PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); | ||
415 | |||
416 | // PLL-B setting for Mobilygen Host Bus Interface | ||
417 | cx_write( PLL_B_INT_FRAC, 0x9883A86F); | ||
418 | |||
419 | // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 | ||
420 | cx_write( PLL_B_POST_STAT_BIST, 0x8000018D); | ||
421 | |||
422 | // clear reset bit [31] | ||
423 | tmp = cx_read( PLL_B_INT_FRAC ); | ||
424 | cx_write( PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); | ||
425 | |||
426 | // PLL-C setting for video upstream channel | ||
427 | cx_write( PLL_C_INT_FRAC, 0x96A0EA3F); | ||
428 | |||
429 | // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 | ||
430 | cx_write( PLL_C_POST_STAT_BIST, 0x80000103); | ||
431 | |||
432 | // clear reset bit [31] | ||
433 | tmp = cx_read( PLL_C_INT_FRAC ); | ||
434 | cx_write( PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); | ||
435 | |||
436 | // PLL-D setting for audio upstream channel | ||
437 | cx_write( PLL_D_INT_FRAC, 0x98757F5B); | ||
438 | |||
439 | // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 | ||
440 | cx_write( PLL_D_POST_STAT_BIST, 0x80000113); | ||
441 | |||
442 | // clear reset bit [31] | ||
443 | tmp = cx_read( PLL_D_INT_FRAC ); | ||
444 | cx_write( PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); | ||
445 | |||
446 | |||
447 | // This selects the PLL C clock source for the video upstream channel I and J | ||
448 | tmp = cx_read( VID_CH_CLK_SEL ); | ||
449 | cx_write( VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); | ||
450 | |||
451 | |||
452 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
453 | //select 656/VIP DST for downstream Channel A - C | ||
454 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
455 | //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
456 | cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
457 | |||
458 | |||
459 | // enables 656 port I and J as output | ||
460 | tmp = cx_read( CLK_RST ); | ||
461 | tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead | ||
462 | cx_write( CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE) ); | ||
463 | |||
464 | mdelay(100); | ||
465 | } | ||
466 | |||
467 | |||
468 | int cx25821_sram_channel_setup(struct cx25821_dev *dev, | ||
469 | struct sram_channel *ch, | ||
470 | unsigned int bpl, u32 risc) | ||
471 | { | ||
472 | unsigned int i, lines; | ||
473 | u32 cdt; | ||
474 | |||
475 | if (ch->cmds_start == 0) { | ||
476 | cx_write(ch->ptr1_reg, 0); | ||
477 | cx_write(ch->ptr2_reg, 0); | ||
478 | cx_write(ch->cnt2_reg, 0); | ||
479 | cx_write(ch->cnt1_reg, 0); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
484 | cdt = ch->cdt; | ||
485 | lines = ch->fifo_size / bpl; | ||
486 | |||
487 | if (lines > 4) | ||
488 | { | ||
489 | lines = 4; | ||
490 | } | ||
491 | |||
492 | BUG_ON(lines < 2); | ||
493 | |||
494 | cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
495 | cx_write(8 + 4, 8); | ||
496 | cx_write(8 + 8, 0); | ||
497 | |||
498 | /* write CDT */ | ||
499 | for (i = 0; i < lines; i++) { | ||
500 | cx_write(cdt + 16*i, ch->fifo_start + bpl*i); | ||
501 | cx_write(cdt + 16*i + 4, 0); | ||
502 | cx_write(cdt + 16*i + 8, 0); | ||
503 | cx_write(cdt + 16*i + 12, 0); | ||
504 | } | ||
505 | |||
506 | //init the first cdt buffer | ||
507 | for(i=0; i<128; i++) | ||
508 | cx_write(ch->fifo_start+4*i, i); | ||
509 | |||
510 | /* write CMDS */ | ||
511 | if (ch->jumponly) | ||
512 | { | ||
513 | cx_write(ch->cmds_start + 0, 8); | ||
514 | } | ||
515 | else | ||
516 | { | ||
517 | cx_write(ch->cmds_start + 0, risc); | ||
518 | } | ||
519 | |||
520 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | ||
521 | cx_write(ch->cmds_start + 8, cdt); | ||
522 | cx_write(ch->cmds_start + 12, (lines*16) >> 3); | ||
523 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
524 | |||
525 | if (ch->jumponly) | ||
526 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); | ||
527 | else | ||
528 | cx_write(ch->cmds_start + 20, 64 >> 2); | ||
529 | |||
530 | for (i = 24; i < 80; i += 4) | ||
531 | cx_write(ch->cmds_start + i, 0); | ||
532 | |||
533 | /* fill registers */ | ||
534 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
535 | cx_write(ch->ptr2_reg, cdt); | ||
536 | cx_write(ch->cnt2_reg, (lines*16) >> 3); | ||
537 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | ||
543 | struct sram_channel *ch, | ||
544 | unsigned int bpl, u32 risc) | ||
545 | { | ||
546 | unsigned int i, lines; | ||
547 | u32 cdt; | ||
548 | |||
549 | |||
550 | if (ch->cmds_start == 0) { | ||
551 | cx_write(ch->ptr1_reg, 0); | ||
552 | cx_write(ch->ptr2_reg, 0); | ||
553 | cx_write(ch->cnt2_reg, 0); | ||
554 | cx_write(ch->cnt1_reg, 0); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
559 | cdt = ch->cdt; | ||
560 | lines = ch->fifo_size / bpl; | ||
561 | |||
562 | if (lines > 3) | ||
563 | { | ||
564 | lines = 3; //for AUDIO | ||
565 | } | ||
566 | |||
567 | BUG_ON(lines < 2); | ||
568 | |||
569 | |||
570 | cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
571 | cx_write(8 + 4, 8); | ||
572 | cx_write(8 + 8, 0); | ||
573 | |||
574 | /* write CDT */ | ||
575 | for (i = 0; i < lines; i++) { | ||
576 | cx_write(cdt + 16*i, ch->fifo_start + bpl*i); | ||
577 | cx_write(cdt + 16*i + 4, 0); | ||
578 | cx_write(cdt + 16*i + 8, 0); | ||
579 | cx_write(cdt + 16*i + 12, 0); | ||
580 | } | ||
581 | |||
582 | /* write CMDS */ | ||
583 | if (ch->jumponly) | ||
584 | { | ||
585 | cx_write(ch->cmds_start + 0, 8); | ||
586 | } | ||
587 | else | ||
588 | { | ||
589 | cx_write(ch->cmds_start + 0, risc); | ||
590 | } | ||
591 | |||
592 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | ||
593 | cx_write(ch->cmds_start + 8, cdt); | ||
594 | cx_write(ch->cmds_start + 12, (lines*16) >> 3); | ||
595 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
596 | |||
597 | //IQ size | ||
598 | if (ch->jumponly) | ||
599 | { | ||
600 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); | ||
601 | } | ||
602 | else | ||
603 | { | ||
604 | cx_write(ch->cmds_start + 20, 64 >> 2); | ||
605 | } | ||
606 | |||
607 | //zero out | ||
608 | for (i = 24; i < 80; i += 4) | ||
609 | cx_write(ch->cmds_start + i, 0); | ||
610 | |||
611 | /* fill registers */ | ||
612 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
613 | cx_write(ch->ptr2_reg, cdt); | ||
614 | cx_write(ch->cnt2_reg, (lines*16) >> 3); | ||
615 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | |||
621 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | ||
622 | { | ||
623 | static char *name[] = { | ||
624 | "init risc lo", | ||
625 | "init risc hi", | ||
626 | "cdt base", | ||
627 | "cdt size", | ||
628 | "iq base", | ||
629 | "iq size", | ||
630 | "risc pc lo", | ||
631 | "risc pc hi", | ||
632 | "iq wr ptr", | ||
633 | "iq rd ptr", | ||
634 | "cdt current", | ||
635 | "pci target lo", | ||
636 | "pci target hi", | ||
637 | "line / byte", | ||
638 | }; | ||
639 | u32 risc; | ||
640 | unsigned int i, j, n; | ||
641 | |||
642 | printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, ch->name); | ||
643 | for (i = 0; i < ARRAY_SIZE(name); i++) | ||
644 | printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i*4, name[i], | ||
645 | cx_read(ch->cmds_start + 4*i)); | ||
646 | |||
647 | j=i*4; | ||
648 | for (i = 0; i < 4; ) { | ||
649 | risc = cx_read(ch->cmds_start + 4 * (i + 14)); | ||
650 | printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); | ||
651 | i +=cx25821_risc_decode(risc); | ||
652 | } | ||
653 | |||
654 | for (i = 0; i < (64 >> 2); i += n) { | ||
655 | risc = cx_read(ch->ctrl_start + 4 * i); | ||
656 | /* No consideration for bits 63-32 */ | ||
657 | |||
658 | printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); | ||
659 | n = cx25821_risc_decode(risc); | ||
660 | for (j = 1; j < n; j++) { | ||
661 | risc = cx_read(ch->ctrl_start + 4 * (i + j)); | ||
662 | printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); | ||
667 | printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); | ||
668 | printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); | ||
669 | printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); | ||
670 | printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); | ||
671 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); | ||
672 | } | ||
673 | |||
674 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch) | ||
675 | { | ||
676 | static char *name[] = { | ||
677 | "init risc lo", | ||
678 | "init risc hi", | ||
679 | "cdt base", | ||
680 | "cdt size", | ||
681 | "iq base", | ||
682 | "iq size", | ||
683 | "risc pc lo", | ||
684 | "risc pc hi", | ||
685 | "iq wr ptr", | ||
686 | "iq rd ptr", | ||
687 | "cdt current", | ||
688 | "pci target lo", | ||
689 | "pci target hi", | ||
690 | "line / byte", | ||
691 | }; | ||
692 | |||
693 | u32 risc, value, tmp; | ||
694 | unsigned int i, j, n; | ||
695 | |||
696 | |||
697 | printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", dev->name, ch->name); | ||
698 | |||
699 | for (i = 0; i < ARRAY_SIZE(name); i++) | ||
700 | printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i)); | ||
701 | |||
702 | |||
703 | j=i*4; | ||
704 | for (i = 0; i < 4; ) { | ||
705 | risc = cx_read(ch->cmds_start + 4 * (i + 14)); | ||
706 | printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); | ||
707 | i += cx25821_risc_decode(risc); | ||
708 | } | ||
709 | |||
710 | for (i = 0; i < (64 >> 2); i += n) { | ||
711 | risc = cx_read(ch->ctrl_start + 4 * i); | ||
712 | /* No consideration for bits 63-32 */ | ||
713 | |||
714 | printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); | ||
715 | n = cx25821_risc_decode(risc); | ||
716 | |||
717 | for (j = 1; j < n; j++) { | ||
718 | risc = cx_read(ch->ctrl_start + 4 * (i + j)); | ||
719 | printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); | ||
720 | } | ||
721 | } | ||
722 | |||
723 | printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); | ||
724 | printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); | ||
725 | printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); | ||
726 | printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); | ||
727 | printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); | ||
728 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); | ||
729 | |||
730 | for( i=0; i < 4; i++) | ||
731 | { | ||
732 | risc = cx_read(ch->cmds_start + 56 + (i*4)); | ||
733 | printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); | ||
734 | } | ||
735 | |||
736 | //read data from the first cdt buffer | ||
737 | risc = cx_read(AUD_A_CDT); | ||
738 | printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); | ||
739 | for(i=0; i<8; i++) | ||
740 | { | ||
741 | n = cx_read(risc+i*4); | ||
742 | printk(KERN_WARNING "0x%x ", n); | ||
743 | } | ||
744 | printk(KERN_WARNING "\n\n"); | ||
745 | |||
746 | |||
747 | value = cx_read(CLK_RST); | ||
748 | CX25821_INFO(" CLK_RST = 0x%x \n\n", value); | ||
749 | |||
750 | value = cx_read(PLL_A_POST_STAT_BIST); | ||
751 | CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); | ||
752 | value = cx_read(PLL_A_INT_FRAC); | ||
753 | CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); | ||
754 | |||
755 | value = cx_read(PLL_B_POST_STAT_BIST); | ||
756 | CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); | ||
757 | value = cx_read(PLL_B_INT_FRAC); | ||
758 | CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); | ||
759 | |||
760 | value = cx_read(PLL_C_POST_STAT_BIST); | ||
761 | CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); | ||
762 | value = cx_read(PLL_C_INT_FRAC); | ||
763 | CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); | ||
764 | |||
765 | value = cx_read(PLL_D_POST_STAT_BIST); | ||
766 | CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); | ||
767 | value = cx_read(PLL_D_INT_FRAC); | ||
768 | CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); | ||
769 | |||
770 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | ||
771 | CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); | ||
772 | } | ||
773 | |||
774 | static void cx25821_shutdown(struct cx25821_dev *dev) | ||
775 | { | ||
776 | int i; | ||
777 | |||
778 | /* disable RISC controller */ | ||
779 | cx_write(DEV_CNTRL2, 0); | ||
780 | |||
781 | /* Disable Video A/B activity */ | ||
782 | for(i=0; i<VID_CHANNEL_NUM; i++) | ||
783 | { | ||
784 | cx_write(dev->sram_channels[i].dma_ctl, 0); | ||
785 | cx_write(dev->sram_channels[i].int_msk, 0); | ||
786 | } | ||
787 | |||
788 | for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) | ||
789 | { | ||
790 | cx_write(dev->sram_channels[i].dma_ctl, 0); | ||
791 | cx_write(dev->sram_channels[i].int_msk, 0); | ||
792 | } | ||
793 | |||
794 | /* Disable Audio activity */ | ||
795 | cx_write(AUD_INT_DMA_CTL, 0); | ||
796 | |||
797 | /* Disable Serial port */ | ||
798 | cx_write(UART_CTL, 0); | ||
799 | |||
800 | /* Disable Interrupts */ | ||
801 | cx_write(PCI_INT_MSK, 0); | ||
802 | cx_write(AUD_A_INT_MSK, 0); | ||
803 | } | ||
804 | |||
805 | void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) | ||
806 | { | ||
807 | struct sram_channel *ch; | ||
808 | |||
809 | if( channel_select <= 7 && channel_select >= 0 ) | ||
810 | { | ||
811 | ch = &cx25821_sram_channels[channel_select]; | ||
812 | cx_write(ch->pix_frmt, format); | ||
813 | dev->pixel_formats[channel_select] = format; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | static void cx25821_set_vip_mode(struct cx25821_dev *dev, struct sram_channel *ch) | ||
818 | { | ||
819 | cx_write(ch->pix_frmt, PIXEL_FRMT_422); | ||
820 | cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); | ||
821 | } | ||
822 | |||
823 | static void cx25821_initialize(struct cx25821_dev *dev) | ||
824 | { | ||
825 | int i; | ||
826 | |||
827 | dprintk(1, "%s()\n", __func__); | ||
828 | |||
829 | cx25821_shutdown(dev); | ||
830 | cx_write(PCI_INT_STAT, 0xffffffff); | ||
831 | |||
832 | for(i=0; i<VID_CHANNEL_NUM; i++) | ||
833 | cx_write(dev->sram_channels[i].int_stat, 0xffffffff); | ||
834 | |||
835 | |||
836 | cx_write(AUD_A_INT_STAT, 0xffffffff); | ||
837 | cx_write(AUD_B_INT_STAT, 0xffffffff); | ||
838 | cx_write(AUD_C_INT_STAT, 0xffffffff); | ||
839 | cx_write(AUD_D_INT_STAT, 0xffffffff); | ||
840 | cx_write(AUD_E_INT_STAT, 0xffffffff); | ||
841 | |||
842 | cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); | ||
843 | cx_write(PAD_CTRL, 0x12); //for I2C | ||
844 | cx25821_registers_init(dev); //init Pecos registers | ||
845 | mdelay(100); | ||
846 | |||
847 | |||
848 | for(i=0; i<VID_CHANNEL_NUM; i++) | ||
849 | { | ||
850 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); | ||
851 | cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0); | ||
852 | dev->pixel_formats[i] = PIXEL_FRMT_422; | ||
853 | dev->use_cif_resolution[i] = FALSE; | ||
854 | } | ||
855 | |||
856 | //Probably only affect Downstream | ||
857 | for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) | ||
858 | { | ||
859 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); | ||
860 | } | ||
861 | |||
862 | cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0); | ||
863 | |||
864 | cx25821_gpio_init(dev); | ||
865 | } | ||
866 | |||
867 | static int get_resources(struct cx25821_dev *dev) | ||
868 | { | ||
869 | if (request_mem_region(pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), dev->name)) | ||
870 | return 0; | ||
871 | |||
872 | printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", | ||
873 | dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); | ||
874 | |||
875 | return -EBUSY; | ||
876 | } | ||
877 | |||
878 | |||
879 | static void cx25821_dev_checkrevision(struct cx25821_dev *dev) | ||
880 | { | ||
881 | dev->hwrevision = cx_read(RDR_CFG2) & 0xff; | ||
882 | |||
883 | printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, dev->hwrevision); | ||
884 | } | ||
885 | |||
886 | static void cx25821_iounmap(struct cx25821_dev *dev) | ||
887 | { | ||
888 | if (dev == NULL) | ||
889 | return; | ||
890 | |||
891 | /* Releasing IO memory */ | ||
892 | if (dev->lmmio != NULL) | ||
893 | { | ||
894 | CX25821_INFO("Releasing lmmio.\n"); | ||
895 | iounmap(dev->lmmio); | ||
896 | dev->lmmio = NULL; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | |||
901 | static int cx25821_dev_setup(struct cx25821_dev *dev) | ||
902 | { | ||
903 | int io_size = 0, i; | ||
904 | |||
905 | struct video_device *video_template[] = { | ||
906 | &cx25821_video_template0, | ||
907 | &cx25821_video_template1, | ||
908 | &cx25821_video_template2, | ||
909 | &cx25821_video_template3, | ||
910 | &cx25821_video_template4, | ||
911 | &cx25821_video_template5, | ||
912 | &cx25821_video_template6, | ||
913 | &cx25821_video_template7, | ||
914 | &cx25821_video_template9, | ||
915 | &cx25821_video_template10, | ||
916 | &cx25821_video_template11, | ||
917 | &cx25821_videoioctl_template, | ||
918 | }; | ||
919 | |||
920 | printk(KERN_INFO "\n***********************************\n"); | ||
921 | printk(KERN_INFO "cx25821 set up\n"); | ||
922 | printk(KERN_INFO "***********************************\n\n"); | ||
923 | |||
924 | mutex_init(&dev->lock); | ||
925 | |||
926 | atomic_inc(&dev->refcount); | ||
927 | |||
928 | dev->nr = ++cx25821_devcount; | ||
929 | sprintf(dev->name, "cx25821[%d]", dev->nr); | ||
930 | |||
931 | mutex_lock(&devlist); | ||
932 | list_add_tail(&dev->devlist, &cx25821_devlist); | ||
933 | mutex_unlock(&devlist); | ||
934 | |||
935 | strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); | ||
936 | strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); | ||
937 | |||
938 | |||
939 | if( dev->pci->device != 0x8210 ) | ||
940 | { | ||
941 | printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n", | ||
942 | __func__, dev->pci->device); | ||
943 | return -1; | ||
944 | } | ||
945 | else | ||
946 | { | ||
947 | printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device); | ||
948 | } | ||
949 | |||
950 | /* Apply a sensible clock frequency for the PCIe bridge */ | ||
951 | dev->clk_freq = 28000000; | ||
952 | dev->sram_channels = cx25821_sram_channels; | ||
953 | |||
954 | if(dev->nr > 1) | ||
955 | { | ||
956 | CX25821_INFO("dev->nr > 1!"); | ||
957 | } | ||
958 | |||
959 | /* board config */ | ||
960 | dev->board = 1; //card[dev->nr]; | ||
961 | dev->_max_num_decoders = MAX_DECODERS; | ||
962 | |||
963 | |||
964 | dev->pci_bus = dev->pci->bus->number; | ||
965 | dev->pci_slot = PCI_SLOT(dev->pci->devfn); | ||
966 | dev->pci_irqmask = 0x001f00; | ||
967 | |||
968 | /* External Master 1 Bus */ | ||
969 | dev->i2c_bus[0].nr = 0; | ||
970 | dev->i2c_bus[0].dev = dev; | ||
971 | dev->i2c_bus[0].reg_stat = I2C1_STAT; | ||
972 | dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; | ||
973 | dev->i2c_bus[0].reg_addr = I2C1_ADDR; | ||
974 | dev->i2c_bus[0].reg_rdata = I2C1_RDATA; | ||
975 | dev->i2c_bus[0].reg_wdata = I2C1_WDATA; | ||
976 | dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ | ||
977 | |||
978 | |||
979 | |||
980 | if (get_resources(dev) < 0) | ||
981 | { | ||
982 | printk(KERN_ERR "%s No more PCIe resources for " | ||
983 | "subsystem: %04x:%04x\n", | ||
984 | dev->name, dev->pci->subsystem_vendor, | ||
985 | dev->pci->subsystem_device); | ||
986 | |||
987 | cx25821_devcount--; | ||
988 | return -ENODEV; | ||
989 | } | ||
990 | |||
991 | /* PCIe stuff */ | ||
992 | dev->base_io_addr = pci_resource_start(dev->pci, 0); | ||
993 | io_size = pci_resource_len(dev->pci, 0); | ||
994 | |||
995 | if (!dev->base_io_addr) { | ||
996 | CX25821_ERR("No PCI Memory resources, exiting!\n"); | ||
997 | return -ENODEV; | ||
998 | } | ||
999 | |||
1000 | dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | ||
1001 | |||
1002 | if (!dev->lmmio) { | ||
1003 | CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); | ||
1004 | cx25821_iounmap(dev); | ||
1005 | return -ENOMEM; | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | dev->bmmio = (u8 __iomem *)dev->lmmio; | ||
1010 | |||
1011 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | ||
1012 | dev->name, dev->pci->subsystem_vendor, | ||
1013 | dev->pci->subsystem_device, cx25821_boards[dev->board].name, | ||
1014 | dev->board, card[dev->nr] == dev->board ? | ||
1015 | "insmod option" : "autodetected"); | ||
1016 | |||
1017 | /* init hardware */ | ||
1018 | cx25821_initialize(dev); | ||
1019 | |||
1020 | cx25821_i2c_register(&dev->i2c_bus[0]); | ||
1021 | // cx25821_i2c_register(&dev->i2c_bus[1]); | ||
1022 | // cx25821_i2c_register(&dev->i2c_bus[2]); | ||
1023 | |||
1024 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", dev->i2c_bus[0].i2c_rc); | ||
1025 | |||
1026 | cx25821_card_setup(dev); | ||
1027 | medusa_video_init(dev); | ||
1028 | |||
1029 | for(i = 0; i < VID_CHANNEL_NUM; i++) | ||
1030 | { | ||
1031 | if (cx25821_video_register(dev, i, video_template[i]) < 0) { | ||
1032 | printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) | ||
1038 | { | ||
1039 | //Since we don't have template8 for Audio Downstream | ||
1040 | if (cx25821_video_register(dev, i, video_template[i-1]) < 0) { | ||
1041 | printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i); | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | // register IOCTL device | ||
1046 | dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], "video"); | ||
1047 | |||
1048 | if( video_register_device(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0 ) | ||
1049 | { | ||
1050 | cx25821_videoioctl_unregister(dev); | ||
1051 | printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__); | ||
1052 | } | ||
1053 | |||
1054 | cx25821_dev_checkrevision(dev); | ||
1055 | CX25821_INFO("cx25821 setup done!\n"); | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | |||
1061 | void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data) | ||
1062 | { | ||
1063 | dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0; | ||
1064 | |||
1065 | dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1066 | medusa_set_videostandard(dev); | ||
1067 | |||
1068 | cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format); | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data) | ||
1073 | { | ||
1074 | dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0; | ||
1075 | |||
1076 | dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1077 | medusa_set_videostandard(dev); | ||
1078 | |||
1079 | cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2); | ||
1080 | } | ||
1081 | |||
1082 | |||
1083 | void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data) | ||
1084 | { | ||
1085 | cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); | ||
1086 | } | ||
1087 | |||
1088 | void cx25821_dev_unregister(struct cx25821_dev *dev) | ||
1089 | { | ||
1090 | int i; | ||
1091 | |||
1092 | if (!dev->base_io_addr) | ||
1093 | return; | ||
1094 | |||
1095 | cx25821_free_mem_upstream_ch1(dev); | ||
1096 | cx25821_free_mem_upstream_ch2(dev); | ||
1097 | cx25821_free_mem_upstream_audio(dev); | ||
1098 | |||
1099 | release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | ||
1100 | |||
1101 | if (!atomic_dec_and_test(&dev->refcount)) | ||
1102 | return; | ||
1103 | |||
1104 | for(i=0; i < VID_CHANNEL_NUM; i++) | ||
1105 | cx25821_video_unregister(dev, i); | ||
1106 | |||
1107 | |||
1108 | for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) | ||
1109 | { | ||
1110 | cx25821_video_unregister(dev, i); | ||
1111 | } | ||
1112 | |||
1113 | cx25821_videoioctl_unregister(dev); | ||
1114 | |||
1115 | cx25821_i2c_unregister( &dev->i2c_bus[0] ); | ||
1116 | cx25821_iounmap(dev); | ||
1117 | } | ||
1118 | |||
1119 | |||
1120 | |||
1121 | static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist, | ||
1122 | unsigned int offset, u32 sync_line, | ||
1123 | unsigned int bpl, unsigned int padding, | ||
1124 | unsigned int lines) | ||
1125 | { | ||
1126 | struct scatterlist *sg; | ||
1127 | unsigned int line, todo; | ||
1128 | |||
1129 | /* sync instruction */ | ||
1130 | if (sync_line != NO_SYNC_LINE) | ||
1131 | { | ||
1132 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
1133 | } | ||
1134 | |||
1135 | /* scan lines */ | ||
1136 | sg = sglist; | ||
1137 | for (line = 0; line < lines; line++) { | ||
1138 | while (offset && offset >= sg_dma_len(sg)) { | ||
1139 | offset -= sg_dma_len(sg); | ||
1140 | sg++; | ||
1141 | } | ||
1142 | if (bpl <= sg_dma_len(sg)-offset) { | ||
1143 | /* fits into current chunk */ | ||
1144 | *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); | ||
1145 | *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); | ||
1146 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1147 | offset += bpl; | ||
1148 | } else { | ||
1149 | /* scanline needs to be split */ | ||
1150 | todo = bpl; | ||
1151 | *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); | ||
1152 | *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); | ||
1153 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1154 | todo -= (sg_dma_len(sg)-offset); | ||
1155 | offset = 0; | ||
1156 | sg++; | ||
1157 | while (todo > sg_dma_len(sg)) { | ||
1158 | *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg)); | ||
1159 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1160 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1161 | todo -= sg_dma_len(sg); | ||
1162 | sg++; | ||
1163 | } | ||
1164 | *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); | ||
1165 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1166 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1167 | offset += todo; | ||
1168 | } | ||
1169 | |||
1170 | offset += padding; | ||
1171 | } | ||
1172 | |||
1173 | return rp; | ||
1174 | } | ||
1175 | |||
1176 | int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
1177 | struct scatterlist *sglist, unsigned int top_offset, | ||
1178 | unsigned int bottom_offset, unsigned int bpl, | ||
1179 | unsigned int padding, unsigned int lines) | ||
1180 | { | ||
1181 | u32 instructions; | ||
1182 | u32 fields; | ||
1183 | __le32 *rp; | ||
1184 | int rc; | ||
1185 | |||
1186 | fields = 0; | ||
1187 | if (UNSET != top_offset) | ||
1188 | fields++; | ||
1189 | if (UNSET != bottom_offset) | ||
1190 | fields++; | ||
1191 | |||
1192 | /* estimate risc mem: worst case is one write per page border + | ||
1193 | one write per scan line + syncs + jump (all 2 dwords). Padding | ||
1194 | can cause next bpl to start close to a page border. First DMA | ||
1195 | region may be smaller than PAGE_SIZE */ | ||
1196 | /* write and jump need and extra dword */ | ||
1197 | instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | ||
1198 | instructions += 2; | ||
1199 | rc = btcx_riscmem_alloc(pci, risc, instructions*12); | ||
1200 | |||
1201 | if (rc < 0) | ||
1202 | return rc; | ||
1203 | |||
1204 | /* write risc instructions */ | ||
1205 | rp = risc->cpu; | ||
1206 | |||
1207 | if (UNSET != top_offset) | ||
1208 | { | ||
1209 | rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines); | ||
1210 | } | ||
1211 | |||
1212 | if (UNSET != bottom_offset) | ||
1213 | { | ||
1214 | rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines); | ||
1215 | } | ||
1216 | |||
1217 | /* save pointer to jmp instruction address */ | ||
1218 | risc->jmp = rp; | ||
1219 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); | ||
1220 | |||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | static __le32* cx25821_risc_field_audio(__le32 *rp, struct scatterlist *sglist, | ||
1226 | unsigned int offset, u32 sync_line, | ||
1227 | unsigned int bpl, unsigned int padding, | ||
1228 | unsigned int lines, unsigned int lpi) | ||
1229 | { | ||
1230 | struct scatterlist *sg; | ||
1231 | unsigned int line, todo, sol; | ||
1232 | |||
1233 | /* sync instruction */ | ||
1234 | if (sync_line != NO_SYNC_LINE) | ||
1235 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
1236 | |||
1237 | /* scan lines */ | ||
1238 | sg = sglist; | ||
1239 | for (line = 0; line < lines; line++) { | ||
1240 | while (offset && offset >= sg_dma_len(sg)) { | ||
1241 | offset -= sg_dma_len(sg); | ||
1242 | sg++; | ||
1243 | } | ||
1244 | |||
1245 | if (lpi && line > 0 && !(line % lpi)) | ||
1246 | sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; | ||
1247 | else | ||
1248 | sol = RISC_SOL; | ||
1249 | |||
1250 | if (bpl <= sg_dma_len(sg)-offset) { | ||
1251 | /* fits into current chunk */ | ||
1252 | *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); | ||
1253 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | ||
1254 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
1255 | offset+=bpl; | ||
1256 | } else { | ||
1257 | /* scanline needs to be split */ | ||
1258 | todo = bpl; | ||
1259 | *(rp++) = cpu_to_le32(RISC_WRITE|sol| | ||
1260 | (sg_dma_len(sg)-offset)); | ||
1261 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | ||
1262 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
1263 | todo -= (sg_dma_len(sg)-offset); | ||
1264 | offset = 0; | ||
1265 | sg++; | ||
1266 | while (todo > sg_dma_len(sg)) { | ||
1267 | *(rp++)=cpu_to_le32(RISC_WRITE| | ||
1268 | sg_dma_len(sg)); | ||
1269 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | ||
1270 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
1271 | todo -= sg_dma_len(sg); | ||
1272 | sg++; | ||
1273 | } | ||
1274 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); | ||
1275 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | ||
1276 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
1277 | offset += todo; | ||
1278 | } | ||
1279 | offset += padding; | ||
1280 | } | ||
1281 | |||
1282 | return rp; | ||
1283 | } | ||
1284 | |||
1285 | int cx25821_risc_databuffer_audio(struct pci_dev *pci, | ||
1286 | struct btcx_riscmem *risc, | ||
1287 | struct scatterlist *sglist, | ||
1288 | unsigned int bpl, | ||
1289 | unsigned int lines, | ||
1290 | unsigned int lpi) | ||
1291 | { | ||
1292 | u32 instructions; | ||
1293 | __le32 *rp; | ||
1294 | int rc; | ||
1295 | |||
1296 | /* estimate risc mem: worst case is one write per page border + | ||
1297 | one write per scan line + syncs + jump (all 2 dwords). Here | ||
1298 | there is no padding and no sync. First DMA region may be smaller | ||
1299 | than PAGE_SIZE */ | ||
1300 | /* Jump and write need an extra dword */ | ||
1301 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; | ||
1302 | instructions += 1; | ||
1303 | |||
1304 | if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) | ||
1305 | return rc; | ||
1306 | |||
1307 | |||
1308 | /* write risc instructions */ | ||
1309 | rp = risc->cpu; | ||
1310 | rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); | ||
1311 | |||
1312 | /* save pointer to jmp instruction address */ | ||
1313 | risc->jmp = rp; | ||
1314 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); | ||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | |||
1319 | int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value) | ||
1320 | { | ||
1321 | __le32 *rp; | ||
1322 | int rc; | ||
1323 | |||
1324 | rc = btcx_riscmem_alloc(pci, risc, 4*16); | ||
1325 | |||
1326 | if (rc < 0) | ||
1327 | return rc; | ||
1328 | |||
1329 | /* write risc instructions */ | ||
1330 | rp = risc->cpu; | ||
1331 | |||
1332 | *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); | ||
1333 | *(rp++) = cpu_to_le32(reg); | ||
1334 | *(rp++) = cpu_to_le32(value); | ||
1335 | *(rp++) = cpu_to_le32(mask); | ||
1336 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
1337 | *(rp++) = cpu_to_le32(risc->dma); | ||
1338 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) | ||
1343 | { | ||
1344 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | ||
1345 | |||
1346 | BUG_ON(in_interrupt()); | ||
1347 | videobuf_waiton(&buf->vb, 0, 0); | ||
1348 | videobuf_dma_unmap(q, dma); | ||
1349 | videobuf_dma_free(dma); | ||
1350 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); | ||
1351 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | static irqreturn_t cx25821_irq(int irq, void *dev_id) | ||
1356 | { | ||
1357 | struct cx25821_dev *dev = dev_id; | ||
1358 | u32 pci_status, pci_mask; | ||
1359 | u32 vid_status; | ||
1360 | int i, handled = 0; | ||
1361 | u32 mask[8] = {1, 2, 4, 8, 16, 32, 64, 128}; | ||
1362 | |||
1363 | pci_status = cx_read(PCI_INT_STAT); | ||
1364 | pci_mask = cx_read(PCI_INT_MSK); | ||
1365 | |||
1366 | |||
1367 | if (pci_status == 0) | ||
1368 | goto out; | ||
1369 | |||
1370 | for(i = 0; i < VID_CHANNEL_NUM; i++) | ||
1371 | { | ||
1372 | if(pci_status & mask[i]) | ||
1373 | { | ||
1374 | vid_status = cx_read(dev->sram_channels[i].int_stat); | ||
1375 | |||
1376 | if(vid_status) | ||
1377 | handled += cx25821_video_irq(dev, i, vid_status); | ||
1378 | |||
1379 | cx_write(PCI_INT_STAT, mask[i]); | ||
1380 | } | ||
1381 | } | ||
1382 | |||
1383 | out: | ||
1384 | return IRQ_RETVAL(handled); | ||
1385 | } | ||
1386 | |||
1387 | void cx25821_print_irqbits(char *name, char *tag, char **strings, | ||
1388 | int len, u32 bits, u32 mask) | ||
1389 | { | ||
1390 | unsigned int i; | ||
1391 | |||
1392 | printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); | ||
1393 | |||
1394 | for (i = 0; i < len; i++) { | ||
1395 | if (!(bits & (1 << i))) | ||
1396 | continue; | ||
1397 | if (strings[i]) | ||
1398 | printk(" %s", strings[i]); | ||
1399 | else | ||
1400 | printk(" %d", i); | ||
1401 | if (!(mask & (1 << i))) | ||
1402 | continue; | ||
1403 | printk("*"); | ||
1404 | } | ||
1405 | printk("\n"); | ||
1406 | } | ||
1407 | |||
1408 | struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci) | ||
1409 | { | ||
1410 | struct cx25821_dev *dev = pci_get_drvdata(pci); | ||
1411 | return dev; | ||
1412 | } | ||
1413 | |||
1414 | static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) | ||
1415 | { | ||
1416 | struct cx25821_dev *dev; | ||
1417 | int err = 0; | ||
1418 | |||
1419 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1420 | if (NULL == dev) | ||
1421 | return -ENOMEM; | ||
1422 | |||
1423 | |||
1424 | err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); | ||
1425 | if (err < 0) | ||
1426 | goto fail_free; | ||
1427 | |||
1428 | /* pci init */ | ||
1429 | dev->pci = pci_dev; | ||
1430 | if (pci_enable_device(pci_dev)) | ||
1431 | { | ||
1432 | err = -EIO; | ||
1433 | |||
1434 | printk(KERN_INFO "pci enable failed! "); | ||
1435 | |||
1436 | goto fail_unregister_device; | ||
1437 | } | ||
1438 | |||
1439 | printk(KERN_INFO "cx25821 Athena pci enable ! \n"); | ||
1440 | |||
1441 | if (cx25821_dev_setup(dev) < 0) | ||
1442 | { | ||
1443 | err = -EINVAL; | ||
1444 | goto fail_unregister_device; | ||
1445 | } | ||
1446 | |||
1447 | /* print pci info */ | ||
1448 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | ||
1449 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | ||
1450 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | ||
1451 | "latency: %d, mmio: 0x%llx\n", dev->name, | ||
1452 | pci_name(pci_dev), dev->pci_rev, pci_dev->irq, | ||
1453 | dev->pci_lat, | ||
1454 | (unsigned long long)dev->base_io_addr ); | ||
1455 | |||
1456 | |||
1457 | pci_set_master(pci_dev); | ||
1458 | if (!pci_dma_supported(pci_dev, 0xffffffff)) | ||
1459 | { | ||
1460 | printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); | ||
1461 | err = -EIO; | ||
1462 | goto fail_irq; | ||
1463 | } | ||
1464 | |||
1465 | err = request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
1466 | |||
1467 | if (err < 0) | ||
1468 | { | ||
1469 | printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); | ||
1470 | goto fail_irq; | ||
1471 | } | ||
1472 | |||
1473 | return 0; | ||
1474 | |||
1475 | fail_irq: | ||
1476 | printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); | ||
1477 | cx25821_dev_unregister(dev); | ||
1478 | |||
1479 | fail_unregister_device: | ||
1480 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1481 | |||
1482 | fail_free: | ||
1483 | kfree(dev); | ||
1484 | return err; | ||
1485 | } | ||
1486 | |||
1487 | static void __devexit cx25821_finidev(struct pci_dev *pci_dev) | ||
1488 | { | ||
1489 | struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); | ||
1490 | struct cx25821_dev *dev = get_cx25821(v4l2_dev); | ||
1491 | |||
1492 | cx25821_shutdown(dev); | ||
1493 | pci_disable_device(pci_dev); | ||
1494 | |||
1495 | /* unregister stuff */ | ||
1496 | if( pci_dev->irq ) | ||
1497 | free_irq(pci_dev->irq, dev); | ||
1498 | |||
1499 | |||
1500 | mutex_lock(&devlist); | ||
1501 | list_del(&dev->devlist); | ||
1502 | mutex_unlock(&devlist); | ||
1503 | |||
1504 | cx25821_dev_unregister(dev); | ||
1505 | v4l2_device_unregister(v4l2_dev); | ||
1506 | kfree(dev); | ||
1507 | } | ||
1508 | |||
1509 | static struct pci_device_id cx25821_pci_tbl[] = { | ||
1510 | { | ||
1511 | /* CX25821 Athena*/ | ||
1512 | .vendor = 0x14f1, | ||
1513 | .device = 0x8210, | ||
1514 | .subvendor = 0x14f1, | ||
1515 | .subdevice = 0x0920, | ||
1516 | }, | ||
1517 | { | ||
1518 | /* --- end of list --- */ | ||
1519 | } | ||
1520 | }; | ||
1521 | |||
1522 | MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl); | ||
1523 | |||
1524 | static struct pci_driver cx25821_pci_driver = | ||
1525 | { | ||
1526 | .name = "cx25821", | ||
1527 | .id_table = cx25821_pci_tbl, | ||
1528 | .probe = cx25821_initdev, | ||
1529 | .remove = __devexit_p(cx25821_finidev), | ||
1530 | /* TODO */ | ||
1531 | .suspend = NULL, | ||
1532 | .resume = NULL, | ||
1533 | }; | ||
1534 | |||
1535 | static int cx25821_init(void) | ||
1536 | { | ||
1537 | INIT_LIST_HEAD(&cx25821_devlist); | ||
1538 | printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", | ||
1539 | (CX25821_VERSION_CODE >> 16) & 0xff, | ||
1540 | (CX25821_VERSION_CODE >> 8) & 0xff, | ||
1541 | CX25821_VERSION_CODE & 0xff); | ||
1542 | return pci_register_driver(&cx25821_pci_driver); | ||
1543 | } | ||
1544 | |||
1545 | static void cx25821_fini(void) | ||
1546 | { | ||
1547 | pci_unregister_driver(&cx25821_pci_driver); | ||
1548 | } | ||
1549 | |||
1550 | |||
1551 | EXPORT_SYMBOL(cx25821_devlist); | ||
1552 | EXPORT_SYMBOL(cx25821_sram_channels); | ||
1553 | EXPORT_SYMBOL(cx25821_print_irqbits); | ||
1554 | EXPORT_SYMBOL(cx25821_dev_get); | ||
1555 | EXPORT_SYMBOL(cx25821_dev_unregister); | ||
1556 | EXPORT_SYMBOL(cx25821_sram_channel_setup); | ||
1557 | EXPORT_SYMBOL(cx25821_sram_channel_dump); | ||
1558 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); | ||
1559 | EXPORT_SYMBOL(cx25821_sram_channel_dump_audio); | ||
1560 | EXPORT_SYMBOL(cx25821_risc_databuffer_audio); | ||
1561 | EXPORT_SYMBOL(cx25821_set_gpiopin_direction); | ||
1562 | |||
1563 | module_init(cx25821_init); | ||
1564 | module_exit(cx25821_fini); | ||
1565 | |||
diff --git a/drivers/staging/cx25821/cx25821-gpio.c b/drivers/staging/cx25821/cx25821-gpio.c new file mode 100644 index 00000000000..aa029fe3438 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-gpio.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include "cx25821.h" | ||
24 | |||
25 | |||
26 | /********************* GPIO stuffs *********************/ | ||
27 | void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, | ||
28 | int pin_number, | ||
29 | int pin_logic_value) | ||
30 | { | ||
31 | int bit = pin_number; | ||
32 | u32 gpio_oe_reg = GPIO_LO_OE; | ||
33 | u32 gpio_register = 0; | ||
34 | u32 value = 0; | ||
35 | |||
36 | // Check for valid pinNumber | ||
37 | if ( pin_number >= 47 ) | ||
38 | return; | ||
39 | |||
40 | |||
41 | if ( pin_number > 31 ) | ||
42 | { | ||
43 | bit = pin_number - 31; | ||
44 | gpio_oe_reg = GPIO_HI_OE; | ||
45 | } | ||
46 | |||
47 | // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is | ||
48 | gpio_register = cx_read( gpio_oe_reg ); | ||
49 | |||
50 | if (pin_logic_value == 1) | ||
51 | { | ||
52 | value = gpio_register | Set_GPIO_Bit(bit) ; | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | value = gpio_register & Clear_GPIO_Bit(bit) ; | ||
57 | } | ||
58 | |||
59 | cx_write( gpio_oe_reg, value ); | ||
60 | } | ||
61 | |||
62 | static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev, | ||
63 | int pin_number, | ||
64 | int pin_logic_value) | ||
65 | { | ||
66 | int bit = pin_number; | ||
67 | u32 gpio_reg = GPIO_LO; | ||
68 | u32 value = 0; | ||
69 | |||
70 | |||
71 | // Check for valid pinNumber | ||
72 | if (pin_number >= 47) | ||
73 | return; | ||
74 | |||
75 | cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction | ||
76 | |||
77 | |||
78 | if ( pin_number > 31 ) | ||
79 | { | ||
80 | bit = pin_number - 31; | ||
81 | gpio_reg = GPIO_HI; | ||
82 | } | ||
83 | |||
84 | value = cx_read( gpio_reg ); | ||
85 | |||
86 | |||
87 | if (pin_logic_value == 0) | ||
88 | { | ||
89 | value &= Clear_GPIO_Bit(bit); | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | value |= Set_GPIO_Bit(bit); | ||
94 | } | ||
95 | |||
96 | cx_write( gpio_reg, value); | ||
97 | } | ||
98 | |||
99 | void cx25821_gpio_init(struct cx25821_dev *dev) | ||
100 | { | ||
101 | if( dev == NULL ) | ||
102 | { | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | switch (dev->board) | ||
107 | { | ||
108 | case CX25821_BOARD_CONEXANT_ATHENA10: | ||
109 | default: | ||
110 | //set GPIO 5 to select the path for Medusa/Athena | ||
111 | cx25821_set_gpiopin_logicvalue(dev, 5, 1); | ||
112 | mdelay(20); | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-gpio.h b/drivers/staging/cx25821/cx25821-gpio.h new file mode 100644 index 00000000000..2dd938dbdc4 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-gpio.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | void cx25821_gpio_init(struct athena_dev *dev); | ||
3 | |||
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c new file mode 100644 index 00000000000..16303f80d4f --- /dev/null +++ b/drivers/staging/cx25821/cx25821-i2c.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821.h" | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | |||
28 | static unsigned int i2c_debug; | ||
29 | module_param(i2c_debug, int, 0644); | ||
30 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
31 | |||
32 | static unsigned int i2c_scan=0; | ||
33 | module_param(i2c_scan, int, 0444); | ||
34 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | ||
35 | |||
36 | #define dprintk(level, fmt, arg...)\ | ||
37 | do { if (i2c_debug >= level)\ | ||
38 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ | ||
39 | } while (0) | ||
40 | |||
41 | #define I2C_WAIT_DELAY 32 | ||
42 | #define I2C_WAIT_RETRY 64 | ||
43 | |||
44 | #define I2C_EXTEND (1 << 3) | ||
45 | #define I2C_NOSTOP (1 << 4) | ||
46 | |||
47 | |||
48 | static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) | ||
49 | { | ||
50 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
51 | struct cx25821_dev *dev = bus->dev; | ||
52 | return cx_read(bus->reg_stat) & 0x01; | ||
53 | } | ||
54 | |||
55 | static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) | ||
56 | { | ||
57 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
58 | struct cx25821_dev *dev = bus->dev; | ||
59 | return cx_read(bus->reg_stat) & 0x02 ? 1 : 0; | ||
60 | } | ||
61 | |||
62 | static int i2c_wait_done(struct i2c_adapter *i2c_adap) | ||
63 | { | ||
64 | int count; | ||
65 | |||
66 | for (count = 0; count < I2C_WAIT_RETRY; count++) { | ||
67 | if (!i2c_is_busy(i2c_adap)) | ||
68 | break; | ||
69 | udelay(I2C_WAIT_DELAY); | ||
70 | } | ||
71 | |||
72 | if (I2C_WAIT_RETRY == count) | ||
73 | return 0; | ||
74 | |||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined_rlen) | ||
79 | { | ||
80 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
81 | struct cx25821_dev *dev = bus->dev; | ||
82 | u32 wdata, addr, ctrl; | ||
83 | int retval, cnt; | ||
84 | |||
85 | if (joined_rlen) | ||
86 | dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, msg->len, joined_rlen); | ||
87 | else | ||
88 | dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); | ||
89 | |||
90 | /* Deal with i2c probe functions with zero payload */ | ||
91 | if (msg->len == 0) | ||
92 | { | ||
93 | cx_write(bus->reg_addr, msg->addr << 25); | ||
94 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); | ||
95 | |||
96 | if (!i2c_wait_done(i2c_adap)) | ||
97 | return -EIO; | ||
98 | |||
99 | if (!i2c_slave_did_ack(i2c_adap)) | ||
100 | return -EIO; | ||
101 | |||
102 | dprintk(1, "%s() returns 0\n", __func__); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | /* dev, reg + first byte */ | ||
107 | addr = (msg->addr << 25) | msg->buf[0]; | ||
108 | wdata = msg->buf[0]; | ||
109 | |||
110 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
111 | |||
112 | if (msg->len > 1) | ||
113 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
114 | else if (joined_rlen) | ||
115 | ctrl |= I2C_NOSTOP; | ||
116 | |||
117 | cx_write(bus->reg_addr, addr); | ||
118 | cx_write(bus->reg_wdata, wdata); | ||
119 | cx_write(bus->reg_ctrl, ctrl); | ||
120 | |||
121 | retval = i2c_wait_done(i2c_adap); | ||
122 | if (retval < 0) | ||
123 | goto err; | ||
124 | |||
125 | if (retval == 0) | ||
126 | goto eio; | ||
127 | |||
128 | if (i2c_debug) | ||
129 | { | ||
130 | if (!(ctrl & I2C_NOSTOP)) | ||
131 | printk(" >\n"); | ||
132 | } | ||
133 | |||
134 | for (cnt = 1; cnt < msg->len; cnt++) { | ||
135 | /* following bytes */ | ||
136 | wdata = msg->buf[cnt]; | ||
137 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
138 | |||
139 | if (cnt < msg->len - 1) | ||
140 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
141 | else if (joined_rlen) | ||
142 | ctrl |= I2C_NOSTOP; | ||
143 | |||
144 | cx_write(bus->reg_addr, addr); | ||
145 | cx_write(bus->reg_wdata, wdata); | ||
146 | cx_write(bus->reg_ctrl, ctrl); | ||
147 | |||
148 | retval = i2c_wait_done(i2c_adap); | ||
149 | if (retval < 0) | ||
150 | goto err; | ||
151 | |||
152 | if (retval == 0) | ||
153 | goto eio; | ||
154 | |||
155 | if (i2c_debug) | ||
156 | { | ||
157 | dprintk(1, " %02x", msg->buf[cnt]); | ||
158 | if (!(ctrl & I2C_NOSTOP)) | ||
159 | dprintk(1, " >\n"); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return msg->len; | ||
164 | |||
165 | eio: | ||
166 | retval = -EIO; | ||
167 | err: | ||
168 | if (i2c_debug) | ||
169 | printk(KERN_ERR " ERR: %d\n", retval); | ||
170 | return retval; | ||
171 | } | ||
172 | |||
173 | static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined) | ||
174 | { | ||
175 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
176 | struct cx25821_dev *dev = bus->dev; | ||
177 | u32 ctrl, cnt; | ||
178 | int retval; | ||
179 | |||
180 | |||
181 | if (i2c_debug && !joined) | ||
182 | dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len); | ||
183 | |||
184 | /* Deal with i2c probe functions with zero payload */ | ||
185 | if (msg->len == 0) { | ||
186 | cx_write(bus->reg_addr, msg->addr << 25); | ||
187 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1); | ||
188 | if (!i2c_wait_done(i2c_adap)) | ||
189 | return -EIO; | ||
190 | if (!i2c_slave_did_ack(i2c_adap)) | ||
191 | return -EIO; | ||
192 | |||
193 | |||
194 | dprintk(1, "%s() returns 0\n", __func__); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | if (i2c_debug) { | ||
199 | if (joined) | ||
200 | dprintk(1, " R"); | ||
201 | else | ||
202 | dprintk(1, " <R %02x", (msg->addr << 1) + 1); | ||
203 | } | ||
204 | |||
205 | for (cnt = 0; cnt < msg->len; cnt++) { | ||
206 | |||
207 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1; | ||
208 | |||
209 | if (cnt < msg->len - 1) | ||
210 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
211 | |||
212 | |||
213 | cx_write(bus->reg_addr, msg->addr << 25); | ||
214 | cx_write(bus->reg_ctrl, ctrl); | ||
215 | |||
216 | retval = i2c_wait_done(i2c_adap); | ||
217 | if (retval < 0) | ||
218 | goto err; | ||
219 | if (retval == 0) | ||
220 | goto eio; | ||
221 | msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; | ||
222 | |||
223 | if (i2c_debug) { | ||
224 | dprintk(1, " %02x", msg->buf[cnt]); | ||
225 | if (!(ctrl & I2C_NOSTOP)) | ||
226 | dprintk(1, " >\n"); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | return msg->len; | ||
231 | eio: | ||
232 | retval = -EIO; | ||
233 | err: | ||
234 | if (i2c_debug) | ||
235 | printk(KERN_ERR " ERR: %d\n", retval); | ||
236 | return retval; | ||
237 | } | ||
238 | |||
239 | static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | ||
240 | { | ||
241 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
242 | struct cx25821_dev *dev = bus->dev; | ||
243 | int i, retval = 0; | ||
244 | |||
245 | dprintk(1, "%s(num = %d)\n", __func__, num); | ||
246 | |||
247 | for (i = 0 ; i < num; i++) | ||
248 | { | ||
249 | dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", | ||
250 | __func__, num, msgs[i].addr, msgs[i].len); | ||
251 | |||
252 | if (msgs[i].flags & I2C_M_RD) | ||
253 | { | ||
254 | /* read */ | ||
255 | retval = i2c_readbytes(i2c_adap, &msgs[i], 0); | ||
256 | } | ||
257 | else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | ||
258 | msgs[i].addr == msgs[i + 1].addr) | ||
259 | { | ||
260 | /* write then read from same address */ | ||
261 | retval = i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); | ||
262 | |||
263 | if (retval < 0) | ||
264 | goto err; | ||
265 | i++; | ||
266 | retval = i2c_readbytes(i2c_adap, &msgs[i], 1); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | /* write */ | ||
271 | retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); | ||
272 | } | ||
273 | |||
274 | if (retval < 0) | ||
275 | goto err; | ||
276 | } | ||
277 | return num; | ||
278 | |||
279 | err: | ||
280 | return retval; | ||
281 | } | ||
282 | |||
283 | |||
284 | static u32 cx25821_functionality(struct i2c_adapter *adap) | ||
285 | { | ||
286 | return I2C_FUNC_SMBUS_EMUL | | ||
287 | I2C_FUNC_I2C | | ||
288 | I2C_FUNC_SMBUS_WORD_DATA | | ||
289 | I2C_FUNC_SMBUS_READ_WORD_DATA | | ||
290 | I2C_FUNC_SMBUS_WRITE_WORD_DATA; | ||
291 | } | ||
292 | |||
293 | static struct i2c_algorithm cx25821_i2c_algo_template = { | ||
294 | .master_xfer = i2c_xfer, | ||
295 | .functionality = cx25821_functionality, | ||
296 | }; | ||
297 | |||
298 | |||
299 | static struct i2c_adapter cx25821_i2c_adap_template = { | ||
300 | .name = "cx25821", | ||
301 | .owner = THIS_MODULE, | ||
302 | .id = I2C_HW_B_CX25821, | ||
303 | .algo = &cx25821_i2c_algo_template, | ||
304 | }; | ||
305 | |||
306 | static struct i2c_client cx25821_i2c_client_template = { | ||
307 | .name = "cx25821 internal", | ||
308 | }; | ||
309 | |||
310 | /* init + register i2c algo-bit adapter */ | ||
311 | int cx25821_i2c_register(struct cx25821_i2c *bus) | ||
312 | { | ||
313 | struct cx25821_dev *dev = bus->dev; | ||
314 | |||
315 | dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); | ||
316 | |||
317 | memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template, | ||
318 | sizeof(bus->i2c_adap)); | ||
319 | memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template, | ||
320 | sizeof(bus->i2c_algo)); | ||
321 | memcpy(&bus->i2c_client, &cx25821_i2c_client_template, | ||
322 | sizeof(bus->i2c_client)); | ||
323 | |||
324 | bus->i2c_adap.dev.parent = &dev->pci->dev; | ||
325 | |||
326 | strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); | ||
327 | |||
328 | bus->i2c_algo.data = bus; | ||
329 | bus->i2c_adap.algo_data = bus; | ||
330 | i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); | ||
331 | i2c_add_adapter(&bus->i2c_adap); | ||
332 | |||
333 | bus->i2c_client.adapter = &bus->i2c_adap; | ||
334 | |||
335 | //set up the I2c | ||
336 | bus->i2c_client.addr = (0x88>>1); | ||
337 | |||
338 | return bus->i2c_rc; | ||
339 | } | ||
340 | |||
341 | int cx25821_i2c_unregister(struct cx25821_i2c *bus) | ||
342 | { | ||
343 | i2c_del_adapter(&bus->i2c_adap); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | void cx25821_av_clk(struct cx25821_dev *dev, int enable) | ||
348 | { | ||
349 | /* write 0 to bus 2 addr 0x144 via i2x_xfer() */ | ||
350 | char buffer[3]; | ||
351 | struct i2c_msg msg; | ||
352 | dprintk(1, "%s(enabled = %d)\n", __func__, enable); | ||
353 | |||
354 | /* Register 0x144 */ | ||
355 | buffer[0] = 0x01; | ||
356 | buffer[1] = 0x44; | ||
357 | if (enable == 1) | ||
358 | buffer[2] = 0x05; | ||
359 | else | ||
360 | buffer[2] = 0x00; | ||
361 | |||
362 | msg.addr = 0x44; | ||
363 | msg.flags = I2C_M_TEN; | ||
364 | msg.len = 3; | ||
365 | msg.buf = buffer; | ||
366 | |||
367 | i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1); | ||
368 | } | ||
369 | |||
370 | |||
371 | int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) | ||
372 | { | ||
373 | struct i2c_client *client = &bus->i2c_client; | ||
374 | int retval = 0; | ||
375 | int v = 0; | ||
376 | u8 addr[2] = {0, 0}; | ||
377 | u8 buf[4] = {0,0,0,0}; | ||
378 | |||
379 | struct i2c_msg msgs[2]={ | ||
380 | { | ||
381 | .addr = client->addr, | ||
382 | .flags = 0, | ||
383 | .len = 2, | ||
384 | .buf = addr, | ||
385 | }, { | ||
386 | .addr = client->addr, | ||
387 | .flags = I2C_M_RD, | ||
388 | .len = 4, | ||
389 | .buf = buf, | ||
390 | } | ||
391 | }; | ||
392 | |||
393 | |||
394 | addr[0] = (reg_addr>>8); | ||
395 | addr[1] = (reg_addr & 0xff); | ||
396 | msgs[0].addr = 0x44; | ||
397 | msgs[1].addr = 0x44; | ||
398 | |||
399 | retval = i2c_xfer(client->adapter, msgs, 2); | ||
400 | |||
401 | v = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0]; | ||
402 | *value = v; | ||
403 | |||
404 | return v; | ||
405 | } | ||
406 | |||
407 | |||
408 | int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value) | ||
409 | { | ||
410 | struct i2c_client *client = &bus->i2c_client; | ||
411 | int retval = 0; | ||
412 | u8 buf[6] = {0, 0, 0, 0, 0, 0}; | ||
413 | |||
414 | struct i2c_msg msgs[1]={ | ||
415 | { | ||
416 | .addr = client->addr, | ||
417 | .flags = 0, | ||
418 | .len = 6, | ||
419 | .buf = buf, | ||
420 | } | ||
421 | }; | ||
422 | |||
423 | |||
424 | buf[0] = reg_addr>>8; | ||
425 | buf[1] = reg_addr & 0xff; | ||
426 | buf[5] = (value>>24) & 0xff; | ||
427 | buf[4] = (value>>16) & 0xff; | ||
428 | buf[3] = (value>>8) & 0xff; | ||
429 | buf[2] = value & 0xff; | ||
430 | client->flags = 0; | ||
431 | msgs[0].addr = 0x44; | ||
432 | |||
433 | retval = i2c_xfer(client->adapter, msgs, 1); | ||
434 | |||
435 | return retval; | ||
436 | } | ||
437 | |||
diff --git a/drivers/staging/cx25821/cx25821-medusa-defines.h b/drivers/staging/cx25821/cx25821-medusa-defines.h new file mode 100644 index 00000000000..75161e488e1 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-defines.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef _MEDUSA_DEF_H_ | ||
24 | #define _MEDUSA_DEF_H_ | ||
25 | |||
26 | // Video deocder that we supported | ||
27 | #define VDEC_A 0 | ||
28 | #define VDEC_B 1 | ||
29 | #define VDEC_C 2 | ||
30 | #define VDEC_D 3 | ||
31 | #define VDEC_E 4 | ||
32 | #define VDEC_F 5 | ||
33 | #define VDEC_G 6 | ||
34 | #define VDEC_H 7 | ||
35 | |||
36 | //#define AUTO_SWITCH_BIT[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; | ||
37 | |||
38 | // The following bit position enables automatic source switching for decoder A-H. | ||
39 | // Display index per camera. | ||
40 | //#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; | ||
41 | |||
42 | // Select input bit to video decoder A-H. | ||
43 | //#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31}; | ||
44 | |||
45 | // end of display sequence | ||
46 | #define END_OF_SEQ 0xF; | ||
47 | |||
48 | // registry string size | ||
49 | #define MAX_REGISTRY_SZ 40; | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-reg.h b/drivers/staging/cx25821/cx25821-medusa-reg.h new file mode 100644 index 00000000000..b877cd284aa --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-reg.h | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef __MEDUSA_REGISTERS__ | ||
24 | #define __MEDUSA_REGISTERS__ | ||
25 | |||
26 | // Serial Slave Registers | ||
27 | #define HOST_REGISTER1 0x0000 | ||
28 | #define HOST_REGISTER2 0x0001 | ||
29 | |||
30 | // Chip Configuration Registers | ||
31 | #define CHIP_CTRL 0x0100 | ||
32 | #define AFE_AB_CTRL 0x0104 | ||
33 | #define AFE_CD_CTRL 0x0108 | ||
34 | #define AFE_EF_CTRL 0x010C | ||
35 | #define AFE_GH_CTRL 0x0110 | ||
36 | #define DENC_AB_CTRL 0x0114 | ||
37 | #define BYP_AB_CTRL 0x0118 | ||
38 | #define MON_A_CTRL 0x011C | ||
39 | #define DISP_SEQ_A 0x0120 | ||
40 | #define DISP_SEQ_B 0x0124 | ||
41 | #define DISP_AB_CNT 0x0128 | ||
42 | #define DISP_CD_CNT 0x012C | ||
43 | #define DISP_EF_CNT 0x0130 | ||
44 | #define DISP_GH_CNT 0x0134 | ||
45 | #define DISP_IJ_CNT 0x0138 | ||
46 | #define PIN_OE_CTRL 0x013C | ||
47 | #define PIN_SPD_CTRL 0x0140 | ||
48 | #define PIN_SPD_CTRL2 0x0144 | ||
49 | #define IRQ_STAT_CTRL 0x0148 | ||
50 | #define POWER_CTRL_AB 0x014C | ||
51 | #define POWER_CTRL_CD 0x0150 | ||
52 | #define POWER_CTRL_EF 0x0154 | ||
53 | #define POWER_CTRL_GH 0x0158 | ||
54 | #define TUNE_CTRL 0x015C | ||
55 | #define BIAS_CTRL 0x0160 | ||
56 | #define AFE_AB_DIAG_CTRL 0x0164 | ||
57 | #define AFE_CD_DIAG_CTRL 0x0168 | ||
58 | #define AFE_EF_DIAG_CTRL 0x016C | ||
59 | #define AFE_GH_DIAG_CTRL 0x0170 | ||
60 | #define PLL_AB_DIAG_CTRL 0x0174 | ||
61 | #define PLL_CD_DIAG_CTRL 0x0178 | ||
62 | #define PLL_EF_DIAG_CTRL 0x017C | ||
63 | #define PLL_GH_DIAG_CTRL 0x0180 | ||
64 | #define TEST_CTRL 0x0184 | ||
65 | #define BIST_STAT 0x0188 | ||
66 | #define BIST_STAT2 0x018C | ||
67 | #define BIST_VID_PLL_AB_STAT 0x0190 | ||
68 | #define BIST_VID_PLL_CD_STAT 0x0194 | ||
69 | #define BIST_VID_PLL_EF_STAT 0x0198 | ||
70 | #define BIST_VID_PLL_GH_STAT 0x019C | ||
71 | #define DLL_DIAG_CTRL 0x01A0 | ||
72 | #define DEV_CH_ID_CTRL 0x01A4 | ||
73 | #define ABIST_CTRL_STATUS 0x01A8 | ||
74 | #define ABIST_FREQ 0x01AC | ||
75 | #define ABIST_GOERT_SHIFT 0x01B0 | ||
76 | #define ABIST_COEF12 0x01B4 | ||
77 | #define ABIST_COEF34 0x01B8 | ||
78 | #define ABIST_COEF56 0x01BC | ||
79 | #define ABIST_COEF7_SNR 0x01C0 | ||
80 | #define ABIST_ADC_CAL 0x01C4 | ||
81 | #define ABIST_BIN1_VGA0 0x01C8 | ||
82 | #define ABIST_BIN2_VGA1 0x01CC | ||
83 | #define ABIST_BIN3_VGA2 0x01D0 | ||
84 | #define ABIST_BIN4_VGA3 0x01D4 | ||
85 | #define ABIST_BIN5_VGA4 0x01D8 | ||
86 | #define ABIST_BIN6_VGA5 0x01DC | ||
87 | #define ABIST_BIN7_VGA6 0x0x1E0 | ||
88 | #define ABIST_CLAMP_A 0x0x1E4 | ||
89 | #define ABIST_CLAMP_B 0x0x1E8 | ||
90 | #define ABIST_CLAMP_C 0x01EC | ||
91 | #define ABIST_CLAMP_D 0x01F0 | ||
92 | #define ABIST_CLAMP_E 0x01F4 | ||
93 | #define ABIST_CLAMP_F 0x01F8 | ||
94 | |||
95 | // Digital Video Encoder A Registers | ||
96 | #define DENC_A_REG_1 0x0200 | ||
97 | #define DENC_A_REG_2 0x0204 | ||
98 | #define DENC_A_REG_3 0x0208 | ||
99 | #define DENC_A_REG_4 0x020C | ||
100 | #define DENC_A_REG_5 0x0210 | ||
101 | #define DENC_A_REG_6 0x0214 | ||
102 | #define DENC_A_REG_7 0x0218 | ||
103 | #define DENC_A_REG_8 0x021C | ||
104 | |||
105 | // Digital Video Encoder B Registers | ||
106 | #define DENC_B_REG_1 0x0300 | ||
107 | #define DENC_B_REG_2 0x0304 | ||
108 | #define DENC_B_REG_3 0x0308 | ||
109 | #define DENC_B_REG_4 0x030C | ||
110 | #define DENC_B_REG_5 0x0310 | ||
111 | #define DENC_B_REG_6 0x0314 | ||
112 | #define DENC_B_REG_7 0x0318 | ||
113 | #define DENC_B_REG_8 0x031C | ||
114 | |||
115 | // Video Decoder A Registers | ||
116 | #define MODE_CTRL 0x1000 | ||
117 | #define OUT_CTRL1 0x1004 | ||
118 | #define OUT_CTRL_NS 0x1008 | ||
119 | #define GEN_STAT 0x100C | ||
120 | #define INT_STAT_MASK 0x1010 | ||
121 | #define LUMA_CTRL 0x1014 | ||
122 | #define CHROMA_CTRL 0x1018 | ||
123 | #define CRUSH_CTRL 0x101C | ||
124 | #define HORIZ_TIM_CTRL 0x1020 | ||
125 | #define VERT_TIM_CTRL 0x1024 | ||
126 | #define MISC_TIM_CTRL 0x1028 | ||
127 | #define FIELD_COUNT 0x102C | ||
128 | #define HSCALE_CTRL 0x1030 | ||
129 | #define VSCALE_CTRL 0x1034 | ||
130 | #define MAN_VGA_CTRL 0x1038 | ||
131 | #define MAN_AGC_CTRL 0x103C | ||
132 | #define DFE_CTRL1 0x1040 | ||
133 | #define DFE_CTRL2 0x1044 | ||
134 | #define DFE_CTRL3 0x1048 | ||
135 | #define PLL_CTRL 0x104C | ||
136 | #define PLL_CTRL_FAST 0x1050 | ||
137 | #define HTL_CTRL 0x1054 | ||
138 | #define SRC_CFG 0x1058 | ||
139 | #define SC_STEP_SIZE 0x105C | ||
140 | #define SC_CONVERGE_CTRL 0x1060 | ||
141 | #define SC_LOOP_CTRL 0x1064 | ||
142 | #define COMB_2D_HFS_CFG 0x1068 | ||
143 | #define COMB_2D_HFD_CFG 0x106C | ||
144 | #define COMB_2D_LF_CFG 0x1070 | ||
145 | #define COMB_2D_BLEND 0x1074 | ||
146 | #define COMB_MISC_CTRL 0x1078 | ||
147 | #define COMB_FLAT_THRESH_CTRL 0x107C | ||
148 | #define COMB_TEST 0x1080 | ||
149 | #define BP_MISC_CTRL 0x1084 | ||
150 | #define VCR_DET_CTRL 0x1088 | ||
151 | #define NOISE_DET_CTRL 0x108C | ||
152 | #define COMB_FLAT_NOISE_CTRL 0x1090 | ||
153 | #define VERSION 0x11F8 | ||
154 | #define SOFT_RST_CTRL 0x11FC | ||
155 | |||
156 | // Video Decoder B Registers | ||
157 | #define VDEC_B_MODE_CTRL 0x1200 | ||
158 | #define VDEC_B_OUT_CTRL1 0x1204 | ||
159 | #define VDEC_B_OUT_CTRL_NS 0x1208 | ||
160 | #define VDEC_B_GEN_STAT 0x120C | ||
161 | #define VDEC_B_INT_STAT_MASK 0x1210 | ||
162 | #define VDEC_B_LUMA_CTRL 0x1214 | ||
163 | #define VDEC_B_CHROMA_CTRL 0x1218 | ||
164 | #define VDEC_B_CRUSH_CTRL 0x121C | ||
165 | #define VDEC_B_HORIZ_TIM_CTRL 0x1220 | ||
166 | #define VDEC_B_VERT_TIM_CTRL 0x1224 | ||
167 | #define VDEC_B_MISC_TIM_CTRL 0x1228 | ||
168 | #define VDEC_B_FIELD_COUNT 0x122C | ||
169 | #define VDEC_B_HSCALE_CTRL 0x1230 | ||
170 | #define VDEC_B_VSCALE_CTRL 0x1234 | ||
171 | #define VDEC_B_MAN_VGA_CTRL 0x1238 | ||
172 | #define VDEC_B_MAN_AGC_CTRL 0x123C | ||
173 | #define VDEC_B_DFE_CTRL1 0x1240 | ||
174 | #define VDEC_B_DFE_CTRL2 0x1244 | ||
175 | #define VDEC_B_DFE_CTRL3 0x1248 | ||
176 | #define VDEC_B_PLL_CTRL 0x124C | ||
177 | #define VDEC_B_PLL_CTRL_FAST 0x1250 | ||
178 | #define VDEC_B_HTL_CTRL 0x1254 | ||
179 | #define VDEC_B_SRC_CFG 0x1258 | ||
180 | #define VDEC_B_SC_STEP_SIZE 0x125C | ||
181 | #define VDEC_B_SC_CONVERGE_CTRL 0x1260 | ||
182 | #define VDEC_B_SC_LOOP_CTRL 0x1264 | ||
183 | #define VDEC_B_COMB_2D_HFS_CFG 0x1268 | ||
184 | #define VDEC_B_COMB_2D_HFD_CFG 0x126C | ||
185 | #define VDEC_B_COMB_2D_LF_CFG 0x1270 | ||
186 | #define VDEC_B_COMB_2D_BLEND 0x1274 | ||
187 | #define VDEC_B_COMB_MISC_CTRL 0x1278 | ||
188 | #define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C | ||
189 | #define VDEC_B_COMB_TEST 0x1280 | ||
190 | #define VDEC_B_BP_MISC_CTRL 0x1284 | ||
191 | #define VDEC_B_VCR_DET_CTRL 0x1288 | ||
192 | #define VDEC_B_NOISE_DET_CTRL 0x128C | ||
193 | #define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 | ||
194 | #define VDEC_B_VERSION 0x13F8 | ||
195 | #define VDEC_B_SOFT_RST_CTRL 0x13FC | ||
196 | |||
197 | // Video Decoder C Registers | ||
198 | #define VDEC_C_MODE_CTRL 0x1400 | ||
199 | #define VDEC_C_OUT_CTRL1 0x1404 | ||
200 | #define VDEC_C_OUT_CTRL_NS 0x1408 | ||
201 | #define VDEC_C_GEN_STAT 0x140C | ||
202 | #define VDEC_C_INT_STAT_MASK 0x1410 | ||
203 | #define VDEC_C_LUMA_CTRL 0x1414 | ||
204 | #define VDEC_C_CHROMA_CTRL 0x1418 | ||
205 | #define VDEC_C_CRUSH_CTRL 0x141C | ||
206 | #define VDEC_C_HORIZ_TIM_CTRL 0x1420 | ||
207 | #define VDEC_C_VERT_TIM_CTRL 0x1424 | ||
208 | #define VDEC_C_MISC_TIM_CTRL 0x1428 | ||
209 | #define VDEC_C_FIELD_COUNT 0x142C | ||
210 | #define VDEC_C_HSCALE_CTRL 0x1430 | ||
211 | #define VDEC_C_VSCALE_CTRL 0x1434 | ||
212 | #define VDEC_C_MAN_VGA_CTRL 0x1438 | ||
213 | #define VDEC_C_MAN_AGC_CTRL 0x143C | ||
214 | #define VDEC_C_DFE_CTRL1 0x1440 | ||
215 | #define VDEC_C_DFE_CTRL2 0x1444 | ||
216 | #define VDEC_C_DFE_CTRL3 0x1448 | ||
217 | #define VDEC_C_PLL_CTRL 0x144C | ||
218 | #define VDEC_C_PLL_CTRL_FAST 0x1450 | ||
219 | #define VDEC_C_HTL_CTRL 0x1454 | ||
220 | #define VDEC_C_SRC_CFG 0x1458 | ||
221 | #define VDEC_C_SC_STEP_SIZE 0x145C | ||
222 | #define VDEC_C_SC_CONVERGE_CTRL 0x1460 | ||
223 | #define VDEC_C_SC_LOOP_CTRL 0x1464 | ||
224 | #define VDEC_C_COMB_2D_HFS_CFG 0x1468 | ||
225 | #define VDEC_C_COMB_2D_HFD_CFG 0x146C | ||
226 | #define VDEC_C_COMB_2D_LF_CFG 0x1470 | ||
227 | #define VDEC_C_COMB_2D_BLEND 0x1474 | ||
228 | #define VDEC_C_COMB_MISC_CTRL 0x1478 | ||
229 | #define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C | ||
230 | #define VDEC_C_COMB_TEST 0x1480 | ||
231 | #define VDEC_C_BP_MISC_CTRL 0x1484 | ||
232 | #define VDEC_C_VCR_DET_CTRL 0x1488 | ||
233 | #define VDEC_C_NOISE_DET_CTRL 0x148C | ||
234 | #define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 | ||
235 | #define VDEC_C_VERSION 0x15F8 | ||
236 | #define VDEC_C_SOFT_RST_CTRL 0x15FC | ||
237 | |||
238 | // Video Decoder D Registers | ||
239 | #define VDEC_D_MODE_CTRL 0x1600 | ||
240 | #define VDEC_D_OUT_CTRL1 0x1604 | ||
241 | #define VDEC_D_OUT_CTRL_NS 0x1608 | ||
242 | #define VDEC_D_GEN_STAT 0x160C | ||
243 | #define VDEC_D_INT_STAT_MASK 0x1610 | ||
244 | #define VDEC_D_LUMA_CTRL 0x1614 | ||
245 | #define VDEC_D_CHROMA_CTRL 0x1618 | ||
246 | #define VDEC_D_CRUSH_CTRL 0x161C | ||
247 | #define VDEC_D_HORIZ_TIM_CTRL 0x1620 | ||
248 | #define VDEC_D_VERT_TIM_CTRL 0x1624 | ||
249 | #define VDEC_D_MISC_TIM_CTRL 0x1628 | ||
250 | #define VDEC_D_FIELD_COUNT 0x162C | ||
251 | #define VDEC_D_HSCALE_CTRL 0x1630 | ||
252 | #define VDEC_D_VSCALE_CTRL 0x1634 | ||
253 | #define VDEC_D_MAN_VGA_CTRL 0x1638 | ||
254 | #define VDEC_D_MAN_AGC_CTRL 0x163C | ||
255 | #define VDEC_D_DFE_CTRL1 0x1640 | ||
256 | #define VDEC_D_DFE_CTRL2 0x1644 | ||
257 | #define VDEC_D_DFE_CTRL3 0x1648 | ||
258 | #define VDEC_D_PLL_CTRL 0x164C | ||
259 | #define VDEC_D_PLL_CTRL_FAST 0x1650 | ||
260 | #define VDEC_D_HTL_CTRL 0x1654 | ||
261 | #define VDEC_D_SRC_CFG 0x1658 | ||
262 | #define VDEC_D_SC_STEP_SIZE 0x165C | ||
263 | #define VDEC_D_SC_CONVERGE_CTRL 0x1660 | ||
264 | #define VDEC_D_SC_LOOP_CTRL 0x1664 | ||
265 | #define VDEC_D_COMB_2D_HFS_CFG 0x1668 | ||
266 | #define VDEC_D_COMB_2D_HFD_CFG 0x166C | ||
267 | #define VDEC_D_COMB_2D_LF_CFG 0x1670 | ||
268 | #define VDEC_D_COMB_2D_BLEND 0x1674 | ||
269 | #define VDEC_D_COMB_MISC_CTRL 0x1678 | ||
270 | #define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C | ||
271 | #define VDEC_D_COMB_TEST 0x1680 | ||
272 | #define VDEC_D_BP_MISC_CTRL 0x1684 | ||
273 | #define VDEC_D_VCR_DET_CTRL 0x1688 | ||
274 | #define VDEC_D_NOISE_DET_CTRL 0x168C | ||
275 | #define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 | ||
276 | #define VDEC_D_VERSION 0x17F8 | ||
277 | #define VDEC_D_SOFT_RST_CTRL 0x17FC | ||
278 | |||
279 | // Video Decoder E Registers | ||
280 | #define VDEC_E_MODE_CTRL 0x1800 | ||
281 | #define VDEC_E_OUT_CTRL1 0x1804 | ||
282 | #define VDEC_E_OUT_CTRL_NS 0x1808 | ||
283 | #define VDEC_E_GEN_STAT 0x180C | ||
284 | #define VDEC_E_INT_STAT_MASK 0x1810 | ||
285 | #define VDEC_E_LUMA_CTRL 0x1814 | ||
286 | #define VDEC_E_CHROMA_CTRL 0x1818 | ||
287 | #define VDEC_E_CRUSH_CTRL 0x181C | ||
288 | #define VDEC_E_HORIZ_TIM_CTRL 0x1820 | ||
289 | #define VDEC_E_VERT_TIM_CTRL 0x1824 | ||
290 | #define VDEC_E_MISC_TIM_CTRL 0x1828 | ||
291 | #define VDEC_E_FIELD_COUNT 0x182C | ||
292 | #define VDEC_E_HSCALE_CTRL 0x1830 | ||
293 | #define VDEC_E_VSCALE_CTRL 0x1834 | ||
294 | #define VDEC_E_MAN_VGA_CTRL 0x1838 | ||
295 | #define VDEC_E_MAN_AGC_CTRL 0x183C | ||
296 | #define VDEC_E_DFE_CTRL1 0x1840 | ||
297 | #define VDEC_E_DFE_CTRL2 0x1844 | ||
298 | #define VDEC_E_DFE_CTRL3 0x1848 | ||
299 | #define VDEC_E_PLL_CTRL 0x184C | ||
300 | #define VDEC_E_PLL_CTRL_FAST 0x1850 | ||
301 | #define VDEC_E_HTL_CTRL 0x1854 | ||
302 | #define VDEC_E_SRC_CFG 0x1858 | ||
303 | #define VDEC_E_SC_STEP_SIZE 0x185C | ||
304 | #define VDEC_E_SC_CONVERGE_CTRL 0x1860 | ||
305 | #define VDEC_E_SC_LOOP_CTRL 0x1864 | ||
306 | #define VDEC_E_COMB_2D_HFS_CFG 0x1868 | ||
307 | #define VDEC_E_COMB_2D_HFD_CFG 0x186C | ||
308 | #define VDEC_E_COMB_2D_LF_CFG 0x1870 | ||
309 | #define VDEC_E_COMB_2D_BLEND 0x1874 | ||
310 | #define VDEC_E_COMB_MISC_CTRL 0x1878 | ||
311 | #define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C | ||
312 | #define VDEC_E_COMB_TEST 0x1880 | ||
313 | #define VDEC_E_BP_MISC_CTRL 0x1884 | ||
314 | #define VDEC_E_VCR_DET_CTRL 0x1888 | ||
315 | #define VDEC_E_NOISE_DET_CTRL 0x188C | ||
316 | #define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 | ||
317 | #define VDEC_E_VERSION 0x19F8 | ||
318 | #define VDEC_E_SOFT_RST_CTRL 0x19FC | ||
319 | |||
320 | // Video Decoder F Registers | ||
321 | #define VDEC_F_MODE_CTRL 0x1A00 | ||
322 | #define VDEC_F_OUT_CTRL1 0x1A04 | ||
323 | #define VDEC_F_OUT_CTRL_NS 0x1A08 | ||
324 | #define VDEC_F_GEN_STAT 0x1A0C | ||
325 | #define VDEC_F_INT_STAT_MASK 0x1A10 | ||
326 | #define VDEC_F_LUMA_CTRL 0x1A14 | ||
327 | #define VDEC_F_CHROMA_CTRL 0x1A18 | ||
328 | #define VDEC_F_CRUSH_CTRL 0x1A1C | ||
329 | #define VDEC_F_HORIZ_TIM_CTRL 0x1A20 | ||
330 | #define VDEC_F_VERT_TIM_CTRL 0x1A24 | ||
331 | #define VDEC_F_MISC_TIM_CTRL 0x1A28 | ||
332 | #define VDEC_F_FIELD_COUNT 0x1A2C | ||
333 | #define VDEC_F_HSCALE_CTRL 0x1A30 | ||
334 | #define VDEC_F_VSCALE_CTRL 0x1A34 | ||
335 | #define VDEC_F_MAN_VGA_CTRL 0x1A38 | ||
336 | #define VDEC_F_MAN_AGC_CTRL 0x1A3C | ||
337 | #define VDEC_F_DFE_CTRL1 0x1A40 | ||
338 | #define VDEC_F_DFE_CTRL2 0x1A44 | ||
339 | #define VDEC_F_DFE_CTRL3 0x1A48 | ||
340 | #define VDEC_F_PLL_CTRL 0x1A4C | ||
341 | #define VDEC_F_PLL_CTRL_FAST 0x1A50 | ||
342 | #define VDEC_F_HTL_CTRL 0x1A54 | ||
343 | #define VDEC_F_SRC_CFG 0x1A58 | ||
344 | #define VDEC_F_SC_STEP_SIZE 0x1A5C | ||
345 | #define VDEC_F_SC_CONVERGE_CTRL 0x1A60 | ||
346 | #define VDEC_F_SC_LOOP_CTRL 0x1A64 | ||
347 | #define VDEC_F_COMB_2D_HFS_CFG 0x1A68 | ||
348 | #define VDEC_F_COMB_2D_HFD_CFG 0x1A6C | ||
349 | #define VDEC_F_COMB_2D_LF_CFG 0x1A70 | ||
350 | #define VDEC_F_COMB_2D_BLEND 0x1A74 | ||
351 | #define VDEC_F_COMB_MISC_CTRL 0x1A78 | ||
352 | #define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C | ||
353 | #define VDEC_F_COMB_TEST 0x1A80 | ||
354 | #define VDEC_F_BP_MISC_CTRL 0x1A84 | ||
355 | #define VDEC_F_VCR_DET_CTRL 0x1A88 | ||
356 | #define VDEC_F_NOISE_DET_CTRL 0x1A8C | ||
357 | #define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 | ||
358 | #define VDEC_F_VERSION 0x1BF8 | ||
359 | #define VDEC_F_SOFT_RST_CTRL 0x1BFC | ||
360 | |||
361 | // Video Decoder G Registers | ||
362 | #define VDEC_G_MODE_CTRL 0x1C00 | ||
363 | #define VDEC_G_OUT_CTRL1 0x1C04 | ||
364 | #define VDEC_G_OUT_CTRL_NS 0x1C08 | ||
365 | #define VDEC_G_GEN_STAT 0x1C0C | ||
366 | #define VDEC_G_INT_STAT_MASK 0x1C10 | ||
367 | #define VDEC_G_LUMA_CTRL 0x1C14 | ||
368 | #define VDEC_G_CHROMA_CTRL 0x1C18 | ||
369 | #define VDEC_G_CRUSH_CTRL 0x1C1C | ||
370 | #define VDEC_G_HORIZ_TIM_CTRL 0x1C20 | ||
371 | #define VDEC_G_VERT_TIM_CTRL 0x1C24 | ||
372 | #define VDEC_G_MISC_TIM_CTRL 0x1C28 | ||
373 | #define VDEC_G_FIELD_COUNT 0x1C2C | ||
374 | #define VDEC_G_HSCALE_CTRL 0x1C30 | ||
375 | #define VDEC_G_VSCALE_CTRL 0x1C34 | ||
376 | #define VDEC_G_MAN_VGA_CTRL 0x1C38 | ||
377 | #define VDEC_G_MAN_AGC_CTRL 0x1C3C | ||
378 | #define VDEC_G_DFE_CTRL1 0x1C40 | ||
379 | #define VDEC_G_DFE_CTRL2 0x1C44 | ||
380 | #define VDEC_G_DFE_CTRL3 0x1C48 | ||
381 | #define VDEC_G_PLL_CTRL 0x1C4C | ||
382 | #define VDEC_G_PLL_CTRL_FAST 0x1C50 | ||
383 | #define VDEC_G_HTL_CTRL 0x1C54 | ||
384 | #define VDEC_G_SRC_CFG 0x1C58 | ||
385 | #define VDEC_G_SC_STEP_SIZE 0x1C5C | ||
386 | #define VDEC_G_SC_CONVERGE_CTRL 0x1C60 | ||
387 | #define VDEC_G_SC_LOOP_CTRL 0x1C64 | ||
388 | #define VDEC_G_COMB_2D_HFS_CFG 0x1C68 | ||
389 | #define VDEC_G_COMB_2D_HFD_CFG 0x1C6C | ||
390 | #define VDEC_G_COMB_2D_LF_CFG 0x1C70 | ||
391 | #define VDEC_G_COMB_2D_BLEND 0x1C74 | ||
392 | #define VDEC_G_COMB_MISC_CTRL 0x1C78 | ||
393 | #define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C | ||
394 | #define VDEC_G_COMB_TEST 0x1C80 | ||
395 | #define VDEC_G_BP_MISC_CTRL 0x1C84 | ||
396 | #define VDEC_G_VCR_DET_CTRL 0x1C88 | ||
397 | #define VDEC_G_NOISE_DET_CTRL 0x1C8C | ||
398 | #define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 | ||
399 | #define VDEC_G_VERSION 0x1DF8 | ||
400 | #define VDEC_G_SOFT_RST_CTRL 0x1DFC | ||
401 | |||
402 | // Video Decoder H Registers | ||
403 | #define VDEC_H_MODE_CTRL 0x1E00 | ||
404 | #define VDEC_H_OUT_CTRL1 0x1E04 | ||
405 | #define VDEC_H_OUT_CTRL_NS 0x1E08 | ||
406 | #define VDEC_H_GEN_STAT 0x1E0C | ||
407 | #define VDEC_H_INT_STAT_MASK 0x1E1E | ||
408 | #define VDEC_H_LUMA_CTRL 0x1E14 | ||
409 | #define VDEC_H_CHROMA_CTRL 0x1E18 | ||
410 | #define VDEC_H_CRUSH_CTRL 0x1E1C | ||
411 | #define VDEC_H_HORIZ_TIM_CTRL 0x1E20 | ||
412 | #define VDEC_H_VERT_TIM_CTRL 0x1E24 | ||
413 | #define VDEC_H_MISC_TIM_CTRL 0x1E28 | ||
414 | #define VDEC_H_FIELD_COUNT 0x1E2C | ||
415 | #define VDEC_H_HSCALE_CTRL 0x1E30 | ||
416 | #define VDEC_H_VSCALE_CTRL 0x1E34 | ||
417 | #define VDEC_H_MAN_VGA_CTRL 0x1E38 | ||
418 | #define VDEC_H_MAN_AGC_CTRL 0x1E3C | ||
419 | #define VDEC_H_DFE_CTRL1 0x1E40 | ||
420 | #define VDEC_H_DFE_CTRL2 0x1E44 | ||
421 | #define VDEC_H_DFE_CTRL3 0x1E48 | ||
422 | #define VDEC_H_PLL_CTRL 0x1E4C | ||
423 | #define VDEC_H_PLL_CTRL_FAST 0x1E50 | ||
424 | #define VDEC_H_HTL_CTRL 0x1E54 | ||
425 | #define VDEC_H_SRC_CFG 0x1E58 | ||
426 | #define VDEC_H_SC_STEP_SIZE 0x1E5C | ||
427 | #define VDEC_H_SC_CONVERGE_CTRL 0x1E60 | ||
428 | #define VDEC_H_SC_LOOP_CTRL 0x1E64 | ||
429 | #define VDEC_H_COMB_2D_HFS_CFG 0x1E68 | ||
430 | #define VDEC_H_COMB_2D_HFD_CFG 0x1E6C | ||
431 | #define VDEC_H_COMB_2D_LF_CFG 0x1E70 | ||
432 | #define VDEC_H_COMB_2D_BLEND 0x1E74 | ||
433 | #define VDEC_H_COMB_MISC_CTRL 0x1E78 | ||
434 | #define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C | ||
435 | #define VDEC_H_COMB_TEST 0x1E80 | ||
436 | #define VDEC_H_BP_MISC_CTRL 0x1E84 | ||
437 | #define VDEC_H_VCR_DET_CTRL 0x1E88 | ||
438 | #define VDEC_H_NOISE_DET_CTRL 0x1E8C | ||
439 | #define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 | ||
440 | #define VDEC_H_VERSION 0x1FF8 | ||
441 | #define VDEC_H_SOFT_RST_CTRL 0x1FFC | ||
442 | |||
443 | //***************************************************************************** | ||
444 | // LUMA_CTRL register fields | ||
445 | #define VDEC_A_BRITE_CTRL 0x1014 | ||
446 | #define VDEC_A_CNTRST_CTRL 0x1015 | ||
447 | #define VDEC_A_PEAK_SEL 0x1016 | ||
448 | |||
449 | //***************************************************************************** | ||
450 | // CHROMA_CTRL register fields | ||
451 | #define VDEC_A_USAT_CTRL 0x1018 | ||
452 | #define VDEC_A_VSAT_CTRL 0x1019 | ||
453 | #define VDEC_A_HUE_CTRL 0x101A | ||
454 | |||
455 | |||
456 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c new file mode 100644 index 00000000000..6225f1079bc --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-video.c | |||
@@ -0,0 +1,769 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include "cx25821.h" | ||
24 | #include "cx25821-medusa-video.h" | ||
25 | #include "cx25821-biffuncs.h" | ||
26 | |||
27 | |||
28 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
29 | //medusa_enable_bluefield_output() | ||
30 | // | ||
31 | // Enable the generation of blue filed output if no video | ||
32 | // | ||
33 | static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, int enable) | ||
34 | { | ||
35 | int ret_val = 1; | ||
36 | u32 value = 0; | ||
37 | u32 tmp = 0; | ||
38 | int out_ctrl = OUT_CTRL1; | ||
39 | int out_ctrl_ns = OUT_CTRL_NS; | ||
40 | |||
41 | |||
42 | switch (channel) | ||
43 | { | ||
44 | default: | ||
45 | case VDEC_A: | ||
46 | break; | ||
47 | case VDEC_B: | ||
48 | out_ctrl = VDEC_B_OUT_CTRL1; | ||
49 | out_ctrl_ns = VDEC_B_OUT_CTRL_NS; | ||
50 | break; | ||
51 | case VDEC_C: | ||
52 | out_ctrl = VDEC_C_OUT_CTRL1; | ||
53 | out_ctrl_ns = VDEC_C_OUT_CTRL_NS; | ||
54 | break; | ||
55 | case VDEC_D: | ||
56 | out_ctrl = VDEC_D_OUT_CTRL1; | ||
57 | out_ctrl_ns = VDEC_D_OUT_CTRL_NS; | ||
58 | break; | ||
59 | case VDEC_E: | ||
60 | out_ctrl = VDEC_E_OUT_CTRL1; | ||
61 | out_ctrl_ns = VDEC_E_OUT_CTRL_NS; | ||
62 | return; | ||
63 | case VDEC_F: | ||
64 | out_ctrl = VDEC_F_OUT_CTRL1; | ||
65 | out_ctrl_ns = VDEC_F_OUT_CTRL_NS; | ||
66 | return; | ||
67 | case VDEC_G: | ||
68 | out_ctrl = VDEC_G_OUT_CTRL1; | ||
69 | out_ctrl_ns = VDEC_G_OUT_CTRL_NS; | ||
70 | return; | ||
71 | case VDEC_H: | ||
72 | out_ctrl = VDEC_H_OUT_CTRL1; | ||
73 | out_ctrl_ns = VDEC_H_OUT_CTRL_NS; | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); | ||
78 | value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN | ||
79 | if (enable) | ||
80 | value |= 0x00000080; // set BLUE_FIELD_EN | ||
81 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); | ||
82 | |||
83 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); | ||
84 | value &= 0xFFFFFF7F; | ||
85 | if (enable) | ||
86 | value |= 0x00000080; // set BLUE_FIELD_EN | ||
87 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); | ||
88 | } | ||
89 | |||
90 | |||
91 | static int medusa_initialize_ntsc(struct cx25821_dev *dev) | ||
92 | { | ||
93 | int ret_val = 0; | ||
94 | int i = 0; | ||
95 | u32 value = 0; | ||
96 | u32 tmp = 0; | ||
97 | |||
98 | mutex_lock(&dev->lock); | ||
99 | |||
100 | |||
101 | for (i=0; i < MAX_DECODERS; i++) | ||
102 | { | ||
103 | // set video format NTSC-M | ||
104 | value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); | ||
105 | value &= 0xFFFFFFF0; | ||
106 | value |= 0x10001; // enable the fast locking mode bit[16] | ||
107 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); | ||
108 | |||
109 | // resolution NTSC 720x480 | ||
110 | value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); | ||
111 | value &= 0x00C00C00; | ||
112 | value |= 0x612D0074; | ||
113 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); | ||
114 | |||
115 | value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); | ||
116 | value &= 0x00C00C00; | ||
117 | value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID | ||
118 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); | ||
119 | |||
120 | // chroma subcarrier step size | ||
121 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000); | ||
122 | |||
123 | // enable VIP optional active | ||
124 | value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); | ||
125 | value &= 0xFFFBFFFF; | ||
126 | value |= 0x00040000; | ||
127 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); | ||
128 | |||
129 | // enable VIP optional active (VIP_OPT_AL) for direct output. | ||
130 | value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); | ||
131 | value &= 0xFFFBFFFF; | ||
132 | value |= 0x00040000; | ||
133 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); | ||
134 | |||
135 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | ||
136 | // when the input switching rate < 16 fields | ||
137 | // | ||
138 | value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); | ||
139 | value = setBitAtPos(value, 14); // disable special play detection | ||
140 | value = clearBitAtPos(value, 15); | ||
141 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); | ||
142 | |||
143 | // set vbi_gate_en to 0 | ||
144 | value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); | ||
145 | value = clearBitAtPos(value, 29); | ||
146 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); | ||
147 | |||
148 | // Enable the generation of blue field output if no video | ||
149 | medusa_enable_bluefield_output(dev, i, 1); | ||
150 | } | ||
151 | |||
152 | |||
153 | for (i=0; i < MAX_ENCODERS; i++) | ||
154 | { | ||
155 | // NTSC hclock | ||
156 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); | ||
157 | value &= 0xF000FC00; | ||
158 | value |= 0x06B402D0; | ||
159 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); | ||
160 | |||
161 | // burst begin and burst end | ||
162 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); | ||
163 | value &= 0xFF000000; | ||
164 | value |= 0x007E9054; | ||
165 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); | ||
166 | |||
167 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); | ||
168 | value &= 0xFC00FE00; | ||
169 | value |= 0x00EC00F0; | ||
170 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); | ||
171 | |||
172 | // set NTSC vblank, no phase alternation, 7.5 IRE pedestal | ||
173 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); | ||
174 | value &= 0x00FCFFFF; | ||
175 | value |= 0x13020000; | ||
176 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); | ||
177 | |||
178 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); | ||
179 | value &= 0xFFFF0000; | ||
180 | value |= 0x0000E575; | ||
181 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); | ||
182 | |||
183 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1); | ||
184 | |||
185 | // Subcarrier Increment | ||
186 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F); | ||
187 | } | ||
188 | |||
189 | |||
190 | //set picture resolutions | ||
191 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | ||
192 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 | ||
193 | |||
194 | // set Bypass input format to NTSC 525 lines | ||
195 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
196 | value |= 0x00080200; | ||
197 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
198 | |||
199 | mutex_unlock(&dev->lock); | ||
200 | |||
201 | return ret_val; | ||
202 | } | ||
203 | |||
204 | |||
205 | static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | ||
206 | { | ||
207 | int ret_val = -1; | ||
208 | u32 value = 0, tmp = 0; | ||
209 | |||
210 | // Setup for 2D threshold | ||
211 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG+(0x200*dec), 0x20002861); | ||
212 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); | ||
213 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); | ||
214 | |||
215 | // Setup flat chroma and luma thresholds | ||
216 | value = cx25821_i2c_read(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), &tmp); | ||
217 | value &= 0x06230000; | ||
218 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), value); | ||
219 | |||
220 | // set comb 2D blend | ||
221 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND+(0x200*dec), 0x210F0F0F); | ||
222 | |||
223 | // COMB MISC CONTROL | ||
224 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL+(0x200*dec), 0x41120A7F); | ||
225 | |||
226 | return ret_val; | ||
227 | } | ||
228 | |||
229 | |||
230 | static int medusa_initialize_pal(struct cx25821_dev *dev) | ||
231 | { | ||
232 | int ret_val = 0; | ||
233 | int i = 0; | ||
234 | u32 value = 0; | ||
235 | u32 tmp = 0; | ||
236 | |||
237 | mutex_lock(&dev->lock); | ||
238 | |||
239 | for (i=0; i < MAX_DECODERS; i++) | ||
240 | { | ||
241 | // set video format PAL-BDGHI | ||
242 | value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); | ||
243 | value &= 0xFFFFFFF0; | ||
244 | value |= 0x10004; // enable the fast locking mode bit[16] | ||
245 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); | ||
246 | |||
247 | |||
248 | // resolution PAL 720x576 | ||
249 | value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); | ||
250 | value &= 0x00C00C00; | ||
251 | value |= 0x632D007D; | ||
252 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); | ||
253 | |||
254 | // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 | ||
255 | value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); | ||
256 | value &= 0x00C00C00; | ||
257 | value |= 0x28240026; // vblank_cnt + 2 to get camera ID | ||
258 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); | ||
259 | |||
260 | // chroma subcarrier step size | ||
261 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0); | ||
262 | |||
263 | // enable VIP optional active | ||
264 | value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); | ||
265 | value &= 0xFFFBFFFF; | ||
266 | value |= 0x00040000; | ||
267 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); | ||
268 | |||
269 | // enable VIP optional active (VIP_OPT_AL) for direct output. | ||
270 | value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); | ||
271 | value &= 0xFFFBFFFF; | ||
272 | value |= 0x00040000; | ||
273 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); | ||
274 | |||
275 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | ||
276 | // when the input switching rate < 16 fields | ||
277 | value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); | ||
278 | value = setBitAtPos(value, 14); // disable special play detection | ||
279 | value = clearBitAtPos(value, 15); | ||
280 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); | ||
281 | |||
282 | // set vbi_gate_en to 0 | ||
283 | value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); | ||
284 | value = clearBitAtPos(value, 29); | ||
285 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); | ||
286 | |||
287 | medusa_PALCombInit(dev, i); | ||
288 | |||
289 | // Enable the generation of blue field output if no video | ||
290 | medusa_enable_bluefield_output(dev, i, 1); | ||
291 | } | ||
292 | |||
293 | |||
294 | for (i=0; i < MAX_ENCODERS; i++) | ||
295 | { | ||
296 | // PAL hclock | ||
297 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); | ||
298 | value &= 0xF000FC00; | ||
299 | value |= 0x06C002D0; | ||
300 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); | ||
301 | |||
302 | // burst begin and burst end | ||
303 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); | ||
304 | value &= 0xFF000000; | ||
305 | value |= 0x007E9754; | ||
306 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); | ||
307 | |||
308 | // hblank and vactive | ||
309 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); | ||
310 | value &= 0xFC00FE00; | ||
311 | value |= 0x00FC0120; | ||
312 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); | ||
313 | |||
314 | // set PAL vblank, phase alternation, 0 IRE pedestal | ||
315 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); | ||
316 | value &= 0x00FCFFFF; | ||
317 | value |= 0x14010000; | ||
318 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); | ||
319 | |||
320 | |||
321 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); | ||
322 | value &= 0xFFFF0000; | ||
323 | value |= 0x0000F078; | ||
324 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); | ||
325 | |||
326 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF); | ||
327 | |||
328 | // Subcarrier Increment | ||
329 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB); | ||
330 | } | ||
331 | |||
332 | |||
333 | //set picture resolutions | ||
334 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | ||
335 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 | ||
336 | |||
337 | // set Bypass input format to PAL 625 lines | ||
338 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
339 | value &= 0xFFF7FDFF; | ||
340 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
341 | |||
342 | mutex_unlock(&dev->lock); | ||
343 | |||
344 | return ret_val; | ||
345 | } | ||
346 | |||
347 | |||
348 | int medusa_set_videostandard(struct cx25821_dev *dev) | ||
349 | { | ||
350 | int status = STATUS_SUCCESS; | ||
351 | u32 value = 0, tmp = 0; | ||
352 | |||
353 | |||
354 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
355 | { | ||
356 | status = medusa_initialize_pal(dev); | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | status = medusa_initialize_ntsc(dev); | ||
361 | } | ||
362 | |||
363 | // Enable DENC_A output | ||
364 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); | ||
365 | value = setBitAtPos(value, 4); | ||
366 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); | ||
367 | |||
368 | // Enable DENC_B output | ||
369 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); | ||
370 | value = setBitAtPos(value, 4); | ||
371 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); | ||
372 | |||
373 | return status; | ||
374 | } | ||
375 | |||
376 | |||
377 | void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select) | ||
378 | { | ||
379 | int decoder = 0; | ||
380 | int decoder_count = 0; | ||
381 | int ret_val = 0; | ||
382 | u32 hscale = 0x0; | ||
383 | u32 vscale = 0x0; | ||
384 | const int MAX_WIDTH = 720; | ||
385 | |||
386 | mutex_lock(&dev->lock); | ||
387 | |||
388 | // validate the width - cannot be negative | ||
389 | if (width > MAX_WIDTH) | ||
390 | { | ||
391 | printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH); | ||
392 | width = MAX_WIDTH; | ||
393 | } | ||
394 | |||
395 | if( decoder_select <= 7 && decoder_select >= 0 ) | ||
396 | { | ||
397 | decoder = decoder_select; | ||
398 | decoder_count = decoder_select + 1; | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | decoder = 0; | ||
403 | decoder_count = _num_decoders; | ||
404 | } | ||
405 | |||
406 | |||
407 | switch( width ) | ||
408 | { | ||
409 | case 320: | ||
410 | hscale = 0x13E34B; | ||
411 | vscale = 0x0; | ||
412 | break; | ||
413 | |||
414 | case 352: | ||
415 | hscale = 0x10A273; | ||
416 | vscale = 0x0; | ||
417 | break; | ||
418 | |||
419 | case 176: | ||
420 | hscale = 0x3115B2; | ||
421 | vscale = 0x1E00; | ||
422 | break; | ||
423 | |||
424 | case 160: | ||
425 | hscale = 0x378D84; | ||
426 | vscale = 0x1E00; | ||
427 | break; | ||
428 | |||
429 | default: //720 | ||
430 | hscale = 0x0; | ||
431 | vscale = 0x0; | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | for( ; decoder < decoder_count; decoder++) | ||
436 | { | ||
437 | // write scaling values for each decoder | ||
438 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale); | ||
439 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale); | ||
440 | } | ||
441 | |||
442 | mutex_unlock(&dev->lock); | ||
443 | } | ||
444 | |||
445 | static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, int duration) | ||
446 | { | ||
447 | int ret_val = 0; | ||
448 | u32 fld_cnt = 0; | ||
449 | u32 tmp = 0; | ||
450 | u32 disp_cnt_reg = DISP_AB_CNT; | ||
451 | |||
452 | mutex_lock(&dev->lock); | ||
453 | |||
454 | // no support | ||
455 | if (decoder < VDEC_A && decoder > VDEC_H) | ||
456 | { | ||
457 | mutex_unlock(&dev->lock); | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | switch (decoder) | ||
462 | { | ||
463 | default: | ||
464 | break; | ||
465 | case VDEC_C: | ||
466 | case VDEC_D: | ||
467 | disp_cnt_reg = DISP_CD_CNT; | ||
468 | break; | ||
469 | case VDEC_E: | ||
470 | case VDEC_F: | ||
471 | disp_cnt_reg = DISP_EF_CNT; | ||
472 | break; | ||
473 | case VDEC_G: | ||
474 | case VDEC_H: | ||
475 | disp_cnt_reg = DISP_GH_CNT; | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | _display_field_cnt[decoder] = duration; | ||
480 | |||
481 | // update hardware | ||
482 | fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); | ||
483 | |||
484 | if (!(decoder % 2)) // EVEN decoder | ||
485 | { | ||
486 | fld_cnt &= 0xFFFF0000; | ||
487 | fld_cnt |= duration; | ||
488 | } | ||
489 | else | ||
490 | { | ||
491 | fld_cnt &= 0x0000FFFF; | ||
492 | fld_cnt |= ((u32)duration) << 16; | ||
493 | } | ||
494 | |||
495 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); | ||
496 | |||
497 | mutex_unlock(&dev->lock); | ||
498 | } | ||
499 | |||
500 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
501 | // Map to Medusa register setting | ||
502 | static int mapM( | ||
503 | int srcMin, | ||
504 | int srcMax, | ||
505 | int srcVal, | ||
506 | int dstMin, | ||
507 | int dstMax, | ||
508 | int* dstVal | ||
509 | ) | ||
510 | { | ||
511 | int numerator; | ||
512 | int denominator; | ||
513 | int quotient; | ||
514 | |||
515 | if((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) | ||
516 | { | ||
517 | return -1; | ||
518 | } | ||
519 | |||
520 | // This is the overall expression used: | ||
521 | // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; | ||
522 | // but we need to account for rounding so below we use the modulus | ||
523 | // operator to find the remainder and increment if necessary. | ||
524 | numerator = (srcVal - srcMin)*(dstMax - dstMin); | ||
525 | denominator = srcMax - srcMin; | ||
526 | quotient = numerator/denominator; | ||
527 | |||
528 | if(2 * ( numerator % denominator ) >= denominator) | ||
529 | { | ||
530 | quotient++; | ||
531 | } | ||
532 | |||
533 | *dstVal = quotient + dstMin; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static unsigned long convert_to_twos(long numeric, unsigned long bits_len) | ||
539 | { | ||
540 | unsigned char temp; | ||
541 | |||
542 | if (numeric >= 0) | ||
543 | return numeric; | ||
544 | else | ||
545 | { | ||
546 | temp = ~(abs(numeric) & 0xFF); | ||
547 | temp += 1; | ||
548 | return temp; | ||
549 | } | ||
550 | } | ||
551 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
552 | int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | ||
553 | { | ||
554 | int ret_val = 0; | ||
555 | int value = 0; | ||
556 | u32 val = 0, tmp = 0; | ||
557 | |||
558 | mutex_lock(&dev->lock); | ||
559 | if((brightness > VIDEO_PROCAMP_MAX) || (brightness < VIDEO_PROCAMP_MIN)) | ||
560 | { | ||
561 | mutex_unlock(&dev->lock); | ||
562 | return -1; | ||
563 | } | ||
564 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); | ||
565 | value = convert_to_twos(value, 8); | ||
566 | val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), &tmp); | ||
567 | val &= 0xFFFFFF00; | ||
568 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), val | value); | ||
569 | mutex_unlock(&dev->lock); | ||
570 | return ret_val; | ||
571 | } | ||
572 | |||
573 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
574 | int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | ||
575 | { | ||
576 | int ret_val = 0; | ||
577 | int value = 0; | ||
578 | u32 val = 0, tmp = 0; | ||
579 | |||
580 | mutex_lock(&dev->lock); | ||
581 | |||
582 | if((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) | ||
583 | { | ||
584 | mutex_unlock(&dev->lock); | ||
585 | return -1; | ||
586 | } | ||
587 | |||
588 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | ||
589 | val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), &tmp); | ||
590 | val &= 0xFFFFFF00; | ||
591 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), val | value); | ||
592 | |||
593 | mutex_unlock(&dev->lock); | ||
594 | return ret_val; | ||
595 | } | ||
596 | |||
597 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
598 | int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | ||
599 | { | ||
600 | int ret_val = 0; | ||
601 | int value = 0; | ||
602 | u32 val = 0, tmp = 0; | ||
603 | |||
604 | mutex_lock(&dev->lock); | ||
605 | |||
606 | if((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) | ||
607 | { | ||
608 | mutex_unlock(&dev->lock); | ||
609 | return -1; | ||
610 | } | ||
611 | |||
612 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); | ||
613 | |||
614 | value = convert_to_twos(value, 8); | ||
615 | val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), &tmp); | ||
616 | val &= 0xFFFFFF00; | ||
617 | |||
618 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), val | value); | ||
619 | |||
620 | mutex_unlock(&dev->lock); | ||
621 | return ret_val; | ||
622 | } | ||
623 | |||
624 | |||
625 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
626 | int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | ||
627 | { | ||
628 | int ret_val = 0; | ||
629 | int value = 0; | ||
630 | u32 val = 0, tmp = 0; | ||
631 | |||
632 | mutex_lock(&dev->lock); | ||
633 | |||
634 | if((saturation > VIDEO_PROCAMP_MAX) || (saturation < VIDEO_PROCAMP_MIN)) | ||
635 | { | ||
636 | mutex_unlock(&dev->lock); | ||
637 | return -1; | ||
638 | } | ||
639 | |||
640 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | ||
641 | |||
642 | val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), &tmp); | ||
643 | val &= 0xFFFFFF00; | ||
644 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), val | value); | ||
645 | |||
646 | val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), &tmp); | ||
647 | val &= 0xFFFFFF00; | ||
648 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), val | value); | ||
649 | |||
650 | mutex_unlock(&dev->lock); | ||
651 | return ret_val; | ||
652 | } | ||
653 | |||
654 | |||
655 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
656 | // Program the display sequence and monitor output. | ||
657 | // | ||
658 | int medusa_video_init(struct cx25821_dev *dev) | ||
659 | { | ||
660 | u32 value = 0, tmp = 0; | ||
661 | int ret_val = 0; | ||
662 | int i=0; | ||
663 | |||
664 | mutex_lock(&dev->lock); | ||
665 | |||
666 | _num_decoders = dev->_max_num_decoders; | ||
667 | |||
668 | |||
669 | // disable Auto source selection on all video decoders | ||
670 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | ||
671 | value &= 0xFFFFF0FF; | ||
672 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | ||
673 | |||
674 | if (ret_val < 0) | ||
675 | { | ||
676 | mutex_unlock(&dev->lock); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | |||
680 | // Turn off Master source switch enable | ||
681 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | ||
682 | value &= 0xFFFFFFDF; | ||
683 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | ||
684 | |||
685 | if (ret_val < 0) | ||
686 | { | ||
687 | mutex_unlock(&dev->lock); | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | mutex_unlock(&dev->lock); | ||
692 | |||
693 | for (i=0; i < _num_decoders; i++) | ||
694 | { | ||
695 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); | ||
696 | } | ||
697 | |||
698 | mutex_lock(&dev->lock); | ||
699 | |||
700 | // Select monitor as DENC A input, power up the DAC | ||
701 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); | ||
702 | value &= 0xFF70FF70; | ||
703 | value |= 0x00090008; // set en_active | ||
704 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); | ||
705 | |||
706 | if (ret_val < 0) | ||
707 | { | ||
708 | mutex_unlock(&dev->lock); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
712 | // enable input is VIP/656 | ||
713 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
714 | value |= 0x00040100; // enable VIP | ||
715 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
716 | |||
717 | if (ret_val < 0) | ||
718 | { | ||
719 | mutex_unlock(&dev->lock); | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | |||
723 | // select AFE clock to output mode | ||
724 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | ||
725 | value &= 0x83FFFFFF; | ||
726 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000); | ||
727 | |||
728 | if (ret_val < 0) | ||
729 | { | ||
730 | mutex_unlock(&dev->lock); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | |||
734 | // Turn on all of the data out and control output pins. | ||
735 | value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); | ||
736 | value &= 0xFEF0FE00; | ||
737 | if (_num_decoders == MAX_DECODERS) | ||
738 | { | ||
739 | // Note: The octal board does not support control pins(bit16-19). | ||
740 | // These bits are ignored in the octal board. | ||
741 | value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface | ||
742 | } | ||
743 | else | ||
744 | { | ||
745 | value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface | ||
746 | } | ||
747 | |||
748 | value |= 7; | ||
749 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); | ||
750 | if (ret_val < 0) | ||
751 | { | ||
752 | mutex_unlock(&dev->lock); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
756 | mutex_unlock(&dev->lock); | ||
757 | |||
758 | |||
759 | ret_val = medusa_set_videostandard(dev); | ||
760 | |||
761 | |||
762 | if (ret_val < 0) | ||
763 | { | ||
764 | mutex_unlock(&dev->lock); | ||
765 | return -EINVAL; | ||
766 | } | ||
767 | |||
768 | return 1; | ||
769 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.h b/drivers/staging/cx25821/cx25821-medusa-video.h new file mode 100644 index 00000000000..0ba3cc7db5a --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-video.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef _MEDUSA_VIDEO_H | ||
24 | #define _MEDUSA_VIDEO_H | ||
25 | |||
26 | #include "cx25821-medusa-defines.h" | ||
27 | |||
28 | |||
29 | // Color control constants | ||
30 | #define VIDEO_PROCAMP_MIN 0 | ||
31 | #define VIDEO_PROCAMP_MAX 10000 | ||
32 | #define UNSIGNED_BYTE_MIN 0 | ||
33 | #define UNSIGNED_BYTE_MAX 0xFF | ||
34 | #define SIGNED_BYTE_MIN -128 | ||
35 | #define SIGNED_BYTE_MAX 127 | ||
36 | |||
37 | // Default video color settings | ||
38 | #define SHARPNESS_DEFAULT 50 | ||
39 | #define SATURATION_DEFAULT 5000 | ||
40 | #define BRIGHTNESS_DEFAULT 6200 | ||
41 | #define CONTRAST_DEFAULT 5000 | ||
42 | #define HUE_DEFAULT 5000 | ||
43 | |||
44 | |||
45 | unsigned short _num_decoders; | ||
46 | unsigned short _num_cameras; | ||
47 | |||
48 | unsigned int _video_standard; | ||
49 | int _display_field_cnt[MAX_DECODERS]; | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h new file mode 100644 index 00000000000..82f4f16b831 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-reg.h | |||
@@ -0,0 +1,1609 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef __CX25821_REGISTERS__ | ||
24 | #define __CX25821_REGISTERS__ | ||
25 | |||
26 | /* Risc Instructions */ | ||
27 | #define RISC_CNT_INC 0x00010000 | ||
28 | #define RISC_CNT_RESET 0x00030000 | ||
29 | #define RISC_IRQ1 0x01000000 | ||
30 | #define RISC_IRQ2 0x02000000 | ||
31 | #define RISC_EOL 0x04000000 | ||
32 | #define RISC_SOL 0x08000000 | ||
33 | #define RISC_WRITE 0x10000000 | ||
34 | #define RISC_SKIP 0x20000000 | ||
35 | #define RISC_JUMP 0x70000000 | ||
36 | #define RISC_SYNC 0x80000000 | ||
37 | #define RISC_RESYNC 0x80008000 | ||
38 | #define RISC_READ 0x90000000 | ||
39 | #define RISC_WRITERM 0xB0000000 | ||
40 | #define RISC_WRITECM 0xC0000000 | ||
41 | #define RISC_WRITECR 0xD0000000 | ||
42 | #define RISC_WRITEC 0x50000000 | ||
43 | #define RISC_READC 0xA0000000 | ||
44 | |||
45 | #define RISC_SYNC_ODD 0x00000000 | ||
46 | #define RISC_SYNC_EVEN 0x00000200 | ||
47 | #define RISC_SYNC_ODD_VBI 0x00000006 | ||
48 | #define RISC_SYNC_EVEN_VBI 0x00000207 | ||
49 | #define RISC_NOOP 0xF0000000 | ||
50 | |||
51 | //***************************************************************************** | ||
52 | // ASB SRAM | ||
53 | //***************************************************************************** | ||
54 | #define TX_SRAM 0x000000 // Transmit SRAM | ||
55 | |||
56 | //***************************************************************************** | ||
57 | #define RX_RAM 0x010000 // Receive SRAM | ||
58 | |||
59 | //***************************************************************************** | ||
60 | // Application Layer (AL) | ||
61 | //***************************************************************************** | ||
62 | #define DEV_CNTRL2 0x040000 // Device control | ||
63 | #define FLD_RUN_RISC 0x00000020 | ||
64 | |||
65 | //***************************************************************************** | ||
66 | #define PCI_INT_MSK 0x040010 // PCI interrupt mask | ||
67 | #define PCI_INT_STAT 0x040014 // PCI interrupt status | ||
68 | #define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status | ||
69 | #define FLD_HAMMERHEAD_INT (1 << 27) | ||
70 | #define FLD_UART_INT (1 << 26) | ||
71 | #define FLD_IRQN_INT (1 << 25) | ||
72 | #define FLD_TM_INT (1 << 28) | ||
73 | #define FLD_I2C_3_RACK (1 << 27) | ||
74 | #define FLD_I2C_3_INT (1 << 26) | ||
75 | #define FLD_I2C_2_RACK (1 << 25) | ||
76 | #define FLD_I2C_2_INT (1 << 24) | ||
77 | #define FLD_I2C_1_RACK (1 << 23) | ||
78 | #define FLD_I2C_1_INT (1 << 22) | ||
79 | |||
80 | #define FLD_APB_DMA_BERR_INT (1 << 21) | ||
81 | #define FLD_AL_WR_BERR_INT (1 << 20) | ||
82 | #define FLD_AL_RD_BERR_INT (1 << 19) | ||
83 | #define FLD_RISC_WR_BERR_INT (1 << 18) | ||
84 | #define FLD_RISC_RD_BERR_INT (1 << 17) | ||
85 | |||
86 | #define FLD_VID_I_INT (1 << 8) | ||
87 | #define FLD_VID_H_INT (1 << 7) | ||
88 | #define FLD_VID_G_INT (1 << 6) | ||
89 | #define FLD_VID_F_INT (1 << 5) | ||
90 | #define FLD_VID_E_INT (1 << 4) | ||
91 | #define FLD_VID_D_INT (1 << 3) | ||
92 | #define FLD_VID_C_INT (1 << 2) | ||
93 | #define FLD_VID_B_INT (1 << 1) | ||
94 | #define FLD_VID_A_INT (1 << 0) | ||
95 | |||
96 | //***************************************************************************** | ||
97 | #define VID_A_INT_MSK 0x040020 // Video A interrupt mask | ||
98 | #define VID_A_INT_STAT 0x040024 // Video A interrupt status | ||
99 | #define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status | ||
100 | #define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status | ||
101 | |||
102 | //***************************************************************************** | ||
103 | #define VID_B_INT_MSK 0x040030 // Video B interrupt mask | ||
104 | #define VID_B_INT_STAT 0x040034 // Video B interrupt status | ||
105 | #define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status | ||
106 | #define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status | ||
107 | |||
108 | //***************************************************************************** | ||
109 | #define VID_C_INT_MSK 0x040040 // Video C interrupt mask | ||
110 | #define VID_C_INT_STAT 0x040044 // Video C interrupt status | ||
111 | #define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status | ||
112 | #define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status | ||
113 | |||
114 | //***************************************************************************** | ||
115 | #define VID_D_INT_MSK 0x040050 // Video D interrupt mask | ||
116 | #define VID_D_INT_STAT 0x040054 // Video D interrupt status | ||
117 | #define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status | ||
118 | #define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status | ||
119 | |||
120 | //***************************************************************************** | ||
121 | #define VID_E_INT_MSK 0x040060 // Video E interrupt mask | ||
122 | #define VID_E_INT_STAT 0x040064 // Video E interrupt status | ||
123 | #define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status | ||
124 | #define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status | ||
125 | |||
126 | //***************************************************************************** | ||
127 | #define VID_F_INT_MSK 0x040070 // Video F interrupt mask | ||
128 | #define VID_F_INT_STAT 0x040074 // Video F interrupt status | ||
129 | #define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status | ||
130 | #define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status | ||
131 | |||
132 | //***************************************************************************** | ||
133 | #define VID_G_INT_MSK 0x040080 // Video G interrupt mask | ||
134 | #define VID_G_INT_STAT 0x040084 // Video G interrupt status | ||
135 | #define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status | ||
136 | #define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status | ||
137 | |||
138 | //***************************************************************************** | ||
139 | #define VID_H_INT_MSK 0x040090 // Video H interrupt mask | ||
140 | #define VID_H_INT_STAT 0x040094 // Video H interrupt status | ||
141 | #define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status | ||
142 | #define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status | ||
143 | |||
144 | //***************************************************************************** | ||
145 | #define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask | ||
146 | #define VID_I_INT_STAT 0x0400A4 // Video I interrupt status | ||
147 | #define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status | ||
148 | #define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status | ||
149 | |||
150 | //***************************************************************************** | ||
151 | #define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask | ||
152 | #define VID_J_INT_STAT 0x0400B4 // Video J interrupt status | ||
153 | #define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status | ||
154 | #define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status | ||
155 | |||
156 | #define FLD_VID_SRC_OPC_ERR 0x00020000 | ||
157 | #define FLD_VID_DST_OPC_ERR 0x00010000 | ||
158 | #define FLD_VID_SRC_SYNC 0x00002000 | ||
159 | #define FLD_VID_DST_SYNC 0x00001000 | ||
160 | #define FLD_VID_SRC_UF 0x00000200 | ||
161 | #define FLD_VID_DST_OF 0x00000100 | ||
162 | #define FLD_VID_SRC_RISC2 0x00000020 | ||
163 | #define FLD_VID_DST_RISC2 0x00000010 | ||
164 | #define FLD_VID_SRC_RISC1 0x00000002 | ||
165 | #define FLD_VID_DST_RISC1 0x00000001 | ||
166 | #define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF | ||
167 | #define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF | ||
168 | |||
169 | |||
170 | //***************************************************************************** | ||
171 | #define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask | ||
172 | #define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status | ||
173 | #define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status | ||
174 | #define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status | ||
175 | |||
176 | //***************************************************************************** | ||
177 | #define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask | ||
178 | #define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status | ||
179 | #define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status | ||
180 | #define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status | ||
181 | |||
182 | //***************************************************************************** | ||
183 | #define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask | ||
184 | #define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status | ||
185 | #define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status | ||
186 | #define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status | ||
187 | |||
188 | //***************************************************************************** | ||
189 | #define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask | ||
190 | #define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status | ||
191 | #define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status | ||
192 | #define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status | ||
193 | |||
194 | //***************************************************************************** | ||
195 | #define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask | ||
196 | #define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status | ||
197 | #define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status | ||
198 | #define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status | ||
199 | |||
200 | #define FLD_AUD_SRC_OPC_ERR 0x00020000 | ||
201 | #define FLD_AUD_DST_OPC_ERR 0x00010000 | ||
202 | #define FLD_AUD_SRC_SYNC 0x00002000 | ||
203 | #define FLD_AUD_DST_SYNC 0x00001000 | ||
204 | #define FLD_AUD_SRC_OF 0x00000200 | ||
205 | #define FLD_AUD_DST_OF 0x00000100 | ||
206 | #define FLD_AUD_SRC_RISCI2 0x00000020 | ||
207 | #define FLD_AUD_DST_RISCI2 0x00000010 | ||
208 | #define FLD_AUD_SRC_RISCI1 0x00000002 | ||
209 | #define FLD_AUD_DST_RISCI1 0x00000001 | ||
210 | |||
211 | //***************************************************************************** | ||
212 | #define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask | ||
213 | #define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status | ||
214 | #define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status | ||
215 | #define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status | ||
216 | |||
217 | //***************************************************************************** | ||
218 | #define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask | ||
219 | #define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status | ||
220 | #define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status | ||
221 | #define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status | ||
222 | |||
223 | #define FLD_MBIF_DST_OPC_ERR 0x00010000 | ||
224 | #define FLD_MBIF_DST_SYNC 0x00001000 | ||
225 | #define FLD_MBIF_DST_OF 0x00000100 | ||
226 | #define FLD_MBIF_DST_RISCI2 0x00000010 | ||
227 | #define FLD_MBIF_DST_RISCI1 0x00000001 | ||
228 | |||
229 | //***************************************************************************** | ||
230 | #define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask | ||
231 | #define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status | ||
232 | #define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status | ||
233 | #define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status | ||
234 | #define FLD_AUD_EXT_OPC_ERR 0x00010000 | ||
235 | #define FLD_AUD_EXT_SYNC 0x00001000 | ||
236 | #define FLD_AUD_EXT_OF 0x00000100 | ||
237 | #define FLD_AUD_EXT_RISCI2 0x00000010 | ||
238 | #define FLD_AUD_EXT_RISCI1 0x00000001 | ||
239 | |||
240 | |||
241 | //***************************************************************************** | ||
242 | #define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] | ||
243 | #define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] | ||
244 | |||
245 | #define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] | ||
246 | #define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] | ||
247 | |||
248 | #define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask | ||
249 | #define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status | ||
250 | #define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status | ||
251 | #define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity | ||
252 | #define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity | ||
253 | |||
254 | #define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask | ||
255 | #define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status | ||
256 | #define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status | ||
257 | #define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity | ||
258 | #define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity | ||
259 | |||
260 | #define FLD_GPIO43_INT (1 << 11) | ||
261 | #define FLD_GPIO42_INT (1 << 10) | ||
262 | #define FLD_GPIO41_INT (1 << 9) | ||
263 | #define FLD_GPIO40_INT (1 << 8) | ||
264 | |||
265 | #define FLD_GPIO9_INT (1 << 9) | ||
266 | #define FLD_GPIO8_INT (1 << 8) | ||
267 | #define FLD_GPIO7_INT (1 << 7) | ||
268 | #define FLD_GPIO6_INT (1 << 6) | ||
269 | #define FLD_GPIO5_INT (1 << 5) | ||
270 | #define FLD_GPIO4_INT (1 << 4) | ||
271 | #define FLD_GPIO3_INT (1 << 3) | ||
272 | #define FLD_GPIO2_INT (1 << 2) | ||
273 | #define FLD_GPIO1_INT (1 << 1) | ||
274 | #define FLD_GPIO0_INT (1 << 0) | ||
275 | |||
276 | //***************************************************************************** | ||
277 | #define TC_REQ 0x040090 // Rider PCI Express traFFic class request | ||
278 | |||
279 | //***************************************************************************** | ||
280 | #define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set | ||
281 | |||
282 | |||
283 | //***************************************************************************** | ||
284 | // Rider | ||
285 | //***************************************************************************** | ||
286 | |||
287 | // PCI Compatible Header | ||
288 | //***************************************************************************** | ||
289 | #define RDR_CFG0 0x050000 | ||
290 | #define RDR_VENDOR_DEVICE_ID_CFG 0x050000 | ||
291 | |||
292 | //***************************************************************************** | ||
293 | #define RDR_CFG1 0x050004 | ||
294 | |||
295 | //***************************************************************************** | ||
296 | #define RDR_CFG2 0x050008 | ||
297 | |||
298 | //***************************************************************************** | ||
299 | #define RDR_CFG3 0x05000C | ||
300 | |||
301 | //***************************************************************************** | ||
302 | #define RDR_CFG4 0x050010 | ||
303 | |||
304 | //***************************************************************************** | ||
305 | #define RDR_CFG5 0x050014 | ||
306 | |||
307 | //***************************************************************************** | ||
308 | #define RDR_CFG6 0x050018 | ||
309 | |||
310 | //***************************************************************************** | ||
311 | #define RDR_CFG7 0x05001C | ||
312 | |||
313 | //***************************************************************************** | ||
314 | #define RDR_CFG8 0x050020 | ||
315 | |||
316 | //***************************************************************************** | ||
317 | #define RDR_CFG9 0x050024 | ||
318 | |||
319 | //***************************************************************************** | ||
320 | #define RDR_CFGA 0x050028 | ||
321 | |||
322 | //***************************************************************************** | ||
323 | #define RDR_CFGB 0x05002C | ||
324 | #define RDR_SUSSYSTEM_ID_CFG 0x05002C | ||
325 | |||
326 | //***************************************************************************** | ||
327 | #define RDR_CFGC 0x050030 | ||
328 | |||
329 | //***************************************************************************** | ||
330 | #define RDR_CFGD 0x050034 | ||
331 | |||
332 | //***************************************************************************** | ||
333 | #define RDR_CFGE 0x050038 | ||
334 | |||
335 | //***************************************************************************** | ||
336 | #define RDR_CFGF 0x05003C | ||
337 | |||
338 | //***************************************************************************** | ||
339 | // PCI-Express Capabilities | ||
340 | //***************************************************************************** | ||
341 | #define RDR_PECAP 0x050040 | ||
342 | |||
343 | //***************************************************************************** | ||
344 | #define RDR_PEDEVCAP 0x050044 | ||
345 | |||
346 | //***************************************************************************** | ||
347 | #define RDR_PEDEVSC 0x050048 | ||
348 | |||
349 | //***************************************************************************** | ||
350 | #define RDR_PELINKCAP 0x05004C | ||
351 | |||
352 | //***************************************************************************** | ||
353 | #define RDR_PELINKSC 0x050050 | ||
354 | |||
355 | //***************************************************************************** | ||
356 | #define RDR_PMICAP 0x050080 | ||
357 | |||
358 | //***************************************************************************** | ||
359 | #define RDR_PMCSR 0x050084 | ||
360 | |||
361 | //***************************************************************************** | ||
362 | #define RDR_VPDCAP 0x050090 | ||
363 | |||
364 | //***************************************************************************** | ||
365 | #define RDR_VPDDATA 0x050094 | ||
366 | |||
367 | //***************************************************************************** | ||
368 | #define RDR_MSICAP 0x0500A0 | ||
369 | |||
370 | //***************************************************************************** | ||
371 | #define RDR_MSIARL 0x0500A4 | ||
372 | |||
373 | //***************************************************************************** | ||
374 | #define RDR_MSIARU 0x0500A8 | ||
375 | |||
376 | //***************************************************************************** | ||
377 | #define RDR_MSIDATA 0x0500AC | ||
378 | |||
379 | //***************************************************************************** | ||
380 | // PCI Express Extended Capabilities | ||
381 | //***************************************************************************** | ||
382 | #define RDR_AERXCAP 0x050100 | ||
383 | |||
384 | //***************************************************************************** | ||
385 | #define RDR_AERUESTA 0x050104 | ||
386 | |||
387 | //***************************************************************************** | ||
388 | #define RDR_AERUEMSK 0x050108 | ||
389 | |||
390 | //***************************************************************************** | ||
391 | #define RDR_AERUESEV 0x05010C | ||
392 | |||
393 | //***************************************************************************** | ||
394 | #define RDR_AERCESTA 0x050110 | ||
395 | |||
396 | //***************************************************************************** | ||
397 | #define RDR_AERCEMSK 0x050114 | ||
398 | |||
399 | //***************************************************************************** | ||
400 | #define RDR_AERCC 0x050118 | ||
401 | |||
402 | //***************************************************************************** | ||
403 | #define RDR_AERHL0 0x05011C | ||
404 | |||
405 | //***************************************************************************** | ||
406 | #define RDR_AERHL1 0x050120 | ||
407 | |||
408 | //***************************************************************************** | ||
409 | #define RDR_AERHL2 0x050124 | ||
410 | |||
411 | //***************************************************************************** | ||
412 | #define RDR_AERHL3 0x050128 | ||
413 | |||
414 | //***************************************************************************** | ||
415 | #define RDR_VCXCAP 0x050200 | ||
416 | |||
417 | //***************************************************************************** | ||
418 | #define RDR_VCCAP1 0x050204 | ||
419 | |||
420 | //***************************************************************************** | ||
421 | #define RDR_VCCAP2 0x050208 | ||
422 | |||
423 | //***************************************************************************** | ||
424 | #define RDR_VCSC 0x05020C | ||
425 | |||
426 | //***************************************************************************** | ||
427 | #define RDR_VCR0_CAP 0x050210 | ||
428 | |||
429 | //***************************************************************************** | ||
430 | #define RDR_VCR0_CTRL 0x050214 | ||
431 | |||
432 | //***************************************************************************** | ||
433 | #define RDR_VCR0_STAT 0x050218 | ||
434 | |||
435 | //***************************************************************************** | ||
436 | #define RDR_VCR1_CAP 0x05021C | ||
437 | |||
438 | //***************************************************************************** | ||
439 | #define RDR_VCR1_CTRL 0x050220 | ||
440 | |||
441 | //***************************************************************************** | ||
442 | #define RDR_VCR1_STAT 0x050224 | ||
443 | |||
444 | //***************************************************************************** | ||
445 | #define RDR_VCR2_CAP 0x050228 | ||
446 | |||
447 | //***************************************************************************** | ||
448 | #define RDR_VCR2_CTRL 0x05022C | ||
449 | |||
450 | //***************************************************************************** | ||
451 | #define RDR_VCR2_STAT 0x050230 | ||
452 | |||
453 | //***************************************************************************** | ||
454 | #define RDR_VCR3_CAP 0x050234 | ||
455 | |||
456 | //***************************************************************************** | ||
457 | #define RDR_VCR3_CTRL 0x050238 | ||
458 | |||
459 | //***************************************************************************** | ||
460 | #define RDR_VCR3_STAT 0x05023C | ||
461 | |||
462 | //***************************************************************************** | ||
463 | #define RDR_VCARB0 0x050240 | ||
464 | |||
465 | //***************************************************************************** | ||
466 | #define RDR_VCARB1 0x050244 | ||
467 | |||
468 | //***************************************************************************** | ||
469 | #define RDR_VCARB2 0x050248 | ||
470 | |||
471 | //***************************************************************************** | ||
472 | #define RDR_VCARB3 0x05024C | ||
473 | |||
474 | //***************************************************************************** | ||
475 | #define RDR_VCARB4 0x050250 | ||
476 | |||
477 | //***************************************************************************** | ||
478 | #define RDR_VCARB5 0x050254 | ||
479 | |||
480 | //***************************************************************************** | ||
481 | #define RDR_VCARB6 0x050258 | ||
482 | |||
483 | //***************************************************************************** | ||
484 | #define RDR_VCARB7 0x05025C | ||
485 | |||
486 | //***************************************************************************** | ||
487 | #define RDR_RDRSTAT0 0x050300 | ||
488 | |||
489 | //***************************************************************************** | ||
490 | #define RDR_RDRSTAT1 0x050304 | ||
491 | |||
492 | //***************************************************************************** | ||
493 | #define RDR_RDRCTL0 0x050308 | ||
494 | |||
495 | //***************************************************************************** | ||
496 | #define RDR_RDRCTL1 0x05030C | ||
497 | |||
498 | //***************************************************************************** | ||
499 | // Transaction Layer Registers | ||
500 | //***************************************************************************** | ||
501 | #define RDR_TLSTAT0 0x050310 | ||
502 | |||
503 | //***************************************************************************** | ||
504 | #define RDR_TLSTAT1 0x050314 | ||
505 | |||
506 | //***************************************************************************** | ||
507 | #define RDR_TLCTL0 0x050318 | ||
508 | #define FLD_CFG_UR_CPL_MODE 0x00000040 | ||
509 | #define FLD_CFG_CORR_ERR_QUITE 0x00000020 | ||
510 | #define FLD_CFG_RCB_CK_EN 0x00000010 | ||
511 | #define FLD_CFG_BNDRY_CK_EN 0x00000008 | ||
512 | #define FLD_CFG_BYTE_EN_CK_EN 0x00000004 | ||
513 | #define FLD_CFG_RELAX_ORDER_MSK 0x00000002 | ||
514 | #define FLD_CFG_TAG_ORDER_EN 0x00000001 | ||
515 | |||
516 | //***************************************************************************** | ||
517 | #define RDR_TLCTL1 0x05031C | ||
518 | |||
519 | //***************************************************************************** | ||
520 | #define RDR_REQRCAL 0x050320 | ||
521 | |||
522 | //***************************************************************************** | ||
523 | #define RDR_REQRCAU 0x050324 | ||
524 | |||
525 | //***************************************************************************** | ||
526 | #define RDR_REQEPA 0x050328 | ||
527 | |||
528 | //***************************************************************************** | ||
529 | #define RDR_REQCTRL 0x05032C | ||
530 | |||
531 | //***************************************************************************** | ||
532 | #define RDR_REQSTAT 0x050330 | ||
533 | |||
534 | //***************************************************************************** | ||
535 | #define RDR_TL_TEST 0x050334 | ||
536 | |||
537 | //***************************************************************************** | ||
538 | #define RDR_VCR01_CTL 0x050348 | ||
539 | |||
540 | //***************************************************************************** | ||
541 | #define RDR_VCR23_CTL 0x05034C | ||
542 | |||
543 | //***************************************************************************** | ||
544 | #define RDR_RX_VCR0_FC 0x050350 | ||
545 | |||
546 | //***************************************************************************** | ||
547 | #define RDR_RX_VCR1_FC 0x050354 | ||
548 | |||
549 | //***************************************************************************** | ||
550 | #define RDR_RX_VCR2_FC 0x050358 | ||
551 | |||
552 | //***************************************************************************** | ||
553 | #define RDR_RX_VCR3_FC 0x05035C | ||
554 | |||
555 | //***************************************************************************** | ||
556 | // Data Link Layer Registers | ||
557 | //***************************************************************************** | ||
558 | #define RDR_DLLSTAT 0x050360 | ||
559 | |||
560 | //***************************************************************************** | ||
561 | #define RDR_DLLCTRL 0x050364 | ||
562 | |||
563 | //***************************************************************************** | ||
564 | #define RDR_REPLAYTO 0x050368 | ||
565 | |||
566 | //***************************************************************************** | ||
567 | #define RDR_ACKLATTO 0x05036C | ||
568 | |||
569 | //***************************************************************************** | ||
570 | // MAC Layer Registers | ||
571 | //***************************************************************************** | ||
572 | #define RDR_MACSTAT0 0x050380 | ||
573 | |||
574 | //***************************************************************************** | ||
575 | #define RDR_MACSTAT1 0x050384 | ||
576 | |||
577 | //***************************************************************************** | ||
578 | #define RDR_MACCTRL0 0x050388 | ||
579 | |||
580 | //***************************************************************************** | ||
581 | #define RDR_MACCTRL1 0x05038C | ||
582 | |||
583 | //***************************************************************************** | ||
584 | #define RDR_MACCTRL2 0x050390 | ||
585 | |||
586 | //***************************************************************************** | ||
587 | #define RDR_MAC_LB_DATA 0x050394 | ||
588 | |||
589 | //***************************************************************************** | ||
590 | #define RDR_L0S_EXIT_LAT 0x050398 | ||
591 | |||
592 | //***************************************************************************** | ||
593 | // DMAC | ||
594 | //***************************************************************************** | ||
595 | #define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 | ||
596 | |||
597 | //***************************************************************************** | ||
598 | #define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 | ||
599 | |||
600 | //***************************************************************************** | ||
601 | #define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 | ||
602 | |||
603 | //***************************************************************************** | ||
604 | #define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 | ||
605 | |||
606 | //***************************************************************************** | ||
607 | #define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 | ||
608 | |||
609 | //***************************************************************************** | ||
610 | #define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 | ||
611 | |||
612 | //***************************************************************************** | ||
613 | #define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 | ||
614 | |||
615 | //***************************************************************************** | ||
616 | #define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 | ||
617 | |||
618 | //***************************************************************************** | ||
619 | #define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 | ||
620 | |||
621 | //***************************************************************************** | ||
622 | #define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 | ||
623 | |||
624 | //***************************************************************************** | ||
625 | #define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 | ||
626 | |||
627 | //***************************************************************************** | ||
628 | #define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 | ||
629 | |||
630 | //***************************************************************************** | ||
631 | #define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 | ||
632 | |||
633 | //***************************************************************************** | ||
634 | #define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 | ||
635 | |||
636 | //***************************************************************************** | ||
637 | #define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 | ||
638 | |||
639 | //***************************************************************************** | ||
640 | #define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 | ||
641 | |||
642 | //***************************************************************************** | ||
643 | #define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 | ||
644 | |||
645 | //***************************************************************************** | ||
646 | #define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 | ||
647 | |||
648 | //***************************************************************************** | ||
649 | #define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 | ||
650 | |||
651 | //***************************************************************************** | ||
652 | #define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 | ||
653 | |||
654 | //***************************************************************************** | ||
655 | #define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 | ||
656 | |||
657 | //***************************************************************************** | ||
658 | #define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 | ||
659 | |||
660 | //***************************************************************************** | ||
661 | #define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 | ||
662 | |||
663 | //***************************************************************************** | ||
664 | #define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 | ||
665 | |||
666 | //***************************************************************************** | ||
667 | #define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 | ||
668 | |||
669 | //***************************************************************************** | ||
670 | #define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 | ||
671 | |||
672 | |||
673 | //***************************************************************************** | ||
674 | #define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 | ||
675 | |||
676 | //***************************************************************************** | ||
677 | #define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 | ||
678 | |||
679 | //***************************************************************************** | ||
680 | #define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 | ||
681 | |||
682 | //***************************************************************************** | ||
683 | #define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 | ||
684 | |||
685 | //***************************************************************************** | ||
686 | #define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 | ||
687 | |||
688 | //***************************************************************************** | ||
689 | #define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 | ||
690 | |||
691 | //***************************************************************************** | ||
692 | #define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 | ||
693 | |||
694 | //***************************************************************************** | ||
695 | #define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 | ||
696 | |||
697 | //***************************************************************************** | ||
698 | #define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 | ||
699 | |||
700 | //***************************************************************************** | ||
701 | #define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 | ||
702 | |||
703 | //***************************************************************************** | ||
704 | #define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 | ||
705 | |||
706 | //***************************************************************************** | ||
707 | #define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 | ||
708 | |||
709 | //***************************************************************************** | ||
710 | #define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 | ||
711 | |||
712 | //***************************************************************************** | ||
713 | #define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 | ||
714 | |||
715 | //***************************************************************************** | ||
716 | #define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 | ||
717 | |||
718 | //***************************************************************************** | ||
719 | #define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 | ||
720 | |||
721 | //***************************************************************************** | ||
722 | #define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 | ||
723 | |||
724 | //***************************************************************************** | ||
725 | #define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 | ||
726 | |||
727 | //***************************************************************************** | ||
728 | #define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 | ||
729 | |||
730 | //***************************************************************************** | ||
731 | #define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 | ||
732 | |||
733 | //***************************************************************************** | ||
734 | #define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 | ||
735 | |||
736 | //***************************************************************************** | ||
737 | #define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 | ||
738 | |||
739 | //***************************************************************************** | ||
740 | #define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 | ||
741 | |||
742 | //***************************************************************************** | ||
743 | #define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 | ||
744 | |||
745 | //***************************************************************************** | ||
746 | #define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 | ||
747 | |||
748 | //***************************************************************************** | ||
749 | #define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 | ||
750 | |||
751 | |||
752 | |||
753 | //***************************************************************************** | ||
754 | #define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 | ||
755 | |||
756 | //***************************************************************************** | ||
757 | #define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 | ||
758 | |||
759 | //***************************************************************************** | ||
760 | #define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 | ||
761 | |||
762 | //***************************************************************************** | ||
763 | #define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 | ||
764 | |||
765 | //***************************************************************************** | ||
766 | #define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 | ||
767 | |||
768 | //***************************************************************************** | ||
769 | #define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 | ||
770 | |||
771 | //***************************************************************************** | ||
772 | #define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 | ||
773 | |||
774 | //***************************************************************************** | ||
775 | #define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 | ||
776 | |||
777 | //***************************************************************************** | ||
778 | #define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 | ||
779 | |||
780 | //***************************************************************************** | ||
781 | #define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 | ||
782 | |||
783 | //***************************************************************************** | ||
784 | #define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 | ||
785 | |||
786 | //***************************************************************************** | ||
787 | #define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 | ||
788 | |||
789 | //***************************************************************************** | ||
790 | #define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 | ||
791 | |||
792 | //***************************************************************************** | ||
793 | #define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 | ||
794 | |||
795 | //***************************************************************************** | ||
796 | #define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 | ||
797 | |||
798 | //***************************************************************************** | ||
799 | #define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 | ||
800 | |||
801 | //***************************************************************************** | ||
802 | #define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 | ||
803 | |||
804 | //***************************************************************************** | ||
805 | #define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 | ||
806 | |||
807 | //***************************************************************************** | ||
808 | #define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 | ||
809 | |||
810 | //***************************************************************************** | ||
811 | #define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 | ||
812 | |||
813 | //***************************************************************************** | ||
814 | #define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 | ||
815 | |||
816 | //***************************************************************************** | ||
817 | #define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 | ||
818 | |||
819 | //***************************************************************************** | ||
820 | #define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 | ||
821 | |||
822 | //***************************************************************************** | ||
823 | #define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 | ||
824 | |||
825 | //***************************************************************************** | ||
826 | #define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 | ||
827 | |||
828 | //***************************************************************************** | ||
829 | #define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 | ||
830 | |||
831 | |||
832 | //***************************************************************************** | ||
833 | #define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 | ||
834 | |||
835 | //***************************************************************************** | ||
836 | #define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 | ||
837 | |||
838 | //***************************************************************************** | ||
839 | #define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 | ||
840 | |||
841 | //***************************************************************************** | ||
842 | #define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 | ||
843 | |||
844 | //***************************************************************************** | ||
845 | #define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 | ||
846 | |||
847 | //***************************************************************************** | ||
848 | #define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 | ||
849 | |||
850 | //***************************************************************************** | ||
851 | #define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 | ||
852 | |||
853 | //***************************************************************************** | ||
854 | #define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 | ||
855 | |||
856 | //***************************************************************************** | ||
857 | #define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 | ||
858 | |||
859 | //***************************************************************************** | ||
860 | #define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 | ||
861 | |||
862 | //***************************************************************************** | ||
863 | #define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 | ||
864 | |||
865 | //***************************************************************************** | ||
866 | #define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 | ||
867 | |||
868 | //***************************************************************************** | ||
869 | #define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 | ||
870 | |||
871 | //***************************************************************************** | ||
872 | #define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 | ||
873 | |||
874 | //***************************************************************************** | ||
875 | #define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 | ||
876 | |||
877 | //***************************************************************************** | ||
878 | #define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 | ||
879 | |||
880 | //***************************************************************************** | ||
881 | #define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 | ||
882 | |||
883 | //***************************************************************************** | ||
884 | #define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 | ||
885 | |||
886 | //***************************************************************************** | ||
887 | #define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 | ||
888 | |||
889 | //***************************************************************************** | ||
890 | #define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 | ||
891 | |||
892 | //***************************************************************************** | ||
893 | #define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 | ||
894 | |||
895 | //***************************************************************************** | ||
896 | #define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 | ||
897 | |||
898 | //***************************************************************************** | ||
899 | #define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 | ||
900 | |||
901 | //***************************************************************************** | ||
902 | #define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 | ||
903 | |||
904 | //***************************************************************************** | ||
905 | #define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 | ||
906 | |||
907 | //***************************************************************************** | ||
908 | #define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 | ||
909 | |||
910 | |||
911 | |||
912 | //***************************************************************************** | ||
913 | // ITG | ||
914 | //***************************************************************************** | ||
915 | #define TM_CNT_LDW 0x110000 // Timer : Counter low | ||
916 | |||
917 | //***************************************************************************** | ||
918 | #define TM_CNT_UW 0x110004 // Timer : Counter high word | ||
919 | |||
920 | //***************************************************************************** | ||
921 | #define TM_LMT_LDW 0x110008 // Timer : Limit low | ||
922 | |||
923 | //***************************************************************************** | ||
924 | #define TM_LMT_UW 0x11000C // Timer : Limit high word | ||
925 | |||
926 | //***************************************************************************** | ||
927 | #define GP0_IO 0x110010 // GPIO output enables data I/O | ||
928 | #define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable | ||
929 | #define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status | ||
930 | #define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control | ||
931 | |||
932 | //***************************************************************************** | ||
933 | #define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode | ||
934 | #define FLD_GP_ISM_SNS 0x00000070 | ||
935 | #define FLD_GP_ISM_POL 0x00000007 | ||
936 | |||
937 | //***************************************************************************** | ||
938 | #define SOFT_RESET 0x11001C // Output system reset reg | ||
939 | #define FLD_PECOS_SOFT_RESET 0x00000001 | ||
940 | |||
941 | //***************************************************************************** | ||
942 | #define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin | ||
943 | #define MC416_OEN 0x110024 // Output enable of GPIO[18:3] | ||
944 | #define MC416_CTL 0x110028 | ||
945 | |||
946 | //***************************************************************************** | ||
947 | #define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select | ||
948 | |||
949 | #define FLD_ALT_GPIO_OUT_SEL 0xF0000000 | ||
950 | // 0 Disabled <-- default | ||
951 | // 1 GPIO[0] | ||
952 | // 2 GPIO[10] | ||
953 | // 3 VIP_656_DATA_VAL | ||
954 | // 4 VIP_656_DATA[0] | ||
955 | // 5 VIP_656_CLK | ||
956 | // 6 VIP_656_DATA_EXT[1] | ||
957 | // 7 VIP_656_DATA_EXT[0] | ||
958 | // 8 ATT_IF | ||
959 | |||
960 | #define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 | ||
961 | // 0 AUX_PLL_CLK<-- default | ||
962 | // 1 GPIO[2] | ||
963 | // 2 GPIO[10] | ||
964 | // 3 VIP_656_DATA_VAL | ||
965 | // 4 VIP_656_DATA[0] | ||
966 | // 5 VIP_656_CLK | ||
967 | // 6 VIP_656_DATA_EXT[1] | ||
968 | // 7 VIP_656_DATA_EXT[0] | ||
969 | |||
970 | #define FLD_IR_TX_ALT_SEL 0x00F00000 | ||
971 | // 0 IR_TX <-- default | ||
972 | // 1 GPIO[1] | ||
973 | // 2 GPIO[10] | ||
974 | // 3 VIP_656_DATA_VAL | ||
975 | // 4 VIP_656_DATA[0] | ||
976 | // 5 VIP_656_CLK | ||
977 | // 6 VIP_656_DATA_EXT[1] | ||
978 | // 7 VIP_656_DATA_EXT[0] | ||
979 | |||
980 | #define FLD_IR_RX_ALT_SEL 0x000F0000 | ||
981 | // 0 IR_RX <-- default | ||
982 | // 1 GPIO[0] | ||
983 | // 2 GPIO[10] | ||
984 | // 3 VIP_656_DATA_VAL | ||
985 | // 4 VIP_656_DATA[0] | ||
986 | // 5 VIP_656_CLK | ||
987 | // 6 VIP_656_DATA_EXT[1] | ||
988 | // 7 VIP_656_DATA_EXT[0] | ||
989 | |||
990 | #define FLD_GPIO10_ALT_SEL 0x0000F000 | ||
991 | // 0 GPIO[10] <-- default | ||
992 | // 1 GPIO[0] | ||
993 | // 2 GPIO[10] | ||
994 | // 3 VIP_656_DATA_VAL | ||
995 | // 4 VIP_656_DATA[0] | ||
996 | // 5 VIP_656_CLK | ||
997 | // 6 VIP_656_DATA_EXT[1] | ||
998 | // 7 VIP_656_DATA_EXT[0] | ||
999 | |||
1000 | #define FLD_GPIO2_ALT_SEL 0x00000F00 | ||
1001 | // 0 GPIO[2] <-- default | ||
1002 | // 1 GPIO[1] | ||
1003 | // 2 GPIO[10] | ||
1004 | // 3 VIP_656_DATA_VAL | ||
1005 | // 4 VIP_656_DATA[0] | ||
1006 | // 5 VIP_656_CLK | ||
1007 | // 6 VIP_656_DATA_EXT[1] | ||
1008 | // 7 VIP_656_DATA_EXT[0] | ||
1009 | |||
1010 | #define FLD_GPIO1_ALT_SEL 0x000000F0 | ||
1011 | // 0 GPIO[1] <-- default | ||
1012 | // 1 GPIO[0] | ||
1013 | // 2 GPIO[10] | ||
1014 | // 3 VIP_656_DATA_VAL | ||
1015 | // 4 VIP_656_DATA[0] | ||
1016 | // 5 VIP_656_CLK | ||
1017 | // 6 VIP_656_DATA_EXT[1] | ||
1018 | // 7 VIP_656_DATA_EXT[0] | ||
1019 | |||
1020 | #define FLD_GPIO0_ALT_SEL 0x0000000F | ||
1021 | // 0 GPIO[0] <-- default | ||
1022 | // 1 GPIO[1] | ||
1023 | // 2 GPIO[10] | ||
1024 | // 3 VIP_656_DATA_VAL | ||
1025 | // 4 VIP_656_DATA[0] | ||
1026 | // 5 VIP_656_CLK | ||
1027 | // 6 VIP_656_DATA_EXT[1] | ||
1028 | // 7 VIP_656_DATA_EXT[0] | ||
1029 | |||
1030 | #define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select | ||
1031 | |||
1032 | #define FLD_GPIO10_ALT_IN_SEL 0x0000F000 | ||
1033 | // 0 GPIO[10] <-- default | ||
1034 | // 1 IR_RX | ||
1035 | // 2 IR_TX | ||
1036 | // 3 AUX_PLL_CLK | ||
1037 | // 4 IF_ATT_SEL | ||
1038 | // 5 GPIO[0] | ||
1039 | // 6 GPIO[1] | ||
1040 | // 7 GPIO[2] | ||
1041 | |||
1042 | #define FLD_GPIO2_ALT_IN_SEL 0x00000F00 | ||
1043 | // 0 GPIO[2] <-- default | ||
1044 | // 1 IR_RX | ||
1045 | // 2 IR_TX | ||
1046 | // 3 AUX_PLL_CLK | ||
1047 | // 4 IF_ATT_SEL | ||
1048 | |||
1049 | #define FLD_GPIO1_ALT_IN_SEL 0x000000F0 | ||
1050 | // 0 GPIO[1] <-- default | ||
1051 | // 1 IR_RX | ||
1052 | // 2 IR_TX | ||
1053 | // 3 AUX_PLL_CLK | ||
1054 | // 4 IF_ATT_SEL | ||
1055 | |||
1056 | #define FLD_GPIO0_ALT_IN_SEL 0x0000000F | ||
1057 | // 0 GPIO[0] <-- default | ||
1058 | // 1 IR_RX | ||
1059 | // 2 IR_TX | ||
1060 | // 3 AUX_PLL_CLK | ||
1061 | // 4 IF_ATT_SEL | ||
1062 | |||
1063 | //***************************************************************************** | ||
1064 | #define TEST_BUS_CTL1 0x110040 // Test bus control register #1 | ||
1065 | |||
1066 | //***************************************************************************** | ||
1067 | #define TEST_BUS_CTL2 0x110044 // Test bus control register #2 | ||
1068 | |||
1069 | //***************************************************************************** | ||
1070 | #define CLK_DELAY 0x110048 // Clock delay | ||
1071 | #define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock | ||
1072 | |||
1073 | |||
1074 | //***************************************************************************** | ||
1075 | #define PAD_CTRL 0x110068 // Pad drive strength control | ||
1076 | |||
1077 | //***************************************************************************** | ||
1078 | #define MBIST_CTRL 0x110050 // SRAM memory built-in self test control | ||
1079 | |||
1080 | //***************************************************************************** | ||
1081 | #define MBIST_STAT 0x110054 // SRAM memory built-in self test status | ||
1082 | |||
1083 | //***************************************************************************** | ||
1084 | // PLL registers | ||
1085 | //***************************************************************************** | ||
1086 | #define PLL_A_INT_FRAC 0x110088 | ||
1087 | #define PLL_A_POST_STAT_BIST 0x11008C | ||
1088 | #define PLL_B_INT_FRAC 0x110090 | ||
1089 | #define PLL_B_POST_STAT_BIST 0x110094 | ||
1090 | #define PLL_C_INT_FRAC 0x110098 | ||
1091 | #define PLL_C_POST_STAT_BIST 0x11009C | ||
1092 | #define PLL_D_INT_FRAC 0x1100A0 | ||
1093 | #define PLL_D_POST_STAT_BIST 0x1100A4 | ||
1094 | |||
1095 | #define CLK_RST 0x11002C | ||
1096 | #define FLD_VID_I_CLK_NOE 0x00001000 | ||
1097 | #define FLD_VID_J_CLK_NOE 0x00002000 | ||
1098 | #define FLD_USE_ALT_PLL_REF 0x00004000 | ||
1099 | |||
1100 | #define VID_CH_MODE_SEL 0x110078 | ||
1101 | #define VID_CH_CLK_SEL 0x11007C | ||
1102 | |||
1103 | |||
1104 | //***************************************************************************** | ||
1105 | #define VBI_A_DMA 0x130008 // VBI A DMA data port | ||
1106 | |||
1107 | //***************************************************************************** | ||
1108 | #define VID_A_VIP_CTL 0x130080 // Video A VIP format control | ||
1109 | #define FLD_VIP_MODE 0x00000001 | ||
1110 | |||
1111 | //***************************************************************************** | ||
1112 | #define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format | ||
1113 | #define FLD_VID_A_GAMMA_DIS 0x00000008 | ||
1114 | #define FLD_VID_A_FORMAT 0x00000007 | ||
1115 | #define FLD_VID_A_GAMMA_FACTOR 0x00000010 | ||
1116 | |||
1117 | //***************************************************************************** | ||
1118 | #define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control | ||
1119 | #define FLD_VID_A_VIP_EXT 0x00000003 | ||
1120 | |||
1121 | //***************************************************************************** | ||
1122 | #define VID_B_DMA 0x130100 // Video B DMA data port | ||
1123 | |||
1124 | //***************************************************************************** | ||
1125 | #define VBI_B_DMA 0x130108 // VBI B DMA data port | ||
1126 | |||
1127 | //***************************************************************************** | ||
1128 | #define VID_B_SRC_SEL 0x130144 // Video B source select | ||
1129 | #define FLD_VID_B_SRC_SEL 0x00000000 | ||
1130 | |||
1131 | //***************************************************************************** | ||
1132 | #define VID_B_LNGTH 0x130150 // Video B line length | ||
1133 | #define FLD_VID_B_LN_LNGTH 0x00000FFF | ||
1134 | |||
1135 | //***************************************************************************** | ||
1136 | #define VID_B_VIP_CTL 0x130180 // Video B VIP format control | ||
1137 | |||
1138 | //***************************************************************************** | ||
1139 | #define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format | ||
1140 | #define FLD_VID_B_GAMMA_DIS 0x00000008 | ||
1141 | #define FLD_VID_B_FORMAT 0x00000007 | ||
1142 | #define FLD_VID_B_GAMMA_FACTOR 0x00000010 | ||
1143 | |||
1144 | //***************************************************************************** | ||
1145 | #define VID_C_DMA 0x130200 // Video C DMA data port | ||
1146 | |||
1147 | //***************************************************************************** | ||
1148 | #define VID_C_LNGTH 0x130250 // Video C line length | ||
1149 | #define FLD_VID_C_LN_LNGTH 0x00000FFF | ||
1150 | |||
1151 | |||
1152 | //***************************************************************************** | ||
1153 | // Video Destination Channels | ||
1154 | //***************************************************************************** | ||
1155 | |||
1156 | #define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter | ||
1157 | #define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter | ||
1158 | #define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter | ||
1159 | #define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter | ||
1160 | #define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter | ||
1161 | #define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter | ||
1162 | #define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter | ||
1163 | #define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter | ||
1164 | |||
1165 | //***************************************************************************** | ||
1166 | |||
1167 | #define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control | ||
1168 | #define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control | ||
1169 | #define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control | ||
1170 | #define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control | ||
1171 | #define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control | ||
1172 | #define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control | ||
1173 | #define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control | ||
1174 | #define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control | ||
1175 | |||
1176 | |||
1177 | //***************************************************************************** | ||
1178 | |||
1179 | #define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control | ||
1180 | #define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control | ||
1181 | #define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control | ||
1182 | #define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control | ||
1183 | #define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control | ||
1184 | #define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control | ||
1185 | #define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control | ||
1186 | #define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control | ||
1187 | |||
1188 | #define FLD_VID_RISC_EN 0x00000010 | ||
1189 | #define FLD_VID_FIFO_EN 0x00000001 | ||
1190 | |||
1191 | //***************************************************************************** | ||
1192 | |||
1193 | #define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control | ||
1194 | #define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control | ||
1195 | #define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control | ||
1196 | #define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control | ||
1197 | #define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control | ||
1198 | #define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control | ||
1199 | #define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control | ||
1200 | #define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control | ||
1201 | |||
1202 | //***************************************************************************** | ||
1203 | |||
1204 | #define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format | ||
1205 | #define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format | ||
1206 | #define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format | ||
1207 | #define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format | ||
1208 | #define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format | ||
1209 | #define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format | ||
1210 | #define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format | ||
1211 | #define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format | ||
1212 | |||
1213 | //***************************************************************************** | ||
1214 | // Video Source Channels | ||
1215 | //***************************************************************************** | ||
1216 | |||
1217 | #define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control | ||
1218 | #define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control | ||
1219 | #define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control | ||
1220 | #define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control | ||
1221 | #define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control | ||
1222 | #define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control | ||
1223 | #define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control | ||
1224 | #define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control | ||
1225 | |||
1226 | //***************************************************************************** | ||
1227 | |||
1228 | #define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter | ||
1229 | #define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter | ||
1230 | #define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter | ||
1231 | #define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter | ||
1232 | #define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter | ||
1233 | #define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter | ||
1234 | #define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter | ||
1235 | #define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter | ||
1236 | |||
1237 | //***************************************************************************** | ||
1238 | |||
1239 | #define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control | ||
1240 | #define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control | ||
1241 | #define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control | ||
1242 | #define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control | ||
1243 | #define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control | ||
1244 | #define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control | ||
1245 | #define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control | ||
1246 | #define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control | ||
1247 | |||
1248 | #define FLD_APB_RISC_EN 0x00000010 | ||
1249 | #define FLD_APB_FIFO_EN 0x00000001 | ||
1250 | |||
1251 | //***************************************************************************** | ||
1252 | |||
1253 | #define VID_SRC_A_FMT_CTL 0x130810 // Video A format control | ||
1254 | #define VID_SRC_B_FMT_CTL 0x130910 // Video B format control | ||
1255 | #define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control | ||
1256 | #define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control | ||
1257 | #define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control | ||
1258 | #define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control | ||
1259 | #define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control | ||
1260 | #define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control | ||
1261 | |||
1262 | //***************************************************************************** | ||
1263 | |||
1264 | #define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 | ||
1265 | #define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 | ||
1266 | #define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 | ||
1267 | #define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 | ||
1268 | #define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 | ||
1269 | #define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 | ||
1270 | #define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 | ||
1271 | #define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 | ||
1272 | |||
1273 | //***************************************************************************** | ||
1274 | |||
1275 | #define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 | ||
1276 | #define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 | ||
1277 | #define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 | ||
1278 | #define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 | ||
1279 | #define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 | ||
1280 | #define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 | ||
1281 | #define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 | ||
1282 | #define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 | ||
1283 | |||
1284 | //***************************************************************************** | ||
1285 | |||
1286 | #define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size | ||
1287 | #define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size | ||
1288 | #define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size | ||
1289 | #define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size | ||
1290 | #define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size | ||
1291 | #define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size | ||
1292 | #define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size | ||
1293 | #define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size | ||
1294 | |||
1295 | //***************************************************************************** | ||
1296 | // Audio I/F | ||
1297 | //***************************************************************************** | ||
1298 | #define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port | ||
1299 | #define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port | ||
1300 | |||
1301 | #define AUD_A_GPCNT 0x140010 // Audio Int A gp counter | ||
1302 | #define FLD_AUD_A_GP_CNT 0x0000FFFF | ||
1303 | |||
1304 | #define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control | ||
1305 | |||
1306 | #define AUD_A_LNGTH 0x140018 // Audio Int A line length | ||
1307 | |||
1308 | #define AUD_A_CFG 0x14001C // Audio Int A configuration | ||
1309 | |||
1310 | //***************************************************************************** | ||
1311 | #define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port | ||
1312 | #define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port | ||
1313 | |||
1314 | #define AUD_B_GPCNT 0x140110 // Audio Int B gp counter | ||
1315 | #define FLD_AUD_B_GP_CNT 0x0000FFFF | ||
1316 | |||
1317 | #define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control | ||
1318 | |||
1319 | #define AUD_B_LNGTH 0x140118 // Audio Int B line length | ||
1320 | |||
1321 | #define AUD_B_CFG 0x14011C // Audio Int B configuration | ||
1322 | |||
1323 | //***************************************************************************** | ||
1324 | #define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port | ||
1325 | #define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port | ||
1326 | |||
1327 | #define AUD_C_GPCNT 0x140210 // Audio Int C gp counter | ||
1328 | #define FLD_AUD_C_GP_CNT 0x0000FFFF | ||
1329 | |||
1330 | #define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control | ||
1331 | |||
1332 | #define AUD_C_LNGTH 0x140218 // Audio Int C line length | ||
1333 | |||
1334 | #define AUD_C_CFG 0x14021C // Audio Int C configuration | ||
1335 | |||
1336 | //***************************************************************************** | ||
1337 | #define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port | ||
1338 | #define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port | ||
1339 | |||
1340 | #define AUD_D_GPCNT 0x140310 // Audio Int D gp counter | ||
1341 | #define FLD_AUD_D_GP_CNT 0x0000FFFF | ||
1342 | |||
1343 | #define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control | ||
1344 | |||
1345 | #define AUD_D_LNGTH 0x140318 // Audio Int D line length | ||
1346 | |||
1347 | #define AUD_D_CFG 0x14031C // Audio Int D configuration | ||
1348 | |||
1349 | //***************************************************************************** | ||
1350 | #define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port | ||
1351 | |||
1352 | #define AUD_E_GPCNT 0x140410 // Audio Int E gp counter | ||
1353 | #define FLD_AUD_E_GP_CNT 0x0000FFFF | ||
1354 | |||
1355 | #define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control | ||
1356 | |||
1357 | #define AUD_E_CFG 0x14041C // Audio Int E configuration | ||
1358 | |||
1359 | //***************************************************************************** | ||
1360 | |||
1361 | #define FLD_AUD_DST_LN_LNGTH 0x00000FFF | ||
1362 | |||
1363 | #define FLD_AUD_DST_PK_MODE 0x00004000 | ||
1364 | |||
1365 | #define FLD_AUD_CLK_ENABLE 0x00000200 | ||
1366 | |||
1367 | #define FLD_AUD_MASTER_MODE 0x00000002 | ||
1368 | |||
1369 | #define FLD_AUD_SONY_MODE 0x00000001 | ||
1370 | |||
1371 | #define FLD_AUD_CLK_SELECT_PLL_D 0x00001800 | ||
1372 | |||
1373 | #define FLD_AUD_DST_ENABLE 0x00020000 | ||
1374 | |||
1375 | #define FLD_AUD_SRC_ENABLE 0x00010000 | ||
1376 | |||
1377 | //***************************************************************************** | ||
1378 | #define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control | ||
1379 | |||
1380 | #define FLD_AUD_SRC_E_RISC_EN 0x00008000 | ||
1381 | #define FLD_AUD_SRC_C_RISC_EN 0x00004000 | ||
1382 | #define FLD_AUD_SRC_B_RISC_EN 0x00002000 | ||
1383 | #define FLD_AUD_SRC_A_RISC_EN 0x00001000 | ||
1384 | |||
1385 | #define FLD_AUD_DST_D_RISC_EN 0x00000800 | ||
1386 | #define FLD_AUD_DST_C_RISC_EN 0x00000400 | ||
1387 | #define FLD_AUD_DST_B_RISC_EN 0x00000200 | ||
1388 | #define FLD_AUD_DST_A_RISC_EN 0x00000100 | ||
1389 | |||
1390 | #define FLD_AUD_SRC_E_FIFO_EN 0x00000080 | ||
1391 | #define FLD_AUD_SRC_C_FIFO_EN 0x00000040 | ||
1392 | #define FLD_AUD_SRC_B_FIFO_EN 0x00000020 | ||
1393 | #define FLD_AUD_SRC_A_FIFO_EN 0x00000010 | ||
1394 | |||
1395 | #define FLD_AUD_DST_D_FIFO_EN 0x00000008 | ||
1396 | #define FLD_AUD_DST_C_FIFO_EN 0x00000004 | ||
1397 | #define FLD_AUD_DST_B_FIFO_EN 0x00000002 | ||
1398 | #define FLD_AUD_DST_A_FIFO_EN 0x00000001 | ||
1399 | |||
1400 | |||
1401 | //***************************************************************************** | ||
1402 | // | ||
1403 | // Mobilygen Interface Registers | ||
1404 | // | ||
1405 | //***************************************************************************** | ||
1406 | // Mobilygen Interface A | ||
1407 | //***************************************************************************** | ||
1408 | #define MB_IF_A_DMA 0x150000 // MBIF A DMA data port | ||
1409 | #define MB_IF_A_GPCN 0x150008 // MBIF A GP counter | ||
1410 | #define MB_IF_A_GPCN_CTRL 0x15000C | ||
1411 | #define MB_IF_A_DMA_CTRL 0x150010 | ||
1412 | #define MB_IF_A_LENGTH 0x150014 | ||
1413 | #define MB_IF_A_HDMA_XFER_SZ 0x150018 | ||
1414 | #define MB_IF_A_HCMD 0x15001C | ||
1415 | #define MB_IF_A_HCONFIG 0x150020 | ||
1416 | #define MB_IF_A_DATA_STRUCT_0 0x150024 | ||
1417 | #define MB_IF_A_DATA_STRUCT_1 0x150028 | ||
1418 | #define MB_IF_A_DATA_STRUCT_2 0x15002C | ||
1419 | #define MB_IF_A_DATA_STRUCT_3 0x150030 | ||
1420 | #define MB_IF_A_DATA_STRUCT_4 0x150034 | ||
1421 | #define MB_IF_A_DATA_STRUCT_5 0x150038 | ||
1422 | #define MB_IF_A_DATA_STRUCT_6 0x15003C | ||
1423 | #define MB_IF_A_DATA_STRUCT_7 0x150040 | ||
1424 | #define MB_IF_A_DATA_STRUCT_8 0x150044 | ||
1425 | #define MB_IF_A_DATA_STRUCT_9 0x150048 | ||
1426 | #define MB_IF_A_DATA_STRUCT_A 0x15004C | ||
1427 | #define MB_IF_A_DATA_STRUCT_B 0x150050 | ||
1428 | #define MB_IF_A_DATA_STRUCT_C 0x150054 | ||
1429 | #define MB_IF_A_DATA_STRUCT_D 0x150058 | ||
1430 | #define MB_IF_A_DATA_STRUCT_E 0x15005C | ||
1431 | #define MB_IF_A_DATA_STRUCT_F 0x150060 | ||
1432 | //***************************************************************************** | ||
1433 | // Mobilygen Interface B | ||
1434 | //***************************************************************************** | ||
1435 | #define MB_IF_B_DMA 0x160000 // MBIF A DMA data port | ||
1436 | #define MB_IF_B_GPCN 0x160008 // MBIF A GP counter | ||
1437 | #define MB_IF_B_GPCN_CTRL 0x16000C | ||
1438 | #define MB_IF_B_DMA_CTRL 0x160010 | ||
1439 | #define MB_IF_B_LENGTH 0x160014 | ||
1440 | #define MB_IF_B_HDMA_XFER_SZ 0x160018 | ||
1441 | #define MB_IF_B_HCMD 0x16001C | ||
1442 | #define MB_IF_B_HCONFIG 0x160020 | ||
1443 | #define MB_IF_B_DATA_STRUCT_0 0x160024 | ||
1444 | #define MB_IF_B_DATA_STRUCT_1 0x160028 | ||
1445 | #define MB_IF_B_DATA_STRUCT_2 0x16002C | ||
1446 | #define MB_IF_B_DATA_STRUCT_3 0x160030 | ||
1447 | #define MB_IF_B_DATA_STRUCT_4 0x160034 | ||
1448 | #define MB_IF_B_DATA_STRUCT_5 0x160038 | ||
1449 | #define MB_IF_B_DATA_STRUCT_6 0x16003C | ||
1450 | #define MB_IF_B_DATA_STRUCT_7 0x160040 | ||
1451 | #define MB_IF_B_DATA_STRUCT_8 0x160044 | ||
1452 | #define MB_IF_B_DATA_STRUCT_9 0x160048 | ||
1453 | #define MB_IF_B_DATA_STRUCT_A 0x16004C | ||
1454 | #define MB_IF_B_DATA_STRUCT_B 0x160050 | ||
1455 | #define MB_IF_B_DATA_STRUCT_C 0x160054 | ||
1456 | #define MB_IF_B_DATA_STRUCT_D 0x160058 | ||
1457 | #define MB_IF_B_DATA_STRUCT_E 0x16005C | ||
1458 | #define MB_IF_B_DATA_STRUCT_F 0x160060 | ||
1459 | |||
1460 | // MB_DMA_CTRL | ||
1461 | #define FLD_MB_IF_RISC_EN 0x00000010 | ||
1462 | #define FLD_MB_IF_FIFO_EN 0x00000001 | ||
1463 | |||
1464 | // MB_LENGTH | ||
1465 | #define FLD_MB_IF_LN_LNGTH 0x00000FFF | ||
1466 | |||
1467 | // MB_HCMD register | ||
1468 | #define FLD_MB_HCMD_H_GO 0x80000000 | ||
1469 | #define FLD_MB_HCMD_H_BUSY 0x40000000 | ||
1470 | #define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 | ||
1471 | #define FLD_MB_HCMD_H_DMA_BUSY 0x08000000 | ||
1472 | #define FLD_MB_HCMD_H_DMA_TYPE 0x04000000 | ||
1473 | #define FLD_MB_HCMD_H_DMA_XACT 0x02000000 | ||
1474 | #define FLD_MB_HCMD_H_RW_N 0x01000000 | ||
1475 | #define FLD_MB_HCMD_H_ADDR 0x00FF0000 | ||
1476 | #define FLD_MB_HCMD_H_DATA 0x0000FFFF | ||
1477 | |||
1478 | |||
1479 | //***************************************************************************** | ||
1480 | // I2C #1 | ||
1481 | //***************************************************************************** | ||
1482 | #define I2C1_ADDR 0x180000 // I2C #1 address | ||
1483 | #define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address | ||
1484 | // RO [24] reserved | ||
1485 | //***************************************************************************** | ||
1486 | #define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address | ||
1487 | |||
1488 | //***************************************************************************** | ||
1489 | #define I2C1_WDATA 0x180004 // I2C #1 write data | ||
1490 | #define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] | ||
1491 | |||
1492 | //***************************************************************************** | ||
1493 | #define I2C1_CTRL 0x180008 // I2C #1 control | ||
1494 | #define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] | ||
1495 | #define FLD_I2C_SCL_IN 0x00200000 // RW [21] | ||
1496 | #define FLD_I2C_SDA_IN 0x00100000 // RW [20] | ||
1497 | // RO [19:18] reserved | ||
1498 | #define FLD_I2C_SCL_OUT 0x00020000 // RW [17] | ||
1499 | #define FLD_I2C_SDA_OUT 0x00010000 // RW [16] | ||
1500 | // RO [15] reserved | ||
1501 | #define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] | ||
1502 | #define FLD_I2C_SADDR_INC 0x00000800 // RW [11] | ||
1503 | // RO [10:9] reserved | ||
1504 | #define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] | ||
1505 | // RO [7:6] reserved | ||
1506 | #define FLD_I2C_SOFT 0x00000020 // RW [5] | ||
1507 | #define FLD_I2C_NOSTOP 0x00000010 // RW [4] | ||
1508 | #define FLD_I2C_EXTEND 0x00000008 // RW [3] | ||
1509 | #define FLD_I2C_SYNC 0x00000004 // RW [2] | ||
1510 | #define FLD_I2C_READ_SA 0x00000002 // RW [1] | ||
1511 | #define FLD_I2C_READ_WRN 0x00000001 // RW [0] | ||
1512 | |||
1513 | //***************************************************************************** | ||
1514 | #define I2C1_RDATA 0x18000C // I2C #1 read data | ||
1515 | #define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] | ||
1516 | |||
1517 | //***************************************************************************** | ||
1518 | #define I2C1_STAT 0x180010 // I2C #1 status | ||
1519 | #define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] | ||
1520 | #define FLD_I2C_RACK 0x00000001 // RO [0] | ||
1521 | |||
1522 | //***************************************************************************** | ||
1523 | // I2C #2 | ||
1524 | //***************************************************************************** | ||
1525 | #define I2C2_ADDR 0x190000 // I2C #2 address | ||
1526 | |||
1527 | //***************************************************************************** | ||
1528 | #define I2C2_WDATA 0x190004 // I2C #2 write data | ||
1529 | |||
1530 | //***************************************************************************** | ||
1531 | #define I2C2_CTRL 0x190008 // I2C #2 control | ||
1532 | |||
1533 | //***************************************************************************** | ||
1534 | #define I2C2_RDATA 0x19000C // I2C #2 read data | ||
1535 | |||
1536 | //***************************************************************************** | ||
1537 | #define I2C2_STAT 0x190010 // I2C #2 status | ||
1538 | |||
1539 | //***************************************************************************** | ||
1540 | // I2C #3 | ||
1541 | //***************************************************************************** | ||
1542 | #define I2C3_ADDR 0x1A0000 // I2C #3 address | ||
1543 | |||
1544 | //***************************************************************************** | ||
1545 | #define I2C3_WDATA 0x1A0004 // I2C #3 write data | ||
1546 | |||
1547 | //***************************************************************************** | ||
1548 | #define I2C3_CTRL 0x1A0008 // I2C #3 control | ||
1549 | |||
1550 | //***************************************************************************** | ||
1551 | #define I2C3_RDATA 0x1A000C // I2C #3 read data | ||
1552 | |||
1553 | //***************************************************************************** | ||
1554 | #define I2C3_STAT 0x1A0010 // I2C #3 status | ||
1555 | |||
1556 | //***************************************************************************** | ||
1557 | // UART | ||
1558 | //***************************************************************************** | ||
1559 | #define UART_CTL 0x1B0000 // UART Control Register | ||
1560 | #define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 | ||
1561 | #define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 | ||
1562 | #define FLD_RX_EN (1 << 1) // RW field - default 0 | ||
1563 | #define FLD_TX_EN (1 << 0) // RW field - default 0 | ||
1564 | |||
1565 | //***************************************************************************** | ||
1566 | #define UART_BRD 0x1B0004 // UART Baud Rate Divisor | ||
1567 | #define FLD_BRD 0x0000FFFF // RW field - default 0x197 | ||
1568 | |||
1569 | //***************************************************************************** | ||
1570 | #define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer | ||
1571 | #define FLD_DB 0xFFFFFFFF // RW field - default 0 | ||
1572 | |||
1573 | //***************************************************************************** | ||
1574 | #define UART_ISR 0x1B000C // UART Interrupt Status | ||
1575 | #define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 | ||
1576 | #define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 | ||
1577 | #define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 | ||
1578 | #define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 | ||
1579 | #define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 | ||
1580 | #define FLD_FRM_ERR (1 << 2) // RW field - default 0 | ||
1581 | #define FLD_RXD_RDY (1 << 1) // RW field - default 0 | ||
1582 | #define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 | ||
1583 | |||
1584 | //***************************************************************************** | ||
1585 | #define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count | ||
1586 | #define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 | ||
1587 | #define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 | ||
1588 | |||
1589 | //***************************************************************************** | ||
1590 | // Motion Detection | ||
1591 | #define MD_CH0_GRID_BLOCK_YCNT 0x170014 | ||
1592 | #define MD_CH1_GRID_BLOCK_YCNT 0x170094 | ||
1593 | #define MD_CH2_GRID_BLOCK_YCNT 0x170114 | ||
1594 | #define MD_CH3_GRID_BLOCK_YCNT 0x170194 | ||
1595 | #define MD_CH4_GRID_BLOCK_YCNT 0x170214 | ||
1596 | #define MD_CH5_GRID_BLOCK_YCNT 0x170294 | ||
1597 | #define MD_CH6_GRID_BLOCK_YCNT 0x170314 | ||
1598 | #define MD_CH7_GRID_BLOCK_YCNT 0x170394 | ||
1599 | |||
1600 | #define PIXEL_FRMT_422 4 | ||
1601 | #define PIXEL_FRMT_411 5 | ||
1602 | #define PIXEL_FRMT_Y8 6 | ||
1603 | |||
1604 | #define PIXEL_ENGINE_VIP1 0 | ||
1605 | #define PIXEL_ENGINE_VIP2 1 | ||
1606 | |||
1607 | #endif //Athena_REGISTERS | ||
1608 | |||
1609 | |||
diff --git a/drivers/staging/cx25821/cx25821-sram.h b/drivers/staging/cx25821/cx25821-sram.h new file mode 100644 index 00000000000..81306358226 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-sram.h | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef __ATHENA_SRAM_H__ | ||
24 | #define __ATHENA_SRAM_H__ | ||
25 | |||
26 | //#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM | ||
27 | #define VID_CMDS_SIZE 80 // Video CMDS size in bytes | ||
28 | #define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes | ||
29 | #define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes | ||
30 | |||
31 | //#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers | ||
32 | #define VID_IQ_SIZE 64 // VID instruction queue size in bytes | ||
33 | #define MBIF_IQ_SIZE 64 | ||
34 | #define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes | ||
35 | |||
36 | #define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes | ||
37 | #define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes | ||
38 | #define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes | ||
39 | |||
40 | //#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM | ||
41 | //#define RX_SRAM_END_SIZE = 0; // End of RX SRAM | ||
42 | |||
43 | //#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM | ||
44 | //#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora | ||
45 | |||
46 | #define VID_CLUSTER_SIZE 1440 // VID cluster data line | ||
47 | #define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line | ||
48 | #define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line | ||
49 | |||
50 | |||
51 | //#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM | ||
52 | //#define TX_SRAM_END_SIZE = 0; // End of TX SRAM | ||
53 | |||
54 | // Receive SRAM | ||
55 | #define RX_SRAM_START 0x10000 | ||
56 | #define VID_A_DOWN_CMDS 0x10000 | ||
57 | #define VID_B_DOWN_CMDS 0x10050 | ||
58 | #define VID_C_DOWN_CMDS 0x100A0 | ||
59 | #define VID_D_DOWN_CMDS 0x100F0 | ||
60 | #define VID_E_DOWN_CMDS 0x10140 | ||
61 | #define VID_F_DOWN_CMDS 0x10190 | ||
62 | #define VID_G_DOWN_CMDS 0x101E0 | ||
63 | #define VID_H_DOWN_CMDS 0x10230 | ||
64 | #define VID_A_UP_CMDS 0x10280 | ||
65 | #define VID_B_UP_CMDS 0x102D0 | ||
66 | #define VID_C_UP_CMDS 0x10320 | ||
67 | #define VID_D_UP_CMDS 0x10370 | ||
68 | #define VID_E_UP_CMDS 0x103C0 | ||
69 | #define VID_F_UP_CMDS 0x10410 | ||
70 | #define VID_I_UP_CMDS 0x10460 | ||
71 | #define VID_J_UP_CMDS 0x104B0 | ||
72 | #define AUD_A_DOWN_CMDS 0x10500 | ||
73 | #define AUD_B_DOWN_CMDS 0x10550 | ||
74 | #define AUD_C_DOWN_CMDS 0x105A0 | ||
75 | #define AUD_D_DOWN_CMDS 0x105F0 | ||
76 | #define AUD_A_UP_CMDS 0x10640 | ||
77 | #define AUD_B_UP_CMDS 0x10690 | ||
78 | #define AUD_C_UP_CMDS 0x106E0 | ||
79 | #define AUD_E_UP_CMDS 0x10730 | ||
80 | #define MBIF_A_DOWN_CMDS 0x10780 | ||
81 | #define MBIF_B_DOWN_CMDS 0x107D0 | ||
82 | #define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 | ||
83 | |||
84 | //#define RX_SRAM_POOL_START = 0x105B0; | ||
85 | |||
86 | #define VID_A_IQ 0x11000 | ||
87 | #define VID_B_IQ 0x11040 | ||
88 | #define VID_C_IQ 0x11080 | ||
89 | #define VID_D_IQ 0x110C0 | ||
90 | #define VID_E_IQ 0x11100 | ||
91 | #define VID_F_IQ 0x11140 | ||
92 | #define VID_G_IQ 0x11180 | ||
93 | #define VID_H_IQ 0x111C0 | ||
94 | #define VID_I_IQ 0x11200 | ||
95 | #define VID_J_IQ 0x11240 | ||
96 | #define AUD_A_IQ 0x11280 | ||
97 | #define AUD_B_IQ 0x112C0 | ||
98 | #define AUD_C_IQ 0x11300 | ||
99 | #define AUD_D_IQ 0x11340 | ||
100 | #define AUD_E_IQ 0x11380 | ||
101 | #define MBIF_A_IQ 0x11000 | ||
102 | #define MBIF_B_IQ 0x110C0 | ||
103 | |||
104 | #define VID_A_CDT 0x10C00 | ||
105 | #define VID_B_CDT 0x10C40 | ||
106 | #define VID_C_CDT 0x10C80 | ||
107 | #define VID_D_CDT 0x10CC0 | ||
108 | #define VID_E_CDT 0x10D00 | ||
109 | #define VID_F_CDT 0x10D40 | ||
110 | #define VID_G_CDT 0x10D80 | ||
111 | #define VID_H_CDT 0x10DC0 | ||
112 | #define VID_I_CDT 0x10E00 | ||
113 | #define VID_J_CDT 0x10E40 | ||
114 | #define AUD_A_CDT 0x10E80 | ||
115 | #define AUD_B_CDT 0x10EB0 | ||
116 | #define AUD_C_CDT 0x10EE0 | ||
117 | #define AUD_D_CDT 0x10F10 | ||
118 | #define AUD_E_CDT 0x10F40 | ||
119 | #define MBIF_A_CDT 0x10C00 | ||
120 | #define MBIF_B_CDT 0x10CC0 | ||
121 | |||
122 | // Cluster Buffer for RX | ||
123 | #define VID_A_UP_CLUSTER_1 0x11400 | ||
124 | #define VID_A_UP_CLUSTER_2 0x119A0 | ||
125 | #define VID_A_UP_CLUSTER_3 0x11F40 | ||
126 | #define VID_A_UP_CLUSTER_4 0x124E0 | ||
127 | |||
128 | #define VID_B_UP_CLUSTER_1 0x12A80 | ||
129 | #define VID_B_UP_CLUSTER_2 0x13020 | ||
130 | #define VID_B_UP_CLUSTER_3 0x135C0 | ||
131 | #define VID_B_UP_CLUSTER_4 0x13B60 | ||
132 | |||
133 | #define VID_C_UP_CLUSTER_1 0x14100 | ||
134 | #define VID_C_UP_CLUSTER_2 0x146A0 | ||
135 | #define VID_C_UP_CLUSTER_3 0x14C40 | ||
136 | #define VID_C_UP_CLUSTER_4 0x151E0 | ||
137 | |||
138 | #define VID_D_UP_CLUSTER_1 0x15780 | ||
139 | #define VID_D_UP_CLUSTER_2 0x15D20 | ||
140 | #define VID_D_UP_CLUSTER_3 0x162C0 | ||
141 | #define VID_D_UP_CLUSTER_4 0x16860 | ||
142 | |||
143 | #define VID_E_UP_CLUSTER_1 0x16E00 | ||
144 | #define VID_E_UP_CLUSTER_2 0x173A0 | ||
145 | #define VID_E_UP_CLUSTER_3 0x17940 | ||
146 | #define VID_E_UP_CLUSTER_4 0x17EE0 | ||
147 | |||
148 | #define VID_F_UP_CLUSTER_1 0x18480 | ||
149 | #define VID_F_UP_CLUSTER_2 0x18A20 | ||
150 | #define VID_F_UP_CLUSTER_3 0x18FC0 | ||
151 | #define VID_F_UP_CLUSTER_4 0x19560 | ||
152 | |||
153 | #define VID_I_UP_CLUSTER_1 0x19B00 | ||
154 | #define VID_I_UP_CLUSTER_2 0x1A0A0 | ||
155 | #define VID_I_UP_CLUSTER_3 0x1A640 | ||
156 | #define VID_I_UP_CLUSTER_4 0x1ABE0 | ||
157 | |||
158 | #define VID_J_UP_CLUSTER_1 0x1B180 | ||
159 | #define VID_J_UP_CLUSTER_2 0x1B720 | ||
160 | #define VID_J_UP_CLUSTER_3 0x1BCC0 | ||
161 | #define VID_J_UP_CLUSTER_4 0x1C260 | ||
162 | |||
163 | #define AUD_A_UP_CLUSTER_1 0x1C800 | ||
164 | #define AUD_A_UP_CLUSTER_2 0x1C880 | ||
165 | #define AUD_A_UP_CLUSTER_3 0x1C900 | ||
166 | |||
167 | #define AUD_B_UP_CLUSTER_1 0x1C980 | ||
168 | #define AUD_B_UP_CLUSTER_2 0x1CA00 | ||
169 | #define AUD_B_UP_CLUSTER_3 0x1CA80 | ||
170 | |||
171 | #define AUD_C_UP_CLUSTER_1 0x1CB00 | ||
172 | #define AUD_C_UP_CLUSTER_2 0x1CB80 | ||
173 | #define AUD_C_UP_CLUSTER_3 0x1CC00 | ||
174 | |||
175 | #define AUD_E_UP_CLUSTER_1 0x1CC80 | ||
176 | #define AUD_E_UP_CLUSTER_2 0x1CD00 | ||
177 | #define AUD_E_UP_CLUSTER_3 0x1CD80 | ||
178 | |||
179 | #define RX_SRAM_POOL_FREE 0x1CE00 | ||
180 | #define RX_SRAM_END 0x1D000 | ||
181 | |||
182 | // Free Receive SRAM 144 Bytes | ||
183 | |||
184 | |||
185 | // Transmit SRAM | ||
186 | #define TX_SRAM_POOL_START 0x00000 | ||
187 | |||
188 | #define VID_A_DOWN_CLUSTER_1 0x00040 | ||
189 | #define VID_A_DOWN_CLUSTER_2 0x005E0 | ||
190 | #define VID_A_DOWN_CLUSTER_3 0x00B80 | ||
191 | #define VID_A_DOWN_CLUSTER_4 0x01120 | ||
192 | |||
193 | #define VID_B_DOWN_CLUSTER_1 0x016C0 | ||
194 | #define VID_B_DOWN_CLUSTER_2 0x01C60 | ||
195 | #define VID_B_DOWN_CLUSTER_3 0x02200 | ||
196 | #define VID_B_DOWN_CLUSTER_4 0x027A0 | ||
197 | |||
198 | #define VID_C_DOWN_CLUSTER_1 0x02D40 | ||
199 | #define VID_C_DOWN_CLUSTER_2 0x032E0 | ||
200 | #define VID_C_DOWN_CLUSTER_3 0x03880 | ||
201 | #define VID_C_DOWN_CLUSTER_4 0x03E20 | ||
202 | |||
203 | #define VID_D_DOWN_CLUSTER_1 0x043C0 | ||
204 | #define VID_D_DOWN_CLUSTER_2 0x04960 | ||
205 | #define VID_D_DOWN_CLUSTER_3 0x04F00 | ||
206 | #define VID_D_DOWN_CLUSTER_4 0x054A0 | ||
207 | |||
208 | #define VID_E_DOWN_CLUSTER_1 0x05a40 | ||
209 | #define VID_E_DOWN_CLUSTER_2 0x05FE0 | ||
210 | #define VID_E_DOWN_CLUSTER_3 0x06580 | ||
211 | #define VID_E_DOWN_CLUSTER_4 0x06B20 | ||
212 | |||
213 | #define VID_F_DOWN_CLUSTER_1 0x070C0 | ||
214 | #define VID_F_DOWN_CLUSTER_2 0x07660 | ||
215 | #define VID_F_DOWN_CLUSTER_3 0x07C00 | ||
216 | #define VID_F_DOWN_CLUSTER_4 0x081A0 | ||
217 | |||
218 | #define VID_G_DOWN_CLUSTER_1 0x08740 | ||
219 | #define VID_G_DOWN_CLUSTER_2 0x08CE0 | ||
220 | #define VID_G_DOWN_CLUSTER_3 0x09280 | ||
221 | #define VID_G_DOWN_CLUSTER_4 0x09820 | ||
222 | |||
223 | #define VID_H_DOWN_CLUSTER_1 0x09DC0 | ||
224 | #define VID_H_DOWN_CLUSTER_2 0x0A360 | ||
225 | #define VID_H_DOWN_CLUSTER_3 0x0A900 | ||
226 | #define VID_H_DOWN_CLUSTER_4 0x0AEA0 | ||
227 | |||
228 | #define AUD_A_DOWN_CLUSTER_1 0x0B500 | ||
229 | #define AUD_A_DOWN_CLUSTER_2 0x0B580 | ||
230 | #define AUD_A_DOWN_CLUSTER_3 0x0B600 | ||
231 | |||
232 | #define AUD_B_DOWN_CLUSTER_1 0x0B680 | ||
233 | #define AUD_B_DOWN_CLUSTER_2 0x0B700 | ||
234 | #define AUD_B_DOWN_CLUSTER_3 0x0B780 | ||
235 | |||
236 | #define AUD_C_DOWN_CLUSTER_1 0x0B800 | ||
237 | #define AUD_C_DOWN_CLUSTER_2 0x0B880 | ||
238 | #define AUD_C_DOWN_CLUSTER_3 0x0B900 | ||
239 | |||
240 | #define AUD_D_DOWN_CLUSTER_1 0x0B980 | ||
241 | #define AUD_D_DOWN_CLUSTER_2 0x0BA00 | ||
242 | #define AUD_D_DOWN_CLUSTER_3 0x0BA80 | ||
243 | |||
244 | #define TX_SRAM_POOL_FREE 0x0BB00 | ||
245 | #define TX_SRAM_END 0x0C000 | ||
246 | |||
247 | |||
248 | #define BYTES_TO_DWORDS(bcount) ((bcount) >> 2) | ||
249 | #define BYTES_TO_QWORDS(bcount) ((bcount) >> 3) | ||
250 | #define BYTES_TO_OWORDS(bcount) ((bcount) >> 4) | ||
251 | |||
252 | #define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE) | ||
253 | #define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE) | ||
254 | #define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE) | ||
255 | |||
256 | #define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE) | ||
257 | #define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE) | ||
258 | #define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE) | ||
259 | |||
260 | #define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE) | ||
261 | #define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE) | ||
262 | #define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE) | ||
263 | |||
264 | |||
265 | #endif | ||
266 | |||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c new file mode 100644 index 00000000000..ca91b832b01 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include "cx25821-video.h" | ||
25 | #include "cx25821-video-upstream-ch2.h" | ||
26 | |||
27 | #include <linux/fs.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/syscalls.h> | ||
33 | #include <linux/file.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | |||
38 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
39 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
40 | MODULE_LICENSE("GPL"); | ||
41 | |||
42 | |||
43 | static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; | ||
44 | |||
45 | |||
46 | static __le32 *cx25821_update_riscprogram_ch2( struct cx25821_dev *dev, | ||
47 | __le32 *rp, unsigned int offset, unsigned int bpl, | ||
48 | u32 sync_line, unsigned int lines, int fifo_enable, int field_type) | ||
49 | { | ||
50 | unsigned int line, i; | ||
51 | int dist_betwn_starts = bpl * 2; | ||
52 | |||
53 | |||
54 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
55 | |||
56 | |||
57 | if( USE_RISC_NOOP_VIDEO ) | ||
58 | { | ||
59 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
60 | { | ||
61 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | /* scan lines */ | ||
66 | for (line = 0; line < lines; line++) | ||
67 | { | ||
68 | *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); | ||
69 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset); | ||
70 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
71 | |||
72 | if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) | ||
73 | { | ||
74 | offset += dist_betwn_starts; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | return rp; | ||
79 | } | ||
80 | |||
81 | static __le32 *cx25821_risc_field_upstream_ch2( struct cx25821_dev *dev, | ||
82 | __le32 *rp, | ||
83 | dma_addr_t databuf_phys_addr, | ||
84 | unsigned int offset, u32 sync_line, unsigned int bpl, | ||
85 | unsigned int lines, int fifo_enable, int field_type) | ||
86 | { | ||
87 | unsigned int line, i; | ||
88 | struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel2_upstream_select]; | ||
89 | int dist_betwn_starts = bpl * 2; | ||
90 | |||
91 | |||
92 | /* sync instruction */ | ||
93 | if (sync_line != NO_SYNC_LINE) | ||
94 | { | ||
95 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
96 | } | ||
97 | |||
98 | |||
99 | if( USE_RISC_NOOP_VIDEO ) | ||
100 | { | ||
101 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
102 | { | ||
103 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /* scan lines */ | ||
108 | for (line = 0; line < lines; line++) | ||
109 | { | ||
110 | *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); | ||
111 | *(rp++) = cpu_to_le32(databuf_phys_addr+offset); | ||
112 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
113 | |||
114 | |||
115 | if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) | ||
116 | { | ||
117 | offset += dist_betwn_starts; | ||
118 | } | ||
119 | |||
120 | |||
121 | // check if we need to enable the FIFO after the first 4 lines | ||
122 | // For the upstream video channel, the risc engine will enable the FIFO. | ||
123 | if ( fifo_enable && line == 3 ) | ||
124 | { | ||
125 | *(rp++) = RISC_WRITECR; | ||
126 | *(rp++) = sram_ch->dma_ctl; | ||
127 | *(rp++) = FLD_VID_FIFO_EN; | ||
128 | *(rp++) = 0x00000001; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | return rp; | ||
133 | } | ||
134 | |||
135 | int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *pci, | ||
136 | unsigned int top_offset, | ||
137 | unsigned int bpl, unsigned int lines) | ||
138 | { | ||
139 | __le32 *rp; | ||
140 | int fifo_enable = 0; | ||
141 | int singlefield_lines = lines >> 1; //get line count for single field | ||
142 | int odd_num_lines = singlefield_lines; | ||
143 | int frame = 0; | ||
144 | int frame_size = 0; | ||
145 | int databuf_offset = 0; | ||
146 | int risc_program_size = 0; | ||
147 | int risc_flag = RISC_CNT_RESET; | ||
148 | unsigned int bottom_offset = bpl; | ||
149 | dma_addr_t risc_phys_jump_addr; | ||
150 | |||
151 | |||
152 | if( dev->_isNTSC_ch2 ) | ||
153 | { | ||
154 | odd_num_lines = singlefield_lines + 1; | ||
155 | risc_program_size = FRAME1_VID_PROG_SIZE; | ||
156 | frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | ||
157 | } | ||
158 | else | ||
159 | { | ||
160 | risc_program_size = PAL_VID_PROG_SIZE; | ||
161 | frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
162 | } | ||
163 | |||
164 | |||
165 | /* Virtual address of Risc buffer program */ | ||
166 | rp = dev->_dma_virt_addr_ch2; | ||
167 | |||
168 | for( frame = 0; frame < NUM_FRAMES; frame++ ) | ||
169 | { | ||
170 | databuf_offset = frame_size * frame; | ||
171 | |||
172 | |||
173 | if (UNSET != top_offset) | ||
174 | { | ||
175 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | ||
176 | rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); | ||
177 | } | ||
178 | |||
179 | fifo_enable = FIFO_DISABLE; | ||
180 | |||
181 | |||
182 | //Even field | ||
183 | rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); | ||
184 | |||
185 | |||
186 | if( frame == 0 ) | ||
187 | { | ||
188 | risc_flag = RISC_CNT_RESET; | ||
189 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size; | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | risc_flag = RISC_CNT_INC; | ||
194 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; | ||
195 | } | ||
196 | |||
197 | |||
198 | // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ | ||
199 | *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); | ||
200 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
201 | *(rp++) = cpu_to_le32(0); | ||
202 | } | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | |||
208 | void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) | ||
209 | { | ||
210 | struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; | ||
211 | u32 tmp = 0; | ||
212 | |||
213 | if( !dev->_is_running_ch2 ) | ||
214 | { | ||
215 | printk("cx25821: No video file is currently running so return!\n"); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | //Disable RISC interrupts | ||
220 | tmp = cx_read( sram_ch->int_msk ); | ||
221 | cx_write( sram_ch->int_msk, tmp & ~_intr_msk); | ||
222 | |||
223 | //Turn OFF risc and fifo | ||
224 | tmp = cx_read( sram_ch->dma_ctl ); | ||
225 | cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); | ||
226 | |||
227 | //Clear data buffer memory | ||
228 | if( dev->_data_buf_virt_addr_ch2 ) | ||
229 | memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); | ||
230 | |||
231 | dev->_is_running_ch2 = 0; | ||
232 | dev->_is_first_frame_ch2 = 0; | ||
233 | dev->_frame_count_ch2 = 0; | ||
234 | dev->_file_status_ch2 = END_OF_FILE; | ||
235 | |||
236 | if( dev->_irq_queues_ch2 ) | ||
237 | { | ||
238 | kfree(dev->_irq_queues_ch2); | ||
239 | dev->_irq_queues_ch2 = NULL; | ||
240 | } | ||
241 | |||
242 | if( dev->_filename_ch2 != NULL ) | ||
243 | kfree(dev->_filename_ch2); | ||
244 | |||
245 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
246 | cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
247 | } | ||
248 | |||
249 | void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) | ||
250 | { | ||
251 | if( dev->_is_running_ch2 ) | ||
252 | { | ||
253 | cx25821_stop_upstream_video_ch2(dev); | ||
254 | } | ||
255 | |||
256 | if (dev->_dma_virt_addr_ch2) | ||
257 | { | ||
258 | pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); | ||
259 | dev->_dma_virt_addr_ch2 = NULL; | ||
260 | } | ||
261 | |||
262 | if (dev->_data_buf_virt_addr_ch2) | ||
263 | { | ||
264 | pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); | ||
265 | dev->_data_buf_virt_addr_ch2 = NULL; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | |||
270 | int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch ) | ||
271 | { | ||
272 | struct file * myfile; | ||
273 | int frame_index_temp = dev->_frame_index_ch2; | ||
274 | int i = 0; | ||
275 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
276 | int frame_size = 0; | ||
277 | int frame_offset = 0; | ||
278 | ssize_t vfs_read_retval = 0; | ||
279 | char mybuf[line_size]; | ||
280 | loff_t file_offset; | ||
281 | loff_t pos; | ||
282 | mm_segment_t old_fs; | ||
283 | |||
284 | |||
285 | if( dev->_file_status_ch2 == END_OF_FILE ) | ||
286 | return 0; | ||
287 | |||
288 | if( dev->_isNTSC_ch2 ) | ||
289 | { | ||
290 | frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | ||
291 | } | ||
292 | else | ||
293 | { | ||
294 | frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
295 | } | ||
296 | |||
297 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | ||
298 | file_offset = dev->_frame_count_ch2 * frame_size; | ||
299 | |||
300 | |||
301 | myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); | ||
302 | |||
303 | |||
304 | if (IS_ERR(myfile)) | ||
305 | { | ||
306 | const int open_errno = -PTR_ERR(myfile); | ||
307 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); | ||
308 | return PTR_ERR(myfile); | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | if( !(myfile->f_op) ) | ||
313 | { | ||
314 | printk("%s: File has no file operations registered!", __func__); | ||
315 | filp_close(myfile, NULL); | ||
316 | return -EIO; | ||
317 | } | ||
318 | |||
319 | |||
320 | if( !myfile->f_op->read ) | ||
321 | { | ||
322 | printk("%s: File has no READ operations registered!", __func__); | ||
323 | filp_close(myfile, NULL); | ||
324 | return -EIO; | ||
325 | } | ||
326 | |||
327 | pos = myfile->f_pos; | ||
328 | old_fs = get_fs(); | ||
329 | set_fs(KERNEL_DS); | ||
330 | |||
331 | |||
332 | for( i = 0; i < dev->_lines_count_ch2; i++ ) | ||
333 | { | ||
334 | pos = file_offset; | ||
335 | |||
336 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
337 | |||
338 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) | ||
339 | { | ||
340 | memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval); | ||
341 | } | ||
342 | |||
343 | file_offset += vfs_read_retval; | ||
344 | frame_offset += vfs_read_retval; | ||
345 | |||
346 | if( vfs_read_retval < line_size ) | ||
347 | { | ||
348 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); | ||
349 | break; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | if( i > 0 ) | ||
354 | dev->_frame_count_ch2++; | ||
355 | |||
356 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
357 | |||
358 | |||
359 | set_fs(old_fs); | ||
360 | filp_close(myfile, NULL); | ||
361 | } | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static void cx25821_vidups_handler_ch2(struct work_struct *work) | ||
367 | { | ||
368 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry_ch2); | ||
369 | |||
370 | if( !dev ) | ||
371 | { | ||
372 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | cx25821_get_frame_ch2( dev, &dev->sram_channels[dev->_channel2_upstream_select] ); | ||
377 | } | ||
378 | |||
379 | |||
380 | int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
381 | { | ||
382 | struct file * myfile; | ||
383 | int i = 0, j = 0; | ||
384 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
385 | ssize_t vfs_read_retval = 0; | ||
386 | char mybuf[line_size]; | ||
387 | loff_t pos; | ||
388 | loff_t offset = (unsigned long)0; | ||
389 | mm_segment_t old_fs; | ||
390 | |||
391 | |||
392 | myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); | ||
393 | |||
394 | |||
395 | if (IS_ERR(myfile)) | ||
396 | { | ||
397 | const int open_errno = -PTR_ERR(myfile); | ||
398 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); | ||
399 | return PTR_ERR(myfile); | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | if( !(myfile->f_op) ) | ||
404 | { | ||
405 | printk("%s: File has no file operations registered!", __func__); | ||
406 | filp_close(myfile, NULL); | ||
407 | return -EIO; | ||
408 | } | ||
409 | |||
410 | |||
411 | if( !myfile->f_op->read ) | ||
412 | { | ||
413 | printk("%s: File has no READ operations registered! Returning.", __func__); | ||
414 | filp_close(myfile, NULL); | ||
415 | return -EIO; | ||
416 | } | ||
417 | |||
418 | pos = myfile->f_pos; | ||
419 | old_fs = get_fs(); | ||
420 | set_fs(KERNEL_DS); | ||
421 | |||
422 | |||
423 | for( j = 0; j < NUM_FRAMES; j++ ) | ||
424 | { | ||
425 | for( i = 0; i < dev->_lines_count_ch2; i++ ) | ||
426 | { | ||
427 | pos = offset; | ||
428 | |||
429 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
430 | |||
431 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) | ||
432 | { | ||
433 | memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); | ||
434 | } | ||
435 | |||
436 | |||
437 | offset += vfs_read_retval; | ||
438 | |||
439 | if( vfs_read_retval < line_size ) | ||
440 | { | ||
441 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | if( i > 0 ) | ||
447 | dev->_frame_count_ch2++; | ||
448 | |||
449 | if( vfs_read_retval < line_size ) | ||
450 | { | ||
451 | break; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
456 | |||
457 | set_fs(old_fs); | ||
458 | myfile->f_pos = 0; | ||
459 | filp_close(myfile, NULL); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | |||
466 | static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, | ||
467 | struct sram_channel *sram_ch, | ||
468 | int bpl) | ||
469 | { | ||
470 | int ret = 0; | ||
471 | dma_addr_t dma_addr; | ||
472 | dma_addr_t data_dma_addr; | ||
473 | |||
474 | |||
475 | if( dev->_dma_virt_addr_ch2 != NULL ) | ||
476 | { | ||
477 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); | ||
478 | } | ||
479 | |||
480 | dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, &dma_addr); | ||
481 | dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; | ||
482 | dev->_dma_phys_start_addr_ch2 = dma_addr; | ||
483 | dev->_dma_phys_addr_ch2 = dma_addr; | ||
484 | dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; | ||
485 | |||
486 | |||
487 | if (!dev->_dma_virt_addr_ch2) | ||
488 | { | ||
489 | printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); | ||
490 | return -ENOMEM; | ||
491 | } | ||
492 | |||
493 | |||
494 | //Iniitize at this address until n bytes to 0 | ||
495 | memset( dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2 ); | ||
496 | |||
497 | |||
498 | if( dev->_data_buf_virt_addr_ch2 != NULL ) | ||
499 | { | ||
500 | pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); | ||
501 | } | ||
502 | |||
503 | //For Video Data buffer allocation | ||
504 | dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, &data_dma_addr); | ||
505 | dev->_data_buf_phys_addr_ch2 = data_dma_addr; | ||
506 | dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; | ||
507 | |||
508 | if (!dev->_data_buf_virt_addr_ch2) | ||
509 | { | ||
510 | printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); | ||
511 | return -ENOMEM; | ||
512 | } | ||
513 | |||
514 | |||
515 | //Initialize at this address until n bytes to 0 | ||
516 | memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); | ||
517 | |||
518 | |||
519 | ret = cx25821_openfile_ch2(dev, sram_ch); | ||
520 | if( ret < 0 ) | ||
521 | return ret; | ||
522 | |||
523 | |||
524 | //Creating RISC programs | ||
525 | ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2 ); | ||
526 | if (ret < 0) | ||
527 | { | ||
528 | printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); | ||
529 | goto error; | ||
530 | } | ||
531 | |||
532 | return 0; | ||
533 | |||
534 | error: | ||
535 | return ret; | ||
536 | } | ||
537 | |||
538 | int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 status) | ||
539 | { | ||
540 | u32 int_msk_tmp; | ||
541 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
542 | int singlefield_lines = NTSC_FIELD_HEIGHT; | ||
543 | int line_size_in_bytes = Y422_LINE_SZ; | ||
544 | int odd_risc_prog_size = 0; | ||
545 | dma_addr_t risc_phys_jump_addr; | ||
546 | __le32 * rp; | ||
547 | |||
548 | |||
549 | |||
550 | if (status & FLD_VID_SRC_RISC1) | ||
551 | { | ||
552 | // We should only process one program per call | ||
553 | u32 prog_cnt = cx_read( channel->gpcnt ); | ||
554 | |||
555 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
556 | int_msk_tmp = cx_read(channel->int_msk); | ||
557 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | ||
558 | cx_write( channel->int_stat, _intr_msk ); | ||
559 | |||
560 | spin_lock(&dev->slock); | ||
561 | |||
562 | dev->_frame_index_ch2 = prog_cnt; | ||
563 | |||
564 | queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); | ||
565 | |||
566 | |||
567 | if ( dev->_is_first_frame_ch2 ) | ||
568 | { | ||
569 | dev->_is_first_frame_ch2 = 0; | ||
570 | |||
571 | if( dev->_isNTSC_ch2 ) | ||
572 | { | ||
573 | singlefield_lines += 1; | ||
574 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | singlefield_lines = PAL_FIELD_HEIGHT; | ||
579 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | ||
580 | } | ||
581 | |||
582 | |||
583 | if( dev->_dma_virt_start_addr_ch2 != NULL ) | ||
584 | { | ||
585 | line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
586 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size; | ||
587 | |||
588 | rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); | ||
589 | |||
590 | // Jump to Even Risc program of 1st Frame | ||
591 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
592 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
593 | *(rp++) = cpu_to_le32(0); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | spin_unlock(&dev->slock); | ||
598 | } | ||
599 | |||
600 | |||
601 | if( dev->_file_status_ch2 == END_OF_FILE ) | ||
602 | { | ||
603 | printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 ); | ||
604 | return -1; | ||
605 | } | ||
606 | |||
607 | //ElSE, set the interrupt mask register, re-enable irq. | ||
608 | int_msk_tmp = cx_read( channel->int_msk ); | ||
609 | cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) | ||
615 | { | ||
616 | struct cx25821_dev *dev = dev_id; | ||
617 | u32 msk_stat, vid_status; | ||
618 | int handled = 0; | ||
619 | int channel_num = 0; | ||
620 | struct sram_channel *sram_ch; | ||
621 | |||
622 | |||
623 | if( !dev ) | ||
624 | return -1; | ||
625 | |||
626 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; | ||
627 | |||
628 | sram_ch = &dev->sram_channels[channel_num]; | ||
629 | |||
630 | msk_stat = cx_read(sram_ch->int_mstat); | ||
631 | vid_status = cx_read(sram_ch->int_stat); | ||
632 | |||
633 | // Only deal with our interrupt | ||
634 | if(vid_status) | ||
635 | { | ||
636 | handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status); | ||
637 | } | ||
638 | |||
639 | |||
640 | if( handled < 0 ) | ||
641 | { | ||
642 | cx25821_stop_upstream_video_ch2(dev); | ||
643 | } | ||
644 | else | ||
645 | { | ||
646 | handled += handled; | ||
647 | } | ||
648 | |||
649 | return IRQ_RETVAL(handled); | ||
650 | } | ||
651 | |||
652 | |||
653 | static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) | ||
654 | { | ||
655 | int width = WIDTH_D1; | ||
656 | int height = dev->_lines_count_ch2; | ||
657 | int num_lines, odd_num_lines; | ||
658 | u32 value; | ||
659 | int vip_mode = PIXEL_ENGINE_VIP1; | ||
660 | |||
661 | |||
662 | value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); | ||
663 | value &= 0xFFFFFFEF; | ||
664 | value |= dev->_isNTSC_ch2 ? 0 : 0x10; | ||
665 | cx_write( ch->vid_fmt_ctl, value ); | ||
666 | |||
667 | // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format | ||
668 | cx_write( ch->vid_active_ctl1, width ); | ||
669 | |||
670 | num_lines = (height / 2) & 0x3FF; | ||
671 | odd_num_lines = num_lines; | ||
672 | |||
673 | if(dev->_isNTSC_ch2) | ||
674 | { | ||
675 | odd_num_lines += 1; | ||
676 | } | ||
677 | |||
678 | value = (num_lines << 16) | odd_num_lines; | ||
679 | |||
680 | // set number of active lines in field 0 (top) and field 1 (bottom) | ||
681 | cx_write( ch->vid_active_ctl2, value ); | ||
682 | |||
683 | cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); | ||
684 | } | ||
685 | |||
686 | |||
687 | int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, | ||
688 | struct sram_channel *sram_ch) | ||
689 | { | ||
690 | u32 tmp = 0; | ||
691 | int err = 0; | ||
692 | |||
693 | |||
694 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
695 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
696 | cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
697 | |||
698 | |||
699 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. | ||
700 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); | ||
701 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
702 | |||
703 | /* reset counter */ | ||
704 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
705 | |||
706 | // Clear our bits from the interrupt status register. | ||
707 | cx_write( sram_ch->int_stat, _intr_msk ); | ||
708 | |||
709 | |||
710 | //Set the interrupt mask register, enable irq. | ||
711 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
712 | tmp = cx_read( sram_ch->int_msk ); | ||
713 | cx_write( sram_ch->int_msk, tmp |= _intr_msk ); | ||
714 | |||
715 | |||
716 | err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
717 | if (err < 0) | ||
718 | { | ||
719 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); | ||
720 | goto fail_irq; | ||
721 | } | ||
722 | |||
723 | // Start the DMA engine | ||
724 | tmp = cx_read( sram_ch->dma_ctl ); | ||
725 | cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); | ||
726 | |||
727 | dev->_is_running_ch2 = 1; | ||
728 | dev->_is_first_frame_ch2 = 1; | ||
729 | |||
730 | return 0; | ||
731 | |||
732 | |||
733 | fail_irq: | ||
734 | cx25821_dev_unregister(dev); | ||
735 | return err; | ||
736 | } | ||
737 | |||
738 | |||
739 | int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format) | ||
740 | { | ||
741 | struct sram_channel *sram_ch; | ||
742 | u32 tmp; | ||
743 | int retval = 0; | ||
744 | int err = 0; | ||
745 | int data_frame_size = 0; | ||
746 | int risc_buffer_size = 0; | ||
747 | int str_length = 0; | ||
748 | |||
749 | if( dev->_is_running_ch2 ) | ||
750 | { | ||
751 | printk("Video Channel is still running so return!\n"); | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | dev->_channel2_upstream_select = channel_select; | ||
756 | sram_ch = &dev->sram_channels[channel_select]; | ||
757 | |||
758 | |||
759 | INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); | ||
760 | dev->_irq_queues_ch2 = create_singlethread_workqueue("cx25821_workqueue2"); | ||
761 | |||
762 | if(!dev->_irq_queues_ch2) | ||
763 | { | ||
764 | printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); | ||
765 | return -ENOMEM; | ||
766 | } | ||
767 | |||
768 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
769 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
770 | cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
771 | |||
772 | |||
773 | dev->_is_running_ch2 = 0; | ||
774 | dev->_frame_count_ch2 = 0; | ||
775 | dev->_file_status_ch2 = RESET_STATUS; | ||
776 | dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; | ||
777 | dev->_pixel_format_ch2 = pixel_format; | ||
778 | dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
779 | data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | ||
780 | risc_buffer_size = dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | ||
781 | |||
782 | |||
783 | if( dev->input_filename_ch2 ) | ||
784 | { | ||
785 | str_length = strlen(dev->input_filename_ch2); | ||
786 | dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
787 | |||
788 | if( !dev->_filename_ch2 ) | ||
789 | goto error; | ||
790 | |||
791 | memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1); | ||
792 | } | ||
793 | else | ||
794 | { | ||
795 | str_length = strlen(dev->_defaultname_ch2); | ||
796 | dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
797 | |||
798 | if( !dev->_filename_ch2 ) | ||
799 | goto error; | ||
800 | |||
801 | memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1); | ||
802 | } | ||
803 | |||
804 | |||
805 | //Default if filename is empty string | ||
806 | if( strcmp(dev->input_filename_ch2,"") == 0) | ||
807 | { | ||
808 | if( dev->_isNTSC_ch2 ) | ||
809 | { | ||
810 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; | ||
811 | } | ||
812 | else | ||
813 | { | ||
814 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | |||
819 | retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size_ch2, 0); | ||
820 | |||
821 | |||
822 | /* setup fifo + format */ | ||
823 | cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); | ||
824 | |||
825 | dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; | ||
826 | dev->upstream_databuf_size_ch2 = data_frame_size * 2; | ||
827 | |||
828 | |||
829 | //Allocating buffers and prepare RISC program | ||
830 | retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); | ||
831 | if (retval < 0) | ||
832 | { | ||
833 | printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); | ||
834 | goto error; | ||
835 | } | ||
836 | |||
837 | |||
838 | cx25821_start_video_dma_upstream_ch2(dev, sram_ch); | ||
839 | |||
840 | return 0; | ||
841 | |||
842 | error: | ||
843 | cx25821_dev_unregister(dev); | ||
844 | |||
845 | return err; | ||
846 | } | ||
847 | |||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h new file mode 100644 index 00000000000..71de8742be6 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | |||
27 | #define OPEN_FILE_1 0 | ||
28 | #define NUM_PROGS 8 | ||
29 | #define NUM_FRAMES 2 | ||
30 | #define ODD_FIELD 0 | ||
31 | #define EVEN_FIELD 1 | ||
32 | #define TOP_OFFSET 0 | ||
33 | #define FIFO_DISABLE 0 | ||
34 | #define FIFO_ENABLE 1 | ||
35 | #define TEST_FRAMES 5 | ||
36 | #define END_OF_FILE 0 | ||
37 | #define IN_PROGRESS 1 | ||
38 | #define RESET_STATUS -1 | ||
39 | #define NUM_NO_OPS 5 | ||
40 | |||
41 | |||
42 | |||
43 | // PAL and NTSC line sizes and number of lines. | ||
44 | #define WIDTH_D1 720 | ||
45 | #define NTSC_LINES_PER_FRAME 480 | ||
46 | #define PAL_LINES_PER_FRAME 576 | ||
47 | #define PAL_LINE_SZ 1440 | ||
48 | #define Y422_LINE_SZ 1440 | ||
49 | #define Y411_LINE_SZ 1080 | ||
50 | #define NTSC_FIELD_HEIGHT 240 | ||
51 | #define NTSC_ODD_FLD_LINES 241 | ||
52 | #define PAL_FIELD_HEIGHT 288 | ||
53 | |||
54 | #define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) | ||
55 | #define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) | ||
56 | #define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) | ||
57 | #define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) | ||
58 | |||
59 | #define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) | ||
60 | #define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) | ||
61 | |||
62 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
63 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
64 | #define JUMP_INSTRUCTION_SIZE 12 | ||
65 | #define MAXSIZE_NO_OPS 36 | ||
66 | #define DWORD_SIZE 4 | ||
67 | |||
68 | |||
69 | |||
70 | #define USE_RISC_NOOP_VIDEO 1 | ||
71 | |||
72 | #ifdef USE_RISC_NOOP_VIDEO | ||
73 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
74 | RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
75 | |||
76 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
77 | |||
78 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
79 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
80 | |||
81 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
82 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
83 | |||
84 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
85 | JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
86 | |||
87 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
88 | |||
89 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
90 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
91 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
92 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
93 | #endif | ||
94 | |||
95 | |||
96 | #ifndef USE_RISC_NOOP_VIDEO | ||
97 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
98 | #define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) | ||
99 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
100 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
101 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
102 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
103 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
104 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) | ||
105 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
106 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
107 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c new file mode 100644 index 00000000000..14d204aaa84 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream.c | |||
@@ -0,0 +1,923 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include "cx25821-video.h" | ||
25 | #include "cx25821-video-upstream.h" | ||
26 | |||
27 | #include <linux/fs.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/syscalls.h> | ||
33 | #include <linux/file.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | |||
38 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
39 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
40 | MODULE_LICENSE("GPL"); | ||
41 | |||
42 | |||
43 | static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; | ||
44 | |||
45 | int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | ||
46 | struct sram_channel *ch, | ||
47 | unsigned int bpl, u32 risc) | ||
48 | { | ||
49 | unsigned int i, lines; | ||
50 | u32 cdt; | ||
51 | |||
52 | |||
53 | if (ch->cmds_start == 0) { | ||
54 | cx_write(ch->ptr1_reg, 0); | ||
55 | cx_write(ch->ptr2_reg, 0); | ||
56 | cx_write(ch->cnt2_reg, 0); | ||
57 | cx_write(ch->cnt1_reg, 0); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
62 | cdt = ch->cdt; | ||
63 | lines = ch->fifo_size / bpl; | ||
64 | |||
65 | if (lines > 4) | ||
66 | { | ||
67 | lines = 4; | ||
68 | } | ||
69 | |||
70 | BUG_ON(lines < 2); | ||
71 | |||
72 | |||
73 | /* write CDT */ | ||
74 | for (i = 0; i < lines; i++) { | ||
75 | cx_write(cdt + 16*i, ch->fifo_start + bpl*i); | ||
76 | cx_write(cdt + 16*i + 4, 0); | ||
77 | cx_write(cdt + 16*i + 8, 0); | ||
78 | cx_write(cdt + 16*i + 12, 0); | ||
79 | } | ||
80 | |||
81 | /* write CMDS */ | ||
82 | cx_write(ch->cmds_start + 0, risc); | ||
83 | |||
84 | cx_write(ch->cmds_start + 4, 0); | ||
85 | cx_write(ch->cmds_start + 8, cdt); | ||
86 | cx_write(ch->cmds_start + 12, (lines*16) >> 3); | ||
87 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
88 | |||
89 | |||
90 | cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); | ||
91 | |||
92 | for (i = 24; i < 80; i += 4) | ||
93 | cx_write(ch->cmds_start + i, 0); | ||
94 | |||
95 | /* fill registers */ | ||
96 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
97 | cx_write(ch->ptr2_reg, cdt); | ||
98 | cx_write(ch->cnt2_reg, (lines*16) >> 3); | ||
99 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev, | ||
105 | __le32 *rp, unsigned int offset, unsigned int bpl, | ||
106 | u32 sync_line, unsigned int lines, int fifo_enable, int field_type) | ||
107 | { | ||
108 | unsigned int line, i; | ||
109 | int dist_betwn_starts = bpl * 2; | ||
110 | |||
111 | |||
112 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
113 | |||
114 | |||
115 | if( USE_RISC_NOOP_VIDEO ) | ||
116 | { | ||
117 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
118 | { | ||
119 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /* scan lines */ | ||
124 | for (line = 0; line < lines; line++) | ||
125 | { | ||
126 | *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); | ||
127 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset); | ||
128 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
129 | |||
130 | if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) | ||
131 | { | ||
132 | offset += dist_betwn_starts; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | return rp; | ||
137 | } | ||
138 | |||
139 | static __le32 *cx25821_risc_field_upstream( struct cx25821_dev *dev, __le32 *rp, | ||
140 | dma_addr_t databuf_phys_addr, | ||
141 | unsigned int offset, u32 sync_line, | ||
142 | unsigned int bpl, unsigned int lines, int fifo_enable, int field_type) | ||
143 | { | ||
144 | unsigned int line, i; | ||
145 | struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel_upstream_select]; | ||
146 | int dist_betwn_starts = bpl * 2; | ||
147 | |||
148 | |||
149 | /* sync instruction */ | ||
150 | if (sync_line != NO_SYNC_LINE) | ||
151 | { | ||
152 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
153 | } | ||
154 | |||
155 | |||
156 | if( USE_RISC_NOOP_VIDEO ) | ||
157 | { | ||
158 | for( i = 0; i < NUM_NO_OPS; i++ ) | ||
159 | { | ||
160 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /* scan lines */ | ||
165 | for (line = 0; line < lines; line++) | ||
166 | { | ||
167 | *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); | ||
168 | *(rp++) = cpu_to_le32(databuf_phys_addr+offset); | ||
169 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
170 | |||
171 | |||
172 | if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) | ||
173 | { | ||
174 | offset += dist_betwn_starts; //to skip the other field line | ||
175 | } | ||
176 | |||
177 | |||
178 | // check if we need to enable the FIFO after the first 4 lines | ||
179 | // For the upstream video channel, the risc engine will enable the FIFO. | ||
180 | if ( fifo_enable && line == 3 ) | ||
181 | { | ||
182 | *(rp++) = RISC_WRITECR; | ||
183 | *(rp++) = sram_ch->dma_ctl; | ||
184 | *(rp++) = FLD_VID_FIFO_EN; | ||
185 | *(rp++) = 0x00000001; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return rp; | ||
190 | } | ||
191 | |||
192 | int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, | ||
193 | struct pci_dev *pci, | ||
194 | unsigned int top_offset, | ||
195 | unsigned int bpl, unsigned int lines) | ||
196 | { | ||
197 | __le32 *rp; | ||
198 | int fifo_enable = 0; | ||
199 | int singlefield_lines = lines >> 1; //get line count for single field | ||
200 | int odd_num_lines = singlefield_lines; | ||
201 | int frame = 0; | ||
202 | int frame_size = 0; | ||
203 | int databuf_offset = 0; | ||
204 | int risc_program_size = 0; | ||
205 | int risc_flag = RISC_CNT_RESET; | ||
206 | unsigned int bottom_offset = bpl; | ||
207 | dma_addr_t risc_phys_jump_addr; | ||
208 | |||
209 | if( dev->_isNTSC ) | ||
210 | { | ||
211 | odd_num_lines = singlefield_lines + 1; | ||
212 | risc_program_size = FRAME1_VID_PROG_SIZE; | ||
213 | frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | risc_program_size = PAL_VID_PROG_SIZE; | ||
218 | frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
219 | } | ||
220 | |||
221 | |||
222 | /* Virtual address of Risc buffer program */ | ||
223 | rp = dev->_dma_virt_addr; | ||
224 | |||
225 | for( frame = 0; frame < NUM_FRAMES; frame++ ) | ||
226 | { | ||
227 | databuf_offset = frame_size * frame; | ||
228 | |||
229 | if (UNSET != top_offset) | ||
230 | { | ||
231 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | ||
232 | rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); | ||
233 | } | ||
234 | |||
235 | |||
236 | fifo_enable = FIFO_DISABLE; | ||
237 | |||
238 | |||
239 | //Even Field | ||
240 | rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); | ||
241 | |||
242 | |||
243 | if( frame == 0 ) | ||
244 | { | ||
245 | risc_flag = RISC_CNT_RESET; | ||
246 | risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size; | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | risc_phys_jump_addr = dev->_dma_phys_start_addr; | ||
251 | risc_flag = RISC_CNT_INC; | ||
252 | } | ||
253 | |||
254 | |||
255 | // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ | ||
256 | *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); | ||
257 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
258 | *(rp++) = cpu_to_le32(0); | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | |||
265 | void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | ||
266 | { | ||
267 | struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; | ||
268 | u32 tmp = 0; | ||
269 | |||
270 | if( !dev->_is_running ) | ||
271 | { | ||
272 | printk("cx25821: No video file is currently running so return!\n"); | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | //Disable RISC interrupts | ||
277 | tmp = cx_read( sram_ch->int_msk ); | ||
278 | cx_write( sram_ch->int_msk, tmp & ~_intr_msk); | ||
279 | |||
280 | //Turn OFF risc and fifo enable | ||
281 | tmp = cx_read( sram_ch->dma_ctl ); | ||
282 | cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); | ||
283 | |||
284 | //Clear data buffer memory | ||
285 | if( dev->_data_buf_virt_addr ) | ||
286 | memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); | ||
287 | |||
288 | dev->_is_running = 0; | ||
289 | dev->_is_first_frame = 0; | ||
290 | dev->_frame_count = 0; | ||
291 | dev->_file_status = END_OF_FILE; | ||
292 | |||
293 | if( dev->_irq_queues ) | ||
294 | { | ||
295 | kfree(dev->_irq_queues); | ||
296 | dev->_irq_queues = NULL; | ||
297 | } | ||
298 | |||
299 | if( dev->_filename != NULL ) | ||
300 | kfree(dev->_filename); | ||
301 | |||
302 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
303 | cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
304 | } | ||
305 | |||
306 | void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) | ||
307 | { | ||
308 | if( dev->_is_running ) | ||
309 | { | ||
310 | cx25821_stop_upstream_video_ch1(dev); | ||
311 | } | ||
312 | |||
313 | if (dev->_dma_virt_addr) | ||
314 | { | ||
315 | pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr); | ||
316 | dev->_dma_virt_addr = NULL; | ||
317 | } | ||
318 | |||
319 | if (dev->_data_buf_virt_addr) | ||
320 | { | ||
321 | pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); | ||
322 | dev->_data_buf_virt_addr = NULL; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | |||
327 | int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch ) | ||
328 | { | ||
329 | struct file * myfile; | ||
330 | int frame_index_temp = dev->_frame_index; | ||
331 | int i = 0; | ||
332 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
333 | int frame_size = 0; | ||
334 | int frame_offset = 0; | ||
335 | ssize_t vfs_read_retval = 0; | ||
336 | char mybuf[line_size]; | ||
337 | loff_t file_offset; | ||
338 | loff_t pos; | ||
339 | mm_segment_t old_fs; | ||
340 | |||
341 | |||
342 | if( dev->_file_status == END_OF_FILE ) | ||
343 | return 0; | ||
344 | |||
345 | if( dev->_isNTSC ) | ||
346 | { | ||
347 | frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | ||
348 | } | ||
349 | else | ||
350 | { | ||
351 | frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
352 | } | ||
353 | |||
354 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | ||
355 | file_offset = dev->_frame_count * frame_size; | ||
356 | |||
357 | |||
358 | myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); | ||
359 | |||
360 | |||
361 | if (IS_ERR(myfile)) | ||
362 | { | ||
363 | const int open_errno = -PTR_ERR(myfile); | ||
364 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); | ||
365 | return PTR_ERR(myfile); | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | if( !(myfile->f_op) ) | ||
370 | { | ||
371 | printk("%s: File has no file operations registered!", __func__); | ||
372 | filp_close(myfile, NULL); | ||
373 | return -EIO; | ||
374 | } | ||
375 | |||
376 | |||
377 | if( !myfile->f_op->read ) | ||
378 | { | ||
379 | printk("%s: File has no READ operations registered!", __func__); | ||
380 | filp_close(myfile, NULL); | ||
381 | return -EIO; | ||
382 | } | ||
383 | |||
384 | pos = myfile->f_pos; | ||
385 | old_fs = get_fs(); | ||
386 | set_fs(KERNEL_DS); | ||
387 | |||
388 | |||
389 | for( i = 0; i < dev->_lines_count; i++ ) | ||
390 | { | ||
391 | pos = file_offset; | ||
392 | |||
393 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
394 | |||
395 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) | ||
396 | { | ||
397 | memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); | ||
398 | } | ||
399 | |||
400 | file_offset += vfs_read_retval; | ||
401 | frame_offset += vfs_read_retval; | ||
402 | |||
403 | if( vfs_read_retval < line_size ) | ||
404 | { | ||
405 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); | ||
406 | break; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | if( i > 0 ) | ||
411 | dev->_frame_count++; | ||
412 | |||
413 | dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
414 | |||
415 | |||
416 | set_fs(old_fs); | ||
417 | filp_close(myfile, NULL); | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static void cx25821_vidups_handler(struct work_struct *work) | ||
424 | { | ||
425 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry); | ||
426 | |||
427 | if( !dev ) | ||
428 | { | ||
429 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | cx25821_get_frame( dev, &dev->sram_channels[dev->_channel_upstream_select] ); | ||
434 | } | ||
435 | |||
436 | |||
437 | int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
438 | { | ||
439 | struct file * myfile; | ||
440 | int i = 0, j = 0; | ||
441 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
442 | ssize_t vfs_read_retval = 0; | ||
443 | char mybuf[line_size]; | ||
444 | loff_t pos; | ||
445 | loff_t offset = (unsigned long)0; | ||
446 | mm_segment_t old_fs; | ||
447 | |||
448 | |||
449 | myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); | ||
450 | |||
451 | |||
452 | if (IS_ERR(myfile)) | ||
453 | { | ||
454 | const int open_errno = -PTR_ERR(myfile); | ||
455 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); | ||
456 | return PTR_ERR(myfile); | ||
457 | } | ||
458 | else | ||
459 | { | ||
460 | if( !(myfile->f_op) ) | ||
461 | { | ||
462 | printk("%s: File has no file operations registered!", __func__); | ||
463 | filp_close(myfile, NULL); | ||
464 | return -EIO; | ||
465 | } | ||
466 | |||
467 | |||
468 | if( !myfile->f_op->read ) | ||
469 | { | ||
470 | printk("%s: File has no READ operations registered! Returning.", __func__); | ||
471 | filp_close(myfile, NULL); | ||
472 | return -EIO; | ||
473 | } | ||
474 | |||
475 | pos = myfile->f_pos; | ||
476 | old_fs = get_fs(); | ||
477 | set_fs(KERNEL_DS); | ||
478 | |||
479 | |||
480 | for( j = 0; j < NUM_FRAMES; j++ ) | ||
481 | { | ||
482 | for( i = 0; i < dev->_lines_count; i++ ) | ||
483 | { | ||
484 | pos = offset; | ||
485 | |||
486 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); | ||
487 | |||
488 | if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) | ||
489 | { | ||
490 | memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval); | ||
491 | } | ||
492 | |||
493 | |||
494 | offset += vfs_read_retval; | ||
495 | |||
496 | if( vfs_read_retval < line_size ) | ||
497 | { | ||
498 | printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); | ||
499 | break; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | if( i > 0 ) | ||
504 | dev->_frame_count++; | ||
505 | |||
506 | if( vfs_read_retval < line_size ) | ||
507 | { | ||
508 | break; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | |||
513 | dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
514 | |||
515 | set_fs(old_fs); | ||
516 | myfile->f_pos = 0; | ||
517 | filp_close(myfile, NULL); | ||
518 | } | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | |||
524 | int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | ||
525 | struct sram_channel *sram_ch, | ||
526 | int bpl) | ||
527 | { | ||
528 | int ret = 0; | ||
529 | dma_addr_t dma_addr; | ||
530 | dma_addr_t data_dma_addr; | ||
531 | |||
532 | if( dev->_dma_virt_addr != NULL ) | ||
533 | { | ||
534 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); | ||
535 | } | ||
536 | |||
537 | |||
538 | dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, &dma_addr); | ||
539 | dev->_dma_virt_start_addr = dev->_dma_virt_addr; | ||
540 | dev->_dma_phys_start_addr = dma_addr; | ||
541 | dev->_dma_phys_addr = dma_addr; | ||
542 | dev->_risc_size = dev->upstream_riscbuf_size; | ||
543 | |||
544 | |||
545 | if (!dev->_dma_virt_addr) | ||
546 | { | ||
547 | printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); | ||
548 | return -ENOMEM; | ||
549 | } | ||
550 | |||
551 | |||
552 | //Clear memory at address | ||
553 | memset( dev->_dma_virt_addr, 0, dev->_risc_size ); | ||
554 | |||
555 | |||
556 | if( dev->_data_buf_virt_addr != NULL ) | ||
557 | { | ||
558 | pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); | ||
559 | } | ||
560 | |||
561 | //For Video Data buffer allocation | ||
562 | dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, &data_dma_addr); | ||
563 | dev->_data_buf_phys_addr = data_dma_addr; | ||
564 | dev->_data_buf_size = dev->upstream_databuf_size; | ||
565 | |||
566 | if (!dev->_data_buf_virt_addr) | ||
567 | { | ||
568 | printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); | ||
569 | return -ENOMEM; | ||
570 | } | ||
571 | |||
572 | |||
573 | //Clear memory at address | ||
574 | memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); | ||
575 | |||
576 | |||
577 | ret = cx25821_openfile(dev, sram_ch); | ||
578 | if( ret < 0 ) | ||
579 | return ret; | ||
580 | |||
581 | |||
582 | //Create RISC programs | ||
583 | ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, dev->_lines_count ); | ||
584 | if (ret < 0) | ||
585 | { | ||
586 | printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); | ||
587 | goto error; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | |||
592 | error: | ||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) | ||
597 | { | ||
598 | u32 int_msk_tmp; | ||
599 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
600 | int singlefield_lines = NTSC_FIELD_HEIGHT; | ||
601 | int line_size_in_bytes = Y422_LINE_SZ; | ||
602 | int odd_risc_prog_size = 0; | ||
603 | dma_addr_t risc_phys_jump_addr; | ||
604 | __le32 * rp; | ||
605 | |||
606 | |||
607 | |||
608 | if (status & FLD_VID_SRC_RISC1) | ||
609 | { | ||
610 | // We should only process one program per call | ||
611 | u32 prog_cnt = cx_read( channel->gpcnt ); | ||
612 | |||
613 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
614 | int_msk_tmp = cx_read(channel->int_msk); | ||
615 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | ||
616 | cx_write( channel->int_stat, _intr_msk ); | ||
617 | |||
618 | spin_lock(&dev->slock); | ||
619 | |||
620 | dev->_frame_index = prog_cnt; | ||
621 | |||
622 | queue_work(dev->_irq_queues, &dev->_irq_work_entry); | ||
623 | |||
624 | |||
625 | if ( dev->_is_first_frame ) | ||
626 | { | ||
627 | dev->_is_first_frame = 0; | ||
628 | |||
629 | if( dev->_isNTSC ) | ||
630 | { | ||
631 | singlefield_lines += 1; | ||
632 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | ||
633 | } | ||
634 | else | ||
635 | { | ||
636 | singlefield_lines = PAL_FIELD_HEIGHT; | ||
637 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | ||
638 | } | ||
639 | |||
640 | |||
641 | if( dev->_dma_virt_start_addr != NULL ) | ||
642 | { | ||
643 | line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
644 | risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size; | ||
645 | |||
646 | rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); | ||
647 | |||
648 | // Jump to Even Risc program of 1st Frame | ||
649 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
650 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
651 | *(rp++) = cpu_to_le32(0); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | spin_unlock(&dev->slock); | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | if(status & FLD_VID_SRC_UF) | ||
660 | printk("%s: Video Received Underflow Error Interrupt!\n", __func__); | ||
661 | |||
662 | if(status & FLD_VID_SRC_SYNC) | ||
663 | printk("%s: Video Received Sync Error Interrupt!\n", __func__); | ||
664 | |||
665 | if(status & FLD_VID_SRC_OPC_ERR) | ||
666 | printk("%s: Video Received OpCode Error Interrupt!\n", __func__); | ||
667 | } | ||
668 | |||
669 | |||
670 | if( dev->_file_status == END_OF_FILE ) | ||
671 | { | ||
672 | printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count ); | ||
673 | return -1; | ||
674 | } | ||
675 | |||
676 | //ElSE, set the interrupt mask register, re-enable irq. | ||
677 | int_msk_tmp = cx_read( channel->int_msk ); | ||
678 | cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) | ||
684 | { | ||
685 | struct cx25821_dev *dev = dev_id; | ||
686 | u32 msk_stat, vid_status; | ||
687 | int handled = 0; | ||
688 | int channel_num = 0; | ||
689 | struct sram_channel *sram_ch; | ||
690 | |||
691 | |||
692 | if( !dev ) | ||
693 | return -1; | ||
694 | |||
695 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; | ||
696 | |||
697 | sram_ch = &dev->sram_channels[channel_num]; | ||
698 | |||
699 | msk_stat = cx_read(sram_ch->int_mstat); | ||
700 | vid_status = cx_read(sram_ch->int_stat); | ||
701 | |||
702 | // Only deal with our interrupt | ||
703 | if(vid_status) | ||
704 | { | ||
705 | handled = cx25821_video_upstream_irq(dev, channel_num, vid_status); | ||
706 | } | ||
707 | |||
708 | if( handled < 0 ) | ||
709 | { | ||
710 | cx25821_stop_upstream_video_ch1(dev); | ||
711 | } | ||
712 | else | ||
713 | { | ||
714 | handled += handled; | ||
715 | } | ||
716 | |||
717 | return IRQ_RETVAL(handled); | ||
718 | } | ||
719 | |||
720 | |||
721 | void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) | ||
722 | { | ||
723 | int width = WIDTH_D1; | ||
724 | int height = dev->_lines_count; | ||
725 | int num_lines, odd_num_lines; | ||
726 | u32 value; | ||
727 | int vip_mode = OUTPUT_FRMT_656; | ||
728 | |||
729 | |||
730 | value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); | ||
731 | value &= 0xFFFFFFEF; | ||
732 | value |= dev->_isNTSC ? 0 : 0x10; | ||
733 | cx_write( ch->vid_fmt_ctl, value ); | ||
734 | |||
735 | |||
736 | // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format | ||
737 | cx_write( ch->vid_active_ctl1, width ); | ||
738 | |||
739 | num_lines = (height / 2) & 0x3FF; | ||
740 | odd_num_lines = num_lines; | ||
741 | |||
742 | if(dev->_isNTSC) | ||
743 | { | ||
744 | odd_num_lines += 1; | ||
745 | } | ||
746 | |||
747 | value = (num_lines << 16) | odd_num_lines; | ||
748 | |||
749 | // set number of active lines in field 0 (top) and field 1 (bottom) | ||
750 | cx_write( ch->vid_active_ctl2, value ); | ||
751 | |||
752 | cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); | ||
753 | } | ||
754 | |||
755 | |||
756 | int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | ||
757 | struct sram_channel *sram_ch) | ||
758 | { | ||
759 | u32 tmp = 0; | ||
760 | int err = 0; | ||
761 | |||
762 | |||
763 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
764 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
765 | cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
766 | |||
767 | |||
768 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. | ||
769 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); | ||
770 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
771 | |||
772 | /* reset counter */ | ||
773 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
774 | |||
775 | // Clear our bits from the interrupt status register. | ||
776 | cx_write( sram_ch->int_stat, _intr_msk ); | ||
777 | |||
778 | |||
779 | //Set the interrupt mask register, enable irq. | ||
780 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
781 | tmp = cx_read( sram_ch->int_msk ); | ||
782 | cx_write( sram_ch->int_msk, tmp |= _intr_msk ); | ||
783 | |||
784 | |||
785 | err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
786 | if (err < 0) | ||
787 | { | ||
788 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); | ||
789 | goto fail_irq; | ||
790 | } | ||
791 | |||
792 | |||
793 | // Start the DMA engine | ||
794 | tmp = cx_read( sram_ch->dma_ctl ); | ||
795 | cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); | ||
796 | |||
797 | dev->_is_running = 1; | ||
798 | dev->_is_first_frame = 1; | ||
799 | |||
800 | return 0; | ||
801 | |||
802 | fail_irq: | ||
803 | cx25821_dev_unregister(dev); | ||
804 | return err; | ||
805 | } | ||
806 | |||
807 | |||
808 | int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format) | ||
809 | { | ||
810 | struct sram_channel *sram_ch; | ||
811 | u32 tmp; | ||
812 | int retval = 0; | ||
813 | int err = 0; | ||
814 | int data_frame_size = 0; | ||
815 | int risc_buffer_size = 0; | ||
816 | int str_length = 0; | ||
817 | |||
818 | |||
819 | if( dev->_is_running ) | ||
820 | { | ||
821 | printk("Video Channel is still running so return!\n"); | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | |||
826 | dev->_channel_upstream_select = channel_select; | ||
827 | sram_ch = &dev->sram_channels[channel_select]; | ||
828 | |||
829 | |||
830 | INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); | ||
831 | dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); | ||
832 | |||
833 | if(!dev->_irq_queues) | ||
834 | { | ||
835 | printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); | ||
836 | return -ENOMEM; | ||
837 | } | ||
838 | |||
839 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
840 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
841 | cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
842 | |||
843 | |||
844 | dev->_is_running = 0; | ||
845 | dev->_frame_count = 0; | ||
846 | dev->_file_status = RESET_STATUS; | ||
847 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | ||
848 | dev->_pixel_format = pixel_format; | ||
849 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
850 | data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | ||
851 | risc_buffer_size = dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | ||
852 | |||
853 | |||
854 | if( dev->input_filename ) | ||
855 | { | ||
856 | str_length = strlen(dev->input_filename); | ||
857 | dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
858 | |||
859 | if( !dev->_filename ) | ||
860 | goto error; | ||
861 | |||
862 | memcpy(dev->_filename, dev->input_filename, str_length + 1); | ||
863 | } | ||
864 | else | ||
865 | { | ||
866 | str_length = strlen(dev->_defaultname); | ||
867 | dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); | ||
868 | |||
869 | if( !dev->_filename ) | ||
870 | goto error; | ||
871 | |||
872 | memcpy(dev->_filename, dev->_defaultname, str_length + 1); | ||
873 | } | ||
874 | |||
875 | |||
876 | //Default if filename is empty string | ||
877 | if( strcmp(dev->input_filename,"") == 0) | ||
878 | { | ||
879 | if( dev->_isNTSC ) | ||
880 | { | ||
881 | dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; | ||
882 | } | ||
883 | else | ||
884 | { | ||
885 | dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; | ||
886 | } | ||
887 | } | ||
888 | |||
889 | dev->_is_running = 0; | ||
890 | dev->_frame_count = 0; | ||
891 | dev->_file_status = RESET_STATUS; | ||
892 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | ||
893 | dev->_pixel_format = pixel_format; | ||
894 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
895 | |||
896 | retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, 0); | ||
897 | |||
898 | /* setup fifo + format */ | ||
899 | cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); | ||
900 | |||
901 | dev->upstream_riscbuf_size = risc_buffer_size * 2; | ||
902 | dev->upstream_databuf_size = data_frame_size * 2; | ||
903 | |||
904 | |||
905 | //Allocating buffers and prepare RISC program | ||
906 | retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); | ||
907 | if (retval < 0) | ||
908 | { | ||
909 | printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); | ||
910 | goto error; | ||
911 | } | ||
912 | |||
913 | |||
914 | cx25821_start_video_dma_upstream(dev, sram_ch); | ||
915 | |||
916 | return 0; | ||
917 | |||
918 | error: | ||
919 | cx25821_dev_unregister(dev); | ||
920 | |||
921 | return err; | ||
922 | } | ||
923 | |||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h new file mode 100644 index 00000000000..632ccc65bc7 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #define OUTPUT_FRMT_656 0 | ||
27 | #define OPEN_FILE_1 0 | ||
28 | #define NUM_PROGS 8 | ||
29 | #define NUM_FRAMES 2 | ||
30 | #define ODD_FIELD 0 | ||
31 | #define EVEN_FIELD 1 | ||
32 | #define TOP_OFFSET 0 | ||
33 | #define FIFO_DISABLE 0 | ||
34 | #define FIFO_ENABLE 1 | ||
35 | #define TEST_FRAMES 5 | ||
36 | #define END_OF_FILE 0 | ||
37 | #define IN_PROGRESS 1 | ||
38 | #define RESET_STATUS -1 | ||
39 | #define NUM_NO_OPS 5 | ||
40 | |||
41 | |||
42 | |||
43 | // PAL and NTSC line sizes and number of lines. | ||
44 | #define WIDTH_D1 720 | ||
45 | #define NTSC_LINES_PER_FRAME 480 | ||
46 | #define PAL_LINES_PER_FRAME 576 | ||
47 | #define PAL_LINE_SZ 1440 | ||
48 | #define Y422_LINE_SZ 1440 | ||
49 | #define Y411_LINE_SZ 1080 | ||
50 | #define NTSC_FIELD_HEIGHT 240 | ||
51 | #define NTSC_ODD_FLD_LINES 241 | ||
52 | #define PAL_FIELD_HEIGHT 288 | ||
53 | |||
54 | #define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) | ||
55 | #define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) | ||
56 | #define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) | ||
57 | #define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) | ||
58 | |||
59 | #define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) | ||
60 | #define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) | ||
61 | |||
62 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
63 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
64 | #define JUMP_INSTRUCTION_SIZE 12 | ||
65 | #define MAXSIZE_NO_OPS 36 | ||
66 | #define DWORD_SIZE 4 | ||
67 | |||
68 | |||
69 | #define USE_RISC_NOOP_VIDEO 1 | ||
70 | |||
71 | #ifdef USE_RISC_NOOP_VIDEO | ||
72 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
73 | RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
74 | |||
75 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
76 | |||
77 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
78 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
79 | |||
80 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
81 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
82 | |||
83 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
84 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
85 | |||
86 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
87 | JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
88 | |||
89 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
90 | |||
91 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
92 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
93 | |||
94 | #endif | ||
95 | |||
96 | |||
97 | #ifndef USE_RISC_NOOP_VIDEO | ||
98 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
99 | RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
100 | |||
101 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
102 | |||
103 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
104 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
105 | |||
106 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
107 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
108 | |||
109 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
110 | #define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) | ||
111 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
112 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
113 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c new file mode 100644 index 00000000000..512cbe3bae8 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video.c | |||
@@ -0,0 +1,1337 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
27 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | ||
31 | static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | ||
32 | |||
33 | module_param_array(video_nr, int, NULL, 0444); | ||
34 | module_param_array(radio_nr, int, NULL, 0444); | ||
35 | |||
36 | MODULE_PARM_DESC(video_nr, "video device numbers"); | ||
37 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | ||
38 | |||
39 | static unsigned int video_debug=VIDEO_DEBUG; | ||
40 | module_param(video_debug, int, 0644); | ||
41 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | ||
42 | |||
43 | static unsigned int irq_debug; | ||
44 | module_param(irq_debug, int, 0644); | ||
45 | MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); | ||
46 | |||
47 | unsigned int vid_limit = 16; | ||
48 | module_param(vid_limit, int, 0644); | ||
49 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | ||
50 | |||
51 | static void init_controls(struct cx25821_dev *dev, int chan_num); | ||
52 | |||
53 | #define FORMAT_FLAGS_PACKED 0x01 | ||
54 | |||
55 | struct cx25821_fmt formats[] = { | ||
56 | { | ||
57 | .name = "8 bpp, gray", | ||
58 | .fourcc = V4L2_PIX_FMT_GREY, | ||
59 | .depth = 8, | ||
60 | .flags = FORMAT_FLAGS_PACKED, | ||
61 | }, { | ||
62 | .name = "4:1:1, packed, Y41P", | ||
63 | .fourcc = V4L2_PIX_FMT_Y41P, | ||
64 | .depth = 12, | ||
65 | .flags = FORMAT_FLAGS_PACKED, | ||
66 | }, { | ||
67 | .name = "4:2:2, packed, YUYV", | ||
68 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
69 | .depth = 16, | ||
70 | .flags = FORMAT_FLAGS_PACKED, | ||
71 | }, { | ||
72 | .name = "4:2:2, packed, UYVY", | ||
73 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
74 | .depth = 16, | ||
75 | .flags = FORMAT_FLAGS_PACKED, | ||
76 | },{ | ||
77 | .name = "4:2:0, YUV", | ||
78 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
79 | .depth = 12, | ||
80 | .flags = FORMAT_FLAGS_PACKED, | ||
81 | }, | ||
82 | }; | ||
83 | |||
84 | |||
85 | int get_format_size(void) | ||
86 | { | ||
87 | return ARRAY_SIZE(formats); | ||
88 | } | ||
89 | |||
90 | |||
91 | struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) | ||
92 | { | ||
93 | unsigned int i; | ||
94 | |||
95 | if( fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P ) | ||
96 | { | ||
97 | return formats+1; | ||
98 | } | ||
99 | |||
100 | for (i = 0; i < ARRAY_SIZE(formats); i++) | ||
101 | if (formats[i].fourcc == fourcc) | ||
102 | return formats+i; | ||
103 | |||
104 | printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); | ||
105 | return NULL; | ||
106 | } | ||
107 | |||
108 | void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) | ||
109 | { | ||
110 | struct cx25821_buffer *buf; | ||
111 | struct list_head *item; | ||
112 | dprintk(1, "%s()\n", __func__); | ||
113 | |||
114 | if (!list_empty(&q->active)) { | ||
115 | list_for_each(item, &q->active) | ||
116 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
117 | } | ||
118 | |||
119 | if (!list_empty(&q->queued)) | ||
120 | { | ||
121 | list_for_each(item, &q->queued) | ||
122 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
123 | } | ||
124 | |||
125 | } | ||
126 | |||
127 | |||
128 | void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count) | ||
129 | { | ||
130 | struct cx25821_buffer *buf; | ||
131 | int bc; | ||
132 | |||
133 | for (bc = 0;; bc++) { | ||
134 | if (list_empty(&q->active)) | ||
135 | { | ||
136 | dprintk(1, "bc=%d (=0: active empty)\n", bc); | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
141 | |||
142 | /* count comes from the hw and it is 16bit wide -- | ||
143 | * this trick handles wrap-arounds correctly for | ||
144 | * up to 32767 buffers in flight... */ | ||
145 | if ((s16) (count - buf->count) < 0) | ||
146 | { | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | do_gettimeofday(&buf->vb.ts); | ||
151 | buf->vb.state = VIDEOBUF_DONE; | ||
152 | list_del(&buf->vb.queue); | ||
153 | wake_up(&buf->vb.done); | ||
154 | } | ||
155 | |||
156 | if (list_empty(&q->active)) | ||
157 | del_timer(&q->timeout); | ||
158 | else | ||
159 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
160 | if (bc != 1) | ||
161 | printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc); | ||
162 | } | ||
163 | |||
164 | #ifdef TUNER_FLAG | ||
165 | int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) | ||
166 | { | ||
167 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, | ||
168 | (unsigned int)norm, | ||
169 | v4l2_norm_to_name(norm)); | ||
170 | |||
171 | dev->tvnorm = norm; | ||
172 | |||
173 | /* Tell the internal A/V decoder */ | ||
174 | cx25821_call_all(dev, core, s_std, norm); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | #endif | ||
179 | |||
180 | struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
181 | struct pci_dev *pci, | ||
182 | struct video_device *template, | ||
183 | char *type) | ||
184 | { | ||
185 | struct video_device *vfd; | ||
186 | dprintk(1, "%s()\n", __func__); | ||
187 | |||
188 | vfd = video_device_alloc(); | ||
189 | if (NULL == vfd) | ||
190 | return NULL; | ||
191 | *vfd = *template; | ||
192 | vfd->minor = -1; | ||
193 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
194 | vfd->release = video_device_release; | ||
195 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx25821_boards[dev->board].name); | ||
196 | return vfd; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
201 | { | ||
202 | int i; | ||
203 | |||
204 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | ||
205 | return -EINVAL; | ||
206 | for (i = 0; i < CX25821_CTLS; i++) | ||
207 | if (cx25821_ctls[i].v.id == qctrl->id) | ||
208 | break; | ||
209 | if (i == CX25821_CTLS) { | ||
210 | *qctrl = no_ctl; | ||
211 | return 0; | ||
212 | } | ||
213 | *qctrl = cx25821_ctls[i].v; | ||
214 | return 0; | ||
215 | } | ||
216 | */ | ||
217 | |||
218 | // resource management | ||
219 | int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) | ||
220 | { | ||
221 | dprintk(1, "%s()\n", __func__); | ||
222 | if (fh->resources & bit) | ||
223 | /* have it already allocated */ | ||
224 | return 1; | ||
225 | |||
226 | /* is it free? */ | ||
227 | mutex_lock(&dev->lock); | ||
228 | if (dev->resources & bit) { | ||
229 | /* no, someone else uses it */ | ||
230 | mutex_unlock(&dev->lock); | ||
231 | return 0; | ||
232 | } | ||
233 | /* it's free, grab it */ | ||
234 | fh->resources |= bit; | ||
235 | dev->resources |= bit; | ||
236 | dprintk(1, "res: get %d\n", bit); | ||
237 | mutex_unlock(&dev->lock); | ||
238 | return 1; | ||
239 | } | ||
240 | |||
241 | int res_check(struct cx25821_fh *fh, unsigned int bit) | ||
242 | { | ||
243 | return fh->resources & bit; | ||
244 | } | ||
245 | |||
246 | int res_locked(struct cx25821_dev *dev, unsigned int bit) | ||
247 | { | ||
248 | return dev->resources & bit; | ||
249 | } | ||
250 | |||
251 | void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) | ||
252 | { | ||
253 | BUG_ON((fh->resources & bits) != bits); | ||
254 | dprintk(1, "%s()\n", __func__); | ||
255 | |||
256 | mutex_lock(&dev->lock); | ||
257 | fh->resources &= ~bits; | ||
258 | dev->resources &= ~bits; | ||
259 | dprintk(1, "res: put %d\n", bits); | ||
260 | mutex_unlock(&dev->lock); | ||
261 | } | ||
262 | |||
263 | int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) | ||
264 | { | ||
265 | struct v4l2_routing route; | ||
266 | memset(&route, 0, sizeof(route)); | ||
267 | |||
268 | dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, | ||
269 | input, INPUT(input)->vmux, | ||
270 | INPUT(input)->gpio0, INPUT(input)->gpio1, | ||
271 | INPUT(input)->gpio2, INPUT(input)->gpio3); | ||
272 | dev->input = input; | ||
273 | |||
274 | route.input = INPUT(input)->vmux; | ||
275 | |||
276 | /* Tell the internal A/V decoder */ | ||
277 | cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | int cx25821_start_video_dma(struct cx25821_dev *dev, | ||
283 | struct cx25821_dmaqueue *q, | ||
284 | struct cx25821_buffer *buf, | ||
285 | struct sram_channel *channel) | ||
286 | { | ||
287 | int tmp = 0; | ||
288 | |||
289 | /* setup fifo + format */ | ||
290 | cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); | ||
291 | |||
292 | /* reset counter */ | ||
293 | cx_write(channel->gpcnt_ctl, 3); | ||
294 | q->count = 1; | ||
295 | |||
296 | /* enable irq */ | ||
297 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1<<channel->i)); | ||
298 | cx_set(channel->int_msk, 0x11); | ||
299 | |||
300 | /* start dma */ | ||
301 | cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ | ||
302 | |||
303 | /* make sure upstream setting if any is reversed */ | ||
304 | tmp = cx_read( VID_CH_MODE_SEL ); | ||
305 | cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | |||
311 | int cx25821_restart_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, struct sram_channel *channel) | ||
312 | { | ||
313 | struct cx25821_buffer *buf, *prev; | ||
314 | struct list_head *item; | ||
315 | |||
316 | if (!list_empty(&q->active)) { | ||
317 | buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
318 | |||
319 | cx25821_start_video_dma(dev, q, buf, channel); | ||
320 | |||
321 | list_for_each(item, &q->active) { | ||
322 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
323 | buf->count = q->count++; | ||
324 | } | ||
325 | |||
326 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | prev = NULL; | ||
331 | for (;;) { | ||
332 | if (list_empty(&q->queued)) | ||
333 | return 0; | ||
334 | |||
335 | buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue); | ||
336 | |||
337 | if (NULL == prev) { | ||
338 | list_move_tail(&buf->vb.queue, &q->active); | ||
339 | cx25821_start_video_dma(dev, q, buf, channel); | ||
340 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
341 | buf->count = q->count++; | ||
342 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
343 | } else if (prev->vb.width == buf->vb.width && | ||
344 | prev->vb.height == buf->vb.height && | ||
345 | prev->fmt == buf->fmt) { | ||
346 | list_move_tail(&buf->vb.queue, &q->active); | ||
347 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
348 | buf->count = q->count++; | ||
349 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
350 | prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ | ||
351 | } else { | ||
352 | return 0; | ||
353 | } | ||
354 | prev = buf; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | void cx25821_vid_timeout(unsigned long data) | ||
359 | { | ||
360 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; | ||
361 | struct cx25821_dev *dev = timeout_data->dev; | ||
362 | struct sram_channel *channel = timeout_data->channel; | ||
363 | struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; | ||
364 | struct cx25821_buffer *buf; | ||
365 | unsigned long flags; | ||
366 | |||
367 | //cx25821_sram_channel_dump(dev, channel); | ||
368 | cx_clear(channel->dma_ctl, 0x11); | ||
369 | |||
370 | spin_lock_irqsave(&dev->slock, flags); | ||
371 | while (!list_empty(&q->active)) { | ||
372 | buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
373 | list_del(&buf->vb.queue); | ||
374 | |||
375 | buf->vb.state = VIDEOBUF_ERROR; | ||
376 | wake_up(&buf->vb.done); | ||
377 | } | ||
378 | |||
379 | cx25821_restart_video_queue(dev, q, channel); | ||
380 | spin_unlock_irqrestore(&dev->slock, flags); | ||
381 | } | ||
382 | |||
383 | int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | ||
384 | { | ||
385 | u32 count=0; | ||
386 | int handled = 0; | ||
387 | u32 mask; | ||
388 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
389 | |||
390 | mask = cx_read(channel->int_msk); | ||
391 | if (0 == (status & mask)) | ||
392 | return handled; | ||
393 | |||
394 | cx_write(channel->int_stat, status); | ||
395 | |||
396 | /* risc op code error */ | ||
397 | if (status & (1 << 16)) { | ||
398 | printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name); | ||
399 | cx_clear(channel->dma_ctl, 0x11); | ||
400 | cx25821_sram_channel_dump(dev, channel); | ||
401 | } | ||
402 | |||
403 | /* risc1 y */ | ||
404 | if (status & FLD_VID_DST_RISC1) { | ||
405 | spin_lock(&dev->slock); | ||
406 | count = cx_read(channel->gpcnt); | ||
407 | cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); | ||
408 | spin_unlock(&dev->slock); | ||
409 | handled++; | ||
410 | } | ||
411 | |||
412 | /* risc2 y */ | ||
413 | if (status & 0x10) { | ||
414 | dprintk(2, "stopper video\n"); | ||
415 | spin_lock(&dev->slock); | ||
416 | cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel); | ||
417 | spin_unlock(&dev->slock); | ||
418 | handled++; | ||
419 | } | ||
420 | return handled; | ||
421 | } | ||
422 | |||
423 | void cx25821_videoioctl_unregister(struct cx25821_dev *dev) | ||
424 | { | ||
425 | if( dev->ioctl_dev ) | ||
426 | { | ||
427 | if (dev->ioctl_dev->minor != -1) | ||
428 | video_unregister_device(dev->ioctl_dev); | ||
429 | else | ||
430 | video_device_release(dev->ioctl_dev); | ||
431 | |||
432 | dev->ioctl_dev = NULL; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) | ||
437 | { | ||
438 | cx_clear(PCI_INT_MSK, 1); | ||
439 | |||
440 | if (dev->video_dev[chan_num]) { | ||
441 | if (-1 != dev->video_dev[chan_num]->minor) | ||
442 | video_unregister_device(dev->video_dev[chan_num]); | ||
443 | else | ||
444 | video_device_release(dev->video_dev[chan_num]); | ||
445 | |||
446 | dev->video_dev[chan_num] = NULL; | ||
447 | |||
448 | btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); | ||
449 | |||
450 | printk(KERN_WARNING "device %d released!\n", chan_num); | ||
451 | } | ||
452 | |||
453 | } | ||
454 | |||
455 | |||
456 | int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template) | ||
457 | { | ||
458 | int err; | ||
459 | |||
460 | spin_lock_init(&dev->slock); | ||
461 | |||
462 | //printk(KERN_WARNING "Channel %d\n", chan_num); | ||
463 | |||
464 | #ifdef TUNER_FLAG | ||
465 | dev->tvnorm = video_template->current_norm; | ||
466 | #endif | ||
467 | |||
468 | /* init video dma queues */ | ||
469 | dev->timeout_data[chan_num].dev = dev; | ||
470 | dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num]; | ||
471 | INIT_LIST_HEAD(&dev->vidq[chan_num].active); | ||
472 | INIT_LIST_HEAD(&dev->vidq[chan_num].queued); | ||
473 | dev->vidq[chan_num].timeout.function = cx25821_vid_timeout; | ||
474 | dev->vidq[chan_num].timeout.data = (unsigned long)&dev->timeout_data[chan_num]; | ||
475 | init_timer(&dev->vidq[chan_num].timeout); | ||
476 | cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, dev->sram_channels[chan_num].dma_ctl, 0x11, 0); | ||
477 | |||
478 | |||
479 | /* register v4l devices */ | ||
480 | dev->video_dev[chan_num] = cx25821_vdev_init(dev, dev->pci, video_template, "video"); | ||
481 | err = video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, video_nr[dev->nr]); | ||
482 | |||
483 | if (err < 0) { | ||
484 | goto fail_unreg; | ||
485 | } | ||
486 | |||
487 | //set PCI interrupt | ||
488 | cx_set(PCI_INT_MSK, 0xff); | ||
489 | |||
490 | |||
491 | /* initial device configuration */ | ||
492 | mutex_lock(&dev->lock); | ||
493 | #ifdef TUNER_FLAG | ||
494 | cx25821_set_tvnorm(dev, dev->tvnorm); | ||
495 | #endif | ||
496 | mutex_unlock(&dev->lock); | ||
497 | |||
498 | init_controls(dev, chan_num); | ||
499 | |||
500 | return 0; | ||
501 | |||
502 | fail_unreg: | ||
503 | cx25821_video_unregister(dev, chan_num); | ||
504 | return err; | ||
505 | } | ||
506 | |||
507 | int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | ||
508 | { | ||
509 | struct cx25821_fh *fh = q->priv_data; | ||
510 | |||
511 | *size = fh->fmt->depth*fh->width*fh->height >> 3; | ||
512 | |||
513 | |||
514 | if (0 == *count) | ||
515 | *count = 32; | ||
516 | |||
517 | while (*size * *count > vid_limit * 1024 * 1024) | ||
518 | (*count)--; | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) | ||
524 | { | ||
525 | struct cx25821_fh *fh = q->priv_data; | ||
526 | struct cx25821_dev *dev = fh->dev; | ||
527 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
528 | int rc, init_buffer = 0; | ||
529 | u32 line0_offset, line1_offset; | ||
530 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | ||
531 | int bpl_local = LINE_SIZE_D1; | ||
532 | int channel_opened = 0; | ||
533 | |||
534 | |||
535 | BUG_ON(NULL == fh->fmt); | ||
536 | if (fh->width < 48 || fh->width > 720 || | ||
537 | fh->height < 32 || fh->height > 576) | ||
538 | return -EINVAL; | ||
539 | |||
540 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; | ||
541 | |||
542 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
543 | return -EINVAL; | ||
544 | |||
545 | |||
546 | if (buf->fmt != fh->fmt || | ||
547 | buf->vb.width != fh->width || | ||
548 | buf->vb.height != fh->height || | ||
549 | buf->vb.field != field) { | ||
550 | buf->fmt = fh->fmt; | ||
551 | buf->vb.width = fh->width; | ||
552 | buf->vb.height = fh->height; | ||
553 | buf->vb.field = field; | ||
554 | init_buffer = 1; | ||
555 | } | ||
556 | |||
557 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
558 | init_buffer = 1; | ||
559 | rc = videobuf_iolock(q, &buf->vb, NULL); | ||
560 | if (0 != rc) | ||
561 | { | ||
562 | printk(KERN_DEBUG "videobuf_iolock failed!\n"); | ||
563 | goto fail; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | dprintk(1, "init_buffer=%d\n", init_buffer); | ||
568 | |||
569 | if (init_buffer) { | ||
570 | |||
571 | channel_opened = dev->channel_opened; | ||
572 | channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; | ||
573 | |||
574 | if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) | ||
575 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; | ||
576 | else | ||
577 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); | ||
578 | |||
579 | |||
580 | if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) | ||
581 | { | ||
582 | bpl_local = buf->bpl; | ||
583 | } | ||
584 | else | ||
585 | { | ||
586 | bpl_local = buf->bpl; //Default | ||
587 | |||
588 | if( channel_opened >= 0 && channel_opened <= 7 ) | ||
589 | { | ||
590 | if( dev->use_cif_resolution[channel_opened] ) | ||
591 | { | ||
592 | if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) | ||
593 | bpl_local = 352 << 1; | ||
594 | else | ||
595 | bpl_local = dev->cif_width[channel_opened] << 1; | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | |||
600 | |||
601 | switch (buf->vb.field) { | ||
602 | case V4L2_FIELD_TOP: | ||
603 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
604 | dma->sglist, 0, UNSET, | ||
605 | buf->bpl, 0, buf->vb.height); | ||
606 | break; | ||
607 | case V4L2_FIELD_BOTTOM: | ||
608 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
609 | dma->sglist, UNSET, 0, | ||
610 | buf->bpl, 0, buf->vb.height); | ||
611 | break; | ||
612 | case V4L2_FIELD_INTERLACED: | ||
613 | /* All other formats are top field first */ | ||
614 | line0_offset = 0; | ||
615 | line1_offset = buf->bpl; | ||
616 | dprintk(1, "top field first\n"); | ||
617 | |||
618 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
619 | dma->sglist, line0_offset, | ||
620 | bpl_local, bpl_local, bpl_local, | ||
621 | buf->vb.height >> 1); | ||
622 | break; | ||
623 | case V4L2_FIELD_SEQ_TB: | ||
624 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
625 | dma->sglist, | ||
626 | 0, buf->bpl * (buf->vb.height >> 1), | ||
627 | buf->bpl, 0, | ||
628 | buf->vb.height >> 1); | ||
629 | break; | ||
630 | case V4L2_FIELD_SEQ_BT: | ||
631 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
632 | dma->sglist, | ||
633 | buf->bpl * (buf->vb.height >> 1), 0, | ||
634 | buf->bpl, 0, | ||
635 | buf->vb.height >> 1); | ||
636 | break; | ||
637 | default: | ||
638 | BUG(); | ||
639 | } | ||
640 | } | ||
641 | |||
642 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | ||
643 | buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name, | ||
644 | (unsigned long)buf->risc.dma); | ||
645 | |||
646 | buf->vb.state = VIDEOBUF_PREPARED; | ||
647 | |||
648 | return 0; | ||
649 | |||
650 | fail: | ||
651 | cx25821_free_buffer(q, buf); | ||
652 | return rc; | ||
653 | } | ||
654 | |||
655 | |||
656 | void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
657 | { | ||
658 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
659 | |||
660 | cx25821_free_buffer(q, buf); | ||
661 | } | ||
662 | |||
663 | |||
664 | struct videobuf_queue *get_queue(struct cx25821_fh *fh) | ||
665 | { | ||
666 | switch (fh->type) { | ||
667 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
668 | return &fh->vidq; | ||
669 | default: | ||
670 | BUG(); | ||
671 | return NULL; | ||
672 | } | ||
673 | } | ||
674 | |||
675 | int get_resource(struct cx25821_fh *fh, int resource) | ||
676 | { | ||
677 | switch (fh->type) { | ||
678 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
679 | return resource; | ||
680 | default: | ||
681 | BUG(); | ||
682 | return 0; | ||
683 | } | ||
684 | } | ||
685 | |||
686 | |||
687 | int video_mmap(struct file *file, struct vm_area_struct *vma) | ||
688 | { | ||
689 | struct cx25821_fh *fh = file->private_data; | ||
690 | |||
691 | return videobuf_mmap_mapper(get_queue(fh), vma); | ||
692 | } | ||
693 | |||
694 | /* VIDEO IOCTLS */ | ||
695 | int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
696 | { | ||
697 | struct cx25821_fh *fh = priv; | ||
698 | |||
699 | f->fmt.pix.width = fh->width; | ||
700 | f->fmt.pix.height = fh->height; | ||
701 | f->fmt.pix.field = fh->vidq.field; | ||
702 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
703 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
704 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
710 | { | ||
711 | struct cx25821_fmt *fmt; | ||
712 | enum v4l2_field field; | ||
713 | unsigned int maxw, maxh; | ||
714 | |||
715 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
716 | if (NULL == fmt) | ||
717 | return -EINVAL; | ||
718 | |||
719 | field = f->fmt.pix.field; | ||
720 | maxw = 720; | ||
721 | maxh = 576; | ||
722 | |||
723 | if (V4L2_FIELD_ANY == field) { | ||
724 | field = (f->fmt.pix.height > maxh/2) | ||
725 | ? V4L2_FIELD_INTERLACED | ||
726 | : V4L2_FIELD_TOP; | ||
727 | } | ||
728 | |||
729 | switch (field) { | ||
730 | case V4L2_FIELD_TOP: | ||
731 | case V4L2_FIELD_BOTTOM: | ||
732 | maxh = maxh / 2; | ||
733 | break; | ||
734 | case V4L2_FIELD_INTERLACED: | ||
735 | break; | ||
736 | default: | ||
737 | return -EINVAL; | ||
738 | } | ||
739 | |||
740 | f->fmt.pix.field = field; | ||
741 | if (f->fmt.pix.height < 32) | ||
742 | f->fmt.pix.height = 32; | ||
743 | if (f->fmt.pix.height > maxh) | ||
744 | f->fmt.pix.height = maxh; | ||
745 | if (f->fmt.pix.width < 48) | ||
746 | f->fmt.pix.width = 48; | ||
747 | if (f->fmt.pix.width > maxw) | ||
748 | f->fmt.pix.width = maxw; | ||
749 | f->fmt.pix.width &= ~0x03; | ||
750 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
751 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
752 | |||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | |||
757 | |||
758 | int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) | ||
759 | { | ||
760 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
761 | |||
762 | strcpy(cap->driver, "cx25821"); | ||
763 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); | ||
764 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); | ||
765 | cap->version = CX25821_VERSION_CODE; | ||
766 | cap->capabilities = | ||
767 | V4L2_CAP_VIDEO_CAPTURE | | ||
768 | V4L2_CAP_READWRITE | | ||
769 | V4L2_CAP_STREAMING; | ||
770 | if (UNSET != dev->tuner_type) | ||
771 | cap->capabilities |= V4L2_CAP_TUNER; | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) | ||
776 | { | ||
777 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | ||
778 | return -EINVAL; | ||
779 | |||
780 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | ||
781 | f->pixelformat = formats[f->index].fourcc; | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
787 | int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | ||
788 | { | ||
789 | struct cx25821_fh *fh = priv; | ||
790 | struct videobuf_queue *q; | ||
791 | struct v4l2_requestbuffers req; | ||
792 | unsigned int i; | ||
793 | int err; | ||
794 | |||
795 | q = get_queue(fh); | ||
796 | memset(&req, 0, sizeof(req)); | ||
797 | req.type = q->type; | ||
798 | req.count = 8; | ||
799 | req.memory = V4L2_MEMORY_MMAP; | ||
800 | err = videobuf_reqbufs(q, &req); | ||
801 | if (err < 0) | ||
802 | return err; | ||
803 | |||
804 | mbuf->frames = req.count; | ||
805 | mbuf->size = 0; | ||
806 | for (i = 0; i < mbuf->frames; i++) { | ||
807 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
808 | mbuf->size += q->bufs[i]->bsize; | ||
809 | } | ||
810 | return 0; | ||
811 | } | ||
812 | #endif | ||
813 | |||
814 | int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
815 | { | ||
816 | struct cx25821_fh *fh = priv; | ||
817 | return videobuf_reqbufs(get_queue(fh), p); | ||
818 | } | ||
819 | |||
820 | int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
821 | { | ||
822 | struct cx25821_fh *fh = priv; | ||
823 | return videobuf_querybuf(get_queue(fh), p); | ||
824 | } | ||
825 | |||
826 | int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
827 | { | ||
828 | struct cx25821_fh *fh = priv; | ||
829 | return videobuf_qbuf(get_queue(fh), p); | ||
830 | } | ||
831 | |||
832 | int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | ||
833 | { | ||
834 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | ||
835 | |||
836 | *p = v4l2_prio_max(&dev->prio); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | int vidioc_s_priority(struct file *file, void *f, | ||
842 | enum v4l2_priority prio) | ||
843 | { | ||
844 | struct cx25821_fh *fh = f; | ||
845 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | ||
846 | |||
847 | return v4l2_prio_change(&dev->prio, &fh->prio, prio); | ||
848 | } | ||
849 | |||
850 | |||
851 | #ifdef TUNER_FLAG | ||
852 | int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | ||
853 | { | ||
854 | struct cx25821_fh *fh = priv; | ||
855 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
856 | int err; | ||
857 | |||
858 | dprintk(1, "%s()\n", __func__); | ||
859 | |||
860 | if (fh) | ||
861 | { | ||
862 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
863 | if (0 != err) | ||
864 | return err; | ||
865 | } | ||
866 | |||
867 | if( dev->tvnorm == *tvnorms ) | ||
868 | { | ||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | mutex_lock(&dev->lock); | ||
873 | cx25821_set_tvnorm(dev, *tvnorms); | ||
874 | mutex_unlock(&dev->lock); | ||
875 | |||
876 | medusa_set_videostandard(dev); | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | #endif | ||
881 | |||
882 | int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) | ||
883 | { | ||
884 | static const char *iname[] = { | ||
885 | [CX25821_VMUX_COMPOSITE] = "Composite", | ||
886 | [CX25821_VMUX_SVIDEO] = "S-Video", | ||
887 | [CX25821_VMUX_DEBUG] = "for debug only", | ||
888 | }; | ||
889 | unsigned int n; | ||
890 | dprintk(1, "%s()\n", __func__); | ||
891 | |||
892 | n = i->index; | ||
893 | if (n > 2) | ||
894 | return -EINVAL; | ||
895 | |||
896 | if (0 == INPUT(n)->type) | ||
897 | return -EINVAL; | ||
898 | |||
899 | memset(i, 0, sizeof(*i)); | ||
900 | i->index = n; | ||
901 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
902 | strcpy(i->name, iname[INPUT(n)->type]); | ||
903 | |||
904 | i->std = CX25821_NORMS; | ||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) | ||
909 | { | ||
910 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
911 | dprintk(1, "%s()\n", __func__); | ||
912 | return cx25821_enum_input(dev, i); | ||
913 | } | ||
914 | |||
915 | int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
916 | { | ||
917 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
918 | |||
919 | *i = dev->input; | ||
920 | dprintk(1, "%s() returns %d\n", __func__, *i); | ||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | |||
925 | int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
926 | { | ||
927 | struct cx25821_fh *fh = priv; | ||
928 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
929 | int err; | ||
930 | |||
931 | dprintk(1, "%s(%d)\n", __func__, i); | ||
932 | |||
933 | if (fh) | ||
934 | { | ||
935 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
936 | if (0 != err) | ||
937 | return err; | ||
938 | } | ||
939 | |||
940 | if (i > 2) { | ||
941 | dprintk(1, "%s() -EINVAL\n", __func__); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | |||
945 | mutex_lock(&dev->lock); | ||
946 | cx25821_video_mux(dev, i); | ||
947 | mutex_unlock(&dev->lock); | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | #ifdef TUNER_FLAG | ||
952 | int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | ||
953 | { | ||
954 | struct cx25821_fh *fh = priv; | ||
955 | struct cx25821_dev *dev = fh->dev; | ||
956 | |||
957 | f->frequency = dev->freq; | ||
958 | |||
959 | cx25821_call_all(dev, tuner, g_frequency, f); | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) | ||
965 | { | ||
966 | mutex_lock(&dev->lock); | ||
967 | dev->freq = f->frequency; | ||
968 | |||
969 | cx25821_call_all(dev, tuner, s_frequency, f); | ||
970 | |||
971 | /* When changing channels it is required to reset TVAUDIO */ | ||
972 | msleep(10); | ||
973 | |||
974 | mutex_unlock(&dev->lock); | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | ||
980 | { | ||
981 | struct cx25821_fh *fh = priv; | ||
982 | struct cx25821_dev *dev = fh->dev; | ||
983 | int err; | ||
984 | |||
985 | if (fh) | ||
986 | { | ||
987 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
988 | if (0 != err) | ||
989 | return err; | ||
990 | } | ||
991 | |||
992 | return cx25821_set_freq(dev, f); | ||
993 | } | ||
994 | #endif | ||
995 | |||
996 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
997 | int vidioc_g_register(struct file *file, void *fh, | ||
998 | struct v4l2_dbg_register *reg) | ||
999 | { | ||
1000 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
1001 | |||
1002 | if (!v4l2_chip_match_host(®->match)) | ||
1003 | return -EINVAL; | ||
1004 | |||
1005 | cx25821_call_all(dev, core, g_register, reg); | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | int vidioc_s_register(struct file *file, void *fh, | ||
1011 | struct v4l2_dbg_register *reg) | ||
1012 | { | ||
1013 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
1014 | |||
1015 | if (!v4l2_chip_match_host(®->match)) | ||
1016 | return -EINVAL; | ||
1017 | |||
1018 | cx25821_call_all(dev, core, s_register, reg); | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | #endif | ||
1024 | |||
1025 | |||
1026 | #ifdef TUNER_FLAG | ||
1027 | int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | ||
1028 | { | ||
1029 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1030 | |||
1031 | if (unlikely(UNSET == dev->tuner_type)) | ||
1032 | return -EINVAL; | ||
1033 | if (0 != t->index) | ||
1034 | return -EINVAL; | ||
1035 | |||
1036 | strcpy(t->name, "Television"); | ||
1037 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1038 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1039 | t->rangehigh = 0xffffffffUL; | ||
1040 | |||
1041 | t->signal = 0xffff ; /* LOCKED */ | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | int vidioc_s_tuner(struct file *file, void *priv, | ||
1046 | struct v4l2_tuner *t) | ||
1047 | { | ||
1048 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1049 | struct cx25821_fh *fh = priv; | ||
1050 | int err; | ||
1051 | |||
1052 | if (fh) | ||
1053 | { | ||
1054 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
1055 | if (0 != err) | ||
1056 | return err; | ||
1057 | } | ||
1058 | |||
1059 | dprintk(1, "%s()\n", __func__); | ||
1060 | if (UNSET == dev->tuner_type) | ||
1061 | return -EINVAL; | ||
1062 | if (0 != t->index) | ||
1063 | return -EINVAL; | ||
1064 | |||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | #endif | ||
1069 | // ****************************************************************************************** | ||
1070 | static const struct v4l2_queryctrl no_ctl = { | ||
1071 | .name = "42", | ||
1072 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
1073 | }; | ||
1074 | |||
1075 | static struct v4l2_queryctrl cx25821_ctls[] = { | ||
1076 | /* --- video --- */ | ||
1077 | { | ||
1078 | .id = V4L2_CID_BRIGHTNESS, | ||
1079 | .name = "Brightness", | ||
1080 | .minimum = 0, | ||
1081 | .maximum = 10000, | ||
1082 | .step = 1, | ||
1083 | .default_value = 6200, | ||
1084 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1085 | },{ | ||
1086 | .id = V4L2_CID_CONTRAST, | ||
1087 | .name = "Contrast", | ||
1088 | .minimum = 0, | ||
1089 | .maximum = 10000, | ||
1090 | .step = 1, | ||
1091 | .default_value = 5000, | ||
1092 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1093 | },{ | ||
1094 | .id = V4L2_CID_SATURATION, | ||
1095 | .name = "Saturation", | ||
1096 | .minimum = 0, | ||
1097 | .maximum = 10000, | ||
1098 | .step = 1, | ||
1099 | .default_value = 5000, | ||
1100 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1101 | },{ | ||
1102 | .id = V4L2_CID_HUE, | ||
1103 | .name = "Hue", | ||
1104 | .minimum = 0, | ||
1105 | .maximum = 10000, | ||
1106 | .step = 1, | ||
1107 | .default_value = 5000, | ||
1108 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1109 | } | ||
1110 | }; | ||
1111 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); | ||
1112 | |||
1113 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
1114 | { | ||
1115 | int i; | ||
1116 | |||
1117 | if (qctrl->id < V4L2_CID_BASE || | ||
1118 | qctrl->id >= V4L2_CID_LASTP1) | ||
1119 | return -EINVAL; | ||
1120 | for (i = 0; i < CX25821_CTLS; i++) | ||
1121 | if (cx25821_ctls[i].id == qctrl->id) | ||
1122 | break; | ||
1123 | if (i == CX25821_CTLS) { | ||
1124 | *qctrl = no_ctl; | ||
1125 | return 0; | ||
1126 | } | ||
1127 | *qctrl = cx25821_ctls[i]; | ||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | int vidioc_queryctrl(struct file *file, void *priv, | ||
1132 | struct v4l2_queryctrl *qctrl) | ||
1133 | { | ||
1134 | return cx25821_ctrl_query(qctrl); | ||
1135 | } | ||
1136 | |||
1137 | /* ------------------------------------------------------------------ */ | ||
1138 | /* VIDEO CTRL IOCTLS */ | ||
1139 | |||
1140 | static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id) | ||
1141 | { | ||
1142 | unsigned int i; | ||
1143 | |||
1144 | for (i = 0; i < CX25821_CTLS; i++) | ||
1145 | if (cx25821_ctls[i].id == id) | ||
1146 | return cx25821_ctls+i; | ||
1147 | return NULL; | ||
1148 | } | ||
1149 | |||
1150 | int vidioc_g_ctrl(struct file *file, | ||
1151 | void *priv, | ||
1152 | struct v4l2_control *ctl) | ||
1153 | { | ||
1154 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1155 | |||
1156 | const struct v4l2_queryctrl* ctrl; | ||
1157 | |||
1158 | ctrl = ctrl_by_id(ctl->id); | ||
1159 | |||
1160 | if (NULL == ctrl) | ||
1161 | return -EINVAL; | ||
1162 | switch (ctl->id) | ||
1163 | { | ||
1164 | case V4L2_CID_BRIGHTNESS: | ||
1165 | ctl->value = dev->ctl_bright; | ||
1166 | break; | ||
1167 | case V4L2_CID_HUE: | ||
1168 | ctl->value = dev->ctl_hue; | ||
1169 | break; | ||
1170 | case V4L2_CID_CONTRAST: | ||
1171 | ctl->value = dev->ctl_contrast; | ||
1172 | break; | ||
1173 | case V4L2_CID_SATURATION: | ||
1174 | ctl->value = dev->ctl_saturation; | ||
1175 | break; | ||
1176 | } | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | int cx25821_set_control(struct cx25821_dev *dev, | ||
1181 | struct v4l2_control *ctl, int chan_num) | ||
1182 | { | ||
1183 | int err; | ||
1184 | const struct v4l2_queryctrl* ctrl; | ||
1185 | |||
1186 | err = -EINVAL; | ||
1187 | |||
1188 | ctrl = ctrl_by_id(ctl->id); | ||
1189 | |||
1190 | if (NULL == ctrl) | ||
1191 | return err; | ||
1192 | |||
1193 | switch (ctrl->type) | ||
1194 | { | ||
1195 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1196 | case V4L2_CTRL_TYPE_MENU: | ||
1197 | case V4L2_CTRL_TYPE_INTEGER: | ||
1198 | if (ctl->value < ctrl->minimum) | ||
1199 | ctl->value = ctrl->minimum; | ||
1200 | if (ctl->value > ctrl->maximum) | ||
1201 | ctl->value = ctrl->maximum; | ||
1202 | break; | ||
1203 | default: | ||
1204 | /* nothing */; | ||
1205 | }; | ||
1206 | |||
1207 | switch (ctl->id) | ||
1208 | { | ||
1209 | case V4L2_CID_BRIGHTNESS: | ||
1210 | dev->ctl_bright = ctl->value; | ||
1211 | medusa_set_brightness(dev, ctl->value, chan_num); | ||
1212 | break; | ||
1213 | case V4L2_CID_HUE: | ||
1214 | dev->ctl_hue = ctl->value; | ||
1215 | medusa_set_hue(dev, ctl->value, chan_num); | ||
1216 | break; | ||
1217 | case V4L2_CID_CONTRAST: | ||
1218 | dev->ctl_contrast = ctl->value; | ||
1219 | medusa_set_contrast(dev, ctl->value, chan_num); | ||
1220 | break; | ||
1221 | case V4L2_CID_SATURATION: | ||
1222 | dev->ctl_saturation = ctl->value; | ||
1223 | medusa_set_saturation(dev, ctl->value, chan_num); | ||
1224 | break; | ||
1225 | } | ||
1226 | |||
1227 | err = 0; | ||
1228 | |||
1229 | return err; | ||
1230 | } | ||
1231 | |||
1232 | static void init_controls(struct cx25821_dev *dev, int chan_num) | ||
1233 | { | ||
1234 | struct v4l2_control ctrl; | ||
1235 | int i; | ||
1236 | for (i = 0; i < CX25821_CTLS; i++) { | ||
1237 | ctrl.id = cx25821_ctls[i].id; | ||
1238 | ctrl.value = cx25821_ctls[i].default_value; | ||
1239 | |||
1240 | cx25821_set_control(dev, &ctrl, chan_num); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | int vidioc_cropcap(struct file *file, | ||
1245 | void *priv, | ||
1246 | struct v4l2_cropcap *cropcap) | ||
1247 | { | ||
1248 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1249 | |||
1250 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1251 | return -EINVAL; | ||
1252 | cropcap->bounds.top = cropcap->bounds.left = 0; | ||
1253 | cropcap->bounds.width = 720; | ||
1254 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; | ||
1255 | cropcap->pixelaspect.numerator = dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; | ||
1256 | cropcap->pixelaspect.denominator = dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; | ||
1257 | cropcap->defrect = cropcap->bounds; | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | int vidioc_s_crop(struct file *file, | ||
1262 | void *priv, | ||
1263 | struct v4l2_crop *crop) | ||
1264 | { | ||
1265 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1266 | struct cx25821_fh *fh = priv; | ||
1267 | int err; | ||
1268 | |||
1269 | if (fh) | ||
1270 | { | ||
1271 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
1272 | if (0 != err) | ||
1273 | return err; | ||
1274 | } | ||
1275 | // vidioc_s_crop not supported | ||
1276 | return -EINVAL; | ||
1277 | } | ||
1278 | |||
1279 | int vidioc_g_crop(struct file *file, | ||
1280 | void *priv, | ||
1281 | struct v4l2_crop *crop) | ||
1282 | { | ||
1283 | // vidioc_g_crop not supported | ||
1284 | return -EINVAL; | ||
1285 | } | ||
1286 | |||
1287 | int vidioc_querystd(struct file *file, | ||
1288 | void *priv, | ||
1289 | v4l2_std_id *norm) | ||
1290 | { | ||
1291 | // medusa does not support video standard sensing of current input | ||
1292 | *norm = CX25821_NORMS; | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | int is_valid_width(u32 width, v4l2_std_id tvnorm) | ||
1298 | { | ||
1299 | if(tvnorm == V4L2_STD_PAL_BG) | ||
1300 | { | ||
1301 | if (width == 352 || width == 720) | ||
1302 | return 1; | ||
1303 | else | ||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | if(tvnorm == V4L2_STD_NTSC_M) | ||
1308 | { | ||
1309 | if (width == 320 || width == 352 || width == 720) | ||
1310 | return 1; | ||
1311 | else | ||
1312 | return 0; | ||
1313 | } | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | int is_valid_height(u32 height, v4l2_std_id tvnorm) | ||
1318 | { | ||
1319 | if(tvnorm == V4L2_STD_PAL_BG) | ||
1320 | { | ||
1321 | if (height == 576 || height == 288) | ||
1322 | return 1; | ||
1323 | else | ||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | if(tvnorm == V4L2_STD_NTSC_M) | ||
1328 | { | ||
1329 | if (height == 480 || height == 240) | ||
1330 | return 1; | ||
1331 | else | ||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h new file mode 100644 index 00000000000..fa2ec788535 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video.h | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 | #ifndef CX25821_VIDEO_H_ | ||
25 | #define CX25821_VIDEO_H_ | ||
26 | |||
27 | |||
28 | #include <linux/init.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kmod.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/kthread.h> | ||
38 | #include <asm/div64.h> | ||
39 | |||
40 | #include "cx25821.h" | ||
41 | #include <media/v4l2-common.h> | ||
42 | #include <media/v4l2-ioctl.h> | ||
43 | |||
44 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
45 | /* Include V4L1 specific functions. Should be removed soon */ | ||
46 | #include <linux/videodev.h> | ||
47 | #endif | ||
48 | |||
49 | #define TUNER_FLAG | ||
50 | |||
51 | #define VIDEO_DEBUG 0 | ||
52 | |||
53 | #define dprintk(level, fmt, arg...)\ | ||
54 | do { if (VIDEO_DEBUG >= level)\ | ||
55 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ | ||
56 | } while (0) | ||
57 | |||
58 | |||
59 | //For IOCTL to identify running upstream | ||
60 | #define UPSTREAM_START_VIDEO 700 | ||
61 | #define UPSTREAM_STOP_VIDEO 701 | ||
62 | #define UPSTREAM_START_AUDIO 702 | ||
63 | #define UPSTREAM_STOP_AUDIO 703 | ||
64 | #define UPSTREAM_DUMP_REGISTERS 702 | ||
65 | #define SET_VIDEO_STD 800 | ||
66 | #define SET_PIXEL_FORMAT 1000 | ||
67 | #define ENABLE_CIF_RESOLUTION 1001 | ||
68 | |||
69 | #define REG_READ 900 | ||
70 | #define REG_WRITE 901 | ||
71 | #define MEDUSA_READ 910 | ||
72 | #define MEDUSA_WRITE 911 | ||
73 | |||
74 | extern struct sram_channel *channel0; | ||
75 | extern struct sram_channel *channel1; | ||
76 | extern struct sram_channel *channel2; | ||
77 | extern struct sram_channel *channel3; | ||
78 | extern struct sram_channel *channel4; | ||
79 | extern struct sram_channel *channel5; | ||
80 | extern struct sram_channel *channel6; | ||
81 | extern struct sram_channel *channel7; | ||
82 | extern struct sram_channel *channel9; | ||
83 | extern struct sram_channel *channel10; | ||
84 | extern struct sram_channel *channel11; | ||
85 | extern struct video_device cx25821_video_template0; | ||
86 | extern struct video_device cx25821_video_template1; | ||
87 | extern struct video_device cx25821_video_template2; | ||
88 | extern struct video_device cx25821_video_template3; | ||
89 | extern struct video_device cx25821_video_template4; | ||
90 | extern struct video_device cx25821_video_template5; | ||
91 | extern struct video_device cx25821_video_template6; | ||
92 | extern struct video_device cx25821_video_template7; | ||
93 | extern struct video_device cx25821_video_template9; | ||
94 | extern struct video_device cx25821_video_template10; | ||
95 | extern struct video_device cx25821_video_template11; | ||
96 | extern struct video_device cx25821_videoioctl_template; | ||
97 | //extern const u32 *ctrl_classes[]; | ||
98 | |||
99 | extern unsigned int vid_limit; | ||
100 | |||
101 | #define FORMAT_FLAGS_PACKED 0x01 | ||
102 | extern struct cx25821_fmt formats[]; | ||
103 | extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); | ||
104 | extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | ||
105 | |||
106 | extern void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q); | ||
107 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count); | ||
108 | |||
109 | #ifdef TUNER_FLAG | ||
110 | extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); | ||
111 | #endif | ||
112 | |||
113 | |||
114 | extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit); | ||
115 | extern int res_check(struct cx25821_fh *fh, unsigned int bit); | ||
116 | extern int res_locked(struct cx25821_dev *dev, unsigned int bit); | ||
117 | extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits); | ||
118 | extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); | ||
119 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, | ||
120 | struct cx25821_dmaqueue *q, | ||
121 | struct cx25821_buffer *buf, | ||
122 | struct sram_channel *channel); | ||
123 | |||
124 | extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field); | ||
125 | extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); | ||
126 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); | ||
127 | extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template); | ||
128 | extern int get_format_size(void); | ||
129 | |||
130 | extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size); | ||
131 | extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field); | ||
132 | extern void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb); | ||
133 | extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); | ||
134 | extern int get_resource(struct cx25821_fh *fh, int resource); | ||
135 | extern int video_mmap(struct file *file, struct vm_area_struct *vma); | ||
136 | extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); | ||
137 | extern int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap); | ||
138 | extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f); | ||
139 | extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); | ||
140 | extern int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p); | ||
141 | extern int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
142 | extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
143 | extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms); | ||
144 | extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); | ||
145 | extern int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i); | ||
146 | extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i); | ||
147 | extern int vidioc_s_input(struct file *file, void *priv, unsigned int i); | ||
148 | extern int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl); | ||
149 | extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); | ||
150 | extern int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f); | ||
151 | extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); | ||
152 | extern int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f); | ||
153 | extern int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); | ||
154 | extern int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); | ||
155 | extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | ||
156 | extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | ||
157 | |||
158 | extern int is_valid_width(u32 width, v4l2_std_id tvnorm); | ||
159 | extern int is_valid_height(u32 height, v4l2_std_id tvnorm); | ||
160 | |||
161 | extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); | ||
162 | extern int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio); | ||
163 | |||
164 | extern int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl); | ||
165 | extern int cx25821_set_control(struct cx25821_dev *dev, struct v4l2_control *ctrl, int chan_num); | ||
166 | |||
167 | extern int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap); | ||
168 | extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); | ||
169 | extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); | ||
170 | |||
171 | extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm); | ||
172 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c new file mode 100644 index 00000000000..9dbd740f1e2 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video0.c | |||
@@ -0,0 +1,457 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | u32 pix_format; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor) | ||
106 | { | ||
107 | dev = h; | ||
108 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (NULL == dev) { | ||
113 | unlock_kernel(); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
118 | |||
119 | /* allocate + initialize per filehandle data */ | ||
120 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
121 | if (NULL == fh) { | ||
122 | unlock_kernel(); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | file->private_data = fh; | ||
127 | fh->dev = dev; | ||
128 | fh->type = type; | ||
129 | fh->width = 720; | ||
130 | |||
131 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
132 | fh->height = 576; | ||
133 | else | ||
134 | fh->height = 480; | ||
135 | |||
136 | dev->channel_opened = SRAM_CH00; | ||
137 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
138 | fh->fmt = format_by_fourcc(pix_format); | ||
139 | |||
140 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
141 | |||
142 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
143 | &dev->pci->dev, &dev->slock, | ||
144 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
145 | V4L2_FIELD_INTERLACED, | ||
146 | sizeof(struct cx25821_buffer), | ||
147 | fh); | ||
148 | |||
149 | dprintk(1, "post videobuf_queue_init()\n"); | ||
150 | unlock_kernel(); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
156 | { | ||
157 | struct cx25821_fh *fh = file->private_data; | ||
158 | |||
159 | switch (fh->type) | ||
160 | { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO0)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
166 | |||
167 | default: | ||
168 | BUG(); | ||
169 | return 0; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
174 | { | ||
175 | struct cx25821_fh *fh = file->private_data; | ||
176 | struct cx25821_buffer *buf; | ||
177 | |||
178 | if (res_check(fh, RESOURCE_VIDEO0)) { | ||
179 | /* streaming capture */ | ||
180 | if (list_empty(&fh->vidq.stream)) | ||
181 | return POLLERR; | ||
182 | buf = list_entry(fh->vidq.stream.next, | ||
183 | struct cx25821_buffer, vb.stream); | ||
184 | } else { | ||
185 | /* read() capture */ | ||
186 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
187 | if (NULL == buf) | ||
188 | return POLLERR; | ||
189 | } | ||
190 | |||
191 | poll_wait(file, &buf->vb.done, wait); | ||
192 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
193 | { | ||
194 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
195 | { | ||
196 | struct cx25821_dev *dev = fh->dev; | ||
197 | |||
198 | if( dev && dev->use_cif_resolution[SRAM_CH00] ) | ||
199 | { | ||
200 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
201 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
202 | *((char*)buf->vb.baddr+3) = cam_id; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | return POLLIN|POLLRDNORM; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | |||
213 | static int video_release(struct file *file) | ||
214 | { | ||
215 | struct cx25821_fh *fh = file->private_data; | ||
216 | struct cx25821_dev *dev = fh->dev; | ||
217 | |||
218 | //stop the risc engine and fifo | ||
219 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ | ||
220 | |||
221 | /* stop video capture */ | ||
222 | if (res_check(fh, RESOURCE_VIDEO0)) { | ||
223 | videobuf_queue_cancel(&fh->vidq); | ||
224 | res_free(dev, fh, RESOURCE_VIDEO0); | ||
225 | } | ||
226 | |||
227 | if (fh->vidq.read_buf) { | ||
228 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
229 | kfree(fh->vidq.read_buf); | ||
230 | } | ||
231 | |||
232 | videobuf_mmap_free(&fh->vidq); | ||
233 | |||
234 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
235 | file->private_data = NULL; | ||
236 | kfree(fh); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | |||
242 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
243 | { | ||
244 | struct cx25821_fh *fh = priv; | ||
245 | struct cx25821_dev *dev = fh->dev; | ||
246 | |||
247 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
248 | { | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | if (unlikely(i != fh->type)) | ||
253 | { | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) | ||
258 | { | ||
259 | return -EBUSY; | ||
260 | } | ||
261 | |||
262 | return videobuf_streamon(get_queue(fh)); | ||
263 | } | ||
264 | |||
265 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
266 | { | ||
267 | struct cx25821_fh *fh = priv; | ||
268 | struct cx25821_dev *dev = fh->dev; | ||
269 | int err, res; | ||
270 | |||
271 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
272 | return -EINVAL; | ||
273 | if (i != fh->type) | ||
274 | return -EINVAL; | ||
275 | |||
276 | res = get_resource(fh, RESOURCE_VIDEO0); | ||
277 | err = videobuf_streamoff(get_queue(fh)); | ||
278 | if (err < 0) | ||
279 | return err; | ||
280 | res_free(dev, fh, res); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | |||
285 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
286 | { | ||
287 | struct cx25821_fh *fh = priv; | ||
288 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
289 | int err; | ||
290 | int pix_format = PIXEL_FRMT_422; | ||
291 | |||
292 | if (fh) | ||
293 | { | ||
294 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
295 | if (0 != err) | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | dprintk(2, "%s()\n", __func__); | ||
300 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
301 | |||
302 | if (0 != err) | ||
303 | return err; | ||
304 | |||
305 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
306 | fh->vidq.field = f->fmt.pix.field; | ||
307 | |||
308 | // check if width and height is valid based on set standard | ||
309 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
310 | { | ||
311 | fh->width = f->fmt.pix.width; | ||
312 | } | ||
313 | |||
314 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
315 | { | ||
316 | fh->height = f->fmt.pix.height; | ||
317 | } | ||
318 | |||
319 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
320 | pix_format = PIXEL_FRMT_411; | ||
321 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
322 | pix_format = PIXEL_FRMT_422; | ||
323 | else | ||
324 | return -EINVAL; | ||
325 | |||
326 | cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); | ||
327 | |||
328 | // check if cif resolution | ||
329 | if (fh->width == 320 || fh->width == 352) | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH00] = 1; | ||
332 | }else | ||
333 | { | ||
334 | dev->use_cif_resolution[SRAM_CH00] = 0; | ||
335 | } | ||
336 | dev->cif_width[SRAM_CH00] = fh->width; | ||
337 | medusa_set_resolution( dev, fh->width, SRAM_CH00 ); | ||
338 | |||
339 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
340 | cx25821_call_all(dev, video, s_fmt, f); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
346 | { | ||
347 | int ret_val = 0; | ||
348 | struct cx25821_fh *fh = priv; | ||
349 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
350 | |||
351 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
352 | |||
353 | p->sequence = dev->vidq[SRAM_CH00].count; | ||
354 | |||
355 | return ret_val; | ||
356 | } | ||
357 | |||
358 | static int vidioc_log_status (struct file *file, void *priv) | ||
359 | { | ||
360 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
361 | char name[32 + 2]; | ||
362 | |||
363 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; | ||
364 | u32 tmp = 0; | ||
365 | |||
366 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
367 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
368 | dev->name); | ||
369 | cx25821_call_all(dev, core, log_status); | ||
370 | tmp = cx_read(sram_ch->dma_ctl); | ||
371 | printk(KERN_INFO "Video input 0 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
372 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
373 | dev->name); | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
378 | struct v4l2_control *ctl) | ||
379 | { | ||
380 | struct cx25821_fh *fh = priv; | ||
381 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
382 | int err; | ||
383 | |||
384 | if (fh) { | ||
385 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
386 | if (0 != err) | ||
387 | return err; | ||
388 | } | ||
389 | |||
390 | return cx25821_set_control(dev, ctl, SRAM_CH00); | ||
391 | } | ||
392 | |||
393 | // exported stuff | ||
394 | static const struct v4l2_file_operations video_fops = { | ||
395 | .owner = THIS_MODULE, | ||
396 | .open = video_open, | ||
397 | .release = video_release, | ||
398 | .read = video_read, | ||
399 | .poll = video_poll, | ||
400 | .mmap = video_mmap, | ||
401 | .ioctl = video_ioctl2, | ||
402 | }; | ||
403 | |||
404 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
405 | .vidioc_querycap = vidioc_querycap, | ||
406 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
407 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
408 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
409 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
410 | .vidioc_reqbufs = vidioc_reqbufs, | ||
411 | .vidioc_querybuf = vidioc_querybuf, | ||
412 | .vidioc_qbuf = vidioc_qbuf, | ||
413 | .vidioc_dqbuf = vidioc_dqbuf, | ||
414 | #ifdef TUNER_FLAG | ||
415 | .vidioc_s_std = vidioc_s_std, | ||
416 | .vidioc_querystd = vidioc_querystd, | ||
417 | #endif | ||
418 | .vidioc_cropcap = vidioc_cropcap, | ||
419 | .vidioc_s_crop = vidioc_s_crop, | ||
420 | .vidioc_g_crop = vidioc_g_crop, | ||
421 | .vidioc_enum_input = vidioc_enum_input, | ||
422 | .vidioc_g_input = vidioc_g_input, | ||
423 | .vidioc_s_input = vidioc_s_input, | ||
424 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
425 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
426 | .vidioc_queryctrl = vidioc_queryctrl, | ||
427 | .vidioc_streamon = vidioc_streamon, | ||
428 | .vidioc_streamoff = vidioc_streamoff, | ||
429 | .vidioc_log_status = vidioc_log_status, | ||
430 | .vidioc_g_priority = vidioc_g_priority, | ||
431 | .vidioc_s_priority = vidioc_s_priority, | ||
432 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
433 | .vidiocgmbuf = vidiocgmbuf, | ||
434 | #endif | ||
435 | #ifdef TUNER_FLAG | ||
436 | .vidioc_g_tuner = vidioc_g_tuner, | ||
437 | .vidioc_s_tuner = vidioc_s_tuner, | ||
438 | .vidioc_g_frequency = vidioc_g_frequency, | ||
439 | .vidioc_s_frequency = vidioc_s_frequency, | ||
440 | #endif | ||
441 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
442 | .vidioc_g_register = vidioc_g_register, | ||
443 | .vidioc_s_register = vidioc_s_register, | ||
444 | #endif | ||
445 | }; | ||
446 | |||
447 | struct video_device cx25821_video_template0 = { | ||
448 | .name = "cx25821-video", | ||
449 | .fops = &video_fops, | ||
450 | .minor = -1, | ||
451 | .ioctl_ops = &video_ioctl_ops, | ||
452 | .tvnorms = CX25821_NORMS, | ||
453 | .current_norm = V4L2_STD_NTSC_M, | ||
454 | }; | ||
455 | |||
456 | |||
457 | |||
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c new file mode 100644 index 00000000000..44db11940ff --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video1.c | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01]; | ||
34 | |||
35 | |||
36 | /* add jump to stopper */ | ||
37 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
38 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
39 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
40 | |||
41 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
42 | |||
43 | if (!list_empty(&q->queued)) { | ||
44 | list_add_tail(&buf->vb.queue, &q->queued); | ||
45 | buf->vb.state = VIDEOBUF_QUEUED; | ||
46 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
47 | |||
48 | } else if (list_empty(&q->active)) { | ||
49 | list_add_tail(&buf->vb.queue, &q->active); | ||
50 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]); | ||
51 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
52 | buf->count = q->count++; | ||
53 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
54 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
55 | buf, buf->vb. i, buf->count, q->count); | ||
56 | } else { | ||
57 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
58 | if (prev->vb.width == buf->vb.width && | ||
59 | prev->vb.height == buf->vb.height && | ||
60 | prev->fmt == buf->fmt) { | ||
61 | list_add_tail(&buf->vb.queue, &q->active); | ||
62 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
63 | buf->count = q->count++; | ||
64 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
65 | |||
66 | /* 64 bit bits 63-32 */ | ||
67 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
68 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
69 | |||
70 | } else { | ||
71 | list_add_tail(&buf->vb.queue, &q->queued); | ||
72 | buf->vb.state = VIDEOBUF_QUEUED; | ||
73 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (list_empty(&q->active)) | ||
78 | { | ||
79 | dprintk(2, "active queue empty!\n"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
85 | .buf_setup = buffer_setup, | ||
86 | .buf_prepare = buffer_prepare, | ||
87 | .buf_queue = buffer_queue, | ||
88 | .buf_release = buffer_release, | ||
89 | }; | ||
90 | |||
91 | |||
92 | static int video_open(struct file *file) | ||
93 | { | ||
94 | int minor = video_devdata(file)->minor; | ||
95 | struct cx25821_dev *h, *dev = NULL; | ||
96 | struct cx25821_fh *fh; | ||
97 | struct list_head *list; | ||
98 | enum v4l2_buf_type type = 0; | ||
99 | u32 pix_format; | ||
100 | |||
101 | lock_kernel(); | ||
102 | list_for_each(list, &cx25821_devlist) | ||
103 | { | ||
104 | h = list_entry(list, struct cx25821_dev, devlist); | ||
105 | |||
106 | if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) { | ||
107 | dev = h; | ||
108 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (NULL == dev) { | ||
113 | unlock_kernel(); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
118 | |||
119 | /* allocate + initialize per filehandle data */ | ||
120 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
121 | if (NULL == fh) { | ||
122 | unlock_kernel(); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | file->private_data = fh; | ||
127 | fh->dev = dev; | ||
128 | fh->type = type; | ||
129 | fh->width = 720; | ||
130 | |||
131 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
132 | fh->height = 576; | ||
133 | else | ||
134 | fh->height = 480; | ||
135 | |||
136 | dev->channel_opened = SRAM_CH01; | ||
137 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
138 | fh->fmt = format_by_fourcc(pix_format); | ||
139 | |||
140 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
141 | |||
142 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
143 | &dev->pci->dev, &dev->slock, | ||
144 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
145 | V4L2_FIELD_INTERLACED, | ||
146 | sizeof(struct cx25821_buffer), | ||
147 | fh); | ||
148 | |||
149 | dprintk(1, "post videobuf_queue_init()\n"); | ||
150 | unlock_kernel(); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
156 | { | ||
157 | struct cx25821_fh *fh = file->private_data; | ||
158 | |||
159 | switch (fh->type) | ||
160 | { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO1)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
166 | |||
167 | default: | ||
168 | BUG(); | ||
169 | return 0; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
174 | { | ||
175 | struct cx25821_fh *fh = file->private_data; | ||
176 | struct cx25821_buffer *buf; | ||
177 | |||
178 | if (res_check(fh, RESOURCE_VIDEO1)) { | ||
179 | /* streaming capture */ | ||
180 | if (list_empty(&fh->vidq.stream)) | ||
181 | return POLLERR; | ||
182 | buf = list_entry(fh->vidq.stream.next, | ||
183 | struct cx25821_buffer, vb.stream); | ||
184 | } else { | ||
185 | /* read() capture */ | ||
186 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
187 | if (NULL == buf) | ||
188 | return POLLERR; | ||
189 | } | ||
190 | |||
191 | poll_wait(file, &buf->vb.done, wait); | ||
192 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
193 | { | ||
194 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
195 | { | ||
196 | struct cx25821_dev *dev = fh->dev; | ||
197 | |||
198 | if( dev && dev->use_cif_resolution[SRAM_CH01] ) | ||
199 | { | ||
200 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
201 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
202 | *((char*)buf->vb.baddr+3) = cam_id; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | return POLLIN|POLLRDNORM; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int video_release(struct file *file) | ||
213 | { | ||
214 | struct cx25821_fh *fh = file->private_data; | ||
215 | struct cx25821_dev *dev = fh->dev; | ||
216 | |||
217 | //stop the risc engine and fifo | ||
218 | cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ | ||
219 | |||
220 | /* stop video capture */ | ||
221 | if (res_check(fh, RESOURCE_VIDEO1)) { | ||
222 | videobuf_queue_cancel(&fh->vidq); | ||
223 | res_free(dev, fh, RESOURCE_VIDEO1); | ||
224 | } | ||
225 | |||
226 | if (fh->vidq.read_buf) { | ||
227 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
228 | kfree(fh->vidq.read_buf); | ||
229 | } | ||
230 | |||
231 | videobuf_mmap_free(&fh->vidq); | ||
232 | |||
233 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
234 | file->private_data = NULL; | ||
235 | kfree(fh); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | |||
241 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
242 | { | ||
243 | struct cx25821_fh *fh = priv; | ||
244 | struct cx25821_dev *dev = fh->dev; | ||
245 | |||
246 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
247 | { | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | |||
251 | if (unlikely(i != fh->type)) | ||
252 | { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) | ||
257 | { | ||
258 | return -EBUSY; | ||
259 | } | ||
260 | |||
261 | return videobuf_streamon(get_queue(fh)); | ||
262 | } | ||
263 | |||
264 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
265 | { | ||
266 | struct cx25821_fh *fh = priv; | ||
267 | struct cx25821_dev *dev = fh->dev; | ||
268 | int err, res; | ||
269 | |||
270 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
271 | return -EINVAL; | ||
272 | if (i != fh->type) | ||
273 | return -EINVAL; | ||
274 | |||
275 | res = get_resource(fh, RESOURCE_VIDEO1); | ||
276 | err = videobuf_streamoff(get_queue(fh)); | ||
277 | if (err < 0) | ||
278 | return err; | ||
279 | res_free(dev, fh, res); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | |||
285 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
286 | { | ||
287 | struct cx25821_fh *fh = priv; | ||
288 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
289 | int err; | ||
290 | int pix_format = 0; | ||
291 | |||
292 | if (fh) | ||
293 | { | ||
294 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
295 | if (0 != err) | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | dprintk(2, "%s()\n", __func__); | ||
300 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
301 | |||
302 | if (0 != err) | ||
303 | return err; | ||
304 | |||
305 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
306 | fh->vidq.field = f->fmt.pix.field; | ||
307 | |||
308 | // check if width and height is valid based on set standard | ||
309 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
310 | { | ||
311 | fh->width = f->fmt.pix.width; | ||
312 | } | ||
313 | |||
314 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
315 | { | ||
316 | fh->height = f->fmt.pix.height; | ||
317 | } | ||
318 | |||
319 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
320 | pix_format = PIXEL_FRMT_411; | ||
321 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
322 | pix_format = PIXEL_FRMT_422; | ||
323 | else | ||
324 | return -EINVAL; | ||
325 | |||
326 | cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); | ||
327 | |||
328 | // check if cif resolution | ||
329 | if (fh->width == 320 || fh->width == 352) | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH01] = 1; | ||
332 | }else | ||
333 | { | ||
334 | dev->use_cif_resolution[SRAM_CH01] = 0; | ||
335 | } | ||
336 | dev->cif_width[SRAM_CH01] = fh->width; | ||
337 | medusa_set_resolution( dev, fh->width, SRAM_CH01 ); | ||
338 | |||
339 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
340 | cx25821_call_all(dev, video, s_fmt, f); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
346 | { | ||
347 | int ret_val = 0; | ||
348 | struct cx25821_fh *fh = priv; | ||
349 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
350 | |||
351 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
352 | |||
353 | p->sequence = dev->vidq[SRAM_CH01].count; | ||
354 | |||
355 | return ret_val; | ||
356 | } | ||
357 | |||
358 | static int vidioc_log_status (struct file *file, void *priv) | ||
359 | { | ||
360 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
361 | char name[32 + 2]; | ||
362 | |||
363 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; | ||
364 | u32 tmp = 0; | ||
365 | |||
366 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
367 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
368 | dev->name); | ||
369 | cx25821_call_all(dev, core, log_status); | ||
370 | tmp = cx_read(sram_ch->dma_ctl); | ||
371 | printk(KERN_INFO "Video input 1 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
372 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
373 | dev->name); | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
378 | struct v4l2_control *ctl) | ||
379 | { | ||
380 | struct cx25821_fh *fh = priv; | ||
381 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
382 | int err; | ||
383 | |||
384 | if (fh) { | ||
385 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
386 | if (0 != err) | ||
387 | return err; | ||
388 | } | ||
389 | |||
390 | return cx25821_set_control(dev, ctl, SRAM_CH01); | ||
391 | } | ||
392 | //exported stuff | ||
393 | static const struct v4l2_file_operations video_fops = { | ||
394 | .owner = THIS_MODULE, | ||
395 | .open = video_open, | ||
396 | .release = video_release, | ||
397 | .read = video_read, | ||
398 | .poll = video_poll, | ||
399 | .mmap = video_mmap, | ||
400 | .ioctl = video_ioctl2, | ||
401 | }; | ||
402 | |||
403 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
404 | .vidioc_querycap = vidioc_querycap, | ||
405 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
406 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
407 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
408 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
409 | .vidioc_reqbufs = vidioc_reqbufs, | ||
410 | .vidioc_querybuf = vidioc_querybuf, | ||
411 | .vidioc_qbuf = vidioc_qbuf, | ||
412 | .vidioc_dqbuf = vidioc_dqbuf, | ||
413 | #ifdef TUNER_FLAG | ||
414 | .vidioc_s_std = vidioc_s_std, | ||
415 | .vidioc_querystd = vidioc_querystd, | ||
416 | #endif | ||
417 | .vidioc_cropcap = vidioc_cropcap, | ||
418 | .vidioc_s_crop = vidioc_s_crop, | ||
419 | .vidioc_g_crop = vidioc_g_crop, | ||
420 | .vidioc_enum_input = vidioc_enum_input, | ||
421 | .vidioc_g_input = vidioc_g_input, | ||
422 | .vidioc_s_input = vidioc_s_input, | ||
423 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
424 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
425 | .vidioc_queryctrl = vidioc_queryctrl, | ||
426 | .vidioc_streamon = vidioc_streamon, | ||
427 | .vidioc_streamoff = vidioc_streamoff, | ||
428 | .vidioc_log_status = vidioc_log_status, | ||
429 | .vidioc_g_priority = vidioc_g_priority, | ||
430 | .vidioc_s_priority = vidioc_s_priority, | ||
431 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
432 | .vidiocgmbuf = vidiocgmbuf, | ||
433 | #endif | ||
434 | #ifdef TUNER_FLAG | ||
435 | .vidioc_g_tuner = vidioc_g_tuner, | ||
436 | .vidioc_s_tuner = vidioc_s_tuner, | ||
437 | .vidioc_g_frequency = vidioc_g_frequency, | ||
438 | .vidioc_s_frequency = vidioc_s_frequency, | ||
439 | #endif | ||
440 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
441 | .vidioc_g_register = vidioc_g_register, | ||
442 | .vidioc_s_register = vidioc_s_register, | ||
443 | #endif | ||
444 | }; | ||
445 | |||
446 | struct video_device cx25821_video_template1 = { | ||
447 | .name = "cx25821-video", | ||
448 | .fops = &video_fops, | ||
449 | .minor = -1, | ||
450 | .ioctl_ops = &video_ioctl_ops, | ||
451 | .tvnorms = CX25821_NORMS, | ||
452 | .current_norm = V4L2_STD_NTSC_M, | ||
453 | }; | ||
454 | |||
455 | |||
456 | |||
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c new file mode 100644 index 00000000000..98db1488dcf --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video2.c | |||
@@ -0,0 +1,459 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02]; | ||
34 | |||
35 | |||
36 | /* add jump to stopper */ | ||
37 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
38 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
39 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
40 | |||
41 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
42 | |||
43 | if (!list_empty(&q->queued)) { | ||
44 | list_add_tail(&buf->vb.queue, &q->queued); | ||
45 | buf->vb.state = VIDEOBUF_QUEUED; | ||
46 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
47 | |||
48 | } else if (list_empty(&q->active)) { | ||
49 | list_add_tail(&buf->vb.queue, &q->active); | ||
50 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]); | ||
51 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
52 | buf->count = q->count++; | ||
53 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
54 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
55 | buf, buf->vb. i, buf->count, q->count); | ||
56 | } else { | ||
57 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
58 | if (prev->vb.width == buf->vb.width && | ||
59 | prev->vb.height == buf->vb.height && | ||
60 | prev->fmt == buf->fmt) { | ||
61 | list_add_tail(&buf->vb.queue, &q->active); | ||
62 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
63 | buf->count = q->count++; | ||
64 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
65 | |||
66 | /* 64 bit bits 63-32 */ | ||
67 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
68 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
69 | |||
70 | } else { | ||
71 | list_add_tail(&buf->vb.queue, &q->queued); | ||
72 | buf->vb.state = VIDEOBUF_QUEUED; | ||
73 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (list_empty(&q->active)) | ||
78 | { | ||
79 | dprintk(2, "active queue empty!\n"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
85 | .buf_setup = buffer_setup, | ||
86 | .buf_prepare = buffer_prepare, | ||
87 | .buf_queue = buffer_queue, | ||
88 | .buf_release = buffer_release, | ||
89 | }; | ||
90 | |||
91 | |||
92 | static int video_open(struct file *file) | ||
93 | { | ||
94 | int minor = video_devdata(file)->minor; | ||
95 | struct cx25821_dev *h, *dev = NULL; | ||
96 | struct cx25821_fh *fh; | ||
97 | struct list_head *list; | ||
98 | enum v4l2_buf_type type = 0; | ||
99 | u32 pix_format; | ||
100 | |||
101 | lock_kernel(); | ||
102 | list_for_each(list, &cx25821_devlist) | ||
103 | { | ||
104 | h = list_entry(list, struct cx25821_dev, devlist); | ||
105 | |||
106 | if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) { | ||
107 | dev = h; | ||
108 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (NULL == dev) { | ||
113 | unlock_kernel(); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
118 | |||
119 | /* allocate + initialize per filehandle data */ | ||
120 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
121 | if (NULL == fh) { | ||
122 | unlock_kernel(); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | file->private_data = fh; | ||
126 | fh->dev = dev; | ||
127 | fh->type = type; | ||
128 | fh->width = 720; | ||
129 | |||
130 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
131 | fh->height = 576; | ||
132 | else | ||
133 | fh->height = 480; | ||
134 | |||
135 | dev->channel_opened = SRAM_CH02; | ||
136 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
137 | fh->fmt = format_by_fourcc(pix_format); | ||
138 | |||
139 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
140 | |||
141 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
142 | &dev->pci->dev, &dev->slock, | ||
143 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
144 | V4L2_FIELD_INTERLACED, | ||
145 | sizeof(struct cx25821_buffer), | ||
146 | fh); | ||
147 | |||
148 | dprintk(1, "post videobuf_queue_init()\n"); | ||
149 | unlock_kernel(); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
155 | { | ||
156 | struct cx25821_fh *fh = file->private_data; | ||
157 | |||
158 | switch (fh->type) | ||
159 | { | ||
160 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
161 | if (res_locked(fh->dev, RESOURCE_VIDEO2)) | ||
162 | return -EBUSY; | ||
163 | |||
164 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
165 | |||
166 | default: | ||
167 | BUG(); | ||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
173 | { | ||
174 | struct cx25821_fh *fh = file->private_data; | ||
175 | struct cx25821_buffer *buf; | ||
176 | |||
177 | if (res_check(fh, RESOURCE_VIDEO2)) { | ||
178 | /* streaming capture */ | ||
179 | if (list_empty(&fh->vidq.stream)) | ||
180 | return POLLERR; | ||
181 | buf = list_entry(fh->vidq.stream.next, | ||
182 | struct cx25821_buffer, vb.stream); | ||
183 | } else { | ||
184 | /* read() capture */ | ||
185 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
186 | if (NULL == buf) | ||
187 | return POLLERR; | ||
188 | } | ||
189 | |||
190 | poll_wait(file, &buf->vb.done, wait); | ||
191 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
192 | { | ||
193 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
194 | { | ||
195 | struct cx25821_dev *dev = fh->dev; | ||
196 | |||
197 | if( dev && dev->use_cif_resolution[SRAM_CH02] ) | ||
198 | { | ||
199 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
200 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
201 | *((char*)buf->vb.baddr+3) = cam_id; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | return POLLIN|POLLRDNORM; | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | |||
212 | static int video_release(struct file *file) | ||
213 | { | ||
214 | struct cx25821_fh *fh = file->private_data; | ||
215 | struct cx25821_dev *dev = fh->dev; | ||
216 | |||
217 | //stop the risc engine and fifo | ||
218 | cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ | ||
219 | |||
220 | /* stop video capture */ | ||
221 | if (res_check(fh, RESOURCE_VIDEO2)) { | ||
222 | videobuf_queue_cancel(&fh->vidq); | ||
223 | res_free(dev, fh, RESOURCE_VIDEO2); | ||
224 | } | ||
225 | |||
226 | if (fh->vidq.read_buf) { | ||
227 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
228 | kfree(fh->vidq.read_buf); | ||
229 | } | ||
230 | |||
231 | videobuf_mmap_free(&fh->vidq); | ||
232 | |||
233 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
234 | file->private_data = NULL; | ||
235 | kfree(fh); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | |||
241 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
242 | { | ||
243 | struct cx25821_fh *fh = priv; | ||
244 | struct cx25821_dev *dev = fh->dev; | ||
245 | |||
246 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
247 | { | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | |||
251 | if (unlikely(i != fh->type)) | ||
252 | { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) | ||
257 | { | ||
258 | return -EBUSY; | ||
259 | } | ||
260 | |||
261 | return videobuf_streamon(get_queue(fh)); | ||
262 | } | ||
263 | |||
264 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
265 | { | ||
266 | struct cx25821_fh *fh = priv; | ||
267 | struct cx25821_dev *dev = fh->dev; | ||
268 | int err, res; | ||
269 | |||
270 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
271 | return -EINVAL; | ||
272 | if (i != fh->type) | ||
273 | return -EINVAL; | ||
274 | |||
275 | res = get_resource(fh, RESOURCE_VIDEO2); | ||
276 | err = videobuf_streamoff(get_queue(fh)); | ||
277 | if (err < 0) | ||
278 | return err; | ||
279 | res_free(dev, fh, res); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | |||
285 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
286 | { | ||
287 | struct cx25821_fh *fh = priv; | ||
288 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
289 | int err; | ||
290 | int pix_format = 0; | ||
291 | |||
292 | if (fh) | ||
293 | { | ||
294 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
295 | if (0 != err) | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | dprintk(2, "%s()\n", __func__); | ||
300 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
301 | |||
302 | if (0 != err) | ||
303 | return err; | ||
304 | |||
305 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
306 | fh->vidq.field = f->fmt.pix.field; | ||
307 | |||
308 | // check if width and height is valid based on set standard | ||
309 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
310 | { | ||
311 | fh->width = f->fmt.pix.width; | ||
312 | } | ||
313 | |||
314 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
315 | { | ||
316 | fh->height = f->fmt.pix.height; | ||
317 | } | ||
318 | |||
319 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
320 | pix_format = PIXEL_FRMT_411; | ||
321 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
322 | pix_format = PIXEL_FRMT_422; | ||
323 | else | ||
324 | return -EINVAL; | ||
325 | |||
326 | cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); | ||
327 | |||
328 | // check if cif resolution | ||
329 | if (fh->width == 320 || fh->width == 352) | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH02] = 1; | ||
332 | }else | ||
333 | { | ||
334 | dev->use_cif_resolution[SRAM_CH02] = 0; | ||
335 | } | ||
336 | dev->cif_width[SRAM_CH02] = fh->width; | ||
337 | medusa_set_resolution( dev, fh->width, SRAM_CH02 ); | ||
338 | |||
339 | |||
340 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
341 | cx25821_call_all(dev, video, s_fmt, f); | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
347 | { | ||
348 | int ret_val = 0; | ||
349 | struct cx25821_fh *fh = priv; | ||
350 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
351 | |||
352 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
353 | |||
354 | p->sequence = dev->vidq[SRAM_CH02].count; | ||
355 | |||
356 | return ret_val; | ||
357 | } | ||
358 | |||
359 | static int vidioc_log_status (struct file *file, void *priv) | ||
360 | { | ||
361 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
362 | char name[32 + 2]; | ||
363 | |||
364 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; | ||
365 | u32 tmp = 0; | ||
366 | |||
367 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
368 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
369 | dev->name); | ||
370 | |||
371 | cx25821_call_all(dev, core, log_status); | ||
372 | |||
373 | tmp = cx_read(sram_ch->dma_ctl); | ||
374 | printk(KERN_INFO "Video input 2 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
375 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
376 | dev->name); | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
381 | struct v4l2_control *ctl) | ||
382 | { | ||
383 | struct cx25821_fh *fh = priv; | ||
384 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
385 | int err; | ||
386 | |||
387 | if (fh) { | ||
388 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
389 | if (0 != err) | ||
390 | return err; | ||
391 | } | ||
392 | |||
393 | return cx25821_set_control(dev, ctl, SRAM_CH02); | ||
394 | } | ||
395 | // exported stuff | ||
396 | static const struct v4l2_file_operations video_fops = { | ||
397 | .owner = THIS_MODULE, | ||
398 | .open = video_open, | ||
399 | .release = video_release, | ||
400 | .read = video_read, | ||
401 | .poll = video_poll, | ||
402 | .mmap = video_mmap, | ||
403 | .ioctl = video_ioctl2, | ||
404 | }; | ||
405 | |||
406 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
407 | .vidioc_querycap = vidioc_querycap, | ||
408 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
409 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
410 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
411 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
412 | .vidioc_reqbufs = vidioc_reqbufs, | ||
413 | .vidioc_querybuf = vidioc_querybuf, | ||
414 | .vidioc_qbuf = vidioc_qbuf, | ||
415 | .vidioc_dqbuf = vidioc_dqbuf, | ||
416 | #ifdef TUNER_FLAG | ||
417 | .vidioc_s_std = vidioc_s_std, | ||
418 | .vidioc_querystd = vidioc_querystd, | ||
419 | #endif | ||
420 | .vidioc_cropcap = vidioc_cropcap, | ||
421 | .vidioc_s_crop = vidioc_s_crop, | ||
422 | .vidioc_g_crop = vidioc_g_crop, | ||
423 | .vidioc_enum_input = vidioc_enum_input, | ||
424 | .vidioc_g_input = vidioc_g_input, | ||
425 | .vidioc_s_input = vidioc_s_input, | ||
426 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
427 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
428 | .vidioc_queryctrl = vidioc_queryctrl, | ||
429 | .vidioc_streamon = vidioc_streamon, | ||
430 | .vidioc_streamoff = vidioc_streamoff, | ||
431 | .vidioc_log_status = vidioc_log_status, | ||
432 | .vidioc_g_priority = vidioc_g_priority, | ||
433 | .vidioc_s_priority = vidioc_s_priority, | ||
434 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
435 | .vidiocgmbuf = vidiocgmbuf, | ||
436 | #endif | ||
437 | #ifdef TUNER_FLAG | ||
438 | .vidioc_g_tuner = vidioc_g_tuner, | ||
439 | .vidioc_s_tuner = vidioc_s_tuner, | ||
440 | .vidioc_g_frequency = vidioc_g_frequency, | ||
441 | .vidioc_s_frequency = vidioc_s_frequency, | ||
442 | #endif | ||
443 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
444 | .vidioc_g_register = vidioc_g_register, | ||
445 | .vidioc_s_register = vidioc_s_register, | ||
446 | #endif | ||
447 | }; | ||
448 | |||
449 | struct video_device cx25821_video_template2 = { | ||
450 | .name = "cx25821-video", | ||
451 | .fops = &video_fops, | ||
452 | .minor = -1, | ||
453 | .ioctl_ops = &video_ioctl_ops, | ||
454 | .tvnorms = CX25821_NORMS, | ||
455 | .current_norm = V4L2_STD_NTSC_M, | ||
456 | }; | ||
457 | |||
458 | |||
459 | |||
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c new file mode 100644 index 00000000000..3dcecd26466 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video3.c | |||
@@ -0,0 +1,458 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03]; | ||
34 | |||
35 | |||
36 | /* add jump to stopper */ | ||
37 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
38 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
39 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
40 | |||
41 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
42 | |||
43 | if (!list_empty(&q->queued)) { | ||
44 | list_add_tail(&buf->vb.queue, &q->queued); | ||
45 | buf->vb.state = VIDEOBUF_QUEUED; | ||
46 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
47 | |||
48 | } else if (list_empty(&q->active)) { | ||
49 | list_add_tail(&buf->vb.queue, &q->active); | ||
50 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]); | ||
51 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
52 | buf->count = q->count++; | ||
53 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
54 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
55 | buf, buf->vb. i, buf->count, q->count); | ||
56 | } else { | ||
57 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
58 | if (prev->vb.width == buf->vb.width && | ||
59 | prev->vb.height == buf->vb.height && | ||
60 | prev->fmt == buf->fmt) { | ||
61 | list_add_tail(&buf->vb.queue, &q->active); | ||
62 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
63 | buf->count = q->count++; | ||
64 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
65 | |||
66 | /* 64 bit bits 63-32 */ | ||
67 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
68 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
69 | |||
70 | } else { | ||
71 | list_add_tail(&buf->vb.queue, &q->queued); | ||
72 | buf->vb.state = VIDEOBUF_QUEUED; | ||
73 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (list_empty(&q->active)) | ||
78 | { | ||
79 | dprintk(2, "active queue empty!\n"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
85 | .buf_setup = buffer_setup, | ||
86 | .buf_prepare = buffer_prepare, | ||
87 | .buf_queue = buffer_queue, | ||
88 | .buf_release = buffer_release, | ||
89 | }; | ||
90 | |||
91 | |||
92 | static int video_open(struct file *file) | ||
93 | { | ||
94 | int minor = video_devdata(file)->minor; | ||
95 | struct cx25821_dev *h, *dev = NULL; | ||
96 | struct cx25821_fh *fh; | ||
97 | struct list_head *list; | ||
98 | enum v4l2_buf_type type = 0; | ||
99 | u32 pix_format; | ||
100 | |||
101 | lock_kernel(); | ||
102 | list_for_each(list, &cx25821_devlist) | ||
103 | { | ||
104 | h = list_entry(list, struct cx25821_dev, devlist); | ||
105 | |||
106 | if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) { | ||
107 | dev = h; | ||
108 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (NULL == dev) { | ||
113 | unlock_kernel(); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
118 | |||
119 | /* allocate + initialize per filehandle data */ | ||
120 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
121 | if (NULL == fh) { | ||
122 | unlock_kernel(); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | file->private_data = fh; | ||
126 | fh->dev = dev; | ||
127 | fh->type = type; | ||
128 | fh->width = 720; | ||
129 | |||
130 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
131 | fh->height = 576; | ||
132 | else | ||
133 | fh->height = 480; | ||
134 | |||
135 | dev->channel_opened = SRAM_CH03; | ||
136 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
137 | fh->fmt = format_by_fourcc(pix_format); | ||
138 | |||
139 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
140 | |||
141 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
142 | &dev->pci->dev, &dev->slock, | ||
143 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
144 | V4L2_FIELD_INTERLACED, | ||
145 | sizeof(struct cx25821_buffer), | ||
146 | fh); | ||
147 | |||
148 | dprintk(1, "post videobuf_queue_init()\n"); | ||
149 | unlock_kernel(); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
155 | { | ||
156 | struct cx25821_fh *fh = file->private_data; | ||
157 | |||
158 | switch (fh->type) | ||
159 | { | ||
160 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
161 | if (res_locked(fh->dev, RESOURCE_VIDEO3)) | ||
162 | return -EBUSY; | ||
163 | |||
164 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
165 | |||
166 | default: | ||
167 | BUG(); | ||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
173 | { | ||
174 | struct cx25821_fh *fh = file->private_data; | ||
175 | struct cx25821_buffer *buf; | ||
176 | |||
177 | if (res_check(fh, RESOURCE_VIDEO3)) { | ||
178 | /* streaming capture */ | ||
179 | if (list_empty(&fh->vidq.stream)) | ||
180 | return POLLERR; | ||
181 | buf = list_entry(fh->vidq.stream.next, | ||
182 | struct cx25821_buffer, vb.stream); | ||
183 | } else { | ||
184 | /* read() capture */ | ||
185 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
186 | if (NULL == buf) | ||
187 | return POLLERR; | ||
188 | } | ||
189 | |||
190 | poll_wait(file, &buf->vb.done, wait); | ||
191 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
192 | { | ||
193 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
194 | { | ||
195 | struct cx25821_dev *dev = fh->dev; | ||
196 | |||
197 | if( dev && dev->use_cif_resolution[SRAM_CH03] ) | ||
198 | { | ||
199 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
200 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
201 | *((char*)buf->vb.baddr+3) = cam_id; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | return POLLIN|POLLRDNORM; | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | |||
212 | static int video_release(struct file *file) | ||
213 | { | ||
214 | struct cx25821_fh *fh = file->private_data; | ||
215 | struct cx25821_dev *dev = fh->dev; | ||
216 | |||
217 | //stop the risc engine and fifo | ||
218 | cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ | ||
219 | |||
220 | /* stop video capture */ | ||
221 | if (res_check(fh, RESOURCE_VIDEO3)) { | ||
222 | videobuf_queue_cancel(&fh->vidq); | ||
223 | res_free(dev, fh, RESOURCE_VIDEO3); | ||
224 | } | ||
225 | |||
226 | if (fh->vidq.read_buf) { | ||
227 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
228 | kfree(fh->vidq.read_buf); | ||
229 | } | ||
230 | |||
231 | videobuf_mmap_free(&fh->vidq); | ||
232 | |||
233 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
234 | file->private_data = NULL; | ||
235 | kfree(fh); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | |||
241 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
242 | { | ||
243 | struct cx25821_fh *fh = priv; | ||
244 | struct cx25821_dev *dev = fh->dev; | ||
245 | |||
246 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
247 | { | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | |||
251 | if (unlikely(i != fh->type)) | ||
252 | { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) | ||
257 | { | ||
258 | return -EBUSY; | ||
259 | } | ||
260 | |||
261 | return videobuf_streamon(get_queue(fh)); | ||
262 | } | ||
263 | |||
264 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
265 | { | ||
266 | struct cx25821_fh *fh = priv; | ||
267 | struct cx25821_dev *dev = fh->dev; | ||
268 | int err, res; | ||
269 | |||
270 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
271 | return -EINVAL; | ||
272 | if (i != fh->type) | ||
273 | return -EINVAL; | ||
274 | |||
275 | res = get_resource(fh, RESOURCE_VIDEO3); | ||
276 | err = videobuf_streamoff(get_queue(fh)); | ||
277 | if (err < 0) | ||
278 | return err; | ||
279 | res_free(dev, fh, res); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | |||
285 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
286 | { | ||
287 | struct cx25821_fh *fh = priv; | ||
288 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
289 | int err; | ||
290 | int pix_format = 0; | ||
291 | |||
292 | if (fh) | ||
293 | { | ||
294 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
295 | if (0 != err) | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | dprintk(2, "%s()\n", __func__); | ||
300 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
301 | |||
302 | if (0 != err) | ||
303 | return err; | ||
304 | |||
305 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
306 | fh->vidq.field = f->fmt.pix.field; | ||
307 | |||
308 | // check if width and height is valid based on set standard | ||
309 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
310 | { | ||
311 | fh->width = f->fmt.pix.width; | ||
312 | } | ||
313 | |||
314 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
315 | { | ||
316 | fh->height = f->fmt.pix.height; | ||
317 | } | ||
318 | |||
319 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
320 | pix_format = PIXEL_FRMT_411; | ||
321 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
322 | pix_format = PIXEL_FRMT_422; | ||
323 | else | ||
324 | return -EINVAL; | ||
325 | |||
326 | cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); | ||
327 | |||
328 | // check if cif resolution | ||
329 | if (fh->width == 320 || fh->width == 352) | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH03] = 1; | ||
332 | }else | ||
333 | { | ||
334 | dev->use_cif_resolution[SRAM_CH03] = 0; | ||
335 | } | ||
336 | dev->cif_width[SRAM_CH03] = fh->width; | ||
337 | medusa_set_resolution( dev, fh->width, SRAM_CH03 ); | ||
338 | |||
339 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
340 | cx25821_call_all(dev, video, s_fmt, f); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
346 | { | ||
347 | int ret_val = 0; | ||
348 | struct cx25821_fh *fh = priv; | ||
349 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
350 | |||
351 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
352 | |||
353 | p->sequence = dev->vidq[SRAM_CH03].count; | ||
354 | |||
355 | return ret_val; | ||
356 | } | ||
357 | |||
358 | static int vidioc_log_status (struct file *file, void *priv) | ||
359 | { | ||
360 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
361 | char name[32 + 2]; | ||
362 | |||
363 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; | ||
364 | u32 tmp = 0; | ||
365 | |||
366 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
367 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
368 | dev->name); | ||
369 | cx25821_call_all(dev, core, log_status); | ||
370 | |||
371 | tmp = cx_read(sram_ch->dma_ctl); | ||
372 | printk(KERN_INFO "Video input 3 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
373 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
374 | dev->name); | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
379 | struct v4l2_control *ctl) | ||
380 | { | ||
381 | struct cx25821_fh *fh = priv; | ||
382 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
383 | int err; | ||
384 | |||
385 | if (fh) { | ||
386 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
387 | if (0 != err) | ||
388 | return err; | ||
389 | } | ||
390 | |||
391 | return cx25821_set_control(dev, ctl, SRAM_CH03); | ||
392 | } | ||
393 | |||
394 | // exported stuff | ||
395 | static const struct v4l2_file_operations video_fops = { | ||
396 | .owner = THIS_MODULE, | ||
397 | .open = video_open, | ||
398 | .release = video_release, | ||
399 | .read = video_read, | ||
400 | .poll = video_poll, | ||
401 | .mmap = video_mmap, | ||
402 | .ioctl = video_ioctl2, | ||
403 | }; | ||
404 | |||
405 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
406 | .vidioc_querycap = vidioc_querycap, | ||
407 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
408 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
409 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
410 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
411 | .vidioc_reqbufs = vidioc_reqbufs, | ||
412 | .vidioc_querybuf = vidioc_querybuf, | ||
413 | .vidioc_qbuf = vidioc_qbuf, | ||
414 | .vidioc_dqbuf = vidioc_dqbuf, | ||
415 | #ifdef TUNER_FLAG | ||
416 | .vidioc_s_std = vidioc_s_std, | ||
417 | .vidioc_querystd = vidioc_querystd, | ||
418 | #endif | ||
419 | .vidioc_cropcap = vidioc_cropcap, | ||
420 | .vidioc_s_crop = vidioc_s_crop, | ||
421 | .vidioc_g_crop = vidioc_g_crop, | ||
422 | .vidioc_enum_input = vidioc_enum_input, | ||
423 | .vidioc_g_input = vidioc_g_input, | ||
424 | .vidioc_s_input = vidioc_s_input, | ||
425 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
426 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
427 | .vidioc_queryctrl = vidioc_queryctrl, | ||
428 | .vidioc_streamon = vidioc_streamon, | ||
429 | .vidioc_streamoff = vidioc_streamoff, | ||
430 | .vidioc_log_status = vidioc_log_status, | ||
431 | .vidioc_g_priority = vidioc_g_priority, | ||
432 | .vidioc_s_priority = vidioc_s_priority, | ||
433 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
434 | .vidiocgmbuf = vidiocgmbuf, | ||
435 | #endif | ||
436 | #ifdef TUNER_FLAG | ||
437 | .vidioc_g_tuner = vidioc_g_tuner, | ||
438 | .vidioc_s_tuner = vidioc_s_tuner, | ||
439 | .vidioc_g_frequency = vidioc_g_frequency, | ||
440 | .vidioc_s_frequency = vidioc_s_frequency, | ||
441 | #endif | ||
442 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
443 | .vidioc_g_register = vidioc_g_register, | ||
444 | .vidioc_s_register = vidioc_s_register, | ||
445 | #endif | ||
446 | }; | ||
447 | |||
448 | struct video_device cx25821_video_template3 = { | ||
449 | .name = "cx25821-video", | ||
450 | .fops = &video_fops, | ||
451 | .minor = -1, | ||
452 | .ioctl_ops = &video_ioctl_ops, | ||
453 | .tvnorms = CX25821_NORMS, | ||
454 | .current_norm = V4L2_STD_NTSC_M, | ||
455 | }; | ||
456 | |||
457 | |||
458 | |||
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c new file mode 100644 index 00000000000..03da3642cc3 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video4.c | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | u32 pix_format; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | file->private_data = fh; | ||
125 | fh->dev = dev; | ||
126 | fh->type = type; | ||
127 | fh->width = 720; | ||
128 | |||
129 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
130 | fh->height = 576; | ||
131 | else | ||
132 | fh->height = 480; | ||
133 | |||
134 | dev->channel_opened = SRAM_CH04; | ||
135 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
136 | fh->fmt = format_by_fourcc(pix_format); | ||
137 | |||
138 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
139 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
140 | &dev->pci->dev, &dev->slock, | ||
141 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
142 | V4L2_FIELD_INTERLACED, | ||
143 | sizeof(struct cx25821_buffer), | ||
144 | fh); | ||
145 | |||
146 | dprintk(1, "post videobuf_queue_init()\n"); | ||
147 | unlock_kernel(); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
153 | { | ||
154 | struct cx25821_fh *fh = file->private_data; | ||
155 | |||
156 | switch (fh->type) | ||
157 | { | ||
158 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
159 | if (res_locked(fh->dev, RESOURCE_VIDEO4)) | ||
160 | return -EBUSY; | ||
161 | |||
162 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
163 | |||
164 | default: | ||
165 | BUG(); | ||
166 | return 0; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
171 | { | ||
172 | struct cx25821_fh *fh = file->private_data; | ||
173 | struct cx25821_buffer *buf; | ||
174 | |||
175 | if (res_check(fh, RESOURCE_VIDEO4)) { | ||
176 | /* streaming capture */ | ||
177 | if (list_empty(&fh->vidq.stream)) | ||
178 | return POLLERR; | ||
179 | buf = list_entry(fh->vidq.stream.next, | ||
180 | struct cx25821_buffer, vb.stream); | ||
181 | } else { | ||
182 | /* read() capture */ | ||
183 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
184 | if (NULL == buf) | ||
185 | return POLLERR; | ||
186 | } | ||
187 | |||
188 | poll_wait(file, &buf->vb.done, wait); | ||
189 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
190 | { | ||
191 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
192 | { | ||
193 | struct cx25821_dev *dev = fh->dev; | ||
194 | |||
195 | if( dev && dev->use_cif_resolution[SRAM_CH04] ) | ||
196 | { | ||
197 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
198 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
199 | *((char*)buf->vb.baddr+3) = cam_id; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return POLLIN|POLLRDNORM; | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | |||
210 | static int video_release(struct file *file) | ||
211 | { | ||
212 | struct cx25821_fh *fh = file->private_data; | ||
213 | struct cx25821_dev *dev = fh->dev; | ||
214 | |||
215 | //stop the risc engine and fifo | ||
216 | cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ | ||
217 | |||
218 | /* stop video capture */ | ||
219 | if (res_check(fh, RESOURCE_VIDEO4)) { | ||
220 | videobuf_queue_cancel(&fh->vidq); | ||
221 | res_free(dev, fh, RESOURCE_VIDEO4); | ||
222 | } | ||
223 | |||
224 | if (fh->vidq.read_buf) { | ||
225 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
226 | kfree(fh->vidq.read_buf); | ||
227 | } | ||
228 | |||
229 | videobuf_mmap_free(&fh->vidq); | ||
230 | |||
231 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
232 | file->private_data = NULL; | ||
233 | kfree(fh); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | |||
239 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
240 | { | ||
241 | struct cx25821_fh *fh = priv; | ||
242 | struct cx25821_dev *dev = fh->dev; | ||
243 | |||
244 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
245 | { | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | if (unlikely(i != fh->type)) | ||
250 | { | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) | ||
255 | { | ||
256 | return -EBUSY; | ||
257 | } | ||
258 | |||
259 | return videobuf_streamon(get_queue(fh)); | ||
260 | } | ||
261 | |||
262 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
263 | { | ||
264 | struct cx25821_fh *fh = priv; | ||
265 | struct cx25821_dev *dev = fh->dev; | ||
266 | int err, res; | ||
267 | |||
268 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
269 | return -EINVAL; | ||
270 | if (i != fh->type) | ||
271 | return -EINVAL; | ||
272 | |||
273 | res = get_resource(fh, RESOURCE_VIDEO4); | ||
274 | err = videobuf_streamoff(get_queue(fh)); | ||
275 | if (err < 0) | ||
276 | return err; | ||
277 | res_free(dev, fh, res); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | |||
282 | |||
283 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
284 | { | ||
285 | struct cx25821_fh *fh = priv; | ||
286 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
287 | int err; | ||
288 | int pix_format = 0; | ||
289 | |||
290 | // check priority | ||
291 | if (fh) | ||
292 | { | ||
293 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
294 | if (0 != err) | ||
295 | return err; | ||
296 | } | ||
297 | dprintk(2, "%s()\n", __func__); | ||
298 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
299 | |||
300 | if (0 != err) | ||
301 | return err; | ||
302 | |||
303 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
304 | fh->vidq.field = f->fmt.pix.field; | ||
305 | |||
306 | // check if width and height is valid based on set standard | ||
307 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
308 | { | ||
309 | fh->width = f->fmt.pix.width; | ||
310 | } | ||
311 | |||
312 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
313 | { | ||
314 | fh->height = f->fmt.pix.height; | ||
315 | } | ||
316 | |||
317 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
318 | pix_format = PIXEL_FRMT_411; | ||
319 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
320 | pix_format = PIXEL_FRMT_422; | ||
321 | else | ||
322 | return -EINVAL; | ||
323 | |||
324 | cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); | ||
325 | |||
326 | // check if cif resolution | ||
327 | if (fh->width == 320 || fh->width == 352) | ||
328 | { | ||
329 | dev->use_cif_resolution[SRAM_CH04] = 1; | ||
330 | }else | ||
331 | { | ||
332 | dev->use_cif_resolution[SRAM_CH04] = 0; | ||
333 | } | ||
334 | dev->cif_width[SRAM_CH04] = fh->width; | ||
335 | medusa_set_resolution( dev, fh->width, SRAM_CH04); | ||
336 | |||
337 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
338 | cx25821_call_all(dev, video, s_fmt, f); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
344 | { | ||
345 | int ret_val = 0; | ||
346 | struct cx25821_fh *fh = priv; | ||
347 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
348 | |||
349 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
350 | |||
351 | p->sequence = dev->vidq[SRAM_CH04].count; | ||
352 | |||
353 | return ret_val; | ||
354 | } | ||
355 | |||
356 | static int vidioc_log_status (struct file *file, void *priv) | ||
357 | { | ||
358 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
359 | char name[32 + 2]; | ||
360 | |||
361 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; | ||
362 | u32 tmp = 0; | ||
363 | |||
364 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
365 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
366 | dev->name); | ||
367 | cx25821_call_all(dev, core, log_status); | ||
368 | |||
369 | tmp = cx_read(sram_ch->dma_ctl); | ||
370 | printk(KERN_INFO "Video input 4 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
371 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
372 | dev->name); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
377 | struct v4l2_control *ctl) | ||
378 | { | ||
379 | struct cx25821_fh *fh = priv; | ||
380 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
381 | int err; | ||
382 | |||
383 | if (fh) { | ||
384 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
385 | if (0 != err) | ||
386 | return err; | ||
387 | } | ||
388 | |||
389 | return cx25821_set_control(dev, ctl, SRAM_CH04); | ||
390 | } | ||
391 | |||
392 | // exported stuff | ||
393 | static const struct v4l2_file_operations video_fops = { | ||
394 | .owner = THIS_MODULE, | ||
395 | .open = video_open, | ||
396 | .release = video_release, | ||
397 | .read = video_read, | ||
398 | .poll = video_poll, | ||
399 | .mmap = video_mmap, | ||
400 | .ioctl = video_ioctl2, | ||
401 | }; | ||
402 | |||
403 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
404 | .vidioc_querycap = vidioc_querycap, | ||
405 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
406 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
407 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
408 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
409 | .vidioc_reqbufs = vidioc_reqbufs, | ||
410 | .vidioc_querybuf = vidioc_querybuf, | ||
411 | .vidioc_qbuf = vidioc_qbuf, | ||
412 | .vidioc_dqbuf = vidioc_dqbuf, | ||
413 | #ifdef TUNER_FLAG | ||
414 | .vidioc_s_std = vidioc_s_std, | ||
415 | .vidioc_querystd = vidioc_querystd, | ||
416 | #endif | ||
417 | .vidioc_cropcap = vidioc_cropcap, | ||
418 | .vidioc_s_crop = vidioc_s_crop, | ||
419 | .vidioc_g_crop = vidioc_g_crop, | ||
420 | .vidioc_enum_input = vidioc_enum_input, | ||
421 | .vidioc_g_input = vidioc_g_input, | ||
422 | .vidioc_s_input = vidioc_s_input, | ||
423 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
424 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
425 | .vidioc_queryctrl = vidioc_queryctrl, | ||
426 | .vidioc_streamon = vidioc_streamon, | ||
427 | .vidioc_streamoff = vidioc_streamoff, | ||
428 | .vidioc_log_status = vidioc_log_status, | ||
429 | .vidioc_g_priority = vidioc_g_priority, | ||
430 | .vidioc_s_priority = vidioc_s_priority, | ||
431 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
432 | .vidiocgmbuf = vidiocgmbuf, | ||
433 | #endif | ||
434 | #ifdef TUNER_FLAG | ||
435 | .vidioc_g_tuner = vidioc_g_tuner, | ||
436 | .vidioc_s_tuner = vidioc_s_tuner, | ||
437 | .vidioc_g_frequency = vidioc_g_frequency, | ||
438 | .vidioc_s_frequency = vidioc_s_frequency, | ||
439 | #endif | ||
440 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
441 | .vidioc_g_register = vidioc_g_register, | ||
442 | .vidioc_s_register = vidioc_s_register, | ||
443 | #endif | ||
444 | }; | ||
445 | |||
446 | struct video_device cx25821_video_template4 = { | ||
447 | .name = "cx25821-video", | ||
448 | .fops = &video_fops, | ||
449 | .minor = -1, | ||
450 | .ioctl_ops = &video_ioctl_ops, | ||
451 | .tvnorms = CX25821_NORMS, | ||
452 | .current_norm = V4L2_STD_NTSC_M, | ||
453 | }; | ||
454 | |||
455 | |||
456 | |||
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c new file mode 100644 index 00000000000..1d47543920b --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video5.c | |||
@@ -0,0 +1,455 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | u32 pix_format; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | file->private_data = fh; | ||
125 | fh->dev = dev; | ||
126 | fh->type = type; | ||
127 | fh->width = 720; | ||
128 | |||
129 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
130 | fh->height = 576; | ||
131 | else | ||
132 | fh->height = 480; | ||
133 | |||
134 | dev->channel_opened = SRAM_CH05; | ||
135 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
136 | fh->fmt = format_by_fourcc(pix_format); | ||
137 | |||
138 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
139 | |||
140 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
141 | &dev->pci->dev, &dev->slock, | ||
142 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
143 | V4L2_FIELD_INTERLACED, | ||
144 | sizeof(struct cx25821_buffer), | ||
145 | fh); | ||
146 | |||
147 | dprintk(1, "post videobuf_queue_init()\n"); | ||
148 | unlock_kernel(); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
154 | { | ||
155 | struct cx25821_fh *fh = file->private_data; | ||
156 | |||
157 | switch (fh->type) | ||
158 | { | ||
159 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
160 | if (res_locked(fh->dev, RESOURCE_VIDEO5)) | ||
161 | return -EBUSY; | ||
162 | |||
163 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
164 | |||
165 | default: | ||
166 | BUG(); | ||
167 | return 0; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
172 | { | ||
173 | struct cx25821_fh *fh = file->private_data; | ||
174 | struct cx25821_buffer *buf; | ||
175 | |||
176 | if (res_check(fh, RESOURCE_VIDEO5)) { | ||
177 | /* streaming capture */ | ||
178 | if (list_empty(&fh->vidq.stream)) | ||
179 | return POLLERR; | ||
180 | buf = list_entry(fh->vidq.stream.next, | ||
181 | struct cx25821_buffer, vb.stream); | ||
182 | } else { | ||
183 | /* read() capture */ | ||
184 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
185 | if (NULL == buf) | ||
186 | return POLLERR; | ||
187 | } | ||
188 | |||
189 | poll_wait(file, &buf->vb.done, wait); | ||
190 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
191 | { | ||
192 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
193 | { | ||
194 | struct cx25821_dev *dev = fh->dev; | ||
195 | |||
196 | if( dev && dev->use_cif_resolution[SRAM_CH05] ) | ||
197 | { | ||
198 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
199 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
200 | *((char*)buf->vb.baddr+3) = cam_id; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return POLLIN|POLLRDNORM; | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | |||
211 | static int video_release(struct file *file) | ||
212 | { | ||
213 | struct cx25821_fh *fh = file->private_data; | ||
214 | struct cx25821_dev *dev = fh->dev; | ||
215 | |||
216 | //stop the risc engine and fifo | ||
217 | cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ | ||
218 | |||
219 | /* stop video capture */ | ||
220 | if (res_check(fh, RESOURCE_VIDEO5)) { | ||
221 | videobuf_queue_cancel(&fh->vidq); | ||
222 | res_free(dev, fh, RESOURCE_VIDEO5); | ||
223 | } | ||
224 | |||
225 | if (fh->vidq.read_buf) { | ||
226 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
227 | kfree(fh->vidq.read_buf); | ||
228 | } | ||
229 | |||
230 | videobuf_mmap_free(&fh->vidq); | ||
231 | |||
232 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
233 | file->private_data = NULL; | ||
234 | kfree(fh); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | |||
240 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
241 | { | ||
242 | struct cx25821_fh *fh = priv; | ||
243 | struct cx25821_dev *dev = fh->dev; | ||
244 | |||
245 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
246 | { | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
250 | if (unlikely(i != fh->type)) | ||
251 | { | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) | ||
256 | { | ||
257 | return -EBUSY; | ||
258 | } | ||
259 | |||
260 | return videobuf_streamon(get_queue(fh)); | ||
261 | } | ||
262 | |||
263 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
264 | { | ||
265 | struct cx25821_fh *fh = priv; | ||
266 | struct cx25821_dev *dev = fh->dev; | ||
267 | int err, res; | ||
268 | |||
269 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
270 | return -EINVAL; | ||
271 | if (i != fh->type) | ||
272 | return -EINVAL; | ||
273 | |||
274 | res = get_resource(fh, RESOURCE_VIDEO5); | ||
275 | err = videobuf_streamoff(get_queue(fh)); | ||
276 | if (err < 0) | ||
277 | return err; | ||
278 | res_free(dev, fh, res); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | |||
283 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
284 | { | ||
285 | struct cx25821_fh *fh = priv; | ||
286 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
287 | int err; | ||
288 | int pix_format = 0; | ||
289 | |||
290 | if (fh) | ||
291 | { | ||
292 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
293 | if (0 != err) | ||
294 | return err; | ||
295 | } | ||
296 | |||
297 | dprintk(2, "%s()\n", __func__); | ||
298 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
299 | |||
300 | if (0 != err) | ||
301 | return err; | ||
302 | |||
303 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
304 | fh->vidq.field = f->fmt.pix.field; | ||
305 | |||
306 | // check if width and height is valid based on set standard | ||
307 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
308 | { | ||
309 | fh->width = f->fmt.pix.width; | ||
310 | } | ||
311 | |||
312 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
313 | { | ||
314 | fh->height = f->fmt.pix.height; | ||
315 | } | ||
316 | |||
317 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
318 | pix_format = PIXEL_FRMT_411; | ||
319 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
320 | pix_format = PIXEL_FRMT_422; | ||
321 | else | ||
322 | return -EINVAL; | ||
323 | |||
324 | cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); | ||
325 | |||
326 | // check if cif resolution | ||
327 | if (fh->width == 320 || fh->width == 352) | ||
328 | { | ||
329 | dev->use_cif_resolution[SRAM_CH05] = 1; | ||
330 | }else | ||
331 | { | ||
332 | dev->use_cif_resolution[SRAM_CH05] = 0; | ||
333 | } | ||
334 | dev->cif_width[SRAM_CH05] = fh->width; | ||
335 | medusa_set_resolution( dev, fh->width, SRAM_CH05 ); | ||
336 | |||
337 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
338 | cx25821_call_all(dev, video, s_fmt, f); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
344 | { | ||
345 | int ret_val = 0; | ||
346 | struct cx25821_fh *fh = priv; | ||
347 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
348 | |||
349 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
350 | |||
351 | p->sequence = dev->vidq[SRAM_CH05].count; | ||
352 | |||
353 | return ret_val; | ||
354 | } | ||
355 | static int vidioc_log_status (struct file *file, void *priv) | ||
356 | { | ||
357 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
358 | char name[32 + 2]; | ||
359 | |||
360 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; | ||
361 | u32 tmp = 0; | ||
362 | |||
363 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
364 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
365 | dev->name); | ||
366 | cx25821_call_all(dev, core, log_status); | ||
367 | |||
368 | tmp = cx_read(sram_ch->dma_ctl); | ||
369 | printk(KERN_INFO "Video input 5 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
370 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
371 | dev->name); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
376 | struct v4l2_control *ctl) | ||
377 | { | ||
378 | struct cx25821_fh *fh = priv; | ||
379 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
380 | int err; | ||
381 | |||
382 | if (fh) { | ||
383 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
384 | if (0 != err) | ||
385 | return err; | ||
386 | } | ||
387 | |||
388 | return cx25821_set_control(dev, ctl, SRAM_CH05); | ||
389 | } | ||
390 | |||
391 | // exported stuff | ||
392 | static const struct v4l2_file_operations video_fops = { | ||
393 | .owner = THIS_MODULE, | ||
394 | .open = video_open, | ||
395 | .release = video_release, | ||
396 | .read = video_read, | ||
397 | .poll = video_poll, | ||
398 | .mmap = video_mmap, | ||
399 | .ioctl = video_ioctl2, | ||
400 | }; | ||
401 | |||
402 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
403 | .vidioc_querycap = vidioc_querycap, | ||
404 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
405 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
406 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
407 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
408 | .vidioc_reqbufs = vidioc_reqbufs, | ||
409 | .vidioc_querybuf = vidioc_querybuf, | ||
410 | .vidioc_qbuf = vidioc_qbuf, | ||
411 | .vidioc_dqbuf = vidioc_dqbuf, | ||
412 | #ifdef TUNER_FLAG | ||
413 | .vidioc_s_std = vidioc_s_std, | ||
414 | .vidioc_querystd = vidioc_querystd, | ||
415 | #endif | ||
416 | .vidioc_cropcap = vidioc_cropcap, | ||
417 | .vidioc_s_crop = vidioc_s_crop, | ||
418 | .vidioc_g_crop = vidioc_g_crop, | ||
419 | .vidioc_enum_input = vidioc_enum_input, | ||
420 | .vidioc_g_input = vidioc_g_input, | ||
421 | .vidioc_s_input = vidioc_s_input, | ||
422 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
423 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
424 | .vidioc_queryctrl = vidioc_queryctrl, | ||
425 | .vidioc_streamon = vidioc_streamon, | ||
426 | .vidioc_streamoff = vidioc_streamoff, | ||
427 | .vidioc_log_status = vidioc_log_status, | ||
428 | .vidioc_g_priority = vidioc_g_priority, | ||
429 | .vidioc_s_priority = vidioc_s_priority, | ||
430 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
431 | .vidiocgmbuf = vidiocgmbuf, | ||
432 | #endif | ||
433 | #ifdef TUNER_FLAG | ||
434 | .vidioc_g_tuner = vidioc_g_tuner, | ||
435 | .vidioc_s_tuner = vidioc_s_tuner, | ||
436 | .vidioc_g_frequency = vidioc_g_frequency, | ||
437 | .vidioc_s_frequency = vidioc_s_frequency, | ||
438 | #endif | ||
439 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
440 | .vidioc_g_register = vidioc_g_register, | ||
441 | .vidioc_s_register = vidioc_s_register, | ||
442 | #endif | ||
443 | }; | ||
444 | |||
445 | struct video_device cx25821_video_template5 = { | ||
446 | .name = "cx25821-video", | ||
447 | .fops = &video_fops, | ||
448 | .minor = -1, | ||
449 | .ioctl_ops = &video_ioctl_ops, | ||
450 | .tvnorms = CX25821_NORMS, | ||
451 | .current_norm = V4L2_STD_NTSC_M, | ||
452 | }; | ||
453 | |||
454 | |||
455 | |||
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c new file mode 100644 index 00000000000..980565af5c3 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video6.c | |||
@@ -0,0 +1,455 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | u32 pix_format; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | file->private_data = fh; | ||
125 | fh->dev = dev; | ||
126 | fh->type = type; | ||
127 | fh->width = 720; | ||
128 | |||
129 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
130 | fh->height = 576; | ||
131 | else | ||
132 | fh->height = 480; | ||
133 | |||
134 | dev->channel_opened = SRAM_CH06; | ||
135 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
136 | fh->fmt = format_by_fourcc(pix_format); | ||
137 | |||
138 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
139 | |||
140 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
141 | &dev->pci->dev, &dev->slock, | ||
142 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
143 | V4L2_FIELD_INTERLACED, | ||
144 | sizeof(struct cx25821_buffer), | ||
145 | fh); | ||
146 | |||
147 | dprintk(1, "post videobuf_queue_init()\n"); | ||
148 | unlock_kernel(); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
154 | { | ||
155 | struct cx25821_fh *fh = file->private_data; | ||
156 | |||
157 | switch (fh->type) | ||
158 | { | ||
159 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
160 | if (res_locked(fh->dev, RESOURCE_VIDEO6)) | ||
161 | return -EBUSY; | ||
162 | |||
163 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
164 | |||
165 | default: | ||
166 | BUG(); | ||
167 | return 0; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
172 | { | ||
173 | struct cx25821_fh *fh = file->private_data; | ||
174 | struct cx25821_buffer *buf; | ||
175 | |||
176 | if (res_check(fh, RESOURCE_VIDEO6)) { | ||
177 | /* streaming capture */ | ||
178 | if (list_empty(&fh->vidq.stream)) | ||
179 | return POLLERR; | ||
180 | buf = list_entry(fh->vidq.stream.next, | ||
181 | struct cx25821_buffer, vb.stream); | ||
182 | } else { | ||
183 | /* read() capture */ | ||
184 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
185 | if (NULL == buf) | ||
186 | return POLLERR; | ||
187 | } | ||
188 | |||
189 | poll_wait(file, &buf->vb.done, wait); | ||
190 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
191 | { | ||
192 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
193 | { | ||
194 | struct cx25821_dev *dev = fh->dev; | ||
195 | |||
196 | if( dev && dev->use_cif_resolution[SRAM_CH06] ) | ||
197 | { | ||
198 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
199 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
200 | *((char*)buf->vb.baddr+3) = cam_id; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return POLLIN|POLLRDNORM; | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | |||
211 | static int video_release(struct file *file) | ||
212 | { | ||
213 | struct cx25821_fh *fh = file->private_data; | ||
214 | struct cx25821_dev *dev = fh->dev; | ||
215 | |||
216 | //stop the risc engine and fifo | ||
217 | cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ | ||
218 | |||
219 | /* stop video capture */ | ||
220 | if (res_check(fh, RESOURCE_VIDEO6)) { | ||
221 | videobuf_queue_cancel(&fh->vidq); | ||
222 | res_free(dev, fh, RESOURCE_VIDEO6); | ||
223 | } | ||
224 | if (fh->vidq.read_buf) { | ||
225 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
226 | kfree(fh->vidq.read_buf); | ||
227 | } | ||
228 | |||
229 | videobuf_mmap_free(&fh->vidq); | ||
230 | |||
231 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
232 | file->private_data = NULL; | ||
233 | kfree(fh); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | |||
239 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
240 | { | ||
241 | struct cx25821_fh *fh = priv; | ||
242 | struct cx25821_dev *dev = fh->dev; | ||
243 | |||
244 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
245 | { | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | if (unlikely(i != fh->type)) | ||
250 | { | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) | ||
255 | { | ||
256 | return -EBUSY; | ||
257 | } | ||
258 | |||
259 | return videobuf_streamon(get_queue(fh)); | ||
260 | } | ||
261 | |||
262 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
263 | { | ||
264 | struct cx25821_fh *fh = priv; | ||
265 | struct cx25821_dev *dev = fh->dev; | ||
266 | int err, res; | ||
267 | |||
268 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
269 | return -EINVAL; | ||
270 | if (i != fh->type) | ||
271 | return -EINVAL; | ||
272 | |||
273 | res = get_resource(fh, RESOURCE_VIDEO6); | ||
274 | err = videobuf_streamoff(get_queue(fh)); | ||
275 | if (err < 0) | ||
276 | return err; | ||
277 | res_free(dev, fh, res); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | |||
282 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
283 | { | ||
284 | struct cx25821_fh *fh = priv; | ||
285 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
286 | int err; | ||
287 | int pix_format = 0; | ||
288 | |||
289 | if (fh) | ||
290 | { | ||
291 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
292 | if (0 != err) | ||
293 | return err; | ||
294 | } | ||
295 | |||
296 | dprintk(2, "%s()\n", __func__); | ||
297 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
298 | |||
299 | if (0 != err) | ||
300 | return err; | ||
301 | |||
302 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
303 | fh->vidq.field = f->fmt.pix.field; | ||
304 | |||
305 | // check if width and height is valid based on set standard | ||
306 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
307 | { | ||
308 | fh->width = f->fmt.pix.width; | ||
309 | } | ||
310 | |||
311 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
312 | { | ||
313 | fh->height = f->fmt.pix.height; | ||
314 | } | ||
315 | |||
316 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
317 | pix_format = PIXEL_FRMT_411; | ||
318 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
319 | pix_format = PIXEL_FRMT_422; | ||
320 | else | ||
321 | return -EINVAL; | ||
322 | |||
323 | cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); | ||
324 | |||
325 | // check if cif resolution | ||
326 | if (fh->width == 320 || fh->width == 352) | ||
327 | { | ||
328 | dev->use_cif_resolution[SRAM_CH06] = 1; | ||
329 | }else | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH06] = 0; | ||
332 | } | ||
333 | dev->cif_width[SRAM_CH06] = fh->width; | ||
334 | medusa_set_resolution( dev, fh->width, SRAM_CH06 ); | ||
335 | |||
336 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
337 | cx25821_call_all(dev, video, s_fmt, f); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
343 | { | ||
344 | int ret_val = 0; | ||
345 | struct cx25821_fh *fh = priv; | ||
346 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
347 | |||
348 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
349 | |||
350 | p->sequence = dev->vidq[SRAM_CH06].count; | ||
351 | |||
352 | return ret_val; | ||
353 | } | ||
354 | |||
355 | static int vidioc_log_status (struct file *file, void *priv) | ||
356 | { | ||
357 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
358 | char name[32 + 2]; | ||
359 | |||
360 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; | ||
361 | u32 tmp = 0; | ||
362 | |||
363 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
364 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
365 | dev->name); | ||
366 | cx25821_call_all(dev, core, log_status); | ||
367 | |||
368 | tmp = cx_read(sram_ch->dma_ctl); | ||
369 | printk(KERN_INFO "Video input 6 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
370 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
371 | dev->name); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
376 | struct v4l2_control *ctl) | ||
377 | { | ||
378 | struct cx25821_fh *fh = priv; | ||
379 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
380 | int err; | ||
381 | |||
382 | if (fh) { | ||
383 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
384 | if (0 != err) | ||
385 | return err; | ||
386 | } | ||
387 | |||
388 | return cx25821_set_control(dev, ctl, SRAM_CH06); | ||
389 | } | ||
390 | |||
391 | // exported stuff | ||
392 | static const struct v4l2_file_operations video_fops = { | ||
393 | .owner = THIS_MODULE, | ||
394 | .open = video_open, | ||
395 | .release = video_release, | ||
396 | .read = video_read, | ||
397 | .poll = video_poll, | ||
398 | .mmap = video_mmap, | ||
399 | .ioctl = video_ioctl2, | ||
400 | }; | ||
401 | |||
402 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
403 | .vidioc_querycap = vidioc_querycap, | ||
404 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
405 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
406 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
407 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
408 | .vidioc_reqbufs = vidioc_reqbufs, | ||
409 | .vidioc_querybuf = vidioc_querybuf, | ||
410 | .vidioc_qbuf = vidioc_qbuf, | ||
411 | .vidioc_dqbuf = vidioc_dqbuf, | ||
412 | #ifdef TUNER_FLAG | ||
413 | .vidioc_s_std = vidioc_s_std, | ||
414 | .vidioc_querystd = vidioc_querystd, | ||
415 | #endif | ||
416 | .vidioc_cropcap = vidioc_cropcap, | ||
417 | .vidioc_s_crop = vidioc_s_crop, | ||
418 | .vidioc_g_crop = vidioc_g_crop, | ||
419 | .vidioc_enum_input = vidioc_enum_input, | ||
420 | .vidioc_g_input = vidioc_g_input, | ||
421 | .vidioc_s_input = vidioc_s_input, | ||
422 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
423 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
424 | .vidioc_queryctrl = vidioc_queryctrl, | ||
425 | .vidioc_streamon = vidioc_streamon, | ||
426 | .vidioc_streamoff = vidioc_streamoff, | ||
427 | .vidioc_log_status = vidioc_log_status, | ||
428 | .vidioc_g_priority = vidioc_g_priority, | ||
429 | .vidioc_s_priority = vidioc_s_priority, | ||
430 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
431 | .vidiocgmbuf = vidiocgmbuf, | ||
432 | #endif | ||
433 | #ifdef TUNER_FLAG | ||
434 | .vidioc_g_tuner = vidioc_g_tuner, | ||
435 | .vidioc_s_tuner = vidioc_s_tuner, | ||
436 | .vidioc_g_frequency = vidioc_g_frequency, | ||
437 | .vidioc_s_frequency = vidioc_s_frequency, | ||
438 | #endif | ||
439 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
440 | .vidioc_g_register = vidioc_g_register, | ||
441 | .vidioc_s_register = vidioc_s_register, | ||
442 | #endif | ||
443 | }; | ||
444 | |||
445 | struct video_device cx25821_video_template6 = { | ||
446 | .name = "cx25821-video", | ||
447 | .fops = &video_fops, | ||
448 | .minor = -1, | ||
449 | .ioctl_ops = &video_ioctl_ops, | ||
450 | .tvnorms = CX25821_NORMS, | ||
451 | .current_norm = V4L2_STD_NTSC_M, | ||
452 | }; | ||
453 | |||
454 | |||
455 | |||
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c new file mode 100644 index 00000000000..966e369a4ab --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video7.c | |||
@@ -0,0 +1,454 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | if (!list_empty(&q->queued)) { | ||
42 | list_add_tail(&buf->vb.queue, &q->queued); | ||
43 | buf->vb.state = VIDEOBUF_QUEUED; | ||
44 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
45 | |||
46 | } else if (list_empty(&q->active)) { | ||
47 | list_add_tail(&buf->vb.queue, &q->active); | ||
48 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]); | ||
49 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
50 | buf->count = q->count++; | ||
51 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
52 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
53 | buf, buf->vb. i, buf->count, q->count); | ||
54 | } else { | ||
55 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
56 | if (prev->vb.width == buf->vb.width && | ||
57 | prev->vb.height == buf->vb.height && | ||
58 | prev->fmt == buf->fmt) { | ||
59 | list_add_tail(&buf->vb.queue, &q->active); | ||
60 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
61 | buf->count = q->count++; | ||
62 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
63 | |||
64 | /* 64 bit bits 63-32 */ | ||
65 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
66 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
67 | |||
68 | } else { | ||
69 | list_add_tail(&buf->vb.queue, &q->queued); | ||
70 | buf->vb.state = VIDEOBUF_QUEUED; | ||
71 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | if (list_empty(&q->active)) | ||
76 | { | ||
77 | dprintk(2, "active queue empty!\n"); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | |||
82 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
83 | .buf_setup = buffer_setup, | ||
84 | .buf_prepare = buffer_prepare, | ||
85 | .buf_queue = buffer_queue, | ||
86 | .buf_release = buffer_release, | ||
87 | }; | ||
88 | |||
89 | |||
90 | static int video_open(struct file *file) | ||
91 | { | ||
92 | int minor = video_devdata(file)->minor; | ||
93 | struct cx25821_dev *h, *dev = NULL; | ||
94 | struct cx25821_fh *fh; | ||
95 | struct list_head *list; | ||
96 | enum v4l2_buf_type type = 0; | ||
97 | u32 pix_format; | ||
98 | |||
99 | lock_kernel(); | ||
100 | list_for_each(list, &cx25821_devlist) | ||
101 | { | ||
102 | h = list_entry(list, struct cx25821_dev, devlist); | ||
103 | |||
104 | if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) { | ||
105 | dev = h; | ||
106 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | if (NULL == dev) { | ||
111 | unlock_kernel(); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | |||
115 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
116 | |||
117 | /* allocate + initialize per filehandle data */ | ||
118 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
119 | if (NULL == fh) { | ||
120 | unlock_kernel(); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | file->private_data = fh; | ||
124 | fh->dev = dev; | ||
125 | fh->type = type; | ||
126 | fh->width = 720; | ||
127 | |||
128 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
129 | fh->height = 576; | ||
130 | else | ||
131 | fh->height = 480; | ||
132 | |||
133 | dev->channel_opened = SRAM_CH07; | ||
134 | pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
135 | fh->fmt = format_by_fourcc(pix_format); | ||
136 | |||
137 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
138 | |||
139 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
140 | &dev->pci->dev, &dev->slock, | ||
141 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
142 | V4L2_FIELD_INTERLACED, | ||
143 | sizeof(struct cx25821_buffer), | ||
144 | fh); | ||
145 | |||
146 | dprintk(1, "post videobuf_queue_init()\n"); | ||
147 | unlock_kernel(); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
153 | { | ||
154 | struct cx25821_fh *fh = file->private_data; | ||
155 | |||
156 | switch (fh->type) | ||
157 | { | ||
158 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
159 | if (res_locked(fh->dev, RESOURCE_VIDEO7)) | ||
160 | return -EBUSY; | ||
161 | |||
162 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
163 | |||
164 | default: | ||
165 | BUG(); | ||
166 | return 0; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
171 | { | ||
172 | struct cx25821_fh *fh = file->private_data; | ||
173 | struct cx25821_buffer *buf; | ||
174 | |||
175 | if (res_check(fh, RESOURCE_VIDEO7)) { | ||
176 | /* streaming capture */ | ||
177 | if (list_empty(&fh->vidq.stream)) | ||
178 | return POLLERR; | ||
179 | buf = list_entry(fh->vidq.stream.next, | ||
180 | struct cx25821_buffer, vb.stream); | ||
181 | } else { | ||
182 | /* read() capture */ | ||
183 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
184 | if (NULL == buf) | ||
185 | return POLLERR; | ||
186 | } | ||
187 | |||
188 | poll_wait(file, &buf->vb.done, wait); | ||
189 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
190 | { | ||
191 | if( buf->vb.state == VIDEOBUF_DONE ) | ||
192 | { | ||
193 | struct cx25821_dev *dev = fh->dev; | ||
194 | |||
195 | if( dev && dev->use_cif_resolution[SRAM_CH07] ) | ||
196 | { | ||
197 | u8 cam_id = *((char*)buf->vb.baddr+3); | ||
198 | memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); | ||
199 | *((char*)buf->vb.baddr+3) = cam_id; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return POLLIN|POLLRDNORM; | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | |||
210 | static int video_release(struct file *file) | ||
211 | { | ||
212 | struct cx25821_fh *fh = file->private_data; | ||
213 | struct cx25821_dev *dev = fh->dev; | ||
214 | |||
215 | //stop the risc engine and fifo | ||
216 | cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ | ||
217 | |||
218 | /* stop video capture */ | ||
219 | if (res_check(fh, RESOURCE_VIDEO7)) { | ||
220 | videobuf_queue_cancel(&fh->vidq); | ||
221 | res_free(dev, fh, RESOURCE_VIDEO7); | ||
222 | } | ||
223 | |||
224 | if (fh->vidq.read_buf) { | ||
225 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
226 | kfree(fh->vidq.read_buf); | ||
227 | } | ||
228 | |||
229 | videobuf_mmap_free(&fh->vidq); | ||
230 | |||
231 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
232 | file->private_data = NULL; | ||
233 | kfree(fh); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | |||
239 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
240 | { | ||
241 | struct cx25821_fh *fh = priv; | ||
242 | struct cx25821_dev *dev = fh->dev; | ||
243 | |||
244 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
245 | { | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | if (unlikely(i != fh->type)) | ||
250 | { | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) | ||
255 | { | ||
256 | return -EBUSY; | ||
257 | } | ||
258 | |||
259 | return videobuf_streamon(get_queue(fh)); | ||
260 | } | ||
261 | |||
262 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
263 | { | ||
264 | struct cx25821_fh *fh = priv; | ||
265 | struct cx25821_dev *dev = fh->dev; | ||
266 | int err, res; | ||
267 | |||
268 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
269 | return -EINVAL; | ||
270 | if (i != fh->type) | ||
271 | return -EINVAL; | ||
272 | |||
273 | res = get_resource(fh, RESOURCE_VIDEO7); | ||
274 | err = videobuf_streamoff(get_queue(fh)); | ||
275 | if (err < 0) | ||
276 | return err; | ||
277 | res_free(dev, fh, res); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | |||
282 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
283 | { | ||
284 | struct cx25821_fh *fh = priv; | ||
285 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
286 | int err; | ||
287 | int pix_format = 0; | ||
288 | |||
289 | if (fh) | ||
290 | { | ||
291 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
292 | if (0 != err) | ||
293 | return err; | ||
294 | } | ||
295 | |||
296 | dprintk(2, "%s()\n", __func__); | ||
297 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
298 | |||
299 | if (0 != err) | ||
300 | return err; | ||
301 | |||
302 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
303 | fh->vidq.field = f->fmt.pix.field; | ||
304 | |||
305 | // check if width and height is valid based on set standard | ||
306 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
307 | { | ||
308 | fh->width = f->fmt.pix.width; | ||
309 | } | ||
310 | |||
311 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
312 | { | ||
313 | fh->height = f->fmt.pix.height; | ||
314 | } | ||
315 | |||
316 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
317 | pix_format = PIXEL_FRMT_411; | ||
318 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
319 | pix_format = PIXEL_FRMT_422; | ||
320 | else | ||
321 | return -EINVAL; | ||
322 | |||
323 | cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); | ||
324 | |||
325 | // check if cif resolution | ||
326 | if (fh->width == 320 || fh->width == 352) | ||
327 | { | ||
328 | dev->use_cif_resolution[SRAM_CH07] = 1; | ||
329 | }else | ||
330 | { | ||
331 | dev->use_cif_resolution[SRAM_CH07] = 0; | ||
332 | } | ||
333 | dev->cif_width[SRAM_CH07] = fh->width; | ||
334 | medusa_set_resolution( dev, fh->width, SRAM_CH07 ); | ||
335 | |||
336 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
337 | cx25821_call_all(dev, video, s_fmt, f); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
343 | { | ||
344 | int ret_val = 0; | ||
345 | struct cx25821_fh *fh = priv; | ||
346 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
347 | |||
348 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
349 | |||
350 | p->sequence = dev->vidq[SRAM_CH07].count; | ||
351 | |||
352 | return ret_val; | ||
353 | } | ||
354 | static int vidioc_log_status (struct file *file, void *priv) | ||
355 | { | ||
356 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
357 | char name[32 + 2]; | ||
358 | |||
359 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; | ||
360 | u32 tmp = 0; | ||
361 | |||
362 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
363 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
364 | dev->name); | ||
365 | cx25821_call_all(dev, core, log_status); | ||
366 | |||
367 | tmp = cx_read(sram_ch->dma_ctl); | ||
368 | printk(KERN_INFO "Video input 7 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); | ||
369 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
370 | dev->name); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
375 | struct v4l2_control *ctl) | ||
376 | { | ||
377 | struct cx25821_fh *fh = priv; | ||
378 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
379 | int err; | ||
380 | |||
381 | if (fh) { | ||
382 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
383 | if (0 != err) | ||
384 | return err; | ||
385 | } | ||
386 | |||
387 | return cx25821_set_control(dev, ctl, SRAM_CH07); | ||
388 | } | ||
389 | |||
390 | // exported stuff | ||
391 | static const struct v4l2_file_operations video_fops = { | ||
392 | .owner = THIS_MODULE, | ||
393 | .open = video_open, | ||
394 | .release = video_release, | ||
395 | .read = video_read, | ||
396 | .poll = video_poll, | ||
397 | .mmap = video_mmap, | ||
398 | .ioctl = video_ioctl2, | ||
399 | }; | ||
400 | |||
401 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
402 | .vidioc_querycap = vidioc_querycap, | ||
403 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
404 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
405 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
406 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
407 | .vidioc_reqbufs = vidioc_reqbufs, | ||
408 | .vidioc_querybuf = vidioc_querybuf, | ||
409 | .vidioc_qbuf = vidioc_qbuf, | ||
410 | .vidioc_dqbuf = vidioc_dqbuf, | ||
411 | #ifdef TUNER_FLAG | ||
412 | .vidioc_s_std = vidioc_s_std, | ||
413 | .vidioc_querystd = vidioc_querystd, | ||
414 | #endif | ||
415 | .vidioc_cropcap = vidioc_cropcap, | ||
416 | .vidioc_s_crop = vidioc_s_crop, | ||
417 | .vidioc_g_crop = vidioc_g_crop, | ||
418 | .vidioc_enum_input = vidioc_enum_input, | ||
419 | .vidioc_g_input = vidioc_g_input, | ||
420 | .vidioc_s_input = vidioc_s_input, | ||
421 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
422 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
423 | .vidioc_queryctrl = vidioc_queryctrl, | ||
424 | .vidioc_streamon = vidioc_streamon, | ||
425 | .vidioc_streamoff = vidioc_streamoff, | ||
426 | .vidioc_log_status = vidioc_log_status, | ||
427 | .vidioc_g_priority = vidioc_g_priority, | ||
428 | .vidioc_s_priority = vidioc_s_priority, | ||
429 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
430 | .vidiocgmbuf = vidiocgmbuf, | ||
431 | #endif | ||
432 | #ifdef TUNER_FLAG | ||
433 | .vidioc_g_tuner = vidioc_g_tuner, | ||
434 | .vidioc_s_tuner = vidioc_s_tuner, | ||
435 | .vidioc_g_frequency = vidioc_g_frequency, | ||
436 | .vidioc_s_frequency = vidioc_s_frequency, | ||
437 | #endif | ||
438 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
439 | .vidioc_g_register = vidioc_g_register, | ||
440 | .vidioc_s_register = vidioc_s_register, | ||
441 | #endif | ||
442 | }; | ||
443 | |||
444 | struct video_device cx25821_video_template7 = { | ||
445 | .name = "cx25821-video", | ||
446 | .fops = &video_fops, | ||
447 | .minor = -1, | ||
448 | .ioctl_ops = &video_ioctl_ops, | ||
449 | .tvnorms = CX25821_NORMS, | ||
450 | .current_norm = V4L2_STD_NTSC_M, | ||
451 | }; | ||
452 | |||
453 | |||
454 | |||
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c new file mode 100644 index 00000000000..a5363e486f7 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-videoioctl.c | |||
@@ -0,0 +1,500 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | u32 pix_format; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->ioctl_dev && h->ioctl_dev->minor == minor) | ||
106 | { | ||
107 | dev = h; | ||
108 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (NULL == dev) { | ||
113 | unlock_kernel(); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
118 | |||
119 | /* allocate + initialize per filehandle data */ | ||
120 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
121 | if (NULL == fh) { | ||
122 | unlock_kernel(); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | file->private_data = fh; | ||
127 | fh->dev = dev; | ||
128 | fh->type = type; | ||
129 | fh->width = 720; | ||
130 | |||
131 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
132 | fh->height = 576; | ||
133 | else | ||
134 | fh->height = 480; | ||
135 | |||
136 | dev->channel_opened = VIDEO_IOCTL_CH; | ||
137 | pix_format = V4L2_PIX_FMT_YUYV; | ||
138 | fh->fmt = format_by_fourcc(pix_format); | ||
139 | |||
140 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
141 | |||
142 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
143 | &dev->pci->dev, &dev->slock, | ||
144 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
145 | V4L2_FIELD_INTERLACED, | ||
146 | sizeof(struct cx25821_buffer), | ||
147 | fh); | ||
148 | |||
149 | dprintk(1, "post videobuf_queue_init()\n"); | ||
150 | unlock_kernel(); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
156 | { | ||
157 | struct cx25821_fh *fh = file->private_data; | ||
158 | |||
159 | switch (fh->type) | ||
160 | { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
166 | |||
167 | default: | ||
168 | BUG(); | ||
169 | return 0; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
174 | { | ||
175 | struct cx25821_fh *fh = file->private_data; | ||
176 | struct cx25821_buffer *buf; | ||
177 | |||
178 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | ||
179 | /* streaming capture */ | ||
180 | if (list_empty(&fh->vidq.stream)) | ||
181 | return POLLERR; | ||
182 | buf = list_entry(fh->vidq.stream.next, | ||
183 | struct cx25821_buffer, vb.stream); | ||
184 | } else { | ||
185 | /* read() capture */ | ||
186 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
187 | if (NULL == buf) | ||
188 | return POLLERR; | ||
189 | } | ||
190 | |||
191 | poll_wait(file, &buf->vb.done, wait); | ||
192 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
193 | return POLLIN|POLLRDNORM; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | |||
199 | static int video_release(struct file *file) | ||
200 | { | ||
201 | struct cx25821_fh *fh = file->private_data; | ||
202 | struct cx25821_dev *dev = fh->dev; | ||
203 | |||
204 | /* stop video capture */ | ||
205 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | ||
206 | videobuf_queue_cancel(&fh->vidq); | ||
207 | res_free(dev, fh, RESOURCE_VIDEO_IOCTL); | ||
208 | } | ||
209 | |||
210 | if (fh->vidq.read_buf) { | ||
211 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
212 | kfree(fh->vidq.read_buf); | ||
213 | } | ||
214 | |||
215 | videobuf_mmap_free(&fh->vidq); | ||
216 | |||
217 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
218 | |||
219 | file->private_data = NULL; | ||
220 | kfree(fh); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
227 | { | ||
228 | struct cx25821_fh *fh = priv; | ||
229 | struct cx25821_dev *dev = fh->dev; | ||
230 | |||
231 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
232 | { | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | if (unlikely(i != fh->type)) | ||
237 | { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) | ||
242 | { | ||
243 | return -EBUSY; | ||
244 | } | ||
245 | |||
246 | return videobuf_streamon(get_queue(fh)); | ||
247 | } | ||
248 | |||
249 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
250 | { | ||
251 | struct cx25821_fh *fh = priv; | ||
252 | struct cx25821_dev *dev = fh->dev; | ||
253 | int err, res; | ||
254 | |||
255 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
256 | return -EINVAL; | ||
257 | if (i != fh->type) | ||
258 | return -EINVAL; | ||
259 | |||
260 | res = get_resource(fh, RESOURCE_VIDEO_IOCTL); | ||
261 | err = videobuf_streamoff(get_queue(fh)); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | res_free(dev, fh, res); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | |||
269 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
270 | { | ||
271 | struct cx25821_fh *fh = priv; | ||
272 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
273 | int err; | ||
274 | |||
275 | if (fh) | ||
276 | { | ||
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
278 | if (0 != err) | ||
279 | return err; | ||
280 | } | ||
281 | |||
282 | dprintk(2, "%s()\n", __func__); | ||
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
284 | |||
285 | if (0 != err) | ||
286 | return err; | ||
287 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
288 | fh->width = f->fmt.pix.width; | ||
289 | fh->height = f->fmt.pix.height; | ||
290 | fh->vidq.field = f->fmt.pix.field; | ||
291 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
292 | cx25821_call_all(dev, video, s_fmt, f); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
297 | { | ||
298 | struct cx25821_fh *fh = priv; | ||
299 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
300 | } | ||
301 | |||
302 | static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg) | ||
303 | { | ||
304 | struct cx25821_fh *fh = file->private_data; | ||
305 | struct cx25821_dev *dev = fh->dev; | ||
306 | struct downstream_user_struct *data_from_user; | ||
307 | int command; | ||
308 | int width = 720; | ||
309 | int selected_channel = 0, pix_format = 0, i = 0; | ||
310 | int cif_enable = 0, cif_width = 0; | ||
311 | u32 value = 0; | ||
312 | |||
313 | |||
314 | data_from_user = (struct downstream_user_struct *)arg; | ||
315 | |||
316 | if( !data_from_user ) | ||
317 | { | ||
318 | printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__); | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | command = data_from_user->command; | ||
323 | |||
324 | if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION && | ||
325 | command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE) | ||
326 | { | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | |||
331 | switch(command) | ||
332 | { | ||
333 | case SET_VIDEO_STD: | ||
334 | dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
335 | medusa_set_videostandard(dev); | ||
336 | break; | ||
337 | |||
338 | case SET_PIXEL_FORMAT: | ||
339 | selected_channel = data_from_user->decoder_select; | ||
340 | pix_format = data_from_user->pixel_format; | ||
341 | |||
342 | if( !(selected_channel <= 7 && selected_channel >= 0) ) | ||
343 | { | ||
344 | selected_channel -= 4; | ||
345 | selected_channel = selected_channel % 8; | ||
346 | } | ||
347 | |||
348 | if( selected_channel >= 0 ) | ||
349 | cx25821_set_pixel_format( dev, selected_channel, pix_format ); | ||
350 | |||
351 | break; | ||
352 | |||
353 | case ENABLE_CIF_RESOLUTION: | ||
354 | selected_channel = data_from_user->decoder_select; | ||
355 | cif_enable = data_from_user->cif_resolution_enable; | ||
356 | cif_width = data_from_user->cif_width; | ||
357 | |||
358 | if( cif_enable ) | ||
359 | { | ||
360 | if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) | ||
361 | width = 352; | ||
362 | else | ||
363 | width = (cif_width == 320 || cif_width == 352) ? cif_width : 320; | ||
364 | } | ||
365 | |||
366 | if( !(selected_channel <= 7 && selected_channel >= 0) ) | ||
367 | { | ||
368 | selected_channel -= 4; | ||
369 | selected_channel = selected_channel % 8; | ||
370 | } | ||
371 | |||
372 | |||
373 | if( selected_channel <= 7 && selected_channel >= 0 ) | ||
374 | { | ||
375 | dev->use_cif_resolution[selected_channel] = cif_enable; | ||
376 | dev->cif_width[selected_channel] = width; | ||
377 | } | ||
378 | else | ||
379 | { | ||
380 | for( i=0; i < VID_CHANNEL_NUM; i++ ) | ||
381 | { | ||
382 | dev->use_cif_resolution[i] = cif_enable; | ||
383 | dev->cif_width[i] = width; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | medusa_set_resolution( dev, width, selected_channel ); | ||
388 | break; | ||
389 | case REG_READ: | ||
390 | data_from_user->reg_data = cx_read(data_from_user->reg_address); | ||
391 | break; | ||
392 | case REG_WRITE: | ||
393 | cx_write(data_from_user->reg_address, data_from_user->reg_data); | ||
394 | break; | ||
395 | case MEDUSA_READ: | ||
396 | value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data); | ||
397 | break; | ||
398 | case MEDUSA_WRITE: | ||
399 | cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data); | ||
400 | break; | ||
401 | } | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int vidioc_log_status (struct file *file, void *priv) | ||
407 | { | ||
408 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
409 | char name[32 + 2]; | ||
410 | |||
411 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
412 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
413 | dev->name); | ||
414 | cx25821_call_all(dev, core, log_status); | ||
415 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
416 | dev->name); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
421 | struct v4l2_control *ctl) | ||
422 | { | ||
423 | struct cx25821_fh *fh = priv; | ||
424 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
425 | int err; | ||
426 | |||
427 | if (fh) | ||
428 | { | ||
429 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
430 | if (0 != err) | ||
431 | return err; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | // exported stuff | ||
437 | static const struct v4l2_file_operations video_fops = { | ||
438 | .owner = THIS_MODULE, | ||
439 | .open = video_open, | ||
440 | .release = video_release, | ||
441 | .read = video_read, | ||
442 | .poll = video_poll, | ||
443 | .mmap = video_mmap, | ||
444 | .ioctl = video_ioctl_set, | ||
445 | }; | ||
446 | |||
447 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
448 | .vidioc_querycap = vidioc_querycap, | ||
449 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
450 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
451 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
452 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
453 | .vidioc_reqbufs = vidioc_reqbufs, | ||
454 | .vidioc_querybuf = vidioc_querybuf, | ||
455 | .vidioc_qbuf = vidioc_qbuf, | ||
456 | .vidioc_dqbuf = vidioc_dqbuf, | ||
457 | #ifdef TUNER_FLAG | ||
458 | .vidioc_s_std = vidioc_s_std, | ||
459 | .vidioc_querystd = vidioc_querystd, | ||
460 | #endif | ||
461 | .vidioc_cropcap = vidioc_cropcap, | ||
462 | .vidioc_s_crop = vidioc_s_crop, | ||
463 | .vidioc_g_crop = vidioc_g_crop, | ||
464 | .vidioc_enum_input = vidioc_enum_input, | ||
465 | .vidioc_g_input = vidioc_g_input, | ||
466 | .vidioc_s_input = vidioc_s_input, | ||
467 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
468 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
469 | .vidioc_queryctrl = vidioc_queryctrl, | ||
470 | .vidioc_streamon = vidioc_streamon, | ||
471 | .vidioc_streamoff = vidioc_streamoff, | ||
472 | .vidioc_log_status = vidioc_log_status, | ||
473 | .vidioc_g_priority = vidioc_g_priority, | ||
474 | .vidioc_s_priority = vidioc_s_priority, | ||
475 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
476 | .vidiocgmbuf = vidiocgmbuf, | ||
477 | #endif | ||
478 | #ifdef TUNER_FLAG | ||
479 | .vidioc_g_tuner = vidioc_g_tuner, | ||
480 | .vidioc_s_tuner = vidioc_s_tuner, | ||
481 | .vidioc_g_frequency = vidioc_g_frequency, | ||
482 | .vidioc_s_frequency = vidioc_s_frequency, | ||
483 | #endif | ||
484 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
485 | .vidioc_g_register = vidioc_g_register, | ||
486 | .vidioc_s_register = vidioc_s_register, | ||
487 | #endif | ||
488 | }; | ||
489 | |||
490 | struct video_device cx25821_videoioctl_template = { | ||
491 | .name = "cx25821-videoioctl", | ||
492 | .fops = &video_fops, | ||
493 | .minor = -1, | ||
494 | .ioctl_ops = &video_ioctl_ops, | ||
495 | .tvnorms = CX25821_NORMS, | ||
496 | .current_norm = V4L2_STD_NTSC_M, | ||
497 | }; | ||
498 | |||
499 | |||
500 | |||
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c new file mode 100644 index 00000000000..4738e9184a8 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-vidups10.c | |||
@@ -0,0 +1,443 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10]; | ||
34 | |||
35 | |||
36 | /* add jump to stopper */ | ||
37 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
38 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
39 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
40 | |||
41 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
42 | |||
43 | if (!list_empty(&q->queued)) { | ||
44 | list_add_tail(&buf->vb.queue, &q->queued); | ||
45 | buf->vb.state = VIDEOBUF_QUEUED; | ||
46 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
47 | |||
48 | } else if (list_empty(&q->active)) { | ||
49 | list_add_tail(&buf->vb.queue, &q->active); | ||
50 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]); | ||
51 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
52 | buf->count = q->count++; | ||
53 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
54 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
55 | buf, buf->vb. i, buf->count, q->count); | ||
56 | } else { | ||
57 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
58 | if (prev->vb.width == buf->vb.width && | ||
59 | prev->vb.height == buf->vb.height && | ||
60 | prev->fmt == buf->fmt) { | ||
61 | list_add_tail(&buf->vb.queue, &q->active); | ||
62 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
63 | buf->count = q->count++; | ||
64 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
65 | |||
66 | /* 64 bit bits 63-32 */ | ||
67 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
68 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
69 | |||
70 | } else { | ||
71 | list_add_tail(&buf->vb.queue, &q->queued); | ||
72 | buf->vb.state = VIDEOBUF_QUEUED; | ||
73 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (list_empty(&q->active)) | ||
78 | { | ||
79 | dprintk(2, "active queue empty!\n"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
85 | .buf_setup = buffer_setup, | ||
86 | .buf_prepare = buffer_prepare, | ||
87 | .buf_queue = buffer_queue, | ||
88 | .buf_release = buffer_release, | ||
89 | }; | ||
90 | |||
91 | |||
92 | static int video_open(struct file *file) | ||
93 | { | ||
94 | int minor = video_devdata(file)->minor; | ||
95 | struct cx25821_dev *h, *dev = NULL; | ||
96 | struct cx25821_fh *fh; | ||
97 | struct list_head *list; | ||
98 | enum v4l2_buf_type type = 0; | ||
99 | |||
100 | lock_kernel(); | ||
101 | list_for_each(list, &cx25821_devlist) | ||
102 | { | ||
103 | h = list_entry(list, struct cx25821_dev, devlist); | ||
104 | |||
105 | if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | file->private_data = fh; | ||
126 | fh->dev = dev; | ||
127 | fh->type = type; | ||
128 | fh->width = 720; | ||
129 | |||
130 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
131 | fh->height = 576; | ||
132 | else | ||
133 | fh->height = 480; | ||
134 | |||
135 | |||
136 | dev->channel_opened = 9; | ||
137 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
138 | |||
139 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
140 | |||
141 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
142 | &dev->pci->dev, &dev->slock, | ||
143 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
144 | V4L2_FIELD_INTERLACED, | ||
145 | sizeof(struct cx25821_buffer), | ||
146 | fh); | ||
147 | |||
148 | dprintk(1, "post videobuf_queue_init()\n"); | ||
149 | unlock_kernel(); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
155 | { | ||
156 | struct cx25821_fh *fh = file->private_data; | ||
157 | |||
158 | switch (fh->type) | ||
159 | { | ||
160 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
161 | if (res_locked(fh->dev, RESOURCE_VIDEO10)) | ||
162 | return -EBUSY; | ||
163 | |||
164 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
165 | |||
166 | default: | ||
167 | BUG(); | ||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
173 | { | ||
174 | struct cx25821_fh *fh = file->private_data; | ||
175 | struct cx25821_buffer *buf; | ||
176 | |||
177 | if (res_check(fh, RESOURCE_VIDEO10)) { | ||
178 | /* streaming capture */ | ||
179 | if (list_empty(&fh->vidq.stream)) | ||
180 | return POLLERR; | ||
181 | buf = list_entry(fh->vidq.stream.next, | ||
182 | struct cx25821_buffer, vb.stream); | ||
183 | } else { | ||
184 | /* read() capture */ | ||
185 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
186 | if (NULL == buf) | ||
187 | return POLLERR; | ||
188 | } | ||
189 | |||
190 | poll_wait(file, &buf->vb.done, wait); | ||
191 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
192 | return POLLIN|POLLRDNORM; | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int video_release(struct file *file) | ||
197 | { | ||
198 | struct cx25821_fh *fh = file->private_data; | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | //stop the risc engine and fifo | ||
202 | //cx_write(channel10->dma_ctl, 0); | ||
203 | |||
204 | /* stop video capture */ | ||
205 | if (res_check(fh, RESOURCE_VIDEO10)) { | ||
206 | videobuf_queue_cancel(&fh->vidq); | ||
207 | res_free(dev, fh, RESOURCE_VIDEO10); | ||
208 | } | ||
209 | |||
210 | if (fh->vidq.read_buf) { | ||
211 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
212 | kfree(fh->vidq.read_buf); | ||
213 | } | ||
214 | |||
215 | videobuf_mmap_free(&fh->vidq); | ||
216 | |||
217 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
218 | |||
219 | file->private_data = NULL; | ||
220 | kfree(fh); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
227 | { | ||
228 | struct cx25821_fh *fh = priv; | ||
229 | struct cx25821_dev *dev = fh->dev; | ||
230 | |||
231 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
232 | { | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | if (unlikely(i != fh->type)) | ||
237 | { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) | ||
242 | { | ||
243 | return -EBUSY; | ||
244 | } | ||
245 | |||
246 | return videobuf_streamon(get_queue(fh)); | ||
247 | } | ||
248 | |||
249 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
250 | { | ||
251 | struct cx25821_fh *fh = priv; | ||
252 | struct cx25821_dev *dev = fh->dev; | ||
253 | int err, res; | ||
254 | |||
255 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
256 | return -EINVAL; | ||
257 | if (i != fh->type) | ||
258 | return -EINVAL; | ||
259 | |||
260 | res = get_resource(fh, RESOURCE_VIDEO10); | ||
261 | err = videobuf_streamoff(get_queue(fh)); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | res_free(dev, fh, res); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | |||
269 | static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) | ||
270 | { | ||
271 | struct cx25821_fh *fh = file->private_data; | ||
272 | struct cx25821_dev *dev = fh->dev; | ||
273 | int command = 0; | ||
274 | struct upstream_user_struct *data_from_user; | ||
275 | |||
276 | |||
277 | data_from_user = (struct upstream_user_struct *)arg; | ||
278 | |||
279 | if( !data_from_user ) | ||
280 | { | ||
281 | printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | command = data_from_user->command; | ||
286 | |||
287 | if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) | ||
288 | { | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | dev->input_filename_ch2 = data_from_user->input_filename; | ||
293 | dev->input_audiofilename = data_from_user->input_filename; | ||
294 | dev->vid_stdname_ch2 = data_from_user->vid_stdname; | ||
295 | dev->pixel_format_ch2 = data_from_user->pixel_format; | ||
296 | dev->channel_select_ch2 = data_from_user->channel_select; | ||
297 | dev->command_ch2 = data_from_user->command; | ||
298 | |||
299 | |||
300 | switch(command) | ||
301 | { | ||
302 | case UPSTREAM_START_VIDEO: | ||
303 | cx25821_start_upstream_video_ch2(dev, data_from_user); | ||
304 | break; | ||
305 | |||
306 | case UPSTREAM_STOP_VIDEO: | ||
307 | cx25821_stop_upstream_video_ch2(dev); | ||
308 | break; | ||
309 | } | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | |||
315 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
316 | { | ||
317 | struct cx25821_fh *fh = priv; | ||
318 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
319 | int err; | ||
320 | |||
321 | if (fh) | ||
322 | { | ||
323 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
324 | if (0 != err) | ||
325 | return err; | ||
326 | } | ||
327 | |||
328 | dprintk(2, "%s()\n", __func__); | ||
329 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
330 | |||
331 | if (0 != err) | ||
332 | return err; | ||
333 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
334 | fh->width = f->fmt.pix.width; | ||
335 | fh->height = f->fmt.pix.height; | ||
336 | fh->vidq.field = f->fmt.pix.field; | ||
337 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
338 | cx25821_call_all(dev, video, s_fmt, f); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
343 | { | ||
344 | struct cx25821_fh *fh = priv; | ||
345 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
346 | } | ||
347 | |||
348 | static int vidioc_log_status (struct file *file, void *priv) | ||
349 | { | ||
350 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
351 | char name[32 + 2]; | ||
352 | |||
353 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
354 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
355 | dev->name); | ||
356 | cx25821_call_all(dev, core, log_status); | ||
357 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
358 | dev->name); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
363 | struct v4l2_control *ctl) | ||
364 | { | ||
365 | struct cx25821_fh *fh = priv; | ||
366 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
367 | int err; | ||
368 | |||
369 | if (fh) | ||
370 | { | ||
371 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
372 | if (0 != err) | ||
373 | return err; | ||
374 | } | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | //exported stuff | ||
380 | static const struct v4l2_file_operations video_fops = { | ||
381 | .owner = THIS_MODULE, | ||
382 | .open = video_open, | ||
383 | .release = video_release, | ||
384 | .read = video_read, | ||
385 | .poll = video_poll, | ||
386 | .mmap = video_mmap, | ||
387 | .ioctl = video_ioctl_upstream10, | ||
388 | }; | ||
389 | |||
390 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
391 | .vidioc_querycap = vidioc_querycap, | ||
392 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
393 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
394 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
395 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
396 | .vidioc_reqbufs = vidioc_reqbufs, | ||
397 | .vidioc_querybuf = vidioc_querybuf, | ||
398 | .vidioc_qbuf = vidioc_qbuf, | ||
399 | .vidioc_dqbuf = vidioc_dqbuf, | ||
400 | #ifdef TUNER_FLAG | ||
401 | .vidioc_s_std = vidioc_s_std, | ||
402 | .vidioc_querystd = vidioc_querystd, | ||
403 | #endif | ||
404 | .vidioc_cropcap = vidioc_cropcap, | ||
405 | .vidioc_s_crop = vidioc_s_crop, | ||
406 | .vidioc_g_crop = vidioc_g_crop, | ||
407 | .vidioc_enum_input = vidioc_enum_input, | ||
408 | .vidioc_g_input = vidioc_g_input, | ||
409 | .vidioc_s_input = vidioc_s_input, | ||
410 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
411 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
412 | .vidioc_queryctrl = vidioc_queryctrl, | ||
413 | .vidioc_streamon = vidioc_streamon, | ||
414 | .vidioc_streamoff = vidioc_streamoff, | ||
415 | .vidioc_log_status = vidioc_log_status, | ||
416 | .vidioc_g_priority = vidioc_g_priority, | ||
417 | .vidioc_s_priority = vidioc_s_priority, | ||
418 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
419 | .vidiocgmbuf = vidiocgmbuf, | ||
420 | #endif | ||
421 | #ifdef TUNER_FLAG | ||
422 | .vidioc_g_tuner = vidioc_g_tuner, | ||
423 | .vidioc_s_tuner = vidioc_s_tuner, | ||
424 | .vidioc_g_frequency = vidioc_g_frequency, | ||
425 | .vidioc_s_frequency = vidioc_s_frequency, | ||
426 | #endif | ||
427 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
428 | .vidioc_g_register = vidioc_g_register, | ||
429 | .vidioc_s_register = vidioc_s_register, | ||
430 | #endif | ||
431 | }; | ||
432 | |||
433 | struct video_device cx25821_video_template10 = { | ||
434 | .name = "cx25821-upstream10", | ||
435 | .fops = &video_fops, | ||
436 | .minor = -1, | ||
437 | .ioctl_ops = &video_ioctl_ops, | ||
438 | .tvnorms = CX25821_NORMS, | ||
439 | .current_norm = V4L2_STD_NTSC_M, | ||
440 | }; | ||
441 | |||
442 | |||
443 | |||
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c new file mode 100644 index 00000000000..7832fd1603b --- /dev/null +++ b/drivers/staging/cx25821/cx25821-vidups9.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 "cx25821-video.h" | ||
25 | |||
26 | |||
27 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
28 | { | ||
29 | struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); | ||
30 | struct cx25821_buffer *prev; | ||
31 | struct cx25821_fh *fh = vq->priv_data; | ||
32 | struct cx25821_dev *dev = fh->dev; | ||
33 | struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09]; | ||
34 | |||
35 | /* add jump to stopper */ | ||
36 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
37 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | ||
38 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
39 | |||
40 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | ||
41 | |||
42 | if (!list_empty(&q->queued)) { | ||
43 | list_add_tail(&buf->vb.queue, &q->queued); | ||
44 | buf->vb.state = VIDEOBUF_QUEUED; | ||
45 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); | ||
46 | |||
47 | } else if (list_empty(&q->active)) { | ||
48 | list_add_tail(&buf->vb.queue, &q->active); | ||
49 | cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]); | ||
50 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
51 | buf->count = q->count++; | ||
52 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
53 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
54 | buf, buf->vb. i, buf->count, q->count); | ||
55 | } else { | ||
56 | prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
57 | if (prev->vb.width == buf->vb.width && | ||
58 | prev->vb.height == buf->vb.height && | ||
59 | prev->fmt == buf->fmt) { | ||
60 | list_add_tail(&buf->vb.queue, &q->active); | ||
61 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
62 | buf->count = q->count++; | ||
63 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
64 | |||
65 | /* 64 bit bits 63-32 */ | ||
66 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
67 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); | ||
68 | |||
69 | } else { | ||
70 | list_add_tail(&buf->vb.queue, &q->queued); | ||
71 | buf->vb.state = VIDEOBUF_QUEUED; | ||
72 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (list_empty(&q->active)) | ||
77 | { | ||
78 | dprintk(2, "active queue empty!\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
84 | .buf_setup = buffer_setup, | ||
85 | .buf_prepare = buffer_prepare, | ||
86 | .buf_queue = buffer_queue, | ||
87 | .buf_release = buffer_release, | ||
88 | }; | ||
89 | |||
90 | |||
91 | static int video_open(struct file *file) | ||
92 | { | ||
93 | int minor = video_devdata(file)->minor; | ||
94 | struct cx25821_dev *h, *dev = NULL; | ||
95 | struct cx25821_fh *fh; | ||
96 | struct list_head *list; | ||
97 | enum v4l2_buf_type type = 0; | ||
98 | |||
99 | lock_kernel(); | ||
100 | list_for_each(list, &cx25821_devlist) | ||
101 | { | ||
102 | h = list_entry(list, struct cx25821_dev, devlist); | ||
103 | |||
104 | if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor) | ||
105 | { | ||
106 | dev = h; | ||
107 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (NULL == dev) { | ||
112 | unlock_kernel(); | ||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
117 | |||
118 | /* allocate + initialize per filehandle data */ | ||
119 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
120 | if (NULL == fh) { | ||
121 | unlock_kernel(); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | file->private_data = fh; | ||
126 | fh->dev = dev; | ||
127 | fh->type = type; | ||
128 | fh->width = 720; | ||
129 | |||
130 | if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
131 | fh->height = 576; | ||
132 | else | ||
133 | fh->height = 480; | ||
134 | |||
135 | dev->channel_opened = 8; | ||
136 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
137 | |||
138 | v4l2_prio_open(&dev->prio,&fh->prio); | ||
139 | |||
140 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
141 | &dev->pci->dev, &dev->slock, | ||
142 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
143 | V4L2_FIELD_INTERLACED, | ||
144 | sizeof(struct cx25821_buffer), | ||
145 | fh); | ||
146 | |||
147 | dprintk(1, "post videobuf_queue_init()\n"); | ||
148 | unlock_kernel(); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
154 | { | ||
155 | struct cx25821_fh *fh = file->private_data; | ||
156 | |||
157 | switch (fh->type) | ||
158 | { | ||
159 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
160 | if (res_locked(fh->dev, RESOURCE_VIDEO9)) | ||
161 | return -EBUSY; | ||
162 | |||
163 | return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); | ||
164 | |||
165 | default: | ||
166 | BUG(); | ||
167 | return 0; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) | ||
172 | { | ||
173 | struct cx25821_fh *fh = file->private_data; | ||
174 | struct cx25821_buffer *buf; | ||
175 | |||
176 | if (res_check(fh, RESOURCE_VIDEO9)) { | ||
177 | /* streaming capture */ | ||
178 | if (list_empty(&fh->vidq.stream)) | ||
179 | return POLLERR; | ||
180 | buf = list_entry(fh->vidq.stream.next, | ||
181 | struct cx25821_buffer, vb.stream); | ||
182 | } else { | ||
183 | /* read() capture */ | ||
184 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
185 | if (NULL == buf) | ||
186 | return POLLERR; | ||
187 | } | ||
188 | |||
189 | poll_wait(file, &buf->vb.done, wait); | ||
190 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
191 | return POLLIN|POLLRDNORM; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | |||
196 | static int video_release(struct file *file) | ||
197 | { | ||
198 | struct cx25821_fh *fh = file->private_data; | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | //stop the risc engine and fifo | ||
202 | //cx_write(channel9->dma_ctl, 0); | ||
203 | |||
204 | /* stop video capture */ | ||
205 | if (res_check(fh, RESOURCE_VIDEO9)) { | ||
206 | videobuf_queue_cancel(&fh->vidq); | ||
207 | res_free(dev, fh, RESOURCE_VIDEO9); | ||
208 | } | ||
209 | |||
210 | if (fh->vidq.read_buf) { | ||
211 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
212 | kfree(fh->vidq.read_buf); | ||
213 | } | ||
214 | |||
215 | videobuf_mmap_free(&fh->vidq); | ||
216 | |||
217 | v4l2_prio_close(&dev->prio,&fh->prio); | ||
218 | |||
219 | file->private_data = NULL; | ||
220 | kfree(fh); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
227 | { | ||
228 | struct cx25821_fh *fh = priv; | ||
229 | struct cx25821_dev *dev = fh->dev; | ||
230 | |||
231 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | ||
232 | { | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | if (unlikely(i != fh->type)) | ||
237 | { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) | ||
242 | { | ||
243 | return -EBUSY; | ||
244 | } | ||
245 | |||
246 | return videobuf_streamon(get_queue(fh)); | ||
247 | } | ||
248 | |||
249 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
250 | { | ||
251 | struct cx25821_fh *fh = priv; | ||
252 | struct cx25821_dev *dev = fh->dev; | ||
253 | int err, res; | ||
254 | |||
255 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
256 | return -EINVAL; | ||
257 | if (i != fh->type) | ||
258 | return -EINVAL; | ||
259 | |||
260 | res = get_resource(fh, RESOURCE_VIDEO9); | ||
261 | err = videobuf_streamoff(get_queue(fh)); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | res_free(dev, fh, res); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | |||
269 | static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg) | ||
270 | { | ||
271 | struct cx25821_fh *fh = file->private_data; | ||
272 | struct cx25821_dev *dev = fh->dev; | ||
273 | int command = 0; | ||
274 | struct upstream_user_struct *data_from_user; | ||
275 | |||
276 | |||
277 | data_from_user = (struct upstream_user_struct *)arg; | ||
278 | |||
279 | if( !data_from_user ) | ||
280 | { | ||
281 | printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | command = data_from_user->command; | ||
286 | |||
287 | if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) | ||
288 | { | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | |||
293 | dev->input_filename = data_from_user->input_filename; | ||
294 | dev->input_audiofilename = data_from_user->input_filename; | ||
295 | dev->vid_stdname = data_from_user->vid_stdname; | ||
296 | dev->pixel_format = data_from_user->pixel_format; | ||
297 | dev->channel_select = data_from_user->channel_select; | ||
298 | dev->command = data_from_user->command; | ||
299 | |||
300 | |||
301 | switch(command) | ||
302 | { | ||
303 | case UPSTREAM_START_VIDEO: | ||
304 | cx25821_start_upstream_video_ch1(dev, data_from_user); | ||
305 | break; | ||
306 | |||
307 | case UPSTREAM_STOP_VIDEO: | ||
308 | cx25821_stop_upstream_video_ch1(dev); | ||
309 | break; | ||
310 | } | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | |||
316 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
317 | { | ||
318 | struct cx25821_fh *fh = priv; | ||
319 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
320 | int err; | ||
321 | |||
322 | if (fh) | ||
323 | { | ||
324 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
325 | if (0 != err) | ||
326 | return err; | ||
327 | } | ||
328 | |||
329 | dprintk(2, "%s()\n", __func__); | ||
330 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
331 | |||
332 | if (0 != err) | ||
333 | return err; | ||
334 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
335 | fh->width = f->fmt.pix.width; | ||
336 | fh->height = f->fmt.pix.height; | ||
337 | fh->vidq.field = f->fmt.pix.field; | ||
338 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); | ||
339 | cx25821_call_all(dev, video, s_fmt, f); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
344 | { | ||
345 | struct cx25821_fh *fh = priv; | ||
346 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
347 | } | ||
348 | static int vidioc_log_status (struct file *file, void *priv) | ||
349 | { | ||
350 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
351 | char name[32 + 2]; | ||
352 | |||
353 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
354 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
355 | dev->name); | ||
356 | cx25821_call_all(dev, core, log_status); | ||
357 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
358 | dev->name); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
363 | struct v4l2_control *ctl) | ||
364 | { | ||
365 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
366 | struct cx25821_fh *fh = priv; | ||
367 | int err; | ||
368 | if (fh) | ||
369 | { | ||
370 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
371 | if (0 != err) | ||
372 | return err; | ||
373 | } | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | // exported stuff | ||
378 | static const struct v4l2_file_operations video_fops = { | ||
379 | .owner = THIS_MODULE, | ||
380 | .open = video_open, | ||
381 | .release = video_release, | ||
382 | .read = video_read, | ||
383 | .poll = video_poll, | ||
384 | .mmap = video_mmap, | ||
385 | .ioctl = video_ioctl_upstream9, | ||
386 | }; | ||
387 | |||
388 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
389 | .vidioc_querycap = vidioc_querycap, | ||
390 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
391 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
392 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
393 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
394 | .vidioc_reqbufs = vidioc_reqbufs, | ||
395 | .vidioc_querybuf = vidioc_querybuf, | ||
396 | .vidioc_qbuf = vidioc_qbuf, | ||
397 | .vidioc_dqbuf = vidioc_dqbuf, | ||
398 | #ifdef TUNER_FLAG | ||
399 | .vidioc_s_std = vidioc_s_std, | ||
400 | .vidioc_querystd = vidioc_querystd, | ||
401 | #endif | ||
402 | .vidioc_cropcap = vidioc_cropcap, | ||
403 | .vidioc_s_crop = vidioc_s_crop, | ||
404 | .vidioc_g_crop = vidioc_g_crop, | ||
405 | .vidioc_enum_input = vidioc_enum_input, | ||
406 | .vidioc_g_input = vidioc_g_input, | ||
407 | .vidioc_s_input = vidioc_s_input, | ||
408 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
409 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
410 | .vidioc_queryctrl = vidioc_queryctrl, | ||
411 | .vidioc_streamon = vidioc_streamon, | ||
412 | .vidioc_streamoff = vidioc_streamoff, | ||
413 | .vidioc_log_status = vidioc_log_status, | ||
414 | .vidioc_g_priority = vidioc_g_priority, | ||
415 | .vidioc_s_priority = vidioc_s_priority, | ||
416 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
417 | .vidiocgmbuf = vidiocgmbuf, | ||
418 | #endif | ||
419 | #ifdef TUNER_FLAG | ||
420 | .vidioc_g_tuner = vidioc_g_tuner, | ||
421 | .vidioc_s_tuner = vidioc_s_tuner, | ||
422 | .vidioc_g_frequency = vidioc_g_frequency, | ||
423 | .vidioc_s_frequency = vidioc_s_frequency, | ||
424 | #endif | ||
425 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
426 | .vidioc_g_register = vidioc_g_register, | ||
427 | .vidioc_s_register = vidioc_s_register, | ||
428 | #endif | ||
429 | }; | ||
430 | |||
431 | struct video_device cx25821_video_template9 = { | ||
432 | .name = "cx25821-upstream9", | ||
433 | .fops = &video_fops, | ||
434 | .minor = -1, | ||
435 | .ioctl_ops = &video_ioctl_ops, | ||
436 | .tvnorms = CX25821_NORMS, | ||
437 | .current_norm = V4L2_STD_NTSC_M, | ||
438 | }; | ||
439 | |||
440 | |||
441 | |||
diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h new file mode 100644 index 00000000000..074ea34c3b2 --- /dev/null +++ b/drivers/staging/cx25821/cx25821.h | |||
@@ -0,0 +1,589 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * 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 | |||
25 | #ifndef CX25821_H_ | ||
26 | #define CX25821_H_ | ||
27 | |||
28 | #include <linux/pci.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/i2c-algo-bit.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/kdev_t.h> | ||
35 | |||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/v4l2-device.h> | ||
38 | #include <media/tuner.h> | ||
39 | #include <media/tveeprom.h> | ||
40 | #include <media/videobuf-dma-sg.h> | ||
41 | #include <media/videobuf-dvb.h> | ||
42 | |||
43 | #include "btcx-risc.h" | ||
44 | #include "cx25821-reg.h" | ||
45 | #include "cx25821-medusa-reg.h" | ||
46 | #include "cx25821-sram.h" | ||
47 | #include "cx25821-audio.h" | ||
48 | #include "media/cx2341x.h" | ||
49 | |||
50 | #include <linux/version.h> | ||
51 | #include <linux/mutex.h> | ||
52 | |||
53 | #define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106) | ||
54 | |||
55 | #define UNSET (-1U) | ||
56 | #define NO_SYNC_LINE (-1U) | ||
57 | |||
58 | #define CX25821_MAXBOARDS 2 | ||
59 | |||
60 | #define TRUE 1 | ||
61 | #define FALSE 0 | ||
62 | #define LINE_SIZE_D1 1440 | ||
63 | |||
64 | // Number of decoders and encoders | ||
65 | #define MAX_DECODERS 8 | ||
66 | #define MAX_ENCODERS 2 | ||
67 | #define QUAD_DECODERS 4 | ||
68 | #define MAX_CAMERAS 16 | ||
69 | |||
70 | /* Max number of inputs by card */ | ||
71 | #define MAX_CX25821_INPUT 8 | ||
72 | #define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) | ||
73 | #define RESOURCE_VIDEO0 1 | ||
74 | #define RESOURCE_VIDEO1 2 | ||
75 | #define RESOURCE_VIDEO2 4 | ||
76 | #define RESOURCE_VIDEO3 8 | ||
77 | #define RESOURCE_VIDEO4 16 | ||
78 | #define RESOURCE_VIDEO5 32 | ||
79 | #define RESOURCE_VIDEO6 64 | ||
80 | #define RESOURCE_VIDEO7 128 | ||
81 | #define RESOURCE_VIDEO8 256 | ||
82 | #define RESOURCE_VIDEO9 512 | ||
83 | #define RESOURCE_VIDEO10 1024 | ||
84 | #define RESOURCE_VIDEO11 2048 | ||
85 | #define RESOURCE_VIDEO_IOCTL 4096 | ||
86 | |||
87 | |||
88 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ | ||
89 | |||
90 | #define UNKNOWN_BOARD 0 | ||
91 | #define CX25821_BOARD 1 | ||
92 | |||
93 | /* Currently supported by the driver */ | ||
94 | #define CX25821_NORMS (\ | ||
95 | V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ | ||
96 | V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ | ||
97 | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \ | ||
98 | V4L2_STD_PAL_Nc ) | ||
99 | |||
100 | #define CX25821_BOARD_CONEXANT_ATHENA10 1 | ||
101 | #define MAX_VID_CHANNEL_NUM 12 | ||
102 | #define VID_CHANNEL_NUM 8 | ||
103 | |||
104 | struct cx25821_fmt { | ||
105 | char *name; | ||
106 | u32 fourcc; /* v4l2 format id */ | ||
107 | int depth; | ||
108 | int flags; | ||
109 | u32 cxformat; | ||
110 | }; | ||
111 | |||
112 | struct cx25821_ctrl { | ||
113 | struct v4l2_queryctrl v; | ||
114 | u32 off; | ||
115 | u32 reg; | ||
116 | u32 mask; | ||
117 | u32 shift; | ||
118 | }; | ||
119 | |||
120 | struct cx25821_tvnorm { | ||
121 | char *name; | ||
122 | v4l2_std_id id; | ||
123 | u32 cxiformat; | ||
124 | u32 cxoformat; | ||
125 | }; | ||
126 | |||
127 | struct cx25821_fh { | ||
128 | struct cx25821_dev *dev; | ||
129 | enum v4l2_buf_type type; | ||
130 | int radio; | ||
131 | u32 resources; | ||
132 | |||
133 | enum v4l2_priority prio; | ||
134 | |||
135 | /* video overlay */ | ||
136 | struct v4l2_window win; | ||
137 | struct v4l2_clip *clips; | ||
138 | unsigned int nclips; | ||
139 | |||
140 | /* video capture */ | ||
141 | struct cx25821_fmt *fmt; | ||
142 | unsigned int width, height; | ||
143 | |||
144 | /* vbi capture */ | ||
145 | struct videobuf_queue vidq; | ||
146 | struct videobuf_queue vbiq; | ||
147 | |||
148 | /* H264 Encoder specifics ONLY */ | ||
149 | struct videobuf_queue mpegq; | ||
150 | atomic_t v4l_reading; | ||
151 | }; | ||
152 | |||
153 | enum cx25821_itype { | ||
154 | CX25821_VMUX_COMPOSITE = 1, | ||
155 | CX25821_VMUX_SVIDEO, | ||
156 | CX25821_VMUX_DEBUG, | ||
157 | CX25821_RADIO, | ||
158 | }; | ||
159 | |||
160 | enum cx25821_src_sel_type { | ||
161 | CX25821_SRC_SEL_EXT_656_VIDEO = 0, | ||
162 | CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO | ||
163 | }; | ||
164 | |||
165 | /* buffer for one video frame */ | ||
166 | struct cx25821_buffer { | ||
167 | /* common v4l buffer stuff -- must be first */ | ||
168 | struct videobuf_buffer vb; | ||
169 | |||
170 | /* cx25821 specific */ | ||
171 | unsigned int bpl; | ||
172 | struct btcx_riscmem risc; | ||
173 | struct cx25821_fmt *fmt; | ||
174 | u32 count; | ||
175 | }; | ||
176 | |||
177 | struct cx25821_input { | ||
178 | enum cx25821_itype type; | ||
179 | unsigned int vmux; | ||
180 | u32 gpio0, gpio1, gpio2, gpio3; | ||
181 | }; | ||
182 | |||
183 | typedef enum { | ||
184 | CX25821_UNDEFINED = 0, | ||
185 | CX25821_RAW, | ||
186 | CX25821_264 | ||
187 | } port_t; | ||
188 | |||
189 | struct cx25821_board { | ||
190 | char *name; | ||
191 | port_t porta, portb, portc; | ||
192 | unsigned int tuner_type; | ||
193 | unsigned int radio_type; | ||
194 | unsigned char tuner_addr; | ||
195 | unsigned char radio_addr; | ||
196 | |||
197 | u32 clk_freq; | ||
198 | struct cx25821_input input[2]; | ||
199 | }; | ||
200 | |||
201 | struct cx25821_subid { | ||
202 | u16 subvendor; | ||
203 | u16 subdevice; | ||
204 | u32 card; | ||
205 | }; | ||
206 | |||
207 | struct cx25821_i2c { | ||
208 | struct cx25821_dev *dev; | ||
209 | |||
210 | int nr; | ||
211 | |||
212 | /* i2c i/o */ | ||
213 | struct i2c_adapter i2c_adap; | ||
214 | struct i2c_algo_bit_data i2c_algo; | ||
215 | struct i2c_client i2c_client; | ||
216 | u32 i2c_rc; | ||
217 | |||
218 | /* cx25821 registers used for raw addess */ | ||
219 | u32 i2c_period; | ||
220 | u32 reg_ctrl; | ||
221 | u32 reg_stat; | ||
222 | u32 reg_addr; | ||
223 | u32 reg_rdata; | ||
224 | u32 reg_wdata; | ||
225 | }; | ||
226 | |||
227 | struct cx25821_dmaqueue { | ||
228 | struct list_head active; | ||
229 | struct list_head queued; | ||
230 | struct timer_list timeout; | ||
231 | struct btcx_riscmem stopper; | ||
232 | u32 count; | ||
233 | }; | ||
234 | |||
235 | struct cx25821_data { | ||
236 | struct cx25821_dev *dev; | ||
237 | struct sram_channel *channel; | ||
238 | }; | ||
239 | |||
240 | struct cx25821_dev { | ||
241 | struct list_head devlist; | ||
242 | atomic_t refcount; | ||
243 | struct v4l2_device v4l2_dev; | ||
244 | |||
245 | struct v4l2_prio_state prio; | ||
246 | |||
247 | /* pci stuff */ | ||
248 | struct pci_dev *pci; | ||
249 | unsigned char pci_rev, pci_lat; | ||
250 | int pci_bus, pci_slot; | ||
251 | u32 base_io_addr; | ||
252 | u32 __iomem *lmmio; | ||
253 | u8 __iomem *bmmio; | ||
254 | int pci_irqmask; | ||
255 | int hwrevision; | ||
256 | |||
257 | u32 clk_freq; | ||
258 | |||
259 | /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ | ||
260 | struct cx25821_i2c i2c_bus[3]; | ||
261 | |||
262 | int nr; | ||
263 | struct mutex lock; | ||
264 | |||
265 | /* board details */ | ||
266 | unsigned int board; | ||
267 | char name[32]; | ||
268 | |||
269 | /* sram configuration */ | ||
270 | struct sram_channel *sram_channels; | ||
271 | |||
272 | /* Analog video */ | ||
273 | u32 resources; | ||
274 | unsigned int input; | ||
275 | u32 tvaudio; | ||
276 | v4l2_std_id tvnorm; | ||
277 | unsigned int tuner_type; | ||
278 | unsigned char tuner_addr; | ||
279 | unsigned int radio_type; | ||
280 | unsigned char radio_addr; | ||
281 | unsigned int has_radio; | ||
282 | unsigned int videc_type; | ||
283 | unsigned char videc_addr; | ||
284 | unsigned short _max_num_decoders; | ||
285 | |||
286 | int ctl_bright; | ||
287 | int ctl_contrast; | ||
288 | int ctl_hue; | ||
289 | int ctl_saturation; | ||
290 | |||
291 | struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | ||
292 | |||
293 | /* Analog Audio Upstream */ | ||
294 | int _audio_is_running; | ||
295 | int _audiopixel_format; | ||
296 | int _is_first_audio_frame; | ||
297 | int _audiofile_status; | ||
298 | int _audio_lines_count; | ||
299 | int _audioframe_count; | ||
300 | int _audio_upstream_channel_select; | ||
301 | int _last_index_irq; //The last interrupt index processed. | ||
302 | |||
303 | __le32 * _risc_audio_jmp_addr; | ||
304 | __le32 * _risc_virt_start_addr; | ||
305 | __le32 * _risc_virt_addr; | ||
306 | dma_addr_t _risc_phys_addr; | ||
307 | dma_addr_t _risc_phys_start_addr; | ||
308 | |||
309 | unsigned int _audiorisc_size; | ||
310 | unsigned int _audiodata_buf_size; | ||
311 | __le32 * _audiodata_buf_virt_addr; | ||
312 | dma_addr_t _audiodata_buf_phys_addr; | ||
313 | char *_audiofilename; | ||
314 | |||
315 | /* V4l */ | ||
316 | u32 freq; | ||
317 | struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; | ||
318 | struct video_device *vbi_dev; | ||
319 | struct video_device *radio_dev; | ||
320 | struct video_device *ioctl_dev; | ||
321 | |||
322 | struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; | ||
323 | spinlock_t slock; | ||
324 | |||
325 | /* Video Upstream */ | ||
326 | int _line_size; | ||
327 | int _prog_cnt; | ||
328 | int _pixel_format; | ||
329 | int _is_first_frame; | ||
330 | int _is_running; | ||
331 | int _file_status; | ||
332 | int _lines_count; | ||
333 | int _frame_count; | ||
334 | int _channel_upstream_select; | ||
335 | unsigned int _risc_size; | ||
336 | |||
337 | __le32 * _dma_virt_start_addr; | ||
338 | __le32 * _dma_virt_addr; | ||
339 | dma_addr_t _dma_phys_addr; | ||
340 | dma_addr_t _dma_phys_start_addr; | ||
341 | |||
342 | unsigned int _data_buf_size; | ||
343 | __le32 * _data_buf_virt_addr; | ||
344 | dma_addr_t _data_buf_phys_addr; | ||
345 | char * _filename; | ||
346 | char * _defaultname; | ||
347 | |||
348 | |||
349 | int _line_size_ch2; | ||
350 | int _prog_cnt_ch2; | ||
351 | int _pixel_format_ch2; | ||
352 | int _is_first_frame_ch2; | ||
353 | int _is_running_ch2; | ||
354 | int _file_status_ch2; | ||
355 | int _lines_count_ch2; | ||
356 | int _frame_count_ch2; | ||
357 | int _channel2_upstream_select; | ||
358 | unsigned int _risc_size_ch2; | ||
359 | |||
360 | __le32 * _dma_virt_start_addr_ch2; | ||
361 | __le32 * _dma_virt_addr_ch2; | ||
362 | dma_addr_t _dma_phys_addr_ch2; | ||
363 | dma_addr_t _dma_phys_start_addr_ch2; | ||
364 | |||
365 | unsigned int _data_buf_size_ch2; | ||
366 | __le32 * _data_buf_virt_addr_ch2; | ||
367 | dma_addr_t _data_buf_phys_addr_ch2; | ||
368 | char * _filename_ch2; | ||
369 | char * _defaultname_ch2; | ||
370 | |||
371 | /* MPEG Encoder ONLY settings */ | ||
372 | u32 cx23417_mailbox; | ||
373 | struct cx2341x_mpeg_params mpeg_params; | ||
374 | struct video_device *v4l_device; | ||
375 | atomic_t v4l_reader_count; | ||
376 | struct cx25821_tvnorm encodernorm; | ||
377 | |||
378 | u32 upstream_riscbuf_size; | ||
379 | u32 upstream_databuf_size; | ||
380 | u32 upstream_riscbuf_size_ch2; | ||
381 | u32 upstream_databuf_size_ch2; | ||
382 | u32 audio_upstream_riscbuf_size; | ||
383 | u32 audio_upstream_databuf_size; | ||
384 | int _isNTSC; | ||
385 | int _frame_index; | ||
386 | int _audioframe_index; | ||
387 | struct workqueue_struct * _irq_queues; | ||
388 | struct work_struct _irq_work_entry; | ||
389 | struct workqueue_struct * _irq_queues_ch2; | ||
390 | struct work_struct _irq_work_entry_ch2; | ||
391 | struct workqueue_struct * _irq_audio_queues; | ||
392 | struct work_struct _audio_work_entry; | ||
393 | char *input_filename; | ||
394 | char *input_filename_ch2; | ||
395 | int _frame_index_ch2; | ||
396 | int _isNTSC_ch2; | ||
397 | char *vid_stdname_ch2; | ||
398 | int pixel_format_ch2; | ||
399 | int channel_select_ch2; | ||
400 | int command_ch2; | ||
401 | char *input_audiofilename; | ||
402 | char *vid_stdname; | ||
403 | int pixel_format; | ||
404 | int channel_select; | ||
405 | int command; | ||
406 | int pixel_formats[VID_CHANNEL_NUM]; | ||
407 | int use_cif_resolution[VID_CHANNEL_NUM]; | ||
408 | int cif_width[VID_CHANNEL_NUM]; | ||
409 | int channel_opened; | ||
410 | }; | ||
411 | |||
412 | |||
413 | struct upstream_user_struct { | ||
414 | char *input_filename; | ||
415 | char *vid_stdname; | ||
416 | int pixel_format; | ||
417 | int channel_select; | ||
418 | int command; | ||
419 | }; | ||
420 | |||
421 | struct downstream_user_struct { | ||
422 | char *vid_stdname; | ||
423 | int pixel_format; | ||
424 | int cif_resolution_enable; | ||
425 | int cif_width; | ||
426 | int decoder_select; | ||
427 | int command; | ||
428 | int reg_address; | ||
429 | int reg_data; | ||
430 | }; | ||
431 | |||
432 | extern struct upstream_user_struct *up_data; | ||
433 | |||
434 | static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) | ||
435 | { | ||
436 | return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); | ||
437 | } | ||
438 | |||
439 | #define cx25821_call_all(dev, o, f, args...) \ | ||
440 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) | ||
441 | |||
442 | extern struct list_head cx25821_devlist; | ||
443 | extern struct cx25821_board cx25821_boards[]; | ||
444 | extern struct cx25821_subid cx25821_subids[]; | ||
445 | |||
446 | #define SRAM_CH00 0 /* Video A */ | ||
447 | #define SRAM_CH01 1 /* Video B */ | ||
448 | #define SRAM_CH02 2 /* Video C */ | ||
449 | #define SRAM_CH03 3 /* Video D */ | ||
450 | #define SRAM_CH04 4 /* Video E */ | ||
451 | #define SRAM_CH05 5 /* Video F */ | ||
452 | #define SRAM_CH06 6 /* Video G */ | ||
453 | #define SRAM_CH07 7 /* Video H */ | ||
454 | |||
455 | #define SRAM_CH08 8 /* Audio A */ | ||
456 | #define SRAM_CH09 9 /* Video Upstream I */ | ||
457 | #define SRAM_CH10 10 /* Video Upstream J */ | ||
458 | #define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */ | ||
459 | |||
460 | |||
461 | |||
462 | #define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 | ||
463 | #define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 | ||
464 | #define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11 | ||
465 | #define VIDEO_IOCTL_CH 11 | ||
466 | |||
467 | struct sram_channel { | ||
468 | char *name; | ||
469 | u32 i; | ||
470 | u32 cmds_start; | ||
471 | u32 ctrl_start; | ||
472 | u32 cdt; | ||
473 | u32 fifo_start; | ||
474 | u32 fifo_size; | ||
475 | u32 ptr1_reg; | ||
476 | u32 ptr2_reg; | ||
477 | u32 cnt1_reg; | ||
478 | u32 cnt2_reg; | ||
479 | u32 int_msk; | ||
480 | u32 int_stat; | ||
481 | u32 int_mstat; | ||
482 | u32 dma_ctl; | ||
483 | u32 gpcnt_ctl; | ||
484 | u32 gpcnt; | ||
485 | u32 aud_length; | ||
486 | u32 aud_cfg; | ||
487 | u32 fld_aud_fifo_en; | ||
488 | u32 fld_aud_risc_en; | ||
489 | |||
490 | //For Upstream Video | ||
491 | u32 vid_fmt_ctl; | ||
492 | u32 vid_active_ctl1; | ||
493 | u32 vid_active_ctl2; | ||
494 | u32 vid_cdt_size; | ||
495 | |||
496 | u32 vip_ctl; | ||
497 | u32 pix_frmt; | ||
498 | u32 jumponly; | ||
499 | u32 irq_bit; | ||
500 | }; | ||
501 | extern struct sram_channel cx25821_sram_channels[]; | ||
502 | |||
503 | #define STATUS_SUCCESS 0 | ||
504 | #define STATUS_UNSUCCESSFUL -1 | ||
505 | |||
506 | #define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) | ||
507 | #define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) | ||
508 | |||
509 | #define cx_andor(reg, mask, value) \ | ||
510 | writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ | ||
511 | ((value) & (mask)), dev->lmmio+((reg)>>2)) | ||
512 | |||
513 | #define cx_set(reg, bit) cx_andor((reg), (bit), (bit)) | ||
514 | #define cx_clear(reg, bit) cx_andor((reg), (bit), 0) | ||
515 | |||
516 | #define Set_GPIO_Bit(Bit) (1 << Bit) | ||
517 | #define Clear_GPIO_Bit(Bit) (~(1 << Bit)) | ||
518 | |||
519 | #define CX25821_ERR(fmt, args...) printk(KERN_ERR "cx25821(%d): " fmt, dev->board, ## args) | ||
520 | #define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args) | ||
521 | #define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args) | ||
522 | |||
523 | extern int cx25821_i2c_register(struct cx25821_i2c *bus); | ||
524 | extern void cx25821_card_setup(struct cx25821_dev *dev); | ||
525 | extern int cx25821_ir_init(struct cx25821_dev *dev); | ||
526 | extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); | ||
527 | extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); | ||
528 | extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); | ||
529 | extern void cx25821_gpio_init(struct cx25821_dev *dev); | ||
530 | extern void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, | ||
531 | int pin_number, | ||
532 | int pin_logic_value); | ||
533 | |||
534 | extern int medusa_video_init(struct cx25821_dev *dev); | ||
535 | extern int medusa_set_videostandard(struct cx25821_dev *dev); | ||
536 | extern void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select); | ||
537 | extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder); | ||
538 | extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder); | ||
539 | extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder); | ||
540 | extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder); | ||
541 | |||
542 | extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); | ||
543 | |||
544 | extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
545 | struct scatterlist *sglist, | ||
546 | unsigned int top_offset, | ||
547 | unsigned int bottom_offset, | ||
548 | unsigned int bpl, | ||
549 | unsigned int padding, | ||
550 | unsigned int lines); | ||
551 | extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, | ||
552 | struct btcx_riscmem *risc, | ||
553 | struct scatterlist *sglist, | ||
554 | unsigned int bpl, | ||
555 | unsigned int lines, | ||
556 | unsigned int lpi); | ||
557 | extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf); | ||
558 | extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value); | ||
559 | extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch); | ||
560 | extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch); | ||
561 | |||
562 | |||
563 | extern struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci); | ||
564 | extern void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask); | ||
565 | extern void cx25821_dev_unregister(struct cx25821_dev *dev); | ||
566 | extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | ||
567 | struct sram_channel *ch, | ||
568 | unsigned int bpl, u32 risc); | ||
569 | |||
570 | extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format); | ||
571 | extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format); | ||
572 | extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select); | ||
573 | extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); | ||
574 | extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); | ||
575 | extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); | ||
576 | extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data); | ||
577 | extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data); | ||
578 | extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data); | ||
579 | extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); | ||
580 | extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); | ||
581 | extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); | ||
582 | extern int cx25821_sram_channel_setup_upstream( struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); | ||
583 | extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format); | ||
584 | extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); | ||
585 | extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
586 | struct pci_dev *pci, | ||
587 | struct video_device *template, | ||
588 | char *type); | ||
589 | #endif | ||