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