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

📄 cx25840-core.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	case 0x14: p = "tri with SAP"; break;	case 0xfe: p = "forced mode"; break;	default: p = "not defined";	}	v4l_info(client, "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";	}	v4l_info(client, "Detected audio standard:   %s\n", p);	v4l_info(client, "Audio muted:               %s\n",		    (state->unmute_volume >= 0) ? "yes" : "no");	v4l_info(client, "Audio microcontroller:     %s\n",		    (download_ctl & 0x10) ?				((mute_ctl & 0x2) ? "detecting" : "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";	}	v4l_info(client, "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";		}		v4l_info(client, "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";		}		v4l_info(client, "Configured audio system:   %s\n", p);	}	if (aud_input) {		v4l_info(client, "Specified audio input:     Tuner (In%d)\n", aud_input);	} else {		v4l_info(client, "Specified audio input:     External\n");	}	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";	}	v4l_info(client, "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";		}		v4l_info(client, "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";		}		v4l_info(client, "Selected 45 MHz format:    %s\n", p);	}}/* ----------------------------------------------------------------------- */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;	struct v4l2_routing *route = arg;	/* ignore these commands */	switch (cmd) {		case TUNER_SET_TYPE_ADDR:			return 0;	}	if (!state->is_initialized) {		v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd);		/* initialize on first use */		state->is_initialized = 1;		if (state->is_cx25836)			cx25836_initialize(client);		else if (state->is_cx23885)			cx23885_initialize(client);		else			cx25840_initialize(client);	}	switch (cmd) {#ifdef CONFIG_VIDEO_ADV_DEBUG	/* ioctls to allow direct access to the	 * cx25840 registers for testing */	case VIDIOC_DBG_G_REGISTER:	case VIDIOC_DBG_S_REGISTER:	{		struct v4l2_register *reg = arg;		if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))			return -EINVAL;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if (cmd == VIDIOC_DBG_G_REGISTER)			reg->val = cx25840_read(client, reg->reg & 0x0fff);		else			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:		return cx25840_audio(client, cmd, arg);	case VIDIOC_STREAMON:		v4l_dbg(1, cx25840_debug, client, "enable output\n");		if (state->is_cx23885) {			u8 v = (cx25840_read(client, 0x421) | 0x0b);			cx25840_write(client, 0x421, v);		} else {			cx25840_write(client, 0x115,				state->is_cx25836 ? 0x0c : 0x8c);			cx25840_write(client, 0x116,				state->is_cx25836 ? 0x04 : 0x07);		}		break;	case VIDIOC_STREAMOFF:		v4l_dbg(1, cx25840_debug, client, "disable output\n");		if (state->is_cx23885) {			u8 v = cx25840_read(client, 0x421) & ~(0x0b);			cx25840_write(client, 0x421, v);		} else {			cx25840_write(client, 0x115, 0x00);			cx25840_write(client, 0x116, 0x00);		}		break;	case VIDIOC_LOG_STATUS:		log_video_status(client);		if (!state->is_cx25836)			log_audio_status(client);		break;	case VIDIOC_G_CTRL:		return get_v4lctrl(client, (struct v4l2_control *)arg);	case VIDIOC_S_CTRL:		return set_v4lctrl(client, (struct v4l2_control *)arg);	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *qc = arg;		switch (qc->id) {			case V4L2_CID_BRIGHTNESS:			case V4L2_CID_CONTRAST:			case V4L2_CID_SATURATION:			case V4L2_CID_HUE:				return v4l2_ctrl_query_fill_std(qc);			default:				break;		}		if (state->is_cx25836)			return -EINVAL;		switch (qc->id) {			case V4L2_CID_AUDIO_VOLUME:				return v4l2_ctrl_query_fill(qc, 0, 65535,					65535 / 100, state->default_volume);			case V4L2_CID_AUDIO_MUTE:			case V4L2_CID_AUDIO_BALANCE:			case V4L2_CID_AUDIO_BASS:			case V4L2_CID_AUDIO_TREBLE:				return v4l2_ctrl_query_fill_std(qc);			default:				return -EINVAL;		}		return -EINVAL;	}	case VIDIOC_G_STD:		*(v4l2_std_id *)arg = state->std;		break;	case VIDIOC_S_STD:		if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)			return 0;		state->radio = 0;		state->std = *(v4l2_std_id *)arg;		return set_v4lstd(client);	case AUDC_SET_RADIO:		state->radio = 1;		break;	case VIDIOC_INT_G_VIDEO_ROUTING:		route->input = state->vid_input;		route->output = 0;		break;	case VIDIOC_INT_S_VIDEO_ROUTING:		return set_input(client, route->input, state->aud_input);	case VIDIOC_INT_G_AUDIO_ROUTING:		if (state->is_cx25836)			return -EINVAL;		route->input = state->aud_input;		route->output = 0;		break;	case VIDIOC_INT_S_AUDIO_ROUTING:		if (state->is_cx25836)			return -EINVAL;		return set_input(client, state->vid_input, route->input);	case VIDIOC_S_FREQUENCY:		if (!state->is_cx25836) {			input_change(client);		}		break;	case VIDIOC_G_TUNER:	{		u8 vpres = cx25840_read(client, 0x40e) & 0x20;		u8 mode;		int val = 0;		if (state->radio)			break;		vt->signal = vpres ? 0xffff : 0x0;		if (state->is_cx25836)			break;		vt->capability |=		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;		mode = cx25840_read(client, 0x804);		/* 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;		vt->audmode = state->audmode;		break;	}	case VIDIOC_S_TUNER:		if (state->radio || state->is_cx25836)			break;		switch (vt->audmode) {		case V4L2_TUNER_MODE_MONO:			/* mono      -> mono			   stereo    -> mono			   bilingual -> lang1 */			cx25840_and_or(client, 0x809, ~0xf, 0x00);			break;		case V4L2_TUNER_MODE_STEREO:		case V4L2_TUNER_MODE_LANG1:			/* mono      -> mono			   stereo    -> stereo			   bilingual -> lang1 */			cx25840_and_or(client, 0x809, ~0xf, 0x04);			break;		case V4L2_TUNER_MODE_LANG1_LANG2:			/* mono      -> mono			   stereo    -> stereo			   bilingual -> lang1/lang2 */			cx25840_and_or(client, 0x809, ~0xf, 0x07);			break;		case V4L2_TUNER_MODE_LANG2:			/* mono      -> mono			   stereo    -> stereo			   bilingual -> lang2 */			cx25840_and_or(client, 0x809, ~0xf, 0x01);			break;		default:			return -EINVAL;		}		state->audmode = vt->audmode;		break;	case VIDIOC_G_FMT:		return get_v4lfmt(client, (struct v4l2_format *)arg);	case VIDIOC_S_FMT:		return set_v4lfmt(client, (struct v4l2_format *)arg);	case VIDIOC_INT_RESET:		if (state->is_cx25836)			cx25836_initialize(client);		else if (state->is_cx23885)			cx23885_initialize(client);		else			cx25840_initialize(client);		break;	case VIDIOC_G_CHIP_IDENT:		return v4l2_chip_ident_i2c_client(client, arg, state->id, state->rev);	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */static int cx25840_probe(struct i2c_client *client,			 const struct i2c_device_id *did){	struct cx25840_state *state;	u32 id;	u16 device_id;	/* Check if the adapter supports the needed features */	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))		return -EIO;	v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1);	device_id = cx25840_read(client, 0x101) << 8;	device_id |= cx25840_read(client, 0x100);	v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n", device_id);	/* The high byte of the device ID should be	 * 0x83 for the cx2583x and 0x84 for the cx2584x */	if ((device_id & 0xff00) == 0x8300) {		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;	}	else if ((device_id & 0xff00) == 0x8400) {		id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);	} else if (device_id == 0x0000) {		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;	} else if (device_id == 0x1313) {		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;	}	else {		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");		return -ENODEV;	}	state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);	if (state == NULL) {		return -ENOMEM;	}	/* Note: revision '(device_id & 0x0f) == 2' was never built. The	   marking skips from 0x1 == 22 to 0x3 == 23. */	v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",		    (device_id & 0xfff0) >> 4,		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f),		    client->addr << 1, client->adapter->name);	i2c_set_clientdata(client, state);	state->c = client;	state->is_cx25836 = ((device_id & 0xff00) == 0x8300);	state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313);	state->vid_input = CX25840_COMPOSITE7;	state->aud_input = CX25840_AUDIO8;	state->audclk_freq = 48000;	state->pvr150_workaround = 0;	state->audmode = V4L2_TUNER_MODE_LANG1;	state->unmute_volume = -1;	state->default_volume = 228 - cx25840_read(client, 0x8d4);	state->default_volume = ((state->default_volume / 2) + 23) << 9;	state->vbi_line_offset = 8;	state->id = id;	state->rev = device_id;	if (state->is_cx23885) {		/* Drive GPIO2 direction and values */		cx25840_write(client, 0x160, 0x1d);		cx25840_write(client, 0x164, 0x00);	}	return 0;}static int cx25840_remove(struct i2c_client *client){	kfree(i2c_get_clientdata(client));	return 0;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)static const struct i2c_device_id cx25840_id[] = {	{ "cx25840", 0 },	{ }};MODULE_DEVICE_TABLE(i2c, cx25840_id);#endifstatic struct v4l2_i2c_driver_data v4l2_i2c_data = {	.name = "cx25840",	.driverid = I2C_DRIVERID_CX25840,	.command = cx25840_command,	.probe = cx25840_probe,	.remove = cx25840_remove,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	.id_table = cx25840_id,#endif};

⌨️ 快捷键说明

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