ks0127.c

来自「trident tm5600的linux驱动」· C语言 代码 · 共 799 行 · 第 1/2 页

C
799
字号
		break;	default:		v4l_dbg(1, debug, c, "unknown revision\n");		break;	}}static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg){	struct ks0127 *ks = i2c_get_clientdata(c);	int		*iarg = (int *)arg;	int		status;	if (!ks)		return -ENODEV;	switch (cmd) {	case DECODER_INIT:		v4l_dbg(1, debug, c, "DECODER_INIT\n");		ks0127_reset(c);		break;	case DECODER_SET_INPUT:		switch(*iarg) {		case KS_INPUT_COMPOSITE_1:		case KS_INPUT_COMPOSITE_2:		case KS_INPUT_COMPOSITE_3:		case KS_INPUT_COMPOSITE_4:		case KS_INPUT_COMPOSITE_5:		case KS_INPUT_COMPOSITE_6:			v4l_dbg(1, debug, c,				"DECODER_SET_INPUT %d: Composite\n", *iarg);			/* autodetect 50/60 Hz */			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);			/* VSE=0 */			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);			/* set input line */			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);			/* non-freerunning mode */			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);			/* analog input */			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);			/* enable chroma demodulation */			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);			/* chroma trap, HYBWR=1 */			ks0127_and_or(c, KS_LUMA,   0x00,				       (reg_defaults[KS_LUMA])|0x0c);			/* scaler fullbw, luma comb off */			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);			/* manual chroma comb .25 .5 .25 */			ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90);			/* chroma path delay */			ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90);			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);			break;		case KS_INPUT_SVIDEO_1:		case KS_INPUT_SVIDEO_2:		case KS_INPUT_SVIDEO_3:			v4l_dbg(1, debug, c,				"DECODER_SET_INPUT %d: S-Video\n", *iarg);			/* autodetect 50/60 Hz */			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);			/* VSE=0 */			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);			/* set input line */			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);			/* non-freerunning mode */			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);			/* analog input */			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);			/* enable chroma demodulation */			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);			ks0127_and_or(c, KS_LUMA, 0x00,				       reg_defaults[KS_LUMA]);			/* disable luma comb */			ks0127_and_or(c, KS_VERTIA, 0x08,				       (reg_defaults[KS_VERTIA]&0xf0)|0x01);			ks0127_and_or(c, KS_VERTIC, 0x0f,				       reg_defaults[KS_VERTIC]&0xf0);			ks0127_and_or(c, KS_CHROMB, 0x0f,				       reg_defaults[KS_CHROMB]&0xf0);			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);			break;		case KS_INPUT_YUV656:			v4l_dbg(1, debug, c,				"DECODER_SET_INPUT 15: YUV656\n");			if (ks->norm == VIDEO_MODE_NTSC ||			    ks->norm == KS_STD_PAL_M)				/* force 60 Hz */				ks0127_and_or(c, KS_CMDA,   0xfc, 0x03);			else				/* force 50 Hz */				ks0127_and_or(c, KS_CMDA,   0xfc, 0x02);			ks0127_and_or(c, KS_CMDA,   0xff, 0x40); /* VSE=1 */			/* set input line and VALIGN */			ks0127_and_or(c, KS_CMDB,   0xb0, (*iarg | 0x40));			/* freerunning mode, */			/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/			ks0127_and_or(c, KS_CMDC,   0x70, 0x87);			/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */			ks0127_and_or(c, KS_CMDD,   0x03, 0x08);			/* disable chroma demodulation */			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30);			/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */			ks0127_and_or(c, KS_LUMA,   0x00, 0x71);			ks0127_and_or(c, KS_VERTIC, 0x0f,				       reg_defaults[KS_VERTIC]&0xf0);			/* scaler fullbw, luma comb off */			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);			ks0127_and_or(c, KS_CHROMB, 0x0f,				       reg_defaults[KS_CHROMB]&0xf0);			ks0127_and_or(c, KS_CON, 0x00, 0x00);			ks0127_and_or(c, KS_BRT, 0x00, 32);	/* spec: 34 */				/* spec: 229 (e5) */			ks0127_and_or(c, KS_SAT, 0x00, 0xe8);			ks0127_and_or(c, KS_HUE, 0x00, 0);			ks0127_and_or(c, KS_UGAIN, 0x00, 238);			ks0127_and_or(c, KS_VGAIN, 0x00, 0x00);			/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */			ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f);			ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00);			break;		default:			v4l_dbg(1, debug, c,				"DECODER_SET_INPUT: Unknown input %d\n", *iarg);			break;		}		/* hack: CDMLPF sometimes spontaneously switches on; */		/* force back off */		ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);		break;	case DECODER_SET_OUTPUT:		switch(*iarg) {		case KS_OUTPUT_YUV656E:			v4l_dbg(1, debug, c,				"DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n");			return -EINVAL;		case KS_OUTPUT_EXV:			v4l_dbg(1, debug, c,				"DECODER_SET_OUTPUT: OUTPUT_EXV\n");			ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09);			break;		}		break;	case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */		/* Set to automatic SECAM/Fsc mode */		ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);		ks->norm = *iarg;		switch (*iarg) {		/* this is untested !! */		/* It just detects PAL_N/NTSC_M (no special frequencies) */		/* And you have to set the standard a second time afterwards */		case VIDEO_MODE_AUTO:			v4l_dbg(1, debug, c,				"DECODER_SET_NORM: AUTO\n");			/* The chip determines the format */			/* based on the current field rate */			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);			/* This is wrong for PAL ! As I said, */			/* you need to set the standard once again !! */			ks->format_height = 240;			ks->format_width = 704;			break;		case VIDEO_MODE_NTSC:			v4l_dbg(1, debug, c,				"DECODER_SET_NORM: NTSC_M\n");			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);			ks->format_height = 240;			ks->format_width = 704;			break;		case KS_STD_NTSC_N:			v4l_dbg(1, debug, c,				"KS0127_SET_NORM: NTSC_N (fixme)\n");			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);			ks->format_height = 240;			ks->format_width = 704;			break;		case VIDEO_MODE_PAL:			v4l_dbg(1, debug, c,				"DECODER_SET_NORM: PAL_N\n");			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);			ks->format_height = 290;			ks->format_width = 704;			break;		case KS_STD_PAL_M:			v4l_dbg(1, debug, c,				"KS0127_SET_NORM: PAL_M (fixme)\n");			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);			ks->format_height = 290;			ks->format_width = 704;			break;		case VIDEO_MODE_SECAM:			v4l_dbg(1, debug, c,				"KS0127_SET_NORM: SECAM\n");			ks->format_height = 290;			ks->format_width = 704;			/* set to secam autodetection */			ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20);			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);			schedule_timeout_interruptible(HZ/10+1);			/* did it autodetect? */			if (ks0127_read(c, KS_DEMOD) & 0x40)				break;			/* force to secam mode */			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);			break;		default:			v4l_dbg(1, debug, c,				"DECODER_SET_NORM: Unknown norm %d\n", *iarg);			break;		}		break;	case DECODER_SET_PICTURE:		v4l_dbg(1, debug, c,			"DECODER_SET_PICTURE: not yet supported\n");		return -EINVAL;	/* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */	/* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */	/* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */	/* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */	/* sam todo: KS0127_SET_AGC_MODE: */	/* sam todo: KS0127_SET_AGC: */	/* sam todo: KS0127_SET_CHROMA_MODE: */	/* sam todo: KS0127_SET_PIXCLK_MODE: */	/* sam todo: KS0127_SET_GAMMA_MODE: */	/* sam todo: KS0127_SET_UGAIN: */	/* sam todo: KS0127_SET_VGAIN: */	/* sam todo: KS0127_SET_INVALY: */	/* sam todo: KS0127_SET_INVALU: */	/* sam todo: KS0127_SET_INVALV: */	/* sam todo: KS0127_SET_UNUSEY: */	/* sam todo: KS0127_SET_UNUSEU: */	/* sam todo: KS0127_SET_UNUSEV: */	/* sam todo: KS0127_SET_VSALIGN_MODE: */	case DECODER_ENABLE_OUTPUT:	{		int enable;		iarg = arg;		enable = (*iarg != 0);		if (enable) {			v4l_dbg(1, debug, c,				"DECODER_ENABLE_OUTPUT on\n");			/* All output pins on */			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);			/* Obey the OEN pin */			ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);		} else {			v4l_dbg(1, debug, c,				"DECODER_ENABLE_OUTPUT off\n");			/* Video output pins off */			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);			/* Ignore the OEN pin */			ks0127_and_or(c, KS_CDEM, 0x7f, 0x80);		}		break;	}	/* sam todo: KS0127_SET_OUTPUT_MODE: */	/* sam todo: KS0127_SET_WIDTH: */	/* sam todo: KS0127_SET_HEIGHT: */	/* sam todo: KS0127_SET_HSCALE: */	case DECODER_GET_STATUS:		v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n");		*iarg = 0;		status = ks0127_read(c, KS_STAT);		if (!(status & 0x20))		 /* NOVID not set */			*iarg = (*iarg | DECODER_STATUS_GOOD);		if ((status & 0x01))		      /* CLOCK set */			*iarg = (*iarg | DECODER_STATUS_COLOR);		if ((status & 0x08))		   /* PALDET set */			*iarg = (*iarg | DECODER_STATUS_PAL);		else			*iarg = (*iarg | DECODER_STATUS_NTSC);		break;	/* Catch any unknown command */	default:		v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd);		return -EINVAL;	}	return 0;}/* Addresses to scan */#define I2C_KS0127_ADDON   0xD8#define I2C_KS0127_ONBOARD 0xDAstatic unsigned short normal_i2c[] = {	I2C_KS0127_ADDON >> 1,	I2C_KS0127_ONBOARD >> 1,	I2C_CLIENT_END};I2C_CLIENT_INSMOD;static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id){	struct ks0127 *ks;	v4l_info(c, "%s chip found @ 0x%x (%s)\n",		c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",		c->addr << 1, c->adapter->name);	ks = kzalloc(sizeof(*ks), GFP_KERNEL);	if (ks == NULL)		return -ENOMEM;	i2c_set_clientdata(c, ks);	ks->ks_type = KS_TYPE_UNKNOWN;	/* power up */	init_reg_defaults();	ks0127_write(c, KS_CMDA, 0x2c);	mdelay(10);	/* reset the device */	ks0127_reset(c);	return 0;}static int ks0127_remove(struct i2c_client *c){	struct ks0127 *ks = i2c_get_clientdata(c);	ks0127_write(c, KS_OFMTA, 0x20); /* tristate */	ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */	kfree(ks);	return 0;}static int ks0127_legacy_probe(struct i2c_adapter *adapter){	return adapter->id == I2C_HW_B_ZR36067;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)static const struct i2c_device_id ks0127_id[] = {	{ "ks0127", 0 },	{ }};MODULE_DEVICE_TABLE(i2c, ks0127_id);#endifstatic struct v4l2_i2c_driver_data v4l2_i2c_data = {	.name = "ks0127",	.driverid = I2C_DRIVERID_KS0127,	.command = ks0127_command,	.probe = ks0127_probe,	.remove = ks0127_remove,	.legacy_probe = ks0127_legacy_probe,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	.id_table = ks0127_id,#endif};

⌨️ 快捷键说明

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