⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppscale.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
字号:
/* drivers/media/video/mx2ads/ppscale.c * * MX21 PP image scaling primitives * * Copyright (C) 2004 MontaVista Software, Inc. * * Author: MontaVista Software, Inc. *              source@mvista.com * * This file is based on scale.c, pphw.c from Motorola Dragonball MX2 ADS BSP * Copyright 2002, 2003, 2004  Motorola, Inc. All Rights Reserved. * * 2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/kernel.h>#include <asm/hardware.h>#include <linux/errno.h>#include "common.h"#define MODULE_NAME "PP scaler"/* resize table dimensions     dest pixel index    left/32    right/32    #src pixels to read    0                   [BC_COEF]  [BC_COEF]   [BC_NXT]    :    pp_tbl_max-1*/#define SCALE_RETRY      16#define BC_NXT		2#define BC_COEF		5#define SZ_COEF		(1 << BC_COEF)#define SZ_NXT		(1 << BC_NXT)static const int pp_tbl_max = 40;static const int pp_skip  = 1;static unsigned short	scale_tbl[40];static intgcd(int x, int y){	int k;	if (x < y)	{		k = x;		x = y;		y = k;	}	while ((k = x % y)) 	{		x = y;		y = k;	}	return y;}static intratio(int x, int y, int *den){	int	g;	if (!x || !y)	{		return 0;	}	g = gcd(x, y);	*den = y / g;	return x / g;}static intscale_PP(int k, int coeff, int base, int nxt){	if (k >= pp_tbl_max)	{		/* no more space in table */                err("pp: no space in scale table, k=%d\n", k); 		return -1;	}	coeff = ((coeff << BC_COEF) + (base >> 1)) / base;	if (coeff >= SZ_COEF - 1)	{		/* 31 means 32, so 30 will handle 30&31 */		coeff--;	}	else if (coeff == 1)	{		coeff++;	}	coeff = coeff << BC_NXT;	if (nxt < SZ_NXT)	{		coeff |= nxt;                coeff <<= 1;                coeff |= 1;	}	else	{		/* 			src inc field is 2 bit wide			for 4+, use special code 0:0:1 to prevent dest inc		*/		coeff |= pp_skip;                coeff <<= 1;                coeff |= 1;		nxt -= pp_skip;		do		{			scale_tbl[k++] = coeff;			coeff = (nxt > pp_skip) ? pp_skip : nxt;			coeff <<= 1;		}		while ((nxt -= pp_skip) > 0);	}        dbg("pp: tbl=%03X\n", coeff);	scale_tbl[k++] = coeff;	return k;}/*	inv	input resolution reduced ratio	outv	output resolution reduced ratio	k	index into free table entry*/static int scale(int inv, int outv, int k){	int	v;		/* overflow counter */	int	coeff, nxt;	/* table output */	if (inv == outv)	{		/* force scaling */		return scale_PP(k, 1, 1, 1);	}	v = 0;	if (inv < outv)	{		/* upscale: mix <= 2 input pixels per output pixel */		do		{			coeff = outv - v;			v += inv;			if (v >= outv)			{				v -= outv;				nxt = 1;			}			else			{				nxt = 0;			}                        dbg("upscale: coeff=%d/%d nxt=%d\n", coeff, outv, nxt);			k = scale_PP(k, coeff, outv, nxt);			if (k < 0)			{				return -1;			}		}		while (v);	}	else if (inv >= 2 * outv)	{		/* downscale: >=2:1 bilinear approximation */		coeff  = inv - 2 * outv;		v = 0; 		nxt = 0;		do		{			v += coeff;			nxt = 2;			while (v >= outv)			{				v -= outv;				nxt++;			}                        dbg("dnscale: coeff=1/2 nxt=%d\n", nxt);			k = scale_PP(k, 1, 2, nxt);			if (k < 0)			{				return -1;			}		}		while (v);	}	else	{		/* downscale: bilinear */		int	inPosInc = 2 * outv;		int	outPos = inv;		int	outPosInc = 2 * inv;		int	init_carry = inv - outv;		int	carry = init_carry;		v = outv + inPosInc;		do		{			coeff = v - outPos;			outPos += outPosInc;			carry += outPosInc;			for (nxt = 0; v < outPos; nxt++)			{				v += inPosInc;				carry -= inPosInc;			}                        dbg("dnscale: coeff=%d/%d nxt=%d\n", coeff, inPosInc, nxt);			k = scale_PP(k, coeff, inPosInc, nxt);			if (k < 0)			{				return -1;			}		} 		while (carry != init_carry);	}	return k;}/*	To facilitate quick scaling*/int  pp_rescale(int in_width, int in_height, int *out_width, int *out_height){	int	hlen;	int	vlen;	int	numx;	int	denx;	int	numy;	int	deny;	int	tin;	int	temp;	int	retry;        volatile unsigned int *resize_coef_table =                 (volatile unsigned int *)(EMMA_PP_BASE + 0x100);        tin = in_width;        temp = *out_width;	retry = SCALE_RETRY;h_retry:	numx = ratio(tin, temp, &denx);	if (!numx)	{                err("pp: x:Bad ratio err\n");		return -EINVAL;	}	hlen = scale(numx, denx, 0);	if (hlen < 0)	{		temp++;		if (retry--)		{			goto h_retry;		}                err("pp: hscale err\n");		return -EINVAL;	}                *out_width = temp;        tin = in_height;        temp = *out_height;        	retry = SCALE_RETRY;v_retry:	numy = ratio(tin, temp, &deny);	if (!numy)	{                err("pp: y:Bad ratio err\n");		return -EINVAL;	}	if (numy == numx && deny == denx)	{		/* same ratio - share table entries */		vlen = hlen;	}	else	{		vlen = scale(numy, deny, hlen);		if (vlen < 0)		{			temp++;			if (retry--)			{				goto v_retry;			}                        err("pp: vscale err\n");			return -EINVAL;		}	}	EMMA_PP_DIMAGE_SIZE = (*out_width << 16) | (*out_height);	EMMA_PP_RSIZE_IDX = ((hlen - 1) << 16) | 				(vlen == hlen ? 0 : (hlen << 8)) | (vlen - 1);	for (hlen = 0; hlen < vlen; hlen++)	{		resize_coef_table[hlen] = scale_tbl[hlen];	}        *out_height = temp;	*out_width &= ~1;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -