Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2474ed44 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (3582): Implement correct msp3400 input/output routing



- implement VIDIOC_INT_S_AUDIO_ROUTING for msp3400 and tvaudio
- use the new command in bttv, pvrusb2 and em28xx.
- remove the now obsolete MSP_SET_MATRIX from msp3400 (yeah!)
- remove the obsolete VIDIOC_S_AUDIO from msp3400.

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 49965a80
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "bttvp.h"
#include <media/v4l2-common.h>
#include <media/tvaudio.h>
#include <media/msp3400.h>

#include <linux/dma-mapping.h>

@@ -934,11 +935,9 @@ static int
audio_mux(struct bttv *btv, int input, int mute)
{
	int gpio_val, signal;
	struct v4l2_audio aud_input;
	struct v4l2_control ctrl;
	struct i2c_client *c;

	memset(&aud_input, 0, sizeof(aud_input));
	gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
		   bttv_tvcards[btv->c.type].gpiomask);
	signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
@@ -953,7 +952,6 @@ audio_mux(struct bttv *btv, int input, int mute)
		gpio_val = bttv_tvcards[btv->c.type].gpiomute;
	else
		gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
	aud_input.index = btv->audio;

	gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
	if (bttv_gpio)
@@ -962,15 +960,51 @@ audio_mux(struct bttv *btv, int input, int mute)
		return 0;

	ctrl.id = V4L2_CID_AUDIO_MUTE;
	/* take automute into account, just btv->mute is not enough */
	ctrl.value = mute;
	ctrl.value = btv->mute;
	bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
	c = btv->i2c_msp34xx_client;
	if (c)
		c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
	if (c) {
		struct v4l2_routing route;

		/* Note: the inputs tuner/radio/extern/intern are translated
		   to msp routings. This assumes common behavior for all msp3400
		   based TV cards. When this assumption fails, then the
		   specific MSP routing must be added to the card table.
		   For now this is sufficient. */
		switch (input) {
		case TVAUDIO_INPUT_RADIO:
			route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
			break;
		case TVAUDIO_INPUT_EXTERN:
			route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
			break;
		case TVAUDIO_INPUT_INTERN:
			/* Yes, this is the same input as for RADIO. I doubt
			   if this is ever used. The only board with an INTERN
			   input is the BTTV_BOARD_AVERMEDIA98. I wonder how
			   that was tested. My guess is that the whole INTERN
			   input does not work. */
			route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
			break;
		case TVAUDIO_INPUT_TUNER:
		default:
			route.input = MSP_INPUT_DEFAULT;
			break;
		}
		route.output = MSP_OUTPUT_DEFAULT;
		c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
	}
	c = btv->i2c_tvaudio_client;
	if (c)
		c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
	if (c) {
		struct v4l2_routing route;

		route.input = input;
		route.output = 0;
		c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
	}
	return 0;
}

+5 −3
Original line number Diff line number Diff line
@@ -28,8 +28,9 @@
#include <linux/i2c.h>
#include <linux/usb.h>
#include <media/tuner.h>
#include <media/audiochip.h>
#include <media/msp3400.h>
#include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h>

#include "em28xx.h"
@@ -146,11 +147,12 @@ struct em28xx_board em28xx_boards[] = {
		.input          = {{
			.type     = EM28XX_VMUX_TELEVISION,
			.vmux     = 0,
			.amux     = 6,
			.amux     = MSP_INPUT_DEFAULT,
		},{
			.type     = EM28XX_VMUX_SVIDEO,
			.vmux     = 2,
			.amux     = 1,
			.amux     = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
					MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
		}},
	},
	[EM2820_BOARD_MSI_VOX_USB_2] = {
+7 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include "em28xx.h"
#include <media/tuner.h>
#include <media/v4l2-common.h>
#include <media/msp3400.h>

#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
		      "Markus Rechberger <mrechberger@gmail.com>, " \
@@ -216,9 +217,14 @@ static void video_mux(struct em28xx *dev, int index)
	em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);

	if (dev->has_msp34xx) {
		struct v4l2_routing route;

		if (dev->i2s_speed)
			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
		em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput);
		route.input = dev->ctl_ainput;
		route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
		/* Note: this is msp3400 specific */
		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
		ainput = EM28XX_AUDIO_SRC_TUNER;
		em28xx_audio_source(dev, ainput);
	} else {
+31 −36
Original line number Diff line number Diff line
@@ -555,7 +555,6 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
	struct msp_state *state = i2c_get_clientdata(client);
	int scart = -1;

	if (msp_debug >= 2)
		v4l_i2c_print_ioctl(client, cmd);
@@ -660,15 +659,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
		break;
	}

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

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

	/* --- v4l2 ioctls --- */
	case VIDIOC_S_STD:
	{
@@ -682,35 +672,37 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
		return 0;
	}

	case VIDIOC_S_AUDIO:
	case VIDIOC_INT_G_AUDIO_ROUTING:
	{
		struct v4l2_audio *sarg = arg;
		struct v4l2_routing *rt = arg;

		switch (sarg->index) {
		case TVAUDIO_INPUT_RADIO:
			/* Hauppauge uses IN2 for the radio */
			state->mode = MSP_MODE_FM_RADIO;
			scart       = SCART_IN2;
			break;
		case TVAUDIO_INPUT_EXTERN:
			/* IN1 is often used for external input ... */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN1;
			break;
		case TVAUDIO_INPUT_INTERN:
			/* ... sometimes it is IN2 through ;) */
			state->mode = MSP_MODE_EXTERN;
			scart       = SCART_IN2;
			break;
		case TVAUDIO_INPUT_TUNER:
			state->mode = -1;
		*rt = state->routing;
		break;
	}
		if (scart >= 0) {
			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
			msp_set_scart(client, scart, 0);

	case VIDIOC_INT_S_AUDIO_ROUTING:
	{
		struct v4l2_routing *rt = arg;
		int tuner = (rt->input >> 3) & 1;
		int old_tuner = (state->routing.input >> 3) & 1;
		int sc_in = rt->input & 0x7;
		int sc1_out = rt->output & 0xf;
		int sc2_out = (rt->output >> 4) & 0xf;
		u16 val;

		state->routing = *rt;
		if (state->opmode == OPMODE_AUTOSELECT) {
			val = msp_read_dem(client, 0x30) & ~0x100;
			msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
		} else {
			val = msp_read_dem(client, 0xbb) & ~0x100;
			msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
		}
		msp_set_scart(client, sc_in, 0);
		msp_set_scart(client, sc1_out, 1);
		msp_set_scart(client, sc2_out, 2);
		msp_set_audmode(client);
		if (tuner != old_tuner)
			msp_wake_thread(client);
		break;
	}
@@ -941,6 +933,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
	state->muted = 0;
	state->i2s_mode = 0;
	init_waitqueue_head(&state->wq);
	/* These are the reset input/output positions */
	state->routing.input = MSP_INPUT_DEFAULT;
	state->routing.output = MSP_OUTPUT_DEFAULT;

	state->rev1 = msp_read_dsp(client, 0x1e);
	if (state->rev1 != -1)
+3 −1
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
#ifndef MSP3400_DRIVER_H
#define MSP3400_DRIVER_H

#include <media/msp3400.h>

/* ---------------------------------------------------------------------- */

/* This macro is allowed for *constants* only, gcc must calculate it
@@ -72,7 +74,7 @@ struct msp_state {
	int i2s_mode;
	int main, second;	/* sound carrier */
	int input;
	int source;             /* see msp34xxg_set_source */
	struct v4l2_routing routing;

	/* v4l2 */
	int audmode;
Loading