brintos

brintos / linux-shallow public Read only

0
0
Text · 13.7 KiB · 268f05f Raw
586 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card3*4* Copyright (C) 2006 Mario Hlawitschka (dh1pa@amsat.org)5* Copyright (C) 2006 Marco Gittler (g.marco@freenet.de)6*7* see Documentation/driver-api/media/drivers/dvb-usb.rst for more information8*/9 10#define DVB_USB_LOG_PREFIX "opera"11 12#include "dvb-usb.h"13#include "stv0299.h"14 15#define OPERA_READ_MSG 016#define OPERA_WRITE_MSG 117#define OPERA_I2C_TUNER 0xd118 19#define READ_FX2_REG_REQ  0xba20#define READ_MAC_ADDR 0x0821#define OPERA_WRITE_FX2 0xbb22#define OPERA_TUNER_REQ 0xb123#define REG_1F_SYMBOLRATE_BYTE0 0x1f24#define REG_20_SYMBOLRATE_BYTE1 0x2025#define REG_21_SYMBOLRATE_BYTE2 0x2126 27#define ADDR_B600_VOLTAGE_13V (0x02)28#define ADDR_B601_VOLTAGE_18V (0x03)29#define ADDR_B1A6_STREAM_CTRL (0x04)30#define ADDR_B880_READ_REMOTE (0x05)31 32struct opera1_state {33	u32 last_key_pressed;34};35 36static int dvb_usb_opera1_debug;37module_param_named(debug, dvb_usb_opera1_debug, int, 0644);38MODULE_PARM_DESC(debug,39		 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."40		 DVB_USB_DEBUG_STATUS);41 42DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);43 44 45static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,46			    u8 * data, u16 len, int flags)47{48	int ret;49	u8 tmp;50	u8 *buf;51	unsigned int pipe = (flags == OPERA_READ_MSG) ?52		usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);53	u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;54 55	buf = kmalloc(len, GFP_KERNEL);56	if (!buf)57		return -ENOMEM;58 59	if (flags == OPERA_WRITE_MSG)60		memcpy(buf, data, len);61	ret = usb_control_msg(dev, pipe, request,62			request_type | USB_TYPE_VENDOR, value, 0x0,63			buf, len, 2000);64 65	if (request == OPERA_TUNER_REQ) {66		tmp = buf[0];67		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),68			    OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,69			    0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) {70			ret = 0;71			goto out;72		}73		buf[0] = tmp;74	}75	if (flags == OPERA_READ_MSG)76		memcpy(data, buf, len);77out:78	kfree(buf);79	return ret;80}81 82/* I2C */83 84static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr,85				  u8 * buf, u16 len)86{87	int ret = 0;88	u8 request;89	u16 value;90 91	if (!dev) {92		info("no usb_device");93		return -EINVAL;94	}95	if (mutex_lock_interruptible(&dev->usb_mutex) < 0)96		return -EAGAIN;97 98	switch (addr>>1){99		case ADDR_B600_VOLTAGE_13V:100			request=0xb6;101			value=0x00;102			break;103		case ADDR_B601_VOLTAGE_18V:104			request=0xb6;105			value=0x01;106			break;107		case ADDR_B1A6_STREAM_CTRL:108			request=0xb1;109			value=0xa6;110			break;111		case ADDR_B880_READ_REMOTE:112			request=0xb8;113			value=0x80;114			break;115		default:116			request=0xb1;117			value=addr;118	}119	ret = opera1_xilinx_rw(dev->udev, request,120		value, buf, len,121		addr&0x01?OPERA_READ_MSG:OPERA_WRITE_MSG);122 123	mutex_unlock(&dev->usb_mutex);124	return ret;125}126 127static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],128			   int num)129{130	struct dvb_usb_device *d = i2c_get_adapdata(adap);131	int i = 0, tmp = 0;132 133	if (!d)134		return -ENODEV;135	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)136		return -EAGAIN;137 138	for (i = 0; i < num; i++) {139		if ((tmp = opera1_usb_i2c_msgxfer(d,140					(msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0),141					msg[i].buf,142					msg[i].len143					)) != msg[i].len) {144			break;145		}146		if (dvb_usb_opera1_debug & 0x10)147			info("sending i2c message %d %d", tmp, msg[i].len);148	}149	mutex_unlock(&d->i2c_mutex);150	return num;151}152 153static u32 opera1_i2c_func(struct i2c_adapter *adapter)154{155	return I2C_FUNC_I2C;156}157 158static struct i2c_algorithm opera1_i2c_algo = {159	.master_xfer = opera1_i2c_xfer,160	.functionality = opera1_i2c_func,161};162 163static int opera1_set_voltage(struct dvb_frontend *fe,164			      enum fe_sec_voltage voltage)165{166	static u8 command_13v[1]={0x00};167	static u8 command_18v[1]={0x01};168	struct i2c_msg msg[] = {169		{.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1},170	};171	struct dvb_usb_adapter *udev_adap = fe->dvb->priv;172	if (voltage == SEC_VOLTAGE_18) {173		msg[0].addr = ADDR_B601_VOLTAGE_18V;174		msg[0].buf = command_18v;175	}176	i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);177	return 0;178}179 180static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,181					  u32 ratio)182{183	stv0299_writereg(fe, 0x13, 0x98);184	stv0299_writereg(fe, 0x14, 0x95);185	stv0299_writereg(fe, REG_1F_SYMBOLRATE_BYTE0, (ratio >> 16) & 0xff);186	stv0299_writereg(fe, REG_20_SYMBOLRATE_BYTE1, (ratio >> 8) & 0xff);187	stv0299_writereg(fe, REG_21_SYMBOLRATE_BYTE2, (ratio) & 0xf0);188	return 0;189 190}191static u8 opera1_inittab[] = {192	0x00, 0xa1,193	0x01, 0x15,194	0x02, 0x30,195	0x03, 0x00,196	0x04, 0x7d,197	0x05, 0x05,198	0x06, 0x02,199	0x07, 0x00,200	0x0b, 0x00,201	0x0c, 0x01,202	0x0d, 0x81,203	0x0e, 0x44,204	0x0f, 0x19,205	0x10, 0x3f,206	0x11, 0x84,207	0x12, 0xda,208	0x13, 0x98,209	0x14, 0x95,210	0x15, 0xc9,211	0x16, 0xeb,212	0x17, 0x00,213	0x18, 0x19,214	0x19, 0x8b,215	0x1a, 0x00,216	0x1b, 0x82,217	0x1c, 0x7f,218	0x1d, 0x00,219	0x1e, 0x00,220	REG_1F_SYMBOLRATE_BYTE0, 0x06,221	REG_20_SYMBOLRATE_BYTE1, 0x50,222	REG_21_SYMBOLRATE_BYTE2, 0x10,223	0x22, 0x00,224	0x23, 0x00,225	0x24, 0x37,226	0x25, 0xbc,227	0x26, 0x00,228	0x27, 0x00,229	0x28, 0x00,230	0x29, 0x1e,231	0x2a, 0x14,232	0x2b, 0x1f,233	0x2c, 0x09,234	0x2d, 0x0a,235	0x2e, 0x00,236	0x2f, 0x00,237	0x30, 0x00,238	0x31, 0x1f,239	0x32, 0x19,240	0x33, 0xfc,241	0x34, 0x13,242	0xff, 0xff,243};244 245static struct stv0299_config opera1_stv0299_config = {246	.demod_address = 0xd0>>1,247	.min_delay_ms = 100,248	.mclk = 88000000UL,249	.invert = 1,250	.skip_reinit = 0,251	.lock_output = STV0299_LOCKOUTPUT_0,252	.volt13_op0_op1 = STV0299_VOLT13_OP0,253	.inittab = opera1_inittab,254	.set_symbol_rate = opera1_stv0299_set_symbol_rate,255};256 257static int opera1_frontend_attach(struct dvb_usb_adapter *d)258{259	d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,260				      &d->dev->i2c_adap);261	if ((d->fe_adap[0].fe) != NULL) {262		d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;263		return 0;264	}265	info("not attached stv0299");266	return -EIO;267}268 269static int opera1_tuner_attach(struct dvb_usb_adapter *adap)270{271	dvb_attach(272		dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,273		&adap->dev->i2c_adap, DVB_PLL_OPERA1274	);275	return 0;276}277 278static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff)279{280	u8 val = onoff ? 0x01 : 0x00;281 282	if (dvb_usb_opera1_debug)283		info("power %s", onoff ? "on" : "off");284	return opera1_xilinx_rw(d->udev, 0xb7, val,285				&val, 1, OPERA_WRITE_MSG);286}287 288static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)289{290	static u8 buf_start[2] = { 0xff, 0x03 };291	static u8 buf_stop[2] = { 0xff, 0x00 };292	struct i2c_msg start_tuner[] = {293		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = onoff ? buf_start : buf_stop,.len = 2},294	};295	if (dvb_usb_opera1_debug)296		info("streaming %s", onoff ? "on" : "off");297	i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1);298	return 0;299}300 301static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,302			     int onoff)303{304	u8 b_pid[3];305	struct i2c_msg msg[] = {306		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},307	};308	if (dvb_usb_opera1_debug)309		info("pidfilter index: %d pid: %d %s", index, pid,310			onoff ? "on" : "off");311	b_pid[0] = (2 * index) + 4;312	b_pid[1] = onoff ? (pid & 0xff) : (0x00);313	b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00);314	i2c_transfer(&adap->dev->i2c_adap, msg, 1);315	return 0;316}317 318static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)319{320	int u = 0x04;321	u8 b_pid[3];322	struct i2c_msg msg[] = {323		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},324	};325	if (dvb_usb_opera1_debug)326		info("%s hw-pidfilter", onoff ? "enable" : "disable");327	for (; u < 0x7e; u += 2) {328		b_pid[0] = u;329		b_pid[1] = 0;330		b_pid[2] = 0x80;331		i2c_transfer(&adap->dev->i2c_adap, msg, 1);332	}333	return 0;334}335 336static struct rc_map_table rc_map_opera1_table[] = {337	{0x5fa0, KEY_1},338	{0x51af, KEY_2},339	{0x5da2, KEY_3},340	{0x41be, KEY_4},341	{0x0bf5, KEY_5},342	{0x43bd, KEY_6},343	{0x47b8, KEY_7},344	{0x49b6, KEY_8},345	{0x05fa, KEY_9},346	{0x45ba, KEY_0},347	{0x09f6, KEY_CHANNELUP},	/*chanup */348	{0x1be5, KEY_CHANNELDOWN},	/*chandown */349	{0x5da3, KEY_VOLUMEDOWN},	/*voldown */350	{0x5fa1, KEY_VOLUMEUP},		/*volup */351	{0x07f8, KEY_SPACE},		/*tab */352	{0x1fe1, KEY_OK},		/*play ok */353	{0x1be4, KEY_ZOOM},		/*zoom */354	{0x59a6, KEY_MUTE},		/*mute */355	{0x5ba5, KEY_RADIO},		/*tv/f */356	{0x19e7, KEY_RECORD},		/*rec */357	{0x01fe, KEY_STOP},		/*Stop */358	{0x03fd, KEY_PAUSE},		/*pause */359	{0x03fc, KEY_SCREEN},		/*<- -> */360	{0x07f9, KEY_CAMERA},		/*capture */361	{0x47b9, KEY_ESC},		/*exit */362	{0x43bc, KEY_POWER2},		/*power */363};364 365static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)366{367	struct opera1_state *opst = dev->priv;368	u8 rcbuffer[32];369	const u16 startmarker1 = 0x10ed;370	const u16 startmarker2 = 0x11ec;371	struct i2c_msg read_remote[] = {372		{.addr = ADDR_B880_READ_REMOTE,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32},373	};374	int i = 0;375	u32 send_key = 0;376 377	if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) {378		for (i = 0; i < 32; i++) {379			if (rcbuffer[i])380				send_key |= 1;381			if (i < 31)382				send_key = send_key << 1;383		}384		if (send_key & 0x8000)385			send_key = (send_key << 1) | (send_key >> 15 & 0x01);386 387		if (send_key == 0xffff && opst->last_key_pressed != 0) {388			*state = REMOTE_KEY_REPEAT;389			*event = opst->last_key_pressed;390			return 0;391		}392		for (; send_key != 0;) {393			if (send_key >> 16 == startmarker2) {394				break;395			} else if (send_key >> 16 == startmarker1) {396				send_key =397					(send_key & 0xfffeffff) | (startmarker1 << 16);398				break;399			} else400				send_key >>= 1;401		}402 403		if (send_key == 0)404			return 0;405 406		send_key = (send_key & 0xffff) | 0x0100;407 408		for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) {409			if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) {410				*state = REMOTE_KEY_PRESSED;411				*event = rc_map_opera1_table[i].keycode;412				opst->last_key_pressed =413					rc_map_opera1_table[i].keycode;414				break;415			}416			opst->last_key_pressed = 0;417		}418	} else419		*state = REMOTE_NO_KEY_PRESSED;420	return 0;421}422 423enum {424	CYPRESS_OPERA1_COLD,425	OPERA1_WARM,426};427 428static struct usb_device_id opera1_table[] = {429	DVB_USB_DEV(CYPRESS, CYPRESS_OPERA1_COLD),430	DVB_USB_DEV(OPERA1, OPERA1_WARM),431	{ }432};433 434MODULE_DEVICE_TABLE(usb, opera1_table);435 436static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6])437{438	int ret;439	u8 command[] = { READ_MAC_ADDR };440	ret = opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG);441	if (ret)442		return ret;443	ret = opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG);444	if (ret)445		return ret;446	return 0;447}448static int opera1_xilinx_load_firmware(struct usb_device *dev,449				       const char *filename)450{451	const struct firmware *fw = NULL;452	u8 *b, *p;453	int ret = 0, i,fpgasize=40;454	u8 testval;455	info("start downloading fpga firmware %s",filename);456 457	if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {458		err("did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",459			filename);460		return ret;461	} else {462		p = kmalloc(fw->size, GFP_KERNEL);463		opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG);464		if (p != NULL && testval != 0x67) {465 466			u8 reset = 0, fpga_command = 0;467			memcpy(p, fw->data, fw->size);468			/* clear fpga ? */469			opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1,470					 OPERA_WRITE_MSG);471			for (i = 0; i < fw->size;) {472				if ( (fw->size - i) <fpgasize){473				    fpgasize=fw->size-i;474				}475				b = (u8 *) p + i;476				if (opera1_xilinx_rw477					(dev, OPERA_WRITE_FX2, 0x0, b , fpgasize,478						OPERA_WRITE_MSG) != fpgasize479					) {480					err("error while transferring firmware");481					ret = -EINVAL;482					break;483				}484				i = i + fpgasize;485			}486			/* restart the CPU */487			if (ret || opera1_xilinx_rw488					(dev, 0xa0, 0xe600, &reset, 1,489					OPERA_WRITE_MSG) != 1) {490				err("could not restart the USB controller CPU.");491				ret = -EINVAL;492			}493		}494	}495	kfree(p);496	release_firmware(fw);497	return ret;498}499 500static struct dvb_usb_device_properties opera1_properties = {501	.caps = DVB_USB_IS_AN_I2C_ADAPTER,502	.usb_ctrl = CYPRESS_FX2,503	.firmware = "dvb-usb-opera-01.fw",504	.size_of_priv = sizeof(struct opera1_state),505 506	.power_ctrl = opera1_power_ctrl,507	.i2c_algo = &opera1_i2c_algo,508 509	.rc.legacy = {510		.rc_map_table = rc_map_opera1_table,511		.rc_map_size = ARRAY_SIZE(rc_map_opera1_table),512		.rc_interval = 200,513		.rc_query = opera1_rc_query,514	},515	.read_mac_address = opera1_read_mac_address,516	.generic_bulk_ctrl_endpoint = 0x00,517	/* parameter for the MPEG2-data transfer */518	.num_adapters = 1,519	.adapter = {520		{521		.num_frontends = 1,522		.fe = {{523			.frontend_attach = opera1_frontend_attach,524			.streaming_ctrl = opera1_streaming_ctrl,525			.tuner_attach = opera1_tuner_attach,526			.caps =527				DVB_USB_ADAP_HAS_PID_FILTER |528				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,529			.pid_filter = opera1_pid_filter,530			.pid_filter_ctrl = opera1_pid_filter_control,531			.pid_filter_count = 252,532			.stream = {533				.type = USB_BULK,534				.count = 10,535				.endpoint = 0x82,536				.u = {537					.bulk = {538						.buffersize = 4096,539					}540				}541			},542		}},543		}544	},545	.num_device_descs = 1,546	.devices = {547		{"Opera1 DVB-S USB2.0",548			{&opera1_table[CYPRESS_OPERA1_COLD], NULL},549			{&opera1_table[OPERA1_WARM], NULL},550		},551	}552};553 554static int opera1_probe(struct usb_interface *intf,555			const struct usb_device_id *id)556{557	struct usb_device *udev = interface_to_usbdev(intf);558 559	if (le16_to_cpu(udev->descriptor.idProduct) == USB_PID_OPERA1_WARM &&560	    le16_to_cpu(udev->descriptor.idVendor) == USB_VID_OPERA1 &&561		opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga-01.fw") != 0562	    ) {563		return -EINVAL;564	}565 566	if (0 != dvb_usb_device_init(intf, &opera1_properties,567				     THIS_MODULE, NULL, adapter_nr))568		return -EINVAL;569	return 0;570}571 572static struct usb_driver opera1_driver = {573	.name = "opera1",574	.probe = opera1_probe,575	.disconnect = dvb_usb_device_exit,576	.id_table = opera1_table,577};578 579module_usb_driver(opera1_driver);580 581MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@amsat.org");582MODULE_AUTHOR("Marco Gittler (c) g.marco@freenet.de");583MODULE_DESCRIPTION("Driver for Opera1 DVB-S device");584MODULE_VERSION("0.1");585MODULE_LICENSE("GPL");586