19bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota/* DVB USB compliant Linux driver for the
2458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
39bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *
4458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
5458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
69bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *
79bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota * Thanks to GENPIX for the sample code used to implement this module.
89bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *
99bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota * This module is based off the vp7045 and vp702x modules
109bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *
119bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *	This program is free software; you can redistribute it and/or modify it
129bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *	under the terms of the GNU General Public License as published by the Free
139bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *	Software Foundation, version 2.
149bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota *
159bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota * see Documentation/dvb/README.dvb-usb for more information
169bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota */
179bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota#include "gp8psk.h"
189bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
199bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota/* debug */
209bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
219bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotaint dvb_usb_gp8psk_debug;
229bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotamodule_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
239bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan NisotaMODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
249bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2578e92006f410a4044f8c1760c25ac9d11d259aa2Janne GrunauDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
2678e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau
279e21ccaa69674e1b0aa887722801258f7de842dbVDR Userstatic int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
289e21ccaa69674e1b0aa887722801258f7de842dbVDR User{
299e21ccaa69674e1b0aa887722801258f7de842dbVDR User	return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
309e21ccaa69674e1b0aa887722801258f7de842dbVDR User}
319e21ccaa69674e1b0aa887722801258f7de842dbVDR User
329e21ccaa69674e1b0aa887722801258f7de842dbVDR Userstatic int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers)
339e21ccaa69674e1b0aa887722801258f7de842dbVDR User{
349e21ccaa69674e1b0aa887722801258f7de842dbVDR User	return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1));
359e21ccaa69674e1b0aa887722801258f7de842dbVDR User}
369e21ccaa69674e1b0aa887722801258f7de842dbVDR User
379e21ccaa69674e1b0aa887722801258f7de842dbVDR Userstatic void gp8psk_info(struct dvb_usb_device *d)
389e21ccaa69674e1b0aa887722801258f7de842dbVDR User{
399e21ccaa69674e1b0aa887722801258f7de842dbVDR User	u8 fpga_vers, fw_vers[6];
409e21ccaa69674e1b0aa887722801258f7de842dbVDR User
419e21ccaa69674e1b0aa887722801258f7de842dbVDR User	if (!gp8psk_get_fw_version(d, fw_vers))
429e21ccaa69674e1b0aa887722801258f7de842dbVDR User		info("FW Version = %i.%02i.%i (0x%x)  Build %4i/%02i/%02i",
439e21ccaa69674e1b0aa887722801258f7de842dbVDR User		fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers),
449e21ccaa69674e1b0aa887722801258f7de842dbVDR User		2000 + fw_vers[5], fw_vers[4], fw_vers[3]);
459e21ccaa69674e1b0aa887722801258f7de842dbVDR User	else
469e21ccaa69674e1b0aa887722801258f7de842dbVDR User		info("failed to get FW version");
479e21ccaa69674e1b0aa887722801258f7de842dbVDR User
489e21ccaa69674e1b0aa887722801258f7de842dbVDR User	if (!gp8psk_get_fpga_version(d, &fpga_vers))
499e21ccaa69674e1b0aa887722801258f7de842dbVDR User		info("FPGA Version = %i", fpga_vers);
509e21ccaa69674e1b0aa887722801258f7de842dbVDR User	else
519e21ccaa69674e1b0aa887722801258f7de842dbVDR User		info("failed to get FPGA version");
529e21ccaa69674e1b0aa887722801258f7de842dbVDR User}
539e21ccaa69674e1b0aa887722801258f7de842dbVDR User
549bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotaint gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
559bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
569bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	int ret = 0,try = 0;
579bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
589bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
599bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		return ret;
609bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
619bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	while (ret >= 0 && ret != blen && try < 3) {
629bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ret = usb_control_msg(d->udev,
639bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			usb_rcvctrlpipe(d->udev,0),
649bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			req,
659bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			USB_TYPE_VENDOR | USB_DIR_IN,
669bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			value,index,b,blen,
679bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			2000);
689bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		deb_info("reading number %d (ret: %d)\n",try,ret);
699bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		try++;
709bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	}
719bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
729bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if (ret < 0 || ret != blen) {
73458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		warn("usb in %d operation failed.", req);
749bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ret = -EIO;
759bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	} else
769bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ret = 0;
779bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
789bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
799bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	debug_dump(b,blen,deb_xfer);
809bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
819bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	mutex_unlock(&d->usb_mutex);
829bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
839bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	return ret;
849bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
859bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
869bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotaint gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
879bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			     u16 index, u8 *b, int blen)
889bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
899bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	int ret;
909bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
919bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
929bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	debug_dump(b,blen,deb_xfer);
939bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
949bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
959bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		return ret;
969bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
979bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if (usb_control_msg(d->udev,
989bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			usb_sndctrlpipe(d->udev,0),
999bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			req,
1009bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			USB_TYPE_VENDOR | USB_DIR_OUT,
1019bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			value,index,b,blen,
1029bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			2000) != blen) {
1039bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		warn("usb out operation failed.");
1049bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ret = -EIO;
1059bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	} else
1069bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ret = 0;
1079bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	mutex_unlock(&d->usb_mutex);
1089bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
1099bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	return ret;
1109bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
1119bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
1129bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
1139bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
1149bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	int ret;
1159bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	const struct firmware *fw = NULL;
1163a9282cacdb13466b9c745518237938434dbde0bDavid Woodhouse	const u8 *ptr;
1173a9282cacdb13466b9c745518237938434dbde0bDavid Woodhouse	u8 *buf;
1189bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if ((ret = request_firmware(&fw, bcm4500_firmware,
1199bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota					&d->udev->dev)) != 0) {
1209bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		err("did not find the bcm4500 firmware file. (%s) "
1219bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
1229bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			bcm4500_firmware,ret);
1239bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		return ret;
1249bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	}
1259bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
126976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher	ret = -EINVAL;
127976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher
128976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher	if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
129976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher		goto out_rel_fw;
1309bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
131458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
1329bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
1339bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	ptr = fw->data;
134458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
135205161ed03b53c467dd669a340ea704ce0fb6f9eJiri Slaby	if (!buf) {
136205161ed03b53c467dd669a340ea704ce0fb6f9eJiri Slaby		ret = -ENOMEM;
137205161ed03b53c467dd669a340ea704ce0fb6f9eJiri Slaby		goto out_rel_fw;
138205161ed03b53c467dd669a340ea704ce0fb6f9eJiri Slaby	}
1399bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
1409bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	while (ptr[0] != 0xff) {
1419bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		u16 buflen = ptr[0] + 4;
1429bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		if (ptr + buflen >= fw->data + fw->size) {
1439bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			err("failed to load bcm4500 firmware.");
144976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher			goto out_free;
1459bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		}
1469bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		memcpy(buf, ptr, buflen);
1479bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		if (dvb_usb_generic_write(d, buf, buflen)) {
1489bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			err("failed to load bcm4500 firmware.");
149976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher			goto out_free;
1509bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		}
1519bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		ptr += buflen;
1529bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	}
153976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher
154976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher	ret = 0;
155976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher
156976e3483799ce5f718753d67454378d46500f0daPatrick Boettcherout_free:
1579bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	kfree(buf);
158976e3483799ce5f718753d67454378d46500f0daPatrick Boettcherout_rel_fw:
159976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher	release_firmware(fw);
160976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher
161976e3483799ce5f718753d67454378d46500f0daPatrick Boettcher	return ret;
1629bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
1639bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
1649bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
1659bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
1669bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	u8 status, buf;
167458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
168458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota
1699bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	if (onoff) {
1709bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
171458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if (! (status & bm8pskStarted)) {  /* started */
172458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota			if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
173458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota				gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
1749bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
1759bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota				return -EINVAL;
1769e21ccaa69674e1b0aa887722801258f7de842dbVDR User			gp8psk_info(d);
177458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		}
1789bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
179458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
180458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota			if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
181458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota				if(gp8psk_load_bcm4500fw(d))
1827fa7b8583f14889aaceebcd8dca3093987e289f7Marcin Slusarz					return -EINVAL;
1839bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
184458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if (! (status & bmIntersilOn)) /* LNB Power */
1859bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
1869bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota					&buf, 1))
1877fa7b8583f14889aaceebcd8dca3093987e289f7Marcin Slusarz				return -EINVAL;
1889bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
189458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		/* Set DVB mode to 1 */
190458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
191458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota			if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
1927fa7b8583f14889aaceebcd8dca3093987e289f7Marcin Slusarz				return -EINVAL;
193458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		/* Abort possible TS (if previous tune crashed) */
194458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
1957fa7b8583f14889aaceebcd8dca3093987e289f7Marcin Slusarz			return -EINVAL;
1969bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	} else {
1979bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		/* Turn off LNB power */
1989bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
1997fa7b8583f14889aaceebcd8dca3093987e289f7Marcin Slusarz			return -EINVAL;
2009bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		/* Turn off 8psk power */
2019bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
2029bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota			return -EINVAL;
203458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
204458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota			gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
2059bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	}
2069bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	return 0;
2079bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
2089bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
20902ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisotaint gp8psk_bcm4500_reload(struct dvb_usb_device *d)
21002ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota{
21102ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	u8 buf;
21202ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
21302ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	/* Turn off 8psk power */
21402ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
21502ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota		return -EINVAL;
21602ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	/* Turn On 8psk power */
21702ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
21802ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota		return -EINVAL;
21902ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	/* load BCM4500 firmware */
22002ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
22102ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota		if (gp8psk_load_bcm4500fw(d))
222da1b5c95e49bb564ae8c61ed135d34ed09acbb66Hans Verkuil			return -EINVAL;
22302ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota	return 0;
22402ebf23bc20eee5d91d008a9e831e7768d963946Alan Nisota}
2259bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2264d43e13f723e12734257277cc38497fab1efc605Patrick Boettcherstatic int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
2279bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
2284d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
2299bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
2309bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2314d43e13f723e12734257277cc38497fab1efc605Patrick Boettcherstatic int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
2329bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
23377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
2349bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	return 0;
2359bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
2369bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2374d43e13f723e12734257277cc38497fab1efc605Patrick Boettcherstatic struct dvb_usb_device_properties gp8psk_properties;
2389bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2399bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic int gp8psk_usb_probe(struct usb_interface *intf,
2409bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		const struct usb_device_id *id)
2419bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota{
242458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	int ret;
243458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	struct usb_device *udev = interface_to_usbdev(intf);
24478e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau	ret = dvb_usb_device_init(intf, &gp8psk_properties,
24578e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau				  THIS_MODULE, NULL, adapter_nr);
246458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	if (ret == 0) {
247458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		info("found Genpix USB device pID = %x (hex)",
248458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota			le16_to_cpu(udev->descriptor.idProduct));
249458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	}
250458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	return ret;
2519bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota}
2529bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2539bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic struct usb_device_id gp8psk_usb_table [] = {
254458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
255458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
256458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
257458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
258bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_2) },
25986cf5f84e60fe32e3e665fdc69325f8993970189Alan Nisota/*	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
2609bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	    { 0 },
2619bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota};
2629bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan NisotaMODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
2639bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2644d43e13f723e12734257277cc38497fab1efc605Patrick Boettcherstatic struct dvb_usb_device_properties gp8psk_properties = {
2659bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.usb_ctrl = CYPRESS_FX2,
2669bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.firmware = "dvb-usb-gp8psk-01.fw",
2679bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
2684d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	.num_adapters = 1,
2694d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	.adapter = {
2704d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher		{
27177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.num_frontends = 1,
27277eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.fe = {{
27301451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher			.streaming_ctrl   = gp8psk_streaming_ctrl,
27401451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher			.frontend_attach  = gp8psk_frontend_attach,
27501451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher			/* parameter for the MPEG2-data transfer */
2764d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher			.stream = {
2774d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher				.type = USB_BULK,
27801451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher				.count = 7,
27901451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher				.endpoint = 0x82,
28001451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher				.u = {
28101451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher					.bulk = {
28201451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher						.buffersize = 8192,
28301451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher					}
28401451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher				}
28501451e722793f191f6e13c5150dd8664f4439d17Patrick Boettcher			},
28677eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		}},
2874d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher		}
2884d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	},
2894d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	.power_ctrl       = gp8psk_power_ctrl,
2904d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher
2914d43e13f723e12734257277cc38497fab1efc605Patrick Boettcher	.generic_bulk_ctrl_endpoint = 0x01,
2929bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
293bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly	.num_device_descs = 4,
2949bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.devices = {
295458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
2969bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		  .cold_ids = { &gp8psk_usb_table[0], NULL },
2979bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		  .warm_ids = { &gp8psk_usb_table[1], NULL },
2989bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota		},
299458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		{ .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
300458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		  .cold_ids = { NULL },
301458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		  .warm_ids = { &gp8psk_usb_table[2], NULL },
302458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		},
303458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		{ .name = "Genpix SkyWalker-1 DVB-S receiver",
304458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		  .cold_ids = { NULL },
305458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		  .warm_ids = { &gp8psk_usb_table[3], NULL },
306458b634cd86968032171a4d6db5c89a772ff0348Alan Nisota		},
307bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly		{ .name = "Genpix SkyWalker-2 DVB-S receiver",
308bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly		  .cold_ids = { NULL },
309bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly		  .warm_ids = { &gp8psk_usb_table[4], NULL },
310bdd1751b49be2860cc8c6a61e8fadda0caf22e5aDerek Kelly		},
311ab9caf9e221ee1b13186a9144da26ac358f2a6f4Randy Dunlap		{ NULL },
3129bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	}
3139bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota};
3149bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
3159bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota/* usb specific object needed to register this driver with the usb subsystem */
3169bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisotastatic struct usb_driver gp8psk_usb_driver = {
3179bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.name		= "dvb_usb_gp8psk",
3189bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.probe		= gp8psk_usb_probe,
3199bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.disconnect = dvb_usb_device_exit,
3209bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota	.id_table	= gp8psk_usb_table,
3219bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota};
3229bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
323ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(gp8psk_usb_driver);
3249bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan Nisota
3259bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan NisotaMODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
326d12da8e9349667336753709915c5bf7d0de15700Derek KellyMODULE_DESCRIPTION("Driver for Genpix DVB-S");
327458b634cd86968032171a4d6db5c89a772ff0348Alan NisotaMODULE_VERSION("1.1");
3289bbe076f364aa7ba8c2e49e417a76d628ffb164cAlan NisotaMODULE_LICENSE("GPL");
329