Blame view

drivers/media/common/saa7146_vbi.c 13.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  #include <media/saa7146_vv.h>
  
  static int vbi_pixel_to_capture = 720 * 2;
  
  static int vbi_workaround(struct saa7146_dev *dev)
  {
  	struct saa7146_vv *vv = dev->vv_data;
afd1a0c9a   Mauro Carvalho Chehab   [PATCH] V4L/DVB: ...
8
9
  	u32          *cpu;
  	dma_addr_t   dma_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
  
  	int count = 0;
  	int i;
  
  	DECLARE_WAITQUEUE(wait, current);
44d0b80e5   Joe Perches   [media] saa7146: ...
15
16
  	DEB_VBI("dev:%p
  ", dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  
  	/* once again, a bug in the saa7146: the brs acquisition
  	   is buggy and especially the BXO-counter does not work
  	   as specified. there is this workaround, but please
  	   don't let me explain it. ;-) */
  
  	cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr);
  	if (NULL == cpu)
  		return -ENOMEM;
  
  	/* setup some basic programming, just for the workaround */
  	saa7146_write(dev, BASE_EVEN3,	dma_addr);
  	saa7146_write(dev, BASE_ODD3,	dma_addr+vbi_pixel_to_capture);
  	saa7146_write(dev, PROT_ADDR3,	dma_addr+4096);
  	saa7146_write(dev, PITCH3,	vbi_pixel_to_capture);
  	saa7146_write(dev, BASE_PAGE3,	0x0);
  	saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
  	saa7146_write(dev, MC2, MASK_04|MASK_20);
  
  	/* load brs-control register */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
  	/* BXO = 1h, BRS to outbound */
  	WRITE_RPS1(0xc000008c);
  	/* wait for vbi_a or vbi_b*/
  	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
44d0b80e5   Joe Perches   [media] saa7146: ...
42
43
  		DEB_D("...using port b
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
  		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
  		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
  /*
  		WRITE_RPS1(CMD_PAUSE | MASK_09);
  */
  	} else {
44d0b80e5   Joe Perches   [media] saa7146: ...
50
51
  		DEB_D("...using port a
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  		WRITE_RPS1(CMD_PAUSE | MASK_10);
  	}
  	/* upload brs */
  	WRITE_RPS1(CMD_UPLOAD | MASK_08);
  	/* load brs-control register */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
  	/* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
  	WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
  	/* wait for brs_done */
  	WRITE_RPS1(CMD_PAUSE | MASK_08);
  	/* upload brs */
  	WRITE_RPS1(CMD_UPLOAD | MASK_08);
  	/* load video-dma3 NumLines3 and NumBytes3 */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
  	/* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
  	WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
  	/* load brs-control register */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
  	/* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
  	WRITE_RPS1((540 << 7) | (5 << 19));  // 5 == vbi_start
  	/* wait for brs_done */
  	WRITE_RPS1(CMD_PAUSE | MASK_08);
  	/* upload brs and video-dma3*/
  	WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
  	/* load mc2 register: enable dma3 */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
  	WRITE_RPS1(MASK_20 | MASK_04);
  	/* generate interrupt */
  	WRITE_RPS1(CMD_INTERRUPT);
  	/* stop rps1 */
  	WRITE_RPS1(CMD_STOP);
  
  	/* we have to do the workaround twice to be sure that
  	   everything is ok */
  	for(i = 0; i < 2; i++) {
  
  		/* indicate to the irq handler that we do the workaround */
  		saa7146_write(dev, MC2, MASK_31|MASK_15);
  
  		saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
  		saa7146_write(dev, MC2, MASK_04|MASK_20);
  
  		/* enable rps1 irqs */
  		SAA7146_IER_ENABLE(dev,MASK_28);
  
  		/* prepare to wait to be woken up by the irq-handler */
  		add_wait_queue(&vv->vbi_wq, &wait);
  		current->state = TASK_INTERRUPTIBLE;
  
  		/* start rps1 to enable workaround */
  		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
  		saa7146_write(dev, MC1, (MASK_13 | MASK_29));
  
  		schedule();
44d0b80e5   Joe Perches   [media] saa7146: ...
106
107
  		DEB_VBI("brs bug workaround %d/1
  ", i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
114
115
116
117
118
  
  		remove_wait_queue(&vv->vbi_wq, &wait);
  		current->state = TASK_RUNNING;
  
  		/* disable rps1 irqs */
  		SAA7146_IER_DISABLE(dev,MASK_28);
  
  		/* stop video-dma3 */
  		saa7146_write(dev, MC1, MASK_20);
  
  		if(signal_pending(current)) {
44d0b80e5   Joe Perches   [media] saa7146: ...
119
120
121
  			DEB_VBI("aborted (rps:0x%08x)
  ",
  				saa7146_read(dev, RPS_ADDR1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  
  			/* stop rps1 for sure */
  			saa7146_write(dev, MC1, MASK_29);
  
  			pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
  			return -EINTR;
  		}
  	}
  
  	pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
  	return 0;
  }
  
  static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
  {
  	struct saa7146_vv *vv = dev->vv_data;
  
  	struct saa7146_video_dma vdma3;
  
  	int count = 0;
  	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
  	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
  
  /*
  	vdma3.base_even	= 0xc8000000+2560*70;
  	vdma3.base_odd	= 0xc8000000;
  	vdma3.prot_addr	= 0xc8000000+2560*164;
  	vdma3.pitch	= 2560;
  	vdma3.base_page	= 0;
  	vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
  */
  	vdma3.base_even	= buf->pt[2].offset;
  	vdma3.base_odd	= buf->pt[2].offset + 16 * vbi_pixel_to_capture;
  	vdma3.prot_addr	= buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture;
  	vdma3.pitch	= vbi_pixel_to_capture;
  	vdma3.base_page	= buf->pt[2].dma | ME1;
  	vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
  
  	saa7146_write_out_dma(dev, 3, &vdma3);
  
  	/* write beginning of rps-program */
  	count = 0;
  
  	/* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */
  
  	/* we don't wait here for the first field anymore. this is different from the video
  	   capture and might cause that the first buffer is only half filled (with only
  	   one field). but since this is some sort of streaming data, this is not that negative.
c1accaa21   Mauro Carvalho Chehab   V4L/DVB (6252): A...
170
  	   but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  
  /*
  	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
  	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
  */
  	/* set bit 1 */
  	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
  	WRITE_RPS1(MASK_28 | MASK_12);
  
  	/* turn on video-dma3 */
  	WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
  	WRITE_RPS1(MASK_04 | MASK_20);			/* => mask */
  	WRITE_RPS1(MASK_04 | MASK_20);			/* => values */
  
  	/* wait for o_fid_a/b / e_fid_a/b toggle */
  	WRITE_RPS1(CMD_PAUSE | o_wait);
  	WRITE_RPS1(CMD_PAUSE | e_wait);
  
  	/* generate interrupt */
  	WRITE_RPS1(CMD_INTERRUPT);
  
  	/* stop */
  	WRITE_RPS1(CMD_STOP);
  
  	/* enable rps1 irqs */
  	SAA7146_IER_ENABLE(dev, MASK_28);
  
  	/* write the address of the rps-program */
  	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
  
  	/* turn on rps */
  	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
  }
  
  static int buffer_activate(struct saa7146_dev *dev,
  			   struct saa7146_buf *buf,
  			   struct saa7146_buf *next)
  {
  	struct saa7146_vv *vv = dev->vv_data;
0fc0686e6   Brandon Philips   V4L/DVB (6600): V...
210
  	buf->vb.state = VIDEOBUF_ACTIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

44d0b80e5   Joe Perches   [media] saa7146: ...
212
213
  	DEB_VBI("dev:%p, buf:%p, next:%p
  ", dev, buf, next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	saa7146_set_vbi_capture(dev,buf,next);
  
  	mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
  	return 0;
  }
  
  static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
  {
  	struct file *file = q->priv_data;
  	struct saa7146_fh *fh = file->private_data;
  	struct saa7146_dev *dev = fh->dev;
  	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
  
  	int err = 0;
  	int lines, llength, size;
  
  	lines   = 16 * 2 ; /* 2 fields */
  	llength = vbi_pixel_to_capture;
  	size = lines * llength;
44d0b80e5   Joe Perches   [media] saa7146: ...
233
234
  	DEB_VBI("vb:%p
  ", vb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  
  	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
44d0b80e5   Joe Perches   [media] saa7146: ...
237
238
  		DEB_VBI("size mismatch
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
  		return -EINVAL;
  	}
  
  	if (buf->vb.size != size)
c7b0ac054   Mauro Carvalho Chehab   V4L/DVB (3516): M...
243
  		saa7146_dma_free(dev,q,buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

0fc0686e6   Brandon Philips   V4L/DVB (6600): V...
245
  	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
c1accaa21   Mauro Carvalho Chehab   V4L/DVB (6252): A...
246
  		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
  		buf->vb.width  = llength;
  		buf->vb.height = lines;
  		buf->vb.size   = size;
  		buf->vb.field  = field;	// FIXME: check this
  
  		saa7146_pgtable_free(dev->pci, &buf->pt[2]);
  		saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
c7b0ac054   Mauro Carvalho Chehab   V4L/DVB (3516): M...
254
  		err = videobuf_iolock(q,&buf->vb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  		if (err)
  			goto oops;
c1accaa21   Mauro Carvalho Chehab   V4L/DVB (6252): A...
257
258
  		err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
  						 dma->sglist, dma->sglen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
  		if (0 != err)
  			return err;
  	}
0fc0686e6   Brandon Philips   V4L/DVB (6600): V...
262
  	buf->vb.state = VIDEOBUF_PREPARED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
266
267
  	buf->activate = buffer_activate;
  
  	return 0;
  
   oops:
44d0b80e5   Joe Perches   [media] saa7146: ...
268
269
  	DEB_VBI("error out
  ");
c7b0ac054   Mauro Carvalho Chehab   V4L/DVB (3516): M...
270
  	saa7146_dma_free(dev,q,buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
276
277
278
279
280
281
282
283
  
  	return err;
  }
  
  static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
  {
  	int llength,lines;
  
  	lines   = 16 * 2 ; /* 2 fields */
  	llength = vbi_pixel_to_capture;
  
  	*size = lines * llength;
  	*count = 2;
44d0b80e5   Joe Perches   [media] saa7146: ...
284
285
  	DEB_VBI("count:%d, size:%d
  ", *count, *size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
293
294
295
296
  
  	return 0;
  }
  
  static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
  {
  	struct file *file = q->priv_data;
  	struct saa7146_fh *fh = file->private_data;
  	struct saa7146_dev *dev = fh->dev;
  	struct saa7146_vv *vv = dev->vv_data;
  	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
44d0b80e5   Joe Perches   [media] saa7146: ...
297
298
  	DEB_VBI("vb:%p
  ", vb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
304
305
306
307
  	saa7146_buffer_queue(dev,&vv->vbi_q,buf);
  }
  
  static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
  {
  	struct file *file = q->priv_data;
  	struct saa7146_fh *fh   = file->private_data;
  	struct saa7146_dev *dev = fh->dev;
  	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
44d0b80e5   Joe Perches   [media] saa7146: ...
308
309
  	DEB_VBI("vb:%p
  ", vb);
c7b0ac054   Mauro Carvalho Chehab   V4L/DVB (3516): M...
310
  	saa7146_dma_free(dev,q,buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  }
  
  static struct videobuf_queue_ops vbi_qops = {
  	.buf_setup    = buffer_setup,
  	.buf_prepare  = buffer_prepare,
  	.buf_queue    = buffer_queue,
  	.buf_release  = buffer_release,
  };
  
  /* ------------------------------------------------------------------ */
  
  static void vbi_stop(struct saa7146_fh *fh, struct file *file)
  {
  	struct saa7146_dev *dev = fh->dev;
  	struct saa7146_vv *vv = dev->vv_data;
  	unsigned long flags;
44d0b80e5   Joe Perches   [media] saa7146: ...
327
328
  	DEB_VBI("dev:%p, fh:%p
  ", dev, fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
333
334
335
336
337
338
339
340
341
  
  	spin_lock_irqsave(&dev->slock,flags);
  
  	/* disable rps1  */
  	saa7146_write(dev, MC1, MASK_29);
  
  	/* disable rps1 irqs */
  	SAA7146_IER_DISABLE(dev, MASK_28);
  
  	/* shut down dma 3 transfers */
  	saa7146_write(dev, MC1, MASK_20);
  
  	if (vv->vbi_q.curr) {
0fc0686e6   Brandon Philips   V4L/DVB (6600): V...
342
  		saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  	}
  
  	videobuf_queue_cancel(&fh->vbi_q);
  
  	vv->vbi_streaming = NULL;
  
  	del_timer(&vv->vbi_q.timeout);
  	del_timer(&fh->vbi_read_timeout);
  
  	spin_unlock_irqrestore(&dev->slock, flags);
  }
  
  static void vbi_read_timeout(unsigned long data)
  {
  	struct file *file = (struct file*)data;
  	struct saa7146_fh *fh = file->private_data;
  	struct saa7146_dev *dev = fh->dev;
44d0b80e5   Joe Perches   [media] saa7146: ...
360
361
  	DEB_VBI("dev:%p, fh:%p
  ", dev, fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
366
367
  
  	vbi_stop(fh, file);
  }
  
  static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
  {
44d0b80e5   Joe Perches   [media] saa7146: ...
368
369
  	DEB_VBI("dev:%p
  ", dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
375
376
377
378
379
380
381
382
  
  	INIT_LIST_HEAD(&vv->vbi_q.queue);
  
  	init_timer(&vv->vbi_q.timeout);
  	vv->vbi_q.timeout.function = saa7146_buffer_timeout;
  	vv->vbi_q.timeout.data     = (unsigned long)(&vv->vbi_q);
  	vv->vbi_q.dev              = dev;
  
  	init_waitqueue_head(&vv->vbi_wq);
  }
  
  static int vbi_open(struct saa7146_dev *dev, struct file *file)
  {
abf84383e   Joe Perches   V4L/DVB: drivers/...
383
  	struct saa7146_fh *fh = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
  
  	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
  	int ret = 0;
44d0b80e5   Joe Perches   [media] saa7146: ...
387
388
  	DEB_VBI("dev:%p, fh:%p
  ", dev, fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
391
  
  	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
  	if (0 == ret) {
44d0b80e5   Joe Perches   [media] saa7146: ...
392
393
  		DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  		return -EBUSY;
  	}
  
  	/* adjust arbitrition control for video dma 3 */
  	arbtr_ctrl &= ~0x1f0000;
  	arbtr_ctrl |=  0x1d0000;
  	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
  	saa7146_write(dev, MC2, (MASK_04|MASK_20));
  
  	memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
  
  	fh->vbi_fmt.sampling_rate	= 27000000;
  	fh->vbi_fmt.offset		= 248; /* todo */
  	fh->vbi_fmt.samples_per_line	= vbi_pixel_to_capture;
  	fh->vbi_fmt.sample_format	= V4L2_PIX_FMT_GREY;
  
  	/* fixme: this only works for PAL */
  	fh->vbi_fmt.start[0] = 5;
  	fh->vbi_fmt.count[0] = 16;
  	fh->vbi_fmt.start[1] = 312;
  	fh->vbi_fmt.count[1] = 16;
0705135e5   Guennadi Liakhovetski   V4L/DVB (7237): C...
415
416
  	videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
  			    &dev->pci->dev, &dev->slock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
  			    V4L2_BUF_TYPE_VBI_CAPTURE,
  			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
  			    sizeof(struct saa7146_buf),
9af39713f   Hans Verkuil   [media] saa7146: ...
420
  			    file, &dev->v4l2_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
424
425
426
427
428
429
430
431
432
  
  	init_timer(&fh->vbi_read_timeout);
  	fh->vbi_read_timeout.function = vbi_read_timeout;
  	fh->vbi_read_timeout.data = (unsigned long)file;
  
  	/* initialize the brs */
  	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
  		saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
  	} else {
  		saa7146_write(dev, BRS_CTRL, 0x00000001);
  
  		if (0 != (ret = vbi_workaround(dev))) {
44d0b80e5   Joe Perches   [media] saa7146: ...
433
434
  			DEB_VBI("vbi workaround failed!
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
439
440
441
442
443
444
445
  			/* return ret;*/
  		}
  	}
  
  	/* upload brs register */
  	saa7146_write(dev, MC2, (MASK_08|MASK_24));
  	return 0;
  }
  
  static void vbi_close(struct saa7146_dev *dev, struct file *file)
  {
abf84383e   Joe Perches   V4L/DVB: drivers/...
446
  	struct saa7146_fh *fh = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  	struct saa7146_vv *vv = dev->vv_data;
44d0b80e5   Joe Perches   [media] saa7146: ...
448
449
  	DEB_VBI("dev:%p, fh:%p
  ", dev, fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
454
455
456
457
458
459
460
461
462
  
  	if( fh == vv->vbi_streaming ) {
  		vbi_stop(fh, file);
  	}
  	saa7146_res_free(fh, RESOURCE_DMA3_BRS);
  }
  
  static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
  {
  	struct saa7146_vv *vv = dev->vv_data;
  	spin_lock(&dev->slock);
  
  	if (vv->vbi_q.curr) {
44d0b80e5   Joe Perches   [media] saa7146: ...
463
464
  		DEB_VBI("dev:%p, curr:%p
  ", dev, vv->vbi_q.curr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
  		/* this must be += 2, one count for each field */
  		vv->vbi_fieldcount+=2;
  		vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
0fc0686e6   Brandon Philips   V4L/DVB (6600): V...
468
  		saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	} else {
44d0b80e5   Joe Perches   [media] saa7146: ...
470
471
  		DEB_VBI("dev:%p
  ", dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
  	}
  	saa7146_buffer_next(dev,&vv->vbi_q,1);
  
  	spin_unlock(&dev->slock);
  }
  
  static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
  {
  	struct saa7146_fh *fh = file->private_data;
  	struct saa7146_dev *dev = fh->dev;
  	struct saa7146_vv *vv = dev->vv_data;
  	ssize_t ret = 0;
44d0b80e5   Joe Perches   [media] saa7146: ...
484
485
  	DEB_VBI("dev:%p, fh:%p
  ", dev, fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
491
492
493
  
  	if( NULL == vv->vbi_streaming ) {
  		// fixme: check if dma3 is available
  		// fixme: activate vbi engine here if necessary. (really?)
  		vv->vbi_streaming = fh;
  	}
  
  	if( fh != vv->vbi_streaming ) {
44d0b80e5   Joe Perches   [media] saa7146: ...
494
495
496
  		DEB_VBI("open %p is already using vbi capture
  ",
  			vv->vbi_streaming);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
  		return -EBUSY;
  	}
  
  	mod_timer(&fh->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
  	ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
  				   file->f_flags & O_NONBLOCK);
  /*
  	printk("BASE_ODD3:      0x%08x
  ", saa7146_read(dev, BASE_ODD3));
  	printk("BASE_EVEN3:     0x%08x
  ", saa7146_read(dev, BASE_EVEN3));
  	printk("PROT_ADDR3:     0x%08x
  ", saa7146_read(dev, PROT_ADDR3));
  	printk("PITCH3:         0x%08x
  ", saa7146_read(dev, PITCH3));
  	printk("BASE_PAGE3:     0x%08x
  ", saa7146_read(dev, BASE_PAGE3));
  	printk("NUM_LINE_BYTE3: 0x%08x
  ", saa7146_read(dev, NUM_LINE_BYTE3));
  	printk("BRS_CTRL:       0x%08x
  ", saa7146_read(dev, BRS_CTRL));
  */
  	return ret;
  }
  
  struct saa7146_use_ops saa7146_vbi_uops = {
50c25fff5   Michael Krufky   V4L/DVB (3218): W...
523
524
  	.init		= vbi_init,
  	.open		= vbi_open,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
  	.release	= vbi_close,
  	.irq_done	= vbi_irq_done,
50c25fff5   Michael Krufky   V4L/DVB (3218): W...
527
  	.read		= vbi_read,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  };