|
@@ -196,17 +196,15 @@ static void recover_arm(struct av7110 *av7110)
|
|
|
|
|
|
av7110_bootarm(av7110);
|
|
|
msleep(100);
|
|
|
- restart_feeds(av7110);
|
|
|
- av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
|
|
|
-}
|
|
|
|
|
|
-static void arm_error(struct av7110 *av7110)
|
|
|
-{
|
|
|
- dprintk(4, "%p\n",av7110);
|
|
|
+ init_av7110_av(av7110);
|
|
|
+
|
|
|
+ /* card-specific recovery */
|
|
|
+ if (av7110->recover)
|
|
|
+ av7110->recover(av7110);
|
|
|
|
|
|
- av7110->arm_errors++;
|
|
|
- av7110->arm_ready = 0;
|
|
|
- recover_arm(av7110);
|
|
|
+ restart_feeds(av7110);
|
|
|
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
|
|
|
}
|
|
|
|
|
|
static void av7110_arm_sync(struct av7110 *av7110)
|
|
@@ -246,26 +244,22 @@ static int arm_thread(void *data)
|
|
|
|
|
|
if (down_interruptible(&av7110->dcomlock))
|
|
|
break;
|
|
|
-
|
|
|
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
|
|
|
up(&av7110->dcomlock);
|
|
|
|
|
|
- if (newloops == av7110->arm_loops) {
|
|
|
+ if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
|
|
|
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
|
|
|
av7110->dvb_adapter.num);
|
|
|
|
|
|
- arm_error(av7110);
|
|
|
- av7710_set_video_mode(av7110, vidmode);
|
|
|
-
|
|
|
- init_av7110_av(av7110);
|
|
|
+ recover_arm(av7110);
|
|
|
|
|
|
if (down_interruptible(&av7110->dcomlock))
|
|
|
break;
|
|
|
-
|
|
|
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
|
|
|
up(&av7110->dcomlock);
|
|
|
}
|
|
|
av7110->arm_loops = newloops;
|
|
|
+ av7110->arm_errors = 0;
|
|
|
}
|
|
|
|
|
|
av7110->arm_thread = NULL;
|
|
@@ -516,10 +510,6 @@ static void gpioirq(unsigned long data)
|
|
|
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
|
|
|
|
|
|
av7110->video_size.h = h_ar & 0xfff;
|
|
|
- dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
|
|
|
- av7110->video_size.w,
|
|
|
- av7110->video_size.h,
|
|
|
- av7110->video_size.aspect_ratio);
|
|
|
|
|
|
event.type = VIDEO_EVENT_SIZE_CHANGED;
|
|
|
event.u.size.w = av7110->video_size.w;
|
|
@@ -541,6 +531,11 @@ static void gpioirq(unsigned long data)
|
|
|
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
|
|
|
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
|
|
|
}
|
|
|
+
|
|
|
+ dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
|
|
|
+ av7110->video_size.w, av7110->video_size.h,
|
|
|
+ av7110->video_size.aspect_ratio);
|
|
|
+
|
|
|
dvb_video_add_event(av7110, &event);
|
|
|
break;
|
|
|
}
|
|
@@ -1054,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
|
|
|
struct dvb_demux *dvbdmx = &av7110->demux;
|
|
|
struct dvb_demux_feed *feed;
|
|
|
int mode;
|
|
|
- int i;
|
|
|
+ int i, j;
|
|
|
|
|
|
dprintk(4, "%p\n", av7110);
|
|
|
|
|
@@ -1062,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
|
|
|
av7110->playing = 0;
|
|
|
av7110->rec_mode = 0;
|
|
|
|
|
|
- for (i = 0; i < dvbdmx->filternum; i++) {
|
|
|
+ for (i = 0; i < dvbdmx->feednum; i++) {
|
|
|
feed = &dvbdmx->feed[i];
|
|
|
- if (feed->state == DMX_STATE_GO)
|
|
|
+ if (feed->state == DMX_STATE_GO) {
|
|
|
+ if (feed->type == DMX_TYPE_SEC) {
|
|
|
+ for (j = 0; j < dvbdmx->filternum; j++) {
|
|
|
+ if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
|
|
|
+ continue;
|
|
|
+ if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
|
|
|
+ continue;
|
|
|
+ if (dvbdmx->filter[j].state == DMX_STATE_GO)
|
|
|
+ dvbdmx->filter[j].state = DMX_STATE_READY;
|
|
|
+ }
|
|
|
+ }
|
|
|
av7110_start_feed(feed);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (mode)
|
|
@@ -2121,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
|
|
|
struct av7110* av7110 = fe->dvb->priv;
|
|
|
|
|
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
|
|
- if (!ret)
|
|
|
+ if (!ret) {
|
|
|
+ av7110->saved_fe_params = *params;
|
|
|
ret = av7110->fe_set_frontend(fe, params);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2164,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
|
|
|
struct av7110* av7110 = fe->dvb->priv;
|
|
|
|
|
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
|
|
- if (!ret)
|
|
|
+ if (!ret) {
|
|
|
+ av7110->saved_master_cmd = *cmd;
|
|
|
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2174,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
|
|
|
struct av7110* av7110 = fe->dvb->priv;
|
|
|
|
|
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
|
|
- if (!ret)
|
|
|
+ if (!ret) {
|
|
|
+ av7110->saved_minicmd = minicmd;
|
|
|
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2184,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
|
|
struct av7110* av7110 = fe->dvb->priv;
|
|
|
|
|
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
|
|
- if (!ret)
|
|
|
+ if (!ret) {
|
|
|
+ av7110->saved_tone = tone;
|
|
|
ret = av7110->fe_set_tone(fe, tone);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2194,8 +2208,10 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
|
|
|
struct av7110* av7110 = fe->dvb->priv;
|
|
|
|
|
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
|
|
- if (!ret)
|
|
|
+ if (!ret) {
|
|
|
+ av7110->saved_voltage = voltage;
|
|
|
ret = av7110->fe_set_voltage(fe, voltage);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2209,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void dvb_s_recover(struct av7110* av7110)
|
|
|
+{
|
|
|
+ av7110_fe_init(av7110->fe);
|
|
|
+
|
|
|
+ av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
|
|
|
+ if (av7110->saved_master_cmd.msg_len) {
|
|
|
+ msleep(20);
|
|
|
+ av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
|
|
|
+ }
|
|
|
+ msleep(20);
|
|
|
+ av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
|
|
|
+ msleep(20);
|
|
|
+ av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
|
|
|
+
|
|
|
+ av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
|
|
|
+}
|
|
|
+
|
|
|
static u8 read_pwm(struct av7110* av7110)
|
|
|
{
|
|
|
u8 b = 0xff;
|
|
@@ -2246,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
|
|
|
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
|
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
|
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
|
|
+ av7110->recover = dvb_s_recover;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2255,6 +2289,7 @@ static int frontend_init(struct av7110 *av7110)
|
|
|
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
|
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
|
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
|
|
+ av7110->recover = dvb_s_recover;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2264,6 +2299,7 @@ static int frontend_init(struct av7110 *av7110)
|
|
|
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
|
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
|
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
|
|
+ av7110->recover = dvb_s_recover;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2300,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
|
|
|
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
|
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
|
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
|
|
+ av7110->recover = dvb_s_recover;
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -2328,6 +2365,7 @@ static int frontend_init(struct av7110 *av7110)
|
|
|
if (av7110->fe) {
|
|
|
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
|
|
|
av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
|
|
|
+ av7110->recover = dvb_s_recover;
|
|
|
}
|
|
|
break;
|
|
|
}
|