[PATCH] dvb: let other frontends support FE_DISHNETWORK_SEND_LEGACY_CMD
Add support to FE_DISHNETWORK_SEND_LEGACY_CMD code to support other frontends besides stv0299. The generic code is a fallback in the case that it doesn't work for some specific frontends (again stv0299 being a good example). Signed-off-by: NooneImportant <nxhxzi702@sneakemail.com> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Cc: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
b90ed914e5
commit
83b75b049b
@ -577,6 +577,49 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
|||||||
fepriv->thread_pid);
|
fepriv->thread_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
|
||||||
|
{
|
||||||
|
return ((curtime.tv_usec < lasttime.tv_usec) ?
|
||||||
|
1000000 - lasttime.tv_usec + curtime.tv_usec :
|
||||||
|
curtime.tv_usec - lasttime.tv_usec);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(timeval_usec_diff);
|
||||||
|
|
||||||
|
static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
|
||||||
|
{
|
||||||
|
curtime->tv_usec += add_usec;
|
||||||
|
if (curtime->tv_usec >= 1000000) {
|
||||||
|
curtime->tv_usec -= 1000000;
|
||||||
|
curtime->tv_sec++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleep until gettimeofday() > waketime + add_usec
|
||||||
|
* This needs to be as precise as possible, but as the delay is
|
||||||
|
* usually between 2ms and 32ms, it is done using a scheduled msleep
|
||||||
|
* followed by usleep (normally a busy-wait loop) for the remainder
|
||||||
|
*/
|
||||||
|
void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
|
||||||
|
{
|
||||||
|
struct timeval lasttime;
|
||||||
|
s32 delta, newdelta;
|
||||||
|
|
||||||
|
timeval_usec_add(waketime, add_usec);
|
||||||
|
|
||||||
|
do_gettimeofday(&lasttime);
|
||||||
|
delta = timeval_usec_diff(lasttime, *waketime);
|
||||||
|
if (delta > 2500) {
|
||||||
|
msleep((delta - 1500) / 1000);
|
||||||
|
do_gettimeofday(&lasttime);
|
||||||
|
newdelta = timeval_usec_diff(lasttime, *waketime);
|
||||||
|
delta = (newdelta > delta) ? 0 : newdelta;
|
||||||
|
}
|
||||||
|
if (delta > 0)
|
||||||
|
udelay(delta);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_frontend_sleep_until);
|
||||||
|
|
||||||
static int dvb_frontend_start(struct dvb_frontend *fe)
|
static int dvb_frontend_start(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -728,6 +771,60 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||||||
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
|
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
|
||||||
fepriv->state = FESTATE_DISEQC;
|
fepriv->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
|
} else if (fe->ops->set_voltage) {
|
||||||
|
/*
|
||||||
|
* NOTE: This is a fallback condition. Some frontends
|
||||||
|
* (stv0299 for instance) take longer than 8msec to
|
||||||
|
* respond to a set_voltage command. Those switches
|
||||||
|
* need custom routines to switch properly. For all
|
||||||
|
* other frontends, the following shoule work ok.
|
||||||
|
* Dish network legacy switches (as used by Dish500)
|
||||||
|
* are controlled by sending 9-bit command words
|
||||||
|
* spaced 8msec apart.
|
||||||
|
* the actual command word is switch/port dependant
|
||||||
|
* so it is up to the userspace application to send
|
||||||
|
* the right command.
|
||||||
|
* The command must always start with a '0' after
|
||||||
|
* initialization, so parg is 8 bits and does not
|
||||||
|
* include the initialization or start bit
|
||||||
|
*/
|
||||||
|
unsigned int cmd = ((unsigned int) parg) << 1;
|
||||||
|
struct timeval nexttime;
|
||||||
|
struct timeval tv[10];
|
||||||
|
int i;
|
||||||
|
u8 last = 1;
|
||||||
|
if (dvb_frontend_debug)
|
||||||
|
printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
|
||||||
|
do_gettimeofday(&nexttime);
|
||||||
|
if (dvb_frontend_debug)
|
||||||
|
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
|
||||||
|
/* before sending a command, initialize by sending
|
||||||
|
* a 32ms 18V to the switch
|
||||||
|
*/
|
||||||
|
fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
|
||||||
|
dvb_frontend_sleep_until(&nexttime, 32000);
|
||||||
|
|
||||||
|
for (i = 0; i < 9; i++) {
|
||||||
|
if (dvb_frontend_debug)
|
||||||
|
do_gettimeofday(&tv[i + 1]);
|
||||||
|
if ((cmd & 0x01) != last) {
|
||||||
|
/* set voltage to (last ? 13V : 18V) */
|
||||||
|
fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
|
||||||
|
last = (last) ? 0 : 1;
|
||||||
|
}
|
||||||
|
cmd = cmd >> 1;
|
||||||
|
if (i != 8)
|
||||||
|
dvb_frontend_sleep_until(&nexttime, 8000);
|
||||||
|
}
|
||||||
|
if (dvb_frontend_debug) {
|
||||||
|
printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
|
||||||
|
__FUNCTION__, fe->dvb->num);
|
||||||
|
for (i = 1; i < 10; i++)
|
||||||
|
printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
|
||||||
|
}
|
||||||
|
err = 0;
|
||||||
|
fepriv->state = FESTATE_DISEQC;
|
||||||
|
fepriv->status = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -101,4 +101,7 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||||||
|
|
||||||
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
|
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
|
||||||
|
|
||||||
|
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
|
||||||
|
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -387,36 +387,6 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime)
|
|
||||||
{
|
|
||||||
return ((curtime.tv_usec < lasttime.tv_usec) ?
|
|
||||||
1000000 - lasttime.tv_usec + curtime.tv_usec :
|
|
||||||
curtime.tv_usec - lasttime.tv_usec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec)
|
|
||||||
{
|
|
||||||
struct timeval lasttime;
|
|
||||||
s32 delta, newdelta;
|
|
||||||
|
|
||||||
waketime->tv_usec += add_usec;
|
|
||||||
if (waketime->tv_usec >= 1000000) {
|
|
||||||
waketime->tv_usec -= 1000000;
|
|
||||||
waketime->tv_sec++;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_gettimeofday (&lasttime);
|
|
||||||
delta = stv0299_calc_usec_delay (lasttime, *waketime);
|
|
||||||
if (delta > 2500) {
|
|
||||||
msleep ((delta - 1500) / 1000);
|
|
||||||
do_gettimeofday (&lasttime);
|
|
||||||
newdelta = stv0299_calc_usec_delay (lasttime, *waketime);
|
|
||||||
delta = (newdelta > delta) ? 0 : newdelta;
|
|
||||||
}
|
|
||||||
if (delta > 0)
|
|
||||||
udelay (delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
|
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
|
||||||
{
|
{
|
||||||
struct stv0299_state* state = fe->demodulator_priv;
|
struct stv0299_state* state = fe->demodulator_priv;
|
||||||
@ -444,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
|
|||||||
memcpy (&tv[0], &nexttime, sizeof (struct timeval));
|
memcpy (&tv[0], &nexttime, sizeof (struct timeval));
|
||||||
stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
|
stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
|
||||||
|
|
||||||
stv0299_sleep_until (&nexttime, 32000);
|
dvb_frontend_sleep_until(&nexttime, 32000);
|
||||||
|
|
||||||
for (i=0; i<9; i++) {
|
for (i=0; i<9; i++) {
|
||||||
if (debug_legacy_dish_switch)
|
if (debug_legacy_dish_switch)
|
||||||
@ -458,13 +428,13 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
|
|||||||
cmd = cmd >> 1;
|
cmd = cmd >> 1;
|
||||||
|
|
||||||
if (i != 8)
|
if (i != 8)
|
||||||
stv0299_sleep_until (&nexttime, 8000);
|
dvb_frontend_sleep_until(&nexttime, 8000);
|
||||||
}
|
}
|
||||||
if (debug_legacy_dish_switch) {
|
if (debug_legacy_dish_switch) {
|
||||||
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
|
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
|
||||||
__FUNCTION__, fe->dvb->num);
|
__FUNCTION__, fe->dvb->num);
|
||||||
for (i=1; i < 10; i++)
|
for (i = 1; i < 10; i++)
|
||||||
printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i]));
|
printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user