Enscript Output

extractedLnx/linux-2.6.16/drivers/media/video/msp3400-driver.c_msp_command.c

static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
	struct msp_state *state = i2c_get_clientdata(client);
	u16 *sarg = arg;
	int scart = 0;

	if (msp_debug >= 2)
		v4l_i2c_print_ioctl(client, cmd);

	switch (cmd) {
	case AUDC_SET_INPUT:
		if (*sarg == state->input)
			break;
		state->input = *sarg;
		switch (*sarg) {
		case AUDIO_RADIO:
			/* Hauppauge uses IN2 for the radio */
			state->mode = MSP_MODE_FM_RADIO;
			scart       = SCART_IN2;
			break;
		case AUDIO_EXTERN_1:
			/* IN1 is often used for external input ... */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN1;
			break;
		case AUDIO_EXTERN_2:
			/* ... sometimes it is IN2 through ;) */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN2;
			break;
		case AUDIO_TUNER:
			state->mode = -1;
			break;
		default:
			if (*sarg & AUDIO_MUTE)
				msp_set_scart(client, SCART_MUTE, 0);
			break;
		}
		if (scart) {
			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
			state->audmode = V4L2_TUNER_MODE_STEREO;
			msp_set_scart(client, scart, 0);
			msp_write_dsp(client, 0x000d, 0x1900);
			if (state->opmode != OPMODE_AUTOSELECT)
				msp3400c_setstereo(client, state->audmode);
		}
		msp_wake_thread(client);
		break;

	case AUDC_SET_RADIO:
		if (state->radio)
			return 0;
		state->radio = 1;
		v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
		state->watch_stereo = 0;
		switch (state->opmode) {
		case OPMODE_MANUAL:
			/* set msp3400 to FM radio mode */
			msp3400c_setmode(client, MSP_MODE_FM_RADIO);
			msp3400c_setcarrier(client, MSP_CARRIER(10.7),
					    MSP_CARRIER(10.7));
			msp_set_audio(client);
			break;
		case OPMODE_AUTODETECT:
		case OPMODE_AUTOSELECT:
			/* the thread will do for us */
			msp_wake_thread(client);
			break;
		}
		break;

	/* --- v4l ioctls --- */
	/* take care: bttv does userspace copying, we'll get a
	   kernel pointer here... */
	case VIDIOCGAUDIO:
	{
		struct video_audio *va = arg;

		va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
		if (state->has_sound_processing)
			va->flags |= VIDEO_AUDIO_BALANCE |
				VIDEO_AUDIO_BASS |
				VIDEO_AUDIO_TREBLE;
		if (state->muted)
			va->flags |= VIDEO_AUDIO_MUTE;
		va->volume = state->volume;
		va->balance = state->volume ? state->balance : 32768;
		va->bass = state->bass;
		va->treble = state->treble;

		if (state->radio)
			break;
		if (state->opmode == OPMODE_AUTOSELECT)
			msp_any_detect_stereo(client);
		va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
		break;
	}

	case VIDIOCSAUDIO:
	{
		struct video_audio *va = arg;

		state->muted = (va->flags & VIDEO_AUDIO_MUTE);
		state->volume = va->volume;
		state->balance = va->balance;
		state->bass = va->bass;
		state->treble = va->treble;
		msp_set_audio(client);

		if (va->mode != 0 && state->radio == 0)
			msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode));
		break;
	}

	case VIDIOCSCHAN:
	{
		struct video_channel *vc = arg;
		int update = 0;
		v4l2_std_id std;

		if (state->radio)
			update = 1;
		state->radio = 0;
		if (vc->norm == VIDEO_MODE_PAL)
			std = V4L2_STD_PAL;
		else if (vc->norm == VIDEO_MODE_SECAM)
			std = V4L2_STD_SECAM;
		else
			std = V4L2_STD_NTSC;
		if (std != state->v4l2_std) {
			state->v4l2_std = std;
			update = 1;
		}
		if (update)
			msp_wake_thread(client);
		break;
	}

	case VIDIOCSFREQ:
	case VIDIOC_S_FREQUENCY:
	{
		/* new channel -- kick audio carrier scan */
		msp_wake_thread(client);
		break;
	}

	/* msp34xx specific */
	case MSP_SET_MATRIX:
	{
		struct msp_matrix *mspm = arg;

		msp_set_scart(client, mspm->input, mspm->output);
		break;
	}

	/* --- v4l2 ioctls --- */
	case VIDIOC_S_STD:
	{
		v4l2_std_id *id = arg;
		int update = state->radio || state->v4l2_std != *id;

		state->v4l2_std = *id;
		state->radio = 0;
		if (update)
			msp_wake_thread(client);
		return 0;
	}

	case VIDIOC_ENUMINPUT:
	{
		struct v4l2_input *i = arg;

		if (i->index != 0)
			return -EINVAL;

		i->type = V4L2_INPUT_TYPE_TUNER;
		switch (i->index) {
		case AUDIO_RADIO:
			strcpy(i->name, "Radio");
			break;
		case AUDIO_EXTERN_1:
			strcpy(i->name, "Extern 1");
			break;
		case AUDIO_EXTERN_2:
			strcpy(i->name, "Extern 2");
			break;
		case AUDIO_TUNER:
			strcpy(i->name, "Television");
			break;
		default:
			return -EINVAL;
		}
		return 0;
	}

	case VIDIOC_G_AUDIO:
	{
		struct v4l2_audio *a = arg;

		memset(a, 0, sizeof(*a));

		switch (a->index) {
		case AUDIO_RADIO:
			strcpy(a->name, "Radio");
			break;
		case AUDIO_EXTERN_1:
			strcpy(a->name, "Extern 1");
			break;
		case AUDIO_EXTERN_2:
			strcpy(a->name, "Extern 2");
			break;
		case AUDIO_TUNER:
			strcpy(a->name, "Television");
			break;
		default:
			return -EINVAL;
		}

		msp_any_detect_stereo(client);
		if (state->audmode == V4L2_TUNER_MODE_STEREO) {
			a->capability = V4L2_AUDCAP_STEREO;
		}

		break;
	}

	case VIDIOC_S_AUDIO:
	{
		struct v4l2_audio *sarg = arg;

		switch (sarg->index) {
		case AUDIO_RADIO:
			/* Hauppauge uses IN2 for the radio */
			state->mode = MSP_MODE_FM_RADIO;
			scart       = SCART_IN2;
			break;
		case AUDIO_EXTERN_1:
			/* IN1 is often used for external input ... */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN1;
			break;
		case AUDIO_EXTERN_2:
			/* ... sometimes it is IN2 through ;) */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN2;
			break;
		case AUDIO_TUNER:
			state->mode = -1;
			break;
		}
		if (scart) {
			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
			state->audmode = V4L2_TUNER_MODE_STEREO;
			msp_set_scart(client, scart, 0);
			msp_write_dsp(client, 0x000d, 0x1900);
		}
		if (sarg->capability == V4L2_AUDCAP_STEREO) {
			state->audmode = V4L2_TUNER_MODE_STEREO;
		} else {
			state->audmode &= ~V4L2_TUNER_MODE_STEREO;
		}
		msp_any_set_audmode(client, state->audmode);
		msp_wake_thread(client);
		break;
	}

	case VIDIOC_G_TUNER:
	{
		struct v4l2_tuner *vt = arg;

		if (state->radio)
			break;
		if (state->opmode == OPMODE_AUTOSELECT)
			msp_any_detect_stereo(client);
		vt->audmode    = state->audmode;
		vt->rxsubchans = state->rxsubchans;
		vt->capability = V4L2_TUNER_CAP_STEREO |
			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
		break;
	}

	case VIDIOC_S_TUNER:
	{
		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;

		if (state->radio)
			break;
		/* only set audmode */
		if (vt->audmode != -1 && vt->audmode != 0)
			msp_any_set_audmode(client, vt->audmode);
		break;
	}

	case VIDIOC_G_AUDOUT:
	{
		struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
		int idx = a->index;

		memset(a, 0, sizeof(*a));

		switch (idx) {
		case 0:
			strcpy(a->name, "Scart1 Out");
			break;
		case 1:
			strcpy(a->name, "Scart2 Out");
			break;
		case 2:
			strcpy(a->name, "I2S Out");
			break;
		default:
			return -EINVAL;
		}
		break;

	}

	case VIDIOC_S_AUDOUT:
	{
		struct v4l2_audioout *a = (struct v4l2_audioout *)arg;

		if (a->index < 0 || a->index > 2)
			return -EINVAL;

		v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index);
		msp_set_scart(client, state->in_scart, a->index + 1);

		break;
	}

	case VIDIOC_INT_I2S_CLOCK_FREQ:
	{
		u32 *a = (u32 *)arg;

		v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", *a);

		switch (*a) {
			case 1024000:
				state->i2s_mode = 0;
				break;
			case 2048000:
				state->i2s_mode = 1;
				break;
			default:
				return -EINVAL;
		}
		break;
	}

	case VIDIOC_QUERYCTRL:
	{
		struct v4l2_queryctrl *qc = arg;
		int i;

		for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
			if (qc->id && qc->id == msp_qctrl_std[i].id) {
				memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
				return 0;
			}
		if (!state->has_sound_processing)
			return -EINVAL;
		for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
			if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
				memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
				return 0;
			}
		return -EINVAL;
	}

	case VIDIOC_G_CTRL:
		return msp_get_ctrl(client, arg);

	case VIDIOC_S_CTRL:
		return msp_set_ctrl(client, arg);

	case VIDIOC_LOG_STATUS:
	{
		const char *p;

		if (state->opmode == OPMODE_AUTOSELECT)
			msp_any_detect_stereo(client);
		v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
				client->name, state->rev1, state->rev2);
		v4l_info(client, "Audio:    volume %d%s\n",
				state->volume, state->muted ? " (muted)" : "");
		if (state->has_sound_processing) {
			v4l_info(client, "Audio:    balance %d bass %d treble %d loudness %s\n",
					state->balance, state->bass, state->treble,
					state->loudness ? "on" : "off");
		}
		switch (state->mode) {
		case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
		case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
		case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono + FM-stereo"; break;
		case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
		case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
		case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
		case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break;
		case MSP_MODE_BTSC: p = "BTSC"; break;
		case MSP_MODE_EXTERN: p = "External input"; break;
		default: p = "unknown"; break;
		}
		if (state->opmode == OPMODE_MANUAL) {
			v4l_info(client, "Mode:     %s (%s%s)\n", p,
				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
		} else {
			v4l_info(client, "Mode:     %s\n", p);
			v4l_info(client, "Standard: %s (%s%s)\n",
				msp_standard_std_name(state->std),
				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
		}
		v4l_info(client, "ACB:      0x%04x\n", state->acb);
		break;
	}

	default:
		/* unknown */
		return -EINVAL;
	}
	return 0;
}

Generated by GNU enscript 1.6.4.