Re: [PATCH] Opera S1- DVB-USB

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks for your answer

if fixed the things you wrote, and now it look a bit nicer.

the values used here for many command here are unknown to me, because i have no doc for this part of dvb box.

so i this first enough to put it in and have some more testern for this device ?

mchehab@xxxxxxxxxxxxx schrieb:
Hi Marco,

I've some comments bellow about your patch.

Cheers,
Mauro

Em Dom, 2007-04-15 às 19:55 +0200, Marco Gittler escreveu:
+config DVB_USB_OPERA1
+        tristate "Opera1 DVB-S USB2.0 receiver"
+        depends on DVB_USB
+ select DVB_STV0299 + #if !DVB_FE_CUSTOMISE
Why the above is commented? If DVB_FE_CUSTOMISE is not yet supported,
just remove it, but the better is to allow supporting it.

+static const u8* xilinx_init="\x90\x6e\xc5\xfa\x32\xd0\x73\x23\x1e";

Instead of writing as a string, better to write as a char array:

static const u8* xilinx_init= {0x90, 0x6e, 0xc5, ...

Better yet if you can better document the values at the array, by
replacing it by aliases, like:

static const u8* xilinx_init= { R90_INIT_DEV, R60_SELECT_MODE, ...

(of course if you know what the init is doing)


+ memset(r,0,10);
Avoid using magic numbers. Instead, do:
    memset (r,0,sizeof(*r));

+ //if (mutex_lock_interruptible(&mymutex)){
+ //    return -EAGAIN;
+ //}

Instead, use #if 0 for commenting codes like the above

Also, to follow kernel Documentation/CodingStyle, you should do:

    if (foo) {
instead of if (foo){

The same trouble (and other CodingStyle things, like column max size)
happens also on other parts of the code. Maybe the better is to run
indent with the following options:
    indent -kr -i8 -ts8 -sob -l80 -ss -ncs <files>

This will apply several common CodingStyle used on kernel. You should
review the code, since sometimes it mess some stuff and remove spaces
used for alignment on some undesirable places.

So, the above should be something like this:

#if 0
    if (mutex_lock_interruptible(&mymutex)) {
        return -EAGAIN;
    }
#endif

+ ret=usb_control_msg(dev, pipe,request, request_type| USB_TYPE_VENDOR,value, 0x0 /*index*/, u8buf,len, 2000);
The /*index*/ comment here is useless and can be removed.

+ }else
+     *state = REMOTE_NO_KEY_PRESSED;
+     return 0;
Hmm... return 0 is wrongly indented here.

+ if(ret==0)
+ {
Another CodingStyle. Should be, instead
    if ( ret==0 ) {

+         // clear fpga ?

Generally, we avoid using c++ style comments, using instead:
              /* clear fpga */

+ .entries = {
+     {   1064000, 500, 0xe5, 0xc6 },
+     {   1169000, 500, 0xe5, 0xe6 },
+     {    1299000, 500, 0xe5, 0x24 },
Hmm... this went missaligned at the email. Probably, you've mixed tabs
with spaces. Better to use or one or the other at the table.

Cheers,
Mauro


diff -r b5be3479f070 linux/drivers/media/dvb/dvb-usb/Kconfig
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig	Sat Apr 14 16:19:13 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig	Mon Apr 16 12:06:05 2007 +0200
@@ -110,6 +110,7 @@ config DVB_USB_CXUSB
 
 	  Medion MD95700 hybrid USB2.0 device.
 	  DViCO FusionHDTV (Bluebird) USB2.0 devices
+
 
 config DVB_USB_M920X
 	tristate "Uli m920x DVB-T USB2.0 support"
@@ -211,3 +212,10 @@ config DVB_USB_DTT200U
 	  The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
 
 	  The WT-220U and its clones are pen-sized.
+
+config DVB_USB_OPERA1
+        tristate "Opera1 DVB-S USB2.0 receiver"
+        depends on DVB_USB
+        select DVB_STV0299 if !DVB_FE_CUSTOMISE
+        help
+	    Say Y here to support the Opera DVB-S USB2.0 receiver.
diff -r b5be3479f070 linux/drivers/media/dvb/dvb-usb/Makefile
--- a/linux/drivers/media/dvb/dvb-usb/Makefile	Sat Apr 14 16:19:13 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/Makefile	Sun Apr 15 12:08:27 2007 +0200
@@ -51,4 +51,8 @@ dvb-usb-dib0700-objs = dib0700_core.o di
 dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
 obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
 
+dvb-usb-opera-objs = opera1.o
+obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
+
+
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -r b5be3479f070 linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	Sat Apr 14 16:19:13 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	Sun Apr 15 11:57:27 2007 +0200
@@ -38,6 +38,7 @@
 #define USB_VID_ULTIMA_ELECTRONIC		0x05d8
 #define USB_VID_UNIWILL				0x1584
 #define USB_VID_WIDEVIEW			0x14aa
+#define USB_VID_OPERA1				0x695C
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD			0xa333
@@ -142,6 +143,8 @@
 #define USB_PID_GENPIX_8PSK_WARM			0x0201
 #define USB_PID_SIGMATEK_DVB_110			0x6610
 #define USB_PID_MSI_DIGI_VOX_MINI_II			0x1513
+#define USB_PID_OPERA1_COLD				0x2830
+#define USB_PID_OPERA1_WARM				0x3829
 
 
 #endif
diff -r b5be3479f070 linux/drivers/media/dvb/dvb-usb/opera1.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux/drivers/media/dvb/dvb-usb/opera1.c	Mon Apr 16 13:16:17 2007 +0200
@@ -0,0 +1,604 @@
+/* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card
+*
+* Copyright (C) 2006 Mario Hlawitschka (dh1pa@xxxxxxxxx)
+* Copyright (C) 2006 Marco Gittler (g.marco@xxxxxxxxxx)
+*
+*	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
+*/
+#include "opera1.h"
+#include "linux/module.h"
+#include "linux/init.h"
+#include "linux/firmware.h"
+#include "dvb-usb.h"
+#include "dvb-pll.h"
+#include "stv0299.h"
+
+#define OPERA_READ_MSG 0
+#define OPERA_WRITE_MSG 1
+#define OPERA_I2C_TUNER 0xd1
+
+#define READ_FX2_REG_REQ  0xBA
+#define READ_MAC_ADDR 0x08
+#define OPERA_WRITE_FX2 0xBB
+#define OPERA_TUNER_REQ 0xB1
+
+struct opera1_state {
+	u32 last_key_pressed;
+};
+struct opera_rc_keys {
+	u32 keycode;
+	u32 event;
+};
+
+int dvb_usb_opera1_debug;
+module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+		 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
+		 DVB_USB_DEBUG_STATUS);
+#if 0
+struct mutex mymutex;
+#endif
+
+static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
+			    u8 * data, u16 len, int flags)
+{
+	int ret = 0, t = 0;
+	u8 r[10];
+	u8 u8buf[len];
+	unsigned int pipe = (flags == OPERA_READ_MSG) ? 
+		usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
+	u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+	memset(r, 0, sizeof(*r));
+#if 0
+	if (mutex_lock_interruptible(&mymutex)) {
+		return -EAGAIN;
+	}
+#endif
+	if (flags == OPERA_WRITE_MSG)
+		memcpy(u8buf, data, len);
+	ret =
+		usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
+			value, 0x0, u8buf, len, 2000);
+
+	if (request == OPERA_TUNER_REQ) {
+		t = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
+				0x01, 0x0, r, 10, 2000);
+	}
+	if (flags == OPERA_READ_MSG)
+		memcpy(data, u8buf, len);
+#if 0
+	mutex_unlock(&mymutex);
+#endif
+	return ret;
+}
+
+/* I2C */
+
+static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr,
+				  u8 * buf, u16 len, int flag)
+{
+	int ret = 0;
+	u8 request;
+	u16 value;
+
+	if (dev == NULL) {
+		info("no usb_device");
+		return -EINVAL;
+	}
+	if (mutex_lock_interruptible(&dev->usb_mutex) < 0)
+		return -EAGAIN;
+
+	request = (addr & 0xff00) >> 8;
+	if (!request)
+		request = 0xb1;
+	value = (addr & 0xff);
+	if (flag & OPERA_READ_MSG) {
+		value |= 0x01;
+	}
+	if (request == 0xa0)
+		value = 0xe600;
+	ret = opera1_xilinx_rw(dev->udev, request, value, buf, len, flag);
+
+	mutex_unlock(&dev->usb_mutex);
+	return ret;
+}
+
+static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			   int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i = 0, tmp = 0;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	if (d) {
+		for (i = 0; i < num; i++) {
+			if ((tmp = opera1_usb_i2c_msgxfer(d,
+						msg[i].addr,
+						msg[i].buf,
+						msg[i].len,
+						(msg[i].flags ==
+						I2C_M_RD ?
+						OPERA_READ_MSG :
+						OPERA_WRITE_MSG))!= msg[i].len)) {
+				break;
+			}
+			if (dvb_usb_opera1_debug & 0x10)
+				info("sending i2c mesage %d %d", tmp, msg[i].len);
+		}
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return num;
+}
+
+static u32 opera1_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm opera1_i2c_algo = {
+	.master_xfer = opera1_i2c_xfer,
+	.functionality = opera1_i2c_func,
+};
+
+static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	u8 command_13v[]={0x00};
+	u8 command_18v[]={0x01};
+	struct i2c_msg msg[] = {
+		{.addr = 0xb600,.flags = 0,.buf = command_13v,.len = 1},	/*13 V */
+	};
+	struct dvb_usb_adapter *udev_adap =
+	    (struct dvb_usb_adapter *)(fe->dvb->priv);
+	if (voltage == SEC_VOLTAGE_18) {
+		msg[0].addr = 0xb601;
+		msg[0].buf = command_18v;
+	}
+	i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
+	return 0;
+}
+
+static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
+					  u32 ratio)
+{
+	stv0299_writereg(fe, 0x13, 0x98);
+	stv0299_writereg(fe, 0x14, 0x95);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+	return 0;
+
+}
+static u8 opera1_inittab[] = {
+	0x00, 0xa1,
+	0x01, 0x15,
+	0x02, 0x00,
+	0x03, 0x00,
+	0x04, 0x7d,
+	0x05, 0x05,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x0b, 0x00,
+	0x0c, 0x01,
+	0x0d, 0x81,
+	0x0e, 0x44,
+	0x0f, 0x19,
+	0x10, 0x3f,
+	0x11, 0x84,
+	0x12, 0xda,
+	0x13, 0x98,
+	0x14, 0x95,
+	0x15, 0xc9,
+	0x16, 0xeb,
+	0x17, 0x00,
+	0x18, 0x19,
+	0x19, 0x8b,
+	0x1a, 0x00,
+	0x1b, 0x82,
+	0x1c, 0x7f,
+	0x1d, 0x00,
+	0x1e, 0x00,
+	0x1f, 0x06,
+	0x20, 0x50,
+	0x21, 0x10,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x24, 0x37,
+	0x25, 0xbc,
+	0x26, 0x00,
+	0x27, 0x00,
+	0x28, 0x00,
+	0x29, 0x1e,
+	0x2a, 0x14,
+	0x2b, 0x1f,
+	0x2c, 0x09,
+	0x2d, 0x0a,
+	0x2e, 0x00,
+	0x2f, 0x00,
+	0x30, 0x00,
+	0x31, 0x1f,
+	0x32, 0x19,
+	0x33, 0xfc,
+	0x34, 0x13,
+	0xff, 0xff,
+};
+
+static struct stv0299_config opera1_stv0299_config = {
+	.demod_address = 0xd0,
+	.min_delay_ms = 100,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0229_LOCKOUTPUT_0,
+	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+	.inittab = opera1_inittab,
+	.set_symbol_rate = opera1_stv0299_set_symbol_rate,
+};
+
+static int opera1_frontend_attach(struct dvb_usb_adapter *d)
+{
+	if ((d->fe =
+	     dvb_attach(stv0299_attach, &opera1_stv0299_config,
+			&d->dev->i2c_adap)) != NULL) {
+		d->fe->ops.set_voltage = opera1_set_voltage;
+		return 0;
+	}
+	info("not attached stv0299");
+	return -EIO;
+}
+
+static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	adap->pll_addr = 0xc0;
+	adap->pll_desc = &dvb_pll_opera1;
+	adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+	return 0;
+}
+
+static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	int addr = onoff ? 0xb701 : 0xb700;
+	u8 val = onoff ? 0x01 : 0x00;
+	if (dvb_usb_opera1_debug)
+		info("power %s", onoff ? "on" : "off");
+	return opera1_usb_i2c_msgxfer(d, addr, &val, 1, OPERA_WRITE_MSG);
+}
+
+static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	u8 buf_start[2] = { 0xff, 0x03 };
+	u8 buf_stop[2] = { 0xff, 0x00 };
+	struct i2c_msg start_tuner[] = {
+		{.addr = 0xb1a6,.buf = onoff ? buf_start : buf_stop,.len = 2},
+	};
+	if (dvb_usb_opera1_debug)
+		info("streaming %s", onoff ? "on" : "off");
+	i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1);
+	return 0;
+}
+
+static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+			     int onoff)
+{
+	u8 b_pid[3];
+	struct i2c_msg msg[] = {
+		{.addr = 0xb1a6,.buf = b_pid,.len = 3},
+	};
+	if (dvb_usb_opera1_debug)
+		info("pidfilter index: %d pid: %d %s", index, pid,
+			onoff ? "on" : "off");
+	b_pid[0] = (2 * index) + 4;
+	b_pid[1] = onoff ? (pid & 0xff) : (0x00);
+	b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00);
+	i2c_transfer(&adap->dev->i2c_adap, msg, 1);
+	return 0;
+}
+
+static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
+{
+	int u = 0x04;
+	u8 b_pid[3];
+	struct i2c_msg msg[] = {
+		{.addr = 0xb1a6,.buf = b_pid,.len = 3},
+	};
+	if (dvb_usb_opera1_debug)
+		info("%s hw-pidfilter", onoff ? "enable" : "disable");
+	for (; u < 0x7e; u += 2) {
+		b_pid[0] = u;
+		b_pid[1] = 0;
+		b_pid[2] = 0x80;
+		i2c_transfer(&adap->dev->i2c_adap, msg, 1);
+	}
+	return 0;
+}
+
+static struct dvb_usb_rc_key opera1_rc_keys[] = {
+	{0x5f, 0xa0, KEY_1},
+	{0x51, 0xaf, KEY_2},
+	{0x5d, 0xa2, KEY_3},
+	{0x41, 0xbe, KEY_4},
+	{0x0b, 0xf5, KEY_5},
+	{0x43, 0xbd, KEY_6},
+	{0x47, 0xb8, KEY_7},
+	{0x49, 0xb6, KEY_8},
+	{0x05, 0xfa, KEY_9},
+	{0x45, 0xba, KEY_0},
+	{0x09, 0xf6, KEY_UP},	/*chanup */
+	{0x1b, 0xe5, KEY_DOWN},	/*chandown */
+	{0x5d, 0xa3, KEY_LEFT},	/*voldown */
+	{0x5f, 0xa1, KEY_RIGHT},	/*volup */
+	{0x07, 0xf8, KEY_SPACE},	/*tab */
+	{0x1f, 0xe1, KEY_ENTER},	/*play ok */
+	{0x1b, 0xe4, KEY_Z},	/*zoom */
+	{0x59, 0xa6, KEY_M},	/*mute */
+	{0x5b, 0xa5, KEY_F},	/*tv/f */
+	{0x19, 0xe7, KEY_R},	/*rec */
+	{0x01, 0xfe, KEY_S},	/*Stop */
+	{0x03, 0xfd, KEY_P},	/*pause */
+	{0x03, 0xfc, KEY_W},	/*<- -> */
+	{0x07, 0xf9, KEY_C},	/*capture */
+	{0x47, 0xb9, KEY_Q},	/*exit */
+	{0x43, 0xbc, KEY_O},	/*power */
+
+};
+
+static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
+{
+	struct opera1_state *opst = dev->priv;
+	u8 rcbuffer[32];
+	const u16 startmarker1 = 0x10ed;
+	const u16 startmarker2 = 0x11ec;
+	struct i2c_msg read_remote[] = {
+		{.addr = 0xb880,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32},
+	};
+	int i = 0;
+	u32 send_key = 0;
+	memset(rcbuffer, 0, 32);
+
+	if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) {
+		for (i = 0; i < 32; i++) {
+			if (rcbuffer[i])
+				send_key |= 1;
+			if (i < 31)
+				send_key = send_key << 1;
+		}
+		if (send_key & 0x8000)
+			send_key = (send_key << 1) | (send_key >> 15 & 0x01);
+
+		if (send_key == 0xffff && opst->last_key_pressed != 0) {
+			*state = REMOTE_KEY_REPEAT;
+			*event = opst->last_key_pressed;
+			return 0;
+		}
+		for (; send_key != 0;) {
+			if (send_key >> 16 == startmarker2) {
+				break;
+			} else if (send_key >> 16 == startmarker1) {
+				send_key =
+					(send_key & 0xfffeffff) | (startmarker1 << 16);
+				break;
+			} else
+				send_key >>= 1;
+		}
+
+		if (send_key == 0)
+			return 0;
+
+		send_key = (send_key & 0xffff) | 0x0100;
+
+		for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) {
+			if ((opera1_rc_keys[i].custom * 256 +
+					opera1_rc_keys[i].data) == (send_key & 0xffff)) {
+				*state = REMOTE_KEY_PRESSED;
+				*event = opera1_rc_keys[i].event;
+				opst->last_key_pressed =
+					opera1_rc_keys[i].event;
+				break;
+			}
+			opst->last_key_pressed = 0;
+		}
+	} else
+		*state = REMOTE_NO_KEY_PRESSED;
+	return 0;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id opera1_table[] = {
+/* 00 */ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD)},
+	{USB_DEVICE(USB_VID_OPERA1, USB_PID_OPERA1_WARM)},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, opera1_table);
+static int opera1_firmware_download(struct usb_device *udev,
+				    const struct firmware *fw)
+{
+	int ret = usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
+	const struct firmware *fw1 = NULL;
+
+	if (ret == 0) {
+		if ((ret =
+			request_firmware(&fw1, "opera1-2.fw", &udev->dev)) != 0) {
+			err("did not find the firmware file. (%s) "
+				"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+				"opera1-2.fw", ret);
+
+		} else {
+			ret = usb_cypress_load_firmware(udev, fw1, CYPRESS_FX2);
+			release_firmware(fw1);
+			if (ret != 0)
+				info("error loading firmware1 %d,%d", -EIO,
+					ret);
+		}
+	}
+	return ret;
+
+}
+
+static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+	u8 command[] = { READ_MAC_ADDR };
+	opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG);
+	opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG);
+	return 0;
+}
+static int opera1_xilinx_load_firmware(struct usb_device *dev,
+				       const char *filename)
+{
+	const struct firmware *fw = NULL;
+	u8 *b, *p;
+	int ret = 0, i;
+	u8 testval;
+	info("start downloading fpga firmware");
+
+	if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
+		err("did not find the firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+			filename);
+		return ret;
+	} else {
+		p = kmalloc(fw->size, GFP_KERNEL);
+		opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG);
+		if (p != NULL && testval != 0x67) {
+
+			u8 reset = 0, fpga_command = 0;
+			memcpy(p, fw->data, fw->size);
+			/* clear fpga ? */
+			opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1,
+					 OPERA_WRITE_MSG);
+			for (i = 0; p[i] != 0 && i < fw->size;) {
+				b = (u8 *) p + i;
+				if (opera1_xilinx_rw
+					(dev, OPERA_WRITE_FX2, 0x0, b + 1, b[0],
+						OPERA_WRITE_MSG) != b[0]
+					) {
+					err("error while transferring firmware");
+					ret = -EINVAL;
+					break;
+				}
+				i = i + 1 + b[0];
+			}
+			/* restart the CPU */
+			if (ret || opera1_xilinx_rw
+					(dev, 0xa0, 0xe600, &reset, 1,
+					OPERA_WRITE_MSG) != 1) {
+				err("could not restart the USB controller CPU.");
+				ret = -EINVAL;
+			}
+			kfree(p);
+		}
+	}
+	if (fw) {
+		release_firmware(fw);
+	}
+	return ret;
+}
+
+static struct dvb_usb_device_properties opera1_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.firmware = "opera1.fw",
+	.download_firmware = opera1_firmware_download,
+	.size_of_priv = sizeof(struct opera1_state),
+
+	.power_ctrl = opera1_power_ctrl,
+	.i2c_algo = &opera1_i2c_algo,
+
+	.rc_key_map = opera1_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(opera1_rc_keys),
+	.rc_interval = 200,
+	.rc_query = opera1_rc_query,
+	.read_mac_address = opera1_read_mac_address,
+	.generic_bulk_ctrl_endpoint = 0x00,
+	/* parameter for the MPEG2-data transfer */
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.frontend_attach = opera1_frontend_attach,
+			.streaming_ctrl = opera1_streaming_ctrl,
+			.tuner_attach = opera1_tuner_attach,
+			.caps =
+				DVB_USB_ADAP_HAS_PID_FILTER |
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter = opera1_pid_filter,
+			.pid_filter_ctrl = opera1_pid_filter_control,
+			.pid_filter_count = 252,
+			.stream = {
+				.type = USB_BULK,
+				.count = 10,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			},
+		}
+	},
+	.num_device_descs = 1,
+	.devices = {
+		{"Opera1 DVB-S USB2.0",
+			{&opera1_table[0], NULL},
+			{&opera1_table[1], NULL},
+		},
+	}
+};
+
+static int opera1_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM &&
+		udev->descriptor.idVendor == USB_VID_OPERA1 &&
+		(d == NULL
+			|| opera1_xilinx_load_firmware(udev, "opera1-fpga.fw") != 0)
+		) {
+		return -EINVAL;
+	}
+
+	if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, &d) != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static struct usb_driver opera1_driver = {
+	.name = "opera1",
+	.probe = opera1_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table = opera1_table,
+};
+
+static int __init opera1_module_init(void)
+{
+	int result = 0;
+#if 0
+	mutex_init(&mymutex);
+#endif
+	if ((result = usb_register(&opera1_driver))) {
+		err("usb_register failed. Error number %d", result);
+	}
+	return result;
+}
+
+static void __exit opera1_module_exit(void)
+{
+	usb_deregister(&opera1_driver);
+}
+
+module_init(opera1_module_init);
+module_exit(opera1_module_exit);
+
+MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@xxxxxxxxx");
+MODULE_AUTHOR("Marco Gittler (c) g.marco@xxxxxxxxxx");
+MODULE_DESCRIPTION("Driver for Opera1 DVB-S device");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -r b5be3479f070 linux/drivers/media/dvb/dvb-usb/opera1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux/drivers/media/dvb/dvb-usb/opera1.h	Sun Apr 15 11:58:00 2007 +0200
@@ -0,0 +1,7 @@
+#ifndef _OPERA1_H_
+#define _OPERA1_H_
+
+#define DVB_USB_LOG_PREFIX "opera"
+extern int dvb_usb_opera1_debug;
+#define deb_xfer(args...) dprintk(dvb_usb_opera1_debug,0x02,args)
+#endif
diff -r b5be3479f070 linux/drivers/media/dvb/frontends/dvb-pll.c
--- a/linux/drivers/media/dvb/frontends/dvb-pll.c	Sat Apr 14 16:19:13 2007 -0300
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.c	Mon Apr 16 12:48:58 2007 +0200
@@ -451,6 +451,31 @@ struct dvb_pll_desc dvb_pll_thomson_fe66
 	}
 };
 EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
+static void opera1_bw(u8 *buf, u32 freq, int bandwidth)
+{
+	if (bandwidth == BANDWIDTH_8_MHZ)
+		buf[2] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_opera1 = {
+	.name  = "Opera Tuner",
+	.min   =  900000,
+	.max   = 2250000,
+	.iffreq= 0,
+	.setbw = opera1_bw,
+	.count = 8,
+	.entries = {
+		{ 1064000, 500, 0xe5, 0xc6 },
+		{ 1169000, 500, 0xe5, 0xe6 },
+		{ 1299000, 500, 0xe5, 0x24 },
+		{ 1444000, 500, 0xe5, 0x44 },
+		{ 1606000, 500, 0xe5, 0x64 },
+		{ 1777000, 500, 0xe5, 0x84 },
+		{ 1941000, 500, 0xe5, 0xa4 },
+		{ 2250000, 500, 0xe5, 0xc4 },
+	}
+};
+EXPORT_SYMBOL(dvb_pll_opera1);
 
 struct dvb_pll_priv {
 	/* i2c details */
diff -r b5be3479f070 linux/drivers/media/dvb/frontends/dvb-pll.h
--- a/linux/drivers/media/dvb/frontends/dvb-pll.h	Sat Apr 14 16:19:13 2007 -0300
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.h	Sun Apr 15 19:52:10 2007 +0200
@@ -48,6 +48,7 @@ extern struct dvb_pll_desc dvb_pll_phili
 extern struct dvb_pll_desc dvb_pll_philips_td1316;
 
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
+extern struct dvb_pll_desc dvb_pll_opera1;
 
 extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 			     u32 freq, int bandwidth);
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux