brintos

brintos / linux-shallow public Read only

0
0
Text · 25.9 KiB · a14b839 Raw
879 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3    mxb - v4l2 driver for the Multimedia eXtension Board4 5    Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>6 7    Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html8    for further details about this card.9 10*/11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt13 14#define DEBUG_VARIABLE debug15 16#include <media/drv-intf/saa7146_vv.h>17#include <media/tuner.h>18#include <media/v4l2-common.h>19#include <media/i2c/saa7115.h>20#include <linux/module.h>21#include <linux/kernel.h>22 23#include "tea6415c.h"24#include "tea6420.h"25 26#define MXB_AUDIOS	627 28#define I2C_SAA7111A  0x2429#define	I2C_TDA9840   0x4230#define	I2C_TEA6415C  0x4331#define	I2C_TEA6420_1 0x4c32#define	I2C_TEA6420_2 0x4d33#define	I2C_TUNER     0x6034 35#define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)36 37/* global variable */38static int mxb_num;39 40/* initial frequence the tuner will be tuned to.41   in verden (lower saxony, germany) 4148 is a42   channel called "phoenix" */43static int freq = 4148;44module_param(freq, int, 0644);45MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");46 47static int debug;48module_param(debug, int, 0644);49MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");50 51#define MXB_STD (V4L2_STD_PAL_BG | V4L2_STD_PAL_I | V4L2_STD_SECAM | V4L2_STD_NTSC)52#define MXB_INPUTS 453enum { TUNER, AUX1, AUX3, AUX3_YC };54 55static struct v4l2_input mxb_inputs[MXB_INPUTS] = {56	{ TUNER,   "Tuner",          V4L2_INPUT_TYPE_TUNER,  0x3f, 0,57		V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },58	{ AUX1,	   "AUX1",           V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,59		MXB_STD, 0, V4L2_IN_CAP_STD },60	{ AUX3,	   "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,61		MXB_STD, 0, V4L2_IN_CAP_STD },62	{ AUX3_YC, "AUX3 S-Video",   V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,63		MXB_STD, 0, V4L2_IN_CAP_STD },64};65 66/* this array holds the information, which port of the saa7146 each67   input actually uses. the mxb uses port 0 for every input */68static struct {69	int hps_source;70	int hps_sync;71} input_port_selection[MXB_INPUTS] = {72	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },73	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },74	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },75	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },76};77 78/* this array holds the information of the audio source (mxb_audios),79   which has to be switched corresponding to the video source (mxb_channels) */80static int video_audio_connect[MXB_INPUTS] =81	{ 0, 1, 3, 3 };82 83struct mxb_routing {84	u32 input;85	u32 output;86};87 88/* these are the available audio sources, which can switched89   to the line- and cd-output individually */90static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {91	    {92		.index	= 0,93		.name	= "Tuner",94		.capability = V4L2_AUDCAP_STEREO,95	} , {96		.index	= 1,97		.name	= "AUX1",98		.capability = V4L2_AUDCAP_STEREO,99	} , {100		.index	= 2,101		.name	= "AUX2",102		.capability = V4L2_AUDCAP_STEREO,103	} , {104		.index	= 3,105		.name	= "AUX3",106		.capability = V4L2_AUDCAP_STEREO,107	} , {108		.index	= 4,109		.name	= "Radio (X9)",110		.capability = V4L2_AUDCAP_STEREO,111	} , {112		.index	= 5,113		.name	= "CD-ROM (X10)",114		.capability = V4L2_AUDCAP_STEREO,115	}116};117 118/* These are the necessary input-output-pins for bringing one audio source119   (see above) to the CD-output. Note that gain is set to 0 in this table. */120static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {121	{ { 1, 1 }, { 1, 1 } },	/* Tuner */122	{ { 5, 1 }, { 6, 1 } },	/* AUX 1 */123	{ { 4, 1 }, { 6, 1 } },	/* AUX 2 */124	{ { 3, 1 }, { 6, 1 } },	/* AUX 3 */125	{ { 1, 1 }, { 3, 1 } },	/* Radio */126	{ { 1, 1 }, { 2, 1 } },	/* CD-Rom */127	{ { 6, 1 }, { 6, 1 } }	/* Mute */128};129 130/* These are the necessary input-output-pins for bringing one audio source131   (see above) to the line-output. Note that gain is set to 0 in this table. */132static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {133	{ { 2, 3 }, { 1, 2 } },134	{ { 5, 3 }, { 6, 2 } },135	{ { 4, 3 }, { 6, 2 } },136	{ { 3, 3 }, { 6, 2 } },137	{ { 2, 3 }, { 3, 2 } },138	{ { 2, 3 }, { 2, 2 } },139	{ { 6, 3 }, { 6, 2 } }	/* Mute */140};141 142struct mxb143{144	struct video_device	video_dev;145	struct video_device	vbi_dev;146 147	struct i2c_adapter	i2c_adapter;148 149	struct v4l2_subdev	*saa7111a;150	struct v4l2_subdev	*tda9840;151	struct v4l2_subdev	*tea6415c;152	struct v4l2_subdev	*tuner;153	struct v4l2_subdev	*tea6420_1;154	struct v4l2_subdev	*tea6420_2;155 156	int	cur_mode;	/* current audio mode (mono, stereo, ...) */157	int	cur_input;	/* current input */158	int	cur_audinput;	/* current audio input */159	int	cur_mute;	/* current mute status */160	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */161};162 163#define saa7111a_call(mxb, o, f, args...) \164	v4l2_subdev_call(mxb->saa7111a, o, f, ##args)165#define tda9840_call(mxb, o, f, args...) \166	v4l2_subdev_call(mxb->tda9840, o, f, ##args)167#define tea6415c_call(mxb, o, f, args...) \168	v4l2_subdev_call(mxb->tea6415c, o, f, ##args)169#define tuner_call(mxb, o, f, args...) \170	v4l2_subdev_call(mxb->tuner, o, f, ##args)171#define call_all(dev, o, f, args...) \172	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)173 174static void mxb_update_audmode(struct mxb *mxb)175{176	struct v4l2_tuner t = {177		.audmode = mxb->cur_mode,178	};179 180	tda9840_call(mxb, tuner, s_tuner, &t);181}182 183static inline void tea6420_route(struct mxb *mxb, int idx)184{185	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,186		TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);187	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,188		TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);189	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,190		TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);191	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,192		TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);193}194 195static struct saa7146_extension extension;196 197static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)198{199	struct saa7146_dev *dev = container_of(ctrl->handler,200				struct saa7146_dev, ctrl_handler);201	struct mxb *mxb = dev->ext_priv;202 203	switch (ctrl->id) {204	case V4L2_CID_AUDIO_MUTE:205		mxb->cur_mute = ctrl->val;206		/* switch the audio-source */207		tea6420_route(mxb, ctrl->val ? 6 :208				video_audio_connect[mxb->cur_input]);209		break;210	default:211		return -EINVAL;212	}213	return 0;214}215 216static const struct v4l2_ctrl_ops mxb_ctrl_ops = {217	.s_ctrl = mxb_s_ctrl,218};219 220static int mxb_probe(struct saa7146_dev *dev)221{222	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;223	struct mxb *mxb = NULL;224 225	v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,226			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);227	if (hdl->error)228		return hdl->error;229	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);230	if (mxb == NULL) {231		DEB_D("not enough kernel memory\n");232		return -ENOMEM;233	}234 235 236	snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);237 238	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);239	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {240		DEB_S("cannot register i2c-device. skipping.\n");241		kfree(mxb);242		return -EFAULT;243	}244 245	mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,246			"saa7111", I2C_SAA7111A, NULL);247	mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,248			"tea6420", I2C_TEA6420_1, NULL);249	mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,250			"tea6420", I2C_TEA6420_2, NULL);251	mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,252			"tea6415c", I2C_TEA6415C, NULL);253	mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,254			"tda9840", I2C_TDA9840, NULL);255	mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,256			"tuner", I2C_TUNER, NULL);257 258	/* check if all devices are present */259	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||260	    !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {261		pr_err("did not find all i2c devices. aborting\n");262		i2c_del_adapter(&mxb->i2c_adapter);263		kfree(mxb);264		return -ENODEV;265	}266 267	/* all devices are present, probe was successful */268 269	/* we store the pointer in our private data field */270	dev->ext_priv = mxb;271 272	v4l2_ctrl_handler_setup(hdl);273 274	return 0;275}276 277/* some init data for the saa7740, the so-called 'sound arena module'.278   there are no specs available, so we simply use some init values */279static struct {280	int	length;281	char	data[9];282} mxb_saa7740_init[] = {283	{ 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },284	{ 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },285	{ 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },286	{ 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },287	{ 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },288	{ 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },289	{ 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },290	{ 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },291	{ 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },292	{ 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },293	{ 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },294	{ 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },295	{ 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },296	{ 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },297	{ 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },298	{ 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },299	{ 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },300	{ 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },301	{ 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },302	{ 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },303	{ 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },304	{ 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },305	{ 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },306	{ 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },307	{ 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },308	{ 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },309	{ 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },310	{ 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },311	{ 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },312	{ 3, { 0x48, 0x00, 0x01 } },313	{ 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },314	{ 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },315	{ 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },316	{ 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },317	{ 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },318	{ 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },319	{ 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },320	{ 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },321	{ 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },322	{ 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },323	{ 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },324	{ 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },325	{ 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },326	{ 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },327	{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },328	{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },329	{ 3, { 0x80, 0xb3, 0x0a } },330	{-1, { 0 } }331};332 333/* bring hardware to a sane state. this has to be done, just in case someone334   wants to capture from this device before it has been properly initialized.335   the capture engine would badly fail, because no valid signal arrives on the336   saa7146, thus leading to timeouts and stuff. */337static int mxb_init_done(struct saa7146_dev* dev)338{339	struct mxb* mxb = (struct mxb*)dev->ext_priv;340	struct i2c_msg msg;341	struct tuner_setup tun_setup;342	v4l2_std_id std = V4L2_STD_PAL_BG;343 344	int i, err = 0;345 346	/* mute audio on tea6420s */347	tea6420_route(mxb, 6);348 349	/* select video mode in saa7111a */350	saa7111a_call(mxb, video, s_std, std);351 352	/* select tuner-output on saa7111a */353	saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,354		SAA7111_FMT_CCIR, 0);355 356	/* select a tuner type */357	tun_setup.mode_mask = T_ANALOG_TV;358	tun_setup.addr = ADDR_UNSET;359	tun_setup.type = TUNER_PHILIPS_PAL;360	tuner_call(mxb, tuner, s_type_addr, &tun_setup);361	/* tune in some frequency on tuner */362	mxb->cur_freq.tuner = 0;363	mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;364	mxb->cur_freq.frequency = freq;365	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);366 367	/* set a default video standard */368	/* These two gpio calls set the GPIO pins that control the tda9820 */369	saa7146_write(dev, GPIO_CTRL, 0x00404050);370	saa7111a_call(mxb, core, s_gpio, 1);371	saa7111a_call(mxb, video, s_std, std);372	tuner_call(mxb, video, s_std, std);373 374	/* switch to tuner-channel on tea6415c */375	tea6415c_call(mxb, video, s_routing, 3, 17, 0);376 377	/* select tuner-output on multicable on tea6415c */378	tea6415c_call(mxb, video, s_routing, 3, 13, 0);379 380	/* the rest for mxb */381	mxb->cur_input = 0;382	mxb->cur_audinput = video_audio_connect[mxb->cur_input];383	mxb->cur_mute = 1;384 385	mxb->cur_mode = V4L2_TUNER_MODE_STEREO;386	mxb_update_audmode(mxb);387 388	/* check if the saa7740 (aka 'sound arena module') is present389	   on the mxb. if so, we must initialize it. due to lack of390	   information about the saa7740, the values were reverse391	   engineered. */392	msg.addr = 0x1b;393	msg.flags = 0;394	msg.len = mxb_saa7740_init[0].length;395	msg.buf = &mxb_saa7740_init[0].data[0];396 397	err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);398	if (err == 1) {399		/* the sound arena module is a pos, that's probably the reason400		   philips refuses to hand out a datasheet for the saa7740...401		   it seems to screw up the i2c bus, so we disable fast irq402		   based i2c transactions here and rely on the slow and safe403		   polling method ... */404		extension.flags &= ~SAA7146_USE_I2C_IRQ;405		for (i = 1; ; i++) {406			if (-1 == mxb_saa7740_init[i].length)407				break;408 409			msg.len = mxb_saa7740_init[i].length;410			msg.buf = &mxb_saa7740_init[i].data[0];411			err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);412			if (err != 1) {413				DEB_D("failed to initialize 'sound arena module'\n");414				goto err;415			}416		}417		pr_info("'sound arena module' detected\n");418	}419err:420	/* the rest for saa7146: you should definitely set some basic values421	   for the input-port handling of the saa7146. */422 423	/* ext->saa has been filled by the core driver */424 425	/* some stuff is done via variables */426	saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,427			input_port_selection[mxb->cur_input].hps_sync);428 429	/* some stuff is done via direct write to the registers */430 431	/* this is ugly, but because of the fact that this is completely432	   hardware dependend, it should be done directly... */433	saa7146_write(dev, DD1_STREAM_B,	0x00000000);434	saa7146_write(dev, DD1_INIT,		0x02000200);435	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));436 437	return 0;438}439 440/* interrupt-handler. this gets called when irq_mask is != 0.441   it must clear the interrupt-bits in irq_mask it has handled */442/*443void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)444{445	struct mxb* mxb = (struct mxb*)dev->ext_priv;446}447*/448 449static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)450{451	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);452	if (i->index >= MXB_INPUTS)453		return -EINVAL;454	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));455	return 0;456}457 458static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)459{460	struct saa7146_dev *dev = video_drvdata(file);461	struct mxb *mxb = (struct mxb *)dev->ext_priv;462	*i = mxb->cur_input;463 464	DEB_EE("VIDIOC_G_INPUT %d\n", *i);465	return 0;466}467 468static int vidioc_s_input(struct file *file, void *fh, unsigned int input)469{470	struct saa7146_dev *dev = video_drvdata(file);471	struct mxb *mxb = (struct mxb *)dev->ext_priv;472	int err = 0;473	int i = 0;474 475	DEB_EE("VIDIOC_S_INPUT %d\n", input);476 477	if (input >= MXB_INPUTS)478		return -EINVAL;479 480	mxb->cur_input = input;481 482	saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,483			input_port_selection[input].hps_sync);484 485	/* prepare switching of tea6415c and saa7111a;486	   have a look at the 'background'-file for further information  */487	switch (input) {488	case TUNER:489		i = SAA7115_COMPOSITE0;490 491		err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);492 493		/* connect tuner-output always to multicable */494		if (!err)495			err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);496		break;497	case AUX3_YC:498		/* nothing to be done here. aux3_yc is499		   directly connected to the saa711a */500		i = SAA7115_SVIDEO1;501		break;502	case AUX3:503		/* nothing to be done here. aux3 is504		   directly connected to the saa711a */505		i = SAA7115_COMPOSITE1;506		break;507	case AUX1:508		i = SAA7115_COMPOSITE0;509		err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);510		break;511	}512 513	if (err)514		return err;515 516	mxb->video_dev.tvnorms = mxb_inputs[input].std;517	mxb->vbi_dev.tvnorms = mxb_inputs[input].std;518 519	/* switch video in saa7111a */520	if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))521		pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");522 523	mxb->cur_audinput = video_audio_connect[input];524	/* switch the audio-source only if necessary */525	if (0 == mxb->cur_mute)526		tea6420_route(mxb, mxb->cur_audinput);527	if (mxb->cur_audinput == 0)528		mxb_update_audmode(mxb);529 530	return 0;531}532 533static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)534{535	struct saa7146_dev *dev = video_drvdata(file);536	struct mxb *mxb = (struct mxb *)dev->ext_priv;537 538	if (t->index) {539		DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",540		      t->index);541		return -EINVAL;542	}543 544	DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);545 546	memset(t, 0, sizeof(*t));547	strscpy(t->name, "TV Tuner", sizeof(t->name));548	t->type = V4L2_TUNER_ANALOG_TV;549	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |550			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;551	t->audmode = mxb->cur_mode;552	return call_all(dev, tuner, g_tuner, t);553}554 555static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)556{557	struct saa7146_dev *dev = video_drvdata(file);558	struct mxb *mxb = (struct mxb *)dev->ext_priv;559 560	if (t->index) {561		DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",562		      t->index);563		return -EINVAL;564	}565 566	mxb->cur_mode = t->audmode;567	return call_all(dev, tuner, s_tuner, t);568}569 570static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)571{572	struct saa7146_dev *dev = video_drvdata(file);573 574	return call_all(dev, video, querystd, norm);575}576 577static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)578{579	struct saa7146_dev *dev = video_drvdata(file);580	struct mxb *mxb = (struct mxb *)dev->ext_priv;581 582	if (f->tuner)583		return -EINVAL;584	*f = mxb->cur_freq;585 586	DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);587	return 0;588}589 590static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)591{592	struct saa7146_dev *dev = video_drvdata(file);593	struct mxb *mxb = (struct mxb *)dev->ext_priv;594 595	if (f->tuner)596		return -EINVAL;597 598	if (V4L2_TUNER_ANALOG_TV != f->type)599		return -EINVAL;600 601	DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);602 603	/* tune in desired frequency */604	tuner_call(mxb, tuner, s_frequency, f);605	/* let the tuner subdev clamp the frequency to the tuner range */606	mxb->cur_freq = *f;607	tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);608	if (mxb->cur_audinput == 0)609		mxb_update_audmode(mxb);610	return 0;611}612 613static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)614{615	if (a->index >= MXB_AUDIOS)616		return -EINVAL;617	*a = mxb_audios[a->index];618	return 0;619}620 621static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)622{623	struct saa7146_dev *dev = video_drvdata(file);624	struct mxb *mxb = (struct mxb *)dev->ext_priv;625 626	DEB_EE("VIDIOC_G_AUDIO\n");627	*a = mxb_audios[mxb->cur_audinput];628	return 0;629}630 631static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)632{633	struct saa7146_dev *dev = video_drvdata(file);634	struct mxb *mxb = (struct mxb *)dev->ext_priv;635 636	DEB_D("VIDIOC_S_AUDIO %d\n", a->index);637	if (a->index >= 32 ||638	    !(mxb_inputs[mxb->cur_input].audioset & (1 << a->index)))639		return -EINVAL;640 641	if (mxb->cur_audinput != a->index) {642		mxb->cur_audinput = a->index;643		tea6420_route(mxb, a->index);644		if (mxb->cur_audinput == 0)645			mxb_update_audmode(mxb);646	}647	return 0;648}649 650#ifdef CONFIG_VIDEO_ADV_DEBUG651static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)652{653	struct saa7146_dev *dev = video_drvdata(file);654 655	if (reg->reg > pci_resource_len(dev->pci, 0) - 4)656		return -EINVAL;657	reg->val = saa7146_read(dev, reg->reg);658	reg->size = 4;659	return 0;660}661 662static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)663{664	struct saa7146_dev *dev = video_drvdata(file);665 666	if (reg->reg > pci_resource_len(dev->pci, 0) - 4)667		return -EINVAL;668	saa7146_write(dev, reg->reg, reg->val);669	return 0;670}671#endif672 673static struct saa7146_ext_vv vv_data;674 675/* this function only gets called when the probing was successful */676static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)677{678	struct mxb *mxb;679	int ret;680 681	DEB_EE("dev:%p\n", dev);682 683	ret = saa7146_vv_init(dev, &vv_data);684	if (ret) {685		ERR("Error in saa7146_vv_init()");686		return ret;687	}688 689	if (mxb_probe(dev)) {690		saa7146_vv_release(dev);691		return -1;692	}693	mxb = (struct mxb *)dev->ext_priv;694 695	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;696	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;697	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;698	vv_data.vid_ops.vidioc_querystd = vidioc_querystd;699	vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;700	vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;701	vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;702	vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;703	vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;704	vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;705	vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;706#ifdef CONFIG_VIDEO_ADV_DEBUG707	vv_data.vid_ops.vidioc_g_register = vidioc_g_register;708	vv_data.vid_ops.vidioc_s_register = vidioc_s_register;709#endif710	vv_data.vbi_ops.vidioc_enum_input = vidioc_enum_input;711	vv_data.vbi_ops.vidioc_g_input = vidioc_g_input;712	vv_data.vbi_ops.vidioc_s_input = vidioc_s_input;713	vv_data.vbi_ops.vidioc_querystd = vidioc_querystd;714	vv_data.vbi_ops.vidioc_g_tuner = vidioc_g_tuner;715	vv_data.vbi_ops.vidioc_s_tuner = vidioc_s_tuner;716	vv_data.vbi_ops.vidioc_g_frequency = vidioc_g_frequency;717	vv_data.vbi_ops.vidioc_s_frequency = vidioc_s_frequency;718	vv_data.vbi_ops.vidioc_enumaudio = vidioc_enumaudio;719	vv_data.vbi_ops.vidioc_g_audio = vidioc_g_audio;720	vv_data.vbi_ops.vidioc_s_audio = vidioc_s_audio;721	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_VIDEO)) {722		ERR("cannot register capture v4l2 device. skipping.\n");723		saa7146_vv_release(dev);724		return -1;725	}726 727	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/728	if (MXB_BOARD_CAN_DO_VBI(dev)) {729		if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {730			ERR("cannot register vbi v4l2 device. skipping.\n");731		}732	}733 734	pr_info("found Multimedia eXtension Board #%d\n", mxb_num);735 736	mxb_num++;737	mxb_init_done(dev);738	return 0;739}740 741static int mxb_detach(struct saa7146_dev *dev)742{743	struct mxb *mxb = (struct mxb *)dev->ext_priv;744 745	DEB_EE("dev:%p\n", dev);746 747	/* mute audio on tea6420s */748	tea6420_route(mxb, 6);749 750	saa7146_unregister_device(&mxb->video_dev,dev);751	if (MXB_BOARD_CAN_DO_VBI(dev))752		saa7146_unregister_device(&mxb->vbi_dev, dev);753	saa7146_vv_release(dev);754 755	mxb_num--;756 757	i2c_del_adapter(&mxb->i2c_adapter);758	kfree(mxb);759 760	return 0;761}762 763static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)764{765	struct mxb *mxb = (struct mxb *)dev->ext_priv;766 767	if (V4L2_STD_PAL_I == standard->id) {768		v4l2_std_id std = V4L2_STD_PAL_I;769 770		DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");771		/* These two gpio calls set the GPIO pins that control the tda9820 */772		saa7146_write(dev, GPIO_CTRL, 0x00404050);773		saa7111a_call(mxb, core, s_gpio, 0);774		saa7111a_call(mxb, video, s_std, std);775		if (mxb->cur_input == 0)776			tuner_call(mxb, video, s_std, std);777	} else {778		v4l2_std_id std = V4L2_STD_PAL_BG;779 780		if (mxb->cur_input)781			std = standard->id;782		DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");783		/* These two gpio calls set the GPIO pins that control the tda9820 */784		saa7146_write(dev, GPIO_CTRL, 0x00404050);785		saa7111a_call(mxb, core, s_gpio, 1);786		saa7111a_call(mxb, video, s_std, std);787		if (mxb->cur_input == 0)788			tuner_call(mxb, video, s_std, std);789	}790	return 0;791}792 793static struct saa7146_standard standard[] = {794	{795		.name	= "PAL-BG",	.id	= V4L2_STD_PAL_BG,796		.v_offset	= 0x17,	.v_field	= 288,797		.h_offset	= 0x14,	.h_pixels	= 680,798		.v_max_out	= 576,	.h_max_out	= 768,799	}, {800		.name	= "PAL-I",	.id	= V4L2_STD_PAL_I,801		.v_offset	= 0x17,	.v_field	= 288,802		.h_offset	= 0x14,	.h_pixels	= 680,803		.v_max_out	= 576,	.h_max_out	= 768,804	}, {805		.name	= "NTSC",	.id	= V4L2_STD_NTSC,806		.v_offset	= 0x16,	.v_field	= 240,807		.h_offset	= 0x06,	.h_pixels	= 708,808		.v_max_out	= 480,	.h_max_out	= 640,809	}, {810		.name	= "SECAM",	.id	= V4L2_STD_SECAM,811		.v_offset	= 0x14,	.v_field	= 288,812		.h_offset	= 0x14,	.h_pixels	= 720,813		.v_max_out	= 576,	.h_max_out	= 768,814	}815};816 817static struct saa7146_pci_extension_data mxb = {818	.ext_priv = "Multimedia eXtension Board",819	.ext = &extension,820};821 822static const struct pci_device_id pci_tbl[] = {823	{824		.vendor    = PCI_VENDOR_ID_PHILIPS,825		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,826		.subvendor = 0x0000,827		.subdevice = 0x0000,828		.driver_data = (unsigned long)&mxb,829	}, {830		.vendor	= 0,831	}832};833 834MODULE_DEVICE_TABLE(pci, pci_tbl);835 836static struct saa7146_ext_vv vv_data = {837	.inputs		= MXB_INPUTS,838	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,839	.stds		= &standard[0],840	.num_stds	= ARRAY_SIZE(standard),841	.std_callback	= &std_callback,842};843 844static struct saa7146_extension extension = {845	.name		= "Multimedia eXtension Board",846	.flags		= SAA7146_USE_I2C_IRQ,847 848	.pci_tbl	= &pci_tbl[0],849	.module		= THIS_MODULE,850 851	.attach		= mxb_attach,852	.detach		= mxb_detach,853 854	.irq_mask	= 0,855	.irq_func	= NULL,856};857 858static int __init mxb_init_module(void)859{860	if (saa7146_register_extension(&extension)) {861		DEB_S("failed to register extension\n");862		return -ENODEV;863	}864 865	return 0;866}867 868static void __exit mxb_cleanup_module(void)869{870	saa7146_unregister_extension(&extension);871}872 873module_init(mxb_init_module);874module_exit(mxb_cleanup_module);875 876MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");877MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");878MODULE_LICENSE("GPL");879