brintos

brintos / linux-shallow public Read only

0
0
Text · 22.5 KiB · 241a696 Raw
805 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 4    bttv-risc.c  --  interfaces to other kernel modules5 6    bttv risc code handling7	- memory management8	- generation9 10    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>11 12 13*/14 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt16 17#include <linux/module.h>18#include <linux/init.h>19#include <linux/slab.h>20#include <linux/pci.h>21#include <linux/vmalloc.h>22#include <linux/interrupt.h>23#include <linux/pgtable.h>24#include <asm/page.h>25#include <media/v4l2-ioctl.h>26 27#include "bttvp.h"28 29#define VCR_HACK_LINES 430 31/* ---------------------------------------------------------- */32/* risc code generators                                       */33 34int35bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,36		 struct scatterlist *sglist,37		 unsigned int offset, unsigned int bpl,38		 unsigned int padding, unsigned int skip_lines,39		 unsigned int store_lines)40{41	u32 instructions,line,todo;42	struct scatterlist *sg;43	__le32 *rp;44	int rc;45 46	/* estimate risc mem: worst case is one write per page border +47	   one write per scan line + sync + jump (all 2 dwords).  padding48	   can cause next bpl to start close to a page border.  First DMA49	   region may be smaller than PAGE_SIZE */50	instructions  = skip_lines * 4;51	instructions += (1 + ((bpl + padding) * store_lines)52			 / PAGE_SIZE + store_lines) * 8;53	instructions += 2 * 8;54	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)55		return rc;56 57	/* sync instruction */58	rp = risc->cpu;59	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);60	*(rp++) = cpu_to_le32(0);61 62	while (skip_lines-- > 0) {63		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |64				      BT848_RISC_EOL | bpl);65	}66 67	/* scan lines */68	sg = sglist;69	for (line = 0; line < store_lines; line++) {70		if ((line >= (store_lines - VCR_HACK_LINES)) &&71		    btv->opt_vcr_hack)72			continue;73		while (offset && offset >= sg_dma_len(sg)) {74			offset -= sg_dma_len(sg);75			sg = sg_next(sg);76		}77		if (bpl <= sg_dma_len(sg)-offset) {78			/* fits into current chunk */79			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|80					    BT848_RISC_EOL|bpl);81			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);82			offset+=bpl;83		} else {84			/* scanline needs to be split */85			todo = bpl;86			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|87					    (sg_dma_len(sg)-offset));88			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);89			todo -= (sg_dma_len(sg)-offset);90			offset = 0;91			sg = sg_next(sg);92			while (todo > sg_dma_len(sg)) {93				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|94						    sg_dma_len(sg));95				*(rp++)=cpu_to_le32(sg_dma_address(sg));96				todo -= sg_dma_len(sg);97				sg = sg_next(sg);98			}99			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|100					    todo);101			*(rp++)=cpu_to_le32(sg_dma_address(sg));102			offset += todo;103		}104		offset += padding;105	}106 107	/* save pointer to jmp instruction address */108	risc->jmp = rp;109	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);110	return 0;111}112 113static int114bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,115		 struct scatterlist *sglist,116		 unsigned int yoffset,  unsigned int ybpl,117		 unsigned int ypadding, unsigned int ylines,118		 unsigned int uoffset,  unsigned int voffset,119		 unsigned int hshift,   unsigned int vshift,120		 unsigned int cpadding)121{122	unsigned int instructions,line,todo,ylen,chroma;123	__le32 *rp;124	u32 ri;125	struct scatterlist *ysg;126	struct scatterlist *usg;127	struct scatterlist *vsg;128	int topfield = (0 == yoffset);129	int rc;130 131	/* estimate risc mem: worst case is one write per page border +132	   one write per scan line (5 dwords)133	   plus sync + jump (2 dwords) */134	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)135			 / PAGE_SIZE) + ylines;136	instructions += 2;137	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)138		return rc;139 140	/* sync instruction */141	rp = risc->cpu;142	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);143	*(rp++) = cpu_to_le32(0);144 145	/* scan lines */146	ysg = sglist;147	usg = sglist;148	vsg = sglist;149	for (line = 0; line < ylines; line++) {150		if ((btv->opt_vcr_hack) &&151		    (line >= (ylines - VCR_HACK_LINES)))152			continue;153		switch (vshift) {154		case 0:155			chroma = 1;156			break;157		case 1:158			if (topfield)159				chroma = ((line & 1) == 0);160			else161				chroma = ((line & 1) == 1);162			break;163		case 2:164			if (topfield)165				chroma = ((line & 3) == 0);166			else167				chroma = ((line & 3) == 2);168			break;169		default:170			chroma = 0;171			break;172		}173 174		for (todo = ybpl; todo > 0; todo -= ylen) {175			/* go to next sg entry if needed */176			while (yoffset && yoffset >= sg_dma_len(ysg)) {177				yoffset -= sg_dma_len(ysg);178				ysg = sg_next(ysg);179			}180 181			/* calculate max number of bytes we can write */182			ylen = todo;183			if (yoffset + ylen > sg_dma_len(ysg))184				ylen = sg_dma_len(ysg) - yoffset;185			if (chroma) {186				while (uoffset && uoffset >= sg_dma_len(usg)) {187					uoffset -= sg_dma_len(usg);188					usg = sg_next(usg);189				}190				while (voffset && voffset >= sg_dma_len(vsg)) {191					voffset -= sg_dma_len(vsg);192					vsg = sg_next(vsg);193				}194 195				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))196					ylen = (sg_dma_len(usg) - uoffset) << hshift;197				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))198					ylen = (sg_dma_len(vsg) - voffset) << hshift;199				ri = BT848_RISC_WRITE123;200			} else {201				ri = BT848_RISC_WRITE1S23;202			}203			if (ybpl == todo)204				ri |= BT848_RISC_SOL;205			if (ylen == todo)206				ri |= BT848_RISC_EOL;207 208			/* write risc instruction */209			*(rp++)=cpu_to_le32(ri | ylen);210			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |211					    (ylen >> hshift));212			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);213			yoffset += ylen;214			if (chroma) {215				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);216				uoffset += ylen >> hshift;217				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);218				voffset += ylen >> hshift;219			}220		}221		yoffset += ypadding;222		if (chroma) {223			uoffset += cpadding;224			voffset += cpadding;225		}226	}227 228	/* save pointer to jmp instruction address */229	risc->jmp = rp;230	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);231	return 0;232}233 234/* ---------------------------------------------------------- */235 236static void237bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,238		  int width, int height, int interleaved,239		  const struct bttv_tvnorm *tvnorm)240{241	u32 xsf, sr;242	int vdelay;243 244	int swidth       = tvnorm->swidth;245	int totalwidth   = tvnorm->totalwidth;246	int scaledtwidth = tvnorm->scaledtwidth;247 248	if (btv->input == btv->dig) {249		swidth       = 720;250		totalwidth   = 858;251		scaledtwidth = 858;252	}253 254	vdelay = tvnorm->vdelay;255 256	xsf = (width*scaledtwidth)/swidth;257	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);258	geo->hdelay =  tvnorm->hdelayx1;259	geo->hdelay =  (geo->hdelay*width)/swidth;260	geo->hdelay &= 0x3fe;261	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;262	geo->vscale =  (0x10000UL-sr) & 0x1fff;263	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |264		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);265	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;266	geo->vdelay  =  vdelay;267	geo->width   =  width;268	geo->sheight =  tvnorm->sheight;269	geo->vtotal  =  tvnorm->vtotal;270 271	if (btv->opt_combfilter) {272		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);273		geo->comb = (width < 769) ? 1 : 0;274	} else {275		geo->vtc  = 0;276		geo->comb = 0;277	}278}279 280static void281bttv_calc_geo		(struct bttv *                  btv,282			 struct bttv_geometry *         geo,283			 unsigned int                   width,284			 unsigned int                   height,285			 int                            both_fields,286			 const struct bttv_tvnorm *     tvnorm,287			 const struct v4l2_rect *       crop)288{289	unsigned int c_width;290	unsigned int c_height;291	u32 sr;292 293	if ((crop->left == tvnorm->cropcap.defrect.left294	     && crop->top == tvnorm->cropcap.defrect.top295	     && crop->width == tvnorm->cropcap.defrect.width296	     && crop->height == tvnorm->cropcap.defrect.height297	     && width <= tvnorm->swidth /* see PAL-Nc et al */)298	    || btv->input == btv->dig) {299		bttv_calc_geo_old(btv, geo, width, height,300				  both_fields, tvnorm);301		return;302	}303 304	/* For bug compatibility the image size checks permit scale305	   factors > 16. See bttv_crop_calc_limits(). */306	c_width = min((unsigned int) crop->width, width * 16);307	c_height = min((unsigned int) crop->height, height * 16);308 309	geo->width = width;310	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;311	/* Even to store Cb first, odd for Cr. */312	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;313 314	geo->sheight = c_height;315	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;316	sr = c_height >> !both_fields;317	sr = (sr * 512U + (height >> 1)) / height - 512;318	geo->vscale = (0x10000UL - sr) & 0x1fff;319	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;320	geo->vtotal = tvnorm->vtotal;321 322	geo->crop = (((geo->width   >> 8) & 0x03) |323		     ((geo->hdelay  >> 6) & 0x0c) |324		     ((geo->sheight >> 4) & 0x30) |325		     ((geo->vdelay  >> 2) & 0xc0));326 327	if (btv->opt_combfilter) {328		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);329		geo->comb = (width < 769) ? 1 : 0;330	} else {331		geo->vtc  = 0;332		geo->comb = 0;333	}334}335 336static void337bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)338{339	int off = odd ? 0x80 : 0x00;340 341	if (geo->comb)342		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);343	else344		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);345 346	btwrite(geo->vtc,             BT848_E_VTC+off);347	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);348	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);349	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);350	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);351	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);352	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);353	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);354	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);355	btwrite(geo->crop,            BT848_E_CROP+off);356	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);357	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);358}359 360/* ---------------------------------------------------------- */361/* risc group / risc main loop / dma management               */362 363static void bttv_set_risc_status(struct bttv *btv)364{365	unsigned long cmd = BT848_RISC_JUMP;366	if (btv->loop_irq) {367		cmd |= BT848_RISC_IRQ;368		cmd |= (btv->loop_irq  & 0x0f) << 16;369		cmd |= (~btv->loop_irq & 0x0f) << 20;370	}371	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);372}373 374static void bttv_set_irq_timer(struct bttv *btv)375{376	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)377		mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);378	else379		del_timer(&btv->timeout);380}381 382static int bttv_set_capture_control(struct bttv *btv, int start_capture)383{384	int capctl = 0;385 386	if (btv->curr.top || btv->curr.bottom)387		capctl = BT848_CAP_CTL_CAPTURE_ODD |388			 BT848_CAP_CTL_CAPTURE_EVEN;389 390	if (btv->cvbi)391		capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |392			  BT848_CAP_CTL_CAPTURE_VBI_EVEN;393 394	capctl |= start_capture;395 396	btaor(capctl, ~0x0f, BT848_CAP_CTL);397 398	return capctl;399}400 401static void bttv_start_dma(struct bttv *btv)402{403	if (btv->dma_on)404		return;405	btwrite(btv->main.dma, BT848_RISC_STRT_ADD);406	btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,407	     BT848_GPIO_DMA_CTL);408	btv->dma_on = 1;409}410 411static void bttv_stop_dma(struct bttv *btv)412{413	if (!btv->dma_on)414		return;415	btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |416		BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);417	btv->dma_on = 0;418}419 420void bttv_set_dma(struct bttv *btv, int start_capture)421{422	int capctl = 0;423 424	bttv_set_risc_status(btv);425	bttv_set_irq_timer(btv);426	capctl = bttv_set_capture_control(btv, start_capture);427 428	if (capctl)429		bttv_start_dma(btv);430	else431		bttv_stop_dma(btv);432 433	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",434		 btv->c.nr,capctl,btv->loop_irq,435		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,436		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,437		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,438		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);439}440 441int442bttv_risc_init_main(struct bttv *btv)443{444	int rc;445 446	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)447		return rc;448	dprintk("%d: risc main @ %08llx\n",449		btv->c.nr, (unsigned long long)btv->main.dma);450 451	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |452				       BT848_FIFO_STATUS_VRE);453	btv->main.cpu[1] = cpu_to_le32(0);454	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);455	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));456 457	/* top field */458	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);459	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));460	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);461	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));462 463	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |464				       BT848_FIFO_STATUS_VRO);465	btv->main.cpu[9] = cpu_to_le32(0);466 467	/* bottom field */468	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);469	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));470	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);471	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));472 473	/* jump back to top field */474	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);475	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));476 477	return 0;478}479 480int481bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,482	       int irqflags)483{484	unsigned long cmd;485	unsigned long next = btv->main.dma + ((slot+2) << 2);486 487	if (NULL == risc) {488		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);489		btv->main.cpu[slot+1] = cpu_to_le32(next);490	} else {491		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",492			 btv->c.nr, risc, slot,493			 (unsigned long long)risc->dma, irqflags);494		cmd = BT848_RISC_JUMP;495		if (irqflags) {496			cmd |= BT848_RISC_IRQ;497			cmd |= (irqflags  & 0x0f) << 16;498			cmd |= (~irqflags & 0x0f) << 20;499		}500		risc->jmp[0] = cpu_to_le32(cmd);501		risc->jmp[1] = cpu_to_le32(next);502		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);503	}504	return 0;505}506 507int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)508{509	int r = 0;510	unsigned int offset;511	unsigned int bpl = 2044; /* max. vbipack */512	unsigned int padding = VBI_BPL - bpl;513	unsigned int skip_lines0 = 0;514	unsigned int skip_lines1 = 0;515	unsigned int min_vdelay = MIN_VDELAY;516 517	const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;518	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);519	struct scatterlist *list = sgt->sgl;520 521	if (btv->vbi_fmt.fmt.count[0] > 0)522		skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -523					tvnorm->vbistart[0]));524	if (btv->vbi_fmt.fmt.count[1] > 0)525		skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -526					tvnorm->vbistart[1]));527 528	if (btv->vbi_fmt.fmt.count[0] > 0) {529		r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,530				     skip_lines0, btv->vbi_fmt.fmt.count[0]);531		if (r)532			return r;533	}534 535	if (btv->vbi_fmt.fmt.count[1] > 0) {536		offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;537		r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,538				     padding, skip_lines1,539				     btv->vbi_fmt.fmt.count[1]);540		if (r)541			return r;542	}543 544	if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)545		min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;546 547	/* For bttv_buffer_activate_vbi(). */548	buf->geo.vdelay = min_vdelay;549 550	return r;551}552 553int554bttv_buffer_activate_vbi(struct bttv *btv,555			 struct bttv_buffer *vbi)556{557	struct btcx_riscmem *top;558	struct btcx_riscmem *bottom;559	int top_irq_flags;560	int bottom_irq_flags;561 562	top = NULL;563	bottom = NULL;564	top_irq_flags = 0;565	bottom_irq_flags = 0;566 567	if (vbi) {568		unsigned int crop, vdelay;569 570		list_del(&vbi->list);571 572		/* VDELAY is start of video, end of VBI capturing. */573		crop = btread(BT848_E_CROP);574		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);575 576		if (vbi->geo.vdelay > vdelay) {577			vdelay = vbi->geo.vdelay & 0xfe;578			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);579 580			btwrite(vdelay, BT848_E_VDELAY_LO);581			btwrite(crop,	BT848_E_CROP);582			btwrite(vdelay, BT848_O_VDELAY_LO);583			btwrite(crop,	BT848_O_CROP);584		}585 586		if (btv->vbi_count[0] > 0) {587			top = &vbi->top;588			top_irq_flags = 4;589		}590 591		if (btv->vbi_count[1] > 0) {592			top_irq_flags = 0;593			bottom = &vbi->bottom;594			bottom_irq_flags = 4;595		}596	}597 598	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);599	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);600 601	return 0;602}603 604int605bttv_buffer_activate_video(struct bttv *btv,606			   struct bttv_buffer_set *set)607{608	/* video capture */609	if (NULL != set->top  &&  NULL != set->bottom) {610		if (set->top == set->bottom) {611			if (set->top->list.next)612				list_del(&set->top->list);613		} else {614			if (set->top->list.next)615				list_del(&set->top->list);616			if (set->bottom->list.next)617				list_del(&set->bottom->list);618		}619		bttv_apply_geo(btv, &set->top->geo, 1);620		bttv_apply_geo(btv, &set->bottom->geo,0);621		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,622			       set->top_irq);623		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,624			       set->frame_irq);625		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),626		      ~0xff, BT848_COLOR_FMT);627		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),628		      ~0x0f, BT848_COLOR_CTL);629	} else if (NULL != set->top) {630		if (set->top->list.next)631			list_del(&set->top->list);632		bttv_apply_geo(btv, &set->top->geo,1);633		bttv_apply_geo(btv, &set->top->geo,0);634		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,635			       set->frame_irq);636		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);637		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);638		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);639	} else if (NULL != set->bottom) {640		if (set->bottom->list.next)641			list_del(&set->bottom->list);642		bttv_apply_geo(btv, &set->bottom->geo,1);643		bttv_apply_geo(btv, &set->bottom->geo,0);644		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);645		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,646			       set->frame_irq);647		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);648		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);649	} else {650		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);651		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);652	}653	return 0;654}655 656/* ---------------------------------------------------------- */657 658/* calculate geometry, build risc code */659int660bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)661{662	int r = 0;663	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;664	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);665	struct scatterlist *list = sgt->sgl;666	unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;667 668	/* packed pixel modes */669	if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {670		int bpl = (btv->fmt->depth >> 3) * btv->width;671		int bpf = bpl * (btv->height >> 1);672 673		bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,674			      V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,675			      &btv->crop[!!btv->do_crop].rect);676		switch (buf->vbuf.field) {677		case V4L2_FIELD_TOP:678			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,679					     0, btv->height);680			break;681		case V4L2_FIELD_BOTTOM:682			r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,683					     0, 0, btv->height);684			break;685		case V4L2_FIELD_INTERLACED:686			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,687					     bpl, 0, btv->height >> 1);688			r = bttv_risc_packed(btv, &buf->bottom, list, bpl,689					     bpl, bpl, 0, btv->height >> 1);690			break;691		case V4L2_FIELD_SEQ_TB:692			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,693					     0, btv->height >> 1);694			r = bttv_risc_packed(btv, &buf->bottom, list, bpf,695					     bpl, 0, 0, btv->height >> 1);696			break;697		default:698			WARN_ON(1);699			return -EINVAL;700		}701	}702	/* planar modes */703	if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {704		int uoffset, voffset;705		int ypadding, cpadding, lines;706 707		/* calculate chroma offsets */708		uoffset = btv->width * btv->height;709		voffset = btv->width * btv->height;710		if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {711			/* Y-Cr-Cb plane order */712			uoffset >>= btv->fmt->hshift;713			uoffset >>= btv->fmt->vshift;714			uoffset  += voffset;715		} else {716			/* Y-Cb-Cr plane order */717			voffset >>= btv->fmt->hshift;718			voffset >>= btv->fmt->vshift;719			voffset  += uoffset;720		}721		switch (buf->vbuf.field) {722		case V4L2_FIELD_TOP:723			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,724				      0, tvnorm,725				      &btv->crop[!!btv->do_crop].rect);726			r = bttv_risc_planar(btv, &buf->top, list, 0,727					     btv->width, 0, btv->height,728					     uoffset, voffset,729					     btv->fmt->hshift,730					     btv->fmt->vshift, 0);731			break;732		case V4L2_FIELD_BOTTOM:733			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,734				      0, tvnorm,735				      &btv->crop[!!btv->do_crop].rect);736			r = bttv_risc_planar(btv, &buf->bottom, list, 0,737					     btv->width, 0, btv->height,738					     uoffset, voffset,739					     btv->fmt->hshift,740					     btv->fmt->vshift, 0);741			break;742		case V4L2_FIELD_INTERLACED:743			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,744				      1, tvnorm,745				      &btv->crop[!!btv->do_crop].rect);746			lines = btv->height >> 1;747			ypadding = btv->width;748			cpadding = btv->width >> btv->fmt->hshift;749			r = bttv_risc_planar(btv, &buf->top, list, 0,750					     btv->width, ypadding, lines,751					     uoffset, voffset,752					     btv->fmt->hshift,753					     btv->fmt->vshift, cpadding);754 755			r = bttv_risc_planar(btv, &buf->bottom, list,756					     ypadding, btv->width, ypadding,757					     lines,  uoffset + cpadding,758					     voffset + cpadding,759					     btv->fmt->hshift,760					     btv->fmt->vshift, cpadding);761			break;762		case V4L2_FIELD_SEQ_TB:763			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,764				      1, tvnorm,765				      &btv->crop[!!btv->do_crop].rect);766			lines = btv->height >> 1;767			ypadding = btv->width;768			cpadding = btv->width >> btv->fmt->hshift;769			r = bttv_risc_planar(btv, &buf->top, list, 0,770					     btv->width, 0, lines,771					     uoffset >> 1, voffset >> 1,772					     btv->fmt->hshift,773					     btv->fmt->vshift, 0);774			r = bttv_risc_planar(btv, &buf->bottom, list,775					     lines * ypadding,776					     btv->width, 0, lines,777					     lines * ypadding + (uoffset >> 1),778					     lines * ypadding + (voffset >> 1),779					     btv->fmt->hshift,780					     btv->fmt->vshift, 0);781			break;782		default:783			WARN_ON(1);784			return -EINVAL;785		}786	}787	/* raw data */788	if (btv->fmt->flags & FORMAT_FLAGS_RAW) {789		/* build risc code */790		buf->vbuf.field = V4L2_FIELD_SEQ_TB;791		bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,792			      1, tvnorm, &btv->crop[!!btv->do_crop].rect);793		r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,794				     RAW_LINES);795		r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,796				     RAW_BPL, 0, 0, RAW_LINES);797	}798 799	/* copy format info */800	buf->btformat = btv->fmt->btformat;801	buf->btswap   = btv->fmt->btswap;802 803	return r;804}805