]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * |
3 | * device driver for philips saa7134 based TV cards | |
4 | * video4linux video interface | |
5 | * | |
6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
1da177e4 LT |
17 | */ |
18 | ||
9a12ccfc MCC |
19 | #include "saa7134.h" |
20 | #include "saa7134-reg.h" | |
21 | ||
1da177e4 LT |
22 | #include <linux/init.h> |
23 | #include <linux/list.h> | |
24 | #include <linux/module.h> | |
1da177e4 | 25 | #include <linux/kernel.h> |
1da177e4 | 26 | |
1da177e4 LT |
27 | /* ------------------------------------------------------------------ */ |
28 | ||
ff699e6b | 29 | static unsigned int vbi_debug; |
1da177e4 LT |
30 | module_param(vbi_debug, int, 0644); |
31 | MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); | |
32 | ||
33 | static unsigned int vbibufs = 4; | |
34 | module_param(vbibufs, int, 0444); | |
35 | MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); | |
36 | ||
45f38cb3 MCC |
37 | #define vbi_dbg(fmt, arg...) do { \ |
38 | if (vbi_debug) \ | |
39 | printk(KERN_DEBUG pr_fmt("vbi: " fmt), ## arg); \ | |
40 | } while (0) | |
1da177e4 LT |
41 | |
42 | /* ------------------------------------------------------------------ */ | |
43 | ||
033d0088 | 44 | #define VBI_LINE_COUNT 17 |
1da177e4 LT |
45 | #define VBI_LINE_LENGTH 2048 |
46 | #define VBI_SCALE 0x200 | |
47 | ||
48 | static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf, | |
49 | int task) | |
50 | { | |
51 | struct saa7134_tvnorm *norm = dev->tvnorm; | |
52 | ||
53 | /* setup video scaler */ | |
54 | saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start & 0xff); | |
55 | saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8); | |
56 | saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff); | |
57 | saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8); | |
f246a817 MS |
58 | saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 & 0xff); |
59 | saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8); | |
60 | saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop_0 & 0xff); | |
61 | saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop_0 >> 8); | |
1da177e4 LT |
62 | |
63 | saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff); | |
64 | saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8); | |
65 | saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task), 0x00); | |
66 | saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00); | |
67 | ||
01c3a846 HV |
68 | saa_writeb(SAA7134_VBI_H_LEN1(task), dev->vbi_hlen & 0xff); |
69 | saa_writeb(SAA7134_VBI_H_LEN2(task), dev->vbi_hlen >> 8); | |
70 | saa_writeb(SAA7134_VBI_V_LEN1(task), dev->vbi_vlen & 0xff); | |
71 | saa_writeb(SAA7134_VBI_V_LEN2(task), dev->vbi_vlen >> 8); | |
1da177e4 LT |
72 | |
73 | saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00); | |
74 | } | |
75 | ||
76 | /* ------------------------------------------------------------------ */ | |
77 | ||
78 | static int buffer_activate(struct saa7134_dev *dev, | |
79 | struct saa7134_buf *buf, | |
80 | struct saa7134_buf *next) | |
81 | { | |
2d700715 | 82 | struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv; |
e72936d2 | 83 | unsigned long control, base; |
1da177e4 | 84 | |
630983b7 | 85 | vbi_dbg("buffer_activate [%p]\n", buf); |
1da177e4 LT |
86 | buf->top_seen = 0; |
87 | ||
e72936d2 HV |
88 | task_init(dev, buf, TASK_A); |
89 | task_init(dev, buf, TASK_B); | |
1da177e4 LT |
90 | saa_writeb(SAA7134_OFMT_DATA_A, 0x06); |
91 | saa_writeb(SAA7134_OFMT_DATA_B, 0x06); | |
92 | ||
93 | /* DMA: setup channel 2+3 (= VBI Task A+B) */ | |
94 | base = saa7134_buffer_base(buf); | |
95 | control = SAA7134_RS_CONTROL_BURST_16 | | |
96 | SAA7134_RS_CONTROL_ME | | |
2ada815f | 97 | (dmaq->pt.dma >> 12); |
e72936d2 | 98 | saa_writel(SAA7134_RS_BA1(2), base); |
01c3a846 HV |
99 | saa_writel(SAA7134_RS_BA2(2), base + dev->vbi_hlen * dev->vbi_vlen); |
100 | saa_writel(SAA7134_RS_PITCH(2), dev->vbi_hlen); | |
e72936d2 HV |
101 | saa_writel(SAA7134_RS_CONTROL(2), control); |
102 | saa_writel(SAA7134_RS_BA1(3), base); | |
01c3a846 HV |
103 | saa_writel(SAA7134_RS_BA2(3), base + dev->vbi_hlen * dev->vbi_vlen); |
104 | saa_writel(SAA7134_RS_PITCH(3), dev->vbi_hlen); | |
e72936d2 | 105 | saa_writel(SAA7134_RS_CONTROL(3), control); |
1da177e4 LT |
106 | |
107 | /* start DMA */ | |
108 | saa7134_set_dmabits(dev); | |
2ada815f | 109 | mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT); |
1da177e4 LT |
110 | |
111 | return 0; | |
112 | } | |
113 | ||
2ada815f | 114 | static int buffer_prepare(struct vb2_buffer *vb2) |
1da177e4 | 115 | { |
2ada815f | 116 | struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; |
a00e6888 | 117 | struct saa7134_dev *dev = dmaq->dev; |
2d700715 JS |
118 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); |
119 | struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); | |
120 | struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0); | |
01c3a846 | 121 | unsigned int size; |
1da177e4 | 122 | |
a3f415ab HV |
123 | if (dma->sgl->offset) { |
124 | pr_err("The buffer is not page-aligned\n"); | |
125 | return -EINVAL; | |
126 | } | |
01c3a846 | 127 | size = dev->vbi_hlen * dev->vbi_vlen * 2; |
2ada815f | 128 | if (vb2_plane_size(vb2, 0) < size) |
1da177e4 LT |
129 | return -EINVAL; |
130 | ||
2ada815f | 131 | vb2_set_plane_payload(vb2, 0, size); |
1da177e4 | 132 | |
2ada815f HV |
133 | return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, |
134 | saa7134_buffer_startpage(buf)); | |
1da177e4 LT |
135 | } |
136 | ||
df9ecb0c | 137 | static int queue_setup(struct vb2_queue *q, |
2ada815f | 138 | unsigned int *nbuffers, unsigned int *nplanes, |
36c0f8b3 | 139 | unsigned int sizes[], struct device *alloc_devs[]) |
1da177e4 | 140 | { |
2ada815f | 141 | struct saa7134_dmaqueue *dmaq = q->drv_priv; |
a00e6888 | 142 | struct saa7134_dev *dev = dmaq->dev; |
2ada815f | 143 | unsigned int size; |
1da177e4 | 144 | |
01c3a846 HV |
145 | dev->vbi_vlen = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 + 1; |
146 | if (dev->vbi_vlen > VBI_LINE_COUNT) | |
147 | dev->vbi_vlen = VBI_LINE_COUNT; | |
148 | dev->vbi_hlen = VBI_LINE_LENGTH; | |
2ada815f HV |
149 | size = dev->vbi_hlen * dev->vbi_vlen * 2; |
150 | ||
151 | *nbuffers = saa7134_buffer_count(size, *nbuffers); | |
152 | *nplanes = 1; | |
153 | sizes[0] = size; | |
1da177e4 LT |
154 | return 0; |
155 | } | |
156 | ||
2ada815f | 157 | static int buffer_init(struct vb2_buffer *vb2) |
1da177e4 | 158 | { |
2ada815f | 159 | struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; |
2d700715 JS |
160 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); |
161 | struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); | |
1da177e4 | 162 | |
2ada815f HV |
163 | dmaq->curr = NULL; |
164 | buf->activate = buffer_activate; | |
165 | return 0; | |
1da177e4 LT |
166 | } |
167 | ||
2ada815f HV |
168 | struct vb2_ops saa7134_vbi_qops = { |
169 | .queue_setup = queue_setup, | |
170 | .buf_init = buffer_init, | |
171 | .buf_prepare = buffer_prepare, | |
2ada815f HV |
172 | .buf_queue = saa7134_vb2_buffer_queue, |
173 | .wait_prepare = vb2_ops_wait_prepare, | |
174 | .wait_finish = vb2_ops_wait_finish, | |
175 | .start_streaming = saa7134_vb2_start_streaming, | |
176 | .stop_streaming = saa7134_vb2_stop_streaming, | |
1da177e4 LT |
177 | }; |
178 | ||
179 | /* ------------------------------------------------------------------ */ | |
180 | ||
181 | int saa7134_vbi_init1(struct saa7134_dev *dev) | |
182 | { | |
183 | INIT_LIST_HEAD(&dev->vbi_q.queue); | |
184 | init_timer(&dev->vbi_q.timeout); | |
185 | dev->vbi_q.timeout.function = saa7134_buffer_timeout; | |
186 | dev->vbi_q.timeout.data = (unsigned long)(&dev->vbi_q); | |
187 | dev->vbi_q.dev = dev; | |
188 | ||
189 | if (vbibufs < 2) | |
190 | vbibufs = 2; | |
191 | if (vbibufs > VIDEO_MAX_FRAME) | |
192 | vbibufs = VIDEO_MAX_FRAME; | |
193 | return 0; | |
194 | } | |
195 | ||
196 | int saa7134_vbi_fini(struct saa7134_dev *dev) | |
197 | { | |
198 | /* nothing */ | |
199 | return 0; | |
200 | } | |
201 | ||
202 | void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status) | |
203 | { | |
204 | spin_lock(&dev->slock); | |
205 | if (dev->vbi_q.curr) { | |
1da177e4 LT |
206 | /* make sure we have seen both fields */ |
207 | if ((status & 0x10) == 0x00) { | |
208 | dev->vbi_q.curr->top_seen = 1; | |
209 | goto done; | |
210 | } | |
211 | if (!dev->vbi_q.curr->top_seen) | |
212 | goto done; | |
213 | ||
2ada815f | 214 | saa7134_buffer_finish(dev, &dev->vbi_q, VB2_BUF_STATE_DONE); |
1da177e4 | 215 | } |
e72936d2 | 216 | saa7134_buffer_next(dev, &dev->vbi_q); |
1da177e4 LT |
217 | |
218 | done: | |
219 | spin_unlock(&dev->slock); | |
220 | } |