sorry missing patch itself is in this post. Signed-of-by Marco Gittler <g.marco@xxxxxxxxxx> Signed-of-by: Mario Hlawitschka <dh1pa@xxxxxxxxx> g.marco@xxxxxxxxxx schrieb:
here the corrected patch for the opera dvb s1 usb-box i hope it is now nicer than last time. some hints about the code are also welcome. firmware files can put somewhere here ? thx Signed-of-by Marco Gittler <g.marco@xxxxxxxxxx> Signed-of-by: Mario Hlawitschka <dh1pa@xxxxxxxxx> _______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
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 Fri Mar 02 19:04:20 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,11 @@ 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 Sun Apr 15 12:05:45 2007 +0200 @@ -0,0 +1,574 @@ +/* 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 OPERA_WRITE_FX2 0xBB +#define OPERA_TUNER_REQ 0xB1 + + +struct opera1_state{ + u32 last_key_pressed; +}; +struct opera_rc_keys { + u32 keycode; + u32 event; +}; +static const u8* xilinx_init="\x90\x6e\xc5\xfa\x32\xd0\x73\x23\x1e"; +static int opera1_xilinx_load_firmware(struct usb_device *dev, const char *filename); + +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); +//struct mutex mymutex; + +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,10); + //if (mutex_lock_interruptible(&mymutex)){ + // return -EAGAIN; + //} + + if (flags==OPERA_WRITE_MSG) + memcpy(u8buf,data,len); + ret=usb_control_msg(dev, pipe,request, request_type| USB_TYPE_VENDOR,value, 0x0 /*index*/, u8buf,len, 2000); + //msleep(20); + 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/*index*/, r, 10, 2000); + } + if (flags==OPERA_READ_MSG) + memcpy(data,u8buf,len); + //mutex_unlock(&mymutex); + 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) +{ + struct i2c_msg msg[]={ + {.addr=0xb600,.flags=0,.buf="\x00",.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="\x01"; + } + 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) +{ + + struct i2c_msg start_tuner[]={ + {.addr=0xb1a6,.buf=onoff?"\xff\x03":"\xff\x00",.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},//power7 + +}; + +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]){ + opera1_xilinx_rw(d->udev,0xb1,0xa0,"\x08",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 dummydata[10],testval; + memcpy(dummydata, xilinx_init, 9); + 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; + memcpy(p,fw->data,fw->size); + // clear fpga ? + opera1_xilinx_rw(dev,0xbc,0xaa,"\x00",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 */ + reset = 0; + 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,//0x200, + } + } + }, + } + }, + + .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; +// mutex_init(&mymutex); + 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 Sun Apr 15 12:01:47 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