mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
- add support for new Max S8/A8 with temperature monitor
- move temperature monitor code from mod to core and cleanup modulator ioctls
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user