// SPDX-License-Identifier: GPL-2.0-or-later
/*
mxb - v4l2 driver for the Multimedia eXtension Board
Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
for further details about this card.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DEBUG_VARIABLE debug
#include <media/drv-intf/saa7146_vv.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>
#include <media/i2c/saa7115.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "tea6415c.h"
#include "tea6420.h"
#define MXB_AUDIOS 6
#define I2C_SAA7111A 0x24
#define I2C_TDA9840 0x42
#define I2C_TEA6415C 0x43
#define I2C_TEA6420_1 0x4c
#define I2C_TEA6420_2 0x4d
#define I2C_TUNER 0x60
#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
/* global variable */
static int mxb_num;
/* initial frequence the tuner will be tuned to.
in verden (lower saxony, germany) 4148 is a
channel called "phoenix" */
static int freq = 4148;
module_param(freq, int, 0644);
MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define MXB_INPUTS 4
enum { TUNER, AUX1, AUX3, AUX3_YC };
static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
{ TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
{ AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
{ AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
{ AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
};
/* this array holds the information, which port of the saa7146 each
input actually uses. the mxb uses port 0 for every input */
static struct {
int hps_source;
int hps_sync;
} input_port_selection[MXB_INPUTS] = {
{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
};
/* this array holds the information of the audio source (mxb_audios),
which has to be switched corresponding to the video source (mxb_channels) */
static int video_audio_connect[MXB_INPUTS] =
{ 0, 1, 3, 3 };
struct mxb_routing {
u32 input;
u32 output;
};
/* these are the available audio sources, which can switched
to the line- and cd-output individually */
static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
{
.index = 0,
.name = "Tuner",
.capability = V4L2_AUDCAP_STEREO,
} , {
.index = 1,
.name = "AUX1",
.capability = V4L2_AUDCAP_STEREO,
} , {
.index = 2,
.name = "AUX2",
.capability = V4L2_AUDCAP_STEREO,
} , {
.index = 3,
.name = "AUX3",
.capability = V4L2_AUDCAP_STEREO,
} , {
.index = 4,
.name = "Radio (X9)",
.capability = V4L2_AUDCAP_STEREO,
} , {
.index = 5,
.name = "CD-ROM (X10)",
.capability = V4L2_AUDCAP_STEREO,
}
};
/* These are the necessary input-output-pins for bringing one audio source
(see above) to the CD-output. Note that gain is set to 0 in this table. */
static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
{ { 1, 1 }, { 1, 1 } }, /* Tuner */
{ { 5, 1 }, { 6, 1 } }, /* AUX 1 */
{ { 4, 1 }, { 6, 1 } }, /* AUX 2 */
{ { 3, 1 }, { 6, 1 } }, /* AUX 3 */
{ { 1, 1 }, { 3, 1 } }, /* Radio */
{ { 1, 1 }, { 2, 1 } }, /* CD-Rom */
{ { 6, 1 }, { 6, 1 } } /* Mute */
};
/* These are the necessary input-output-pins for bringing one audio source
(see above) to the line-output. Note that gain is set to 0 in this table. */
static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
{ { 2, 3 }, { 1, 2 } },
{ { 5, 3 }, { 6, 2 } },
{ { 4, 3 }, { 6, 2 } },
{ { 3, 3 }, { 6, 2 } },
{ { 2, 3 }, { 3, 2 } },
{ { 2, 3 }, { 2, 2 } },
{ { 6, 3 }, { 6, 2 } } /* Mute */
};
struct mxb
{
struct video_device video_dev;
struct video_device vbi_dev;
struct i2c_adapter i2c_adapter;
struct v4l2_subdev *saa7111a;
struct v4l2_subdev *tda9840;
struct v4l2_subdev *tea6415c;
struct v4l2_subdev *tuner;
struct v4l2_subdev *tea6420_1;
struct