summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/frontends/dst.c207
1 files changed, 158 insertions, 49 deletions
diff --git a/linux/drivers/media/dvb/frontends/dst.c b/linux/drivers/media/dvb/frontends/dst.c
index ae2a68313..5d3a176a3 100644
--- a/linux/drivers/media/dvb/frontends/dst.c
+++ b/linux/drivers/media/dvb/frontends/dst.c
@@ -37,20 +37,31 @@
unsigned int dst_debug = 0;
unsigned int dst_verbose = 0;
+
MODULE_PARM(dst_verbose, "i");
MODULE_PARM_DESC(dst_verbose,
"verbose startup messages, default is 1 (yes)");
MODULE_PARM(dst_debug, "i");
MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");
+unsigned int dst_type = (-1U);
+unsigned int dst_type_flags = (-1U);
+MODULE_PARM(dst_type, "i");
+MODULE_PARM_DESC(dst_type,
+ "Type of DST card, 0 Satellite, 1 terrestial TV, 2 Cable, default driver determined");
+MODULE_PARM(dst_type_flags, "i");
+MODULE_PARM_DESC(dst_type_flags,
+ "Type flags of DST card, bitfield 1=10 byte tuner, 2=TS is 204, 4=symdiv");
+
#define dprintk if (dst_debug) printk
-#define DST_TYPE_HAS_TERR 1
-#define DST_TYPE_HAS_SAT 2
-#define DST_TYPE_HAS_CABLE 4
-#define DST_TYPE_HAS_NEWTUNE 8
-#define DST_TYPE_HAS_TS204 0x10
-#define DST_TYPE_HAS_SYMDIV 0x20
+#define DST_TYPE_IS_SAT 0
+#define DST_TYPE_IS_TERR 1
+#define DST_TYPE_IS_CABLE 2
+
+#define DST_TYPE_HAS_NEWTUNE 1
+#define DST_TYPE_HAS_TS204 2
+#define DST_TYPE_HAS_SYMDIV 4
#define HAS_LOCK 1
#define ATTEMPT_TUNE 2
@@ -61,6 +72,7 @@ struct dst_data {
u8 rx_tuna[10];
u8 rxbuffer[10];
u8 diseq_flags;
+ u8 dst_type;
u32 type_flags;
u32 frequency; /* intermediate frequency in kHz for QPSK */
fe_spectral_inversion_t inversion;
@@ -95,6 +107,21 @@ static struct dvb_frontend_info dst_info_sat = {
FE_CAN_QPSK
};
+static struct dvb_frontend_info dst_info_cable = {
+ .name = "DST CABLE",
+ .type = FE_QAM,
+ .frequency_stepsize = 62500,
+ .frequency_min = 51000000,
+ .frequency_max = 858000000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+/* . symbol_rate_tolerance = ???,*/
+ .notifier_delay = 50, /* 1/20 s */
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_AUTO
+};
+
static struct dvb_frontend_info dst_info_tv = {
.name = "DST TERR",
.type = FE_OFDM,
@@ -298,7 +325,7 @@ static int dst_set_freq(struct dst_data *dst, u32 freq)
dst->frequency = freq;
// dprintk("%s: set frequency %u\n", __FUNCTION__, freq);
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
freq = freq / 1000;
if (freq < 950 || freq > 2150)
return -EINVAL;
@@ -309,7 +336,7 @@ static int dst_set_freq(struct dst_data *dst, u32 freq)
val[8] &= ~4;
if (freq < 1531)
val[8] |= 4;
- } else if (dst->type_flags & DST_TYPE_HAS_TERR) {
+ } else if (dst->dst_type == DST_TYPE_IS_TERR) {
freq = freq / 1000;
if (freq < 137000 || freq > 858000)
return -EINVAL;
@@ -335,14 +362,15 @@ static int dst_set_freq(struct dst_data *dst, u32 freq)
val[7] = 0;
val[8] = 0;
- } else if (dst->type_flags & DST_TYPE_HAS_CABLE) {
+ } else if (dst->dst_type == DST_TYPE_IS_CABLE) {
/* guess till will get one */
freq = freq / 1000;
val = &dst->tx_tuna[0];
val[2] = (freq >> 16) & 0xff;
val[3] = (freq >> 8) & 0xff;
val[4] = (u8)freq;
- }
+ } else
+ return -EINVAL;
return 0;
}
@@ -352,7 +380,7 @@ static int dst_set_bandwidth(struct dst_data *dst, fe_bandwidth_t bandwidth)
dst->bandwidth = bandwidth;
- if (0 == (dst->type_flags & DST_TYPE_HAS_TERR))
+ if (dst->dst_type != DST_TYPE_IS_TERR)
return 0;
val = &dst->tx_tuna[0];
@@ -419,7 +447,7 @@ static int dst_set_symbolrate (struct dst_data *dst, u32 srate)
dst->symbol_rate = srate;
- if (dst->type_flags & DST_TYPE_HAS_TERR) {
+ if (dst->dst_type == DST_TYPE_IS_TERR) {
return 0;
}
@@ -460,26 +488,60 @@ static u8 dst_check_sum(u8 *buf, u32 len)
return ((~val) + 1);
}
-
typedef struct dst_types {
char *mstr;
int offs;
+ u8 dst_type;
u32 type_flags;
} DST_TYPES;
struct dst_types dst_tlist[] = {
- { "DST-020", 0, DST_TYPE_HAS_SAT|DST_TYPE_HAS_SYMDIV },
- { "DST-030", 0, DST_TYPE_HAS_SAT|DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
- { "DST-03T", 0, DST_TYPE_HAS_SAT|DST_TYPE_HAS_SYMDIV},
- { "DST-M0T", 0, DST_TYPE_HAS_SAT|DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
- { "DST-CI", 1, DST_TYPE_HAS_SAT|DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
- { "DSTMCI", 1, DST_TYPE_HAS_SAT|DST_TYPE_HAS_NEWTUNE },
- { "DSTFCI", 1, DST_TYPE_HAS_SAT|DST_TYPE_HAS_NEWTUNE },
- { "DCTNEW", 1, DST_TYPE_HAS_CABLE|DST_TYPE_HAS_NEWTUNE },
- { "DCT_CI", 1, DST_TYPE_HAS_CABLE|DST_TYPE_HAS_NEWTUNE|DST_TYPE_HAS_TS204 },
- { "DTTDIG" , 1, DST_TYPE_HAS_TERR} };
+ { "DST-020", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV },
+ { "DST-030", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
+ { "DST-03T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV|DST_TYPE_HAS_TS204},
+ { "DST-M0T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
+ { "DST-CI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
+ { "DSTMCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE },
+ { "DSTFCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE },
+ { "DCTNEW", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE },
+ { "DCT_CI", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE|DST_TYPE_HAS_TS204 },
+ { "DTTDIG" , 1, DST_TYPE_IS_TERR, 0} };
/* DCTNEW and DCT-CI are guesses */
+static void dst_type_flags_print(u32 type_flags)
+{
+ printk("DST type flags :");
+ if (type_flags & DST_TYPE_HAS_NEWTUNE)
+ printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+ if (type_flags & DST_TYPE_HAS_TS204)
+ printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
+ if (type_flags & DST_TYPE_HAS_SYMDIV)
+ printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+ printk("\n");
+}
+
+static int dst_type_print(u8 type)
+{
+ char *otype;
+ switch (type) {
+ case DST_TYPE_IS_SAT:
+ otype = "satellite";
+ break;
+ case DST_TYPE_IS_TERR:
+ otype = "terrestial TV";
+ break;
+ case DST_TYPE_IS_CABLE:
+ otype = "terrestial TV";
+ break;
+ default:
+ printk("%s: invalid dst type %d\n",
+ __FUNCTION__, type);
+ return -EINVAL;
+ }
+ printk("DST type : %s\n", otype);
+ return 0;
+}
+
static int dst_check_ci (struct dst_data *dst)
{
u8 txbuf[8];
@@ -487,6 +549,8 @@ static int dst_check_ci (struct dst_data *dst)
int retval;
int i;
struct dst_types *dsp;
+ u8 use_dst_type;
+ u32 use_type_flags;
memset(txbuf, 0, sizeof(txbuf));
txbuf[1] = 6;
@@ -529,16 +593,42 @@ static int dst_check_ci (struct dst_data *dst)
if (!strncmp(&rxbuf[dsp->offs],
dsp->mstr,
strlen(dsp->mstr))) {
- dst->type_flags = dsp->type_flags;
+ use_type_flags = dsp->type_flags;
+ use_dst_type = dsp->dst_type;
printk("%s: recognize %s\n", __FUNCTION__, dsp->mstr);
break;
}
}
if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) {
- printk("%s: unable to recognize %s or %s, guessing CI satellite\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]);
- printk("%s please email dvb-kernel@linuxtv.org with this type info\n", __FUNCTION__);
- dst->type_flags = DST_TYPE_HAS_SAT|DST_TYPE_HAS_SYMDIV;
+ printk("%s: unable to recognize %s or %s\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]);
+ printk("%s please email dvb-kernel@linuxtv.org with this type in\n", __FUNCTION__);
+ use_dst_type = DST_TYPE_IS_SAT;
+ use_type_flags = DST_TYPE_HAS_SYMDIV;
}
+ switch (dst_type) {
+ case (-1U):
+ /* not used */
+ break;
+ case DST_TYPE_IS_SAT:
+ case DST_TYPE_IS_TERR:
+ case DST_TYPE_IS_CABLE:
+ use_dst_type = (u8)dst_type;
+ break;
+ default:
+ printk("%s: invalid user override dst type %d, not used\n",
+ __FUNCTION__, dst_type);
+ break;
+ }
+ dst_type_print(use_dst_type);
+ if (dst_type_flags != (-1U)) {
+ printk("%s: user override dst type flags 0x%x\n",
+ __FUNCTION__, dst_type_flags);
+ use_type_flags = dst_type_flags;
+ }
+ dst->type_flags = use_type_flags;
+ dst->dst_type= use_dst_type;
+ dst_type_flags_print(dst->type_flags);
+
if (dst->type_flags & DST_TYPE_HAS_TS204) {
dst_packsize(dst, 204);
}
@@ -604,14 +694,14 @@ static int dst_get_signal(struct dst_data *dst)
retval = dst_command(dst, get_signal, 8);
if (retval < 0)
return retval;
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
dst->decode_lock = ((dst->rxbuffer[6] & 0x10) == 0) ?
1 : 0;
dst->decode_strength = dst->rxbuffer[5] << 8;
dst->decode_snr = dst->rxbuffer[2] << 8 |
dst->rxbuffer[3];
- } else if (dst->type_flags &
- (DST_TYPE_HAS_TERR|DST_TYPE_HAS_CABLE)) {
+ } else if ((dst->dst_type == DST_TYPE_IS_TERR) ||
+ (dst->dst_type == DST_TYPE_IS_CABLE)) {
dst->decode_lock = (dst->rxbuffer[2]) ?
1 : 0;
dst->decode_strength = dst->rxbuffer[6] << 8;
@@ -640,7 +730,7 @@ static int dst_set_diseqc (struct dst_data *dst, u8 *cmd, u8 len)
{
u8 paket[8] = {0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
- if (dst->type_flags & DST_TYPE_HAS_TERR)
+ if (dst->dst_type == DST_TYPE_IS_TERR)
return 0;
if (len == 0 || len > 4)
@@ -655,7 +745,7 @@ static int dst_tone_power_cmd (struct dst_data *dst)
{
u8 paket[8] = {0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00};
- if (dst->type_flags & DST_TYPE_HAS_TERR)
+ if (dst->dst_type == DST_TYPE_IS_TERR)
return 0;
if (dst->voltage == SEC_VOLTAGE_OFF)
@@ -678,7 +768,7 @@ static int dst_set_voltage (struct dst_data *dst, fe_sec_voltage_t voltage)
dst->voltage = voltage;
- if (dst->type_flags & DST_TYPE_HAS_TERR)
+ if (dst->dst_type == DST_TYPE_IS_TERR)
return 0;
need_cmd = 0;
@@ -716,7 +806,7 @@ static int dst_set_tone (struct dst_data *dst, fe_sec_tone_mode_t tone)
dst->tone = tone;
- if (dst->type_flags & DST_TYPE_HAS_TERR)
+ if (dst->dst_type == DST_TYPE_IS_TERR)
return 0;
val = &dst->tx_tuna[0];
@@ -790,7 +880,7 @@ static int dst_write_tuna (struct dst_data *dst)
dprintk("%s: type_flags 0x%x \n", __FUNCTION__, dst->type_flags);
dst->decode_freq = 0;
dst->decode_lock = dst->decode_strength = dst->decode_snr = 0;
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
if (!(dst->diseq_flags & HAS_POWER))
dst_set_voltage (dst, SEC_VOLTAGE_13);
}
@@ -830,6 +920,8 @@ static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
+static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
+static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
dst->inversion = INVERSION_ON;
dst->voltage = SEC_VOLTAGE_13;
dst->tone = SEC_TONE_OFF;
@@ -839,16 +931,21 @@ static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
dst->k22 = 0x02;
dst->bandwidth = BANDWIDTH_7_MHZ;
dst->cur_jiff = jiffies;
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
dst->frequency = 950000;
memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE )?
ini_satci_tuna : ini_satfta_tuna),
sizeof(ini_satfta_tuna));
- } else if (dst->type_flags & DST_TYPE_HAS_TERR) {
+ } else if (dst->dst_type == DST_TYPE_IS_TERR) {
dst->frequency = 137000000;
memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE )?
ini_tvci_tuna : ini_tvfta_tuna),
sizeof(ini_tvfta_tuna));
+ } else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+ dst->frequency = 51000000;
+ memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE )?
+ ini_cabci_tuna : ini_cabfta_tuna),
+ sizeof(ini_cabfta_tuna));
}
}
@@ -891,13 +988,17 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
/* should be set by attach, but just in case */
dst->i2c = fe->i2c;
switch (cmd) {
- case FE_GET_INFO:
- memcpy (arg,
- ((dst->type_flags & DST_TYPE_HAS_TERR) ?
- &dst_info_tv : &dst_info_sat),
- sizeof(struct dvb_frontend_info));
+ case FE_GET_INFO:
+ {
+ struct dvb_frontend_info *info;
+ info = &dst_info_sat;
+ if (dst->dst_type == DST_TYPE_IS_TERR)
+ info = &dst_info_tv;
+ else if (dst->dst_type == DST_TYPE_IS_CABLE)
+ info = &dst_info_cable;
+ memcpy (arg, info, sizeof(struct dvb_frontend_info));
break;
-
+ }
case FE_READ_STATUS:
{
fe_status_t *status = arg;
@@ -949,12 +1050,14 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
dst_set_freq (dst, p->frequency);
dst_set_inversion (dst, p->inversion);
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
dst_set_fec (dst, p->u.qpsk.fec_inner);
dst_set_symbolrate (dst, p->u.qpsk.symbol_rate);
- } else
- if (dst->type_flags & DST_TYPE_HAS_TERR) {
+ } else if (dst->dst_type == DST_TYPE_IS_TERR) {
dst_set_bandwidth(dst, p->u.ofdm.bandwidth);
+ } else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+ dst_set_fec (dst, p->u.qam.fec_inner);
+ dst_set_symbolrate (dst, p->u.qam.symbol_rate);
}
dst_write_tuna (dst);
@@ -968,11 +1071,15 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
p->frequency = dst->decode_freq;
p->inversion = dst->inversion;
- if (dst->type_flags & DST_TYPE_HAS_SAT) {
+ if (dst->dst_type == DST_TYPE_IS_SAT) {
p->u.qpsk.symbol_rate = dst->symbol_rate;
p->u.qpsk.fec_inner = dst_get_fec (dst);
- } else if (dst->type_flags & DST_TYPE_HAS_TERR) {
+ } else if (dst->dst_type == DST_TYPE_IS_TERR) {
p->u.ofdm.bandwidth = dst->bandwidth;
+ } else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+ p->u.qam.symbol_rate = dst->symbol_rate;
+ p->u.qam.fec_inner = dst_get_fec (dst);
+ p->u.qam.modulation = QAM_AUTO;
}
break;
}
@@ -1042,8 +1149,10 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
(u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
info = &dst_info_sat;
- if (dst->type_flags & DST_TYPE_HAS_TERR)
+ if (dst->dst_type == DST_TYPE_IS_TERR)
info = &dst_info_tv;
+ else if (dst->dst_type == DST_TYPE_IS_CABLE)
+ info = &dst_info_cable;
dvb_register_frontend (dst_ioctl, i2c, dst, info);