174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
268de959fSMauro Carvalho Chehab /*
368de959fSMauro Carvalho Chehab
468de959fSMauro Carvalho Chehab bttv-risc.c -- interfaces to other kernel modules
568de959fSMauro Carvalho Chehab
668de959fSMauro Carvalho Chehab bttv risc code handling
768de959fSMauro Carvalho Chehab - memory management
868de959fSMauro Carvalho Chehab - generation
968de959fSMauro Carvalho Chehab
1068de959fSMauro Carvalho Chehab (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
1168de959fSMauro Carvalho Chehab
1268de959fSMauro Carvalho Chehab
1368de959fSMauro Carvalho Chehab */
1468de959fSMauro Carvalho Chehab
1568de959fSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1668de959fSMauro Carvalho Chehab
1768de959fSMauro Carvalho Chehab #include <linux/module.h>
1868de959fSMauro Carvalho Chehab #include <linux/init.h>
1968de959fSMauro Carvalho Chehab #include <linux/slab.h>
2068de959fSMauro Carvalho Chehab #include <linux/pci.h>
2168de959fSMauro Carvalho Chehab #include <linux/vmalloc.h>
2268de959fSMauro Carvalho Chehab #include <linux/interrupt.h>
23ca5999fdSMike Rapoport #include <linux/pgtable.h>
2465fddcfcSMike Rapoport #include <asm/page.h>
2568de959fSMauro Carvalho Chehab #include <media/v4l2-ioctl.h>
2668de959fSMauro Carvalho Chehab
2768de959fSMauro Carvalho Chehab #include "bttvp.h"
2868de959fSMauro Carvalho Chehab
2968de959fSMauro Carvalho Chehab #define VCR_HACK_LINES 4
3068de959fSMauro Carvalho Chehab
3168de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
3268de959fSMauro Carvalho Chehab /* risc code generators */
3368de959fSMauro Carvalho Chehab
3468de959fSMauro Carvalho Chehab int
bttv_risc_packed(struct bttv * btv,struct btcx_riscmem * risc,struct scatterlist * sglist,unsigned int offset,unsigned int bpl,unsigned int padding,unsigned int skip_lines,unsigned int store_lines)3568de959fSMauro Carvalho Chehab bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
3668de959fSMauro Carvalho Chehab struct scatterlist *sglist,
3768de959fSMauro Carvalho Chehab unsigned int offset, unsigned int bpl,
3868de959fSMauro Carvalho Chehab unsigned int padding, unsigned int skip_lines,
3968de959fSMauro Carvalho Chehab unsigned int store_lines)
4068de959fSMauro Carvalho Chehab {
4168de959fSMauro Carvalho Chehab u32 instructions,line,todo;
4268de959fSMauro Carvalho Chehab struct scatterlist *sg;
4368de959fSMauro Carvalho Chehab __le32 *rp;
4468de959fSMauro Carvalho Chehab int rc;
4568de959fSMauro Carvalho Chehab
4668de959fSMauro Carvalho Chehab /* estimate risc mem: worst case is one write per page border +
4768de959fSMauro Carvalho Chehab one write per scan line + sync + jump (all 2 dwords). padding
4868de959fSMauro Carvalho Chehab can cause next bpl to start close to a page border. First DMA
4968de959fSMauro Carvalho Chehab region may be smaller than PAGE_SIZE */
5068de959fSMauro Carvalho Chehab instructions = skip_lines * 4;
5168de959fSMauro Carvalho Chehab instructions += (1 + ((bpl + padding) * store_lines)
5268de959fSMauro Carvalho Chehab / PAGE_SIZE + store_lines) * 8;
5368de959fSMauro Carvalho Chehab instructions += 2 * 8;
5468de959fSMauro Carvalho Chehab if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
5568de959fSMauro Carvalho Chehab return rc;
5668de959fSMauro Carvalho Chehab
5768de959fSMauro Carvalho Chehab /* sync instruction */
5868de959fSMauro Carvalho Chehab rp = risc->cpu;
5968de959fSMauro Carvalho Chehab *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
6068de959fSMauro Carvalho Chehab *(rp++) = cpu_to_le32(0);
6168de959fSMauro Carvalho Chehab
6268de959fSMauro Carvalho Chehab while (skip_lines-- > 0) {
6368de959fSMauro Carvalho Chehab *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
6468de959fSMauro Carvalho Chehab BT848_RISC_EOL | bpl);
6568de959fSMauro Carvalho Chehab }
6668de959fSMauro Carvalho Chehab
6768de959fSMauro Carvalho Chehab /* scan lines */
6868de959fSMauro Carvalho Chehab sg = sglist;
6968de959fSMauro Carvalho Chehab for (line = 0; line < store_lines; line++) {
70b7ec3212SDeborah Brouwer if ((line >= (store_lines - VCR_HACK_LINES)) &&
71*861ab817SHans Verkuil btv->opt_vcr_hack)
7268de959fSMauro Carvalho Chehab continue;
7368de959fSMauro Carvalho Chehab while (offset && offset >= sg_dma_len(sg)) {
7468de959fSMauro Carvalho Chehab offset -= sg_dma_len(sg);
75872dfcfeSHans Verkuil sg = sg_next(sg);
7668de959fSMauro Carvalho Chehab }
7768de959fSMauro Carvalho Chehab if (bpl <= sg_dma_len(sg)-offset) {
7868de959fSMauro Carvalho Chehab /* fits into current chunk */
7968de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
8068de959fSMauro Carvalho Chehab BT848_RISC_EOL|bpl);
8168de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
8268de959fSMauro Carvalho Chehab offset+=bpl;
8368de959fSMauro Carvalho Chehab } else {
8416790554SMauro Carvalho Chehab /* scanline needs to be split */
8568de959fSMauro Carvalho Chehab todo = bpl;
8668de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
8768de959fSMauro Carvalho Chehab (sg_dma_len(sg)-offset));
8868de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
8968de959fSMauro Carvalho Chehab todo -= (sg_dma_len(sg)-offset);
9068de959fSMauro Carvalho Chehab offset = 0;
91872dfcfeSHans Verkuil sg = sg_next(sg);
9268de959fSMauro Carvalho Chehab while (todo > sg_dma_len(sg)) {
9368de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
9468de959fSMauro Carvalho Chehab sg_dma_len(sg));
9568de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(sg));
9668de959fSMauro Carvalho Chehab todo -= sg_dma_len(sg);
97872dfcfeSHans Verkuil sg = sg_next(sg);
9868de959fSMauro Carvalho Chehab }
9968de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
10068de959fSMauro Carvalho Chehab todo);
10168de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(sg));
10268de959fSMauro Carvalho Chehab offset += todo;
10368de959fSMauro Carvalho Chehab }
10468de959fSMauro Carvalho Chehab offset += padding;
10568de959fSMauro Carvalho Chehab }
10668de959fSMauro Carvalho Chehab
10768de959fSMauro Carvalho Chehab /* save pointer to jmp instruction address */
10868de959fSMauro Carvalho Chehab risc->jmp = rp;
109615c5450SDeborah Brouwer WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
11068de959fSMauro Carvalho Chehab return 0;
11168de959fSMauro Carvalho Chehab }
11268de959fSMauro Carvalho Chehab
11368de959fSMauro Carvalho Chehab static int
bttv_risc_planar(struct bttv * btv,struct btcx_riscmem * risc,struct scatterlist * sglist,unsigned int yoffset,unsigned int ybpl,unsigned int ypadding,unsigned int ylines,unsigned int uoffset,unsigned int voffset,unsigned int hshift,unsigned int vshift,unsigned int cpadding)11468de959fSMauro Carvalho Chehab bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
11568de959fSMauro Carvalho Chehab struct scatterlist *sglist,
11668de959fSMauro Carvalho Chehab unsigned int yoffset, unsigned int ybpl,
11768de959fSMauro Carvalho Chehab unsigned int ypadding, unsigned int ylines,
11868de959fSMauro Carvalho Chehab unsigned int uoffset, unsigned int voffset,
11968de959fSMauro Carvalho Chehab unsigned int hshift, unsigned int vshift,
12068de959fSMauro Carvalho Chehab unsigned int cpadding)
12168de959fSMauro Carvalho Chehab {
12268de959fSMauro Carvalho Chehab unsigned int instructions,line,todo,ylen,chroma;
12368de959fSMauro Carvalho Chehab __le32 *rp;
12468de959fSMauro Carvalho Chehab u32 ri;
12568de959fSMauro Carvalho Chehab struct scatterlist *ysg;
12668de959fSMauro Carvalho Chehab struct scatterlist *usg;
12768de959fSMauro Carvalho Chehab struct scatterlist *vsg;
12868de959fSMauro Carvalho Chehab int topfield = (0 == yoffset);
12968de959fSMauro Carvalho Chehab int rc;
13068de959fSMauro Carvalho Chehab
13168de959fSMauro Carvalho Chehab /* estimate risc mem: worst case is one write per page border +
13268de959fSMauro Carvalho Chehab one write per scan line (5 dwords)
13368de959fSMauro Carvalho Chehab plus sync + jump (2 dwords) */
13468de959fSMauro Carvalho Chehab instructions = ((3 + (ybpl + ypadding) * ylines * 2)
13568de959fSMauro Carvalho Chehab / PAGE_SIZE) + ylines;
13668de959fSMauro Carvalho Chehab instructions += 2;
13768de959fSMauro Carvalho Chehab if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
13868de959fSMauro Carvalho Chehab return rc;
13968de959fSMauro Carvalho Chehab
14068de959fSMauro Carvalho Chehab /* sync instruction */
14168de959fSMauro Carvalho Chehab rp = risc->cpu;
14268de959fSMauro Carvalho Chehab *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
14368de959fSMauro Carvalho Chehab *(rp++) = cpu_to_le32(0);
14468de959fSMauro Carvalho Chehab
14568de959fSMauro Carvalho Chehab /* scan lines */
14668de959fSMauro Carvalho Chehab ysg = sglist;
14768de959fSMauro Carvalho Chehab usg = sglist;
14868de959fSMauro Carvalho Chehab vsg = sglist;
14968de959fSMauro Carvalho Chehab for (line = 0; line < ylines; line++) {
15068de959fSMauro Carvalho Chehab if ((btv->opt_vcr_hack) &&
15168de959fSMauro Carvalho Chehab (line >= (ylines - VCR_HACK_LINES)))
15268de959fSMauro Carvalho Chehab continue;
15368de959fSMauro Carvalho Chehab switch (vshift) {
15468de959fSMauro Carvalho Chehab case 0:
15568de959fSMauro Carvalho Chehab chroma = 1;
15668de959fSMauro Carvalho Chehab break;
15768de959fSMauro Carvalho Chehab case 1:
15868de959fSMauro Carvalho Chehab if (topfield)
15968de959fSMauro Carvalho Chehab chroma = ((line & 1) == 0);
16068de959fSMauro Carvalho Chehab else
16168de959fSMauro Carvalho Chehab chroma = ((line & 1) == 1);
16268de959fSMauro Carvalho Chehab break;
16368de959fSMauro Carvalho Chehab case 2:
16468de959fSMauro Carvalho Chehab if (topfield)
16568de959fSMauro Carvalho Chehab chroma = ((line & 3) == 0);
16668de959fSMauro Carvalho Chehab else
16768de959fSMauro Carvalho Chehab chroma = ((line & 3) == 2);
16868de959fSMauro Carvalho Chehab break;
16968de959fSMauro Carvalho Chehab default:
17068de959fSMauro Carvalho Chehab chroma = 0;
17168de959fSMauro Carvalho Chehab break;
17268de959fSMauro Carvalho Chehab }
17368de959fSMauro Carvalho Chehab
17468de959fSMauro Carvalho Chehab for (todo = ybpl; todo > 0; todo -= ylen) {
17568de959fSMauro Carvalho Chehab /* go to next sg entry if needed */
17668de959fSMauro Carvalho Chehab while (yoffset && yoffset >= sg_dma_len(ysg)) {
17768de959fSMauro Carvalho Chehab yoffset -= sg_dma_len(ysg);
178872dfcfeSHans Verkuil ysg = sg_next(ysg);
17968de959fSMauro Carvalho Chehab }
1806f7e780bSSamuel Williams
1816f7e780bSSamuel Williams /* calculate max number of bytes we can write */
1826f7e780bSSamuel Williams ylen = todo;
1836f7e780bSSamuel Williams if (yoffset + ylen > sg_dma_len(ysg))
1846f7e780bSSamuel Williams ylen = sg_dma_len(ysg) - yoffset;
1856f7e780bSSamuel Williams if (chroma) {
18668de959fSMauro Carvalho Chehab while (uoffset && uoffset >= sg_dma_len(usg)) {
18768de959fSMauro Carvalho Chehab uoffset -= sg_dma_len(usg);
188872dfcfeSHans Verkuil usg = sg_next(usg);
18968de959fSMauro Carvalho Chehab }
19068de959fSMauro Carvalho Chehab while (voffset && voffset >= sg_dma_len(vsg)) {
19168de959fSMauro Carvalho Chehab voffset -= sg_dma_len(vsg);
192872dfcfeSHans Verkuil vsg = sg_next(vsg);
19368de959fSMauro Carvalho Chehab }
19468de959fSMauro Carvalho Chehab
19568de959fSMauro Carvalho Chehab if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
19668de959fSMauro Carvalho Chehab ylen = (sg_dma_len(usg) - uoffset) << hshift;
19768de959fSMauro Carvalho Chehab if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
19868de959fSMauro Carvalho Chehab ylen = (sg_dma_len(vsg) - voffset) << hshift;
19968de959fSMauro Carvalho Chehab ri = BT848_RISC_WRITE123;
20068de959fSMauro Carvalho Chehab } else {
20168de959fSMauro Carvalho Chehab ri = BT848_RISC_WRITE1S23;
20268de959fSMauro Carvalho Chehab }
20368de959fSMauro Carvalho Chehab if (ybpl == todo)
20468de959fSMauro Carvalho Chehab ri |= BT848_RISC_SOL;
20568de959fSMauro Carvalho Chehab if (ylen == todo)
20668de959fSMauro Carvalho Chehab ri |= BT848_RISC_EOL;
20768de959fSMauro Carvalho Chehab
20868de959fSMauro Carvalho Chehab /* write risc instruction */
20968de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(ri | ylen);
21068de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
21168de959fSMauro Carvalho Chehab (ylen >> hshift));
21268de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
21368de959fSMauro Carvalho Chehab yoffset += ylen;
21468de959fSMauro Carvalho Chehab if (chroma) {
21568de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
21668de959fSMauro Carvalho Chehab uoffset += ylen >> hshift;
21768de959fSMauro Carvalho Chehab *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
21868de959fSMauro Carvalho Chehab voffset += ylen >> hshift;
21968de959fSMauro Carvalho Chehab }
22068de959fSMauro Carvalho Chehab }
22168de959fSMauro Carvalho Chehab yoffset += ypadding;
22268de959fSMauro Carvalho Chehab if (chroma) {
22368de959fSMauro Carvalho Chehab uoffset += cpadding;
22468de959fSMauro Carvalho Chehab voffset += cpadding;
22568de959fSMauro Carvalho Chehab }
22668de959fSMauro Carvalho Chehab }
22768de959fSMauro Carvalho Chehab
22868de959fSMauro Carvalho Chehab /* save pointer to jmp instruction address */
22968de959fSMauro Carvalho Chehab risc->jmp = rp;
230615c5450SDeborah Brouwer WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
23168de959fSMauro Carvalho Chehab return 0;
23268de959fSMauro Carvalho Chehab }
23368de959fSMauro Carvalho Chehab
23468de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
23568de959fSMauro Carvalho Chehab
23668de959fSMauro Carvalho Chehab static void
bttv_calc_geo_old(struct bttv * btv,struct bttv_geometry * geo,int width,int height,int interleaved,const struct bttv_tvnorm * tvnorm)23768de959fSMauro Carvalho Chehab bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
23868de959fSMauro Carvalho Chehab int width, int height, int interleaved,
23968de959fSMauro Carvalho Chehab const struct bttv_tvnorm *tvnorm)
24068de959fSMauro Carvalho Chehab {
24168de959fSMauro Carvalho Chehab u32 xsf, sr;
24268de959fSMauro Carvalho Chehab int vdelay;
24368de959fSMauro Carvalho Chehab
24468de959fSMauro Carvalho Chehab int swidth = tvnorm->swidth;
24568de959fSMauro Carvalho Chehab int totalwidth = tvnorm->totalwidth;
24668de959fSMauro Carvalho Chehab int scaledtwidth = tvnorm->scaledtwidth;
24768de959fSMauro Carvalho Chehab
24868de959fSMauro Carvalho Chehab if (btv->input == btv->dig) {
24968de959fSMauro Carvalho Chehab swidth = 720;
25068de959fSMauro Carvalho Chehab totalwidth = 858;
25168de959fSMauro Carvalho Chehab scaledtwidth = 858;
25268de959fSMauro Carvalho Chehab }
25368de959fSMauro Carvalho Chehab
25468de959fSMauro Carvalho Chehab vdelay = tvnorm->vdelay;
25568de959fSMauro Carvalho Chehab
25668de959fSMauro Carvalho Chehab xsf = (width*scaledtwidth)/swidth;
25768de959fSMauro Carvalho Chehab geo->hscale = ((totalwidth*4096UL)/xsf-4096);
25868de959fSMauro Carvalho Chehab geo->hdelay = tvnorm->hdelayx1;
25968de959fSMauro Carvalho Chehab geo->hdelay = (geo->hdelay*width)/swidth;
26068de959fSMauro Carvalho Chehab geo->hdelay &= 0x3fe;
26168de959fSMauro Carvalho Chehab sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
26268de959fSMauro Carvalho Chehab geo->vscale = (0x10000UL-sr) & 0x1fff;
26368de959fSMauro Carvalho Chehab geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
26468de959fSMauro Carvalho Chehab ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
26568de959fSMauro Carvalho Chehab geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
26668de959fSMauro Carvalho Chehab geo->vdelay = vdelay;
26768de959fSMauro Carvalho Chehab geo->width = width;
26868de959fSMauro Carvalho Chehab geo->sheight = tvnorm->sheight;
26968de959fSMauro Carvalho Chehab geo->vtotal = tvnorm->vtotal;
27068de959fSMauro Carvalho Chehab
27168de959fSMauro Carvalho Chehab if (btv->opt_combfilter) {
27268de959fSMauro Carvalho Chehab geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
27368de959fSMauro Carvalho Chehab geo->comb = (width < 769) ? 1 : 0;
27468de959fSMauro Carvalho Chehab } else {
27568de959fSMauro Carvalho Chehab geo->vtc = 0;
27668de959fSMauro Carvalho Chehab geo->comb = 0;
27768de959fSMauro Carvalho Chehab }
27868de959fSMauro Carvalho Chehab }
27968de959fSMauro Carvalho Chehab
28068de959fSMauro Carvalho Chehab static void
bttv_calc_geo(struct bttv * btv,struct bttv_geometry * geo,unsigned int width,unsigned int height,int both_fields,const struct bttv_tvnorm * tvnorm,const struct v4l2_rect * crop)28168de959fSMauro Carvalho Chehab bttv_calc_geo (struct bttv * btv,
28268de959fSMauro Carvalho Chehab struct bttv_geometry * geo,
28368de959fSMauro Carvalho Chehab unsigned int width,
28468de959fSMauro Carvalho Chehab unsigned int height,
28568de959fSMauro Carvalho Chehab int both_fields,
28668de959fSMauro Carvalho Chehab const struct bttv_tvnorm * tvnorm,
28768de959fSMauro Carvalho Chehab const struct v4l2_rect * crop)
28868de959fSMauro Carvalho Chehab {
28968de959fSMauro Carvalho Chehab unsigned int c_width;
29068de959fSMauro Carvalho Chehab unsigned int c_height;
29168de959fSMauro Carvalho Chehab u32 sr;
29268de959fSMauro Carvalho Chehab
29368de959fSMauro Carvalho Chehab if ((crop->left == tvnorm->cropcap.defrect.left
29468de959fSMauro Carvalho Chehab && crop->top == tvnorm->cropcap.defrect.top
29568de959fSMauro Carvalho Chehab && crop->width == tvnorm->cropcap.defrect.width
29668de959fSMauro Carvalho Chehab && crop->height == tvnorm->cropcap.defrect.height
29768de959fSMauro Carvalho Chehab && width <= tvnorm->swidth /* see PAL-Nc et al */)
29868de959fSMauro Carvalho Chehab || btv->input == btv->dig) {
29968de959fSMauro Carvalho Chehab bttv_calc_geo_old(btv, geo, width, height,
30068de959fSMauro Carvalho Chehab both_fields, tvnorm);
30168de959fSMauro Carvalho Chehab return;
30268de959fSMauro Carvalho Chehab }
30368de959fSMauro Carvalho Chehab
30468de959fSMauro Carvalho Chehab /* For bug compatibility the image size checks permit scale
30568de959fSMauro Carvalho Chehab factors > 16. See bttv_crop_calc_limits(). */
30668de959fSMauro Carvalho Chehab c_width = min((unsigned int) crop->width, width * 16);
30768de959fSMauro Carvalho Chehab c_height = min((unsigned int) crop->height, height * 16);
30868de959fSMauro Carvalho Chehab
30968de959fSMauro Carvalho Chehab geo->width = width;
31068de959fSMauro Carvalho Chehab geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
31168de959fSMauro Carvalho Chehab /* Even to store Cb first, odd for Cr. */
31268de959fSMauro Carvalho Chehab geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
31368de959fSMauro Carvalho Chehab
31468de959fSMauro Carvalho Chehab geo->sheight = c_height;
31568de959fSMauro Carvalho Chehab geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
31668de959fSMauro Carvalho Chehab sr = c_height >> !both_fields;
31768de959fSMauro Carvalho Chehab sr = (sr * 512U + (height >> 1)) / height - 512;
31868de959fSMauro Carvalho Chehab geo->vscale = (0x10000UL - sr) & 0x1fff;
31968de959fSMauro Carvalho Chehab geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
32068de959fSMauro Carvalho Chehab geo->vtotal = tvnorm->vtotal;
32168de959fSMauro Carvalho Chehab
32268de959fSMauro Carvalho Chehab geo->crop = (((geo->width >> 8) & 0x03) |
32368de959fSMauro Carvalho Chehab ((geo->hdelay >> 6) & 0x0c) |
32468de959fSMauro Carvalho Chehab ((geo->sheight >> 4) & 0x30) |
32568de959fSMauro Carvalho Chehab ((geo->vdelay >> 2) & 0xc0));
32668de959fSMauro Carvalho Chehab
32768de959fSMauro Carvalho Chehab if (btv->opt_combfilter) {
32868de959fSMauro Carvalho Chehab geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
32968de959fSMauro Carvalho Chehab geo->comb = (width < 769) ? 1 : 0;
33068de959fSMauro Carvalho Chehab } else {
33168de959fSMauro Carvalho Chehab geo->vtc = 0;
33268de959fSMauro Carvalho Chehab geo->comb = 0;
33368de959fSMauro Carvalho Chehab }
33468de959fSMauro Carvalho Chehab }
33568de959fSMauro Carvalho Chehab
33668de959fSMauro Carvalho Chehab static void
bttv_apply_geo(struct bttv * btv,struct bttv_geometry * geo,int odd)33768de959fSMauro Carvalho Chehab bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
33868de959fSMauro Carvalho Chehab {
33968de959fSMauro Carvalho Chehab int off = odd ? 0x80 : 0x00;
34068de959fSMauro Carvalho Chehab
34168de959fSMauro Carvalho Chehab if (geo->comb)
34268de959fSMauro Carvalho Chehab btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
34368de959fSMauro Carvalho Chehab else
34468de959fSMauro Carvalho Chehab btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
34568de959fSMauro Carvalho Chehab
34668de959fSMauro Carvalho Chehab btwrite(geo->vtc, BT848_E_VTC+off);
34768de959fSMauro Carvalho Chehab btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
34868de959fSMauro Carvalho Chehab btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
34968de959fSMauro Carvalho Chehab btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
35068de959fSMauro Carvalho Chehab btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
35168de959fSMauro Carvalho Chehab btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
35268de959fSMauro Carvalho Chehab btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
35368de959fSMauro Carvalho Chehab btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
35468de959fSMauro Carvalho Chehab btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
35568de959fSMauro Carvalho Chehab btwrite(geo->crop, BT848_E_CROP+off);
35668de959fSMauro Carvalho Chehab btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
35768de959fSMauro Carvalho Chehab btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
35868de959fSMauro Carvalho Chehab }
35968de959fSMauro Carvalho Chehab
36068de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
36168de959fSMauro Carvalho Chehab /* risc group / risc main loop / dma management */
36268de959fSMauro Carvalho Chehab
bttv_set_risc_status(struct bttv * btv)3637df8d5cfSDeborah Brouwer static void bttv_set_risc_status(struct bttv *btv)
36468de959fSMauro Carvalho Chehab {
3657df8d5cfSDeborah Brouwer unsigned long cmd = BT848_RISC_JUMP;
3667df8d5cfSDeborah Brouwer if (btv->loop_irq) {
3677df8d5cfSDeborah Brouwer cmd |= BT848_RISC_IRQ;
3687df8d5cfSDeborah Brouwer cmd |= (btv->loop_irq & 0x0f) << 16;
3697df8d5cfSDeborah Brouwer cmd |= (~btv->loop_irq & 0x0f) << 20;
3707df8d5cfSDeborah Brouwer }
3717df8d5cfSDeborah Brouwer btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
3727df8d5cfSDeborah Brouwer }
37368de959fSMauro Carvalho Chehab
bttv_set_irq_timer(struct bttv * btv)3747df8d5cfSDeborah Brouwer static void bttv_set_irq_timer(struct bttv *btv)
3757df8d5cfSDeborah Brouwer {
3767df8d5cfSDeborah Brouwer if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
3777df8d5cfSDeborah Brouwer mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
3787df8d5cfSDeborah Brouwer else
3797df8d5cfSDeborah Brouwer del_timer(&btv->timeout);
3807df8d5cfSDeborah Brouwer }
38168de959fSMauro Carvalho Chehab
bttv_set_capture_control(struct bttv * btv,int start_capture)3827df8d5cfSDeborah Brouwer static int bttv_set_capture_control(struct bttv *btv, int start_capture)
3837df8d5cfSDeborah Brouwer {
3847df8d5cfSDeborah Brouwer int capctl = 0;
3857df8d5cfSDeborah Brouwer
3867df8d5cfSDeborah Brouwer if (btv->curr.top || btv->curr.bottom)
3877df8d5cfSDeborah Brouwer capctl = BT848_CAP_CTL_CAPTURE_ODD |
3887df8d5cfSDeborah Brouwer BT848_CAP_CTL_CAPTURE_EVEN;
3897df8d5cfSDeborah Brouwer
3907df8d5cfSDeborah Brouwer if (btv->cvbi)
3917df8d5cfSDeborah Brouwer capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
3927df8d5cfSDeborah Brouwer BT848_CAP_CTL_CAPTURE_VBI_EVEN;
3937df8d5cfSDeborah Brouwer
3947df8d5cfSDeborah Brouwer capctl |= start_capture;
3957df8d5cfSDeborah Brouwer
3967df8d5cfSDeborah Brouwer btaor(capctl, ~0x0f, BT848_CAP_CTL);
3977df8d5cfSDeborah Brouwer
3987df8d5cfSDeborah Brouwer return capctl;
3997df8d5cfSDeborah Brouwer }
4007df8d5cfSDeborah Brouwer
bttv_start_dma(struct bttv * btv)4017df8d5cfSDeborah Brouwer static void bttv_start_dma(struct bttv *btv)
4027df8d5cfSDeborah Brouwer {
4037df8d5cfSDeborah Brouwer if (btv->dma_on)
4047df8d5cfSDeborah Brouwer return;
4057df8d5cfSDeborah Brouwer btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
406b7ec3212SDeborah Brouwer btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
407b7ec3212SDeborah Brouwer BT848_GPIO_DMA_CTL);
4087df8d5cfSDeborah Brouwer btv->dma_on = 1;
4097df8d5cfSDeborah Brouwer }
4107df8d5cfSDeborah Brouwer
bttv_stop_dma(struct bttv * btv)4117df8d5cfSDeborah Brouwer static void bttv_stop_dma(struct bttv *btv)
4127df8d5cfSDeborah Brouwer {
4137df8d5cfSDeborah Brouwer if (!btv->dma_on)
4147df8d5cfSDeborah Brouwer return;
415b7ec3212SDeborah Brouwer btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
416b7ec3212SDeborah Brouwer BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
4177df8d5cfSDeborah Brouwer btv->dma_on = 0;
4187df8d5cfSDeborah Brouwer }
4197df8d5cfSDeborah Brouwer
bttv_set_dma(struct bttv * btv,int start_capture)4207df8d5cfSDeborah Brouwer void bttv_set_dma(struct bttv *btv, int start_capture)
4217df8d5cfSDeborah Brouwer {
4227df8d5cfSDeborah Brouwer int capctl = 0;
4237df8d5cfSDeborah Brouwer
4247df8d5cfSDeborah Brouwer bttv_set_risc_status(btv);
4257df8d5cfSDeborah Brouwer bttv_set_irq_timer(btv);
4267df8d5cfSDeborah Brouwer capctl = bttv_set_capture_control(btv, start_capture);
4277df8d5cfSDeborah Brouwer
4287df8d5cfSDeborah Brouwer if (capctl)
4297df8d5cfSDeborah Brouwer bttv_start_dma(btv);
4307df8d5cfSDeborah Brouwer else
4317df8d5cfSDeborah Brouwer bttv_stop_dma(btv);
43268de959fSMauro Carvalho Chehab
43368de959fSMauro Carvalho Chehab d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
43468de959fSMauro Carvalho Chehab btv->c.nr,capctl,btv->loop_irq,
43568de959fSMauro Carvalho Chehab btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
43668de959fSMauro Carvalho Chehab btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
43768de959fSMauro Carvalho Chehab btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
43868de959fSMauro Carvalho Chehab btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
43968de959fSMauro Carvalho Chehab }
44068de959fSMauro Carvalho Chehab
44168de959fSMauro Carvalho Chehab int
bttv_risc_init_main(struct bttv * btv)44268de959fSMauro Carvalho Chehab bttv_risc_init_main(struct bttv *btv)
44368de959fSMauro Carvalho Chehab {
44468de959fSMauro Carvalho Chehab int rc;
44568de959fSMauro Carvalho Chehab
44668de959fSMauro Carvalho Chehab if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
44768de959fSMauro Carvalho Chehab return rc;
44868de959fSMauro Carvalho Chehab dprintk("%d: risc main @ %08llx\n",
44968de959fSMauro Carvalho Chehab btv->c.nr, (unsigned long long)btv->main.dma);
45068de959fSMauro Carvalho Chehab
45168de959fSMauro Carvalho Chehab btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
45268de959fSMauro Carvalho Chehab BT848_FIFO_STATUS_VRE);
45368de959fSMauro Carvalho Chehab btv->main.cpu[1] = cpu_to_le32(0);
45468de959fSMauro Carvalho Chehab btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
45568de959fSMauro Carvalho Chehab btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
45668de959fSMauro Carvalho Chehab
45768de959fSMauro Carvalho Chehab /* top field */
45868de959fSMauro Carvalho Chehab btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
45968de959fSMauro Carvalho Chehab btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
46068de959fSMauro Carvalho Chehab btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
46168de959fSMauro Carvalho Chehab btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
46268de959fSMauro Carvalho Chehab
46368de959fSMauro Carvalho Chehab btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
46468de959fSMauro Carvalho Chehab BT848_FIFO_STATUS_VRO);
46568de959fSMauro Carvalho Chehab btv->main.cpu[9] = cpu_to_le32(0);
46668de959fSMauro Carvalho Chehab
46768de959fSMauro Carvalho Chehab /* bottom field */
46868de959fSMauro Carvalho Chehab btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
46968de959fSMauro Carvalho Chehab btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
47068de959fSMauro Carvalho Chehab btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
47168de959fSMauro Carvalho Chehab btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
47268de959fSMauro Carvalho Chehab
47368de959fSMauro Carvalho Chehab /* jump back to top field */
47468de959fSMauro Carvalho Chehab btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
47568de959fSMauro Carvalho Chehab btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
47668de959fSMauro Carvalho Chehab
47768de959fSMauro Carvalho Chehab return 0;
47868de959fSMauro Carvalho Chehab }
47968de959fSMauro Carvalho Chehab
48068de959fSMauro Carvalho Chehab int
bttv_risc_hook(struct bttv * btv,int slot,struct btcx_riscmem * risc,int irqflags)48168de959fSMauro Carvalho Chehab bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
48268de959fSMauro Carvalho Chehab int irqflags)
48368de959fSMauro Carvalho Chehab {
48468de959fSMauro Carvalho Chehab unsigned long cmd;
48568de959fSMauro Carvalho Chehab unsigned long next = btv->main.dma + ((slot+2) << 2);
48668de959fSMauro Carvalho Chehab
48768de959fSMauro Carvalho Chehab if (NULL == risc) {
48868de959fSMauro Carvalho Chehab d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
48968de959fSMauro Carvalho Chehab btv->main.cpu[slot+1] = cpu_to_le32(next);
49068de959fSMauro Carvalho Chehab } else {
49168de959fSMauro Carvalho Chehab d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
49268de959fSMauro Carvalho Chehab btv->c.nr, risc, slot,
49368de959fSMauro Carvalho Chehab (unsigned long long)risc->dma, irqflags);
49468de959fSMauro Carvalho Chehab cmd = BT848_RISC_JUMP;
49568de959fSMauro Carvalho Chehab if (irqflags) {
49668de959fSMauro Carvalho Chehab cmd |= BT848_RISC_IRQ;
49768de959fSMauro Carvalho Chehab cmd |= (irqflags & 0x0f) << 16;
49868de959fSMauro Carvalho Chehab cmd |= (~irqflags & 0x0f) << 20;
49968de959fSMauro Carvalho Chehab }
50068de959fSMauro Carvalho Chehab risc->jmp[0] = cpu_to_le32(cmd);
50168de959fSMauro Carvalho Chehab risc->jmp[1] = cpu_to_le32(next);
50268de959fSMauro Carvalho Chehab btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
50368de959fSMauro Carvalho Chehab }
50468de959fSMauro Carvalho Chehab return 0;
50568de959fSMauro Carvalho Chehab }
50668de959fSMauro Carvalho Chehab
bttv_buffer_risc_vbi(struct bttv * btv,struct bttv_buffer * buf)507b7ec3212SDeborah Brouwer int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
50868de959fSMauro Carvalho Chehab {
509b7ec3212SDeborah Brouwer int r = 0;
510b7ec3212SDeborah Brouwer unsigned int offset;
511b7ec3212SDeborah Brouwer unsigned int bpl = 2044; /* max. vbipack */
512b7ec3212SDeborah Brouwer unsigned int padding = VBI_BPL - bpl;
513b7ec3212SDeborah Brouwer unsigned int skip_lines0 = 0;
514b7ec3212SDeborah Brouwer unsigned int skip_lines1 = 0;
515b7ec3212SDeborah Brouwer unsigned int min_vdelay = MIN_VDELAY;
51668de959fSMauro Carvalho Chehab
517b7ec3212SDeborah Brouwer const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
518b7ec3212SDeborah Brouwer struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
519b7ec3212SDeborah Brouwer struct scatterlist *list = sgt->sgl;
520b7ec3212SDeborah Brouwer
521b7ec3212SDeborah Brouwer if (btv->vbi_fmt.fmt.count[0] > 0)
522b7ec3212SDeborah Brouwer skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
523b7ec3212SDeborah Brouwer tvnorm->vbistart[0]));
524b7ec3212SDeborah Brouwer if (btv->vbi_fmt.fmt.count[1] > 0)
525b7ec3212SDeborah Brouwer skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
526b7ec3212SDeborah Brouwer tvnorm->vbistart[1]));
527b7ec3212SDeborah Brouwer
528b7ec3212SDeborah Brouwer if (btv->vbi_fmt.fmt.count[0] > 0) {
529b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
530b7ec3212SDeborah Brouwer skip_lines0, btv->vbi_fmt.fmt.count[0]);
531b7ec3212SDeborah Brouwer if (r)
532b7ec3212SDeborah Brouwer return r;
533b7ec3212SDeborah Brouwer }
534b7ec3212SDeborah Brouwer
535b7ec3212SDeborah Brouwer if (btv->vbi_fmt.fmt.count[1] > 0) {
536b7ec3212SDeborah Brouwer offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
537b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
538b7ec3212SDeborah Brouwer padding, skip_lines1,
539b7ec3212SDeborah Brouwer btv->vbi_fmt.fmt.count[1]);
540b7ec3212SDeborah Brouwer if (r)
541b7ec3212SDeborah Brouwer return r;
542b7ec3212SDeborah Brouwer }
543b7ec3212SDeborah Brouwer
544b7ec3212SDeborah Brouwer if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
545b7ec3212SDeborah Brouwer min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
546b7ec3212SDeborah Brouwer
547b7ec3212SDeborah Brouwer /* For bttv_buffer_activate_vbi(). */
548b7ec3212SDeborah Brouwer buf->geo.vdelay = min_vdelay;
549b7ec3212SDeborah Brouwer
550b7ec3212SDeborah Brouwer return r;
55168de959fSMauro Carvalho Chehab }
55268de959fSMauro Carvalho Chehab
55368de959fSMauro Carvalho Chehab int
bttv_buffer_activate_vbi(struct bttv * btv,struct bttv_buffer * vbi)55468de959fSMauro Carvalho Chehab bttv_buffer_activate_vbi(struct bttv *btv,
55568de959fSMauro Carvalho Chehab struct bttv_buffer *vbi)
55668de959fSMauro Carvalho Chehab {
55768de959fSMauro Carvalho Chehab struct btcx_riscmem *top;
55868de959fSMauro Carvalho Chehab struct btcx_riscmem *bottom;
55968de959fSMauro Carvalho Chehab int top_irq_flags;
56068de959fSMauro Carvalho Chehab int bottom_irq_flags;
56168de959fSMauro Carvalho Chehab
56268de959fSMauro Carvalho Chehab top = NULL;
56368de959fSMauro Carvalho Chehab bottom = NULL;
56468de959fSMauro Carvalho Chehab top_irq_flags = 0;
56568de959fSMauro Carvalho Chehab bottom_irq_flags = 0;
56668de959fSMauro Carvalho Chehab
56768de959fSMauro Carvalho Chehab if (vbi) {
56868de959fSMauro Carvalho Chehab unsigned int crop, vdelay;
56968de959fSMauro Carvalho Chehab
570b7ec3212SDeborah Brouwer list_del(&vbi->list);
57168de959fSMauro Carvalho Chehab
57268de959fSMauro Carvalho Chehab /* VDELAY is start of video, end of VBI capturing. */
57368de959fSMauro Carvalho Chehab crop = btread(BT848_E_CROP);
57468de959fSMauro Carvalho Chehab vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
57568de959fSMauro Carvalho Chehab
57668de959fSMauro Carvalho Chehab if (vbi->geo.vdelay > vdelay) {
57768de959fSMauro Carvalho Chehab vdelay = vbi->geo.vdelay & 0xfe;
57868de959fSMauro Carvalho Chehab crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
57968de959fSMauro Carvalho Chehab
58068de959fSMauro Carvalho Chehab btwrite(vdelay, BT848_E_VDELAY_LO);
58168de959fSMauro Carvalho Chehab btwrite(crop, BT848_E_CROP);
58268de959fSMauro Carvalho Chehab btwrite(vdelay, BT848_O_VDELAY_LO);
58368de959fSMauro Carvalho Chehab btwrite(crop, BT848_O_CROP);
58468de959fSMauro Carvalho Chehab }
58568de959fSMauro Carvalho Chehab
586c9c0df31SDeborah Brouwer if (btv->vbi_count[0] > 0) {
58768de959fSMauro Carvalho Chehab top = &vbi->top;
58868de959fSMauro Carvalho Chehab top_irq_flags = 4;
58968de959fSMauro Carvalho Chehab }
59068de959fSMauro Carvalho Chehab
591c9c0df31SDeborah Brouwer if (btv->vbi_count[1] > 0) {
59268de959fSMauro Carvalho Chehab top_irq_flags = 0;
59368de959fSMauro Carvalho Chehab bottom = &vbi->bottom;
59468de959fSMauro Carvalho Chehab bottom_irq_flags = 4;
59568de959fSMauro Carvalho Chehab }
59668de959fSMauro Carvalho Chehab }
59768de959fSMauro Carvalho Chehab
59868de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
59968de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
60068de959fSMauro Carvalho Chehab
60168de959fSMauro Carvalho Chehab return 0;
60268de959fSMauro Carvalho Chehab }
60368de959fSMauro Carvalho Chehab
60468de959fSMauro Carvalho Chehab int
bttv_buffer_activate_video(struct bttv * btv,struct bttv_buffer_set * set)60568de959fSMauro Carvalho Chehab bttv_buffer_activate_video(struct bttv *btv,
60668de959fSMauro Carvalho Chehab struct bttv_buffer_set *set)
60768de959fSMauro Carvalho Chehab {
60868de959fSMauro Carvalho Chehab /* video capture */
60968de959fSMauro Carvalho Chehab if (NULL != set->top && NULL != set->bottom) {
61068de959fSMauro Carvalho Chehab if (set->top == set->bottom) {
611b7ec3212SDeborah Brouwer if (set->top->list.next)
612b7ec3212SDeborah Brouwer list_del(&set->top->list);
61368de959fSMauro Carvalho Chehab } else {
614b7ec3212SDeborah Brouwer if (set->top->list.next)
615b7ec3212SDeborah Brouwer list_del(&set->top->list);
616b7ec3212SDeborah Brouwer if (set->bottom->list.next)
617b7ec3212SDeborah Brouwer list_del(&set->bottom->list);
61868de959fSMauro Carvalho Chehab }
61968de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->top->geo, 1);
62068de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->bottom->geo,0);
62168de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
62268de959fSMauro Carvalho Chehab set->top_irq);
62368de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
62468de959fSMauro Carvalho Chehab set->frame_irq);
62568de959fSMauro Carvalho Chehab btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
62668de959fSMauro Carvalho Chehab ~0xff, BT848_COLOR_FMT);
62768de959fSMauro Carvalho Chehab btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
62868de959fSMauro Carvalho Chehab ~0x0f, BT848_COLOR_CTL);
62968de959fSMauro Carvalho Chehab } else if (NULL != set->top) {
630b7ec3212SDeborah Brouwer if (set->top->list.next)
631b7ec3212SDeborah Brouwer list_del(&set->top->list);
63268de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->top->geo,1);
63368de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->top->geo,0);
63468de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
63568de959fSMauro Carvalho Chehab set->frame_irq);
63668de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
63768de959fSMauro Carvalho Chehab btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
63868de959fSMauro Carvalho Chehab btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
63968de959fSMauro Carvalho Chehab } else if (NULL != set->bottom) {
640b7ec3212SDeborah Brouwer if (set->bottom->list.next)
641b7ec3212SDeborah Brouwer list_del(&set->bottom->list);
64268de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->bottom->geo,1);
64368de959fSMauro Carvalho Chehab bttv_apply_geo(btv, &set->bottom->geo,0);
64468de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
64568de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
64668de959fSMauro Carvalho Chehab set->frame_irq);
64768de959fSMauro Carvalho Chehab btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
64868de959fSMauro Carvalho Chehab btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
64968de959fSMauro Carvalho Chehab } else {
65068de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
65168de959fSMauro Carvalho Chehab bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
65268de959fSMauro Carvalho Chehab }
65368de959fSMauro Carvalho Chehab return 0;
65468de959fSMauro Carvalho Chehab }
65568de959fSMauro Carvalho Chehab
65668de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
65768de959fSMauro Carvalho Chehab
65868de959fSMauro Carvalho Chehab /* calculate geometry, build risc code */
65968de959fSMauro Carvalho Chehab int
bttv_buffer_risc(struct bttv * btv,struct bttv_buffer * buf)66068de959fSMauro Carvalho Chehab bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
66168de959fSMauro Carvalho Chehab {
662b7ec3212SDeborah Brouwer int r = 0;
66387df33beSDeborah Brouwer const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
664b7ec3212SDeborah Brouwer struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
665b7ec3212SDeborah Brouwer struct scatterlist *list = sgt->sgl;
666b7ec3212SDeborah Brouwer unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
66768de959fSMauro Carvalho Chehab
66868de959fSMauro Carvalho Chehab /* packed pixel modes */
6699764252dSDeborah Brouwer if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
670b7ec3212SDeborah Brouwer int bpl = (btv->fmt->depth >> 3) * btv->width;
671b7ec3212SDeborah Brouwer int bpf = bpl * (btv->height >> 1);
67268de959fSMauro Carvalho Chehab
673b7ec3212SDeborah Brouwer bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
674b7ec3212SDeborah Brouwer V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
675b7ec3212SDeborah Brouwer &btv->crop[!!btv->do_crop].rect);
676b7ec3212SDeborah Brouwer switch (buf->vbuf.field) {
67768de959fSMauro Carvalho Chehab case V4L2_FIELD_TOP:
678b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
679b7ec3212SDeborah Brouwer 0, btv->height);
68068de959fSMauro Carvalho Chehab break;
68168de959fSMauro Carvalho Chehab case V4L2_FIELD_BOTTOM:
682b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
683b7ec3212SDeborah Brouwer 0, 0, btv->height);
68468de959fSMauro Carvalho Chehab break;
68568de959fSMauro Carvalho Chehab case V4L2_FIELD_INTERLACED:
686b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
687b7ec3212SDeborah Brouwer bpl, 0, btv->height >> 1);
688b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
689b7ec3212SDeborah Brouwer bpl, bpl, 0, btv->height >> 1);
69068de959fSMauro Carvalho Chehab break;
69168de959fSMauro Carvalho Chehab case V4L2_FIELD_SEQ_TB:
692b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
693b7ec3212SDeborah Brouwer 0, btv->height >> 1);
694b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
695b7ec3212SDeborah Brouwer bpl, 0, 0, btv->height >> 1);
69668de959fSMauro Carvalho Chehab break;
69768de959fSMauro Carvalho Chehab default:
698615c5450SDeborah Brouwer WARN_ON(1);
699b7ec3212SDeborah Brouwer return -EINVAL;
70068de959fSMauro Carvalho Chehab }
70168de959fSMauro Carvalho Chehab }
70268de959fSMauro Carvalho Chehab /* planar modes */
7039764252dSDeborah Brouwer if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
70468de959fSMauro Carvalho Chehab int uoffset, voffset;
70568de959fSMauro Carvalho Chehab int ypadding, cpadding, lines;
70668de959fSMauro Carvalho Chehab
70768de959fSMauro Carvalho Chehab /* calculate chroma offsets */
708b7ec3212SDeborah Brouwer uoffset = btv->width * btv->height;
709b7ec3212SDeborah Brouwer voffset = btv->width * btv->height;
7109764252dSDeborah Brouwer if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
71168de959fSMauro Carvalho Chehab /* Y-Cr-Cb plane order */
7129764252dSDeborah Brouwer uoffset >>= btv->fmt->hshift;
7139764252dSDeborah Brouwer uoffset >>= btv->fmt->vshift;
71468de959fSMauro Carvalho Chehab uoffset += voffset;
71568de959fSMauro Carvalho Chehab } else {
71668de959fSMauro Carvalho Chehab /* Y-Cb-Cr plane order */
7179764252dSDeborah Brouwer voffset >>= btv->fmt->hshift;
7189764252dSDeborah Brouwer voffset >>= btv->fmt->vshift;
71968de959fSMauro Carvalho Chehab voffset += uoffset;
72068de959fSMauro Carvalho Chehab }
721b7ec3212SDeborah Brouwer switch (buf->vbuf.field) {
72268de959fSMauro Carvalho Chehab case V4L2_FIELD_TOP:
723b7ec3212SDeborah Brouwer bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
724b7ec3212SDeborah Brouwer 0, tvnorm,
725b7ec3212SDeborah Brouwer &btv->crop[!!btv->do_crop].rect);
726b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->top, list, 0,
727b7ec3212SDeborah Brouwer btv->width, 0, btv->height,
728b7ec3212SDeborah Brouwer uoffset, voffset,
729b7ec3212SDeborah Brouwer btv->fmt->hshift,
7309764252dSDeborah Brouwer btv->fmt->vshift, 0);
73168de959fSMauro Carvalho Chehab break;
73268de959fSMauro Carvalho Chehab case V4L2_FIELD_BOTTOM:
733b7ec3212SDeborah Brouwer bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
734b7ec3212SDeborah Brouwer 0, tvnorm,
735b7ec3212SDeborah Brouwer &btv->crop[!!btv->do_crop].rect);
736b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->bottom, list, 0,
737b7ec3212SDeborah Brouwer btv->width, 0, btv->height,
738b7ec3212SDeborah Brouwer uoffset, voffset,
739b7ec3212SDeborah Brouwer btv->fmt->hshift,
7409764252dSDeborah Brouwer btv->fmt->vshift, 0);
74168de959fSMauro Carvalho Chehab break;
74268de959fSMauro Carvalho Chehab case V4L2_FIELD_INTERLACED:
743b7ec3212SDeborah Brouwer bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
744b7ec3212SDeborah Brouwer 1, tvnorm,
745b7ec3212SDeborah Brouwer &btv->crop[!!btv->do_crop].rect);
746b7ec3212SDeborah Brouwer lines = btv->height >> 1;
747b7ec3212SDeborah Brouwer ypadding = btv->width;
748b7ec3212SDeborah Brouwer cpadding = btv->width >> btv->fmt->hshift;
749b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->top, list, 0,
750b7ec3212SDeborah Brouwer btv->width, ypadding, lines,
75168de959fSMauro Carvalho Chehab uoffset, voffset,
7529764252dSDeborah Brouwer btv->fmt->hshift,
753b7ec3212SDeborah Brouwer btv->fmt->vshift, cpadding);
754b7ec3212SDeborah Brouwer
755b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->bottom, list,
756b7ec3212SDeborah Brouwer ypadding, btv->width, ypadding,
757b7ec3212SDeborah Brouwer lines, uoffset + cpadding,
75868de959fSMauro Carvalho Chehab voffset + cpadding,
7599764252dSDeborah Brouwer btv->fmt->hshift,
760b7ec3212SDeborah Brouwer btv->fmt->vshift, cpadding);
76168de959fSMauro Carvalho Chehab break;
76268de959fSMauro Carvalho Chehab case V4L2_FIELD_SEQ_TB:
763b7ec3212SDeborah Brouwer bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
764b7ec3212SDeborah Brouwer 1, tvnorm,
765b7ec3212SDeborah Brouwer &btv->crop[!!btv->do_crop].rect);
766b7ec3212SDeborah Brouwer lines = btv->height >> 1;
767b7ec3212SDeborah Brouwer ypadding = btv->width;
768b7ec3212SDeborah Brouwer cpadding = btv->width >> btv->fmt->hshift;
769b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->top, list, 0,
770b7ec3212SDeborah Brouwer btv->width, 0, lines,
771b7ec3212SDeborah Brouwer uoffset >> 1, voffset >> 1,
7729764252dSDeborah Brouwer btv->fmt->hshift,
773b7ec3212SDeborah Brouwer btv->fmt->vshift, 0);
774b7ec3212SDeborah Brouwer r = bttv_risc_planar(btv, &buf->bottom, list,
775b7ec3212SDeborah Brouwer lines * ypadding,
776b7ec3212SDeborah Brouwer btv->width, 0, lines,
77768de959fSMauro Carvalho Chehab lines * ypadding + (uoffset >> 1),
77868de959fSMauro Carvalho Chehab lines * ypadding + (voffset >> 1),
7799764252dSDeborah Brouwer btv->fmt->hshift,
780b7ec3212SDeborah Brouwer btv->fmt->vshift, 0);
78168de959fSMauro Carvalho Chehab break;
78268de959fSMauro Carvalho Chehab default:
783615c5450SDeborah Brouwer WARN_ON(1);
784b7ec3212SDeborah Brouwer return -EINVAL;
78568de959fSMauro Carvalho Chehab }
78668de959fSMauro Carvalho Chehab }
78768de959fSMauro Carvalho Chehab /* raw data */
7889764252dSDeborah Brouwer if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
78968de959fSMauro Carvalho Chehab /* build risc code */
790b7ec3212SDeborah Brouwer buf->vbuf.field = V4L2_FIELD_SEQ_TB;
79168de959fSMauro Carvalho Chehab bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
7920f5f12e4SDeborah Brouwer 1, tvnorm, &btv->crop[!!btv->do_crop].rect);
793b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
794b7ec3212SDeborah Brouwer RAW_LINES);
795b7ec3212SDeborah Brouwer r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
796b7ec3212SDeborah Brouwer RAW_BPL, 0, 0, RAW_LINES);
79768de959fSMauro Carvalho Chehab }
79868de959fSMauro Carvalho Chehab
79968de959fSMauro Carvalho Chehab /* copy format info */
8009764252dSDeborah Brouwer buf->btformat = btv->fmt->btformat;
8019764252dSDeborah Brouwer buf->btswap = btv->fmt->btswap;
802b7ec3212SDeborah Brouwer
803b7ec3212SDeborah Brouwer return r;
80468de959fSMauro Carvalho Chehab }
805