From: Michael Krufky <mkrufky@m1k.net>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org, linux-dvb-maintainer@linuxtv.org
Subject: [PATCH 18/37] dvb: let other frontends support FE_DISHNETWORK_SEND_LEGACY_CMD
Date: Tue, 01 Nov 2005 03:14:19 -0500 [thread overview]
Message-ID: <436723DB.2000300@m1k.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 2 bytes --]
[-- Attachment #2: 2382.patch --]
[-- Type: text/x-patch, Size: 6657 bytes --]
From: NooneImportant <nxhxzi702@sneakemail.com>
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>
drivers/media/dvb/dvb-core/dvb_frontend.c | 97 ++++++++++++++++++++++++++++++
drivers/media/dvb/dvb-core/dvb_frontend.h | 3
drivers/media/dvb/frontends/stv0299.c | 38 +----------
3 files changed, 104 insertions(+), 34 deletions(-)
--- linux-2.6.14-git3.orig/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ linux-2.6.14-git3/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -577,6 +577,49 @@
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)
{
int ret;
@@ -728,6 +771,60 @@
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
fepriv->state = FESTATE_DISEQC;
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;
--- linux-2.6.14-git3.orig/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ linux-2.6.14-git3/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -101,4 +101,7 @@
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
--- linux-2.6.14-git3.orig/drivers/media/dvb/frontends/stv0299.c
+++ linux-2.6.14-git3/drivers/media/dvb/frontends/stv0299.c
@@ -387,36 +387,6 @@
};
}
-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)
{
struct stv0299_state* state = fe->demodulator_priv;
@@ -444,7 +414,7 @@
memcpy (&tv[0], &nexttime, sizeof (struct timeval));
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++) {
if (debug_legacy_dish_switch)
@@ -458,13 +428,13 @@
cmd = cmd >> 1;
if (i != 8)
- stv0299_sleep_until (&nexttime, 8000);
+ dvb_frontend_sleep_until(&nexttime, 8000);
}
if (debug_legacy_dish_switch) {
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, stv0299_calc_usec_delay (tv[i-1] , tv[i]));
+ for (i = 1; i < 10; i++)
+ printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
}
return 0;
next reply other threads:[~2005-11-01 8:22 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-01 8:14 Michael Krufky [this message]
2005-11-03 2:52 ` [PATCH 18/37] dvb: let other frontends support FE_DISHNETWORK_SEND_LEGACY_CMD Andrew Morton
2005-11-03 4:17 ` NooneImportant
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=436723DB.2000300@m1k.net \
--to=mkrufky@m1k.net \
--cc=akpm@osdl.org \
--cc=linux-dvb-maintainer@linuxtv.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.