B2C2 / FlexCop driver rewrite
Subsystems (2)
cover B2C2 / FlexCop driver rewrite
Hi Andrew,
the following patchset adds a refactored driver for DVB PCI cards and USB devices based on the FlexCopII or FlexCopIII chips by B2C2. It consists of the following parts:
- drop the abandoned attempt to add USB support based on the existing skystar2 driver
- add a modular flexcop driver
- a bunch of fixes for the new driver from CVS
The second patch is probably too large to make it to the list (130K) but I see no reasonable way to split it. Just in case, it is also available here:
http://linuxtv.org/downloads/patches/2.6.12-rc4-2/quilt/dvb-b2c2-refactoring.patch
This driver has been in CVS for two months so I believe it is quite stable by now, and IMHO good for 2.6.12.
Please apply.
Thanks,
Johannes
PATCH 1/11 b2c2/flexcop driver refactoring part 1: drop old b2c2-usb stuff
b2c2/flexcop driver refactoring to support PCI and USB based cards, part 1: drop abandoned attempt to support USB devices
---
drivers/media/dvb/b2c2/Kconfig | 13 drivers/media/dvb/b2c2/Makefile | 3 drivers/media/dvb/b2c2/b2c2-common.c | 214 ------------ drivers/media/dvb/b2c2/b2c2-usb-core.c | 549 --------------------------------- 4 files changed, 779 deletions(-)
drivers/media/dvb/b2c2/b2c2-common.c deleted +0 -214
@@ -1,214 +0,0 @@ -/* -* b2c2-common.c - common methods for the B2C2/Technisat SkyStar2 PCI DVB card and -* for the B2C2/Technisat Sky/Cable/AirStar USB devices -* based on the FlexCopII/FlexCopIII by B2C2, Inc. -* -* Copyright (C) 2003 Vadim Catana, [email protected] -* -* FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl() -* FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped -* Vincenzo Di Massa, hawk.it at tiscalinet.it -* -* Converted to Linux coding style -* Misc reorganization, polishing, restyling -* Roberto Ragusa, r.ragusa at libero.it -* -* Added hardware filtering support, -* Niklas Peinecke, peinecke at gdv.uni-hannover.de -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public License -* as published by the Free Software Foundation; either version 2.1 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ -#include "stv0299.h" -#include "mt352.h" -#include "mt312.h" - -static int samsung_tbmu24112_set_symbol_rate (struct dvb_frontend * fe,u32 srate,u32 ratio) -{ -u8 aclk =0 ; -u8 bclk =0 ; - -if (srate <1500000 ) { aclk =0xb7 ; bclk =0x47 ; } -else if (srate <3000000 ) { aclk =0xb7 ; bclk =0x4b ; } -else if (srate <7000000 ) { aclk =0xb7 ; bclk =0x4f ; } -else if (srate <14000000 ) { aclk =0xb7 ; bclk =0x53 ; } -else if (srate <30000000 ) { aclk =0xb6 ; bclk =0x53 ; } -else if (srate <45000000 ) { aclk =0xb4 ; bclk =0x51 ; } - -stv0299_writereg (fe,0x13 , aclk); -stv0299_writereg (fe,0x14 , bclk); -stv0299_writereg (fe,0x1f , (ratio >>16 ) &0xff ); -stv0299_writereg (fe,0x20 , (ratio >>8 ) &0xff ); -stv0299_writereg (fe,0x21 , (ratio ) &0xf0 ); - -return 0 ; -} - -static int samsung_tbmu24112_pll_set (struct dvb_frontend * fe,struct dvb_frontend_parameters * params) -{ -u8 buf[4 ]; -u32 div; -struct i2c_msg msg = { .addr =0x61 , .flags =0 , .buf = buf, .len =sizeof (buf) }; -// struct adapter* adapter = (struct adapter*) fe->dvb->priv; - - div = params->frequency /125 ; - - buf[0 ] = (div >>8 ) &0x7f ; - buf[1 ] = div &0xff ; - buf[2 ] =0x84 ;// 0xC4 - buf[3 ] =0x08 ; - -if (params->frequency <1500000 ) buf[3 ] |=0x10 ; - -// if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; -return 0 ; -} - -static u8 samsung_tbmu24112_inittab[] = { -0x01 ,0x15 , -0x02 ,0x30 , -0x03 ,0x00 , -0x04 ,0x7D , -0x05 ,0x35 , -0x06 ,0x02 , -0x07 ,0x00 , -0x08 ,0xC3 , -0x0C ,0x00 , -0x0D ,0x81 , -0x0E ,0x23 , -0x0F ,0x12 , -0x10 ,0x7E , -0x11 ,0x84 , -0x12 ,0xB9 , -0x13 ,0x88 , -0x14 ,0x89 , -0x15 ,0xC9 , -0x16 ,0x00 , -0x17 ,0x5C , -0x18 ,0x00 , -0x19 ,0x00 , -0x1A ,0x00 , -0x1C ,0x00 , -0x1D ,0x00 , -0x1E ,0x00 , -0x1F ,0x3A , -0x20 ,0x2E , -0x21 ,0x80 , -0x22 ,0xFF , -0x23 ,0xC1 , -0x28 ,0x00 , -0x29 ,0x1E , -0x2A ,0x14 , -0x2B ,0x0F , -0x2C ,0x09 , -0x2D ,0x05 , -0x31 ,0x1F , -0x32 ,0x19 , -0x33 ,0xFE , -0x34 ,0x93 , -0xff ,0xff , -}; - -static struct stv0299_config samsung_tbmu24112_config = { - .demod_address =0x68 , - .inittab = samsung_tbmu24112_inittab, - .mclk =88000000UL , - .invert =0 , - .enhanced_tuning =0 , - .skip_reinit =0 , - .lock_output =STV0229_LOCKOUTPUT_LK , - .volt13_op0_op1 =STV0299_VOLT13_OP1 , - .min_delay_ms =100 , - .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, - .pll_set = samsung_tbmu24112_pll_set, -}; - - - - - -static int samsung_tdtc9251dh0_demod_init (struct dvb_frontend * fe) -{ -static u8 mt352_clock_config [] = {0x89 ,0x10 ,0x2d }; -static u8 mt352_reset [] = {0x50 ,0x80 }; -static u8 mt352_adc_ctl_1_cfg [] = {0x8E ,0x40 }; -static u8 mt352_agc_cfg [] = {0x67 ,0x28 ,0xa1 }; -static u8 mt352_capt_range_cfg[] = {0x75 ,0x32 }; - -mt352_write (fe, mt352_clock_config,sizeof (mt352_clock_config)); -udelay (2000 ); -mt352_write (fe, mt352_reset,sizeof (mt352_reset)); -mt352_write (fe, mt352_adc_ctl_1_cfg,sizeof (mt352_adc_ctl_1_cfg)); - -mt352_write (fe, mt352_agc_cfg,sizeof (mt352_agc_cfg)); -mt352_write (fe, mt352_capt_range_cfg,sizeof (mt352_capt_range_cfg)); - -return 0 ; -} - -static int samsung_tdtc9251dh0_pll_set (struct dvb_frontend * fe,struct dvb_frontend_parameters * params,u8 * pllbuf) -{ -u32 div; -unsigned char bs =0 ; - -#define IF_FREQUENCYx6 217/* 6 * 36.16666666667MHz */ - div = (((params->frequency +83333 ) *3 ) /500000 ) + IF_FREQUENCYx6; - -if (params->frequency >=48000000 && params->frequency <=154000000 ) bs =0x09 ; -if (params->frequency >=161000000 && params->frequency <=439000000 ) bs =0x0a ; -if (params->frequency >=447000000 && params->frequency <=863000000 ) bs =0x08 ; - - pllbuf[0 ] =0xc2 ;// Note: non-linux standard PLL i2c address - pllbuf[1 ] = div >>8 ; - pllbuf[2 ] = div &0xff ; - pllbuf[3 ] =0xcc ; - pllbuf[4 ] = bs; - -return 0 ; -} - -static struct mt352_config samsung_tdtc9251dh0_config = { - - .demod_address =0x0f , - .demod_init = samsung_tdtc9251dh0_demod_init, - .pll_set = samsung_tdtc9251dh0_pll_set, -}; - -static int skystar23_samsung_tbdu18132_pll_set (struct dvb_frontend * fe,struct dvb_frontend_parameters * params) -{ -u8 buf[4 ]; -u32 div; -struct i2c_msg msg = { .addr =0x61 , .flags =0 , .buf = buf, .len =sizeof (buf) }; -// struct adapter* adapter = (struct adapter*) fe->dvb->priv; - - div = (params->frequency + (125 /2 )) /125 ; - - buf[0 ] = (div >>8 ) &0x7f ; - buf[1 ] = (div >>0 ) &0xff ; - buf[2 ] =0x84 | ((div >>10 ) &0x60 ); - buf[3 ] =0x80 ; - -if (params->frequency <1550000 ) - buf[3 ] |=0x02 ; - -//if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; -return 0 ; -} - -static struct mt312_config skystar23_samsung_tbdu18132_config = { - - .demod_address =0x0e , - .pll_set = skystar23_samsung_tbdu18132_pll_set, -};
drivers/media/dvb/b2c2/b2c2-usb-core.c deleted +0 -549
549 lines not on this page · raw message
drivers/media/dvb/b2c2/Makefile +0 -3
@@ -1,6 +1,3 @@ -obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o - obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o -obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
drivers/media/dvb/b2c2/Kconfig +0 -13
@@ -11,16 +11,3 @@ config DVB_B2C2_SKYSTAR for the B2C2/BBTI Air2PC-ATSC card. Say Y if you own such a device and want to use it. - -config DVB_B2C2_USB - tristate "B2C2/Technisat Air/Sky/Cable2PC USB" - depends on DVB_CORE && USB && EXPERIMENTAL - select DVB_STV0299 - select DVB_MT352 - help - Support for the Air/Sky/Cable2PC USB DVB device by B2C2. Currently - the does nothing, but providing basic function for the used usb - protocol. - - Say Y if you own such a device and want to use it. -
--
PATCH 3/11 flexcop: fix USB transfer handling
In reply to Johannes Stezenbach- driver receives many null TS packets (pid=0x1fff). They occupy the limited USB bandwidth and this leads to loss of video packets. Enabling the null packet filter fixes this.
- packets that flexcop sends to USB have a 2 byte header that has to be removed.
- sometimes a TS packet is split between different urbs. These parts have to be combined in a temporary buffer.
---
drivers/media/dvb/b2c2/flexcop-hw-filter.c | 9 +++-- drivers/media/dvb/b2c2/flexcop-usb.c | 47 ++++++++++++++++++++++++++++- drivers/media/dvb/b2c2/flexcop-usb.h | 3 + 3 files changed, 55 insertions(+), 4 deletions(-)
drivers/media/dvb/b2c2/flexcop-hw-filter.c +6 -3
@@ -159,7 +159,7 @@ int flexcop_pid_feed_control(struct flex }else if (fc->feedcount == onoff && !onoff) {if (!fc->pid_filtering) {deb_ts ("disabling full TS transfer\n" ); -flexcop_pid_group_filter (fc,0x1fe0 ,0 ); +flexcop_pid_group_filter (fc,0 ,0x1fe0 );flexcop_pid_group_filter_ctrl (fc,0 ); }
@@ -175,7 +175,7 @@ int flexcop_pid_feed_control(struct flexflexcop_pid_group_filter (fc,0 ,0 );flexcop_pid_group_filter_ctrl (fc,1 ); }else if (fc->pid_filtering && fc->feedcount <= max_pid_filter) { -flexcop_pid_group_filter (fc,0x1fe0 ,0 ); +flexcop_pid_group_filter (fc,0 ,0x1fe0 );flexcop_pid_group_filter_ctrl (fc,0 ); }
@@ -189,10 +189,13 @@ void flexcop_hw_filter_init(struct flexcfor (i =0 ; i <6 +32 *fc->has_32_hw_pid_filter; i++)flexcop_pid_control (fc,i,0x1fff ,0 ); -flexcop_pid_group_filter (fc,0x1fe0 ,0 ); +flexcop_pid_group_filter (fc,0 ,0x1fe0 ); +flexcop_pid_group_filter_ctrl (fc,0 ); v = fc->read_ibi_reg (fc,pid_filter_308); v.pid_filter_308.EMM_filter_4 =1 ; v.pid_filter_308.EMM_filter_6 =0 ; fc->write_ibi_reg (fc,pid_filter_308,v); + +flexcop_null_filter_ctrl (fc,1 ); }
drivers/media/dvb/b2c2/flexcop-usb.c +46 -1
59 lines not on this page · raw message
drivers/media/dvb/b2c2/flexcop-usb.h +3 -0
@@ -21,6 +21,9 @@ struct flexcop_usb {struct urb *iso_urb[B2C2_USB_NUM_ISO_URB ];struct flexcop_device *fc_dev; + +u8 tmp_buffer[1023 +190 ]; +int tmp_buffer_length; };#if 0
--
PATCH 4/11 flexcop: add acknowledgements
In reply to Johannes Stezenbachadd acknowledgements
---
Documentation/dvb/README.flexcop | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletion(-)
Documentation/dvb/README.flexcop +6 -1
@@ -274,6 +274,11 @@ Acknowledgements (just for the rewriting Bjarne Steinsbo thought a lot in the first place of the pci part for this code sharing idea. -Andreas Oberritter for providing a recent PCI initialization template (pluto2.c). +Andreas Oberritter for providing a recent PCI initialization template +(pluto2.c). + +Boleslaw Ciesielski for pointing out a problem with firmware loader. + +Vadim Catana for correcting the USB transfer. comments, critics and ideas to [email protected] or [email protected]
--
PATCH 5/11 flexcop: fix MAC address reading
In reply to Johannes Stezenbachread MAC address directly into dvb_adapter->proposed_mac
---
drivers/media/dvb/b2c2/flexcop-common.h | 1 - drivers/media/dvb/b2c2/flexcop-eeprom.c | 10 +++------- drivers/media/dvb/b2c2/flexcop-usb.c | 3 ++- drivers/media/dvb/b2c2/flexcop.c | 10 ++++++---- 4 files changed, 11 insertions(+), 13 deletions(-)
drivers/media/dvb/b2c2/flexcop-common.h +0 -1
@@ -57,7 +57,6 @@ struct flexcop_device {int init_state;/* device information */ -u8 mac_address[6 ];int has_32_hw_pid_filter;flexcop_revision_t rev;flexcop_device_type_t dev_type;
drivers/media/dvb/b2c2/flexcop-eeprom.c +3 -7
@@ -129,8 +129,6 @@ static int flexcop_eeprom_lrc_read(strucreturn ret; } -/* TODO how is it handled in USB */ -/* JJ's comment about extended == 1: it is not presently used anywhere but was * added to the low-level functions for possible support of EUI64 */
@@ -139,18 +137,16 @@ int flexcop_eeprom_check_mac_addr(structu8 buf[8 ];int ret =0 ; -memset (fc->mac_address,0 ,6 ); -if ((ret =flexcop_eeprom_lrc_read (fc,0x3f8 ,buf,8 ,4 )) ==0 ) {if (extended !=0 ) {err ("TODO: extended (EUI64) MAC addresses aren't completely supported yet" ); ret = -EINVAL ; -/* memcpy(fc->mac_address,buf,3); +/* memcpy(fc->dvb_adapter.proposed_mac,buf,3); mac[3] = 0xfe; mac[4] = 0xff; -memcpy(&fc->mac_address[3],&buf[5],3); */ +memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */ }else -memcpy (fc->mac_address,buf,6 ); +memcpy (fc->dvb_adapter.proposed_mac,buf,6 ); }return ret; }
drivers/media/dvb/b2c2/flexcop-usb.c +2 -1
@@ -180,7 +180,8 @@ static int flexcop_usb_memory_req(structstatic int flexcop_usb_get_mac_addr (struct flexcop_device *fc,int extended) { -return flexcop_usb_memory_req (fc->bus_specific,B2C2_USB_READ_V8_MEM ,V8_MEMORY_PAGE_FLASH ,0x1f010 ,1 ,fc->mac_address,6 ); +return flexcop_usb_memory_req (fc->bus_specific,B2C2_USB_READ_V8_MEM , +V8_MEMORY_PAGE_FLASH ,0x1f010 ,1 ,fc->dvb_adapter.proposed_mac,6 ); }#if 0
drivers/media/dvb/b2c2/flexcop.c +6 -4
@@ -233,16 +233,18 @@ int flexcop_device_initialize(struct fleflexcop_smc_ctrl (fc,0 ); +if ((ret =flexcop_dvb_init (fc))) + goto error; + +/* do the MAC address reading after initializing the dvb_adapter */ if (fc->get_mac_addr (fc,0 ) ==0 ) { -u8 *b = fc->mac_address; +u8 *b = fc->dvb_adapter.proposed_mac;info ("MAC address = %02x:%02x:%02x:%02x:%02x:%02x" , b[0 ],b[1 ],b[2 ],b[3 ],b[4 ],b[5 ]); -flexcop_set_mac_filter (fc,fc->mac_address); +flexcop_set_mac_filter (fc,b);flexcop_mac_filter_ctrl (fc,1 ); }else warn ("reading of MAC address failed.\n" ); -if ((ret =flexcop_dvb_init (fc))) - goto error;if ((ret =flexcop_i2c_init (fc))) goto error;
--
PATCH 6/11 flexcop: fixed interrupt-sharing
In reply to Johannes Stezenbachfixed interrupt-sharing and added a spinlock to the irq-callback (thanks to Pascal Riekenberg)
---
drivers/media/dvb/b2c2/flexcop-pci.c | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-)
drivers/media/dvb/b2c2/flexcop-pci.c +13 -2
@@ -53,6 +53,8 @@ struct flexcop_pci {int active_dma1_addr;/* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos;/* position of the pointer last time the timer/packet irq occured */ +spinlock_t irq_lock; +struct flexcop_device *fc_dev; };
@@ -93,6 +95,9 @@ static irqreturn_t flexcop_pci_irq(int istruct flexcop_pci *fc_pci = dev_id;struct flexcop_device *fc = fc_pci->fc_dev;flexcop_ibi_value v = fc->read_ibi_reg (fc,irq_20c); +irqreturn_t ret =IRQ_HANDLED ; + +spin_lock_irq (&fc_pci->irq_lock); deb_irq("irq: %08x cur_addr: %08x (%d), our addrs. 1: %08x 2: %08x; 0x000: " "%08x, 0x00c: %08x\n",v.raw,
@@ -102,6 +107,7 @@ static irqreturn_t flexcop_pci_irq(int i fc->read_ibi_reg (fc,dma1_000).raw, fc->read_ibi_reg(fc,dma1_00c).raw); +if (v.irq_20c.DMA1_IRQ_Status ==1 ) {if (fc_pci->active_dma1_addr ==0 )flexcop_pass_dmx_packets (fc_pci->fc_dev,fc_pci->dma[0 ].cpu_addr0,fc_pci->dma[0 ].size /188 );
@@ -134,14 +140,17 @@ static irqreturn_t flexcop_pci_irq(int i } fc_pci->last_dma1_cur_pos = cur_pos; - } + }else + ret =IRQ_NONE ; + +spin_unlock_irq (&fc_pci->irq_lock);/* packet count would be ideal for hw filtering, but it isn't working. Either * the data book is wrong, or I'm unable to read it correctly */ /* if (v.irq_20c.DMA1_Size_IRQ_Status == 1) { packet counter */ -return IRQ_HANDLED ; +return ret; }static int flexcop_pci_stream_control (struct flexcop_device *fc,int onoff)
@@ -240,6 +249,8 @@ static int flexcop_pci_init(struct flexc SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0) goto err_pci_iounmap; +spin_lock_init (&fc_pci->irq_lock); + fc_pci->init_state |=FC_PCI_INIT ; goto success;
--
PATCH 7/11 flexcop: use hw pid filter
In reply to Johannes Stezenbach- enabled the HW PID by default for the PCI cards
- correct the TS demux parsing when PID filter is enabled (and thus the timer IRQ)
- rewrote the PID-filter and FULLTS control part in flexcop-hw-filter (thanks to Krzysztof Matula for pointing that out)
---
drivers/media/dvb/b2c2/flexcop-common.h | 2 drivers/media/dvb/b2c2/flexcop-hw-filter.c | 73 +++++++++++++++-------------- drivers/media/dvb/b2c2/flexcop-pci.c | 28 ++++++----- 3 files changed, 56 insertions(+), 47 deletions(-)
drivers/media/dvb/b2c2/flexcop-hw-filter.c +38 -35
@@ -104,6 +104,9 @@ static void flexcop_pid_ECM_PID_ctrl(strstatic void flexcop_pid_control (struct flexcop_device *fc,int index,u16 pid,int onoff) { +if (pid ==0x2000 ) +return ; +deb_ts ("setting pid: %5d %04x at index %d '%s'\n" ,pid,pid,index,onoff ?"on" :"off" );/* We could use bit magic here to reduce source code size.
@@ -133,50 +136,50 @@ static void flexcop_pid_control(struct f } } +static int flexcop_toggle_fullts_streaming (struct flexcop_device *fc,int onoff) +{ +if (fc->fullts_streaming_state != onoff) { +deb_ts ("%s full TS transfer\n" ,onoff ?"enabling" :"disabling" ); +flexcop_pid_group_filter (fc,0 ,0x1fe0 * (!onoff)); +flexcop_pid_group_filter_ctrl (fc,onoff); + fc->fullts_streaming_state = onoff; + } +return 0 ; +} +int flexcop_pid_feed_control (struct flexcop_device *fc,struct dvb_demux_feed *dvbdmxfeed,int onoff) {int max_pid_filter =6 + fc->has_32_hw_pid_filter*32 ; - fc->feedcount += (onoff ?1 :-1 ); + fc->feedcount += onoff ?1 :-1 ; +if (dvbdmxfeed->index >= max_pid_filter) + fc->extra_feedcount += onoff ?1 :-1 ; + +/* toggle complete-TS-streaming when: +* - pid_filtering is not enabled and it is the first or last feed requested +* - pid_filtering is enabled, +* - but the number of requested feeds is exceeded +* - or the requested pid is 0x2000 */ -/* when doing hw pid filtering, set the pid */ -if (fc->pid_filtering) -flexcop_pid_control (fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); +if (!fc->pid_filtering && fc->feedcount == onoff) +flexcop_toggle_fullts_streaming (fc,onoff); -/* if it was the first feed request */ -if (fc->feedcount == onoff && onoff) { -if (!fc->pid_filtering) { -deb_ts ("enabling full TS transfer\n" ); -flexcop_pid_group_filter (fc,0 ,0 ); -flexcop_pid_group_filter_ctrl (fc,1 ); - } - -if (fc->stream_control) - fc->stream_control (fc,1 ); -flexcop_rcv_data_ctrl (fc,1 ); - -/* if there is no more feed left to feed */ - }else if (fc->feedcount == onoff && !onoff) { -if (!fc->pid_filtering) { -deb_ts ("disabling full TS transfer\n" ); -flexcop_pid_group_filter (fc,0 ,0x1fe0 ); -flexcop_pid_group_filter_ctrl (fc,0 ); - } +if (fc->pid_filtering) { +flexcop_pid_control (fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); -flexcop_rcv_data_ctrl (fc,0 ); -if (fc->stream_control) - fc->stream_control (fc,0 ); +if (fc->extra_feedcount >0 ) +flexcop_toggle_fullts_streaming (fc,1 ); +else if (dvbdmxfeed->pid ==0x2000 ) +flexcop_toggle_fullts_streaming (fc,onoff); +else +flexcop_toggle_fullts_streaming (fc,0 ); } -/* if pid_filtering is on and more pids than the hw-filter can provide are -* requested enable the whole bandwidth. -*/ -if (fc->pid_filtering && fc->feedcount > max_pid_filter) { -flexcop_pid_group_filter (fc,0 ,0 ); -flexcop_pid_group_filter_ctrl (fc,1 ); - }else if (fc->pid_filtering && fc->feedcount <= max_pid_filter) { -flexcop_pid_group_filter (fc,0 ,0x1fe0 ); -flexcop_pid_group_filter_ctrl (fc,0 ); +/* if it was the first or last feed request change the stream-status */ +if (fc->feedcount == onoff) { +flexcop_rcv_data_ctrl (fc,onoff); +if (fc->stream_control) + fc->stream_control (fc,onoff); }return 0 ;
drivers/media/dvb/b2c2/flexcop-pci.c +16 -12
@@ -9,7 +9,7 @@#define FC_LOG_PREFIX "flexcop-pci"#include "flexcop-common.h" -static int enable_pid_filtering =0 ; +static int enable_pid_filtering =1 ;module_param (enable_pid_filtering, int,0444 );MODULE_PARM_DESC (enable_pid_filtering,"enable hardware pid filtering: supported values: 0 (fullts), 1" );
@@ -45,13 +45,14 @@ struct flexcop_pci {void __iomem *io_mem;u32 irq;/* buffersize (at least for DMA1, need to be % 188 == 0, -* this is logic is required */ +* this logic is required */ #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)#define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)struct flexcop_dma dma[2 ];int active_dma1_addr;/* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos;/* position of the pointer last time the timer/packet irq occured */ +int count;spinlock_t irq_lock;
@@ -99,15 +100,6 @@ static irqreturn_t flexcop_pci_irq(int ispin_lock_irq (&fc_pci->irq_lock); -deb_irq ("irq: %08x cur_addr: %08x (%d), our addrs. 1: %08x 2: %08x; 0x000: " -"%08x, 0x00c: %08x\n" ,v.raw, - fc->read_ibi_reg (fc,dma1_008).dma_0x8.dma_cur_addr <<2 , - fc_pci->active_dma1_addr, - fc_pci->dma[0 ].dma_addr0,fc_pci->dma[0 ].dma_addr1, - fc->read_ibi_reg (fc,dma1_000).raw, - fc->read_ibi_reg (fc,dma1_00c).raw); - -if (v.irq_20c.DMA1_IRQ_Status ==1 ) {if (fc_pci->active_dma1_addr ==0 )flexcop_pass_dmx_packets (fc_pci->fc_dev,fc_pci->dma[0 ].cpu_addr0,fc_pci->dma[0 ].size /188 );
@@ -123,21 +115,28 @@ static irqreturn_t flexcop_pci_irq(int i fc->read_ibi_reg (fc,dma1_008).dma_0x8.dma_cur_addr <<2 ;u32 cur_pos = cur_addr - fc_pci->dma[0 ].dma_addr0; +deb_irq ("irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x " , + v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); +/* buffer end was reached, restarted from the beginning * pass the data from last_cur_pos to the buffer end to the demux */ if (cur_pos < fc_pci->last_dma1_cur_pos) { +deb_irq (" end was reached: passing %d bytes " ,(fc_pci->dma[0 ].size*2 -1 ) - fc_pci->last_dma1_cur_pos);flexcop_pass_dmx_data (fc_pci->fc_dev, fc_pci->dma[0 ].cpu_addr0 + fc_pci->last_dma1_cur_pos, - (fc_pci->dma[0 ].size*2 -1 ) - fc_pci->last_dma1_cur_pos); + (fc_pci->dma[0 ].size*2 ) - fc_pci->last_dma1_cur_pos); fc_pci->last_dma1_cur_pos =0 ; + fc_pci->count =0 ; }if (cur_pos > fc_pci->last_dma1_cur_pos) { +deb_irq (" passing %d bytes " ,cur_pos - fc_pci->last_dma1_cur_pos);flexcop_pass_dmx_data (fc_pci->fc_dev, fc_pci->dma[0 ].cpu_addr0 + fc_pci->last_dma1_cur_pos, cur_pos - fc_pci->last_dma1_cur_pos); } +deb_irq ("\n" ); fc_pci->last_dma1_cur_pos = cur_pos; }else
@@ -301,6 +300,11 @@ static int flexcop_pci_probe(struct pci_ fc->stream_control = flexcop_pci_stream_control; +if (enable_pid_filtering) +info ("will use the HW PID filter." ); +else +info ("will pass the complete TS to the demuxer." ); + fc->pid_filtering = enable_pid_filtering; fc->bus_type =FC_PCI ;
drivers/media/dvb/b2c2/flexcop-common.h +2 -0
@@ -76,8 +76,10 @@ struct flexcop_device {struct semaphore i2c_sem;/* options and status */ +int extra_feedcount;int feedcount;int pid_filtering; +int fullts_streaming_state;/* bus specific callbacks */ flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *,flexcop_ibi_register );
--
PATCH 8/11 flexcop: fix module refcount handling
In reply to Johannes StezenbachCorrected the THIS_MODULE handling for the flexcop-stuff and dvb-usb which lead to oopses because of misorganized module dependencies.
---
drivers/media/dvb/b2c2/flexcop-common.h | 2 ++ drivers/media/dvb/b2c2/flexcop-pci.c | 1 + drivers/media/dvb/b2c2/flexcop-usb.c | 1 + drivers/media/dvb/b2c2/flexcop.c | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-)
drivers/media/dvb/b2c2/flexcop-common.h +2 -0
@@ -75,6 +75,8 @@ struct flexcop_device {struct i2c_adapter i2c_adap;struct semaphore i2c_sem; +struct module *owner; +/* options and status */ int extra_feedcount;int feedcount;
drivers/media/dvb/b2c2/flexcop-pci.c +1 -0
@@ -309,6 +309,7 @@ static int flexcop_pci_probe(struct pci_ fc->bus_type =FC_PCI ; fc->dev = &pdev->dev; + fc->owner =THIS_MODULE ;/* bus specific part */ fc_pci->pdev = pdev;
drivers/media/dvb/b2c2/flexcop-usb.c +1 -0
@@ -498,6 +498,7 @@ static int flexcop_usb_probe(struct usb_ fc->bus_type =FC_USB ; fc->dev = &udev->dev; + fc->owner =THIS_MODULE ;/* bus specific part */ fc_usb->udev = udev;
drivers/media/dvb/b2c2/flexcop.c +1 -1
@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(structstatic int flexcop_dvb_init (struct flexcop_device *fc) {int ret; -if ((ret =dvb_register_adapter (&fc->dvb_adapter,"FlexCop Digital TV device" ,THIS_MODULE )) <0 ) { +if ((ret =dvb_register_adapter (&fc->dvb_adapter,"FlexCop Digital TV device" ,fc->owner)) <0 ) {err ("error registering DVB adapter" );return ret; }
--
PATCH 9/11 flexcop: readme update
In reply to Johannes Stezenbachreadme update
---
Documentation/dvb/README.flexcop | 121 ++++++--------------------------------- 1 files changed, 21 insertions(+), 100 deletions(-)
Documentation/dvb/README.flexcop +21 -100
@@ -2,26 +2,20 @@ This README escorted the skystar2-driver state of the new flexcop-driver set and some internals are written down here too. -How to do something in here? -============================ - -make -f Makefile.t -make -C ../build-2.6 -./in.sh # load the drivers -./rm.sh # unload the drivers - -Please read this file, if you want to contribute. - This document hopefully describes things about the flexcop and its -device-offsprings. Goal is to write a easy-to-write and easy-to-read set of +device-offsprings. Goal was to write an easy-to-write and easy-to-read set of drivers based on the skystar2.c and other information. -This directory is temporary. It is used for rewriting the skystar2.c and to -create shared code, which then can be used by the usb box as well. - Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been touched and rewritten. +History & News +============== + 2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana) + + + + General coding processing =========================
@@ -81,16 +75,15 @@ non-static where possible, moved code to 2) Search for errors in the leftover of flexcop-pci.c (partially done) 5a) add MAC address reading +5c) feeding of ISOC data to the software demux (format of the isochronous data +and speed optimization, no real error) (thanks to Vadim Catana) What to do in the near future? -------------------------------------- (no special order here) - 5) USB driver 5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting) -5c) feeding of ISOC data to the software demux (format of the isochronous data -and speed optimization, no real error) Testing changes ---------------
@@ -118,7 +111,7 @@ item | mt352 | nxt2002 | stv0299 | mt3 2) | O | N 5a) | N | O 5b)* | N | -5c)* | N | +5c) | N | O * - not done yet
@@ -155,17 +148,21 @@ working) SOLUTION: also index 0 was affected, because net_translation is done for these indexes by default -5b) isochronous transfer does only work in the first attempt (for the Sky2PC USB, -Air2PC is working) -SOLUTION: the flexcop was going asleep and never really woke up again (don't -know if this need fixes, see flexcop-fe-tuner.c:flexcop_sleep) +5b) isochronous transfer does only work in the first attempt (for the Sky2PC +USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really +woke up again (don't know if this need fixes, see +flexcop-fe-tuner.c:flexcop_sleep) + +NEWS: when the driver is loaded and unloaded and loaded again (w/o doing +anything in the while the driver is loaded the first time), no transfers take +place anymore. Improvements when rewriting (refactoring) is done ================================================= - split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control (enable sleeping for other demods than dvb-s) -- add support for CableStar (stv0297 Microtune 203x/ALPS) +- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA) Debugging ---------
@@ -192,82 +189,6 @@ Sram destinations: accessing reg Tuner/Demod: I2C bus DVB-stuff: can be written for common use -Restrictions: -============ - -We need to create a bus-specific-struct and a flexcop-struct. - -bus-specific-struct: - -struct flexcop_pci -... - -struct flexcop_usb -... - - -struct flexcop_device { - void *bus_specific; /* container for bus-specific struct */ -... -} - -PCI i2c can read/write max 4 bytes at a time, USB can more - -Functions -========= - -Syntax ------- - -- Flexcop functions will be called "flexcop(_[a-z0-9]+)+" and exported as such - if needed. -- Flexcop-device functions will be called "flexcop_device(_[a-z0-9]+)+" and - exported as such if needed. -- Both will be compiled to b2c2-flexcop.ko and their source can be found in the - flexcop*.[hc] - -Callbacks and exports ---------------------- - -Bus-specific functions will be given as callbacks (function pointers) to the -flexcop-module. (within the flexcop_device-struct) - -Initialization process -====================== - -b2c2-flexcop.ko is loaded -b2c2-flexcop-<bus>.ko is loaded - -suppose a device is found: -malloc flexcop and the bus-specific variables (via flexcop_device_malloc) -fill the bus-specific variable -fill the flexcop variable (especially the bus-specific callbacks) -bus-specific initialization - - ... -do the common initialization (via flexcop_device_initialize) - - reset the card - - determine flexcop type (II, IIB, III) - - hw_filters (bus dependent) - - 0x204 - - set sram size - - create the dvb-stuff - - create i2c stuff - - frontend-initialization -done -bus specific: - - media_destination (this and the following 3 are bus specific) - - cai_dest - - cao_dest - - net_destination - -Bugs fixed while rewriting the driver -===================================== - -- EEPROM access (to read the MAC address) was fixed to death some time last - year. (fixed here and in skystar2.c) (Bjarne, this was the piece of code - (fix-chipaddr) we were wondering about) - - Acknowledgements (just for the rewriting part) ================
@@ -281,4 +202,4 @@ Boleslaw Ciesielski for pointing out a p Vadim Catana for correcting the USB transfer. -comments, critics and ideas to [email protected] or [email protected] +comments, critics and ideas to [email protected].
--
PATCH 10/11 flexcop: i2c read fixes
In reply to Johannes Stezenbachrewrote the i2c-reading-part (no more ack-error ignoring, which was inherited from the skystar2-driver)
---
drivers/media/dvb/b2c2/flexcop-i2c.c | 116 ++++++++++++++++++----------------- drivers/media/dvb/b2c2/flexcop-reg.h | 3 drivers/media/dvb/b2c2/flexcop.c | 4 - 3 files changed, 63 insertions(+), 60 deletions(-)
drivers/media/dvb/b2c2/flexcop-i2c.c +61 -55
@@ -9,9 +9,9 @@#define FC_MAX_I2C_RETRIES 100000 -static int flexcop_i2c_operation (struct flexcop_device *fc,flexcop_ibi_value *r100,int max_ack_errors) +static int flexcop_i2c_operation (struct flexcop_device *fc,flexcop_ibi_value *r100) { -int i,ack_errors =0 ; +int i;flexcop_ibi_value r; r100->tw_sm_c_100.working_start =1 ;
@@ -31,11 +31,7 @@ static int flexcop_i2c_operation(struct } }else {deb_i2c ("suffering from an i2c ack_error\n" ); -if (++ack_errors >= max_ack_errors) -break ; - - fc->write_ibi_reg (fc, tw_sm_c_100, ibi_zero); - fc->write_ibi_reg (fc, tw_sm_c_100, *r100); +return -EREMOTEIO ; } }deb_i2c ("tried %d times i2c operation, never finished or too many ack errors.\n" ,i);
@@ -48,19 +44,30 @@ static int flexcop_i2c_read4(struct flexint len = r100.tw_sm_c_100.total_bytes,/* remember total_bytes is buflen-1 */ ret; -if ((ret =flexcop_i2c_operation (fc,&r100,30 )) !=0 ) -return ret; - - r104 = fc->read_ibi_reg (fc,tw_sm_c_104); - -deb_i2c ("read: r100: %08x, r104: %08x\n" ,r100.raw,r104.raw); +if ((ret =flexcop_i2c_operation (fc,&r100)) !=0 ) { +/* The Cablestar needs a different kind of i2c-transfer (does not +* support "Repeat Start"): +* wait for the ACK failure, +* and do a subsequent read with the Bit 30 enabled +*/ + r100.tw_sm_c_100.no_base_addr_ack_error =1 ; +if ((ret =flexcop_i2c_operation (fc,&r100)) !=0 ) { +deb_i2c ("no_base_addr read failed. %d\n" ,ret); +return ret; + } + } -/* there is at least one byte, otherwise we wouldn't be here */ buf[0 ] = r100.tw_sm_c_100.data1_reg; -if (len >0 ) buf[1 ] = r104.tw_sm_c_104.data2_reg; -if (len >1 ) buf[2 ] = r104.tw_sm_c_104.data3_reg; -if (len >2 ) buf[3 ] = r104.tw_sm_c_104.data4_reg; +if (len >0 ) { + r104 = fc->read_ibi_reg (fc,tw_sm_c_104); +deb_i2c ("read: r100: %08x, r104: %08x\n" ,r100.raw,r104.raw); + +/* there is at least one more byte, otherwise we wouldn't be here */ + buf[1 ] = r104.tw_sm_c_104.data2_reg; +if (len >1 ) buf[2 ] = r104.tw_sm_c_104.data3_reg; +if (len >2 ) buf[3 ] = r104.tw_sm_c_104.data4_reg; + }return 0 ; }
@@ -82,9 +89,45 @@ static int flexcop_i2c_write4(struct fle/* write the additional i2c data before doing the actual i2c operation */ fc->write_ibi_reg (fc,tw_sm_c_104,r104); +return flexcop_i2c_operation (fc,&r100); +} + +int flexcop_i2c_request (struct flexcop_device *fc,flexcop_access_op_t op, +flexcop_i2c_port_t port,u8 chipaddr,u8 addr,u8 *buf,u16 len) +{ +int ret; +u16 bytes_to_transfer; +flexcop_ibi_value r100; + +deb_i2c ("op = %d\n" ,op); + r100.raw =0 ; + r100.tw_sm_c_100.chipaddr = chipaddr; + r100.tw_sm_c_100.twoWS_rw = op; + r100.tw_sm_c_100.twoWS_port_reg = port; + +while (len !=0 ) { + bytes_to_transfer = len >4 ?4 : len; + + r100.tw_sm_c_100.total_bytes = bytes_to_transfer -1 ; + r100.tw_sm_c_100.baseaddr = addr; + +if (op ==FC_READ ) + ret =flexcop_i2c_read4 (fc, r100, buf); +else + ret =flexcop_i2c_write4 (fc,r100, buf); + +if (ret <0 ) +return ret; + + buf += bytes_to_transfer; + addr += bytes_to_transfer; + len -= bytes_to_transfer; + }; -return flexcop_i2c_operation (fc,&r100,30 ); +return 0 ; } +/* exported for PCI i2c */ +EXPORT_SYMBOL (flexcop_i2c_request);/* master xfer callback for demodulator */ static int flexcop_master_xfer (struct i2c_adapter *i2c_adap,struct i2c_msg msgs[],int num)
@@ -123,43 +166,6 @@ static int flexcop_master_xfer(struct i2return ret; } -int flexcop_i2c_request (struct flexcop_device *fc,flexcop_access_op_t op, -flexcop_i2c_port_t port,u8 chipaddr,u8 addr,u8 *buf,u16 len) -{ -int ret; -u16 bytes_to_transfer; -flexcop_ibi_value r100; - -deb_i2c ("op = %d\n" ,op); - r100.raw =0 ; - r100.tw_sm_c_100.chipaddr = chipaddr; - r100.tw_sm_c_100.twoWS_rw = op; - r100.tw_sm_c_100.twoWS_port_reg = port; - -while (len !=0 ) { - bytes_to_transfer = len >4 ?4 : len; - - r100.tw_sm_c_100.total_bytes = bytes_to_transfer -1 ; - r100.tw_sm_c_100.baseaddr = addr; - -if (op ==FC_READ ) - ret =flexcop_i2c_read4 (fc, r100, buf); -else - ret =flexcop_i2c_write4 (fc,r100, buf); - -if (ret <0 ) -return ret; - - buf += bytes_to_transfer; - addr += bytes_to_transfer; - len -= bytes_to_transfer; - }; - -return 0 ; -} -/* exported for PCI i2c */ -EXPORT_SYMBOL (flexcop_i2c_request); -static u32 flexcop_i2c_func (struct i2c_adapter *adapter) {return I2C_FUNC_I2C ;
drivers/media/dvb/b2c2/flexcop-reg.h +2 -1
@@ -692,9 +692,10 @@ typedef enum { wan_ctrl_reg_71c =0x71c , } flexcop_ibi_register; -#define flexcop_set_ibi_value (reg,attr,val) \ +#define flexcop_set_ibi_value (reg,attr,val) { \ flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ v.reg.attr = val; \ fc->write_ibi_reg(fc,reg,v); \ +}#endif
drivers/media/dvb/b2c2/flexcop.c +0 -4
@@ -184,10 +184,6 @@ static void flexcop_reset(struct flexcop fc->write_ibi_reg (fc,misc_204,v204); v204.misc_204.Per_reset_sig =1 ; fc->write_ibi_reg (fc,misc_204,v204); - -/* v208.raw = 0; -v208.ctrl_208.Null_filter_sig = 1; -fc->write_ibi_reg(fc,ctrl_208,v208);*/ }struct flexcop_device *flexcop_device_kmalloc (size_t bus_specific_len)
--
PATCH 11/11 B2C2 / FlexCop driver rewrite
In reply to Johannes StezenbachFixed DiSeqC switching, which was wrongly taking over from skystar2.c. Thanks to Joerg Riechardt for finding the bug and testing the Fix.
---
drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/media/dvb/b2c2/flexcop-fe-tuner.c +2 -2
@@ -79,8 +79,8 @@ static int flexcop_set_tone(struct dvb_f v.lnb_switch_freq_200.LNB_CTLPrescaler_sig =1 ;/* divide by 2 */ - v.lnb_switch_freq_200.LNB_CTLHighCount_sig = - v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax; + v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; + v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax ==0 ?0x1ff : ax;return fc->write_ibi_reg (fc,lnb_switch_freq_200,v); }
--