msp3400-kthreads.c 30.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Programming the mspx4xx sound processor family
 *
 * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
29
#include <media/msp3400.h>
30 31
#include <linux/kthread.h>
#include <linux/suspend.h>
32
#include "msp3400-driver.h"
33 34 35 36 37 38 39

/* this one uses the automatic sound standard detection of newer msp34xx
   chip versions */
static struct {
	int retval;
	int main, second;
	char *name;
40
} msp_stdlist[] = {
41 42 43 44 45 46 47
	{ 0x0000, 0, 0, "could not detect sound standard" },
	{ 0x0001, 0, 0, "autodetect start" },
	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72  M Dual FM-Stereo" },
	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74  B/G Dual FM-Stereo" },
	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25  D/K1 Dual FM-Stereo" },
	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74  D/K2 Dual FM-Stereo" },
	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  D/K FM-Mono (HDEV3)" },
48
	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74  D/K3 Dual FM-Stereo" },
49 50 51 52 53
	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85  B/G NICAM FM" },
	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  L NICAM AM" },
	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55  I NICAM FM" },
	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM" },
	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV2)" },
54
	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV3)" },
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Stereo" },
	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Mono + SAP" },
	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M EIA-J Japan Stereo" },
	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7  FM-Stereo Radio" },
	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  SAT-Mono" },
	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20  SAT-Stereo" },
	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2  SAT ADR" },
	{     -1, 0, 0, NULL }, /* EOF */
};

static struct msp3400c_init_data_dem {
	int fir1[6];
	int fir2[6];
	int cdo1;
	int cdo2;
	int ad_cv;
	int mode_reg;
	int dsp_src;
	int dsp_matrix;
} msp3400c_init_data[] = {
	{	/* AM (for carrier detect / msp3400) */
		{75, 19, 36, 35, 39, 40},
		{75, 19, 36, 35, 39, 40},
		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
		0x00d0, 0x0500, 0x0020, 0x3000
	},{	/* AM (for carrier detect / msp3410) */
		{-1, -1, -8, 2, 59, 126},
		{-1, -1, -8, 2, 59, 126},
		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
		0x00d0, 0x0100, 0x0020, 0x3000
	},{	/* FM Radio */
		{-8, -8, 4, 6, 78, 107},
		{-8, -8, 4, 6, 78, 107},
		MSP_CARRIER(10.7), MSP_CARRIER(10.7),
		0x00d0, 0x0480, 0x0020, 0x3000
	},{	/* Terrestial FM-mono + FM-stereo */
		{3, 18, 27, 48, 66, 72},
		{3, 18, 27, 48, 66, 72},
		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
		0x00d0, 0x0480, 0x0030, 0x3000
	},{	/* Sat FM-mono */
		{ 1, 9, 14, 24, 33, 37},
		{ 3, 18, 27, 48, 66, 72},
		MSP_CARRIER(6.5), MSP_CARRIER(6.5),
		0x00c6, 0x0480, 0x0000, 0x3000
	},{	/* NICAM/FM --  B/G (5.5/5.85), D/K (6.5/5.85) */
		{-2, -8, -10, 10, 50, 86},
		{3, 18, 27, 48, 66, 72},
		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
		0x00d0, 0x0040, 0x0120, 0x3000
	},{	/* NICAM/FM -- I (6.0/6.552) */
		{2, 4, -6, -4, 40, 94},
		{3, 18, 27, 48, 66, 72},
		MSP_CARRIER(6.0), MSP_CARRIER(6.0),
		0x00d0, 0x0040, 0x0120, 0x3000
	},{	/* NICAM/AM -- L (6.5/5.85) */
		{-2, -8, -10, 10, 50, 86},
		{-4, -12, -9, 23, 79, 126},
		MSP_CARRIER(6.5), MSP_CARRIER(6.5),
114
		0x00c6, 0x0140, 0x0120, 0x7c00
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
	},
};

struct msp3400c_carrier_detect {
	int   cdo;
	char *name;
};

static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = {
	/* main carrier */
	{ MSP_CARRIER(4.5),        "4.5   NTSC"                   },
	{ MSP_CARRIER(5.5),        "5.5   PAL B/G"                },
	{ MSP_CARRIER(6.0),        "6.0   PAL I"                  },
	{ MSP_CARRIER(6.5),        "6.5   PAL D/K + SAT + SECAM"  }
};

static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = {
	/* PAL B/G */
	{ MSP_CARRIER(5.7421875),  "5.742 PAL B/G FM-stereo"     },
	{ MSP_CARRIER(5.85),       "5.85  PAL B/G NICAM"         }
};

static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = {
	/* PAL SAT / SECAM */
	{ MSP_CARRIER(5.85),       "5.85  PAL D/K + SECAM NICAM" },
	{ MSP_CARRIER(6.2578125),  "6.25  PAL D/K1 FM-stereo" },
	{ MSP_CARRIER(6.7421875),  "6.74  PAL D/K2 FM-stereo" },
	{ MSP_CARRIER(7.02),       "7.02  PAL SAT FM-stereo s/b" },
	{ MSP_CARRIER(7.20),       "7.20  PAL SAT FM-stereo s"   },
	{ MSP_CARRIER(7.38),       "7.38  PAL SAT FM-stereo b"   },
};

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

149
const char *msp_standard_std_name(int std)
150 151 152
{
	int i;

153 154 155
	for (i = 0; msp_stdlist[i].name != NULL; i++)
		if (msp_stdlist[i].retval == std)
			return msp_stdlist[i].name;
156 157 158
	return "unknown";
}

159
static void msp_set_source(struct i2c_client *client, u16 src)
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
{
	struct msp_state *state = i2c_get_clientdata(client);

	if (msp_dolby) {
		msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */
		msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */
	} else {
		msp_write_dsp(client, 0x0008, src);
		msp_write_dsp(client, 0x0009, src);
	}
	msp_write_dsp(client, 0x000a, src);
	msp_write_dsp(client, 0x000b, src);
	msp_write_dsp(client, 0x000c, src);
	if (state->has_scart23_in_scart2_out)
		msp_write_dsp(client, 0x0041, src);
}

void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2)
178 179 180 181 182
{
	msp_write_dem(client, 0x0093, cdo1 & 0xfff);
	msp_write_dem(client, 0x009b, cdo1 >> 12);
	msp_write_dem(client, 0x00a3, cdo2 & 0xfff);
	msp_write_dem(client, 0x00ab, cdo2 >> 12);
183
	msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */
184 185
}

186
void msp3400c_set_mode(struct i2c_client *client, int mode)
187 188
{
	struct msp_state *state = i2c_get_clientdata(client);
189
	struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
190
	int tuner = (state->routing.input >> 3) & 1;
191 192
	int i;

193 194
	v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
	state->mode = mode;
195 196
	state->rxsubchans = V4L2_TUNER_SUB_MONO;

197
	msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
198 199

	for (i = 5; i >= 0; i--)               /* fir 1 */
200
		msp_write_dem(client, 0x0001, data->fir1[i]);
201 202 203 204 205

	msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */
	msp_write_dem(client, 0x0005, 0x0040);
	msp_write_dem(client, 0x0005, 0x0000);
	for (i = 5; i >= 0; i--)
206
		msp_write_dem(client, 0x0005, data->fir2[i]);
207

208
	msp_write_dem(client, 0x0083, data->mode_reg);
209

210
	msp3400c_set_carrier(client, data->cdo1, data->cdo2);
211

212
	msp_set_source(client, data->dsp_src);
213
	/* set prescales */
214

215 216 217 218 219
	/* volume prescale for SCART (AM mono input) */
	msp_write_dsp(client, 0x000d, 0x1900);
	msp_write_dsp(client, 0x000e, data->dsp_matrix);
	if (state->has_nicam) /* nicam prescale */
		msp_write_dsp(client, 0x0010, 0x5a00);
220 221
}

222 223
/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP,
   nor do they support stereo BTSC. */
224
static void msp3400c_set_audmode(struct i2c_client *client)
225
{
226
	static char *strmode[] = { "mono", "stereo", "lang2", "lang1" };
227
	struct msp_state *state = i2c_get_clientdata(client);
228 229 230
	char *modestr = (state->audmode >= 0 && state->audmode < 4) ?
		strmode[state->audmode] : "unknown";
	int src = 0;	/* channel source: FM/AM, nicam or SCART */
231 232 233 234 235

	if (state->opmode == OPMODE_AUTOSELECT) {
		/* this method would break everything, let's make sure
		 * it's never called
		 */
236 237 238
		v4l_dbg(1, msp_debug, client,
			"set_audmode called with mode=%d instead of set_source (ignored)\n",
			state->audmode);
239 240 241 242 243 244
		return;
	}

	/* switch demodulator */
	switch (state->mode) {
	case MSP_MODE_FM_TERRA:
245 246
		v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
		switch (state->audmode) {
247 248 249 250 251 252 253 254 255 256 257
		case V4L2_TUNER_MODE_STEREO:
			msp_write_dsp(client, 0x000e, 0x3001);
			break;
		case V4L2_TUNER_MODE_MONO:
		case V4L2_TUNER_MODE_LANG1:
		case V4L2_TUNER_MODE_LANG2:
			msp_write_dsp(client, 0x000e, 0x3000);
			break;
		}
		break;
	case MSP_MODE_FM_SAT:
258 259
		v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
		switch (state->audmode) {
260
		case V4L2_TUNER_MODE_MONO:
261
			msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
262 263
			break;
		case V4L2_TUNER_MODE_STEREO:
264
			msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
265 266
			break;
		case V4L2_TUNER_MODE_LANG1:
267
			msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
268 269
			break;
		case V4L2_TUNER_MODE_LANG2:
270
			msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
271 272 273 274 275 276
			break;
		}
		break;
	case MSP_MODE_FM_NICAM1:
	case MSP_MODE_FM_NICAM2:
	case MSP_MODE_AM_NICAM:
277
		v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr);
278
		if (state->nicam_on)
279
			src = 0x0100;  /* NICAM */
280 281
		break;
	case MSP_MODE_BTSC:
282
		v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr);
283 284
		break;
	case MSP_MODE_EXTERN:
285 286
		v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr);
		src = 0x0200;  /* SCART */
287 288
		break;
	case MSP_MODE_FM_RADIO:
289
		v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr);
290 291
		break;
	default:
292
		v4l_dbg(1, msp_debug, client, "mono set_audmode\n");
293 294 295 296
		return;
	}

	/* switch audio */
297
	switch (state->audmode) {
298
	case V4L2_TUNER_MODE_STEREO:
299
		src |= 0x0020;
300 301 302
		break;
	case V4L2_TUNER_MODE_MONO:
		if (state->mode == MSP_MODE_AM_NICAM) {
M
 
Mauro Carvalho Chehab 已提交
303
			v4l_dbg(1, msp_debug, client, "switching to AM mono\n");
304 305 306 307 308 309
			/* AM mono decoding is handled by tuner, not MSP chip */
			/* SCART switching control register */
			msp_set_scart(client, SCART_MONO, 0);
			src = 0x0200;
			break;
		}
310 311 312
		if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
			src = 0x0030;
		break;
313
	case V4L2_TUNER_MODE_LANG1:
314 315 316 317
		/* switch to stereo for stereo transmission, otherwise
		   keep first language */
		if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
			src |= 0x0020;
318 319
		break;
	case V4L2_TUNER_MODE_LANG2:
320
		src |= 0x0010;
321 322
		break;
	}
323
	v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src);
324

325
	msp_set_source(client, src);
326 327 328 329 330 331 332
}

static void msp3400c_print_mode(struct i2c_client *client)
{
	struct msp_state *state = i2c_get_clientdata(client);

	if (state->main == state->second) {
M
 
Mauro Carvalho Chehab 已提交
333
		v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n",
334 335
		       state->main / 910000, (state->main / 910) % 1000);
	} else {
M
 
Mauro Carvalho Chehab 已提交
336
		v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n",
337 338 339
		       state->main / 910000, (state->main / 910) % 1000);
	}
	if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
M
 
Mauro Carvalho Chehab 已提交
340
		v4l_dbg(1, msp_debug, client, "NICAM/FM carrier  : %d.%03d MHz\n",
341 342
		       state->second / 910000, (state->second/910) % 1000);
	if (state->mode == MSP_MODE_AM_NICAM)
M
 
Mauro Carvalho Chehab 已提交
343
		v4l_dbg(1, msp_debug, client, "NICAM/AM carrier  : %d.%03d MHz\n",
344 345
		       state->second / 910000, (state->second / 910) % 1000);
	if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
M
 
Mauro Carvalho Chehab 已提交
346
		v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n",
347 348 349 350 351 352
		       state->second / 910000, (state->second / 910) % 1000);
	}
}

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

353
static int msp3400c_detect_stereo(struct i2c_client *client)
354 355 356 357
{
	struct msp_state *state = i2c_get_clientdata(client);
	int val;
	int rxsubchans = state->rxsubchans;
358
	int newnicam = state->nicam_on;
359 360 361 362 363 364 365
	int update = 0;

	switch (state->mode) {
	case MSP_MODE_FM_TERRA:
		val = msp_read_dsp(client, 0x18);
		if (val > 32767)
			val -= 65536;
M
 
Mauro Carvalho Chehab 已提交
366
		v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
367
		if (val > 4096) {
368
			rxsubchans = V4L2_TUNER_SUB_STEREO;
369 370 371 372 373 374 375 376 377 378 379
		} else if (val < -4096) {
			rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
		} else {
			rxsubchans = V4L2_TUNER_SUB_MONO;
		}
		newnicam = 0;
		break;
	case MSP_MODE_FM_NICAM1:
	case MSP_MODE_FM_NICAM2:
	case MSP_MODE_AM_NICAM:
		val = msp_read_dem(client, 0x23);
M
 
Mauro Carvalho Chehab 已提交
380
		v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n",
381 382 383 384 385 386 387 388 389 390 391
			val & 1, (val & 0x1e) >> 1);

		if (val & 1) {
			/* nicam synced */
			switch ((val & 0x1e) >> 1)  {
			case 0:
			case 8:
				rxsubchans = V4L2_TUNER_SUB_STEREO;
				break;
			case 1:
			case 9:
392
				rxsubchans = V4L2_TUNER_SUB_MONO;
393 394 395
				break;
			case 2:
			case 10:
396
				rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
397 398 399 400 401 402 403 404 405 406 407 408 409 410
				break;
			default:
				rxsubchans = V4L2_TUNER_SUB_MONO;
				break;
			}
			newnicam = 1;
		} else {
			newnicam = 0;
			rxsubchans = V4L2_TUNER_SUB_MONO;
		}
		break;
	}
	if (rxsubchans != state->rxsubchans) {
		update = 1;
411 412
		v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n",
			state->rxsubchans, rxsubchans);
413 414 415 416
		state->rxsubchans = rxsubchans;
	}
	if (newnicam != state->nicam_on) {
		update = 1;
M
 
Mauro Carvalho Chehab 已提交
417
		v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n",
418
			state->nicam_on, newnicam);
419 420 421 422 423 424 425 426 427 428 429 430 431 432
		state->nicam_on = newnicam;
	}
	return update;
}

/*
 * A kernel thread for msp3400 control -- we don't want to block the
 * in the ioctl while doing the sound carrier & stereo detect
 */
/* stereo/multilang monitoring */
static void watch_stereo(struct i2c_client *client)
{
	struct msp_state *state = i2c_get_clientdata(client);

433 434
	if (msp_detect_stereo(client)) {
		msp_set_audmode(client);
435 436
	}

M
 
Mauro Carvalho Chehab 已提交
437
	if (msp_once)
438 439 440 441 442 443 444 445
		state->watch_stereo = 0;
}

int msp3400c_thread(void *data)
{
	struct i2c_client *client = data;
	struct msp_state *state = i2c_get_clientdata(client);
	struct msp3400c_carrier_detect *cd;
446
	int count, max1, max2, val1, val2, val, this;
447 448


M
 
Mauro Carvalho Chehab 已提交
449
	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
450
	for (;;) {
M
 
Mauro Carvalho Chehab 已提交
451
		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
452
		msp_sleep(state, -1);
M
 
Mauro Carvalho Chehab 已提交
453
		v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n");
454 455

	restart:
456
		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
457 458 459 460
		state->restart = 0;
		if (kthread_should_stop())
			break;

461
		if (state->radio || MSP_MODE_EXTERN == state->mode) {
462
			/* no carrier scan, just unmute */
M
 
Mauro Carvalho Chehab 已提交
463
			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
464 465 466 467 468 469
			msp_set_audio(client);
			continue;
		}

		/* mute */
		msp_set_mute(client);
470
		msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
471 472 473
		val1 = val2 = 0;
		max1 = max2 = -1;
		state->watch_stereo = 0;
474
		state->nicam_on = 0;
475 476

		/* some time for the tuner to sync */
477
		if (msp_sleep(state, 200))
478 479 480 481 482 483
			goto restart;

		/* carrier detect pass #1 -- main carrier */
		cd = msp3400c_carrier_detect_main;
		count = ARRAY_SIZE(msp3400c_carrier_detect_main);

M
 
Mauro Carvalho Chehab 已提交
484
		if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
485 486 487
			/* autodetect doesn't work well with AM ... */
			max1 = 3;
			count = 0;
M
 
Mauro Carvalho Chehab 已提交
488
			v4l_dbg(1, msp_debug, client, "AM sound override\n");
489 490 491
		}

		for (this = 0; this < count; this++) {
492
			msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo);
493 494 495 496 497 498 499
			if (msp_sleep(state,100))
				goto restart;
			val = msp_read_dsp(client, 0x1b);
			if (val > 32767)
				val -= 65536;
			if (val1 < val)
				val1 = val, max1 = this;
M
 
Mauro Carvalho Chehab 已提交
500
			v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name);
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
		}

		/* carrier detect pass #2 -- second (stereo) carrier */
		switch (max1) {
		case 1: /* 5.5 */
			cd = msp3400c_carrier_detect_55;
			count = ARRAY_SIZE(msp3400c_carrier_detect_55);
			break;
		case 3: /* 6.5 */
			cd = msp3400c_carrier_detect_65;
			count = ARRAY_SIZE(msp3400c_carrier_detect_65);
			break;
		case 0: /* 4.5 */
		case 2: /* 6.0 */
		default:
			cd = NULL;
			count = 0;
			break;
		}

M
 
Mauro Carvalho Chehab 已提交
521
		if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
522 523 524 525 526 527
			/* autodetect doesn't work well with AM ... */
			cd = NULL;
			count = 0;
			max2 = 0;
		}
		for (this = 0; this < count; this++) {
528
			msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo);
529 530 531 532 533 534 535
			if (msp_sleep(state,100))
				goto restart;
			val = msp_read_dsp(client, 0x1b);
			if (val > 32767)
				val -= 65536;
			if (val2 < val)
				val2 = val, max2 = this;
M
 
Mauro Carvalho Chehab 已提交
536
			v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name);
537 538 539
		}

		/* program the msp3400 according to the results */
540
		state->main = msp3400c_carrier_detect_main[max1].cdo;
541 542 543 544 545
		switch (max1) {
		case 1: /* 5.5 */
			if (max2 == 0) {
				/* B/G FM-stereo */
				state->second = msp3400c_carrier_detect_55[max2].cdo;
546
				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
547
				state->watch_stereo = 1;
548
			} else if (max2 == 1 && state->has_nicam) {
549 550
				/* B/G NICAM */
				state->second = msp3400c_carrier_detect_55[max2].cdo;
551 552
				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
				msp3400c_set_carrier(client, state->second, state->main);
553 554 555 556 557 558 559 560 561
				state->nicam_on = 1;
				state->watch_stereo = 1;
			} else {
				goto no_second;
			}
			break;
		case 2: /* 6.0 */
			/* PAL I NICAM */
			state->second = MSP_CARRIER(6.552);
562 563
			msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
			msp3400c_set_carrier(client, state->second, state->main);
564 565 566 567 568 569 570
			state->nicam_on = 1;
			state->watch_stereo = 1;
			break;
		case 3: /* 6.5 */
			if (max2 == 1 || max2 == 2) {
				/* D/K FM-stereo */
				state->second = msp3400c_carrier_detect_65[max2].cdo;
571
				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
572
				state->watch_stereo = 1;
573
			} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
574 575
				/* L NICAM or AM-mono */
				state->second = msp3400c_carrier_detect_65[max2].cdo;
576 577
				msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
				msp3400c_set_carrier(client, state->second, state->main);
578
				state->watch_stereo = 1;
579
			} else if (max2 == 0 && state->has_nicam) {
580 581
				/* D/K NICAM */
				state->second = msp3400c_carrier_detect_65[max2].cdo;
582 583
				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
				msp3400c_set_carrier(client, state->second, state->main);
584 585 586 587 588 589 590 591 592 593
				state->nicam_on = 1;
				state->watch_stereo = 1;
			} else {
				goto no_second;
			}
			break;
		case 0: /* 4.5 */
		default:
		no_second:
			state->second = msp3400c_carrier_detect_main[max1].cdo;
594 595
			msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
			msp3400c_set_carrier(client, state->second, state->main);
596 597 598 599 600 601
			state->rxsubchans = V4L2_TUNER_SUB_MONO;
			break;
		}

		/* unmute */
		msp_set_audio(client);
602
		msp3400c_set_audmode(client);
603

M
 
Mauro Carvalho Chehab 已提交
604
		if (msp_debug)
605 606
			msp3400c_print_mode(client);

607 608 609 610
		/* monitor tv audio mode, the first time don't wait
		   so long to get a quick stereo/bilingual result */
		if (msp_sleep(state, 1000))
			goto restart;
611
		while (state->watch_stereo) {
612
			if (msp_sleep(state, 5000))
613 614 615 616
				goto restart;
			watch_stereo(client);
		}
	}
M
 
Mauro Carvalho Chehab 已提交
617
	v4l_dbg(1, msp_debug, client, "thread: exit\n");
618 619 620 621 622 623 624 625
	return 0;
}


int msp3410d_thread(void *data)
{
	struct i2c_client *client = data;
	struct msp_state *state = i2c_get_clientdata(client);
626
	int val, i, std;
627

M
 
Mauro Carvalho Chehab 已提交
628
	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
629 630

	for (;;) {
M
 
Mauro Carvalho Chehab 已提交
631
		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
632
		msp_sleep(state,-1);
M
 
Mauro Carvalho Chehab 已提交
633
		v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n");
634 635

	restart:
636
		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
637 638 639 640 641 642
		state->restart = 0;
		if (kthread_should_stop())
			break;

		if (state->mode == MSP_MODE_EXTERN) {
			/* no carrier scan needed, just unmute */
M
 
Mauro Carvalho Chehab 已提交
643
			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
644 645 646 647 648 649 650 651 652 653 654
			msp_set_audio(client);
			continue;
		}

		/* put into sane state (and mute) */
		msp_reset(client);

		/* some time for the tuner to sync */
		if (msp_sleep(state,200))
			goto restart;

655 656
		/* start autodetect. Note: autodetect is not supported for
		   NTSC-M and radio, hence we force the standard in those cases. */
657 658
		if (state->radio)
			std = 0x40;
659
		else
660
			std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
661
		state->watch_stereo = 0;
662
		state->nicam_on = 0;
663

M
 
Mauro Carvalho Chehab 已提交
664
		if (msp_debug)
665
			v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n",
666
			       msp_standard_std_name(std), std);
667 668 669 670 671 672

		if (std != 1) {
			/* programmed some specific mode */
			val = std;
		} else {
			/* triggered autodetect */
673
			msp_write_dem(client, 0x20, std);
674
			for (;;) {
675
				if (msp_sleep(state, 100))
676 677 678 679 680 681
					goto restart;

				/* check results */
				val = msp_read_dem(client, 0x7e);
				if (val < 0x07ff)
					break;
682
				v4l_dbg(2, msp_debug, client, "detection still in progress\n");
683 684
			}
		}
685 686
		for (i = 0; msp_stdlist[i].name != NULL; i++)
			if (msp_stdlist[i].retval == val)
687
				break;
M
 
Mauro Carvalho Chehab 已提交
688
		v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
689 690 691 692 693
			msp_standard_std_name(val), val);
		state->main   = msp_stdlist[i].main;
		state->second = msp_stdlist[i].second;
		state->std = val;

M
 
Mauro Carvalho Chehab 已提交
694
		if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
695
				(val != 0x0009)) {
696
			/* autodetection has failed, let backup */
M
 
Mauro Carvalho Chehab 已提交
697
			v4l_dbg(1, msp_debug, client, "autodetection failed,"
698 699
				" switching to backup standard: %s (0x%04x)\n",
				msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val);
700
			state->std = val = 0x0009;
701 702 703 704 705 706 707
			msp_write_dem(client, 0x20, val);
		}

		/* set stereo */
		switch (val) {
		case 0x0008: /* B/G NICAM */
		case 0x000a: /* I NICAM */
708 709
		case 0x000b: /* D/K NICAM */
			if (val == 0x000a)
710
				state->mode = MSP_MODE_FM_NICAM2;
711 712
			else
				state->mode = MSP_MODE_FM_NICAM1;
713 714 715 716 717 718 719 720 721 722 723 724
			/* just turn on stereo */
			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
			state->nicam_on = 1;
			state->watch_stereo = 1;
			break;
		case 0x0009:
			state->mode = MSP_MODE_AM_NICAM;
			state->rxsubchans = V4L2_TUNER_SUB_MONO;
			state->nicam_on = 1;
			state->watch_stereo = 1;
			break;
		case 0x0020: /* BTSC */
725
			/* The pre-'G' models only have BTSC-mono */
726
			state->mode = MSP_MODE_BTSC;
727
			state->rxsubchans = V4L2_TUNER_SUB_MONO;
728 729
			break;
		case 0x0040: /* FM radio */
730
			state->mode = MSP_MODE_FM_RADIO;
731
			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
732
			/* not needed in theory if we have radio, but
733
			   short programming enables carrier mute */
734 735
			msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
			msp3400c_set_carrier(client, MSP_CARRIER(10.7),
736
					    MSP_CARRIER(10.7));
737
			/* scart routing (this doesn't belong here I think) */
738 739
			msp_set_scart(client,SCART_IN2,0);
			break;
740
		case 0x0002:
741 742 743
		case 0x0003:
		case 0x0004:
		case 0x0005:
744
			state->mode = MSP_MODE_FM_TERRA;
745 746 747 748 749
			state->rxsubchans = V4L2_TUNER_SUB_MONO;
			state->watch_stereo = 1;
			break;
		}

750 751 752 753 754 755
		/* set various prescales */
		msp_write_dsp(client, 0x0d, 0x1900); /* scart */
		msp_write_dsp(client, 0x0e, 0x3000); /* FM */
		if (state->has_nicam)
			msp_write_dsp(client, 0x10, 0x5a00); /* nicam */

756 757
		if (state->has_i2s_conf)
			msp_write_dem(client, 0x40, state->i2s_mode);
758

759 760 761 762
		/* unmute, restore misc registers */
		msp_set_audio(client);

		msp_write_dsp(client, 0x13, state->acb);
763 764 765 766 767 768
		msp3400c_set_audmode(client);

		/* monitor tv audio mode, the first time don't wait
		   so long to get a quick stereo/bilingual result */
		if (msp_sleep(state, 1000))
			goto restart;
769 770
		while (state->watch_stereo) {
			watch_stereo(client);
771 772
			if (msp_sleep(state, 5000))
				goto restart;
773 774
		}
	}
M
 
Mauro Carvalho Chehab 已提交
775
	v4l_dbg(1, msp_debug, client, "thread: exit\n");
776 777 778 779 780
	return 0;
}

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

781 782 783 784 785
/* msp34xxG + (autoselect no-thread)
 * this one uses both automatic standard detection and automatic sound
 * select which are available in the newer G versions
 * struct msp: only norm, acb and source are really used in this mode
 */
786

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
static int msp34xxg_modus(struct i2c_client *client)
{
	struct msp_state *state = i2c_get_clientdata(client);

	if (state->radio) {
		v4l_dbg(1, msp_debug, client, "selected radio modus\n");
		return 0x0001;
	}

	if (state->v4l2_std & V4L2_STD_PAL) {
		v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
		return 0x7001;
	}
	if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
		v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
		return 0x4001;
	}
	if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
		v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
		return 0x0001;
	}
	if (state->v4l2_std & V4L2_STD_MN) {
		v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
		return 0x2001;
	}
	if (state->v4l2_std & V4L2_STD_SECAM) {
		v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
		return 0x6001;
	}
	return 0x0001;
}

819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
 {
	struct msp_state *state = i2c_get_clientdata(client);
	int source, matrix;

	switch (state->audmode) {
	case V4L2_TUNER_MODE_MONO:
		source = 0; /* mono only */
		matrix = 0x30;
		break;
	case V4L2_TUNER_MODE_LANG1:
		source = 3; /* stereo or A */
		matrix = 0x00;
		break;
	case V4L2_TUNER_MODE_LANG2:
		source = 4; /* stereo or B */
		matrix = 0x10;
		break;
	case V4L2_TUNER_MODE_STEREO:
	default:
		source = 1; /* stereo or A|B */
		matrix = 0x20;
		break;
	}

	if (in == MSP_DSP_OUT_TUNER)
		source = (source << 8) | 0x20;
	/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
	   instead of 11, 12, 13. So we add one for that msp version. */
	else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
		source = ((in + 1) << 8) | matrix;
	else
		source = (in << 8) | matrix;

	v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n",
			in, source, reg);
	msp_write_dsp(client, reg, source);
}

static void msp34xxg_set_sources(struct i2c_client *client)
{
	struct msp_state *state = i2c_get_clientdata(client);
	u32 in = state->routing.input;

	msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
	/* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
	msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
	msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
	msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
	if (state->has_scart23_in_scart2_out)
		msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
	msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
}

873 874
/* (re-)initialize the msp34xxg */
static void msp34xxg_reset(struct i2c_client *client)
875 876
{
	struct msp_state *state = i2c_get_clientdata(client);
877
	int tuner = (state->routing.input >> 3) & 1;
878
	int modus;
879

880 881 882 883 884
	/* initialize std to 1 (autodetect) to signal that no standard is
	   selected yet. */
	state->std = 1;

	msp_reset(client);
885 886 887

	/* make sure that input/output is muted (paranoid mode) */
	/* ACB, mute DSP input, mute SCART 1 */
888
	msp_write_dsp(client, 0x13, 0x0f20);
889

890 891
	if (state->has_i2s_conf)
		msp_write_dem(client, 0x40, state->i2s_mode);
892 893

	/* step-by-step initialisation, as described in the manual */
894
	modus = msp34xxg_modus(client);
895
	modus |= tuner ? 0x100 : 0;
896
	msp_write_dem(client, 0x30, modus);
897 898 899

	/* write the dsps that may have an influence on
	   standard/audio autodetection right now */
900
	msp34xxg_set_sources(client);
901

902 903 904 905
	msp_write_dsp(client, 0x0d, 0x1900); /* scart */
	msp_write_dsp(client, 0x0e, 0x3000); /* FM */
	if (state->has_nicam)
		msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
906

907 908 909 910 911 912 913 914 915 916 917
	/* set identification threshold. Personally, I
	 * I set it to a higher value than the default
	 * of 0x190 to ignore noisy stereo signals.
	 * this needs tuning. (recommended range 0x00a0-0x03c0)
	 * 0x7f0 = forced mono mode
	 *
	 * a2 threshold for stereo/bilingual.
	 * Note: this register is part of the Manual/Compatibility mode.
	 * It is supported by all 'G'-family chips.
	 */
	msp_write_dem(client, 0x22, msp_stereo_thresh);
918 919 920 921 922 923
}

int msp34xxg_thread(void *data)
{
	struct i2c_client *client = data;
	struct msp_state *state = i2c_get_clientdata(client);
924
	int val, i;
925

M
 
Mauro Carvalho Chehab 已提交
926
	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
927 928

	for (;;) {
M
 
Mauro Carvalho Chehab 已提交
929
		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
930
		msp_sleep(state, -1);
M
 
Mauro Carvalho Chehab 已提交
931
		v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");
932 933

	restart:
M
 
Mauro Carvalho Chehab 已提交
934
		v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
935 936 937 938 939 940
		state->restart = 0;
		if (kthread_should_stop())
			break;

		/* setup the chip*/
		msp34xxg_reset(client);
941 942
		state->std = state->radio ? 0x40 : msp_standard;
		if (state->std != 1)
943
			goto unmute;
944 945
		/* start autodetect */
		msp_write_dem(client, 0x20, state->std);
946 947

		/* watch autodetect */
948
		v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
949 950 951 952 953 954 955
		for (i = 0; i < 10; i++) {
			if (msp_sleep(state, 100))
				goto restart;

			/* check results */
			val = msp_read_dem(client, 0x7e);
			if (val < 0x07ff) {
956
				state->std = val;
957 958
				break;
			}
M
 
Mauro Carvalho Chehab 已提交
959
			v4l_dbg(2, msp_debug, client, "detection still in progress\n");
960
		}
961
		if (state->std == 1) {
M
 
Mauro Carvalho Chehab 已提交
962
			v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");
963 964 965 966
			continue;
		}

	unmute:
967 968
		v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",
			msp_standard_std_name(state->std), state->std);
969 970 971 972 973 974 975 976

		/* unmute: dispatch sound to scart output, set scart volume */
		msp_set_audio(client);

		/* restore ACB */
		if (msp_write_dsp(client, 0x13, state->acb))
			return -1;

977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
		/* the periodic stereo/SAP check is only relevant for
		   the 0x20 standard (BTSC) */
		if (state->std != 0x20)
			continue;

		state->watch_stereo = 1;

		/* monitor tv audio mode, the first time don't wait
		   in order to get a quick stereo/SAP update */
		watch_stereo(client);
		while (state->watch_stereo) {
			watch_stereo(client);
			if (msp_sleep(state, 5000))
				goto restart;
		}
992
	}
M
 
Mauro Carvalho Chehab 已提交
993
	v4l_dbg(1, msp_debug, client, "thread: exit\n");
994 995 996
	return 0;
}

997
static int msp34xxg_detect_stereo(struct i2c_client *client)
998 999 1000 1001 1002
{
	struct msp_state *state = i2c_get_clientdata(client);
	int status = msp_read_dem(client, 0x0200);
	int is_bilingual = status & 0x100;
	int is_stereo = status & 0x40;
1003
	int oldrx = state->rxsubchans;
1004 1005 1006

	state->rxsubchans = 0;
	if (is_stereo)
1007
		state->rxsubchans = V4L2_TUNER_SUB_STEREO;
1008
	else
1009
		state->rxsubchans = V4L2_TUNER_SUB_MONO;
1010
	if (is_bilingual) {
1011 1012 1013 1014
		if (state->std == 0x20)
			state->rxsubchans |= V4L2_TUNER_SUB_SAP;
		else
			state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
1015
	}
M
 
Mauro Carvalho Chehab 已提交
1016
	v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
1017
		status, is_stereo, is_bilingual, state->rxsubchans);
1018
	return (oldrx != state->rxsubchans);
1019 1020
}

1021
static void msp34xxg_set_audmode(struct i2c_client *client)
1022 1023 1024
{
	struct msp_state *state = i2c_get_clientdata(client);

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
	if (state->std == 0x20) {
	       if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
		   (state->audmode == V4L2_TUNER_MODE_STEREO ||
		    state->audmode == V4L2_TUNER_MODE_LANG2)) {
			msp_write_dem(client, 0x20, 0x21);
	       } else {
			msp_write_dem(client, 0x20, 0x20);
	       }
	}

1035
	msp34xxg_set_sources(client);
1036 1037
}

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
void msp_set_audmode(struct i2c_client *client)
{
	struct msp_state *state = i2c_get_clientdata(client);

	switch (state->opmode) {
	case OPMODE_MANUAL:
	case OPMODE_AUTODETECT:
		msp3400c_set_audmode(client);
		break;
	case OPMODE_AUTOSELECT:
		msp34xxg_set_audmode(client);
		break;
	}
}

1053
int msp_detect_stereo(struct i2c_client *client)
1054 1055 1056 1057 1058 1059
{
	struct msp_state *state  = i2c_get_clientdata(client);

	switch (state->opmode) {
	case OPMODE_MANUAL:
	case OPMODE_AUTODETECT:
1060
		return msp3400c_detect_stereo(client);
1061
	case OPMODE_AUTOSELECT:
1062
		return msp34xxg_detect_stereo(client);
1063
	}
1064
	return 0;
1065 1066
}