m920x.c 12.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
 *
 * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.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, version 2.
 *
 * see Documentation/dvb/README.dvb-usb for more information
 */
11

12
#include "m920x.h"
13 14 15

#include "mt352.h"
#include "mt352_priv.h"
16
#include "qt1010.h"
17 18

/* debug */
19
static int dvb_usb_m920x_debug;
20
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);

static struct dvb_usb_rc_key megasky_rc_keys [] = {
	{ 0x0, 0x12, KEY_POWER },
	{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
	{ 0x0, 0x02, KEY_CHANNELUP },
	{ 0x0, 0x05, KEY_CHANNELDOWN },
	{ 0x0, 0x03, KEY_VOLUMEUP },
	{ 0x0, 0x06, KEY_VOLUMEDOWN },
	{ 0x0, 0x04, KEY_MUTE },
	{ 0x0, 0x07, KEY_OK }, /* TS */
	{ 0x0, 0x08, KEY_STOP },
	{ 0x0, 0x09, KEY_MENU }, /* swap */
	{ 0x0, 0x0a, KEY_REWIND },
	{ 0x0, 0x1b, KEY_PAUSE },
	{ 0x0, 0x1f, KEY_FASTFORWARD },
	{ 0x0, 0x0c, KEY_RECORD },
	{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
	{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
};

42 43
static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
			     u16 index, void *data, int size)
44 45 46 47 48 49
{
	int ret;

	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
			      request, USB_TYPE_VENDOR | USB_DIR_IN,
			      value, index, data, size, 2000);
50 51
	if (ret < 0) {
		printk(KERN_INFO "m920x_read = error: %d\n", ret);
52
		return ret;
53
	}
54

55 56
	if (ret != size) {
		deb_rc("m920x_read = no data\n");
57
		return -EIO;
58
	}
59 60 61 62

	return 0;
}

63 64
static inline int m9206_write(struct usb_device *udev, u8 request,
			      u16 value, u16 index)
65 66 67 68 69 70
{
	int ret;

	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
			      request, USB_TYPE_VENDOR | USB_DIR_OUT,
			      value, index, NULL, 0, 2000);
71

72 73 74
	return ret;
}

75
static int m9206_init(struct dvb_usb_device *d)
76 77 78 79
{
	int ret = 0;

	/* Remote controller init. */
80 81 82
	if (d->props.rc_query) {
		if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
			return ret;
83

84 85 86
		if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
			return ret;
	}
87 88 89 90 91 92

	return ret;
}

static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
93
	struct m9206_state *m = d->priv;
94 95 96
	int i, ret = 0;
	u8 rc_state[2];

97
	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
98 99
		goto unlock;

100
	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
101 102
		goto unlock;

103 104 105
	for (i = 0; i < d->props.rc_key_map_size; i++)
		if (d->props.rc_key_map[i].data == rc_state[1]) {
			*event = d->props.rc_key_map[i].event;
106 107 108 109 110 111 112 113

			switch(rc_state[0]) {
			case 0x80:
				*state = REMOTE_NO_KEY_PRESSED;
				goto unlock;

			case 0x93:
			case 0x92:
114
				m->rep_count = 0;
115 116 117 118
				*state = REMOTE_KEY_PRESSED;
				goto unlock;

			case 0x91:
119 120 121
				/* For comfort. */
				if (++m->rep_count > 2)
					*state = REMOTE_KEY_REPEAT;
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
				goto unlock;

			default:
				deb_rc("Unexpected rc response %x\n", rc_state[0]);
				*state = REMOTE_NO_KEY_PRESSED;
				goto unlock;
			}
		}

	if (rc_state[1] != 0)
		deb_rc("Unknown rc key %x\n", rc_state[1]);

	*state = REMOTE_NO_KEY_PRESSED;

	unlock:

	return ret;
}

/* I2C */
142 143
static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
			  int num)
144 145
{
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
146
	int i, j;
147 148
	int ret = 0;

149 150 151
	if (!num)
		return -EINVAL;

152 153 154 155
	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
		return -EAGAIN;

	for (i = 0; i < num; i++) {
156 157 158 159 160 161
		if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) ||
		    msg[i].len == 0) {
			/* For a 0 byte message, I think sending the address to index 0x80|0x40
			 * would be the correct thing to do.  However, zero byte messages are
			 * only used for probing, and since we don't know how to get the slave's
			 * ack, we can't probe. */
162 163 164 165 166
			ret = -ENOTSUPP;
			goto unlock;
		}
		/* Send START & address/RW bit */
		if (!(msg[i].flags & I2C_M_NOSTART)) {
167
			if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0)
168
				goto unlock;
169 170 171 172 173 174 175 176
			/* Should check for ack here, if we knew how. */
		}
		if (msg[i].flags & I2C_M_RD) {
			for (j = 0; j < msg[i].len; j++) {
				/* Last byte of transaction? Send STOP, otherwise send ACK. */
				int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01;
				if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0)
					goto unlock;
177
			}
178
		} else {
179 180 181 182 183 184
			for (j = 0; j < msg[i].len; j++) {
				/* Last byte of transaction? Then send STOP. */
				int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00;
				if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
					goto unlock;
				/* Should check for ack here too. */
185
			}
186 187
		}
	}
188
	ret = num;
189 190

unlock:
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	mutex_unlock(&d->i2c_mutex);

	return ret;
}

static u32 m9206_i2c_func(struct i2c_adapter *adapter)
{
	return I2C_FUNC_I2C;
}

static struct i2c_algorithm m9206_i2c_algo = {
	.master_xfer   = m9206_i2c_xfer,
	.functionality = m9206_i2c_func,
};


207 208
static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
			    int pid)
209 210 211 212 213 214 215 216
{
	int ret = 0;

	if (pid >= 0x8000)
		return -EINVAL;

	pid |= 0x8000;

217
	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
218 219
		return ret;

220
	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
221 222 223 224 225
		return ret;

	return ret;
}

226
static int m9206_update_filters(struct dvb_usb_adapter *adap)
227
{
228 229 230
	struct m9206_state *m = adap->dev->priv;
	int enabled = m->filtering_enabled;
	int i, ret = 0, filter = 0;
231

232 233 234
	for (i = 0; i < M9206_MAX_FILTERS; i++)
		if (m->filters[i] == 8192)
			enabled = 0;
235

236
	/* Disable all filters */
237
	if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
238
		return ret;
239

240
	for (i = 0; i < M9206_MAX_FILTERS; i++)
241
		if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
242 243
			return ret;

244
	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
245 246 247 248 249 250 251 252
		return ret;

	/* Set */
	if (enabled) {
		for (i = 0; i < M9206_MAX_FILTERS; i++) {
			if (m->filters[i] == 0)
				continue;

253
			if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
254 255 256 257
				return ret;

			filter++;
		}
258
	}
259

260
	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
261
		return ret;
262 263 264 265

	return ret;
}

266
static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
267
{
268
	struct m9206_state *m = adap->dev->priv;
269

270
	m->filtering_enabled = onoff ? 1 : 0;
271

272 273
	return m9206_update_filters(adap);
}
274

275 276
static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
			    int onoff)
277 278
{
	struct m9206_state *m = adap->dev->priv;
279

280
	m->filters[index] = onoff ? pid : 0;
281

282
	return m9206_update_filters(adap);
283 284
}

285 286
static int m9206_firmware_download(struct usb_device *udev,
				   const struct firmware *fw)
287 288 289 290 291 292 293
{
	u16 value, index, size;
	u8 read[4], *buff;
	int i, pass, ret = 0;

	buff = kmalloc(65536, GFP_KERNEL);

294
	if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
295 296 297
		goto done;
	deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);

298
	if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
		goto done;
	deb_rc("%x\n", read[0]);

	for (pass = 0; pass < 2; pass++) {
		for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
			value = le16_to_cpu(*(u16 *)(fw->data + i));
			i += sizeof(u16);

			index = le16_to_cpu(*(u16 *)(fw->data + i));
			i += sizeof(u16);

			size = le16_to_cpu(*(u16 *)(fw->data + i));
			i += sizeof(u16);

			if (pass == 1) {
				/* Will stall if using fw->data ... */
				memcpy(buff, fw->data + i, size);

				ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
318 319
					    M9206_FW,
					    USB_TYPE_VENDOR | USB_DIR_OUT,
320 321 322 323 324 325 326 327 328 329 330
					    value, index, buff, size, 20);
				if (ret != size) {
					deb_rc("error while uploading fw!\n");
					ret = -EIO;
					goto done;
				}
				msleep(3);
			}
			i += size;
		}
		if (i != fw->size) {
331
			deb_rc("bad firmware file!\n");
332 333 334 335 336 337 338 339
			ret = -EINVAL;
			goto done;
		}
	}

	msleep(36);

	/* m9206 will disconnect itself from the bus after this. */
340
	(void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
341 342 343 344 345 346 347 348
	deb_rc("firmware uploaded!\n");

	done:
	kfree(buff);

	return ret;
}

349
/* Callbacks for DVB USB */
350 351 352 353
static int m920x_identify_state(struct usb_device *udev,
				struct dvb_usb_device_properties *props,
				struct dvb_usb_device_description **desc,
				int *cold)
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
{
	struct usb_host_interface *alt;

	alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
	*cold = (alt == NULL) ? 1 : 0;

	return 0;
}

static int megasky_mt352_demod_init(struct dvb_frontend *fe)
{
	u8 config[] = { CONFIG, 0x3d };
	u8 clock[] = { CLOCK_CTL, 0x30 };
	u8 reset[] = { RESET, 0x80 };
	u8 adc_ctl[] = { ADC_CTL_1, 0x40 };
	u8 agc[] = { AGC_TARGET, 0x1c, 0x20 };
	u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 };
	u8 unk1[] = { 0x93, 0x1a };
	u8 unk2[] = { 0xb5, 0x7a };

	mt352_write(fe, config, ARRAY_SIZE(config));
	mt352_write(fe, clock, ARRAY_SIZE(clock));
	mt352_write(fe, reset, ARRAY_SIZE(reset));
	mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
	mt352_write(fe, agc, ARRAY_SIZE(agc));
	mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
	mt352_write(fe, unk1, ARRAY_SIZE(unk1));
	mt352_write(fe, unk2, ARRAY_SIZE(unk2));

	deb_rc("Demod init!\n");

	return 0;
}

static struct mt352_config megasky_mt352_config = {
389
	.demod_address = 0x0f,
390 391 392 393 394 395 396 397 398 399 400 401 402 403
	.no_tuner = 1,
	.demod_init = megasky_mt352_demod_init,
};

static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
{
	deb_rc("megasky_frontend_attach!\n");

	if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
		return -EIO;

	return 0;
}

404
static struct qt1010_config megasky_qt1010_config = {
405
	.i2c_address = 0x62
406 407
};

408
static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
409
{
410 411 412 413 414
	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
		       &megasky_qt1010_config) == NULL)
		return -ENODEV;

	return 0;
415 416
}

417 418 419
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties megasky_properties;

420 421
static int m920x_probe(struct usb_interface *intf,
		       const struct usb_device_id *id)
422 423 424 425 426
{
	struct dvb_usb_device *d;
	struct usb_host_interface *alt;
	int ret;

427
	deb_rc("Probed!\n");
428

429 430
	if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0)
		goto found;
431

432
	return ret;
433

434 435 436 437 438
found:
	alt = usb_altnum_to_altsetting(intf, 1);
	if (alt == NULL) {
		deb_rc("No alt found!\n");
		return -ENODEV;
439
	}
440 441 442 443 444 445 446 447 448

	ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
				alt->desc.bAlternateSetting);
	if (ret < 0)
		return ret;

	if ((ret = m9206_init(d)) != 0)
		return ret;

449 450 451 452 453 454 455 456 457
	return ret;
}

static struct usb_device_id m920x_table [] = {
		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
		{ }		/* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, m920x_table);

458
static struct dvb_usb_device_properties megasky_properties = {
459
	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
460

461 462 463 464
	.usb_ctrl = DEVICE_SPECIFIC,
	.firmware = "dvb-usb-megasky-02.fw",
	.download_firmware = m9206_firmware_download,

465
	.rc_interval      = 100,
466 467 468 469
	.rc_key_map       = megasky_rc_keys,
	.rc_key_map_size  = ARRAY_SIZE(megasky_rc_keys),
	.rc_query         = m9206_rc_query,

470
	.size_of_priv     = sizeof(struct m9206_state),
471

472
	.identify_state   = m920x_identify_state,
473 474
	.num_adapters = 1,
	.adapter = {{
475 476 477
		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,

478 479 480 481
		.pid_filter_count = 8,
		.pid_filter       = m9206_pid_filter,
		.pid_filter_ctrl  = m9206_pid_filter_ctrl,

482 483
		.frontend_attach  = megasky_mt352_frontend_attach,
		.tuner_attach     = megasky_qt1010_tuner_attach,
484 485 486 487 488 489 490 491 492 493 494 495

		.stream = {
			.type = USB_BULK,
			.count = 8,
			.endpoint = 0x81,
			.u = {
				.bulk = {
					.buffersize = 512,
				}
			}
		},
	}},
496 497 498 499 500
	.i2c_algo         = &m9206_i2c_algo,

	.num_device_descs = 1,
	.devices = {
		{   "MSI Mega Sky 580 DVB-T USB2.0",
501
			{ &m920x_table[0], NULL },
502 503 504 505 506
			{ NULL },
		},
	}
};

507 508
static struct usb_driver m920x_driver = {
	.name		= "dvb_usb_m920x",
509
	.probe		= m920x_probe,
510
	.disconnect	= dvb_usb_device_exit,
511
	.id_table	= m920x_table,
512 513 514
};

/* module stuff */
515
static int __init m920x_module_init(void)
516 517 518
{
	int ret;

519
	if ((ret = usb_register(&m920x_driver))) {
520 521 522 523 524 525 526
		err("usb_register failed. Error number %d", ret);
		return ret;
	}

	return 0;
}

527
static void __exit m920x_module_exit(void)
528 529
{
	/* deregister this driver from the USB subsystem */
530
	usb_deregister(&m920x_driver);
531 532
}

533 534
module_init (m920x_module_init);
module_exit (m920x_module_exit);
535 536

MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
537
MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
538 539
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");