adapt to latest MCI interface changes

This commit is contained in:
Ralph Metzler 2018-01-01 21:01:49 +01:00
parent c5b45cdbac
commit 4ebb3ca938
2 changed files with 187 additions and 39 deletions

View File

@ -47,6 +47,7 @@ struct mci_base {
u8 assigned_demod[8];
u32 used_ldpc_bitrate[8];
u8 demod_in_use[8];
u32 iq_mode;
};
struct mci {
@ -58,6 +59,8 @@ struct mci {
int first_time_lock;
int started;
struct mci_result signal_info;
u32 bb_mode;
};
@ -87,6 +90,17 @@ static int mci_reset(struct mci *state)
return 0;
}
static int mci_config(struct mci *state, u32 config)
{
struct ddb_link *link = state->base->link;
if (link->ids.device != 0x0009)
return -EINVAL;
ddblwritel(link, config, SX8_TSCONFIG);
return 0;
}
static int _mci_cmd_unlocked(struct mci *state,
u32 *cmd, u32 cmd_len,
u32 *res, u32 res_len)
@ -217,7 +231,7 @@ static int get_info(struct dvb_frontend *fe)
struct mci *state = fe->demodulator_priv;
struct mci_command cmd;
cmd.command = SX8_CMD_GETSIGNALINFO;
cmd.command = MCI_CMD_GETSIGNALINFO;
cmd.demod = state->demod;
stat = mci_cmd(state, &cmd, &state->signal_info);
return stat;
@ -231,7 +245,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
u32 val;
struct mci_result *res = (struct mci_result *)&val;
cmd.command = SX8_CMD_GETSTATUS;
cmd.command = MCI_CMD_GETSTATUS;
cmd.demod = state->demod;
stat = _mci_cmd(state, &cmd, 1, res, 1);
if (stat)
@ -250,7 +264,7 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
memset(&cmd, 0, sizeof(cmd));
cmd.tuner = state->tuner;
cmd.command = on ? SX8_CMD_TUNER_ENABLE : SX8_CMD_TUNER_DISABLE;
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
return mci_cmd(state, &cmd, NULL);
}
@ -260,11 +274,18 @@ static int stop(struct dvb_frontend *fe)
struct mci_command cmd;
u32 input = state->tuner;
memset(&cmd, 0, sizeof(cmd));
if (state->demod != 0xff) {
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_STOP;
cmd.demod = state->demod;
cmd.command = SX8_CMD_STOP;
mci_cmd(state, &cmd, NULL);
if (state->base->iq_mode) {
cmd.command = MCI_CMD_STOP;
cmd.demod = state->demod;
cmd.output = 0;
mci_cmd(state, &cmd, NULL);
mci_config(state, SX8_TSCONFIG_MODE_NORMAL);
}
}
mutex_lock(&state->base->tuner_lock);
state->base->tuner_use_count[input]--;
@ -274,26 +295,52 @@ static int stop(struct dvb_frontend *fe)
state->base->used_ldpc_bitrate[state->nr] = 0;
state->demod = 0xff;
state->base->assigned_demod[state->nr] = 0xff;
state->base->iq_mode = 0;
mutex_unlock(&state->base->tuner_lock);
state->started = 0;
return 0;
}
static int start(struct dvb_frontend *fe)
static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
{
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6);
u32 used_ldpc_bitrate = 0, free_ldpc_bitrate;
u32 used_demods = 0;
struct mci_command cmd;
u32 input = state->tuner;
u32 bits_per_symbol = 3;
u32 bits_per_symbol = 0;
int i, stat = 0;
if (p->symbol_rate >= MCLK / 2)
flags &= ~1;
if ((flags & 3) == 0)
return -EINVAL;
if (flags & 2) {
u32 tmp = modmask;
bits_per_symbol = 1;
while (tmp & 1) {
tmp >>= 1;
bits_per_symbol++;
}
}
mutex_lock(&state->base->tuner_lock);
for (i = 0; i < 8; i++)
if (state->base->iq_mode) {
stat = -EBUSY;
goto unlock;
}
for (i = 0; i < 8; i++) {
used_ldpc_bitrate += state->base->used_ldpc_bitrate[i];
if (used_ldpc_bitrate >= MAX_LDPC_BITRATE) {
if (state->base->demod_in_use[i])
used_demods++;
}
if ((used_ldpc_bitrate >= MAX_LDPC_BITRATE) ||
((ts_config & SX8_TSCONFIG_MODE_MASK) >
SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) {
stat = -EBUSY;
goto unlock;
}
@ -301,10 +348,9 @@ static int start(struct dvb_frontend *fe)
if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE)
free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE;
while (p->symbol_rate * bits_per_symbol > MAX_DEMOD_LDPC_BITRATE)
while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate)
bits_per_symbol--;
if (bits_per_symbol < 2) {
if (bits_per_symbol < 2) {
stat = -EBUSY;
goto unlock;
}
@ -322,28 +368,84 @@ static int start(struct dvb_frontend *fe)
if (!state->base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
state->base->tuner_use_count[input]++;
state->base->iq_mode = (ts_config > 1);
unlock:
mutex_unlock(&state->base->tuner_lock);
if (stat)
return stat;
memset(&cmd, 0, sizeof(cmd));
if (state->base->iq_mode) {
cmd.command = SX8_CMD_SELECT_IQOUT;
cmd.demod = state->demod;
cmd.output = 0;
mci_cmd(state, &cmd, NULL);
mci_config(state, ts_config);
}
printk("frontend %u: tuner=%u demod=%u\n", state->nr, state->tuner, state->demod);
cmd.command = SX8_CMD_SEARCH;
cmd.dvbs2_search.flags = 3; /* S1 + S2 */
#if 1
/* Enable all Modcods up to bits_per_symbol */
cmd.dvbs2_search.s2_modulation_mask = (1 << (bits_per_symbol - 1)) - 1;
#else
/* Enable Modcods matching bits_per_symbol */
cmd.dvbs2_search.s2_modulation_mask = (1 << (bits_per_symbol - 2));
#endif
cmd.command = MCI_CMD_SEARCH_DVBS;
cmd.dvbs2_search.flags = flags;
cmd.dvbs2_search.s2_modulation_mask = modmask & ((1 << (bits_per_symbol - 1)) - 1);
cmd.dvbs2_search.retry = 255; /* forever */
cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
cmd.dvbs2_search.scrambling_sequence_index =
(p->pls != NO_SCRAMBLING_CODE) ? p->pls : 0;
cmd.dvbs2_search.input_stream_id =
(p->stream_id != NO_STREAM_ID_FILTER) ? p->stream_id : 0;
cmd.tuner = state->tuner;
cmd.demod = state->demod;
cmd.output = state->nr;
stat = mci_cmd(state, &cmd, NULL);
if (stat)
stop(fe);
return stat;
}
static int start_iq(struct dvb_frontend *fe, u32 ts_config)
{
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6);
u32 used_ldpc_bitrate = 0, free_ldpc_bitrate;
u32 used_demods = 0;
struct mci_command cmd;
u32 input = state->tuner;
int i, stat = 0;
mutex_lock(&state->base->tuner_lock);
if (state->base->iq_mode) {
stat = -EBUSY;
goto unlock;
}
for (i = 0; i < 8; i++)
if (state->base->demod_in_use[i])
used_demods++;
if (used_demods > 0) {
stat = -EBUSY;
goto unlock;
}
state->demod = state->base->assigned_demod[state->nr] = 0;
if (!state->base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
state->base->tuner_use_count[input]++;
state->base->iq_mode = (ts_config > 1);
unlock:
mutex_unlock(&state->base->tuner_lock);
if (stat)
return stat;
cmd.command = SX8_CMD_START_IQ;
cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
cmd.tuner = state->tuner;
cmd.demod = state->demod;
cmd.output = 7;
mci_config(state, ts_config);
stat = mci_cmd(state, &cmd, NULL);
if (stat)
stop(fe);
return stat;
}
@ -351,10 +453,39 @@ static int set_parameters(struct dvb_frontend *fe)
{
int stat = 0;
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 ts_config, iq_mode = 0, isi;
if (state->started)
stop(fe);
stat = start(fe);
isi = p->stream_id;
if (isi != NO_STREAM_ID_FILTER) {
iq_mode = (isi & 0x30000000) >> 28;
}
switch (iq_mode) {
case 1:
ts_config = (SX8_TSCONFIG_TSHEADER|SX8_TSCONFIG_MODE_IQ);
break;
case 2:
ts_config = (SX8_TSCONFIG_TSHEADER|SX8_TSCONFIG_MODE_IQ);
break;
default:
ts_config = SX8_TSCONFIG_MODE_NORMAL;
break;
}
if (iq_mode != 2) {
u32 flags = 3;
u32 mask = 3;
if (p->modulation == APSK_16 ||
p->modulation == APSK_32) {
flags = 2;
mask = 15;
}
stat = start(fe, flags, mask, ts_config);
} else {
stat = start_iq(fe, ts_config);
}
if (!stat) {
state->started = 1;
state->first_time_lock = 1;

View File

@ -43,32 +43,49 @@
#define SX8_TSCONFIG_MODE_NORMAL (0x00000001)
#define SX8_TSCONFIG_MODE_IQ (0x00000003)
#define SX8_TSCONFIG_TSHEADER (0x00000004)
#define SX8_TSCONFIG_BURST (0x00000008)
#define SX8_TSCONFIG_BURSTSIZE_MASK (0x00000030)
#define SX8_TSCONFIG_BURSTSIZE_2K (0x00000000)
#define SX8_TSCONFIG_BURSTSIZE_4K (0x00000010)
#define SX8_TSCONFIG_BURSTSIZE_8K (0x00000020)
#define SX8_TSCONFIG_BURSTSIZE_16K (0x00000030)
#define SX8_DEMOD_STOPPED (0)
#define SX8_DEMOD_IQ_MODE (1)
#define SX8_DEMOD_WAIT_SIGNAL (2)
#define SX8_DEMOD_WAIT_MATYPE (3)
#define SX8_DEMOD_TIMEOUT (14)
#define SX8_DEMOD_LOCKED (15)
#define SX8_CMD_TUNER_ENABLE (0x01)
#define SX8_CMD_TUNER_DISABLE (0x02)
#define SX8_CMD_SEARCH (0x03)
#define SX8_CMD_GETSTATUS (0x04)
#define SX8_CMD_STOP (0x05)
#define SX8_CMD_GETSIGNALINFO (0x07)
#define MCI_CMD_STOP (0x01)
#define MCI_CMD_GETSTATUS (0x02)
#define MCI_CMD_GETSIGNALINFO (0x03)
#define MCI_CMD_RFPOWER (0x04)
#define SX8_CMD_SELECT_IQOUT (0x10)
#define SX8_CMD_SELECT_TSOUT (0x11)
#define MCI_CMD_SEARCH_DVBS (0x10)
#define SX8_CMD_GET_IQSYMBOL (0x30)
#define MCI_CMD_GET_IQSYMBOL (0x30)
#define SX8_CMD_INPUT_ENABLE (0x40)
#define SX8_CMD_INPUT_DISABLE (0x41)
#define SX8_CMD_START_IQ (0x42)
#define SX8_CMD_STOP_IQ (0x43)
#define SX8_CMD_SELECT_IQOUT (0x44)
#define SX8_CMD_SELECT_TSOUT (0x45)
#define SX8_ERROR_UNSUPPORTED (0x80)
#define SX8_SUCCESS(status) (status < SX8_ERROR_UNSUPPORTED)
#define SX8_CMD_DIAG_READ8 (0xE0)
#define SX8_CMD_DIAG_READ32 (0xE1)
#define SX8_CMD_DIAG_WRITE8 (0xE2)
#define SX8_CMD_DIAG_WRITE32 (0xE3)
#define SX8_CMD_DIAG_READV (0xE8)
#define SX8_CMD_DIAG_WRITEV (0xE9)
#define M4_CMD_DIAG_READRF (0xE8)
#define M4_CMD_DIAG_WRITERF (0xE9)
#define M4_CMD_DIAG_READX (0xE0)
#define M4_CMD_DIAG_READT (0xE1)
@ -79,9 +96,6 @@
#define M4_CMD_DIAG_WRITERF (0xE9)
#define SX8_ERROR_UNSUPPORTED (0x80)
#define SX8_SUCCESS(status) (status < SX8_ERROR_UNSUPPORTED)
struct mci_command {
union {
u32 command_word;
@ -97,10 +111,13 @@ struct mci_command {
struct {
u8 flags;
u8 s2_modulation_mask;
u8 rsvd;
u8 rsvd1;
u8 retry;
u32 frequency;
u32 symbol_rate;
u8 input_stream_id;
u8 rsvd2[3];
u32 scrambling_sequence_index;
} dvbs2_search;
};
};