From 1f4ae2bd51c7c525767a3bcb88314bc94365026f Mon Sep 17 00:00:00 2001 From: Ralph Metzler Date: Mon, 29 Aug 2016 18:44:53 +0200 Subject: [PATCH] - add support for new Max S8/A8 with temperature monitor - move temperature monitor code from mod to core and cleanup modulator ioctls --- ddbridge/ddbridge-core.c | 209 +++++++++++++++++++++++++-- ddbridge/ddbridge-mod.c | 304 ++++++++++++++++----------------------- ddbridge/ddbridge-regs.h | 2 +- ddbridge/ddbridge.c | 12 +- ddbridge/ddbridge.h | 17 +-- 5 files changed, 340 insertions(+), 204 deletions(-) diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index 8530957..e276c65 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -285,7 +285,6 @@ static struct ddb_regmap octopus_mod_map = { .channel = &octopus_mod_channel, }; - static struct ddb_regmap octopus_mod_2_map = { .irq_version = 2, .irq_base_odma = 64, @@ -306,17 +305,67 @@ static struct ddb_info ddb_s2_48 = { .port_num = 4, .i2c_mask = 0x01, .board_control = 1, + .tempmon_irq = 24, }; -static struct ddb_info ddb_ct_8 = { +static struct ddb_info ddb_ct2_8 = { .type = DDB_OCTOPUS_MAX_CT, - .name = "Digital Devices MAX CT8", + .name = "Digital Devices MAX A8 CT2", .regmap = &octopus_map, .port_num = 4, .i2c_mask = 0x0f, .board_control = 0x0ff, .board_control_2 = 0xf00, .ts_quirks = TS_QUIRK_SERIAL, + .tempmon_irq = 24, +}; + +static struct ddb_info ddb_c2t2_8 = { + .type = DDB_OCTOPUS_MAX_CT, + .name = "Digital Devices MAX A8 C2T2", + .regmap = &octopus_map, + .port_num = 4, + .i2c_mask = 0x0f, + .board_control = 0x0ff, + .board_control_2 = 0xf00, + .ts_quirks = TS_QUIRK_SERIAL, + .tempmon_irq = 24, +}; + +static struct ddb_info ddb_isdbt_8 = { + .type = DDB_OCTOPUS_MAX_CT, + .name = "Digital Devices MAX A8 ISDBT", + .regmap = &octopus_map, + .port_num = 4, + .i2c_mask = 0x0f, + .board_control = 0x0ff, + .board_control_2 = 0xf00, + .ts_quirks = TS_QUIRK_SERIAL, + .tempmon_irq = 24, +}; + +static struct ddb_info ddb_c2t2i_v0_8 = { + .type = DDB_OCTOPUS_MAX_CT, + .name = "Digital Devices MAX A8 C2T2I V0", + .regmap = &octopus_map, + .port_num = 4, + .i2c_mask = 0x0f, + .board_control = 0x0ff, + .board_control_2 = 0xf00, + .ts_quirks = TS_QUIRK_SERIAL, + .tempmon_irq = 24, +}; + +static struct ddb_info ddb_c2t2i_8 = { + .type = DDB_OCTOPUS_MAX_CT, + .name = "Digital Devices MAX A8 C2T2I", + .regmap = &octopus_map, + .port_num = 4, + .i2c_mask = 0x0f, + .board_control = 0x0ff, + .board_control_2 = 0xf00, + .ts_quirks = TS_QUIRK_SERIAL, + .tempmon_irq = 24, }; @@ -2601,6 +2650,11 @@ static void ddb_port_probe(struct ddb_port *port) port->type = DDB_TUNER_ISDBT_SONY_P; port->type_name = "ISDBT_SONY"; break; + case 0xc1: + port->name = "DUAL DVB-C2T2 ISDB-T CXD2854"; + port->type = DDB_TUNER_DVBC2T2_SONY_P; + port->type_name = "DVBC2T2_ISDBT_SONY"; + break; default: return; } @@ -4359,15 +4413,28 @@ static ssize_t fan_store(struct device *device, struct device_attribute *d, return count; } +static ssize_t fanspeed_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct ddb *dev = dev_get_drvdata(device); + int num = attr->attr.name[8] - 0x30; + struct ddb_link *link = &dev->link[num]; + u32 spd; + + spd = ddblreadl(link, TEMPMON_FANCONTROL) & 0xff; + return sprintf(buf, "%u\n", spd * 100); +} + static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf) { struct ddb *dev = dev_get_drvdata(device); + struct ddb_link *link = &dev->link[0]; struct i2c_adapter *adap; s32 temp, temp2, temp3; int i; u8 tmp[2]; - + if (dev->link[0].info->type == DDB_MOD) { if (dev->link[0].info->version == 2) { temp = ddbreadl(dev, TEMPMON2_BOARD); @@ -4849,6 +4916,13 @@ static struct device_attribute ddb_attrs_led[] = { __ATTR(led3, 0664, led_show, led_store), }; +static struct device_attribute ddb_attrs_fanspeed[] = { + __ATTR_MRO(fanspeed0, fanspeed_show), + __ATTR_MRO(fanspeed1, fanspeed_show), + __ATTR_MRO(fanspeed2, fanspeed_show), + __ATTR_MRO(fanspeed3, fanspeed_show), +}; + static struct class ddb_class = { .name = "ddbridge", .owner = THIS_MODULE, @@ -4878,6 +4952,9 @@ static void ddb_device_attrs_del(struct ddb *dev) { int i; + for (i = 0; i < 4; i++) + if (dev->link[i].info->tempmon_irq) + device_remove_file(dev->ddb_dev, &ddb_attrs_fanspeed[i]); for (i = 0; i < dev->link[0].info->temp_num; i++) device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]); for (i = 0; i < dev->link[0].info->port_num; i++) @@ -4920,6 +4997,12 @@ static int ddb_device_attrs_add(struct ddb *dev) &ddb_attrs_led[i])) goto fail; } + for (i = 0; i < 4; i++) + if (dev->link[i].info && + dev->link[i].info->tempmon_irq) + if (device_create_file(dev->ddb_dev, + &ddb_attrs_fanspeed[i])) + goto fail; return 0; fail: return -1; @@ -4994,6 +5077,7 @@ static void link_tasklet(unsigned long data) LINK_IRQ_HANDLE(l, 1); LINK_IRQ_HANDLE(l, 2); LINK_IRQ_HANDLE(l, 3); + LINK_IRQ_HANDLE(l, 24); } static void gtl_irq_handler(unsigned long priv) @@ -5010,6 +5094,7 @@ static void gtl_irq_handler(unsigned long priv) LINK_IRQ_HANDLE(l, 1); LINK_IRQ_HANDLE(l, 2); LINK_IRQ_HANDLE(l, 3); + LINK_IRQ_HANDLE(l, 24); } #else tasklet_schedule(&link->tasklet); @@ -5054,7 +5139,7 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l) link->info = &ddb_s2_48; break; case 0x0008dd01: - link->info = &ddb_ct_8; + link->info = &ddb_c2t2_8; break; default: pr_info("DDBridge: Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.", @@ -5068,16 +5153,24 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l) dev->handler_data[0][base + l] = (unsigned long) link; dev->handler[0][base + l] = gtl_irq_handler; + dev->link[l].ids.hwid = ddbreadl(dev, DDB_LINK_TAG(l) | 0); + dev->link[l].ids.regmapid = ddbreadl(dev, DDB_LINK_TAG(l) | 4); + dev->link[l].ids.vendor = id >> 16;; + dev->link[l].ids.device = id & 0xffff;; + //dev->link[l].ids.subvendor = id->subvendor; + //dev->link[l].ids.subdevice = id->subdevice; + pr_info("GTL %s\n", dev->link[l].info->name); + pr_info("GTL HW %08x REGMAP %08x\n", - ddbreadl(dev, DDB_LINK_TAG(l) | 0), - ddbreadl(dev, DDB_LINK_TAG(l) | 4)); + dev->link[l].ids.hwid, + dev->link[l].ids.regmapid); pr_info("GTL ID %08x\n", ddbreadl(dev, DDB_LINK_TAG(l) | 8)); tasklet_init(&link->tasklet, link_tasklet, (unsigned long) link); ddbwritel(dev, 0xffffffff, DDB_LINK_TAG(l) | INTERRUPT_ACK); - ddbwritel(dev, 0xf, DDB_LINK_TAG(l) | INTERRUPT_ENABLE); + ddbwritel(dev, 0x0100000f, DDB_LINK_TAG(l) | INTERRUPT_ENABLE); return 0; } @@ -5093,13 +5186,110 @@ static int ddb_gtl_init(struct ddb *dev) return 0; } +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +static void tempmon_setfan(struct ddb_link *link) +{ + u32 temp, temp2, pwm; + + if ((ddblreadl(link, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0) { + pr_info("Over temperature condition\n"); + link->OverTemperatureError = 1; + } + temp = (ddblreadl(link, TEMPMON_SENSOR0) >> 8) & 0xFF; + if (temp & 0x80) + temp = 0; + temp2 = (ddblreadl(link, TEMPMON_SENSOR1) >> 8) & 0xFF; + if (temp2 & 0x80) + temp2 = 0; + if (temp2 > temp) + temp = temp2; + + pwm = (ddblreadl(link, TEMPMON_FANCONTROL) >> 8) & 0x0F; + if (pwm > 10) + pwm = 10; + + if (temp >= link->temp_tab[pwm]) { + while( pwm < 10 && temp >= link->temp_tab[pwm + 1]) + pwm += 1; + } else { + while( pwm > 1 && temp < link->temp_tab[pwm - 2]) + pwm -= 1; + } + ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL); + } + + +static void temp_handler(unsigned long data) +{ + struct ddb_link *link = (struct ddb_link *) data; + + spin_lock(&link->temp_lock); + tempmon_setfan(link); + spin_unlock(&link->temp_lock); +} + +static int tempmon_init(struct ddb_link *link, int FirstTime) +{ + struct ddb *dev = link->dev; + int status = 0; + u32 l = link->nr; + + spin_lock_irq(&link->temp_lock); + if (FirstTime) { + static u8 TemperatureTable[11] = {30,35,40,45,50,55,60,65,70,75,80}; + + memcpy(link->temp_tab, TemperatureTable, sizeof(TemperatureTable)); + } + dev->handler[l][link->info->tempmon_irq] = temp_handler; + dev->handler_data[l][link->info->tempmon_irq] = (unsigned long) link; + ddblwritel(link, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN | + TEMPMON_CONTROL_INTENABLE), + TEMPMON_CONTROL); + ddblwritel(link, (3 << 8), TEMPMON_FANCONTROL); + + link->OverTemperatureError = + ((ddblreadl(link, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0); + if (link->OverTemperatureError) { + pr_info("Over temperature condition\n"); + status = -1; + } + tempmon_setfan(link); + spin_unlock_irq(&link->temp_lock); + return status; +} + +static int ddb_init_tempmon(struct ddb_link *link) +{ + struct ddb *dev = link->dev; + struct ddb_info *info = link->info; + + if (!info->tempmon_irq) + return; + if (info->type == DDB_OCTOPUS_MAX || + info->type == DDB_OCTOPUS_MAX_CT) + if (link->ids.regmapid < 0x00010002) + return; + spin_lock_init(&link->temp_lock); + printk("init_tempmon\n"); + tempmon_init(link, 1); +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + static int ddb_init_boards(struct ddb *dev) { struct ddb_info *info; + struct ddb_link *link; u32 l; for (l = 0; l < DDB_MAX_LINK; l++) { - info = dev->link[l].info; + link = &dev->link[l]; + info = link->info; if (!info) continue; if (info->board_control) { @@ -5113,6 +5303,7 @@ static int ddb_init_boards(struct ddb *dev) DDB_LINK_TAG(l) | BOARD_CONTROL); usleep_range(2000, 3000); } + ddb_init_tempmon(link); } return 0; } diff --git a/ddbridge/ddbridge-mod.c b/ddbridge/ddbridge-mod.c index 6545f7a..2cd97b4 100644 --- a/ddbridge/ddbridge-mod.c +++ b/ddbridge/ddbridge-mod.c @@ -215,12 +215,12 @@ static void mod_set_rateinc(struct ddb *dev, u32 chan) static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 }; -void ddbridge_mod_output_start(struct ddb_output *output) +int ddbridge_mod_output_start(struct ddb_output *output) { struct ddb *dev = output->port->dev; u32 Channel = output->nr; struct ddb_mod *mod = &dev->mod[output->nr]; - u32 Symbolrate = 6900000; + u32 Symbolrate = mod->symbolrate; /*PCRIncrement = RoundPCR(PCRIncrement);*/ /*PCRDecrement = RoundPCR(PCRDecrement);*/ @@ -256,8 +256,7 @@ void ddbridge_mod_output_start(struct ddb_output *output) u32 d = gcd(KF,LF); u32 checkLF; - mod->modulation = QAM_256 - 1; - ddbwritel(dev, mod->modulation, CHANNEL_SETTINGS(Channel)); + ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel)); ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel)); KF = KF / d; @@ -297,6 +296,7 @@ void ddbridge_mod_output_start(struct ddb_output *output) if (mod_SendChannelCommand(dev, Channel, CHANNEL_CONTROL_CMD_UNMUTE)) return -EINVAL; pr_info("mod_output_start %d.%d\n", dev->nr, output->nr); + return 0; } /****************************************************************************/ @@ -422,14 +422,14 @@ static int mod_get_vga(struct ddb *dev, u32 *pGain) *pGain = ddbreadl(dev, RF_VGA); return 0; } - -static void mod_TemperatureMonitorSetFan(struct ddb *dev) +#if 0 +static void 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; + dev->OverTemperatureError = 1; } tqam = (ddbreadl(dev, TEMPMON2_QAMCORE) >> 8) & 0xFF; if (tqam & 0x80) @@ -439,55 +439,55 @@ static void mod_TemperatureMonitorSetFan(struct ddb *dev) if (pwm > 10) pwm = 10; - if (tqam >= dev->mod_base.temp_tab[pwm]) { - while( pwm < 10 && tqam >= dev->mod_base.temp_tab[pwm + 1]) + if (tqam >= dev->temp_tab[pwm]) { + while( pwm < 10 && tqam >= dev->temp_tab[pwm + 1]) pwm += 1; } else { - while( pwm > 1 && tqam < dev->mod_base.temp_tab[pwm - 2]) + while( pwm > 1 && tqam < dev->temp_tab[pwm - 2]) pwm -= 1; } ddbwritel(dev, (pwm << 8), TEMPMON_FANCONTROL); } -static void mod_temp_handler(unsigned long data) +static void temp_handler(unsigned long data) { struct ddb *dev = (struct ddb *) data; - pr_info("mod_temp_handler\n"); + pr_info("temp_handler\n"); - spin_lock(&dev->mod_base.temp_lock); - mod_TemperatureMonitorSetFan(dev); - spin_unlock(&dev->mod_base.temp_lock); + spin_lock(&dev->temp_lock); + TemperatureMonitorSetFan(dev); + spin_unlock(&dev->temp_lock); } -static int mod_TemperatureMonitorInit(struct ddb *dev, int FirstTime) { +static int TemperatureMonitorInit(struct ddb *dev, int FirstTime) { int status = 0; - spin_lock_irq(&dev->mod_base.temp_lock); + spin_lock_irq(&dev->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)); + memcpy(dev->temp_tab, TemperatureTable, sizeof(TemperatureTable)); } - dev->handler[0][8] = mod_temp_handler; + dev->handler[0][8] = 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 = + dev->OverTemperatureError = ((ddbreadl(dev, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0); - if (dev->mod_base.OverTemperatureError) { + if (dev->OverTemperatureError) { pr_info("Over temperature condition\n"); status = -1; } - mod_TemperatureMonitorSetFan(dev); - spin_unlock_irq(&dev->mod_base.temp_lock); + TemperatureMonitorSetFan(dev); + spin_unlock_irq(&dev->temp_lock); return status; } - +#endif /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ @@ -1063,12 +1063,24 @@ u32 eqtab[] = { 0x00001B23, 0x0000EEB7, 0x00006A28 }; -static int mod_set_modulation(struct ddb *dev, int chan, enum fe_modulation mod) +static int mod_set_modrate(struct ddb *dev, int chan, + enum fe_modulation mod, u32 srate) { + u64 ofac; + if (mod > QAM_256 || mod < QAM_16) return -EINVAL; + if (dev->link[0].info->version < 2) { + if (srate != 6900000) + return -EINVAL; + } else { + if (srate > 7100000) + return -EINVAL; + } + dev->mod[chan].symbolrate = srate; dev->mod[chan].modulation = mod; - dev->mod[chan].obitrate = 0x0061072787900000ULL * (mod + 3); + ofac = ((((u64) srate) << 32) * 188 ) / 204; + dev->mod[chan].obitrate = ofac * (mod + 3); dev->mod[chan].ibitrate = dev->mod[chan].obitrate; if (dev->link[0].info->version < 2) ddbwritel(dev, qamtab[mod], CHANNEL_SETTINGS(chan)); @@ -1180,9 +1192,10 @@ static int mod_init_1(struct ddb *dev, u32 Frequency) iqfreq = flash->DataSet[0].FrequencyFactor * (FrequencyCH10 + (9 - i) * 8); + iqfreq += (dev->link[0].ids.hwid == 0x0203dd01) ? 22 : 0 ; iqsteps = flash->DataSet[0].IQTableLength; mod_set_iq(dev, iqsteps, i, iqfreq); - mod_set_modulation(dev, i, QAM_256); + mod_set_modrate(dev, i, QAM_256, 6900000); } mod_bypass_equalizer(dev, 1); @@ -1391,157 +1404,26 @@ void ddbridge_mod_rate_handler(unsigned long data) PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement); } -static int mod_ioctl_1(struct file *file, unsigned int cmd, void *parg) +static void mod_calc_rateinc(struct ddb_mod *mod) { - 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"); - if (mp->base_frequency != dev->mod_base.frequency) - if (set_base_frequency(dev, mp->base_frequency)) - return -EINVAL; - 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_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; - - 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; - int streams = dev->link[0].info->port_num; - - dev->mod_base.frequency = Frequency; - mod_TemperatureMonitorInit(dev, 1); - status = mod_fsm_setup(dev, 0, 0); - - if (streams <= 8) - mod_set_vga(dev, RF_VGA_GAIN_N8); - else if (streams <= 16) - mod_set_vga(dev, RF_VGA_GAIN_N16); - else - mod_set_vga(dev, RF_VGA_GAIN_N24); - - mod_set_attenuator(dev, 0); - return 0; + u32 ri; + + pr_info("ibitrate %llu\n", mod->ibitrate); + pr_info("obitrate %llu\n", mod->obitrate); + + if (mod->ibitrate != 0) { + u64 d = mod->obitrate - mod->ibitrate; + + d = div64_u64(d, mod->obitrate >> 24); + if (d > 0xfffffe) + ri = 0xfffffe; + else + ri = d; + } else + ri = 0; + mod->rate_inc = ri; + pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n", + mod->ibitrate >> 32, mod->obitrate >> 32, ri); } int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) @@ -1549,17 +1431,73 @@ 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; + + /* unsigned long arg = (unsigned long) parg; */ + int ret = 0; + + switch (cmd) { + case DVB_MOD_SET: + { + struct dvb_mod_params *mp = parg; + + if (dev->link[0].info->version < 2) { + if (mp->base_frequency != dev->mod_base.frequency) + if (set_base_frequency(dev, mp->base_frequency)) + return -EINVAL; + } else { + dev->mod_base.frequency = mp->base_frequency; + } + mod_set_attenuator(dev, mp->attenuator); + break; + } + case DVB_MOD_CHANNEL_SET: + { + struct dvb_mod_channel_params *cp = parg; + int res; + + res = mod_set_modrate(dev, output->nr, cp->modulation, 6900000); + 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; + + mod_calc_rateinc(&dev->mod[output->nr]); + break; + } + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int mod_init_2(struct ddb *dev, u32 Frequency) +{ + int status, i; + int streams = dev->link[0].info->port_num; + + dev->mod_base.frequency = Frequency; + status = mod_fsm_setup(dev, 0, 0); + + for (i = 0; i < streams; i++) + mod_set_modrate(dev, i, QAM_256, 6900000); - 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; + if (streams <= 8) + mod_set_vga(dev, RF_VGA_GAIN_N8); + else if (streams <= 16) + mod_set_vga(dev, RF_VGA_GAIN_N16); + else + mod_set_vga(dev, RF_VGA_GAIN_N24); + + mod_set_attenuator(dev, 0); + return 0; } int ddbridge_mod_init(struct ddb *dev) { - 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) diff --git a/ddbridge/ddbridge-regs.h b/ddbridge/ddbridge-regs.h index b887381..22ba6f3 100644 --- a/ddbridge/ddbridge-regs.h +++ b/ddbridge/ddbridge-regs.h @@ -147,7 +147,7 @@ #define DAC_CONTROL_RESET (0x200) /* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */ -#define TEMPMON_BASE (0xA0) +#define TEMPMON_BASE (0x1c0) #define TEMPMON_CONTROL (TEMPMON_BASE + 0x00) #define TEMPMON_CONTROL_SCAN (0x00000001) diff --git a/ddbridge/ddbridge.c b/ddbridge/ddbridge.c index ce7699f..45f3f7c 100644 --- a/ddbridge/ddbridge.c +++ b/ddbridge/ddbridge.c @@ -475,6 +475,7 @@ static struct ddb_info ddb_mod_fsm_24 = { .regmap = &octopus_mod_2_map, .port_num = 24, .temp_num = 1, + .tempmon_irq = 8, }; static struct ddb_info ddb_mod_fsm_16 = { @@ -484,6 +485,7 @@ static struct ddb_info ddb_mod_fsm_16 = { .regmap = &octopus_mod_2_map, .port_num = 16, .temp_num = 1, + .tempmon_irq = 8, }; static struct ddb_info ddb_mod_fsm_8 = { @@ -493,6 +495,7 @@ static struct ddb_info ddb_mod_fsm_8 = { .regmap = &octopus_mod_2_map, .port_num = 8, .temp_num = 1, + .tempmon_irq = 8, }; static struct ddb_info ddb_octopro_hdin = { @@ -541,15 +544,18 @@ static const struct pci_device_id ddb_id_tbl[] __devinitconst = { DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7), DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7), DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48), - DDB_ID(DDVID, 0x0008, DDVID, 0x0034, ddb_ct_8), - DDB_ID(DDVID, 0x0008, DDVID, 0x0035, ddb_ct_8), - DDB_ID(DDVID, 0x0008, DDVID, 0x0036, ddb_ct_8), + DDB_ID(DDVID, 0x0008, DDVID, 0x0034, ddb_ct2_8), + DDB_ID(DDVID, 0x0008, DDVID, 0x0035, ddb_c2t2_8), + DDB_ID(DDVID, 0x0008, DDVID, 0x0036, ddb_isdbt_8), + DDB_ID(DDVID, 0x0008, DDVID, 0x0037, ddb_c2t2i_v0_8), + DDB_ID(DDVID, 0x0008, DDVID, 0x0038, ddb_c2t2i_8), DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), DDB_ID(DDVID, 0x0012, DDVID, 0x0042, ddb_ci), 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, 0x0203, DDVID, 0x0001, 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), diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index cb70974..68168a1 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -113,7 +113,7 @@ struct ddb_regmap { u32 irq_base_odma; u32 irq_base_gtl; u32 irq_base_rate; - + struct ddb_regset *i2c; struct ddb_regset *i2c_buf; struct ddb_regset *idma; @@ -172,6 +172,7 @@ struct ddb_info { #define TS_QUIRK_SERIAL 1 #define TS_QUIRK_REVERSED 2 #define TS_QUIRK_NO_OUTPUT 4 + u32 tempmon_irq; struct ddb_regmap *regmap; }; @@ -338,10 +339,6 @@ struct mod_base { u32 frequency; u32 flat_start; u32 flat_end; - - spinlock_t temp_lock; - int OverTemperatureError; - u8 temp_tab[11]; }; struct ddb_mod { @@ -424,6 +421,10 @@ struct ddb_link { struct ddb_lnb lnb; struct tasklet_struct tasklet; struct ddb_ids ids; + + spinlock_t temp_lock; + int OverTemperatureError; + u8 temp_tab[11]; }; struct ddb { @@ -471,6 +472,7 @@ struct ddb { struct mod_base mod_base; struct ddb_mod mod[24]; + }; static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr) @@ -520,7 +522,7 @@ static inline void gtlw(struct ddb_link *link) } #endif -#if 0 + static u32 ddblreadl(struct ddb_link *link, u32 adr) { if (unlikely(link->nr)) { @@ -554,7 +556,6 @@ static void ddblwritel(struct ddb_link *link, u32 val, u32 adr) } writel(val, (char *) (link->dev->regs + (adr))); } -#endif static u32 ddbreadl(struct ddb *dev, u32 adr) { @@ -744,7 +745,7 @@ struct DDMOD_FLASH { int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg); int ddbridge_mod_init(struct ddb *dev); void ddbridge_mod_output_stop(struct ddb_output *output); -void ddbridge_mod_output_start(struct ddb_output *output); +int ddbridge_mod_output_start(struct ddb_output *output); void ddbridge_mod_rate_handler(unsigned long data);