From 8c82d0166c1bbaa9d01365c74679fa4bd082111b Mon Sep 17 00:00:00 2001 From: Ralph Metzler Date: Sun, 31 Jul 2016 21:41:03 +0200 Subject: [PATCH] first support for V2 modulator cards --- ddbridge/ddbridge-core.c | 56 +++-- ddbridge/ddbridge-mod.c | 447 +++++++++++++++++++++++++++++++++++++-- ddbridge/ddbridge-regs.h | 127 ++++++++++- ddbridge/ddbridge.c | 30 +++ ddbridge/ddbridge.h | 24 ++- 5 files changed, 645 insertions(+), 39 deletions(-) diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index 62c7d4c..8d75011 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -92,6 +92,32 @@ static struct ddb_regset octopus_mod_odma_buf = { .size = 0x100, }; +static struct ddb_regset octopus_mod_channel = { + .base = 0x400, + .num = 0x0a, + .size = 0x40, +}; + +/****************************************************************************/ + +static struct ddb_regset octopus_mod_2_odma = { + .base = 0x400, + .num = 0x18, + .size = 0x10, +}; + +static struct ddb_regset octopus_mod_2_odma_buf = { + .base = 0x8000, + .num = 0x18, + .size = 0x100, +}; + +static struct ddb_regset octopus_mod_2_channel = { + .base = 0x800, + .num = 0x18, + .size = 0x40, +}; + /****************************************************************************/ static struct ddb_regset octopus_input = { @@ -249,15 +275,10 @@ static struct ddb_regmap octopro_hdin_map = { .output = &octopro_output, }; -static struct ddb_regset octopus_mod_channel = { - .base = 0x400, - .num = 0x0c, - .size = 0x40, -}; - static struct ddb_regmap octopus_mod_map = { .irq_version = 1, .irq_base_odma = 8, + .irq_base_rate = 18, .output = &octopus_output, .odma = &octopus_mod_odma, .odma_buf = &octopus_mod_odma_buf, @@ -265,6 +286,17 @@ static struct ddb_regmap octopus_mod_map = { }; +static struct ddb_regmap octopus_mod_2_map = { + .irq_version = 2, + .irq_base_odma = 64, + .irq_base_rate = 32, + .output = &octopus_output, + .odma = &octopus_mod_2_odma, + .odma_buf = &octopus_mod_2_odma_buf, + .channel = &octopus_mod_2_channel, +}; + + /****************************************************************************/ static struct ddb_info ddb_s2_48 = { @@ -3395,9 +3427,9 @@ static void ddb_ports_init(struct ddb *dev) break; case DDB_MOD: ddb_output_init(port, i); - dev->handler[0][i + 18] = + dev->handler[0][i + rm->irq_base_rate] = ddbridge_mod_rate_handler; - dev->handler_data[0][i + 18] = + dev->handler_data[0][i + rm->irq_base_rate] = (unsigned long) &dev->output[i]; break; default: @@ -4845,7 +4877,7 @@ static void ddb_device_attrs_del(struct ddb *dev) device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]); device_remove_file(dev->ddb_dev, &ddb_attrs_ctemp[i]); } - for (i = 0; ddb_attrs[i].attr.name; i++) + for (i = 0; ddb_attrs[i].attr.name != NULL; i++) device_remove_file(dev->ddb_dev, &ddb_attrs[i]); } @@ -4853,19 +4885,19 @@ static int ddb_device_attrs_add(struct ddb *dev) { int i; - for (i = 0; ddb_attrs[i].attr.name; i++) + for (i = 0; ddb_attrs[i].attr.name != NULL; i++) if (device_create_file(dev->ddb_dev, &ddb_attrs[i])) goto fail; for (i = 0; i < dev->link[0].info->temp_num; i++) if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i])) goto fail; - for (i = 0; i < dev->link[0].info->port_num; i++) + for (i = 0; (i < dev->link[0].info->port_num) && (i < 10); i++) if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])) goto fail; for (i = 0; i < dev->link[0].info->fan_num; i++) if (device_create_file(dev->ddb_dev, &ddb_attrs_fan[i])) goto fail; - for (i = 0; i < dev->i2c_num && i < 4; i++) { + for (i = 0; (i < dev->i2c_num) && (i < 4); i++) { if (device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])) goto fail; if (device_create_file(dev->ddb_dev, &ddb_attrs_ctemp[i])) diff --git a/ddbridge/ddbridge-mod.c b/ddbridge/ddbridge-mod.c index 5503328..ec5428d 100644 --- a/ddbridge/ddbridge-mod.c +++ b/ddbridge/ddbridge-mod.c @@ -28,6 +28,10 @@ #include +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + inline s64 ConvertPCR(s64 a) { s32 ext; @@ -72,6 +76,81 @@ inline s64 RoundPCRDown(s64 a) return a & ~(HW_LSB_MASK - 1); } +// Calculating KF, LF from Symbolrate +// +// Symbolrate is usually calculated as (M/N) * 10.24 MS/s +// +// Common Values for M,N +// J.83 Annex A, +// Euro Docsis 6.952 MS/s : M = 869, N = 1280 +// 6.900 MS/s : M = 345, N = 512 +// 6.875 MS/s : M = 1375, N = 2048 +// 6.111 MS/s : M = 6111, N = 10240 +// J.83 Annex B ** +// QAM64 5.056941 : M = 401, N = 812 +// QAM256 5.360537 : M = 78, N = 149 +// J.83 Annex C ** +// 5.309734 : M = 1889, N = 3643 +// +// For the present hardware +// KF' = 256 * M +// LF' = 225 * N +// or +// KF' = Symbolrate in Hz +// LF' = 9000000 +// +// KF = KF' / gcd(KF',LF') +// LF = LF' / gcd(KF',LF') +// Note: LF must not be a power of 2. +// Maximum value for KF,LF = 13421727 ( 0x7FFFFFF ) +// ** using these M,N values will result in a small err (<5ppm) +// calculating KF,LF directly gives the exact normative result +// but with rather large KF,LF values + +static inline u32 gcd(u32 u,u32 v) +{ + int s = 0; + while (((u|v)&1) == 0) { + s += 1; + u >>= 1; + v >>= 1; + } + while ((u&1) == 0) + u >>= 1; + do { + while ( (v&1) == 0 ) v >>= 1; + if( u > v ) { + u32 t = v; + v = u; + u = t; + } + v = v - u; + } while(v != 0); + return u << s; +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +static int mod_SendChannelCommand(struct ddb *dev, u32 Channel, u32 Command) +{ + u32 ControlReg = ddbreadl(dev, CHANNEL_CONTROL(Channel)); + + ControlReg = (ControlReg & ~CHANNEL_CONTROL_CMD_MASK)|Command; + ddbwritel(dev, ControlReg, CHANNEL_CONTROL(Channel)); + while(1) { + ControlReg = ddbreadl(dev, CHANNEL_CONTROL(Channel)); + if (ControlReg == 0xFFFFFFFF) + return -EIO; + if((ControlReg & CHANNEL_CONTROL_CMD_STATUS) == 0) + break; + } + if (ControlReg & CHANNEL_CONTROL_ERROR_CMD) + return -EINVAL; + return 0; +} + static int mod_busy(struct ddb *dev, int chan) { u32 creg; @@ -89,10 +168,12 @@ static int mod_busy(struct ddb *dev, int chan) void ddbridge_mod_output_stop(struct ddb_output *output) { struct ddb *dev = output->port->dev; - struct mod_state *mod = &dev->mod[output->nr]; + struct ddb_mod *mod = &dev->mod[output->nr]; mod->State = CM_IDLE; mod->Control = 0; + if (dev->link[0].info->version == 2) + mod_SendChannelCommand(dev, output->nr, CHANNEL_CONTROL_CMD_FREE); ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); #if 0 udelay(10); @@ -108,7 +189,7 @@ static void mod_set_incs(struct ddb_output *output) { s64 pcr; struct ddb *dev = output->port->dev; - struct mod_state *mod = &dev->mod[output->nr]; + struct ddb_mod *mod = &dev->mod[output->nr]; pcr = ConvertPCR(mod->PCRIncrement); ddbwritel(dev, pcr & 0xffffffff, @@ -137,8 +218,10 @@ static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 }; void ddbridge_mod_output_start(struct ddb_output *output) { struct ddb *dev = output->port->dev; - struct mod_state *mod = &dev->mod[output->nr]; - + u32 Channel = output->nr; + struct ddb_mod *mod = &dev->mod[output->nr]; + u32 Symbolrate = 6900000; + /*PCRIncrement = RoundPCR(PCRIncrement);*/ /*PCRDecrement = RoundPCR(PCRDecrement);*/ @@ -164,18 +247,55 @@ void ddbridge_mod_output_start(struct ddb_output *output) udelay(10); ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); - /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ - /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ - ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr)); + pr_info("CHANNEL_BASE = %08x\n", CHANNEL_BASE); + pr_info("CHANNEL_CONTROL = %08x\n", CHANNEL_CONTROL(Channel)); + if (dev->link[0].info->version == 2) { + u32 Output = ((dev->mod_base.frequency - 114000000)/8000000 + Channel) % 96; + u32 KF = Symbolrate; + u32 LF = 9000000UL; + u32 d = gcd(KF,LF); + u32 checkLF; + mod->modulation = QAM_256 - 1; + ddbwritel(dev, mod->modulation, CHANNEL_SETTINGS(Channel)); + ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel)); + + KF = KF / d; + LF = LF / d; + + while( (KF > KFLF_MAX) || (LF > KFLF_MAX) ) { + KF >>= 1; + LF >>= 1; + } + + checkLF = LF; + while ((checkLF & 1) == 0) + checkLF >>= 1; + if (checkLF <= 1) + return -EINVAL; + + pr_info("KF=%u LF=%u Output=%u mod=%u\n", KF, LF, Output, mod->modulation); + ddbwritel(dev, KF, CHANNEL_KF(Channel)); + ddbwritel(dev, LF, CHANNEL_LF(Channel)); + + if (mod_SendChannelCommand(dev, Channel, CHANNEL_CONTROL_CMD_SETUP)) + return -EINVAL; + mod->Control = CHANNEL_CONTROL_ENABLE_DVB; + } else { + /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ + /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ + ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr)); + mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | CHANNEL_CONTROL_ENABLE_DVB); + } mod_set_rateinc(dev, output->nr); mod_set_incs(output); - mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | - CHANNEL_CONTROL_ENABLE_DVB | - CHANNEL_CONTROL_ENABLE_SOURCE); + mod->Control |= CHANNEL_CONTROL_ENABLE_SOURCE; ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); + if (dev->link[0].info->version == 2) + if (mod_SendChannelCommand(dev, Channel, CHANNEL_CONTROL_CMD_UNMUTE)) + return -EINVAL; pr_info("mod_output_start %d.%d\n", dev->nr, output->nr); } @@ -183,6 +303,195 @@ void ddbridge_mod_output_start(struct ddb_output *output) /****************************************************************************/ /****************************************************************************/ +static int mod_write_max2871(struct ddb *dev, u32 val) +{ + ddbwritel(dev, val, MAX2871_OUTDATA); + ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE, MAX2871_CONTROL); + while(1) { + u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL); + if (ControlReg == 0xFFFFFFFF) + return -EIO; + if ((ControlReg & MAX2871_CONTROL_WRITE) == 0) + break; + } + return 0; +} + +static int mod_setup_max2871(struct ddb *dev) +{ + int status = 0; + int i; + + ddbwritel(dev, MAX2871_CONTROL_CE, MAX2871_CONTROL); + for (i = 0; i < 2; i++) { + status = mod_write_max2871(dev, 0x00440005); + if (status) + break; + status = mod_write_max2871(dev, 0x6199003C); + if (status) + break; + status = mod_write_max2871(dev, 0x000000CB); + if (status) + break; + status = mod_write_max2871(dev, 0x510061C2); + if (status) + break; + status = mod_write_max2871(dev, 0x600080A1); + if (status) + break; + status = mod_write_max2871(dev, 0x00730040); + if (status) + break; + msleep(30); + } while(0); + + if (status == 0) { + u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL); + + if ((ControlReg & MAX2871_CONTROL_LOCK) == 0) + status = -EIO; + } + + return status; +} + + +static int mod_fsm_setup(struct ddb *dev, u32 FrequencyPlan, u32 MaxUsedChannels) +{ + int status = 0; + u32 Capacity; + u32 tmp = ddbreadl(dev, FSM_STATUS); + + if ((tmp & FSM_STATUS_READY) == 0) { + status = mod_setup_max2871(dev); + if (status) + return status; + ddbwritel(dev, FSM_CMD_RESET, FSM_CONTROL); + msleep(10); + + tmp = ddbreadl(dev, FSM_STATUS); + if ((tmp & FSM_STATUS_READY) == 0) + return -1; + } + Capacity = ddbreadl(dev, FSM_CAPACITY); + if (((tmp & FSM_STATUS_QAMREADY) != 0) && + ((Capacity & FSM_CAPACITY_INUSE) != 0)) + return -EBUSY; + + ddbwritel(dev, FSM_CMD_SETUP, FSM_CONTROL); + msleep(10); + tmp = ddbreadl(dev, FSM_STATUS); + + if ((tmp & FSM_STATUS_QAMREADY) == 0) + return -1; + + if (MaxUsedChannels == 0) + MaxUsedChannels = (Capacity & FSM_CAPACITY_CUR) >> 16; + + pr_info("max used chan = %u\n", MaxUsedChannels); + if (MaxUsedChannels <= 1 ) + ddbwritel(dev, FSM_GAIN_N1, FSM_GAIN); + else if (MaxUsedChannels <= 2) + ddbwritel(dev, FSM_GAIN_N2, FSM_GAIN); + else if (MaxUsedChannels <= 4) + ddbwritel(dev, FSM_GAIN_N4, FSM_GAIN); + else if (MaxUsedChannels <= 8) + ddbwritel(dev, FSM_GAIN_N8, FSM_GAIN); + else if (MaxUsedChannels <= 16) + ddbwritel(dev, FSM_GAIN_N16, FSM_GAIN); + else if (MaxUsedChannels <= 24) + ddbwritel(dev, FSM_GAIN_N24, FSM_GAIN); + else + ddbwritel(dev, FSM_GAIN_N96, FSM_GAIN); + + ddbwritel(dev, FSM_CONTROL_ENABLE, FSM_CONTROL); + + return status; +} + +static int mod_set_vga(struct ddb *dev, u32 Gain) +{ + if( Gain > 255 ) + return -EINVAL; + ddbwritel(dev, Gain, RF_VGA); + return 0; +} + +static int mod_get_vga(struct ddb *dev, u32 *pGain) +{ + *pGain = ddbreadl(dev, RF_VGA); + return 0; +} + +static void mod_TemperatureMonitorSetFan(struct ddb *dev) +{ + u32 tqam, pwm; + + if ((ddbreadl(dev, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0) { + pr_info("Over temperature condition\n"); + dev->mod_base.OverTemperatureError = 1; + } + tqam = (ddbreadl(dev, TEMPMON2_QAMCORE) >> 8) & 0xFF; + if (tqam & 0x80) + tqam = 0; + + pwm = (ddbreadl(dev, TEMPMON_FANCONTROL) >> 8) & 0x0F; + if (pwm > 10) + pwm = 10; + + if (tqam >= dev->mod_base.temp_tab[pwm]) { + while( pwm < 10 && tqam >= dev->mod_base.temp_tab[pwm + 1]) + pwm += 1; + } else { + while( pwm > 1 && tqam < dev->mod_base.temp_tab[pwm - 2]) + pwm -= 1; + } + ddbwritel(dev, (pwm << 8), TEMPMON_FANCONTROL); +} + + +static void mod_temp_handler(unsigned long data) +{ + struct ddb *dev = (struct ddb *) data; + + pr_info("mod_temp_handler\n"); + + spin_lock(&dev->mod_base.temp_lock); + mod_TemperatureMonitorSetFan(dev); + spin_unlock(&dev->mod_base.temp_lock); +} + +static int mod_TemperatureMonitorInit(struct ddb *dev, int FirstTime) { + int status = 0; + + spin_lock_irq(&dev->mod_base.temp_lock); + if (FirstTime) { + static u8 TemperatureTable[11] = {30,35,40,45,50,55,60,65,70,75,80}; + + memcpy(dev->mod_base.temp_tab, TemperatureTable, sizeof(TemperatureTable)); + } + dev->handler[0][8] = mod_temp_handler; + dev->handler_data[0][8] = (unsigned long) dev; + ddbwritel(dev, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN | + TEMPMON_CONTROL_INTENABLE), + TEMPMON_CONTROL); + ddbwritel(dev, (3 << 8), TEMPMON_FANCONTROL); + + dev->mod_base.OverTemperatureError = + ((ddbreadl(dev, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0); + if (dev->mod_base.OverTemperatureError) { + pr_info("Over temperature condition\n"); + status = -1; + } + mod_TemperatureMonitorSetFan(dev); + spin_unlock_irq(&dev->mod_base.temp_lock); + return status; +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value) { u32 RegValue = 0; @@ -804,7 +1113,7 @@ static int set_base_frequency(struct ddb *dev, u32 freq) return mod_set_down(dev, down, 8, Ext); } -static int mod_init(struct ddb *dev, u32 Frequency) +static int mod_init_1(struct ddb *dev, u32 Frequency) { int stat = 0; u8 *buffer; @@ -906,7 +1215,7 @@ void ddbridge_mod_rate_handler(unsigned long data) struct ddb_output *output = (struct ddb_output *) data; struct ddb_dma *dma = output->dma; struct ddb *dev = output->port->dev; - struct mod_state *mod = &dev->mod[output->nr]; + struct ddb_mod *mod = &dev->mod[output->nr]; u32 chan = output->nr; u32 OutPacketCount; @@ -1081,7 +1390,7 @@ void ddbridge_mod_rate_handler(unsigned long data) PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement); } -int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) +static int mod_ioctl_1(struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; struct ddb_output *output = dvbdev->priv; @@ -1146,7 +1455,117 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) return ret; } + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +static int mod_ioctl_2(struct file *file, unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct ddb_output *output = dvbdev->priv; + struct ddb *dev = output->port->dev; + + /* unsigned long arg = (unsigned long) parg; */ + int ret = 0; + + switch (cmd) { + case DVB_MOD_SET: + { + struct dvb_mod_params *mp = parg; + + pr_info("set base freq\n"); + dev->mod_base.frequency = mp->base_frequency; + pr_info("set attenuator\n"); + mod_set_attenuator(dev, mp->attenuator); + break; + } + case DVB_MOD_CHANNEL_SET: + { + struct dvb_mod_channel_params *cp = parg; + int res; + u32 ri; + + pr_info("set modulation\n"); + res = mod_set_modulation(dev, output->nr, cp->modulation); + if (res) + return res; + + if (cp->input_bitrate > dev->mod[output->nr].obitrate) + return -EINVAL; + dev->mod[output->nr].ibitrate = cp->input_bitrate; + dev->mod[output->nr].pcr_correction = cp->pcr_correction; + + pr_info("ibitrate %llu\n", dev->mod[output->nr].ibitrate); + pr_info("obitrate %llu\n", dev->mod[output->nr].obitrate); + if (cp->input_bitrate != 0) { + u64 d = dev->mod[output->nr].obitrate - + dev->mod[output->nr].ibitrate; + + d = div64_u64(d, dev->mod[output->nr].obitrate >> 24); + if (d > 0xfffffe) + ri = 0xfffffe; + else + ri = d; + } else + ri = 0; + dev->mod[output->nr].rate_inc = ri; + pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n", + dev->mod[output->nr].ibitrate >> 32, + dev->mod[output->nr].obitrate >> 32, + ri); + break; + } + default: + ret = -EINVAL; + break; + } + return ret; +} + + +static int mod_init_2(struct ddb *dev, u32 Frequency) +{ + int status; + printk("mod_init_2\n"); + + dev->mod_base.frequency = Frequency; + mod_TemperatureMonitorInit(dev, 1); + status = mod_fsm_setup(dev, 0, 0); + pr_info("fsm_setup = %d\n", status); + +#if 0 + if (pdx->NumOutputStreams <= 8) + mod_set_vga(dev, RF_VGA_GAIN_N8); + else if (pdx->NumOutputStreams <= 16) + mod_set_vga(dev, RF_VGA_GAIN_N16); + else +#endif + mod_set_vga(dev, RF_VGA_GAIN_N24); + + mod_set_attenuator(dev, 0); + return 0; +} + +int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct ddb_output *output = dvbdev->priv; + struct ddb *dev = output->port->dev; + + if (dev->link[0].info->version <= 0) + return mod_ioctl_1(file, cmd, parg); + if (dev->link[0].info->version == 2) + return mod_ioctl_2(file, cmd, parg); + return -1; +} + int ddbridge_mod_init(struct ddb *dev) { - return mod_init(dev, 722000000); + spin_lock_init(&dev->mod_base.temp_lock); + if (dev->link[0].info->version <= 1) + return mod_init_1(dev, 722000000); + if (dev->link[0].info->version == 2) + return mod_init_2(dev, 114000000); + return -1; } diff --git a/ddbridge/ddbridge-regs.h b/ddbridge/ddbridge-regs.h index 1bf9f69..b887381 100644 --- a/ddbridge/ddbridge-regs.h +++ b/ddbridge/ddbridge-regs.h @@ -23,12 +23,11 @@ /* Register Definitions */ -#define CUR_REGISTERMAP_VERSION 0x10003 -#define CUR_REGISTERMAP_VERSION_CI 0x10000 -#define CUR_REGISTERMAP_VERSION_MOD 0x10000 +#define CUR_REGISTERMAP_VERSION_V1 0x00010001 +#define CUR_REGISTERMAP_VERSION_V2 0x00020000 -#define HARDWARE_VERSION 0x00 -#define REGISTERMAP_VERSION 0x04 +#define HARDWARE_VERSION 0x00000000 +#define REGISTERMAP_VERSION 0x00000004 /* ------------------------------------------------------------------------- */ /* SPI Controller */ @@ -76,6 +75,8 @@ #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20) #define INTERRUPT_ACK (INTERRUPT_BASE + 0x20) +#define INTERRUPT_ACK1 (INTERRUPT_BASE + 0x24) +#define INTERRUPT_ACK2 (INTERRUPT_BASE + 0x28) #define INTMASK_CLOCKGEN (0x00000001) #define INTMASK_TEMPMON (0x00000002) @@ -148,11 +149,37 @@ /* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */ #define TEMPMON_BASE (0xA0) #define TEMPMON_CONTROL (TEMPMON_BASE + 0x00) + +#define TEMPMON_CONTROL_SCAN (0x00000001) +#define TEMPMON_CONTROL_AUTOSCAN (0x00000002) +#define TEMPMON_CONTROL_INTENABLE (0x00000004) +#define TEMPMON_CONTROL_OVERTEMP (0x00008000) + + /* SHORT Temperature in °C x 256 */ #define TEMPMON_CORE (TEMPMON_BASE + 0x04) +#define TEMPMON_SENSOR0 (TEMPMON_BASE + 0x04) #define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08) #define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C) +#define TEMPMON_FANCONTROL (TEMPMON_BASE + 0x10) +#define TEMPMON_FANPWM (0x00000F00) // PWM speed in 10% steps +#define TEMPMON_FANTACHO (0x000000FF) // Rotations in 100/min steps + +// V1 Temperature Monitor +// Temperature Monitor TEMPMON_CONTROL & 0x8000 == 0 : ( 2x LM75A @ 0x90,0x92 ) +// Temperature Monitor TEMPMON_CONTROL & 0x8000 == 1 : ( 1x LM75A @ 0x90, 1x ADM1032 @ 0x9A ) + +#define TEMPMON1_CORE (TEMPMON_SENSOR0) // SHORT Temperature in °C x 256 (ADM1032 ext) +#define TEMPMON1_SENSOR1 (TEMPMON_BASE + 0x08) // SHORT Temperature in °C x 256 (LM75A 0x90) +#define TEMPMON1_SENSOR2 (TEMPMON_BASE + 0x0C) // SHORT Temperature in °C x 256 (LM75A 0x92 or ADM1032 Int) + +// V2 Temperature Monitor 2 ADM1032 + +#define TEMPMON2_BOARD (TEMPMON_SENSOR0) // SHORT Temperature in °C x 256 (ADM1032 int) +#define TEMPMON2_FPGACORE (TEMPMON_SENSOR1) // SHORT Temperature in °C x 256 (ADM1032 ext) +#define TEMPMON2_QAMCORE (TEMPMON_SENSOR2) // SHORT Temperature in °C x 256 (ADM1032 ext) + /* ------------------------------------------------------------------------- */ /* I2C Master Controller */ @@ -271,6 +298,8 @@ #define CI_BLOCKIO_SEND_BUFFER(i) \ (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) +// V1 + #define VCO1_BASE (0xC0) #define VCO1_CONTROL (VCO1_BASE + 0x00) #define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */ @@ -301,6 +330,53 @@ /* Muxout from VCO (usually = Lock) */ #define VCO3_CONTROL_MUXOUT (0x00000004) +// V2 + +#define MAX2871_BASE (0xC0) +#define MAX2871_CONTROL (MAX2871_BASE + 0x00) +#define MAX2871_OUTDATA (MAX2871_BASE + 0x04) // 32 Bit +#define MAX2871_INDATA (MAX2871_BASE + 0x08) // 32 Bit +#define MAX2871_CONTROL_WRITE (0x00000001) // 1 = Trigger write, resets when done +#define MAX2871_CONTROL_CE (0x00000002) // 0 = Put VCO into power down +#define MAX2871_CONTROL_MUXOUT (0x00000004) // Muxout from VCO +#define MAX2871_CONTROL_LOCK (0x00000008) // Lock from VCO + +#define FSM_BASE (0x200) +#define FSM_CONTROL (FSM_BASE + 0x00) + +#define FSM_CONTROL_ENABLE (0x00000100) + +#define FSM_CMD_MASK (0x00000087) +#define FSM_CMD_STATUS (0x00000080) +#define FSM_CMD_RESET (0x00000080) +#define FSM_CMD_POWERDOWN (0x00000081) +#define FSM_CMD_SETUP (0x00000082) + +#define FSM_STATUS (FSM_BASE + 0x00) +#define FSM_STATUS_READY (0x00010000) +#define FSM_STATUS_QAMREADY (0x00020000) + + +#define FSM_CAPACITY (FSM_BASE + 0x04) +#define FSM_CAPACITY_MAX (0x3F000000) +#define FSM_CAPACITY_CUR (0x003F0000) +#define FSM_CAPACITY_INUSE (0x0000003F) + +#define FSM_GAIN (FSM_BASE + 0x10) +#define FSM_GAINMASK (0x000000FF) + +#define FSM_GAIN_N1 (0x000000FE) +#define FSM_GAIN_N2 (0x000000A1) +#define FSM_GAIN_N4 (0x00000066) +#define FSM_GAIN_N8 (0x00000048) +#define FSM_GAIN_N16 (0x0000002D) +#define FSM_GAIN_N24 (0x00000029) +#define FSM_GAIN_N96 (0x00000011) + + +// Attenuator/VGA + +#define RF_ATTENUATOR (0xD8) #define RF_ATTENUATOR (0xD8) /* 0x00 = 0 dB 0x01 = 1 dB @@ -308,6 +384,20 @@ 0x1F = 31 dB */ +#define RF_VGA (0xDC) +/* Only V2 */ +/* 8 bit range 0 - 31.75 dB Gain */ + +/* VGA Gain for same output level as V1 Modulator */ +#define RF_VGA_GAIN_N8 (85) +#define RF_VGA_GAIN_N16 (117) +#define RF_VGA_GAIN_N24 (122) + +#define RF_VGA_GAIN_MAX (200) + + +/* V1 only */ + #define RF_POWER (0xE0) #define RF_POWER_BASE (0xE0) #define RF_POWER_CONTROL (RF_POWER_BASE + 0x00) @@ -351,7 +441,7 @@ #define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010) -/* Modulator Base */ +/* Modulator Base V1 */ #define MODULATOR_BASE (0x200) #define MODULATOR_CONTROL (MODULATOR_BASE) @@ -369,9 +459,11 @@ /* Modulator Channels */ -#define CHANNEL_BASE (0x400) +#define CHANNEL_BASE dev->link[0].info->regmap->channel->base + #define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00) #define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04) +#define CHANNEL_SETTINGS2(i) (CHANNEL_BASE + (i) * 64 + 0x08) #define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C) #define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10) #define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14) @@ -381,6 +473,8 @@ #define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24) #define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28) #define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C) +#define CHANNEL_KF(i) (CHANNEL_BASE + (i) * 64 + 0x30) +#define CHANNEL_LF(i) (CHANNEL_BASE + (i) * 64 + 0x34) #define CHANNEL_CONTROL_RESET (0x00000001) #define CHANNEL_CONTROL_ENABLE_DVB (0x00000002) @@ -389,8 +483,17 @@ #define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010) #define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100) +#define CHANNEL_CONTROL_CMD_MASK (0x0000F000) +#define CHANNEL_CONTROL_CMD_STATUS (0x00008000) +#define CHANNEL_CONTROL_CMD_FREE (0x00008000) +#define CHANNEL_CONTROL_CMD_SETUP (0x00009000) +#define CHANNEL_CONTROL_CMD_MUTE (0x0000A000) +#define CHANNEL_CONTROL_CMD_UNMUTE (0x0000B000) + #define CHANNEL_CONTROL_RESET_ERROR (0x00010000) -#define CHANNEL_CONTROL_BUSY (0x01000000) +#define CHANNEL_CONTROL_ACTIVE (0x00400000) +#define CHANNEL_CONTROL_BUSY (0x00800000) +#define CHANNEL_CONTROL_ERROR_CMD (0x10000000) #define CHANNEL_CONTROL_ERROR_SYNC (0x20000000) #define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000) #define CHANNEL_CONTROL_ERROR_FATAL (0x80000000) @@ -402,6 +505,14 @@ #define CHANNEL_SETTINGS_QAM128 (0x00000003) #define CHANNEL_SETTINGS_QAM256 (0x00000004) +#define CHANNEL_SETTINGS2_OUTPUT_MASK (0x0000007F) + +#define KFLF_MAX (0x07FFFFFFUL) +#define KF_INIT(Symbolrate) (Symbolrate) +#define LF_INIT(Symbolrate) (9000000UL) +#define MIN_SYMBOLRATE (1000000) +#define MAX_SYMBOLRATE (7100000) + /* OCTONET */ diff --git a/ddbridge/ddbridge.c b/ddbridge/ddbridge.c index 29d375f..ce7699f 100644 --- a/ddbridge/ddbridge.c +++ b/ddbridge/ddbridge.c @@ -468,6 +468,33 @@ static struct ddb_info ddb_mod = { .temp_num = 1, }; +static struct ddb_info ddb_mod_fsm_24 = { + .type = DDB_MOD, + .version = 2, + .name = "Digital Devices DVB-C modulator FSM-24", + .regmap = &octopus_mod_2_map, + .port_num = 24, + .temp_num = 1, +}; + +static struct ddb_info ddb_mod_fsm_16 = { + .type = DDB_MOD, + .version = 2, + .name = "Digital Devices DVB-C modulator FSM-16", + .regmap = &octopus_mod_2_map, + .port_num = 16, + .temp_num = 1, +}; + +static struct ddb_info ddb_mod_fsm_8 = { + .type = DDB_MOD, + .name = "Digital Devices DVB-C modulator FSM-8", + .version = 2, + .regmap = &octopus_mod_2_map, + .port_num = 8, + .temp_num = 1, +}; + static struct ddb_info ddb_octopro_hdin = { .type = DDB_OCTOPRO_HDIN, .name = "Digital Devices OctopusNet Pro HDIN", @@ -523,6 +550,9 @@ static const struct pci_device_id ddb_id_tbl[] __devinitconst = { DDB_ID(DDVID, 0x0013, DDVID, 0x0043, ddb_ci_s2_pro), DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod), DDB_ID(DDVID, 0x0201, DDVID, 0x0002, ddb_mod), + DDB_ID(DDVID, 0x0210, DDVID, 0x0001, ddb_mod_fsm_24), + DDB_ID(DDVID, 0x0210, DDVID, 0x0002, ddb_mod_fsm_16), + DDB_ID(DDVID, 0x0210, DDVID, 0x0003, ddb_mod_fsm_8), /* testing on OctopusNet Pro */ DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_octopro_hdin), DDB_ID(DDVID, 0x0321, PCI_ANY_ID, PCI_ANY_ID, ddb_none), diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index 8b2859d..316fbf5 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -112,6 +112,7 @@ struct ddb_regmap { u32 irq_base_idma; u32 irq_base_odma; u32 irq_base_gtl; + u32 irq_base_rate; struct ddb_regset *i2c; struct ddb_regset *i2c_buf; @@ -144,7 +145,7 @@ struct ddb_ids { }; struct ddb_info { - int type; + u32 type; #define DDB_NONE 0 #define DDB_OCTOPUS 1 #define DDB_OCTOPUS_CI 2 @@ -154,6 +155,7 @@ struct ddb_info { #define DDB_OCTOPUS_MAX_CT 6 #define DDB_OCTOPRO 7 #define DDB_OCTOPRO_HDIN 8 + u32 version; char *name; u32 i2c_mask; u8 port_num; @@ -167,8 +169,9 @@ struct ddb_info { u8 mdio_num; u8 con_clock; /* use a continuous clock */ u8 ts_quirks; -#define TS_QUIRK_SERIAL 1 -#define TS_QUIRK_REVERSED 2 +#define TS_QUIRK_SERIAL 1 +#define TS_QUIRK_REVERSED 2 +#define TS_QUIRK_NO_OUTPUT 4 struct ddb_regmap *regmap; }; @@ -335,10 +338,21 @@ struct mod_base { u32 frequency; u32 flat_start; u32 flat_end; + + spinlock_t temp_lock; + int OverTemperatureError; + u8 temp_tab[11]; }; -struct mod_state { +struct ddb_mod { + struct ddb_port *port; + u32 nr; + u32 regs; + + u32 frequency; u32 modulation; + u32 symbolrate; + u64 obitrate; u64 ibitrate; u32 pcr_correction; @@ -456,7 +470,7 @@ struct ddb { u8 tsbuf[TS_CAPTURE_LEN]; struct mod_base mod_base; - struct mod_state mod[10]; + struct ddb_mod mod[24]; }; static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)