1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

- add lock loss irq handler

- add modulator ioctl mutex
- some more documentation about modulator properties
This commit is contained in:
Ralph Metzler 2017-10-17 23:49:31 +02:00
parent 4a93f79093
commit 0f05b1988a
6 changed files with 91 additions and 24 deletions

View File

@ -63,12 +63,18 @@ int main()
/* gain 0-255 */ /* gain 0-255 */
get_property(fd, MODULATOR_GAIN, &data); get_property(fd, MODULATOR_GAIN, &data);
printf("Modulator gain = %u\n", data); printf("Modulator gain = %u\n", data);
set_property(fd, MODULATOR_GAIN, 120); set_property(fd, MODULATOR_GAIN, 100);
get_property(fd, MODULATOR_GAIN, &data); get_property(fd, MODULATOR_GAIN, &data);
printf("Modulator gain = %u\n", data); printf("Modulator gain = %u\n", data);
get_property(fd, MODULATOR_ATTENUATOR, &data);
printf("Modulator attenuator = %u\n", data);
get_property(fd, MODULATOR_STATUS, &data); get_property(fd, MODULATOR_STATUS, &data);
printf("Modulator status = %u\n", data); printf("Modulator status = %u\n", data);
set_property(fd, MODULATOR_STATUS, 2);
//set_property(fd, MODULATOR_RESET, 0); //set_property(fd, MODULATOR_RESET, 0);

View File

@ -4341,6 +4341,7 @@ static int ddb_init_boards(struct ddb *dev)
int ddb_init(struct ddb *dev) int ddb_init(struct ddb *dev)
{ {
mutex_init(&dev->link[0].flash_mutex); mutex_init(&dev->link[0].flash_mutex);
mutex_init(&dev->ioctl_mutex);
if (no_init) { if (no_init) {
ddb_device_create(dev); ddb_device_create(dev);
return 0; return 0;

View File

@ -437,6 +437,7 @@ static const struct ddb_info ddb_mod_fsm_24 = {
.port_num = 24, .port_num = 24,
.temp_num = 1, .temp_num = 1,
.tempmon_irq = 8, .tempmon_irq = 8,
.lostlock_irq = 9,
}; };
static const struct ddb_info ddb_mod_fsm_16 = { static const struct ddb_info ddb_mod_fsm_16 = {
@ -447,6 +448,7 @@ static const struct ddb_info ddb_mod_fsm_16 = {
.port_num = 16, .port_num = 16,
.temp_num = 1, .temp_num = 1,
.tempmon_irq = 8, .tempmon_irq = 8,
.lostlock_irq = 9,
}; };
static const struct ddb_info ddb_mod_fsm_8 = { static const struct ddb_info ddb_mod_fsm_8 = {
@ -457,6 +459,7 @@ static const struct ddb_info ddb_mod_fsm_8 = {
.port_num = 8, .port_num = 8,
.temp_num = 1, .temp_num = 1,
.tempmon_irq = 8, .tempmon_irq = 8,
.lostlock_irq = 9,
}; };
static const struct ddb_info ddb_mod_fsm_4 = { static const struct ddb_info ddb_mod_fsm_4 = {
@ -467,6 +470,7 @@ static const struct ddb_info ddb_mod_fsm_4 = {
.port_num = 4, .port_num = 4,
.temp_num = 1, .temp_num = 1,
.tempmon_irq = 8, .tempmon_irq = 8,
.lostlock_irq = 9,
}; };
static const struct ddb_info ddb_sdr = { static const struct ddb_info ddb_sdr = {

View File

@ -434,6 +434,16 @@ static u32 max2871_sdr[6] = {
0x007A8098, 0x600080C9, 0x510061C2, 0x010000CB, 0x6199003C, 0x60440005 0x007A8098, 0x600080C9, 0x510061C2, 0x010000CB, 0x6199003C, 0x60440005
}; };
static void lostlock_handler(unsigned long data)
{
struct ddb *dev = (struct ddb *)data;
dev_err(dev->dev, "Lost PLL lock!\n");
ddbwritel(dev, 0, RF_VGA);
udelay(10);
ddbwritel(dev, 31, RF_ATTENUATOR);
}
static int mod_setup_max2871(struct ddb *dev, u32 *reg) static int mod_setup_max2871(struct ddb *dev, u32 *reg)
{ {
int status = 0; int status = 0;
@ -467,6 +477,12 @@ static int mod_setup_max2871(struct ddb *dev, u32 *reg)
ddbwritel(dev, ddbwritel(dev,
MAX2871_CONTROL_CE | MAX2871_CONTROL_LOSTLOCK, MAX2871_CONTROL_CE | MAX2871_CONTROL_LOSTLOCK,
MAX2871_CONTROL); MAX2871_CONTROL);
if (dev->link[0].info->lostlock_irq) {
dev->handler_data[0][dev->link[0].info->lostlock_irq] =
(unsigned long)dev;
dev->handler[0][dev->link[0].info->lostlock_irq] =
lostlock_handler;
}
} }
return status; return status;
} }
@ -1536,6 +1552,17 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
if (mod->port->dev->link[0].info->version == 2) if (mod->port->dev->link[0].info->version == 2)
return mod_fsm_setup(mod->port->dev,0 ); return mod_fsm_setup(mod->port->dev,0 );
return -EINVAL; return -EINVAL;
case MODULATOR_STATUS:
if (mod->port->dev->link[0].info->version != 2)
return -EINVAL;
if (tvp->u.data & 2)
ddbwritel(mod->port->dev,
MAX2871_CONTROL_CE |
MAX2871_CONTROL_LOSTLOCK |
MAX2871_CONTROL_ENABLE_LOSTLOCK_EVENT,
MAX2871_CONTROL);
return 0;
} }
return 0; return 0;
} }
@ -1560,8 +1587,6 @@ static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
u32 status = 0, val; u32 status = 0, val;
val = ddbreadl(dev, MAX2871_CONTROL); val = ddbreadl(dev, MAX2871_CONTROL);
if (!(val & MAX2871_CONTROL_LOCK))
status |= 1;
if (!(val & MAX2871_CONTROL_LOCK)) if (!(val & MAX2871_CONTROL_LOCK))
status |= 1; status |= 1;
if (val & MAX2871_CONTROL_LOSTLOCK) if (val & MAX2871_CONTROL_LOSTLOCK)
@ -1571,6 +1596,9 @@ static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
val = ddbreadl(dev, TEMPMON_CONTROL); val = ddbreadl(dev, TEMPMON_CONTROL);
if (val & TEMPMON_CONTROL_OVERTEMP) if (val & TEMPMON_CONTROL_OVERTEMP)
status |= 4; status |= 4;
val = ddbreadl(dev, HARDWARE_VERSION);
if (val == 0xffffffff)
status |= 8;
tvp->u.data = status; tvp->u.data = status;
return 0; return 0;
} }
@ -1592,13 +1620,18 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
if (dev->link[0].info->version == 3 && cmd != FE_SET_PROPERTY) if (dev->link[0].info->version == 3 && cmd != FE_SET_PROPERTY)
return -EINVAL; return -EINVAL;
mutex_lock(&dev->ioctl_mutex);
switch (cmd) { switch (cmd) {
case FE_SET_PROPERTY: case FE_SET_PROPERTY:
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) {
return -EINVAL; ret = -EINVAL;
break;
}
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp)) if (IS_ERR(tvp)) {
return PTR_ERR(tvp); ret = PTR_ERR(tvp);
break;
}
for (i = 0; i < tvps->num; i++) { for (i = 0; i < tvps->num; i++) {
ret = mod_prop_proc(mod, tvp + i); ret = mod_prop_proc(mod, tvp + i);
if (ret < 0) if (ret < 0)
@ -1606,14 +1639,18 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
(tvp + i)->result = ret; (tvp + i)->result = ret;
} }
kfree(tvp); kfree(tvp);
return ret; break;
case FE_GET_PROPERTY: case FE_GET_PROPERTY:
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) {
return -EINVAL; ret = -EINVAL;
break;
}
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp)) if (IS_ERR(tvp)) {
return PTR_ERR(tvp); ret = PTR_ERR(tvp);
break;
}
for (i = 0; i < tvps->num; i++) { for (i = 0; i < tvps->num; i++) {
ret = mod_prop_get(mod, tvp + i); ret = mod_prop_get(mod, tvp + i);
if (ret < 0) if (ret < 0)
@ -1625,7 +1662,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
tvps->num * sizeof(struct dtv_property))) tvps->num * sizeof(struct dtv_property)))
ret = -EFAULT; ret = -EFAULT;
kfree(tvp); kfree(tvp);
return ret; break;
case DVB_MOD_SET: case DVB_MOD_SET:
{ {
@ -1633,8 +1670,10 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
if (dev->link[0].info->version < 2) { if (dev->link[0].info->version < 2) {
if (mp->base_frequency != dev->mod_base.frequency) if (mp->base_frequency != dev->mod_base.frequency)
if (set_base_frequency(dev, mp->base_frequency)) if (set_base_frequency(dev, mp->base_frequency)) {
return -EINVAL; ret = -EINVAL;
break;
}
} else { } else {
int i, streams = dev->link[0].info->port_num; int i, streams = dev->link[0].info->port_num;
@ -1659,11 +1698,15 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
int res; int res;
res = mod_set_modulation(mod, cp->modulation); res = mod_set_modulation(mod, cp->modulation);
if (res) if (res) {
return res; ret = res;
break;
}
res = mod_set_ibitrate(mod, cp->input_bitrate); res = mod_set_ibitrate(mod, cp->input_bitrate);
if (res) if (res) {
return res; ret = res;
break;
}
mod->pcr_correction = cp->pcr_correction; mod->pcr_correction = cp->pcr_correction;
break; break;
} }
@ -1671,6 +1714,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
mutex_unlock(&dev->ioctl_mutex);
return ret; return ret;
} }
@ -1700,6 +1744,7 @@ static int mod_init_2(struct ddb *dev, u32 Frequency)
else else
mod_set_vga(dev, RF_VGA_GAIN_N24); mod_set_vga(dev, RF_VGA_GAIN_N24);
udelay(10);
mod_set_attenuator(dev, 0); mod_set_attenuator(dev, 0);
return 0; return 0;
} }

View File

@ -172,6 +172,7 @@ struct ddb_info {
#define TS_QUIRK_NO_OUTPUT 4 #define TS_QUIRK_NO_OUTPUT 4
#define TS_QUIRK_ALT_OSC 8 #define TS_QUIRK_ALT_OSC 8
u32 tempmon_irq; u32 tempmon_irq;
u32 lostlock_irq;
const struct ddb_regmap *regmap; const struct ddb_regmap *regmap;
}; };
@ -474,7 +475,7 @@ struct ddb {
struct mod_base mod_base; struct mod_base mod_base;
struct ddb_mod mod[24]; struct ddb_mod mod[24];
struct mutex ioctl_mutex; /* lock extra ioctls */
}; };
/****************************************************************************/ /****************************************************************************/

View File

@ -102,7 +102,7 @@ MODULATOR_STATUS and MODULATOR_RESET have been added to debug
possible problems with too high temperatures (overtemperature) possible problems with too high temperatures (overtemperature)
or PLL lock loss on FSM type cards. or PLL lock loss on FSM type cards.
The MODUALTOR_STATUS property returns a __u32 with the following status bits: The MODULATOR_STATUS property returns a __u32 with the following status bits:
- bit 0 : Lock status 1=lock OK, 0 = lock lost - bit 0 : Lock status 1=lock OK, 0 = lock lost
@ -113,8 +113,18 @@ The MODUALTOR_STATUS property returns a __u32 with the following status bits:
- bit 2 : 0 = no overtemperature - bit 2 : 0 = no overtemperature
1 = overtemperature detected 1 = overtemperature detected
- bit 4 : 0 = PCIe link OK
1 = PCIe link lost
In case of overtemperratur or PCIe link loss you will have to reboot the PC.
Putting a MODULATOR_STATUS property with value 2 will enable the lost lock
interrupt. This will set the gain to 0 and the attenuation to 31 in case
of a lost PLL lock.
The MODULATOR_RESET property can be used to reset the modulator without The MODULATOR_RESET property can be used to reset the modulator without
needing to reload the driver or rebooting. needing to reload the driver or rebooting in case of PLL lock loss.
All channels should be stopped before using it and restarted after using it. All channels should be stopped before using it and restarted after using it.
Otherwise, results are unpredictable. Otherwise, results are unpredictable.