aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/common
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/Kconfig12
-rw-r--r--drivers/media/common/Makefile6
-rw-r--r--drivers/media/common/ir-common.c381
-rw-r--r--drivers/media/common/saa7146_core.c547
-rw-r--r--drivers/media/common/saa7146_fops.c564
-rw-r--r--drivers/media/common/saa7146_hlp.c1036
-rw-r--r--drivers/media/common/saa7146_i2c.c421
-rw-r--r--drivers/media/common/saa7146_vbi.c508
-rw-r--r--drivers/media/common/saa7146_video.c1509
-rw-r--r--drivers/media/common/saa7146_vv_ksyms.c12
10 files changed, 4996 insertions, 0 deletions
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
new file mode 100644
index 000000000000..caebd0a1c021
--- /dev/null
+++ b/drivers/media/common/Kconfig
@@ -0,0 +1,12 @@
1config VIDEO_SAA7146
2 tristate
3 select I2C
4
5config VIDEO_SAA7146_VV
6 tristate
7 select VIDEO_BUF
8 select VIDEO_VIDEOBUF
9 select VIDEO_SAA7146
10
11config VIDEO_VIDEOBUF
12 tristate
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
new file mode 100644
index 000000000000..97b4341255ea
--- /dev/null
+++ b/drivers/media/common/Makefile
@@ -0,0 +1,6 @@
1saa7146-objs := saa7146_i2c.o saa7146_core.o
2saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
3
4obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
5obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
6obj-$(CONFIG_VIDEO_IR) += ir-common.o
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
new file mode 100644
index 000000000000..8c842e2f59a2
--- /dev/null
+++ b/drivers/media/common/ir-common.c
@@ -0,0 +1,381 @@
1/*
2 * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $
3 *
4 * some common structs and functions to handle infrared remotes via
5 * input layer ...
6 *
7 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <media/ir-common.h>
27
28/* -------------------------------------------------------------------------- */
29
30MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
31MODULE_LICENSE("GPL");
32
33static int repeat = 1;
34module_param(repeat, int, 0444);
35MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
36
37static int debug = 0; /* debug level (0,1,2) */
38module_param(debug, int, 0644);
39
40#define dprintk(level, fmt, arg...) if (debug >= level) \
41 printk(KERN_DEBUG fmt , ## arg)
42
43/* -------------------------------------------------------------------------- */
44
45/* generic RC5 keytable */
46/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
47/* used by old (black) Hauppauge remotes */
48IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = {
49 [ 0x00 ] = KEY_KP0, // 0
50 [ 0x01 ] = KEY_KP1, // 1
51 [ 0x02 ] = KEY_KP2, // 2
52 [ 0x03 ] = KEY_KP3, // 3
53 [ 0x04 ] = KEY_KP4, // 4
54 [ 0x05 ] = KEY_KP5, // 5
55 [ 0x06 ] = KEY_KP6, // 6
56 [ 0x07 ] = KEY_KP7, // 7
57 [ 0x08 ] = KEY_KP8, // 8
58 [ 0x09 ] = KEY_KP9, // 9
59
60 [ 0x0b ] = KEY_CHANNEL, // channel / program (japan: 11)
61 [ 0x0c ] = KEY_POWER, // standby
62 [ 0x0d ] = KEY_MUTE, // mute / demute
63 [ 0x0f ] = KEY_TV, // display
64 [ 0x10 ] = KEY_VOLUMEUP, // volume +
65 [ 0x11 ] = KEY_VOLUMEDOWN, // volume -
66 [ 0x12 ] = KEY_BRIGHTNESSUP, // brightness +
67 [ 0x13 ] = KEY_BRIGHTNESSDOWN, // brightness -
68 [ 0x1e ] = KEY_SEARCH, // search +
69 [ 0x20 ] = KEY_CHANNELUP, // channel / program +
70 [ 0x21 ] = KEY_CHANNELDOWN, // channel / program -
71 [ 0x22 ] = KEY_CHANNEL, // alt / channel
72 [ 0x23 ] = KEY_LANGUAGE, // 1st / 2nd language
73 [ 0x26 ] = KEY_SLEEP, // sleeptimer
74 [ 0x2e ] = KEY_MENU, // 2nd controls (USA: menu)
75 [ 0x30 ] = KEY_PAUSE, // pause
76 [ 0x32 ] = KEY_REWIND, // rewind
77 [ 0x33 ] = KEY_GOTO, // go to
78 [ 0x35 ] = KEY_PLAY, // play
79 [ 0x36 ] = KEY_STOP, // stop
80 [ 0x37 ] = KEY_RECORD, // recording
81 [ 0x3c ] = KEY_TEXT, // teletext submode (Japan: 12)
82 [ 0x3d ] = KEY_SUSPEND, // system standby
83
84#if 0 /* FIXME */
85 [ 0x0a ] = KEY_RESERVED, // 1/2/3 digits (japan: 10)
86 [ 0x0e ] = KEY_RESERVED, // P.P. (personal preference)
87 [ 0x14 ] = KEY_RESERVED, // colour saturation +
88 [ 0x15 ] = KEY_RESERVED, // colour saturation -
89 [ 0x16 ] = KEY_RESERVED, // bass +
90 [ 0x17 ] = KEY_RESERVED, // bass -
91 [ 0x18 ] = KEY_RESERVED, // treble +
92 [ 0x19 ] = KEY_RESERVED, // treble -
93 [ 0x1a ] = KEY_RESERVED, // balance right
94 [ 0x1b ] = KEY_RESERVED, // balance left
95 [ 0x1c ] = KEY_RESERVED, // contrast +
96 [ 0x1d ] = KEY_RESERVED, // contrast -
97 [ 0x1f ] = KEY_RESERVED, // tint/hue +
98 [ 0x24 ] = KEY_RESERVED, // spacial stereo on/off
99 [ 0x25 ] = KEY_RESERVED, // mono / stereo (USA)
100 [ 0x27 ] = KEY_RESERVED, // tint / hue -
101 [ 0x28 ] = KEY_RESERVED, // RF switch/PIP select
102 [ 0x29 ] = KEY_RESERVED, // vote
103 [ 0x2a ] = KEY_RESERVED, // timed page/channel clck
104 [ 0x2b ] = KEY_RESERVED, // increment (USA)
105 [ 0x2c ] = KEY_RESERVED, // decrement (USA)
106 [ 0x2d ] = KEY_RESERVED, //
107 [ 0x2f ] = KEY_RESERVED, // PIP shift
108 [ 0x31 ] = KEY_RESERVED, // erase
109 [ 0x34 ] = KEY_RESERVED, // wind
110 [ 0x38 ] = KEY_RESERVED, // external 1
111 [ 0x39 ] = KEY_RESERVED, // external 2
112 [ 0x3a ] = KEY_RESERVED, // PIP display mode
113 [ 0x3b ] = KEY_RESERVED, // view data mode / advance
114 [ 0x3e ] = KEY_RESERVED, // crispener on/off
115 [ 0x3f ] = KEY_RESERVED, // system select
116#endif
117};
118EXPORT_SYMBOL_GPL(ir_codes_rc5_tv);
119
120/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
121IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
122 [ 5 ] = KEY_KP1,
123 [ 6 ] = KEY_KP2,
124 [ 7 ] = KEY_KP3,
125 [ 9 ] = KEY_KP4,
126 [ 10 ] = KEY_KP5,
127 [ 11 ] = KEY_KP6,
128 [ 13 ] = KEY_KP7,
129 [ 14 ] = KEY_KP8,
130 [ 15 ] = KEY_KP9,
131 [ 18 ] = KEY_KP0,
132
133 [ 0 ] = KEY_POWER,
134// [ 27 ] = MTS button
135 [ 2 ] = KEY_TUNER, // TV/FM
136 [ 30 ] = KEY_VIDEO,
137// [ 22 ] = display button
138 [ 4 ] = KEY_VOLUMEUP,
139 [ 8 ] = KEY_VOLUMEDOWN,
140 [ 12 ] = KEY_CHANNELUP,
141 [ 16 ] = KEY_CHANNELDOWN,
142 [ 3 ] = KEY_ZOOM, // fullscreen
143 [ 31 ] = KEY_SUBTITLE, // closed caption/teletext
144 [ 32 ] = KEY_SLEEP,
145// [ 41 ] = boss key
146 [ 20 ] = KEY_MUTE,
147 [ 43 ] = KEY_RED,
148 [ 44 ] = KEY_GREEN,
149 [ 45 ] = KEY_YELLOW,
150 [ 46 ] = KEY_BLUE,
151 [ 24 ] = KEY_KPPLUS, //fine tune +
152 [ 25 ] = KEY_KPMINUS, //fine tune -
153// [ 42 ] = picture in picture
154 [ 33 ] = KEY_KPDOT,
155 [ 19 ] = KEY_KPENTER,
156// [ 17 ] = recall
157 [ 34 ] = KEY_BACK,
158 [ 35 ] = KEY_PLAYPAUSE,
159 [ 36 ] = KEY_NEXT,
160// [ 37 ] = time shifting
161 [ 38 ] = KEY_STOP,
162 [ 39 ] = KEY_RECORD
163// [ 40 ] = snapshot
164};
165EXPORT_SYMBOL_GPL(ir_codes_winfast);
166
167/* empty keytable, can be used as placeholder for not-yet created keytables */
168IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = {
169 [ 42 ] = KEY_COFFEE,
170};
171EXPORT_SYMBOL_GPL(ir_codes_empty);
172
173/* Hauppauge: the newer, gray remotes (seems there are multiple
174 * slightly different versions), shipped with cx88+ivtv cards.
175 * almost rc5 coding, but some non-standard keys */
176IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
177 [ 0x00 ] = KEY_KP0, // 0
178 [ 0x01 ] = KEY_KP1, // 1
179 [ 0x02 ] = KEY_KP2, // 2
180 [ 0x03 ] = KEY_KP3, // 3
181 [ 0x04 ] = KEY_KP4, // 4
182 [ 0x05 ] = KEY_KP5, // 5
183 [ 0x06 ] = KEY_KP6, // 6
184 [ 0x07 ] = KEY_KP7, // 7
185 [ 0x08 ] = KEY_KP8, // 8
186 [ 0x09 ] = KEY_KP9, // 9
187 [ 0x0b ] = KEY_RED, // red button
188 [ 0x0c ] = KEY_OPTION, // black key without text
189 [ 0x0d ] = KEY_MENU, // menu
190 [ 0x0f ] = KEY_MUTE, // mute
191 [ 0x10 ] = KEY_VOLUMEUP, // volume +
192 [ 0x11 ] = KEY_VOLUMEDOWN, // volume -
193 [ 0x1e ] = KEY_NEXT, // skip >|
194 [ 0x1f ] = KEY_EXIT, // back/exit
195 [ 0x20 ] = KEY_CHANNELUP, // channel / program +
196 [ 0x21 ] = KEY_CHANNELDOWN, // channel / program -
197 [ 0x22 ] = KEY_CHANNEL, // source (old black remote)
198 [ 0x24 ] = KEY_PREVIOUS, // replay |<
199 [ 0x25 ] = KEY_ENTER, // OK
200 [ 0x26 ] = KEY_SLEEP, // minimize (old black remote)
201 [ 0x29 ] = KEY_BLUE, // blue key
202 [ 0x2e ] = KEY_GREEN, // green button
203 [ 0x30 ] = KEY_PAUSE, // pause
204 [ 0x32 ] = KEY_REWIND, // backward <<
205 [ 0x34 ] = KEY_FASTFORWARD, // forward >>
206 [ 0x35 ] = KEY_PLAY, // play
207 [ 0x36 ] = KEY_STOP, // stop
208 [ 0x37 ] = KEY_RECORD, // recording
209 [ 0x38 ] = KEY_YELLOW, // yellow key
210 [ 0x3b ] = KEY_SELECT, // top right button
211 [ 0x3c ] = KEY_ZOOM, // full
212 [ 0x3d ] = KEY_POWER, // system power (green button)
213};
214EXPORT_SYMBOL(ir_codes_hauppauge_new);
215
216/* -------------------------------------------------------------------------- */
217
218static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
219{
220 if (KEY_RESERVED == ir->keycode) {
221 printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n",
222 dev->name,ir->ir_key,ir->ir_raw,ir->keypressed);
223 return;
224 }
225 dprintk(1,"%s: key event code=%d down=%d\n",
226 dev->name,ir->keycode,ir->keypressed);
227 input_report_key(dev,ir->keycode,ir->keypressed);
228 input_sync(dev);
229}
230
231/* -------------------------------------------------------------------------- */
232
233void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
234 int ir_type, IR_KEYTAB_TYPE *ir_codes)
235{
236 int i;
237
238 ir->ir_type = ir_type;
239 if (ir_codes)
240 memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
241
242 init_input_dev(dev);
243 dev->keycode = ir->ir_codes;
244 dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
245 dev->keycodemax = IR_KEYTAB_SIZE;
246 for (i = 0; i < IR_KEYTAB_SIZE; i++)
247 set_bit(ir->ir_codes[i], dev->keybit);
248 clear_bit(0, dev->keybit);
249
250 set_bit(EV_KEY, dev->evbit);
251 if (repeat)
252 set_bit(EV_REP, dev->evbit);
253}
254
255void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
256{
257 if (ir->keypressed) {
258 ir->keypressed = 0;
259 ir_input_key_event(dev,ir);
260 }
261}
262
263void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
264 u32 ir_key, u32 ir_raw)
265{
266 u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key);
267
268 if (ir->keypressed && ir->keycode != keycode) {
269 ir->keypressed = 0;
270 ir_input_key_event(dev,ir);
271 }
272 if (!ir->keypressed) {
273 ir->ir_key = ir_key;
274 ir->ir_raw = ir_raw;
275 ir->keycode = keycode;
276 ir->keypressed = 1;
277 ir_input_key_event(dev,ir);
278 }
279#if 0
280 /* maybe do something like this ??? */
281 input_event(a, EV_IR, ir->ir_type, ir->ir_raw);
282#endif
283}
284
285/* -------------------------------------------------------------------------- */
286
287u32 ir_extract_bits(u32 data, u32 mask)
288{
289 int mbit, vbit;
290 u32 value;
291
292 value = 0;
293 vbit = 0;
294 for (mbit = 0; mbit < 32; mbit++) {
295 if (!(mask & ((u32)1 << mbit)))
296 continue;
297 if (data & ((u32)1 << mbit))
298 value |= (1 << vbit);
299 vbit++;
300 }
301 return value;
302}
303
304static int inline getbit(u32 *samples, int bit)
305{
306 return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0;
307}
308
309/* sump raw samples for visual debugging ;) */
310int ir_dump_samples(u32 *samples, int count)
311{
312 int i, bit, start;
313
314 printk(KERN_DEBUG "ir samples: ");
315 start = 0;
316 for (i = 0; i < count * 32; i++) {
317 bit = getbit(samples,i);
318 if (bit)
319 start = 1;
320 if (0 == start)
321 continue;
322 printk("%s", bit ? "#" : "_");
323 }
324 printk("\n");
325 return 0;
326}
327
328/* decode raw samples, biphase coding, used by rc5 for example */
329int ir_decode_biphase(u32 *samples, int count, int low, int high)
330{
331 int i,last,bit,len,flips;
332 u32 value;
333
334 /* find start bit (1) */
335 for (i = 0; i < 32; i++) {
336 bit = getbit(samples,i);
337 if (bit)
338 break;
339 }
340
341 /* go decoding */
342 len = 0;
343 flips = 0;
344 value = 1;
345 for (; i < count * 32; i++) {
346 if (len > high)
347 break;
348 if (flips > 1)
349 break;
350 last = bit;
351 bit = getbit(samples,i);
352 if (last == bit) {
353 len++;
354 continue;
355 }
356 if (len < low) {
357 len++;
358 flips++;
359 continue;
360 }
361 value <<= 1;
362 value |= bit;
363 flips = 0;
364 len = 1;
365 }
366 return value;
367}
368
369EXPORT_SYMBOL_GPL(ir_input_init);
370EXPORT_SYMBOL_GPL(ir_input_nokey);
371EXPORT_SYMBOL_GPL(ir_input_keydown);
372
373EXPORT_SYMBOL_GPL(ir_extract_bits);
374EXPORT_SYMBOL_GPL(ir_dump_samples);
375EXPORT_SYMBOL_GPL(ir_decode_biphase);
376
377/*
378 * Local variables:
379 * c-basic-offset: 8
380 * End:
381 */
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
new file mode 100644
index 000000000000..9f6c19ac1285
--- /dev/null
+++ b/drivers/media/common/saa7146_core.c
@@ -0,0 +1,547 @@
1/*
2 saa7146.o - driver for generic saa7146-based hardware
3
4 Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include <media/saa7146.h>
22
23LIST_HEAD(saa7146_devices);
24DECLARE_MUTEX(saa7146_devices_lock);
25
26static int saa7146_num = 0;
27
28unsigned int saa7146_debug = 0;
29
30module_param(saa7146_debug, int, 0644);
31MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
32
33#if 0
34static void dump_registers(struct saa7146_dev* dev)
35{
36 int i = 0;
37
38 INFO((" @ %li jiffies:\n",jiffies));
39 for(i = 0; i <= 0x148; i+=4) {
40 printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
41 }
42}
43#endif
44
45/****************************************************************************
46 * gpio and debi helper functions
47 ****************************************************************************/
48
49void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
50{
51 u32 value = 0;
52
53 BUG_ON(port > 3);
54
55 value = saa7146_read(dev, GPIO_CTRL);
56 value &= ~(0xff << (8*port));
57 value |= (data << (8*port));
58 saa7146_write(dev, GPIO_CTRL, value);
59}
60
61/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
62int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
63{
64 unsigned long start;
65
66 /* wait for registers to be programmed */
67 start = jiffies;
68 while (1) {
69 if (saa7146_read(dev, MC2) & 2)
70 break;
71 if (time_after(jiffies, start + HZ/20)) {
72 DEB_S(("timed out while waiting for registers getting programmed\n"));
73 return -ETIMEDOUT;
74 }
75 if (nobusyloop)
76 msleep(1);
77 }
78
79 /* wait for transfer to complete */
80 start = jiffies;
81 while (1) {
82 if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
83 break;
84 saa7146_read(dev, MC2);
85 if (time_after(jiffies, start + HZ/4)) {
86 DEB_S(("timed out while waiting for transfer completion\n"));
87 return -ETIMEDOUT;
88 }
89 if (nobusyloop)
90 msleep(1);
91 }
92
93 return 0;
94}
95
96/****************************************************************************
97 * general helper functions
98 ****************************************************************************/
99
100/* this is videobuf_vmalloc_to_sg() from video-buf.c
101 make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
102 may be triggered on highmem machines */
103static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
104{
105 struct scatterlist *sglist;
106 struct page *pg;
107 int i;
108
109 sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
110 if (NULL == sglist)
111 return NULL;
112 memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
113 for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
114 pg = vmalloc_to_page(virt);
115 if (NULL == pg)
116 goto err;
117 if (PageHighMem(pg))
118 BUG();
119 sglist[i].page = pg;
120 sglist[i].length = PAGE_SIZE;
121 }
122 return sglist;
123
124 err:
125 kfree(sglist);
126 return NULL;
127}
128
129/********************************************************************************/
130/* common page table functions */
131
132char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
133{
134 int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
135 char *mem = vmalloc_32(length);
136 int slen = 0;
137
138 if (NULL == mem) {
139 return NULL;
140 }
141
142 if (!(pt->slist = vmalloc_to_sg(mem, pages))) {
143 vfree(mem);
144 return NULL;
145 }
146
147 if (saa7146_pgtable_alloc(pci, pt)) {
148 kfree(pt->slist);
149 pt->slist = NULL;
150 vfree(mem);
151 return NULL;
152 }
153
154 slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
155 if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
156 return NULL;
157 }
158
159 return mem;
160}
161
162void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
163{
164 if (NULL == pt->cpu)
165 return;
166 pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
167 pt->cpu = NULL;
168 if (NULL != pt->slist) {
169 kfree(pt->slist);
170 pt->slist = NULL;
171 }
172}
173
174int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
175{
176 u32 *cpu;
177 dma_addr_t dma_addr;
178
179 cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
180 if (NULL == cpu) {
181 return -ENOMEM;
182 }
183 pt->size = PAGE_SIZE;
184 pt->cpu = cpu;
185 pt->dma = dma_addr;
186
187 return 0;
188}
189
190int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
191 struct scatterlist *list, int sglen )
192{
193 u32 *ptr, fill;
194 int nr_pages = 0;
195 int i,p;
196
197 BUG_ON(0 == sglen);
198 BUG_ON(list->offset > PAGE_SIZE);
199
200 /* if we have a user buffer, the first page may not be
201 aligned to a page boundary. */
202 pt->offset = list->offset;
203
204 ptr = pt->cpu;
205 for (i = 0; i < sglen; i++, list++) {
206/*
207 printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
208*/
209 for (p = 0; p * 4096 < list->length; p++, ptr++) {
210 *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
211 nr_pages++;
212 }
213 }
214
215
216 /* safety; fill the page table up with the last valid page */
217 fill = *(ptr-1);
218 for(i=nr_pages;i<1024;i++) {
219 *ptr++ = fill;
220 }
221
222/*
223 ptr = pt->cpu;
224 printk("offset: %d\n",pt->offset);
225 for(i=0;i<5;i++) {
226 printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
227 }
228*/
229 return 0;
230}
231
232/********************************************************************************/
233/* interrupt handler */
234static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
235{
236 struct saa7146_dev *dev = dev_id;
237 u32 isr = 0;
238
239 /* read out the interrupt status register */
240 isr = saa7146_read(dev, ISR);
241
242 /* is this our interrupt? */
243 if ( 0 == isr ) {
244 /* nope, some other device */
245 return IRQ_NONE;
246 }
247
248 saa7146_write(dev, ISR, isr);
249
250 if( 0 != (dev->ext)) {
251 if( 0 != (dev->ext->irq_mask & isr )) {
252 if( 0 != dev->ext->irq_func ) {
253 dev->ext->irq_func(dev, &isr);
254 }
255 isr &= ~dev->ext->irq_mask;
256 }
257 }
258 if (0 != (isr & (MASK_27))) {
259 DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
260 if( 0 != dev->vv_data && 0 != dev->vv_callback) {
261 dev->vv_callback(dev,isr);
262 }
263 isr &= ~MASK_27;
264 }
265 if (0 != (isr & (MASK_28))) {
266 if( 0 != dev->vv_data && 0 != dev->vv_callback) {
267 dev->vv_callback(dev,isr);
268 }
269 isr &= ~MASK_28;
270 }
271 if (0 != (isr & (MASK_16|MASK_17))) {
272 u32 status = saa7146_read(dev, I2C_STATUS);
273 if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
274 SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
275 /* only wake up if we expect something */
276 if( 0 != dev->i2c_op ) {
277 u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2;
278 u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f;
279 DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr));
280 dev->i2c_op = 0;
281 wake_up(&dev->i2c_wq);
282 } else {
283 DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
284 }
285 } else {
286 DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
287 }
288 isr &= ~(MASK_16|MASK_17);
289 }
290 if( 0 != isr ) {
291 ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
292 ERR(("disabling interrupt source(s)!\n"));
293 SAA7146_IER_DISABLE(dev,isr);
294 }
295 return IRQ_HANDLED;
296}
297
298/*********************************************************************************/
299/* configuration-functions */
300
301static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
302{
303 struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
304 struct saa7146_extension *ext = pci_ext->ext;
305 struct saa7146_dev *dev;
306 int err = -ENOMEM;
307
308 dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
309 if (!dev) {
310 ERR(("out of memory.\n"));
311 goto out;
312 }
313
314 /* clear out mem for sure */
315 memset(dev, 0x0, sizeof(struct saa7146_dev));
316
317 DEB_EE(("pci:%p\n",pci));
318
319 err = pci_enable_device(pci);
320 if (err < 0) {
321 ERR(("pci_enable_device() failed.\n"));
322 goto err_free;
323 }
324
325 /* enable bus-mastering */
326 pci_set_master(pci);
327
328 dev->pci = pci;
329
330 /* get chip-revision; this is needed to enable bug-fixes */
331 err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
332 if (err < 0) {
333 ERR(("pci_read_config_dword() failed.\n"));
334 goto err_disable;
335 }
336 dev->revision &= 0xf;
337
338 /* remap the memory from virtual to physical adress */
339
340 err = pci_request_region(pci, 0, "saa7146");
341 if (err < 0)
342 goto err_disable;
343
344 dev->mem = ioremap(pci_resource_start(pci, 0),
345 pci_resource_len(pci, 0));
346 if (!dev->mem) {
347 ERR(("ioremap() failed.\n"));
348 err = -ENODEV;
349 goto err_release;
350 }
351
352 /* we don't do a master reset here anymore, it screws up
353 some boards that don't have an i2c-eeprom for configuration
354 values */
355/*
356 saa7146_write(dev, MC1, MASK_31);
357*/
358
359 /* disable all irqs */
360 saa7146_write(dev, IER, 0);
361
362 /* shut down all dma transfers and rps tasks */
363 saa7146_write(dev, MC1, 0x30ff0000);
364
365 /* clear out any rps-signals pending */
366 saa7146_write(dev, MC2, 0xf8000000);
367
368 /* request an interrupt for the saa7146 */
369 err = request_irq(pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT,
370 dev->name, dev);
371 if (err < 0) {
372 ERR(("request_irq() failed.\n"));
373 goto err_unmap;
374 }
375
376 err = -ENOMEM;
377
378 /* get memory for various stuff */
379 dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
380 &dev->d_rps0.dma_handle);
381 if (!dev->d_rps0.cpu_addr)
382 goto err_free_irq;
383 memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
384
385 dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
386 &dev->d_rps1.dma_handle);
387 if (!dev->d_rps1.cpu_addr)
388 goto err_free_rps0;
389 memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
390
391 dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
392 &dev->d_i2c.dma_handle);
393 if (!dev->d_i2c.cpu_addr)
394 goto err_free_rps1;
395 memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
396
397 /* the rest + print status message */
398
399 /* create a nice device name */
400 sprintf(dev->name, "saa7146 (%d)", saa7146_num);
401
402 INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
403 dev->ext = ext;
404
405 pci_set_drvdata(pci, dev);
406
407 init_MUTEX(&dev->lock);
408 spin_lock_init(&dev->int_slock);
409 spin_lock_init(&dev->slock);
410
411 init_MUTEX(&dev->i2c_lock);
412
413 dev->module = THIS_MODULE;
414 init_waitqueue_head(&dev->i2c_wq);
415
416 /* set some sane pci arbitrition values */
417 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
418
419 /* TODO: use the status code of the callback */
420
421 err = -ENODEV;
422
423 if (ext->probe && ext->probe(dev)) {
424 DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
425 goto err_free_i2c;
426 }
427
428 if (ext->attach(dev, pci_ext)) {
429 DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
430 goto err_unprobe;
431 }
432
433 INIT_LIST_HEAD(&dev->item);
434 list_add_tail(&dev->item,&saa7146_devices);
435 saa7146_num++;
436
437 err = 0;
438out:
439 return err;
440
441err_unprobe:
442 pci_set_drvdata(pci, NULL);
443err_free_i2c:
444 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
445 dev->d_i2c.dma_handle);
446err_free_rps1:
447 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr,
448 dev->d_rps1.dma_handle);
449err_free_rps0:
450 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr,
451 dev->d_rps0.dma_handle);
452err_free_irq:
453 free_irq(pci->irq, (void *)dev);
454err_unmap:
455 iounmap(dev->mem);
456err_release:
457 pci_release_region(pci, 0);
458err_disable:
459 pci_disable_device(pci);
460err_free:
461 kfree(dev);
462 goto out;
463}
464
465static void saa7146_remove_one(struct pci_dev *pdev)
466{
467 struct saa7146_dev* dev = pci_get_drvdata(pdev);
468 struct {
469 void *addr;
470 dma_addr_t dma;
471 } dev_map[] = {
472 { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle },
473 { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle },
474 { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle },
475 { NULL, 0 }
476 }, *p;
477
478 DEB_EE(("dev:%p\n",dev));
479
480 dev->ext->detach(dev);
481
482 /* shut down all video dma transfers */
483 saa7146_write(dev, MC1, 0x00ff0000);
484
485 /* disable all irqs, release irq-routine */
486 saa7146_write(dev, IER, 0);
487
488 free_irq(pdev->irq, dev);
489
490 for (p = dev_map; p->addr; p++)
491 pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma);
492
493 iounmap(dev->mem);
494 pci_release_region(pdev, 0);
495 list_del(&dev->item);
496 pci_disable_device(pdev);
497 kfree(dev);
498
499 saa7146_num--;
500}
501
502/*********************************************************************************/
503/* extension handling functions */
504
505int saa7146_register_extension(struct saa7146_extension* ext)
506{
507 DEB_EE(("ext:%p\n",ext));
508
509 ext->driver.name = ext->name;
510 ext->driver.id_table = ext->pci_tbl;
511 ext->driver.probe = saa7146_init_one;
512 ext->driver.remove = saa7146_remove_one;
513
514 printk("saa7146: register extension '%s'.\n",ext->name);
515 return pci_module_init(&ext->driver);
516}
517
518int saa7146_unregister_extension(struct saa7146_extension* ext)
519{
520 DEB_EE(("ext:%p\n",ext));
521 printk("saa7146: unregister extension '%s'.\n",ext->name);
522 pci_unregister_driver(&ext->driver);
523 return 0;
524}
525
526EXPORT_SYMBOL_GPL(saa7146_register_extension);
527EXPORT_SYMBOL_GPL(saa7146_unregister_extension);
528
529/* misc functions used by extension modules */
530EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
531EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
532EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
533EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
534EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
535
536EXPORT_SYMBOL_GPL(saa7146_setgpio);
537
538EXPORT_SYMBOL_GPL(saa7146_i2c_transfer);
539EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
540
541EXPORT_SYMBOL_GPL(saa7146_debug);
542EXPORT_SYMBOL_GPL(saa7146_devices);
543EXPORT_SYMBOL_GPL(saa7146_devices_lock);
544
545MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
546MODULE_DESCRIPTION("driver for generic saa7146-based hardware");
547MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
new file mode 100644
index 000000000000..cb826c9adfe7
--- /dev/null
+++ b/drivers/media/common/saa7146_fops.c
@@ -0,0 +1,564 @@
1#include <media/saa7146_vv.h>
2#include <linux/version.h>
3
4#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
5
6/****************************************************************************/
7/* resource management functions, shamelessly stolen from saa7134 driver */
8
9int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
10{
11 struct saa7146_dev *dev = fh->dev;
12 struct saa7146_vv *vv = dev->vv_data;
13
14 if (fh->resources & bit) {
15 DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
16 /* have it already allocated */
17 return 1;
18 }
19
20 /* is it free? */
21 down(&dev->lock);
22 if (vv->resources & bit) {
23 DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
24 /* no, someone else uses it */
25 up(&dev->lock);
26 return 0;
27 }
28 /* it's free, grab it */
29 fh->resources |= bit;
30 vv->resources |= bit;
31 DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
32 up(&dev->lock);
33 return 1;
34}
35
36void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
37{
38 struct saa7146_dev *dev = fh->dev;
39 struct saa7146_vv *vv = dev->vv_data;
40
41 if ((fh->resources & bits) != bits)
42 BUG();
43
44 down(&dev->lock);
45 fh->resources &= ~bits;
46 vv->resources &= ~bits;
47 DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
48 up(&dev->lock);
49}
50
51
52/********************************************************************************/
53/* common dma functions */
54
55void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf)
56{
57 DEB_EE(("dev:%p, buf:%p\n",dev,buf));
58
59 if (in_interrupt())
60 BUG();
61
62 videobuf_waiton(&buf->vb,0,0);
63 videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma);
64 videobuf_dma_free(&buf->vb.dma);
65 buf->vb.state = STATE_NEEDS_INIT;
66}
67
68
69/********************************************************************************/
70/* common buffer functions */
71
72int saa7146_buffer_queue(struct saa7146_dev *dev,
73 struct saa7146_dmaqueue *q,
74 struct saa7146_buf *buf)
75{
76 assert_spin_locked(&dev->slock);
77 DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
78
79 BUG_ON(!q);
80
81 if (NULL == q->curr) {
82 q->curr = buf;
83 DEB_D(("immediately activating buffer %p\n", buf));
84 buf->activate(dev,buf,NULL);
85 } else {
86 list_add_tail(&buf->vb.queue,&q->queue);
87 buf->vb.state = STATE_QUEUED;
88 DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
89 }
90 return 0;
91}
92
93void saa7146_buffer_finish(struct saa7146_dev *dev,
94 struct saa7146_dmaqueue *q,
95 int state)
96{
97 assert_spin_locked(&dev->slock);
98 DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
99 DEB_EE(("q->curr:%p\n",q->curr));
100
101 BUG_ON(!q->curr);
102
103 /* finish current buffer */
104 if (NULL == q->curr) {
105 DEB_D(("aiii. no current buffer\n"));
106 return;
107 }
108
109 q->curr->vb.state = state;
110 do_gettimeofday(&q->curr->vb.ts);
111 wake_up(&q->curr->vb.done);
112
113 q->curr = NULL;
114}
115
116void saa7146_buffer_next(struct saa7146_dev *dev,
117 struct saa7146_dmaqueue *q, int vbi)
118{
119 struct saa7146_buf *buf,*next = NULL;
120
121 BUG_ON(!q);
122
123 DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
124
125 assert_spin_locked(&dev->slock);
126 if (!list_empty(&q->queue)) {
127 /* activate next one from queue */
128 buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
129 list_del(&buf->vb.queue);
130 if (!list_empty(&q->queue))
131 next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
132 q->curr = buf;
133 DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
134 buf->activate(dev,buf,next);
135 } else {
136 DEB_INT(("no next buffer. stopping.\n"));
137 if( 0 != vbi ) {
138 /* turn off video-dma3 */
139 saa7146_write(dev,MC1, MASK_20);
140 } else {
141 /* nothing to do -- just prevent next video-dma1 transfer
142 by lowering the protection address */
143
144 // fixme: fix this for vflip != 0
145
146 saa7146_write(dev, PROT_ADDR1, 0);
147 saa7146_write(dev, MC2, (MASK_02|MASK_18));
148
149 /* write the address of the rps-program */
150 saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
151 /* turn on rps */
152 saa7146_write(dev, MC1, (MASK_12 | MASK_28));
153
154/*
155 printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
156 printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
157 printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
158 printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
159 printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1));
160 printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
161*/
162 }
163 del_timer(&q->timeout);
164 }
165}
166
167void saa7146_buffer_timeout(unsigned long data)
168{
169 struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data;
170 struct saa7146_dev *dev = q->dev;
171 unsigned long flags;
172
173 DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
174
175 spin_lock_irqsave(&dev->slock,flags);
176 if (q->curr) {
177 DEB_D(("timeout on %p\n", q->curr));
178 saa7146_buffer_finish(dev,q,STATE_ERROR);
179 }
180
181 /* we don't restart the transfer here like other drivers do. when
182 a streaming capture is disabled, the timeout function will be
183 called for the current buffer. if we activate the next buffer now,
184 we mess up our capture logic. if a timeout occurs on another buffer,
185 then something is seriously broken before, so no need to buffer the
186 next capture IMHO... */
187/*
188 saa7146_buffer_next(dev,q);
189*/
190 spin_unlock_irqrestore(&dev->slock,flags);
191}
192
193/********************************************************************************/
194/* file operations */
195
196static int fops_open(struct inode *inode, struct file *file)
197{
198 unsigned int minor = iminor(inode);
199 struct saa7146_dev *h = NULL, *dev = NULL;
200 struct list_head *list;
201 struct saa7146_fh *fh = NULL;
202 int result = 0;
203
204 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
205
206 DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor));
207
208 if (down_interruptible(&saa7146_devices_lock))
209 return -ERESTARTSYS;
210
211 list_for_each(list,&saa7146_devices) {
212 h = list_entry(list, struct saa7146_dev, item);
213 if( NULL == h->vv_data ) {
214 DEB_D(("device %p has not registered video devices.\n",h));
215 continue;
216 }
217 DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor));
218
219 if (h->vv_data->video_minor == minor) {
220 dev = h;
221 }
222 if (h->vv_data->vbi_minor == minor) {
223 type = V4L2_BUF_TYPE_VBI_CAPTURE;
224 dev = h;
225 }
226 }
227 if (NULL == dev) {
228 DEB_S(("no such video device.\n"));
229 result = -ENODEV;
230 goto out;
231 }
232
233 DEB_D(("using: %p\n",dev));
234
235 /* check if an extension is registered */
236 if( NULL == dev->ext ) {
237 DEB_S(("no extension registered for this device.\n"));
238 result = -ENODEV;
239 goto out;
240 }
241
242 /* allocate per open data */
243 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
244 if (NULL == fh) {
245 DEB_S(("cannot allocate memory for per open data.\n"));
246 result = -ENOMEM;
247 goto out;
248 }
249 memset(fh,0,sizeof(*fh));
250
251 file->private_data = fh;
252 fh->dev = dev;
253 fh->type = type;
254
255 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
256 DEB_S(("initializing vbi...\n"));
257 result = saa7146_vbi_uops.open(dev,file);
258 } else {
259 DEB_S(("initializing video...\n"));
260 result = saa7146_video_uops.open(dev,file);
261 }
262
263 if (0 != result) {
264 goto out;
265 }
266
267 if( 0 == try_module_get(dev->ext->module)) {
268 result = -EINVAL;
269 goto out;
270 }
271
272 result = 0;
273out:
274 if( fh != 0 && result != 0 ) {
275 kfree(fh);
276 file->private_data = NULL;
277 }
278 up(&saa7146_devices_lock);
279 return result;
280}
281
282static int fops_release(struct inode *inode, struct file *file)
283{
284 struct saa7146_fh *fh = file->private_data;
285 struct saa7146_dev *dev = fh->dev;
286
287 DEB_EE(("inode:%p, file:%p\n",inode,file));
288
289 if (down_interruptible(&saa7146_devices_lock))
290 return -ERESTARTSYS;
291
292 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
293 saa7146_vbi_uops.release(dev,file);
294 } else {
295 saa7146_video_uops.release(dev,file);
296 }
297
298 module_put(dev->ext->module);
299 file->private_data = NULL;
300 kfree(fh);
301
302 up(&saa7146_devices_lock);
303
304 return 0;
305}
306
307int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg);
308static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
309{
310/*
311 DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg));
312*/
313 return video_usercopy(inode, file, cmd, arg, saa7146_video_do_ioctl);
314}
315
316static int fops_mmap(struct file *file, struct vm_area_struct * vma)
317{
318 struct saa7146_fh *fh = file->private_data;
319 struct videobuf_queue *q;
320
321 switch (fh->type) {
322 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
323 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
324 q = &fh->video_q;
325 break;
326 }
327 case V4L2_BUF_TYPE_VBI_CAPTURE: {
328 DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
329 q = &fh->vbi_q;
330 break;
331 }
332 default:
333 BUG();
334 return 0;
335 }
336 return videobuf_mmap_mapper(q,vma);
337}
338
339static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
340{
341 struct saa7146_fh *fh = file->private_data;
342 struct videobuf_buffer *buf = NULL;
343 struct videobuf_queue *q;
344
345 DEB_EE(("file:%p, poll:%p\n",file, wait));
346
347 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
348 if( 0 == fh->vbi_q.streaming )
349 return videobuf_poll_stream(file, &fh->vbi_q, wait);
350 q = &fh->vbi_q;
351 } else {
352 DEB_D(("using video queue.\n"));
353 q = &fh->video_q;
354 }
355
356 if (!list_empty(&q->stream))
357 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
358
359 if (!buf) {
360 DEB_D(("buf == NULL!\n"));
361 return POLLERR;
362 }
363
364 poll_wait(file, &buf->done, wait);
365 if (buf->state == STATE_DONE || buf->state == STATE_ERROR) {
366 DEB_D(("poll succeeded!\n"));
367 return POLLIN|POLLRDNORM;
368 }
369
370 DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
371 return 0;
372}
373
374static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
375{
376 struct saa7146_fh *fh = file->private_data;
377
378 switch (fh->type) {
379 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
380// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
381 return saa7146_video_uops.read(file,data,count,ppos);
382 }
383 case V4L2_BUF_TYPE_VBI_CAPTURE: {
384// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
385 return saa7146_vbi_uops.read(file,data,count,ppos);
386 }
387 break;
388 default:
389 BUG();
390 return 0;
391 }
392}
393
394static struct file_operations video_fops =
395{
396 .owner = THIS_MODULE,
397 .open = fops_open,
398 .release = fops_release,
399 .read = fops_read,
400 .poll = fops_poll,
401 .mmap = fops_mmap,
402 .ioctl = fops_ioctl,
403 .llseek = no_llseek,
404};
405
406void vv_callback(struct saa7146_dev *dev, unsigned long status)
407{
408 u32 isr = status;
409
410 DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
411
412 if (0 != (isr & (MASK_27))) {
413 DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
414 saa7146_video_uops.irq_done(dev,isr);
415 }
416
417 if (0 != (isr & (MASK_28))) {
418 u32 mc2 = saa7146_read(dev, MC2);
419 if( 0 != (mc2 & MASK_15)) {
420 DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
421 wake_up(&dev->vv_data->vbi_wq);
422 saa7146_write(dev,MC2, MASK_31);
423 return;
424 }
425 DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
426 saa7146_vbi_uops.irq_done(dev,isr);
427 }
428}
429
430static struct video_device device_template =
431{
432 .hardware = VID_HARDWARE_SAA7146,
433 .fops = &video_fops,
434 .minor = -1,
435};
436
437int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
438{
439 struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
440 if( NULL == vv ) {
441 ERR(("out of memory. aborting.\n"));
442 return -1;
443 }
444 memset(vv, 0x0, sizeof(*vv));
445
446 DEB_EE(("dev:%p\n",dev));
447
448 /* set default values for video parts of the saa7146 */
449 saa7146_write(dev, BCS_CTRL, 0x80400040);
450
451 /* enable video-port pins */
452 saa7146_write(dev, MC1, (MASK_10 | MASK_26));
453
454 /* save per-device extension data (one extension can
455 handle different devices that might need different
456 configuration data) */
457 dev->ext_vv_data = ext_vv;
458
459 vv->video_minor = -1;
460 vv->vbi_minor = -1;
461
462 vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
463 if( NULL == vv->d_clipping.cpu_addr ) {
464 ERR(("out of memory. aborting.\n"));
465 kfree(vv);
466 return -1;
467 }
468 memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
469
470 saa7146_video_uops.init(dev,vv);
471 saa7146_vbi_uops.init(dev,vv);
472
473 dev->vv_data = vv;
474 dev->vv_callback = &vv_callback;
475
476 return 0;
477}
478
479int saa7146_vv_release(struct saa7146_dev* dev)
480{
481 struct saa7146_vv *vv = dev->vv_data;
482
483 DEB_EE(("dev:%p\n",dev));
484
485 pci_free_consistent(dev->pci, SAA7146_RPS_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
486 kfree(vv);
487 dev->vv_data = NULL;
488 dev->vv_callback = NULL;
489
490 return 0;
491}
492
493int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
494 char *name, int type)
495{
496 struct saa7146_vv *vv = dev->vv_data;
497 struct video_device *vfd;
498
499 DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
500
501 // released by vfd->release
502 vfd = video_device_alloc();
503 if (vfd == NULL)
504 return -ENOMEM;
505
506 memcpy(vfd, &device_template, sizeof(struct video_device));
507 strlcpy(vfd->name, name, sizeof(vfd->name));
508 vfd->release = video_device_release;
509 vfd->priv = dev;
510
511 // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
512 if (video_register_device(vfd, type, -1) < 0) {
513 ERR(("cannot register v4l2 device. skipping.\n"));
514 return -1;
515 }
516
517 if( VFL_TYPE_GRABBER == type ) {
518 vv->video_minor = vfd->minor;
519 INFO(("%s: registered device video%d [v4l2]\n",
520 dev->name, vfd->minor & 0x1f));
521 } else {
522 vv->vbi_minor = vfd->minor;
523 INFO(("%s: registered device vbi%d [v4l2]\n",
524 dev->name, vfd->minor & 0x1f));
525 }
526
527 *vid = vfd;
528 return 0;
529}
530
531int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
532{
533 struct saa7146_vv *vv = dev->vv_data;
534
535 DEB_EE(("dev:%p\n",dev));
536
537 if( VFL_TYPE_GRABBER == (*vid)->type ) {
538 vv->video_minor = -1;
539 } else {
540 vv->vbi_minor = -1;
541 }
542
543 video_unregister_device(*vid);
544 *vid = NULL;
545
546 return 0;
547}
548
549static int __init saa7146_vv_init_module(void)
550{
551 return 0;
552}
553
554
555static void __exit saa7146_vv_cleanup_module(void)
556{
557}
558
559module_init(saa7146_vv_init_module);
560module_exit(saa7146_vv_cleanup_module);
561
562MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
563MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
564MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
new file mode 100644
index 000000000000..ec52dff8cb69
--- /dev/null
+++ b/drivers/media/common/saa7146_hlp.c
@@ -0,0 +1,1036 @@
1#include <linux/kernel.h>
2#include <media/saa7146_vv.h>
3
4static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
5{
6 /* clear out the necessary bits */
7 *clip_format &= 0x0000ffff;
8 /* set these bits new */
9 *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
10}
11
12static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl)
13{
14 *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28);
15 *hps_ctrl |= (source << 30) | (sync << 28);
16}
17
18static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl)
19{
20 int hyo = 0, hxo = 0;
21
22 hyo = vv->standard->v_offset;
23 hxo = vv->standard->h_offset;
24
25 *hps_h_scale &= ~(MASK_B0 | 0xf00);
26 *hps_h_scale |= (hxo << 0);
27
28 *hps_ctrl &= ~(MASK_W0 | MASK_B2);
29 *hps_ctrl |= (hyo << 12);
30}
31
32/* helper functions for the calculation of the horizontal- and vertical
33 scaling registers, clip-format-register etc ...
34 these functions take pointers to the (most-likely read-out
35 original-values) and manipulate them according to the requested
36 changes.
37*/
38
39/* hps_coeff used for CXY and CXUV; scale 1/1 -> scale 1/64 */
40static struct {
41 u16 hps_coeff;
42 u16 weight_sum;
43} hps_h_coeff_tab [] = {
44 {0x00, 2}, {0x02, 4}, {0x00, 4}, {0x06, 8}, {0x02, 8},
45 {0x08, 8}, {0x00, 8}, {0x1E, 16}, {0x0E, 8}, {0x26, 8},
46 {0x06, 8}, {0x42, 8}, {0x02, 8}, {0x80, 8}, {0x00, 8},
47 {0xFE, 16}, {0xFE, 8}, {0x7E, 8}, {0x7E, 8}, {0x3E, 8},
48 {0x3E, 8}, {0x1E, 8}, {0x1E, 8}, {0x0E, 8}, {0x0E, 8},
49 {0x06, 8}, {0x06, 8}, {0x02, 8}, {0x02, 8}, {0x00, 8},
50 {0x00, 8}, {0xFE, 16}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
51 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
52 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
53 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0x7E, 8},
54 {0x7E, 8}, {0x3E, 8}, {0x3E, 8}, {0x1E, 8}, {0x1E, 8},
55 {0x0E, 8}, {0x0E, 8}, {0x06, 8}, {0x06, 8}, {0x02, 8},
56 {0x02, 8}, {0x00, 8}, {0x00, 8}, {0xFE, 16}
57};
58
59/* table of attenuation values for horizontal scaling */
60static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
61
62/* calculate horizontal scale registers */
63static int calculate_h_scale_registers(struct saa7146_dev *dev,
64 int in_x, int out_x, int flip_lr,
65 u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale)
66{
67 /* horizontal prescaler */
68 u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
69 /* horizontal scaler */
70 u32 xim = 0, xp = 0, xsci =0;
71 /* vertical scale & gain */
72 u32 pfuv = 0;
73
74 /* helper variables */
75 u32 h_atten = 0, i = 0;
76
77 if ( 0 == out_x ) {
78 return -EINVAL;
79 }
80
81 /* mask out vanity-bit */
82 *hps_ctrl &= ~MASK_29;
83
84 /* calculate prescale-(xspc)-value: [n .. 1/2) : 1
85 [1/2 .. 1/3) : 2
86 [1/3 .. 1/4) : 3
87 ... */
88 if (in_x > out_x) {
89 xpsc = in_x / out_x;
90 }
91 else {
92 /* zooming */
93 xpsc = 1;
94 }
95
96 /* if flip_lr-bit is set, number of pixels after
97 horizontal prescaling must be < 384 */
98 if ( 0 != flip_lr ) {
99
100 /* set vanity bit */
101 *hps_ctrl |= MASK_29;
102
103 while (in_x / xpsc >= 384 )
104 xpsc++;
105 }
106 /* if zooming is wanted, number of pixels after
107 horizontal prescaling must be < 768 */
108 else {
109 while ( in_x / xpsc >= 768 )
110 xpsc++;
111 }
112
113 /* maximum prescale is 64 (p.69) */
114 if ( xpsc > 64 )
115 xpsc = 64;
116
117 /* keep xacm clear*/
118 xacm = 0;
119
120 /* set horizontal filter parameters (CXY = CXUV) */
121 cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff;
122 cxuv = cxy;
123
124 /* calculate and set horizontal fine scale (xsci) */
125
126 /* bypass the horizontal scaler ? */
127 if ( (in_x == out_x) && ( 1 == xpsc ) )
128 xsci = 0x400;
129 else
130 xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
131
132 /* set start phase for horizontal fine scale (xp) to 0 */
133 xp = 0;
134
135 /* set xim, if we bypass the horizontal scaler */
136 if ( 0x400 == xsci )
137 xim = 1;
138 else
139 xim = 0;
140
141 /* if the prescaler is bypassed, enable horizontal
142 accumulation mode (xacm) and clear dcgx */
143 if( 1 == xpsc ) {
144 xacm = 1;
145 dcgx = 0;
146 } else {
147 xacm = 0;
148 /* get best match in the table of attenuations
149 for horizontal scaling */
150 h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum;
151
152 for (i = 0; h_attenuation[i] != 0; i++) {
153 if (h_attenuation[i] >= h_atten)
154 break;
155 }
156
157 dcgx = i;
158 }
159
160 /* the horizontal scaling increment controls the UV filter
161 to reduce the bandwith to improve the display quality,
162 so set it ... */
163 if ( xsci == 0x400)
164 pfuv = 0x00;
165 else if ( xsci < 0x600)
166 pfuv = 0x01;
167 else if ( xsci < 0x680)
168 pfuv = 0x11;
169 else if ( xsci < 0x700)
170 pfuv = 0x22;
171 else
172 pfuv = 0x33;
173
174
175 *hps_v_gain &= MASK_W0|MASK_B2;
176 *hps_v_gain |= (pfuv << 24);
177
178 *hps_h_scale &= ~(MASK_W1 | 0xf000);
179 *hps_h_scale |= (xim << 31) | (xp << 24) | (xsci << 12);
180
181 *hps_h_prescale |= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
182
183 return 0;
184}
185
186static struct {
187 u16 hps_coeff;
188 u16 weight_sum;
189} hps_v_coeff_tab [] = {
190 {0x0100, 2}, {0x0102, 4}, {0x0300, 4}, {0x0106, 8}, {0x0502, 8},
191 {0x0708, 8}, {0x0F00, 8}, {0x011E, 16}, {0x110E, 16}, {0x1926, 16},
192 {0x3906, 16}, {0x3D42, 16}, {0x7D02, 16}, {0x7F80, 16}, {0xFF00, 16},
193 {0x01FE, 32}, {0x01FE, 32}, {0x817E, 32}, {0x817E, 32}, {0xC13E, 32},
194 {0xC13E, 32}, {0xE11E, 32}, {0xE11E, 32}, {0xF10E, 32}, {0xF10E, 32},
195 {0xF906, 32}, {0xF906, 32}, {0xFD02, 32}, {0xFD02, 32}, {0xFF00, 32},
196 {0xFF00, 32}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
197 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
198 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
199 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x817E, 64},
200 {0x817E, 64}, {0xC13E, 64}, {0xC13E, 64}, {0xE11E, 64}, {0xE11E, 64},
201 {0xF10E, 64}, {0xF10E, 64}, {0xF906, 64}, {0xF906, 64}, {0xFD02, 64},
202 {0xFD02, 64}, {0xFF00, 64}, {0xFF00, 64}, {0x01FE, 128}
203};
204
205/* table of attenuation values for vertical scaling */
206static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
207
208/* calculate vertical scale registers */
209static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field,
210 int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain)
211{
212 int lpi = 0;
213
214 /* vertical scaling */
215 u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
216 /* vertical scale & gain */
217 u32 dcgy = 0, cya_cyb = 0;
218
219 /* helper variables */
220 u32 v_atten = 0, i = 0;
221
222 /* error, if vertical zooming */
223 if ( in_y < out_y ) {
224 return -EINVAL;
225 }
226
227 /* linear phase interpolation may be used
228 if scaling is between 1 and 1/2 (both fields used)
229 or scaling is between 1/2 and 1/4 (if only one field is used) */
230
231 if (V4L2_FIELD_HAS_BOTH(field)) {
232 if( 2*out_y >= in_y) {
233 lpi = 1;
234 }
235 } else if (field == V4L2_FIELD_TOP
236 || field == V4L2_FIELD_ALTERNATE
237 || field == V4L2_FIELD_BOTTOM) {
238 if( 4*out_y >= in_y ) {
239 lpi = 1;
240 }
241 out_y *= 2;
242 }
243 if( 0 != lpi ) {
244
245 yacm = 0;
246 yacl = 0;
247 cya_cyb = 0x00ff;
248
249 /* calculate scaling increment */
250 if ( in_y > out_y )
251 ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
252 else
253 ysci = 0;
254
255 dcgy = 0;
256
257 /* calculate ype and ypo */
258 ype = ysci / 16;
259 ypo = ype + (ysci / 64);
260
261 } else {
262 yacm = 1;
263
264 /* calculate scaling increment */
265 ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
266
267 /* calculate ype and ypo */
268 ypo = ype = ((ysci + 15) / 16);
269
270 /* the sequence length interval (yacl) has to be set according
271 to the prescale value, e.g. [n .. 1/2) : 0
272 [1/2 .. 1/3) : 1
273 [1/3 .. 1/4) : 2
274 ... */
275 if ( ysci < 512) {
276 yacl = 0;
277 } else {
278 yacl = ( ysci / (1024 - ysci) );
279 }
280
281 /* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
282 cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff;
283
284 /* get best match in the table of attenuations for vertical scaling */
285 v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].weight_sum;
286
287 for (i = 0; v_attenuation[i] != 0; i++) {
288 if (v_attenuation[i] >= v_atten)
289 break;
290 }
291
292 dcgy = i;
293 }
294
295 /* ypo and ype swapped in spec ? */
296 *hps_v_scale |= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1);
297
298 *hps_v_gain &= ~(MASK_W0|MASK_B2);
299 *hps_v_gain |= (dcgy << 16) | (cya_cyb << 0);
300
301 return 0;
302}
303
304/* simple bubble-sort algorithm with duplicate elimination */
305static int sort_and_eliminate(u32* values, int* count)
306{
307 int low = 0, high = 0, top = 0, temp = 0;
308 int cur = 0, next = 0;
309
310 /* sanity checks */
311 if( (0 > *count) || (NULL == values) ) {
312 return -EINVAL;
313 }
314
315 /* bubble sort the first ´count´ items of the array ´values´ */
316 for( top = *count; top > 0; top--) {
317 for( low = 0, high = 1; high < top; low++, high++) {
318 if( values[low] > values[high] ) {
319 temp = values[low];
320 values[low] = values[high];
321 values[high] = temp;
322 }
323 }
324 }
325
326 /* remove duplicate items */
327 for( cur = 0, next = 1; next < *count; next++) {
328 if( values[cur] != values[next])
329 values[++cur] = values[next];
330 }
331
332 *count = cur + 1;
333
334 return 0;
335}
336
337static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
338 struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
339{
340 struct saa7146_vv *vv = dev->vv_data;
341 u32 *clipping = vv->d_clipping.cpu_addr;
342
343 int width = fh->ov.win.w.width;
344 int height = fh->ov.win.w.height;
345 int clipcount = fh->ov.nclips;
346
347 u32 line_list[32];
348 u32 pixel_list[32];
349 int numdwords = 0;
350
351 int i = 0, j = 0;
352 int cnt_line = 0, cnt_pixel = 0;
353
354 int x[32], y[32], w[32], h[32];
355
356 /* clear out memory */
357 memset(&line_list[0], 0x00, sizeof(u32)*32);
358 memset(&pixel_list[0], 0x00, sizeof(u32)*32);
359 memset(clipping, 0x00, SAA7146_CLIPPING_MEM);
360
361 /* fill the line and pixel-lists */
362 for(i = 0; i < clipcount; i++) {
363 int l = 0, r = 0, t = 0, b = 0;
364
365 x[i] = fh->ov.clips[i].c.left;
366 y[i] = fh->ov.clips[i].c.top;
367 w[i] = fh->ov.clips[i].c.width;
368 h[i] = fh->ov.clips[i].c.height;
369
370 if( w[i] < 0) {
371 x[i] += w[i]; w[i] = -w[i];
372 }
373 if( h[i] < 0) {
374 y[i] += h[i]; h[i] = -h[i];
375 }
376 if( x[i] < 0) {
377 w[i] += x[i]; x[i] = 0;
378 }
379 if( y[i] < 0) {
380 h[i] += y[i]; y[i] = 0;
381 }
382 if( 0 != vv->vflip ) {
383 y[i] = height - y[i] - h[i];
384 }
385
386 l = x[i];
387 r = x[i]+w[i];
388 t = y[i];
389 b = y[i]+h[i];
390
391 /* insert left/right coordinates */
392 pixel_list[ 2*i ] = min_t(int, l, width);
393 pixel_list[(2*i)+1] = min_t(int, r, width);
394 /* insert top/bottom coordinates */
395 line_list[ 2*i ] = min_t(int, t, height);
396 line_list[(2*i)+1] = min_t(int, b, height);
397 }
398
399 /* sort and eliminate lists */
400 cnt_line = cnt_pixel = 2*clipcount;
401 sort_and_eliminate( &pixel_list[0], &cnt_pixel );
402 sort_and_eliminate( &line_list[0], &cnt_line );
403
404 /* calculate the number of used u32s */
405 numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
406 numdwords = max_t(int, 4, numdwords);
407 numdwords = min_t(int, 64, numdwords);
408
409 /* fill up cliptable */
410 for(i = 0; i < cnt_pixel; i++) {
411 clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
412 }
413 for(i = 0; i < cnt_line; i++) {
414 clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
415 }
416
417 /* fill up cliptable with the display infos */
418 for(j = 0; j < clipcount; j++) {
419
420 for(i = 0; i < cnt_pixel; i++) {
421
422 if( x[j] < 0)
423 x[j] = 0;
424
425 if( pixel_list[i] < (x[j] + w[j])) {
426
427 if ( pixel_list[i] >= x[j] ) {
428 clipping[2*i] |= cpu_to_le32(1 << j);
429 }
430 }
431 }
432 for(i = 0; i < cnt_line; i++) {
433
434 if( y[j] < 0)
435 y[j] = 0;
436
437 if( line_list[i] < (y[j] + h[j]) ) {
438
439 if( line_list[i] >= y[j] ) {
440 clipping[(2*i)+1] |= cpu_to_le32(1 << j);
441 }
442 }
443 }
444 }
445
446 /* adjust arbitration control register */
447 *arbtr_ctrl &= 0xffff00ff;
448 *arbtr_ctrl |= 0x00001c00;
449
450 vdma2->base_even = vv->d_clipping.dma_handle;
451 vdma2->base_odd = vv->d_clipping.dma_handle;
452 vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
453 vdma2->base_page = 0x04;
454 vdma2->pitch = 0x00;
455 vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) );
456
457 /* set clipping-mode. this depends on the field(s) used */
458 *clip_format &= 0xfffffff7;
459 if (V4L2_FIELD_HAS_BOTH(field)) {
460 *clip_format |= 0x00000008;
461 } else {
462 *clip_format |= 0x00000000;
463 }
464}
465
466/* disable clipping */
467static void saa7146_disable_clipping(struct saa7146_dev *dev)
468{
469 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
470
471 /* mask out relevant bits (=lower word)*/
472 clip_format &= MASK_W1;
473
474 /* upload clipping-registers*/
475 saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
476 saa7146_write(dev, MC2, (MASK_05 | MASK_21));
477
478 /* disable video dma2 */
479 saa7146_write(dev, MC1, MASK_21);
480}
481
482static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
483{
484 struct saa7146_dev *dev = fh->dev;
485 enum v4l2_field field = fh->ov.win.field;
486 struct saa7146_video_dma vdma2;
487 u32 clip_format;
488 u32 arbtr_ctrl;
489
490 /* check clipcount, disable clipping if clipcount == 0*/
491 if( fh->ov.nclips == 0 ) {
492 saa7146_disable_clipping(dev);
493 return;
494 }
495
496 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
497 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
498
499 calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
500
501 /* set clipping format */
502 clip_format &= 0xffff0008;
503 clip_format |= (SAA7146_CLIPPING_RECT << 4);
504
505 /* prepare video dma2 */
506 saa7146_write(dev, BASE_EVEN2, vdma2.base_even);
507 saa7146_write(dev, BASE_ODD2, vdma2.base_odd);
508 saa7146_write(dev, PROT_ADDR2, vdma2.prot_addr);
509 saa7146_write(dev, BASE_PAGE2, vdma2.base_page);
510 saa7146_write(dev, PITCH2, vdma2.pitch);
511 saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte);
512
513 /* prepare the rest */
514 saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
515 saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
516
517 /* upload clip_control-register, clipping-registers, enable video dma2 */
518 saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
519 saa7146_write(dev, MC1, (MASK_05 | MASK_21));
520}
521
522static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
523{
524 struct saa7146_vv *vv = dev->vv_data;
525
526 int source = vv->current_hps_source;
527 int sync = vv->current_hps_sync;
528
529 u32 hps_v_scale = 0, hps_v_gain = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0;
530
531 /* set vertical scale */
532 hps_v_scale = 0; /* all bits get set by the function-call */
533 hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
534 calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
535
536 /* set horizontal scale */
537 hps_ctrl = 0;
538 hps_h_prescale = 0; /* all bits get set in the function */
539 hps_h_scale = 0;
540 calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
541
542 /* set hyo and hxo */
543 calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
544 calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
545
546 /* write out new register contents */
547 saa7146_write(dev, HPS_V_SCALE, hps_v_scale);
548 saa7146_write(dev, HPS_V_GAIN, hps_v_gain);
549 saa7146_write(dev, HPS_CTRL, hps_ctrl);
550 saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale);
551 saa7146_write(dev, HPS_H_SCALE, hps_h_scale);
552
553 /* upload shadow-ram registers */
554 saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
555}
556
557/* calculate the new memory offsets for a desired position */
558static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
559{
560 struct saa7146_vv *vv = dev->vv_data;
561 struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
562
563 int b_depth = vv->ov_fmt->depth;
564 int b_bpl = vv->ov_fb.fmt.bytesperline;
565 u32 base = (u32)vv->ov_fb.base;
566
567 struct saa7146_video_dma vdma1;
568
569 /* calculate memory offsets for picture, look if we shall top-down-flip */
570 vdma1.pitch = 2*b_bpl;
571 if ( 0 == vv->vflip ) {
572 vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
573 vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
574 vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
575 }
576 else {
577 vdma1.base_even = (u32)base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
578 vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
579 vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
580 }
581
582 if (V4L2_FIELD_HAS_BOTH(field)) {
583 } else if (field == V4L2_FIELD_ALTERNATE) {
584 /* fixme */
585 vdma1.base_odd = vdma1.prot_addr;
586 vdma1.pitch /= 2;
587 } else if (field == V4L2_FIELD_TOP) {
588 vdma1.base_odd = vdma1.prot_addr;
589 vdma1.pitch /= 2;
590 } else if (field == V4L2_FIELD_BOTTOM) {
591 vdma1.base_odd = vdma1.base_even;
592 vdma1.base_even = vdma1.prot_addr;
593 vdma1.pitch /= 2;
594 }
595
596 if ( 0 != vv->vflip ) {
597 vdma1.pitch *= -1;
598 }
599
600 vdma1.base_page = sfmt->swap;
601 vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
602
603 saa7146_write_out_dma(dev, 1, &vdma1);
604}
605
606static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
607{
608 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
609
610 /* call helper function */
611 calculate_output_format_register(dev,palette,&clip_format);
612
613 /* update the hps registers */
614 saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
615 saa7146_write(dev, MC2, (MASK_05 | MASK_21));
616}
617
618/* select input-source */
619void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync)
620{
621 struct saa7146_vv *vv = dev->vv_data;
622 u32 hps_ctrl = 0;
623
624 /* read old state */
625 hps_ctrl = saa7146_read(dev, HPS_CTRL);
626
627 hps_ctrl &= ~( MASK_31 | MASK_30 | MASK_28 );
628 hps_ctrl |= (source << 30) | (sync << 28);
629
630 /* write back & upload register */
631 saa7146_write(dev, HPS_CTRL, hps_ctrl);
632 saa7146_write(dev, MC2, (MASK_05 | MASK_21));
633
634 vv->current_hps_source = source;
635 vv->current_hps_sync = sync;
636}
637
638int saa7146_enable_overlay(struct saa7146_fh *fh)
639{
640 struct saa7146_dev *dev = fh->dev;
641 struct saa7146_vv *vv = dev->vv_data;
642
643 saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field);
644 saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field, vv->ov_fmt->pixelformat);
645 saa7146_set_output_format(dev, vv->ov_fmt->trans);
646 saa7146_set_clipping_rect(fh);
647
648 /* enable video dma1 */
649 saa7146_write(dev, MC1, (MASK_06 | MASK_22));
650 return 0;
651}
652
653void saa7146_disable_overlay(struct saa7146_fh *fh)
654{
655 struct saa7146_dev *dev = fh->dev;
656
657 /* disable clipping + video dma1 */
658 saa7146_disable_clipping(dev);
659 saa7146_write(dev, MC1, MASK_22);
660}
661
662void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
663{
664 int where = 0;
665
666 if( which < 1 || which > 3) {
667 return;
668 }
669
670 /* calculate starting address */
671 where = (which-1)*0x18;
672
673 saa7146_write(dev, where, vdma->base_odd);
674 saa7146_write(dev, where+0x04, vdma->base_even);
675 saa7146_write(dev, where+0x08, vdma->prot_addr);
676 saa7146_write(dev, where+0x0c, vdma->pitch);
677 saa7146_write(dev, where+0x10, vdma->base_page);
678 saa7146_write(dev, where+0x14, vdma->num_line_byte);
679
680 /* upload */
681 saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
682/*
683 printk("vdma%d.base_even: 0x%08x\n", which,vdma->base_even);
684 printk("vdma%d.base_odd: 0x%08x\n", which,vdma->base_odd);
685 printk("vdma%d.prot_addr: 0x%08x\n", which,vdma->prot_addr);
686 printk("vdma%d.base_page: 0x%08x\n", which,vdma->base_page);
687 printk("vdma%d.pitch: 0x%08x\n", which,vdma->pitch);
688 printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte);
689*/
690}
691
692static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
693{
694 struct saa7146_vv *vv = dev->vv_data;
695 struct saa7146_video_dma vdma1;
696
697 struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
698
699 int width = buf->fmt->width;
700 int height = buf->fmt->height;
701 int bytesperline = buf->fmt->bytesperline;
702 enum v4l2_field field = buf->fmt->field;
703
704 int depth = sfmt->depth;
705
706 DEB_CAP(("[size=%dx%d,fields=%s]\n",
707 width,height,v4l2_field_names[field]));
708
709 if( bytesperline != 0) {
710 vdma1.pitch = bytesperline*2;
711 } else {
712 vdma1.pitch = (width*depth*2)/8;
713 }
714 vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
715 vdma1.base_page = buf->pt[0].dma | ME1 | sfmt->swap;
716
717 if( 0 != vv->vflip ) {
718 vdma1.prot_addr = buf->pt[0].offset;
719 vdma1.base_even = buf->pt[0].offset+(vdma1.pitch/2)*height;
720 vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
721 } else {
722 vdma1.base_even = buf->pt[0].offset;
723 vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
724 vdma1.prot_addr = buf->pt[0].offset+(vdma1.pitch/2)*height;
725 }
726
727 if (V4L2_FIELD_HAS_BOTH(field)) {
728 } else if (field == V4L2_FIELD_ALTERNATE) {
729 /* fixme */
730 if ( vv->last_field == V4L2_FIELD_TOP ) {
731 vdma1.base_odd = vdma1.prot_addr;
732 vdma1.pitch /= 2;
733 } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
734 vdma1.base_odd = vdma1.base_even;
735 vdma1.base_even = vdma1.prot_addr;
736 vdma1.pitch /= 2;
737 }
738 } else if (field == V4L2_FIELD_TOP) {
739 vdma1.base_odd = vdma1.prot_addr;
740 vdma1.pitch /= 2;
741 } else if (field == V4L2_FIELD_BOTTOM) {
742 vdma1.base_odd = vdma1.base_even;
743 vdma1.base_even = vdma1.prot_addr;
744 vdma1.pitch /= 2;
745 }
746
747 if( 0 != vv->vflip ) {
748 vdma1.pitch *= -1;
749 }
750
751 saa7146_write_out_dma(dev, 1, &vdma1);
752 return 0;
753}
754
755static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
756{
757 int height = buf->fmt->height;
758 int width = buf->fmt->width;
759
760 vdma2->pitch = width;
761 vdma3->pitch = width;
762
763 /* fixme: look at bytesperline! */
764
765 if( 0 != vv->vflip ) {
766 vdma2->prot_addr = buf->pt[1].offset;
767 vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[1].offset;
768 vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2);
769
770 vdma3->prot_addr = buf->pt[2].offset;
771 vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[2].offset;
772 vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2);
773 } else {
774 vdma3->base_even = buf->pt[2].offset;
775 vdma3->base_odd = vdma3->base_even + (vdma3->pitch/2);
776 vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset;
777
778 vdma2->base_even = buf->pt[1].offset;
779 vdma2->base_odd = vdma2->base_even + (vdma2->pitch/2);
780 vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset;
781 }
782
783 return 0;
784}
785
786static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
787{
788 int height = buf->fmt->height;
789 int width = buf->fmt->width;
790
791 vdma2->pitch = width/2;
792 vdma3->pitch = width/2;
793
794 if( 0 != vv->vflip ) {
795 vdma2->prot_addr = buf->pt[2].offset;
796 vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[2].offset;
797 vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2);
798
799 vdma3->prot_addr = buf->pt[1].offset;
800 vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[1].offset;
801 vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2);
802
803 } else {
804 vdma3->base_even = buf->pt[2].offset;
805 vdma3->base_odd = vdma3->base_even + (vdma3->pitch);
806 vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset;
807
808 vdma2->base_even = buf->pt[1].offset;
809 vdma2->base_odd = vdma2->base_even + (vdma2->pitch);
810 vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset;
811 }
812 return 0;
813}
814
815static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
816{
817 struct saa7146_vv *vv = dev->vv_data;
818 struct saa7146_video_dma vdma1;
819 struct saa7146_video_dma vdma2;
820 struct saa7146_video_dma vdma3;
821
822 struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
823
824 int width = buf->fmt->width;
825 int height = buf->fmt->height;
826 enum v4l2_field field = buf->fmt->field;
827
828 BUG_ON(0 == buf->pt[0].dma);
829 BUG_ON(0 == buf->pt[1].dma);
830 BUG_ON(0 == buf->pt[2].dma);
831
832 DEB_CAP(("[size=%dx%d,fields=%s]\n",
833 width,height,v4l2_field_names[field]));
834
835 /* fixme: look at bytesperline! */
836
837 /* fixme: what happens for user space buffers here?. The offsets are
838 most likely wrong, this version here only works for page-aligned
839 buffers, modifications to the pagetable-functions are necessary...*/
840
841 vdma1.pitch = width*2;
842 vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
843 vdma1.base_page = buf->pt[0].dma | ME1;
844
845 if( 0 != vv->vflip ) {
846 vdma1.prot_addr = buf->pt[0].offset;
847 vdma1.base_even = ((vdma1.pitch/2)*height)+buf->pt[0].offset;
848 vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
849 } else {
850 vdma1.base_even = buf->pt[0].offset;
851 vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
852 vdma1.prot_addr = (vdma1.pitch/2)*height+buf->pt[0].offset;
853 }
854
855 vdma2.num_line_byte = 0; /* unused */
856 vdma2.base_page = buf->pt[1].dma | ME1;
857
858 vdma3.num_line_byte = 0; /* unused */
859 vdma3.base_page = buf->pt[2].dma | ME1;
860
861 switch( sfmt->depth ) {
862 case 12: {
863 calc_planar_420(vv,buf,&vdma2,&vdma3);
864 break;
865 }
866 case 16: {
867 calc_planar_422(vv,buf,&vdma2,&vdma3);
868 break;
869 }
870 default: {
871 return -1;
872 }
873 }
874
875 if (V4L2_FIELD_HAS_BOTH(field)) {
876 } else if (field == V4L2_FIELD_ALTERNATE) {
877 /* fixme */
878 vdma1.base_odd = vdma1.prot_addr;
879 vdma1.pitch /= 2;
880 vdma2.base_odd = vdma2.prot_addr;
881 vdma2.pitch /= 2;
882 vdma3.base_odd = vdma3.prot_addr;
883 vdma3.pitch /= 2;
884 } else if (field == V4L2_FIELD_TOP) {
885 vdma1.base_odd = vdma1.prot_addr;
886 vdma1.pitch /= 2;
887 vdma2.base_odd = vdma2.prot_addr;
888 vdma2.pitch /= 2;
889 vdma3.base_odd = vdma3.prot_addr;
890 vdma3.pitch /= 2;
891 } else if (field == V4L2_FIELD_BOTTOM) {
892 vdma1.base_odd = vdma1.base_even;
893 vdma1.base_even = vdma1.prot_addr;
894 vdma1.pitch /= 2;
895 vdma2.base_odd = vdma2.base_even;
896 vdma2.base_even = vdma2.prot_addr;
897 vdma2.pitch /= 2;
898 vdma3.base_odd = vdma3.base_even;
899 vdma3.base_even = vdma3.prot_addr;
900 vdma3.pitch /= 2;
901 }
902
903 if( 0 != vv->vflip ) {
904 vdma1.pitch *= -1;
905 vdma2.pitch *= -1;
906 vdma3.pitch *= -1;
907 }
908
909 saa7146_write_out_dma(dev, 1, &vdma1);
910 if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
911 saa7146_write_out_dma(dev, 3, &vdma2);
912 saa7146_write_out_dma(dev, 2, &vdma3);
913 } else {
914 saa7146_write_out_dma(dev, 2, &vdma2);
915 saa7146_write_out_dma(dev, 3, &vdma3);
916 }
917 return 0;
918}
919
920static void program_capture_engine(struct saa7146_dev *dev, int planar)
921{
922 struct saa7146_vv *vv = dev->vv_data;
923 int count = 0;
924
925 unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
926 unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
927
928 /* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
929 WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
930 WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
931
932 /* set rps register 0 */
933 WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
934 WRITE_RPS0(MASK_27 | MASK_11);
935
936 /* turn on video-dma1 */
937 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
938 WRITE_RPS0(MASK_06 | MASK_22); /* => mask */
939 WRITE_RPS0(MASK_06 | MASK_22); /* => values */
940 if( 0 != planar ) {
941 /* turn on video-dma2 */
942 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
943 WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
944 WRITE_RPS0(MASK_05 | MASK_21); /* => values */
945
946 /* turn on video-dma3 */
947 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
948 WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
949 WRITE_RPS0(MASK_04 | MASK_20); /* => values */
950 }
951
952 /* wait for o_fid_a/b / e_fid_a/b toggle */
953 if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
954 WRITE_RPS0(CMD_PAUSE | o_wait);
955 WRITE_RPS0(CMD_PAUSE | e_wait);
956 } else if ( vv->last_field == V4L2_FIELD_TOP ) {
957 WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
958 WRITE_RPS0(CMD_PAUSE | o_wait);
959 } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
960 WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
961 WRITE_RPS0(CMD_PAUSE | e_wait);
962 }
963
964 /* turn off video-dma1 */
965 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
966 WRITE_RPS0(MASK_22 | MASK_06); /* => mask */
967 WRITE_RPS0(MASK_22); /* => values */
968 if( 0 != planar ) {
969 /* turn off video-dma2 */
970 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
971 WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
972 WRITE_RPS0(MASK_21); /* => values */
973
974 /* turn off video-dma3 */
975 WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
976 WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
977 WRITE_RPS0(MASK_20); /* => values */
978 }
979
980 /* generate interrupt */
981 WRITE_RPS0(CMD_INTERRUPT);
982
983 /* stop */
984 WRITE_RPS0(CMD_STOP);
985}
986
987void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
988{
989 struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
990 struct saa7146_vv *vv = dev->vv_data;
991 u32 vdma1_prot_addr;
992
993 DEB_CAP(("buf:%p, next:%p\n",buf,next));
994
995 vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
996 if( 0 == vdma1_prot_addr ) {
997 /* clear out beginning of streaming bit (rps register 0)*/
998 DEB_CAP(("forcing sync to new frame\n"));
999 saa7146_write(dev, MC2, MASK_27 );
1000 }
1001
1002 saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
1003 saa7146_set_output_format(dev, sfmt->trans);
1004 saa7146_disable_clipping(dev);
1005
1006 if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
1007 } else if ( vv->last_field == V4L2_FIELD_TOP ) {
1008 vv->last_field = V4L2_FIELD_BOTTOM;
1009 } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
1010 vv->last_field = V4L2_FIELD_TOP;
1011 }
1012
1013 if( 0 != IS_PLANAR(sfmt->trans)) {
1014 calculate_video_dma_grab_planar(dev, buf);
1015 program_capture_engine(dev,1);
1016 } else {
1017 calculate_video_dma_grab_packed(dev, buf);
1018 program_capture_engine(dev,0);
1019 }
1020
1021/*
1022 printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
1023 printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
1024 printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
1025 printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
1026 printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1));
1027 printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
1028 printk("vdma%d => vptr : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
1029*/
1030
1031 /* write the address of the rps-program */
1032 saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
1033
1034 /* turn on rps */
1035 saa7146_write(dev, MC1, (MASK_12 | MASK_28));
1036}
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
new file mode 100644
index 000000000000..781f23f0cbcc
--- /dev/null
+++ b/drivers/media/common/saa7146_i2c.c
@@ -0,0 +1,421 @@
1#include <linux/version.h>
2#include <media/saa7146_vv.h>
3
4static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
5{
6//fm DEB_I2C(("'%s'.\n", adapter->name));
7
8 return I2C_FUNC_I2C
9 | I2C_FUNC_SMBUS_QUICK
10 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE
11 | I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
12}
13
14/* this function returns the status-register of our i2c-device */
15static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
16{
17 u32 iicsta = saa7146_read(dev, I2C_STATUS);
18/*
19 DEB_I2C(("status: 0x%08x\n",iicsta));
20*/
21 return iicsta;
22}
23
24/* this function runs through the i2c-messages and prepares the data to be
25 sent through the saa7146. have a look at the specifications p. 122 ff
26 to understand this. it returns the number of u32s to send, or -1
27 in case of an error. */
28static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
29{
30 int h1, h2;
31 int i, j, addr;
32 int mem = 0, op_count = 0;
33
34 /* first determine size of needed memory */
35 for(i = 0; i < num; i++) {
36 mem += m[i].len + 1;
37 }
38
39 /* worst case: we need one u32 for three bytes to be send
40 plus one extra byte to address the device */
41 mem = 1 + ((mem-1) / 3);
42
43 /* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
44 size. if we exceed this limit... */
45 if ( (4*mem) > SAA7146_I2C_MEM ) {
46//fm DEB_I2C(("cannot prepare i2c-message.\n"));
47 return -ENOMEM;
48 }
49
50 /* be careful: clear out the i2c-mem first */
51 memset(op,0,sizeof(u32)*mem);
52
53 /* loop through all messages */
54 for(i = 0; i < num; i++) {
55
56 /* insert the address of the i2c-slave.
57 note: we get 7 bit i2c-addresses,
58 so we have to perform a translation */
59 addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
60 h1 = op_count/3; h2 = op_count%3;
61 op[h1] |= ( (u8)addr << ((3-h2)*8));
62 op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
63 op_count++;
64
65 /* loop through all bytes of message i */
66 for(j = 0; j < m[i].len; j++) {
67 /* insert the data bytes */
68 h1 = op_count/3; h2 = op_count%3;
69 op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
70 op[h1] |= ( SAA7146_I2C_CONT << ((3-h2)*2));
71 op_count++;
72 }
73
74 }
75
76 /* have a look at the last byte inserted:
77 if it was: ...CONT change it to ...STOP */
78 h1 = (op_count-1)/3; h2 = (op_count-1)%3;
79 if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) {
80 op[h1] &= ~(0x2 << ((3-h2)*2));
81 op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
82 }
83
84 /* return the number of u32s to send */
85 return mem;
86}
87
88/* this functions loops through all i2c-messages. normally, it should determine
89 which bytes were read through the adapter and write them back to the corresponding
90 i2c-message. but instead, we simply write back all bytes.
91 fixme: this could be improved. */
92static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
93{
94 int i, j;
95 int op_count = 0;
96
97 /* loop through all messages */
98 for(i = 0; i < num; i++) {
99
100 op_count++;
101
102 /* loop throgh all bytes of message i */
103 for(j = 0; j < m[i].len; j++) {
104 /* write back all bytes that could have been read */
105 m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8));
106 op_count++;
107 }
108 }
109
110 return 0;
111}
112
113/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
114static int saa7146_i2c_reset(struct saa7146_dev *dev)
115{
116 /* get current status */
117 u32 status = saa7146_i2c_status(dev);
118
119 /* clear registers for sure */
120 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
121 saa7146_write(dev, I2C_TRANSFER, 0);
122
123 /* check if any operation is still in progress */
124 if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
125
126 /* yes, kill ongoing operation */
127 DEB_I2C(("busy_state detected.\n"));
128
129 /* set "ABORT-OPERATION"-bit (bit 7)*/
130 saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
131 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
132 msleep(SAA7146_I2C_DELAY);
133
134 /* clear all error-bits pending; this is needed because p.123, note 1 */
135 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
136 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
137 msleep(SAA7146_I2C_DELAY);
138 }
139
140 /* check if any error is (still) present. (this can be necessary because p.123, note 1) */
141 status = saa7146_i2c_status(dev);
142
143 if ( dev->i2c_bitrate != status ) {
144
145 DEB_I2C(("error_state detected. status:0x%08x\n",status));
146
147 /* Repeat the abort operation. This seems to be necessary
148 after serious protocol errors caused by e.g. the SAA7740 */
149 saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
150 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
151 msleep(SAA7146_I2C_DELAY);
152
153 /* clear all error-bits pending */
154 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
155 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
156 msleep(SAA7146_I2C_DELAY);
157
158 /* the data sheet says it might be necessary to clear the status
159 twice after an abort */
160 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
161 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
162 msleep(SAA7146_I2C_DELAY);
163 }
164
165 /* if any error is still present, a fatal error has occured ... */
166 status = saa7146_i2c_status(dev);
167 if ( dev->i2c_bitrate != status ) {
168 DEB_I2C(("fatal error. status:0x%08x\n",status));
169 return -1;
170 }
171
172 return 0;
173}
174
175/* this functions writes out the data-byte 'dword' to the i2c-device.
176 it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
177 failed badly (e.g. address error) */
178static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
179{
180 u32 status = 0, mc2 = 0;
181 int trial = 0;
182 unsigned long timeout;
183
184 /* write out i2c-command */
185 DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
186
187 if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
188
189 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
190 saa7146_write(dev, I2C_TRANSFER, *dword);
191
192 dev->i2c_op = 1;
193 SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
194 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
195
196 wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
197 if (signal_pending (current)) {
198 /* a signal arrived */
199 return -ERESTARTSYS;
200 }
201 status = saa7146_read(dev, I2C_STATUS);
202 } else {
203 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
204 saa7146_write(dev, I2C_TRANSFER, *dword);
205 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
206
207 /* do not poll for i2c-status before upload is complete */
208 timeout = jiffies + HZ/100 + 1; /* 10ms */
209 while(1) {
210 mc2 = (saa7146_read(dev, MC2) & 0x1);
211 if( 0 != mc2 ) {
212 break;
213 }
214 if (time_after(jiffies,timeout)) {
215 printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
216 return -EIO;
217 }
218 }
219 /* wait until we get a transfer done or error */
220 timeout = jiffies + HZ/100 + 1; /* 10ms */
221 while(1) {
222 /**
223 * first read usually delivers bogus results...
224 */
225 saa7146_i2c_status(dev);
226 status = saa7146_i2c_status(dev);
227 if ((status & 0x3) != 1)
228 break;
229 if (time_after(jiffies,timeout)) {
230 /* this is normal when probing the bus
231 * (no answer from nonexisistant device...)
232 */
233 DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
234 return -EIO;
235 }
236 if ((++trial < 20) && short_delay)
237 udelay(10);
238 else
239 msleep(1);
240 }
241 }
242
243 /* give a detailed status report */
244 if ( 0 != (status & SAA7146_I2C_ERR)) {
245
246 if( 0 != (status & SAA7146_I2C_SPERR) ) {
247 DEB_I2C(("error due to invalid start/stop condition.\n"));
248 }
249 if( 0 != (status & SAA7146_I2C_DTERR) ) {
250 DEB_I2C(("error in data transmission.\n"));
251 }
252 if( 0 != (status & SAA7146_I2C_DRERR) ) {
253 DEB_I2C(("error when receiving data.\n"));
254 }
255 if( 0 != (status & SAA7146_I2C_AL) ) {
256 DEB_I2C(("error because arbitration lost.\n"));
257 }
258
259 /* we handle address-errors here */
260 if( 0 != (status & SAA7146_I2C_APERR) ) {
261 DEB_I2C(("error in address phase.\n"));
262 return -EREMOTEIO;
263 }
264
265 return -EIO;
266 }
267
268 /* read back data, just in case we were reading ... */
269 *dword = saa7146_read(dev, I2C_TRANSFER);
270
271 DEB_I2C(("after: 0x%08x\n",*dword));
272 return 0;
273}
274
275int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
276{
277 int i = 0, count = 0;
278 u32* buffer = dev->d_i2c.cpu_addr;
279 int err = 0;
280 int address_err = 0;
281 int short_delay = 0;
282
283 if (down_interruptible (&dev->i2c_lock))
284 return -ERESTARTSYS;
285
286 for(i=0;i<num;i++) {
287 DEB_I2C(("msg:%d/%d\n",i+1,num));
288 }
289
290 /* prepare the message(s), get number of u32s to transfer */
291 count = saa7146_i2c_msg_prepare(msgs, num, buffer);
292 if ( 0 > count ) {
293 err = -1;
294 goto out;
295 }
296
297 if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
298 short_delay = 1;
299
300 do {
301 /* reset the i2c-device if necessary */
302 err = saa7146_i2c_reset(dev);
303 if ( 0 > err ) {
304 DEB_I2C(("could not reset i2c-device.\n"));
305 goto out;
306 }
307
308 /* write out the u32s one after another */
309 for(i = 0; i < count; i++) {
310 err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
311 if ( 0 != err) {
312 /* this one is unsatisfying: some i2c slaves on some
313 dvb cards don't acknowledge correctly, so the saa7146
314 thinks that an address error occured. in that case, the
315 transaction should be retrying, even if an address error
316 occured. analog saa7146 based cards extensively rely on
317 i2c address probing, however, and address errors indicate that a
318 device is really *not* there. retrying in that case
319 increases the time the device needs to probe greatly, so
320 it should be avoided. because of the fact, that only
321 analog based cards use irq based i2c transactions (for dvb
322 cards, this screwes up other interrupt sources), we bail out
323 completely for analog cards after an address error and trust
324 the saa7146 address error detection. */
325 if ( -EREMOTEIO == err ) {
326 if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
327 goto out;
328 }
329 address_err++;
330 }
331 DEB_I2C(("error while sending message(s). starting again.\n"));
332 break;
333 }
334 }
335 if( 0 == err ) {
336 err = num;
337 break;
338 }
339
340 /* delay a bit before retrying */
341 msleep(10);
342
343 } while (err != num && retries--);
344
345 /* if every retry had an address error, exit right away */
346 if (address_err == retries) {
347 goto out;
348 }
349
350 /* if any things had to be read, get the results */
351 if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
352 DEB_I2C(("could not cleanup i2c-message.\n"));
353 err = -1;
354 goto out;
355 }
356
357 /* return the number of delivered messages */
358 DEB_I2C(("transmission successful. (msg:%d).\n",err));
359out:
360 /* another bug in revision 0: the i2c-registers get uploaded randomly by other
361 uploads, so we better clear them out before continueing */
362 if( 0 == dev->revision ) {
363 u32 zero = 0;
364 saa7146_i2c_reset(dev);
365 if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
366 INFO(("revision 0 error. this should never happen.\n"));
367 }
368 }
369
370 up(&dev->i2c_lock);
371 return err;
372}
373
374/* utility functions */
375static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
376{
377 struct saa7146_dev* dev = i2c_get_adapdata(adapter);
378
379 /* use helper function to transfer data */
380 return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
381}
382
383
384/*****************************************************************************/
385/* i2c-adapter helper functions */
386#include <linux/i2c-id.h>
387
388/* exported algorithm data */
389static struct i2c_algorithm saa7146_algo = {
390 .name = "saa7146 i2c algorithm",
391 .id = I2C_ALGO_SAA7146,
392 .master_xfer = saa7146_i2c_xfer,
393 .functionality = saa7146_i2c_func,
394};
395
396int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
397{
398 DEB_EE(("bitrate: 0x%08x\n",bitrate));
399
400 /* enable i2c-port pins */
401 saa7146_write(dev, MC1, (MASK_08 | MASK_24));
402
403 dev->i2c_bitrate = bitrate;
404 saa7146_i2c_reset(dev);
405
406 if( NULL != i2c_adapter ) {
407#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
408 i2c_adapter->data = dev;
409#else
410 BUG_ON(!i2c_adapter->class);
411 i2c_set_adapdata(i2c_adapter,dev);
412#endif
413 i2c_adapter->algo = &saa7146_algo;
414 i2c_adapter->algo_data = NULL;
415 i2c_adapter->id = I2C_ALGO_SAA7146;
416 i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
417 i2c_adapter->retries = SAA7146_I2C_RETRIES;
418 }
419
420 return 0;
421}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
new file mode 100644
index 000000000000..cb86a97fda1f
--- /dev/null
+++ b/drivers/media/common/saa7146_vbi.c
@@ -0,0 +1,508 @@
1#include <media/saa7146_vv.h>
2
3static int vbi_pixel_to_capture = 720 * 2;
4
5static int vbi_workaround(struct saa7146_dev *dev)
6{
7 struct saa7146_vv *vv = dev->vv_data;
8
9 u32 *cpu;
10 dma_addr_t dma_addr;
11
12 int count = 0;
13 int i;
14
15 DECLARE_WAITQUEUE(wait, current);
16
17 DEB_VBI(("dev:%p\n",dev));
18
19 /* once again, a bug in the saa7146: the brs acquisition
20 is buggy and especially the BXO-counter does not work
21 as specified. there is this workaround, but please
22 don't let me explain it. ;-) */
23
24 cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr);
25 if (NULL == cpu)
26 return -ENOMEM;
27
28 /* setup some basic programming, just for the workaround */
29 saa7146_write(dev, BASE_EVEN3, dma_addr);
30 saa7146_write(dev, BASE_ODD3, dma_addr+vbi_pixel_to_capture);
31 saa7146_write(dev, PROT_ADDR3, dma_addr+4096);
32 saa7146_write(dev, PITCH3, vbi_pixel_to_capture);
33 saa7146_write(dev, BASE_PAGE3, 0x0);
34 saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
35 saa7146_write(dev, MC2, MASK_04|MASK_20);
36
37 /* load brs-control register */
38 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
39 /* BXO = 1h, BRS to outbound */
40 WRITE_RPS1(0xc000008c);
41 /* wait for vbi_a or vbi_b*/
42 if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
43 DEB_D(("...using port b\n"));
44 WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
45 WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
46/*
47 WRITE_RPS1(CMD_PAUSE | MASK_09);
48*/
49 } else {
50 DEB_D(("...using port a\n"));
51 WRITE_RPS1(CMD_PAUSE | MASK_10);
52 }
53 /* upload brs */
54 WRITE_RPS1(CMD_UPLOAD | MASK_08);
55 /* load brs-control register */
56 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
57 /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
58 WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
59 /* wait for brs_done */
60 WRITE_RPS1(CMD_PAUSE | MASK_08);
61 /* upload brs */
62 WRITE_RPS1(CMD_UPLOAD | MASK_08);
63 /* load video-dma3 NumLines3 and NumBytes3 */
64 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
65 /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
66 WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
67 /* load brs-control register */
68 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
69 /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
70 WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start
71 /* wait for brs_done */
72 WRITE_RPS1(CMD_PAUSE | MASK_08);
73 /* upload brs and video-dma3*/
74 WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
75 /* load mc2 register: enable dma3 */
76 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
77 WRITE_RPS1(MASK_20 | MASK_04);
78 /* generate interrupt */
79 WRITE_RPS1(CMD_INTERRUPT);
80 /* stop rps1 */
81 WRITE_RPS1(CMD_STOP);
82
83 /* we have to do the workaround twice to be sure that
84 everything is ok */
85 for(i = 0; i < 2; i++) {
86
87 /* indicate to the irq handler that we do the workaround */
88 saa7146_write(dev, MC2, MASK_31|MASK_15);
89
90 saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
91 saa7146_write(dev, MC2, MASK_04|MASK_20);
92
93 /* enable rps1 irqs */
94 SAA7146_IER_ENABLE(dev,MASK_28);
95
96 /* prepare to wait to be woken up by the irq-handler */
97 add_wait_queue(&vv->vbi_wq, &wait);
98 current->state = TASK_INTERRUPTIBLE;
99
100 /* start rps1 to enable workaround */
101 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
102 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
103
104 schedule();
105
106 DEB_VBI(("brs bug workaround %d/1.\n",i));
107
108 remove_wait_queue(&vv->vbi_wq, &wait);
109 current->state = TASK_RUNNING;
110
111 /* disable rps1 irqs */
112 SAA7146_IER_DISABLE(dev,MASK_28);
113
114 /* stop video-dma3 */
115 saa7146_write(dev, MC1, MASK_20);
116
117 if(signal_pending(current)) {
118
119 DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
120
121 /* stop rps1 for sure */
122 saa7146_write(dev, MC1, MASK_29);
123
124 pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
125 return -EINTR;
126 }
127 }
128
129 pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
130 return 0;
131}
132
133static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
134{
135 struct saa7146_vv *vv = dev->vv_data;
136
137 struct saa7146_video_dma vdma3;
138
139 int count = 0;
140 unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
141 unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
142
143/*
144 vdma3.base_even = 0xc8000000+2560*70;
145 vdma3.base_odd = 0xc8000000;
146 vdma3.prot_addr = 0xc8000000+2560*164;
147 vdma3.pitch = 2560;
148 vdma3.base_page = 0;
149 vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
150*/
151 vdma3.base_even = buf->pt[2].offset;
152 vdma3.base_odd = buf->pt[2].offset + 16 * vbi_pixel_to_capture;
153 vdma3.prot_addr = buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture;
154 vdma3.pitch = vbi_pixel_to_capture;
155 vdma3.base_page = buf->pt[2].dma | ME1;
156 vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
157
158 saa7146_write_out_dma(dev, 3, &vdma3);
159
160 /* write beginning of rps-program */
161 count = 0;
162
163 /* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */
164
165 /* we don't wait here for the first field anymore. this is different from the video
166 capture and might cause that the first buffer is only half filled (with only
167 one field). but since this is some sort of streaming data, this is not that negative.
168 but by doing this, we can use the whole engine from video-buf.c... */
169
170/*
171 WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
172 WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
173*/
174 /* set bit 1 */
175 WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
176 WRITE_RPS1(MASK_28 | MASK_12);
177
178 /* turn on video-dma3 */
179 WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
180 WRITE_RPS1(MASK_04 | MASK_20); /* => mask */
181 WRITE_RPS1(MASK_04 | MASK_20); /* => values */
182
183 /* wait for o_fid_a/b / e_fid_a/b toggle */
184 WRITE_RPS1(CMD_PAUSE | o_wait);
185 WRITE_RPS1(CMD_PAUSE | e_wait);
186
187 /* generate interrupt */
188 WRITE_RPS1(CMD_INTERRUPT);
189
190 /* stop */
191 WRITE_RPS1(CMD_STOP);
192
193 /* enable rps1 irqs */
194 SAA7146_IER_ENABLE(dev, MASK_28);
195
196 /* write the address of the rps-program */
197 saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
198
199 /* turn on rps */
200 saa7146_write(dev, MC1, (MASK_13 | MASK_29));
201}
202
203static int buffer_activate(struct saa7146_dev *dev,
204 struct saa7146_buf *buf,
205 struct saa7146_buf *next)
206{
207 struct saa7146_vv *vv = dev->vv_data;
208 buf->vb.state = STATE_ACTIVE;
209
210 DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
211 saa7146_set_vbi_capture(dev,buf,next);
212
213 mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
214 return 0;
215}
216
217static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
218{
219 struct file *file = q->priv_data;
220 struct saa7146_fh *fh = file->private_data;
221 struct saa7146_dev *dev = fh->dev;
222 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
223
224 int err = 0;
225 int lines, llength, size;
226
227 lines = 16 * 2 ; /* 2 fields */
228 llength = vbi_pixel_to_capture;
229 size = lines * llength;
230
231 DEB_VBI(("vb:%p\n",vb));
232
233 if (0 != buf->vb.baddr && buf->vb.bsize < size) {
234 DEB_VBI(("size mismatch.\n"));
235 return -EINVAL;
236 }
237
238 if (buf->vb.size != size)
239 saa7146_dma_free(dev,buf);
240
241 if (STATE_NEEDS_INIT == buf->vb.state) {
242 buf->vb.width = llength;
243 buf->vb.height = lines;
244 buf->vb.size = size;
245 buf->vb.field = field; // FIXME: check this
246
247 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
248 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
249
250 err = videobuf_iolock(dev->pci,&buf->vb, NULL);
251 if (err)
252 goto oops;
253 err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
254 if (0 != err)
255 return err;
256 }
257 buf->vb.state = STATE_PREPARED;
258 buf->activate = buffer_activate;
259
260 return 0;
261
262 oops:
263 DEB_VBI(("error out.\n"));
264 saa7146_dma_free(dev,buf);
265
266 return err;
267}
268
269static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
270{
271 int llength,lines;
272
273 lines = 16 * 2 ; /* 2 fields */
274 llength = vbi_pixel_to_capture;
275
276 *size = lines * llength;
277 *count = 2;
278
279 DEB_VBI(("count:%d, size:%d\n",*count,*size));
280
281 return 0;
282}
283
284static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
285{
286 struct file *file = q->priv_data;
287 struct saa7146_fh *fh = file->private_data;
288 struct saa7146_dev *dev = fh->dev;
289 struct saa7146_vv *vv = dev->vv_data;
290 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
291
292 DEB_VBI(("vb:%p\n",vb));
293 saa7146_buffer_queue(dev,&vv->vbi_q,buf);
294}
295
296static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
297{
298 struct file *file = q->priv_data;
299 struct saa7146_fh *fh = file->private_data;
300 struct saa7146_dev *dev = fh->dev;
301 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
302
303 DEB_VBI(("vb:%p\n",vb));
304 saa7146_dma_free(dev,buf);
305}
306
307static struct videobuf_queue_ops vbi_qops = {
308 .buf_setup = buffer_setup,
309 .buf_prepare = buffer_prepare,
310 .buf_queue = buffer_queue,
311 .buf_release = buffer_release,
312};
313
314/* ------------------------------------------------------------------ */
315
316static void vbi_stop(struct saa7146_fh *fh, struct file *file)
317{
318 struct saa7146_dev *dev = fh->dev;
319 struct saa7146_vv *vv = dev->vv_data;
320 unsigned long flags;
321 DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
322
323 spin_lock_irqsave(&dev->slock,flags);
324
325 /* disable rps1 */
326 saa7146_write(dev, MC1, MASK_29);
327
328 /* disable rps1 irqs */
329 SAA7146_IER_DISABLE(dev, MASK_28);
330
331 /* shut down dma 3 transfers */
332 saa7146_write(dev, MC1, MASK_20);
333
334 if (vv->vbi_q.curr) {
335 saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
336 }
337
338 videobuf_queue_cancel(&fh->vbi_q);
339
340 vv->vbi_streaming = NULL;
341
342 del_timer(&vv->vbi_q.timeout);
343 del_timer(&fh->vbi_read_timeout);
344
345 spin_unlock_irqrestore(&dev->slock, flags);
346}
347
348static void vbi_read_timeout(unsigned long data)
349{
350 struct file *file = (struct file*)data;
351 struct saa7146_fh *fh = file->private_data;
352 struct saa7146_dev *dev = fh->dev;
353
354 DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
355
356 vbi_stop(fh, file);
357}
358
359static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
360{
361 DEB_VBI(("dev:%p\n",dev));
362
363 INIT_LIST_HEAD(&vv->vbi_q.queue);
364
365 init_timer(&vv->vbi_q.timeout);
366 vv->vbi_q.timeout.function = saa7146_buffer_timeout;
367 vv->vbi_q.timeout.data = (unsigned long)(&vv->vbi_q);
368 vv->vbi_q.dev = dev;
369
370 init_waitqueue_head(&vv->vbi_wq);
371}
372
373static int vbi_open(struct saa7146_dev *dev, struct file *file)
374{
375 struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
376
377 u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
378 int ret = 0;
379
380 DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
381
382 ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
383 if (0 == ret) {
384 DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
385 return -EBUSY;
386 }
387
388 /* adjust arbitrition control for video dma 3 */
389 arbtr_ctrl &= ~0x1f0000;
390 arbtr_ctrl |= 0x1d0000;
391 saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
392 saa7146_write(dev, MC2, (MASK_04|MASK_20));
393
394 memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
395
396 fh->vbi_fmt.sampling_rate = 27000000;
397 fh->vbi_fmt.offset = 248; /* todo */
398 fh->vbi_fmt.samples_per_line = vbi_pixel_to_capture;
399 fh->vbi_fmt.sample_format = V4L2_PIX_FMT_GREY;
400
401 /* fixme: this only works for PAL */
402 fh->vbi_fmt.start[0] = 5;
403 fh->vbi_fmt.count[0] = 16;
404 fh->vbi_fmt.start[1] = 312;
405 fh->vbi_fmt.count[1] = 16;
406
407 videobuf_queue_init(&fh->vbi_q, &vbi_qops,
408 dev->pci, &dev->slock,
409 V4L2_BUF_TYPE_VBI_CAPTURE,
410 V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
411 sizeof(struct saa7146_buf),
412 file);
413 init_MUTEX(&fh->vbi_q.lock);
414
415 init_timer(&fh->vbi_read_timeout);
416 fh->vbi_read_timeout.function = vbi_read_timeout;
417 fh->vbi_read_timeout.data = (unsigned long)file;
418
419 /* initialize the brs */
420 if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
421 saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
422 } else {
423 saa7146_write(dev, BRS_CTRL, 0x00000001);
424
425 if (0 != (ret = vbi_workaround(dev))) {
426 DEB_VBI(("vbi workaround failed!\n"));
427 /* return ret;*/
428 }
429 }
430
431 /* upload brs register */
432 saa7146_write(dev, MC2, (MASK_08|MASK_24));
433 return 0;
434}
435
436static void vbi_close(struct saa7146_dev *dev, struct file *file)
437{
438 struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
439 struct saa7146_vv *vv = dev->vv_data;
440 DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
441
442 if( fh == vv->vbi_streaming ) {
443 vbi_stop(fh, file);
444 }
445 saa7146_res_free(fh, RESOURCE_DMA3_BRS);
446}
447
448static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
449{
450 struct saa7146_vv *vv = dev->vv_data;
451 spin_lock(&dev->slock);
452
453 if (vv->vbi_q.curr) {
454 DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
455 /* this must be += 2, one count for each field */
456 vv->vbi_fieldcount+=2;
457 vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
458 saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
459 } else {
460 DEB_VBI(("dev:%p\n",dev));
461 }
462 saa7146_buffer_next(dev,&vv->vbi_q,1);
463
464 spin_unlock(&dev->slock);
465}
466
467static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
468{
469 struct saa7146_fh *fh = file->private_data;
470 struct saa7146_dev *dev = fh->dev;
471 struct saa7146_vv *vv = dev->vv_data;
472 ssize_t ret = 0;
473
474 DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
475
476 if( NULL == vv->vbi_streaming ) {
477 // fixme: check if dma3 is available
478 // fixme: activate vbi engine here if necessary. (really?)
479 vv->vbi_streaming = fh;
480 }
481
482 if( fh != vv->vbi_streaming ) {
483 DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
484 return -EBUSY;
485 }
486
487 mod_timer(&fh->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
488 ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
489 file->f_flags & O_NONBLOCK);
490/*
491 printk("BASE_ODD3: 0x%08x\n", saa7146_read(dev, BASE_ODD3));
492 printk("BASE_EVEN3: 0x%08x\n", saa7146_read(dev, BASE_EVEN3));
493 printk("PROT_ADDR3: 0x%08x\n", saa7146_read(dev, PROT_ADDR3));
494 printk("PITCH3: 0x%08x\n", saa7146_read(dev, PITCH3));
495 printk("BASE_PAGE3: 0x%08x\n", saa7146_read(dev, BASE_PAGE3));
496 printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
497 printk("BRS_CTRL: 0x%08x\n", saa7146_read(dev, BRS_CTRL));
498*/
499 return ret;
500}
501
502struct saa7146_use_ops saa7146_vbi_uops = {
503 .init = vbi_init,
504 .open = vbi_open,
505 .release = vbi_close,
506 .irq_done = vbi_irq_done,
507 .read = vbi_read,
508};
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
new file mode 100644
index 000000000000..8dd4d15ca36d
--- /dev/null
+++ b/drivers/media/common/saa7146_video.c
@@ -0,0 +1,1509 @@
1#include <media/saa7146_vv.h>
2
3static int max_memory = 32;
4
5module_param(max_memory, int, 0644);
6MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
7
8#define IS_CAPTURE_ACTIVE(fh) \
9 (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
10
11#define IS_OVERLAY_ACTIVE(fh) \
12 (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
13
14/* format descriptions for capture and preview */
15static struct saa7146_format formats[] = {
16 {
17 .name = "RGB-8 (3-3-2)",
18 .pixelformat = V4L2_PIX_FMT_RGB332,
19 .trans = RGB08_COMPOSED,
20 .depth = 8,
21 .flags = 0,
22 }, {
23 .name = "RGB-16 (5/B-6/G-5/R)",
24 .pixelformat = V4L2_PIX_FMT_RGB565,
25 .trans = RGB16_COMPOSED,
26 .depth = 16,
27 .flags = 0,
28 }, {
29 .name = "RGB-24 (B-G-R)",
30 .pixelformat = V4L2_PIX_FMT_BGR24,
31 .trans = RGB24_COMPOSED,
32 .depth = 24,
33 .flags = 0,
34 }, {
35 .name = "RGB-32 (B-G-R)",
36 .pixelformat = V4L2_PIX_FMT_BGR32,
37 .trans = RGB32_COMPOSED,
38 .depth = 32,
39 .flags = 0,
40 }, {
41 .name = "RGB-32 (R-G-B)",
42 .pixelformat = V4L2_PIX_FMT_RGB32,
43 .trans = RGB32_COMPOSED,
44 .depth = 32,
45 .flags = 0,
46 .swap = 0x2,
47 }, {
48 .name = "Greyscale-8",
49 .pixelformat = V4L2_PIX_FMT_GREY,
50 .trans = Y8,
51 .depth = 8,
52 .flags = 0,
53 }, {
54 .name = "YUV 4:2:2 planar (Y-Cb-Cr)",
55 .pixelformat = V4L2_PIX_FMT_YUV422P,
56 .trans = YUV422_DECOMPOSED,
57 .depth = 16,
58 .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
59 }, {
60 .name = "YVU 4:2:0 planar (Y-Cb-Cr)",
61 .pixelformat = V4L2_PIX_FMT_YVU420,
62 .trans = YUV420_DECOMPOSED,
63 .depth = 12,
64 .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
65 }, {
66 .name = "YUV 4:2:0 planar (Y-Cb-Cr)",
67 .pixelformat = V4L2_PIX_FMT_YUV420,
68 .trans = YUV420_DECOMPOSED,
69 .depth = 12,
70 .flags = FORMAT_IS_PLANAR,
71 }, {
72 .name = "YUV 4:2:2 (U-Y-V-Y)",
73 .pixelformat = V4L2_PIX_FMT_UYVY,
74 .trans = YUV422_COMPOSED,
75 .depth = 16,
76 .flags = 0,
77 }
78};
79
80/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
81 due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
82 (like V4L2_PIX_FMT_YUYV) ... 8-( */
83
84static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
85
86struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
87{
88 int i, j = NUM_FORMATS;
89
90 for (i = 0; i < j; i++) {
91 if (formats[i].pixelformat == fourcc) {
92 return formats+i;
93 }
94 }
95
96 DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
97 return NULL;
98}
99
100static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
101{
102 struct saa7146_dev *dev = fh->dev;
103 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
104
105 switch (f->type) {
106 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
107 f->fmt.pix = fh->video_fmt;
108 return 0;
109 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
110 f->fmt.win = fh->ov.win;
111 return 0;
112 case V4L2_BUF_TYPE_VBI_CAPTURE:
113 {
114 f->fmt.vbi = fh->vbi_fmt;
115 return 0;
116 }
117 default:
118 DEB_D(("invalid format type '%d'.\n",f->type));
119 return -EINVAL;
120 }
121}
122
123static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
124{
125 struct saa7146_vv *vv = dev->vv_data;
126 enum v4l2_field field;
127 int maxw, maxh;
128
129 DEB_EE(("dev:%p\n",dev));
130
131 if (NULL == vv->ov_fb.base) {
132 DEB_D(("no fb base set.\n"));
133 return -EINVAL;
134 }
135 if (NULL == vv->ov_fmt) {
136 DEB_D(("no fb fmt set.\n"));
137 return -EINVAL;
138 }
139 if (win->w.width < 48 || win->w.height < 32) {
140 DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
141 return -EINVAL;
142 }
143 if (win->clipcount > 16) {
144 DEB_D(("clipcount too big.\n"));
145 return -EINVAL;
146 }
147
148 field = win->field;
149 maxw = vv->standard->h_max_out;
150 maxh = vv->standard->v_max_out;
151
152 if (V4L2_FIELD_ANY == field) {
153 field = (win->w.height > maxh/2)
154 ? V4L2_FIELD_INTERLACED
155 : V4L2_FIELD_TOP;
156 }
157 switch (field) {
158 case V4L2_FIELD_TOP:
159 case V4L2_FIELD_BOTTOM:
160 case V4L2_FIELD_ALTERNATE:
161 maxh = maxh / 2;
162 break;
163 case V4L2_FIELD_INTERLACED:
164 break;
165 default: {
166 DEB_D(("no known field mode '%d'.\n",field));
167 return -EINVAL;
168 }
169 }
170
171 win->field = field;
172 if (win->w.width > maxw)
173 win->w.width = maxw;
174 if (win->w.height > maxh)
175 win->w.height = maxh;
176
177 return 0;
178}
179
180static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
181{
182 struct saa7146_dev *dev = fh->dev;
183 struct saa7146_vv *vv = dev->vv_data;
184 int err;
185
186 switch (f->type) {
187 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
188 {
189 struct saa7146_format *fmt;
190 enum v4l2_field field;
191 int maxw, maxh;
192 int calc_bpl;
193
194 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
195
196 fmt = format_by_fourcc(dev,f->fmt.pix.pixelformat);
197 if (NULL == fmt) {
198 return -EINVAL;
199 }
200
201 field = f->fmt.pix.field;
202 maxw = vv->standard->h_max_out;
203 maxh = vv->standard->v_max_out;
204
205 if (V4L2_FIELD_ANY == field) {
206 field = (f->fmt.pix.height > maxh/2)
207 ? V4L2_FIELD_INTERLACED
208 : V4L2_FIELD_BOTTOM;
209 }
210 switch (field) {
211 case V4L2_FIELD_ALTERNATE: {
212 vv->last_field = V4L2_FIELD_TOP;
213 maxh = maxh / 2;
214 break;
215 }
216 case V4L2_FIELD_TOP:
217 case V4L2_FIELD_BOTTOM:
218 vv->last_field = V4L2_FIELD_INTERLACED;
219 maxh = maxh / 2;
220 break;
221 case V4L2_FIELD_INTERLACED:
222 vv->last_field = V4L2_FIELD_INTERLACED;
223 break;
224 default: {
225 DEB_D(("no known field mode '%d'.\n",field));
226 return -EINVAL;
227 }
228 }
229
230 f->fmt.pix.field = field;
231 if (f->fmt.pix.width > maxw)
232 f->fmt.pix.width = maxw;
233 if (f->fmt.pix.height > maxh)
234 f->fmt.pix.height = maxh;
235
236 calc_bpl = (f->fmt.pix.width * fmt->depth)/8;
237
238 if (f->fmt.pix.bytesperline < calc_bpl)
239 f->fmt.pix.bytesperline = calc_bpl;
240
241 if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
242 f->fmt.pix.bytesperline = calc_bpl;
243
244 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
245 DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
246
247 return 0;
248 }
249 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
250 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
251 err = try_win(dev,&f->fmt.win);
252 if (0 != err) {
253 return err;
254 }
255 return 0;
256 default:
257 DEB_EE(("unknown format type '%d'\n",f->type));
258 return -EINVAL;
259 }
260}
261
262int saa7146_start_preview(struct saa7146_fh *fh)
263{
264 struct saa7146_dev *dev = fh->dev;
265 struct saa7146_vv *vv = dev->vv_data;
266 int ret = 0, err = 0;
267
268 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
269
270 /* check if we have overlay informations */
271 if( NULL == fh->ov.fh ) {
272 DEB_D(("no overlay data available. try S_FMT first.\n"));
273 return -EAGAIN;
274 }
275
276 /* check if streaming capture is running */
277 if (IS_CAPTURE_ACTIVE(fh) != 0) {
278 DEB_D(("streaming capture is active.\n"));
279 return -EBUSY;
280 }
281
282 /* check if overlay is running */
283 if (IS_OVERLAY_ACTIVE(fh) != 0) {
284 if (vv->video_fh == fh) {
285 DEB_D(("overlay is already active.\n"));
286 return 0;
287 }
288 DEB_D(("overlay is already active in another open.\n"));
289 return -EBUSY;
290 }
291
292 if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
293 DEB_D(("cannot get necessary overlay resources\n"));
294 return -EBUSY;
295 }
296
297 err = try_win(dev,&fh->ov.win);
298 if (0 != err) {
299 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
300 return -EBUSY;
301 }
302
303 vv->ov_data = &fh->ov;
304
305 DEB_D(("%dx%d+%d+%d %s field=%s\n",
306 fh->ov.win.w.width,fh->ov.win.w.height,
307 fh->ov.win.w.left,fh->ov.win.w.top,
308 vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
309
310 if (0 != (ret = saa7146_enable_overlay(fh))) {
311 DEB_D(("enabling overlay failed: %d\n",ret));
312 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
313 return ret;
314 }
315
316 vv->video_status = STATUS_OVERLAY;
317 vv->video_fh = fh;
318
319 return 0;
320}
321
322int saa7146_stop_preview(struct saa7146_fh *fh)
323{
324 struct saa7146_dev *dev = fh->dev;
325 struct saa7146_vv *vv = dev->vv_data;
326
327 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
328
329 /* check if streaming capture is running */
330 if (IS_CAPTURE_ACTIVE(fh) != 0) {
331 DEB_D(("streaming capture is active.\n"));
332 return -EBUSY;
333 }
334
335 /* check if overlay is running at all */
336 if ((vv->video_status & STATUS_OVERLAY) == 0) {
337 DEB_D(("no active overlay.\n"));
338 return 0;
339 }
340
341 if (vv->video_fh != fh) {
342 DEB_D(("overlay is active, but in another open.\n"));
343 return -EBUSY;
344 }
345
346 vv->video_status = 0;
347 vv->video_fh = NULL;
348
349 saa7146_disable_overlay(fh);
350
351 saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
352
353 return 0;
354}
355
356static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
357{
358 struct saa7146_dev *dev = fh->dev;
359 struct saa7146_vv *vv = dev->vv_data;
360
361 int err;
362
363 switch (f->type) {
364 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
365 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
366 if (IS_CAPTURE_ACTIVE(fh) != 0) {
367 DEB_EE(("streaming capture is active\n"));
368 return -EBUSY;
369 }
370 err = try_fmt(fh,f);
371 if (0 != err)
372 return err;
373 fh->video_fmt = f->fmt.pix;
374 DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat));
375 return 0;
376 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
377 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
378 err = try_win(dev,&f->fmt.win);
379 if (0 != err)
380 return err;
381 down(&dev->lock);
382 fh->ov.win = f->fmt.win;
383 fh->ov.nclips = f->fmt.win.clipcount;
384 if (fh->ov.nclips > 16)
385 fh->ov.nclips = 16;
386 if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) {
387 up(&dev->lock);
388 return -EFAULT;
389 }
390
391 /* fh->ov.fh is used to indicate that we have valid overlay informations, too */
392 fh->ov.fh = fh;
393
394 up(&dev->lock);
395
396 /* check if our current overlay is active */
397 if (IS_OVERLAY_ACTIVE(fh) != 0) {
398 saa7146_stop_preview(fh);
399 saa7146_start_preview(fh);
400 }
401 return 0;
402 default:
403 DEB_D(("unknown format type '%d'\n",f->type));
404 return -EINVAL;
405 }
406}
407
408/********************************************************************************/
409/* device controls */
410
411static struct v4l2_queryctrl controls[] = {
412 {
413 .id = V4L2_CID_BRIGHTNESS,
414 .name = "Brightness",
415 .minimum = 0,
416 .maximum = 255,
417 .step = 1,
418 .default_value = 128,
419 .type = V4L2_CTRL_TYPE_INTEGER,
420 },{
421 .id = V4L2_CID_CONTRAST,
422 .name = "Contrast",
423 .minimum = 0,
424 .maximum = 127,
425 .step = 1,
426 .default_value = 64,
427 .type = V4L2_CTRL_TYPE_INTEGER,
428 },{
429 .id = V4L2_CID_SATURATION,
430 .name = "Saturation",
431 .minimum = 0,
432 .maximum = 127,
433 .step = 1,
434 .default_value = 64,
435 .type = V4L2_CTRL_TYPE_INTEGER,
436 },{
437 .id = V4L2_CID_VFLIP,
438 .name = "Vertical flip",
439 .minimum = 0,
440 .maximum = 1,
441 .type = V4L2_CTRL_TYPE_BOOLEAN,
442 },{
443 .id = V4L2_CID_HFLIP,
444 .name = "Horizontal flip",
445 .minimum = 0,
446 .maximum = 1,
447 .type = V4L2_CTRL_TYPE_BOOLEAN,
448 },
449};
450static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl);
451
452#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0)
453
454static struct v4l2_queryctrl* ctrl_by_id(int id)
455{
456 int i;
457
458 for (i = 0; i < NUM_CONTROLS; i++)
459 if (controls[i].id == id)
460 return controls+i;
461 return NULL;
462}
463
464static int get_control(struct saa7146_fh *fh, struct v4l2_control *c)
465{
466 struct saa7146_dev *dev = fh->dev;
467 struct saa7146_vv *vv = dev->vv_data;
468
469 const struct v4l2_queryctrl* ctrl;
470 u32 value = 0;
471
472 ctrl = ctrl_by_id(c->id);
473 if (NULL == ctrl)
474 return -EINVAL;
475 switch (c->id) {
476 case V4L2_CID_BRIGHTNESS:
477 value = saa7146_read(dev, BCS_CTRL);
478 c->value = 0xff & (value >> 24);
479 DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value));
480 break;
481 case V4L2_CID_CONTRAST:
482 value = saa7146_read(dev, BCS_CTRL);
483 c->value = 0x7f & (value >> 16);
484 DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value));
485 break;
486 case V4L2_CID_SATURATION:
487 value = saa7146_read(dev, BCS_CTRL);
488 c->value = 0x7f & (value >> 0);
489 DEB_D(("V4L2_CID_SATURATION: %d\n",c->value));
490 break;
491 case V4L2_CID_VFLIP:
492 c->value = vv->vflip;
493 DEB_D(("V4L2_CID_VFLIP: %d\n",c->value));
494 break;
495 case V4L2_CID_HFLIP:
496 c->value = vv->hflip;
497 DEB_D(("V4L2_CID_HFLIP: %d\n",c->value));
498 break;
499 default:
500 return -EINVAL;
501 }
502
503 return 0;
504}
505
506static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
507{
508 struct saa7146_dev *dev = fh->dev;
509 struct saa7146_vv *vv = dev->vv_data;
510
511 const struct v4l2_queryctrl* ctrl;
512
513 ctrl = ctrl_by_id(c->id);
514 if (NULL == ctrl) {
515 DEB_D(("unknown control %d\n",c->id));
516 return -EINVAL;
517 }
518
519 down(&dev->lock);
520
521 switch (ctrl->type) {
522 case V4L2_CTRL_TYPE_BOOLEAN:
523 case V4L2_CTRL_TYPE_MENU:
524 case V4L2_CTRL_TYPE_INTEGER:
525 if (c->value < ctrl->minimum)
526 c->value = ctrl->minimum;
527 if (c->value > ctrl->maximum)
528 c->value = ctrl->maximum;
529 break;
530 default:
531 /* nothing */;
532 };
533
534 switch (c->id) {
535 case V4L2_CID_BRIGHTNESS: {
536 u32 value = saa7146_read(dev, BCS_CTRL);
537 value &= 0x00ffffff;
538 value |= (c->value << 24);
539 saa7146_write(dev, BCS_CTRL, value);
540 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
541 break;
542 }
543 case V4L2_CID_CONTRAST: {
544 u32 value = saa7146_read(dev, BCS_CTRL);
545 value &= 0xff00ffff;
546 value |= (c->value << 16);
547 saa7146_write(dev, BCS_CTRL, value);
548 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
549 break;
550 }
551 case V4L2_CID_SATURATION: {
552 u32 value = saa7146_read(dev, BCS_CTRL);
553 value &= 0xffffff00;
554 value |= (c->value << 0);
555 saa7146_write(dev, BCS_CTRL, value);
556 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
557 break;
558 }
559 case V4L2_CID_HFLIP:
560 /* fixme: we can support changing VFLIP and HFLIP here... */
561 if (IS_CAPTURE_ACTIVE(fh) != 0) {
562 DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
563 up(&dev->lock);
564 return -EINVAL;
565 }
566 vv->hflip = c->value;
567 break;
568 case V4L2_CID_VFLIP:
569 if (IS_CAPTURE_ACTIVE(fh) != 0) {
570 DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
571 up(&dev->lock);
572 return -EINVAL;
573 }
574 vv->vflip = c->value;
575 break;
576 default: {
577 return -EINVAL;
578 }
579 }
580 up(&dev->lock);
581
582 if (IS_OVERLAY_ACTIVE(fh) != 0) {
583 saa7146_stop_preview(fh);
584 saa7146_start_preview(fh);
585 }
586 return 0;
587}
588
589/********************************************************************************/
590/* common pagetable functions */
591
592static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
593{
594 struct pci_dev *pci = dev->pci;
595 struct scatterlist *list = buf->vb.dma.sglist;
596 int length = buf->vb.dma.sglen;
597 struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
598
599 DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
600
601 if( 0 != IS_PLANAR(sfmt->trans)) {
602 struct saa7146_pgtable *pt1 = &buf->pt[0];
603 struct saa7146_pgtable *pt2 = &buf->pt[1];
604 struct saa7146_pgtable *pt3 = &buf->pt[2];
605 u32 *ptr1, *ptr2, *ptr3;
606 u32 fill;
607
608 int size = buf->fmt->width*buf->fmt->height;
609 int i,p,m1,m2,m3,o1,o2;
610
611 switch( sfmt->depth ) {
612 case 12: {
613 /* create some offsets inside the page table */
614 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
615 m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
616 m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
617 o1 = size%PAGE_SIZE;
618 o2 = (size+(size/4))%PAGE_SIZE;
619 DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
620 break;
621 }
622 case 16: {
623 /* create some offsets inside the page table */
624 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
625 m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
626 m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
627 o1 = size%PAGE_SIZE;
628 o2 = (size+(size/2))%PAGE_SIZE;
629 DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
630 break;
631 }
632 default: {
633 return -1;
634 }
635 }
636
637 ptr1 = pt1->cpu;
638 ptr2 = pt2->cpu;
639 ptr3 = pt3->cpu;
640
641 /* walk all pages, copy all page addresses to ptr1 */
642 for (i = 0; i < length; i++, list++) {
643 for (p = 0; p * 4096 < list->length; p++, ptr1++) {
644 *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
645 }
646 }
647/*
648 ptr1 = pt1->cpu;
649 for(j=0;j<40;j++) {
650 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
651 }
652*/
653
654 /* if we have a user buffer, the first page may not be
655 aligned to a page boundary. */
656 pt1->offset = buf->vb.dma.sglist->offset;
657 pt2->offset = pt1->offset+o1;
658 pt3->offset = pt1->offset+o2;
659
660 /* create video-dma2 page table */
661 ptr1 = pt1->cpu;
662 for(i = m1; i <= m2 ; i++, ptr2++) {
663 *ptr2 = ptr1[i];
664 }
665 fill = *(ptr2-1);
666 for(;i<1024;i++,ptr2++) {
667 *ptr2 = fill;
668 }
669 /* create video-dma3 page table */
670 ptr1 = pt1->cpu;
671 for(i = m2; i <= m3; i++,ptr3++) {
672 *ptr3 = ptr1[i];
673 }
674 fill = *(ptr3-1);
675 for(;i<1024;i++,ptr3++) {
676 *ptr3 = fill;
677 }
678 /* finally: finish up video-dma1 page table */
679 ptr1 = pt1->cpu+m1;
680 fill = pt1->cpu[m1];
681 for(i=m1;i<1024;i++,ptr1++) {
682 *ptr1 = fill;
683 }
684/*
685 ptr1 = pt1->cpu;
686 ptr2 = pt2->cpu;
687 ptr3 = pt3->cpu;
688 for(j=0;j<40;j++) {
689 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
690 }
691 for(j=0;j<40;j++) {
692 printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
693 }
694 for(j=0;j<40;j++) {
695 printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
696 }
697*/
698 } else {
699 struct saa7146_pgtable *pt = &buf->pt[0];
700 return saa7146_pgtable_build_single(pci, pt, list, length);
701 }
702
703 return 0;
704}
705
706
707/********************************************************************************/
708/* file operations */
709
710static int video_begin(struct saa7146_fh *fh)
711{
712 struct saa7146_dev *dev = fh->dev;
713 struct saa7146_vv *vv = dev->vv_data;
714 struct saa7146_format *fmt = NULL;
715 unsigned int resource;
716 int ret = 0, err = 0;
717
718 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
719
720 if ((vv->video_status & STATUS_CAPTURE) != 0) {
721 if (vv->video_fh == fh) {
722 DEB_S(("already capturing.\n"));
723 return 0;
724 }
725 DEB_S(("already capturing in another open.\n"));
726 return -EBUSY;
727 }
728
729 if ((vv->video_status & STATUS_OVERLAY) != 0) {
730 DEB_S(("warning: suspending overlay video for streaming capture.\n"));
731 vv->ov_suspend = vv->video_fh;
732 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
733 if (0 != err) {
734 DEB_D(("suspending video failed. aborting\n"));
735 return err;
736 }
737 }
738
739 fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
740 /* we need to have a valid format set here */
741 BUG_ON(NULL == fmt);
742
743 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
744 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
745 } else {
746 resource = RESOURCE_DMA1_HPS;
747 }
748
749 ret = saa7146_res_get(fh, resource);
750 if (0 == ret) {
751 DEB_S(("cannot get capture resource %d\n",resource));
752 if (vv->ov_suspend != NULL) {
753 saa7146_start_preview(vv->ov_suspend);
754 vv->ov_suspend = NULL;
755 }
756 return -EBUSY;
757 }
758
759 /* clear out beginning of streaming bit (rps register 0)*/
760 saa7146_write(dev, MC2, MASK_27 );
761
762 /* enable rps0 irqs */
763 SAA7146_IER_ENABLE(dev, MASK_27);
764
765 vv->video_fh = fh;
766 vv->video_status = STATUS_CAPTURE;
767
768 return 0;
769}
770
771static int video_end(struct saa7146_fh *fh, struct file *file)
772{
773 struct saa7146_dev *dev = fh->dev;
774 struct saa7146_vv *vv = dev->vv_data;
775 struct saa7146_format *fmt = NULL;
776 unsigned long flags;
777 unsigned int resource;
778 u32 dmas = 0;
779 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
780
781 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
782 DEB_S(("not capturing.\n"));
783 return 0;
784 }
785
786 if (vv->video_fh != fh) {
787 DEB_S(("capturing, but in another open.\n"));
788 return -EBUSY;
789 }
790
791 fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
792 /* we need to have a valid format set here */
793 BUG_ON(NULL == fmt);
794
795 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
796 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
797 dmas = MASK_22 | MASK_21 | MASK_20;
798 } else {
799 resource = RESOURCE_DMA1_HPS;
800 dmas = MASK_22;
801 }
802 spin_lock_irqsave(&dev->slock,flags);
803
804 /* disable rps0 */
805 saa7146_write(dev, MC1, MASK_28);
806
807 /* disable rps0 irqs */
808 SAA7146_IER_DISABLE(dev, MASK_27);
809
810 /* shut down all used video dma transfers */
811 saa7146_write(dev, MC1, dmas);
812
813 spin_unlock_irqrestore(&dev->slock, flags);
814
815 vv->video_fh = NULL;
816 vv->video_status = 0;
817
818 saa7146_res_free(fh, resource);
819
820 if (vv->ov_suspend != NULL) {
821 saa7146_start_preview(vv->ov_suspend);
822 vv->ov_suspend = NULL;
823 }
824
825 return 0;
826}
827
828/*
829 * This function is _not_ called directly, but from
830 * video_generic_ioctl (and maybe others). userspace
831 * copying is done already, arg is a kernel pointer.
832 */
833
834int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
835{
836 struct saa7146_fh *fh = file->private_data;
837 struct saa7146_dev *dev = fh->dev;
838 struct saa7146_vv *vv = dev->vv_data;
839
840 int err = 0, result = 0, ee = 0;
841
842 struct saa7146_use_ops *ops;
843 struct videobuf_queue *q;
844
845 /* check if extension handles the command */
846 for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) {
847 if( cmd == dev->ext_vv_data->ioctls[ee].cmd )
848 break;
849 }
850
851 if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
852 DEB_D(("extension handles ioctl exclusive.\n"));
853 result = dev->ext_vv_data->ioctl(fh, cmd, arg);
854 return result;
855 }
856 if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
857 DEB_D(("extension handles ioctl before.\n"));
858 result = dev->ext_vv_data->ioctl(fh, cmd, arg);
859 if( -EAGAIN != result ) {
860 return result;
861 }
862 }
863
864 /* fixme: add handle "after" case (is it still needed?) */
865
866 switch (fh->type) {
867 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
868 ops = &saa7146_video_uops;
869 q = &fh->video_q;
870 break;
871 }
872 case V4L2_BUF_TYPE_VBI_CAPTURE: {
873 ops = &saa7146_vbi_uops;
874 q = &fh->vbi_q;
875 break;
876 }
877 default:
878 BUG();
879 return 0;
880 }
881
882 switch (cmd) {
883 case VIDIOC_QUERYCAP:
884 {
885 struct v4l2_capability *cap = arg;
886 memset(cap,0,sizeof(*cap));
887
888 DEB_EE(("VIDIOC_QUERYCAP\n"));
889
890 strcpy(cap->driver, "saa7146 v4l2");
891 strlcpy(cap->card, dev->ext->name, sizeof(cap->card));
892 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
893 cap->version = SAA7146_VERSION_CODE;
894 cap->capabilities =
895 V4L2_CAP_VIDEO_CAPTURE |
896 V4L2_CAP_VIDEO_OVERLAY |
897 V4L2_CAP_READWRITE |
898 V4L2_CAP_STREAMING;
899 cap->capabilities |= dev->ext_vv_data->capabilities;
900 return 0;
901 }
902 case VIDIOC_G_FBUF:
903 {
904 struct v4l2_framebuffer *fb = arg;
905
906 DEB_EE(("VIDIOC_G_FBUF\n"));
907
908 *fb = vv->ov_fb;
909 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
910 return 0;
911 }
912 case VIDIOC_S_FBUF:
913 {
914 struct v4l2_framebuffer *fb = arg;
915 struct saa7146_format *fmt;
916
917 DEB_EE(("VIDIOC_S_FBUF\n"));
918
919 if(!capable(CAP_SYS_ADMIN) &&
920 !capable(CAP_SYS_RAWIO))
921 return -EPERM;
922
923 /* check args */
924 fmt = format_by_fourcc(dev,fb->fmt.pixelformat);
925 if (NULL == fmt) {
926 return -EINVAL;
927 }
928
929 /* planar formats are not allowed for overlay video, clipping and video dma would clash */
930 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
931 DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
932 }
933
934 /* check if overlay is running */
935 if (IS_OVERLAY_ACTIVE(fh) != 0) {
936 if (vv->video_fh != fh) {
937 DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
938 return -EBUSY;
939 }
940 }
941
942 down(&dev->lock);
943
944 /* ok, accept it */
945 vv->ov_fb = *fb;
946 vv->ov_fmt = fmt;
947 if (0 == vv->ov_fb.fmt.bytesperline)
948 vv->ov_fb.fmt.bytesperline =
949 vv->ov_fb.fmt.width*fmt->depth/8;
950
951 up(&dev->lock);
952
953 return 0;
954 }
955 case VIDIOC_ENUM_FMT:
956 {
957 struct v4l2_fmtdesc *f = arg;
958 int index;
959
960 switch (f->type) {
961 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
962 case V4L2_BUF_TYPE_VIDEO_OVERLAY: {
963 index = f->index;
964 if (index < 0 || index >= NUM_FORMATS) {
965 return -EINVAL;
966 }
967 memset(f,0,sizeof(*f));
968 f->index = index;
969 strlcpy(f->description,formats[index].name,sizeof(f->description));
970 f->pixelformat = formats[index].pixelformat;
971 break;
972 }
973 default:
974 return -EINVAL;
975 }
976
977 DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index));
978 return 0;
979 }
980 case VIDIOC_QUERYCTRL:
981 {
982 const struct v4l2_queryctrl *ctrl;
983 struct v4l2_queryctrl *c = arg;
984
985 if ((c->id < V4L2_CID_BASE ||
986 c->id >= V4L2_CID_LASTP1) &&
987 (c->id < V4L2_CID_PRIVATE_BASE ||
988 c->id >= V4L2_CID_PRIVATE_LASTP1))
989 return -EINVAL;
990
991 ctrl = ctrl_by_id(c->id);
992 if( NULL == ctrl ) {
993 return -EINVAL;
994/*
995 c->flags = V4L2_CTRL_FLAG_DISABLED;
996 return 0;
997*/
998 }
999
1000 DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id));
1001 *c = *ctrl;
1002 return 0;
1003 }
1004 case VIDIOC_G_CTRL: {
1005 DEB_EE(("VIDIOC_G_CTRL\n"));
1006 return get_control(fh,arg);
1007 }
1008 case VIDIOC_S_CTRL:
1009 {
1010 DEB_EE(("VIDIOC_S_CTRL\n"));
1011 err = set_control(fh,arg);
1012 return err;
1013 }
1014 case VIDIOC_G_PARM:
1015 {
1016 struct v4l2_streamparm *parm = arg;
1017 if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
1018 return -EINVAL;
1019 }
1020 memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));
1021 parm->parm.capture.readbuffers = 1;
1022 // fixme: only for PAL!
1023 parm->parm.capture.timeperframe.numerator = 1;
1024 parm->parm.capture.timeperframe.denominator = 25;
1025 return 0;
1026 }
1027 case VIDIOC_G_FMT:
1028 {
1029 struct v4l2_format *f = arg;
1030 DEB_EE(("VIDIOC_G_FMT\n"));
1031 return g_fmt(fh,f);
1032 }
1033 case VIDIOC_S_FMT:
1034 {
1035 struct v4l2_format *f = arg;
1036 DEB_EE(("VIDIOC_S_FMT\n"));
1037 return s_fmt(fh,f);
1038 }
1039 case VIDIOC_TRY_FMT:
1040 {
1041 struct v4l2_format *f = arg;
1042 DEB_EE(("VIDIOC_TRY_FMT\n"));
1043 return try_fmt(fh,f);
1044 }
1045 case VIDIOC_G_STD:
1046 {
1047 v4l2_std_id *id = arg;
1048 DEB_EE(("VIDIOC_G_STD\n"));
1049 *id = vv->standard->id;
1050 return 0;
1051 }
1052 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
1053 PAL / NTSC / SECAM. if your hardware does not (or does more)
1054 -- override this function in your extension */
1055 case VIDIOC_ENUMSTD:
1056 {
1057 struct v4l2_standard *e = arg;
1058 if (e->index < 0 )
1059 return -EINVAL;
1060 if( e->index < dev->ext_vv_data->num_stds ) {
1061 DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
1062 v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
1063 return 0;
1064 }
1065 return -EINVAL;
1066 }
1067 case VIDIOC_S_STD:
1068 {
1069 v4l2_std_id *id = arg;
1070 int found = 0;
1071 int i, err;
1072
1073 DEB_EE(("VIDIOC_S_STD\n"));
1074
1075 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
1076 DEB_D(("cannot change video standard while streaming capture is active\n"));
1077 return -EBUSY;
1078 }
1079
1080 if ((vv->video_status & STATUS_OVERLAY) != 0) {
1081 vv->ov_suspend = vv->video_fh;
1082 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
1083 if (0 != err) {
1084 DEB_D(("suspending video failed. aborting\n"));
1085 return err;
1086 }
1087 }
1088
1089 down(&dev->lock);
1090
1091 for(i = 0; i < dev->ext_vv_data->num_stds; i++)
1092 if (*id & dev->ext_vv_data->stds[i].id)
1093 break;
1094 if (i != dev->ext_vv_data->num_stds) {
1095 vv->standard = &dev->ext_vv_data->stds[i];
1096 if( NULL != dev->ext_vv_data->std_callback )
1097 dev->ext_vv_data->std_callback(dev, vv->standard);
1098 found = 1;
1099 }
1100
1101 up(&dev->lock);
1102
1103 if (vv->ov_suspend != NULL) {
1104 saa7146_start_preview(vv->ov_suspend);
1105 vv->ov_suspend = NULL;
1106 }
1107
1108 if( 0 == found ) {
1109 DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
1110 return -EINVAL;
1111 }
1112
1113 DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name));
1114 return 0;
1115 }
1116 case VIDIOC_OVERLAY:
1117
1118
1119
1120
1121 {
1122 int on = *(int *)arg;
1123 int err = 0;
1124
1125 DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
1126 if (on != 0) {
1127 err = saa7146_start_preview(fh);
1128 } else {
1129 err = saa7146_stop_preview(fh);
1130 }
1131 return err;
1132 }
1133 case VIDIOC_REQBUFS: {
1134 struct v4l2_requestbuffers *req = arg;
1135 DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
1136 return videobuf_reqbufs(q,req);
1137 }
1138 case VIDIOC_QUERYBUF: {
1139 struct v4l2_buffer *buf = arg;
1140 DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
1141 return videobuf_querybuf(q,buf);
1142 }
1143 case VIDIOC_QBUF: {
1144 struct v4l2_buffer *buf = arg;
1145 int ret = 0;
1146 ret = videobuf_qbuf(q,buf);
1147 DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
1148 return ret;
1149 }
1150 case VIDIOC_DQBUF: {
1151 struct v4l2_buffer *buf = arg;
1152 int ret = 0;
1153 ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK);
1154 DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
1155 return ret;
1156 }
1157 case VIDIOC_STREAMON: {
1158 int *type = arg;
1159 DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
1160
1161 err = video_begin(fh);
1162 if( 0 != err) {
1163 return err;
1164 }
1165 err = videobuf_streamon(q);
1166 return err;
1167 }
1168 case VIDIOC_STREAMOFF: {
1169 int *type = arg;
1170
1171 DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
1172
1173 /* ugly: we need to copy some checks from video_end(),
1174 because videobuf_streamoff() relies on the capture running.
1175 check and fix this */
1176 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
1177 DEB_S(("not capturing.\n"));
1178 return 0;
1179 }
1180
1181 if (vv->video_fh != fh) {
1182 DEB_S(("capturing, but in another open.\n"));
1183 return -EBUSY;
1184 }
1185
1186 err = videobuf_streamoff(q);
1187 if (0 != err) {
1188 DEB_D(("warning: videobuf_streamoff() failed.\n"));
1189 video_end(fh, file);
1190 } else {
1191 err = video_end(fh, file);
1192 }
1193 return err;
1194 }
1195 case VIDIOCGMBUF:
1196 {
1197 struct video_mbuf *mbuf = arg;
1198 struct videobuf_queue *q;
1199 int i;
1200
1201 /* fixme: number of capture buffers and sizes for v4l apps */
1202 int gbuffers = 2;
1203 int gbufsize = 768*576*4;
1204
1205 DEB_D(("VIDIOCGMBUF \n"));
1206
1207 q = &fh->video_q;
1208 down(&q->lock);
1209 err = videobuf_mmap_setup(q,gbuffers,gbufsize,
1210 V4L2_MEMORY_MMAP);
1211 if (err < 0) {
1212 up(&q->lock);
1213 return err;
1214 }
1215 memset(mbuf,0,sizeof(*mbuf));
1216 mbuf->frames = gbuffers;
1217 mbuf->size = gbuffers * gbufsize;
1218 for (i = 0; i < gbuffers; i++)
1219 mbuf->offsets[i] = i * gbufsize;
1220 up(&q->lock);
1221 return 0;
1222 }
1223 default:
1224 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
1225 saa7146_video_do_ioctl);
1226 }
1227 return 0;
1228}
1229
1230/*********************************************************************************/
1231/* buffer handling functions */
1232
1233static int buffer_activate (struct saa7146_dev *dev,
1234 struct saa7146_buf *buf,
1235 struct saa7146_buf *next)
1236{
1237 struct saa7146_vv *vv = dev->vv_data;
1238
1239 buf->vb.state = STATE_ACTIVE;
1240 saa7146_set_capture(dev,buf,next);
1241
1242 mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
1243 return 0;
1244}
1245
1246static int buffer_prepare(struct videobuf_queue *q,
1247 struct videobuf_buffer *vb, enum v4l2_field field)
1248{
1249 struct file *file = q->priv_data;
1250 struct saa7146_fh *fh = file->private_data;
1251 struct saa7146_dev *dev = fh->dev;
1252 struct saa7146_vv *vv = dev->vv_data;
1253 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1254 int size,err = 0;
1255
1256 DEB_CAP(("vbuf:%p\n",vb));
1257
1258 /* sanity checks */
1259 if (fh->video_fmt.width < 48 ||
1260 fh->video_fmt.height < 32 ||
1261 fh->video_fmt.width > vv->standard->h_max_out ||
1262 fh->video_fmt.height > vv->standard->v_max_out) {
1263 DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
1264 return -EINVAL;
1265 }
1266
1267 size = fh->video_fmt.sizeimage;
1268 if (0 != buf->vb.baddr && buf->vb.bsize < size) {
1269 DEB_D(("size mismatch.\n"));
1270 return -EINVAL;
1271 }
1272
1273 DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
1274 fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
1275 if (buf->vb.width != fh->video_fmt.width ||
1276 buf->vb.bytesperline != fh->video_fmt.bytesperline ||
1277 buf->vb.height != fh->video_fmt.height ||
1278 buf->vb.size != size ||
1279 buf->vb.field != field ||
1280 buf->vb.field != fh->video_fmt.field ||
1281 buf->fmt != &fh->video_fmt) {
1282 saa7146_dma_free(dev,buf);
1283 }
1284
1285 if (STATE_NEEDS_INIT == buf->vb.state) {
1286 struct saa7146_format *sfmt;
1287
1288 buf->vb.bytesperline = fh->video_fmt.bytesperline;
1289 buf->vb.width = fh->video_fmt.width;
1290 buf->vb.height = fh->video_fmt.height;
1291 buf->vb.size = size;
1292 buf->vb.field = field;
1293 buf->fmt = &fh->video_fmt;
1294 buf->vb.field = fh->video_fmt.field;
1295
1296 sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
1297
1298 if( 0 != IS_PLANAR(sfmt->trans)) {
1299 saa7146_pgtable_free(dev->pci, &buf->pt[0]);
1300 saa7146_pgtable_free(dev->pci, &buf->pt[1]);
1301 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
1302
1303 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1304 saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
1305 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
1306 } else {
1307 saa7146_pgtable_free(dev->pci, &buf->pt[0]);
1308 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1309 }
1310
1311 err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb);
1312 if (err)
1313 goto oops;
1314 err = saa7146_pgtable_build(dev,buf);
1315 if (err)
1316 goto oops;
1317 }
1318 buf->vb.state = STATE_PREPARED;
1319 buf->activate = buffer_activate;
1320
1321 return 0;
1322
1323 oops:
1324 DEB_D(("error out.\n"));
1325 saa7146_dma_free(dev,buf);
1326
1327 return err;
1328}
1329
1330static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1331{
1332 struct file *file = q->priv_data;
1333 struct saa7146_fh *fh = file->private_data;
1334
1335 if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
1336 *count = MAX_SAA7146_CAPTURE_BUFFERS;
1337
1338 *size = fh->video_fmt.sizeimage;
1339
1340 /* check if we exceed the "max_memory" parameter */
1341 if( (*count * *size) > (max_memory*1048576) ) {
1342 *count = (max_memory*1048576) / *size;
1343 }
1344
1345 DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
1346
1347 return 0;
1348}
1349
1350static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1351{
1352 struct file *file = q->priv_data;
1353 struct saa7146_fh *fh = file->private_data;
1354 struct saa7146_dev *dev = fh->dev;
1355 struct saa7146_vv *vv = dev->vv_data;
1356 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1357
1358 DEB_CAP(("vbuf:%p\n",vb));
1359 saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
1360}
1361
1362
1363static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1364{
1365 struct file *file = q->priv_data;
1366 struct saa7146_fh *fh = file->private_data;
1367 struct saa7146_dev *dev = fh->dev;
1368 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1369
1370 DEB_CAP(("vbuf:%p\n",vb));
1371 saa7146_dma_free(dev,buf);
1372}
1373
1374static struct videobuf_queue_ops video_qops = {
1375 .buf_setup = buffer_setup,
1376 .buf_prepare = buffer_prepare,
1377 .buf_queue = buffer_queue,
1378 .buf_release = buffer_release,
1379};
1380
1381/********************************************************************************/
1382/* file operations */
1383
1384static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
1385{
1386 INIT_LIST_HEAD(&vv->video_q.queue);
1387
1388 init_timer(&vv->video_q.timeout);
1389 vv->video_q.timeout.function = saa7146_buffer_timeout;
1390 vv->video_q.timeout.data = (unsigned long)(&vv->video_q);
1391 vv->video_q.dev = dev;
1392
1393 /* set some default values */
1394 vv->standard = &dev->ext_vv_data->stds[0];
1395
1396 /* FIXME: what's this? */
1397 vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
1398 vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
1399}
1400
1401
1402static int video_open(struct saa7146_dev *dev, struct file *file)
1403{
1404 struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
1405 struct saa7146_format *sfmt;
1406
1407 fh->video_fmt.width = 384;
1408 fh->video_fmt.height = 288;
1409 fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
1410 fh->video_fmt.bytesperline = 0;
1411 fh->video_fmt.field = V4L2_FIELD_ANY;
1412 sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
1413 fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
1414
1415 videobuf_queue_init(&fh->video_q, &video_qops,
1416 dev->pci, &dev->slock,
1417 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1418 V4L2_FIELD_INTERLACED,
1419 sizeof(struct saa7146_buf),
1420 file);
1421
1422 init_MUTEX(&fh->video_q.lock);
1423
1424 return 0;
1425}
1426
1427
1428static void video_close(struct saa7146_dev *dev, struct file *file)
1429{
1430 struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
1431 struct saa7146_vv *vv = dev->vv_data;
1432 int err;
1433
1434 if (IS_CAPTURE_ACTIVE(fh) != 0) {
1435 err = video_end(fh, file);
1436 } else if (IS_OVERLAY_ACTIVE(fh) != 0) {
1437 err = saa7146_stop_preview(fh);
1438 }
1439
1440 /* hmm, why is this function declared void? */
1441 /* return err */
1442}
1443
1444
1445static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
1446{
1447 struct saa7146_vv *vv = dev->vv_data;
1448 struct saa7146_dmaqueue *q = &vv->video_q;
1449
1450 spin_lock(&dev->slock);
1451 DEB_CAP(("called.\n"));
1452
1453 /* only finish the buffer if we have one... */
1454 if( NULL != q->curr ) {
1455 saa7146_buffer_finish(dev,q,STATE_DONE);
1456 }
1457 saa7146_buffer_next(dev,q,0);
1458
1459 spin_unlock(&dev->slock);
1460}
1461
1462static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1463{
1464 struct saa7146_fh *fh = file->private_data;
1465 struct saa7146_dev *dev = fh->dev;
1466 struct saa7146_vv *vv = dev->vv_data;
1467 ssize_t ret = 0;
1468
1469 DEB_EE(("called.\n"));
1470
1471 if ((vv->video_status & STATUS_CAPTURE) != 0) {
1472 /* fixme: should we allow read() captures while streaming capture? */
1473 if (vv->video_fh == fh) {
1474 DEB_S(("already capturing.\n"));
1475 return -EBUSY;
1476 }
1477 DEB_S(("already capturing in another open.\n"));
1478 return -EBUSY;
1479 }
1480
1481 ret = video_begin(fh);
1482 if( 0 != ret) {
1483 goto out;
1484 }
1485
1486 ret = videobuf_read_one(&fh->video_q , data, count, ppos,
1487 file->f_flags & O_NONBLOCK);
1488 if (ret != 0) {
1489 video_end(fh, file);
1490 } else {
1491 ret = video_end(fh, file);
1492 }
1493out:
1494 /* restart overlay if it was active before */
1495 if (vv->ov_suspend != NULL) {
1496 saa7146_start_preview(vv->ov_suspend);
1497 vv->ov_suspend = NULL;
1498 }
1499
1500 return ret;
1501}
1502
1503struct saa7146_use_ops saa7146_video_uops = {
1504 .init = video_init,
1505 .open = video_open,
1506 .release = video_close,
1507 .irq_done = video_irq_done,
1508 .read = video_read,
1509};
diff --git a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c
new file mode 100644
index 000000000000..62226eb4753b
--- /dev/null
+++ b/drivers/media/common/saa7146_vv_ksyms.c
@@ -0,0 +1,12 @@
1#include <linux/module.h>
2#include <media/saa7146_vv.h>
3
4EXPORT_SYMBOL_GPL(saa7146_start_preview);
5EXPORT_SYMBOL_GPL(saa7146_stop_preview);
6
7EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
8EXPORT_SYMBOL_GPL(saa7146_register_device);
9EXPORT_SYMBOL_GPL(saa7146_unregister_device);
10
11EXPORT_SYMBOL_GPL(saa7146_vv_init);
12EXPORT_SYMBOL_GPL(saa7146_vv_release);