diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:03:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:03:10 -0400 |
commit | c720f5655df159a630fa0290a0bd67c93e92b0bf (patch) | |
tree | 940d139d0ec1ff5201efddef6cc663166a8a2df3 /drivers/staging | |
parent | 33e6c1a0de818d3698cdab27c42915661011319d (diff) | |
parent | 84d6ae431f315e8973aac3c3fe1d550fc9240ef3 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (222 commits)
V4L/DVB (13033): pt1: Don't use a deprecated DMA_BIT_MASK macro
V4L/DVB (13029): radio-si4713: remove #include <linux/version.h>
V4L/DVB (13027): go7007: convert printks to v4l2_info
V4L/DVB (13026): s2250-board: Implement brightness and contrast controls
V4L/DVB (13025): s2250-board: Fix memory leaks
V4L/DVB (13024): go7007: Implement vidioc_g_std and vidioc_querystd
V4L/DVB (13023): go7007: Merge struct gofh and go declarations
V4L/DVB (13022): go7007: Fix mpeg controls
V4L/DVB (13021): go7007: Fix whitespace and line lengths
V4L/DVB (13020): go7007: Updates to Kconfig and Makefile
V4L/DVB (13019): video: initial support for ADV7180
V4L/DVB (13018): kzalloc failure ignored in au8522_probe()
V4L/DVB (13017): gspca: kmalloc failure ignored in sd_start()
V4L/DVB (13016): kmalloc failure ignored in lgdt3304_attach() and s921_attach()
V4L/DVB (13015): kmalloc failure ignored in m920x_firmware_download()
V4L/DVB (13014): Add support for Compro VideoMate E800 (DVB-T part only)
V4L/DVB (13013): FM TX: si4713: Kconfig: Fixed two typos.
V4L/DVB (13012): uvc: introduce missing kfree
V4L/DVB (13011): Change tuner type of BeholdTV cards
V4L/DVB (13009): gspca - stv06xx-hdcs: Reduce exposure range
...
Diffstat (limited to 'drivers/staging')
53 files changed, 17103 insertions, 298 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 10d3fcffe91c..82b34893e5b5 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -47,6 +47,8 @@ source "drivers/staging/slicoss/Kconfig" | |||
47 | 47 | ||
48 | source "drivers/staging/go7007/Kconfig" | 48 | source "drivers/staging/go7007/Kconfig" |
49 | 49 | ||
50 | source "drivers/staging/cx25821/Kconfig" | ||
51 | |||
50 | source "drivers/staging/usbip/Kconfig" | 52 | source "drivers/staging/usbip/Kconfig" |
51 | 53 | ||
52 | source "drivers/staging/winbond/Kconfig" | 54 | source "drivers/staging/winbond/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c30093bae621..b1cad0d9ba72 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_STAGING) += staging.o | |||
6 | obj-$(CONFIG_ET131X) += et131x/ | 6 | obj-$(CONFIG_ET131X) += et131x/ |
7 | obj-$(CONFIG_SLICOSS) += slicoss/ | 7 | obj-$(CONFIG_SLICOSS) += slicoss/ |
8 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | 8 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
9 | obj-$(CONFIG_VIDEO_CX25821) += cx25821/ | ||
9 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ | 10 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ |
10 | obj-$(CONFIG_W35UND) += winbond/ | 11 | obj-$(CONFIG_W35UND) += winbond/ |
11 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ | 12 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ |
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig new file mode 100644 index 000000000000..df7756a95fad --- /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 000000000000..10f87f05d8e8 --- /dev/null +++ b/drivers/staging/cx25821/Makefile | |||
@@ -0,0 +1,14 @@ | |||
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/common/tuners | ||
13 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
14 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
diff --git a/drivers/staging/cx25821/README b/drivers/staging/cx25821/README new file mode 100644 index 000000000000..a9ba50b9888b --- /dev/null +++ b/drivers/staging/cx25821/README | |||
@@ -0,0 +1,6 @@ | |||
1 | Todo: | ||
2 | - checkpatch.pl cleanups | ||
3 | - sparse cleanups | ||
4 | |||
5 | Please send patches to linux-media@vger.kernel.org | ||
6 | |||
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c new file mode 100644 index 000000000000..e0eef12759e4 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-alsa.c | |||
@@ -0,0 +1,789 @@ | |||
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 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/pci.h> | ||
30 | |||
31 | #include <asm/delay.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | #include <sound/pcm_params.h> | ||
35 | #include <sound/control.h> | ||
36 | #include <sound/initval.h> | ||
37 | #include <sound/tlv.h> | ||
38 | |||
39 | #include "cx25821.h" | ||
40 | #include "cx25821-reg.h" | ||
41 | |||
42 | #define AUDIO_SRAM_CHANNEL SRAM_CH08 | ||
43 | |||
44 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
45 | printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) | ||
46 | |||
47 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ | ||
48 | printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) | ||
49 | |||
50 | /**************************************************************************** | ||
51 | Data type declarations - Can be moded to a header file later | ||
52 | ****************************************************************************/ | ||
53 | |||
54 | static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; | ||
55 | static int devno; | ||
56 | |||
57 | struct cx25821_audio_dev { | ||
58 | struct cx25821_dev *dev; | ||
59 | struct cx25821_dmaqueue q; | ||
60 | |||
61 | /* pci i/o */ | ||
62 | struct pci_dev *pci; | ||
63 | |||
64 | /* audio controls */ | ||
65 | int irq; | ||
66 | |||
67 | struct snd_card *card; | ||
68 | |||
69 | unsigned long iobase; | ||
70 | spinlock_t reg_lock; | ||
71 | atomic_t count; | ||
72 | |||
73 | unsigned int dma_size; | ||
74 | unsigned int period_size; | ||
75 | unsigned int num_periods; | ||
76 | |||
77 | struct videobuf_dmabuf *dma_risc; | ||
78 | |||
79 | struct cx25821_buffer *buf; | ||
80 | |||
81 | struct snd_pcm_substream *substream; | ||
82 | }; | ||
83 | typedef struct cx25821_audio_dev snd_cx25821_card_t; | ||
84 | |||
85 | |||
86 | /**************************************************************************** | ||
87 | Module global static vars | ||
88 | ****************************************************************************/ | ||
89 | |||
90 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
91 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
92 | static int enable[SNDRV_CARDS] = { 1,[1 ... (SNDRV_CARDS - 1)] = 1 }; | ||
93 | |||
94 | module_param_array(enable, bool, NULL, 0444); | ||
95 | MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); | ||
96 | |||
97 | module_param_array(index, int, NULL, 0444); | ||
98 | MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); | ||
99 | |||
100 | /**************************************************************************** | ||
101 | Module macros | ||
102 | ****************************************************************************/ | ||
103 | |||
104 | MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); | ||
105 | MODULE_AUTHOR("Hiep Huynh"); | ||
106 | MODULE_LICENSE("GPL"); | ||
107 | MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); //"{{Conexant,23881}," | ||
108 | |||
109 | static unsigned int debug; | ||
110 | module_param(debug, int, 0644); | ||
111 | MODULE_PARM_DESC(debug, "enable debug messages"); | ||
112 | |||
113 | /**************************************************************************** | ||
114 | Module specific funtions | ||
115 | ****************************************************************************/ | ||
116 | /* Constants taken from cx88-reg.h */ | ||
117 | #define AUD_INT_DN_RISCI1 (1 << 0) | ||
118 | #define AUD_INT_UP_RISCI1 (1 << 1) | ||
119 | #define AUD_INT_RDS_DN_RISCI1 (1 << 2) | ||
120 | #define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ | ||
121 | #define AUD_INT_UP_RISCI2 (1 << 5) | ||
122 | #define AUD_INT_RDS_DN_RISCI2 (1 << 6) | ||
123 | #define AUD_INT_DN_SYNC (1 << 12) | ||
124 | #define AUD_INT_UP_SYNC (1 << 13) | ||
125 | #define AUD_INT_RDS_DN_SYNC (1 << 14) | ||
126 | #define AUD_INT_OPC_ERR (1 << 16) | ||
127 | #define AUD_INT_BER_IRQ (1 << 20) | ||
128 | #define AUD_INT_MCHG_IRQ (1 << 21) | ||
129 | #define GP_COUNT_CONTROL_RESET 0x3 | ||
130 | |||
131 | #define PCI_MSK_AUD_EXT (1 << 4) | ||
132 | #define PCI_MSK_AUD_INT (1 << 3) | ||
133 | /* | ||
134 | * BOARD Specific: Sets audio DMA | ||
135 | */ | ||
136 | |||
137 | static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | ||
138 | { | ||
139 | struct cx25821_buffer *buf = chip->buf; | ||
140 | struct cx25821_dev *dev = chip->dev; | ||
141 | struct sram_channel *audio_ch = | ||
142 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; | ||
143 | u32 tmp = 0; | ||
144 | |||
145 | // enable output on the GPIO 0 for the MCLK ADC (Audio) | ||
146 | cx25821_set_gpiopin_direction(chip->dev, 0, 0); | ||
147 | |||
148 | /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ | ||
149 | cx_clear(AUD_INT_DMA_CTL, | ||
150 | FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); | ||
151 | |||
152 | /* setup fifo + format - out channel */ | ||
153 | cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, | ||
154 | buf->risc.dma); | ||
155 | |||
156 | /* sets bpl size */ | ||
157 | cx_write(AUD_A_LNGTH, buf->bpl); | ||
158 | |||
159 | /* reset counter */ | ||
160 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 | ||
161 | atomic_set(&chip->count, 0); | ||
162 | |||
163 | //Set the input mode to 16-bit | ||
164 | tmp = cx_read(AUD_A_CFG); | ||
165 | cx_write(AUD_A_CFG, | ||
166 | tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | | ||
167 | FLD_AUD_CLK_ENABLE); | ||
168 | |||
169 | //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d " | ||
170 | // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, | ||
171 | // chip->num_periods, buf->bpl * chip->num_periods); | ||
172 | |||
173 | /* Enables corresponding bits at AUD_INT_STAT */ | ||
174 | cx_write(AUD_A_INT_MSK, | ||
175 | FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | | ||
176 | 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, | ||
187 | tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); | ||
188 | |||
189 | mdelay(100); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * BOARD Specific: Resets audio DMA | ||
195 | */ | ||
196 | static int _cx25821_stop_audio_dma(snd_cx25821_card_t * chip) | ||
197 | { | ||
198 | struct cx25821_dev *dev = chip->dev; | ||
199 | |||
200 | /* stop dma */ | ||
201 | cx_clear(AUD_INT_DMA_CTL, | ||
202 | FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); | ||
203 | |||
204 | /* disable irqs */ | ||
205 | cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); | ||
206 | cx_clear(AUD_A_INT_MSK, | ||
207 | AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | | ||
208 | AUD_INT_DN_RISCI1); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | #define MAX_IRQ_LOOP 50 | ||
214 | |||
215 | /* | ||
216 | * BOARD Specific: IRQ dma bits | ||
217 | */ | ||
218 | static char *cx25821_aud_irqs[32] = { | ||
219 | "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ | ||
220 | NULL, /* reserved */ | ||
221 | "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ | ||
222 | NULL, /* reserved */ | ||
223 | "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ | ||
224 | NULL, /* reserved */ | ||
225 | "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ | ||
226 | NULL, /* reserved */ | ||
227 | "opc_err", "par_err", "rip_err", /* 16-18 */ | ||
228 | "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ | ||
229 | }; | ||
230 | |||
231 | /* | ||
232 | * BOARD Specific: Threats IRQ audio specific calls | ||
233 | */ | ||
234 | static void cx25821_aud_irq(snd_cx25821_card_t * chip, u32 status, u32 mask) | ||
235 | { | ||
236 | struct cx25821_dev *dev = chip->dev; | ||
237 | |||
238 | if (0 == (status & mask)) { | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | cx_write(AUD_A_INT_STAT, status); | ||
243 | if (debug > 1 || (status & mask & ~0xff)) | ||
244 | cx25821_print_irqbits(dev->name, "irq aud", | ||
245 | cx25821_aud_irqs, | ||
246 | ARRAY_SIZE(cx25821_aud_irqs), status, | ||
247 | mask); | ||
248 | |||
249 | /* risc op code error */ | ||
250 | if (status & AUD_INT_OPC_ERR) { | ||
251 | printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n", | ||
252 | dev->name); | ||
253 | |||
254 | cx_clear(AUD_INT_DMA_CTL, | ||
255 | FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); | ||
256 | cx25821_sram_channel_dump_audio(dev, | ||
257 | &cx25821_sram_channels | ||
258 | [AUDIO_SRAM_CHANNEL]); | ||
259 | } | ||
260 | if (status & AUD_INT_DN_SYNC) { | ||
261 | printk(KERN_WARNING "WARNING %s: Downstream sync error!\n", | ||
262 | dev->name); | ||
263 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | /* risc1 downstream */ | ||
268 | if (status & AUD_INT_DN_RISCI1) { | ||
269 | atomic_set(&chip->count, cx_read(AUD_A_GPCNT)); | ||
270 | snd_pcm_period_elapsed(chip->substream); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * BOARD Specific: Handles IRQ calls | ||
276 | */ | ||
277 | static irqreturn_t cx25821_irq(int irq, void *dev_id) | ||
278 | { | ||
279 | snd_cx25821_card_t *chip = dev_id; | ||
280 | struct cx25821_dev *dev = chip->dev; | ||
281 | u32 status, pci_status; | ||
282 | u32 audint_status, audint_mask; | ||
283 | int loop, handled = 0; | ||
284 | int audint_count = 0; | ||
285 | |||
286 | audint_status = cx_read(AUD_A_INT_STAT); | ||
287 | audint_mask = cx_read(AUD_A_INT_MSK); | ||
288 | audint_count = cx_read(AUD_A_GPCNT); | ||
289 | status = cx_read(PCI_INT_STAT); | ||
290 | |||
291 | for (loop = 0; loop < 1; loop++) { | ||
292 | status = cx_read(PCI_INT_STAT); | ||
293 | if (0 == status) { | ||
294 | status = cx_read(PCI_INT_STAT); | ||
295 | audint_status = cx_read(AUD_A_INT_STAT); | ||
296 | audint_mask = cx_read(AUD_A_INT_MSK); | ||
297 | |||
298 | if (status) { | ||
299 | handled = 1; | ||
300 | cx_write(PCI_INT_STAT, status); | ||
301 | |||
302 | cx25821_aud_irq(chip, audint_status, | ||
303 | audint_mask); | ||
304 | break; | ||
305 | } else | ||
306 | goto out; | ||
307 | } | ||
308 | |||
309 | handled = 1; | ||
310 | cx_write(PCI_INT_STAT, status); | ||
311 | |||
312 | cx25821_aud_irq(chip, audint_status, audint_mask); | ||
313 | } | ||
314 | |||
315 | pci_status = cx_read(PCI_INT_STAT); | ||
316 | |||
317 | if (handled) | ||
318 | cx_write(PCI_INT_STAT, pci_status); | ||
319 | |||
320 | out: | ||
321 | return IRQ_RETVAL(handled); | ||
322 | } | ||
323 | |||
324 | static int dsp_buffer_free(snd_cx25821_card_t * chip) | ||
325 | { | ||
326 | BUG_ON(!chip->dma_size); | ||
327 | |||
328 | dprintk(2, "Freeing buffer\n"); | ||
329 | videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); | ||
330 | videobuf_dma_free(chip->dma_risc); | ||
331 | btcx_riscmem_free(chip->pci, &chip->buf->risc); | ||
332 | kfree(chip->buf); | ||
333 | |||
334 | chip->dma_risc = NULL; | ||
335 | chip->dma_size = 0; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | /**************************************************************************** | ||
341 | ALSA PCM Interface | ||
342 | ****************************************************************************/ | ||
343 | |||
344 | /* | ||
345 | * Digital hardware definition | ||
346 | */ | ||
347 | #define DEFAULT_FIFO_SIZE 384 | ||
348 | static struct snd_pcm_hardware snd_cx25821_digital_hw = { | ||
349 | .info = SNDRV_PCM_INFO_MMAP | | ||
350 | SNDRV_PCM_INFO_INTERLEAVED | | ||
351 | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, | ||
352 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
353 | |||
354 | .rates = SNDRV_PCM_RATE_48000, | ||
355 | .rate_min = 48000, | ||
356 | .rate_max = 48000, | ||
357 | .channels_min = 2, | ||
358 | .channels_max = 2, | ||
359 | /* Analog audio output will be full of clicks and pops if there | ||
360 | are not exactly four lines in the SRAM FIFO buffer. */ | ||
361 | .period_bytes_min = DEFAULT_FIFO_SIZE / 3, | ||
362 | .period_bytes_max = DEFAULT_FIFO_SIZE / 3, | ||
363 | .periods_min = 1, | ||
364 | .periods_max = AUDIO_LINE_SIZE, | ||
365 | .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 | ||
366 | }; | ||
367 | |||
368 | /* | ||
369 | * audio pcm capture open callback | ||
370 | */ | ||
371 | static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) | ||
372 | { | ||
373 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
374 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
375 | int err; | ||
376 | unsigned int bpl = 0; | ||
377 | |||
378 | if (!chip) { | ||
379 | printk(KERN_ERR "DEBUG: cx25821 can't find device struct." | ||
380 | " Can't proceed with open\n"); | ||
381 | return -ENODEV; | ||
382 | } | ||
383 | |||
384 | err = | ||
385 | 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 != | ||
394 | DEFAULT_FIFO_SIZE) { | ||
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 | bpl = AUDIO_LINE_SIZE; | ||
400 | } | ||
401 | runtime->hw.period_bytes_min = bpl; | ||
402 | runtime->hw.period_bytes_max = bpl; | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | _error: | ||
407 | dprintk(1, "Error opening PCM!\n"); | ||
408 | return err; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * audio close callback | ||
413 | */ | ||
414 | static int snd_cx25821_close(struct snd_pcm_substream *substream) | ||
415 | { | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * hw_params callback | ||
421 | */ | ||
422 | static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | ||
423 | struct snd_pcm_hw_params *hw_params) | ||
424 | { | ||
425 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
426 | struct videobuf_dmabuf *dma; | ||
427 | |||
428 | struct cx25821_buffer *buf; | ||
429 | int ret; | ||
430 | |||
431 | if (substream->runtime->dma_area) { | ||
432 | dsp_buffer_free(chip); | ||
433 | substream->runtime->dma_area = NULL; | ||
434 | } | ||
435 | |||
436 | chip->period_size = params_period_bytes(hw_params); | ||
437 | chip->num_periods = params_periods(hw_params); | ||
438 | chip->dma_size = chip->period_size * params_periods(hw_params); | ||
439 | |||
440 | BUG_ON(!chip->dma_size); | ||
441 | BUG_ON(chip->num_periods & (chip->num_periods - 1)); | ||
442 | |||
443 | buf = videobuf_sg_alloc(sizeof(*buf)); | ||
444 | if (NULL == buf) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | if (chip->period_size > AUDIO_LINE_SIZE) { | ||
448 | chip->period_size = AUDIO_LINE_SIZE; | ||
449 | } | ||
450 | |||
451 | buf->vb.memory = V4L2_MEMORY_MMAP; | ||
452 | buf->vb.field = V4L2_FIELD_NONE; | ||
453 | buf->vb.width = chip->period_size; | ||
454 | buf->bpl = chip->period_size; | ||
455 | buf->vb.height = chip->num_periods; | ||
456 | buf->vb.size = chip->dma_size; | ||
457 | |||
458 | dma = videobuf_to_dma(&buf->vb); | ||
459 | videobuf_dma_init(dma); | ||
460 | |||
461 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | ||
462 | (PAGE_ALIGN(buf->vb.size) >> | ||
463 | PAGE_SHIFT)); | ||
464 | if (ret < 0) | ||
465 | goto error; | ||
466 | |||
467 | ret = videobuf_sg_dma_map(&chip->pci->dev, dma); | ||
468 | if (ret < 0) | ||
469 | goto error; | ||
470 | |||
471 | ret = | ||
472 | cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, | ||
473 | buf->vb.width, buf->vb.height, 1); | ||
474 | if (ret < 0) { | ||
475 | printk(KERN_INFO | ||
476 | "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); | ||
477 | goto error; | ||
478 | } | ||
479 | |||
480 | /* Loop back to start of program */ | ||
481 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
482 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
483 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
484 | |||
485 | buf->vb.state = VIDEOBUF_PREPARED; | ||
486 | |||
487 | chip->buf = buf; | ||
488 | chip->dma_risc = dma; | ||
489 | |||
490 | substream->runtime->dma_area = chip->dma_risc->vmalloc; | ||
491 | substream->runtime->dma_bytes = chip->dma_size; | ||
492 | substream->runtime->dma_addr = 0; | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | error: | ||
497 | kfree(buf); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * hw free callback | ||
503 | */ | ||
504 | static int snd_cx25821_hw_free(struct snd_pcm_substream *substream) | ||
505 | { | ||
506 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
507 | |||
508 | if (substream->runtime->dma_area) { | ||
509 | dsp_buffer_free(chip); | ||
510 | substream->runtime->dma_area = NULL; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * prepare callback | ||
518 | */ | ||
519 | static int snd_cx25821_prepare(struct snd_pcm_substream *substream) | ||
520 | { | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * trigger callback | ||
526 | */ | ||
527 | static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, | ||
528 | int cmd) | ||
529 | { | ||
530 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
531 | int err = 0; | ||
532 | |||
533 | /* Local interrupts are already disabled by ALSA */ | ||
534 | spin_lock(&chip->reg_lock); | ||
535 | |||
536 | switch (cmd) { | ||
537 | case SNDRV_PCM_TRIGGER_START: | ||
538 | err = _cx25821_start_audio_dma(chip); | ||
539 | break; | ||
540 | case SNDRV_PCM_TRIGGER_STOP: | ||
541 | err = _cx25821_stop_audio_dma(chip); | ||
542 | break; | ||
543 | default: | ||
544 | err = -EINVAL; | ||
545 | break; | ||
546 | } | ||
547 | |||
548 | spin_unlock(&chip->reg_lock); | ||
549 | |||
550 | return err; | ||
551 | } | ||
552 | |||
553 | /* | ||
554 | * pointer callback | ||
555 | */ | ||
556 | static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream | ||
557 | *substream) | ||
558 | { | ||
559 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | ||
560 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
561 | u16 count; | ||
562 | |||
563 | count = atomic_read(&chip->count); | ||
564 | |||
565 | return runtime->period_size * (count & (runtime->periods - 1)); | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * page callback (needed for mmap) | ||
570 | */ | ||
571 | static struct page *snd_cx25821_page(struct snd_pcm_substream *substream, | ||
572 | unsigned long offset) | ||
573 | { | ||
574 | void *pageptr = substream->runtime->dma_area + offset; | ||
575 | |||
576 | return vmalloc_to_page(pageptr); | ||
577 | } | ||
578 | |||
579 | /* | ||
580 | * operators | ||
581 | */ | ||
582 | static struct snd_pcm_ops snd_cx25821_pcm_ops = { | ||
583 | .open = snd_cx25821_pcm_open, | ||
584 | .close = snd_cx25821_close, | ||
585 | .ioctl = snd_pcm_lib_ioctl, | ||
586 | .hw_params = snd_cx25821_hw_params, | ||
587 | .hw_free = snd_cx25821_hw_free, | ||
588 | .prepare = snd_cx25821_prepare, | ||
589 | .trigger = snd_cx25821_card_trigger, | ||
590 | .pointer = snd_cx25821_pointer, | ||
591 | .page = snd_cx25821_page, | ||
592 | }; | ||
593 | |||
594 | /* | ||
595 | * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up | ||
596 | * the callbacks | ||
597 | */ | ||
598 | static int snd_cx25821_pcm(snd_cx25821_card_t * chip, int device, char *name) | ||
599 | { | ||
600 | struct snd_pcm *pcm; | ||
601 | int err; | ||
602 | |||
603 | err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); | ||
604 | if (err < 0) { | ||
605 | printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", | ||
606 | __func__); | ||
607 | return err; | ||
608 | } | ||
609 | pcm->private_data = chip; | ||
610 | pcm->info_flags = 0; | ||
611 | strcpy(pcm->name, name); | ||
612 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | /**************************************************************************** | ||
618 | Basic Flow for Sound Devices | ||
619 | ****************************************************************************/ | ||
620 | |||
621 | /* | ||
622 | * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio | ||
623 | * Only boards with eeprom and byte 1 at eeprom=1 have it | ||
624 | */ | ||
625 | |||
626 | static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = { | ||
627 | {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
628 | {0,} | ||
629 | }; | ||
630 | |||
631 | MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); | ||
632 | |||
633 | /* | ||
634 | * Not used in the function snd_cx25821_dev_free so removing | ||
635 | * from the file. | ||
636 | */ | ||
637 | /* | ||
638 | static int snd_cx25821_free(snd_cx25821_card_t *chip) | ||
639 | { | ||
640 | if (chip->irq >= 0) | ||
641 | free_irq(chip->irq, chip); | ||
642 | |||
643 | cx25821_dev_unregister(chip->dev); | ||
644 | pci_disable_device(chip->pci); | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | */ | ||
649 | |||
650 | /* | ||
651 | * Component Destructor | ||
652 | */ | ||
653 | static void snd_cx25821_dev_free(struct snd_card *card) | ||
654 | { | ||
655 | snd_cx25821_card_t *chip = card->private_data; | ||
656 | |||
657 | //snd_cx25821_free(chip); | ||
658 | snd_card_free(chip->card); | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Alsa Constructor - Component probe | ||
663 | */ | ||
664 | static int cx25821_audio_initdev(struct cx25821_dev *dev) | ||
665 | { | ||
666 | struct snd_card *card; | ||
667 | snd_cx25821_card_t *chip; | ||
668 | int err; | ||
669 | |||
670 | if (devno >= SNDRV_CARDS) { | ||
671 | printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", | ||
672 | __func__); | ||
673 | return (-ENODEV); | ||
674 | } | ||
675 | |||
676 | if (!enable[devno]) { | ||
677 | ++devno; | ||
678 | printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); | ||
679 | return (-ENOENT); | ||
680 | } | ||
681 | |||
682 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, | ||
683 | sizeof(snd_cx25821_card_t), &card); | ||
684 | if (err < 0) { | ||
685 | printk(KERN_INFO | ||
686 | "DEBUG ERROR: cannot create snd_card_new in %s\n", | ||
687 | __func__); | ||
688 | return err; | ||
689 | } | ||
690 | |||
691 | strcpy(card->driver, "cx25821"); | ||
692 | |||
693 | /* Card "creation" */ | ||
694 | card->private_free = snd_cx25821_dev_free; | ||
695 | chip = (snd_cx25821_card_t *) card->private_data; | ||
696 | spin_lock_init(&chip->reg_lock); | ||
697 | |||
698 | chip->dev = dev; | ||
699 | chip->card = card; | ||
700 | chip->pci = dev->pci; | ||
701 | chip->iobase = pci_resource_start(dev->pci, 0); | ||
702 | |||
703 | chip->irq = dev->pci->irq; | ||
704 | |||
705 | err = request_irq(dev->pci->irq, cx25821_irq, | ||
706 | IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip); | ||
707 | |||
708 | if (err < 0) { | ||
709 | printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", | ||
710 | chip->dev->name, dev->pci->irq); | ||
711 | goto error; | ||
712 | } | ||
713 | |||
714 | if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) { | ||
715 | printk(KERN_INFO | ||
716 | "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", | ||
717 | __func__); | ||
718 | goto error; | ||
719 | } | ||
720 | |||
721 | snd_card_set_dev(card, &chip->pci->dev); | ||
722 | |||
723 | strcpy(card->shortname, "cx25821"); | ||
724 | sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, | ||
725 | chip->iobase, chip->irq); | ||
726 | strcpy(card->mixername, "CX25821"); | ||
727 | |||
728 | printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", | ||
729 | card->driver, devno); | ||
730 | |||
731 | err = snd_card_register(card); | ||
732 | if (err < 0) { | ||
733 | printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", | ||
734 | __func__); | ||
735 | goto error; | ||
736 | } | ||
737 | |||
738 | snd_cx25821_cards[devno] = card; | ||
739 | |||
740 | devno++; | ||
741 | return 0; | ||
742 | |||
743 | error: | ||
744 | snd_card_free(card); | ||
745 | return err; | ||
746 | } | ||
747 | |||
748 | /**************************************************************************** | ||
749 | LINUX MODULE INIT | ||
750 | ****************************************************************************/ | ||
751 | static void cx25821_audio_fini(void) | ||
752 | { | ||
753 | snd_card_free(snd_cx25821_cards[0]); | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * Module initializer | ||
758 | * | ||
759 | * Loops through present saa7134 cards, and assigns an ALSA device | ||
760 | * to each one | ||
761 | * | ||
762 | */ | ||
763 | static int cx25821_alsa_init(void) | ||
764 | { | ||
765 | struct cx25821_dev *dev = NULL; | ||
766 | struct list_head *list; | ||
767 | |||
768 | list_for_each(list, &cx25821_devlist) { | ||
769 | dev = list_entry(list, struct cx25821_dev, devlist); | ||
770 | cx25821_audio_initdev(dev); | ||
771 | } | ||
772 | |||
773 | if (dev == NULL) | ||
774 | printk(KERN_INFO | ||
775 | "cx25821 ERROR ALSA: no cx25821 cards found\n"); | ||
776 | |||
777 | return 0; | ||
778 | |||
779 | } | ||
780 | |||
781 | late_initcall(cx25821_alsa_init); | ||
782 | module_exit(cx25821_audio_fini); | ||
783 | |||
784 | /* ----------------------------------------------------------- */ | ||
785 | /* | ||
786 | * Local variables: | ||
787 | * c-basic-offset: 8 | ||
788 | * End: | ||
789 | */ | ||
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c new file mode 100644 index 000000000000..ddddf651266b --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio-upstream.c | |||
@@ -0,0 +1,804 @@ | |||
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 "cx25821-video.h" | ||
24 | #include "cx25821-audio-upstream.h" | ||
25 | |||
26 | #include <linux/fs.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/syscalls.h> | ||
32 | #include <linux/file.h> | ||
33 | #include <linux/fcntl.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
38 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | static int _intr_msk = | ||
42 | FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | | ||
43 | FLD_AUD_SRC_OPC_ERR; | ||
44 | |||
45 | int cx25821_sram_channel_setup_upstream_audio(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 | if (ch->cmds_start == 0) { | ||
53 | cx_write(ch->ptr1_reg, 0); | ||
54 | cx_write(ch->ptr2_reg, 0); | ||
55 | cx_write(ch->cnt2_reg, 0); | ||
56 | cx_write(ch->cnt1_reg, 0); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
61 | cdt = ch->cdt; | ||
62 | lines = ch->fifo_size / bpl; | ||
63 | |||
64 | if (lines > 3) { | ||
65 | lines = 3; | ||
66 | } | ||
67 | |||
68 | BUG_ON(lines < 2); | ||
69 | |||
70 | /* write CDT */ | ||
71 | for (i = 0; i < lines; i++) { | ||
72 | cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); | ||
73 | cx_write(cdt + 16 * i + 4, 0); | ||
74 | cx_write(cdt + 16 * i + 8, 0); | ||
75 | cx_write(cdt + 16 * i + 12, 0); | ||
76 | } | ||
77 | |||
78 | /* write CMDS */ | ||
79 | cx_write(ch->cmds_start + 0, risc); | ||
80 | |||
81 | cx_write(ch->cmds_start + 4, 0); | ||
82 | cx_write(ch->cmds_start + 8, cdt); | ||
83 | cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); | ||
84 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
85 | |||
86 | //IQ size | ||
87 | cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); | ||
88 | |||
89 | for (i = 24; i < 80; i += 4) | ||
90 | cx_write(ch->cmds_start + i, 0); | ||
91 | |||
92 | /* fill registers */ | ||
93 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
94 | cx_write(ch->ptr2_reg, cdt); | ||
95 | cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); | ||
96 | cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, | ||
102 | __le32 * rp, | ||
103 | dma_addr_t databuf_phys_addr, | ||
104 | unsigned int bpl, | ||
105 | int fifo_enable) | ||
106 | { | ||
107 | unsigned int line; | ||
108 | struct sram_channel *sram_ch = | ||
109 | &dev->sram_channels[dev->_audio_upstream_channel_select]; | ||
110 | int offset = 0; | ||
111 | |||
112 | /* scan lines */ | ||
113 | for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) { | ||
114 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
115 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | ||
116 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
117 | |||
118 | // Check if we need to enable the FIFO after the first 3 lines | ||
119 | // For the upstream audio channel, the risc engine will enable the FIFO. | ||
120 | if (fifo_enable && line == 2) { | ||
121 | *(rp++) = RISC_WRITECR; | ||
122 | *(rp++) = sram_ch->dma_ctl; | ||
123 | *(rp++) = sram_ch->fld_aud_fifo_en; | ||
124 | *(rp++) = 0x00000020; | ||
125 | } | ||
126 | |||
127 | offset += AUDIO_LINE_SIZE; | ||
128 | } | ||
129 | |||
130 | return rp; | ||
131 | } | ||
132 | |||
133 | int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, | ||
134 | struct pci_dev *pci, | ||
135 | unsigned int bpl, unsigned int lines) | ||
136 | { | ||
137 | __le32 *rp; | ||
138 | int fifo_enable = 0; | ||
139 | int frame = 0, i = 0; | ||
140 | int frame_size = AUDIO_DATA_BUF_SZ; | ||
141 | int databuf_offset = 0; | ||
142 | int risc_flag = RISC_CNT_INC; | ||
143 | dma_addr_t risc_phys_jump_addr; | ||
144 | |||
145 | /* Virtual address of Risc buffer program */ | ||
146 | rp = dev->_risc_virt_addr; | ||
147 | |||
148 | /* sync instruction */ | ||
149 | *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); | ||
150 | |||
151 | for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) { | ||
152 | databuf_offset = frame_size * frame; | ||
153 | |||
154 | if (frame == 0) { | ||
155 | fifo_enable = 1; | ||
156 | risc_flag = RISC_CNT_RESET; | ||
157 | } else { | ||
158 | fifo_enable = 0; | ||
159 | risc_flag = RISC_CNT_INC; | ||
160 | } | ||
161 | |||
162 | //Calculate physical jump address | ||
163 | if ((frame + 1) == NUM_AUDIO_FRAMES) { | ||
164 | risc_phys_jump_addr = | ||
165 | dev->_risc_phys_start_addr + | ||
166 | RISC_SYNC_INSTRUCTION_SIZE; | ||
167 | } else { | ||
168 | risc_phys_jump_addr = | ||
169 | dev->_risc_phys_start_addr + | ||
170 | RISC_SYNC_INSTRUCTION_SIZE + | ||
171 | AUDIO_RISC_DMA_BUF_SIZE * (frame + 1); | ||
172 | } | ||
173 | |||
174 | rp = cx25821_risc_field_upstream_audio(dev, rp, | ||
175 | dev-> | ||
176 | _audiodata_buf_phys_addr | ||
177 | + databuf_offset, bpl, | ||
178 | fifo_enable); | ||
179 | |||
180 | if (USE_RISC_NOOP_AUDIO) { | ||
181 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
182 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ | ||
187 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | ||
188 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
189 | *(rp++) = cpu_to_le32(0); | ||
190 | |||
191 | //Recalculate virtual address based on frame index | ||
192 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + | ||
193 | (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | void cx25821_free_memory_audio(struct cx25821_dev *dev) | ||
200 | { | ||
201 | if (dev->_risc_virt_addr) { | ||
202 | pci_free_consistent(dev->pci, dev->_audiorisc_size, | ||
203 | dev->_risc_virt_addr, dev->_risc_phys_addr); | ||
204 | dev->_risc_virt_addr = NULL; | ||
205 | } | ||
206 | |||
207 | if (dev->_audiodata_buf_virt_addr) { | ||
208 | pci_free_consistent(dev->pci, dev->_audiodata_buf_size, | ||
209 | dev->_audiodata_buf_virt_addr, | ||
210 | dev->_audiodata_buf_phys_addr); | ||
211 | dev->_audiodata_buf_virt_addr = NULL; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | ||
216 | { | ||
217 | struct sram_channel *sram_ch = | ||
218 | &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; | ||
219 | u32 tmp = 0; | ||
220 | |||
221 | if (!dev->_audio_is_running) { | ||
222 | printk | ||
223 | ("cx25821: No audio file is currently running so return!\n"); | ||
224 | return; | ||
225 | } | ||
226 | //Disable RISC interrupts | ||
227 | cx_write(sram_ch->int_msk, 0); | ||
228 | |||
229 | //Turn OFF risc and fifo enable in AUD_DMA_CNTRL | ||
230 | tmp = cx_read(sram_ch->dma_ctl); | ||
231 | cx_write(sram_ch->dma_ctl, | ||
232 | tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en)); | ||
233 | |||
234 | //Clear data buffer memory | ||
235 | if (dev->_audiodata_buf_virt_addr) | ||
236 | memset(dev->_audiodata_buf_virt_addr, 0, | ||
237 | dev->_audiodata_buf_size); | ||
238 | |||
239 | dev->_audio_is_running = 0; | ||
240 | dev->_is_first_audio_frame = 0; | ||
241 | dev->_audioframe_count = 0; | ||
242 | dev->_audiofile_status = END_OF_FILE; | ||
243 | |||
244 | if (dev->_irq_audio_queues) { | ||
245 | kfree(dev->_irq_audio_queues); | ||
246 | dev->_irq_audio_queues = NULL; | ||
247 | } | ||
248 | |||
249 | if (dev->_audiofilename != NULL) | ||
250 | kfree(dev->_audiofilename); | ||
251 | } | ||
252 | |||
253 | void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) | ||
254 | { | ||
255 | if (dev->_audio_is_running) { | ||
256 | cx25821_stop_upstream_audio(dev); | ||
257 | } | ||
258 | |||
259 | cx25821_free_memory_audio(dev); | ||
260 | } | ||
261 | |||
262 | int cx25821_get_audio_data(struct cx25821_dev *dev, | ||
263 | struct sram_channel *sram_ch) | ||
264 | { | ||
265 | struct file *myfile; | ||
266 | int frame_index_temp = dev->_audioframe_index; | ||
267 | int i = 0; | ||
268 | int line_size = AUDIO_LINE_SIZE; | ||
269 | int frame_size = AUDIO_DATA_BUF_SZ; | ||
270 | int frame_offset = frame_size * frame_index_temp; | ||
271 | ssize_t vfs_read_retval = 0; | ||
272 | char mybuf[line_size]; | ||
273 | loff_t file_offset = dev->_audioframe_count * frame_size; | ||
274 | loff_t pos; | ||
275 | mm_segment_t old_fs; | ||
276 | |||
277 | if (dev->_audiofile_status == END_OF_FILE) | ||
278 | return 0; | ||
279 | |||
280 | myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); | ||
281 | |||
282 | if (IS_ERR(myfile)) { | ||
283 | const int open_errno = -PTR_ERR(myfile); | ||
284 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
285 | __func__, dev->_audiofilename, open_errno); | ||
286 | return PTR_ERR(myfile); | ||
287 | } else { | ||
288 | if (!(myfile->f_op)) { | ||
289 | printk("%s: File has no file operations registered!\n", | ||
290 | __func__); | ||
291 | filp_close(myfile, NULL); | ||
292 | return -EIO; | ||
293 | } | ||
294 | |||
295 | if (!myfile->f_op->read) { | ||
296 | printk("%s: File has no READ operations registered! \n", | ||
297 | __func__); | ||
298 | filp_close(myfile, NULL); | ||
299 | return -EIO; | ||
300 | } | ||
301 | |||
302 | pos = myfile->f_pos; | ||
303 | old_fs = get_fs(); | ||
304 | set_fs(KERNEL_DS); | ||
305 | |||
306 | for (i = 0; i < dev->_audio_lines_count; i++) { | ||
307 | pos = file_offset; | ||
308 | |||
309 | vfs_read_retval = | ||
310 | vfs_read(myfile, mybuf, line_size, &pos); | ||
311 | |||
312 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | ||
313 | && dev->_audiodata_buf_virt_addr != NULL) { | ||
314 | memcpy((void *)(dev->_audiodata_buf_virt_addr + | ||
315 | frame_offset / 4), mybuf, | ||
316 | vfs_read_retval); | ||
317 | } | ||
318 | |||
319 | file_offset += vfs_read_retval; | ||
320 | frame_offset += vfs_read_retval; | ||
321 | |||
322 | if (vfs_read_retval < line_size) { | ||
323 | printk(KERN_INFO | ||
324 | "Done: exit %s() since no more bytes to read from Audio file.\n", | ||
325 | __func__); | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | if (i > 0) | ||
331 | dev->_audioframe_count++; | ||
332 | |||
333 | dev->_audiofile_status = | ||
334 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
335 | |||
336 | set_fs(old_fs); | ||
337 | filp_close(myfile, NULL); | ||
338 | } | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static void cx25821_audioups_handler(struct work_struct *work) | ||
344 | { | ||
345 | struct cx25821_dev *dev = | ||
346 | container_of(work, struct cx25821_dev, _audio_work_entry); | ||
347 | |||
348 | if (!dev) { | ||
349 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", | ||
350 | __func__); | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | cx25821_get_audio_data(dev, | ||
355 | &dev->sram_channels[dev-> | ||
356 | _audio_upstream_channel_select]); | ||
357 | } | ||
358 | |||
359 | int cx25821_openfile_audio(struct cx25821_dev *dev, | ||
360 | struct sram_channel *sram_ch) | ||
361 | { | ||
362 | struct file *myfile; | ||
363 | int i = 0, j = 0; | ||
364 | int line_size = AUDIO_LINE_SIZE; | ||
365 | ssize_t vfs_read_retval = 0; | ||
366 | char mybuf[line_size]; | ||
367 | loff_t pos; | ||
368 | loff_t offset = (unsigned long)0; | ||
369 | mm_segment_t old_fs; | ||
370 | |||
371 | myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); | ||
372 | |||
373 | if (IS_ERR(myfile)) { | ||
374 | const int open_errno = -PTR_ERR(myfile); | ||
375 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
376 | __func__, dev->_audiofilename, open_errno); | ||
377 | return PTR_ERR(myfile); | ||
378 | } else { | ||
379 | if (!(myfile->f_op)) { | ||
380 | printk("%s: File has no file operations registered! \n", | ||
381 | __func__); | ||
382 | filp_close(myfile, NULL); | ||
383 | return -EIO; | ||
384 | } | ||
385 | |||
386 | if (!myfile->f_op->read) { | ||
387 | printk("%s: File has no READ operations registered! \n", | ||
388 | __func__); | ||
389 | filp_close(myfile, NULL); | ||
390 | return -EIO; | ||
391 | } | ||
392 | |||
393 | pos = myfile->f_pos; | ||
394 | old_fs = get_fs(); | ||
395 | set_fs(KERNEL_DS); | ||
396 | |||
397 | for (j = 0; j < NUM_AUDIO_FRAMES; j++) { | ||
398 | for (i = 0; i < dev->_audio_lines_count; i++) { | ||
399 | pos = offset; | ||
400 | |||
401 | vfs_read_retval = | ||
402 | vfs_read(myfile, mybuf, line_size, &pos); | ||
403 | |||
404 | if (vfs_read_retval > 0 | ||
405 | && vfs_read_retval == line_size | ||
406 | && dev->_audiodata_buf_virt_addr != NULL) { | ||
407 | memcpy((void *)(dev-> | ||
408 | _audiodata_buf_virt_addr | ||
409 | + offset / 4), mybuf, | ||
410 | vfs_read_retval); | ||
411 | } | ||
412 | |||
413 | offset += vfs_read_retval; | ||
414 | |||
415 | if (vfs_read_retval < line_size) { | ||
416 | printk(KERN_INFO | ||
417 | "Done: exit %s() since no more bytes to read from Audio file.\n", | ||
418 | __func__); | ||
419 | break; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (i > 0) { | ||
424 | dev->_audioframe_count++; | ||
425 | } | ||
426 | |||
427 | if (vfs_read_retval < line_size) { | ||
428 | break; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | dev->_audiofile_status = | ||
433 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
434 | |||
435 | set_fs(old_fs); | ||
436 | myfile->f_pos = 0; | ||
437 | filp_close(myfile, NULL); | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | ||
444 | struct sram_channel *sram_ch, | ||
445 | int bpl) | ||
446 | { | ||
447 | int ret = 0; | ||
448 | dma_addr_t dma_addr; | ||
449 | dma_addr_t data_dma_addr; | ||
450 | |||
451 | cx25821_free_memory_audio(dev); | ||
452 | |||
453 | dev->_risc_virt_addr = | ||
454 | pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, | ||
455 | &dma_addr); | ||
456 | dev->_risc_virt_start_addr = dev->_risc_virt_addr; | ||
457 | dev->_risc_phys_start_addr = dma_addr; | ||
458 | dev->_risc_phys_addr = dma_addr; | ||
459 | dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; | ||
460 | |||
461 | if (!dev->_risc_virt_addr) { | ||
462 | printk | ||
463 | ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); | ||
464 | return -ENOMEM; | ||
465 | } | ||
466 | //Clear out memory at address | ||
467 | memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); | ||
468 | |||
469 | //For Audio Data buffer allocation | ||
470 | dev->_audiodata_buf_virt_addr = | ||
471 | pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, | ||
472 | &data_dma_addr); | ||
473 | dev->_audiodata_buf_phys_addr = data_dma_addr; | ||
474 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; | ||
475 | |||
476 | if (!dev->_audiodata_buf_virt_addr) { | ||
477 | printk | ||
478 | ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); | ||
479 | return -ENOMEM; | ||
480 | } | ||
481 | //Clear out memory at address | ||
482 | memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size); | ||
483 | |||
484 | ret = cx25821_openfile_audio(dev, sram_ch); | ||
485 | if (ret < 0) | ||
486 | return ret; | ||
487 | |||
488 | //Creating RISC programs | ||
489 | ret = | ||
490 | cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, | ||
491 | dev->_audio_lines_count); | ||
492 | if (ret < 0) { | ||
493 | printk(KERN_DEBUG | ||
494 | "cx25821 ERROR creating audio upstream RISC programs! \n"); | ||
495 | goto error; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | |||
500 | error: | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | ||
505 | u32 status) | ||
506 | { | ||
507 | int i = 0; | ||
508 | u32 int_msk_tmp; | ||
509 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
510 | dma_addr_t risc_phys_jump_addr; | ||
511 | __le32 *rp; | ||
512 | |||
513 | if (status & FLD_AUD_SRC_RISCI1) { | ||
514 | //Get interrupt_index of the program that interrupted | ||
515 | u32 prog_cnt = cx_read(channel->gpcnt); | ||
516 | |||
517 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
518 | cx_write(channel->int_msk, 0); | ||
519 | cx_write(channel->int_stat, cx_read(channel->int_stat)); | ||
520 | |||
521 | spin_lock(&dev->slock); | ||
522 | |||
523 | while (prog_cnt != dev->_last_index_irq) { | ||
524 | //Update _last_index_irq | ||
525 | if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) { | ||
526 | dev->_last_index_irq++; | ||
527 | } else { | ||
528 | dev->_last_index_irq = 0; | ||
529 | } | ||
530 | |||
531 | dev->_audioframe_index = dev->_last_index_irq; | ||
532 | |||
533 | queue_work(dev->_irq_audio_queues, | ||
534 | &dev->_audio_work_entry); | ||
535 | } | ||
536 | |||
537 | if (dev->_is_first_audio_frame) { | ||
538 | dev->_is_first_audio_frame = 0; | ||
539 | |||
540 | if (dev->_risc_virt_start_addr != NULL) { | ||
541 | risc_phys_jump_addr = | ||
542 | dev->_risc_phys_start_addr + | ||
543 | RISC_SYNC_INSTRUCTION_SIZE + | ||
544 | AUDIO_RISC_DMA_BUF_SIZE; | ||
545 | |||
546 | rp = cx25821_risc_field_upstream_audio(dev, | ||
547 | dev-> | ||
548 | _risc_virt_start_addr | ||
549 | + 1, | ||
550 | dev-> | ||
551 | _audiodata_buf_phys_addr, | ||
552 | AUDIO_LINE_SIZE, | ||
553 | FIFO_DISABLE); | ||
554 | |||
555 | if (USE_RISC_NOOP_AUDIO) { | ||
556 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
557 | *(rp++) = | ||
558 | cpu_to_le32(RISC_NOOP); | ||
559 | } | ||
560 | } | ||
561 | // Jump to 2nd Audio Frame | ||
562 | *(rp++) = | ||
563 | cpu_to_le32(RISC_JUMP | RISC_IRQ1 | | ||
564 | RISC_CNT_RESET); | ||
565 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
566 | *(rp++) = cpu_to_le32(0); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | spin_unlock(&dev->slock); | ||
571 | } else { | ||
572 | if (status & FLD_AUD_SRC_OF) | ||
573 | printk("%s: Audio Received Overflow Error Interrupt!\n", | ||
574 | __func__); | ||
575 | |||
576 | if (status & FLD_AUD_SRC_SYNC) | ||
577 | printk("%s: Audio Received Sync Error Interrupt!\n", | ||
578 | __func__); | ||
579 | |||
580 | if (status & FLD_AUD_SRC_OPC_ERR) | ||
581 | printk("%s: Audio Received OpCode Error Interrupt!\n", | ||
582 | __func__); | ||
583 | |||
584 | // Read and write back the interrupt status register to clear our bits | ||
585 | cx_write(channel->int_stat, cx_read(channel->int_stat)); | ||
586 | } | ||
587 | |||
588 | if (dev->_audiofile_status == END_OF_FILE) { | ||
589 | printk("cx25821: EOF Channel Audio Framecount = %d\n", | ||
590 | dev->_audioframe_count); | ||
591 | return -1; | ||
592 | } | ||
593 | //ElSE, set the interrupt mask register, re-enable irq. | ||
594 | int_msk_tmp = cx_read(channel->int_msk); | ||
595 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | ||
601 | { | ||
602 | struct cx25821_dev *dev = dev_id; | ||
603 | u32 msk_stat, audio_status; | ||
604 | int handled = 0; | ||
605 | struct sram_channel *sram_ch; | ||
606 | |||
607 | if (!dev) | ||
608 | return -1; | ||
609 | |||
610 | sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; | ||
611 | |||
612 | msk_stat = cx_read(sram_ch->int_mstat); | ||
613 | audio_status = cx_read(sram_ch->int_stat); | ||
614 | |||
615 | // Only deal with our interrupt | ||
616 | if (audio_status) { | ||
617 | handled = | ||
618 | cx25821_audio_upstream_irq(dev, | ||
619 | dev-> | ||
620 | _audio_upstream_channel_select, | ||
621 | audio_status); | ||
622 | } | ||
623 | |||
624 | if (handled < 0) { | ||
625 | cx25821_stop_upstream_audio(dev); | ||
626 | } else { | ||
627 | handled += handled; | ||
628 | } | ||
629 | |||
630 | return IRQ_RETVAL(handled); | ||
631 | } | ||
632 | |||
633 | static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, | ||
634 | struct sram_channel *sram_ch) | ||
635 | { | ||
636 | int count = 0; | ||
637 | u32 tmp; | ||
638 | |||
639 | do { | ||
640 | //Wait 10 microsecond before checking to see if the FIFO is turned ON. | ||
641 | udelay(10); | ||
642 | |||
643 | tmp = cx_read(sram_ch->dma_ctl); | ||
644 | |||
645 | if (count++ > 1000) //10 millisecond timeout | ||
646 | { | ||
647 | printk | ||
648 | ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", | ||
649 | __func__); | ||
650 | return; | ||
651 | } | ||
652 | |||
653 | } while (!(tmp & sram_ch->fld_aud_fifo_en)); | ||
654 | |||
655 | } | ||
656 | |||
657 | int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | ||
658 | struct sram_channel *sram_ch) | ||
659 | { | ||
660 | u32 tmp = 0; | ||
661 | int err = 0; | ||
662 | |||
663 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. | ||
664 | cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); | ||
665 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
666 | |||
667 | /* reset counter */ | ||
668 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
669 | |||
670 | //Set the line length (It looks like we do not need to set the line length) | ||
671 | cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); | ||
672 | |||
673 | //Set the input mode to 16-bit | ||
674 | tmp = cx_read(sram_ch->aud_cfg); | ||
675 | tmp |= | ||
676 | FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | | ||
677 | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; | ||
678 | cx_write(sram_ch->aud_cfg, tmp); | ||
679 | |||
680 | // Read and write back the interrupt status register to clear it | ||
681 | tmp = cx_read(sram_ch->int_stat); | ||
682 | cx_write(sram_ch->int_stat, tmp); | ||
683 | |||
684 | // Clear our bits from the interrupt status register. | ||
685 | cx_write(sram_ch->int_stat, _intr_msk); | ||
686 | |||
687 | //Set the interrupt mask register, enable irq. | ||
688 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
689 | tmp = cx_read(sram_ch->int_msk); | ||
690 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | ||
691 | |||
692 | err = | ||
693 | request_irq(dev->pci->irq, cx25821_upstream_irq_audio, | ||
694 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
695 | if (err < 0) { | ||
696 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, | ||
697 | dev->pci->irq); | ||
698 | goto fail_irq; | ||
699 | } | ||
700 | |||
701 | // Start the DMA engine | ||
702 | tmp = cx_read(sram_ch->dma_ctl); | ||
703 | cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en); | ||
704 | |||
705 | dev->_audio_is_running = 1; | ||
706 | dev->_is_first_audio_frame = 1; | ||
707 | |||
708 | // The fifo_en bit turns on by the first Risc program | ||
709 | cx25821_wait_fifo_enable(dev, sram_ch); | ||
710 | |||
711 | return 0; | ||
712 | |||
713 | fail_irq: | ||
714 | cx25821_dev_unregister(dev); | ||
715 | return err; | ||
716 | } | ||
717 | |||
718 | int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | ||
719 | { | ||
720 | struct sram_channel *sram_ch; | ||
721 | int retval = 0; | ||
722 | int err = 0; | ||
723 | int str_length = 0; | ||
724 | |||
725 | if (dev->_audio_is_running) { | ||
726 | printk("Audio Channel is still running so return!\n"); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | dev->_audio_upstream_channel_select = channel_select; | ||
731 | sram_ch = &dev->sram_channels[channel_select]; | ||
732 | |||
733 | //Work queue | ||
734 | INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); | ||
735 | dev->_irq_audio_queues = | ||
736 | create_singlethread_workqueue("cx25821_audioworkqueue"); | ||
737 | |||
738 | if (!dev->_irq_audio_queues) { | ||
739 | printk | ||
740 | ("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); | ||
741 | return -ENOMEM; | ||
742 | } | ||
743 | |||
744 | dev->_last_index_irq = 0; | ||
745 | dev->_audio_is_running = 0; | ||
746 | dev->_audioframe_count = 0; | ||
747 | dev->_audiofile_status = RESET_STATUS; | ||
748 | dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; | ||
749 | _line_size = AUDIO_LINE_SIZE; | ||
750 | |||
751 | if (dev->input_audiofilename) { | ||
752 | str_length = strlen(dev->input_audiofilename); | ||
753 | dev->_audiofilename = | ||
754 | (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
755 | |||
756 | if (!dev->_audiofilename) | ||
757 | goto error; | ||
758 | |||
759 | memcpy(dev->_audiofilename, dev->input_audiofilename, | ||
760 | str_length + 1); | ||
761 | |||
762 | //Default if filename is empty string | ||
763 | if (strcmp(dev->input_audiofilename, "") == 0) { | ||
764 | dev->_audiofilename = "/root/audioGOOD.wav"; | ||
765 | } | ||
766 | } else { | ||
767 | str_length = strlen(_defaultAudioName); | ||
768 | dev->_audiofilename = | ||
769 | (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
770 | |||
771 | if (!dev->_audiofilename) | ||
772 | goto error; | ||
773 | |||
774 | memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); | ||
775 | } | ||
776 | |||
777 | retval = | ||
778 | cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, | ||
779 | 0); | ||
780 | |||
781 | dev->audio_upstream_riscbuf_size = | ||
782 | AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + | ||
783 | RISC_SYNC_INSTRUCTION_SIZE; | ||
784 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; | ||
785 | |||
786 | //Allocating buffers and prepare RISC program | ||
787 | retval = | ||
788 | cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); | ||
789 | if (retval < 0) { | ||
790 | printk(KERN_ERR | ||
791 | "%s: Failed to set up Audio upstream buffers!\n", | ||
792 | dev->name); | ||
793 | goto error; | ||
794 | } | ||
795 | //Start RISC engine | ||
796 | cx25821_start_audio_dma_upstream(dev, sram_ch); | ||
797 | |||
798 | return 0; | ||
799 | |||
800 | error: | ||
801 | cx25821_dev_unregister(dev); | ||
802 | |||
803 | return err; | ||
804 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.h b/drivers/staging/cx25821/cx25821-audio-upstream.h new file mode 100644 index 000000000000..ca987addf815 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio-upstream.h | |||
@@ -0,0 +1,57 @@ | |||
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 NUM_AUDIO_PROGS 8 | ||
27 | #define NUM_AUDIO_FRAMES 8 | ||
28 | #define END_OF_FILE 0 | ||
29 | #define IN_PROGRESS 1 | ||
30 | #define RESET_STATUS -1 | ||
31 | #define FIFO_DISABLE 0 | ||
32 | #define FIFO_ENABLE 1 | ||
33 | #define NUM_NO_OPS 4 | ||
34 | |||
35 | #define RISC_READ_INSTRUCTION_SIZE 12 | ||
36 | #define RISC_JUMP_INSTRUCTION_SIZE 12 | ||
37 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
38 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
39 | #define DWORD_SIZE 4 | ||
40 | #define AUDIO_SYNC_LINE 4 | ||
41 | |||
42 | #define LINES_PER_AUDIO_BUFFER 15 | ||
43 | #define AUDIO_LINE_SIZE 128 | ||
44 | #define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) | ||
45 | |||
46 | #define USE_RISC_NOOP_AUDIO 1 | ||
47 | |||
48 | #ifdef USE_RISC_NOOP_AUDIO | ||
49 | #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) | ||
50 | #endif | ||
51 | |||
52 | #ifndef USE_RISC_NOOP_AUDIO | ||
53 | #define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) | ||
54 | #endif | ||
55 | |||
56 | static int _line_size; | ||
57 | char *_defaultAudioName = "/root/audioGOOD.wav"; | ||
diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h new file mode 100644 index 000000000000..503f42f036a8 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audio.h | |||
@@ -0,0 +1,57 @@ | |||
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 | #define USE_RISC_NOOP 1 | ||
27 | #define LINES_PER_BUFFER 15 | ||
28 | #define AUDIO_LINE_SIZE 128 | ||
29 | |||
30 | //Number of buffer programs to use at once. | ||
31 | #define NUMBER_OF_PROGRAMS 8 | ||
32 | |||
33 | //Max size of the RISC program for a buffer. - worst case is 2 writes per line | ||
34 | // Space is also added for the 4 no-op instructions added on the end. | ||
35 | |||
36 | #ifndef USE_RISC_NOOP | ||
37 | #define MAX_BUFFER_PROGRAM_SIZE \ | ||
38 | (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) | ||
39 | #endif | ||
40 | |||
41 | // MAE 12 July 2005 Try to use NOOP RISC instruction instead | ||
42 | #ifdef USE_RISC_NOOP | ||
43 | #define MAX_BUFFER_PROGRAM_SIZE \ | ||
44 | (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) | ||
45 | #endif | ||
46 | |||
47 | //Sizes of various instructions in bytes. Used when adding instructions. | ||
48 | #define RISC_WRITE_INSTRUCTION_SIZE 12 | ||
49 | #define RISC_JUMP_INSTRUCTION_SIZE 12 | ||
50 | #define RISC_SKIP_INSTRUCTION_SIZE 4 | ||
51 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
52 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
53 | #define RISC_NOOP_INSTRUCTION_SIZE 4 | ||
54 | |||
55 | #define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) | ||
56 | |||
57 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c new file mode 100644 index 000000000000..f78b8912d905 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-audups11.c | |||
@@ -0,0 +1,434 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH11]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | |||
103 | lock_kernel(); | ||
104 | list_for_each(list, &cx25821_devlist) { | ||
105 | h = list_entry(list, struct cx25821_dev, devlist); | ||
106 | |||
107 | if (h->video_dev[SRAM_CH11] | ||
108 | && h->video_dev[SRAM_CH11]->minor == minor) { | ||
109 | dev = h; | ||
110 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (NULL == dev) { | ||
115 | unlock_kernel(); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
120 | |||
121 | /* allocate + initialize per filehandle data */ | ||
122 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
123 | if (NULL == fh) { | ||
124 | unlock_kernel(); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = 10; | ||
139 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
140 | |||
141 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
142 | |||
143 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
144 | &dev->pci->dev, &dev->slock, | ||
145 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
146 | V4L2_FIELD_INTERLACED, | ||
147 | sizeof(struct cx25821_buffer), 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, | ||
156 | loff_t * ppos) | ||
157 | { | ||
158 | struct cx25821_fh *fh = file->private_data; | ||
159 | |||
160 | switch (fh->type) { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO11)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
166 | file->f_flags & O_NONBLOCK); | ||
167 | |||
168 | default: | ||
169 | BUG(); | ||
170 | return 0; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static unsigned int video_poll(struct file *file, | ||
175 | struct poll_table_struct *wait) | ||
176 | { | ||
177 | struct cx25821_fh *fh = file->private_data; | ||
178 | struct cx25821_buffer *buf; | ||
179 | |||
180 | if (res_check(fh, RESOURCE_VIDEO11)) { | ||
181 | /* streaming capture */ | ||
182 | if (list_empty(&fh->vidq.stream)) | ||
183 | return POLLERR; | ||
184 | buf = list_entry(fh->vidq.stream.next, | ||
185 | struct cx25821_buffer, vb.stream); | ||
186 | } else { | ||
187 | /* read() capture */ | ||
188 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
189 | if (NULL == buf) | ||
190 | return POLLERR; | ||
191 | } | ||
192 | |||
193 | poll_wait(file, &buf->vb.done, wait); | ||
194 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
195 | return POLLIN | POLLRDNORM; | ||
196 | return 0; | ||
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 the risc engine and fifo | ||
205 | //cx_write(channel11->dma_ctl, 0); | ||
206 | |||
207 | /* stop video capture */ | ||
208 | if (res_check(fh, RESOURCE_VIDEO11)) { | ||
209 | videobuf_queue_cancel(&fh->vidq); | ||
210 | res_free(dev, fh, RESOURCE_VIDEO11); | ||
211 | } | ||
212 | |||
213 | if (fh->vidq.read_buf) { | ||
214 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
215 | kfree(fh->vidq.read_buf); | ||
216 | } | ||
217 | |||
218 | videobuf_mmap_free(&fh->vidq); | ||
219 | |||
220 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
221 | |||
222 | file->private_data = NULL; | ||
223 | kfree(fh); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
229 | { | ||
230 | struct cx25821_fh *fh = priv; | ||
231 | struct cx25821_dev *dev = fh->dev; | ||
232 | |||
233 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | |||
237 | if (unlikely(i != fh->type)) { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) { | ||
242 | return -EBUSY; | ||
243 | } | ||
244 | |||
245 | return videobuf_streamon(get_queue(fh)); | ||
246 | } | ||
247 | |||
248 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
249 | { | ||
250 | struct cx25821_fh *fh = priv; | ||
251 | struct cx25821_dev *dev = fh->dev; | ||
252 | int err, res; | ||
253 | |||
254 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
255 | return -EINVAL; | ||
256 | if (i != fh->type) | ||
257 | return -EINVAL; | ||
258 | |||
259 | res = get_resource(fh, RESOURCE_VIDEO11); | ||
260 | err = videobuf_streamoff(get_queue(fh)); | ||
261 | if (err < 0) | ||
262 | return err; | ||
263 | res_free(dev, fh, res); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
268 | struct v4l2_format *f) | ||
269 | { | ||
270 | struct cx25821_fh *fh = priv; | ||
271 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
272 | int err; | ||
273 | |||
274 | if (fh) { | ||
275 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
276 | if (0 != err) | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | dprintk(2, "%s()\n", __func__); | ||
281 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
282 | |||
283 | if (0 != err) | ||
284 | return err; | ||
285 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
286 | fh->width = f->fmt.pix.width; | ||
287 | fh->height = f->fmt.pix.height; | ||
288 | fh->vidq.field = f->fmt.pix.field; | ||
289 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
290 | fh->height, fh->vidq.field); | ||
291 | cx25821_call_all(dev, video, s_fmt, f); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static long video_ioctl_upstream11(struct file *file, unsigned int cmd, | ||
296 | 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 | data_from_user = (struct upstream_user_struct *)arg; | ||
304 | |||
305 | if (!data_from_user) { | ||
306 | printk | ||
307 | ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", | ||
308 | __func__); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | command = data_from_user->command; | ||
313 | |||
314 | if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) { | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | dev->input_filename = data_from_user->input_filename; | ||
319 | dev->input_audiofilename = data_from_user->input_filename; | ||
320 | dev->vid_stdname = data_from_user->vid_stdname; | ||
321 | dev->pixel_format = data_from_user->pixel_format; | ||
322 | dev->channel_select = data_from_user->channel_select; | ||
323 | dev->command = data_from_user->command; | ||
324 | |||
325 | switch (command) { | ||
326 | case UPSTREAM_START_AUDIO: | ||
327 | cx25821_start_upstream_audio(dev, data_from_user); | ||
328 | break; | ||
329 | |||
330 | case UPSTREAM_STOP_AUDIO: | ||
331 | cx25821_stop_upstream_audio(dev); | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
339 | { | ||
340 | struct cx25821_fh *fh = priv; | ||
341 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
342 | } | ||
343 | |||
344 | static int vidioc_log_status(struct file *file, void *priv) | ||
345 | { | ||
346 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
347 | char name[32 + 2]; | ||
348 | |||
349 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
350 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
351 | dev->name); | ||
352 | cx25821_call_all(dev, core, log_status); | ||
353 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
354 | dev->name); | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
359 | struct v4l2_control *ctl) | ||
360 | { | ||
361 | struct cx25821_fh *fh = priv; | ||
362 | struct cx25821_dev *dev = fh->dev; | ||
363 | int err; | ||
364 | |||
365 | if (fh) { | ||
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
367 | if (0 != err) | ||
368 | return err; | ||
369 | } | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | // exported stuff | ||
374 | static const struct v4l2_file_operations video_fops = { | ||
375 | .owner = THIS_MODULE, | ||
376 | .open = video_open, | ||
377 | .release = video_release, | ||
378 | .read = video_read, | ||
379 | .poll = video_poll, | ||
380 | .mmap = video_mmap, | ||
381 | .ioctl = video_ioctl_upstream11, | ||
382 | }; | ||
383 | |||
384 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
385 | .vidioc_querycap = vidioc_querycap, | ||
386 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
387 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
388 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
389 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
390 | .vidioc_reqbufs = vidioc_reqbufs, | ||
391 | .vidioc_querybuf = vidioc_querybuf, | ||
392 | .vidioc_qbuf = vidioc_qbuf, | ||
393 | .vidioc_dqbuf = vidioc_dqbuf, | ||
394 | #ifdef TUNER_FLAG | ||
395 | .vidioc_s_std = vidioc_s_std, | ||
396 | .vidioc_querystd = vidioc_querystd, | ||
397 | #endif | ||
398 | .vidioc_cropcap = vidioc_cropcap, | ||
399 | .vidioc_s_crop = vidioc_s_crop, | ||
400 | .vidioc_g_crop = vidioc_g_crop, | ||
401 | .vidioc_enum_input = vidioc_enum_input, | ||
402 | .vidioc_g_input = vidioc_g_input, | ||
403 | .vidioc_s_input = vidioc_s_input, | ||
404 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
405 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
406 | .vidioc_queryctrl = vidioc_queryctrl, | ||
407 | .vidioc_streamon = vidioc_streamon, | ||
408 | .vidioc_streamoff = vidioc_streamoff, | ||
409 | .vidioc_log_status = vidioc_log_status, | ||
410 | .vidioc_g_priority = vidioc_g_priority, | ||
411 | .vidioc_s_priority = vidioc_s_priority, | ||
412 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
413 | .vidiocgmbuf = vidiocgmbuf, | ||
414 | #endif | ||
415 | #ifdef TUNER_FLAG | ||
416 | .vidioc_g_tuner = vidioc_g_tuner, | ||
417 | .vidioc_s_tuner = vidioc_s_tuner, | ||
418 | .vidioc_g_frequency = vidioc_g_frequency, | ||
419 | .vidioc_s_frequency = vidioc_s_frequency, | ||
420 | #endif | ||
421 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
422 | .vidioc_g_register = vidioc_g_register, | ||
423 | .vidioc_s_register = vidioc_s_register, | ||
424 | #endif | ||
425 | }; | ||
426 | |||
427 | struct video_device cx25821_video_template11 = { | ||
428 | .name = "cx25821-audioupstream", | ||
429 | .fops = &video_fops, | ||
430 | .minor = -1, | ||
431 | .ioctl_ops = &video_ioctl_ops, | ||
432 | .tvnorms = CX25821_NORMS, | ||
433 | .current_norm = V4L2_STD_NTSC_M, | ||
434 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-biffuncs.h b/drivers/staging/cx25821/cx25821-biffuncs.h new file mode 100644 index 000000000000..9326a7c729ec --- /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 000000000000..4d0b9eac3e49 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-cards.c | |||
@@ -0,0 +1,70 @@ | |||
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 | void cx25821_card_setup(struct cx25821_dev *dev) | ||
62 | { | ||
63 | static u8 eeprom[256]; | ||
64 | |||
65 | if (dev->i2c_bus[0].i2c_rc == 0) { | ||
66 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | ||
67 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, | ||
68 | sizeof(eeprom)); | ||
69 | } | ||
70 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c new file mode 100644 index 000000000000..8aceae5a072e --- /dev/null +++ b/drivers/staging/cx25821/cx25821-core.c | |||
@@ -0,0 +1,1551 @@ | |||
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 | static unsigned int cx25821_devcount = 0; | ||
44 | |||
45 | static DEFINE_MUTEX(devlist); | ||
46 | LIST_HEAD(cx25821_devlist); | ||
47 | |||
48 | struct sram_channel cx25821_sram_channels[] = { | ||
49 | [SRAM_CH00] = { | ||
50 | .i = SRAM_CH00, | ||
51 | .name = "VID A", | ||
52 | .cmds_start = VID_A_DOWN_CMDS, | ||
53 | .ctrl_start = VID_A_IQ, | ||
54 | .cdt = VID_A_CDT, | ||
55 | .fifo_start = VID_A_DOWN_CLUSTER_1, | ||
56 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
57 | .ptr1_reg = DMA1_PTR1, | ||
58 | .ptr2_reg = DMA1_PTR2, | ||
59 | .cnt1_reg = DMA1_CNT1, | ||
60 | .cnt2_reg = DMA1_CNT2, | ||
61 | .int_msk = VID_A_INT_MSK, | ||
62 | .int_stat = VID_A_INT_STAT, | ||
63 | .int_mstat = VID_A_INT_MSTAT, | ||
64 | .dma_ctl = VID_DST_A_DMA_CTL, | ||
65 | .gpcnt_ctl = VID_DST_A_GPCNT_CTL, | ||
66 | .gpcnt = VID_DST_A_GPCNT, | ||
67 | .vip_ctl = VID_DST_A_VIP_CTL, | ||
68 | .pix_frmt = VID_DST_A_PIX_FRMT, | ||
69 | }, | ||
70 | |||
71 | [SRAM_CH01] = { | ||
72 | .i = SRAM_CH01, | ||
73 | .name = "VID B", | ||
74 | .cmds_start = VID_B_DOWN_CMDS, | ||
75 | .ctrl_start = VID_B_IQ, | ||
76 | .cdt = VID_B_CDT, | ||
77 | .fifo_start = VID_B_DOWN_CLUSTER_1, | ||
78 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
79 | .ptr1_reg = DMA2_PTR1, | ||
80 | .ptr2_reg = DMA2_PTR2, | ||
81 | .cnt1_reg = DMA2_CNT1, | ||
82 | .cnt2_reg = DMA2_CNT2, | ||
83 | .int_msk = VID_B_INT_MSK, | ||
84 | .int_stat = VID_B_INT_STAT, | ||
85 | .int_mstat = VID_B_INT_MSTAT, | ||
86 | .dma_ctl = VID_DST_B_DMA_CTL, | ||
87 | .gpcnt_ctl = VID_DST_B_GPCNT_CTL, | ||
88 | .gpcnt = VID_DST_B_GPCNT, | ||
89 | .vip_ctl = VID_DST_B_VIP_CTL, | ||
90 | .pix_frmt = VID_DST_B_PIX_FRMT, | ||
91 | }, | ||
92 | |||
93 | [SRAM_CH02] = { | ||
94 | .i = SRAM_CH02, | ||
95 | .name = "VID C", | ||
96 | .cmds_start = VID_C_DOWN_CMDS, | ||
97 | .ctrl_start = VID_C_IQ, | ||
98 | .cdt = VID_C_CDT, | ||
99 | .fifo_start = VID_C_DOWN_CLUSTER_1, | ||
100 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
101 | .ptr1_reg = DMA3_PTR1, | ||
102 | .ptr2_reg = DMA3_PTR2, | ||
103 | .cnt1_reg = DMA3_CNT1, | ||
104 | .cnt2_reg = DMA3_CNT2, | ||
105 | .int_msk = VID_C_INT_MSK, | ||
106 | .int_stat = VID_C_INT_STAT, | ||
107 | .int_mstat = VID_C_INT_MSTAT, | ||
108 | .dma_ctl = VID_DST_C_DMA_CTL, | ||
109 | .gpcnt_ctl = VID_DST_C_GPCNT_CTL, | ||
110 | .gpcnt = VID_DST_C_GPCNT, | ||
111 | .vip_ctl = VID_DST_C_VIP_CTL, | ||
112 | .pix_frmt = VID_DST_C_PIX_FRMT, | ||
113 | }, | ||
114 | |||
115 | [SRAM_CH03] = { | ||
116 | .i = SRAM_CH03, | ||
117 | .name = "VID D", | ||
118 | .cmds_start = VID_D_DOWN_CMDS, | ||
119 | .ctrl_start = VID_D_IQ, | ||
120 | .cdt = VID_D_CDT, | ||
121 | .fifo_start = VID_D_DOWN_CLUSTER_1, | ||
122 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
123 | .ptr1_reg = DMA4_PTR1, | ||
124 | .ptr2_reg = DMA4_PTR2, | ||
125 | .cnt1_reg = DMA4_CNT1, | ||
126 | .cnt2_reg = DMA4_CNT2, | ||
127 | .int_msk = VID_D_INT_MSK, | ||
128 | .int_stat = VID_D_INT_STAT, | ||
129 | .int_mstat = VID_D_INT_MSTAT, | ||
130 | .dma_ctl = VID_DST_D_DMA_CTL, | ||
131 | .gpcnt_ctl = VID_DST_D_GPCNT_CTL, | ||
132 | .gpcnt = VID_DST_D_GPCNT, | ||
133 | .vip_ctl = VID_DST_D_VIP_CTL, | ||
134 | .pix_frmt = VID_DST_D_PIX_FRMT, | ||
135 | }, | ||
136 | |||
137 | [SRAM_CH04] = { | ||
138 | .i = SRAM_CH04, | ||
139 | .name = "VID E", | ||
140 | .cmds_start = VID_E_DOWN_CMDS, | ||
141 | .ctrl_start = VID_E_IQ, | ||
142 | .cdt = VID_E_CDT, | ||
143 | .fifo_start = VID_E_DOWN_CLUSTER_1, | ||
144 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
145 | .ptr1_reg = DMA5_PTR1, | ||
146 | .ptr2_reg = DMA5_PTR2, | ||
147 | .cnt1_reg = DMA5_CNT1, | ||
148 | .cnt2_reg = DMA5_CNT2, | ||
149 | .int_msk = VID_E_INT_MSK, | ||
150 | .int_stat = VID_E_INT_STAT, | ||
151 | .int_mstat = VID_E_INT_MSTAT, | ||
152 | .dma_ctl = VID_DST_E_DMA_CTL, | ||
153 | .gpcnt_ctl = VID_DST_E_GPCNT_CTL, | ||
154 | .gpcnt = VID_DST_E_GPCNT, | ||
155 | .vip_ctl = VID_DST_E_VIP_CTL, | ||
156 | .pix_frmt = VID_DST_E_PIX_FRMT, | ||
157 | }, | ||
158 | |||
159 | [SRAM_CH05] = { | ||
160 | .i = SRAM_CH05, | ||
161 | .name = "VID F", | ||
162 | .cmds_start = VID_F_DOWN_CMDS, | ||
163 | .ctrl_start = VID_F_IQ, | ||
164 | .cdt = VID_F_CDT, | ||
165 | .fifo_start = VID_F_DOWN_CLUSTER_1, | ||
166 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
167 | .ptr1_reg = DMA6_PTR1, | ||
168 | .ptr2_reg = DMA6_PTR2, | ||
169 | .cnt1_reg = DMA6_CNT1, | ||
170 | .cnt2_reg = DMA6_CNT2, | ||
171 | .int_msk = VID_F_INT_MSK, | ||
172 | .int_stat = VID_F_INT_STAT, | ||
173 | .int_mstat = VID_F_INT_MSTAT, | ||
174 | .dma_ctl = VID_DST_F_DMA_CTL, | ||
175 | .gpcnt_ctl = VID_DST_F_GPCNT_CTL, | ||
176 | .gpcnt = VID_DST_F_GPCNT, | ||
177 | .vip_ctl = VID_DST_F_VIP_CTL, | ||
178 | .pix_frmt = VID_DST_F_PIX_FRMT, | ||
179 | }, | ||
180 | |||
181 | [SRAM_CH06] = { | ||
182 | .i = SRAM_CH06, | ||
183 | .name = "VID G", | ||
184 | .cmds_start = VID_G_DOWN_CMDS, | ||
185 | .ctrl_start = VID_G_IQ, | ||
186 | .cdt = VID_G_CDT, | ||
187 | .fifo_start = VID_G_DOWN_CLUSTER_1, | ||
188 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
189 | .ptr1_reg = DMA7_PTR1, | ||
190 | .ptr2_reg = DMA7_PTR2, | ||
191 | .cnt1_reg = DMA7_CNT1, | ||
192 | .cnt2_reg = DMA7_CNT2, | ||
193 | .int_msk = VID_G_INT_MSK, | ||
194 | .int_stat = VID_G_INT_STAT, | ||
195 | .int_mstat = VID_G_INT_MSTAT, | ||
196 | .dma_ctl = VID_DST_G_DMA_CTL, | ||
197 | .gpcnt_ctl = VID_DST_G_GPCNT_CTL, | ||
198 | .gpcnt = VID_DST_G_GPCNT, | ||
199 | .vip_ctl = VID_DST_G_VIP_CTL, | ||
200 | .pix_frmt = VID_DST_G_PIX_FRMT, | ||
201 | }, | ||
202 | |||
203 | [SRAM_CH07] = { | ||
204 | .i = SRAM_CH07, | ||
205 | .name = "VID H", | ||
206 | .cmds_start = VID_H_DOWN_CMDS, | ||
207 | .ctrl_start = VID_H_IQ, | ||
208 | .cdt = VID_H_CDT, | ||
209 | .fifo_start = VID_H_DOWN_CLUSTER_1, | ||
210 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
211 | .ptr1_reg = DMA8_PTR1, | ||
212 | .ptr2_reg = DMA8_PTR2, | ||
213 | .cnt1_reg = DMA8_CNT1, | ||
214 | .cnt2_reg = DMA8_CNT2, | ||
215 | .int_msk = VID_H_INT_MSK, | ||
216 | .int_stat = VID_H_INT_STAT, | ||
217 | .int_mstat = VID_H_INT_MSTAT, | ||
218 | .dma_ctl = VID_DST_H_DMA_CTL, | ||
219 | .gpcnt_ctl = VID_DST_H_GPCNT_CTL, | ||
220 | .gpcnt = VID_DST_H_GPCNT, | ||
221 | .vip_ctl = VID_DST_H_VIP_CTL, | ||
222 | .pix_frmt = VID_DST_H_PIX_FRMT, | ||
223 | }, | ||
224 | |||
225 | [SRAM_CH08] = { | ||
226 | .name = "audio from", | ||
227 | .cmds_start = AUD_A_DOWN_CMDS, | ||
228 | .ctrl_start = AUD_A_IQ, | ||
229 | .cdt = AUD_A_CDT, | ||
230 | .fifo_start = AUD_A_DOWN_CLUSTER_1, | ||
231 | .fifo_size = AUDIO_CLUSTER_SIZE * 3, | ||
232 | .ptr1_reg = DMA17_PTR1, | ||
233 | .ptr2_reg = DMA17_PTR2, | ||
234 | .cnt1_reg = DMA17_CNT1, | ||
235 | .cnt2_reg = DMA17_CNT2, | ||
236 | }, | ||
237 | |||
238 | [SRAM_CH09] = { | ||
239 | .i = SRAM_CH09, | ||
240 | .name = "VID Upstream I", | ||
241 | .cmds_start = VID_I_UP_CMDS, | ||
242 | .ctrl_start = VID_I_IQ, | ||
243 | .cdt = VID_I_CDT, | ||
244 | .fifo_start = VID_I_UP_CLUSTER_1, | ||
245 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
246 | .ptr1_reg = DMA15_PTR1, | ||
247 | .ptr2_reg = DMA15_PTR2, | ||
248 | .cnt1_reg = DMA15_CNT1, | ||
249 | .cnt2_reg = DMA15_CNT2, | ||
250 | .int_msk = VID_I_INT_MSK, | ||
251 | .int_stat = VID_I_INT_STAT, | ||
252 | .int_mstat = VID_I_INT_MSTAT, | ||
253 | .dma_ctl = VID_SRC_I_DMA_CTL, | ||
254 | .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, | ||
255 | .gpcnt = VID_SRC_I_GPCNT, | ||
256 | |||
257 | .vid_fmt_ctl = VID_SRC_I_FMT_CTL, | ||
258 | .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1, | ||
259 | .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2, | ||
260 | .vid_cdt_size = VID_SRC_I_CDT_SZ, | ||
261 | .irq_bit = 8, | ||
262 | }, | ||
263 | |||
264 | [SRAM_CH10] = { | ||
265 | .i = SRAM_CH10, | ||
266 | .name = "VID Upstream J", | ||
267 | .cmds_start = VID_J_UP_CMDS, | ||
268 | .ctrl_start = VID_J_IQ, | ||
269 | .cdt = VID_J_CDT, | ||
270 | .fifo_start = VID_J_UP_CLUSTER_1, | ||
271 | .fifo_size = (VID_CLUSTER_SIZE << 2), | ||
272 | .ptr1_reg = DMA16_PTR1, | ||
273 | .ptr2_reg = DMA16_PTR2, | ||
274 | .cnt1_reg = DMA16_CNT1, | ||
275 | .cnt2_reg = DMA16_CNT2, | ||
276 | .int_msk = VID_J_INT_MSK, | ||
277 | .int_stat = VID_J_INT_STAT, | ||
278 | .int_mstat = VID_J_INT_MSTAT, | ||
279 | .dma_ctl = VID_SRC_J_DMA_CTL, | ||
280 | .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, | ||
281 | .gpcnt = VID_SRC_J_GPCNT, | ||
282 | |||
283 | .vid_fmt_ctl = VID_SRC_J_FMT_CTL, | ||
284 | .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1, | ||
285 | .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2, | ||
286 | .vid_cdt_size = VID_SRC_J_CDT_SZ, | ||
287 | .irq_bit = 9, | ||
288 | }, | ||
289 | |||
290 | [SRAM_CH11] = { | ||
291 | .i = SRAM_CH11, | ||
292 | .name = "Audio Upstream Channel B", | ||
293 | .cmds_start = AUD_B_UP_CMDS, | ||
294 | .ctrl_start = AUD_B_IQ, | ||
295 | .cdt = AUD_B_CDT, | ||
296 | .fifo_start = AUD_B_UP_CLUSTER_1, | ||
297 | .fifo_size = (AUDIO_CLUSTER_SIZE * 3), | ||
298 | .ptr1_reg = DMA22_PTR1, | ||
299 | .ptr2_reg = DMA22_PTR2, | ||
300 | .cnt1_reg = DMA22_CNT1, | ||
301 | .cnt2_reg = DMA22_CNT2, | ||
302 | .int_msk = AUD_B_INT_MSK, | ||
303 | .int_stat = AUD_B_INT_STAT, | ||
304 | .int_mstat = AUD_B_INT_MSTAT, | ||
305 | .dma_ctl = AUD_INT_DMA_CTL, | ||
306 | .gpcnt_ctl = AUD_B_GPCNT_CTL, | ||
307 | .gpcnt = AUD_B_GPCNT, | ||
308 | .aud_length = AUD_B_LNGTH, | ||
309 | .aud_cfg = AUD_B_CFG, | ||
310 | .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, | ||
311 | .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, | ||
312 | .irq_bit = 11, | ||
313 | }, | ||
314 | }; | ||
315 | |||
316 | struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; | ||
317 | struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; | ||
318 | struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02]; | ||
319 | struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03]; | ||
320 | struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04]; | ||
321 | struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05]; | ||
322 | struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06]; | ||
323 | struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07]; | ||
324 | struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; | ||
325 | struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10]; | ||
326 | struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11]; | ||
327 | |||
328 | struct cx25821_dmaqueue mpegq; | ||
329 | |||
330 | static int cx25821_risc_decode(u32 risc) | ||
331 | { | ||
332 | static char *instr[16] = { | ||
333 | [RISC_SYNC >> 28] = "sync", | ||
334 | [RISC_WRITE >> 28] = "write", | ||
335 | [RISC_WRITEC >> 28] = "writec", | ||
336 | [RISC_READ >> 28] = "read", | ||
337 | [RISC_READC >> 28] = "readc", | ||
338 | [RISC_JUMP >> 28] = "jump", | ||
339 | [RISC_SKIP >> 28] = "skip", | ||
340 | [RISC_WRITERM >> 28] = "writerm", | ||
341 | [RISC_WRITECM >> 28] = "writecm", | ||
342 | [RISC_WRITECR >> 28] = "writecr", | ||
343 | }; | ||
344 | static int incr[16] = { | ||
345 | [RISC_WRITE >> 28] = 3, | ||
346 | [RISC_JUMP >> 28] = 3, | ||
347 | [RISC_SKIP >> 28] = 1, | ||
348 | [RISC_SYNC >> 28] = 1, | ||
349 | [RISC_WRITERM >> 28] = 3, | ||
350 | [RISC_WRITECM >> 28] = 3, | ||
351 | [RISC_WRITECR >> 28] = 4, | ||
352 | }; | ||
353 | static char *bits[] = { | ||
354 | "12", "13", "14", "resync", | ||
355 | "cnt0", "cnt1", "18", "19", | ||
356 | "20", "21", "22", "23", | ||
357 | "irq1", "irq2", "eol", "sol", | ||
358 | }; | ||
359 | int i; | ||
360 | |||
361 | printk("0x%08x [ %s", risc, | ||
362 | instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); | ||
363 | for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) { | ||
364 | if (risc & (1 << (i + 12))) | ||
365 | printk(" %s", bits[i]); | ||
366 | } | ||
367 | printk(" count=%d ]\n", risc & 0xfff); | ||
368 | return incr[risc >> 28] ? incr[risc >> 28] : 1; | ||
369 | } | ||
370 | |||
371 | static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) | ||
372 | { | ||
373 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
374 | struct cx25821_dev *dev = bus->dev; | ||
375 | return cx_read(bus->reg_stat) & 0x01; | ||
376 | } | ||
377 | |||
378 | void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string) | ||
379 | { | ||
380 | int tmp = 0; | ||
381 | u32 value = 0; | ||
382 | |||
383 | value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); | ||
384 | } | ||
385 | |||
386 | static void cx25821_registers_init(struct cx25821_dev *dev) | ||
387 | { | ||
388 | u32 tmp; | ||
389 | |||
390 | // enable RUN_RISC in Pecos | ||
391 | cx_write(DEV_CNTRL2, 0x20); | ||
392 | |||
393 | // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts | ||
394 | // I2C interrupt masking is handled by the I2C objects themselves. | ||
395 | cx_write(PCI_INT_MSK, 0x2001FFFF); | ||
396 | |||
397 | tmp = cx_read(RDR_TLCTL0); | ||
398 | tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit | ||
399 | cx_write(RDR_TLCTL0, tmp); | ||
400 | |||
401 | // PLL-A setting for the Audio Master Clock | ||
402 | cx_write(PLL_A_INT_FRAC, 0x9807A58B); | ||
403 | |||
404 | // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 | ||
405 | cx_write(PLL_A_POST_STAT_BIST, 0x8000019C); | ||
406 | |||
407 | // clear reset bit [31] | ||
408 | tmp = cx_read(PLL_A_INT_FRAC); | ||
409 | cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); | ||
410 | |||
411 | // PLL-B setting for Mobilygen Host Bus Interface | ||
412 | cx_write(PLL_B_INT_FRAC, 0x9883A86F); | ||
413 | |||
414 | // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 | ||
415 | cx_write(PLL_B_POST_STAT_BIST, 0x8000018D); | ||
416 | |||
417 | // clear reset bit [31] | ||
418 | tmp = cx_read(PLL_B_INT_FRAC); | ||
419 | cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); | ||
420 | |||
421 | // PLL-C setting for video upstream channel | ||
422 | cx_write(PLL_C_INT_FRAC, 0x96A0EA3F); | ||
423 | |||
424 | // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 | ||
425 | cx_write(PLL_C_POST_STAT_BIST, 0x80000103); | ||
426 | |||
427 | // clear reset bit [31] | ||
428 | tmp = cx_read(PLL_C_INT_FRAC); | ||
429 | cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); | ||
430 | |||
431 | // PLL-D setting for audio upstream channel | ||
432 | cx_write(PLL_D_INT_FRAC, 0x98757F5B); | ||
433 | |||
434 | // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 | ||
435 | cx_write(PLL_D_POST_STAT_BIST, 0x80000113); | ||
436 | |||
437 | // clear reset bit [31] | ||
438 | tmp = cx_read(PLL_D_INT_FRAC); | ||
439 | cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); | ||
440 | |||
441 | // This selects the PLL C clock source for the video upstream channel I and J | ||
442 | tmp = cx_read(VID_CH_CLK_SEL); | ||
443 | cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); | ||
444 | |||
445 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
446 | //select 656/VIP DST for downstream Channel A - C | ||
447 | tmp = cx_read(VID_CH_MODE_SEL); | ||
448 | //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
449 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
450 | |||
451 | // enables 656 port I and J as output | ||
452 | tmp = cx_read(CLK_RST); | ||
453 | tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead | ||
454 | cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE)); | ||
455 | |||
456 | mdelay(100); | ||
457 | } | ||
458 | |||
459 | int cx25821_sram_channel_setup(struct cx25821_dev *dev, | ||
460 | struct sram_channel *ch, | ||
461 | unsigned int bpl, u32 risc) | ||
462 | { | ||
463 | unsigned int i, lines; | ||
464 | u32 cdt; | ||
465 | |||
466 | if (ch->cmds_start == 0) { | ||
467 | cx_write(ch->ptr1_reg, 0); | ||
468 | cx_write(ch->ptr2_reg, 0); | ||
469 | cx_write(ch->cnt2_reg, 0); | ||
470 | cx_write(ch->cnt1_reg, 0); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
475 | cdt = ch->cdt; | ||
476 | lines = ch->fifo_size / bpl; | ||
477 | |||
478 | if (lines > 4) { | ||
479 | lines = 4; | ||
480 | } | ||
481 | |||
482 | BUG_ON(lines < 2); | ||
483 | |||
484 | cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
485 | cx_write(8 + 4, 8); | ||
486 | cx_write(8 + 8, 0); | ||
487 | |||
488 | /* write CDT */ | ||
489 | for (i = 0; i < lines; i++) { | ||
490 | cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); | ||
491 | cx_write(cdt + 16 * i + 4, 0); | ||
492 | cx_write(cdt + 16 * i + 8, 0); | ||
493 | cx_write(cdt + 16 * i + 12, 0); | ||
494 | } | ||
495 | |||
496 | //init the first cdt buffer | ||
497 | for (i = 0; i < 128; i++) | ||
498 | cx_write(ch->fifo_start + 4 * i, i); | ||
499 | |||
500 | /* write CMDS */ | ||
501 | if (ch->jumponly) { | ||
502 | cx_write(ch->cmds_start + 0, 8); | ||
503 | } else { | ||
504 | cx_write(ch->cmds_start + 0, risc); | ||
505 | } | ||
506 | |||
507 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | ||
508 | cx_write(ch->cmds_start + 8, cdt); | ||
509 | cx_write(ch->cmds_start + 12, (lines * 16) >> 3); | ||
510 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
511 | |||
512 | if (ch->jumponly) | ||
513 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); | ||
514 | else | ||
515 | cx_write(ch->cmds_start + 20, 64 >> 2); | ||
516 | |||
517 | for (i = 24; i < 80; i += 4) | ||
518 | cx_write(ch->cmds_start + i, 0); | ||
519 | |||
520 | /* fill registers */ | ||
521 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
522 | cx_write(ch->ptr2_reg, cdt); | ||
523 | cx_write(ch->cnt2_reg, (lines * 16) >> 3); | ||
524 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | ||
530 | struct sram_channel *ch, | ||
531 | unsigned int bpl, u32 risc) | ||
532 | { | ||
533 | unsigned int i, lines; | ||
534 | u32 cdt; | ||
535 | |||
536 | if (ch->cmds_start == 0) { | ||
537 | cx_write(ch->ptr1_reg, 0); | ||
538 | cx_write(ch->ptr2_reg, 0); | ||
539 | cx_write(ch->cnt2_reg, 0); | ||
540 | cx_write(ch->cnt1_reg, 0); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
545 | cdt = ch->cdt; | ||
546 | lines = ch->fifo_size / bpl; | ||
547 | |||
548 | if (lines > 3) { | ||
549 | lines = 3; //for AUDIO | ||
550 | } | ||
551 | |||
552 | BUG_ON(lines < 2); | ||
553 | |||
554 | cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
555 | cx_write(8 + 4, 8); | ||
556 | cx_write(8 + 8, 0); | ||
557 | |||
558 | /* write CDT */ | ||
559 | for (i = 0; i < lines; i++) { | ||
560 | cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); | ||
561 | cx_write(cdt + 16 * i + 4, 0); | ||
562 | cx_write(cdt + 16 * i + 8, 0); | ||
563 | cx_write(cdt + 16 * i + 12, 0); | ||
564 | } | ||
565 | |||
566 | /* write CMDS */ | ||
567 | if (ch->jumponly) { | ||
568 | cx_write(ch->cmds_start + 0, 8); | ||
569 | } else { | ||
570 | cx_write(ch->cmds_start + 0, risc); | ||
571 | } | ||
572 | |||
573 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | ||
574 | cx_write(ch->cmds_start + 8, cdt); | ||
575 | cx_write(ch->cmds_start + 12, (lines * 16) >> 3); | ||
576 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
577 | |||
578 | //IQ size | ||
579 | if (ch->jumponly) { | ||
580 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); | ||
581 | } else { | ||
582 | cx_write(ch->cmds_start + 20, 64 >> 2); | ||
583 | } | ||
584 | |||
585 | //zero out | ||
586 | for (i = 24; i < 80; i += 4) | ||
587 | cx_write(ch->cmds_start + i, 0); | ||
588 | |||
589 | /* fill registers */ | ||
590 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
591 | cx_write(ch->ptr2_reg, cdt); | ||
592 | cx_write(ch->cnt2_reg, (lines * 16) >> 3); | ||
593 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | ||
599 | { | ||
600 | static char *name[] = { | ||
601 | "init risc lo", | ||
602 | "init risc hi", | ||
603 | "cdt base", | ||
604 | "cdt size", | ||
605 | "iq base", | ||
606 | "iq size", | ||
607 | "risc pc lo", | ||
608 | "risc pc hi", | ||
609 | "iq wr ptr", | ||
610 | "iq rd ptr", | ||
611 | "cdt current", | ||
612 | "pci target lo", | ||
613 | "pci target hi", | ||
614 | "line / byte", | ||
615 | }; | ||
616 | u32 risc; | ||
617 | unsigned int i, j, n; | ||
618 | |||
619 | printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, | ||
620 | ch->name); | ||
621 | for (i = 0; i < ARRAY_SIZE(name); i++) | ||
622 | printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i * 4, | ||
623 | name[i], cx_read(ch->cmds_start + 4 * i)); | ||
624 | |||
625 | j = i * 4; | ||
626 | for (i = 0; i < 4;) { | ||
627 | risc = cx_read(ch->cmds_start + 4 * (i + 14)); | ||
628 | printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); | ||
629 | i += cx25821_risc_decode(risc); | ||
630 | } | ||
631 | |||
632 | for (i = 0; i < (64 >> 2); i += n) { | ||
633 | risc = cx_read(ch->ctrl_start + 4 * i); | ||
634 | /* No consideration for bits 63-32 */ | ||
635 | |||
636 | printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, | ||
637 | ch->ctrl_start + 4 * i, i); | ||
638 | n = cx25821_risc_decode(risc); | ||
639 | for (j = 1; j < n; j++) { | ||
640 | risc = cx_read(ch->ctrl_start + 4 * (i + j)); | ||
641 | printk(KERN_WARNING | ||
642 | "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", | ||
643 | 4 * (i + j), i + j, risc, j); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", | ||
648 | ch->fifo_start, ch->fifo_start + ch->fifo_size); | ||
649 | printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", | ||
650 | ch->ctrl_start, ch->ctrl_start + 6 * 16); | ||
651 | printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", | ||
652 | cx_read(ch->ptr1_reg)); | ||
653 | printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", | ||
654 | cx_read(ch->ptr2_reg)); | ||
655 | printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", | ||
656 | cx_read(ch->cnt1_reg)); | ||
657 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", | ||
658 | cx_read(ch->cnt2_reg)); | ||
659 | } | ||
660 | |||
661 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | ||
662 | struct sram_channel *ch) | ||
663 | { | ||
664 | static char *name[] = { | ||
665 | "init risc lo", | ||
666 | "init risc hi", | ||
667 | "cdt base", | ||
668 | "cdt size", | ||
669 | "iq base", | ||
670 | "iq size", | ||
671 | "risc pc lo", | ||
672 | "risc pc hi", | ||
673 | "iq wr ptr", | ||
674 | "iq rd ptr", | ||
675 | "cdt current", | ||
676 | "pci target lo", | ||
677 | "pci target hi", | ||
678 | "line / byte", | ||
679 | }; | ||
680 | |||
681 | u32 risc, value, tmp; | ||
682 | unsigned int i, j, n; | ||
683 | |||
684 | printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", | ||
685 | dev->name, ch->name); | ||
686 | |||
687 | for (i = 0; i < ARRAY_SIZE(name); i++) | ||
688 | printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", | ||
689 | dev->name, i * 4, name[i], | ||
690 | cx_read(ch->cmds_start + 4 * i)); | ||
691 | |||
692 | j = i * 4; | ||
693 | for (i = 0; i < 4;) { | ||
694 | risc = cx_read(ch->cmds_start + 4 * (i + 14)); | ||
695 | printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); | ||
696 | i += cx25821_risc_decode(risc); | ||
697 | } | ||
698 | |||
699 | for (i = 0; i < (64 >> 2); i += n) { | ||
700 | risc = cx_read(ch->ctrl_start + 4 * i); | ||
701 | /* No consideration for bits 63-32 */ | ||
702 | |||
703 | printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, | ||
704 | ch->ctrl_start + 4 * i, i); | ||
705 | n = cx25821_risc_decode(risc); | ||
706 | |||
707 | for (j = 1; j < n; j++) { | ||
708 | risc = cx_read(ch->ctrl_start + 4 * (i + j)); | ||
709 | printk(KERN_WARNING | ||
710 | "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", | ||
711 | 4 * (i + j), i + j, risc, j); | ||
712 | } | ||
713 | } | ||
714 | |||
715 | printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", | ||
716 | ch->fifo_start, ch->fifo_start + ch->fifo_size); | ||
717 | printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", | ||
718 | ch->ctrl_start, ch->ctrl_start + 6 * 16); | ||
719 | printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", | ||
720 | cx_read(ch->ptr1_reg)); | ||
721 | printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", | ||
722 | cx_read(ch->ptr2_reg)); | ||
723 | printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", | ||
724 | cx_read(ch->cnt1_reg)); | ||
725 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", | ||
726 | cx_read(ch->cnt2_reg)); | ||
727 | |||
728 | for (i = 0; i < 4; i++) { | ||
729 | risc = cx_read(ch->cmds_start + 56 + (i * 4)); | ||
730 | printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); | ||
731 | } | ||
732 | |||
733 | //read data from the first cdt buffer | ||
734 | risc = cx_read(AUD_A_CDT); | ||
735 | printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); | ||
736 | for (i = 0; i < 8; i++) { | ||
737 | n = cx_read(risc + i * 4); | ||
738 | printk(KERN_WARNING "0x%x ", n); | ||
739 | } | ||
740 | printk(KERN_WARNING "\n\n"); | ||
741 | |||
742 | value = cx_read(CLK_RST); | ||
743 | CX25821_INFO(" CLK_RST = 0x%x \n\n", value); | ||
744 | |||
745 | value = cx_read(PLL_A_POST_STAT_BIST); | ||
746 | CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); | ||
747 | value = cx_read(PLL_A_INT_FRAC); | ||
748 | CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); | ||
749 | |||
750 | value = cx_read(PLL_B_POST_STAT_BIST); | ||
751 | CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); | ||
752 | value = cx_read(PLL_B_INT_FRAC); | ||
753 | CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); | ||
754 | |||
755 | value = cx_read(PLL_C_POST_STAT_BIST); | ||
756 | CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); | ||
757 | value = cx_read(PLL_C_INT_FRAC); | ||
758 | CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); | ||
759 | |||
760 | value = cx_read(PLL_D_POST_STAT_BIST); | ||
761 | CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); | ||
762 | value = cx_read(PLL_D_INT_FRAC); | ||
763 | CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); | ||
764 | |||
765 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | ||
766 | CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); | ||
767 | } | ||
768 | |||
769 | static void cx25821_shutdown(struct cx25821_dev *dev) | ||
770 | { | ||
771 | int i; | ||
772 | |||
773 | /* disable RISC controller */ | ||
774 | cx_write(DEV_CNTRL2, 0); | ||
775 | |||
776 | /* Disable Video A/B activity */ | ||
777 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
778 | cx_write(dev->sram_channels[i].dma_ctl, 0); | ||
779 | cx_write(dev->sram_channels[i].int_msk, 0); | ||
780 | } | ||
781 | |||
782 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; | ||
783 | i++) { | ||
784 | cx_write(dev->sram_channels[i].dma_ctl, 0); | ||
785 | cx_write(dev->sram_channels[i].int_msk, 0); | ||
786 | } | ||
787 | |||
788 | /* Disable Audio activity */ | ||
789 | cx_write(AUD_INT_DMA_CTL, 0); | ||
790 | |||
791 | /* Disable Serial port */ | ||
792 | cx_write(UART_CTL, 0); | ||
793 | |||
794 | /* Disable Interrupts */ | ||
795 | cx_write(PCI_INT_MSK, 0); | ||
796 | cx_write(AUD_A_INT_MSK, 0); | ||
797 | } | ||
798 | |||
799 | void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, | ||
800 | u32 format) | ||
801 | { | ||
802 | struct sram_channel *ch; | ||
803 | |||
804 | if (channel_select <= 7 && channel_select >= 0) { | ||
805 | ch = &cx25821_sram_channels[channel_select]; | ||
806 | cx_write(ch->pix_frmt, format); | ||
807 | dev->pixel_formats[channel_select] = format; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | static void cx25821_set_vip_mode(struct cx25821_dev *dev, | ||
812 | struct sram_channel *ch) | ||
813 | { | ||
814 | cx_write(ch->pix_frmt, PIXEL_FRMT_422); | ||
815 | cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); | ||
816 | } | ||
817 | |||
818 | static void cx25821_initialize(struct cx25821_dev *dev) | ||
819 | { | ||
820 | int i; | ||
821 | |||
822 | dprintk(1, "%s()\n", __func__); | ||
823 | |||
824 | cx25821_shutdown(dev); | ||
825 | cx_write(PCI_INT_STAT, 0xffffffff); | ||
826 | |||
827 | for (i = 0; i < VID_CHANNEL_NUM; i++) | ||
828 | cx_write(dev->sram_channels[i].int_stat, 0xffffffff); | ||
829 | |||
830 | cx_write(AUD_A_INT_STAT, 0xffffffff); | ||
831 | cx_write(AUD_B_INT_STAT, 0xffffffff); | ||
832 | cx_write(AUD_C_INT_STAT, 0xffffffff); | ||
833 | cx_write(AUD_D_INT_STAT, 0xffffffff); | ||
834 | cx_write(AUD_E_INT_STAT, 0xffffffff); | ||
835 | |||
836 | cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); | ||
837 | cx_write(PAD_CTRL, 0x12); //for I2C | ||
838 | cx25821_registers_init(dev); //init Pecos registers | ||
839 | mdelay(100); | ||
840 | |||
841 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
842 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); | ||
843 | cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, | ||
844 | 0); | ||
845 | dev->pixel_formats[i] = PIXEL_FRMT_422; | ||
846 | dev->use_cif_resolution[i] = FALSE; | ||
847 | } | ||
848 | |||
849 | //Probably only affect Downstream | ||
850 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; | ||
851 | i++) { | ||
852 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); | ||
853 | } | ||
854 | |||
855 | cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], | ||
856 | 128, 0); | ||
857 | |||
858 | cx25821_gpio_init(dev); | ||
859 | } | ||
860 | |||
861 | static int get_resources(struct cx25821_dev *dev) | ||
862 | { | ||
863 | if (request_mem_region | ||
864 | (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), | ||
865 | dev->name)) | ||
866 | return 0; | ||
867 | |||
868 | printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", | ||
869 | dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); | ||
870 | |||
871 | return -EBUSY; | ||
872 | } | ||
873 | |||
874 | static void cx25821_dev_checkrevision(struct cx25821_dev *dev) | ||
875 | { | ||
876 | dev->hwrevision = cx_read(RDR_CFG2) & 0xff; | ||
877 | |||
878 | printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, | ||
879 | dev->hwrevision); | ||
880 | } | ||
881 | |||
882 | static void cx25821_iounmap(struct cx25821_dev *dev) | ||
883 | { | ||
884 | if (dev == NULL) | ||
885 | return; | ||
886 | |||
887 | /* Releasing IO memory */ | ||
888 | if (dev->lmmio != NULL) { | ||
889 | CX25821_INFO("Releasing lmmio.\n"); | ||
890 | iounmap(dev->lmmio); | ||
891 | dev->lmmio = NULL; | ||
892 | } | ||
893 | } | ||
894 | |||
895 | static int cx25821_dev_setup(struct cx25821_dev *dev) | ||
896 | { | ||
897 | int io_size = 0, i; | ||
898 | |||
899 | struct video_device *video_template[] = { | ||
900 | &cx25821_video_template0, | ||
901 | &cx25821_video_template1, | ||
902 | &cx25821_video_template2, | ||
903 | &cx25821_video_template3, | ||
904 | &cx25821_video_template4, | ||
905 | &cx25821_video_template5, | ||
906 | &cx25821_video_template6, | ||
907 | &cx25821_video_template7, | ||
908 | &cx25821_video_template9, | ||
909 | &cx25821_video_template10, | ||
910 | &cx25821_video_template11, | ||
911 | &cx25821_videoioctl_template, | ||
912 | }; | ||
913 | |||
914 | printk(KERN_INFO "\n***********************************\n"); | ||
915 | printk(KERN_INFO "cx25821 set up\n"); | ||
916 | printk(KERN_INFO "***********************************\n\n"); | ||
917 | |||
918 | mutex_init(&dev->lock); | ||
919 | |||
920 | atomic_inc(&dev->refcount); | ||
921 | |||
922 | dev->nr = ++cx25821_devcount; | ||
923 | sprintf(dev->name, "cx25821[%d]", dev->nr); | ||
924 | |||
925 | mutex_lock(&devlist); | ||
926 | list_add_tail(&dev->devlist, &cx25821_devlist); | ||
927 | mutex_unlock(&devlist); | ||
928 | |||
929 | strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); | ||
930 | strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); | ||
931 | |||
932 | if (dev->pci->device != 0x8210) { | ||
933 | printk(KERN_INFO | ||
934 | "%s() Exiting. Incorrect Hardware device = 0x%02x\n", | ||
935 | __func__, dev->pci->device); | ||
936 | return -1; | ||
937 | } else { | ||
938 | printk(KERN_INFO "Athena Hardware device = 0x%02x\n", | ||
939 | dev->pci->device); | ||
940 | } | ||
941 | |||
942 | /* Apply a sensible clock frequency for the PCIe bridge */ | ||
943 | dev->clk_freq = 28000000; | ||
944 | dev->sram_channels = cx25821_sram_channels; | ||
945 | |||
946 | if (dev->nr > 1) { | ||
947 | CX25821_INFO("dev->nr > 1!"); | ||
948 | } | ||
949 | |||
950 | /* board config */ | ||
951 | dev->board = 1; //card[dev->nr]; | ||
952 | dev->_max_num_decoders = MAX_DECODERS; | ||
953 | |||
954 | dev->pci_bus = dev->pci->bus->number; | ||
955 | dev->pci_slot = PCI_SLOT(dev->pci->devfn); | ||
956 | dev->pci_irqmask = 0x001f00; | ||
957 | |||
958 | /* External Master 1 Bus */ | ||
959 | dev->i2c_bus[0].nr = 0; | ||
960 | dev->i2c_bus[0].dev = dev; | ||
961 | dev->i2c_bus[0].reg_stat = I2C1_STAT; | ||
962 | dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; | ||
963 | dev->i2c_bus[0].reg_addr = I2C1_ADDR; | ||
964 | dev->i2c_bus[0].reg_rdata = I2C1_RDATA; | ||
965 | dev->i2c_bus[0].reg_wdata = I2C1_WDATA; | ||
966 | dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ | ||
967 | |||
968 | |||
969 | if (get_resources(dev) < 0) { | ||
970 | printk(KERN_ERR "%s No more PCIe resources for " | ||
971 | "subsystem: %04x:%04x\n", | ||
972 | dev->name, dev->pci->subsystem_vendor, | ||
973 | dev->pci->subsystem_device); | ||
974 | |||
975 | cx25821_devcount--; | ||
976 | return -ENODEV; | ||
977 | } | ||
978 | |||
979 | /* PCIe stuff */ | ||
980 | dev->base_io_addr = pci_resource_start(dev->pci, 0); | ||
981 | io_size = pci_resource_len(dev->pci, 0); | ||
982 | |||
983 | if (!dev->base_io_addr) { | ||
984 | CX25821_ERR("No PCI Memory resources, exiting!\n"); | ||
985 | return -ENODEV; | ||
986 | } | ||
987 | |||
988 | dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | ||
989 | |||
990 | if (!dev->lmmio) { | ||
991 | CX25821_ERR | ||
992 | ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); | ||
993 | cx25821_iounmap(dev); | ||
994 | return -ENOMEM; | ||
995 | } | ||
996 | |||
997 | dev->bmmio = (u8 __iomem *) dev->lmmio; | ||
998 | |||
999 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | ||
1000 | dev->name, dev->pci->subsystem_vendor, | ||
1001 | dev->pci->subsystem_device, cx25821_boards[dev->board].name, | ||
1002 | dev->board, card[dev->nr] == dev->board ? | ||
1003 | "insmod option" : "autodetected"); | ||
1004 | |||
1005 | /* init hardware */ | ||
1006 | cx25821_initialize(dev); | ||
1007 | |||
1008 | cx25821_i2c_register(&dev->i2c_bus[0]); | ||
1009 | // cx25821_i2c_register(&dev->i2c_bus[1]); | ||
1010 | // cx25821_i2c_register(&dev->i2c_bus[2]); | ||
1011 | |||
1012 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", | ||
1013 | dev->i2c_bus[0].i2c_rc); | ||
1014 | |||
1015 | cx25821_card_setup(dev); | ||
1016 | medusa_video_init(dev); | ||
1017 | |||
1018 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
1019 | if (cx25821_video_register(dev, i, video_template[i]) < 0) { | ||
1020 | printk(KERN_ERR | ||
1021 | "%s() Failed to register analog video adapters on VID channel %d\n", | ||
1022 | __func__, i); | ||
1023 | } | ||
1024 | } | ||
1025 | |||
1026 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; | ||
1027 | i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { | ||
1028 | //Since we don't have template8 for Audio Downstream | ||
1029 | if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) { | ||
1030 | printk(KERN_ERR | ||
1031 | "%s() Failed to register analog video adapters for Upstream channel %d.\n", | ||
1032 | __func__, i); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | // register IOCTL device | ||
1037 | dev->ioctl_dev = | ||
1038 | cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], | ||
1039 | "video"); | ||
1040 | |||
1041 | if (video_register_device | ||
1042 | (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { | ||
1043 | cx25821_videoioctl_unregister(dev); | ||
1044 | printk(KERN_ERR | ||
1045 | "%s() Failed to register video adapter for IOCTL so releasing.\n", | ||
1046 | __func__); | ||
1047 | } | ||
1048 | |||
1049 | cx25821_dev_checkrevision(dev); | ||
1050 | CX25821_INFO("cx25821 setup done!\n"); | ||
1051 | |||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, | ||
1056 | struct upstream_user_struct *up_data) | ||
1057 | { | ||
1058 | dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0; | ||
1059 | |||
1060 | dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1061 | medusa_set_videostandard(dev); | ||
1062 | |||
1063 | cx25821_vidupstream_init_ch1(dev, dev->channel_select, | ||
1064 | dev->pixel_format); | ||
1065 | } | ||
1066 | |||
1067 | void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, | ||
1068 | struct upstream_user_struct *up_data) | ||
1069 | { | ||
1070 | dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0; | ||
1071 | |||
1072 | dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1073 | medusa_set_videostandard(dev); | ||
1074 | |||
1075 | cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, | ||
1076 | dev->pixel_format_ch2); | ||
1077 | } | ||
1078 | |||
1079 | void cx25821_start_upstream_audio(struct cx25821_dev *dev, | ||
1080 | struct upstream_user_struct *up_data) | ||
1081 | { | ||
1082 | cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); | ||
1083 | } | ||
1084 | |||
1085 | void cx25821_dev_unregister(struct cx25821_dev *dev) | ||
1086 | { | ||
1087 | int i; | ||
1088 | |||
1089 | if (!dev->base_io_addr) | ||
1090 | return; | ||
1091 | |||
1092 | cx25821_free_mem_upstream_ch1(dev); | ||
1093 | cx25821_free_mem_upstream_ch2(dev); | ||
1094 | cx25821_free_mem_upstream_audio(dev); | ||
1095 | |||
1096 | release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | ||
1097 | |||
1098 | if (!atomic_dec_and_test(&dev->refcount)) | ||
1099 | return; | ||
1100 | |||
1101 | for (i = 0; i < VID_CHANNEL_NUM; i++) | ||
1102 | cx25821_video_unregister(dev, i); | ||
1103 | |||
1104 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; | ||
1105 | i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { | ||
1106 | cx25821_video_unregister(dev, i); | ||
1107 | } | ||
1108 | |||
1109 | cx25821_videoioctl_unregister(dev); | ||
1110 | |||
1111 | cx25821_i2c_unregister(&dev->i2c_bus[0]); | ||
1112 | cx25821_iounmap(dev); | ||
1113 | } | ||
1114 | |||
1115 | static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, | ||
1116 | unsigned int offset, u32 sync_line, | ||
1117 | unsigned int bpl, unsigned int padding, | ||
1118 | unsigned int lines) | ||
1119 | { | ||
1120 | struct scatterlist *sg; | ||
1121 | unsigned int line, todo; | ||
1122 | |||
1123 | /* sync instruction */ | ||
1124 | if (sync_line != NO_SYNC_LINE) { | ||
1125 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
1126 | } | ||
1127 | |||
1128 | /* scan lines */ | ||
1129 | sg = sglist; | ||
1130 | for (line = 0; line < lines; line++) { | ||
1131 | while (offset && offset >= sg_dma_len(sg)) { | ||
1132 | offset -= sg_dma_len(sg); | ||
1133 | sg++; | ||
1134 | } | ||
1135 | if (bpl <= sg_dma_len(sg) - offset) { | ||
1136 | /* fits into current chunk */ | ||
1137 | *(rp++) = | ||
1138 | cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl); | ||
1139 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | ||
1140 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1141 | offset += bpl; | ||
1142 | } else { | ||
1143 | /* scanline needs to be split */ | ||
1144 | todo = bpl; | ||
1145 | *(rp++) = | ||
1146 | cpu_to_le32(RISC_WRITE | RISC_SOL | | ||
1147 | (sg_dma_len(sg) - offset)); | ||
1148 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | ||
1149 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1150 | todo -= (sg_dma_len(sg) - offset); | ||
1151 | offset = 0; | ||
1152 | sg++; | ||
1153 | while (todo > sg_dma_len(sg)) { | ||
1154 | *(rp++) = | ||
1155 | cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); | ||
1156 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1157 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1158 | todo -= sg_dma_len(sg); | ||
1159 | sg++; | ||
1160 | } | ||
1161 | *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); | ||
1162 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1163 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1164 | offset += todo; | ||
1165 | } | ||
1166 | |||
1167 | offset += padding; | ||
1168 | } | ||
1169 | |||
1170 | return rp; | ||
1171 | } | ||
1172 | |||
1173 | int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
1174 | struct scatterlist *sglist, unsigned int top_offset, | ||
1175 | unsigned int bottom_offset, unsigned int bpl, | ||
1176 | unsigned int padding, unsigned int lines) | ||
1177 | { | ||
1178 | u32 instructions; | ||
1179 | u32 fields; | ||
1180 | __le32 *rp; | ||
1181 | int rc; | ||
1182 | |||
1183 | fields = 0; | ||
1184 | if (UNSET != top_offset) | ||
1185 | fields++; | ||
1186 | if (UNSET != bottom_offset) | ||
1187 | fields++; | ||
1188 | |||
1189 | /* estimate risc mem: worst case is one write per page border + | ||
1190 | one write per scan line + syncs + jump (all 2 dwords). Padding | ||
1191 | can cause next bpl to start close to a page border. First DMA | ||
1192 | region may be smaller than PAGE_SIZE */ | ||
1193 | /* write and jump need and extra dword */ | ||
1194 | instructions = | ||
1195 | fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | ||
1196 | instructions += 2; | ||
1197 | rc = btcx_riscmem_alloc(pci, risc, instructions * 12); | ||
1198 | |||
1199 | if (rc < 0) | ||
1200 | return rc; | ||
1201 | |||
1202 | /* write risc instructions */ | ||
1203 | rp = risc->cpu; | ||
1204 | |||
1205 | if (UNSET != top_offset) { | ||
1206 | rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, | ||
1207 | lines); | ||
1208 | } | ||
1209 | |||
1210 | if (UNSET != bottom_offset) { | ||
1211 | rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, | ||
1212 | padding, lines); | ||
1213 | } | ||
1214 | |||
1215 | /* save pointer to jmp instruction address */ | ||
1216 | risc->jmp = rp; | ||
1217 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); | ||
1218 | |||
1219 | return 0; | ||
1220 | } | ||
1221 | |||
1222 | static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, | ||
1223 | unsigned int offset, u32 sync_line, | ||
1224 | unsigned int bpl, unsigned int padding, | ||
1225 | unsigned int lines, unsigned int lpi) | ||
1226 | { | ||
1227 | struct scatterlist *sg; | ||
1228 | unsigned int line, todo, sol; | ||
1229 | |||
1230 | /* sync instruction */ | ||
1231 | if (sync_line != NO_SYNC_LINE) | ||
1232 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
1233 | |||
1234 | /* scan lines */ | ||
1235 | sg = sglist; | ||
1236 | for (line = 0; line < lines; line++) { | ||
1237 | while (offset && offset >= sg_dma_len(sg)) { | ||
1238 | offset -= sg_dma_len(sg); | ||
1239 | sg++; | ||
1240 | } | ||
1241 | |||
1242 | if (lpi && line > 0 && !(line % lpi)) | ||
1243 | sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; | ||
1244 | else | ||
1245 | sol = RISC_SOL; | ||
1246 | |||
1247 | if (bpl <= sg_dma_len(sg) - offset) { | ||
1248 | /* fits into current chunk */ | ||
1249 | *(rp++) = | ||
1250 | cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl); | ||
1251 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | ||
1252 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1253 | offset += bpl; | ||
1254 | } else { | ||
1255 | /* scanline needs to be split */ | ||
1256 | todo = bpl; | ||
1257 | *(rp++) = cpu_to_le32(RISC_WRITE | sol | | ||
1258 | (sg_dma_len(sg) - offset)); | ||
1259 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | ||
1260 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1261 | todo -= (sg_dma_len(sg) - offset); | ||
1262 | offset = 0; | ||
1263 | sg++; | ||
1264 | while (todo > sg_dma_len(sg)) { | ||
1265 | *(rp++) = cpu_to_le32(RISC_WRITE | | ||
1266 | sg_dma_len(sg)); | ||
1267 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1268 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1269 | todo -= sg_dma_len(sg); | ||
1270 | sg++; | ||
1271 | } | ||
1272 | *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); | ||
1273 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | ||
1274 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1275 | offset += todo; | ||
1276 | } | ||
1277 | offset += padding; | ||
1278 | } | ||
1279 | |||
1280 | return rp; | ||
1281 | } | ||
1282 | |||
1283 | int cx25821_risc_databuffer_audio(struct pci_dev *pci, | ||
1284 | struct btcx_riscmem *risc, | ||
1285 | struct scatterlist *sglist, | ||
1286 | unsigned int bpl, | ||
1287 | unsigned int lines, unsigned int lpi) | ||
1288 | { | ||
1289 | u32 instructions; | ||
1290 | __le32 *rp; | ||
1291 | int rc; | ||
1292 | |||
1293 | /* estimate risc mem: worst case is one write per page border + | ||
1294 | one write per scan line + syncs + jump (all 2 dwords). Here | ||
1295 | there is no padding and no sync. First DMA region may be smaller | ||
1296 | than PAGE_SIZE */ | ||
1297 | /* Jump and write need an extra dword */ | ||
1298 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; | ||
1299 | instructions += 1; | ||
1300 | |||
1301 | if ((rc = btcx_riscmem_alloc(pci, risc, instructions * 12)) < 0) | ||
1302 | return rc; | ||
1303 | |||
1304 | /* write risc instructions */ | ||
1305 | rp = risc->cpu; | ||
1306 | rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, | ||
1307 | lines, lpi); | ||
1308 | |||
1309 | /* save pointer to jmp instruction address */ | ||
1310 | risc->jmp = rp; | ||
1311 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
1316 | u32 reg, u32 mask, u32 value) | ||
1317 | { | ||
1318 | __le32 *rp; | ||
1319 | int rc; | ||
1320 | |||
1321 | rc = btcx_riscmem_alloc(pci, risc, 4 * 16); | ||
1322 | |||
1323 | if (rc < 0) | ||
1324 | return rc; | ||
1325 | |||
1326 | /* write risc instructions */ | ||
1327 | rp = risc->cpu; | ||
1328 | |||
1329 | *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); | ||
1330 | *(rp++) = cpu_to_le32(reg); | ||
1331 | *(rp++) = cpu_to_le32(value); | ||
1332 | *(rp++) = cpu_to_le32(mask); | ||
1333 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
1334 | *(rp++) = cpu_to_le32(risc->dma); | ||
1335 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) | ||
1340 | { | ||
1341 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | ||
1342 | |||
1343 | BUG_ON(in_interrupt()); | ||
1344 | videobuf_waiton(&buf->vb, 0, 0); | ||
1345 | videobuf_dma_unmap(q, dma); | ||
1346 | videobuf_dma_free(dma); | ||
1347 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); | ||
1348 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
1349 | } | ||
1350 | |||
1351 | static irqreturn_t cx25821_irq(int irq, void *dev_id) | ||
1352 | { | ||
1353 | struct cx25821_dev *dev = dev_id; | ||
1354 | u32 pci_status, pci_mask; | ||
1355 | u32 vid_status; | ||
1356 | int i, handled = 0; | ||
1357 | u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; | ||
1358 | |||
1359 | pci_status = cx_read(PCI_INT_STAT); | ||
1360 | pci_mask = cx_read(PCI_INT_MSK); | ||
1361 | |||
1362 | if (pci_status == 0) | ||
1363 | goto out; | ||
1364 | |||
1365 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
1366 | if (pci_status & mask[i]) { | ||
1367 | vid_status = cx_read(dev->sram_channels[i].int_stat); | ||
1368 | |||
1369 | if (vid_status) | ||
1370 | handled += | ||
1371 | cx25821_video_irq(dev, i, vid_status); | ||
1372 | |||
1373 | cx_write(PCI_INT_STAT, mask[i]); | ||
1374 | } | ||
1375 | } | ||
1376 | |||
1377 | out: | ||
1378 | return IRQ_RETVAL(handled); | ||
1379 | } | ||
1380 | |||
1381 | void cx25821_print_irqbits(char *name, char *tag, char **strings, | ||
1382 | int len, u32 bits, u32 mask) | ||
1383 | { | ||
1384 | unsigned int i; | ||
1385 | |||
1386 | printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); | ||
1387 | |||
1388 | for (i = 0; i < len; i++) { | ||
1389 | if (!(bits & (1 << i))) | ||
1390 | continue; | ||
1391 | if (strings[i]) | ||
1392 | printk(" %s", strings[i]); | ||
1393 | else | ||
1394 | printk(" %d", i); | ||
1395 | if (!(mask & (1 << i))) | ||
1396 | continue; | ||
1397 | printk("*"); | ||
1398 | } | ||
1399 | printk("\n"); | ||
1400 | } | ||
1401 | |||
1402 | struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci) | ||
1403 | { | ||
1404 | struct cx25821_dev *dev = pci_get_drvdata(pci); | ||
1405 | return dev; | ||
1406 | } | ||
1407 | |||
1408 | static int __devinit cx25821_initdev(struct pci_dev *pci_dev, | ||
1409 | const struct pci_device_id *pci_id) | ||
1410 | { | ||
1411 | struct cx25821_dev *dev; | ||
1412 | int err = 0; | ||
1413 | |||
1414 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1415 | if (NULL == dev) | ||
1416 | return -ENOMEM; | ||
1417 | |||
1418 | err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); | ||
1419 | if (err < 0) | ||
1420 | goto fail_free; | ||
1421 | |||
1422 | /* pci init */ | ||
1423 | dev->pci = pci_dev; | ||
1424 | if (pci_enable_device(pci_dev)) { | ||
1425 | err = -EIO; | ||
1426 | |||
1427 | printk(KERN_INFO "pci enable failed! "); | ||
1428 | |||
1429 | goto fail_unregister_device; | ||
1430 | } | ||
1431 | |||
1432 | printk(KERN_INFO "cx25821 Athena pci enable ! \n"); | ||
1433 | |||
1434 | if (cx25821_dev_setup(dev) < 0) { | ||
1435 | err = -EINVAL; | ||
1436 | goto fail_unregister_device; | ||
1437 | } | ||
1438 | |||
1439 | /* print pci info */ | ||
1440 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | ||
1441 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | ||
1442 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | ||
1443 | "latency: %d, mmio: 0x%llx\n", dev->name, | ||
1444 | pci_name(pci_dev), dev->pci_rev, pci_dev->irq, | ||
1445 | dev->pci_lat, (unsigned long long)dev->base_io_addr); | ||
1446 | |||
1447 | pci_set_master(pci_dev); | ||
1448 | if (!pci_dma_supported(pci_dev, 0xffffffff)) { | ||
1449 | printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); | ||
1450 | err = -EIO; | ||
1451 | goto fail_irq; | ||
1452 | } | ||
1453 | |||
1454 | err = | ||
1455 | request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, | ||
1456 | dev->name, dev); | ||
1457 | |||
1458 | if (err < 0) { | ||
1459 | printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, | ||
1460 | pci_dev->irq); | ||
1461 | goto fail_irq; | ||
1462 | } | ||
1463 | |||
1464 | return 0; | ||
1465 | |||
1466 | fail_irq: | ||
1467 | printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); | ||
1468 | cx25821_dev_unregister(dev); | ||
1469 | |||
1470 | fail_unregister_device: | ||
1471 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1472 | |||
1473 | fail_free: | ||
1474 | kfree(dev); | ||
1475 | return err; | ||
1476 | } | ||
1477 | |||
1478 | static void __devexit cx25821_finidev(struct pci_dev *pci_dev) | ||
1479 | { | ||
1480 | struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); | ||
1481 | struct cx25821_dev *dev = get_cx25821(v4l2_dev); | ||
1482 | |||
1483 | cx25821_shutdown(dev); | ||
1484 | pci_disable_device(pci_dev); | ||
1485 | |||
1486 | /* unregister stuff */ | ||
1487 | if (pci_dev->irq) | ||
1488 | free_irq(pci_dev->irq, dev); | ||
1489 | |||
1490 | mutex_lock(&devlist); | ||
1491 | list_del(&dev->devlist); | ||
1492 | mutex_unlock(&devlist); | ||
1493 | |||
1494 | cx25821_dev_unregister(dev); | ||
1495 | v4l2_device_unregister(v4l2_dev); | ||
1496 | kfree(dev); | ||
1497 | } | ||
1498 | |||
1499 | static struct pci_device_id cx25821_pci_tbl[] = { | ||
1500 | { | ||
1501 | /* CX25821 Athena */ | ||
1502 | .vendor = 0x14f1, | ||
1503 | .device = 0x8210, | ||
1504 | .subvendor = 0x14f1, | ||
1505 | .subdevice = 0x0920, | ||
1506 | }, | ||
1507 | { | ||
1508 | /* --- end of list --- */ | ||
1509 | } | ||
1510 | }; | ||
1511 | |||
1512 | MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl); | ||
1513 | |||
1514 | static struct pci_driver cx25821_pci_driver = { | ||
1515 | .name = "cx25821", | ||
1516 | .id_table = cx25821_pci_tbl, | ||
1517 | .probe = cx25821_initdev, | ||
1518 | .remove = __devexit_p(cx25821_finidev), | ||
1519 | /* TODO */ | ||
1520 | .suspend = NULL, | ||
1521 | .resume = NULL, | ||
1522 | }; | ||
1523 | |||
1524 | static int cx25821_init(void) | ||
1525 | { | ||
1526 | INIT_LIST_HEAD(&cx25821_devlist); | ||
1527 | printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", | ||
1528 | (CX25821_VERSION_CODE >> 16) & 0xff, | ||
1529 | (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff); | ||
1530 | return pci_register_driver(&cx25821_pci_driver); | ||
1531 | } | ||
1532 | |||
1533 | static void cx25821_fini(void) | ||
1534 | { | ||
1535 | pci_unregister_driver(&cx25821_pci_driver); | ||
1536 | } | ||
1537 | |||
1538 | EXPORT_SYMBOL(cx25821_devlist); | ||
1539 | EXPORT_SYMBOL(cx25821_sram_channels); | ||
1540 | EXPORT_SYMBOL(cx25821_print_irqbits); | ||
1541 | EXPORT_SYMBOL(cx25821_dev_get); | ||
1542 | EXPORT_SYMBOL(cx25821_dev_unregister); | ||
1543 | EXPORT_SYMBOL(cx25821_sram_channel_setup); | ||
1544 | EXPORT_SYMBOL(cx25821_sram_channel_dump); | ||
1545 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); | ||
1546 | EXPORT_SYMBOL(cx25821_sram_channel_dump_audio); | ||
1547 | EXPORT_SYMBOL(cx25821_risc_databuffer_audio); | ||
1548 | EXPORT_SYMBOL(cx25821_set_gpiopin_direction); | ||
1549 | |||
1550 | module_init(cx25821_init); | ||
1551 | module_exit(cx25821_fini); | ||
diff --git a/drivers/staging/cx25821/cx25821-gpio.c b/drivers/staging/cx25821/cx25821-gpio.c new file mode 100644 index 000000000000..e8a37b47e437 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-gpio.c | |||
@@ -0,0 +1,98 @@ | |||
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 | /********************* GPIO stuffs *********************/ | ||
26 | void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, | ||
27 | int pin_number, int pin_logic_value) | ||
28 | { | ||
29 | int bit = pin_number; | ||
30 | u32 gpio_oe_reg = GPIO_LO_OE; | ||
31 | u32 gpio_register = 0; | ||
32 | u32 value = 0; | ||
33 | |||
34 | // Check for valid pinNumber | ||
35 | if (pin_number >= 47) | ||
36 | return; | ||
37 | |||
38 | if (pin_number > 31) { | ||
39 | bit = pin_number - 31; | ||
40 | gpio_oe_reg = GPIO_HI_OE; | ||
41 | } | ||
42 | // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is | ||
43 | gpio_register = cx_read(gpio_oe_reg); | ||
44 | |||
45 | if (pin_logic_value == 1) { | ||
46 | value = gpio_register | Set_GPIO_Bit(bit); | ||
47 | } else { | ||
48 | value = gpio_register & Clear_GPIO_Bit(bit); | ||
49 | } | ||
50 | |||
51 | cx_write(gpio_oe_reg, value); | ||
52 | } | ||
53 | |||
54 | static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev, | ||
55 | int pin_number, int pin_logic_value) | ||
56 | { | ||
57 | int bit = pin_number; | ||
58 | u32 gpio_reg = GPIO_LO; | ||
59 | u32 value = 0; | ||
60 | |||
61 | // Check for valid pinNumber | ||
62 | if (pin_number >= 47) | ||
63 | return; | ||
64 | |||
65 | cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction | ||
66 | |||
67 | if (pin_number > 31) { | ||
68 | bit = pin_number - 31; | ||
69 | gpio_reg = GPIO_HI; | ||
70 | } | ||
71 | |||
72 | value = cx_read(gpio_reg); | ||
73 | |||
74 | if (pin_logic_value == 0) { | ||
75 | value &= Clear_GPIO_Bit(bit); | ||
76 | } else { | ||
77 | value |= Set_GPIO_Bit(bit); | ||
78 | } | ||
79 | |||
80 | cx_write(gpio_reg, value); | ||
81 | } | ||
82 | |||
83 | void cx25821_gpio_init(struct cx25821_dev *dev) | ||
84 | { | ||
85 | if (dev == NULL) { | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | switch (dev->board) { | ||
90 | case CX25821_BOARD_CONEXANT_ATHENA10: | ||
91 | default: | ||
92 | //set GPIO 5 to select the path for Medusa/Athena | ||
93 | cx25821_set_gpiopin_logicvalue(dev, 5, 1); | ||
94 | mdelay(20); | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-gpio.h b/drivers/staging/cx25821/cx25821-gpio.h new file mode 100644 index 000000000000..ca07644154af --- /dev/null +++ b/drivers/staging/cx25821/cx25821-gpio.h | |||
@@ -0,0 +1,2 @@ | |||
1 | |||
2 | void cx25821_gpio_init(struct athena_dev *dev); | ||
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c new file mode 100644 index 000000000000..f4f2681d8f1c --- /dev/null +++ b/drivers/staging/cx25821/cx25821-i2c.c | |||
@@ -0,0 +1,419 @@ | |||
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 | static unsigned int i2c_debug; | ||
28 | module_param(i2c_debug, int, 0644); | ||
29 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
30 | |||
31 | static unsigned int i2c_scan = 0; | ||
32 | module_param(i2c_scan, int, 0444); | ||
33 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | ||
34 | |||
35 | #define dprintk(level, fmt, arg...)\ | ||
36 | do { if (i2c_debug >= level)\ | ||
37 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ | ||
38 | } while (0) | ||
39 | |||
40 | #define I2C_WAIT_DELAY 32 | ||
41 | #define I2C_WAIT_RETRY 64 | ||
42 | |||
43 | #define I2C_EXTEND (1 << 3) | ||
44 | #define I2C_NOSTOP (1 << 4) | ||
45 | |||
46 | static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) | ||
47 | { | ||
48 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
49 | struct cx25821_dev *dev = bus->dev; | ||
50 | return cx_read(bus->reg_stat) & 0x01; | ||
51 | } | ||
52 | |||
53 | static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) | ||
54 | { | ||
55 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
56 | struct cx25821_dev *dev = bus->dev; | ||
57 | return cx_read(bus->reg_stat) & 0x02 ? 1 : 0; | ||
58 | } | ||
59 | |||
60 | static int i2c_wait_done(struct i2c_adapter *i2c_adap) | ||
61 | { | ||
62 | int count; | ||
63 | |||
64 | for (count = 0; count < I2C_WAIT_RETRY; count++) { | ||
65 | if (!i2c_is_busy(i2c_adap)) | ||
66 | break; | ||
67 | udelay(I2C_WAIT_DELAY); | ||
68 | } | ||
69 | |||
70 | if (I2C_WAIT_RETRY == count) | ||
71 | return 0; | ||
72 | |||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | static int i2c_sendbytes(struct i2c_adapter *i2c_adap, | ||
77 | const struct i2c_msg *msg, int joined_rlen) | ||
78 | { | ||
79 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
80 | struct cx25821_dev *dev = bus->dev; | ||
81 | u32 wdata, addr, ctrl; | ||
82 | int retval, cnt; | ||
83 | |||
84 | if (joined_rlen) | ||
85 | dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, | ||
86 | 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 | cx_write(bus->reg_addr, msg->addr << 25); | ||
93 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); | ||
94 | |||
95 | if (!i2c_wait_done(i2c_adap)) | ||
96 | return -EIO; | ||
97 | |||
98 | if (!i2c_slave_did_ack(i2c_adap)) | ||
99 | return -EIO; | ||
100 | |||
101 | dprintk(1, "%s() returns 0\n", __func__); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | /* dev, reg + first byte */ | ||
106 | addr = (msg->addr << 25) | msg->buf[0]; | ||
107 | wdata = msg->buf[0]; | ||
108 | |||
109 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
110 | |||
111 | if (msg->len > 1) | ||
112 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
113 | else if (joined_rlen) | ||
114 | ctrl |= I2C_NOSTOP; | ||
115 | |||
116 | cx_write(bus->reg_addr, addr); | ||
117 | cx_write(bus->reg_wdata, wdata); | ||
118 | cx_write(bus->reg_ctrl, ctrl); | ||
119 | |||
120 | retval = i2c_wait_done(i2c_adap); | ||
121 | if (retval < 0) | ||
122 | goto err; | ||
123 | |||
124 | if (retval == 0) | ||
125 | goto eio; | ||
126 | |||
127 | if (i2c_debug) { | ||
128 | if (!(ctrl & I2C_NOSTOP)) | ||
129 | printk(" >\n"); | ||
130 | } | ||
131 | |||
132 | for (cnt = 1; cnt < msg->len; cnt++) { | ||
133 | /* following bytes */ | ||
134 | wdata = msg->buf[cnt]; | ||
135 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
136 | |||
137 | if (cnt < msg->len - 1) | ||
138 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
139 | else if (joined_rlen) | ||
140 | ctrl |= I2C_NOSTOP; | ||
141 | |||
142 | cx_write(bus->reg_addr, addr); | ||
143 | cx_write(bus->reg_wdata, wdata); | ||
144 | cx_write(bus->reg_ctrl, ctrl); | ||
145 | |||
146 | retval = i2c_wait_done(i2c_adap); | ||
147 | if (retval < 0) | ||
148 | goto err; | ||
149 | |||
150 | if (retval == 0) | ||
151 | goto eio; | ||
152 | |||
153 | if (i2c_debug) { | ||
154 | dprintk(1, " %02x", msg->buf[cnt]); | ||
155 | if (!(ctrl & I2C_NOSTOP)) | ||
156 | dprintk(1, " >\n"); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | return msg->len; | ||
161 | |||
162 | eio: | ||
163 | retval = -EIO; | ||
164 | err: | ||
165 | if (i2c_debug) | ||
166 | printk(KERN_ERR " ERR: %d\n", retval); | ||
167 | return retval; | ||
168 | } | ||
169 | |||
170 | static int i2c_readbytes(struct i2c_adapter *i2c_adap, | ||
171 | const struct i2c_msg *msg, int joined) | ||
172 | { | ||
173 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
174 | struct cx25821_dev *dev = bus->dev; | ||
175 | u32 ctrl, cnt; | ||
176 | int retval; | ||
177 | |||
178 | if (i2c_debug && !joined) | ||
179 | dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len); | ||
180 | |||
181 | /* Deal with i2c probe functions with zero payload */ | ||
182 | if (msg->len == 0) { | ||
183 | cx_write(bus->reg_addr, msg->addr << 25); | ||
184 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1); | ||
185 | if (!i2c_wait_done(i2c_adap)) | ||
186 | return -EIO; | ||
187 | if (!i2c_slave_did_ack(i2c_adap)) | ||
188 | return -EIO; | ||
189 | |||
190 | dprintk(1, "%s() returns 0\n", __func__); | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | if (i2c_debug) { | ||
195 | if (joined) | ||
196 | dprintk(1, " R"); | ||
197 | else | ||
198 | dprintk(1, " <R %02x", (msg->addr << 1) + 1); | ||
199 | } | ||
200 | |||
201 | for (cnt = 0; cnt < msg->len; cnt++) { | ||
202 | |||
203 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1; | ||
204 | |||
205 | if (cnt < msg->len - 1) | ||
206 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
207 | |||
208 | cx_write(bus->reg_addr, msg->addr << 25); | ||
209 | cx_write(bus->reg_ctrl, ctrl); | ||
210 | |||
211 | retval = i2c_wait_done(i2c_adap); | ||
212 | if (retval < 0) | ||
213 | goto err; | ||
214 | if (retval == 0) | ||
215 | goto eio; | ||
216 | msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; | ||
217 | |||
218 | if (i2c_debug) { | ||
219 | dprintk(1, " %02x", msg->buf[cnt]); | ||
220 | if (!(ctrl & I2C_NOSTOP)) | ||
221 | dprintk(1, " >\n"); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | return msg->len; | ||
226 | eio: | ||
227 | retval = -EIO; | ||
228 | err: | ||
229 | if (i2c_debug) | ||
230 | printk(KERN_ERR " ERR: %d\n", retval); | ||
231 | return retval; | ||
232 | } | ||
233 | |||
234 | static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | ||
235 | { | ||
236 | struct cx25821_i2c *bus = i2c_adap->algo_data; | ||
237 | struct cx25821_dev *dev = bus->dev; | ||
238 | int i, retval = 0; | ||
239 | |||
240 | dprintk(1, "%s(num = %d)\n", __func__, num); | ||
241 | |||
242 | for (i = 0; i < num; i++) { | ||
243 | dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", | ||
244 | __func__, num, msgs[i].addr, msgs[i].len); | ||
245 | |||
246 | if (msgs[i].flags & I2C_M_RD) { | ||
247 | /* read */ | ||
248 | retval = i2c_readbytes(i2c_adap, &msgs[i], 0); | ||
249 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | ||
250 | msgs[i].addr == msgs[i + 1].addr) { | ||
251 | /* write then read from same address */ | ||
252 | retval = | ||
253 | i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); | ||
254 | |||
255 | if (retval < 0) | ||
256 | goto err; | ||
257 | i++; | ||
258 | retval = i2c_readbytes(i2c_adap, &msgs[i], 1); | ||
259 | } else { | ||
260 | /* write */ | ||
261 | retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); | ||
262 | } | ||
263 | |||
264 | if (retval < 0) | ||
265 | goto err; | ||
266 | } | ||
267 | return num; | ||
268 | |||
269 | err: | ||
270 | return retval; | ||
271 | } | ||
272 | |||
273 | |||
274 | static u32 cx25821_functionality(struct i2c_adapter *adap) | ||
275 | { | ||
276 | return I2C_FUNC_SMBUS_EMUL | | ||
277 | I2C_FUNC_I2C | | ||
278 | I2C_FUNC_SMBUS_WORD_DATA | | ||
279 | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; | ||
280 | } | ||
281 | |||
282 | static struct i2c_algorithm cx25821_i2c_algo_template = { | ||
283 | .master_xfer = i2c_xfer, | ||
284 | .functionality = cx25821_functionality, | ||
285 | }; | ||
286 | |||
287 | static struct i2c_adapter cx25821_i2c_adap_template = { | ||
288 | .name = "cx25821", | ||
289 | .owner = THIS_MODULE, | ||
290 | .algo = &cx25821_i2c_algo_template, | ||
291 | }; | ||
292 | |||
293 | static struct i2c_client cx25821_i2c_client_template = { | ||
294 | .name = "cx25821 internal", | ||
295 | }; | ||
296 | |||
297 | /* init + register i2c algo-bit adapter */ | ||
298 | int cx25821_i2c_register(struct cx25821_i2c *bus) | ||
299 | { | ||
300 | struct cx25821_dev *dev = bus->dev; | ||
301 | |||
302 | dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); | ||
303 | |||
304 | memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template, | ||
305 | sizeof(bus->i2c_adap)); | ||
306 | memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template, | ||
307 | sizeof(bus->i2c_algo)); | ||
308 | memcpy(&bus->i2c_client, &cx25821_i2c_client_template, | ||
309 | sizeof(bus->i2c_client)); | ||
310 | |||
311 | bus->i2c_adap.dev.parent = &dev->pci->dev; | ||
312 | |||
313 | strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); | ||
314 | |||
315 | bus->i2c_algo.data = bus; | ||
316 | bus->i2c_adap.algo_data = bus; | ||
317 | i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); | ||
318 | i2c_add_adapter(&bus->i2c_adap); | ||
319 | |||
320 | bus->i2c_client.adapter = &bus->i2c_adap; | ||
321 | |||
322 | //set up the I2c | ||
323 | bus->i2c_client.addr = (0x88 >> 1); | ||
324 | |||
325 | return bus->i2c_rc; | ||
326 | } | ||
327 | |||
328 | int cx25821_i2c_unregister(struct cx25821_i2c *bus) | ||
329 | { | ||
330 | i2c_del_adapter(&bus->i2c_adap); | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | void cx25821_av_clk(struct cx25821_dev *dev, int enable) | ||
335 | { | ||
336 | /* write 0 to bus 2 addr 0x144 via i2x_xfer() */ | ||
337 | char buffer[3]; | ||
338 | struct i2c_msg msg; | ||
339 | dprintk(1, "%s(enabled = %d)\n", __func__, enable); | ||
340 | |||
341 | /* Register 0x144 */ | ||
342 | buffer[0] = 0x01; | ||
343 | buffer[1] = 0x44; | ||
344 | if (enable == 1) | ||
345 | buffer[2] = 0x05; | ||
346 | else | ||
347 | buffer[2] = 0x00; | ||
348 | |||
349 | msg.addr = 0x44; | ||
350 | msg.flags = I2C_M_TEN; | ||
351 | msg.len = 3; | ||
352 | msg.buf = buffer; | ||
353 | |||
354 | i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1); | ||
355 | } | ||
356 | |||
357 | int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) | ||
358 | { | ||
359 | struct i2c_client *client = &bus->i2c_client; | ||
360 | int retval = 0; | ||
361 | int v = 0; | ||
362 | u8 addr[2] = { 0, 0 }; | ||
363 | u8 buf[4] = { 0, 0, 0, 0 }; | ||
364 | |||
365 | struct i2c_msg msgs[2] = { | ||
366 | { | ||
367 | .addr = client->addr, | ||
368 | .flags = 0, | ||
369 | .len = 2, | ||
370 | .buf = addr, | ||
371 | }, { | ||
372 | .addr = client->addr, | ||
373 | .flags = I2C_M_RD, | ||
374 | .len = 4, | ||
375 | .buf = buf, | ||
376 | } | ||
377 | }; | ||
378 | |||
379 | addr[0] = (reg_addr >> 8); | ||
380 | addr[1] = (reg_addr & 0xff); | ||
381 | msgs[0].addr = 0x44; | ||
382 | msgs[1].addr = 0x44; | ||
383 | |||
384 | retval = i2c_xfer(client->adapter, msgs, 2); | ||
385 | |||
386 | v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
387 | *value = v; | ||
388 | |||
389 | return v; | ||
390 | } | ||
391 | |||
392 | int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value) | ||
393 | { | ||
394 | struct i2c_client *client = &bus->i2c_client; | ||
395 | int retval = 0; | ||
396 | u8 buf[6] = { 0, 0, 0, 0, 0, 0 }; | ||
397 | |||
398 | struct i2c_msg msgs[1] = { | ||
399 | { | ||
400 | .addr = client->addr, | ||
401 | .flags = 0, | ||
402 | .len = 6, | ||
403 | .buf = buf, | ||
404 | } | ||
405 | }; | ||
406 | |||
407 | buf[0] = reg_addr >> 8; | ||
408 | buf[1] = reg_addr & 0xff; | ||
409 | buf[5] = (value >> 24) & 0xff; | ||
410 | buf[4] = (value >> 16) & 0xff; | ||
411 | buf[3] = (value >> 8) & 0xff; | ||
412 | buf[2] = value & 0xff; | ||
413 | client->flags = 0; | ||
414 | msgs[0].addr = 0x44; | ||
415 | |||
416 | retval = i2c_xfer(client->adapter, msgs, 1); | ||
417 | |||
418 | return retval; | ||
419 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-defines.h b/drivers/staging/cx25821/cx25821-medusa-defines.h new file mode 100644 index 000000000000..b0d216ba7f81 --- /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 000000000000..12c90f831b22 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-reg.h | |||
@@ -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 | * | ||
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 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c new file mode 100644 index 000000000000..e4df8134f059 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-video.c | |||
@@ -0,0 +1,869 @@ | |||
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 | //medusa_enable_bluefield_output() | ||
29 | // | ||
30 | // Enable the generation of blue filed output if no video | ||
31 | // | ||
32 | static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, | ||
33 | 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 | switch (channel) { | ||
42 | default: | ||
43 | case VDEC_A: | ||
44 | break; | ||
45 | case VDEC_B: | ||
46 | out_ctrl = VDEC_B_OUT_CTRL1; | ||
47 | out_ctrl_ns = VDEC_B_OUT_CTRL_NS; | ||
48 | break; | ||
49 | case VDEC_C: | ||
50 | out_ctrl = VDEC_C_OUT_CTRL1; | ||
51 | out_ctrl_ns = VDEC_C_OUT_CTRL_NS; | ||
52 | break; | ||
53 | case VDEC_D: | ||
54 | out_ctrl = VDEC_D_OUT_CTRL1; | ||
55 | out_ctrl_ns = VDEC_D_OUT_CTRL_NS; | ||
56 | break; | ||
57 | case VDEC_E: | ||
58 | out_ctrl = VDEC_E_OUT_CTRL1; | ||
59 | out_ctrl_ns = VDEC_E_OUT_CTRL_NS; | ||
60 | return; | ||
61 | case VDEC_F: | ||
62 | out_ctrl = VDEC_F_OUT_CTRL1; | ||
63 | out_ctrl_ns = VDEC_F_OUT_CTRL_NS; | ||
64 | return; | ||
65 | case VDEC_G: | ||
66 | out_ctrl = VDEC_G_OUT_CTRL1; | ||
67 | out_ctrl_ns = VDEC_G_OUT_CTRL_NS; | ||
68 | return; | ||
69 | case VDEC_H: | ||
70 | out_ctrl = VDEC_H_OUT_CTRL1; | ||
71 | out_ctrl_ns = VDEC_H_OUT_CTRL_NS; | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); | ||
76 | value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN | ||
77 | if (enable) | ||
78 | value |= 0x00000080; // set BLUE_FIELD_EN | ||
79 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); | ||
80 | |||
81 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); | ||
82 | value &= 0xFFFFFF7F; | ||
83 | if (enable) | ||
84 | value |= 0x00000080; // set BLUE_FIELD_EN | ||
85 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); | ||
86 | } | ||
87 | |||
88 | static int medusa_initialize_ntsc(struct cx25821_dev *dev) | ||
89 | { | ||
90 | int ret_val = 0; | ||
91 | int i = 0; | ||
92 | u32 value = 0; | ||
93 | u32 tmp = 0; | ||
94 | |||
95 | mutex_lock(&dev->lock); | ||
96 | |||
97 | for (i = 0; i < MAX_DECODERS; i++) { | ||
98 | // set video format NTSC-M | ||
99 | value = | ||
100 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | ||
101 | &tmp); | ||
102 | value &= 0xFFFFFFF0; | ||
103 | value |= 0x10001; // enable the fast locking mode bit[16] | ||
104 | ret_val = | ||
105 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | ||
106 | value); | ||
107 | |||
108 | // resolution NTSC 720x480 | ||
109 | value = | ||
110 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
111 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | ||
112 | value &= 0x00C00C00; | ||
113 | value |= 0x612D0074; | ||
114 | ret_val = | ||
115 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
116 | HORIZ_TIM_CTRL + (0x200 * i), value); | ||
117 | |||
118 | value = | ||
119 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
120 | VERT_TIM_CTRL + (0x200 * i), &tmp); | ||
121 | value &= 0x00C00C00; | ||
122 | value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID | ||
123 | ret_val = | ||
124 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
125 | VERT_TIM_CTRL + (0x200 * i), value); | ||
126 | |||
127 | // chroma subcarrier step size | ||
128 | ret_val = | ||
129 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
130 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); | ||
131 | |||
132 | // enable VIP optional active | ||
133 | value = | ||
134 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
135 | OUT_CTRL_NS + (0x200 * i), &tmp); | ||
136 | value &= 0xFFFBFFFF; | ||
137 | value |= 0x00040000; | ||
138 | ret_val = | ||
139 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
140 | OUT_CTRL_NS + (0x200 * i), value); | ||
141 | |||
142 | // enable VIP optional active (VIP_OPT_AL) for direct output. | ||
143 | value = | ||
144 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | ||
145 | &tmp); | ||
146 | value &= 0xFFFBFFFF; | ||
147 | value |= 0x00040000; | ||
148 | ret_val = | ||
149 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | ||
150 | value); | ||
151 | |||
152 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | ||
153 | // when the input switching rate < 16 fields | ||
154 | // | ||
155 | value = | ||
156 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
157 | MISC_TIM_CTRL + (0x200 * i), &tmp); | ||
158 | value = setBitAtPos(value, 14); // disable special play detection | ||
159 | value = clearBitAtPos(value, 15); | ||
160 | ret_val = | ||
161 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
162 | MISC_TIM_CTRL + (0x200 * i), value); | ||
163 | |||
164 | // set vbi_gate_en to 0 | ||
165 | value = | ||
166 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | ||
167 | &tmp); | ||
168 | value = clearBitAtPos(value, 29); | ||
169 | ret_val = | ||
170 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | ||
171 | value); | ||
172 | |||
173 | // Enable the generation of blue field output if no video | ||
174 | medusa_enable_bluefield_output(dev, i, 1); | ||
175 | } | ||
176 | |||
177 | for (i = 0; i < MAX_ENCODERS; i++) { | ||
178 | // NTSC hclock | ||
179 | value = | ||
180 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
181 | DENC_A_REG_1 + (0x100 * i), &tmp); | ||
182 | value &= 0xF000FC00; | ||
183 | value |= 0x06B402D0; | ||
184 | ret_val = | ||
185 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
186 | DENC_A_REG_1 + (0x100 * i), value); | ||
187 | |||
188 | // burst begin and burst end | ||
189 | value = | ||
190 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
191 | DENC_A_REG_2 + (0x100 * i), &tmp); | ||
192 | value &= 0xFF000000; | ||
193 | value |= 0x007E9054; | ||
194 | ret_val = | ||
195 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
196 | DENC_A_REG_2 + (0x100 * i), value); | ||
197 | |||
198 | value = | ||
199 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
200 | DENC_A_REG_3 + (0x100 * i), &tmp); | ||
201 | value &= 0xFC00FE00; | ||
202 | value |= 0x00EC00F0; | ||
203 | ret_val = | ||
204 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
205 | DENC_A_REG_3 + (0x100 * i), value); | ||
206 | |||
207 | // set NTSC vblank, no phase alternation, 7.5 IRE pedestal | ||
208 | value = | ||
209 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
210 | DENC_A_REG_4 + (0x100 * i), &tmp); | ||
211 | value &= 0x00FCFFFF; | ||
212 | value |= 0x13020000; | ||
213 | ret_val = | ||
214 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
215 | DENC_A_REG_4 + (0x100 * i), value); | ||
216 | |||
217 | value = | ||
218 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
219 | DENC_A_REG_5 + (0x100 * i), &tmp); | ||
220 | value &= 0xFFFF0000; | ||
221 | value |= 0x0000E575; | ||
222 | ret_val = | ||
223 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
224 | DENC_A_REG_5 + (0x100 * i), value); | ||
225 | |||
226 | ret_val = | ||
227 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
228 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); | ||
229 | |||
230 | // Subcarrier Increment | ||
231 | ret_val = | ||
232 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
233 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); | ||
234 | } | ||
235 | |||
236 | //set picture resolutions | ||
237 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | ||
238 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 | ||
239 | |||
240 | // set Bypass input format to NTSC 525 lines | ||
241 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
242 | value |= 0x00080200; | ||
243 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
244 | |||
245 | mutex_unlock(&dev->lock); | ||
246 | |||
247 | return ret_val; | ||
248 | } | ||
249 | |||
250 | static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | ||
251 | { | ||
252 | int ret_val = -1; | ||
253 | u32 value = 0, tmp = 0; | ||
254 | |||
255 | // Setup for 2D threshold | ||
256 | ret_val = | ||
257 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), | ||
258 | 0x20002861); | ||
259 | ret_val = | ||
260 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec), | ||
261 | 0x20002861); | ||
262 | ret_val = | ||
263 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), | ||
264 | 0x200A1023); | ||
265 | |||
266 | // Setup flat chroma and luma thresholds | ||
267 | value = | ||
268 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
269 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); | ||
270 | value &= 0x06230000; | ||
271 | ret_val = | ||
272 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
273 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); | ||
274 | |||
275 | // set comb 2D blend | ||
276 | ret_val = | ||
277 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), | ||
278 | 0x210F0F0F); | ||
279 | |||
280 | // COMB MISC CONTROL | ||
281 | ret_val = | ||
282 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), | ||
283 | 0x41120A7F); | ||
284 | |||
285 | return ret_val; | ||
286 | } | ||
287 | |||
288 | static int medusa_initialize_pal(struct cx25821_dev *dev) | ||
289 | { | ||
290 | int ret_val = 0; | ||
291 | int i = 0; | ||
292 | u32 value = 0; | ||
293 | u32 tmp = 0; | ||
294 | |||
295 | mutex_lock(&dev->lock); | ||
296 | |||
297 | for (i = 0; i < MAX_DECODERS; i++) { | ||
298 | // set video format PAL-BDGHI | ||
299 | value = | ||
300 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | ||
301 | &tmp); | ||
302 | value &= 0xFFFFFFF0; | ||
303 | value |= 0x10004; // enable the fast locking mode bit[16] | ||
304 | ret_val = | ||
305 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | ||
306 | value); | ||
307 | |||
308 | // resolution PAL 720x576 | ||
309 | value = | ||
310 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
311 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | ||
312 | value &= 0x00C00C00; | ||
313 | value |= 0x632D007D; | ||
314 | ret_val = | ||
315 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
316 | HORIZ_TIM_CTRL + (0x200 * i), value); | ||
317 | |||
318 | // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 | ||
319 | value = | ||
320 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
321 | VERT_TIM_CTRL + (0x200 * i), &tmp); | ||
322 | value &= 0x00C00C00; | ||
323 | value |= 0x28240026; // vblank_cnt + 2 to get camera ID | ||
324 | ret_val = | ||
325 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
326 | VERT_TIM_CTRL + (0x200 * i), value); | ||
327 | |||
328 | // chroma subcarrier step size | ||
329 | ret_val = | ||
330 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
331 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); | ||
332 | |||
333 | // enable VIP optional active | ||
334 | value = | ||
335 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
336 | OUT_CTRL_NS + (0x200 * i), &tmp); | ||
337 | value &= 0xFFFBFFFF; | ||
338 | value |= 0x00040000; | ||
339 | ret_val = | ||
340 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
341 | OUT_CTRL_NS + (0x200 * i), value); | ||
342 | |||
343 | // enable VIP optional active (VIP_OPT_AL) for direct output. | ||
344 | value = | ||
345 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | ||
346 | &tmp); | ||
347 | value &= 0xFFFBFFFF; | ||
348 | value |= 0x00040000; | ||
349 | ret_val = | ||
350 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | ||
351 | value); | ||
352 | |||
353 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | ||
354 | // when the input switching rate < 16 fields | ||
355 | value = | ||
356 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
357 | MISC_TIM_CTRL + (0x200 * i), &tmp); | ||
358 | value = setBitAtPos(value, 14); // disable special play detection | ||
359 | value = clearBitAtPos(value, 15); | ||
360 | ret_val = | ||
361 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
362 | MISC_TIM_CTRL + (0x200 * i), value); | ||
363 | |||
364 | // set vbi_gate_en to 0 | ||
365 | value = | ||
366 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | ||
367 | &tmp); | ||
368 | value = clearBitAtPos(value, 29); | ||
369 | ret_val = | ||
370 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | ||
371 | value); | ||
372 | |||
373 | medusa_PALCombInit(dev, i); | ||
374 | |||
375 | // Enable the generation of blue field output if no video | ||
376 | medusa_enable_bluefield_output(dev, i, 1); | ||
377 | } | ||
378 | |||
379 | for (i = 0; i < MAX_ENCODERS; i++) { | ||
380 | // PAL hclock | ||
381 | value = | ||
382 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
383 | DENC_A_REG_1 + (0x100 * i), &tmp); | ||
384 | value &= 0xF000FC00; | ||
385 | value |= 0x06C002D0; | ||
386 | ret_val = | ||
387 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
388 | DENC_A_REG_1 + (0x100 * i), value); | ||
389 | |||
390 | // burst begin and burst end | ||
391 | value = | ||
392 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
393 | DENC_A_REG_2 + (0x100 * i), &tmp); | ||
394 | value &= 0xFF000000; | ||
395 | value |= 0x007E9754; | ||
396 | ret_val = | ||
397 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
398 | DENC_A_REG_2 + (0x100 * i), value); | ||
399 | |||
400 | // hblank and vactive | ||
401 | value = | ||
402 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
403 | DENC_A_REG_3 + (0x100 * i), &tmp); | ||
404 | value &= 0xFC00FE00; | ||
405 | value |= 0x00FC0120; | ||
406 | ret_val = | ||
407 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
408 | DENC_A_REG_3 + (0x100 * i), value); | ||
409 | |||
410 | // set PAL vblank, phase alternation, 0 IRE pedestal | ||
411 | value = | ||
412 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
413 | DENC_A_REG_4 + (0x100 * i), &tmp); | ||
414 | value &= 0x00FCFFFF; | ||
415 | value |= 0x14010000; | ||
416 | ret_val = | ||
417 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
418 | DENC_A_REG_4 + (0x100 * i), value); | ||
419 | |||
420 | value = | ||
421 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
422 | DENC_A_REG_5 + (0x100 * i), &tmp); | ||
423 | value &= 0xFFFF0000; | ||
424 | value |= 0x0000F078; | ||
425 | ret_val = | ||
426 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
427 | DENC_A_REG_5 + (0x100 * i), value); | ||
428 | |||
429 | ret_val = | ||
430 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
431 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); | ||
432 | |||
433 | // Subcarrier Increment | ||
434 | ret_val = | ||
435 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
436 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); | ||
437 | } | ||
438 | |||
439 | //set picture resolutions | ||
440 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | ||
441 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 | ||
442 | |||
443 | // set Bypass input format to PAL 625 lines | ||
444 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
445 | value &= 0xFFF7FDFF; | ||
446 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
447 | |||
448 | mutex_unlock(&dev->lock); | ||
449 | |||
450 | return ret_val; | ||
451 | } | ||
452 | |||
453 | int medusa_set_videostandard(struct cx25821_dev *dev) | ||
454 | { | ||
455 | int status = STATUS_SUCCESS; | ||
456 | u32 value = 0, tmp = 0; | ||
457 | |||
458 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) { | ||
459 | status = medusa_initialize_pal(dev); | ||
460 | } else { | ||
461 | status = medusa_initialize_ntsc(dev); | ||
462 | } | ||
463 | |||
464 | // Enable DENC_A output | ||
465 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); | ||
466 | value = setBitAtPos(value, 4); | ||
467 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); | ||
468 | |||
469 | // Enable DENC_B output | ||
470 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); | ||
471 | value = setBitAtPos(value, 4); | ||
472 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); | ||
473 | |||
474 | return status; | ||
475 | } | ||
476 | |||
477 | void medusa_set_resolution(struct cx25821_dev *dev, int width, | ||
478 | int decoder_select) | ||
479 | { | ||
480 | int decoder = 0; | ||
481 | int decoder_count = 0; | ||
482 | int ret_val = 0; | ||
483 | u32 hscale = 0x0; | ||
484 | u32 vscale = 0x0; | ||
485 | const int MAX_WIDTH = 720; | ||
486 | |||
487 | mutex_lock(&dev->lock); | ||
488 | |||
489 | // validate the width - cannot be negative | ||
490 | if (width > MAX_WIDTH) { | ||
491 | printk | ||
492 | ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", | ||
493 | __func__, width, MAX_WIDTH); | ||
494 | width = MAX_WIDTH; | ||
495 | } | ||
496 | |||
497 | if (decoder_select <= 7 && decoder_select >= 0) { | ||
498 | decoder = decoder_select; | ||
499 | decoder_count = decoder_select + 1; | ||
500 | } else { | ||
501 | decoder = 0; | ||
502 | decoder_count = _num_decoders; | ||
503 | } | ||
504 | |||
505 | switch (width) { | ||
506 | case 320: | ||
507 | hscale = 0x13E34B; | ||
508 | vscale = 0x0; | ||
509 | break; | ||
510 | |||
511 | case 352: | ||
512 | hscale = 0x10A273; | ||
513 | vscale = 0x0; | ||
514 | break; | ||
515 | |||
516 | case 176: | ||
517 | hscale = 0x3115B2; | ||
518 | vscale = 0x1E00; | ||
519 | break; | ||
520 | |||
521 | case 160: | ||
522 | hscale = 0x378D84; | ||
523 | vscale = 0x1E00; | ||
524 | break; | ||
525 | |||
526 | default: //720 | ||
527 | hscale = 0x0; | ||
528 | vscale = 0x0; | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | for (; decoder < decoder_count; decoder++) { | ||
533 | // write scaling values for each decoder | ||
534 | ret_val = | ||
535 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
536 | HSCALE_CTRL + (0x200 * decoder), hscale); | ||
537 | ret_val = | ||
538 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
539 | VSCALE_CTRL + (0x200 * decoder), vscale); | ||
540 | } | ||
541 | |||
542 | mutex_unlock(&dev->lock); | ||
543 | } | ||
544 | |||
545 | static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | ||
546 | int duration) | ||
547 | { | ||
548 | int ret_val = 0; | ||
549 | u32 fld_cnt = 0; | ||
550 | u32 tmp = 0; | ||
551 | u32 disp_cnt_reg = DISP_AB_CNT; | ||
552 | |||
553 | mutex_lock(&dev->lock); | ||
554 | |||
555 | // no support | ||
556 | if (decoder < VDEC_A && decoder > VDEC_H) { | ||
557 | mutex_unlock(&dev->lock); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | switch (decoder) { | ||
562 | default: | ||
563 | break; | ||
564 | case VDEC_C: | ||
565 | case VDEC_D: | ||
566 | disp_cnt_reg = DISP_CD_CNT; | ||
567 | break; | ||
568 | case VDEC_E: | ||
569 | case VDEC_F: | ||
570 | disp_cnt_reg = DISP_EF_CNT; | ||
571 | break; | ||
572 | case VDEC_G: | ||
573 | case VDEC_H: | ||
574 | disp_cnt_reg = DISP_GH_CNT; | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | _display_field_cnt[decoder] = duration; | ||
579 | |||
580 | // update hardware | ||
581 | fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); | ||
582 | |||
583 | if (!(decoder % 2)) // EVEN decoder | ||
584 | { | ||
585 | fld_cnt &= 0xFFFF0000; | ||
586 | fld_cnt |= duration; | ||
587 | } else { | ||
588 | fld_cnt &= 0x0000FFFF; | ||
589 | fld_cnt |= ((u32) duration) << 16; | ||
590 | } | ||
591 | |||
592 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); | ||
593 | |||
594 | mutex_unlock(&dev->lock); | ||
595 | } | ||
596 | |||
597 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
598 | // Map to Medusa register setting | ||
599 | static int mapM(int srcMin, | ||
600 | int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) | ||
601 | { | ||
602 | int numerator; | ||
603 | int denominator; | ||
604 | int quotient; | ||
605 | |||
606 | if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) { | ||
607 | return -1; | ||
608 | } | ||
609 | // This is the overall expression used: | ||
610 | // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; | ||
611 | // but we need to account for rounding so below we use the modulus | ||
612 | // operator to find the remainder and increment if necessary. | ||
613 | numerator = (srcVal - srcMin) * (dstMax - dstMin); | ||
614 | denominator = srcMax - srcMin; | ||
615 | quotient = numerator / denominator; | ||
616 | |||
617 | if (2 * (numerator % denominator) >= denominator) { | ||
618 | quotient++; | ||
619 | } | ||
620 | |||
621 | *dstVal = quotient + dstMin; | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static unsigned long convert_to_twos(long numeric, unsigned long bits_len) | ||
627 | { | ||
628 | unsigned char temp; | ||
629 | |||
630 | if (numeric >= 0) | ||
631 | return numeric; | ||
632 | else { | ||
633 | temp = ~(abs(numeric) & 0xFF); | ||
634 | temp += 1; | ||
635 | return temp; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
640 | int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | ||
641 | { | ||
642 | int ret_val = 0; | ||
643 | int value = 0; | ||
644 | u32 val = 0, tmp = 0; | ||
645 | |||
646 | mutex_lock(&dev->lock); | ||
647 | if ((brightness > VIDEO_PROCAMP_MAX) | ||
648 | || (brightness < VIDEO_PROCAMP_MIN)) { | ||
649 | mutex_unlock(&dev->lock); | ||
650 | return -1; | ||
651 | } | ||
652 | ret_val = | ||
653 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, | ||
654 | SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); | ||
655 | value = convert_to_twos(value, 8); | ||
656 | val = | ||
657 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
658 | VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); | ||
659 | val &= 0xFFFFFF00; | ||
660 | ret_val |= | ||
661 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
662 | VDEC_A_BRITE_CTRL + (0x200 * decoder), | ||
663 | val | value); | ||
664 | mutex_unlock(&dev->lock); | ||
665 | return ret_val; | ||
666 | } | ||
667 | |||
668 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
669 | int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | ||
670 | { | ||
671 | int ret_val = 0; | ||
672 | int value = 0; | ||
673 | u32 val = 0, tmp = 0; | ||
674 | |||
675 | mutex_lock(&dev->lock); | ||
676 | |||
677 | if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { | ||
678 | mutex_unlock(&dev->lock); | ||
679 | return -1; | ||
680 | } | ||
681 | |||
682 | ret_val = | ||
683 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, | ||
684 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | ||
685 | val = | ||
686 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
687 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); | ||
688 | val &= 0xFFFFFF00; | ||
689 | ret_val |= | ||
690 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
691 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), | ||
692 | val | value); | ||
693 | |||
694 | mutex_unlock(&dev->lock); | ||
695 | return ret_val; | ||
696 | } | ||
697 | |||
698 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
699 | int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | ||
700 | { | ||
701 | int ret_val = 0; | ||
702 | int value = 0; | ||
703 | u32 val = 0, tmp = 0; | ||
704 | |||
705 | mutex_lock(&dev->lock); | ||
706 | |||
707 | if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { | ||
708 | mutex_unlock(&dev->lock); | ||
709 | return -1; | ||
710 | } | ||
711 | |||
712 | ret_val = | ||
713 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, | ||
714 | SIGNED_BYTE_MAX, &value); | ||
715 | |||
716 | value = convert_to_twos(value, 8); | ||
717 | val = | ||
718 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
719 | VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); | ||
720 | val &= 0xFFFFFF00; | ||
721 | |||
722 | ret_val |= | ||
723 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
724 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); | ||
725 | |||
726 | mutex_unlock(&dev->lock); | ||
727 | return ret_val; | ||
728 | } | ||
729 | |||
730 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
731 | int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | ||
732 | { | ||
733 | int ret_val = 0; | ||
734 | int value = 0; | ||
735 | u32 val = 0, tmp = 0; | ||
736 | |||
737 | mutex_lock(&dev->lock); | ||
738 | |||
739 | if ((saturation > VIDEO_PROCAMP_MAX) | ||
740 | || (saturation < VIDEO_PROCAMP_MIN)) { | ||
741 | mutex_unlock(&dev->lock); | ||
742 | return -1; | ||
743 | } | ||
744 | |||
745 | ret_val = | ||
746 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, | ||
747 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | ||
748 | |||
749 | val = | ||
750 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
751 | VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); | ||
752 | val &= 0xFFFFFF00; | ||
753 | ret_val |= | ||
754 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
755 | VDEC_A_USAT_CTRL + (0x200 * decoder), | ||
756 | val | value); | ||
757 | |||
758 | val = | ||
759 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
760 | VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); | ||
761 | val &= 0xFFFFFF00; | ||
762 | ret_val |= | ||
763 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
764 | VDEC_A_VSAT_CTRL + (0x200 * decoder), | ||
765 | val | value); | ||
766 | |||
767 | mutex_unlock(&dev->lock); | ||
768 | return ret_val; | ||
769 | } | ||
770 | |||
771 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
772 | // Program the display sequence and monitor output. | ||
773 | // | ||
774 | int medusa_video_init(struct cx25821_dev *dev) | ||
775 | { | ||
776 | u32 value = 0, tmp = 0; | ||
777 | int ret_val = 0; | ||
778 | int i = 0; | ||
779 | |||
780 | mutex_lock(&dev->lock); | ||
781 | |||
782 | _num_decoders = dev->_max_num_decoders; | ||
783 | |||
784 | // disable Auto source selection on all video decoders | ||
785 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | ||
786 | value &= 0xFFFFF0FF; | ||
787 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | ||
788 | |||
789 | if (ret_val < 0) { | ||
790 | mutex_unlock(&dev->lock); | ||
791 | return -EINVAL; | ||
792 | } | ||
793 | // Turn off Master source switch enable | ||
794 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | ||
795 | value &= 0xFFFFFFDF; | ||
796 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | ||
797 | |||
798 | if (ret_val < 0) { | ||
799 | mutex_unlock(&dev->lock); | ||
800 | return -EINVAL; | ||
801 | } | ||
802 | |||
803 | mutex_unlock(&dev->lock); | ||
804 | |||
805 | for (i = 0; i < _num_decoders; i++) { | ||
806 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); | ||
807 | } | ||
808 | |||
809 | mutex_lock(&dev->lock); | ||
810 | |||
811 | // Select monitor as DENC A input, power up the DAC | ||
812 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); | ||
813 | value &= 0xFF70FF70; | ||
814 | value |= 0x00090008; // set en_active | ||
815 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); | ||
816 | |||
817 | if (ret_val < 0) { | ||
818 | mutex_unlock(&dev->lock); | ||
819 | return -EINVAL; | ||
820 | } | ||
821 | // enable input is VIP/656 | ||
822 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | ||
823 | value |= 0x00040100; // enable VIP | ||
824 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | ||
825 | |||
826 | if (ret_val < 0) { | ||
827 | mutex_unlock(&dev->lock); | ||
828 | return -EINVAL; | ||
829 | } | ||
830 | // select AFE clock to output mode | ||
831 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | ||
832 | value &= 0x83FFFFFF; | ||
833 | ret_val = | ||
834 | cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, | ||
835 | value | 0x10000000); | ||
836 | |||
837 | if (ret_val < 0) { | ||
838 | mutex_unlock(&dev->lock); | ||
839 | return -EINVAL; | ||
840 | } | ||
841 | // Turn on all of the data out and control output pins. | ||
842 | value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); | ||
843 | value &= 0xFEF0FE00; | ||
844 | if (_num_decoders == MAX_DECODERS) { | ||
845 | // Note: The octal board does not support control pins(bit16-19). | ||
846 | // These bits are ignored in the octal board. | ||
847 | value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface | ||
848 | } else { | ||
849 | value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface | ||
850 | } | ||
851 | |||
852 | value |= 7; | ||
853 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); | ||
854 | if (ret_val < 0) { | ||
855 | mutex_unlock(&dev->lock); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | |||
859 | mutex_unlock(&dev->lock); | ||
860 | |||
861 | ret_val = medusa_set_videostandard(dev); | ||
862 | |||
863 | if (ret_val < 0) { | ||
864 | mutex_unlock(&dev->lock); | ||
865 | return -EINVAL; | ||
866 | } | ||
867 | |||
868 | return 1; | ||
869 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.h b/drivers/staging/cx25821/cx25821-medusa-video.h new file mode 100644 index 000000000000..2fab4b2f251c --- /dev/null +++ b/drivers/staging/cx25821/cx25821-medusa-video.h | |||
@@ -0,0 +1,49 @@ | |||
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 | // Color control constants | ||
29 | #define VIDEO_PROCAMP_MIN 0 | ||
30 | #define VIDEO_PROCAMP_MAX 10000 | ||
31 | #define UNSIGNED_BYTE_MIN 0 | ||
32 | #define UNSIGNED_BYTE_MAX 0xFF | ||
33 | #define SIGNED_BYTE_MIN -128 | ||
34 | #define SIGNED_BYTE_MAX 127 | ||
35 | |||
36 | // Default video color settings | ||
37 | #define SHARPNESS_DEFAULT 50 | ||
38 | #define SATURATION_DEFAULT 5000 | ||
39 | #define BRIGHTNESS_DEFAULT 6200 | ||
40 | #define CONTRAST_DEFAULT 5000 | ||
41 | #define HUE_DEFAULT 5000 | ||
42 | |||
43 | unsigned short _num_decoders; | ||
44 | unsigned short _num_cameras; | ||
45 | |||
46 | unsigned int _video_standard; | ||
47 | int _display_field_cnt[MAX_DECODERS]; | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h new file mode 100644 index 000000000000..7241e7ee3fd3 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-reg.h | |||
@@ -0,0 +1,1592 @@ | |||
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 | #define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask | ||
171 | #define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status | ||
172 | #define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status | ||
173 | #define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status | ||
174 | |||
175 | //***************************************************************************** | ||
176 | #define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask | ||
177 | #define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status | ||
178 | #define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status | ||
179 | #define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status | ||
180 | |||
181 | //***************************************************************************** | ||
182 | #define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask | ||
183 | #define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status | ||
184 | #define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status | ||
185 | #define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status | ||
186 | |||
187 | //***************************************************************************** | ||
188 | #define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask | ||
189 | #define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status | ||
190 | #define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status | ||
191 | #define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status | ||
192 | |||
193 | //***************************************************************************** | ||
194 | #define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask | ||
195 | #define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status | ||
196 | #define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status | ||
197 | #define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status | ||
198 | |||
199 | #define FLD_AUD_SRC_OPC_ERR 0x00020000 | ||
200 | #define FLD_AUD_DST_OPC_ERR 0x00010000 | ||
201 | #define FLD_AUD_SRC_SYNC 0x00002000 | ||
202 | #define FLD_AUD_DST_SYNC 0x00001000 | ||
203 | #define FLD_AUD_SRC_OF 0x00000200 | ||
204 | #define FLD_AUD_DST_OF 0x00000100 | ||
205 | #define FLD_AUD_SRC_RISCI2 0x00000020 | ||
206 | #define FLD_AUD_DST_RISCI2 0x00000010 | ||
207 | #define FLD_AUD_SRC_RISCI1 0x00000002 | ||
208 | #define FLD_AUD_DST_RISCI1 0x00000001 | ||
209 | |||
210 | //***************************************************************************** | ||
211 | #define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask | ||
212 | #define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status | ||
213 | #define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status | ||
214 | #define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status | ||
215 | |||
216 | //***************************************************************************** | ||
217 | #define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask | ||
218 | #define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status | ||
219 | #define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status | ||
220 | #define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status | ||
221 | |||
222 | #define FLD_MBIF_DST_OPC_ERR 0x00010000 | ||
223 | #define FLD_MBIF_DST_SYNC 0x00001000 | ||
224 | #define FLD_MBIF_DST_OF 0x00000100 | ||
225 | #define FLD_MBIF_DST_RISCI2 0x00000010 | ||
226 | #define FLD_MBIF_DST_RISCI1 0x00000001 | ||
227 | |||
228 | //***************************************************************************** | ||
229 | #define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask | ||
230 | #define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status | ||
231 | #define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status | ||
232 | #define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status | ||
233 | #define FLD_AUD_EXT_OPC_ERR 0x00010000 | ||
234 | #define FLD_AUD_EXT_SYNC 0x00001000 | ||
235 | #define FLD_AUD_EXT_OF 0x00000100 | ||
236 | #define FLD_AUD_EXT_RISCI2 0x00000010 | ||
237 | #define FLD_AUD_EXT_RISCI1 0x00000001 | ||
238 | |||
239 | //***************************************************************************** | ||
240 | #define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] | ||
241 | #define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] | ||
242 | |||
243 | #define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] | ||
244 | #define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] | ||
245 | |||
246 | #define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask | ||
247 | #define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status | ||
248 | #define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status | ||
249 | #define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity | ||
250 | #define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity | ||
251 | |||
252 | #define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask | ||
253 | #define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status | ||
254 | #define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status | ||
255 | #define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity | ||
256 | #define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity | ||
257 | |||
258 | #define FLD_GPIO43_INT (1 << 11) | ||
259 | #define FLD_GPIO42_INT (1 << 10) | ||
260 | #define FLD_GPIO41_INT (1 << 9) | ||
261 | #define FLD_GPIO40_INT (1 << 8) | ||
262 | |||
263 | #define FLD_GPIO9_INT (1 << 9) | ||
264 | #define FLD_GPIO8_INT (1 << 8) | ||
265 | #define FLD_GPIO7_INT (1 << 7) | ||
266 | #define FLD_GPIO6_INT (1 << 6) | ||
267 | #define FLD_GPIO5_INT (1 << 5) | ||
268 | #define FLD_GPIO4_INT (1 << 4) | ||
269 | #define FLD_GPIO3_INT (1 << 3) | ||
270 | #define FLD_GPIO2_INT (1 << 2) | ||
271 | #define FLD_GPIO1_INT (1 << 1) | ||
272 | #define FLD_GPIO0_INT (1 << 0) | ||
273 | |||
274 | //***************************************************************************** | ||
275 | #define TC_REQ 0x040090 // Rider PCI Express traFFic class request | ||
276 | |||
277 | //***************************************************************************** | ||
278 | #define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set | ||
279 | |||
280 | //***************************************************************************** | ||
281 | // Rider | ||
282 | //***************************************************************************** | ||
283 | |||
284 | // PCI Compatible Header | ||
285 | //***************************************************************************** | ||
286 | #define RDR_CFG0 0x050000 | ||
287 | #define RDR_VENDOR_DEVICE_ID_CFG 0x050000 | ||
288 | |||
289 | //***************************************************************************** | ||
290 | #define RDR_CFG1 0x050004 | ||
291 | |||
292 | //***************************************************************************** | ||
293 | #define RDR_CFG2 0x050008 | ||
294 | |||
295 | //***************************************************************************** | ||
296 | #define RDR_CFG3 0x05000C | ||
297 | |||
298 | //***************************************************************************** | ||
299 | #define RDR_CFG4 0x050010 | ||
300 | |||
301 | //***************************************************************************** | ||
302 | #define RDR_CFG5 0x050014 | ||
303 | |||
304 | //***************************************************************************** | ||
305 | #define RDR_CFG6 0x050018 | ||
306 | |||
307 | //***************************************************************************** | ||
308 | #define RDR_CFG7 0x05001C | ||
309 | |||
310 | //***************************************************************************** | ||
311 | #define RDR_CFG8 0x050020 | ||
312 | |||
313 | //***************************************************************************** | ||
314 | #define RDR_CFG9 0x050024 | ||
315 | |||
316 | //***************************************************************************** | ||
317 | #define RDR_CFGA 0x050028 | ||
318 | |||
319 | //***************************************************************************** | ||
320 | #define RDR_CFGB 0x05002C | ||
321 | #define RDR_SUSSYSTEM_ID_CFG 0x05002C | ||
322 | |||
323 | //***************************************************************************** | ||
324 | #define RDR_CFGC 0x050030 | ||
325 | |||
326 | //***************************************************************************** | ||
327 | #define RDR_CFGD 0x050034 | ||
328 | |||
329 | //***************************************************************************** | ||
330 | #define RDR_CFGE 0x050038 | ||
331 | |||
332 | //***************************************************************************** | ||
333 | #define RDR_CFGF 0x05003C | ||
334 | |||
335 | //***************************************************************************** | ||
336 | // PCI-Express Capabilities | ||
337 | //***************************************************************************** | ||
338 | #define RDR_PECAP 0x050040 | ||
339 | |||
340 | //***************************************************************************** | ||
341 | #define RDR_PEDEVCAP 0x050044 | ||
342 | |||
343 | //***************************************************************************** | ||
344 | #define RDR_PEDEVSC 0x050048 | ||
345 | |||
346 | //***************************************************************************** | ||
347 | #define RDR_PELINKCAP 0x05004C | ||
348 | |||
349 | //***************************************************************************** | ||
350 | #define RDR_PELINKSC 0x050050 | ||
351 | |||
352 | //***************************************************************************** | ||
353 | #define RDR_PMICAP 0x050080 | ||
354 | |||
355 | //***************************************************************************** | ||
356 | #define RDR_PMCSR 0x050084 | ||
357 | |||
358 | //***************************************************************************** | ||
359 | #define RDR_VPDCAP 0x050090 | ||
360 | |||
361 | //***************************************************************************** | ||
362 | #define RDR_VPDDATA 0x050094 | ||
363 | |||
364 | //***************************************************************************** | ||
365 | #define RDR_MSICAP 0x0500A0 | ||
366 | |||
367 | //***************************************************************************** | ||
368 | #define RDR_MSIARL 0x0500A4 | ||
369 | |||
370 | //***************************************************************************** | ||
371 | #define RDR_MSIARU 0x0500A8 | ||
372 | |||
373 | //***************************************************************************** | ||
374 | #define RDR_MSIDATA 0x0500AC | ||
375 | |||
376 | //***************************************************************************** | ||
377 | // PCI Express Extended Capabilities | ||
378 | //***************************************************************************** | ||
379 | #define RDR_AERXCAP 0x050100 | ||
380 | |||
381 | //***************************************************************************** | ||
382 | #define RDR_AERUESTA 0x050104 | ||
383 | |||
384 | //***************************************************************************** | ||
385 | #define RDR_AERUEMSK 0x050108 | ||
386 | |||
387 | //***************************************************************************** | ||
388 | #define RDR_AERUESEV 0x05010C | ||
389 | |||
390 | //***************************************************************************** | ||
391 | #define RDR_AERCESTA 0x050110 | ||
392 | |||
393 | //***************************************************************************** | ||
394 | #define RDR_AERCEMSK 0x050114 | ||
395 | |||
396 | //***************************************************************************** | ||
397 | #define RDR_AERCC 0x050118 | ||
398 | |||
399 | //***************************************************************************** | ||
400 | #define RDR_AERHL0 0x05011C | ||
401 | |||
402 | //***************************************************************************** | ||
403 | #define RDR_AERHL1 0x050120 | ||
404 | |||
405 | //***************************************************************************** | ||
406 | #define RDR_AERHL2 0x050124 | ||
407 | |||
408 | //***************************************************************************** | ||
409 | #define RDR_AERHL3 0x050128 | ||
410 | |||
411 | //***************************************************************************** | ||
412 | #define RDR_VCXCAP 0x050200 | ||
413 | |||
414 | //***************************************************************************** | ||
415 | #define RDR_VCCAP1 0x050204 | ||
416 | |||
417 | //***************************************************************************** | ||
418 | #define RDR_VCCAP2 0x050208 | ||
419 | |||
420 | //***************************************************************************** | ||
421 | #define RDR_VCSC 0x05020C | ||
422 | |||
423 | //***************************************************************************** | ||
424 | #define RDR_VCR0_CAP 0x050210 | ||
425 | |||
426 | //***************************************************************************** | ||
427 | #define RDR_VCR0_CTRL 0x050214 | ||
428 | |||
429 | //***************************************************************************** | ||
430 | #define RDR_VCR0_STAT 0x050218 | ||
431 | |||
432 | //***************************************************************************** | ||
433 | #define RDR_VCR1_CAP 0x05021C | ||
434 | |||
435 | //***************************************************************************** | ||
436 | #define RDR_VCR1_CTRL 0x050220 | ||
437 | |||
438 | //***************************************************************************** | ||
439 | #define RDR_VCR1_STAT 0x050224 | ||
440 | |||
441 | //***************************************************************************** | ||
442 | #define RDR_VCR2_CAP 0x050228 | ||
443 | |||
444 | //***************************************************************************** | ||
445 | #define RDR_VCR2_CTRL 0x05022C | ||
446 | |||
447 | //***************************************************************************** | ||
448 | #define RDR_VCR2_STAT 0x050230 | ||
449 | |||
450 | //***************************************************************************** | ||
451 | #define RDR_VCR3_CAP 0x050234 | ||
452 | |||
453 | //***************************************************************************** | ||
454 | #define RDR_VCR3_CTRL 0x050238 | ||
455 | |||
456 | //***************************************************************************** | ||
457 | #define RDR_VCR3_STAT 0x05023C | ||
458 | |||
459 | //***************************************************************************** | ||
460 | #define RDR_VCARB0 0x050240 | ||
461 | |||
462 | //***************************************************************************** | ||
463 | #define RDR_VCARB1 0x050244 | ||
464 | |||
465 | //***************************************************************************** | ||
466 | #define RDR_VCARB2 0x050248 | ||
467 | |||
468 | //***************************************************************************** | ||
469 | #define RDR_VCARB3 0x05024C | ||
470 | |||
471 | //***************************************************************************** | ||
472 | #define RDR_VCARB4 0x050250 | ||
473 | |||
474 | //***************************************************************************** | ||
475 | #define RDR_VCARB5 0x050254 | ||
476 | |||
477 | //***************************************************************************** | ||
478 | #define RDR_VCARB6 0x050258 | ||
479 | |||
480 | //***************************************************************************** | ||
481 | #define RDR_VCARB7 0x05025C | ||
482 | |||
483 | //***************************************************************************** | ||
484 | #define RDR_RDRSTAT0 0x050300 | ||
485 | |||
486 | //***************************************************************************** | ||
487 | #define RDR_RDRSTAT1 0x050304 | ||
488 | |||
489 | //***************************************************************************** | ||
490 | #define RDR_RDRCTL0 0x050308 | ||
491 | |||
492 | //***************************************************************************** | ||
493 | #define RDR_RDRCTL1 0x05030C | ||
494 | |||
495 | //***************************************************************************** | ||
496 | // Transaction Layer Registers | ||
497 | //***************************************************************************** | ||
498 | #define RDR_TLSTAT0 0x050310 | ||
499 | |||
500 | //***************************************************************************** | ||
501 | #define RDR_TLSTAT1 0x050314 | ||
502 | |||
503 | //***************************************************************************** | ||
504 | #define RDR_TLCTL0 0x050318 | ||
505 | #define FLD_CFG_UR_CPL_MODE 0x00000040 | ||
506 | #define FLD_CFG_CORR_ERR_QUITE 0x00000020 | ||
507 | #define FLD_CFG_RCB_CK_EN 0x00000010 | ||
508 | #define FLD_CFG_BNDRY_CK_EN 0x00000008 | ||
509 | #define FLD_CFG_BYTE_EN_CK_EN 0x00000004 | ||
510 | #define FLD_CFG_RELAX_ORDER_MSK 0x00000002 | ||
511 | #define FLD_CFG_TAG_ORDER_EN 0x00000001 | ||
512 | |||
513 | //***************************************************************************** | ||
514 | #define RDR_TLCTL1 0x05031C | ||
515 | |||
516 | //***************************************************************************** | ||
517 | #define RDR_REQRCAL 0x050320 | ||
518 | |||
519 | //***************************************************************************** | ||
520 | #define RDR_REQRCAU 0x050324 | ||
521 | |||
522 | //***************************************************************************** | ||
523 | #define RDR_REQEPA 0x050328 | ||
524 | |||
525 | //***************************************************************************** | ||
526 | #define RDR_REQCTRL 0x05032C | ||
527 | |||
528 | //***************************************************************************** | ||
529 | #define RDR_REQSTAT 0x050330 | ||
530 | |||
531 | //***************************************************************************** | ||
532 | #define RDR_TL_TEST 0x050334 | ||
533 | |||
534 | //***************************************************************************** | ||
535 | #define RDR_VCR01_CTL 0x050348 | ||
536 | |||
537 | //***************************************************************************** | ||
538 | #define RDR_VCR23_CTL 0x05034C | ||
539 | |||
540 | //***************************************************************************** | ||
541 | #define RDR_RX_VCR0_FC 0x050350 | ||
542 | |||
543 | //***************************************************************************** | ||
544 | #define RDR_RX_VCR1_FC 0x050354 | ||
545 | |||
546 | //***************************************************************************** | ||
547 | #define RDR_RX_VCR2_FC 0x050358 | ||
548 | |||
549 | //***************************************************************************** | ||
550 | #define RDR_RX_VCR3_FC 0x05035C | ||
551 | |||
552 | //***************************************************************************** | ||
553 | // Data Link Layer Registers | ||
554 | //***************************************************************************** | ||
555 | #define RDR_DLLSTAT 0x050360 | ||
556 | |||
557 | //***************************************************************************** | ||
558 | #define RDR_DLLCTRL 0x050364 | ||
559 | |||
560 | //***************************************************************************** | ||
561 | #define RDR_REPLAYTO 0x050368 | ||
562 | |||
563 | //***************************************************************************** | ||
564 | #define RDR_ACKLATTO 0x05036C | ||
565 | |||
566 | //***************************************************************************** | ||
567 | // MAC Layer Registers | ||
568 | //***************************************************************************** | ||
569 | #define RDR_MACSTAT0 0x050380 | ||
570 | |||
571 | //***************************************************************************** | ||
572 | #define RDR_MACSTAT1 0x050384 | ||
573 | |||
574 | //***************************************************************************** | ||
575 | #define RDR_MACCTRL0 0x050388 | ||
576 | |||
577 | //***************************************************************************** | ||
578 | #define RDR_MACCTRL1 0x05038C | ||
579 | |||
580 | //***************************************************************************** | ||
581 | #define RDR_MACCTRL2 0x050390 | ||
582 | |||
583 | //***************************************************************************** | ||
584 | #define RDR_MAC_LB_DATA 0x050394 | ||
585 | |||
586 | //***************************************************************************** | ||
587 | #define RDR_L0S_EXIT_LAT 0x050398 | ||
588 | |||
589 | //***************************************************************************** | ||
590 | // DMAC | ||
591 | //***************************************************************************** | ||
592 | #define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 | ||
593 | |||
594 | //***************************************************************************** | ||
595 | #define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 | ||
596 | |||
597 | //***************************************************************************** | ||
598 | #define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 | ||
599 | |||
600 | //***************************************************************************** | ||
601 | #define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 | ||
602 | |||
603 | //***************************************************************************** | ||
604 | #define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 | ||
605 | |||
606 | //***************************************************************************** | ||
607 | #define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 | ||
608 | |||
609 | //***************************************************************************** | ||
610 | #define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 | ||
611 | |||
612 | //***************************************************************************** | ||
613 | #define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 | ||
614 | |||
615 | //***************************************************************************** | ||
616 | #define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 | ||
617 | |||
618 | //***************************************************************************** | ||
619 | #define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 | ||
620 | |||
621 | //***************************************************************************** | ||
622 | #define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 | ||
623 | |||
624 | //***************************************************************************** | ||
625 | #define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 | ||
626 | |||
627 | //***************************************************************************** | ||
628 | #define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 | ||
629 | |||
630 | //***************************************************************************** | ||
631 | #define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 | ||
632 | |||
633 | //***************************************************************************** | ||
634 | #define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 | ||
635 | |||
636 | //***************************************************************************** | ||
637 | #define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 | ||
638 | |||
639 | //***************************************************************************** | ||
640 | #define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 | ||
641 | |||
642 | //***************************************************************************** | ||
643 | #define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 | ||
644 | |||
645 | //***************************************************************************** | ||
646 | #define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 | ||
647 | |||
648 | //***************************************************************************** | ||
649 | #define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 | ||
650 | |||
651 | //***************************************************************************** | ||
652 | #define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 | ||
653 | |||
654 | //***************************************************************************** | ||
655 | #define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 | ||
656 | |||
657 | //***************************************************************************** | ||
658 | #define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 | ||
659 | |||
660 | //***************************************************************************** | ||
661 | #define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 | ||
662 | |||
663 | //***************************************************************************** | ||
664 | #define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 | ||
665 | |||
666 | //***************************************************************************** | ||
667 | #define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 | ||
668 | |||
669 | //***************************************************************************** | ||
670 | #define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 | ||
671 | |||
672 | //***************************************************************************** | ||
673 | #define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 | ||
674 | |||
675 | //***************************************************************************** | ||
676 | #define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 | ||
677 | |||
678 | //***************************************************************************** | ||
679 | #define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 | ||
680 | |||
681 | //***************************************************************************** | ||
682 | #define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 | ||
683 | |||
684 | //***************************************************************************** | ||
685 | #define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 | ||
686 | |||
687 | //***************************************************************************** | ||
688 | #define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 | ||
689 | |||
690 | //***************************************************************************** | ||
691 | #define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 | ||
692 | |||
693 | //***************************************************************************** | ||
694 | #define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 | ||
695 | |||
696 | //***************************************************************************** | ||
697 | #define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 | ||
698 | |||
699 | //***************************************************************************** | ||
700 | #define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 | ||
701 | |||
702 | //***************************************************************************** | ||
703 | #define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 | ||
704 | |||
705 | //***************************************************************************** | ||
706 | #define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 | ||
707 | |||
708 | //***************************************************************************** | ||
709 | #define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 | ||
710 | |||
711 | //***************************************************************************** | ||
712 | #define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 | ||
713 | |||
714 | //***************************************************************************** | ||
715 | #define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 | ||
716 | |||
717 | //***************************************************************************** | ||
718 | #define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 | ||
719 | |||
720 | //***************************************************************************** | ||
721 | #define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 | ||
722 | |||
723 | //***************************************************************************** | ||
724 | #define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 | ||
725 | |||
726 | //***************************************************************************** | ||
727 | #define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 | ||
728 | |||
729 | //***************************************************************************** | ||
730 | #define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 | ||
731 | |||
732 | //***************************************************************************** | ||
733 | #define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 | ||
734 | |||
735 | //***************************************************************************** | ||
736 | #define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 | ||
737 | |||
738 | //***************************************************************************** | ||
739 | #define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 | ||
740 | |||
741 | //***************************************************************************** | ||
742 | #define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 | ||
743 | |||
744 | //***************************************************************************** | ||
745 | #define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 | ||
746 | |||
747 | //***************************************************************************** | ||
748 | #define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 | ||
749 | |||
750 | //***************************************************************************** | ||
751 | #define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 | ||
752 | |||
753 | //***************************************************************************** | ||
754 | #define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 | ||
755 | |||
756 | //***************************************************************************** | ||
757 | #define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 | ||
758 | |||
759 | //***************************************************************************** | ||
760 | #define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 | ||
761 | |||
762 | //***************************************************************************** | ||
763 | #define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 | ||
764 | |||
765 | //***************************************************************************** | ||
766 | #define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 | ||
767 | |||
768 | //***************************************************************************** | ||
769 | #define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 | ||
770 | |||
771 | //***************************************************************************** | ||
772 | #define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 | ||
773 | |||
774 | //***************************************************************************** | ||
775 | #define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 | ||
776 | |||
777 | //***************************************************************************** | ||
778 | #define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 | ||
779 | |||
780 | //***************************************************************************** | ||
781 | #define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 | ||
782 | |||
783 | //***************************************************************************** | ||
784 | #define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 | ||
785 | |||
786 | //***************************************************************************** | ||
787 | #define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 | ||
788 | |||
789 | //***************************************************************************** | ||
790 | #define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 | ||
791 | |||
792 | //***************************************************************************** | ||
793 | #define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 | ||
794 | |||
795 | //***************************************************************************** | ||
796 | #define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 | ||
797 | |||
798 | //***************************************************************************** | ||
799 | #define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 | ||
800 | |||
801 | //***************************************************************************** | ||
802 | #define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 | ||
803 | |||
804 | //***************************************************************************** | ||
805 | #define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 | ||
806 | |||
807 | //***************************************************************************** | ||
808 | #define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 | ||
809 | |||
810 | //***************************************************************************** | ||
811 | #define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 | ||
812 | |||
813 | //***************************************************************************** | ||
814 | #define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 | ||
815 | |||
816 | //***************************************************************************** | ||
817 | #define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 | ||
818 | |||
819 | //***************************************************************************** | ||
820 | #define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 | ||
821 | |||
822 | //***************************************************************************** | ||
823 | #define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 | ||
824 | |||
825 | //***************************************************************************** | ||
826 | #define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 | ||
827 | |||
828 | //***************************************************************************** | ||
829 | #define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 | ||
830 | |||
831 | //***************************************************************************** | ||
832 | #define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 | ||
833 | |||
834 | //***************************************************************************** | ||
835 | #define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 | ||
836 | |||
837 | //***************************************************************************** | ||
838 | #define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 | ||
839 | |||
840 | //***************************************************************************** | ||
841 | #define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 | ||
842 | |||
843 | //***************************************************************************** | ||
844 | #define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 | ||
845 | |||
846 | //***************************************************************************** | ||
847 | #define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 | ||
848 | |||
849 | //***************************************************************************** | ||
850 | #define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 | ||
851 | |||
852 | //***************************************************************************** | ||
853 | #define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 | ||
854 | |||
855 | //***************************************************************************** | ||
856 | #define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 | ||
857 | |||
858 | //***************************************************************************** | ||
859 | #define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 | ||
860 | |||
861 | //***************************************************************************** | ||
862 | #define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 | ||
863 | |||
864 | //***************************************************************************** | ||
865 | #define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 | ||
866 | |||
867 | //***************************************************************************** | ||
868 | #define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 | ||
869 | |||
870 | //***************************************************************************** | ||
871 | #define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 | ||
872 | |||
873 | //***************************************************************************** | ||
874 | #define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 | ||
875 | |||
876 | //***************************************************************************** | ||
877 | #define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 | ||
878 | |||
879 | //***************************************************************************** | ||
880 | #define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 | ||
881 | |||
882 | //***************************************************************************** | ||
883 | #define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 | ||
884 | |||
885 | //***************************************************************************** | ||
886 | #define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 | ||
887 | |||
888 | //***************************************************************************** | ||
889 | #define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 | ||
890 | |||
891 | //***************************************************************************** | ||
892 | #define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 | ||
893 | |||
894 | //***************************************************************************** | ||
895 | #define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 | ||
896 | |||
897 | //***************************************************************************** | ||
898 | #define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 | ||
899 | |||
900 | //***************************************************************************** | ||
901 | #define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 | ||
902 | |||
903 | //***************************************************************************** | ||
904 | // ITG | ||
905 | //***************************************************************************** | ||
906 | #define TM_CNT_LDW 0x110000 // Timer : Counter low | ||
907 | |||
908 | //***************************************************************************** | ||
909 | #define TM_CNT_UW 0x110004 // Timer : Counter high word | ||
910 | |||
911 | //***************************************************************************** | ||
912 | #define TM_LMT_LDW 0x110008 // Timer : Limit low | ||
913 | |||
914 | //***************************************************************************** | ||
915 | #define TM_LMT_UW 0x11000C // Timer : Limit high word | ||
916 | |||
917 | //***************************************************************************** | ||
918 | #define GP0_IO 0x110010 // GPIO output enables data I/O | ||
919 | #define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable | ||
920 | #define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status | ||
921 | #define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control | ||
922 | |||
923 | //***************************************************************************** | ||
924 | #define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode | ||
925 | #define FLD_GP_ISM_SNS 0x00000070 | ||
926 | #define FLD_GP_ISM_POL 0x00000007 | ||
927 | |||
928 | //***************************************************************************** | ||
929 | #define SOFT_RESET 0x11001C // Output system reset reg | ||
930 | #define FLD_PECOS_SOFT_RESET 0x00000001 | ||
931 | |||
932 | //***************************************************************************** | ||
933 | #define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin | ||
934 | #define MC416_OEN 0x110024 // Output enable of GPIO[18:3] | ||
935 | #define MC416_CTL 0x110028 | ||
936 | |||
937 | //***************************************************************************** | ||
938 | #define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select | ||
939 | |||
940 | #define FLD_ALT_GPIO_OUT_SEL 0xF0000000 | ||
941 | // 0 Disabled <-- default | ||
942 | // 1 GPIO[0] | ||
943 | // 2 GPIO[10] | ||
944 | // 3 VIP_656_DATA_VAL | ||
945 | // 4 VIP_656_DATA[0] | ||
946 | // 5 VIP_656_CLK | ||
947 | // 6 VIP_656_DATA_EXT[1] | ||
948 | // 7 VIP_656_DATA_EXT[0] | ||
949 | // 8 ATT_IF | ||
950 | |||
951 | #define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 | ||
952 | // 0 AUX_PLL_CLK<-- default | ||
953 | // 1 GPIO[2] | ||
954 | // 2 GPIO[10] | ||
955 | // 3 VIP_656_DATA_VAL | ||
956 | // 4 VIP_656_DATA[0] | ||
957 | // 5 VIP_656_CLK | ||
958 | // 6 VIP_656_DATA_EXT[1] | ||
959 | // 7 VIP_656_DATA_EXT[0] | ||
960 | |||
961 | #define FLD_IR_TX_ALT_SEL 0x00F00000 | ||
962 | // 0 IR_TX <-- default | ||
963 | // 1 GPIO[1] | ||
964 | // 2 GPIO[10] | ||
965 | // 3 VIP_656_DATA_VAL | ||
966 | // 4 VIP_656_DATA[0] | ||
967 | // 5 VIP_656_CLK | ||
968 | // 6 VIP_656_DATA_EXT[1] | ||
969 | // 7 VIP_656_DATA_EXT[0] | ||
970 | |||
971 | #define FLD_IR_RX_ALT_SEL 0x000F0000 | ||
972 | // 0 IR_RX <-- default | ||
973 | // 1 GPIO[0] | ||
974 | // 2 GPIO[10] | ||
975 | // 3 VIP_656_DATA_VAL | ||
976 | // 4 VIP_656_DATA[0] | ||
977 | // 5 VIP_656_CLK | ||
978 | // 6 VIP_656_DATA_EXT[1] | ||
979 | // 7 VIP_656_DATA_EXT[0] | ||
980 | |||
981 | #define FLD_GPIO10_ALT_SEL 0x0000F000 | ||
982 | // 0 GPIO[10] <-- default | ||
983 | // 1 GPIO[0] | ||
984 | // 2 GPIO[10] | ||
985 | // 3 VIP_656_DATA_VAL | ||
986 | // 4 VIP_656_DATA[0] | ||
987 | // 5 VIP_656_CLK | ||
988 | // 6 VIP_656_DATA_EXT[1] | ||
989 | // 7 VIP_656_DATA_EXT[0] | ||
990 | |||
991 | #define FLD_GPIO2_ALT_SEL 0x00000F00 | ||
992 | // 0 GPIO[2] <-- default | ||
993 | // 1 GPIO[1] | ||
994 | // 2 GPIO[10] | ||
995 | // 3 VIP_656_DATA_VAL | ||
996 | // 4 VIP_656_DATA[0] | ||
997 | // 5 VIP_656_CLK | ||
998 | // 6 VIP_656_DATA_EXT[1] | ||
999 | // 7 VIP_656_DATA_EXT[0] | ||
1000 | |||
1001 | #define FLD_GPIO1_ALT_SEL 0x000000F0 | ||
1002 | // 0 GPIO[1] <-- default | ||
1003 | // 1 GPIO[0] | ||
1004 | // 2 GPIO[10] | ||
1005 | // 3 VIP_656_DATA_VAL | ||
1006 | // 4 VIP_656_DATA[0] | ||
1007 | // 5 VIP_656_CLK | ||
1008 | // 6 VIP_656_DATA_EXT[1] | ||
1009 | // 7 VIP_656_DATA_EXT[0] | ||
1010 | |||
1011 | #define FLD_GPIO0_ALT_SEL 0x0000000F | ||
1012 | // 0 GPIO[0] <-- default | ||
1013 | // 1 GPIO[1] | ||
1014 | // 2 GPIO[10] | ||
1015 | // 3 VIP_656_DATA_VAL | ||
1016 | // 4 VIP_656_DATA[0] | ||
1017 | // 5 VIP_656_CLK | ||
1018 | // 6 VIP_656_DATA_EXT[1] | ||
1019 | // 7 VIP_656_DATA_EXT[0] | ||
1020 | |||
1021 | #define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select | ||
1022 | |||
1023 | #define FLD_GPIO10_ALT_IN_SEL 0x0000F000 | ||
1024 | // 0 GPIO[10] <-- default | ||
1025 | // 1 IR_RX | ||
1026 | // 2 IR_TX | ||
1027 | // 3 AUX_PLL_CLK | ||
1028 | // 4 IF_ATT_SEL | ||
1029 | // 5 GPIO[0] | ||
1030 | // 6 GPIO[1] | ||
1031 | // 7 GPIO[2] | ||
1032 | |||
1033 | #define FLD_GPIO2_ALT_IN_SEL 0x00000F00 | ||
1034 | // 0 GPIO[2] <-- default | ||
1035 | // 1 IR_RX | ||
1036 | // 2 IR_TX | ||
1037 | // 3 AUX_PLL_CLK | ||
1038 | // 4 IF_ATT_SEL | ||
1039 | |||
1040 | #define FLD_GPIO1_ALT_IN_SEL 0x000000F0 | ||
1041 | // 0 GPIO[1] <-- default | ||
1042 | // 1 IR_RX | ||
1043 | // 2 IR_TX | ||
1044 | // 3 AUX_PLL_CLK | ||
1045 | // 4 IF_ATT_SEL | ||
1046 | |||
1047 | #define FLD_GPIO0_ALT_IN_SEL 0x0000000F | ||
1048 | // 0 GPIO[0] <-- default | ||
1049 | // 1 IR_RX | ||
1050 | // 2 IR_TX | ||
1051 | // 3 AUX_PLL_CLK | ||
1052 | // 4 IF_ATT_SEL | ||
1053 | |||
1054 | //***************************************************************************** | ||
1055 | #define TEST_BUS_CTL1 0x110040 // Test bus control register #1 | ||
1056 | |||
1057 | //***************************************************************************** | ||
1058 | #define TEST_BUS_CTL2 0x110044 // Test bus control register #2 | ||
1059 | |||
1060 | //***************************************************************************** | ||
1061 | #define CLK_DELAY 0x110048 // Clock delay | ||
1062 | #define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock | ||
1063 | |||
1064 | //***************************************************************************** | ||
1065 | #define PAD_CTRL 0x110068 // Pad drive strength control | ||
1066 | |||
1067 | //***************************************************************************** | ||
1068 | #define MBIST_CTRL 0x110050 // SRAM memory built-in self test control | ||
1069 | |||
1070 | //***************************************************************************** | ||
1071 | #define MBIST_STAT 0x110054 // SRAM memory built-in self test status | ||
1072 | |||
1073 | //***************************************************************************** | ||
1074 | // PLL registers | ||
1075 | //***************************************************************************** | ||
1076 | #define PLL_A_INT_FRAC 0x110088 | ||
1077 | #define PLL_A_POST_STAT_BIST 0x11008C | ||
1078 | #define PLL_B_INT_FRAC 0x110090 | ||
1079 | #define PLL_B_POST_STAT_BIST 0x110094 | ||
1080 | #define PLL_C_INT_FRAC 0x110098 | ||
1081 | #define PLL_C_POST_STAT_BIST 0x11009C | ||
1082 | #define PLL_D_INT_FRAC 0x1100A0 | ||
1083 | #define PLL_D_POST_STAT_BIST 0x1100A4 | ||
1084 | |||
1085 | #define CLK_RST 0x11002C | ||
1086 | #define FLD_VID_I_CLK_NOE 0x00001000 | ||
1087 | #define FLD_VID_J_CLK_NOE 0x00002000 | ||
1088 | #define FLD_USE_ALT_PLL_REF 0x00004000 | ||
1089 | |||
1090 | #define VID_CH_MODE_SEL 0x110078 | ||
1091 | #define VID_CH_CLK_SEL 0x11007C | ||
1092 | |||
1093 | //***************************************************************************** | ||
1094 | #define VBI_A_DMA 0x130008 // VBI A DMA data port | ||
1095 | |||
1096 | //***************************************************************************** | ||
1097 | #define VID_A_VIP_CTL 0x130080 // Video A VIP format control | ||
1098 | #define FLD_VIP_MODE 0x00000001 | ||
1099 | |||
1100 | //***************************************************************************** | ||
1101 | #define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format | ||
1102 | #define FLD_VID_A_GAMMA_DIS 0x00000008 | ||
1103 | #define FLD_VID_A_FORMAT 0x00000007 | ||
1104 | #define FLD_VID_A_GAMMA_FACTOR 0x00000010 | ||
1105 | |||
1106 | //***************************************************************************** | ||
1107 | #define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control | ||
1108 | #define FLD_VID_A_VIP_EXT 0x00000003 | ||
1109 | |||
1110 | //***************************************************************************** | ||
1111 | #define VID_B_DMA 0x130100 // Video B DMA data port | ||
1112 | |||
1113 | //***************************************************************************** | ||
1114 | #define VBI_B_DMA 0x130108 // VBI B DMA data port | ||
1115 | |||
1116 | //***************************************************************************** | ||
1117 | #define VID_B_SRC_SEL 0x130144 // Video B source select | ||
1118 | #define FLD_VID_B_SRC_SEL 0x00000000 | ||
1119 | |||
1120 | //***************************************************************************** | ||
1121 | #define VID_B_LNGTH 0x130150 // Video B line length | ||
1122 | #define FLD_VID_B_LN_LNGTH 0x00000FFF | ||
1123 | |||
1124 | //***************************************************************************** | ||
1125 | #define VID_B_VIP_CTL 0x130180 // Video B VIP format control | ||
1126 | |||
1127 | //***************************************************************************** | ||
1128 | #define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format | ||
1129 | #define FLD_VID_B_GAMMA_DIS 0x00000008 | ||
1130 | #define FLD_VID_B_FORMAT 0x00000007 | ||
1131 | #define FLD_VID_B_GAMMA_FACTOR 0x00000010 | ||
1132 | |||
1133 | //***************************************************************************** | ||
1134 | #define VID_C_DMA 0x130200 // Video C DMA data port | ||
1135 | |||
1136 | //***************************************************************************** | ||
1137 | #define VID_C_LNGTH 0x130250 // Video C line length | ||
1138 | #define FLD_VID_C_LN_LNGTH 0x00000FFF | ||
1139 | |||
1140 | //***************************************************************************** | ||
1141 | // Video Destination Channels | ||
1142 | //***************************************************************************** | ||
1143 | |||
1144 | #define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter | ||
1145 | #define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter | ||
1146 | #define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter | ||
1147 | #define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter | ||
1148 | #define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter | ||
1149 | #define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter | ||
1150 | #define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter | ||
1151 | #define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter | ||
1152 | |||
1153 | //***************************************************************************** | ||
1154 | |||
1155 | #define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control | ||
1156 | #define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control | ||
1157 | #define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control | ||
1158 | #define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control | ||
1159 | #define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control | ||
1160 | #define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control | ||
1161 | #define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control | ||
1162 | #define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control | ||
1163 | |||
1164 | //***************************************************************************** | ||
1165 | |||
1166 | #define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control | ||
1167 | #define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control | ||
1168 | #define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control | ||
1169 | #define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control | ||
1170 | #define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control | ||
1171 | #define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control | ||
1172 | #define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control | ||
1173 | #define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control | ||
1174 | |||
1175 | #define FLD_VID_RISC_EN 0x00000010 | ||
1176 | #define FLD_VID_FIFO_EN 0x00000001 | ||
1177 | |||
1178 | //***************************************************************************** | ||
1179 | |||
1180 | #define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control | ||
1181 | #define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control | ||
1182 | #define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control | ||
1183 | #define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control | ||
1184 | #define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control | ||
1185 | #define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control | ||
1186 | #define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control | ||
1187 | #define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control | ||
1188 | |||
1189 | //***************************************************************************** | ||
1190 | |||
1191 | #define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format | ||
1192 | #define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format | ||
1193 | #define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format | ||
1194 | #define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format | ||
1195 | #define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format | ||
1196 | #define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format | ||
1197 | #define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format | ||
1198 | #define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format | ||
1199 | |||
1200 | //***************************************************************************** | ||
1201 | // Video Source Channels | ||
1202 | //***************************************************************************** | ||
1203 | |||
1204 | #define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control | ||
1205 | #define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control | ||
1206 | #define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control | ||
1207 | #define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control | ||
1208 | #define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control | ||
1209 | #define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control | ||
1210 | #define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control | ||
1211 | #define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control | ||
1212 | |||
1213 | //***************************************************************************** | ||
1214 | |||
1215 | #define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter | ||
1216 | #define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter | ||
1217 | #define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter | ||
1218 | #define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter | ||
1219 | #define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter | ||
1220 | #define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter | ||
1221 | #define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter | ||
1222 | #define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter | ||
1223 | |||
1224 | //***************************************************************************** | ||
1225 | |||
1226 | #define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control | ||
1227 | #define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control | ||
1228 | #define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control | ||
1229 | #define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control | ||
1230 | #define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control | ||
1231 | #define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control | ||
1232 | #define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control | ||
1233 | #define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control | ||
1234 | |||
1235 | #define FLD_APB_RISC_EN 0x00000010 | ||
1236 | #define FLD_APB_FIFO_EN 0x00000001 | ||
1237 | |||
1238 | //***************************************************************************** | ||
1239 | |||
1240 | #define VID_SRC_A_FMT_CTL 0x130810 // Video A format control | ||
1241 | #define VID_SRC_B_FMT_CTL 0x130910 // Video B format control | ||
1242 | #define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control | ||
1243 | #define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control | ||
1244 | #define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control | ||
1245 | #define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control | ||
1246 | #define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control | ||
1247 | #define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control | ||
1248 | |||
1249 | //***************************************************************************** | ||
1250 | |||
1251 | #define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 | ||
1252 | #define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 | ||
1253 | #define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 | ||
1254 | #define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 | ||
1255 | #define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 | ||
1256 | #define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 | ||
1257 | #define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 | ||
1258 | #define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 | ||
1259 | |||
1260 | //***************************************************************************** | ||
1261 | |||
1262 | #define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 | ||
1263 | #define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 | ||
1264 | #define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 | ||
1265 | #define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 | ||
1266 | #define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 | ||
1267 | #define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 | ||
1268 | #define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 | ||
1269 | #define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 | ||
1270 | |||
1271 | //***************************************************************************** | ||
1272 | |||
1273 | #define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size | ||
1274 | #define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size | ||
1275 | #define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size | ||
1276 | #define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size | ||
1277 | #define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size | ||
1278 | #define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size | ||
1279 | #define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size | ||
1280 | #define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size | ||
1281 | |||
1282 | //***************************************************************************** | ||
1283 | // Audio I/F | ||
1284 | //***************************************************************************** | ||
1285 | #define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port | ||
1286 | #define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port | ||
1287 | |||
1288 | #define AUD_A_GPCNT 0x140010 // Audio Int A gp counter | ||
1289 | #define FLD_AUD_A_GP_CNT 0x0000FFFF | ||
1290 | |||
1291 | #define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control | ||
1292 | |||
1293 | #define AUD_A_LNGTH 0x140018 // Audio Int A line length | ||
1294 | |||
1295 | #define AUD_A_CFG 0x14001C // Audio Int A configuration | ||
1296 | |||
1297 | //***************************************************************************** | ||
1298 | #define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port | ||
1299 | #define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port | ||
1300 | |||
1301 | #define AUD_B_GPCNT 0x140110 // Audio Int B gp counter | ||
1302 | #define FLD_AUD_B_GP_CNT 0x0000FFFF | ||
1303 | |||
1304 | #define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control | ||
1305 | |||
1306 | #define AUD_B_LNGTH 0x140118 // Audio Int B line length | ||
1307 | |||
1308 | #define AUD_B_CFG 0x14011C // Audio Int B configuration | ||
1309 | |||
1310 | //***************************************************************************** | ||
1311 | #define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port | ||
1312 | #define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port | ||
1313 | |||
1314 | #define AUD_C_GPCNT 0x140210 // Audio Int C gp counter | ||
1315 | #define FLD_AUD_C_GP_CNT 0x0000FFFF | ||
1316 | |||
1317 | #define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control | ||
1318 | |||
1319 | #define AUD_C_LNGTH 0x140218 // Audio Int C line length | ||
1320 | |||
1321 | #define AUD_C_CFG 0x14021C // Audio Int C configuration | ||
1322 | |||
1323 | //***************************************************************************** | ||
1324 | #define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port | ||
1325 | #define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port | ||
1326 | |||
1327 | #define AUD_D_GPCNT 0x140310 // Audio Int D gp counter | ||
1328 | #define FLD_AUD_D_GP_CNT 0x0000FFFF | ||
1329 | |||
1330 | #define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control | ||
1331 | |||
1332 | #define AUD_D_LNGTH 0x140318 // Audio Int D line length | ||
1333 | |||
1334 | #define AUD_D_CFG 0x14031C // Audio Int D configuration | ||
1335 | |||
1336 | //***************************************************************************** | ||
1337 | #define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port | ||
1338 | |||
1339 | #define AUD_E_GPCNT 0x140410 // Audio Int E gp counter | ||
1340 | #define FLD_AUD_E_GP_CNT 0x0000FFFF | ||
1341 | |||
1342 | #define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control | ||
1343 | |||
1344 | #define AUD_E_CFG 0x14041C // Audio Int E configuration | ||
1345 | |||
1346 | //***************************************************************************** | ||
1347 | |||
1348 | #define FLD_AUD_DST_LN_LNGTH 0x00000FFF | ||
1349 | |||
1350 | #define FLD_AUD_DST_PK_MODE 0x00004000 | ||
1351 | |||
1352 | #define FLD_AUD_CLK_ENABLE 0x00000200 | ||
1353 | |||
1354 | #define FLD_AUD_MASTER_MODE 0x00000002 | ||
1355 | |||
1356 | #define FLD_AUD_SONY_MODE 0x00000001 | ||
1357 | |||
1358 | #define FLD_AUD_CLK_SELECT_PLL_D 0x00001800 | ||
1359 | |||
1360 | #define FLD_AUD_DST_ENABLE 0x00020000 | ||
1361 | |||
1362 | #define FLD_AUD_SRC_ENABLE 0x00010000 | ||
1363 | |||
1364 | //***************************************************************************** | ||
1365 | #define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control | ||
1366 | |||
1367 | #define FLD_AUD_SRC_E_RISC_EN 0x00008000 | ||
1368 | #define FLD_AUD_SRC_C_RISC_EN 0x00004000 | ||
1369 | #define FLD_AUD_SRC_B_RISC_EN 0x00002000 | ||
1370 | #define FLD_AUD_SRC_A_RISC_EN 0x00001000 | ||
1371 | |||
1372 | #define FLD_AUD_DST_D_RISC_EN 0x00000800 | ||
1373 | #define FLD_AUD_DST_C_RISC_EN 0x00000400 | ||
1374 | #define FLD_AUD_DST_B_RISC_EN 0x00000200 | ||
1375 | #define FLD_AUD_DST_A_RISC_EN 0x00000100 | ||
1376 | |||
1377 | #define FLD_AUD_SRC_E_FIFO_EN 0x00000080 | ||
1378 | #define FLD_AUD_SRC_C_FIFO_EN 0x00000040 | ||
1379 | #define FLD_AUD_SRC_B_FIFO_EN 0x00000020 | ||
1380 | #define FLD_AUD_SRC_A_FIFO_EN 0x00000010 | ||
1381 | |||
1382 | #define FLD_AUD_DST_D_FIFO_EN 0x00000008 | ||
1383 | #define FLD_AUD_DST_C_FIFO_EN 0x00000004 | ||
1384 | #define FLD_AUD_DST_B_FIFO_EN 0x00000002 | ||
1385 | #define FLD_AUD_DST_A_FIFO_EN 0x00000001 | ||
1386 | |||
1387 | //***************************************************************************** | ||
1388 | // | ||
1389 | // Mobilygen Interface Registers | ||
1390 | // | ||
1391 | //***************************************************************************** | ||
1392 | // Mobilygen Interface A | ||
1393 | //***************************************************************************** | ||
1394 | #define MB_IF_A_DMA 0x150000 // MBIF A DMA data port | ||
1395 | #define MB_IF_A_GPCN 0x150008 // MBIF A GP counter | ||
1396 | #define MB_IF_A_GPCN_CTRL 0x15000C | ||
1397 | #define MB_IF_A_DMA_CTRL 0x150010 | ||
1398 | #define MB_IF_A_LENGTH 0x150014 | ||
1399 | #define MB_IF_A_HDMA_XFER_SZ 0x150018 | ||
1400 | #define MB_IF_A_HCMD 0x15001C | ||
1401 | #define MB_IF_A_HCONFIG 0x150020 | ||
1402 | #define MB_IF_A_DATA_STRUCT_0 0x150024 | ||
1403 | #define MB_IF_A_DATA_STRUCT_1 0x150028 | ||
1404 | #define MB_IF_A_DATA_STRUCT_2 0x15002C | ||
1405 | #define MB_IF_A_DATA_STRUCT_3 0x150030 | ||
1406 | #define MB_IF_A_DATA_STRUCT_4 0x150034 | ||
1407 | #define MB_IF_A_DATA_STRUCT_5 0x150038 | ||
1408 | #define MB_IF_A_DATA_STRUCT_6 0x15003C | ||
1409 | #define MB_IF_A_DATA_STRUCT_7 0x150040 | ||
1410 | #define MB_IF_A_DATA_STRUCT_8 0x150044 | ||
1411 | #define MB_IF_A_DATA_STRUCT_9 0x150048 | ||
1412 | #define MB_IF_A_DATA_STRUCT_A 0x15004C | ||
1413 | #define MB_IF_A_DATA_STRUCT_B 0x150050 | ||
1414 | #define MB_IF_A_DATA_STRUCT_C 0x150054 | ||
1415 | #define MB_IF_A_DATA_STRUCT_D 0x150058 | ||
1416 | #define MB_IF_A_DATA_STRUCT_E 0x15005C | ||
1417 | #define MB_IF_A_DATA_STRUCT_F 0x150060 | ||
1418 | //***************************************************************************** | ||
1419 | // Mobilygen Interface B | ||
1420 | //***************************************************************************** | ||
1421 | #define MB_IF_B_DMA 0x160000 // MBIF A DMA data port | ||
1422 | #define MB_IF_B_GPCN 0x160008 // MBIF A GP counter | ||
1423 | #define MB_IF_B_GPCN_CTRL 0x16000C | ||
1424 | #define MB_IF_B_DMA_CTRL 0x160010 | ||
1425 | #define MB_IF_B_LENGTH 0x160014 | ||
1426 | #define MB_IF_B_HDMA_XFER_SZ 0x160018 | ||
1427 | #define MB_IF_B_HCMD 0x16001C | ||
1428 | #define MB_IF_B_HCONFIG 0x160020 | ||
1429 | #define MB_IF_B_DATA_STRUCT_0 0x160024 | ||
1430 | #define MB_IF_B_DATA_STRUCT_1 0x160028 | ||
1431 | #define MB_IF_B_DATA_STRUCT_2 0x16002C | ||
1432 | #define MB_IF_B_DATA_STRUCT_3 0x160030 | ||
1433 | #define MB_IF_B_DATA_STRUCT_4 0x160034 | ||
1434 | #define MB_IF_B_DATA_STRUCT_5 0x160038 | ||
1435 | #define MB_IF_B_DATA_STRUCT_6 0x16003C | ||
1436 | #define MB_IF_B_DATA_STRUCT_7 0x160040 | ||
1437 | #define MB_IF_B_DATA_STRUCT_8 0x160044 | ||
1438 | #define MB_IF_B_DATA_STRUCT_9 0x160048 | ||
1439 | #define MB_IF_B_DATA_STRUCT_A 0x16004C | ||
1440 | #define MB_IF_B_DATA_STRUCT_B 0x160050 | ||
1441 | #define MB_IF_B_DATA_STRUCT_C 0x160054 | ||
1442 | #define MB_IF_B_DATA_STRUCT_D 0x160058 | ||
1443 | #define MB_IF_B_DATA_STRUCT_E 0x16005C | ||
1444 | #define MB_IF_B_DATA_STRUCT_F 0x160060 | ||
1445 | |||
1446 | // MB_DMA_CTRL | ||
1447 | #define FLD_MB_IF_RISC_EN 0x00000010 | ||
1448 | #define FLD_MB_IF_FIFO_EN 0x00000001 | ||
1449 | |||
1450 | // MB_LENGTH | ||
1451 | #define FLD_MB_IF_LN_LNGTH 0x00000FFF | ||
1452 | |||
1453 | // MB_HCMD register | ||
1454 | #define FLD_MB_HCMD_H_GO 0x80000000 | ||
1455 | #define FLD_MB_HCMD_H_BUSY 0x40000000 | ||
1456 | #define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 | ||
1457 | #define FLD_MB_HCMD_H_DMA_BUSY 0x08000000 | ||
1458 | #define FLD_MB_HCMD_H_DMA_TYPE 0x04000000 | ||
1459 | #define FLD_MB_HCMD_H_DMA_XACT 0x02000000 | ||
1460 | #define FLD_MB_HCMD_H_RW_N 0x01000000 | ||
1461 | #define FLD_MB_HCMD_H_ADDR 0x00FF0000 | ||
1462 | #define FLD_MB_HCMD_H_DATA 0x0000FFFF | ||
1463 | |||
1464 | //***************************************************************************** | ||
1465 | // I2C #1 | ||
1466 | //***************************************************************************** | ||
1467 | #define I2C1_ADDR 0x180000 // I2C #1 address | ||
1468 | #define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address | ||
1469 | // RO [24] reserved | ||
1470 | //***************************************************************************** | ||
1471 | #define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address | ||
1472 | |||
1473 | //***************************************************************************** | ||
1474 | #define I2C1_WDATA 0x180004 // I2C #1 write data | ||
1475 | #define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] | ||
1476 | |||
1477 | //***************************************************************************** | ||
1478 | #define I2C1_CTRL 0x180008 // I2C #1 control | ||
1479 | #define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] | ||
1480 | #define FLD_I2C_SCL_IN 0x00200000 // RW [21] | ||
1481 | #define FLD_I2C_SDA_IN 0x00100000 // RW [20] | ||
1482 | // RO [19:18] reserved | ||
1483 | #define FLD_I2C_SCL_OUT 0x00020000 // RW [17] | ||
1484 | #define FLD_I2C_SDA_OUT 0x00010000 // RW [16] | ||
1485 | // RO [15] reserved | ||
1486 | #define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] | ||
1487 | #define FLD_I2C_SADDR_INC 0x00000800 // RW [11] | ||
1488 | // RO [10:9] reserved | ||
1489 | #define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] | ||
1490 | // RO [7:6] reserved | ||
1491 | #define FLD_I2C_SOFT 0x00000020 // RW [5] | ||
1492 | #define FLD_I2C_NOSTOP 0x00000010 // RW [4] | ||
1493 | #define FLD_I2C_EXTEND 0x00000008 // RW [3] | ||
1494 | #define FLD_I2C_SYNC 0x00000004 // RW [2] | ||
1495 | #define FLD_I2C_READ_SA 0x00000002 // RW [1] | ||
1496 | #define FLD_I2C_READ_WRN 0x00000001 // RW [0] | ||
1497 | |||
1498 | //***************************************************************************** | ||
1499 | #define I2C1_RDATA 0x18000C // I2C #1 read data | ||
1500 | #define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] | ||
1501 | |||
1502 | //***************************************************************************** | ||
1503 | #define I2C1_STAT 0x180010 // I2C #1 status | ||
1504 | #define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] | ||
1505 | #define FLD_I2C_RACK 0x00000001 // RO [0] | ||
1506 | |||
1507 | //***************************************************************************** | ||
1508 | // I2C #2 | ||
1509 | //***************************************************************************** | ||
1510 | #define I2C2_ADDR 0x190000 // I2C #2 address | ||
1511 | |||
1512 | //***************************************************************************** | ||
1513 | #define I2C2_WDATA 0x190004 // I2C #2 write data | ||
1514 | |||
1515 | //***************************************************************************** | ||
1516 | #define I2C2_CTRL 0x190008 // I2C #2 control | ||
1517 | |||
1518 | //***************************************************************************** | ||
1519 | #define I2C2_RDATA 0x19000C // I2C #2 read data | ||
1520 | |||
1521 | //***************************************************************************** | ||
1522 | #define I2C2_STAT 0x190010 // I2C #2 status | ||
1523 | |||
1524 | //***************************************************************************** | ||
1525 | // I2C #3 | ||
1526 | //***************************************************************************** | ||
1527 | #define I2C3_ADDR 0x1A0000 // I2C #3 address | ||
1528 | |||
1529 | //***************************************************************************** | ||
1530 | #define I2C3_WDATA 0x1A0004 // I2C #3 write data | ||
1531 | |||
1532 | //***************************************************************************** | ||
1533 | #define I2C3_CTRL 0x1A0008 // I2C #3 control | ||
1534 | |||
1535 | //***************************************************************************** | ||
1536 | #define I2C3_RDATA 0x1A000C // I2C #3 read data | ||
1537 | |||
1538 | //***************************************************************************** | ||
1539 | #define I2C3_STAT 0x1A0010 // I2C #3 status | ||
1540 | |||
1541 | //***************************************************************************** | ||
1542 | // UART | ||
1543 | //***************************************************************************** | ||
1544 | #define UART_CTL 0x1B0000 // UART Control Register | ||
1545 | #define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 | ||
1546 | #define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 | ||
1547 | #define FLD_RX_EN (1 << 1) // RW field - default 0 | ||
1548 | #define FLD_TX_EN (1 << 0) // RW field - default 0 | ||
1549 | |||
1550 | //***************************************************************************** | ||
1551 | #define UART_BRD 0x1B0004 // UART Baud Rate Divisor | ||
1552 | #define FLD_BRD 0x0000FFFF // RW field - default 0x197 | ||
1553 | |||
1554 | //***************************************************************************** | ||
1555 | #define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer | ||
1556 | #define FLD_DB 0xFFFFFFFF // RW field - default 0 | ||
1557 | |||
1558 | //***************************************************************************** | ||
1559 | #define UART_ISR 0x1B000C // UART Interrupt Status | ||
1560 | #define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 | ||
1561 | #define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 | ||
1562 | #define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 | ||
1563 | #define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 | ||
1564 | #define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 | ||
1565 | #define FLD_FRM_ERR (1 << 2) // RW field - default 0 | ||
1566 | #define FLD_RXD_RDY (1 << 1) // RW field - default 0 | ||
1567 | #define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 | ||
1568 | |||
1569 | //***************************************************************************** | ||
1570 | #define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count | ||
1571 | #define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 | ||
1572 | #define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 | ||
1573 | |||
1574 | //***************************************************************************** | ||
1575 | // Motion Detection | ||
1576 | #define MD_CH0_GRID_BLOCK_YCNT 0x170014 | ||
1577 | #define MD_CH1_GRID_BLOCK_YCNT 0x170094 | ||
1578 | #define MD_CH2_GRID_BLOCK_YCNT 0x170114 | ||
1579 | #define MD_CH3_GRID_BLOCK_YCNT 0x170194 | ||
1580 | #define MD_CH4_GRID_BLOCK_YCNT 0x170214 | ||
1581 | #define MD_CH5_GRID_BLOCK_YCNT 0x170294 | ||
1582 | #define MD_CH6_GRID_BLOCK_YCNT 0x170314 | ||
1583 | #define MD_CH7_GRID_BLOCK_YCNT 0x170394 | ||
1584 | |||
1585 | #define PIXEL_FRMT_422 4 | ||
1586 | #define PIXEL_FRMT_411 5 | ||
1587 | #define PIXEL_FRMT_Y8 6 | ||
1588 | |||
1589 | #define PIXEL_ENGINE_VIP1 0 | ||
1590 | #define PIXEL_ENGINE_VIP2 1 | ||
1591 | |||
1592 | #endif //Athena_REGISTERS | ||
diff --git a/drivers/staging/cx25821/cx25821-sram.h b/drivers/staging/cx25821/cx25821-sram.h new file mode 100644 index 000000000000..bd677ee22996 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-sram.h | |||
@@ -0,0 +1,261 @@ | |||
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 | //#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM | ||
51 | //#define TX_SRAM_END_SIZE = 0; // End of TX SRAM | ||
52 | |||
53 | // Receive SRAM | ||
54 | #define RX_SRAM_START 0x10000 | ||
55 | #define VID_A_DOWN_CMDS 0x10000 | ||
56 | #define VID_B_DOWN_CMDS 0x10050 | ||
57 | #define VID_C_DOWN_CMDS 0x100A0 | ||
58 | #define VID_D_DOWN_CMDS 0x100F0 | ||
59 | #define VID_E_DOWN_CMDS 0x10140 | ||
60 | #define VID_F_DOWN_CMDS 0x10190 | ||
61 | #define VID_G_DOWN_CMDS 0x101E0 | ||
62 | #define VID_H_DOWN_CMDS 0x10230 | ||
63 | #define VID_A_UP_CMDS 0x10280 | ||
64 | #define VID_B_UP_CMDS 0x102D0 | ||
65 | #define VID_C_UP_CMDS 0x10320 | ||
66 | #define VID_D_UP_CMDS 0x10370 | ||
67 | #define VID_E_UP_CMDS 0x103C0 | ||
68 | #define VID_F_UP_CMDS 0x10410 | ||
69 | #define VID_I_UP_CMDS 0x10460 | ||
70 | #define VID_J_UP_CMDS 0x104B0 | ||
71 | #define AUD_A_DOWN_CMDS 0x10500 | ||
72 | #define AUD_B_DOWN_CMDS 0x10550 | ||
73 | #define AUD_C_DOWN_CMDS 0x105A0 | ||
74 | #define AUD_D_DOWN_CMDS 0x105F0 | ||
75 | #define AUD_A_UP_CMDS 0x10640 | ||
76 | #define AUD_B_UP_CMDS 0x10690 | ||
77 | #define AUD_C_UP_CMDS 0x106E0 | ||
78 | #define AUD_E_UP_CMDS 0x10730 | ||
79 | #define MBIF_A_DOWN_CMDS 0x10780 | ||
80 | #define MBIF_B_DOWN_CMDS 0x107D0 | ||
81 | #define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 | ||
82 | |||
83 | //#define RX_SRAM_POOL_START = 0x105B0; | ||
84 | |||
85 | #define VID_A_IQ 0x11000 | ||
86 | #define VID_B_IQ 0x11040 | ||
87 | #define VID_C_IQ 0x11080 | ||
88 | #define VID_D_IQ 0x110C0 | ||
89 | #define VID_E_IQ 0x11100 | ||
90 | #define VID_F_IQ 0x11140 | ||
91 | #define VID_G_IQ 0x11180 | ||
92 | #define VID_H_IQ 0x111C0 | ||
93 | #define VID_I_IQ 0x11200 | ||
94 | #define VID_J_IQ 0x11240 | ||
95 | #define AUD_A_IQ 0x11280 | ||
96 | #define AUD_B_IQ 0x112C0 | ||
97 | #define AUD_C_IQ 0x11300 | ||
98 | #define AUD_D_IQ 0x11340 | ||
99 | #define AUD_E_IQ 0x11380 | ||
100 | #define MBIF_A_IQ 0x11000 | ||
101 | #define MBIF_B_IQ 0x110C0 | ||
102 | |||
103 | #define VID_A_CDT 0x10C00 | ||
104 | #define VID_B_CDT 0x10C40 | ||
105 | #define VID_C_CDT 0x10C80 | ||
106 | #define VID_D_CDT 0x10CC0 | ||
107 | #define VID_E_CDT 0x10D00 | ||
108 | #define VID_F_CDT 0x10D40 | ||
109 | #define VID_G_CDT 0x10D80 | ||
110 | #define VID_H_CDT 0x10DC0 | ||
111 | #define VID_I_CDT 0x10E00 | ||
112 | #define VID_J_CDT 0x10E40 | ||
113 | #define AUD_A_CDT 0x10E80 | ||
114 | #define AUD_B_CDT 0x10EB0 | ||
115 | #define AUD_C_CDT 0x10EE0 | ||
116 | #define AUD_D_CDT 0x10F10 | ||
117 | #define AUD_E_CDT 0x10F40 | ||
118 | #define MBIF_A_CDT 0x10C00 | ||
119 | #define MBIF_B_CDT 0x10CC0 | ||
120 | |||
121 | // Cluster Buffer for RX | ||
122 | #define VID_A_UP_CLUSTER_1 0x11400 | ||
123 | #define VID_A_UP_CLUSTER_2 0x119A0 | ||
124 | #define VID_A_UP_CLUSTER_3 0x11F40 | ||
125 | #define VID_A_UP_CLUSTER_4 0x124E0 | ||
126 | |||
127 | #define VID_B_UP_CLUSTER_1 0x12A80 | ||
128 | #define VID_B_UP_CLUSTER_2 0x13020 | ||
129 | #define VID_B_UP_CLUSTER_3 0x135C0 | ||
130 | #define VID_B_UP_CLUSTER_4 0x13B60 | ||
131 | |||
132 | #define VID_C_UP_CLUSTER_1 0x14100 | ||
133 | #define VID_C_UP_CLUSTER_2 0x146A0 | ||
134 | #define VID_C_UP_CLUSTER_3 0x14C40 | ||
135 | #define VID_C_UP_CLUSTER_4 0x151E0 | ||
136 | |||
137 | #define VID_D_UP_CLUSTER_1 0x15780 | ||
138 | #define VID_D_UP_CLUSTER_2 0x15D20 | ||
139 | #define VID_D_UP_CLUSTER_3 0x162C0 | ||
140 | #define VID_D_UP_CLUSTER_4 0x16860 | ||
141 | |||
142 | #define VID_E_UP_CLUSTER_1 0x16E00 | ||
143 | #define VID_E_UP_CLUSTER_2 0x173A0 | ||
144 | #define VID_E_UP_CLUSTER_3 0x17940 | ||
145 | #define VID_E_UP_CLUSTER_4 0x17EE0 | ||
146 | |||
147 | #define VID_F_UP_CLUSTER_1 0x18480 | ||
148 | #define VID_F_UP_CLUSTER_2 0x18A20 | ||
149 | #define VID_F_UP_CLUSTER_3 0x18FC0 | ||
150 | #define VID_F_UP_CLUSTER_4 0x19560 | ||
151 | |||
152 | #define VID_I_UP_CLUSTER_1 0x19B00 | ||
153 | #define VID_I_UP_CLUSTER_2 0x1A0A0 | ||
154 | #define VID_I_UP_CLUSTER_3 0x1A640 | ||
155 | #define VID_I_UP_CLUSTER_4 0x1ABE0 | ||
156 | |||
157 | #define VID_J_UP_CLUSTER_1 0x1B180 | ||
158 | #define VID_J_UP_CLUSTER_2 0x1B720 | ||
159 | #define VID_J_UP_CLUSTER_3 0x1BCC0 | ||
160 | #define VID_J_UP_CLUSTER_4 0x1C260 | ||
161 | |||
162 | #define AUD_A_UP_CLUSTER_1 0x1C800 | ||
163 | #define AUD_A_UP_CLUSTER_2 0x1C880 | ||
164 | #define AUD_A_UP_CLUSTER_3 0x1C900 | ||
165 | |||
166 | #define AUD_B_UP_CLUSTER_1 0x1C980 | ||
167 | #define AUD_B_UP_CLUSTER_2 0x1CA00 | ||
168 | #define AUD_B_UP_CLUSTER_3 0x1CA80 | ||
169 | |||
170 | #define AUD_C_UP_CLUSTER_1 0x1CB00 | ||
171 | #define AUD_C_UP_CLUSTER_2 0x1CB80 | ||
172 | #define AUD_C_UP_CLUSTER_3 0x1CC00 | ||
173 | |||
174 | #define AUD_E_UP_CLUSTER_1 0x1CC80 | ||
175 | #define AUD_E_UP_CLUSTER_2 0x1CD00 | ||
176 | #define AUD_E_UP_CLUSTER_3 0x1CD80 | ||
177 | |||
178 | #define RX_SRAM_POOL_FREE 0x1CE00 | ||
179 | #define RX_SRAM_END 0x1D000 | ||
180 | |||
181 | // Free Receive SRAM 144 Bytes | ||
182 | |||
183 | // Transmit SRAM | ||
184 | #define TX_SRAM_POOL_START 0x00000 | ||
185 | |||
186 | #define VID_A_DOWN_CLUSTER_1 0x00040 | ||
187 | #define VID_A_DOWN_CLUSTER_2 0x005E0 | ||
188 | #define VID_A_DOWN_CLUSTER_3 0x00B80 | ||
189 | #define VID_A_DOWN_CLUSTER_4 0x01120 | ||
190 | |||
191 | #define VID_B_DOWN_CLUSTER_1 0x016C0 | ||
192 | #define VID_B_DOWN_CLUSTER_2 0x01C60 | ||
193 | #define VID_B_DOWN_CLUSTER_3 0x02200 | ||
194 | #define VID_B_DOWN_CLUSTER_4 0x027A0 | ||
195 | |||
196 | #define VID_C_DOWN_CLUSTER_1 0x02D40 | ||
197 | #define VID_C_DOWN_CLUSTER_2 0x032E0 | ||
198 | #define VID_C_DOWN_CLUSTER_3 0x03880 | ||
199 | #define VID_C_DOWN_CLUSTER_4 0x03E20 | ||
200 | |||
201 | #define VID_D_DOWN_CLUSTER_1 0x043C0 | ||
202 | #define VID_D_DOWN_CLUSTER_2 0x04960 | ||
203 | #define VID_D_DOWN_CLUSTER_3 0x04F00 | ||
204 | #define VID_D_DOWN_CLUSTER_4 0x054A0 | ||
205 | |||
206 | #define VID_E_DOWN_CLUSTER_1 0x05a40 | ||
207 | #define VID_E_DOWN_CLUSTER_2 0x05FE0 | ||
208 | #define VID_E_DOWN_CLUSTER_3 0x06580 | ||
209 | #define VID_E_DOWN_CLUSTER_4 0x06B20 | ||
210 | |||
211 | #define VID_F_DOWN_CLUSTER_1 0x070C0 | ||
212 | #define VID_F_DOWN_CLUSTER_2 0x07660 | ||
213 | #define VID_F_DOWN_CLUSTER_3 0x07C00 | ||
214 | #define VID_F_DOWN_CLUSTER_4 0x081A0 | ||
215 | |||
216 | #define VID_G_DOWN_CLUSTER_1 0x08740 | ||
217 | #define VID_G_DOWN_CLUSTER_2 0x08CE0 | ||
218 | #define VID_G_DOWN_CLUSTER_3 0x09280 | ||
219 | #define VID_G_DOWN_CLUSTER_4 0x09820 | ||
220 | |||
221 | #define VID_H_DOWN_CLUSTER_1 0x09DC0 | ||
222 | #define VID_H_DOWN_CLUSTER_2 0x0A360 | ||
223 | #define VID_H_DOWN_CLUSTER_3 0x0A900 | ||
224 | #define VID_H_DOWN_CLUSTER_4 0x0AEA0 | ||
225 | |||
226 | #define AUD_A_DOWN_CLUSTER_1 0x0B500 | ||
227 | #define AUD_A_DOWN_CLUSTER_2 0x0B580 | ||
228 | #define AUD_A_DOWN_CLUSTER_3 0x0B600 | ||
229 | |||
230 | #define AUD_B_DOWN_CLUSTER_1 0x0B680 | ||
231 | #define AUD_B_DOWN_CLUSTER_2 0x0B700 | ||
232 | #define AUD_B_DOWN_CLUSTER_3 0x0B780 | ||
233 | |||
234 | #define AUD_C_DOWN_CLUSTER_1 0x0B800 | ||
235 | #define AUD_C_DOWN_CLUSTER_2 0x0B880 | ||
236 | #define AUD_C_DOWN_CLUSTER_3 0x0B900 | ||
237 | |||
238 | #define AUD_D_DOWN_CLUSTER_1 0x0B980 | ||
239 | #define AUD_D_DOWN_CLUSTER_2 0x0BA00 | ||
240 | #define AUD_D_DOWN_CLUSTER_3 0x0BA80 | ||
241 | |||
242 | #define TX_SRAM_POOL_FREE 0x0BB00 | ||
243 | #define TX_SRAM_END 0x0C000 | ||
244 | |||
245 | #define BYTES_TO_DWORDS(bcount) ((bcount) >> 2) | ||
246 | #define BYTES_TO_QWORDS(bcount) ((bcount) >> 3) | ||
247 | #define BYTES_TO_OWORDS(bcount) ((bcount) >> 4) | ||
248 | |||
249 | #define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE) | ||
250 | #define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE) | ||
251 | #define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE) | ||
252 | |||
253 | #define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE) | ||
254 | #define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE) | ||
255 | #define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE) | ||
256 | |||
257 | #define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE) | ||
258 | #define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE) | ||
259 | #define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE) | ||
260 | |||
261 | #endif | ||
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 000000000000..c8905e0ac509 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c | |||
@@ -0,0 +1,835 @@ | |||
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 "cx25821-video.h" | ||
24 | #include "cx25821-video-upstream-ch2.h" | ||
25 | |||
26 | #include <linux/fs.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/syscalls.h> | ||
32 | #include <linux/file.h> | ||
33 | #include <linux/fcntl.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | |||
36 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
37 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | static int _intr_msk = | ||
41 | FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; | ||
42 | |||
43 | static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, | ||
44 | __le32 * rp, unsigned int offset, | ||
45 | unsigned int bpl, u32 sync_line, | ||
46 | unsigned int lines, | ||
47 | int fifo_enable, int field_type) | ||
48 | { | ||
49 | unsigned int line, i; | ||
50 | int dist_betwn_starts = bpl * 2; | ||
51 | |||
52 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
53 | |||
54 | if (USE_RISC_NOOP_VIDEO) { | ||
55 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
56 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /* scan lines */ | ||
61 | for (line = 0; line < lines; line++) { | ||
62 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
63 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); | ||
64 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
65 | |||
66 | if ((lines <= NTSC_FIELD_HEIGHT) | ||
67 | || (line < (NTSC_FIELD_HEIGHT - 1)) | ||
68 | || !(dev->_isNTSC_ch2)) { | ||
69 | offset += dist_betwn_starts; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | return rp; | ||
74 | } | ||
75 | |||
76 | static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, | ||
77 | __le32 * rp, | ||
78 | dma_addr_t databuf_phys_addr, | ||
79 | unsigned int offset, | ||
80 | u32 sync_line, unsigned int bpl, | ||
81 | unsigned int lines, | ||
82 | int fifo_enable, int field_type) | ||
83 | { | ||
84 | unsigned int line, i; | ||
85 | struct sram_channel *sram_ch = | ||
86 | &dev->sram_channels[dev->_channel2_upstream_select]; | ||
87 | int dist_betwn_starts = bpl * 2; | ||
88 | |||
89 | /* sync instruction */ | ||
90 | if (sync_line != NO_SYNC_LINE) { | ||
91 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
92 | } | ||
93 | |||
94 | if (USE_RISC_NOOP_VIDEO) { | ||
95 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
96 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* scan lines */ | ||
101 | for (line = 0; line < lines; line++) { | ||
102 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
103 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | ||
104 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
105 | |||
106 | if ((lines <= NTSC_FIELD_HEIGHT) | ||
107 | || (line < (NTSC_FIELD_HEIGHT - 1)) | ||
108 | || !(dev->_isNTSC_ch2)) { | ||
109 | offset += dist_betwn_starts; | ||
110 | } | ||
111 | |||
112 | // check if we need to enable the FIFO after the first 4 lines | ||
113 | // For the upstream video channel, the risc engine will enable the FIFO. | ||
114 | if (fifo_enable && line == 3) { | ||
115 | *(rp++) = RISC_WRITECR; | ||
116 | *(rp++) = sram_ch->dma_ctl; | ||
117 | *(rp++) = FLD_VID_FIFO_EN; | ||
118 | *(rp++) = 0x00000001; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | return rp; | ||
123 | } | ||
124 | |||
125 | int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, | ||
126 | struct pci_dev *pci, | ||
127 | unsigned int top_offset, unsigned int bpl, | ||
128 | unsigned int lines) | ||
129 | { | ||
130 | __le32 *rp; | ||
131 | int fifo_enable = 0; | ||
132 | int singlefield_lines = lines >> 1; //get line count for single field | ||
133 | int odd_num_lines = singlefield_lines; | ||
134 | int frame = 0; | ||
135 | int frame_size = 0; | ||
136 | int databuf_offset = 0; | ||
137 | int risc_program_size = 0; | ||
138 | int risc_flag = RISC_CNT_RESET; | ||
139 | unsigned int bottom_offset = bpl; | ||
140 | dma_addr_t risc_phys_jump_addr; | ||
141 | |||
142 | if (dev->_isNTSC_ch2) { | ||
143 | odd_num_lines = singlefield_lines + 1; | ||
144 | risc_program_size = FRAME1_VID_PROG_SIZE; | ||
145 | frame_size = | ||
146 | (bpl == | ||
147 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
148 | FRAME_SIZE_NTSC_Y422; | ||
149 | } else { | ||
150 | risc_program_size = PAL_VID_PROG_SIZE; | ||
151 | frame_size = | ||
152 | (bpl == | ||
153 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
154 | } | ||
155 | |||
156 | /* Virtual address of Risc buffer program */ | ||
157 | rp = dev->_dma_virt_addr_ch2; | ||
158 | |||
159 | for (frame = 0; frame < NUM_FRAMES; frame++) { | ||
160 | databuf_offset = frame_size * frame; | ||
161 | |||
162 | if (UNSET != top_offset) { | ||
163 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | ||
164 | rp = cx25821_risc_field_upstream_ch2(dev, rp, | ||
165 | dev-> | ||
166 | _data_buf_phys_addr_ch2 | ||
167 | + databuf_offset, | ||
168 | top_offset, 0, bpl, | ||
169 | odd_num_lines, | ||
170 | fifo_enable, | ||
171 | ODD_FIELD); | ||
172 | } | ||
173 | |||
174 | fifo_enable = FIFO_DISABLE; | ||
175 | |||
176 | //Even field | ||
177 | rp = cx25821_risc_field_upstream_ch2(dev, rp, | ||
178 | dev-> | ||
179 | _data_buf_phys_addr_ch2 + | ||
180 | databuf_offset, | ||
181 | bottom_offset, 0x200, bpl, | ||
182 | singlefield_lines, | ||
183 | fifo_enable, EVEN_FIELD); | ||
184 | |||
185 | if (frame == 0) { | ||
186 | risc_flag = RISC_CNT_RESET; | ||
187 | risc_phys_jump_addr = | ||
188 | dev->_dma_phys_start_addr_ch2 + risc_program_size; | ||
189 | } else { | ||
190 | risc_flag = RISC_CNT_INC; | ||
191 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; | ||
192 | } | ||
193 | |||
194 | // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ | ||
195 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | ||
196 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
197 | *(rp++) = cpu_to_le32(0); | ||
198 | } | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) | ||
204 | { | ||
205 | struct sram_channel *sram_ch = | ||
206 | &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; | ||
207 | u32 tmp = 0; | ||
208 | |||
209 | if (!dev->_is_running_ch2) { | ||
210 | printk | ||
211 | ("cx25821: No video file is currently running so return!\n"); | ||
212 | return; | ||
213 | } | ||
214 | //Disable RISC interrupts | ||
215 | tmp = cx_read(sram_ch->int_msk); | ||
216 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); | ||
217 | |||
218 | //Turn OFF risc and fifo | ||
219 | tmp = cx_read(sram_ch->dma_ctl); | ||
220 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); | ||
221 | |||
222 | //Clear data buffer memory | ||
223 | if (dev->_data_buf_virt_addr_ch2) | ||
224 | memset(dev->_data_buf_virt_addr_ch2, 0, | ||
225 | dev->_data_buf_size_ch2); | ||
226 | |||
227 | dev->_is_running_ch2 = 0; | ||
228 | dev->_is_first_frame_ch2 = 0; | ||
229 | dev->_frame_count_ch2 = 0; | ||
230 | dev->_file_status_ch2 = END_OF_FILE; | ||
231 | |||
232 | if (dev->_irq_queues_ch2) { | ||
233 | kfree(dev->_irq_queues_ch2); | ||
234 | dev->_irq_queues_ch2 = NULL; | ||
235 | } | ||
236 | |||
237 | if (dev->_filename_ch2 != NULL) | ||
238 | kfree(dev->_filename_ch2); | ||
239 | |||
240 | tmp = cx_read(VID_CH_MODE_SEL); | ||
241 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
242 | } | ||
243 | |||
244 | void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) | ||
245 | { | ||
246 | if (dev->_is_running_ch2) { | ||
247 | cx25821_stop_upstream_video_ch2(dev); | ||
248 | } | ||
249 | |||
250 | if (dev->_dma_virt_addr_ch2) { | ||
251 | pci_free_consistent(dev->pci, dev->_risc_size_ch2, | ||
252 | dev->_dma_virt_addr_ch2, | ||
253 | dev->_dma_phys_addr_ch2); | ||
254 | dev->_dma_virt_addr_ch2 = NULL; | ||
255 | } | ||
256 | |||
257 | if (dev->_data_buf_virt_addr_ch2) { | ||
258 | pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, | ||
259 | dev->_data_buf_virt_addr_ch2, | ||
260 | dev->_data_buf_phys_addr_ch2); | ||
261 | dev->_data_buf_virt_addr_ch2 = NULL; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
266 | { | ||
267 | struct file *myfile; | ||
268 | int frame_index_temp = dev->_frame_index_ch2; | ||
269 | int i = 0; | ||
270 | int line_size = | ||
271 | (dev->_pixel_format_ch2 == | ||
272 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
273 | int frame_size = 0; | ||
274 | int frame_offset = 0; | ||
275 | ssize_t vfs_read_retval = 0; | ||
276 | char mybuf[line_size]; | ||
277 | loff_t file_offset; | ||
278 | loff_t pos; | ||
279 | mm_segment_t old_fs; | ||
280 | |||
281 | if (dev->_file_status_ch2 == END_OF_FILE) | ||
282 | return 0; | ||
283 | |||
284 | if (dev->_isNTSC_ch2) { | ||
285 | frame_size = | ||
286 | (line_size == | ||
287 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
288 | FRAME_SIZE_NTSC_Y422; | ||
289 | } else { | ||
290 | frame_size = | ||
291 | (line_size == | ||
292 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
293 | } | ||
294 | |||
295 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | ||
296 | file_offset = dev->_frame_count_ch2 * frame_size; | ||
297 | |||
298 | myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); | ||
299 | |||
300 | if (IS_ERR(myfile)) { | ||
301 | const int open_errno = -PTR_ERR(myfile); | ||
302 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
303 | __func__, dev->_filename_ch2, open_errno); | ||
304 | return PTR_ERR(myfile); | ||
305 | } else { | ||
306 | if (!(myfile->f_op)) { | ||
307 | printk("%s: File has no file operations registered!", | ||
308 | __func__); | ||
309 | filp_close(myfile, NULL); | ||
310 | return -EIO; | ||
311 | } | ||
312 | |||
313 | if (!myfile->f_op->read) { | ||
314 | printk("%s: File has no READ operations registered!", | ||
315 | __func__); | ||
316 | filp_close(myfile, NULL); | ||
317 | return -EIO; | ||
318 | } | ||
319 | |||
320 | pos = myfile->f_pos; | ||
321 | old_fs = get_fs(); | ||
322 | set_fs(KERNEL_DS); | ||
323 | |||
324 | for (i = 0; i < dev->_lines_count_ch2; i++) { | ||
325 | pos = file_offset; | ||
326 | |||
327 | vfs_read_retval = | ||
328 | vfs_read(myfile, mybuf, line_size, &pos); | ||
329 | |||
330 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | ||
331 | && dev->_data_buf_virt_addr_ch2 != NULL) { | ||
332 | memcpy((void *)(dev->_data_buf_virt_addr_ch2 + | ||
333 | frame_offset / 4), mybuf, | ||
334 | vfs_read_retval); | ||
335 | } | ||
336 | |||
337 | file_offset += vfs_read_retval; | ||
338 | frame_offset += vfs_read_retval; | ||
339 | |||
340 | if (vfs_read_retval < line_size) { | ||
341 | printk(KERN_INFO | ||
342 | "Done: exit %s() since no more bytes to read from Video file.\n", | ||
343 | __func__); | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | if (i > 0) | ||
349 | dev->_frame_count_ch2++; | ||
350 | |||
351 | dev->_file_status_ch2 = | ||
352 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
353 | |||
354 | set_fs(old_fs); | ||
355 | filp_close(myfile, NULL); | ||
356 | } | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static void cx25821_vidups_handler_ch2(struct work_struct *work) | ||
362 | { | ||
363 | struct cx25821_dev *dev = | ||
364 | container_of(work, struct cx25821_dev, _irq_work_entry_ch2); | ||
365 | |||
366 | if (!dev) { | ||
367 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", | ||
368 | __func__); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | cx25821_get_frame_ch2(dev, | ||
373 | &dev->sram_channels[dev-> | ||
374 | _channel2_upstream_select]); | ||
375 | } | ||
376 | |||
377 | int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
378 | { | ||
379 | struct file *myfile; | ||
380 | int i = 0, j = 0; | ||
381 | int line_size = | ||
382 | (dev->_pixel_format_ch2 == | ||
383 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
384 | ssize_t vfs_read_retval = 0; | ||
385 | char mybuf[line_size]; | ||
386 | loff_t pos; | ||
387 | loff_t offset = (unsigned long)0; | ||
388 | mm_segment_t old_fs; | ||
389 | |||
390 | myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); | ||
391 | |||
392 | if (IS_ERR(myfile)) { | ||
393 | const int open_errno = -PTR_ERR(myfile); | ||
394 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
395 | __func__, dev->_filename_ch2, open_errno); | ||
396 | return PTR_ERR(myfile); | ||
397 | } else { | ||
398 | if (!(myfile->f_op)) { | ||
399 | printk("%s: File has no file operations registered!", | ||
400 | __func__); | ||
401 | filp_close(myfile, NULL); | ||
402 | return -EIO; | ||
403 | } | ||
404 | |||
405 | if (!myfile->f_op->read) { | ||
406 | printk | ||
407 | ("%s: File has no READ operations registered! Returning.", | ||
408 | __func__); | ||
409 | filp_close(myfile, NULL); | ||
410 | return -EIO; | ||
411 | } | ||
412 | |||
413 | pos = myfile->f_pos; | ||
414 | old_fs = get_fs(); | ||
415 | set_fs(KERNEL_DS); | ||
416 | |||
417 | for (j = 0; j < NUM_FRAMES; j++) { | ||
418 | for (i = 0; i < dev->_lines_count_ch2; i++) { | ||
419 | pos = offset; | ||
420 | |||
421 | vfs_read_retval = | ||
422 | vfs_read(myfile, mybuf, line_size, &pos); | ||
423 | |||
424 | if (vfs_read_retval > 0 | ||
425 | && vfs_read_retval == line_size | ||
426 | && dev->_data_buf_virt_addr_ch2 != NULL) { | ||
427 | memcpy((void *)(dev-> | ||
428 | _data_buf_virt_addr_ch2 | ||
429 | + offset / 4), mybuf, | ||
430 | vfs_read_retval); | ||
431 | } | ||
432 | |||
433 | offset += vfs_read_retval; | ||
434 | |||
435 | if (vfs_read_retval < line_size) { | ||
436 | printk(KERN_INFO | ||
437 | "Done: exit %s() since no more bytes to read from Video file.\n", | ||
438 | __func__); | ||
439 | break; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | if (i > 0) | ||
444 | dev->_frame_count_ch2++; | ||
445 | |||
446 | if (vfs_read_retval < line_size) { | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | dev->_file_status_ch2 = | ||
452 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
453 | |||
454 | set_fs(old_fs); | ||
455 | myfile->f_pos = 0; | ||
456 | filp_close(myfile, NULL); | ||
457 | } | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, | ||
463 | struct sram_channel *sram_ch, | ||
464 | int bpl) | ||
465 | { | ||
466 | int ret = 0; | ||
467 | dma_addr_t dma_addr; | ||
468 | dma_addr_t data_dma_addr; | ||
469 | |||
470 | if (dev->_dma_virt_addr_ch2 != NULL) { | ||
471 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, | ||
472 | dev->_dma_virt_addr_ch2, | ||
473 | dev->_dma_phys_addr_ch2); | ||
474 | } | ||
475 | |||
476 | dev->_dma_virt_addr_ch2 = | ||
477 | pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, | ||
478 | &dma_addr); | ||
479 | dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; | ||
480 | dev->_dma_phys_start_addr_ch2 = dma_addr; | ||
481 | dev->_dma_phys_addr_ch2 = dma_addr; | ||
482 | dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; | ||
483 | |||
484 | if (!dev->_dma_virt_addr_ch2) { | ||
485 | printk | ||
486 | ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); | ||
487 | return -ENOMEM; | ||
488 | } | ||
489 | |||
490 | //Iniitize at this address until n bytes to 0 | ||
491 | memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2); | ||
492 | |||
493 | if (dev->_data_buf_virt_addr_ch2 != NULL) { | ||
494 | pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, | ||
495 | dev->_data_buf_virt_addr_ch2, | ||
496 | dev->_data_buf_phys_addr_ch2); | ||
497 | } | ||
498 | //For Video Data buffer allocation | ||
499 | dev->_data_buf_virt_addr_ch2 = | ||
500 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, | ||
501 | &data_dma_addr); | ||
502 | dev->_data_buf_phys_addr_ch2 = data_dma_addr; | ||
503 | dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; | ||
504 | |||
505 | if (!dev->_data_buf_virt_addr_ch2) { | ||
506 | printk | ||
507 | ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); | ||
508 | return -ENOMEM; | ||
509 | } | ||
510 | |||
511 | //Initialize at this address until n bytes to 0 | ||
512 | memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); | ||
513 | |||
514 | ret = cx25821_openfile_ch2(dev, sram_ch); | ||
515 | if (ret < 0) | ||
516 | return ret; | ||
517 | |||
518 | //Creating RISC programs | ||
519 | ret = | ||
520 | cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, | ||
521 | dev->_lines_count_ch2); | ||
522 | if (ret < 0) { | ||
523 | printk(KERN_INFO | ||
524 | "cx25821: Failed creating Video Upstream Risc programs! \n"); | ||
525 | goto error; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | |||
530 | error: | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, | ||
535 | u32 status) | ||
536 | { | ||
537 | u32 int_msk_tmp; | ||
538 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
539 | int singlefield_lines = NTSC_FIELD_HEIGHT; | ||
540 | int line_size_in_bytes = Y422_LINE_SZ; | ||
541 | int odd_risc_prog_size = 0; | ||
542 | dma_addr_t risc_phys_jump_addr; | ||
543 | __le32 *rp; | ||
544 | |||
545 | if (status & FLD_VID_SRC_RISC1) { | ||
546 | // We should only process one program per call | ||
547 | u32 prog_cnt = cx_read(channel->gpcnt); | ||
548 | |||
549 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
550 | int_msk_tmp = cx_read(channel->int_msk); | ||
551 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | ||
552 | cx_write(channel->int_stat, _intr_msk); | ||
553 | |||
554 | spin_lock(&dev->slock); | ||
555 | |||
556 | dev->_frame_index_ch2 = prog_cnt; | ||
557 | |||
558 | queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); | ||
559 | |||
560 | if (dev->_is_first_frame_ch2) { | ||
561 | dev->_is_first_frame_ch2 = 0; | ||
562 | |||
563 | if (dev->_isNTSC_ch2) { | ||
564 | singlefield_lines += 1; | ||
565 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | ||
566 | } else { | ||
567 | singlefield_lines = PAL_FIELD_HEIGHT; | ||
568 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | ||
569 | } | ||
570 | |||
571 | if (dev->_dma_virt_start_addr_ch2 != NULL) { | ||
572 | line_size_in_bytes = | ||
573 | (dev->_pixel_format_ch2 == | ||
574 | PIXEL_FRMT_411) ? Y411_LINE_SZ : | ||
575 | Y422_LINE_SZ; | ||
576 | risc_phys_jump_addr = | ||
577 | dev->_dma_phys_start_addr_ch2 + | ||
578 | odd_risc_prog_size; | ||
579 | |||
580 | rp = cx25821_update_riscprogram_ch2(dev, | ||
581 | dev-> | ||
582 | _dma_virt_start_addr_ch2, | ||
583 | TOP_OFFSET, | ||
584 | line_size_in_bytes, | ||
585 | 0x0, | ||
586 | singlefield_lines, | ||
587 | FIFO_DISABLE, | ||
588 | 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 | if (dev->_file_status_ch2 == END_OF_FILE) { | ||
601 | printk("cx25821: EOF Channel 2 Framecount = %d\n", | ||
602 | dev->_frame_count_ch2); | ||
603 | return -1; | ||
604 | } | ||
605 | //ElSE, set the interrupt mask register, re-enable irq. | ||
606 | int_msk_tmp = cx_read(channel->int_msk); | ||
607 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) | ||
613 | { | ||
614 | struct cx25821_dev *dev = dev_id; | ||
615 | u32 msk_stat, vid_status; | ||
616 | int handled = 0; | ||
617 | int channel_num = 0; | ||
618 | struct sram_channel *sram_ch; | ||
619 | |||
620 | if (!dev) | ||
621 | return -1; | ||
622 | |||
623 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; | ||
624 | |||
625 | sram_ch = &dev->sram_channels[channel_num]; | ||
626 | |||
627 | msk_stat = cx_read(sram_ch->int_mstat); | ||
628 | vid_status = cx_read(sram_ch->int_stat); | ||
629 | |||
630 | // Only deal with our interrupt | ||
631 | if (vid_status) { | ||
632 | handled = | ||
633 | cx25821_video_upstream_irq_ch2(dev, channel_num, | ||
634 | vid_status); | ||
635 | } | ||
636 | |||
637 | if (handled < 0) { | ||
638 | cx25821_stop_upstream_video_ch2(dev); | ||
639 | } else { | ||
640 | handled += handled; | ||
641 | } | ||
642 | |||
643 | return IRQ_RETVAL(handled); | ||
644 | } | ||
645 | |||
646 | static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, | ||
647 | struct sram_channel *ch, int pix_format) | ||
648 | { | ||
649 | int width = WIDTH_D1; | ||
650 | int height = dev->_lines_count_ch2; | ||
651 | int num_lines, odd_num_lines; | ||
652 | u32 value; | ||
653 | int vip_mode = PIXEL_ENGINE_VIP1; | ||
654 | |||
655 | value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); | ||
656 | value &= 0xFFFFFFEF; | ||
657 | value |= dev->_isNTSC_ch2 ? 0 : 0x10; | ||
658 | cx_write(ch->vid_fmt_ctl, value); | ||
659 | |||
660 | // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format | ||
661 | cx_write(ch->vid_active_ctl1, width); | ||
662 | |||
663 | num_lines = (height / 2) & 0x3FF; | ||
664 | odd_num_lines = num_lines; | ||
665 | |||
666 | if (dev->_isNTSC_ch2) { | ||
667 | odd_num_lines += 1; | ||
668 | } | ||
669 | |||
670 | value = (num_lines << 16) | odd_num_lines; | ||
671 | |||
672 | // set number of active lines in field 0 (top) and field 1 (bottom) | ||
673 | cx_write(ch->vid_active_ctl2, value); | ||
674 | |||
675 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); | ||
676 | } | ||
677 | |||
678 | int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, | ||
679 | struct sram_channel *sram_ch) | ||
680 | { | ||
681 | u32 tmp = 0; | ||
682 | int err = 0; | ||
683 | |||
684 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
685 | tmp = cx_read(VID_CH_MODE_SEL); | ||
686 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
687 | |||
688 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. | ||
689 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); | ||
690 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
691 | |||
692 | /* reset counter */ | ||
693 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
694 | |||
695 | // Clear our bits from the interrupt status register. | ||
696 | cx_write(sram_ch->int_stat, _intr_msk); | ||
697 | |||
698 | //Set the interrupt mask register, enable irq. | ||
699 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
700 | tmp = cx_read(sram_ch->int_msk); | ||
701 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | ||
702 | |||
703 | err = | ||
704 | request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, | ||
705 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
706 | if (err < 0) { | ||
707 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, | ||
708 | dev->pci->irq); | ||
709 | goto fail_irq; | ||
710 | } | ||
711 | // Start the DMA engine | ||
712 | tmp = cx_read(sram_ch->dma_ctl); | ||
713 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); | ||
714 | |||
715 | dev->_is_running_ch2 = 1; | ||
716 | dev->_is_first_frame_ch2 = 1; | ||
717 | |||
718 | return 0; | ||
719 | |||
720 | fail_irq: | ||
721 | cx25821_dev_unregister(dev); | ||
722 | return err; | ||
723 | } | ||
724 | |||
725 | int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, | ||
726 | int pixel_format) | ||
727 | { | ||
728 | struct sram_channel *sram_ch; | ||
729 | u32 tmp; | ||
730 | int retval = 0; | ||
731 | int err = 0; | ||
732 | int data_frame_size = 0; | ||
733 | int risc_buffer_size = 0; | ||
734 | int str_length = 0; | ||
735 | |||
736 | if (dev->_is_running_ch2) { | ||
737 | printk("Video Channel is still running so return!\n"); | ||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | dev->_channel2_upstream_select = channel_select; | ||
742 | sram_ch = &dev->sram_channels[channel_select]; | ||
743 | |||
744 | INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); | ||
745 | dev->_irq_queues_ch2 = | ||
746 | create_singlethread_workqueue("cx25821_workqueue2"); | ||
747 | |||
748 | if (!dev->_irq_queues_ch2) { | ||
749 | printk | ||
750 | ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); | ||
751 | return -ENOMEM; | ||
752 | } | ||
753 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
754 | tmp = cx_read(VID_CH_MODE_SEL); | ||
755 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
756 | |||
757 | dev->_is_running_ch2 = 0; | ||
758 | dev->_frame_count_ch2 = 0; | ||
759 | dev->_file_status_ch2 = RESET_STATUS; | ||
760 | dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; | ||
761 | dev->_pixel_format_ch2 = pixel_format; | ||
762 | dev->_line_size_ch2 = | ||
763 | (dev->_pixel_format_ch2 == | ||
764 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
765 | data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | ||
766 | risc_buffer_size = | ||
767 | dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | ||
768 | |||
769 | if (dev->input_filename_ch2) { | ||
770 | str_length = strlen(dev->input_filename_ch2); | ||
771 | dev->_filename_ch2 = | ||
772 | (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
773 | |||
774 | if (!dev->_filename_ch2) | ||
775 | goto error; | ||
776 | |||
777 | memcpy(dev->_filename_ch2, dev->input_filename_ch2, | ||
778 | str_length + 1); | ||
779 | } else { | ||
780 | str_length = strlen(dev->_defaultname_ch2); | ||
781 | dev->_filename_ch2 = | ||
782 | (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
783 | |||
784 | if (!dev->_filename_ch2) | ||
785 | goto error; | ||
786 | |||
787 | memcpy(dev->_filename_ch2, dev->_defaultname_ch2, | ||
788 | str_length + 1); | ||
789 | } | ||
790 | |||
791 | //Default if filename is empty string | ||
792 | if (strcmp(dev->input_filename_ch2, "") == 0) { | ||
793 | if (dev->_isNTSC_ch2) { | ||
794 | dev->_filename_ch2 = | ||
795 | (dev->_pixel_format_ch2 == | ||
796 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | ||
797 | "/root/vidtest.yuv"; | ||
798 | } else { | ||
799 | dev->_filename_ch2 = | ||
800 | (dev->_pixel_format_ch2 == | ||
801 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : | ||
802 | "/root/pal422.yuv"; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | retval = | ||
807 | cx25821_sram_channel_setup_upstream(dev, sram_ch, | ||
808 | dev->_line_size_ch2, 0); | ||
809 | |||
810 | /* setup fifo + format */ | ||
811 | cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); | ||
812 | |||
813 | dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; | ||
814 | dev->upstream_databuf_size_ch2 = data_frame_size * 2; | ||
815 | |||
816 | //Allocating buffers and prepare RISC program | ||
817 | retval = | ||
818 | cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, | ||
819 | dev->_line_size_ch2); | ||
820 | if (retval < 0) { | ||
821 | printk(KERN_ERR | ||
822 | "%s: Failed to set up Video upstream buffers!\n", | ||
823 | dev->name); | ||
824 | goto error; | ||
825 | } | ||
826 | |||
827 | cx25821_start_video_dma_upstream_ch2(dev, sram_ch); | ||
828 | |||
829 | return 0; | ||
830 | |||
831 | error: | ||
832 | cx25821_dev_unregister(dev); | ||
833 | |||
834 | return err; | ||
835 | } | ||
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 000000000000..73feea114c1c --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h | |||
@@ -0,0 +1,101 @@ | |||
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 OPEN_FILE_1 0 | ||
27 | #define NUM_PROGS 8 | ||
28 | #define NUM_FRAMES 2 | ||
29 | #define ODD_FIELD 0 | ||
30 | #define EVEN_FIELD 1 | ||
31 | #define TOP_OFFSET 0 | ||
32 | #define FIFO_DISABLE 0 | ||
33 | #define FIFO_ENABLE 1 | ||
34 | #define TEST_FRAMES 5 | ||
35 | #define END_OF_FILE 0 | ||
36 | #define IN_PROGRESS 1 | ||
37 | #define RESET_STATUS -1 | ||
38 | #define NUM_NO_OPS 5 | ||
39 | |||
40 | // PAL and NTSC line sizes and number of lines. | ||
41 | #define WIDTH_D1 720 | ||
42 | #define NTSC_LINES_PER_FRAME 480 | ||
43 | #define PAL_LINES_PER_FRAME 576 | ||
44 | #define PAL_LINE_SZ 1440 | ||
45 | #define Y422_LINE_SZ 1440 | ||
46 | #define Y411_LINE_SZ 1080 | ||
47 | #define NTSC_FIELD_HEIGHT 240 | ||
48 | #define NTSC_ODD_FLD_LINES 241 | ||
49 | #define PAL_FIELD_HEIGHT 288 | ||
50 | |||
51 | #define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) | ||
52 | #define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) | ||
53 | #define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) | ||
54 | #define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) | ||
55 | |||
56 | #define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) | ||
57 | #define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) | ||
58 | |||
59 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
60 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
61 | #define JUMP_INSTRUCTION_SIZE 12 | ||
62 | #define MAXSIZE_NO_OPS 36 | ||
63 | #define DWORD_SIZE 4 | ||
64 | |||
65 | #define USE_RISC_NOOP_VIDEO 1 | ||
66 | |||
67 | #ifdef USE_RISC_NOOP_VIDEO | ||
68 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
69 | RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
70 | |||
71 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
72 | |||
73 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
74 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
75 | |||
76 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
77 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
78 | |||
79 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
80 | JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
81 | |||
82 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
83 | |||
84 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
85 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
86 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
87 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
88 | #endif | ||
89 | |||
90 | #ifndef USE_RISC_NOOP_VIDEO | ||
91 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
92 | #define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) | ||
93 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
94 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
95 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
96 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
97 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
98 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) | ||
99 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
100 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
101 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c new file mode 100644 index 000000000000..3d7dd3f66541 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream.c | |||
@@ -0,0 +1,894 @@ | |||
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 "cx25821-video.h" | ||
24 | #include "cx25821-video-upstream.h" | ||
25 | |||
26 | #include <linux/fs.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/syscalls.h> | ||
32 | #include <linux/file.h> | ||
33 | #include <linux/fcntl.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | |||
36 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
37 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | static int _intr_msk = | ||
41 | FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; | ||
42 | |||
43 | int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | ||
44 | struct sram_channel *ch, | ||
45 | unsigned int bpl, u32 risc) | ||
46 | { | ||
47 | unsigned int i, lines; | ||
48 | u32 cdt; | ||
49 | |||
50 | if (ch->cmds_start == 0) { | ||
51 | cx_write(ch->ptr1_reg, 0); | ||
52 | cx_write(ch->ptr2_reg, 0); | ||
53 | cx_write(ch->cnt2_reg, 0); | ||
54 | cx_write(ch->cnt1_reg, 0); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
59 | cdt = ch->cdt; | ||
60 | lines = ch->fifo_size / bpl; | ||
61 | |||
62 | if (lines > 4) { | ||
63 | lines = 4; | ||
64 | } | ||
65 | |||
66 | BUG_ON(lines < 2); | ||
67 | |||
68 | /* write CDT */ | ||
69 | for (i = 0; i < lines; i++) { | ||
70 | cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); | ||
71 | cx_write(cdt + 16 * i + 4, 0); | ||
72 | cx_write(cdt + 16 * i + 8, 0); | ||
73 | cx_write(cdt + 16 * i + 12, 0); | ||
74 | } | ||
75 | |||
76 | /* write CMDS */ | ||
77 | cx_write(ch->cmds_start + 0, risc); | ||
78 | |||
79 | cx_write(ch->cmds_start + 4, 0); | ||
80 | cx_write(ch->cmds_start + 8, cdt); | ||
81 | cx_write(ch->cmds_start + 12, (lines * 16) >> 3); | ||
82 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
83 | |||
84 | cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); | ||
85 | |||
86 | for (i = 24; i < 80; i += 4) | ||
87 | cx_write(ch->cmds_start + i, 0); | ||
88 | |||
89 | /* fill registers */ | ||
90 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
91 | cx_write(ch->ptr2_reg, cdt); | ||
92 | cx_write(ch->cnt2_reg, (lines * 16) >> 3); | ||
93 | cx_write(ch->cnt1_reg, (bpl >> 3) - 1); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | ||
99 | __le32 * rp, unsigned int offset, | ||
100 | unsigned int bpl, u32 sync_line, | ||
101 | unsigned int lines, int fifo_enable, | ||
102 | int field_type) | ||
103 | { | ||
104 | unsigned int line, i; | ||
105 | int dist_betwn_starts = bpl * 2; | ||
106 | |||
107 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
108 | |||
109 | if (USE_RISC_NOOP_VIDEO) { | ||
110 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
111 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* scan lines */ | ||
116 | for (line = 0; line < lines; line++) { | ||
117 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
118 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset); | ||
119 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
120 | |||
121 | if ((lines <= NTSC_FIELD_HEIGHT) | ||
122 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { | ||
123 | offset += dist_betwn_starts; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | return rp; | ||
128 | } | ||
129 | |||
130 | static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | ||
131 | dma_addr_t databuf_phys_addr, | ||
132 | unsigned int offset, u32 sync_line, | ||
133 | unsigned int bpl, unsigned int lines, | ||
134 | int fifo_enable, int field_type) | ||
135 | { | ||
136 | unsigned int line, i; | ||
137 | struct sram_channel *sram_ch = | ||
138 | &dev->sram_channels[dev->_channel_upstream_select]; | ||
139 | int dist_betwn_starts = bpl * 2; | ||
140 | |||
141 | /* sync instruction */ | ||
142 | if (sync_line != NO_SYNC_LINE) { | ||
143 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
144 | } | ||
145 | |||
146 | if (USE_RISC_NOOP_VIDEO) { | ||
147 | for (i = 0; i < NUM_NO_OPS; i++) { | ||
148 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /* scan lines */ | ||
153 | for (line = 0; line < lines; line++) { | ||
154 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
155 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | ||
156 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
157 | |||
158 | if ((lines <= NTSC_FIELD_HEIGHT) | ||
159 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { | ||
160 | offset += dist_betwn_starts; //to skip the other field line | ||
161 | } | ||
162 | |||
163 | // check if we need to enable the FIFO after the first 4 lines | ||
164 | // For the upstream video channel, the risc engine will enable the FIFO. | ||
165 | if (fifo_enable && line == 3) { | ||
166 | *(rp++) = RISC_WRITECR; | ||
167 | *(rp++) = sram_ch->dma_ctl; | ||
168 | *(rp++) = FLD_VID_FIFO_EN; | ||
169 | *(rp++) = 0x00000001; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return rp; | ||
174 | } | ||
175 | |||
176 | int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | ||
177 | struct pci_dev *pci, | ||
178 | unsigned int top_offset, | ||
179 | unsigned int bpl, unsigned int lines) | ||
180 | { | ||
181 | __le32 *rp; | ||
182 | int fifo_enable = 0; | ||
183 | int singlefield_lines = lines >> 1; //get line count for single field | ||
184 | int odd_num_lines = singlefield_lines; | ||
185 | int frame = 0; | ||
186 | int frame_size = 0; | ||
187 | int databuf_offset = 0; | ||
188 | int risc_program_size = 0; | ||
189 | int risc_flag = RISC_CNT_RESET; | ||
190 | unsigned int bottom_offset = bpl; | ||
191 | dma_addr_t risc_phys_jump_addr; | ||
192 | |||
193 | if (dev->_isNTSC) { | ||
194 | odd_num_lines = singlefield_lines + 1; | ||
195 | risc_program_size = FRAME1_VID_PROG_SIZE; | ||
196 | frame_size = | ||
197 | (bpl == | ||
198 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
199 | FRAME_SIZE_NTSC_Y422; | ||
200 | } else { | ||
201 | risc_program_size = PAL_VID_PROG_SIZE; | ||
202 | frame_size = | ||
203 | (bpl == | ||
204 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
205 | } | ||
206 | |||
207 | /* Virtual address of Risc buffer program */ | ||
208 | rp = dev->_dma_virt_addr; | ||
209 | |||
210 | for (frame = 0; frame < NUM_FRAMES; frame++) { | ||
211 | databuf_offset = frame_size * frame; | ||
212 | |||
213 | if (UNSET != top_offset) { | ||
214 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | ||
215 | rp = cx25821_risc_field_upstream(dev, rp, | ||
216 | dev-> | ||
217 | _data_buf_phys_addr + | ||
218 | databuf_offset, | ||
219 | top_offset, 0, bpl, | ||
220 | odd_num_lines, | ||
221 | fifo_enable, | ||
222 | ODD_FIELD); | ||
223 | } | ||
224 | |||
225 | fifo_enable = FIFO_DISABLE; | ||
226 | |||
227 | //Even Field | ||
228 | rp = cx25821_risc_field_upstream(dev, rp, | ||
229 | dev->_data_buf_phys_addr + | ||
230 | databuf_offset, bottom_offset, | ||
231 | 0x200, bpl, singlefield_lines, | ||
232 | fifo_enable, EVEN_FIELD); | ||
233 | |||
234 | if (frame == 0) { | ||
235 | risc_flag = RISC_CNT_RESET; | ||
236 | risc_phys_jump_addr = | ||
237 | dev->_dma_phys_start_addr + risc_program_size; | ||
238 | } else { | ||
239 | risc_phys_jump_addr = dev->_dma_phys_start_addr; | ||
240 | risc_flag = RISC_CNT_INC; | ||
241 | } | ||
242 | |||
243 | // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ | ||
244 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | ||
245 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
246 | *(rp++) = cpu_to_le32(0); | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | ||
253 | { | ||
254 | struct sram_channel *sram_ch = | ||
255 | &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; | ||
256 | u32 tmp = 0; | ||
257 | |||
258 | if (!dev->_is_running) { | ||
259 | printk | ||
260 | ("cx25821: No video file is currently running so return!\n"); | ||
261 | return; | ||
262 | } | ||
263 | //Disable RISC interrupts | ||
264 | tmp = cx_read(sram_ch->int_msk); | ||
265 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); | ||
266 | |||
267 | //Turn OFF risc and fifo enable | ||
268 | tmp = cx_read(sram_ch->dma_ctl); | ||
269 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); | ||
270 | |||
271 | //Clear data buffer memory | ||
272 | if (dev->_data_buf_virt_addr) | ||
273 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | ||
274 | |||
275 | dev->_is_running = 0; | ||
276 | dev->_is_first_frame = 0; | ||
277 | dev->_frame_count = 0; | ||
278 | dev->_file_status = END_OF_FILE; | ||
279 | |||
280 | if (dev->_irq_queues) { | ||
281 | kfree(dev->_irq_queues); | ||
282 | dev->_irq_queues = NULL; | ||
283 | } | ||
284 | |||
285 | if (dev->_filename != NULL) | ||
286 | kfree(dev->_filename); | ||
287 | |||
288 | tmp = cx_read(VID_CH_MODE_SEL); | ||
289 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
290 | } | ||
291 | |||
292 | void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) | ||
293 | { | ||
294 | if (dev->_is_running) { | ||
295 | cx25821_stop_upstream_video_ch1(dev); | ||
296 | } | ||
297 | |||
298 | if (dev->_dma_virt_addr) { | ||
299 | pci_free_consistent(dev->pci, dev->_risc_size, | ||
300 | dev->_dma_virt_addr, dev->_dma_phys_addr); | ||
301 | dev->_dma_virt_addr = NULL; | ||
302 | } | ||
303 | |||
304 | if (dev->_data_buf_virt_addr) { | ||
305 | pci_free_consistent(dev->pci, dev->_data_buf_size, | ||
306 | dev->_data_buf_virt_addr, | ||
307 | dev->_data_buf_phys_addr); | ||
308 | dev->_data_buf_virt_addr = NULL; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
313 | { | ||
314 | struct file *myfile; | ||
315 | int frame_index_temp = dev->_frame_index; | ||
316 | int i = 0; | ||
317 | int line_size = | ||
318 | (dev->_pixel_format == | ||
319 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
320 | int frame_size = 0; | ||
321 | int frame_offset = 0; | ||
322 | ssize_t vfs_read_retval = 0; | ||
323 | char mybuf[line_size]; | ||
324 | loff_t file_offset; | ||
325 | loff_t pos; | ||
326 | mm_segment_t old_fs; | ||
327 | |||
328 | if (dev->_file_status == END_OF_FILE) | ||
329 | return 0; | ||
330 | |||
331 | if (dev->_isNTSC) { | ||
332 | frame_size = | ||
333 | (line_size == | ||
334 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
335 | FRAME_SIZE_NTSC_Y422; | ||
336 | } else { | ||
337 | frame_size = | ||
338 | (line_size == | ||
339 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
340 | } | ||
341 | |||
342 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | ||
343 | file_offset = dev->_frame_count * frame_size; | ||
344 | |||
345 | myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); | ||
346 | |||
347 | if (IS_ERR(myfile)) { | ||
348 | const int open_errno = -PTR_ERR(myfile); | ||
349 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
350 | __func__, dev->_filename, open_errno); | ||
351 | return PTR_ERR(myfile); | ||
352 | } else { | ||
353 | if (!(myfile->f_op)) { | ||
354 | printk("%s: File has no file operations registered!", | ||
355 | __func__); | ||
356 | filp_close(myfile, NULL); | ||
357 | return -EIO; | ||
358 | } | ||
359 | |||
360 | if (!myfile->f_op->read) { | ||
361 | printk("%s: File has no READ operations registered!", | ||
362 | __func__); | ||
363 | filp_close(myfile, NULL); | ||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | pos = myfile->f_pos; | ||
368 | old_fs = get_fs(); | ||
369 | set_fs(KERNEL_DS); | ||
370 | |||
371 | for (i = 0; i < dev->_lines_count; i++) { | ||
372 | pos = file_offset; | ||
373 | |||
374 | vfs_read_retval = | ||
375 | vfs_read(myfile, mybuf, line_size, &pos); | ||
376 | |||
377 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | ||
378 | && dev->_data_buf_virt_addr != NULL) { | ||
379 | memcpy((void *)(dev->_data_buf_virt_addr + | ||
380 | frame_offset / 4), mybuf, | ||
381 | vfs_read_retval); | ||
382 | } | ||
383 | |||
384 | file_offset += vfs_read_retval; | ||
385 | frame_offset += vfs_read_retval; | ||
386 | |||
387 | if (vfs_read_retval < line_size) { | ||
388 | printk(KERN_INFO | ||
389 | "Done: exit %s() since no more bytes to read from Video file.\n", | ||
390 | __func__); | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (i > 0) | ||
396 | dev->_frame_count++; | ||
397 | |||
398 | dev->_file_status = | ||
399 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
400 | |||
401 | set_fs(old_fs); | ||
402 | filp_close(myfile, NULL); | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static void cx25821_vidups_handler(struct work_struct *work) | ||
409 | { | ||
410 | struct cx25821_dev *dev = | ||
411 | container_of(work, struct cx25821_dev, _irq_work_entry); | ||
412 | |||
413 | if (!dev) { | ||
414 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", | ||
415 | __func__); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | cx25821_get_frame(dev, | ||
420 | &dev->sram_channels[dev->_channel_upstream_select]); | ||
421 | } | ||
422 | |||
423 | int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | ||
424 | { | ||
425 | struct file *myfile; | ||
426 | int i = 0, j = 0; | ||
427 | int line_size = | ||
428 | (dev->_pixel_format == | ||
429 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
430 | ssize_t vfs_read_retval = 0; | ||
431 | char mybuf[line_size]; | ||
432 | loff_t pos; | ||
433 | loff_t offset = (unsigned long)0; | ||
434 | mm_segment_t old_fs; | ||
435 | |||
436 | myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); | ||
437 | |||
438 | if (IS_ERR(myfile)) { | ||
439 | const int open_errno = -PTR_ERR(myfile); | ||
440 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | ||
441 | __func__, dev->_filename, open_errno); | ||
442 | return PTR_ERR(myfile); | ||
443 | } else { | ||
444 | if (!(myfile->f_op)) { | ||
445 | printk("%s: File has no file operations registered!", | ||
446 | __func__); | ||
447 | filp_close(myfile, NULL); | ||
448 | return -EIO; | ||
449 | } | ||
450 | |||
451 | if (!myfile->f_op->read) { | ||
452 | printk | ||
453 | ("%s: File has no READ operations registered! Returning.", | ||
454 | __func__); | ||
455 | filp_close(myfile, NULL); | ||
456 | return -EIO; | ||
457 | } | ||
458 | |||
459 | pos = myfile->f_pos; | ||
460 | old_fs = get_fs(); | ||
461 | set_fs(KERNEL_DS); | ||
462 | |||
463 | for (j = 0; j < NUM_FRAMES; j++) { | ||
464 | for (i = 0; i < dev->_lines_count; i++) { | ||
465 | pos = offset; | ||
466 | |||
467 | vfs_read_retval = | ||
468 | vfs_read(myfile, mybuf, line_size, &pos); | ||
469 | |||
470 | if (vfs_read_retval > 0 | ||
471 | && vfs_read_retval == line_size | ||
472 | && dev->_data_buf_virt_addr != NULL) { | ||
473 | memcpy((void *)(dev-> | ||
474 | _data_buf_virt_addr + | ||
475 | offset / 4), mybuf, | ||
476 | vfs_read_retval); | ||
477 | } | ||
478 | |||
479 | offset += vfs_read_retval; | ||
480 | |||
481 | if (vfs_read_retval < line_size) { | ||
482 | printk(KERN_INFO | ||
483 | "Done: exit %s() since no more bytes to read from Video file.\n", | ||
484 | __func__); | ||
485 | break; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (i > 0) | ||
490 | dev->_frame_count++; | ||
491 | |||
492 | if (vfs_read_retval < line_size) { | ||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | dev->_file_status = | ||
498 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | ||
499 | |||
500 | set_fs(old_fs); | ||
501 | myfile->f_pos = 0; | ||
502 | filp_close(myfile, NULL); | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | ||
509 | struct sram_channel *sram_ch, int bpl) | ||
510 | { | ||
511 | int ret = 0; | ||
512 | dma_addr_t dma_addr; | ||
513 | dma_addr_t data_dma_addr; | ||
514 | |||
515 | if (dev->_dma_virt_addr != NULL) { | ||
516 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, | ||
517 | dev->_dma_virt_addr, dev->_dma_phys_addr); | ||
518 | } | ||
519 | |||
520 | dev->_dma_virt_addr = | ||
521 | pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, | ||
522 | &dma_addr); | ||
523 | dev->_dma_virt_start_addr = dev->_dma_virt_addr; | ||
524 | dev->_dma_phys_start_addr = dma_addr; | ||
525 | dev->_dma_phys_addr = dma_addr; | ||
526 | dev->_risc_size = dev->upstream_riscbuf_size; | ||
527 | |||
528 | if (!dev->_dma_virt_addr) { | ||
529 | printk | ||
530 | ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); | ||
531 | return -ENOMEM; | ||
532 | } | ||
533 | |||
534 | //Clear memory at address | ||
535 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); | ||
536 | |||
537 | if (dev->_data_buf_virt_addr != NULL) { | ||
538 | pci_free_consistent(dev->pci, dev->upstream_databuf_size, | ||
539 | dev->_data_buf_virt_addr, | ||
540 | dev->_data_buf_phys_addr); | ||
541 | } | ||
542 | //For Video Data buffer allocation | ||
543 | dev->_data_buf_virt_addr = | ||
544 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, | ||
545 | &data_dma_addr); | ||
546 | dev->_data_buf_phys_addr = data_dma_addr; | ||
547 | dev->_data_buf_size = dev->upstream_databuf_size; | ||
548 | |||
549 | if (!dev->_data_buf_virt_addr) { | ||
550 | printk | ||
551 | ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); | ||
552 | return -ENOMEM; | ||
553 | } | ||
554 | |||
555 | //Clear memory at address | ||
556 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | ||
557 | |||
558 | ret = cx25821_openfile(dev, sram_ch); | ||
559 | if (ret < 0) | ||
560 | return ret; | ||
561 | |||
562 | //Create RISC programs | ||
563 | ret = | ||
564 | cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, | ||
565 | dev->_lines_count); | ||
566 | if (ret < 0) { | ||
567 | printk(KERN_INFO | ||
568 | "cx25821: Failed creating Video Upstream Risc programs! \n"); | ||
569 | goto error; | ||
570 | } | ||
571 | |||
572 | return 0; | ||
573 | |||
574 | error: | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | ||
579 | u32 status) | ||
580 | { | ||
581 | u32 int_msk_tmp; | ||
582 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
583 | int singlefield_lines = NTSC_FIELD_HEIGHT; | ||
584 | int line_size_in_bytes = Y422_LINE_SZ; | ||
585 | int odd_risc_prog_size = 0; | ||
586 | dma_addr_t risc_phys_jump_addr; | ||
587 | __le32 *rp; | ||
588 | |||
589 | if (status & FLD_VID_SRC_RISC1) { | ||
590 | // We should only process one program per call | ||
591 | u32 prog_cnt = cx_read(channel->gpcnt); | ||
592 | |||
593 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | ||
594 | int_msk_tmp = cx_read(channel->int_msk); | ||
595 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | ||
596 | cx_write(channel->int_stat, _intr_msk); | ||
597 | |||
598 | spin_lock(&dev->slock); | ||
599 | |||
600 | dev->_frame_index = prog_cnt; | ||
601 | |||
602 | queue_work(dev->_irq_queues, &dev->_irq_work_entry); | ||
603 | |||
604 | if (dev->_is_first_frame) { | ||
605 | dev->_is_first_frame = 0; | ||
606 | |||
607 | if (dev->_isNTSC) { | ||
608 | singlefield_lines += 1; | ||
609 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | ||
610 | } else { | ||
611 | singlefield_lines = PAL_FIELD_HEIGHT; | ||
612 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | ||
613 | } | ||
614 | |||
615 | if (dev->_dma_virt_start_addr != NULL) { | ||
616 | line_size_in_bytes = | ||
617 | (dev->_pixel_format == | ||
618 | PIXEL_FRMT_411) ? Y411_LINE_SZ : | ||
619 | Y422_LINE_SZ; | ||
620 | risc_phys_jump_addr = | ||
621 | dev->_dma_phys_start_addr + | ||
622 | odd_risc_prog_size; | ||
623 | |||
624 | rp = cx25821_update_riscprogram(dev, | ||
625 | dev-> | ||
626 | _dma_virt_start_addr, | ||
627 | TOP_OFFSET, | ||
628 | line_size_in_bytes, | ||
629 | 0x0, | ||
630 | singlefield_lines, | ||
631 | FIFO_DISABLE, | ||
632 | ODD_FIELD); | ||
633 | |||
634 | // Jump to Even Risc program of 1st Frame | ||
635 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
636 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
637 | *(rp++) = cpu_to_le32(0); | ||
638 | } | ||
639 | } | ||
640 | |||
641 | spin_unlock(&dev->slock); | ||
642 | } else { | ||
643 | if (status & FLD_VID_SRC_UF) | ||
644 | printk | ||
645 | ("%s: Video Received Underflow Error Interrupt!\n", | ||
646 | __func__); | ||
647 | |||
648 | if (status & FLD_VID_SRC_SYNC) | ||
649 | printk("%s: Video Received Sync Error Interrupt!\n", | ||
650 | __func__); | ||
651 | |||
652 | if (status & FLD_VID_SRC_OPC_ERR) | ||
653 | printk("%s: Video Received OpCode Error Interrupt!\n", | ||
654 | __func__); | ||
655 | } | ||
656 | |||
657 | if (dev->_file_status == END_OF_FILE) { | ||
658 | printk("cx25821: EOF Channel 1 Framecount = %d\n", | ||
659 | dev->_frame_count); | ||
660 | return -1; | ||
661 | } | ||
662 | //ElSE, set the interrupt mask register, re-enable irq. | ||
663 | int_msk_tmp = cx_read(channel->int_msk); | ||
664 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) | ||
670 | { | ||
671 | struct cx25821_dev *dev = dev_id; | ||
672 | u32 msk_stat, vid_status; | ||
673 | int handled = 0; | ||
674 | int channel_num = 0; | ||
675 | struct sram_channel *sram_ch; | ||
676 | |||
677 | if (!dev) | ||
678 | return -1; | ||
679 | |||
680 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; | ||
681 | |||
682 | sram_ch = &dev->sram_channels[channel_num]; | ||
683 | |||
684 | msk_stat = cx_read(sram_ch->int_mstat); | ||
685 | vid_status = cx_read(sram_ch->int_stat); | ||
686 | |||
687 | // Only deal with our interrupt | ||
688 | if (vid_status) { | ||
689 | handled = | ||
690 | cx25821_video_upstream_irq(dev, channel_num, vid_status); | ||
691 | } | ||
692 | |||
693 | if (handled < 0) { | ||
694 | cx25821_stop_upstream_video_ch1(dev); | ||
695 | } else { | ||
696 | handled += handled; | ||
697 | } | ||
698 | |||
699 | return IRQ_RETVAL(handled); | ||
700 | } | ||
701 | |||
702 | void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, | ||
703 | int pix_format) | ||
704 | { | ||
705 | int width = WIDTH_D1; | ||
706 | int height = dev->_lines_count; | ||
707 | int num_lines, odd_num_lines; | ||
708 | u32 value; | ||
709 | int vip_mode = OUTPUT_FRMT_656; | ||
710 | |||
711 | value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); | ||
712 | value &= 0xFFFFFFEF; | ||
713 | value |= dev->_isNTSC ? 0 : 0x10; | ||
714 | cx_write(ch->vid_fmt_ctl, value); | ||
715 | |||
716 | // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format | ||
717 | cx_write(ch->vid_active_ctl1, width); | ||
718 | |||
719 | num_lines = (height / 2) & 0x3FF; | ||
720 | odd_num_lines = num_lines; | ||
721 | |||
722 | if (dev->_isNTSC) { | ||
723 | odd_num_lines += 1; | ||
724 | } | ||
725 | |||
726 | value = (num_lines << 16) | odd_num_lines; | ||
727 | |||
728 | // set number of active lines in field 0 (top) and field 1 (bottom) | ||
729 | cx_write(ch->vid_active_ctl2, value); | ||
730 | |||
731 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); | ||
732 | } | ||
733 | |||
734 | int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | ||
735 | struct sram_channel *sram_ch) | ||
736 | { | ||
737 | u32 tmp = 0; | ||
738 | int err = 0; | ||
739 | |||
740 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
741 | tmp = cx_read(VID_CH_MODE_SEL); | ||
742 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
743 | |||
744 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. | ||
745 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); | ||
746 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
747 | |||
748 | /* reset counter */ | ||
749 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
750 | |||
751 | // Clear our bits from the interrupt status register. | ||
752 | cx_write(sram_ch->int_stat, _intr_msk); | ||
753 | |||
754 | //Set the interrupt mask register, enable irq. | ||
755 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
756 | tmp = cx_read(sram_ch->int_msk); | ||
757 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | ||
758 | |||
759 | err = | ||
760 | request_irq(dev->pci->irq, cx25821_upstream_irq, | ||
761 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
762 | if (err < 0) { | ||
763 | printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, | ||
764 | dev->pci->irq); | ||
765 | goto fail_irq; | ||
766 | } | ||
767 | |||
768 | // Start the DMA engine | ||
769 | tmp = cx_read(sram_ch->dma_ctl); | ||
770 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); | ||
771 | |||
772 | dev->_is_running = 1; | ||
773 | dev->_is_first_frame = 1; | ||
774 | |||
775 | return 0; | ||
776 | |||
777 | fail_irq: | ||
778 | cx25821_dev_unregister(dev); | ||
779 | return err; | ||
780 | } | ||
781 | |||
782 | int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | ||
783 | int pixel_format) | ||
784 | { | ||
785 | struct sram_channel *sram_ch; | ||
786 | u32 tmp; | ||
787 | int retval = 0; | ||
788 | int err = 0; | ||
789 | int data_frame_size = 0; | ||
790 | int risc_buffer_size = 0; | ||
791 | int str_length = 0; | ||
792 | |||
793 | if (dev->_is_running) { | ||
794 | printk("Video Channel is still running so return!\n"); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | dev->_channel_upstream_select = channel_select; | ||
799 | sram_ch = &dev->sram_channels[channel_select]; | ||
800 | |||
801 | INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); | ||
802 | dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); | ||
803 | |||
804 | if (!dev->_irq_queues) { | ||
805 | printk | ||
806 | ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); | ||
807 | return -ENOMEM; | ||
808 | } | ||
809 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | ||
810 | tmp = cx_read(VID_CH_MODE_SEL); | ||
811 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
812 | |||
813 | dev->_is_running = 0; | ||
814 | dev->_frame_count = 0; | ||
815 | dev->_file_status = RESET_STATUS; | ||
816 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | ||
817 | dev->_pixel_format = pixel_format; | ||
818 | dev->_line_size = | ||
819 | (dev->_pixel_format == | ||
820 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
821 | data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | ||
822 | risc_buffer_size = | ||
823 | dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | ||
824 | |||
825 | if (dev->input_filename) { | ||
826 | str_length = strlen(dev->input_filename); | ||
827 | dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
828 | |||
829 | if (!dev->_filename) | ||
830 | goto error; | ||
831 | |||
832 | memcpy(dev->_filename, dev->input_filename, str_length + 1); | ||
833 | } else { | ||
834 | str_length = strlen(dev->_defaultname); | ||
835 | dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL); | ||
836 | |||
837 | if (!dev->_filename) | ||
838 | goto error; | ||
839 | |||
840 | memcpy(dev->_filename, dev->_defaultname, str_length + 1); | ||
841 | } | ||
842 | |||
843 | //Default if filename is empty string | ||
844 | if (strcmp(dev->input_filename, "") == 0) { | ||
845 | if (dev->_isNTSC) { | ||
846 | dev->_filename = | ||
847 | (dev->_pixel_format == | ||
848 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | ||
849 | "/root/vidtest.yuv"; | ||
850 | } else { | ||
851 | dev->_filename = | ||
852 | (dev->_pixel_format == | ||
853 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : | ||
854 | "/root/pal422.yuv"; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | dev->_is_running = 0; | ||
859 | dev->_frame_count = 0; | ||
860 | dev->_file_status = RESET_STATUS; | ||
861 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | ||
862 | dev->_pixel_format = pixel_format; | ||
863 | dev->_line_size = | ||
864 | (dev->_pixel_format == | ||
865 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
866 | |||
867 | retval = | ||
868 | cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, | ||
869 | 0); | ||
870 | |||
871 | /* setup fifo + format */ | ||
872 | cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); | ||
873 | |||
874 | dev->upstream_riscbuf_size = risc_buffer_size * 2; | ||
875 | dev->upstream_databuf_size = data_frame_size * 2; | ||
876 | |||
877 | //Allocating buffers and prepare RISC program | ||
878 | retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); | ||
879 | if (retval < 0) { | ||
880 | printk(KERN_ERR | ||
881 | "%s: Failed to set up Video upstream buffers!\n", | ||
882 | dev->name); | ||
883 | goto error; | ||
884 | } | ||
885 | |||
886 | cx25821_start_video_dma_upstream(dev, sram_ch); | ||
887 | |||
888 | return 0; | ||
889 | |||
890 | error: | ||
891 | cx25821_dev_unregister(dev); | ||
892 | |||
893 | return err; | ||
894 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h new file mode 100644 index 000000000000..cc9f93842514 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video-upstream.h | |||
@@ -0,0 +1,109 @@ | |||
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 | // PAL and NTSC line sizes and number of lines. | ||
42 | #define WIDTH_D1 720 | ||
43 | #define NTSC_LINES_PER_FRAME 480 | ||
44 | #define PAL_LINES_PER_FRAME 576 | ||
45 | #define PAL_LINE_SZ 1440 | ||
46 | #define Y422_LINE_SZ 1440 | ||
47 | #define Y411_LINE_SZ 1080 | ||
48 | #define NTSC_FIELD_HEIGHT 240 | ||
49 | #define NTSC_ODD_FLD_LINES 241 | ||
50 | #define PAL_FIELD_HEIGHT 288 | ||
51 | |||
52 | #define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) | ||
53 | #define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) | ||
54 | #define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) | ||
55 | #define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) | ||
56 | |||
57 | #define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) | ||
58 | #define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) | ||
59 | |||
60 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
61 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
62 | #define JUMP_INSTRUCTION_SIZE 12 | ||
63 | #define MAXSIZE_NO_OPS 36 | ||
64 | #define DWORD_SIZE 4 | ||
65 | |||
66 | #define USE_RISC_NOOP_VIDEO 1 | ||
67 | |||
68 | #ifdef USE_RISC_NOOP_VIDEO | ||
69 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
70 | RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
71 | |||
72 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
73 | |||
74 | #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
75 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
76 | |||
77 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
78 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
79 | |||
80 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
81 | RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
82 | |||
83 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
84 | JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) | ||
85 | |||
86 | #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
87 | |||
88 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
89 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) | ||
90 | |||
91 | #endif | ||
92 | |||
93 | #ifndef USE_RISC_NOOP_VIDEO | ||
94 | #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
95 | RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
96 | |||
97 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
98 | |||
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 | |||
102 | #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
103 | #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) | ||
104 | |||
105 | #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
106 | #define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) | ||
107 | #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ | ||
108 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) | ||
109 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c new file mode 100644 index 000000000000..8834bc80a5ab --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video.c | |||
@@ -0,0 +1,1299 @@ | |||
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 | int get_format_size(void) | ||
85 | { | ||
86 | return ARRAY_SIZE(formats); | ||
87 | } | ||
88 | |||
89 | struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) | ||
90 | { | ||
91 | unsigned int i; | ||
92 | |||
93 | if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) { | ||
94 | return formats + 1; | ||
95 | } | ||
96 | |||
97 | for (i = 0; i < ARRAY_SIZE(formats); i++) | ||
98 | if (formats[i].fourcc == fourcc) | ||
99 | return formats + i; | ||
100 | |||
101 | printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) | ||
106 | { | ||
107 | struct cx25821_buffer *buf; | ||
108 | struct list_head *item; | ||
109 | dprintk(1, "%s()\n", __func__); | ||
110 | |||
111 | if (!list_empty(&q->active)) { | ||
112 | list_for_each(item, &q->active) | ||
113 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
114 | } | ||
115 | |||
116 | if (!list_empty(&q->queued)) { | ||
117 | list_for_each(item, &q->queued) | ||
118 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
119 | } | ||
120 | |||
121 | } | ||
122 | |||
123 | void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, | ||
124 | u32 count) | ||
125 | { | ||
126 | struct cx25821_buffer *buf; | ||
127 | int bc; | ||
128 | |||
129 | for (bc = 0;; bc++) { | ||
130 | if (list_empty(&q->active)) { | ||
131 | dprintk(1, "bc=%d (=0: active empty)\n", bc); | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | buf = | ||
136 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
137 | |||
138 | /* count comes from the hw and it is 16bit wide -- | ||
139 | * this trick handles wrap-arounds correctly for | ||
140 | * up to 32767 buffers in flight... */ | ||
141 | if ((s16) (count - buf->count) < 0) { | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | do_gettimeofday(&buf->vb.ts); | ||
146 | buf->vb.state = VIDEOBUF_DONE; | ||
147 | list_del(&buf->vb.queue); | ||
148 | wake_up(&buf->vb.done); | ||
149 | } | ||
150 | |||
151 | if (list_empty(&q->active)) | ||
152 | del_timer(&q->timeout); | ||
153 | else | ||
154 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
155 | if (bc != 1) | ||
156 | printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", | ||
157 | __func__, bc); | ||
158 | } | ||
159 | |||
160 | #ifdef TUNER_FLAG | ||
161 | int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) | ||
162 | { | ||
163 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, | ||
164 | (unsigned int)norm, v4l2_norm_to_name(norm)); | ||
165 | |||
166 | dev->tvnorm = norm; | ||
167 | |||
168 | /* Tell the internal A/V decoder */ | ||
169 | cx25821_call_all(dev, core, s_std, norm); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | #endif | ||
174 | |||
175 | struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
176 | struct pci_dev *pci, | ||
177 | struct video_device *template, | ||
178 | char *type) | ||
179 | { | ||
180 | struct video_device *vfd; | ||
181 | dprintk(1, "%s()\n", __func__); | ||
182 | |||
183 | vfd = video_device_alloc(); | ||
184 | if (NULL == vfd) | ||
185 | return NULL; | ||
186 | *vfd = *template; | ||
187 | vfd->minor = -1; | ||
188 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
189 | vfd->release = video_device_release; | ||
190 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, | ||
191 | cx25821_boards[dev->board].name); | ||
192 | return vfd; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | ||
201 | return -EINVAL; | ||
202 | for (i = 0; i < CX25821_CTLS; i++) | ||
203 | if (cx25821_ctls[i].v.id == qctrl->id) | ||
204 | break; | ||
205 | if (i == CX25821_CTLS) { | ||
206 | *qctrl = no_ctl; | ||
207 | return 0; | ||
208 | } | ||
209 | *qctrl = cx25821_ctls[i].v; | ||
210 | return 0; | ||
211 | } | ||
212 | */ | ||
213 | |||
214 | // resource management | ||
215 | int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) | ||
216 | { | ||
217 | dprintk(1, "%s()\n", __func__); | ||
218 | if (fh->resources & bit) | ||
219 | /* have it already allocated */ | ||
220 | return 1; | ||
221 | |||
222 | /* is it free? */ | ||
223 | mutex_lock(&dev->lock); | ||
224 | if (dev->resources & bit) { | ||
225 | /* no, someone else uses it */ | ||
226 | mutex_unlock(&dev->lock); | ||
227 | return 0; | ||
228 | } | ||
229 | /* it's free, grab it */ | ||
230 | fh->resources |= bit; | ||
231 | dev->resources |= bit; | ||
232 | dprintk(1, "res: get %d\n", bit); | ||
233 | mutex_unlock(&dev->lock); | ||
234 | return 1; | ||
235 | } | ||
236 | |||
237 | int res_check(struct cx25821_fh *fh, unsigned int bit) | ||
238 | { | ||
239 | return fh->resources & bit; | ||
240 | } | ||
241 | |||
242 | int res_locked(struct cx25821_dev *dev, unsigned int bit) | ||
243 | { | ||
244 | return dev->resources & bit; | ||
245 | } | ||
246 | |||
247 | void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) | ||
248 | { | ||
249 | BUG_ON((fh->resources & bits) != bits); | ||
250 | dprintk(1, "%s()\n", __func__); | ||
251 | |||
252 | mutex_lock(&dev->lock); | ||
253 | fh->resources &= ~bits; | ||
254 | dev->resources &= ~bits; | ||
255 | dprintk(1, "res: put %d\n", bits); | ||
256 | mutex_unlock(&dev->lock); | ||
257 | } | ||
258 | |||
259 | int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) | ||
260 | { | ||
261 | struct v4l2_routing route; | ||
262 | memset(&route, 0, sizeof(route)); | ||
263 | |||
264 | dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", | ||
265 | __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, | ||
266 | INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); | ||
267 | dev->input = input; | ||
268 | |||
269 | route.input = INPUT(input)->vmux; | ||
270 | |||
271 | /* Tell the internal A/V decoder */ | ||
272 | cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int cx25821_start_video_dma(struct cx25821_dev *dev, | ||
278 | struct cx25821_dmaqueue *q, | ||
279 | struct cx25821_buffer *buf, | ||
280 | struct sram_channel *channel) | ||
281 | { | ||
282 | int tmp = 0; | ||
283 | |||
284 | /* setup fifo + format */ | ||
285 | cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); | ||
286 | |||
287 | /* reset counter */ | ||
288 | cx_write(channel->gpcnt_ctl, 3); | ||
289 | q->count = 1; | ||
290 | |||
291 | /* enable irq */ | ||
292 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i)); | ||
293 | cx_set(channel->int_msk, 0x11); | ||
294 | |||
295 | /* start dma */ | ||
296 | cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ | ||
297 | |||
298 | /* make sure upstream setting if any is reversed */ | ||
299 | tmp = cx_read(VID_CH_MODE_SEL); | ||
300 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | int cx25821_restart_video_queue(struct cx25821_dev *dev, | ||
306 | struct cx25821_dmaqueue *q, | ||
307 | struct sram_channel *channel) | ||
308 | { | ||
309 | struct cx25821_buffer *buf, *prev; | ||
310 | struct list_head *item; | ||
311 | |||
312 | if (!list_empty(&q->active)) { | ||
313 | buf = | ||
314 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
315 | |||
316 | cx25821_start_video_dma(dev, q, buf, channel); | ||
317 | |||
318 | list_for_each(item, &q->active) { | ||
319 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | ||
320 | buf->count = q->count++; | ||
321 | } | ||
322 | |||
323 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | prev = NULL; | ||
328 | for (;;) { | ||
329 | if (list_empty(&q->queued)) | ||
330 | return 0; | ||
331 | |||
332 | buf = | ||
333 | list_entry(q->queued.next, struct cx25821_buffer, vb.queue); | ||
334 | |||
335 | if (NULL == prev) { | ||
336 | list_move_tail(&buf->vb.queue, &q->active); | ||
337 | cx25821_start_video_dma(dev, q, buf, channel); | ||
338 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
339 | buf->count = q->count++; | ||
340 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
341 | } else if (prev->vb.width == buf->vb.width && | ||
342 | prev->vb.height == buf->vb.height && | ||
343 | prev->fmt == buf->fmt) { | ||
344 | list_move_tail(&buf->vb.queue, &q->active); | ||
345 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
346 | buf->count = q->count++; | ||
347 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
348 | prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ | ||
349 | } else { | ||
350 | return 0; | ||
351 | } | ||
352 | prev = buf; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | void cx25821_vid_timeout(unsigned long data) | ||
357 | { | ||
358 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; | ||
359 | struct cx25821_dev *dev = timeout_data->dev; | ||
360 | struct sram_channel *channel = timeout_data->channel; | ||
361 | struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; | ||
362 | struct cx25821_buffer *buf; | ||
363 | unsigned long flags; | ||
364 | |||
365 | //cx25821_sram_channel_dump(dev, channel); | ||
366 | cx_clear(channel->dma_ctl, 0x11); | ||
367 | |||
368 | spin_lock_irqsave(&dev->slock, flags); | ||
369 | while (!list_empty(&q->active)) { | ||
370 | buf = | ||
371 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | ||
372 | list_del(&buf->vb.queue); | ||
373 | |||
374 | buf->vb.state = VIDEOBUF_ERROR; | ||
375 | wake_up(&buf->vb.done); | ||
376 | } | ||
377 | |||
378 | cx25821_restart_video_queue(dev, q, channel); | ||
379 | spin_unlock_irqrestore(&dev->slock, flags); | ||
380 | } | ||
381 | |||
382 | int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | ||
383 | { | ||
384 | u32 count = 0; | ||
385 | int handled = 0; | ||
386 | u32 mask; | ||
387 | struct sram_channel *channel = &dev->sram_channels[chan_num]; | ||
388 | |||
389 | mask = cx_read(channel->int_msk); | ||
390 | if (0 == (status & mask)) | ||
391 | return handled; | ||
392 | |||
393 | cx_write(channel->int_stat, status); | ||
394 | |||
395 | /* risc op code error */ | ||
396 | if (status & (1 << 16)) { | ||
397 | printk(KERN_WARNING "%s, %s: video risc op code error\n", | ||
398 | 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], | ||
417 | channel); | ||
418 | spin_unlock(&dev->slock); | ||
419 | handled++; | ||
420 | } | ||
421 | return handled; | ||
422 | } | ||
423 | |||
424 | void cx25821_videoioctl_unregister(struct cx25821_dev *dev) | ||
425 | { | ||
426 | if (dev->ioctl_dev) { | ||
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 | int cx25821_video_register(struct cx25821_dev *dev, int chan_num, | ||
456 | 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 = | ||
475 | (unsigned long)&dev->timeout_data[chan_num]; | ||
476 | init_timer(&dev->vidq[chan_num].timeout); | ||
477 | cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, | ||
478 | dev->sram_channels[chan_num].dma_ctl, 0x11, 0); | ||
479 | |||
480 | /* register v4l devices */ | ||
481 | dev->video_dev[chan_num] = | ||
482 | cx25821_vdev_init(dev, dev->pci, video_template, "video"); | ||
483 | err = | ||
484 | video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, | ||
485 | video_nr[dev->nr]); | ||
486 | |||
487 | if (err < 0) { | ||
488 | goto fail_unreg; | ||
489 | } | ||
490 | //set PCI interrupt | ||
491 | cx_set(PCI_INT_MSK, 0xff); | ||
492 | |||
493 | /* initial device configuration */ | ||
494 | mutex_lock(&dev->lock); | ||
495 | #ifdef TUNER_FLAG | ||
496 | cx25821_set_tvnorm(dev, dev->tvnorm); | ||
497 | #endif | ||
498 | mutex_unlock(&dev->lock); | ||
499 | |||
500 | init_controls(dev, chan_num); | ||
501 | |||
502 | return 0; | ||
503 | |||
504 | fail_unreg: | ||
505 | cx25821_video_unregister(dev, chan_num); | ||
506 | return err; | ||
507 | } | ||
508 | |||
509 | int buffer_setup(struct videobuf_queue *q, unsigned int *count, | ||
510 | unsigned int *size) | ||
511 | { | ||
512 | struct cx25821_fh *fh = q->priv_data; | ||
513 | |||
514 | *size = fh->fmt->depth * fh->width * fh->height >> 3; | ||
515 | |||
516 | if (0 == *count) | ||
517 | *count = 32; | ||
518 | |||
519 | while (*size * *count > vid_limit * 1024 * 1024) | ||
520 | (*count)--; | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
526 | enum v4l2_field field) | ||
527 | { | ||
528 | struct cx25821_fh *fh = q->priv_data; | ||
529 | struct cx25821_dev *dev = fh->dev; | ||
530 | struct cx25821_buffer *buf = | ||
531 | container_of(vb, struct cx25821_buffer, vb); | ||
532 | int rc, init_buffer = 0; | ||
533 | u32 line0_offset, line1_offset; | ||
534 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | ||
535 | int bpl_local = LINE_SIZE_D1; | ||
536 | int channel_opened = 0; | ||
537 | |||
538 | BUG_ON(NULL == fh->fmt); | ||
539 | if (fh->width < 48 || fh->width > 720 || | ||
540 | fh->height < 32 || fh->height > 576) | ||
541 | return -EINVAL; | ||
542 | |||
543 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; | ||
544 | |||
545 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
546 | return -EINVAL; | ||
547 | |||
548 | if (buf->fmt != fh->fmt || | ||
549 | buf->vb.width != fh->width || | ||
550 | buf->vb.height != fh->height || buf->vb.field != field) { | ||
551 | buf->fmt = fh->fmt; | ||
552 | buf->vb.width = fh->width; | ||
553 | buf->vb.height = fh->height; | ||
554 | buf->vb.field = field; | ||
555 | init_buffer = 1; | ||
556 | } | ||
557 | |||
558 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
559 | init_buffer = 1; | ||
560 | rc = videobuf_iolock(q, &buf->vb, NULL); | ||
561 | if (0 != rc) { | ||
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 | ||
573 | || channel_opened > 7) ? 7 : channel_opened; | ||
574 | |||
575 | if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) | ||
576 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; | ||
577 | else | ||
578 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); | ||
579 | |||
580 | if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) { | ||
581 | bpl_local = buf->bpl; | ||
582 | } else { | ||
583 | bpl_local = buf->bpl; //Default | ||
584 | |||
585 | if (channel_opened >= 0 && channel_opened <= 7) { | ||
586 | if (dev->use_cif_resolution[channel_opened]) { | ||
587 | if (dev->tvnorm & V4L2_STD_PAL_BG | ||
588 | || dev->tvnorm & V4L2_STD_PAL_DK) | ||
589 | bpl_local = 352 << 1; | ||
590 | else | ||
591 | bpl_local = | ||
592 | dev-> | ||
593 | cif_width[channel_opened] << | ||
594 | 1; | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | |||
599 | switch (buf->vb.field) { | ||
600 | case V4L2_FIELD_TOP: | ||
601 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
602 | dma->sglist, 0, UNSET, | ||
603 | buf->bpl, 0, buf->vb.height); | ||
604 | break; | ||
605 | case V4L2_FIELD_BOTTOM: | ||
606 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
607 | dma->sglist, UNSET, 0, | ||
608 | buf->bpl, 0, buf->vb.height); | ||
609 | break; | ||
610 | case V4L2_FIELD_INTERLACED: | ||
611 | /* All other formats are top field first */ | ||
612 | line0_offset = 0; | ||
613 | line1_offset = buf->bpl; | ||
614 | dprintk(1, "top field first\n"); | ||
615 | |||
616 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
617 | dma->sglist, line0_offset, | ||
618 | bpl_local, bpl_local, bpl_local, | ||
619 | buf->vb.height >> 1); | ||
620 | break; | ||
621 | case V4L2_FIELD_SEQ_TB: | ||
622 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
623 | dma->sglist, | ||
624 | 0, buf->bpl * (buf->vb.height >> 1), | ||
625 | buf->bpl, 0, buf->vb.height >> 1); | ||
626 | break; | ||
627 | case V4L2_FIELD_SEQ_BT: | ||
628 | cx25821_risc_buffer(dev->pci, &buf->risc, | ||
629 | dma->sglist, | ||
630 | buf->bpl * (buf->vb.height >> 1), 0, | ||
631 | buf->bpl, 0, buf->vb.height >> 1); | ||
632 | break; | ||
633 | default: | ||
634 | BUG(); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | ||
639 | buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, | ||
640 | fh->fmt->name, (unsigned long)buf->risc.dma); | ||
641 | |||
642 | buf->vb.state = VIDEOBUF_PREPARED; | ||
643 | |||
644 | return 0; | ||
645 | |||
646 | fail: | ||
647 | cx25821_free_buffer(q, buf); | ||
648 | return rc; | ||
649 | } | ||
650 | |||
651 | void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
652 | { | ||
653 | struct cx25821_buffer *buf = | ||
654 | container_of(vb, struct cx25821_buffer, vb); | ||
655 | |||
656 | cx25821_free_buffer(q, buf); | ||
657 | } | ||
658 | |||
659 | struct videobuf_queue *get_queue(struct cx25821_fh *fh) | ||
660 | { | ||
661 | switch (fh->type) { | ||
662 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
663 | return &fh->vidq; | ||
664 | default: | ||
665 | BUG(); | ||
666 | return NULL; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | int get_resource(struct cx25821_fh *fh, int resource) | ||
671 | { | ||
672 | switch (fh->type) { | ||
673 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
674 | return resource; | ||
675 | default: | ||
676 | BUG(); | ||
677 | return 0; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | int video_mmap(struct file *file, struct vm_area_struct *vma) | ||
682 | { | ||
683 | struct cx25821_fh *fh = file->private_data; | ||
684 | |||
685 | return videobuf_mmap_mapper(get_queue(fh), vma); | ||
686 | } | ||
687 | |||
688 | /* VIDEO IOCTLS */ | ||
689 | int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
690 | { | ||
691 | struct cx25821_fh *fh = priv; | ||
692 | |||
693 | f->fmt.pix.width = fh->width; | ||
694 | f->fmt.pix.height = fh->height; | ||
695 | f->fmt.pix.field = fh->vidq.field; | ||
696 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
697 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
698 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | ||
704 | { | ||
705 | struct cx25821_fmt *fmt; | ||
706 | enum v4l2_field field; | ||
707 | unsigned int maxw, maxh; | ||
708 | |||
709 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
710 | if (NULL == fmt) | ||
711 | return -EINVAL; | ||
712 | |||
713 | field = f->fmt.pix.field; | ||
714 | maxw = 720; | ||
715 | maxh = 576; | ||
716 | |||
717 | if (V4L2_FIELD_ANY == field) { | ||
718 | field = (f->fmt.pix.height > maxh / 2) | ||
719 | ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; | ||
720 | } | ||
721 | |||
722 | switch (field) { | ||
723 | case V4L2_FIELD_TOP: | ||
724 | case V4L2_FIELD_BOTTOM: | ||
725 | maxh = maxh / 2; | ||
726 | break; | ||
727 | case V4L2_FIELD_INTERLACED: | ||
728 | break; | ||
729 | default: | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | |||
733 | f->fmt.pix.field = field; | ||
734 | if (f->fmt.pix.height < 32) | ||
735 | f->fmt.pix.height = 32; | ||
736 | if (f->fmt.pix.height > maxh) | ||
737 | f->fmt.pix.height = maxh; | ||
738 | if (f->fmt.pix.width < 48) | ||
739 | f->fmt.pix.width = 48; | ||
740 | if (f->fmt.pix.width > maxw) | ||
741 | f->fmt.pix.width = maxw; | ||
742 | f->fmt.pix.width &= ~0x03; | ||
743 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
744 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) | ||
750 | { | ||
751 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
752 | |||
753 | strcpy(cap->driver, "cx25821"); | ||
754 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); | ||
755 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); | ||
756 | cap->version = CX25821_VERSION_CODE; | ||
757 | cap->capabilities = | ||
758 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
759 | if (UNSET != dev->tuner_type) | ||
760 | cap->capabilities |= V4L2_CAP_TUNER; | ||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
765 | struct v4l2_fmtdesc *f) | ||
766 | { | ||
767 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | ||
768 | return -EINVAL; | ||
769 | |||
770 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | ||
771 | f->pixelformat = formats[f->index].fourcc; | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
777 | int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | ||
778 | { | ||
779 | struct cx25821_fh *fh = priv; | ||
780 | struct videobuf_queue *q; | ||
781 | struct v4l2_requestbuffers req; | ||
782 | unsigned int i; | ||
783 | int err; | ||
784 | |||
785 | q = get_queue(fh); | ||
786 | memset(&req, 0, sizeof(req)); | ||
787 | req.type = q->type; | ||
788 | req.count = 8; | ||
789 | req.memory = V4L2_MEMORY_MMAP; | ||
790 | err = videobuf_reqbufs(q, &req); | ||
791 | if (err < 0) | ||
792 | return err; | ||
793 | |||
794 | mbuf->frames = req.count; | ||
795 | mbuf->size = 0; | ||
796 | for (i = 0; i < mbuf->frames; i++) { | ||
797 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
798 | mbuf->size += q->bufs[i]->bsize; | ||
799 | } | ||
800 | return 0; | ||
801 | } | ||
802 | #endif | ||
803 | |||
804 | int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
805 | { | ||
806 | struct cx25821_fh *fh = priv; | ||
807 | return videobuf_reqbufs(get_queue(fh), p); | ||
808 | } | ||
809 | |||
810 | int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
811 | { | ||
812 | struct cx25821_fh *fh = priv; | ||
813 | return videobuf_querybuf(get_queue(fh), p); | ||
814 | } | ||
815 | |||
816 | int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
817 | { | ||
818 | struct cx25821_fh *fh = priv; | ||
819 | return videobuf_qbuf(get_queue(fh), p); | ||
820 | } | ||
821 | |||
822 | int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | ||
823 | { | ||
824 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | ||
825 | |||
826 | *p = v4l2_prio_max(&dev->prio); | ||
827 | |||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio) | ||
832 | { | ||
833 | struct cx25821_fh *fh = f; | ||
834 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | ||
835 | |||
836 | return v4l2_prio_change(&dev->prio, &fh->prio, prio); | ||
837 | } | ||
838 | |||
839 | #ifdef TUNER_FLAG | ||
840 | int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) | ||
841 | { | ||
842 | struct cx25821_fh *fh = priv; | ||
843 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
844 | int err; | ||
845 | |||
846 | dprintk(1, "%s()\n", __func__); | ||
847 | |||
848 | if (fh) { | ||
849 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
850 | if (0 != err) | ||
851 | return err; | ||
852 | } | ||
853 | |||
854 | if (dev->tvnorm == *tvnorms) { | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | mutex_lock(&dev->lock); | ||
859 | cx25821_set_tvnorm(dev, *tvnorms); | ||
860 | mutex_unlock(&dev->lock); | ||
861 | |||
862 | medusa_set_videostandard(dev); | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | #endif | ||
867 | |||
868 | int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) | ||
869 | { | ||
870 | static const char *iname[] = { | ||
871 | [CX25821_VMUX_COMPOSITE] = "Composite", | ||
872 | [CX25821_VMUX_SVIDEO] = "S-Video", | ||
873 | [CX25821_VMUX_DEBUG] = "for debug only", | ||
874 | }; | ||
875 | unsigned int n; | ||
876 | dprintk(1, "%s()\n", __func__); | ||
877 | |||
878 | n = i->index; | ||
879 | if (n > 2) | ||
880 | return -EINVAL; | ||
881 | |||
882 | if (0 == INPUT(n)->type) | ||
883 | return -EINVAL; | ||
884 | |||
885 | memset(i, 0, sizeof(*i)); | ||
886 | i->index = n; | ||
887 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
888 | strcpy(i->name, iname[INPUT(n)->type]); | ||
889 | |||
890 | i->std = CX25821_NORMS; | ||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) | ||
895 | { | ||
896 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
897 | dprintk(1, "%s()\n", __func__); | ||
898 | return cx25821_enum_input(dev, i); | ||
899 | } | ||
900 | |||
901 | int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
902 | { | ||
903 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
904 | |||
905 | *i = dev->input; | ||
906 | dprintk(1, "%s() returns %d\n", __func__, *i); | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
911 | { | ||
912 | struct cx25821_fh *fh = priv; | ||
913 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
914 | int err; | ||
915 | |||
916 | dprintk(1, "%s(%d)\n", __func__, i); | ||
917 | |||
918 | if (fh) { | ||
919 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
920 | if (0 != err) | ||
921 | return err; | ||
922 | } | ||
923 | |||
924 | if (i > 2) { | ||
925 | dprintk(1, "%s() -EINVAL\n", __func__); | ||
926 | return -EINVAL; | ||
927 | } | ||
928 | |||
929 | mutex_lock(&dev->lock); | ||
930 | cx25821_video_mux(dev, i); | ||
931 | mutex_unlock(&dev->lock); | ||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | #ifdef TUNER_FLAG | ||
936 | int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | ||
937 | { | ||
938 | struct cx25821_fh *fh = priv; | ||
939 | struct cx25821_dev *dev = fh->dev; | ||
940 | |||
941 | f->frequency = dev->freq; | ||
942 | |||
943 | cx25821_call_all(dev, tuner, g_frequency, f); | ||
944 | |||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) | ||
949 | { | ||
950 | mutex_lock(&dev->lock); | ||
951 | dev->freq = f->frequency; | ||
952 | |||
953 | cx25821_call_all(dev, tuner, s_frequency, f); | ||
954 | |||
955 | /* When changing channels it is required to reset TVAUDIO */ | ||
956 | msleep(10); | ||
957 | |||
958 | mutex_unlock(&dev->lock); | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | ||
964 | { | ||
965 | struct cx25821_fh *fh = priv; | ||
966 | struct cx25821_dev *dev = fh->dev; | ||
967 | int err; | ||
968 | |||
969 | if (fh) { | ||
970 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
971 | if (0 != err) | ||
972 | return err; | ||
973 | } | ||
974 | |||
975 | return cx25821_set_freq(dev, f); | ||
976 | } | ||
977 | #endif | ||
978 | |||
979 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
980 | int vidioc_g_register(struct file *file, void *fh, | ||
981 | struct v4l2_dbg_register *reg) | ||
982 | { | ||
983 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
984 | |||
985 | if (!v4l2_chip_match_host(®->match)) | ||
986 | return -EINVAL; | ||
987 | |||
988 | cx25821_call_all(dev, core, g_register, reg); | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | int vidioc_s_register(struct file *file, void *fh, | ||
994 | struct v4l2_dbg_register *reg) | ||
995 | { | ||
996 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
997 | |||
998 | if (!v4l2_chip_match_host(®->match)) | ||
999 | return -EINVAL; | ||
1000 | |||
1001 | cx25821_call_all(dev, core, s_register, reg); | ||
1002 | |||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | #endif | ||
1007 | |||
1008 | #ifdef TUNER_FLAG | ||
1009 | int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | ||
1010 | { | ||
1011 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1012 | |||
1013 | if (unlikely(UNSET == dev->tuner_type)) | ||
1014 | return -EINVAL; | ||
1015 | if (0 != t->index) | ||
1016 | return -EINVAL; | ||
1017 | |||
1018 | strcpy(t->name, "Television"); | ||
1019 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1020 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1021 | t->rangehigh = 0xffffffffUL; | ||
1022 | |||
1023 | t->signal = 0xffff; /* LOCKED */ | ||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | ||
1028 | { | ||
1029 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1030 | struct cx25821_fh *fh = priv; | ||
1031 | int err; | ||
1032 | |||
1033 | if (fh) { | ||
1034 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
1035 | if (0 != err) | ||
1036 | return err; | ||
1037 | } | ||
1038 | |||
1039 | dprintk(1, "%s()\n", __func__); | ||
1040 | if (UNSET == dev->tuner_type) | ||
1041 | return -EINVAL; | ||
1042 | if (0 != t->index) | ||
1043 | return -EINVAL; | ||
1044 | |||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | #endif | ||
1049 | // ****************************************************************************************** | ||
1050 | static const struct v4l2_queryctrl no_ctl = { | ||
1051 | .name = "42", | ||
1052 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
1053 | }; | ||
1054 | |||
1055 | static struct v4l2_queryctrl cx25821_ctls[] = { | ||
1056 | /* --- video --- */ | ||
1057 | { | ||
1058 | .id = V4L2_CID_BRIGHTNESS, | ||
1059 | .name = "Brightness", | ||
1060 | .minimum = 0, | ||
1061 | .maximum = 10000, | ||
1062 | .step = 1, | ||
1063 | .default_value = 6200, | ||
1064 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1065 | }, { | ||
1066 | .id = V4L2_CID_CONTRAST, | ||
1067 | .name = "Contrast", | ||
1068 | .minimum = 0, | ||
1069 | .maximum = 10000, | ||
1070 | .step = 1, | ||
1071 | .default_value = 5000, | ||
1072 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1073 | }, { | ||
1074 | .id = V4L2_CID_SATURATION, | ||
1075 | .name = "Saturation", | ||
1076 | .minimum = 0, | ||
1077 | .maximum = 10000, | ||
1078 | .step = 1, | ||
1079 | .default_value = 5000, | ||
1080 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1081 | }, { | ||
1082 | .id = V4L2_CID_HUE, | ||
1083 | .name = "Hue", | ||
1084 | .minimum = 0, | ||
1085 | .maximum = 10000, | ||
1086 | .step = 1, | ||
1087 | .default_value = 5000, | ||
1088 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1089 | } | ||
1090 | }; | ||
1091 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); | ||
1092 | |||
1093 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
1094 | { | ||
1095 | int i; | ||
1096 | |||
1097 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | ||
1098 | return -EINVAL; | ||
1099 | for (i = 0; i < CX25821_CTLS; i++) | ||
1100 | if (cx25821_ctls[i].id == qctrl->id) | ||
1101 | break; | ||
1102 | if (i == CX25821_CTLS) { | ||
1103 | *qctrl = no_ctl; | ||
1104 | return 0; | ||
1105 | } | ||
1106 | *qctrl = cx25821_ctls[i]; | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | int vidioc_queryctrl(struct file *file, void *priv, | ||
1111 | struct v4l2_queryctrl *qctrl) | ||
1112 | { | ||
1113 | return cx25821_ctrl_query(qctrl); | ||
1114 | } | ||
1115 | |||
1116 | /* ------------------------------------------------------------------ */ | ||
1117 | /* VIDEO CTRL IOCTLS */ | ||
1118 | |||
1119 | static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) | ||
1120 | { | ||
1121 | unsigned int i; | ||
1122 | |||
1123 | for (i = 0; i < CX25821_CTLS; i++) | ||
1124 | if (cx25821_ctls[i].id == id) | ||
1125 | return cx25821_ctls + i; | ||
1126 | return NULL; | ||
1127 | } | ||
1128 | |||
1129 | int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) | ||
1130 | { | ||
1131 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1132 | |||
1133 | const struct v4l2_queryctrl *ctrl; | ||
1134 | |||
1135 | ctrl = ctrl_by_id(ctl->id); | ||
1136 | |||
1137 | if (NULL == ctrl) | ||
1138 | return -EINVAL; | ||
1139 | switch (ctl->id) { | ||
1140 | case V4L2_CID_BRIGHTNESS: | ||
1141 | ctl->value = dev->ctl_bright; | ||
1142 | break; | ||
1143 | case V4L2_CID_HUE: | ||
1144 | ctl->value = dev->ctl_hue; | ||
1145 | break; | ||
1146 | case V4L2_CID_CONTRAST: | ||
1147 | ctl->value = dev->ctl_contrast; | ||
1148 | break; | ||
1149 | case V4L2_CID_SATURATION: | ||
1150 | ctl->value = dev->ctl_saturation; | ||
1151 | break; | ||
1152 | } | ||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | int cx25821_set_control(struct cx25821_dev *dev, | ||
1157 | struct v4l2_control *ctl, int chan_num) | ||
1158 | { | ||
1159 | int err; | ||
1160 | const struct v4l2_queryctrl *ctrl; | ||
1161 | |||
1162 | err = -EINVAL; | ||
1163 | |||
1164 | ctrl = ctrl_by_id(ctl->id); | ||
1165 | |||
1166 | if (NULL == ctrl) | ||
1167 | return err; | ||
1168 | |||
1169 | switch (ctrl->type) { | ||
1170 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1171 | case V4L2_CTRL_TYPE_MENU: | ||
1172 | case V4L2_CTRL_TYPE_INTEGER: | ||
1173 | if (ctl->value < ctrl->minimum) | ||
1174 | ctl->value = ctrl->minimum; | ||
1175 | if (ctl->value > ctrl->maximum) | ||
1176 | ctl->value = ctrl->maximum; | ||
1177 | break; | ||
1178 | default: | ||
1179 | /* nothing */ ; | ||
1180 | }; | ||
1181 | |||
1182 | switch (ctl->id) { | ||
1183 | case V4L2_CID_BRIGHTNESS: | ||
1184 | dev->ctl_bright = ctl->value; | ||
1185 | medusa_set_brightness(dev, ctl->value, chan_num); | ||
1186 | break; | ||
1187 | case V4L2_CID_HUE: | ||
1188 | dev->ctl_hue = ctl->value; | ||
1189 | medusa_set_hue(dev, ctl->value, chan_num); | ||
1190 | break; | ||
1191 | case V4L2_CID_CONTRAST: | ||
1192 | dev->ctl_contrast = ctl->value; | ||
1193 | medusa_set_contrast(dev, ctl->value, chan_num); | ||
1194 | break; | ||
1195 | case V4L2_CID_SATURATION: | ||
1196 | dev->ctl_saturation = ctl->value; | ||
1197 | medusa_set_saturation(dev, ctl->value, chan_num); | ||
1198 | break; | ||
1199 | } | ||
1200 | |||
1201 | err = 0; | ||
1202 | |||
1203 | return err; | ||
1204 | } | ||
1205 | |||
1206 | static void init_controls(struct cx25821_dev *dev, int chan_num) | ||
1207 | { | ||
1208 | struct v4l2_control ctrl; | ||
1209 | int i; | ||
1210 | for (i = 0; i < CX25821_CTLS; i++) { | ||
1211 | ctrl.id = cx25821_ctls[i].id; | ||
1212 | ctrl.value = cx25821_ctls[i].default_value; | ||
1213 | |||
1214 | cx25821_set_control(dev, &ctrl, chan_num); | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap) | ||
1219 | { | ||
1220 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1221 | |||
1222 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1223 | return -EINVAL; | ||
1224 | cropcap->bounds.top = cropcap->bounds.left = 0; | ||
1225 | cropcap->bounds.width = 720; | ||
1226 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; | ||
1227 | cropcap->pixelaspect.numerator = | ||
1228 | dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; | ||
1229 | cropcap->pixelaspect.denominator = | ||
1230 | dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; | ||
1231 | cropcap->defrect = cropcap->bounds; | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) | ||
1236 | { | ||
1237 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1238 | struct cx25821_fh *fh = priv; | ||
1239 | int err; | ||
1240 | |||
1241 | if (fh) { | ||
1242 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
1243 | if (0 != err) | ||
1244 | return err; | ||
1245 | } | ||
1246 | // vidioc_s_crop not supported | ||
1247 | return -EINVAL; | ||
1248 | } | ||
1249 | |||
1250 | int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) | ||
1251 | { | ||
1252 | // vidioc_g_crop not supported | ||
1253 | return -EINVAL; | ||
1254 | } | ||
1255 | |||
1256 | int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) | ||
1257 | { | ||
1258 | // medusa does not support video standard sensing of current input | ||
1259 | *norm = CX25821_NORMS; | ||
1260 | |||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | int is_valid_width(u32 width, v4l2_std_id tvnorm) | ||
1265 | { | ||
1266 | if (tvnorm == V4L2_STD_PAL_BG) { | ||
1267 | if (width == 352 || width == 720) | ||
1268 | return 1; | ||
1269 | else | ||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | if (tvnorm == V4L2_STD_NTSC_M) { | ||
1274 | if (width == 320 || width == 352 || width == 720) | ||
1275 | return 1; | ||
1276 | else | ||
1277 | return 0; | ||
1278 | } | ||
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | int is_valid_height(u32 height, v4l2_std_id tvnorm) | ||
1283 | { | ||
1284 | if (tvnorm == V4L2_STD_PAL_BG) { | ||
1285 | if (height == 576 || height == 288) | ||
1286 | return 1; | ||
1287 | else | ||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | if (tvnorm == V4L2_STD_NTSC_M) { | ||
1292 | if (height == 480 || height == 240) | ||
1293 | return 1; | ||
1294 | else | ||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | return 0; | ||
1299 | } | ||
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h new file mode 100644 index 000000000000..4417ff5d90d4 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video.h | |||
@@ -0,0 +1,194 @@ | |||
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 | #include <linux/init.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/kmod.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/kthread.h> | ||
37 | #include <asm/div64.h> | ||
38 | |||
39 | #include "cx25821.h" | ||
40 | #include <media/v4l2-common.h> | ||
41 | #include <media/v4l2-ioctl.h> | ||
42 | |||
43 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
44 | /* Include V4L1 specific functions. Should be removed soon */ | ||
45 | #include <linux/videodev.h> | ||
46 | #endif | ||
47 | |||
48 | #define TUNER_FLAG | ||
49 | |||
50 | #define VIDEO_DEBUG 0 | ||
51 | |||
52 | #define dprintk(level, fmt, arg...)\ | ||
53 | do { if (VIDEO_DEBUG >= level)\ | ||
54 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ | ||
55 | } while (0) | ||
56 | |||
57 | //For IOCTL to identify running upstream | ||
58 | #define UPSTREAM_START_VIDEO 700 | ||
59 | #define UPSTREAM_STOP_VIDEO 701 | ||
60 | #define UPSTREAM_START_AUDIO 702 | ||
61 | #define UPSTREAM_STOP_AUDIO 703 | ||
62 | #define UPSTREAM_DUMP_REGISTERS 702 | ||
63 | #define SET_VIDEO_STD 800 | ||
64 | #define SET_PIXEL_FORMAT 1000 | ||
65 | #define ENABLE_CIF_RESOLUTION 1001 | ||
66 | |||
67 | #define REG_READ 900 | ||
68 | #define REG_WRITE 901 | ||
69 | #define MEDUSA_READ 910 | ||
70 | #define MEDUSA_WRITE 911 | ||
71 | |||
72 | extern struct sram_channel *channel0; | ||
73 | extern struct sram_channel *channel1; | ||
74 | extern struct sram_channel *channel2; | ||
75 | extern struct sram_channel *channel3; | ||
76 | extern struct sram_channel *channel4; | ||
77 | extern struct sram_channel *channel5; | ||
78 | extern struct sram_channel *channel6; | ||
79 | extern struct sram_channel *channel7; | ||
80 | extern struct sram_channel *channel9; | ||
81 | extern struct sram_channel *channel10; | ||
82 | extern struct sram_channel *channel11; | ||
83 | extern struct video_device cx25821_video_template0; | ||
84 | extern struct video_device cx25821_video_template1; | ||
85 | extern struct video_device cx25821_video_template2; | ||
86 | extern struct video_device cx25821_video_template3; | ||
87 | extern struct video_device cx25821_video_template4; | ||
88 | extern struct video_device cx25821_video_template5; | ||
89 | extern struct video_device cx25821_video_template6; | ||
90 | extern struct video_device cx25821_video_template7; | ||
91 | extern struct video_device cx25821_video_template9; | ||
92 | extern struct video_device cx25821_video_template10; | ||
93 | extern struct video_device cx25821_video_template11; | ||
94 | extern struct video_device cx25821_videoioctl_template; | ||
95 | //extern const u32 *ctrl_classes[]; | ||
96 | |||
97 | extern unsigned int vid_limit; | ||
98 | |||
99 | #define FORMAT_FLAGS_PACKED 0x01 | ||
100 | extern struct cx25821_fmt formats[]; | ||
101 | extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); | ||
102 | extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | ||
103 | |||
104 | extern void dump_video_queue(struct cx25821_dev *dev, | ||
105 | struct cx25821_dmaqueue *q); | ||
106 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, | ||
107 | 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 | extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, | ||
114 | 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, | ||
118 | unsigned int bits); | ||
119 | extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); | ||
120 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, | ||
121 | struct cx25821_dmaqueue *q, | ||
122 | struct cx25821_buffer *buf, | ||
123 | struct sram_channel *channel); | ||
124 | |||
125 | extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, | ||
126 | unsigned int height, enum v4l2_field field); | ||
127 | extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); | ||
128 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); | ||
129 | extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, | ||
130 | struct video_device *video_template); | ||
131 | extern int get_format_size(void); | ||
132 | |||
133 | extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, | ||
134 | unsigned int *size); | ||
135 | extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
136 | enum v4l2_field field); | ||
137 | extern void buffer_release(struct videobuf_queue *q, | ||
138 | struct videobuf_buffer *vb); | ||
139 | extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); | ||
140 | extern int get_resource(struct cx25821_fh *fh, int resource); | ||
141 | extern int video_mmap(struct file *file, struct vm_area_struct *vma); | ||
142 | extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
143 | struct v4l2_format *f); | ||
144 | extern int vidioc_querycap(struct file *file, void *priv, | ||
145 | struct v4l2_capability *cap); | ||
146 | extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
147 | struct v4l2_fmtdesc *f); | ||
148 | extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); | ||
149 | extern int vidioc_reqbufs(struct file *file, void *priv, | ||
150 | struct v4l2_requestbuffers *p); | ||
151 | extern int vidioc_querybuf(struct file *file, void *priv, | ||
152 | struct v4l2_buffer *p); | ||
153 | extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
154 | extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms); | ||
155 | extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); | ||
156 | extern int vidioc_enum_input(struct file *file, void *priv, | ||
157 | struct v4l2_input *i); | ||
158 | extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i); | ||
159 | extern int vidioc_s_input(struct file *file, void *priv, unsigned int i); | ||
160 | extern int vidioc_g_ctrl(struct file *file, void *priv, | ||
161 | struct v4l2_control *ctl); | ||
162 | extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
163 | struct v4l2_format *f); | ||
164 | extern int vidioc_g_frequency(struct file *file, void *priv, | ||
165 | struct v4l2_frequency *f); | ||
166 | extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); | ||
167 | extern int vidioc_s_frequency(struct file *file, void *priv, | ||
168 | struct v4l2_frequency *f); | ||
169 | extern int vidioc_g_register(struct file *file, void *fh, | ||
170 | struct v4l2_dbg_register *reg); | ||
171 | extern int vidioc_s_register(struct file *file, void *fh, | ||
172 | struct v4l2_dbg_register *reg); | ||
173 | extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | ||
174 | extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | ||
175 | |||
176 | extern int is_valid_width(u32 width, v4l2_std_id tvnorm); | ||
177 | extern int is_valid_height(u32 height, v4l2_std_id tvnorm); | ||
178 | |||
179 | extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); | ||
180 | extern int vidioc_s_priority(struct file *file, void *f, | ||
181 | enum v4l2_priority prio); | ||
182 | |||
183 | extern int vidioc_queryctrl(struct file *file, void *priv, | ||
184 | struct v4l2_queryctrl *qctrl); | ||
185 | extern int cx25821_set_control(struct cx25821_dev *dev, | ||
186 | struct v4l2_control *ctrl, int chan_num); | ||
187 | |||
188 | extern int vidioc_cropcap(struct file *file, void *fh, | ||
189 | struct v4l2_cropcap *cropcap); | ||
190 | extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); | ||
191 | extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); | ||
192 | |||
193 | extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm); | ||
194 | #endif | ||
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c new file mode 100644 index 000000000000..950fac1d7003 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video0.c | |||
@@ -0,0 +1,451 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH00]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH00] | ||
109 | && h->video_dev[SRAM_CH00]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | |||
129 | file->private_data = fh; | ||
130 | fh->dev = dev; | ||
131 | fh->type = type; | ||
132 | fh->width = 720; | ||
133 | |||
134 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
135 | fh->height = 576; | ||
136 | else | ||
137 | fh->height = 480; | ||
138 | |||
139 | dev->channel_opened = SRAM_CH00; | ||
140 | pix_format = | ||
141 | (dev->pixel_formats[dev->channel_opened] == | ||
142 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
143 | fh->fmt = format_by_fourcc(pix_format); | ||
144 | |||
145 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
146 | |||
147 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
148 | &dev->pci->dev, &dev->slock, | ||
149 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
150 | V4L2_FIELD_INTERLACED, | ||
151 | sizeof(struct cx25821_buffer), fh); | ||
152 | |||
153 | dprintk(1, "post videobuf_queue_init()\n"); | ||
154 | unlock_kernel(); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
160 | loff_t * ppos) | ||
161 | { | ||
162 | struct cx25821_fh *fh = file->private_data; | ||
163 | |||
164 | switch (fh->type) { | ||
165 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
166 | if (res_locked(fh->dev, RESOURCE_VIDEO0)) | ||
167 | return -EBUSY; | ||
168 | |||
169 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
170 | file->f_flags & O_NONBLOCK); | ||
171 | |||
172 | default: | ||
173 | BUG(); | ||
174 | return 0; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static unsigned int video_poll(struct file *file, | ||
179 | struct poll_table_struct *wait) | ||
180 | { | ||
181 | struct cx25821_fh *fh = file->private_data; | ||
182 | struct cx25821_buffer *buf; | ||
183 | |||
184 | if (res_check(fh, RESOURCE_VIDEO0)) { | ||
185 | /* streaming capture */ | ||
186 | if (list_empty(&fh->vidq.stream)) | ||
187 | return POLLERR; | ||
188 | buf = list_entry(fh->vidq.stream.next, | ||
189 | struct cx25821_buffer, vb.stream); | ||
190 | } else { | ||
191 | /* read() capture */ | ||
192 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
193 | if (NULL == buf) | ||
194 | return POLLERR; | ||
195 | } | ||
196 | |||
197 | poll_wait(file, &buf->vb.done, wait); | ||
198 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
199 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
200 | struct cx25821_dev *dev = fh->dev; | ||
201 | |||
202 | if (dev && dev->use_cif_resolution[SRAM_CH00]) { | ||
203 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
204 | memcpy((char *)buf->vb.baddr, | ||
205 | (char *)buf->vb.baddr + (fh->width * 2), | ||
206 | (fh->width * 2)); | ||
207 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return POLLIN | POLLRDNORM; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int video_release(struct file *file) | ||
218 | { | ||
219 | struct cx25821_fh *fh = file->private_data; | ||
220 | struct cx25821_dev *dev = fh->dev; | ||
221 | |||
222 | //stop the risc engine and fifo | ||
223 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ | ||
224 | |||
225 | /* stop video capture */ | ||
226 | if (res_check(fh, RESOURCE_VIDEO0)) { | ||
227 | videobuf_queue_cancel(&fh->vidq); | ||
228 | res_free(dev, fh, RESOURCE_VIDEO0); | ||
229 | } | ||
230 | |||
231 | if (fh->vidq.read_buf) { | ||
232 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
233 | kfree(fh->vidq.read_buf); | ||
234 | } | ||
235 | |||
236 | videobuf_mmap_free(&fh->vidq); | ||
237 | |||
238 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
239 | file->private_data = NULL; | ||
240 | kfree(fh); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
246 | { | ||
247 | struct cx25821_fh *fh = priv; | ||
248 | struct cx25821_dev *dev = fh->dev; | ||
249 | |||
250 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | if (unlikely(i != fh->type)) { | ||
255 | return -EINVAL; | ||
256 | } | ||
257 | |||
258 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) { | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
285 | 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 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
294 | if (0 != err) | ||
295 | return err; | ||
296 | } | ||
297 | |||
298 | dprintk(2, "%s()\n", __func__); | ||
299 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
300 | |||
301 | if (0 != err) | ||
302 | return err; | ||
303 | |||
304 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
305 | fh->vidq.field = f->fmt.pix.field; | ||
306 | |||
307 | // check if width and height is valid based on set standard | ||
308 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | ||
309 | fh->width = f->fmt.pix.width; | ||
310 | } | ||
311 | |||
312 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
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_CH00, pix_format); | ||
324 | |||
325 | // check if cif resolution | ||
326 | if (fh->width == 320 || fh->width == 352) { | ||
327 | dev->use_cif_resolution[SRAM_CH00] = 1; | ||
328 | } else { | ||
329 | dev->use_cif_resolution[SRAM_CH00] = 0; | ||
330 | } | ||
331 | dev->cif_width[SRAM_CH00] = fh->width; | ||
332 | medusa_set_resolution(dev, fh->width, SRAM_CH00); | ||
333 | |||
334 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
335 | fh->height, fh->vidq.field); | ||
336 | cx25821_call_all(dev, video, s_fmt, f); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
342 | { | ||
343 | int ret_val = 0; | ||
344 | struct cx25821_fh *fh = priv; | ||
345 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
346 | |||
347 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
348 | |||
349 | p->sequence = dev->vidq[SRAM_CH00].count; | ||
350 | |||
351 | return ret_val; | ||
352 | } | ||
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_CH00]; | ||
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 | tmp = cx_read(sram_ch->dma_ctl); | ||
367 | printk(KERN_INFO "Video input 0 is %s\n", | ||
368 | (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_CH00); | ||
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_template0 = { | ||
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 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c new file mode 100644 index 000000000000..a4dddc684adf --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video1.c | |||
@@ -0,0 +1,451 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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 | /* 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH01]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH01] | ||
109 | && h->video_dev[SRAM_CH01]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | |||
129 | file->private_data = fh; | ||
130 | fh->dev = dev; | ||
131 | fh->type = type; | ||
132 | fh->width = 720; | ||
133 | |||
134 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
135 | fh->height = 576; | ||
136 | else | ||
137 | fh->height = 480; | ||
138 | |||
139 | dev->channel_opened = SRAM_CH01; | ||
140 | pix_format = | ||
141 | (dev->pixel_formats[dev->channel_opened] == | ||
142 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
143 | fh->fmt = format_by_fourcc(pix_format); | ||
144 | |||
145 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
146 | |||
147 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
148 | &dev->pci->dev, &dev->slock, | ||
149 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
150 | V4L2_FIELD_INTERLACED, | ||
151 | sizeof(struct cx25821_buffer), fh); | ||
152 | |||
153 | dprintk(1, "post videobuf_queue_init()\n"); | ||
154 | unlock_kernel(); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
160 | loff_t * ppos) | ||
161 | { | ||
162 | struct cx25821_fh *fh = file->private_data; | ||
163 | |||
164 | switch (fh->type) { | ||
165 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
166 | if (res_locked(fh->dev, RESOURCE_VIDEO1)) | ||
167 | return -EBUSY; | ||
168 | |||
169 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
170 | file->f_flags & O_NONBLOCK); | ||
171 | |||
172 | default: | ||
173 | BUG(); | ||
174 | return 0; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static unsigned int video_poll(struct file *file, | ||
179 | struct poll_table_struct *wait) | ||
180 | { | ||
181 | struct cx25821_fh *fh = file->private_data; | ||
182 | struct cx25821_buffer *buf; | ||
183 | |||
184 | if (res_check(fh, RESOURCE_VIDEO1)) { | ||
185 | /* streaming capture */ | ||
186 | if (list_empty(&fh->vidq.stream)) | ||
187 | return POLLERR; | ||
188 | buf = list_entry(fh->vidq.stream.next, | ||
189 | struct cx25821_buffer, vb.stream); | ||
190 | } else { | ||
191 | /* read() capture */ | ||
192 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
193 | if (NULL == buf) | ||
194 | return POLLERR; | ||
195 | } | ||
196 | |||
197 | poll_wait(file, &buf->vb.done, wait); | ||
198 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
199 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
200 | struct cx25821_dev *dev = fh->dev; | ||
201 | |||
202 | if (dev && dev->use_cif_resolution[SRAM_CH01]) { | ||
203 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
204 | memcpy((char *)buf->vb.baddr, | ||
205 | (char *)buf->vb.baddr + (fh->width * 2), | ||
206 | (fh->width * 2)); | ||
207 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return POLLIN | POLLRDNORM; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int video_release(struct file *file) | ||
218 | { | ||
219 | struct cx25821_fh *fh = file->private_data; | ||
220 | struct cx25821_dev *dev = fh->dev; | ||
221 | |||
222 | //stop the risc engine and fifo | ||
223 | cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ | ||
224 | |||
225 | /* stop video capture */ | ||
226 | if (res_check(fh, RESOURCE_VIDEO1)) { | ||
227 | videobuf_queue_cancel(&fh->vidq); | ||
228 | res_free(dev, fh, RESOURCE_VIDEO1); | ||
229 | } | ||
230 | |||
231 | if (fh->vidq.read_buf) { | ||
232 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
233 | kfree(fh->vidq.read_buf); | ||
234 | } | ||
235 | |||
236 | videobuf_mmap_free(&fh->vidq); | ||
237 | |||
238 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
239 | file->private_data = NULL; | ||
240 | kfree(fh); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
246 | { | ||
247 | struct cx25821_fh *fh = priv; | ||
248 | struct cx25821_dev *dev = fh->dev; | ||
249 | |||
250 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | if (unlikely(i != fh->type)) { | ||
255 | return -EINVAL; | ||
256 | } | ||
257 | |||
258 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) { | ||
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_VIDEO1); | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
285 | 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 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
294 | if (0 != err) | ||
295 | return err; | ||
296 | } | ||
297 | |||
298 | dprintk(2, "%s()\n", __func__); | ||
299 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
300 | |||
301 | if (0 != err) | ||
302 | return err; | ||
303 | |||
304 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
305 | fh->vidq.field = f->fmt.pix.field; | ||
306 | |||
307 | // check if width and height is valid based on set standard | ||
308 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | ||
309 | fh->width = f->fmt.pix.width; | ||
310 | } | ||
311 | |||
312 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
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_CH01, pix_format); | ||
324 | |||
325 | // check if cif resolution | ||
326 | if (fh->width == 320 || fh->width == 352) { | ||
327 | dev->use_cif_resolution[SRAM_CH01] = 1; | ||
328 | } else { | ||
329 | dev->use_cif_resolution[SRAM_CH01] = 0; | ||
330 | } | ||
331 | dev->cif_width[SRAM_CH01] = fh->width; | ||
332 | medusa_set_resolution(dev, fh->width, SRAM_CH01); | ||
333 | |||
334 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
335 | fh->height, fh->vidq.field); | ||
336 | cx25821_call_all(dev, video, s_fmt, f); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
342 | { | ||
343 | int ret_val = 0; | ||
344 | struct cx25821_fh *fh = priv; | ||
345 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
346 | |||
347 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
348 | |||
349 | p->sequence = dev->vidq[SRAM_CH01].count; | ||
350 | |||
351 | return ret_val; | ||
352 | } | ||
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_CH01]; | ||
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 | tmp = cx_read(sram_ch->dma_ctl); | ||
367 | printk(KERN_INFO "Video input 1 is %s\n", | ||
368 | (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_CH01); | ||
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_template1 = { | ||
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 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c new file mode 100644 index 000000000000..8e04e253f5d9 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video2.c | |||
@@ -0,0 +1,452 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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 | /* 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH02]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH02] | ||
109 | && h->video_dev[SRAM_CH02]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = SRAM_CH02; | ||
139 | pix_format = | ||
140 | (dev->pixel_formats[dev->channel_opened] == | ||
141 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
142 | fh->fmt = format_by_fourcc(pix_format); | ||
143 | |||
144 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
145 | |||
146 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
147 | &dev->pci->dev, &dev->slock, | ||
148 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
149 | V4L2_FIELD_INTERLACED, | ||
150 | sizeof(struct cx25821_buffer), fh); | ||
151 | |||
152 | dprintk(1, "post videobuf_queue_init()\n"); | ||
153 | unlock_kernel(); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
159 | loff_t * ppos) | ||
160 | { | ||
161 | struct cx25821_fh *fh = file->private_data; | ||
162 | |||
163 | switch (fh->type) { | ||
164 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
165 | if (res_locked(fh->dev, RESOURCE_VIDEO2)) | ||
166 | return -EBUSY; | ||
167 | |||
168 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
169 | file->f_flags & O_NONBLOCK); | ||
170 | |||
171 | default: | ||
172 | BUG(); | ||
173 | return 0; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static unsigned int video_poll(struct file *file, | ||
178 | struct poll_table_struct *wait) | ||
179 | { | ||
180 | struct cx25821_fh *fh = file->private_data; | ||
181 | struct cx25821_buffer *buf; | ||
182 | |||
183 | if (res_check(fh, RESOURCE_VIDEO2)) { | ||
184 | /* streaming capture */ | ||
185 | if (list_empty(&fh->vidq.stream)) | ||
186 | return POLLERR; | ||
187 | buf = list_entry(fh->vidq.stream.next, | ||
188 | struct cx25821_buffer, vb.stream); | ||
189 | } else { | ||
190 | /* read() capture */ | ||
191 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
192 | if (NULL == buf) | ||
193 | return POLLERR; | ||
194 | } | ||
195 | |||
196 | poll_wait(file, &buf->vb.done, wait); | ||
197 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
198 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | if (dev && dev->use_cif_resolution[SRAM_CH02]) { | ||
202 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
203 | memcpy((char *)buf->vb.baddr, | ||
204 | (char *)buf->vb.baddr + (fh->width * 2), | ||
205 | (fh->width * 2)); | ||
206 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return POLLIN | POLLRDNORM; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int video_release(struct file *file) | ||
217 | { | ||
218 | struct cx25821_fh *fh = file->private_data; | ||
219 | struct cx25821_dev *dev = fh->dev; | ||
220 | |||
221 | //stop the risc engine and fifo | ||
222 | cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ | ||
223 | |||
224 | /* stop video capture */ | ||
225 | if (res_check(fh, RESOURCE_VIDEO2)) { | ||
226 | videobuf_queue_cancel(&fh->vidq); | ||
227 | res_free(dev, fh, RESOURCE_VIDEO2); | ||
228 | } | ||
229 | |||
230 | if (fh->vidq.read_buf) { | ||
231 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
232 | kfree(fh->vidq.read_buf); | ||
233 | } | ||
234 | |||
235 | videobuf_mmap_free(&fh->vidq); | ||
236 | |||
237 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
238 | file->private_data = NULL; | ||
239 | kfree(fh); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
245 | { | ||
246 | struct cx25821_fh *fh = priv; | ||
247 | struct cx25821_dev *dev = fh->dev; | ||
248 | |||
249 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | if (unlikely(i != fh->type)) { | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) { | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
284 | struct v4l2_format *f) | ||
285 | { | ||
286 | struct cx25821_fh *fh = priv; | ||
287 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
288 | int err; | ||
289 | int pix_format = 0; | ||
290 | |||
291 | if (fh) { | ||
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 | fh->width = f->fmt.pix.width; | ||
309 | } | ||
310 | |||
311 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
312 | fh->height = f->fmt.pix.height; | ||
313 | } | ||
314 | |||
315 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
316 | pix_format = PIXEL_FRMT_411; | ||
317 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
318 | pix_format = PIXEL_FRMT_422; | ||
319 | else | ||
320 | return -EINVAL; | ||
321 | |||
322 | cx25821_set_pixel_format(dev, SRAM_CH02, pix_format); | ||
323 | |||
324 | // check if cif resolution | ||
325 | if (fh->width == 320 || fh->width == 352) { | ||
326 | dev->use_cif_resolution[SRAM_CH02] = 1; | ||
327 | } else { | ||
328 | dev->use_cif_resolution[SRAM_CH02] = 0; | ||
329 | } | ||
330 | dev->cif_width[SRAM_CH02] = fh->width; | ||
331 | medusa_set_resolution(dev, fh->width, SRAM_CH02); | ||
332 | |||
333 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
334 | fh->height, fh->vidq.field); | ||
335 | cx25821_call_all(dev, video, s_fmt, f); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
341 | { | ||
342 | int ret_val = 0; | ||
343 | struct cx25821_fh *fh = priv; | ||
344 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
345 | |||
346 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
347 | |||
348 | p->sequence = dev->vidq[SRAM_CH02].count; | ||
349 | |||
350 | return ret_val; | ||
351 | } | ||
352 | |||
353 | static int vidioc_log_status(struct file *file, void *priv) | ||
354 | { | ||
355 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
356 | char name[32 + 2]; | ||
357 | |||
358 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; | ||
359 | u32 tmp = 0; | ||
360 | |||
361 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
362 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
363 | dev->name); | ||
364 | |||
365 | cx25821_call_all(dev, core, log_status); | ||
366 | |||
367 | tmp = cx_read(sram_ch->dma_ctl); | ||
368 | printk(KERN_INFO "Video input 2 is %s\n", | ||
369 | (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_CH02); | ||
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_template2 = { | ||
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 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c new file mode 100644 index 000000000000..8801a8ead904 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video3.c | |||
@@ -0,0 +1,451 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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 | /* 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH03]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH03] | ||
109 | && h->video_dev[SRAM_CH03]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = SRAM_CH03; | ||
139 | pix_format = | ||
140 | (dev->pixel_formats[dev->channel_opened] == | ||
141 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
142 | fh->fmt = format_by_fourcc(pix_format); | ||
143 | |||
144 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
145 | |||
146 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
147 | &dev->pci->dev, &dev->slock, | ||
148 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
149 | V4L2_FIELD_INTERLACED, | ||
150 | sizeof(struct cx25821_buffer), fh); | ||
151 | |||
152 | dprintk(1, "post videobuf_queue_init()\n"); | ||
153 | unlock_kernel(); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
159 | loff_t * ppos) | ||
160 | { | ||
161 | struct cx25821_fh *fh = file->private_data; | ||
162 | |||
163 | switch (fh->type) { | ||
164 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
165 | if (res_locked(fh->dev, RESOURCE_VIDEO3)) | ||
166 | return -EBUSY; | ||
167 | |||
168 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
169 | file->f_flags & O_NONBLOCK); | ||
170 | |||
171 | default: | ||
172 | BUG(); | ||
173 | return 0; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static unsigned int video_poll(struct file *file, | ||
178 | struct poll_table_struct *wait) | ||
179 | { | ||
180 | struct cx25821_fh *fh = file->private_data; | ||
181 | struct cx25821_buffer *buf; | ||
182 | |||
183 | if (res_check(fh, RESOURCE_VIDEO3)) { | ||
184 | /* streaming capture */ | ||
185 | if (list_empty(&fh->vidq.stream)) | ||
186 | return POLLERR; | ||
187 | buf = list_entry(fh->vidq.stream.next, | ||
188 | struct cx25821_buffer, vb.stream); | ||
189 | } else { | ||
190 | /* read() capture */ | ||
191 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
192 | if (NULL == buf) | ||
193 | return POLLERR; | ||
194 | } | ||
195 | |||
196 | poll_wait(file, &buf->vb.done, wait); | ||
197 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
198 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | if (dev && dev->use_cif_resolution[SRAM_CH03]) { | ||
202 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
203 | memcpy((char *)buf->vb.baddr, | ||
204 | (char *)buf->vb.baddr + (fh->width * 2), | ||
205 | (fh->width * 2)); | ||
206 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return POLLIN | POLLRDNORM; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int video_release(struct file *file) | ||
217 | { | ||
218 | struct cx25821_fh *fh = file->private_data; | ||
219 | struct cx25821_dev *dev = fh->dev; | ||
220 | |||
221 | //stop the risc engine and fifo | ||
222 | cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ | ||
223 | |||
224 | /* stop video capture */ | ||
225 | if (res_check(fh, RESOURCE_VIDEO3)) { | ||
226 | videobuf_queue_cancel(&fh->vidq); | ||
227 | res_free(dev, fh, RESOURCE_VIDEO3); | ||
228 | } | ||
229 | |||
230 | if (fh->vidq.read_buf) { | ||
231 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
232 | kfree(fh->vidq.read_buf); | ||
233 | } | ||
234 | |||
235 | videobuf_mmap_free(&fh->vidq); | ||
236 | |||
237 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
238 | file->private_data = NULL; | ||
239 | kfree(fh); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
245 | { | ||
246 | struct cx25821_fh *fh = priv; | ||
247 | struct cx25821_dev *dev = fh->dev; | ||
248 | |||
249 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | if (unlikely(i != fh->type)) { | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) { | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
284 | struct v4l2_format *f) | ||
285 | { | ||
286 | struct cx25821_fh *fh = priv; | ||
287 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
288 | int err; | ||
289 | int pix_format = 0; | ||
290 | |||
291 | if (fh) { | ||
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 | fh->width = f->fmt.pix.width; | ||
309 | } | ||
310 | |||
311 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
312 | fh->height = f->fmt.pix.height; | ||
313 | } | ||
314 | |||
315 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
316 | pix_format = PIXEL_FRMT_411; | ||
317 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
318 | pix_format = PIXEL_FRMT_422; | ||
319 | else | ||
320 | return -EINVAL; | ||
321 | |||
322 | cx25821_set_pixel_format(dev, SRAM_CH03, pix_format); | ||
323 | |||
324 | // check if cif resolution | ||
325 | if (fh->width == 320 || fh->width == 352) { | ||
326 | dev->use_cif_resolution[SRAM_CH03] = 1; | ||
327 | } else { | ||
328 | dev->use_cif_resolution[SRAM_CH03] = 0; | ||
329 | } | ||
330 | dev->cif_width[SRAM_CH03] = fh->width; | ||
331 | medusa_set_resolution(dev, fh->width, SRAM_CH03); | ||
332 | |||
333 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
334 | fh->height, fh->vidq.field); | ||
335 | cx25821_call_all(dev, video, s_fmt, f); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
341 | { | ||
342 | int ret_val = 0; | ||
343 | struct cx25821_fh *fh = priv; | ||
344 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
345 | |||
346 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
347 | |||
348 | p->sequence = dev->vidq[SRAM_CH03].count; | ||
349 | |||
350 | return ret_val; | ||
351 | } | ||
352 | |||
353 | static int vidioc_log_status(struct file *file, void *priv) | ||
354 | { | ||
355 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
356 | char name[32 + 2]; | ||
357 | |||
358 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; | ||
359 | u32 tmp = 0; | ||
360 | |||
361 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
362 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
363 | dev->name); | ||
364 | cx25821_call_all(dev, core, log_status); | ||
365 | |||
366 | tmp = cx_read(sram_ch->dma_ctl); | ||
367 | printk(KERN_INFO "Video input 3 is %s\n", | ||
368 | (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_CH03); | ||
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_template3 = { | ||
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 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c new file mode 100644 index 000000000000..ab0d747138ad --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video4.c | |||
@@ -0,0 +1,450 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH04]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH04] | ||
109 | && h->video_dev[SRAM_CH04]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = SRAM_CH04; | ||
139 | pix_format = | ||
140 | (dev->pixel_formats[dev->channel_opened] == | ||
141 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
142 | fh->fmt = format_by_fourcc(pix_format); | ||
143 | |||
144 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
145 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
146 | &dev->pci->dev, &dev->slock, | ||
147 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
148 | V4L2_FIELD_INTERLACED, | ||
149 | sizeof(struct cx25821_buffer), fh); | ||
150 | |||
151 | dprintk(1, "post videobuf_queue_init()\n"); | ||
152 | unlock_kernel(); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
158 | loff_t * ppos) | ||
159 | { | ||
160 | struct cx25821_fh *fh = file->private_data; | ||
161 | |||
162 | switch (fh->type) { | ||
163 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
164 | if (res_locked(fh->dev, RESOURCE_VIDEO4)) | ||
165 | return -EBUSY; | ||
166 | |||
167 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
168 | file->f_flags & O_NONBLOCK); | ||
169 | |||
170 | default: | ||
171 | BUG(); | ||
172 | return 0; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | static unsigned int video_poll(struct file *file, | ||
177 | struct poll_table_struct *wait) | ||
178 | { | ||
179 | struct cx25821_fh *fh = file->private_data; | ||
180 | struct cx25821_buffer *buf; | ||
181 | |||
182 | if (res_check(fh, RESOURCE_VIDEO4)) { | ||
183 | /* streaming capture */ | ||
184 | if (list_empty(&fh->vidq.stream)) | ||
185 | return POLLERR; | ||
186 | buf = list_entry(fh->vidq.stream.next, | ||
187 | struct cx25821_buffer, vb.stream); | ||
188 | } else { | ||
189 | /* read() capture */ | ||
190 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
191 | if (NULL == buf) | ||
192 | return POLLERR; | ||
193 | } | ||
194 | |||
195 | poll_wait(file, &buf->vb.done, wait); | ||
196 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
197 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
198 | struct cx25821_dev *dev = fh->dev; | ||
199 | |||
200 | if (dev && dev->use_cif_resolution[SRAM_CH04]) { | ||
201 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
202 | memcpy((char *)buf->vb.baddr, | ||
203 | (char *)buf->vb.baddr + (fh->width * 2), | ||
204 | (fh->width * 2)); | ||
205 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | return POLLIN | POLLRDNORM; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int video_release(struct file *file) | ||
216 | { | ||
217 | struct cx25821_fh *fh = file->private_data; | ||
218 | struct cx25821_dev *dev = fh->dev; | ||
219 | |||
220 | //stop the risc engine and fifo | ||
221 | cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ | ||
222 | |||
223 | /* stop video capture */ | ||
224 | if (res_check(fh, RESOURCE_VIDEO4)) { | ||
225 | videobuf_queue_cancel(&fh->vidq); | ||
226 | res_free(dev, fh, RESOURCE_VIDEO4); | ||
227 | } | ||
228 | |||
229 | if (fh->vidq.read_buf) { | ||
230 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
231 | kfree(fh->vidq.read_buf); | ||
232 | } | ||
233 | |||
234 | videobuf_mmap_free(&fh->vidq); | ||
235 | |||
236 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
237 | file->private_data = NULL; | ||
238 | kfree(fh); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
244 | { | ||
245 | struct cx25821_fh *fh = priv; | ||
246 | struct cx25821_dev *dev = fh->dev; | ||
247 | |||
248 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | if (unlikely(i != fh->type)) { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) { | ||
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_VIDEO4); | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
283 | 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 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
293 | if (0 != err) | ||
294 | return err; | ||
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 | fh->width = f->fmt.pix.width; | ||
308 | } | ||
309 | |||
310 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
311 | fh->height = f->fmt.pix.height; | ||
312 | } | ||
313 | |||
314 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
315 | pix_format = PIXEL_FRMT_411; | ||
316 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
317 | pix_format = PIXEL_FRMT_422; | ||
318 | else | ||
319 | return -EINVAL; | ||
320 | |||
321 | cx25821_set_pixel_format(dev, SRAM_CH04, pix_format); | ||
322 | |||
323 | // check if cif resolution | ||
324 | if (fh->width == 320 || fh->width == 352) { | ||
325 | dev->use_cif_resolution[SRAM_CH04] = 1; | ||
326 | } else { | ||
327 | dev->use_cif_resolution[SRAM_CH04] = 0; | ||
328 | } | ||
329 | dev->cif_width[SRAM_CH04] = fh->width; | ||
330 | medusa_set_resolution(dev, fh->width, SRAM_CH04); | ||
331 | |||
332 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
333 | fh->height, fh->vidq.field); | ||
334 | cx25821_call_all(dev, video, s_fmt, f); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
340 | { | ||
341 | int ret_val = 0; | ||
342 | struct cx25821_fh *fh = priv; | ||
343 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
344 | |||
345 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
346 | |||
347 | p->sequence = dev->vidq[SRAM_CH04].count; | ||
348 | |||
349 | return ret_val; | ||
350 | } | ||
351 | |||
352 | static int vidioc_log_status(struct file *file, void *priv) | ||
353 | { | ||
354 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
355 | char name[32 + 2]; | ||
356 | |||
357 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; | ||
358 | u32 tmp = 0; | ||
359 | |||
360 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
361 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
362 | dev->name); | ||
363 | cx25821_call_all(dev, core, log_status); | ||
364 | |||
365 | tmp = cx_read(sram_ch->dma_ctl); | ||
366 | printk(KERN_INFO "Video input 4 is %s\n", | ||
367 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
368 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
369 | dev->name); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
374 | struct v4l2_control *ctl) | ||
375 | { | ||
376 | struct cx25821_fh *fh = priv; | ||
377 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
378 | int err; | ||
379 | |||
380 | if (fh) { | ||
381 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
382 | if (0 != err) | ||
383 | return err; | ||
384 | } | ||
385 | |||
386 | return cx25821_set_control(dev, ctl, SRAM_CH04); | ||
387 | } | ||
388 | |||
389 | // exported stuff | ||
390 | static const struct v4l2_file_operations video_fops = { | ||
391 | .owner = THIS_MODULE, | ||
392 | .open = video_open, | ||
393 | .release = video_release, | ||
394 | .read = video_read, | ||
395 | .poll = video_poll, | ||
396 | .mmap = video_mmap, | ||
397 | .ioctl = video_ioctl2, | ||
398 | }; | ||
399 | |||
400 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
401 | .vidioc_querycap = vidioc_querycap, | ||
402 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
403 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
404 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
405 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
406 | .vidioc_reqbufs = vidioc_reqbufs, | ||
407 | .vidioc_querybuf = vidioc_querybuf, | ||
408 | .vidioc_qbuf = vidioc_qbuf, | ||
409 | .vidioc_dqbuf = vidioc_dqbuf, | ||
410 | #ifdef TUNER_FLAG | ||
411 | .vidioc_s_std = vidioc_s_std, | ||
412 | .vidioc_querystd = vidioc_querystd, | ||
413 | #endif | ||
414 | .vidioc_cropcap = vidioc_cropcap, | ||
415 | .vidioc_s_crop = vidioc_s_crop, | ||
416 | .vidioc_g_crop = vidioc_g_crop, | ||
417 | .vidioc_enum_input = vidioc_enum_input, | ||
418 | .vidioc_g_input = vidioc_g_input, | ||
419 | .vidioc_s_input = vidioc_s_input, | ||
420 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
421 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
422 | .vidioc_queryctrl = vidioc_queryctrl, | ||
423 | .vidioc_streamon = vidioc_streamon, | ||
424 | .vidioc_streamoff = vidioc_streamoff, | ||
425 | .vidioc_log_status = vidioc_log_status, | ||
426 | .vidioc_g_priority = vidioc_g_priority, | ||
427 | .vidioc_s_priority = vidioc_s_priority, | ||
428 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
429 | .vidiocgmbuf = vidiocgmbuf, | ||
430 | #endif | ||
431 | #ifdef TUNER_FLAG | ||
432 | .vidioc_g_tuner = vidioc_g_tuner, | ||
433 | .vidioc_s_tuner = vidioc_s_tuner, | ||
434 | .vidioc_g_frequency = vidioc_g_frequency, | ||
435 | .vidioc_s_frequency = vidioc_s_frequency, | ||
436 | #endif | ||
437 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
438 | .vidioc_g_register = vidioc_g_register, | ||
439 | .vidioc_s_register = vidioc_s_register, | ||
440 | #endif | ||
441 | }; | ||
442 | |||
443 | struct video_device cx25821_video_template4 = { | ||
444 | .name = "cx25821-video", | ||
445 | .fops = &video_fops, | ||
446 | .minor = -1, | ||
447 | .ioctl_ops = &video_ioctl_ops, | ||
448 | .tvnorms = CX25821_NORMS, | ||
449 | .current_norm = V4L2_STD_NTSC_M, | ||
450 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c new file mode 100644 index 000000000000..7ef0b971f5cf --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video5.c | |||
@@ -0,0 +1,450 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH05]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH05] | ||
109 | && h->video_dev[SRAM_CH05]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = SRAM_CH05; | ||
139 | pix_format = | ||
140 | (dev->pixel_formats[dev->channel_opened] == | ||
141 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
142 | fh->fmt = format_by_fourcc(pix_format); | ||
143 | |||
144 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
145 | |||
146 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
147 | &dev->pci->dev, &dev->slock, | ||
148 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
149 | V4L2_FIELD_INTERLACED, | ||
150 | sizeof(struct cx25821_buffer), fh); | ||
151 | |||
152 | dprintk(1, "post videobuf_queue_init()\n"); | ||
153 | unlock_kernel(); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
159 | loff_t * ppos) | ||
160 | { | ||
161 | struct cx25821_fh *fh = file->private_data; | ||
162 | |||
163 | switch (fh->type) { | ||
164 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
165 | if (res_locked(fh->dev, RESOURCE_VIDEO5)) | ||
166 | return -EBUSY; | ||
167 | |||
168 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
169 | file->f_flags & O_NONBLOCK); | ||
170 | |||
171 | default: | ||
172 | BUG(); | ||
173 | return 0; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static unsigned int video_poll(struct file *file, | ||
178 | struct poll_table_struct *wait) | ||
179 | { | ||
180 | struct cx25821_fh *fh = file->private_data; | ||
181 | struct cx25821_buffer *buf; | ||
182 | |||
183 | if (res_check(fh, RESOURCE_VIDEO5)) { | ||
184 | /* streaming capture */ | ||
185 | if (list_empty(&fh->vidq.stream)) | ||
186 | return POLLERR; | ||
187 | buf = list_entry(fh->vidq.stream.next, | ||
188 | struct cx25821_buffer, vb.stream); | ||
189 | } else { | ||
190 | /* read() capture */ | ||
191 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
192 | if (NULL == buf) | ||
193 | return POLLERR; | ||
194 | } | ||
195 | |||
196 | poll_wait(file, &buf->vb.done, wait); | ||
197 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
198 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | if (dev && dev->use_cif_resolution[SRAM_CH05]) { | ||
202 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
203 | memcpy((char *)buf->vb.baddr, | ||
204 | (char *)buf->vb.baddr + (fh->width * 2), | ||
205 | (fh->width * 2)); | ||
206 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return POLLIN | POLLRDNORM; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int video_release(struct file *file) | ||
217 | { | ||
218 | struct cx25821_fh *fh = file->private_data; | ||
219 | struct cx25821_dev *dev = fh->dev; | ||
220 | |||
221 | //stop the risc engine and fifo | ||
222 | cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ | ||
223 | |||
224 | /* stop video capture */ | ||
225 | if (res_check(fh, RESOURCE_VIDEO5)) { | ||
226 | videobuf_queue_cancel(&fh->vidq); | ||
227 | res_free(dev, fh, RESOURCE_VIDEO5); | ||
228 | } | ||
229 | |||
230 | if (fh->vidq.read_buf) { | ||
231 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
232 | kfree(fh->vidq.read_buf); | ||
233 | } | ||
234 | |||
235 | videobuf_mmap_free(&fh->vidq); | ||
236 | |||
237 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
238 | file->private_data = NULL; | ||
239 | kfree(fh); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
245 | { | ||
246 | struct cx25821_fh *fh = priv; | ||
247 | struct cx25821_dev *dev = fh->dev; | ||
248 | |||
249 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | if (unlikely(i != fh->type)) { | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) { | ||
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_VIDEO5); | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
284 | struct v4l2_format *f) | ||
285 | { | ||
286 | struct cx25821_fh *fh = priv; | ||
287 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
288 | int err; | ||
289 | int pix_format = 0; | ||
290 | |||
291 | if (fh) { | ||
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 | fh->width = f->fmt.pix.width; | ||
309 | } | ||
310 | |||
311 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
312 | fh->height = f->fmt.pix.height; | ||
313 | } | ||
314 | |||
315 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
316 | pix_format = PIXEL_FRMT_411; | ||
317 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
318 | pix_format = PIXEL_FRMT_422; | ||
319 | else | ||
320 | return -EINVAL; | ||
321 | |||
322 | cx25821_set_pixel_format(dev, SRAM_CH05, pix_format); | ||
323 | |||
324 | // check if cif resolution | ||
325 | if (fh->width == 320 || fh->width == 352) { | ||
326 | dev->use_cif_resolution[SRAM_CH05] = 1; | ||
327 | } else { | ||
328 | dev->use_cif_resolution[SRAM_CH05] = 0; | ||
329 | } | ||
330 | dev->cif_width[SRAM_CH05] = fh->width; | ||
331 | medusa_set_resolution(dev, fh->width, SRAM_CH05); | ||
332 | |||
333 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
334 | fh->height, fh->vidq.field); | ||
335 | cx25821_call_all(dev, video, s_fmt, f); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
341 | { | ||
342 | int ret_val = 0; | ||
343 | struct cx25821_fh *fh = priv; | ||
344 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
345 | |||
346 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
347 | |||
348 | p->sequence = dev->vidq[SRAM_CH05].count; | ||
349 | |||
350 | return ret_val; | ||
351 | } | ||
352 | static int vidioc_log_status(struct file *file, void *priv) | ||
353 | { | ||
354 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
355 | char name[32 + 2]; | ||
356 | |||
357 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; | ||
358 | u32 tmp = 0; | ||
359 | |||
360 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
361 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
362 | dev->name); | ||
363 | cx25821_call_all(dev, core, log_status); | ||
364 | |||
365 | tmp = cx_read(sram_ch->dma_ctl); | ||
366 | printk(KERN_INFO "Video input 5 is %s\n", | ||
367 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
368 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
369 | dev->name); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
374 | struct v4l2_control *ctl) | ||
375 | { | ||
376 | struct cx25821_fh *fh = priv; | ||
377 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
378 | int err; | ||
379 | |||
380 | if (fh) { | ||
381 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
382 | if (0 != err) | ||
383 | return err; | ||
384 | } | ||
385 | |||
386 | return cx25821_set_control(dev, ctl, SRAM_CH05); | ||
387 | } | ||
388 | |||
389 | // exported stuff | ||
390 | static const struct v4l2_file_operations video_fops = { | ||
391 | .owner = THIS_MODULE, | ||
392 | .open = video_open, | ||
393 | .release = video_release, | ||
394 | .read = video_read, | ||
395 | .poll = video_poll, | ||
396 | .mmap = video_mmap, | ||
397 | .ioctl = video_ioctl2, | ||
398 | }; | ||
399 | |||
400 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
401 | .vidioc_querycap = vidioc_querycap, | ||
402 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
403 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
404 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
405 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
406 | .vidioc_reqbufs = vidioc_reqbufs, | ||
407 | .vidioc_querybuf = vidioc_querybuf, | ||
408 | .vidioc_qbuf = vidioc_qbuf, | ||
409 | .vidioc_dqbuf = vidioc_dqbuf, | ||
410 | #ifdef TUNER_FLAG | ||
411 | .vidioc_s_std = vidioc_s_std, | ||
412 | .vidioc_querystd = vidioc_querystd, | ||
413 | #endif | ||
414 | .vidioc_cropcap = vidioc_cropcap, | ||
415 | .vidioc_s_crop = vidioc_s_crop, | ||
416 | .vidioc_g_crop = vidioc_g_crop, | ||
417 | .vidioc_enum_input = vidioc_enum_input, | ||
418 | .vidioc_g_input = vidioc_g_input, | ||
419 | .vidioc_s_input = vidioc_s_input, | ||
420 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
421 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
422 | .vidioc_queryctrl = vidioc_queryctrl, | ||
423 | .vidioc_streamon = vidioc_streamon, | ||
424 | .vidioc_streamoff = vidioc_streamoff, | ||
425 | .vidioc_log_status = vidioc_log_status, | ||
426 | .vidioc_g_priority = vidioc_g_priority, | ||
427 | .vidioc_s_priority = vidioc_s_priority, | ||
428 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
429 | .vidiocgmbuf = vidiocgmbuf, | ||
430 | #endif | ||
431 | #ifdef TUNER_FLAG | ||
432 | .vidioc_g_tuner = vidioc_g_tuner, | ||
433 | .vidioc_s_tuner = vidioc_s_tuner, | ||
434 | .vidioc_g_frequency = vidioc_g_frequency, | ||
435 | .vidioc_s_frequency = vidioc_s_frequency, | ||
436 | #endif | ||
437 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
438 | .vidioc_g_register = vidioc_g_register, | ||
439 | .vidioc_s_register = vidioc_s_register, | ||
440 | #endif | ||
441 | }; | ||
442 | |||
443 | struct video_device cx25821_video_template5 = { | ||
444 | .name = "cx25821-video", | ||
445 | .fops = &video_fops, | ||
446 | .minor = -1, | ||
447 | .ioctl_ops = &video_ioctl_ops, | ||
448 | .tvnorms = CX25821_NORMS, | ||
449 | .current_norm = V4L2_STD_NTSC_M, | ||
450 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c new file mode 100644 index 000000000000..3c41b49e2ea9 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video6.c | |||
@@ -0,0 +1,450 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH06]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->video_dev[SRAM_CH06] | ||
109 | && h->video_dev[SRAM_CH06]->minor == minor) { | ||
110 | dev = h; | ||
111 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (NULL == dev) { | ||
116 | unlock_kernel(); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
121 | |||
122 | /* allocate + initialize per filehandle data */ | ||
123 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
124 | if (NULL == fh) { | ||
125 | unlock_kernel(); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = SRAM_CH06; | ||
139 | pix_format = | ||
140 | (dev->pixel_formats[dev->channel_opened] == | ||
141 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
142 | fh->fmt = format_by_fourcc(pix_format); | ||
143 | |||
144 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
145 | |||
146 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
147 | &dev->pci->dev, &dev->slock, | ||
148 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
149 | V4L2_FIELD_INTERLACED, | ||
150 | sizeof(struct cx25821_buffer), fh); | ||
151 | |||
152 | dprintk(1, "post videobuf_queue_init()\n"); | ||
153 | unlock_kernel(); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
159 | loff_t * ppos) | ||
160 | { | ||
161 | struct cx25821_fh *fh = file->private_data; | ||
162 | |||
163 | switch (fh->type) { | ||
164 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
165 | if (res_locked(fh->dev, RESOURCE_VIDEO6)) | ||
166 | return -EBUSY; | ||
167 | |||
168 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
169 | file->f_flags & O_NONBLOCK); | ||
170 | |||
171 | default: | ||
172 | BUG(); | ||
173 | return 0; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static unsigned int video_poll(struct file *file, | ||
178 | struct poll_table_struct *wait) | ||
179 | { | ||
180 | struct cx25821_fh *fh = file->private_data; | ||
181 | struct cx25821_buffer *buf; | ||
182 | |||
183 | if (res_check(fh, RESOURCE_VIDEO6)) { | ||
184 | /* streaming capture */ | ||
185 | if (list_empty(&fh->vidq.stream)) | ||
186 | return POLLERR; | ||
187 | buf = list_entry(fh->vidq.stream.next, | ||
188 | struct cx25821_buffer, vb.stream); | ||
189 | } else { | ||
190 | /* read() capture */ | ||
191 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
192 | if (NULL == buf) | ||
193 | return POLLERR; | ||
194 | } | ||
195 | |||
196 | poll_wait(file, &buf->vb.done, wait); | ||
197 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
198 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
199 | struct cx25821_dev *dev = fh->dev; | ||
200 | |||
201 | if (dev && dev->use_cif_resolution[SRAM_CH06]) { | ||
202 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
203 | memcpy((char *)buf->vb.baddr, | ||
204 | (char *)buf->vb.baddr + (fh->width * 2), | ||
205 | (fh->width * 2)); | ||
206 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return POLLIN | POLLRDNORM; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int video_release(struct file *file) | ||
217 | { | ||
218 | struct cx25821_fh *fh = file->private_data; | ||
219 | struct cx25821_dev *dev = fh->dev; | ||
220 | |||
221 | //stop the risc engine and fifo | ||
222 | cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ | ||
223 | |||
224 | /* stop video capture */ | ||
225 | if (res_check(fh, RESOURCE_VIDEO6)) { | ||
226 | videobuf_queue_cancel(&fh->vidq); | ||
227 | res_free(dev, fh, RESOURCE_VIDEO6); | ||
228 | } | ||
229 | if (fh->vidq.read_buf) { | ||
230 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
231 | kfree(fh->vidq.read_buf); | ||
232 | } | ||
233 | |||
234 | videobuf_mmap_free(&fh->vidq); | ||
235 | |||
236 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
237 | file->private_data = NULL; | ||
238 | kfree(fh); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
244 | { | ||
245 | struct cx25821_fh *fh = priv; | ||
246 | struct cx25821_dev *dev = fh->dev; | ||
247 | |||
248 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | if (unlikely(i != fh->type)) { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) { | ||
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_VIDEO6); | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
283 | 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 | 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 | fh->width = f->fmt.pix.width; | ||
308 | } | ||
309 | |||
310 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
311 | fh->height = f->fmt.pix.height; | ||
312 | } | ||
313 | |||
314 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
315 | pix_format = PIXEL_FRMT_411; | ||
316 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
317 | pix_format = PIXEL_FRMT_422; | ||
318 | else | ||
319 | return -EINVAL; | ||
320 | |||
321 | cx25821_set_pixel_format(dev, SRAM_CH06, pix_format); | ||
322 | |||
323 | // check if cif resolution | ||
324 | if (fh->width == 320 || fh->width == 352) { | ||
325 | dev->use_cif_resolution[SRAM_CH06] = 1; | ||
326 | } else { | ||
327 | dev->use_cif_resolution[SRAM_CH06] = 0; | ||
328 | } | ||
329 | dev->cif_width[SRAM_CH06] = fh->width; | ||
330 | medusa_set_resolution(dev, fh->width, SRAM_CH06); | ||
331 | |||
332 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
333 | fh->height, fh->vidq.field); | ||
334 | cx25821_call_all(dev, video, s_fmt, f); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
340 | { | ||
341 | int ret_val = 0; | ||
342 | struct cx25821_fh *fh = priv; | ||
343 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
344 | |||
345 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
346 | |||
347 | p->sequence = dev->vidq[SRAM_CH06].count; | ||
348 | |||
349 | return ret_val; | ||
350 | } | ||
351 | |||
352 | static int vidioc_log_status(struct file *file, void *priv) | ||
353 | { | ||
354 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
355 | char name[32 + 2]; | ||
356 | |||
357 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; | ||
358 | u32 tmp = 0; | ||
359 | |||
360 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
361 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
362 | dev->name); | ||
363 | cx25821_call_all(dev, core, log_status); | ||
364 | |||
365 | tmp = cx_read(sram_ch->dma_ctl); | ||
366 | printk(KERN_INFO "Video input 6 is %s\n", | ||
367 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
368 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
369 | dev->name); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
374 | struct v4l2_control *ctl) | ||
375 | { | ||
376 | struct cx25821_fh *fh = priv; | ||
377 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
378 | int err; | ||
379 | |||
380 | if (fh) { | ||
381 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
382 | if (0 != err) | ||
383 | return err; | ||
384 | } | ||
385 | |||
386 | return cx25821_set_control(dev, ctl, SRAM_CH06); | ||
387 | } | ||
388 | |||
389 | // exported stuff | ||
390 | static const struct v4l2_file_operations video_fops = { | ||
391 | .owner = THIS_MODULE, | ||
392 | .open = video_open, | ||
393 | .release = video_release, | ||
394 | .read = video_read, | ||
395 | .poll = video_poll, | ||
396 | .mmap = video_mmap, | ||
397 | .ioctl = video_ioctl2, | ||
398 | }; | ||
399 | |||
400 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
401 | .vidioc_querycap = vidioc_querycap, | ||
402 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
403 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
404 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
405 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
406 | .vidioc_reqbufs = vidioc_reqbufs, | ||
407 | .vidioc_querybuf = vidioc_querybuf, | ||
408 | .vidioc_qbuf = vidioc_qbuf, | ||
409 | .vidioc_dqbuf = vidioc_dqbuf, | ||
410 | #ifdef TUNER_FLAG | ||
411 | .vidioc_s_std = vidioc_s_std, | ||
412 | .vidioc_querystd = vidioc_querystd, | ||
413 | #endif | ||
414 | .vidioc_cropcap = vidioc_cropcap, | ||
415 | .vidioc_s_crop = vidioc_s_crop, | ||
416 | .vidioc_g_crop = vidioc_g_crop, | ||
417 | .vidioc_enum_input = vidioc_enum_input, | ||
418 | .vidioc_g_input = vidioc_g_input, | ||
419 | .vidioc_s_input = vidioc_s_input, | ||
420 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
421 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
422 | .vidioc_queryctrl = vidioc_queryctrl, | ||
423 | .vidioc_streamon = vidioc_streamon, | ||
424 | .vidioc_streamoff = vidioc_streamoff, | ||
425 | .vidioc_log_status = vidioc_log_status, | ||
426 | .vidioc_g_priority = vidioc_g_priority, | ||
427 | .vidioc_s_priority = vidioc_s_priority, | ||
428 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
429 | .vidiocgmbuf = vidiocgmbuf, | ||
430 | #endif | ||
431 | #ifdef TUNER_FLAG | ||
432 | .vidioc_g_tuner = vidioc_g_tuner, | ||
433 | .vidioc_s_tuner = vidioc_s_tuner, | ||
434 | .vidioc_g_frequency = vidioc_g_frequency, | ||
435 | .vidioc_s_frequency = vidioc_s_frequency, | ||
436 | #endif | ||
437 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
438 | .vidioc_g_register = vidioc_g_register, | ||
439 | .vidioc_s_register = vidioc_s_register, | ||
440 | #endif | ||
441 | }; | ||
442 | |||
443 | struct video_device cx25821_video_template6 = { | ||
444 | .name = "cx25821-video", | ||
445 | .fops = &video_fops, | ||
446 | .minor = -1, | ||
447 | .ioctl_ops = &video_ioctl_ops, | ||
448 | .tvnorms = CX25821_NORMS, | ||
449 | .current_norm = V4L2_STD_NTSC_M, | ||
450 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c new file mode 100644 index 000000000000..625c9b78a9cf --- /dev/null +++ b/drivers/staging/cx25821/cx25821-video7.c | |||
@@ -0,0 +1,449 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
45 | 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, | ||
50 | &dev->sram_channels[SRAM_CH07]); | ||
51 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
52 | buf->count = q->count++; | ||
53 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
54 | dprintk(2, | ||
55 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
56 | buf, buf->vb.i, buf->count, q->count); | ||
57 | } else { | ||
58 | prev = | ||
59 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
60 | if (prev->vb.width == buf->vb.width | ||
61 | && prev->vb.height == buf->vb.height | ||
62 | && prev->fmt == buf->fmt) { | ||
63 | list_add_tail(&buf->vb.queue, &q->active); | ||
64 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
65 | buf->count = q->count++; | ||
66 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
67 | |||
68 | /* 64 bit bits 63-32 */ | ||
69 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
70 | dprintk(2, | ||
71 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
72 | buf, buf->vb.i, buf->count); | ||
73 | |||
74 | } else { | ||
75 | list_add_tail(&buf->vb.queue, &q->queued); | ||
76 | buf->vb.state = VIDEOBUF_QUEUED; | ||
77 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
78 | buf->vb.i); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | if (list_empty(&q->active)) { | ||
83 | dprintk(2, "active queue empty!\n"); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
88 | .buf_setup = buffer_setup, | ||
89 | .buf_prepare = buffer_prepare, | ||
90 | .buf_queue = buffer_queue, | ||
91 | .buf_release = buffer_release, | ||
92 | }; | ||
93 | |||
94 | static int video_open(struct file *file) | ||
95 | { | ||
96 | int minor = video_devdata(file)->minor; | ||
97 | struct cx25821_dev *h, *dev = NULL; | ||
98 | struct cx25821_fh *fh; | ||
99 | struct list_head *list; | ||
100 | enum v4l2_buf_type type = 0; | ||
101 | u32 pix_format; | ||
102 | |||
103 | lock_kernel(); | ||
104 | list_for_each(list, &cx25821_devlist) { | ||
105 | h = list_entry(list, struct cx25821_dev, devlist); | ||
106 | |||
107 | if (h->video_dev[SRAM_CH07] | ||
108 | && h->video_dev[SRAM_CH07]->minor == minor) { | ||
109 | dev = h; | ||
110 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (NULL == dev) { | ||
115 | unlock_kernel(); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
120 | |||
121 | /* allocate + initialize per filehandle data */ | ||
122 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
123 | if (NULL == fh) { | ||
124 | unlock_kernel(); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | file->private_data = fh; | ||
128 | fh->dev = dev; | ||
129 | fh->type = type; | ||
130 | fh->width = 720; | ||
131 | |||
132 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
133 | fh->height = 576; | ||
134 | else | ||
135 | fh->height = 480; | ||
136 | |||
137 | dev->channel_opened = SRAM_CH07; | ||
138 | pix_format = | ||
139 | (dev->pixel_formats[dev->channel_opened] == | ||
140 | PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; | ||
141 | fh->fmt = format_by_fourcc(pix_format); | ||
142 | |||
143 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
144 | |||
145 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
146 | &dev->pci->dev, &dev->slock, | ||
147 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
148 | V4L2_FIELD_INTERLACED, | ||
149 | sizeof(struct cx25821_buffer), fh); | ||
150 | |||
151 | dprintk(1, "post videobuf_queue_init()\n"); | ||
152 | unlock_kernel(); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
158 | loff_t * ppos) | ||
159 | { | ||
160 | struct cx25821_fh *fh = file->private_data; | ||
161 | |||
162 | switch (fh->type) { | ||
163 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
164 | if (res_locked(fh->dev, RESOURCE_VIDEO7)) | ||
165 | return -EBUSY; | ||
166 | |||
167 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
168 | file->f_flags & O_NONBLOCK); | ||
169 | |||
170 | default: | ||
171 | BUG(); | ||
172 | return 0; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | static unsigned int video_poll(struct file *file, | ||
177 | struct poll_table_struct *wait) | ||
178 | { | ||
179 | struct cx25821_fh *fh = file->private_data; | ||
180 | struct cx25821_buffer *buf; | ||
181 | |||
182 | if (res_check(fh, RESOURCE_VIDEO7)) { | ||
183 | /* streaming capture */ | ||
184 | if (list_empty(&fh->vidq.stream)) | ||
185 | return POLLERR; | ||
186 | buf = list_entry(fh->vidq.stream.next, | ||
187 | struct cx25821_buffer, vb.stream); | ||
188 | } else { | ||
189 | /* read() capture */ | ||
190 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
191 | if (NULL == buf) | ||
192 | return POLLERR; | ||
193 | } | ||
194 | |||
195 | poll_wait(file, &buf->vb.done, wait); | ||
196 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | ||
197 | if (buf->vb.state == VIDEOBUF_DONE) { | ||
198 | struct cx25821_dev *dev = fh->dev; | ||
199 | |||
200 | if (dev && dev->use_cif_resolution[SRAM_CH07]) { | ||
201 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
202 | memcpy((char *)buf->vb.baddr, | ||
203 | (char *)buf->vb.baddr + (fh->width * 2), | ||
204 | (fh->width * 2)); | ||
205 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | return POLLIN | POLLRDNORM; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int video_release(struct file *file) | ||
216 | { | ||
217 | struct cx25821_fh *fh = file->private_data; | ||
218 | struct cx25821_dev *dev = fh->dev; | ||
219 | |||
220 | //stop the risc engine and fifo | ||
221 | cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ | ||
222 | |||
223 | /* stop video capture */ | ||
224 | if (res_check(fh, RESOURCE_VIDEO7)) { | ||
225 | videobuf_queue_cancel(&fh->vidq); | ||
226 | res_free(dev, fh, RESOURCE_VIDEO7); | ||
227 | } | ||
228 | |||
229 | if (fh->vidq.read_buf) { | ||
230 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
231 | kfree(fh->vidq.read_buf); | ||
232 | } | ||
233 | |||
234 | videobuf_mmap_free(&fh->vidq); | ||
235 | |||
236 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
237 | file->private_data = NULL; | ||
238 | kfree(fh); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
244 | { | ||
245 | struct cx25821_fh *fh = priv; | ||
246 | struct cx25821_dev *dev = fh->dev; | ||
247 | |||
248 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | if (unlikely(i != fh->type)) { | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) { | ||
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_VIDEO7); | ||
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 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
283 | 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 | 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 | fh->width = f->fmt.pix.width; | ||
308 | } | ||
309 | |||
310 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | ||
311 | fh->height = f->fmt.pix.height; | ||
312 | } | ||
313 | |||
314 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
315 | pix_format = PIXEL_FRMT_411; | ||
316 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
317 | pix_format = PIXEL_FRMT_422; | ||
318 | else | ||
319 | return -EINVAL; | ||
320 | |||
321 | cx25821_set_pixel_format(dev, SRAM_CH07, pix_format); | ||
322 | |||
323 | // check if cif resolution | ||
324 | if (fh->width == 320 || fh->width == 352) { | ||
325 | dev->use_cif_resolution[SRAM_CH07] = 1; | ||
326 | } else { | ||
327 | dev->use_cif_resolution[SRAM_CH07] = 0; | ||
328 | } | ||
329 | dev->cif_width[SRAM_CH07] = fh->width; | ||
330 | medusa_set_resolution(dev, fh->width, SRAM_CH07); | ||
331 | |||
332 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
333 | fh->height, fh->vidq.field); | ||
334 | cx25821_call_all(dev, video, s_fmt, f); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
340 | { | ||
341 | int ret_val = 0; | ||
342 | struct cx25821_fh *fh = priv; | ||
343 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
344 | |||
345 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
346 | |||
347 | p->sequence = dev->vidq[SRAM_CH07].count; | ||
348 | |||
349 | return ret_val; | ||
350 | } | ||
351 | static int vidioc_log_status(struct file *file, void *priv) | ||
352 | { | ||
353 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
354 | char name[32 + 2]; | ||
355 | |||
356 | struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; | ||
357 | u32 tmp = 0; | ||
358 | |||
359 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
360 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
361 | dev->name); | ||
362 | cx25821_call_all(dev, core, log_status); | ||
363 | |||
364 | tmp = cx_read(sram_ch->dma_ctl); | ||
365 | printk(KERN_INFO "Video input 7 is %s\n", | ||
366 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
367 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
368 | dev->name); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
373 | struct v4l2_control *ctl) | ||
374 | { | ||
375 | struct cx25821_fh *fh = priv; | ||
376 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
377 | int err; | ||
378 | |||
379 | if (fh) { | ||
380 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
381 | if (0 != err) | ||
382 | return err; | ||
383 | } | ||
384 | |||
385 | return cx25821_set_control(dev, ctl, SRAM_CH07); | ||
386 | } | ||
387 | |||
388 | // exported stuff | ||
389 | static const struct v4l2_file_operations video_fops = { | ||
390 | .owner = THIS_MODULE, | ||
391 | .open = video_open, | ||
392 | .release = video_release, | ||
393 | .read = video_read, | ||
394 | .poll = video_poll, | ||
395 | .mmap = video_mmap, | ||
396 | .ioctl = video_ioctl2, | ||
397 | }; | ||
398 | |||
399 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
400 | .vidioc_querycap = vidioc_querycap, | ||
401 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
402 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
403 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
404 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
405 | .vidioc_reqbufs = vidioc_reqbufs, | ||
406 | .vidioc_querybuf = vidioc_querybuf, | ||
407 | .vidioc_qbuf = vidioc_qbuf, | ||
408 | .vidioc_dqbuf = vidioc_dqbuf, | ||
409 | #ifdef TUNER_FLAG | ||
410 | .vidioc_s_std = vidioc_s_std, | ||
411 | .vidioc_querystd = vidioc_querystd, | ||
412 | #endif | ||
413 | .vidioc_cropcap = vidioc_cropcap, | ||
414 | .vidioc_s_crop = vidioc_s_crop, | ||
415 | .vidioc_g_crop = vidioc_g_crop, | ||
416 | .vidioc_enum_input = vidioc_enum_input, | ||
417 | .vidioc_g_input = vidioc_g_input, | ||
418 | .vidioc_s_input = vidioc_s_input, | ||
419 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
420 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
421 | .vidioc_queryctrl = vidioc_queryctrl, | ||
422 | .vidioc_streamon = vidioc_streamon, | ||
423 | .vidioc_streamoff = vidioc_streamoff, | ||
424 | .vidioc_log_status = vidioc_log_status, | ||
425 | .vidioc_g_priority = vidioc_g_priority, | ||
426 | .vidioc_s_priority = vidioc_s_priority, | ||
427 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
428 | .vidiocgmbuf = vidiocgmbuf, | ||
429 | #endif | ||
430 | #ifdef TUNER_FLAG | ||
431 | .vidioc_g_tuner = vidioc_g_tuner, | ||
432 | .vidioc_s_tuner = vidioc_s_tuner, | ||
433 | .vidioc_g_frequency = vidioc_g_frequency, | ||
434 | .vidioc_s_frequency = vidioc_s_frequency, | ||
435 | #endif | ||
436 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
437 | .vidioc_g_register = vidioc_g_register, | ||
438 | .vidioc_s_register = vidioc_s_register, | ||
439 | #endif | ||
440 | }; | ||
441 | |||
442 | struct video_device cx25821_video_template7 = { | ||
443 | .name = "cx25821-video", | ||
444 | .fops = &video_fops, | ||
445 | .minor = -1, | ||
446 | .ioctl_ops = &video_ioctl_ops, | ||
447 | .tvnorms = CX25821_NORMS, | ||
448 | .current_norm = V4L2_STD_NTSC_M, | ||
449 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c new file mode 100644 index 000000000000..2a312ce78c63 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-videoioctl.c | |||
@@ -0,0 +1,496 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[VIDEO_IOCTL_CH]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | u32 pix_format; | ||
103 | |||
104 | lock_kernel(); | ||
105 | list_for_each(list, &cx25821_devlist) { | ||
106 | h = list_entry(list, struct cx25821_dev, devlist); | ||
107 | |||
108 | if (h->ioctl_dev && h->ioctl_dev->minor == minor) { | ||
109 | dev = h; | ||
110 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (NULL == dev) { | ||
115 | unlock_kernel(); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
120 | |||
121 | /* allocate + initialize per filehandle data */ | ||
122 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
123 | if (NULL == fh) { | ||
124 | unlock_kernel(); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = VIDEO_IOCTL_CH; | ||
139 | pix_format = V4L2_PIX_FMT_YUYV; | ||
140 | fh->fmt = format_by_fourcc(pix_format); | ||
141 | |||
142 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
143 | |||
144 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
145 | &dev->pci->dev, &dev->slock, | ||
146 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
147 | V4L2_FIELD_INTERLACED, | ||
148 | sizeof(struct cx25821_buffer), fh); | ||
149 | |||
150 | dprintk(1, "post videobuf_queue_init()\n"); | ||
151 | unlock_kernel(); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | ||
157 | loff_t * ppos) | ||
158 | { | ||
159 | struct cx25821_fh *fh = file->private_data; | ||
160 | |||
161 | switch (fh->type) { | ||
162 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
163 | if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) | ||
164 | return -EBUSY; | ||
165 | |||
166 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
167 | file->f_flags & O_NONBLOCK); | ||
168 | |||
169 | default: | ||
170 | BUG(); | ||
171 | return 0; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static unsigned int video_poll(struct file *file, | ||
176 | struct poll_table_struct *wait) | ||
177 | { | ||
178 | struct cx25821_fh *fh = file->private_data; | ||
179 | struct cx25821_buffer *buf; | ||
180 | |||
181 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | ||
182 | /* streaming capture */ | ||
183 | if (list_empty(&fh->vidq.stream)) | ||
184 | return POLLERR; | ||
185 | buf = list_entry(fh->vidq.stream.next, | ||
186 | struct cx25821_buffer, vb.stream); | ||
187 | } else { | ||
188 | /* read() capture */ | ||
189 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
190 | if (NULL == buf) | ||
191 | return POLLERR; | ||
192 | } | ||
193 | |||
194 | poll_wait(file, &buf->vb.done, wait); | ||
195 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
196 | return POLLIN | POLLRDNORM; | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int video_release(struct file *file) | ||
202 | { | ||
203 | struct cx25821_fh *fh = file->private_data; | ||
204 | struct cx25821_dev *dev = fh->dev; | ||
205 | |||
206 | /* stop video capture */ | ||
207 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | ||
208 | videobuf_queue_cancel(&fh->vidq); | ||
209 | res_free(dev, fh, RESOURCE_VIDEO_IOCTL); | ||
210 | } | ||
211 | |||
212 | if (fh->vidq.read_buf) { | ||
213 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
214 | kfree(fh->vidq.read_buf); | ||
215 | } | ||
216 | |||
217 | videobuf_mmap_free(&fh->vidq); | ||
218 | |||
219 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
220 | |||
221 | file->private_data = NULL; | ||
222 | kfree(fh); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
228 | { | ||
229 | struct cx25821_fh *fh = priv; | ||
230 | struct cx25821_dev *dev = fh->dev; | ||
231 | |||
232 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | if (unlikely(i != fh->type)) { | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { | ||
241 | return -EBUSY; | ||
242 | } | ||
243 | |||
244 | return videobuf_streamon(get_queue(fh)); | ||
245 | } | ||
246 | |||
247 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
248 | { | ||
249 | struct cx25821_fh *fh = priv; | ||
250 | struct cx25821_dev *dev = fh->dev; | ||
251 | int err, res; | ||
252 | |||
253 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
254 | return -EINVAL; | ||
255 | if (i != fh->type) | ||
256 | return -EINVAL; | ||
257 | |||
258 | res = get_resource(fh, RESOURCE_VIDEO_IOCTL); | ||
259 | err = videobuf_streamoff(get_queue(fh)); | ||
260 | if (err < 0) | ||
261 | return err; | ||
262 | res_free(dev, fh, res); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
267 | struct v4l2_format *f) | ||
268 | { | ||
269 | struct cx25821_fh *fh = priv; | ||
270 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
271 | int err; | ||
272 | |||
273 | if (fh) { | ||
274 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
275 | if (0 != err) | ||
276 | return err; | ||
277 | } | ||
278 | |||
279 | dprintk(2, "%s()\n", __func__); | ||
280 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
281 | |||
282 | if (0 != err) | ||
283 | return err; | ||
284 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
285 | fh->width = f->fmt.pix.width; | ||
286 | fh->height = f->fmt.pix.height; | ||
287 | fh->vidq.field = f->fmt.pix.field; | ||
288 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
289 | fh->height, fh->vidq.field); | ||
290 | cx25821_call_all(dev, video, s_fmt, f); | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
295 | { | ||
296 | struct cx25821_fh *fh = priv; | ||
297 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
298 | } | ||
299 | |||
300 | static long video_ioctl_set(struct file *file, unsigned int cmd, | ||
301 | unsigned long arg) | ||
302 | { | ||
303 | struct cx25821_fh *fh = file->private_data; | ||
304 | struct cx25821_dev *dev = fh->dev; | ||
305 | struct downstream_user_struct *data_from_user; | ||
306 | int command; | ||
307 | int width = 720; | ||
308 | int selected_channel = 0, pix_format = 0, i = 0; | ||
309 | int cif_enable = 0, cif_width = 0; | ||
310 | u32 value = 0; | ||
311 | |||
312 | data_from_user = (struct downstream_user_struct *)arg; | ||
313 | |||
314 | if (!data_from_user) { | ||
315 | printk("cx25821 in %s(): User data is INVALID. Returning.\n", | ||
316 | __func__); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | command = data_from_user->command; | ||
321 | |||
322 | if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT | ||
323 | && command != ENABLE_CIF_RESOLUTION && command != REG_READ | ||
324 | && command != REG_WRITE && command != MEDUSA_READ | ||
325 | && command != MEDUSA_WRITE) { | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | switch (command) { | ||
330 | case SET_VIDEO_STD: | ||
331 | dev->tvnorm = | ||
332 | !strcmp(data_from_user->vid_stdname, | ||
333 | "PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
334 | medusa_set_videostandard(dev); | ||
335 | break; | ||
336 | |||
337 | case SET_PIXEL_FORMAT: | ||
338 | selected_channel = data_from_user->decoder_select; | ||
339 | pix_format = data_from_user->pixel_format; | ||
340 | |||
341 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | ||
342 | selected_channel -= 4; | ||
343 | selected_channel = selected_channel % 8; | ||
344 | } | ||
345 | |||
346 | if (selected_channel >= 0) | ||
347 | cx25821_set_pixel_format(dev, selected_channel, | ||
348 | pix_format); | ||
349 | |||
350 | break; | ||
351 | |||
352 | case ENABLE_CIF_RESOLUTION: | ||
353 | selected_channel = data_from_user->decoder_select; | ||
354 | cif_enable = data_from_user->cif_resolution_enable; | ||
355 | cif_width = data_from_user->cif_width; | ||
356 | |||
357 | if (cif_enable) { | ||
358 | if (dev->tvnorm & V4L2_STD_PAL_BG | ||
359 | || dev->tvnorm & V4L2_STD_PAL_DK) | ||
360 | width = 352; | ||
361 | else | ||
362 | width = (cif_width == 320 | ||
363 | || cif_width == 352) ? cif_width : 320; | ||
364 | } | ||
365 | |||
366 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | ||
367 | selected_channel -= 4; | ||
368 | selected_channel = selected_channel % 8; | ||
369 | } | ||
370 | |||
371 | if (selected_channel <= 7 && selected_channel >= 0) { | ||
372 | dev->use_cif_resolution[selected_channel] = cif_enable; | ||
373 | dev->cif_width[selected_channel] = width; | ||
374 | } else { | ||
375 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
376 | dev->use_cif_resolution[i] = cif_enable; | ||
377 | dev->cif_width[i] = width; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | medusa_set_resolution(dev, width, selected_channel); | ||
382 | break; | ||
383 | case REG_READ: | ||
384 | data_from_user->reg_data = cx_read(data_from_user->reg_address); | ||
385 | break; | ||
386 | case REG_WRITE: | ||
387 | cx_write(data_from_user->reg_address, data_from_user->reg_data); | ||
388 | break; | ||
389 | case MEDUSA_READ: | ||
390 | value = | ||
391 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
392 | (u16) data_from_user->reg_address, | ||
393 | &data_from_user->reg_data); | ||
394 | break; | ||
395 | case MEDUSA_WRITE: | ||
396 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
397 | (u16) data_from_user->reg_address, | ||
398 | data_from_user->reg_data); | ||
399 | break; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int vidioc_log_status(struct file *file, void *priv) | ||
406 | { | ||
407 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
408 | char name[32 + 2]; | ||
409 | |||
410 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
411 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
412 | dev->name); | ||
413 | cx25821_call_all(dev, core, log_status); | ||
414 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
415 | dev->name); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
420 | struct v4l2_control *ctl) | ||
421 | { | ||
422 | struct cx25821_fh *fh = priv; | ||
423 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
424 | int err; | ||
425 | |||
426 | if (fh) { | ||
427 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
428 | if (0 != err) | ||
429 | return err; | ||
430 | } | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | // exported stuff | ||
436 | static const struct v4l2_file_operations video_fops = { | ||
437 | .owner = THIS_MODULE, | ||
438 | .open = video_open, | ||
439 | .release = video_release, | ||
440 | .read = video_read, | ||
441 | .poll = video_poll, | ||
442 | .mmap = video_mmap, | ||
443 | .ioctl = video_ioctl_set, | ||
444 | }; | ||
445 | |||
446 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
447 | .vidioc_querycap = vidioc_querycap, | ||
448 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
449 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
450 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
451 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
452 | .vidioc_reqbufs = vidioc_reqbufs, | ||
453 | .vidioc_querybuf = vidioc_querybuf, | ||
454 | .vidioc_qbuf = vidioc_qbuf, | ||
455 | .vidioc_dqbuf = vidioc_dqbuf, | ||
456 | #ifdef TUNER_FLAG | ||
457 | .vidioc_s_std = vidioc_s_std, | ||
458 | .vidioc_querystd = vidioc_querystd, | ||
459 | #endif | ||
460 | .vidioc_cropcap = vidioc_cropcap, | ||
461 | .vidioc_s_crop = vidioc_s_crop, | ||
462 | .vidioc_g_crop = vidioc_g_crop, | ||
463 | .vidioc_enum_input = vidioc_enum_input, | ||
464 | .vidioc_g_input = vidioc_g_input, | ||
465 | .vidioc_s_input = vidioc_s_input, | ||
466 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
467 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
468 | .vidioc_queryctrl = vidioc_queryctrl, | ||
469 | .vidioc_streamon = vidioc_streamon, | ||
470 | .vidioc_streamoff = vidioc_streamoff, | ||
471 | .vidioc_log_status = vidioc_log_status, | ||
472 | .vidioc_g_priority = vidioc_g_priority, | ||
473 | .vidioc_s_priority = vidioc_s_priority, | ||
474 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
475 | .vidiocgmbuf = vidiocgmbuf, | ||
476 | #endif | ||
477 | #ifdef TUNER_FLAG | ||
478 | .vidioc_g_tuner = vidioc_g_tuner, | ||
479 | .vidioc_s_tuner = vidioc_s_tuner, | ||
480 | .vidioc_g_frequency = vidioc_g_frequency, | ||
481 | .vidioc_s_frequency = vidioc_s_frequency, | ||
482 | #endif | ||
483 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
484 | .vidioc_g_register = vidioc_g_register, | ||
485 | .vidioc_s_register = vidioc_s_register, | ||
486 | #endif | ||
487 | }; | ||
488 | |||
489 | struct video_device cx25821_videoioctl_template = { | ||
490 | .name = "cx25821-videoioctl", | ||
491 | .fops = &video_fops, | ||
492 | .minor = -1, | ||
493 | .ioctl_ops = &video_ioctl_ops, | ||
494 | .tvnorms = CX25821_NORMS, | ||
495 | .current_norm = V4L2_STD_NTSC_M, | ||
496 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c new file mode 100644 index 000000000000..77b63b060405 --- /dev/null +++ b/drivers/staging/cx25821/cx25821-vidups10.c | |||
@@ -0,0 +1,435 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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 | /* 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH10]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | |||
103 | lock_kernel(); | ||
104 | list_for_each(list, &cx25821_devlist) { | ||
105 | h = list_entry(list, struct cx25821_dev, devlist); | ||
106 | |||
107 | if (h->video_dev[SRAM_CH10] | ||
108 | && h->video_dev[SRAM_CH10]->minor == minor) { | ||
109 | dev = h; | ||
110 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (NULL == dev) { | ||
115 | unlock_kernel(); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
120 | |||
121 | /* allocate + initialize per filehandle data */ | ||
122 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
123 | if (NULL == fh) { | ||
124 | unlock_kernel(); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = 9; | ||
139 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
140 | |||
141 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
142 | |||
143 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
144 | &dev->pci->dev, &dev->slock, | ||
145 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
146 | V4L2_FIELD_INTERLACED, | ||
147 | sizeof(struct cx25821_buffer), 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, | ||
156 | loff_t * ppos) | ||
157 | { | ||
158 | struct cx25821_fh *fh = file->private_data; | ||
159 | |||
160 | switch (fh->type) { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO10)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
166 | file->f_flags & O_NONBLOCK); | ||
167 | |||
168 | default: | ||
169 | BUG(); | ||
170 | return 0; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static unsigned int video_poll(struct file *file, | ||
175 | struct poll_table_struct *wait) | ||
176 | { | ||
177 | struct cx25821_fh *fh = file->private_data; | ||
178 | struct cx25821_buffer *buf; | ||
179 | |||
180 | if (res_check(fh, RESOURCE_VIDEO10)) { | ||
181 | /* streaming capture */ | ||
182 | if (list_empty(&fh->vidq.stream)) | ||
183 | return POLLERR; | ||
184 | buf = list_entry(fh->vidq.stream.next, | ||
185 | struct cx25821_buffer, vb.stream); | ||
186 | } else { | ||
187 | /* read() capture */ | ||
188 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
189 | if (NULL == buf) | ||
190 | return POLLERR; | ||
191 | } | ||
192 | |||
193 | poll_wait(file, &buf->vb.done, wait); | ||
194 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
195 | return POLLIN | POLLRDNORM; | ||
196 | return 0; | ||
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 the risc engine and fifo | ||
205 | //cx_write(channel10->dma_ctl, 0); | ||
206 | |||
207 | /* stop video capture */ | ||
208 | if (res_check(fh, RESOURCE_VIDEO10)) { | ||
209 | videobuf_queue_cancel(&fh->vidq); | ||
210 | res_free(dev, fh, RESOURCE_VIDEO10); | ||
211 | } | ||
212 | |||
213 | if (fh->vidq.read_buf) { | ||
214 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
215 | kfree(fh->vidq.read_buf); | ||
216 | } | ||
217 | |||
218 | videobuf_mmap_free(&fh->vidq); | ||
219 | |||
220 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
221 | |||
222 | file->private_data = NULL; | ||
223 | kfree(fh); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
229 | { | ||
230 | struct cx25821_fh *fh = priv; | ||
231 | struct cx25821_dev *dev = fh->dev; | ||
232 | |||
233 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | |||
237 | if (unlikely(i != fh->type)) { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) { | ||
242 | return -EBUSY; | ||
243 | } | ||
244 | |||
245 | return videobuf_streamon(get_queue(fh)); | ||
246 | } | ||
247 | |||
248 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
249 | { | ||
250 | struct cx25821_fh *fh = priv; | ||
251 | struct cx25821_dev *dev = fh->dev; | ||
252 | int err, res; | ||
253 | |||
254 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
255 | return -EINVAL; | ||
256 | if (i != fh->type) | ||
257 | return -EINVAL; | ||
258 | |||
259 | res = get_resource(fh, RESOURCE_VIDEO10); | ||
260 | err = videobuf_streamoff(get_queue(fh)); | ||
261 | if (err < 0) | ||
262 | return err; | ||
263 | res_free(dev, fh, res); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static long video_ioctl_upstream10(struct file *file, unsigned int cmd, | ||
268 | unsigned long arg) | ||
269 | { | ||
270 | struct cx25821_fh *fh = file->private_data; | ||
271 | struct cx25821_dev *dev = fh->dev; | ||
272 | int command = 0; | ||
273 | struct upstream_user_struct *data_from_user; | ||
274 | |||
275 | data_from_user = (struct upstream_user_struct *)arg; | ||
276 | |||
277 | if (!data_from_user) { | ||
278 | printk | ||
279 | ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", | ||
280 | __func__); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | command = data_from_user->command; | ||
285 | |||
286 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | dev->input_filename_ch2 = data_from_user->input_filename; | ||
291 | dev->input_audiofilename = data_from_user->input_filename; | ||
292 | dev->vid_stdname_ch2 = data_from_user->vid_stdname; | ||
293 | dev->pixel_format_ch2 = data_from_user->pixel_format; | ||
294 | dev->channel_select_ch2 = data_from_user->channel_select; | ||
295 | dev->command_ch2 = data_from_user->command; | ||
296 | |||
297 | switch (command) { | ||
298 | case UPSTREAM_START_VIDEO: | ||
299 | cx25821_start_upstream_video_ch2(dev, data_from_user); | ||
300 | break; | ||
301 | |||
302 | case UPSTREAM_STOP_VIDEO: | ||
303 | cx25821_stop_upstream_video_ch2(dev); | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
311 | struct v4l2_format *f) | ||
312 | { | ||
313 | struct cx25821_fh *fh = priv; | ||
314 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
315 | int err; | ||
316 | |||
317 | if (fh) { | ||
318 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
319 | if (0 != err) | ||
320 | return err; | ||
321 | } | ||
322 | |||
323 | dprintk(2, "%s()\n", __func__); | ||
324 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
325 | |||
326 | if (0 != err) | ||
327 | return err; | ||
328 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
329 | fh->width = f->fmt.pix.width; | ||
330 | fh->height = f->fmt.pix.height; | ||
331 | fh->vidq.field = f->fmt.pix.field; | ||
332 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
333 | fh->height, fh->vidq.field); | ||
334 | cx25821_call_all(dev, video, s_fmt, f); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
339 | { | ||
340 | struct cx25821_fh *fh = priv; | ||
341 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
342 | } | ||
343 | |||
344 | static int vidioc_log_status(struct file *file, void *priv) | ||
345 | { | ||
346 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
347 | char name[32 + 2]; | ||
348 | |||
349 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
350 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
351 | dev->name); | ||
352 | cx25821_call_all(dev, core, log_status); | ||
353 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
354 | dev->name); | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
359 | struct v4l2_control *ctl) | ||
360 | { | ||
361 | struct cx25821_fh *fh = priv; | ||
362 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
363 | int err; | ||
364 | |||
365 | if (fh) { | ||
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
367 | if (0 != err) | ||
368 | return err; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | //exported stuff | ||
375 | static const struct v4l2_file_operations video_fops = { | ||
376 | .owner = THIS_MODULE, | ||
377 | .open = video_open, | ||
378 | .release = video_release, | ||
379 | .read = video_read, | ||
380 | .poll = video_poll, | ||
381 | .mmap = video_mmap, | ||
382 | .ioctl = video_ioctl_upstream10, | ||
383 | }; | ||
384 | |||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
386 | .vidioc_querycap = vidioc_querycap, | ||
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
391 | .vidioc_reqbufs = vidioc_reqbufs, | ||
392 | .vidioc_querybuf = vidioc_querybuf, | ||
393 | .vidioc_qbuf = vidioc_qbuf, | ||
394 | .vidioc_dqbuf = vidioc_dqbuf, | ||
395 | #ifdef TUNER_FLAG | ||
396 | .vidioc_s_std = vidioc_s_std, | ||
397 | .vidioc_querystd = vidioc_querystd, | ||
398 | #endif | ||
399 | .vidioc_cropcap = vidioc_cropcap, | ||
400 | .vidioc_s_crop = vidioc_s_crop, | ||
401 | .vidioc_g_crop = vidioc_g_crop, | ||
402 | .vidioc_enum_input = vidioc_enum_input, | ||
403 | .vidioc_g_input = vidioc_g_input, | ||
404 | .vidioc_s_input = vidioc_s_input, | ||
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
407 | .vidioc_queryctrl = vidioc_queryctrl, | ||
408 | .vidioc_streamon = vidioc_streamon, | ||
409 | .vidioc_streamoff = vidioc_streamoff, | ||
410 | .vidioc_log_status = vidioc_log_status, | ||
411 | .vidioc_g_priority = vidioc_g_priority, | ||
412 | .vidioc_s_priority = vidioc_s_priority, | ||
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
414 | .vidiocgmbuf = vidiocgmbuf, | ||
415 | #endif | ||
416 | #ifdef TUNER_FLAG | ||
417 | .vidioc_g_tuner = vidioc_g_tuner, | ||
418 | .vidioc_s_tuner = vidioc_s_tuner, | ||
419 | .vidioc_g_frequency = vidioc_g_frequency, | ||
420 | .vidioc_s_frequency = vidioc_s_frequency, | ||
421 | #endif | ||
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
423 | .vidioc_g_register = vidioc_g_register, | ||
424 | .vidioc_s_register = vidioc_s_register, | ||
425 | #endif | ||
426 | }; | ||
427 | |||
428 | struct video_device cx25821_video_template10 = { | ||
429 | .name = "cx25821-upstream10", | ||
430 | .fops = &video_fops, | ||
431 | .minor = -1, | ||
432 | .ioctl_ops = &video_ioctl_ops, | ||
433 | .tvnorms = CX25821_NORMS, | ||
434 | .current_norm = V4L2_STD_NTSC_M, | ||
435 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c new file mode 100644 index 000000000000..75c8c1eed2da --- /dev/null +++ b/drivers/staging/cx25821/cx25821-vidups9.c | |||
@@ -0,0 +1,433 @@ | |||
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 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
27 | { | ||
28 | struct cx25821_buffer *buf = | ||
29 | 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, | ||
46 | 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, | ||
51 | &dev->sram_channels[SRAM_CH09]); | ||
52 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
53 | buf->count = q->count++; | ||
54 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
55 | dprintk(2, | ||
56 | "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | ||
57 | buf, buf->vb.i, buf->count, q->count); | ||
58 | } else { | ||
59 | prev = | ||
60 | list_entry(q->active.prev, struct cx25821_buffer, vb.queue); | ||
61 | if (prev->vb.width == buf->vb.width | ||
62 | && prev->vb.height == buf->vb.height | ||
63 | && prev->fmt == buf->fmt) { | ||
64 | list_add_tail(&buf->vb.queue, &q->active); | ||
65 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
66 | buf->count = q->count++; | ||
67 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
68 | |||
69 | /* 64 bit bits 63-32 */ | ||
70 | prev->risc.jmp[2] = cpu_to_le32(0); | ||
71 | dprintk(2, | ||
72 | "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | ||
73 | buf, buf->vb.i, buf->count); | ||
74 | |||
75 | } else { | ||
76 | list_add_tail(&buf->vb.queue, &q->queued); | ||
77 | buf->vb.state = VIDEOBUF_QUEUED; | ||
78 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | ||
79 | buf->vb.i); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (list_empty(&q->active)) { | ||
84 | dprintk(2, "active queue empty!\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | ||
89 | .buf_setup = buffer_setup, | ||
90 | .buf_prepare = buffer_prepare, | ||
91 | .buf_queue = buffer_queue, | ||
92 | .buf_release = buffer_release, | ||
93 | }; | ||
94 | |||
95 | static int video_open(struct file *file) | ||
96 | { | ||
97 | int minor = video_devdata(file)->minor; | ||
98 | struct cx25821_dev *h, *dev = NULL; | ||
99 | struct cx25821_fh *fh; | ||
100 | struct list_head *list; | ||
101 | enum v4l2_buf_type type = 0; | ||
102 | |||
103 | lock_kernel(); | ||
104 | list_for_each(list, &cx25821_devlist) { | ||
105 | h = list_entry(list, struct cx25821_dev, devlist); | ||
106 | |||
107 | if (h->video_dev[SRAM_CH09] | ||
108 | && h->video_dev[SRAM_CH09]->minor == minor) { | ||
109 | dev = h; | ||
110 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (NULL == dev) { | ||
115 | unlock_kernel(); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); | ||
120 | |||
121 | /* allocate + initialize per filehandle data */ | ||
122 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
123 | if (NULL == fh) { | ||
124 | unlock_kernel(); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | file->private_data = fh; | ||
129 | fh->dev = dev; | ||
130 | fh->type = type; | ||
131 | fh->width = 720; | ||
132 | |||
133 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
134 | fh->height = 576; | ||
135 | else | ||
136 | fh->height = 480; | ||
137 | |||
138 | dev->channel_opened = 8; | ||
139 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
140 | |||
141 | v4l2_prio_open(&dev->prio, &fh->prio); | ||
142 | |||
143 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | ||
144 | &dev->pci->dev, &dev->slock, | ||
145 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
146 | V4L2_FIELD_INTERLACED, | ||
147 | sizeof(struct cx25821_buffer), 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, | ||
156 | loff_t * ppos) | ||
157 | { | ||
158 | struct cx25821_fh *fh = file->private_data; | ||
159 | |||
160 | switch (fh->type) { | ||
161 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
162 | if (res_locked(fh->dev, RESOURCE_VIDEO9)) | ||
163 | return -EBUSY; | ||
164 | |||
165 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
166 | file->f_flags & O_NONBLOCK); | ||
167 | |||
168 | default: | ||
169 | BUG(); | ||
170 | return 0; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static unsigned int video_poll(struct file *file, | ||
175 | struct poll_table_struct *wait) | ||
176 | { | ||
177 | struct cx25821_fh *fh = file->private_data; | ||
178 | struct cx25821_buffer *buf; | ||
179 | |||
180 | if (res_check(fh, RESOURCE_VIDEO9)) { | ||
181 | /* streaming capture */ | ||
182 | if (list_empty(&fh->vidq.stream)) | ||
183 | return POLLERR; | ||
184 | buf = list_entry(fh->vidq.stream.next, | ||
185 | struct cx25821_buffer, vb.stream); | ||
186 | } else { | ||
187 | /* read() capture */ | ||
188 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | ||
189 | if (NULL == buf) | ||
190 | return POLLERR; | ||
191 | } | ||
192 | |||
193 | poll_wait(file, &buf->vb.done, wait); | ||
194 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) | ||
195 | return POLLIN | POLLRDNORM; | ||
196 | return 0; | ||
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 the risc engine and fifo | ||
205 | //cx_write(channel9->dma_ctl, 0); | ||
206 | |||
207 | /* stop video capture */ | ||
208 | if (res_check(fh, RESOURCE_VIDEO9)) { | ||
209 | videobuf_queue_cancel(&fh->vidq); | ||
210 | res_free(dev, fh, RESOURCE_VIDEO9); | ||
211 | } | ||
212 | |||
213 | if (fh->vidq.read_buf) { | ||
214 | buffer_release(&fh->vidq, fh->vidq.read_buf); | ||
215 | kfree(fh->vidq.read_buf); | ||
216 | } | ||
217 | |||
218 | videobuf_mmap_free(&fh->vidq); | ||
219 | |||
220 | v4l2_prio_close(&dev->prio, &fh->prio); | ||
221 | |||
222 | file->private_data = NULL; | ||
223 | kfree(fh); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
229 | { | ||
230 | struct cx25821_fh *fh = priv; | ||
231 | struct cx25821_dev *dev = fh->dev; | ||
232 | |||
233 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | |||
237 | if (unlikely(i != fh->type)) { | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) { | ||
242 | return -EBUSY; | ||
243 | } | ||
244 | |||
245 | return videobuf_streamon(get_queue(fh)); | ||
246 | } | ||
247 | |||
248 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
249 | { | ||
250 | struct cx25821_fh *fh = priv; | ||
251 | struct cx25821_dev *dev = fh->dev; | ||
252 | int err, res; | ||
253 | |||
254 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
255 | return -EINVAL; | ||
256 | if (i != fh->type) | ||
257 | return -EINVAL; | ||
258 | |||
259 | res = get_resource(fh, RESOURCE_VIDEO9); | ||
260 | err = videobuf_streamoff(get_queue(fh)); | ||
261 | if (err < 0) | ||
262 | return err; | ||
263 | res_free(dev, fh, res); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static long video_ioctl_upstream9(struct file *file, unsigned int cmd, | ||
268 | unsigned long arg) | ||
269 | { | ||
270 | struct cx25821_fh *fh = file->private_data; | ||
271 | struct cx25821_dev *dev = fh->dev; | ||
272 | int command = 0; | ||
273 | struct upstream_user_struct *data_from_user; | ||
274 | |||
275 | data_from_user = (struct upstream_user_struct *)arg; | ||
276 | |||
277 | if (!data_from_user) { | ||
278 | printk | ||
279 | ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", | ||
280 | __func__); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | command = data_from_user->command; | ||
285 | |||
286 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | dev->input_filename = data_from_user->input_filename; | ||
291 | dev->input_audiofilename = data_from_user->input_filename; | ||
292 | dev->vid_stdname = data_from_user->vid_stdname; | ||
293 | dev->pixel_format = data_from_user->pixel_format; | ||
294 | dev->channel_select = data_from_user->channel_select; | ||
295 | dev->command = data_from_user->command; | ||
296 | |||
297 | switch (command) { | ||
298 | case UPSTREAM_START_VIDEO: | ||
299 | cx25821_start_upstream_video_ch1(dev, data_from_user); | ||
300 | break; | ||
301 | |||
302 | case UPSTREAM_STOP_VIDEO: | ||
303 | cx25821_stop_upstream_video_ch1(dev); | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
311 | struct v4l2_format *f) | ||
312 | { | ||
313 | struct cx25821_fh *fh = priv; | ||
314 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
315 | int err; | ||
316 | |||
317 | if (fh) { | ||
318 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
319 | if (0 != err) | ||
320 | return err; | ||
321 | } | ||
322 | |||
323 | dprintk(2, "%s()\n", __func__); | ||
324 | err = vidioc_try_fmt_vid_cap(file, priv, f); | ||
325 | |||
326 | if (0 != err) | ||
327 | return err; | ||
328 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
329 | fh->width = f->fmt.pix.width; | ||
330 | fh->height = f->fmt.pix.height; | ||
331 | fh->vidq.field = f->fmt.pix.field; | ||
332 | dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, | ||
333 | fh->height, fh->vidq.field); | ||
334 | cx25821_call_all(dev, video, s_fmt, f); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
339 | { | ||
340 | struct cx25821_fh *fh = priv; | ||
341 | return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | ||
342 | } | ||
343 | static int vidioc_log_status(struct file *file, void *priv) | ||
344 | { | ||
345 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
346 | char name[32 + 2]; | ||
347 | |||
348 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
349 | printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", | ||
350 | dev->name); | ||
351 | cx25821_call_all(dev, core, log_status); | ||
352 | printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", | ||
353 | dev->name); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
358 | struct v4l2_control *ctl) | ||
359 | { | ||
360 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
361 | struct cx25821_fh *fh = priv; | ||
362 | int err; | ||
363 | if (fh) { | ||
364 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
365 | if (0 != err) | ||
366 | return err; | ||
367 | } | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | // exported stuff | ||
373 | static const struct v4l2_file_operations video_fops = { | ||
374 | .owner = THIS_MODULE, | ||
375 | .open = video_open, | ||
376 | .release = video_release, | ||
377 | .read = video_read, | ||
378 | .poll = video_poll, | ||
379 | .mmap = video_mmap, | ||
380 | .ioctl = video_ioctl_upstream9, | ||
381 | }; | ||
382 | |||
383 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
384 | .vidioc_querycap = vidioc_querycap, | ||
385 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
386 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
387 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
388 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
389 | .vidioc_reqbufs = vidioc_reqbufs, | ||
390 | .vidioc_querybuf = vidioc_querybuf, | ||
391 | .vidioc_qbuf = vidioc_qbuf, | ||
392 | .vidioc_dqbuf = vidioc_dqbuf, | ||
393 | #ifdef TUNER_FLAG | ||
394 | .vidioc_s_std = vidioc_s_std, | ||
395 | .vidioc_querystd = vidioc_querystd, | ||
396 | #endif | ||
397 | .vidioc_cropcap = vidioc_cropcap, | ||
398 | .vidioc_s_crop = vidioc_s_crop, | ||
399 | .vidioc_g_crop = vidioc_g_crop, | ||
400 | .vidioc_enum_input = vidioc_enum_input, | ||
401 | .vidioc_g_input = vidioc_g_input, | ||
402 | .vidioc_s_input = vidioc_s_input, | ||
403 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
404 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
405 | .vidioc_queryctrl = vidioc_queryctrl, | ||
406 | .vidioc_streamon = vidioc_streamon, | ||
407 | .vidioc_streamoff = vidioc_streamoff, | ||
408 | .vidioc_log_status = vidioc_log_status, | ||
409 | .vidioc_g_priority = vidioc_g_priority, | ||
410 | .vidioc_s_priority = vidioc_s_priority, | ||
411 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
412 | .vidiocgmbuf = vidiocgmbuf, | ||
413 | #endif | ||
414 | #ifdef TUNER_FLAG | ||
415 | .vidioc_g_tuner = vidioc_g_tuner, | ||
416 | .vidioc_s_tuner = vidioc_s_tuner, | ||
417 | .vidioc_g_frequency = vidioc_g_frequency, | ||
418 | .vidioc_s_frequency = vidioc_s_frequency, | ||
419 | #endif | ||
420 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
421 | .vidioc_g_register = vidioc_g_register, | ||
422 | .vidioc_s_register = vidioc_s_register, | ||
423 | #endif | ||
424 | }; | ||
425 | |||
426 | struct video_device cx25821_video_template9 = { | ||
427 | .name = "cx25821-upstream9", | ||
428 | .fops = &video_fops, | ||
429 | .minor = -1, | ||
430 | .ioctl_ops = &video_ioctl_ops, | ||
431 | .tvnorms = CX25821_NORMS, | ||
432 | .current_norm = V4L2_STD_NTSC_M, | ||
433 | }; | ||
diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h new file mode 100644 index 000000000000..cf2286d83b6a --- /dev/null +++ b/drivers/staging/cx25821/cx25821.h | |||
@@ -0,0 +1,602 @@ | |||
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_H_ | ||
25 | #define CX25821_H_ | ||
26 | |||
27 | #include <linux/pci.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-algo-bit.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/kdev_t.h> | ||
34 | #include <linux/smp_lock.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 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ | ||
88 | |||
89 | #define UNKNOWN_BOARD 0 | ||
90 | #define CX25821_BOARD 1 | ||
91 | |||
92 | /* Currently supported by the driver */ | ||
93 | #define CX25821_NORMS (\ | ||
94 | V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ | ||
95 | V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ | ||
96 | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \ | ||
97 | V4L2_STD_PAL_Nc ) | ||
98 | |||
99 | #define CX25821_BOARD_CONEXANT_ATHENA10 1 | ||
100 | #define MAX_VID_CHANNEL_NUM 12 | ||
101 | #define VID_CHANNEL_NUM 8 | ||
102 | |||
103 | struct cx25821_fmt { | ||
104 | char *name; | ||
105 | u32 fourcc; /* v4l2 format id */ | ||
106 | int depth; | ||
107 | int flags; | ||
108 | u32 cxformat; | ||
109 | }; | ||
110 | |||
111 | struct cx25821_ctrl { | ||
112 | struct v4l2_queryctrl v; | ||
113 | u32 off; | ||
114 | u32 reg; | ||
115 | u32 mask; | ||
116 | u32 shift; | ||
117 | }; | ||
118 | |||
119 | struct cx25821_tvnorm { | ||
120 | char *name; | ||
121 | v4l2_std_id id; | ||
122 | u32 cxiformat; | ||
123 | u32 cxoformat; | ||
124 | }; | ||
125 | |||
126 | struct cx25821_fh { | ||
127 | struct cx25821_dev *dev; | ||
128 | enum v4l2_buf_type type; | ||
129 | int radio; | ||
130 | u32 resources; | ||
131 | |||
132 | enum v4l2_priority prio; | ||
133 | |||
134 | /* video overlay */ | ||
135 | struct v4l2_window win; | ||
136 | struct v4l2_clip *clips; | ||
137 | unsigned int nclips; | ||
138 | |||
139 | /* video capture */ | ||
140 | struct cx25821_fmt *fmt; | ||
141 | unsigned int width, height; | ||
142 | |||
143 | /* vbi capture */ | ||
144 | struct videobuf_queue vidq; | ||
145 | struct videobuf_queue vbiq; | ||
146 | |||
147 | /* H264 Encoder specifics ONLY */ | ||
148 | struct videobuf_queue mpegq; | ||
149 | atomic_t v4l_reading; | ||
150 | }; | ||
151 | |||
152 | enum cx25821_itype { | ||
153 | CX25821_VMUX_COMPOSITE = 1, | ||
154 | CX25821_VMUX_SVIDEO, | ||
155 | CX25821_VMUX_DEBUG, | ||
156 | CX25821_RADIO, | ||
157 | }; | ||
158 | |||
159 | enum cx25821_src_sel_type { | ||
160 | CX25821_SRC_SEL_EXT_656_VIDEO = 0, | ||
161 | CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO | ||
162 | }; | ||
163 | |||
164 | /* buffer for one video frame */ | ||
165 | struct cx25821_buffer { | ||
166 | /* common v4l buffer stuff -- must be first */ | ||
167 | struct videobuf_buffer vb; | ||
168 | |||
169 | /* cx25821 specific */ | ||
170 | unsigned int bpl; | ||
171 | struct btcx_riscmem risc; | ||
172 | struct cx25821_fmt *fmt; | ||
173 | u32 count; | ||
174 | }; | ||
175 | |||
176 | struct cx25821_input { | ||
177 | enum cx25821_itype type; | ||
178 | unsigned int vmux; | ||
179 | u32 gpio0, gpio1, gpio2, gpio3; | ||
180 | }; | ||
181 | |||
182 | typedef enum { | ||
183 | CX25821_UNDEFINED = 0, | ||
184 | CX25821_RAW, | ||
185 | CX25821_264 | ||
186 | } port_t; | ||
187 | |||
188 | struct cx25821_board { | ||
189 | char *name; | ||
190 | port_t porta, portb, portc; | ||
191 | unsigned int tuner_type; | ||
192 | unsigned int radio_type; | ||
193 | unsigned char tuner_addr; | ||
194 | unsigned char radio_addr; | ||
195 | |||
196 | u32 clk_freq; | ||
197 | struct cx25821_input input[2]; | ||
198 | }; | ||
199 | |||
200 | struct cx25821_subid { | ||
201 | u16 subvendor; | ||
202 | u16 subdevice; | ||
203 | u32 card; | ||
204 | }; | ||
205 | |||
206 | struct cx25821_i2c { | ||
207 | struct cx25821_dev *dev; | ||
208 | |||
209 | int nr; | ||
210 | |||
211 | /* i2c i/o */ | ||
212 | struct i2c_adapter i2c_adap; | ||
213 | struct i2c_algo_bit_data i2c_algo; | ||
214 | struct i2c_client i2c_client; | ||
215 | u32 i2c_rc; | ||
216 | |||
217 | /* cx25821 registers used for raw addess */ | ||
218 | u32 i2c_period; | ||
219 | u32 reg_ctrl; | ||
220 | u32 reg_stat; | ||
221 | u32 reg_addr; | ||
222 | u32 reg_rdata; | ||
223 | u32 reg_wdata; | ||
224 | }; | ||
225 | |||
226 | struct cx25821_dmaqueue { | ||
227 | struct list_head active; | ||
228 | struct list_head queued; | ||
229 | struct timer_list timeout; | ||
230 | struct btcx_riscmem stopper; | ||
231 | u32 count; | ||
232 | }; | ||
233 | |||
234 | struct cx25821_data { | ||
235 | struct cx25821_dev *dev; | ||
236 | struct sram_channel *channel; | ||
237 | }; | ||
238 | |||
239 | struct cx25821_dev { | ||
240 | struct list_head devlist; | ||
241 | atomic_t refcount; | ||
242 | struct v4l2_device v4l2_dev; | ||
243 | |||
244 | struct v4l2_prio_state prio; | ||
245 | |||
246 | /* pci stuff */ | ||
247 | struct pci_dev *pci; | ||
248 | unsigned char pci_rev, pci_lat; | ||
249 | int pci_bus, pci_slot; | ||
250 | u32 base_io_addr; | ||
251 | u32 __iomem *lmmio; | ||
252 | u8 __iomem *bmmio; | ||
253 | int pci_irqmask; | ||
254 | int hwrevision; | ||
255 | |||
256 | u32 clk_freq; | ||
257 | |||
258 | /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ | ||
259 | struct cx25821_i2c i2c_bus[3]; | ||
260 | |||
261 | int nr; | ||
262 | struct mutex lock; | ||
263 | |||
264 | /* board details */ | ||
265 | unsigned int board; | ||
266 | char name[32]; | ||
267 | |||
268 | /* sram configuration */ | ||
269 | struct sram_channel *sram_channels; | ||
270 | |||
271 | /* Analog video */ | ||
272 | u32 resources; | ||
273 | unsigned int input; | ||
274 | u32 tvaudio; | ||
275 | v4l2_std_id tvnorm; | ||
276 | unsigned int tuner_type; | ||
277 | unsigned char tuner_addr; | ||
278 | unsigned int radio_type; | ||
279 | unsigned char radio_addr; | ||
280 | unsigned int has_radio; | ||
281 | unsigned int videc_type; | ||
282 | unsigned char videc_addr; | ||
283 | unsigned short _max_num_decoders; | ||
284 | |||
285 | int ctl_bright; | ||
286 | int ctl_contrast; | ||
287 | int ctl_hue; | ||
288 | int ctl_saturation; | ||
289 | |||
290 | struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | ||
291 | |||
292 | /* Analog Audio Upstream */ | ||
293 | int _audio_is_running; | ||
294 | int _audiopixel_format; | ||
295 | int _is_first_audio_frame; | ||
296 | int _audiofile_status; | ||
297 | int _audio_lines_count; | ||
298 | int _audioframe_count; | ||
299 | int _audio_upstream_channel_select; | ||
300 | int _last_index_irq; //The last interrupt index processed. | ||
301 | |||
302 | __le32 *_risc_audio_jmp_addr; | ||
303 | __le32 *_risc_virt_start_addr; | ||
304 | __le32 *_risc_virt_addr; | ||
305 | dma_addr_t _risc_phys_addr; | ||
306 | dma_addr_t _risc_phys_start_addr; | ||
307 | |||
308 | unsigned int _audiorisc_size; | ||
309 | unsigned int _audiodata_buf_size; | ||
310 | __le32 *_audiodata_buf_virt_addr; | ||
311 | dma_addr_t _audiodata_buf_phys_addr; | ||
312 | char *_audiofilename; | ||
313 | |||
314 | /* V4l */ | ||
315 | u32 freq; | ||
316 | struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; | ||
317 | struct video_device *vbi_dev; | ||
318 | struct video_device *radio_dev; | ||
319 | struct video_device *ioctl_dev; | ||
320 | |||
321 | struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; | ||
322 | spinlock_t slock; | ||
323 | |||
324 | /* Video Upstream */ | ||
325 | int _line_size; | ||
326 | int _prog_cnt; | ||
327 | int _pixel_format; | ||
328 | int _is_first_frame; | ||
329 | int _is_running; | ||
330 | int _file_status; | ||
331 | int _lines_count; | ||
332 | int _frame_count; | ||
333 | int _channel_upstream_select; | ||
334 | unsigned int _risc_size; | ||
335 | |||
336 | __le32 *_dma_virt_start_addr; | ||
337 | __le32 *_dma_virt_addr; | ||
338 | dma_addr_t _dma_phys_addr; | ||
339 | dma_addr_t _dma_phys_start_addr; | ||
340 | |||
341 | unsigned int _data_buf_size; | ||
342 | __le32 *_data_buf_virt_addr; | ||
343 | dma_addr_t _data_buf_phys_addr; | ||
344 | char *_filename; | ||
345 | char *_defaultname; | ||
346 | |||
347 | int _line_size_ch2; | ||
348 | int _prog_cnt_ch2; | ||
349 | int _pixel_format_ch2; | ||
350 | int _is_first_frame_ch2; | ||
351 | int _is_running_ch2; | ||
352 | int _file_status_ch2; | ||
353 | int _lines_count_ch2; | ||
354 | int _frame_count_ch2; | ||
355 | int _channel2_upstream_select; | ||
356 | unsigned int _risc_size_ch2; | ||
357 | |||
358 | __le32 *_dma_virt_start_addr_ch2; | ||
359 | __le32 *_dma_virt_addr_ch2; | ||
360 | dma_addr_t _dma_phys_addr_ch2; | ||
361 | dma_addr_t _dma_phys_start_addr_ch2; | ||
362 | |||
363 | unsigned int _data_buf_size_ch2; | ||
364 | __le32 *_data_buf_virt_addr_ch2; | ||
365 | dma_addr_t _data_buf_phys_addr_ch2; | ||
366 | char *_filename_ch2; | ||
367 | char *_defaultname_ch2; | ||
368 | |||
369 | /* MPEG Encoder ONLY settings */ | ||
370 | u32 cx23417_mailbox; | ||
371 | struct cx2341x_mpeg_params mpeg_params; | ||
372 | struct video_device *v4l_device; | ||
373 | atomic_t v4l_reader_count; | ||
374 | struct cx25821_tvnorm encodernorm; | ||
375 | |||
376 | u32 upstream_riscbuf_size; | ||
377 | u32 upstream_databuf_size; | ||
378 | u32 upstream_riscbuf_size_ch2; | ||
379 | u32 upstream_databuf_size_ch2; | ||
380 | u32 audio_upstream_riscbuf_size; | ||
381 | u32 audio_upstream_databuf_size; | ||
382 | int _isNTSC; | ||
383 | int _frame_index; | ||
384 | int _audioframe_index; | ||
385 | struct workqueue_struct *_irq_queues; | ||
386 | struct work_struct _irq_work_entry; | ||
387 | struct workqueue_struct *_irq_queues_ch2; | ||
388 | struct work_struct _irq_work_entry_ch2; | ||
389 | struct workqueue_struct *_irq_audio_queues; | ||
390 | struct work_struct _audio_work_entry; | ||
391 | char *input_filename; | ||
392 | char *input_filename_ch2; | ||
393 | int _frame_index_ch2; | ||
394 | int _isNTSC_ch2; | ||
395 | char *vid_stdname_ch2; | ||
396 | int pixel_format_ch2; | ||
397 | int channel_select_ch2; | ||
398 | int command_ch2; | ||
399 | char *input_audiofilename; | ||
400 | char *vid_stdname; | ||
401 | int pixel_format; | ||
402 | int channel_select; | ||
403 | int command; | ||
404 | int pixel_formats[VID_CHANNEL_NUM]; | ||
405 | int use_cif_resolution[VID_CHANNEL_NUM]; | ||
406 | int cif_width[VID_CHANNEL_NUM]; | ||
407 | int channel_opened; | ||
408 | }; | ||
409 | |||
410 | struct upstream_user_struct { | ||
411 | char *input_filename; | ||
412 | char *vid_stdname; | ||
413 | int pixel_format; | ||
414 | int channel_select; | ||
415 | int command; | ||
416 | }; | ||
417 | |||
418 | struct downstream_user_struct { | ||
419 | char *vid_stdname; | ||
420 | int pixel_format; | ||
421 | int cif_resolution_enable; | ||
422 | int cif_width; | ||
423 | int decoder_select; | ||
424 | int command; | ||
425 | int reg_address; | ||
426 | int reg_data; | ||
427 | }; | ||
428 | |||
429 | extern struct upstream_user_struct *up_data; | ||
430 | |||
431 | static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) | ||
432 | { | ||
433 | return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); | ||
434 | } | ||
435 | |||
436 | #define cx25821_call_all(dev, o, f, args...) \ | ||
437 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) | ||
438 | |||
439 | extern struct list_head cx25821_devlist; | ||
440 | extern struct cx25821_board cx25821_boards[]; | ||
441 | extern struct cx25821_subid cx25821_subids[]; | ||
442 | |||
443 | #define SRAM_CH00 0 /* Video A */ | ||
444 | #define SRAM_CH01 1 /* Video B */ | ||
445 | #define SRAM_CH02 2 /* Video C */ | ||
446 | #define SRAM_CH03 3 /* Video D */ | ||
447 | #define SRAM_CH04 4 /* Video E */ | ||
448 | #define SRAM_CH05 5 /* Video F */ | ||
449 | #define SRAM_CH06 6 /* Video G */ | ||
450 | #define SRAM_CH07 7 /* Video H */ | ||
451 | |||
452 | #define SRAM_CH08 8 /* Audio A */ | ||
453 | #define SRAM_CH09 9 /* Video Upstream I */ | ||
454 | #define SRAM_CH10 10 /* Video Upstream J */ | ||
455 | #define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */ | ||
456 | |||
457 | #define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 | ||
458 | #define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 | ||
459 | #define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11 | ||
460 | #define VIDEO_IOCTL_CH 11 | ||
461 | |||
462 | struct sram_channel { | ||
463 | char *name; | ||
464 | u32 i; | ||
465 | u32 cmds_start; | ||
466 | u32 ctrl_start; | ||
467 | u32 cdt; | ||
468 | u32 fifo_start; | ||
469 | u32 fifo_size; | ||
470 | u32 ptr1_reg; | ||
471 | u32 ptr2_reg; | ||
472 | u32 cnt1_reg; | ||
473 | u32 cnt2_reg; | ||
474 | u32 int_msk; | ||
475 | u32 int_stat; | ||
476 | u32 int_mstat; | ||
477 | u32 dma_ctl; | ||
478 | u32 gpcnt_ctl; | ||
479 | u32 gpcnt; | ||
480 | u32 aud_length; | ||
481 | u32 aud_cfg; | ||
482 | u32 fld_aud_fifo_en; | ||
483 | u32 fld_aud_risc_en; | ||
484 | |||
485 | //For Upstream Video | ||
486 | u32 vid_fmt_ctl; | ||
487 | u32 vid_active_ctl1; | ||
488 | u32 vid_active_ctl2; | ||
489 | u32 vid_cdt_size; | ||
490 | |||
491 | u32 vip_ctl; | ||
492 | u32 pix_frmt; | ||
493 | u32 jumponly; | ||
494 | u32 irq_bit; | ||
495 | }; | ||
496 | extern struct sram_channel cx25821_sram_channels[]; | ||
497 | |||
498 | #define STATUS_SUCCESS 0 | ||
499 | #define STATUS_UNSUCCESSFUL -1 | ||
500 | |||
501 | #define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) | ||
502 | #define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) | ||
503 | |||
504 | #define cx_andor(reg, mask, value) \ | ||
505 | writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ | ||
506 | ((value) & (mask)), dev->lmmio+((reg)>>2)) | ||
507 | |||
508 | #define cx_set(reg, bit) cx_andor((reg), (bit), (bit)) | ||
509 | #define cx_clear(reg, bit) cx_andor((reg), (bit), 0) | ||
510 | |||
511 | #define Set_GPIO_Bit(Bit) (1 << Bit) | ||
512 | #define Clear_GPIO_Bit(Bit) (~(1 << Bit)) | ||
513 | |||
514 | #define CX25821_ERR(fmt, args...) printk(KERN_ERR "cx25821(%d): " fmt, dev->board, ## args) | ||
515 | #define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args) | ||
516 | #define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args) | ||
517 | |||
518 | extern int cx25821_i2c_register(struct cx25821_i2c *bus); | ||
519 | extern void cx25821_card_setup(struct cx25821_dev *dev); | ||
520 | extern int cx25821_ir_init(struct cx25821_dev *dev); | ||
521 | extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); | ||
522 | extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); | ||
523 | extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); | ||
524 | extern void cx25821_gpio_init(struct cx25821_dev *dev); | ||
525 | extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, | ||
526 | int pin_number, int pin_logic_value); | ||
527 | |||
528 | extern int medusa_video_init(struct cx25821_dev *dev); | ||
529 | extern int medusa_set_videostandard(struct cx25821_dev *dev); | ||
530 | extern void medusa_set_resolution(struct cx25821_dev *dev, int width, | ||
531 | int decoder_select); | ||
532 | extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness, | ||
533 | int decoder); | ||
534 | extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast, | ||
535 | int decoder); | ||
536 | extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder); | ||
537 | extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, | ||
538 | int decoder); | ||
539 | |||
540 | extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, | ||
541 | struct sram_channel *ch, unsigned int bpl, | ||
542 | 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, unsigned int lines); | ||
550 | extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, | ||
551 | struct btcx_riscmem *risc, | ||
552 | struct scatterlist *sglist, | ||
553 | unsigned int bpl, | ||
554 | unsigned int lines, unsigned int lpi); | ||
555 | extern void cx25821_free_buffer(struct videobuf_queue *q, | ||
556 | struct cx25821_buffer *buf); | ||
557 | extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
558 | u32 reg, u32 mask, u32 value); | ||
559 | extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, | ||
560 | struct sram_channel *ch); | ||
561 | extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | ||
562 | struct sram_channel *ch); | ||
563 | |||
564 | extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci); | ||
565 | extern void cx25821_print_irqbits(char *name, char *tag, char **strings, | ||
566 | int len, u32 bits, u32 mask); | ||
567 | extern void cx25821_dev_unregister(struct cx25821_dev *dev); | ||
568 | extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | ||
569 | struct sram_channel *ch, | ||
570 | unsigned int bpl, u32 risc); | ||
571 | |||
572 | extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, | ||
573 | int channel_select, int pixel_format); | ||
574 | extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, | ||
575 | int channel_select, int pixel_format); | ||
576 | extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, | ||
577 | int channel_select); | ||
578 | extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); | ||
579 | extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); | ||
580 | extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); | ||
581 | extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, | ||
582 | struct upstream_user_struct | ||
583 | *up_data); | ||
584 | extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, | ||
585 | struct upstream_user_struct | ||
586 | *up_data); | ||
587 | extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, | ||
588 | struct upstream_user_struct *up_data); | ||
589 | extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); | ||
590 | extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); | ||
591 | extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); | ||
592 | extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | ||
593 | struct sram_channel *ch, | ||
594 | unsigned int bpl, u32 risc); | ||
595 | extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, | ||
596 | u32 format); | ||
597 | extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); | ||
598 | extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
599 | struct pci_dev *pci, | ||
600 | struct video_device *template, | ||
601 | char *type); | ||
602 | #endif | ||
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig index ca6ade6c4b47..e47f683a323e 100644 --- a/drivers/staging/go7007/Kconfig +++ b/drivers/staging/go7007/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config VIDEO_GO7007 | 1 | config VIDEO_GO7007 |
2 | tristate "Go 7007 support" | 2 | tristate "WIS GO7007 MPEG encoder support" |
3 | depends on VIDEO_DEV && PCI && I2C && INPUT | 3 | depends on VIDEO_DEV && PCI && I2C && INPUT |
4 | depends on SND | 4 | depends on SND |
5 | select VIDEOBUF_DMA_SG | 5 | select VIDEOBUF_DMA_SG |
@@ -10,17 +10,19 @@ config VIDEO_GO7007 | |||
10 | select CRC32 | 10 | select CRC32 |
11 | default N | 11 | default N |
12 | ---help--- | 12 | ---help--- |
13 | This is a video4linux driver for some weird device... | 13 | This is a video4linux driver for the WIS GO7007 MPEG |
14 | encoder chip. | ||
14 | 15 | ||
15 | To compile this driver as a module, choose M here: the | 16 | To compile this driver as a module, choose M here: the |
16 | module will be called go7007 | 17 | module will be called go7007 |
17 | 18 | ||
18 | config VIDEO_GO7007_USB | 19 | config VIDEO_GO7007_USB |
19 | tristate "Go 7007 USB support" | 20 | tristate "WIS GO7007 USB support" |
20 | depends on VIDEO_GO7007 && USB | 21 | depends on VIDEO_GO7007 && USB |
21 | default N | 22 | default N |
22 | ---help--- | 23 | ---help--- |
23 | This is a video4linux driver for some weird device... | 24 | This is a video4linux driver for the WIS GO7007 MPEG |
25 | encoder chip over USB. | ||
24 | 26 | ||
25 | To compile this driver as a module, choose M here: the | 27 | To compile this driver as a module, choose M here: the |
26 | module will be called go7007-usb | 28 | module will be called go7007-usb |
@@ -30,8 +32,78 @@ config VIDEO_GO7007_USB_S2250_BOARD | |||
30 | depends on VIDEO_GO7007_USB && DVB_USB | 32 | depends on VIDEO_GO7007_USB && DVB_USB |
31 | default N | 33 | default N |
32 | ---help--- | 34 | ---help--- |
33 | This is a video4linux driver for the Sensoray 2250/2251 device | 35 | This is a video4linux driver for the Sensoray 2250/2251 device. |
34 | 36 | ||
35 | To compile this driver as a module, choose M here: the | 37 | To compile this driver as a module, choose M here: the |
36 | module will be called s2250-board | 38 | module will be called s2250 |
39 | |||
40 | config VIDEO_GO7007_OV7640 | ||
41 | tristate "OV7640 subdev support" | ||
42 | depends on VIDEO_GO7007 | ||
43 | default N | ||
44 | ---help--- | ||
45 | This is a video4linux driver for the OV7640 sub-device. | ||
46 | |||
47 | To compile this driver as a module, choose M here: the | ||
48 | module will be called wis-ov7640 | ||
49 | |||
50 | config VIDEO_GO7007_SAA7113 | ||
51 | tristate "SAA7113 subdev support" | ||
52 | depends on VIDEO_GO7007 | ||
53 | default N | ||
54 | ---help--- | ||
55 | This is a video4linux driver for the SAA7113 sub-device. | ||
56 | |||
57 | To compile this driver as a module, choose M here: the | ||
58 | module will be called wis-saa7113 | ||
59 | |||
60 | config VIDEO_GO7007_SAA7115 | ||
61 | tristate "SAA7115 subdev support" | ||
62 | depends on VIDEO_GO7007 | ||
63 | default N | ||
64 | ---help--- | ||
65 | This is a video4linux driver for the SAA7115 sub-device. | ||
66 | |||
67 | To compile this driver as a module, choose M here: the | ||
68 | module will be called wis-saa7115 | ||
69 | |||
70 | config VIDEO_GO7007_TW9903 | ||
71 | tristate "TW9903 subdev support" | ||
72 | depends on VIDEO_GO7007 | ||
73 | default N | ||
74 | ---help--- | ||
75 | This is a video4linux driver for the TW9903 sub-device. | ||
76 | |||
77 | To compile this driver as a module, choose M here: the | ||
78 | module will be called wis-tw9903 | ||
79 | |||
80 | config VIDEO_GO7007_UDA1342 | ||
81 | tristate "UDA1342 subdev support" | ||
82 | depends on VIDEO_GO7007 | ||
83 | default N | ||
84 | ---help--- | ||
85 | This is a video4linux driver for the UDA1342 sub-device. | ||
86 | |||
87 | To compile this driver as a module, choose M here: the | ||
88 | module will be called wis-uda1342 | ||
89 | |||
90 | config VIDEO_GO7007_SONY_TUNER | ||
91 | tristate "Sony tuner subdev support" | ||
92 | depends on VIDEO_GO7007 | ||
93 | default N | ||
94 | ---help--- | ||
95 | This is a video4linux driver for the Sony Tuner sub-device. | ||
96 | |||
97 | To compile this driver as a module, choose M here: the | ||
98 | module will be called wis-sony-tuner | ||
99 | |||
100 | config VIDEO_GO7007_TW2804 | ||
101 | tristate "TW2804 subdev support" | ||
102 | depends on VIDEO_GO7007 | ||
103 | default N | ||
104 | ---help--- | ||
105 | This is a video4linux driver for the TW2804 sub-device. | ||
106 | |||
107 | To compile this driver as a module, choose M here: the | ||
108 | module will be called wis-tw2804 | ||
37 | 109 | ||
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile index e514b4af6d06..d14ea84a01f6 100644 --- a/drivers/staging/go7007/Makefile +++ b/drivers/staging/go7007/Makefile | |||
@@ -6,22 +6,34 @@ | |||
6 | obj-$(CONFIG_VIDEO_GO7007) += go7007.o | 6 | obj-$(CONFIG_VIDEO_GO7007) += go7007.o |
7 | obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o | 7 | obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o |
8 | obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o | 8 | obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o |
9 | obj-$(CONFIG_VIDEO_GO7007_SAA7113) += wis-saa7113.o | ||
10 | obj-$(CONFIG_VIDEO_GO7007_OV7640) += wis-ov7640.o | ||
11 | obj-$(CONFIG_VIDEO_GO7007_SAA7115) += wis-saa7115.o | ||
12 | obj-$(CONFIG_VIDEO_GO7007_TW9903) += wis-tw9903.o | ||
13 | obj-$(CONFIG_VIDEO_GO7007_UDA1342) += wis-uda1342.o | ||
14 | obj-$(CONFIG_VIDEO_GO7007_SONY_TUNER) += wis-sony-tuner.o | ||
15 | obj-$(CONFIG_VIDEO_GO7007_TW2804) += wis-tw2804.o | ||
9 | 16 | ||
10 | go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ | 17 | go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ |
11 | snd-go7007.o wis-saa7113.o | 18 | snd-go7007.o |
12 | 19 | ||
13 | s2250-objs += s2250-board.o s2250-loader.o | 20 | s2250-objs += s2250-board.o s2250-loader.o |
14 | 21 | ||
15 | # Uncompile when the saa7134 patches get into upstream | 22 | # Uncomment when the saa7134 patches get into upstream |
16 | #ifneq ($(CONFIG_VIDEO_SAA7134),) | 23 | #ifneq ($(CONFIG_VIDEO_SAA7134),) |
17 | #obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o | 24 | #obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o |
18 | #EXTRA_CFLAGS += -Idrivers/media/video/saa7134 | 25 | #EXTRA_CFLAGS += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3 |
19 | #endif | 26 | #endif |
20 | 27 | ||
28 | # S2250 needs cypress ezusb loader from dvb-usb | ||
21 | ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) | 29 | ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) |
22 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb | 30 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb |
23 | endif | 31 | endif |
24 | 32 | ||
25 | EXTRA_CFLAGS += -Idrivers/staging/saa7134 | ||
26 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 33 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
27 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 34 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
35 | |||
36 | # Ubuntu 8.04 has CONFIG_SND undefined, so include lum sound/config.h too | ||
37 | ifeq ($(CONFIG_SND),) | ||
38 | EXTRA_CFLAGS += -include sound/config.h | ||
39 | endif | ||
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index 77b1e769ac92..472f4bb08fdc 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
29 | #include <linux/firmware.h> | 29 | #include <linux/firmware.h> |
30 | #include <linux/semaphore.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
33 | #include <linux/videodev2.h> | 33 | #include <linux/videodev2.h> |
@@ -49,7 +49,7 @@ int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) | |||
49 | go->hpi_ops->read_interrupt(go); | 49 | go->hpi_ops->read_interrupt(go); |
50 | if (wait_event_timeout(go->interrupt_waitq, | 50 | if (wait_event_timeout(go->interrupt_waitq, |
51 | go->interrupt_available, 5*HZ) < 0) { | 51 | go->interrupt_available, 5*HZ) < 0) { |
52 | printk(KERN_ERR "go7007: timeout waiting for read interrupt\n"); | 52 | v4l2_err(go->video_dev, "timeout waiting for read interrupt\n"); |
53 | return -1; | 53 | return -1; |
54 | } | 54 | } |
55 | if (!go->interrupt_available) | 55 | if (!go->interrupt_available) |
@@ -97,13 +97,12 @@ static int go7007_load_encoder(struct go7007 *go) | |||
97 | u16 intr_val, intr_data; | 97 | u16 intr_val, intr_data; |
98 | 98 | ||
99 | if (request_firmware(&fw_entry, fw_name, go->dev)) { | 99 | if (request_firmware(&fw_entry, fw_name, go->dev)) { |
100 | printk(KERN_ERR | 100 | v4l2_err(go, "unable to load firmware from file " |
101 | "go7007: unable to load firmware from file \"%s\"\n", | 101 | "\"%s\"\n", fw_name); |
102 | fw_name); | ||
103 | return -1; | 102 | return -1; |
104 | } | 103 | } |
105 | if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { | 104 | if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { |
106 | printk(KERN_ERR "go7007: file \"%s\" does not appear to be " | 105 | v4l2_err(go, "file \"%s\" does not appear to be " |
107 | "go7007 firmware\n", fw_name); | 106 | "go7007 firmware\n", fw_name); |
108 | release_firmware(fw_entry); | 107 | release_firmware(fw_entry); |
109 | return -1; | 108 | return -1; |
@@ -111,7 +110,7 @@ static int go7007_load_encoder(struct go7007 *go) | |||
111 | fw_len = fw_entry->size - 16; | 110 | fw_len = fw_entry->size - 16; |
112 | bounce = kmalloc(fw_len, GFP_KERNEL); | 111 | bounce = kmalloc(fw_len, GFP_KERNEL); |
113 | if (bounce == NULL) { | 112 | if (bounce == NULL) { |
114 | printk(KERN_ERR "go7007: unable to allocate %d bytes for " | 113 | v4l2_err(go, "unable to allocate %d bytes for " |
115 | "firmware transfer\n", fw_len); | 114 | "firmware transfer\n", fw_len); |
116 | release_firmware(fw_entry); | 115 | release_firmware(fw_entry); |
117 | return -1; | 116 | return -1; |
@@ -122,7 +121,7 @@ static int go7007_load_encoder(struct go7007 *go) | |||
122 | go7007_send_firmware(go, bounce, fw_len) < 0 || | 121 | go7007_send_firmware(go, bounce, fw_len) < 0 || |
123 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || | 122 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || |
124 | (intr_val & ~0x1) != 0x5a5a) { | 123 | (intr_val & ~0x1) != 0x5a5a) { |
125 | printk(KERN_ERR "go7007: error transferring firmware\n"); | 124 | v4l2_err(go, "error transferring firmware\n"); |
126 | rv = -1; | 125 | rv = -1; |
127 | } | 126 | } |
128 | kfree(bounce); | 127 | kfree(bounce); |
@@ -140,9 +139,9 @@ int go7007_boot_encoder(struct go7007 *go, int init_i2c) | |||
140 | { | 139 | { |
141 | int ret; | 140 | int ret; |
142 | 141 | ||
143 | down(&go->hw_lock); | 142 | mutex_lock(&go->hw_lock); |
144 | ret = go7007_load_encoder(go); | 143 | ret = go7007_load_encoder(go); |
145 | up(&go->hw_lock); | 144 | mutex_unlock(&go->hw_lock); |
146 | if (ret < 0) | 145 | if (ret < 0) |
147 | return -1; | 146 | return -1; |
148 | if (!init_i2c) | 147 | if (!init_i2c) |
@@ -257,9 +256,9 @@ int go7007_register_encoder(struct go7007 *go) | |||
257 | 256 | ||
258 | printk(KERN_INFO "go7007: registering new %s\n", go->name); | 257 | printk(KERN_INFO "go7007: registering new %s\n", go->name); |
259 | 258 | ||
260 | down(&go->hw_lock); | 259 | mutex_lock(&go->hw_lock); |
261 | ret = go7007_init_encoder(go); | 260 | ret = go7007_init_encoder(go); |
262 | up(&go->hw_lock); | 261 | mutex_unlock(&go->hw_lock); |
263 | if (ret < 0) | 262 | if (ret < 0) |
264 | return -1; | 263 | return -1; |
265 | 264 | ||
@@ -316,7 +315,7 @@ int go7007_start_encoder(struct go7007 *go) | |||
316 | 315 | ||
317 | if (go7007_send_firmware(go, fw, fw_len) < 0 || | 316 | if (go7007_send_firmware(go, fw, fw_len) < 0 || |
318 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { | 317 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { |
319 | printk(KERN_ERR "go7007: error transferring firmware\n"); | 318 | v4l2_err(go->video_dev, "error transferring firmware\n"); |
320 | rv = -1; | 319 | rv = -1; |
321 | goto start_error; | 320 | goto start_error; |
322 | } | 321 | } |
@@ -325,7 +324,7 @@ int go7007_start_encoder(struct go7007 *go) | |||
325 | go->parse_length = 0; | 324 | go->parse_length = 0; |
326 | go->seen_frame = 0; | 325 | go->seen_frame = 0; |
327 | if (go7007_stream_start(go) < 0) { | 326 | if (go7007_stream_start(go) < 0) { |
328 | printk(KERN_ERR "go7007: error starting stream transfer\n"); | 327 | v4l2_err(go->video_dev, "error starting stream transfer\n"); |
329 | rv = -1; | 328 | rv = -1; |
330 | goto start_error; | 329 | goto start_error; |
331 | } | 330 | } |
@@ -421,7 +420,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
421 | for (i = 0; i < length; ++i) { | 420 | for (i = 0; i < length; ++i) { |
422 | if (go->active_buf != NULL && | 421 | if (go->active_buf != NULL && |
423 | go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { | 422 | go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { |
424 | printk(KERN_DEBUG "go7007: dropping oversized frame\n"); | 423 | v4l2_info(go->video_dev, "dropping oversized frame\n"); |
425 | go->active_buf->offset -= go->active_buf->bytesused; | 424 | go->active_buf->offset -= go->active_buf->bytesused; |
426 | go->active_buf->bytesused = 0; | 425 | go->active_buf->bytesused = 0; |
427 | go->active_buf->modet_active = 0; | 426 | go->active_buf->modet_active = 0; |
@@ -604,7 +603,7 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) | |||
604 | go->tuner_type = -1; | 603 | go->tuner_type = -1; |
605 | go->channel_number = 0; | 604 | go->channel_number = 0; |
606 | go->name[0] = 0; | 605 | go->name[0] = 0; |
607 | init_MUTEX(&go->hw_lock); | 606 | mutex_init(&go->hw_lock); |
608 | init_waitqueue_head(&go->frame_waitq); | 607 | init_waitqueue_head(&go->frame_waitq); |
609 | spin_lock_init(&go->spinlock); | 608 | spin_lock_init(&go->spinlock); |
610 | go->video_dev = NULL; | 609 | go->video_dev = NULL; |
@@ -669,8 +668,8 @@ void go7007_remove(struct go7007 *go) | |||
669 | if (i2c_del_adapter(&go->i2c_adapter) == 0) | 668 | if (i2c_del_adapter(&go->i2c_adapter) == 0) |
670 | go->i2c_adapter_online = 0; | 669 | go->i2c_adapter_online = 0; |
671 | else | 670 | else |
672 | printk(KERN_ERR | 671 | v4l2_err(go->video_dev, |
673 | "go7007: error removing I2C adapter!\n"); | 672 | "error removing I2C adapter!\n"); |
674 | } | 673 | } |
675 | 674 | ||
676 | if (go->audio_enabled) | 675 | if (go->audio_enabled) |
diff --git a/drivers/staging/go7007/go7007-fw.c b/drivers/staging/go7007/go7007-fw.c index 871ed43e4e05..a8bb264e0074 100644 --- a/drivers/staging/go7007/go7007-fw.c +++ b/drivers/staging/go7007/go7007-fw.c | |||
@@ -1034,7 +1034,8 @@ static int brctrl_to_package(struct go7007 *go, | |||
1034 | 0xBF1B, framelen[7], | 1034 | 0xBF1B, framelen[7], |
1035 | 0, 0, | 1035 | 0, 0, |
1036 | 1036 | ||
1037 | #if 0 /* Remove once we don't care about matching */ | 1037 | #if 0 |
1038 | /* Remove once we don't care about matching */ | ||
1038 | 0x200e, 0x0000, | 1039 | 0x200e, 0x0000, |
1039 | 0xBF56, 4, | 1040 | 0xBF56, 4, |
1040 | 0xBF57, 0, | 1041 | 0xBF57, 0, |
diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c index c82867fdd28d..b8cfa1a6eaeb 100644 --- a/drivers/staging/go7007/go7007-i2c.c +++ b/drivers/staging/go7007/go7007-i2c.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/semaphore.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <asm/system.h> | 29 | #include <asm/system.h> |
30 | 30 | ||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | /* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs | 49 | /* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs |
50 | * on the Adlink PCI-MPG24, so access is shared between all of them. */ | 50 | * on the Adlink PCI-MPG24, so access is shared between all of them. */ |
51 | static DECLARE_MUTEX(adlink_mpg24_i2c_lock); | 51 | static DEFINE_MUTEX(adlink_mpg24_i2c_lock); |
52 | 52 | ||
53 | static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, | 53 | static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, |
54 | u16 command, int flags, u8 *data) | 54 | u16 command, int flags, u8 *data) |
@@ -69,11 +69,11 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, | |||
69 | *data, command, addr); | 69 | *data, command, addr); |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | down(&go->hw_lock); | 72 | mutex_lock(&go->hw_lock); |
73 | 73 | ||
74 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { | 74 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { |
75 | /* Bridge the I2C port on this GO7007 to the shared bus */ | 75 | /* Bridge the I2C port on this GO7007 to the shared bus */ |
76 | down(&adlink_mpg24_i2c_lock); | 76 | mutex_lock(&adlink_mpg24_i2c_lock); |
77 | go7007_write_addr(go, 0x3c82, 0x0020); | 77 | go7007_write_addr(go, 0x3c82, 0x0020); |
78 | } | 78 | } |
79 | 79 | ||
@@ -134,9 +134,9 @@ i2c_done: | |||
134 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { | 134 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { |
135 | /* Isolate the I2C port on this GO7007 from the shared bus */ | 135 | /* Isolate the I2C port on this GO7007 from the shared bus */ |
136 | go7007_write_addr(go, 0x3c82, 0x0000); | 136 | go7007_write_addr(go, 0x3c82, 0x0000); |
137 | up(&adlink_mpg24_i2c_lock); | 137 | mutex_unlock(&adlink_mpg24_i2c_lock); |
138 | } | 138 | } |
139 | up(&go->hw_lock); | 139 | mutex_unlock(&go->hw_lock); |
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
142 | 142 | ||
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h index 178d18119faa..ce9307e3e186 100644 --- a/drivers/staging/go7007/go7007-priv.h +++ b/drivers/staging/go7007/go7007-priv.h | |||
@@ -132,7 +132,7 @@ struct go7007_buffer { | |||
132 | 132 | ||
133 | struct go7007_file { | 133 | struct go7007_file { |
134 | struct go7007 *go; | 134 | struct go7007 *go; |
135 | struct semaphore lock; | 135 | struct mutex lock; |
136 | int buf_count; | 136 | int buf_count; |
137 | struct go7007_buffer *bufs; | 137 | struct go7007_buffer *bufs; |
138 | }; | 138 | }; |
@@ -170,7 +170,7 @@ struct go7007 { | |||
170 | int ref_count; | 170 | int ref_count; |
171 | enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; | 171 | enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; |
172 | spinlock_t spinlock; | 172 | spinlock_t spinlock; |
173 | struct semaphore hw_lock; | 173 | struct mutex hw_lock; |
174 | int streaming; | 174 | int streaming; |
175 | int in_use; | 175 | int in_use; |
176 | int audio_enabled; | 176 | int audio_enabled; |
@@ -240,7 +240,7 @@ struct go7007 { | |||
240 | unsigned short interrupt_data; | 240 | unsigned short interrupt_data; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | /* All of these must be called with the hpi_lock semaphore held! */ | 243 | /* All of these must be called with the hpi_lock mutex held! */ |
244 | #define go7007_interface_reset(go) \ | 244 | #define go7007_interface_reset(go) \ |
245 | ((go)->hpi_ops->interface_reset(go)) | 245 | ((go)->hpi_ops->interface_reset(go)) |
246 | #define go7007_write_interrupt(go, x, y) \ | 246 | #define go7007_write_interrupt(go, x, y) \ |
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c index aa4a9e0b9954..ecaa3c989cf4 100644 --- a/drivers/staging/go7007/go7007-usb.c +++ b/drivers/staging/go7007/go7007-usb.c | |||
@@ -33,7 +33,8 @@ | |||
33 | 33 | ||
34 | static unsigned int assume_endura; | 34 | static unsigned int assume_endura; |
35 | module_param(assume_endura, int, 0644); | 35 | module_param(assume_endura, int, 0644); |
36 | MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura"); | 36 | MODULE_PARM_DESC(assume_endura, "when probing fails, " |
37 | "hardware is a Pelco Endura"); | ||
37 | 38 | ||
38 | /* #define GO7007_USB_DEBUG */ | 39 | /* #define GO7007_USB_DEBUG */ |
39 | /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ | 40 | /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ |
@@ -44,12 +45,12 @@ MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura" | |||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * Pipes on EZ-USB interface: | 47 | * Pipes on EZ-USB interface: |
47 | * 0 snd - Control | 48 | * 0 snd - Control |
48 | * 0 rcv - Control | 49 | * 0 rcv - Control |
49 | * 2 snd - Download firmware (control) | 50 | * 2 snd - Download firmware (control) |
50 | * 4 rcv - Read Interrupt (interrupt) | 51 | * 4 rcv - Read Interrupt (interrupt) |
51 | * 6 rcv - Read Video (bulk) | 52 | * 6 rcv - Read Video (bulk) |
52 | * 8 rcv - Read Audio (bulk) | 53 | * 8 rcv - Read Audio (bulk) |
53 | */ | 54 | */ |
54 | 55 | ||
55 | #define GO7007_USB_EZUSB (1<<0) | 56 | #define GO7007_USB_EZUSB (1<<0) |
@@ -62,7 +63,7 @@ struct go7007_usb_board { | |||
62 | 63 | ||
63 | struct go7007_usb { | 64 | struct go7007_usb { |
64 | struct go7007_usb_board *board; | 65 | struct go7007_usb_board *board; |
65 | struct semaphore i2c_lock; | 66 | struct mutex i2c_lock; |
66 | struct usb_device *usbdev; | 67 | struct usb_device *usbdev; |
67 | struct urb *video_urbs[8]; | 68 | struct urb *video_urbs[8]; |
68 | struct urb *audio_urbs[8]; | 69 | struct urb *audio_urbs[8]; |
@@ -97,7 +98,7 @@ static struct go7007_usb_board board_matrix_ii = { | |||
97 | }, | 98 | }, |
98 | }, | 99 | }, |
99 | .num_inputs = 2, | 100 | .num_inputs = 2, |
100 | .inputs = { | 101 | .inputs = { |
101 | { | 102 | { |
102 | .video_input = 0, | 103 | .video_input = 0, |
103 | .name = "Composite", | 104 | .name = "Composite", |
@@ -134,7 +135,7 @@ static struct go7007_usb_board board_matrix_reload = { | |||
134 | }, | 135 | }, |
135 | }, | 136 | }, |
136 | .num_inputs = 2, | 137 | .num_inputs = 2, |
137 | .inputs = { | 138 | .inputs = { |
138 | { | 139 | { |
139 | .video_input = 0, | 140 | .video_input = 0, |
140 | .name = "Composite", | 141 | .name = "Composite", |
@@ -172,7 +173,7 @@ static struct go7007_usb_board board_star_trek = { | |||
172 | }, | 173 | }, |
173 | }, | 174 | }, |
174 | .num_inputs = 2, | 175 | .num_inputs = 2, |
175 | .inputs = { | 176 | .inputs = { |
176 | { | 177 | { |
177 | .video_input = 1, | 178 | .video_input = 1, |
178 | /* .audio_input = AUDIO_EXTERN, */ | 179 | /* .audio_input = AUDIO_EXTERN, */ |
@@ -228,7 +229,7 @@ static struct go7007_usb_board board_px_tv402u = { | |||
228 | }, | 229 | }, |
229 | }, | 230 | }, |
230 | .num_inputs = 3, | 231 | .num_inputs = 3, |
231 | .inputs = { | 232 | .inputs = { |
232 | { | 233 | { |
233 | .video_input = 1, | 234 | .video_input = 1, |
234 | .audio_input = TVAUDIO_INPUT_EXTERN, | 235 | .audio_input = TVAUDIO_INPUT_EXTERN, |
@@ -276,7 +277,7 @@ static struct go7007_usb_board board_xmen = { | |||
276 | }, | 277 | }, |
277 | }, | 278 | }, |
278 | .num_inputs = 1, | 279 | .num_inputs = 1, |
279 | .inputs = { | 280 | .inputs = { |
280 | { | 281 | { |
281 | .name = "Camera", | 282 | .name = "Camera", |
282 | }, | 283 | }, |
@@ -309,7 +310,7 @@ static struct go7007_usb_board board_matrix_revolution = { | |||
309 | }, | 310 | }, |
310 | }, | 311 | }, |
311 | .num_inputs = 2, | 312 | .num_inputs = 2, |
312 | .inputs = { | 313 | .inputs = { |
313 | { | 314 | { |
314 | .video_input = 2, | 315 | .video_input = 2, |
315 | .name = "Composite", | 316 | .name = "Composite", |
@@ -341,7 +342,7 @@ static struct go7007_usb_board board_lifeview_lr192 = { | |||
341 | GO7007_SENSOR_SCALING, | 342 | GO7007_SENSOR_SCALING, |
342 | .num_i2c_devs = 0, | 343 | .num_i2c_devs = 0, |
343 | .num_inputs = 1, | 344 | .num_inputs = 1, |
344 | .inputs = { | 345 | .inputs = { |
345 | { | 346 | { |
346 | .video_input = 0, | 347 | .video_input = 0, |
347 | .name = "Composite", | 348 | .name = "Composite", |
@@ -367,7 +368,7 @@ static struct go7007_usb_board board_endura = { | |||
367 | .sensor_h_offset = 8, | 368 | .sensor_h_offset = 8, |
368 | .num_i2c_devs = 0, | 369 | .num_i2c_devs = 0, |
369 | .num_inputs = 1, | 370 | .num_inputs = 1, |
370 | .inputs = { | 371 | .inputs = { |
371 | { | 372 | { |
372 | .name = "Camera", | 373 | .name = "Camera", |
373 | }, | 374 | }, |
@@ -399,7 +400,7 @@ static struct go7007_usb_board board_adlink_mpg24 = { | |||
399 | }, | 400 | }, |
400 | }, | 401 | }, |
401 | .num_inputs = 1, | 402 | .num_inputs = 1, |
402 | .inputs = { | 403 | .inputs = { |
403 | { | 404 | { |
404 | .name = "Composite", | 405 | .name = "Composite", |
405 | }, | 406 | }, |
@@ -430,7 +431,7 @@ static struct go7007_usb_board board_sensoray_2250 = { | |||
430 | }, | 431 | }, |
431 | }, | 432 | }, |
432 | .num_inputs = 2, | 433 | .num_inputs = 2, |
433 | .inputs = { | 434 | .inputs = { |
434 | { | 435 | { |
435 | .video_input = 0, | 436 | .video_input = 0, |
436 | .name = "Composite", | 437 | .name = "Composite", |
@@ -734,14 +735,15 @@ static int go7007_usb_read_interrupt(struct go7007 *go) | |||
734 | static void go7007_usb_read_video_pipe_complete(struct urb *urb) | 735 | static void go7007_usb_read_video_pipe_complete(struct urb *urb) |
735 | { | 736 | { |
736 | struct go7007 *go = (struct go7007 *)urb->context; | 737 | struct go7007 *go = (struct go7007 *)urb->context; |
737 | int r, status = urb-> status; | 738 | int r, status = urb->status; |
738 | 739 | ||
739 | if (!go->streaming) { | 740 | if (!go->streaming) { |
740 | wake_up_interruptible(&go->frame_waitq); | 741 | wake_up_interruptible(&go->frame_waitq); |
741 | return; | 742 | return; |
742 | } | 743 | } |
743 | if (status) { | 744 | if (status) { |
744 | printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", status); | 745 | printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", |
746 | status); | ||
745 | return; | 747 | return; |
746 | } | 748 | } |
747 | if (urb->actual_length != urb->transfer_buffer_length) { | 749 | if (urb->actual_length != urb->transfer_buffer_length) { |
@@ -762,7 +764,8 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb) | |||
762 | if (!go->streaming) | 764 | if (!go->streaming) |
763 | return; | 765 | return; |
764 | if (status) { | 766 | if (status) { |
765 | printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", status); | 767 | printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", |
768 | status); | ||
766 | return; | 769 | return; |
767 | } | 770 | } |
768 | if (urb->actual_length != urb->transfer_buffer_length) { | 771 | if (urb->actual_length != urb->transfer_buffer_length) { |
@@ -877,7 +880,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, | |||
877 | if (go->status == STATUS_SHUTDOWN) | 880 | if (go->status == STATUS_SHUTDOWN) |
878 | return -1; | 881 | return -1; |
879 | 882 | ||
880 | down(&usb->i2c_lock); | 883 | mutex_lock(&usb->i2c_lock); |
881 | 884 | ||
882 | for (i = 0; i < num; ++i) { | 885 | for (i = 0; i < num; ++i) { |
883 | /* The hardware command is "write some bytes then read some | 886 | /* The hardware command is "write some bytes then read some |
@@ -935,7 +938,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, | |||
935 | ret = 0; | 938 | ret = 0; |
936 | 939 | ||
937 | i2c_done: | 940 | i2c_done: |
938 | up(&usb->i2c_lock); | 941 | mutex_unlock(&usb->i2c_lock); |
939 | return ret; | 942 | return ret; |
940 | } | 943 | } |
941 | 944 | ||
@@ -1017,7 +1020,7 @@ static int go7007_usb_probe(struct usb_interface *intf, | |||
1017 | break; | 1020 | break; |
1018 | case GO7007_BOARDID_SENSORAY_2250: | 1021 | case GO7007_BOARDID_SENSORAY_2250: |
1019 | printk(KERN_INFO "Sensoray 2250 found\n"); | 1022 | printk(KERN_INFO "Sensoray 2250 found\n"); |
1020 | name = "Sensoray 2250/2251\n"; | 1023 | name = "Sensoray 2250/2251"; |
1021 | board = &board_sensoray_2250; | 1024 | board = &board_sensoray_2250; |
1022 | break; | 1025 | break; |
1023 | default: | 1026 | default: |
@@ -1065,7 +1068,7 @@ static int go7007_usb_probe(struct usb_interface *intf, | |||
1065 | if (board->flags & GO7007_USB_EZUSB_I2C) { | 1068 | if (board->flags & GO7007_USB_EZUSB_I2C) { |
1066 | memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, | 1069 | memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, |
1067 | sizeof(go7007_usb_adap_templ)); | 1070 | sizeof(go7007_usb_adap_templ)); |
1068 | init_MUTEX(&usb->i2c_lock); | 1071 | mutex_init(&usb->i2c_lock); |
1069 | go->i2c_adapter.dev.parent = go->dev; | 1072 | go->i2c_adapter.dev.parent = go->dev; |
1070 | i2c_set_adapdata(&go->i2c_adapter, go); | 1073 | i2c_set_adapdata(&go->i2c_adapter, go); |
1071 | if (i2c_add_adapter(&go->i2c_adapter) < 0) { | 1074 | if (i2c_add_adapter(&go->i2c_adapter) < 0) { |
@@ -1096,7 +1099,7 @@ static int go7007_usb_probe(struct usb_interface *intf, | |||
1096 | usb->board = board = &board_endura; | 1099 | usb->board = board = &board_endura; |
1097 | go->board_info = &board->main_info; | 1100 | go->board_info = &board->main_info; |
1098 | strncpy(go->name, "Pelco Endura", | 1101 | strncpy(go->name, "Pelco Endura", |
1099 | sizeof(go->name)); | 1102 | sizeof(go->name)); |
1100 | } else { | 1103 | } else { |
1101 | u16 channel; | 1104 | u16 channel; |
1102 | 1105 | ||
@@ -1154,8 +1157,7 @@ static int go7007_usb_probe(struct usb_interface *intf, | |||
1154 | * to the EZ-USB GPIO output pins */ | 1157 | * to the EZ-USB GPIO output pins */ |
1155 | if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, | 1158 | if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, |
1156 | NULL, 0, 0) < 0) { | 1159 | NULL, 0, 0) < 0) { |
1157 | printk(KERN_ERR | 1160 | printk(KERN_ERR "go7007-usb: GPIO write failed!\n"); |
1158 | "go7007-usb: GPIO write failed!\n"); | ||
1159 | goto initfail; | 1161 | goto initfail; |
1160 | } | 1162 | } |
1161 | } | 1163 | } |
diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index 06cacd37bbd8..4bd353afa596 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <media/v4l2-common.h> | 30 | #include <media/v4l2-common.h> |
31 | #include <media/v4l2-ioctl.h> | 31 | #include <media/v4l2-ioctl.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/semaphore.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <asm/system.h> | 35 | #include <asm/system.h> |
36 | 36 | ||
@@ -75,7 +75,7 @@ static int go7007_streamoff(struct go7007 *go) | |||
75 | int retval = -EINVAL; | 75 | int retval = -EINVAL; |
76 | unsigned long flags; | 76 | unsigned long flags; |
77 | 77 | ||
78 | down(&go->hw_lock); | 78 | mutex_lock(&go->hw_lock); |
79 | if (go->streaming) { | 79 | if (go->streaming) { |
80 | go->streaming = 0; | 80 | go->streaming = 0; |
81 | go7007_stream_stop(go); | 81 | go7007_stream_stop(go); |
@@ -85,7 +85,7 @@ static int go7007_streamoff(struct go7007 *go) | |||
85 | go7007_reset_encoder(go); | 85 | go7007_reset_encoder(go); |
86 | retval = 0; | 86 | retval = 0; |
87 | } | 87 | } |
88 | up(&go->hw_lock); | 88 | mutex_unlock(&go->hw_lock); |
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
@@ -101,7 +101,7 @@ static int go7007_open(struct file *file) | |||
101 | return -ENOMEM; | 101 | return -ENOMEM; |
102 | ++go->ref_count; | 102 | ++go->ref_count; |
103 | gofh->go = go; | 103 | gofh->go = go; |
104 | init_MUTEX(&gofh->lock); | 104 | mutex_init(&gofh->lock); |
105 | gofh->buf_count = 0; | 105 | gofh->buf_count = 0; |
106 | file->private_data = gofh; | 106 | file->private_data = gofh; |
107 | return 0; | 107 | return 0; |
@@ -383,13 +383,10 @@ static int clip_to_modet_map(struct go7007 *go, int region, | |||
383 | } | 383 | } |
384 | return 0; | 384 | return 0; |
385 | } | 385 | } |
386 | #endif | ||
386 | 387 | ||
387 | static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl) | 388 | static int mpeg_queryctrl(struct v4l2_queryctrl *ctrl) |
388 | { | 389 | { |
389 | static const u32 user_ctrls[] = { | ||
390 | V4L2_CID_USER_CLASS, | ||
391 | 0 | ||
392 | }; | ||
393 | static const u32 mpeg_ctrls[] = { | 390 | static const u32 mpeg_ctrls[] = { |
394 | V4L2_CID_MPEG_CLASS, | 391 | V4L2_CID_MPEG_CLASS, |
395 | V4L2_CID_MPEG_STREAM_TYPE, | 392 | V4L2_CID_MPEG_STREAM_TYPE, |
@@ -401,26 +398,15 @@ static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl) | |||
401 | 0 | 398 | 0 |
402 | }; | 399 | }; |
403 | static const u32 *ctrl_classes[] = { | 400 | static const u32 *ctrl_classes[] = { |
404 | user_ctrls, | ||
405 | mpeg_ctrls, | 401 | mpeg_ctrls, |
406 | NULL | 402 | NULL |
407 | }; | 403 | }; |
408 | 404 | ||
409 | /* The ctrl may already contain the queried i2c controls, | 405 | ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id); |
410 | * query the mpeg controls if the existing ctrl id is | ||
411 | * greater than the next mpeg ctrl id. | ||
412 | */ | ||
413 | id = v4l2_ctrl_next(ctrl_classes, id); | ||
414 | if (id >= ctrl->id && ctrl->name[0]) | ||
415 | return 0; | ||
416 | |||
417 | memset(ctrl, 0, sizeof(*ctrl)); | ||
418 | ctrl->id = id; | ||
419 | 406 | ||
420 | switch (ctrl->id) { | 407 | switch (ctrl->id) { |
421 | case V4L2_CID_USER_CLASS: | ||
422 | case V4L2_CID_MPEG_CLASS: | 408 | case V4L2_CID_MPEG_CLASS: |
423 | return v4l2_ctrl_query_fill_std(ctrl); | 409 | return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0); |
424 | case V4L2_CID_MPEG_STREAM_TYPE: | 410 | case V4L2_CID_MPEG_STREAM_TYPE: |
425 | return v4l2_ctrl_query_fill(ctrl, | 411 | return v4l2_ctrl_query_fill(ctrl, |
426 | V4L2_MPEG_STREAM_TYPE_MPEG2_DVD, | 412 | V4L2_MPEG_STREAM_TYPE_MPEG2_DVD, |
@@ -437,20 +423,21 @@ static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl) | |||
437 | V4L2_MPEG_VIDEO_ASPECT_16x9, 1, | 423 | V4L2_MPEG_VIDEO_ASPECT_16x9, 1, |
438 | V4L2_MPEG_VIDEO_ASPECT_1x1); | 424 | V4L2_MPEG_VIDEO_ASPECT_1x1); |
439 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | 425 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: |
426 | return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15); | ||
440 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | 427 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
441 | return v4l2_ctrl_query_fill_std(ctrl); | 428 | return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); |
442 | case V4L2_CID_MPEG_VIDEO_BITRATE: | 429 | case V4L2_CID_MPEG_VIDEO_BITRATE: |
443 | return v4l2_ctrl_query_fill(ctrl, | 430 | return v4l2_ctrl_query_fill(ctrl, |
444 | 64000, | 431 | 64000, |
445 | 10000000, 1, | 432 | 10000000, 1, |
446 | 9800000); | 433 | 1500000); |
447 | default: | 434 | default: |
448 | break; | 435 | return -EINVAL; |
449 | } | 436 | } |
450 | return -EINVAL; | 437 | return 0; |
451 | } | 438 | } |
452 | 439 | ||
453 | static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go) | 440 | static int mpeg_s_ctrl(struct v4l2_control *ctrl, struct go7007 *go) |
454 | { | 441 | { |
455 | /* pretty sure we can't change any of these while streaming */ | 442 | /* pretty sure we can't change any of these while streaming */ |
456 | if (go->streaming) | 443 | if (go->streaming) |
@@ -528,6 +515,8 @@ static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go) | |||
528 | } | 515 | } |
529 | break; | 516 | break; |
530 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | 517 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: |
518 | if (ctrl->value < 0 || ctrl->value > 34) | ||
519 | return -EINVAL; | ||
531 | go->gop_size = ctrl->value; | 520 | go->gop_size = ctrl->value; |
532 | break; | 521 | break; |
533 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | 522 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
@@ -547,7 +536,7 @@ static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go) | |||
547 | return 0; | 536 | return 0; |
548 | } | 537 | } |
549 | 538 | ||
550 | static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go) | 539 | static int mpeg_g_ctrl(struct v4l2_control *ctrl, struct go7007 *go) |
551 | { | 540 | { |
552 | switch (ctrl->id) { | 541 | switch (ctrl->id) { |
553 | case V4L2_CID_MPEG_STREAM_TYPE: | 542 | case V4L2_CID_MPEG_STREAM_TYPE: |
@@ -600,13 +589,11 @@ static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go) | |||
600 | } | 589 | } |
601 | return 0; | 590 | return 0; |
602 | } | 591 | } |
603 | #endif | ||
604 | 592 | ||
605 | static int vidioc_querycap(struct file *file, void *priv, | 593 | static int vidioc_querycap(struct file *file, void *priv, |
606 | struct v4l2_capability *cap) | 594 | struct v4l2_capability *cap) |
607 | { | 595 | { |
608 | struct go7007_file *gofh = priv; | 596 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
609 | struct go7007 *go = gofh->go; | ||
610 | 597 | ||
611 | strlcpy(cap->driver, "go7007", sizeof(cap->driver)); | 598 | strlcpy(cap->driver, "go7007", sizeof(cap->driver)); |
612 | strlcpy(cap->card, go->name, sizeof(cap->card)); | 599 | strlcpy(cap->card, go->name, sizeof(cap->card)); |
@@ -653,8 +640,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
653 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 640 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
654 | struct v4l2_format *fmt) | 641 | struct v4l2_format *fmt) |
655 | { | 642 | { |
656 | struct go7007_file *gofh = priv; | 643 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
657 | struct go7007 *go = gofh->go; | ||
658 | 644 | ||
659 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 645 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
660 | fmt->fmt.pix.width = go->width; | 646 | fmt->fmt.pix.width = go->width; |
@@ -672,8 +658,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
672 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 658 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
673 | struct v4l2_format *fmt) | 659 | struct v4l2_format *fmt) |
674 | { | 660 | { |
675 | struct go7007_file *gofh = priv; | 661 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
676 | struct go7007 *go = gofh->go; | ||
677 | 662 | ||
678 | return set_capture_size(go, fmt, 1); | 663 | return set_capture_size(go, fmt, 1); |
679 | } | 664 | } |
@@ -681,8 +666,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
681 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 666 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
682 | struct v4l2_format *fmt) | 667 | struct v4l2_format *fmt) |
683 | { | 668 | { |
684 | struct go7007_file *gofh = priv; | 669 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
685 | struct go7007 *go = gofh->go; | ||
686 | 670 | ||
687 | if (go->streaming) | 671 | if (go->streaming) |
688 | return -EBUSY; | 672 | return -EBUSY; |
@@ -705,14 +689,14 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
705 | req->memory != V4L2_MEMORY_MMAP) | 689 | req->memory != V4L2_MEMORY_MMAP) |
706 | return -EINVAL; | 690 | return -EINVAL; |
707 | 691 | ||
708 | down(&gofh->lock); | 692 | mutex_lock(&gofh->lock); |
709 | for (i = 0; i < gofh->buf_count; ++i) | 693 | for (i = 0; i < gofh->buf_count; ++i) |
710 | if (gofh->bufs[i].mapped > 0) | 694 | if (gofh->bufs[i].mapped > 0) |
711 | goto unlock_and_return; | 695 | goto unlock_and_return; |
712 | 696 | ||
713 | down(&go->hw_lock); | 697 | mutex_lock(&go->hw_lock); |
714 | if (go->in_use > 0 && gofh->buf_count == 0) { | 698 | if (go->in_use > 0 && gofh->buf_count == 0) { |
715 | up(&go->hw_lock); | 699 | mutex_unlock(&go->hw_lock); |
716 | goto unlock_and_return; | 700 | goto unlock_and_return; |
717 | } | 701 | } |
718 | 702 | ||
@@ -731,7 +715,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
731 | GFP_KERNEL); | 715 | GFP_KERNEL); |
732 | 716 | ||
733 | if (!gofh->bufs) { | 717 | if (!gofh->bufs) { |
734 | up(&go->hw_lock); | 718 | mutex_unlock(&go->hw_lock); |
735 | goto unlock_and_return; | 719 | goto unlock_and_return; |
736 | } | 720 | } |
737 | 721 | ||
@@ -750,8 +734,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
750 | } | 734 | } |
751 | 735 | ||
752 | gofh->buf_count = count; | 736 | gofh->buf_count = count; |
753 | up(&go->hw_lock); | 737 | mutex_unlock(&go->hw_lock); |
754 | up(&gofh->lock); | 738 | mutex_unlock(&gofh->lock); |
755 | 739 | ||
756 | memset(req, 0, sizeof(*req)); | 740 | memset(req, 0, sizeof(*req)); |
757 | 741 | ||
@@ -762,7 +746,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
762 | return 0; | 746 | return 0; |
763 | 747 | ||
764 | unlock_and_return: | 748 | unlock_and_return: |
765 | up(&gofh->lock); | 749 | mutex_unlock(&gofh->lock); |
766 | return retval; | 750 | return retval; |
767 | } | 751 | } |
768 | 752 | ||
@@ -778,7 +762,7 @@ static int vidioc_querybuf(struct file *file, void *priv, | |||
778 | 762 | ||
779 | index = buf->index; | 763 | index = buf->index; |
780 | 764 | ||
781 | down(&gofh->lock); | 765 | mutex_lock(&gofh->lock); |
782 | if (index >= gofh->buf_count) | 766 | if (index >= gofh->buf_count) |
783 | goto unlock_and_return; | 767 | goto unlock_and_return; |
784 | 768 | ||
@@ -802,12 +786,12 @@ static int vidioc_querybuf(struct file *file, void *priv, | |||
802 | buf->memory = V4L2_MEMORY_MMAP; | 786 | buf->memory = V4L2_MEMORY_MMAP; |
803 | buf->m.offset = index * GO7007_BUF_SIZE; | 787 | buf->m.offset = index * GO7007_BUF_SIZE; |
804 | buf->length = GO7007_BUF_SIZE; | 788 | buf->length = GO7007_BUF_SIZE; |
805 | up(&gofh->lock); | 789 | mutex_unlock(&gofh->lock); |
806 | 790 | ||
807 | return 0; | 791 | return 0; |
808 | 792 | ||
809 | unlock_and_return: | 793 | unlock_and_return: |
810 | up(&gofh->lock); | 794 | mutex_unlock(&gofh->lock); |
811 | return retval; | 795 | return retval; |
812 | } | 796 | } |
813 | 797 | ||
@@ -824,7 +808,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
824 | buf->memory != V4L2_MEMORY_MMAP) | 808 | buf->memory != V4L2_MEMORY_MMAP) |
825 | return retval; | 809 | return retval; |
826 | 810 | ||
827 | down(&gofh->lock); | 811 | mutex_lock(&gofh->lock); |
828 | if (buf->index < 0 || buf->index >= gofh->buf_count) | 812 | if (buf->index < 0 || buf->index >= gofh->buf_count) |
829 | goto unlock_and_return; | 813 | goto unlock_and_return; |
830 | 814 | ||
@@ -865,12 +849,12 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
865 | spin_lock_irqsave(&go->spinlock, flags); | 849 | spin_lock_irqsave(&go->spinlock, flags); |
866 | list_add_tail(&gobuf->stream, &go->stream); | 850 | list_add_tail(&gobuf->stream, &go->stream); |
867 | spin_unlock_irqrestore(&go->spinlock, flags); | 851 | spin_unlock_irqrestore(&go->spinlock, flags); |
868 | up(&gofh->lock); | 852 | mutex_unlock(&gofh->lock); |
869 | 853 | ||
870 | return 0; | 854 | return 0; |
871 | 855 | ||
872 | unlock_and_return: | 856 | unlock_and_return: |
873 | up(&gofh->lock); | 857 | mutex_unlock(&gofh->lock); |
874 | return retval; | 858 | return retval; |
875 | } | 859 | } |
876 | 860 | ||
@@ -890,7 +874,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
890 | if (buf->memory != V4L2_MEMORY_MMAP) | 874 | if (buf->memory != V4L2_MEMORY_MMAP) |
891 | return retval; | 875 | return retval; |
892 | 876 | ||
893 | down(&gofh->lock); | 877 | mutex_lock(&gofh->lock); |
894 | if (list_empty(&go->stream)) | 878 | if (list_empty(&go->stream)) |
895 | goto unlock_and_return; | 879 | goto unlock_and_return; |
896 | gobuf = list_entry(go->stream.next, | 880 | gobuf = list_entry(go->stream.next, |
@@ -934,11 +918,11 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
934 | buf->length = GO7007_BUF_SIZE; | 918 | buf->length = GO7007_BUF_SIZE; |
935 | buf->reserved = gobuf->modet_active; | 919 | buf->reserved = gobuf->modet_active; |
936 | 920 | ||
937 | up(&gofh->lock); | 921 | mutex_unlock(&gofh->lock); |
938 | return 0; | 922 | return 0; |
939 | 923 | ||
940 | unlock_and_return: | 924 | unlock_and_return: |
941 | up(&gofh->lock); | 925 | mutex_unlock(&gofh->lock); |
942 | return retval; | 926 | return retval; |
943 | } | 927 | } |
944 | 928 | ||
@@ -952,8 +936,8 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
952 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 936 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
953 | return -EINVAL; | 937 | return -EINVAL; |
954 | 938 | ||
955 | down(&gofh->lock); | 939 | mutex_lock(&gofh->lock); |
956 | down(&go->hw_lock); | 940 | mutex_lock(&go->hw_lock); |
957 | 941 | ||
958 | if (!go->streaming) { | 942 | if (!go->streaming) { |
959 | go->streaming = 1; | 943 | go->streaming = 1; |
@@ -964,8 +948,8 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
964 | else | 948 | else |
965 | retval = 0; | 949 | retval = 0; |
966 | } | 950 | } |
967 | up(&go->hw_lock); | 951 | mutex_unlock(&go->hw_lock); |
968 | up(&gofh->lock); | 952 | mutex_unlock(&gofh->lock); |
969 | 953 | ||
970 | return retval; | 954 | return retval; |
971 | } | 955 | } |
@@ -978,9 +962,9 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
978 | 962 | ||
979 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 963 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
980 | return -EINVAL; | 964 | return -EINVAL; |
981 | down(&gofh->lock); | 965 | mutex_lock(&gofh->lock); |
982 | go7007_streamoff(go); | 966 | go7007_streamoff(go); |
983 | up(&gofh->lock); | 967 | mutex_unlock(&gofh->lock); |
984 | 968 | ||
985 | return 0; | 969 | return 0; |
986 | } | 970 | } |
@@ -988,22 +972,20 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
988 | static int vidioc_queryctrl(struct file *file, void *priv, | 972 | static int vidioc_queryctrl(struct file *file, void *priv, |
989 | struct v4l2_queryctrl *query) | 973 | struct v4l2_queryctrl *query) |
990 | { | 974 | { |
991 | struct go7007_file *gofh = priv; | 975 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
992 | struct go7007 *go = gofh->go; | ||
993 | 976 | ||
994 | if (!go->i2c_adapter_online) | 977 | if (!go->i2c_adapter_online) |
995 | return -EIO; | 978 | return -EIO; |
996 | 979 | ||
997 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query); | 980 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query); |
998 | 981 | ||
999 | return (!query->name[0]) ? -EINVAL : 0; | 982 | return (!query->name[0]) ? mpeg_queryctrl(query) : 0; |
1000 | } | 983 | } |
1001 | 984 | ||
1002 | static int vidioc_g_ctrl(struct file *file, void *priv, | 985 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1003 | struct v4l2_control *ctrl) | 986 | struct v4l2_control *ctrl) |
1004 | { | 987 | { |
1005 | struct go7007_file *gofh = priv; | 988 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1006 | struct go7007 *go = gofh->go; | ||
1007 | struct v4l2_queryctrl query; | 989 | struct v4l2_queryctrl query; |
1008 | 990 | ||
1009 | if (!go->i2c_adapter_online) | 991 | if (!go->i2c_adapter_online) |
@@ -1013,7 +995,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1013 | query.id = ctrl->id; | 995 | query.id = ctrl->id; |
1014 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); | 996 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); |
1015 | if (query.name[0] == 0) | 997 | if (query.name[0] == 0) |
1016 | return -EINVAL; | 998 | return mpeg_g_ctrl(ctrl, go); |
1017 | i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl); | 999 | i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl); |
1018 | 1000 | ||
1019 | return 0; | 1001 | return 0; |
@@ -1022,8 +1004,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1022 | static int vidioc_s_ctrl(struct file *file, void *priv, | 1004 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1023 | struct v4l2_control *ctrl) | 1005 | struct v4l2_control *ctrl) |
1024 | { | 1006 | { |
1025 | struct go7007_file *gofh = priv; | 1007 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1026 | struct go7007 *go = gofh->go; | ||
1027 | struct v4l2_queryctrl query; | 1008 | struct v4l2_queryctrl query; |
1028 | 1009 | ||
1029 | if (!go->i2c_adapter_online) | 1010 | if (!go->i2c_adapter_online) |
@@ -1033,7 +1014,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1033 | query.id = ctrl->id; | 1014 | query.id = ctrl->id; |
1034 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); | 1015 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); |
1035 | if (query.name[0] == 0) | 1016 | if (query.name[0] == 0) |
1036 | return -EINVAL; | 1017 | return mpeg_s_ctrl(ctrl, go); |
1037 | i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl); | 1018 | i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl); |
1038 | 1019 | ||
1039 | return 0; | 1020 | return 0; |
@@ -1042,8 +1023,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1042 | static int vidioc_g_parm(struct file *filp, void *priv, | 1023 | static int vidioc_g_parm(struct file *filp, void *priv, |
1043 | struct v4l2_streamparm *parm) | 1024 | struct v4l2_streamparm *parm) |
1044 | { | 1025 | { |
1045 | struct go7007_file *gofh = priv; | 1026 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1046 | struct go7007 *go = gofh->go; | ||
1047 | struct v4l2_fract timeperframe = { | 1027 | struct v4l2_fract timeperframe = { |
1048 | .numerator = 1001 * go->fps_scale, | 1028 | .numerator = 1001 * go->fps_scale, |
1049 | .denominator = go->sensor_framerate, | 1029 | .denominator = go->sensor_framerate, |
@@ -1061,8 +1041,7 @@ static int vidioc_g_parm(struct file *filp, void *priv, | |||
1061 | static int vidioc_s_parm(struct file *filp, void *priv, | 1041 | static int vidioc_s_parm(struct file *filp, void *priv, |
1062 | struct v4l2_streamparm *parm) | 1042 | struct v4l2_streamparm *parm) |
1063 | { | 1043 | { |
1064 | struct go7007_file *gofh = priv; | 1044 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1065 | struct go7007 *go = gofh->go; | ||
1066 | unsigned int n, d; | 1045 | unsigned int n, d; |
1067 | 1046 | ||
1068 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1047 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
@@ -1094,8 +1073,7 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1094 | static int vidioc_enum_framesizes(struct file *filp, void *priv, | 1073 | static int vidioc_enum_framesizes(struct file *filp, void *priv, |
1095 | struct v4l2_frmsizeenum *fsize) | 1074 | struct v4l2_frmsizeenum *fsize) |
1096 | { | 1075 | { |
1097 | struct go7007_file *gofh = priv; | 1076 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1098 | struct go7007 *go = gofh->go; | ||
1099 | 1077 | ||
1100 | /* Return -EINVAL, if it is a TV board */ | 1078 | /* Return -EINVAL, if it is a TV board */ |
1101 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || | 1079 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || |
@@ -1115,8 +1093,7 @@ static int vidioc_enum_framesizes(struct file *filp, void *priv, | |||
1115 | static int vidioc_enum_frameintervals(struct file *filp, void *priv, | 1093 | static int vidioc_enum_frameintervals(struct file *filp, void *priv, |
1116 | struct v4l2_frmivalenum *fival) | 1094 | struct v4l2_frmivalenum *fival) |
1117 | { | 1095 | { |
1118 | struct go7007_file *gofh = priv; | 1096 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1119 | struct go7007 *go = gofh->go; | ||
1120 | 1097 | ||
1121 | /* Return -EINVAL, if it is a TV board */ | 1098 | /* Return -EINVAL, if it is a TV board */ |
1122 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || | 1099 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || |
@@ -1133,10 +1110,27 @@ static int vidioc_enum_frameintervals(struct file *filp, void *priv, | |||
1133 | return 0; | 1110 | return 0; |
1134 | } | 1111 | } |
1135 | 1112 | ||
1113 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) | ||
1114 | { | ||
1115 | struct go7007 *go = ((struct go7007_file *) priv)->go; | ||
1116 | |||
1117 | switch (go->standard) { | ||
1118 | case GO7007_STD_NTSC: | ||
1119 | *std = V4L2_STD_NTSC; | ||
1120 | break; | ||
1121 | case GO7007_STD_PAL: | ||
1122 | *std = V4L2_STD_PAL; | ||
1123 | break; | ||
1124 | default: | ||
1125 | return -EINVAL; | ||
1126 | } | ||
1127 | |||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1136 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) | 1131 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) |
1137 | { | 1132 | { |
1138 | struct go7007_file *gofh = priv; | 1133 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1139 | struct go7007 *go = gofh->go; | ||
1140 | 1134 | ||
1141 | if (go->streaming) | 1135 | if (go->streaming) |
1142 | return -EBUSY; | 1136 | return -EBUSY; |
@@ -1178,30 +1172,27 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) | |||
1178 | return 0; | 1172 | return 0; |
1179 | } | 1173 | } |
1180 | 1174 | ||
1181 | #if 0 | 1175 | static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) |
1182 | case VIDIOC_QUERYSTD: | 1176 | { |
1183 | { | 1177 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1184 | v4l2_std_id *std = arg; | ||
1185 | 1178 | ||
1186 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && | 1179 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && |
1187 | go->input == go->board_info->num_inputs - 1) { | 1180 | go->input == go->board_info->num_inputs - 1) { |
1188 | if (!go->i2c_adapter_online) | 1181 | if (!go->i2c_adapter_online) |
1189 | return -EIO; | 1182 | return -EIO; |
1190 | i2c_clients_command(&go->i2c_adapter, | 1183 | i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYSTD, std); |
1191 | VIDIOC_QUERYSTD, arg); | 1184 | } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) |
1192 | } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) | 1185 | *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; |
1193 | *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; | 1186 | else |
1194 | else | 1187 | *std = 0; |
1195 | *std = 0; | 1188 | |
1196 | return 0; | 1189 | return 0; |
1197 | } | 1190 | } |
1198 | #endif | ||
1199 | 1191 | ||
1200 | static int vidioc_enum_input(struct file *file, void *priv, | 1192 | static int vidioc_enum_input(struct file *file, void *priv, |
1201 | struct v4l2_input *inp) | 1193 | struct v4l2_input *inp) |
1202 | { | 1194 | { |
1203 | struct go7007_file *gofh = priv; | 1195 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1204 | struct go7007 *go = gofh->go; | ||
1205 | 1196 | ||
1206 | if (inp->index >= go->board_info->num_inputs) | 1197 | if (inp->index >= go->board_info->num_inputs) |
1207 | return -EINVAL; | 1198 | return -EINVAL; |
@@ -1230,8 +1221,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1230 | 1221 | ||
1231 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) | 1222 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) |
1232 | { | 1223 | { |
1233 | struct go7007_file *gofh = priv; | 1224 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1234 | struct go7007 *go = gofh->go; | ||
1235 | 1225 | ||
1236 | *input = go->input; | 1226 | *input = go->input; |
1237 | 1227 | ||
@@ -1240,8 +1230,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) | |||
1240 | 1230 | ||
1241 | static int vidioc_s_input(struct file *file, void *priv, unsigned int input) | 1231 | static int vidioc_s_input(struct file *file, void *priv, unsigned int input) |
1242 | { | 1232 | { |
1243 | struct go7007_file *gofh = priv; | 1233 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1244 | struct go7007 *go = gofh->go; | ||
1245 | 1234 | ||
1246 | if (input >= go->board_info->num_inputs) | 1235 | if (input >= go->board_info->num_inputs) |
1247 | return -EINVAL; | 1236 | return -EINVAL; |
@@ -1262,8 +1251,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input) | |||
1262 | static int vidioc_g_tuner(struct file *file, void *priv, | 1251 | static int vidioc_g_tuner(struct file *file, void *priv, |
1263 | struct v4l2_tuner *t) | 1252 | struct v4l2_tuner *t) |
1264 | { | 1253 | { |
1265 | struct go7007_file *gofh = priv; | 1254 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1266 | struct go7007 *go = gofh->go; | ||
1267 | 1255 | ||
1268 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) | 1256 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) |
1269 | return -EINVAL; | 1257 | return -EINVAL; |
@@ -1281,8 +1269,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
1281 | static int vidioc_s_tuner(struct file *file, void *priv, | 1269 | static int vidioc_s_tuner(struct file *file, void *priv, |
1282 | struct v4l2_tuner *t) | 1270 | struct v4l2_tuner *t) |
1283 | { | 1271 | { |
1284 | struct go7007_file *gofh = priv; | 1272 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1285 | struct go7007 *go = gofh->go; | ||
1286 | 1273 | ||
1287 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) | 1274 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) |
1288 | return -EINVAL; | 1275 | return -EINVAL; |
@@ -1308,8 +1295,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
1308 | static int vidioc_g_frequency(struct file *file, void *priv, | 1295 | static int vidioc_g_frequency(struct file *file, void *priv, |
1309 | struct v4l2_frequency *f) | 1296 | struct v4l2_frequency *f) |
1310 | { | 1297 | { |
1311 | struct go7007_file *gofh = priv; | 1298 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1312 | struct go7007 *go = gofh->go; | ||
1313 | 1299 | ||
1314 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) | 1300 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) |
1315 | return -EINVAL; | 1301 | return -EINVAL; |
@@ -1324,8 +1310,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1324 | static int vidioc_s_frequency(struct file *file, void *priv, | 1310 | static int vidioc_s_frequency(struct file *file, void *priv, |
1325 | struct v4l2_frequency *f) | 1311 | struct v4l2_frequency *f) |
1326 | { | 1312 | { |
1327 | struct go7007_file *gofh = priv; | 1313 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1328 | struct go7007 *go = gofh->go; | ||
1329 | 1314 | ||
1330 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) | 1315 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) |
1331 | return -EINVAL; | 1316 | return -EINVAL; |
@@ -1340,8 +1325,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
1340 | static int vidioc_cropcap(struct file *file, void *priv, | 1325 | static int vidioc_cropcap(struct file *file, void *priv, |
1341 | struct v4l2_cropcap *cropcap) | 1326 | struct v4l2_cropcap *cropcap) |
1342 | { | 1327 | { |
1343 | struct go7007_file *gofh = priv; | 1328 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1344 | struct go7007 *go = gofh->go; | ||
1345 | 1329 | ||
1346 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1330 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1347 | return -EINVAL; | 1331 | return -EINVAL; |
@@ -1385,8 +1369,7 @@ static int vidioc_cropcap(struct file *file, void *priv, | |||
1385 | 1369 | ||
1386 | static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) | 1370 | static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) |
1387 | { | 1371 | { |
1388 | struct go7007_file *gofh = priv; | 1372 | struct go7007 *go = ((struct go7007_file *) priv)->go; |
1389 | struct go7007 *go = gofh->go; | ||
1390 | 1373 | ||
1391 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1374 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1392 | return -EINVAL; | 1375 | return -EINVAL; |
@@ -1734,18 +1717,18 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma) | |||
1734 | return -EINVAL; /* only support VM_SHARED mapping */ | 1717 | return -EINVAL; /* only support VM_SHARED mapping */ |
1735 | if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE) | 1718 | if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE) |
1736 | return -EINVAL; /* must map exactly one full buffer */ | 1719 | return -EINVAL; /* must map exactly one full buffer */ |
1737 | down(&gofh->lock); | 1720 | mutex_lock(&gofh->lock); |
1738 | index = vma->vm_pgoff / GO7007_BUF_PAGES; | 1721 | index = vma->vm_pgoff / GO7007_BUF_PAGES; |
1739 | if (index >= gofh->buf_count) { | 1722 | if (index >= gofh->buf_count) { |
1740 | up(&gofh->lock); | 1723 | mutex_unlock(&gofh->lock); |
1741 | return -EINVAL; /* trying to map beyond requested buffers */ | 1724 | return -EINVAL; /* trying to map beyond requested buffers */ |
1742 | } | 1725 | } |
1743 | if (index * GO7007_BUF_PAGES != vma->vm_pgoff) { | 1726 | if (index * GO7007_BUF_PAGES != vma->vm_pgoff) { |
1744 | up(&gofh->lock); | 1727 | mutex_unlock(&gofh->lock); |
1745 | return -EINVAL; /* offset is not aligned on buffer boundary */ | 1728 | return -EINVAL; /* offset is not aligned on buffer boundary */ |
1746 | } | 1729 | } |
1747 | if (gofh->bufs[index].mapped > 0) { | 1730 | if (gofh->bufs[index].mapped > 0) { |
1748 | up(&gofh->lock); | 1731 | mutex_unlock(&gofh->lock); |
1749 | return -EBUSY; | 1732 | return -EBUSY; |
1750 | } | 1733 | } |
1751 | gofh->bufs[index].mapped = 1; | 1734 | gofh->bufs[index].mapped = 1; |
@@ -1754,7 +1737,7 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma) | |||
1754 | vma->vm_flags |= VM_DONTEXPAND; | 1737 | vma->vm_flags |= VM_DONTEXPAND; |
1755 | vma->vm_flags &= ~VM_IO; | 1738 | vma->vm_flags &= ~VM_IO; |
1756 | vma->vm_private_data = &gofh->bufs[index]; | 1739 | vma->vm_private_data = &gofh->bufs[index]; |
1757 | up(&gofh->lock); | 1740 | mutex_unlock(&gofh->lock); |
1758 | return 0; | 1741 | return 0; |
1759 | } | 1742 | } |
1760 | 1743 | ||
@@ -1801,7 +1784,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1801 | .vidioc_querybuf = vidioc_querybuf, | 1784 | .vidioc_querybuf = vidioc_querybuf, |
1802 | .vidioc_qbuf = vidioc_qbuf, | 1785 | .vidioc_qbuf = vidioc_qbuf, |
1803 | .vidioc_dqbuf = vidioc_dqbuf, | 1786 | .vidioc_dqbuf = vidioc_dqbuf, |
1787 | .vidioc_g_std = vidioc_g_std, | ||
1804 | .vidioc_s_std = vidioc_s_std, | 1788 | .vidioc_s_std = vidioc_s_std, |
1789 | .vidioc_querystd = vidioc_querystd, | ||
1805 | .vidioc_enum_input = vidioc_enum_input, | 1790 | .vidioc_enum_input = vidioc_enum_input, |
1806 | .vidioc_g_input = vidioc_g_input, | 1791 | .vidioc_g_input = vidioc_g_input, |
1807 | .vidioc_s_input = vidioc_s_input, | 1792 | .vidioc_s_input = vidioc_s_input, |
@@ -1862,7 +1847,7 @@ void go7007_v4l2_remove(struct go7007 *go) | |||
1862 | { | 1847 | { |
1863 | unsigned long flags; | 1848 | unsigned long flags; |
1864 | 1849 | ||
1865 | down(&go->hw_lock); | 1850 | mutex_lock(&go->hw_lock); |
1866 | if (go->streaming) { | 1851 | if (go->streaming) { |
1867 | go->streaming = 0; | 1852 | go->streaming = 0; |
1868 | go7007_stream_stop(go); | 1853 | go7007_stream_stop(go); |
@@ -1870,7 +1855,7 @@ void go7007_v4l2_remove(struct go7007 *go) | |||
1870 | abort_queued(go); | 1855 | abort_queued(go); |
1871 | spin_unlock_irqrestore(&go->spinlock, flags); | 1856 | spin_unlock_irqrestore(&go->spinlock, flags); |
1872 | } | 1857 | } |
1873 | up(&go->hw_lock); | 1858 | mutex_unlock(&go->hw_lock); |
1874 | if (go->video_dev) | 1859 | if (go->video_dev) |
1875 | video_unregister_device(go->video_dev); | 1860 | video_unregister_device(go->video_dev); |
1876 | } | 1861 | } |
diff --git a/drivers/staging/go7007/go7007.txt b/drivers/staging/go7007/go7007.txt index 1c2907c1dc81..06a76da32128 100644 --- a/drivers/staging/go7007/go7007.txt +++ b/drivers/staging/go7007/go7007.txt | |||
@@ -2,7 +2,7 @@ This is a driver for the WIS GO7007SB multi-format video encoder. | |||
2 | 2 | ||
3 | Pete Eberlein <pete@sensoray.com> | 3 | Pete Eberlein <pete@sensoray.com> |
4 | 4 | ||
5 | The driver was originally released under the GPL and is currently hosted at: | 5 | The driver was orignally released under the GPL and is currently hosted at: |
6 | http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver | 6 | http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver |
7 | The go7007 firmware can be acquired from the package on the site above. | 7 | The go7007 firmware can be acquired from the package on the site above. |
8 | 8 | ||
@@ -24,10 +24,10 @@ These should be used instead of the non-standard GO7007 ioctls described | |||
24 | below. | 24 | below. |
25 | 25 | ||
26 | 26 | ||
27 | The README files from the original package appears below: | 27 | The README files from the orignal package appear below: |
28 | 28 | ||
29 | --------------------------------------------------------------------------- | 29 | --------------------------------------------------------------------------- |
30 | WIS GO7007SB Public Linux Driver | 30 | WIS GO7007SB Public Linux Driver |
31 | --------------------------------------------------------------------------- | 31 | --------------------------------------------------------------------------- |
32 | 32 | ||
33 | 33 | ||
@@ -78,23 +78,23 @@ All vendor-built kernels should already be configured properly. However, | |||
78 | for custom-built kernels, the following options need to be enabled in the | 78 | for custom-built kernels, the following options need to be enabled in the |
79 | kernel as built-in or modules: | 79 | kernel as built-in or modules: |
80 | 80 | ||
81 | CONFIG_HOTPLUG - Support for hot-pluggable devices | 81 | CONFIG_HOTPLUG - Support for hot-pluggable devices |
82 | CONFIG_MODULES - Enable loadable module support | 82 | CONFIG_MODULES - Enable loadable module support |
83 | CONFIG_KMOD - Automatic kernel module loading | 83 | CONFIG_KMOD - Automatic kernel module loading |
84 | CONFIG_FW_LOADER - Hotplug firmware loading support | 84 | CONFIG_FW_LOADER - Hotplug firmware loading support |
85 | CONFIG_I2C - I2C support | 85 | CONFIG_I2C - I2C support |
86 | CONFIG_VIDEO_DEV - Video For Linux | 86 | CONFIG_VIDEO_DEV - Video For Linux |
87 | CONFIG_SOUND - Sound card support | 87 | CONFIG_SOUND - Sound card support |
88 | CONFIG_SND - Advanced Linux Sound Architecture | 88 | CONFIG_SND - Advanced Linux Sound Architecture |
89 | CONFIG_USB - Support for Host-side USB | 89 | CONFIG_USB - Support for Host-side USB |
90 | CONFIG_USB_DEVICEFS - USB device filesystem | 90 | CONFIG_USB_DEVICEFS - USB device filesystem |
91 | CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support | 91 | CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support |
92 | 92 | ||
93 | Additionally, to use the example application, the following options need to | 93 | Additionally, to use the example application, the following options need to |
94 | be enabled in the ALSA section: | 94 | be enabled in the ALSA section: |
95 | 95 | ||
96 | CONFIG_SND_MIXER_OSS - OSS Mixer API | 96 | CONFIG_SND_MIXER_OSS - OSS Mixer API |
97 | CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API | 97 | CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API |
98 | 98 | ||
99 | The hotplug scripts, along with the fxload utility, must also be installed. | 99 | The hotplug scripts, along with the fxload utility, must also be installed. |
100 | These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>. | 100 | These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>. |
@@ -107,7 +107,7 @@ fxload and for loading firmware into the driver using the firmware agent. | |||
107 | 107 | ||
108 | Most users should be able to compile the driver by simply running: | 108 | Most users should be able to compile the driver by simply running: |
109 | 109 | ||
110 | $ make | 110 | $ make |
111 | 111 | ||
112 | in the top-level directory of the driver kit. First the kernel modules | 112 | in the top-level directory of the driver kit. First the kernel modules |
113 | will be built, followed by the example applications. | 113 | will be built, followed by the example applications. |
@@ -117,12 +117,12 @@ currently-running kernel, or if the module should be built for a kernel | |||
117 | other than the currently-running kernel, an additional parameter will need | 117 | other than the currently-running kernel, an additional parameter will need |
118 | to be passed to make to specify the appropriate kernel source directory: | 118 | to be passed to make to specify the appropriate kernel source directory: |
119 | 119 | ||
120 | $ make KERNELSRC=/usr/src/linux-2.6.10-custom3 | 120 | $ make KERNELSRC=/usr/src/linux-2.6.10-custom3 |
121 | 121 | ||
122 | Once the compile completes, the driver and firmware files should be | 122 | Once the compile completes, the driver and firmware files should be |
123 | installed by running: | 123 | installed by running: |
124 | 124 | ||
125 | $ make install | 125 | $ make install |
126 | 126 | ||
127 | The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra" | 127 | The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra" |
128 | and the firmware files will be placed in the appropriate hotplug firmware | 128 | and the firmware files will be placed in the appropriate hotplug firmware |
@@ -200,7 +200,7 @@ stereo audio broadcasts on the A2 carrier. | |||
200 | To verify that the configuration has been placed in the correct location, | 200 | To verify that the configuration has been placed in the correct location, |
201 | execute: | 201 | execute: |
202 | 202 | ||
203 | $ modprobe -c | grep wis-sony-tuner | 203 | $ modprobe -c | grep wis-sony-tuner |
204 | 204 | ||
205 | If the configuration line appears, then modprobe will pass the parameters | 205 | If the configuration line appears, then modprobe will pass the parameters |
206 | correctly the next time the wis-sony-tuner module is loaded into the | 206 | correctly the next time the wis-sony-tuner module is loaded into the |
@@ -223,7 +223,7 @@ This application will auto-detect the V4L2 and ALSA/OSS device names of the | |||
223 | hardware and will record video and audio to an AVI file for a specified | 223 | hardware and will record video and audio to an AVI file for a specified |
224 | number of seconds. For example: | 224 | number of seconds. For example: |
225 | 225 | ||
226 | $ apps/gorecord -duration 60 capture.avi | 226 | $ apps/gorecord -duration 60 capture.avi |
227 | 227 | ||
228 | If this application does not successfully record an AVI file, the error | 228 | If this application does not successfully record an AVI file, the error |
229 | messages produced by gorecord and recorded in the system log (usually in | 229 | messages produced by gorecord and recorded in the system log (usually in |
@@ -286,35 +286,35 @@ features of the GO7007SB encoder, which are described below: | |||
286 | 286 | ||
287 | Fields in struct go7007_comp_params: | 287 | Fields in struct go7007_comp_params: |
288 | 288 | ||
289 | __u32 The maximum number of frames in each | 289 | __u32 The maximum number of frames in each |
290 | gop_size Group Of Pictures; i.e. the maximum | 290 | gop_size Group Of Pictures; i.e. the maximum |
291 | number of frames minus one between | 291 | number of frames minus one between |
292 | each key frame. | 292 | each key frame. |
293 | 293 | ||
294 | __u32 The maximum number of sequential | 294 | __u32 The maximum number of sequential |
295 | max_b_frames bidirectionally-predicted frames. | 295 | max_b_frames bidirectionally-predicted frames. |
296 | (B-frames are not yet supported.) | 296 | (B-frames are not yet supported.) |
297 | 297 | ||
298 | enum go7007_aspect_ratio The aspect ratio to be encoded in the | 298 | enum go7007_aspect_ratio The aspect ratio to be encoded in the |
299 | aspect_ratio meta-data of the compressed format. | 299 | aspect_ratio meta-data of the compressed format. |
300 | 300 | ||
301 | Choices are: | 301 | Choices are: |
302 | GO7007_ASPECT_RATIO_1_1 | 302 | GO7007_ASPECT_RATIO_1_1 |
303 | GO7007_ASPECT_RATIO_4_3_NTSC | 303 | GO7007_ASPECT_RATIO_4_3_NTSC |
304 | GO7007_ASPECT_RATIO_4_3_PAL | 304 | GO7007_ASPECT_RATIO_4_3_PAL |
305 | GO7007_ASPECT_RATIO_16_9_NTSC | 305 | GO7007_ASPECT_RATIO_16_9_NTSC |
306 | GO7007_ASPECT_RATIO_16_9_PAL | 306 | GO7007_ASPECT_RATIO_16_9_PAL |
307 | 307 | ||
308 | __u32 Bit-wise OR of control flags (below) | 308 | __u32 Bit-wise OR of control flags (below) |
309 | flags | 309 | flags |
310 | 310 | ||
311 | Flags in struct go7007_comp_params: | 311 | Flags in struct go7007_comp_params: |
312 | 312 | ||
313 | GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used | 313 | GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used |
314 | to produce streams appropriate for | 314 | to produce streams appropriate for |
315 | random seeking. | 315 | random seeking. |
316 | 316 | ||
317 | GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header. | 317 | GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header. |
318 | 318 | ||
319 | 319 | ||
320 | GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS | 320 | GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS |
@@ -337,56 +337,56 @@ features of the GO7007SB encoder, which are described below: | |||
337 | 337 | ||
338 | Fields in struct go7007_mpeg_params: | 338 | Fields in struct go7007_mpeg_params: |
339 | 339 | ||
340 | enum go7007_mpeg_video_standard | 340 | enum go7007_mpeg_video_standard |
341 | mpeg_video_standard The MPEG video standard in which to | 341 | mpeg_video_standard The MPEG video standard in which to |
342 | compress the video. | 342 | compress the video. |
343 | 343 | ||
344 | Choices are: | 344 | Choices are: |
345 | GO7007_MPEG_VIDEO_MPEG1 | 345 | GO7007_MPEG_VIDEO_MPEG1 |
346 | GO7007_MPEG_VIDEO_MPEG2 | 346 | GO7007_MPEG_VIDEO_MPEG2 |
347 | GO7007_MPEG_VIDEO_MPEG4 | 347 | GO7007_MPEG_VIDEO_MPEG4 |
348 | 348 | ||
349 | __u32 Bit-wise OR of control flags (below) | 349 | __u32 Bit-wise OR of control flags (below) |
350 | flags | 350 | flags |
351 | 351 | ||
352 | __u32 The profile and level indication to be | 352 | __u32 The profile and level indication to be |
353 | pali stored in the sequence header. This | 353 | pali stored in the sequence header. This |
354 | is only used as an indicator to the | 354 | is only used as an indicator to the |
355 | decoder, and does not affect the MPEG | 355 | decoder, and does not affect the MPEG |
356 | features used in the video stream. | 356 | features used in the video stream. |
357 | Not valid for MPEG1. | 357 | Not valid for MPEG1. |
358 | 358 | ||
359 | Choices for MPEG2 are: | 359 | Choices for MPEG2 are: |
360 | GO7007_MPEG2_PROFILE_MAIN_MAIN | 360 | GO7007_MPEG2_PROFILE_MAIN_MAIN |
361 | 361 | ||
362 | Choices for MPEG4 are: | 362 | Choices for MPEG4 are: |
363 | GO7007_MPEG4_PROFILE_S_L0 | 363 | GO7007_MPEG4_PROFILE_S_L0 |
364 | GO7007_MPEG4_PROFILE_S_L1 | 364 | GO7007_MPEG4_PROFILE_S_L1 |
365 | GO7007_MPEG4_PROFILE_S_L2 | 365 | GO7007_MPEG4_PROFILE_S_L2 |
366 | GO7007_MPEG4_PROFILE_S_L3 | 366 | GO7007_MPEG4_PROFILE_S_L3 |
367 | GO7007_MPEG4_PROFILE_ARTS_L1 | 367 | GO7007_MPEG4_PROFILE_ARTS_L1 |
368 | GO7007_MPEG4_PROFILE_ARTS_L2 | 368 | GO7007_MPEG4_PROFILE_ARTS_L2 |
369 | GO7007_MPEG4_PROFILE_ARTS_L3 | 369 | GO7007_MPEG4_PROFILE_ARTS_L3 |
370 | GO7007_MPEG4_PROFILE_ARTS_L4 | 370 | GO7007_MPEG4_PROFILE_ARTS_L4 |
371 | GO7007_MPEG4_PROFILE_AS_L0 | 371 | GO7007_MPEG4_PROFILE_AS_L0 |
372 | GO7007_MPEG4_PROFILE_AS_L1 | 372 | GO7007_MPEG4_PROFILE_AS_L1 |
373 | GO7007_MPEG4_PROFILE_AS_L2 | 373 | GO7007_MPEG4_PROFILE_AS_L2 |
374 | GO7007_MPEG4_PROFILE_AS_L3 | 374 | GO7007_MPEG4_PROFILE_AS_L3 |
375 | GO7007_MPEG4_PROFILE_AS_L4 | 375 | GO7007_MPEG4_PROFILE_AS_L4 |
376 | GO7007_MPEG4_PROFILE_AS_L5 | 376 | GO7007_MPEG4_PROFILE_AS_L5 |
377 | 377 | ||
378 | Flags in struct go7007_mpeg_params: | 378 | Flags in struct go7007_mpeg_params: |
379 | 379 | ||
380 | GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and | 380 | GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and |
381 | bitrate control settings to comply | 381 | bitrate control settings to comply |
382 | with DVD MPEG2 stream requirements. | 382 | with DVD MPEG2 stream requirements. |
383 | This overrides most compression and | 383 | This overrides most compression and |
384 | bitrate settings! | 384 | bitrate settings! |
385 | 385 | ||
386 | GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header. | 386 | GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header. |
387 | 387 | ||
388 | GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at | 388 | GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at |
389 | the start of each GOP. | 389 | the start of each GOP. |
390 | 390 | ||
391 | 391 | ||
392 | GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE | 392 | GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE |
@@ -404,7 +404,7 @@ features of the GO7007SB encoder, which are described below: | |||
404 | 404 | ||
405 | 405 | ||
406 | ---------------------------------------------------------------------------- | 406 | ---------------------------------------------------------------------------- |
407 | Installing the WIS PCI Voyager Driver | 407 | Installing the WIS PCI Voyager Driver |
408 | --------------------------------------------------------------------------- | 408 | --------------------------------------------------------------------------- |
409 | 409 | ||
410 | The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x | 410 | The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x |
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index 1706fbf06847..8c85a9c3665a 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c | |||
@@ -21,12 +21,10 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/videodev2.h> | 22 | #include <linux/videodev2.h> |
23 | #include <media/v4l2-common.h> | 23 | #include <media/v4l2-common.h> |
24 | #include "s2250-loader.h" | ||
24 | #include "go7007-priv.h" | 25 | #include "go7007-priv.h" |
25 | #include "wis-i2c.h" | 26 | #include "wis-i2c.h" |
26 | 27 | ||
27 | extern int s2250loader_init(void); | ||
28 | extern void s2250loader_cleanup(void); | ||
29 | |||
30 | #define TLV320_ADDRESS 0x34 | 28 | #define TLV320_ADDRESS 0x34 |
31 | #define VPX322_ADDR_ANALOGCONTROL1 0x02 | 29 | #define VPX322_ADDR_ANALOGCONTROL1 0x02 |
32 | #define VPX322_ADDR_BRIGHTNESS0 0x0127 | 30 | #define VPX322_ADDR_BRIGHTNESS0 0x0127 |
@@ -34,7 +32,7 @@ extern void s2250loader_cleanup(void); | |||
34 | #define VPX322_ADDR_CONTRAST0 0x0128 | 32 | #define VPX322_ADDR_CONTRAST0 0x0128 |
35 | #define VPX322_ADDR_CONTRAST1 0x0132 | 33 | #define VPX322_ADDR_CONTRAST1 0x0132 |
36 | #define VPX322_ADDR_HUE 0x00dc | 34 | #define VPX322_ADDR_HUE 0x00dc |
37 | #define VPX322_ADDR_SAT 0x0030 | 35 | #define VPX322_ADDR_SAT 0x0030 |
38 | 36 | ||
39 | struct go7007_usb_board { | 37 | struct go7007_usb_board { |
40 | unsigned int flags; | 38 | unsigned int flags; |
@@ -43,7 +41,7 @@ struct go7007_usb_board { | |||
43 | 41 | ||
44 | struct go7007_usb { | 42 | struct go7007_usb { |
45 | struct go7007_usb_board *board; | 43 | struct go7007_usb_board *board; |
46 | struct semaphore i2c_lock; | 44 | struct mutex i2c_lock; |
47 | struct usb_device *usbdev; | 45 | struct usb_device *usbdev; |
48 | struct urb *video_urbs[8]; | 46 | struct urb *video_urbs[8]; |
49 | struct urb *audio_urbs[8]; | 47 | struct urb *audio_urbs[8]; |
@@ -114,7 +112,7 @@ static u16 vid_regs_fp_pal[] = | |||
114 | }; | 112 | }; |
115 | 113 | ||
116 | struct s2250 { | 114 | struct s2250 { |
117 | int std; | 115 | v4l2_std_id std; |
118 | int input; | 116 | int input; |
119 | int brightness; | 117 | int brightness; |
120 | int contrast; | 118 | int contrast; |
@@ -165,7 +163,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) | |||
165 | return -ENOMEM; | 163 | return -ENOMEM; |
166 | 164 | ||
167 | usb = go->hpi_context; | 165 | usb = go->hpi_context; |
168 | if (down_interruptible(&usb->i2c_lock) != 0) { | 166 | if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { |
169 | printk(KERN_INFO "i2c lock failed\n"); | 167 | printk(KERN_INFO "i2c lock failed\n"); |
170 | kfree(buf); | 168 | kfree(buf); |
171 | return -EINTR; | 169 | return -EINTR; |
@@ -175,7 +173,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) | |||
175 | buf, | 173 | buf, |
176 | 16, 1); | 174 | 16, 1); |
177 | 175 | ||
178 | up(&usb->i2c_lock); | 176 | mutex_unlock(&usb->i2c_lock); |
179 | kfree(buf); | 177 | kfree(buf); |
180 | return rc; | 178 | return rc; |
181 | } | 179 | } |
@@ -203,19 +201,23 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) | |||
203 | memset(buf, 0xcd, 6); | 201 | memset(buf, 0xcd, 6); |
204 | 202 | ||
205 | usb = go->hpi_context; | 203 | usb = go->hpi_context; |
206 | if (down_interruptible(&usb->i2c_lock) != 0) { | 204 | if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { |
207 | printk(KERN_INFO "i2c lock failed\n"); | 205 | printk(KERN_INFO "i2c lock failed\n"); |
206 | kfree(buf); | ||
208 | return -EINTR; | 207 | return -EINTR; |
209 | } | 208 | } |
210 | if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) | 209 | if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) { |
210 | kfree(buf); | ||
211 | return -EFAULT; | 211 | return -EFAULT; |
212 | } | ||
212 | 213 | ||
213 | up(&usb->i2c_lock); | 214 | mutex_unlock(&usb->i2c_lock); |
214 | if (buf[0] == 0) { | 215 | if (buf[0] == 0) { |
215 | unsigned int subaddr, val_read; | 216 | unsigned int subaddr, val_read; |
216 | 217 | ||
217 | subaddr = (buf[4] << 8) + buf[5]; | 218 | subaddr = (buf[4] << 8) + buf[5]; |
218 | val_read = (buf[2] << 8) + buf[3]; | 219 | val_read = (buf[2] << 8) + buf[3]; |
220 | kfree(buf); | ||
219 | if (val_read != val) { | 221 | if (val_read != val) { |
220 | printk(KERN_INFO "invalid fp write %x %x\n", | 222 | printk(KERN_INFO "invalid fp write %x %x\n", |
221 | val_read, val); | 223 | val_read, val); |
@@ -226,8 +228,10 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) | |||
226 | subaddr, addr); | 228 | subaddr, addr); |
227 | return -EFAULT; | 229 | return -EFAULT; |
228 | } | 230 | } |
229 | } else | 231 | } else { |
232 | kfree(buf); | ||
230 | return -EFAULT; | 233 | return -EFAULT; |
234 | } | ||
231 | 235 | ||
232 | /* save last 12b value */ | 236 | /* save last 12b value */ |
233 | if (addr == 0x12b) | 237 | if (addr == 0x12b) |
@@ -236,6 +240,45 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) | |||
236 | return 0; | 240 | return 0; |
237 | } | 241 | } |
238 | 242 | ||
243 | static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val) | ||
244 | { | ||
245 | struct go7007 *go = i2c_get_adapdata(client->adapter); | ||
246 | struct go7007_usb *usb; | ||
247 | u8 *buf; | ||
248 | |||
249 | if (go == NULL) | ||
250 | return -ENODEV; | ||
251 | |||
252 | if (go->status == STATUS_SHUTDOWN) | ||
253 | return -EBUSY; | ||
254 | |||
255 | buf = kzalloc(16, GFP_KERNEL); | ||
256 | |||
257 | if (buf == NULL) | ||
258 | return -ENOMEM; | ||
259 | |||
260 | |||
261 | |||
262 | memset(buf, 0xcd, 6); | ||
263 | usb = go->hpi_context; | ||
264 | if (down_interruptible(&usb->i2c_lock) != 0) { | ||
265 | printk(KERN_INFO "i2c lock failed\n"); | ||
266 | kfree(buf); | ||
267 | return -EINTR; | ||
268 | } | ||
269 | if (go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1) < 0) { | ||
270 | kfree(buf); | ||
271 | return -EFAULT; | ||
272 | } | ||
273 | up(&usb->i2c_lock); | ||
274 | |||
275 | *val = (buf[0] << 8) | buf[1]; | ||
276 | kfree(buf); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | |||
239 | static int write_regs(struct i2c_client *client, u8 *regs) | 282 | static int write_regs(struct i2c_client *client, u8 *regs) |
240 | { | 283 | { |
241 | int i; | 284 | int i; |
@@ -350,14 +393,42 @@ static int s2250_command(struct i2c_client *client, | |||
350 | { | 393 | { |
351 | struct v4l2_control *ctrl = arg; | 394 | struct v4l2_control *ctrl = arg; |
352 | int value1; | 395 | int value1; |
396 | u16 oldvalue; | ||
353 | 397 | ||
354 | switch (ctrl->id) { | 398 | switch (ctrl->id) { |
355 | case V4L2_CID_BRIGHTNESS: | 399 | case V4L2_CID_BRIGHTNESS: |
356 | printk(KERN_INFO "s2250: future setting\n"); | 400 | if (ctrl->value > 100) |
357 | return -EINVAL; | 401 | dec->brightness = 100; |
402 | else if (ctrl->value < 0) | ||
403 | dec->brightness = 0; | ||
404 | else | ||
405 | dec->brightness = ctrl->value; | ||
406 | value1 = (dec->brightness - 50) * 255 / 100; | ||
407 | read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); | ||
408 | write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, | ||
409 | value1 | (oldvalue & ~0xff)); | ||
410 | read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); | ||
411 | write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, | ||
412 | value1 | (oldvalue & ~0xff)); | ||
413 | write_reg_fp(client, 0x140, 0x60); | ||
414 | break; | ||
358 | case V4L2_CID_CONTRAST: | 415 | case V4L2_CID_CONTRAST: |
359 | printk(KERN_INFO "s2250: future setting\n"); | 416 | if (ctrl->value > 100) |
360 | return -EINVAL; | 417 | dec->contrast = 100; |
418 | else if (ctrl->value < 0) | ||
419 | dec->contrast = 0; | ||
420 | else | ||
421 | dec->contrast = ctrl->value; | ||
422 | value1 = dec->contrast * 0x40 / 100; | ||
423 | if (value1 > 0x3f) | ||
424 | value1 = 0x3f; /* max */ | ||
425 | read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); | ||
426 | write_reg_fp(client, VPX322_ADDR_CONTRAST0, | ||
427 | value1 | (oldvalue & ~0x3f)); | ||
428 | read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); | ||
429 | write_reg_fp(client, VPX322_ADDR_CONTRAST1, | ||
430 | value1 | (oldvalue & ~0x3f)); | ||
431 | write_reg_fp(client, 0x140, 0x60); | ||
361 | break; | 432 | break; |
362 | case V4L2_CID_SATURATION: | 433 | case V4L2_CID_SATURATION: |
363 | if (ctrl->value > 127) | 434 | if (ctrl->value > 127) |
@@ -541,7 +612,7 @@ static int s2250_probe(struct i2c_client *client, | |||
541 | dec->audio_input = 0; | 612 | dec->audio_input = 0; |
542 | write_reg(client, 0x08, 0x02); /* Line In */ | 613 | write_reg(client, 0x08, 0x02); /* Line In */ |
543 | 614 | ||
544 | if (down_interruptible(&usb->i2c_lock) == 0) { | 615 | if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { |
545 | data = kzalloc(16, GFP_KERNEL); | 616 | data = kzalloc(16, GFP_KERNEL); |
546 | if (data != NULL) { | 617 | if (data != NULL) { |
547 | int rc; | 618 | int rc; |
@@ -560,7 +631,7 @@ static int s2250_probe(struct i2c_client *client, | |||
560 | } | 631 | } |
561 | kfree(data); | 632 | kfree(data); |
562 | } | 633 | } |
563 | up(&usb->i2c_lock); | 634 | mutex_unlock(&usb->i2c_lock); |
564 | } | 635 | } |
565 | 636 | ||
566 | printk("s2250: initialized successfully\n"); | 637 | printk("s2250: initialized successfully\n"); |
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c index bb22347af60e..d7bf82983274 100644 --- a/drivers/staging/go7007/s2250-loader.c +++ b/drivers/staging/go7007/s2250-loader.c | |||
@@ -35,7 +35,7 @@ typedef struct device_extension_s { | |||
35 | #define MAX_DEVICES 256 | 35 | #define MAX_DEVICES 256 |
36 | 36 | ||
37 | static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; | 37 | static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; |
38 | static DECLARE_MUTEX(s2250_dev_table_mutex); | 38 | static DEFINE_MUTEX(s2250_dev_table_mutex); |
39 | 39 | ||
40 | #define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) | 40 | #define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) |
41 | static void s2250loader_delete(struct kref *kref) | 41 | static void s2250loader_delete(struct kref *kref) |
@@ -67,7 +67,7 @@ static int s2250loader_probe(struct usb_interface *interface, | |||
67 | printk(KERN_ERR "can't handle multiple config\n"); | 67 | printk(KERN_ERR "can't handle multiple config\n"); |
68 | return -1; | 68 | return -1; |
69 | } | 69 | } |
70 | down(&s2250_dev_table_mutex); | 70 | mutex_lock(&s2250_dev_table_mutex); |
71 | 71 | ||
72 | for (minor = 0; minor < MAX_DEVICES; minor++) { | 72 | for (minor = 0; minor < MAX_DEVICES; minor++) { |
73 | if (s2250_dev_table[minor] == NULL) | 73 | if (s2250_dev_table[minor] == NULL) |
@@ -96,7 +96,7 @@ static int s2250loader_probe(struct usb_interface *interface, | |||
96 | 96 | ||
97 | kref_init(&(s->kref)); | 97 | kref_init(&(s->kref)); |
98 | 98 | ||
99 | up(&s2250_dev_table_mutex); | 99 | mutex_unlock(&s2250_dev_table_mutex); |
100 | 100 | ||
101 | if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { | 101 | if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { |
102 | printk(KERN_ERR | 102 | printk(KERN_ERR |
@@ -128,7 +128,7 @@ static int s2250loader_probe(struct usb_interface *interface, | |||
128 | return 0; | 128 | return 0; |
129 | 129 | ||
130 | failed: | 130 | failed: |
131 | up(&s2250_dev_table_mutex); | 131 | mutex_unlock(&s2250_dev_table_mutex); |
132 | failed2: | 132 | failed2: |
133 | if (s) | 133 | if (s) |
134 | kref_put(&(s->kref), s2250loader_delete); | 134 | kref_put(&(s->kref), s2250loader_delete); |
diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c index cd19be6c00e0..03c4dfc138a1 100644 --- a/drivers/staging/go7007/snd-go7007.c +++ b/drivers/staging/go7007/snd-go7007.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
29 | #include <linux/semaphore.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c index 6c3427bb6f4c..506dca6e942e 100644 --- a/drivers/staging/go7007/wis-tw9903.c +++ b/drivers/staging/go7007/wis-tw9903.c | |||
@@ -111,7 +111,8 @@ static int wis_tw9903_command(struct i2c_client *client, | |||
111 | i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1)); | 111 | i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1)); |
112 | break; | 112 | break; |
113 | } | 113 | } |
114 | #if 0 /* The scaler on this thing seems to be horribly broken */ | 114 | #if 0 |
115 | /* The scaler on this thing seems to be horribly broken */ | ||
115 | case DECODER_SET_RESOLUTION: | 116 | case DECODER_SET_RESOLUTION: |
116 | { | 117 | { |
117 | struct video_decoder_resolution *res = arg; | 118 | struct video_decoder_resolution *res = arg; |