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

📄 saa7191.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		return saa7191_set_norm(client, SAA7191_NORM_PAL);	}}static int saa7191_get_control(struct i2c_client *client,			       struct saa7191_control *ctrl){	u8 reg;	int ret = 0;	switch (ctrl->type) {	case SAA7191_CONTROL_BANDPASS:	case SAA7191_CONTROL_BANDPASS_WEIGHT:	case SAA7191_CONTROL_CORING:		reg = saa7191_read_reg(client, SAA7191_REG_LUMA);		switch (ctrl->type) {		case SAA7191_CONTROL_BANDPASS:			ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)				>> SAA7191_LUMA_BPSS_SHIFT;			break;		case SAA7191_CONTROL_BANDPASS_WEIGHT:			ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)				>> SAA7191_LUMA_APER_SHIFT;			break;		case SAA7191_CONTROL_CORING:			ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)				>> SAA7191_LUMA_CORI_SHIFT;			break;		}		break;	case SAA7191_CONTROL_FORCE_COLOUR:	case SAA7191_CONTROL_CHROMA_GAIN:		reg = saa7191_read_reg(client, SAA7191_REG_GAIN);		if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR)			ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;		else			ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)				>> SAA7191_GAIN_LFIS_SHIFT;		break;	case SAA7191_CONTROL_HUE:		reg = saa7191_read_reg(client, SAA7191_REG_HUEC);		if (reg < 0x80)			reg += 0x80;		else			reg -= 0x80;		ctrl->value = (s32)reg;		break;	case SAA7191_CONTROL_VTRC:		reg = saa7191_read_reg(client, SAA7191_REG_STDC);		ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;		break;	case SAA7191_CONTROL_LUMA_DELAY:		reg = saa7191_read_reg(client, SAA7191_REG_CTL3);		ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)			>> SAA7191_CTL3_YDEL_SHIFT;		if (ctrl->value >= 4)			ctrl->value -= 8;		break;	case SAA7191_CONTROL_VNR:		reg = saa7191_read_reg(client, SAA7191_REG_CTL4);		ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)			>> SAA7191_CTL4_VNOI_SHIFT;		break;	default:		ret = -EINVAL;	}	return ret;}static int saa7191_set_control(struct i2c_client *client,			       struct saa7191_control *ctrl){	u8 reg;	int ret = 0;	switch (ctrl->type) {	case SAA7191_CONTROL_BANDPASS:	case SAA7191_CONTROL_BANDPASS_WEIGHT:	case SAA7191_CONTROL_CORING:		reg = saa7191_read_reg(client, SAA7191_REG_LUMA);		switch (ctrl->type) {		case SAA7191_CONTROL_BANDPASS:			reg &= ~SAA7191_LUMA_BPSS_MASK;			reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)				& SAA7191_LUMA_BPSS_MASK;			break;		case SAA7191_CONTROL_BANDPASS_WEIGHT:			reg &= ~SAA7191_LUMA_APER_MASK;			reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)				& SAA7191_LUMA_APER_MASK;			break;		case SAA7191_CONTROL_CORING:			reg &= ~SAA7191_LUMA_CORI_MASK;			reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)				& SAA7191_LUMA_CORI_MASK;			break;		}		ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg);		break;	case SAA7191_CONTROL_FORCE_COLOUR:	case SAA7191_CONTROL_CHROMA_GAIN:		reg = saa7191_read_reg(client, SAA7191_REG_GAIN);		if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) {			if (ctrl->value)				reg |= SAA7191_GAIN_COLO;			else				reg &= ~SAA7191_GAIN_COLO;		} else {			reg &= ~SAA7191_GAIN_LFIS_MASK;			reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)				& SAA7191_GAIN_LFIS_MASK;		}		ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg);		break;	case SAA7191_CONTROL_HUE:		reg = ctrl->value & 0xff;		if (reg < 0x80)			reg += 0x80;		else			reg -= 0x80;		ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg);		break;	case SAA7191_CONTROL_VTRC:		reg = saa7191_read_reg(client, SAA7191_REG_STDC);		if (ctrl->value)			reg |= SAA7191_STDC_VTRC;		else			reg &= ~SAA7191_STDC_VTRC;		ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg);		break;	case SAA7191_CONTROL_LUMA_DELAY: {		s32 value = ctrl->value;		if (value < 0)			value += 8;		reg = saa7191_read_reg(client, SAA7191_REG_CTL3);		reg &= ~SAA7191_CTL3_YDEL_MASK;		reg |= (value << SAA7191_CTL3_YDEL_SHIFT)			& SAA7191_CTL3_YDEL_MASK;		ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg);		break;	}	case SAA7191_CONTROL_VNR:		reg = saa7191_read_reg(client, SAA7191_REG_CTL4);		reg &= ~SAA7191_CTL4_VNOI_MASK;		reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)			& SAA7191_CTL4_VNOI_MASK;		ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg);		break;	default:		ret = -EINVAL;	}	return ret;}/* I2C-interface */static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind){	int err = 0;	struct saa7191 *decoder;	struct i2c_client *client;	printk(KERN_INFO "Philips SAA7191 driver version %s\n",	       SAA7191_MODULE_VERSION);	client = kmalloc(sizeof(*client), GFP_KERNEL);	if (!client)		return -ENOMEM;	decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);	if (!decoder) {		err = -ENOMEM;		goto out_free_client;	}	memset(client, 0, sizeof(struct i2c_client));	memset(decoder, 0, sizeof(struct saa7191));	client->addr = addr;	client->adapter = adap;	client->driver = &i2c_driver_saa7191;	client->flags = 0;	strcpy(client->name, "saa7191 client");	i2c_set_clientdata(client, decoder);	decoder->client = client;	err = i2c_attach_client(client);	if (err)		goto out_free_decoder;	err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq);	if (err) {		printk(KERN_ERR "SAA7191 initialization failed\n");		goto out_detach_client;	}	printk(KERN_INFO "SAA7191 initialized\n");	decoder->input = SAA7191_INPUT_COMPOSITE;	decoder->norm = SAA7191_NORM_PAL;	err = saa7191_autodetect_norm(client);	if (err && (err != -EBUSY)) {		printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");	}	return 0;out_detach_client:	i2c_detach_client(client);out_free_decoder:	kfree(decoder);out_free_client:	kfree(client);	return err;}static int saa7191_probe(struct i2c_adapter *adap){	/* Always connected to VINO */	if (adap->id == I2C_HW_SGI_VINO)		return saa7191_attach(adap, SAA7191_ADDR, 0);	/* Feel free to add probe here :-) */	return -ENODEV;}static int saa7191_detach(struct i2c_client *client){	struct saa7191 *decoder = i2c_get_clientdata(client);	i2c_detach_client(client);	kfree(decoder);	kfree(client);	return 0;}static int saa7191_command(struct i2c_client *client, unsigned int cmd,			   void *arg){	struct saa7191 *decoder = i2c_get_clientdata(client);	switch (cmd) {	case DECODER_GET_CAPABILITIES: {		struct video_decoder_capability *cap = arg;		cap->flags  = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |			      VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;		cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1;		cap->outputs = 1;		break;	}	case DECODER_GET_STATUS: {		int *iarg = arg;		u8 status;		int res = 0;		if (saa7191_read_status(client, &status)) {			return -EIO;		}		if ((status & SAA7191_STATUS_HLCK) == 0)			res |= DECODER_STATUS_GOOD;		if (status & SAA7191_STATUS_CODE)			res |= DECODER_STATUS_COLOR;		switch (decoder->norm) {		case SAA7191_NORM_NTSC:			res |= DECODER_STATUS_NTSC;			break;		case SAA7191_NORM_PAL:			res |= DECODER_STATUS_PAL;			break;		case SAA7191_NORM_SECAM:			res |= DECODER_STATUS_SECAM;			break;		case SAA7191_NORM_AUTO:		default:			if (status & SAA7191_STATUS_FIDT)				res |= DECODER_STATUS_NTSC;			else				res |= DECODER_STATUS_PAL;			break;		}		*iarg = res;		break;	}	case DECODER_SET_NORM: {		int *iarg = arg;		switch (*iarg) {		case VIDEO_MODE_AUTO:			return saa7191_autodetect_norm(client);		case VIDEO_MODE_PAL:			return saa7191_set_norm(client, SAA7191_NORM_PAL);		case VIDEO_MODE_NTSC:			return saa7191_set_norm(client, SAA7191_NORM_NTSC);		case VIDEO_MODE_SECAM:			return saa7191_set_norm(client, SAA7191_NORM_SECAM);		default:			return -EINVAL;		}		break;	}	case DECODER_SET_INPUT:	{		int *iarg = arg;		switch (client->adapter->id) {		case I2C_HW_SGI_VINO:			return saa7191_set_input(client, *iarg);		default:			if (*iarg != 0)				return -EINVAL;		}		break;	}	case DECODER_SET_OUTPUT: {		int *iarg = arg;		/* not much choice of outputs */		if (*iarg != 0)			return -EINVAL;		break;	}	case DECODER_ENABLE_OUTPUT: {		/* Always enabled */		break;	}	case DECODER_SET_PICTURE: {		struct video_picture *pic = arg;		unsigned val;		int err;		val = (pic->hue >> 8) - 0x80;		err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);		if (err)			return -EIO;		break;	}	case DECODER_SAA7191_GET_STATUS: {		struct saa7191_status *status = arg;		u8 status_reg;		if (saa7191_read_status(client, &status_reg))			return -EIO;		status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)			? 1 : 0;		status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT)			? 1 : 0;		status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0;		status->input = decoder->input;		status->norm = decoder->norm;		break;	}	case DECODER_SAA7191_SET_NORM: {		int *norm = arg;		switch (*norm) {		case SAA7191_NORM_AUTO:			return saa7191_autodetect_norm(client);		case SAA7191_NORM_AUTO_EXT:			return saa7191_autodetect_norm_extended(client);		default:			return saa7191_set_norm(client, *norm);		}	}	case DECODER_SAA7191_GET_CONTROL: {		return saa7191_get_control(client, arg);	}	case DECODER_SAA7191_SET_CONTROL: {		return saa7191_set_control(client, arg);	}	default:		return -EINVAL;	}	return 0;}static struct i2c_driver i2c_driver_saa7191 = {	.owner		= THIS_MODULE,	.name		= "saa7191",	.id		= I2C_DRIVERID_SAA7191,	.flags		= I2C_DF_NOTIFY,	.attach_adapter = saa7191_probe,	.detach_client	= saa7191_detach,	.command	= saa7191_command};static int saa7191_init(void){	return i2c_add_driver(&i2c_driver_saa7191);}static void saa7191_exit(void){	i2c_del_driver(&i2c_driver_saa7191);}module_init(saa7191_init);module_exit(saa7191_exit);

⌨️ 快捷键说明

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