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

📄 cx25840-core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			cx25840_err("%dx%d is not a valid size!\n",				    pix->width, pix->height);			return -ERANGE;		}		HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);		VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));		VSC &= 0x1fff;		if (pix->width >= 385)			filter = 0;		else if (pix->width > 192)			filter = 1;		else if (pix->width > 96)			filter = 2;		else			filter = 3;		cx25840_dbg("decoder set size %dx%d -> scale  %ux%u\n",			    pix->width, pix->height, HSC, VSC);		/* HSCALE=HSC */		cx25840_write(client, 0x418, HSC & 0xff);		cx25840_write(client, 0x419, (HSC >> 8) & 0xff);		cx25840_write(client, 0x41a, HSC >> 16);		/* VSCALE=VSC */		cx25840_write(client, 0x41c, VSC & 0xff);		cx25840_write(client, 0x41d, VSC >> 8);		/* VS_INTRLACE=1 VFILT=filter */		cx25840_write(client, 0x41e, 0x8 | filter);		break;	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);	case V4L2_BUF_TYPE_VBI_CAPTURE:		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */static int cx25840_command(struct i2c_client *client, unsigned int cmd,			   void *arg){	struct cx25840_state *state = i2c_get_clientdata(client);	struct v4l2_tuner *vt = arg;	int result = 0;	switch (cmd) {	case 0:		break;#ifdef CONFIG_VIDEO_ADV_DEBUG	/* ioctls to allow direct access to the	 * cx25840 registers for testing */	case VIDIOC_INT_G_REGISTER:	{		struct v4l2_register *reg = arg;		if (reg->i2c_id != I2C_DRIVERID_CX25840)			return -EINVAL;		reg->val = cx25840_read(client, reg->reg & 0x0fff);		break;	}	case VIDIOC_INT_S_REGISTER:	{		struct v4l2_register *reg = arg;		if (reg->i2c_id != I2C_DRIVERID_CX25840)			return -EINVAL;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);		break;	}#endif	case VIDIOC_INT_DECODE_VBI_LINE:		return cx25840_vbi(client, cmd, arg);	case VIDIOC_INT_AUDIO_CLOCK_FREQ:	case AUDC_SET_INPUT:		result = cx25840_audio(client, cmd, arg);		break;	case VIDIOC_STREAMON:		cx25840_dbg("enable output\n");		cx25840_write(client, 0x115, 0x8c);		cx25840_write(client, 0x116, 0x07);		break;	case VIDIOC_STREAMOFF:		cx25840_dbg("disable output\n");		cx25840_write(client, 0x115, 0x00);		cx25840_write(client, 0x116, 0x00);		break;	case VIDIOC_LOG_STATUS:		log_status(client);		break;	case VIDIOC_G_CTRL:		result = get_v4lctrl(client, (struct v4l2_control *)arg);		break;	case VIDIOC_S_CTRL:		result = set_v4lctrl(client, (struct v4l2_control *)arg);		break;	case VIDIOC_G_STD:		*(v4l2_std_id *)arg = cx25840_get_v4lstd(client);		break;	case VIDIOC_S_STD:		result = set_v4lstd(client, *(v4l2_std_id *)arg);		break;	case VIDIOC_G_INPUT:		*(int *)arg = state->input;		break;	case VIDIOC_S_INPUT:		result = set_input(client, *(int *)arg);		break;	case VIDIOC_S_FREQUENCY:		input_change(client);		break;	case VIDIOC_G_TUNER:	{		u8 mode = cx25840_read(client, 0x804);		u8 pref = cx25840_read(client, 0x809) & 0xf;		u8 vpres = cx25840_read(client, 0x80a) & 0x10;		int val = 0;		vt->capability |=		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;		vt->signal = vpres ? 0xffff : 0x0;		/* get rxsubchans and audmode */		if ((mode & 0xf) == 1)			val |= V4L2_TUNER_SUB_STEREO;		else			val |= V4L2_TUNER_SUB_MONO;		if (mode == 2 || mode == 4)			val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;		if (mode & 0x10)			val |= V4L2_TUNER_SUB_SAP;		vt->rxsubchans = val;		switch (pref) {		case 0:			vt->audmode = V4L2_TUNER_MODE_MONO;			break;		case 1:		case 2:			vt->audmode = V4L2_TUNER_MODE_LANG2;			break;		case 4:		default:			vt->audmode = V4L2_TUNER_MODE_STEREO;		}		break;	}	case VIDIOC_S_TUNER:		switch (vt->audmode) {		case V4L2_TUNER_MODE_MONO:		case V4L2_TUNER_MODE_LANG1:			/* Force PREF_MODE to MONO */			cx25840_and_or(client, 0x809, ~0xf, 0x00);			break;		case V4L2_TUNER_MODE_STEREO:			/* Force PREF_MODE to STEREO */			cx25840_and_or(client, 0x809, ~0xf, 0x04);			break;		case V4L2_TUNER_MODE_LANG2:			/* Force PREF_MODE to LANG2 */			cx25840_and_or(client, 0x809, ~0xf, 0x01);			break;		}		break;	case VIDIOC_G_FMT:		result = get_v4lfmt(client, (struct v4l2_format *)arg);		break;	case VIDIOC_S_FMT:		result = set_v4lfmt(client, (struct v4l2_format *)arg);		break;	case VIDIOC_INT_RESET:		cx25840_initialize(client, 0);		break;	case VIDIOC_INT_G_CHIP_IDENT:		*(enum v4l2_chip_ident *)arg =			V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf);		break;	default:		cx25840_err("invalid ioctl %x\n", cmd);		return -EINVAL;	}	return result;}/* ----------------------------------------------------------------------- */static struct i2c_driver i2c_driver_cx25840;static int cx25840_detect_client(struct i2c_adapter *adapter, int address,				 int kind){	struct i2c_client *client;	struct cx25840_state *state;	u16 device_id;	/* Check if the adapter supports the needed features	 * Not until kernel version 2.6.11 did the bit-algo	 * correctly report that it would do an I2C-level xfer */	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))		return 0;	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);	if (client == 0)		return -ENOMEM;	memset(client, 0, sizeof(struct i2c_client));	client->addr = address;	client->adapter = adapter;	client->driver = &i2c_driver_cx25840;	client->flags = I2C_CLIENT_ALLOW_USE;	snprintf(client->name, sizeof(client->name) - 1, "cx25840");	cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1);	device_id = cx25840_read(client, 0x101) << 8;	device_id |= cx25840_read(client, 0x100);	/* The high byte of the device ID should be	 * 0x84 if chip is present */	if ((device_id & 0xff00) != 0x8400) {		cx25840_dbg("cx25840 not found\n");		kfree(client);		return 0;	}	cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n",		    (device_id & 0xfff0) >> 4,		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,		    address << 1, adapter->name);	state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL);	if (state == NULL) {		kfree(client);		return -ENOMEM;	}	i2c_set_clientdata(client, state);	memset(state, 0, sizeof(struct cx25840_state));	state->input = CX25840_TUNER;	state->audclk_freq = V4L2_AUDCLK_48_KHZ;	state->audio_input = AUDIO_TUNER;	state->cardtype = CARDTYPE_PVR150;	cx25840_initialize(client, 1);	i2c_attach_client(client);	return 0;}static int cx25840_attach_adapter(struct i2c_adapter *adapter){#ifdef I2C_CLASS_TV_ANALOG	if (adapter->class & I2C_CLASS_TV_ANALOG)#else	if (adapter->id == I2C_HW_B_BT848)#endif		return i2c_probe(adapter, &addr_data, &cx25840_detect_client);	return 0;}static int cx25840_detach_client(struct i2c_client *client){	struct cx25840_state *state = i2c_get_clientdata(client);	int err;	err = i2c_detach_client(client);	if (err) {		return err;	}	kfree(state);	kfree(client);	return 0;}/* ----------------------------------------------------------------------- */static struct i2c_driver i2c_driver_cx25840 = {	.name = "cx25840",	.id = I2C_DRIVERID_CX25840,	.flags = I2C_DF_NOTIFY,	.attach_adapter = cx25840_attach_adapter,	.detach_client = cx25840_detach_client,	.command = cx25840_command,	.owner = THIS_MODULE,};static int __init m__init(void){	return i2c_add_driver(&i2c_driver_cx25840);}static void __exit m__exit(void){	i2c_del_driver(&i2c_driver_cx25840);}module_init(m__init);module_exit(m__exit);/* ----------------------------------------------------------------------- */static void log_status(struct i2c_client *client){	static const char *const fmt_strs[] = {		"0x0",		"NTSC-M", "NTSC-J", "NTSC-4.43",		"PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",		"0x9", "0xA", "0xB",		"SECAM",		"0xD", "0xE", "0xF"	};	struct cx25840_state *state = i2c_get_clientdata(client);	u8 microctrl_vidfmt = cx25840_read(client, 0x80a);	u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;	u8 gen_stat1 = cx25840_read(client, 0x40d);	u8 download_ctl = cx25840_read(client, 0x803);	u8 mod_det_stat0 = cx25840_read(client, 0x804);	u8 mod_det_stat1 = cx25840_read(client, 0x805);	u8 audio_config = cx25840_read(client, 0x808);	u8 pref_mode = cx25840_read(client, 0x809);	u8 afc0 = cx25840_read(client, 0x80b);	u8 mute_ctl = cx25840_read(client, 0x8d3);	char *p;	cx25840_info("Video signal:              %spresent\n",		    (microctrl_vidfmt & 0x10) ? "" : "not ");	cx25840_info("Detected format:           %s\n",		    fmt_strs[gen_stat1 & 0xf]);	switch (mod_det_stat0) {	case 0x00: p = "mono"; break;	case 0x01: p = "stereo"; break;	case 0x02: p = "dual"; break;	case 0x04: p = "tri"; break;	case 0x10: p = "mono with SAP"; break;	case 0x11: p = "stereo with SAP"; break;	case 0x12: p = "dual with SAP"; break;	case 0x14: p = "tri with SAP"; break;	case 0xfe: p = "forced mode"; break;	default: p = "not defined";	}	cx25840_info("Detected audio mode:       %s\n", p);	switch (mod_det_stat1) {	case 0x00: p = "not defined"; break;	case 0x01: p = "EIAJ"; break;	case 0x02: p = "A2-M"; break;	case 0x03: p = "A2-BG"; break;	case 0x04: p = "A2-DK1"; break;	case 0x05: p = "A2-DK2"; break;	case 0x06: p = "A2-DK3"; break;	case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;	case 0x08: p = "AM-L"; break;	case 0x09: p = "NICAM-BG"; break;	case 0x0a: p = "NICAM-DK"; break;	case 0x0b: p = "NICAM-I"; break;	case 0x0c: p = "NICAM-L"; break;	case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;	case 0x0e: p = "IF FM Radio"; break;	case 0x0f: p = "BTSC"; break;	case 0x10: p = "high-deviation FM"; break;	case 0x11: p = "very high-deviation FM"; break;	case 0xfd: p = "unknown audio standard"; break;	case 0xfe: p = "forced audio standard"; break;	case 0xff: p = "no detected audio standard"; break;	default: p = "not defined";	}	cx25840_info("Detected audio standard:   %s\n", p);	cx25840_info("Audio muted:               %s\n",		    (mute_ctl & 0x2) ? "yes" : "no");	cx25840_info("Audio microcontroller:     %s\n",		    (download_ctl & 0x10) ? "running" : "stopped");	switch (audio_config >> 4) {	case 0x00: p = "undefined"; break;	case 0x01: p = "BTSC"; break;	case 0x02: p = "EIAJ"; break;	case 0x03: p = "A2-M"; break;	case 0x04: p = "A2-BG"; break;	case 0x05: p = "A2-DK1"; break;	case 0x06: p = "A2-DK2"; break;	case 0x07: p = "A2-DK3"; break;	case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;	case 0x09: p = "AM-L"; break;	case 0x0a: p = "NICAM-BG"; break;	case 0x0b: p = "NICAM-DK"; break;	case 0x0c: p = "NICAM-I"; break;	case 0x0d: p = "NICAM-L"; break;	case 0x0e: p = "FM radio"; break;	case 0x0f: p = "automatic detection"; break;	default: p = "undefined";	}	cx25840_info("Configured audio standard: %s\n", p);	if ((audio_config >> 4) < 0xF) {		switch (audio_config & 0xF) {		case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;		case 0x01: p = "MONO2 (LANGUAGE B)"; break;		case 0x02: p = "MONO3 (STEREO forced MONO)"; break;		case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;		case 0x04: p = "STEREO"; break;		case 0x05: p = "DUAL1 (AB)"; break;		case 0x06: p = "DUAL2 (AC) (FM)"; break;		case 0x07: p = "DUAL3 (BC) (FM)"; break;		case 0x08: p = "DUAL4 (AC) (AM)"; break;		case 0x09: p = "DUAL5 (BC) (AM)"; break;		case 0x0a: p = "SAP"; break;		default: p = "undefined";		}		cx25840_info("Configured audio mode:     %s\n", p);	} else {		switch (audio_config & 0xF) {		case 0x00: p = "BG"; break;		case 0x01: p = "DK1"; break;		case 0x02: p = "DK2"; break;		case 0x03: p = "DK3"; break;		case 0x04: p = "I"; break;		case 0x05: p = "L"; break;		case 0x06: p = "BTSC"; break;		case 0x07: p = "EIAJ"; break;		case 0x08: p = "A2-M"; break;		case 0x09: p = "FM Radio"; break;		case 0x0f: p = "automatic standard and mode detection"; break;		default: p = "undefined";		}		cx25840_info("Configured audio system:   %s\n", p);	}	cx25840_info("Specified standard:        %s\n",		    vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");	switch (state->input) {	case CX25840_COMPOSITE0: p = "Composite 0"; break;	case CX25840_COMPOSITE1: p = "Composite 1"; break;	case CX25840_SVIDEO0: p = "S-Video 0"; break;	case CX25840_SVIDEO1: p = "S-Video 1"; break;	case CX25840_TUNER: p = "Tuner"; break;	}	cx25840_info("Specified input:           %s\n", p);	cx25840_info("Specified audio input:     %s\n",		    state->audio_input == 0 ? "Tuner" : "External");	switch (state->audclk_freq) {	case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break;	case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break;	case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break;	default: p = "undefined";	}	cx25840_info("Specified audioclock freq: %s\n", p);	switch (pref_mode & 0xf) {	case 0: p = "mono/language A"; break;	case 1: p = "language B"; break;	case 2: p = "language C"; break;	case 3: p = "analog fallback"; break;	case 4: p = "stereo"; break;	case 5: p = "language AC"; break;	case 6: p = "language BC"; break;	case 7: p = "language AB"; break;	default: p = "undefined";	}	cx25840_info("Preferred audio mode:      %s\n", p);	if ((audio_config & 0xf) == 0xf) {		switch ((afc0 >> 3) & 0x3) {		case 0: p = "system DK"; break;		case 1: p = "system L"; break;		case 2: p = "autodetect"; break;		default: p = "undefined";		}		cx25840_info("Selected 65 MHz format:    %s\n", p);		switch (afc0 & 0x7) {		case 0: p = "chroma"; break;		case 1: p = "BTSC"; break;		case 2: p = "EIAJ"; break;		case 3: p = "A2-M"; break;		case 4: p = "autodetect"; break;		default: p = "undefined";		}		cx25840_info("Selected 45 MHz format:    %s\n", p);	}}

⌨️ 快捷键说明

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