ks0127.c

来自「linux 内核源代码」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
	switch (cmd) {	case DECODER_INIT:		dprintk("ks0127: command DECODER_INIT\n");		ks0127_reset(ks);		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:			dprintk("ks0127: command DECODER_SET_INPUT %d: "				"Composite\n", *iarg);			/* autodetect 50/60 Hz */			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);			/* VSE=0 */			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);			/* set input line */			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);			/* non-freerunning mode */			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);			/* analog input */			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);			/* enable chroma demodulation */			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);			/* chroma trap, HYBWR=1 */			ks0127_and_or(ks, KS_LUMA,   0x00,				       (reg_defaults[KS_LUMA])|0x0c);			/* scaler fullbw, luma comb off */			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);			/* manual chroma comb .25 .5 .25 */			ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);			/* chroma path delay */			ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);			break;		case KS_INPUT_SVIDEO_1:		case KS_INPUT_SVIDEO_2:		case KS_INPUT_SVIDEO_3:			dprintk("ks0127: command DECODER_SET_INPUT %d: "				"S-Video\n", *iarg);			/* autodetect 50/60 Hz */			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);			/* VSE=0 */			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);			/* set input line */			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);			/* non-freerunning mode */			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);			/* analog input */			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);			/* enable chroma demodulation */			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);			ks0127_and_or(ks, KS_LUMA, 0x00,				       reg_defaults[KS_LUMA]);			/* disable luma comb */			ks0127_and_or(ks, KS_VERTIA, 0x08,				       (reg_defaults[KS_VERTIA]&0xf0)|0x01);			ks0127_and_or(ks, KS_VERTIC, 0x0f,				       reg_defaults[KS_VERTIC]&0xf0);			ks0127_and_or(ks, KS_CHROMB, 0x0f,				       reg_defaults[KS_CHROMB]&0xf0);			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);			break;		case KS_INPUT_YUV656:			dprintk("ks0127: command DECODER_SET_INPUT 15: "				"YUV656\n");			if (ks->norm == VIDEO_MODE_NTSC ||			    ks->norm == KS_STD_PAL_M)				/* force 60 Hz */				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x03);			else				/* force 50 Hz */				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x02);			ks0127_and_or(ks, KS_CMDA,   0xff, 0x40); /* VSE=1 */			/* set input line and VALIGN */			ks0127_and_or(ks, KS_CMDB,   0xb0, (*iarg | 0x40));			/* freerunning mode, */			/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/			ks0127_and_or(ks, KS_CMDC,   0x70, 0x87);			/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */			ks0127_and_or(ks, KS_CMDD,   0x03, 0x08);			/* disable chroma demodulation */			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);			/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */			ks0127_and_or(ks, KS_LUMA,   0x00, 0x71);			ks0127_and_or(ks, KS_VERTIC, 0x0f,				       reg_defaults[KS_VERTIC]&0xf0);			/* scaler fullbw, luma comb off */			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);			ks0127_and_or(ks, KS_CHROMB, 0x0f,				       reg_defaults[KS_CHROMB]&0xf0);			ks0127_and_or(ks, KS_CON, 0x00, 0x00);			ks0127_and_or(ks, KS_BRT, 0x00, 32);	/* spec: 34 */				/* spec: 229 (e5) */			ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);			ks0127_and_or(ks, KS_HUE, 0x00, 0);			ks0127_and_or(ks, KS_UGAIN, 0x00, 238);			ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);			/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */			ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);			ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);			break;		default:			dprintk("ks0127: command DECODER_SET_INPUT: "				"Unknown input %d\n", *iarg);			break;		}		/* hack: CDMLPF sometimes spontaneously switches on; */		/* force back off */		ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);		break;	case DECODER_SET_OUTPUT:		switch(*iarg) {		case KS_OUTPUT_YUV656E:			dprintk("ks0127: command DECODER_SET_OUTPUT: "				"OUTPUT_YUV656E (Missing)\n");			return -EINVAL;			break;		case KS_OUTPUT_EXV:			dprintk("ks0127: command DECODER_SET_OUTPUT: "				"OUTPUT_EXV\n");			ks0127_and_or(ks, 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(ks, 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:			dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");			/* The chip determines the format */			/* based on the current field rate */			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);			ks0127_and_or(ks, 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:			dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);			ks->format_height = 240;			ks->format_width = 704;			break;		case KS_STD_NTSC_N:			dprintk("ks0127: command KS0127_SET_STANDARD: "				"NTSC_N (fixme)\n");			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);			ks->format_height = 240;			ks->format_width = 704;			break;		case VIDEO_MODE_PAL:			dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);			ks->format_height = 290;			ks->format_width = 704;			break;		case KS_STD_PAL_M:			dprintk("ks0127: command KS0127_SET_STANDARD: "				"PAL_M (fixme)\n");			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);			ks->format_height = 290;			ks->format_width = 704;			break;		case VIDEO_MODE_SECAM:			dprintk("ks0127: command KS0127_SET_STANDARD: "				"SECAM\n");			ks->format_height = 290;			ks->format_width = 704;			/* set to secam autodetection */			ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);			schedule_timeout_interruptible(HZ/10+1);			/* did it autodetect? */			if (ks0127_read(ks, KS_DEMOD) & 0x40)				break;			/* force to secam mode */			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);			break;		default:			dprintk("ks0127: command DECODER_SET_NORM: "				"Unknown norm %d\n", *iarg);			break;		}		break;	case DECODER_SET_PICTURE:		dprintk("ks0127: command DECODER_SET_PICTURE "			"not yet supported (fixme)\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 *iarg = arg;		int enable = (*iarg != 0);			if (enable) {				dprintk("ks0127: command "					"DECODER_ENABLE_OUTPUT on "					"(%d)\n", enable);				/* All output pins on */				ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);				/* Obey the OEN pin */				ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);			} else {				dprintk("ks0127: command "					"DECODER_ENABLE_OUTPUT off "					"(%d)\n", enable);				/* Video output pins off */				ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);				/* Ignore the OEN pin */				ks0127_and_or(ks, 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:		dprintk("ks0127: command DECODER_GET_STATUS\n");		*iarg = 0;		status = ks0127_read(ks, 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:		dprintk("ks0127: command unknown: %04X\n", cmd);		return -EINVAL;	}	return 0;}static int ks0127_probe(struct i2c_adapter *adapter);static int ks0127_detach(struct i2c_client *client);static int ks0127_command(struct i2c_client *client,			  unsigned int cmd, void *arg);/* Addresses to scan */static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,				       I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};static unsigned short probe[2] =	{I2C_CLIENT_END, I2C_CLIENT_END};static unsigned short ignore[2] = 	{I2C_CLIENT_END, I2C_CLIENT_END};static struct i2c_client_address_data addr_data = {	normal_i2c,	probe,	ignore,};static struct i2c_driver i2c_driver_ks0127 = {	.driver.name = "ks0127",	.id             = I2C_DRIVERID_KS0127,	.attach_adapter = ks0127_probe,	.detach_client  = ks0127_detach,	.command        = ks0127_command};static struct i2c_client ks0127_client_tmpl ={	.name = "(ks0127 unset)",	.addr = 0,	.adapter = NULL,	.driver = &i2c_driver_ks0127,	.usage_count = 0};static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind){	struct ks0127 *ks;	struct i2c_client *client;	client = kzalloc(sizeof(*client), GFP_KERNEL);	if (client == NULL)		return -ENOMEM;	memcpy(client, &ks0127_client_tmpl, sizeof(*client));	ks = kzalloc(sizeof(*ks), GFP_KERNEL);	if (ks == NULL) {		kfree(client);		return -ENOMEM;	}	i2c_set_clientdata(client, ks);	client->adapter = adapter;	client->addr = addr;	sprintf(client->name, "ks0127-%02x", adapter->id);	ks->client = client;	ks->addr = addr;	ks->ks_type = KS_TYPE_UNKNOWN;	/* power up */	ks0127_write(ks, KS_CMDA, 0x2c);	mdelay(10);	/* reset the device */	ks0127_reset(ks);	printk(KERN_INFO "ks0127: attach: %s video decoder\n",	       ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");	i2c_attach_client(client);	return 0;}static int ks0127_probe(struct i2c_adapter *adapter){	if (adapter->id == I2C_HW_B_ZR36067)		return i2c_probe(adapter, &addr_data, ks0127_found_proc);	return 0;}static int ks0127_detach(struct i2c_client *client){	struct ks0127 *ks = i2c_get_clientdata(client);	ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/	ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */	i2c_detach_client(client);	kfree(ks);	kfree(client);	dprintk("ks0127: detach\n");	return 0;}static int __devinit ks0127_init_module(void){	init_reg_defaults();	return i2c_add_driver(&i2c_driver_ks0127);}static void __devexit ks0127_cleanup_module(void){	i2c_del_driver(&i2c_driver_ks0127);}module_init(ks0127_init_module);module_exit(ks0127_cleanup_module);

⌨️ 快捷键说明

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