Rev 608 | Rev 621 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
428 | giacomo | 1 | /* |
2 | bttv-risc.c -- interfaces to other kernel modules |
||
3 | |||
4 | bttv risc code handling |
||
5 | - memory management |
||
6 | - generation |
||
7 | |||
8 | (c) 2000 Gerd Knorr <kraxel@bytesex.org> |
||
9 | |||
10 | This program is free software; you can redistribute it and/or modify |
||
11 | it under the terms of the GNU General Public License as published by |
||
12 | the Free Software Foundation; either version 2 of the License, or |
||
13 | (at your option) any later version. |
||
14 | |||
15 | This program is distributed in the hope that it will be useful, |
||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 | GNU General Public License for more details. |
||
19 | |||
20 | You should have received a copy of the GNU General Public License |
||
21 | along with this program; if not, write to the Free Software |
||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
23 | |||
24 | */ |
||
25 | |||
26 | #include <linuxcomp.h> |
||
27 | |||
28 | #include <linux/module.h> |
||
29 | #include <linux/init.h> |
||
30 | #include <linux/pci.h> |
||
31 | #include <linux/vmalloc.h> |
||
32 | #include <linux/interrupt.h> |
||
33 | #include <asm/page.h> |
||
34 | #include <asm/pgtable.h> |
||
35 | |||
36 | #include "drivers/bttvp.h" |
||
37 | |||
38 | #define VCR_HACK_LINES 4 |
||
39 | |||
40 | /* ---------------------------------------------------------- */ |
||
41 | /* risc code generators */ |
||
42 | |||
43 | int |
||
44 | bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, |
||
45 | struct scatterlist *sglist, |
||
46 | unsigned int offset, unsigned int bpl, |
||
47 | unsigned int padding, unsigned int lines) |
||
48 | { |
||
49 | u32 instructions,line,todo; |
||
50 | struct scatterlist *sg; |
||
51 | u32 *rp; |
||
52 | int rc; |
||
53 | |||
54 | /* estimate risc mem: worst case is one write per page border + |
||
55 | one write per scan line + sync + jump (all 2 dwords) */ |
||
56 | instructions = (bpl * lines) / PAGE_SIZE + lines; |
||
57 | instructions += 2; |
||
58 | if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) |
||
59 | return rc; |
||
60 | |||
61 | /* sync instruction */ |
||
62 | rp = risc->cpu; |
||
63 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
64 | *(rp++) = cpu_to_le32(0); |
||
65 | |||
66 | /* scan lines */ |
||
67 | sg = sglist; |
||
68 | for (line = 0; line < lines; line++) { |
||
69 | if ((btv->opt_vcr_hack) && |
||
70 | (line >= (lines - VCR_HACK_LINES))) |
||
71 | continue; |
||
72 | while (offset >= sg_dma_len(sg)) { |
||
73 | offset -= sg_dma_len(sg); |
||
74 | sg++; |
||
75 | } |
||
76 | if (bpl <= sg_dma_len(sg)-offset) { |
||
77 | /* fits into current chunk */ |
||
78 | *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| |
||
79 | BT848_RISC_EOL|bpl); |
||
80 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); |
||
81 | offset+=bpl; |
||
82 | } else { |
||
83 | /* scanline needs to be splitted */ |
||
84 | todo = bpl; |
||
85 | *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| |
||
86 | (sg_dma_len(sg)-offset)); |
||
87 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); |
||
88 | todo -= (sg_dma_len(sg)-offset); |
||
89 | offset = 0; |
||
90 | sg++; |
||
91 | while (todo > sg_dma_len(sg)) { |
||
92 | *(rp++)=cpu_to_le32(BT848_RISC_WRITE| |
||
93 | sg_dma_len(sg)); |
||
94 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); |
||
95 | todo -= sg_dma_len(sg); |
||
96 | sg++; |
||
97 | } |
||
98 | *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| |
||
99 | todo); |
||
100 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); |
||
101 | offset += todo; |
||
102 | } |
||
103 | offset += padding; |
||
104 | } |
||
105 | dprintk("bttv%d: risc planar: %d sglist elems\n", btv->nr, (int)(sg-sglist)); |
||
106 | |||
107 | /* save pointer to jmp instruction address */ |
||
108 | risc->jmp = rp; |
||
109 | return 0; |
||
110 | } |
||
111 | |||
112 | int |
||
113 | bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, |
||
114 | struct scatterlist *sglist, |
||
115 | unsigned int yoffset, unsigned int ybpl, |
||
116 | unsigned int ypadding, unsigned int ylines, |
||
117 | unsigned int uoffset, unsigned int voffset, |
||
118 | unsigned int hshift, unsigned int vshift, |
||
119 | unsigned int cpadding) |
||
120 | { |
||
121 | unsigned int instructions,line,todo,ylen,chroma; |
||
122 | u32 *rp,ri; |
||
123 | struct scatterlist *ysg; |
||
124 | struct scatterlist *usg; |
||
125 | struct scatterlist *vsg; |
||
126 | int rc; |
||
127 | |||
128 | /* estimate risc mem: worst case is one write per page border + |
||
129 | one write per scan line (5 dwords) |
||
130 | plus sync + jump (2 dwords) */ |
||
131 | instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; |
||
132 | instructions += 2; |
||
133 | if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0) |
||
134 | return rc; |
||
135 | |||
136 | /* sync instruction */ |
||
137 | rp = risc->cpu; |
||
138 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); |
||
139 | *(rp++) = cpu_to_le32(0); |
||
140 | |||
141 | /* scan lines */ |
||
142 | ysg = sglist; |
||
143 | usg = sglist; |
||
144 | vsg = sglist; |
||
145 | for (line = 0; line < ylines; line++) { |
||
146 | if ((btv->opt_vcr_hack) && |
||
147 | (line >= (ylines - VCR_HACK_LINES))) |
||
148 | continue; |
||
149 | switch (vshift) { |
||
150 | case 0: chroma = 1; break; |
||
151 | case 1: chroma = !(line & 1); break; |
||
152 | case 2: chroma = !(line & 3); break; |
||
153 | default: chroma = 0; |
||
154 | } |
||
155 | for (todo = ybpl; todo > 0; todo -= ylen) { |
||
156 | /* go to next sg entry if needed */ |
||
157 | while (yoffset >= sg_dma_len(ysg)) { |
||
158 | yoffset -= sg_dma_len(ysg); |
||
159 | ysg++; |
||
160 | } |
||
161 | while (uoffset >= sg_dma_len(usg)) { |
||
162 | uoffset -= sg_dma_len(usg); |
||
163 | usg++; |
||
164 | } |
||
165 | while (voffset >= sg_dma_len(vsg)) { |
||
166 | voffset -= sg_dma_len(vsg); |
||
167 | vsg++; |
||
168 | } |
||
169 | |||
170 | /* calculate max number of bytes we can write */ |
||
171 | ylen = todo; |
||
172 | if (yoffset + ylen > sg_dma_len(ysg)) |
||
173 | ylen = sg_dma_len(ysg) - yoffset; |
||
174 | if (chroma) { |
||
175 | if (uoffset + (ylen>>hshift) > sg_dma_len(usg)) |
||
176 | ylen = (sg_dma_len(usg) - uoffset) << hshift; |
||
177 | if (voffset + (ylen>>hshift) > sg_dma_len(vsg)) |
||
178 | ylen = (sg_dma_len(vsg) - voffset) << hshift; |
||
179 | ri = BT848_RISC_WRITE123; |
||
180 | } else { |
||
181 | ri = BT848_RISC_WRITE1S23; |
||
182 | } |
||
183 | if (ybpl == todo) |
||
184 | ri |= BT848_RISC_SOL; |
||
185 | if (ylen == todo) |
||
186 | ri |= BT848_RISC_EOL; |
||
187 | |||
188 | /* write risc instruction */ |
||
189 | *(rp++)=cpu_to_le32(ri | ylen); |
||
190 | *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | |
||
191 | (ylen >> hshift)); |
||
192 | *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); |
||
193 | yoffset += ylen; |
||
194 | if (chroma) { |
||
195 | *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset); |
||
196 | uoffset += ylen >> hshift; |
||
197 | *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset); |
||
198 | voffset += ylen >> hshift; |
||
199 | } |
||
200 | } |
||
201 | yoffset += ypadding; |
||
202 | if (chroma) { |
||
203 | uoffset += cpadding; |
||
204 | voffset += cpadding; |
||
205 | } |
||
206 | } |
||
207 | |||
208 | /* save pointer to jmp instruction address */ |
||
209 | risc->jmp = rp; |
||
210 | return 0; |
||
211 | } |
||
212 | |||
213 | int |
||
214 | bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, |
||
215 | const struct bttv_format *fmt, struct bttv_overlay *ov, |
||
216 | int skip_even, int skip_odd) |
||
217 | { |
||
218 | int instructions,rc,line,maxy,start,end,skip,nskips; |
||
219 | struct btcx_skiplist *skips; |
||
220 | u32 *rp,ri,ra; |
||
221 | u32 addr; |
||
222 | |||
223 | /* skip list for window clipping */ |
||
224 | if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) |
||
225 | return -ENOMEM; |
||
226 | |||
227 | /* estimate risc mem: worst case is (clip+1) * lines instructions |
||
228 | + sync + jump (all 2 dwords) */ |
||
229 | instructions = (ov->nclips + 1) * |
||
230 | ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); |
||
231 | instructions += 2; |
||
232 | if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) { |
||
233 | kfree(skips); |
||
234 | return rc; |
||
235 | } |
||
236 | |||
237 | /* sync instruction */ |
||
238 | rp = risc->cpu; |
||
239 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
240 | *(rp++) = cpu_to_le32(0); |
||
241 | |||
242 | addr = (unsigned long)btv->fbuf.base; |
||
243 | addr += btv->fbuf.fmt.bytesperline * ov->w.top; |
||
244 | addr += (fmt->depth >> 3) * ov->w.left; |
||
245 | |||
246 | /* scan lines */ |
||
247 | for (maxy = -1, line = 0; line < ov->w.height; |
||
248 | line++, addr += btv->fbuf.fmt.bytesperline) { |
||
249 | if ((btv->opt_vcr_hack) && |
||
250 | (line >= (ov->w.height - VCR_HACK_LINES))) |
||
251 | continue; |
||
252 | if ((line%2) == 0 && skip_even) |
||
253 | continue; |
||
254 | if ((line%2) == 1 && skip_odd) |
||
255 | if ((line%2) == 0 && skip_even) |
||
256 | continue; |
||
257 | if ((line%2) == 1 && skip_odd) |
||
258 | continue; |
||
259 | |||
260 | /* calculate clipping */ |
||
261 | if (line > maxy) |
||
262 | btcx_calc_skips(line, ov->w.width, &maxy, |
||
263 | skips, &nskips, ov->clips, ov->nclips); |
||
264 | |||
265 | /* write out risc code */ |
||
266 | for (start = 0, skip = 0; start < ov->w.width; start = end) { |
||
267 | if (skip >= nskips) { |
||
268 | ri = BT848_RISC_WRITE; |
||
269 | end = ov->w.width; |
||
270 | } else if (start < skips[skip].start) { |
||
271 | ri = BT848_RISC_WRITE; |
||
272 | end = skips[skip].start; |
||
273 | } else { |
||
274 | ri = BT848_RISC_SKIP; |
||
275 | end = skips[skip].end; |
||
276 | skip++; |
||
277 | } |
||
278 | if (BT848_RISC_WRITE == ri) |
||
279 | ra = addr + (fmt->depth>>3)*start; |
||
280 | else |
||
281 | ra = 0; |
||
282 | |||
283 | if (0 == start) |
||
284 | ri |= BT848_RISC_SOL; |
||
285 | if (ov->w.width == end) |
||
286 | ri |= BT848_RISC_EOL; |
||
287 | ri |= (fmt->depth>>3) * (end-start); |
||
288 | |||
289 | *(rp++)=cpu_to_le32(ri); |
||
290 | if (0 != ra) |
||
291 | *(rp++)=cpu_to_le32(ra); |
||
292 | } |
||
293 | } |
||
294 | |||
295 | /* save pointer to jmp instruction address */ |
||
296 | risc->jmp = rp; |
||
297 | kfree(skips); |
||
298 | return 0; |
||
299 | } |
||
300 | |||
301 | /* ---------------------------------------------------------- */ |
||
302 | |||
303 | void |
||
304 | bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, |
||
305 | int width, int height, int interleaved, int norm) |
||
306 | { |
||
307 | const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; |
||
308 | u32 xsf, sr; |
||
309 | int vdelay; |
||
310 | |||
311 | int swidth = tvnorm->swidth; |
||
312 | int totalwidth = tvnorm->totalwidth; |
||
313 | int scaledtwidth = tvnorm->scaledtwidth; |
||
314 | |||
315 | if (bttv_tvcards[btv->type].muxsel[btv->input] < 0) { |
||
316 | swidth = 720; |
||
317 | totalwidth = 858; |
||
318 | scaledtwidth = 858; |
||
319 | } |
||
320 | |||
321 | vdelay = tvnorm->vdelay; |
||
322 | #if 0 /* FIXME */ |
||
323 | if (vdelay < btv->vbi.lines*2) |
||
324 | vdelay = btv->vbi.lines*2; |
||
325 | #endif |
||
326 | |||
327 | xsf = (width*scaledtwidth)/swidth; |
||
328 | geo->hscale = ((totalwidth*4096UL)/xsf-4096); |
||
329 | geo->hdelay = tvnorm->hdelayx1; |
||
330 | geo->hdelay = (geo->hdelay*width)/swidth; |
||
331 | geo->hdelay &= 0x3fe; |
||
332 | sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; |
||
333 | geo->vscale = (0x10000UL-sr) & 0x1fff; |
||
334 | geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | |
||
335 | ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); |
||
336 | geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; |
||
337 | geo->vdelay = vdelay; |
||
338 | geo->width = width; |
||
339 | geo->sheight = tvnorm->sheight; |
||
340 | geo->vtotal = tvnorm->vtotal; |
||
341 | |||
342 | if (btv->opt_combfilter) { |
||
343 | geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); |
||
344 | geo->comb = (width < 769) ? 1 : 0; |
||
345 | } else { |
||
346 | geo->vtc = 0; |
||
347 | geo->comb = 0; |
||
348 | } |
||
349 | } |
||
350 | |||
351 | void |
||
352 | bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) |
||
353 | { |
||
354 | int off = odd ? 0x80 : 0x00; |
||
355 | |||
356 | if (geo->comb) |
||
357 | btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); |
||
358 | else |
||
359 | btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); |
||
360 | |||
361 | btwrite(geo->vtc, BT848_E_VTC+off); |
||
362 | btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); |
||
363 | btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); |
||
364 | btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); |
||
365 | btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); |
||
366 | btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); |
||
367 | btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); |
||
368 | btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); |
||
369 | btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); |
||
370 | btwrite(geo->crop, BT848_E_CROP+off); |
||
371 | btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); |
||
372 | btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); |
||
373 | } |
||
374 | |||
375 | /* ---------------------------------------------------------- */ |
||
376 | /* risc group / risc main loop / dma management */ |
||
377 | |||
378 | void |
||
379 | bttv_set_dma(struct bttv *btv, int override, int irqflags) |
||
380 | { |
||
381 | unsigned long cmd; |
||
382 | int capctl; |
||
383 | |||
384 | btv->cap_ctl = 0; |
||
385 | if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; |
||
386 | if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; |
||
387 | if (NULL != btv->curr.vbi) btv->cap_ctl |= 0x0c; |
||
388 | |||
389 | capctl = 0; |
||
390 | capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ |
||
391 | capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */ |
||
392 | capctl |= override; |
||
393 | |||
394 | d2printk(KERN_DEBUG |
||
395 | "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", |
||
396 | btv->nr,capctl,irqflags, |
||
397 | btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, |
||
398 | btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, |
||
399 | btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0, |
||
400 | btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); |
||
401 | |||
402 | cmd = BT848_RISC_JUMP; |
||
403 | if (irqflags) { |
||
404 | cmd |= BT848_RISC_IRQ; |
||
405 | cmd |= (irqflags & 0x0f) << 16; |
||
406 | cmd |= (~irqflags & 0x0f) << 20; |
||
516 | giacomo | 407 | mod_timer(&btv->timeout, jiffies26+BTTV_TIMEOUT); |
428 | giacomo | 408 | } else { |
409 | del_timer(&btv->timeout); |
||
410 | } |
||
411 | btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); |
||
412 | |||
413 | btaor(capctl, ~0x0f, BT848_CAP_CTL); |
||
414 | if (capctl) { |
||
415 | if (btv->dma_on) |
||
416 | return; |
||
417 | btwrite(btv->main.dma, BT848_RISC_STRT_ADD); |
||
418 | btor(3, BT848_GPIO_DMA_CTL); |
||
419 | btv->dma_on = 1; |
||
420 | } else { |
||
421 | if (!btv->dma_on) |
||
422 | return; |
||
423 | btand(~3, BT848_GPIO_DMA_CTL); |
||
424 | btv->dma_on = 0; |
||
425 | } |
||
426 | return; |
||
427 | } |
||
428 | |||
429 | int |
||
430 | bttv_risc_init_main(struct bttv *btv) |
||
431 | { |
||
432 | int rc; |
||
433 | |||
434 | if ((rc = btcx_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0) |
||
435 | return rc; |
||
436 | dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", |
||
437 | btv->nr,(unsigned long long)btv->main.dma); |
||
438 | |||
439 | btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | |
||
440 | BT848_FIFO_STATUS_VRE); |
||
441 | btv->main.cpu[1] = cpu_to_le32(0); |
||
442 | btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP); |
||
443 | btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2)); |
||
444 | |||
445 | /* top field */ |
||
446 | btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP); |
||
447 | btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2)); |
||
448 | btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); |
||
449 | btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); |
||
450 | |||
451 | btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | |
||
452 | BT848_FIFO_STATUS_VRO); |
||
453 | btv->main.cpu[9] = cpu_to_le32(0); |
||
454 | |||
455 | /* bottom field */ |
||
456 | btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); |
||
457 | btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); |
||
458 | btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); |
||
459 | btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); |
||
460 | |||
461 | /* jump back to top field */ |
||
462 | btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); |
||
463 | btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); |
||
464 | |||
465 | return 0; |
||
466 | } |
||
467 | |||
468 | int |
||
469 | bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, |
||
470 | int irqflags) |
||
471 | { |
||
472 | unsigned long cmd; |
||
473 | unsigned long next = btv->main.dma + ((slot+2) << 2); |
||
474 | |||
475 | if (NULL == risc) { |
||
476 | d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n", |
||
477 | btv->nr,risc,slot); |
||
478 | btv->main.cpu[slot+1] = cpu_to_le32(next); |
||
479 | } else { |
||
480 | d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", |
||
481 | btv->nr,risc,slot,(unsigned long long)risc->dma,irqflags); |
||
482 | cmd = BT848_RISC_JUMP; |
||
483 | if (irqflags) { |
||
484 | cmd |= BT848_RISC_IRQ; |
||
485 | cmd |= (irqflags & 0x0f) << 16; |
||
486 | cmd |= (~irqflags & 0x0f) << 20; |
||
487 | } |
||
488 | risc->jmp[0] = cpu_to_le32(cmd); |
||
489 | risc->jmp[1] = cpu_to_le32(next); |
||
490 | btv->main.cpu[slot+1] = cpu_to_le32(risc->dma); |
||
491 | } |
||
492 | return 0; |
||
493 | } |
||
494 | |||
495 | void |
||
496 | bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) |
||
497 | { |
||
614 | giacomo | 498 | //if (in_interrupt()) |
499 | // BUG(); |
||
500 | videobuf_waiton(&buf->vb,0,0); |
||
516 | giacomo | 501 | //videobuf_dma_pci_unmap(btv->dev, &buf->vb.dma); |
502 | //videobuf_dma_free(&buf->vb.dma); |
||
428 | giacomo | 503 | btcx_riscmem_free(btv->dev,&buf->bottom); |
504 | btcx_riscmem_free(btv->dev,&buf->top); |
||
505 | buf->vb.state = STATE_NEEDS_INIT; |
||
506 | } |
||
507 | |||
508 | int |
||
509 | bttv_buffer_set_activate(struct bttv *btv, |
||
510 | struct bttv_buffer_set *set) |
||
511 | { |
||
512 | /* vbi capture */ |
||
513 | if (set->vbi) { |
||
514 | set->vbi->vb.state = STATE_ACTIVE; |
||
515 | list_del(&set->vbi->vb.queue); |
||
516 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top, 0); |
||
517 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0); |
||
518 | } else { |
||
519 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); |
||
520 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); |
||
521 | } |
||
522 | |||
523 | /* video capture */ |
||
524 | if (NULL != set->top && NULL != set->bottom) { |
||
525 | if (set->top == set->bottom) { |
||
526 | set->top->vb.state = STATE_ACTIVE; |
||
527 | if (set->top->vb.queue.next) |
||
528 | list_del(&set->top->vb.queue); |
||
529 | } else { |
||
530 | set->top->vb.state = STATE_ACTIVE; |
||
531 | set->bottom->vb.state = STATE_ACTIVE; |
||
532 | if (set->top->vb.queue.next) |
||
533 | list_del(&set->top->vb.queue); |
||
534 | if (set->bottom->vb.queue.next) |
||
535 | list_del(&set->bottom->vb.queue); |
||
536 | } |
||
537 | bttv_apply_geo(btv, &set->top->geo, 1); |
||
538 | bttv_apply_geo(btv, &set->bottom->geo,0); |
||
539 | bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, set->topirq); |
||
540 | bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0); |
||
541 | btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f), |
||
542 | ~0xff, BT848_COLOR_FMT); |
||
543 | btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05), |
||
544 | ~0x0f, BT848_COLOR_CTL); |
||
545 | } else if (NULL != set->top) { |
||
546 | set->top->vb.state = STATE_ACTIVE; |
||
547 | if (set->top->vb.queue.next) |
||
548 | list_del(&set->top->vb.queue); |
||
549 | bttv_apply_geo(btv, &set->top->geo,1); |
||
550 | bttv_apply_geo(btv, &set->top->geo,0); |
||
551 | bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, 0); |
||
552 | bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); |
||
553 | btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT); |
||
554 | btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); |
||
555 | } else if (NULL != set->bottom) { |
||
556 | set->bottom->vb.state = STATE_ACTIVE; |
||
557 | if (set->bottom->vb.queue.next) |
||
558 | list_del(&set->bottom->vb.queue); |
||
559 | bttv_apply_geo(btv, &set->bottom->geo,1); |
||
560 | bttv_apply_geo(btv, &set->bottom->geo,0); |
||
561 | bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); |
||
562 | bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0); |
||
563 | btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT); |
||
564 | btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); |
||
565 | } else { |
||
566 | bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); |
||
567 | bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); |
||
568 | } |
||
569 | return 0; |
||
570 | } |
||
571 | |||
572 | /* ---------------------------------------------------------- */ |
||
573 | |||
574 | /* calculate geometry, build risc code */ |
||
575 | int |
||
576 | bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) |
||
577 | { |
||
578 | const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; |
||
579 | |||
516 | giacomo | 580 | //dprintk(KERN_DEBUG |
581 | // "bttv%d: buffer field: %s format: %s size: %dx%d\n", |
||
582 | // btv->nr, v4l2_field_names[buf->vb.field], |
||
583 | // buf->fmt->name, buf->vb.width, buf->vb.height); |
||
428 | giacomo | 584 | |
585 | /* packed pixel modes */ |
||
586 | if (buf->fmt->flags & FORMAT_FLAGS_PACKED) { |
||
587 | int bpl = (buf->fmt->depth >> 3) * buf->vb.width; |
||
588 | int bpf = bpl * (buf->vb.height >> 1); |
||
589 | |||
590 | bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, |
||
591 | V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); |
||
592 | |||
593 | switch (buf->vb.field) { |
||
594 | case V4L2_FIELD_TOP: |
||
595 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
||
596 | 0,bpl,0,buf->vb.height); |
||
597 | break; |
||
598 | case V4L2_FIELD_BOTTOM: |
||
599 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
||
600 | 0,bpl,0,buf->vb.height); |
||
601 | break; |
||
602 | case V4L2_FIELD_INTERLACED: |
||
603 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
||
604 | 0,bpl,bpl,buf->vb.height >> 1); |
||
605 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
||
606 | bpl,bpl,bpl,buf->vb.height >> 1); |
||
607 | break; |
||
608 | case V4L2_FIELD_SEQ_TB: |
||
609 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
||
610 | 0,bpl,0,buf->vb.height >> 1); |
||
611 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
||
612 | bpf,bpl,0,buf->vb.height >> 1); |
||
613 | break; |
||
614 | default: |
||
615 | BUG(); |
||
616 | } |
||
617 | } |
||
618 | |||
619 | /* planar modes */ |
||
620 | if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) { |
||
621 | int uoffset, voffset; |
||
622 | int ypadding, cpadding, lines; |
||
623 | |||
624 | /* calculate chroma offsets */ |
||
625 | uoffset = buf->vb.width * buf->vb.height; |
||
626 | voffset = buf->vb.width * buf->vb.height; |
||
627 | if (buf->fmt->flags & FORMAT_FLAGS_CrCb) { |
||
628 | /* Y-Cr-Cb plane order */ |
||
629 | uoffset >>= buf->fmt->hshift; |
||
630 | uoffset >>= buf->fmt->vshift; |
||
631 | uoffset += voffset; |
||
632 | } else { |
||
633 | /* Y-Cb-Cr plane order */ |
||
634 | voffset >>= buf->fmt->hshift; |
||
635 | voffset >>= buf->fmt->vshift; |
||
636 | voffset += uoffset; |
||
637 | } |
||
638 | |||
639 | switch (buf->vb.field) { |
||
640 | case V4L2_FIELD_TOP: |
||
641 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
||
642 | buf->vb.height,0,buf->tvnorm); |
||
643 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, |
||
644 | 0,buf->vb.width,0,buf->vb.height, |
||
645 | uoffset,voffset,buf->fmt->hshift, |
||
646 | buf->fmt->vshift,0); |
||
647 | break; |
||
648 | case V4L2_FIELD_BOTTOM: |
||
649 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
||
650 | buf->vb.height,0,buf->tvnorm); |
||
651 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, |
||
652 | 0,buf->vb.width,0,buf->vb.height, |
||
653 | uoffset,voffset,buf->fmt->hshift, |
||
654 | buf->fmt->vshift,0); |
||
655 | break; |
||
656 | case V4L2_FIELD_INTERLACED: |
||
657 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
||
658 | buf->vb.height,1,buf->tvnorm); |
||
659 | lines = buf->vb.height >> 1; |
||
660 | ypadding = buf->vb.width; |
||
661 | cpadding = buf->vb.width >> buf->fmt->hshift; |
||
662 | bttv_risc_planar(btv,&buf->top, |
||
663 | buf->vb.dma.sglist, |
||
664 | 0,buf->vb.width,ypadding,lines, |
||
665 | uoffset,voffset, |
||
666 | buf->fmt->hshift, |
||
667 | buf->fmt->vshift, |
||
668 | cpadding); |
||
669 | bttv_risc_planar(btv,&buf->bottom, |
||
670 | buf->vb.dma.sglist, |
||
671 | ypadding,buf->vb.width,ypadding,lines, |
||
672 | uoffset+cpadding, |
||
673 | voffset+cpadding, |
||
674 | buf->fmt->hshift, |
||
675 | buf->fmt->vshift, |
||
676 | cpadding); |
||
677 | break; |
||
678 | case V4L2_FIELD_SEQ_TB: |
||
679 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
||
680 | buf->vb.height,1,buf->tvnorm); |
||
681 | lines = buf->vb.height >> 1; |
||
682 | ypadding = buf->vb.width; |
||
683 | cpadding = buf->vb.width >> buf->fmt->hshift; |
||
684 | bttv_risc_planar(btv,&buf->top, |
||
685 | buf->vb.dma.sglist, |
||
686 | 0,buf->vb.width,0,lines, |
||
687 | uoffset >> 1, |
||
688 | voffset >> 1, |
||
689 | buf->fmt->hshift, |
||
690 | buf->fmt->vshift, |
||
691 | 0); |
||
692 | bttv_risc_planar(btv,&buf->bottom, |
||
693 | buf->vb.dma.sglist, |
||
694 | lines * ypadding,buf->vb.width,0,lines, |
||
695 | lines * ypadding + (uoffset >> 1), |
||
696 | lines * ypadding + (voffset >> 1), |
||
697 | buf->fmt->hshift, |
||
698 | buf->fmt->vshift, |
||
699 | 0); |
||
700 | break; |
||
701 | default: |
||
702 | BUG(); |
||
703 | } |
||
704 | } |
||
705 | |||
706 | /* raw data */ |
||
707 | if (buf->fmt->flags & FORMAT_FLAGS_RAW) { |
||
708 | /* build risc code */ |
||
709 | buf->vb.field = V4L2_FIELD_SEQ_TB; |
||
710 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, |
||
711 | 1,buf->tvnorm); |
||
712 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, |
||
713 | 0, RAW_BPL, 0, RAW_LINES); |
||
714 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, |
||
715 | buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); |
||
716 | } |
||
717 | |||
718 | /* copy format info */ |
||
719 | buf->btformat = buf->fmt->btformat; |
||
720 | buf->btswap = buf->fmt->btswap; |
||
721 | return 0; |
||
722 | } |
||
723 | |||
724 | /* ---------------------------------------------------------- */ |
||
725 | |||
726 | /* calculate geometry, build risc code */ |
||
727 | int |
||
728 | bttv_overlay_risc(struct bttv *btv, |
||
729 | struct bttv_overlay *ov, |
||
730 | const struct bttv_format *fmt, |
||
731 | struct bttv_buffer *buf) |
||
732 | { |
||
733 | /* check interleave, bottom+top fields */ |
||
516 | giacomo | 734 | //dprintk(KERN_DEBUG |
735 | // "bttv%d: overlay fields: %s format: %s size: %dx%d\n", |
||
736 | // btv->nr, v4l2_field_names[buf->vb.field], |
||
737 | // fmt->name,ov->w.width,ov->w.height); |
||
428 | giacomo | 738 | |
739 | /* calculate geometry */ |
||
740 | bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, |
||
741 | V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm); |
||
742 | |||
743 | /* build risc code */ |
||
744 | switch (ov->field) { |
||
745 | case V4L2_FIELD_TOP: |
||
746 | bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0); |
||
747 | break; |
||
748 | case V4L2_FIELD_BOTTOM: |
||
749 | bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0); |
||
750 | break; |
||
751 | case V4L2_FIELD_INTERLACED: |
||
752 | #if 0 |
||
753 | bttv_risc_overlay(btv, &buf->top, fmt, ov, 1, 0); |
||
754 | bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 1); |
||
755 | #else |
||
756 | bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1); |
||
757 | bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0); |
||
758 | #endif |
||
759 | break; |
||
760 | default: |
||
761 | BUG(); |
||
762 | } |
||
763 | |||
764 | /* copy format info */ |
||
765 | buf->btformat = fmt->btformat; |
||
766 | buf->btswap = fmt->btswap; |
||
767 | buf->vb.field = ov->field; |
||
768 | return 0; |
||
769 | } |
||
770 | |||
771 | /* |
||
772 | * Local variables: |
||
773 | * c-basic-offset: 8 |
||
774 | * End: |
||
775 | */ |