1 // SPDX-License-Identifier: GPL-2.0
3 * ddbridge-sx8.c: Digital Devices MAX SX8 driver
5 * Copyright (C) 2018 Digital Devices GmbH
6 * Marcus Metzler <mocm@metzlerbros.de>
7 * Ralph Metzler <rjkm@metzlerbros.de>
11 #include "ddbridge-io.h"
12 #include "ddbridge-mci.h"
14 static const u32 MCLK
= (1550000000 / 12);
15 static const u32 MAX_LDPC_BITRATE
= (720000000);
16 static const u32 MAX_DEMOD_LDPC_BITRATE
= (1550000000 / 6);
18 #define SX8_TUNER_NUM 4
19 #define SX8_DEMOD_NUM 8
20 #define SX8_DEMOD_NONE 0xff
23 struct mci_base mci_base
;
25 u8 tuner_use_count
[SX8_TUNER_NUM
];
26 u32 gain_mode
[SX8_TUNER_NUM
];
28 u32 used_ldpc_bitrate
[SX8_DEMOD_NUM
];
29 u8 demod_in_use
[SX8_DEMOD_NUM
];
40 struct mci_result signal_info
;
46 static void release(struct dvb_frontend
*fe
)
48 struct sx8
*state
= fe
->demodulator_priv
;
49 struct mci_base
*mci_base
= state
->mci
.base
;
52 if (mci_base
->count
== 0) {
53 list_del(&mci_base
->mci_list
);
59 static int get_info(struct dvb_frontend
*fe
)
62 struct sx8
*state
= fe
->demodulator_priv
;
63 struct mci_command cmd
;
65 memset(&cmd
, 0, sizeof(cmd
));
66 cmd
.command
= MCI_CMD_GETSIGNALINFO
;
67 cmd
.demod
= state
->mci
.demod
;
68 stat
= ddb_mci_cmd(&state
->mci
, &cmd
, &state
->signal_info
);
72 static int get_snr(struct dvb_frontend
*fe
)
74 struct sx8
*state
= fe
->demodulator_priv
;
75 struct dtv_frontend_properties
*p
= &fe
->dtv_property_cache
;
78 p
->cnr
.stat
[0].scale
= FE_SCALE_DECIBEL
;
79 p
->cnr
.stat
[0].svalue
=
80 (s64
)state
->signal_info
.dvbs2_signal_info
.signal_to_noise
85 static int get_strength(struct dvb_frontend
*fe
)
87 struct sx8
*state
= fe
->demodulator_priv
;
88 struct dtv_frontend_properties
*p
= &fe
->dtv_property_cache
;
92 (state
->signal_info
.dvbs2_signal_info
.channel_power
95 p
->strength
.stat
[0].scale
= FE_SCALE_DECIBEL
;
96 p
->strength
.stat
[0].svalue
= str
;
100 static int read_status(struct dvb_frontend
*fe
, enum fe_status
*status
)
103 struct sx8
*state
= fe
->demodulator_priv
;
104 struct mci_command cmd
;
105 struct mci_result res
;
107 cmd
.command
= MCI_CMD_GETSTATUS
;
108 cmd
.demod
= state
->mci
.demod
;
109 stat
= ddb_mci_cmd(&state
->mci
, &cmd
, &res
);
115 if (res
.status
== SX8_DEMOD_WAIT_MATYPE
)
117 if (res
.status
== SX8_DEMOD_LOCKED
) {
124 static int mci_set_tuner(struct dvb_frontend
*fe
, u32 tuner
, u32 on
)
126 struct sx8
*state
= fe
->demodulator_priv
;
127 struct mci_base
*mci_base
= state
->mci
.base
;
128 struct sx8_base
*sx8_base
= (struct sx8_base
*)mci_base
;
129 struct mci_command cmd
;
131 memset(&cmd
, 0, sizeof(cmd
));
132 cmd
.tuner
= state
->mci
.tuner
;
133 cmd
.command
= on
? SX8_CMD_INPUT_ENABLE
: SX8_CMD_INPUT_DISABLE
;
134 cmd
.sx8_input_enable
.flags
= sx8_base
->gain_mode
[state
->mci
.tuner
];
135 return ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
138 static int stop(struct dvb_frontend
*fe
)
140 struct sx8
*state
= fe
->demodulator_priv
;
141 struct mci_base
*mci_base
= state
->mci
.base
;
142 struct sx8_base
*sx8_base
= (struct sx8_base
*)mci_base
;
143 struct mci_command cmd
;
144 u32 input
= state
->mci
.tuner
;
146 memset(&cmd
, 0, sizeof(cmd
));
147 if (state
->mci
.demod
!= SX8_DEMOD_NONE
) {
148 cmd
.command
= MCI_CMD_STOP
;
149 cmd
.demod
= state
->mci
.demod
;
150 ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
151 if (sx8_base
->iq_mode
) {
152 cmd
.command
= SX8_CMD_DISABLE_IQOUTPUT
;
153 cmd
.demod
= state
->mci
.demod
;
155 ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
156 ddb_mci_config(&state
->mci
, SX8_TSCONFIG_MODE_NORMAL
);
159 mutex_lock(&mci_base
->tuner_lock
);
160 sx8_base
->tuner_use_count
[input
]--;
161 if (!sx8_base
->tuner_use_count
[input
])
162 mci_set_tuner(fe
, input
, 0);
163 if (state
->mci
.demod
< SX8_DEMOD_NUM
) {
164 sx8_base
->demod_in_use
[state
->mci
.demod
] = 0;
165 state
->mci
.demod
= SX8_DEMOD_NONE
;
167 sx8_base
->used_ldpc_bitrate
[state
->mci
.nr
] = 0;
168 sx8_base
->iq_mode
= 0;
169 mutex_unlock(&mci_base
->tuner_lock
);
174 static int start(struct dvb_frontend
*fe
, u32 flags
, u32 modmask
, u32 ts_config
)
176 struct sx8
*state
= fe
->demodulator_priv
;
177 struct mci_base
*mci_base
= state
->mci
.base
;
178 struct sx8_base
*sx8_base
= (struct sx8_base
*)mci_base
;
179 struct dtv_frontend_properties
*p
= &fe
->dtv_property_cache
;
180 u32 used_ldpc_bitrate
= 0, free_ldpc_bitrate
;
182 struct mci_command cmd
;
183 u32 input
= state
->mci
.tuner
;
184 u32 bits_per_symbol
= 0;
185 int i
= -1, stat
= 0;
187 if (p
->symbol_rate
>= (MCLK
/ 2))
189 if ((flags
& 3) == 0)
202 mutex_lock(&mci_base
->tuner_lock
);
203 if (sx8_base
->iq_mode
) {
208 if (sx8_base
->direct_mode
) {
209 if (p
->symbol_rate
>= MCLK
/ 2) {
210 if (state
->mci
.nr
< 4)
216 for (i
= 0; i
< SX8_DEMOD_NUM
; i
++) {
217 used_ldpc_bitrate
+= sx8_base
->used_ldpc_bitrate
[i
];
218 if (sx8_base
->demod_in_use
[i
])
221 if (used_ldpc_bitrate
>= MAX_LDPC_BITRATE
||
222 ((ts_config
& SX8_TSCONFIG_MODE_MASK
) >
223 SX8_TSCONFIG_MODE_NORMAL
&& used_demods
> 0)) {
227 free_ldpc_bitrate
= MAX_LDPC_BITRATE
- used_ldpc_bitrate
;
228 if (free_ldpc_bitrate
> MAX_DEMOD_LDPC_BITRATE
)
229 free_ldpc_bitrate
= MAX_DEMOD_LDPC_BITRATE
;
231 while (p
->symbol_rate
* bits_per_symbol
> free_ldpc_bitrate
)
233 if (bits_per_symbol
< 2) {
238 modmask
&= ((1 << (bits_per_symbol
- 1)) - 1);
239 if (((flags
& 0x02) != 0) && modmask
== 0) {
244 i
= (p
->symbol_rate
> (MCLK
/ 2)) ? 3 : 7;
245 while (i
>= 0 && sx8_base
->demod_in_use
[i
])
253 sx8_base
->demod_in_use
[i
] = 1;
254 sx8_base
->used_ldpc_bitrate
[state
->mci
.nr
] = p
->symbol_rate
256 state
->mci
.demod
= i
;
258 if (!sx8_base
->tuner_use_count
[input
])
259 mci_set_tuner(fe
, input
, 1);
260 sx8_base
->tuner_use_count
[input
]++;
261 sx8_base
->iq_mode
= (ts_config
> 1);
263 mutex_unlock(&mci_base
->tuner_lock
);
266 memset(&cmd
, 0, sizeof(cmd
));
268 if (sx8_base
->iq_mode
) {
269 cmd
.command
= SX8_CMD_ENABLE_IQOUTPUT
;
270 cmd
.demod
= state
->mci
.demod
;
272 ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
273 ddb_mci_config(&state
->mci
, ts_config
);
275 if (p
->stream_id
!= NO_STREAM_ID_FILTER
&& p
->stream_id
!= 0x80000000)
277 dev_dbg(mci_base
->dev
, "MCI-%d: tuner=%d demod=%d\n",
278 state
->mci
.nr
, state
->mci
.tuner
, state
->mci
.demod
);
279 cmd
.command
= MCI_CMD_SEARCH_DVBS
;
280 cmd
.dvbs2_search
.flags
= flags
;
281 cmd
.dvbs2_search
.s2_modulation_mask
= modmask
;
282 cmd
.dvbs2_search
.retry
= 2;
283 cmd
.dvbs2_search
.frequency
= p
->frequency
* 1000;
284 cmd
.dvbs2_search
.symbol_rate
= p
->symbol_rate
;
285 cmd
.dvbs2_search
.scrambling_sequence_index
=
286 p
->scrambling_sequence_index
| 0x80000000;
287 cmd
.dvbs2_search
.input_stream_id
=
288 (p
->stream_id
!= NO_STREAM_ID_FILTER
) ? p
->stream_id
: 0;
289 cmd
.tuner
= state
->mci
.tuner
;
290 cmd
.demod
= state
->mci
.demod
;
291 cmd
.output
= state
->mci
.nr
;
292 if (p
->stream_id
== 0x80000000)
294 stat
= ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
300 static int start_iq(struct dvb_frontend
*fe
, u32 flags
, u32 roll_off
,
303 struct sx8
*state
= fe
->demodulator_priv
;
304 struct mci_base
*mci_base
= state
->mci
.base
;
305 struct sx8_base
*sx8_base
= (struct sx8_base
*)mci_base
;
306 struct dtv_frontend_properties
*p
= &fe
->dtv_property_cache
;
308 struct mci_command cmd
;
309 u32 input
= state
->mci
.tuner
;
312 mutex_lock(&mci_base
->tuner_lock
);
313 if (sx8_base
->iq_mode
) {
317 for (i
= 0; i
< SX8_DEMOD_NUM
; i
++)
318 if (sx8_base
->demod_in_use
[i
])
320 if (used_demods
> 0) {
324 state
->mci
.demod
= 0;
325 if (!sx8_base
->tuner_use_count
[input
])
326 mci_set_tuner(fe
, input
, 1);
327 sx8_base
->tuner_use_count
[input
]++;
328 sx8_base
->iq_mode
= (ts_config
> 1);
330 mutex_unlock(&mci_base
->tuner_lock
);
334 memset(&cmd
, 0, sizeof(cmd
));
335 cmd
.command
= SX8_CMD_START_IQ
;
336 cmd
.sx8_start_iq
.flags
= flags
;
337 cmd
.sx8_start_iq
.roll_off
= roll_off
;
338 cmd
.sx8_start_iq
.frequency
= p
->frequency
* 1000;
339 cmd
.sx8_start_iq
.symbol_rate
= p
->symbol_rate
;
340 cmd
.tuner
= state
->mci
.tuner
;
341 cmd
.demod
= state
->mci
.demod
;
342 stat
= ddb_mci_cmd(&state
->mci
, &cmd
, NULL
);
345 ddb_mci_config(&state
->mci
, ts_config
);
349 static int set_parameters(struct dvb_frontend
*fe
)
352 struct sx8
*state
= fe
->demodulator_priv
;
353 struct dtv_frontend_properties
*p
= &fe
->dtv_property_cache
;
354 u32 ts_config
= SX8_TSCONFIG_MODE_NORMAL
, iq_mode
= 0, isi
;
360 if (isi
!= NO_STREAM_ID_FILTER
)
361 iq_mode
= (isi
& 0x30000000) >> 28;
364 ts_config
= (SX8_TSCONFIG_TSHEADER
| SX8_TSCONFIG_MODE_IQ
);
368 switch (p
->modulation
) {
369 /* uncomment whenever these modulations hit the DVB API
390 stat
= start(fe
, 3, mask
, ts_config
);
392 stat
= start_iq(fe
, 0, 4, ts_config
);
396 state
->first_time_lock
= 1;
397 state
->signal_info
.status
= SX8_DEMOD_WAIT_SIGNAL
;
403 static int tune(struct dvb_frontend
*fe
, bool re_tune
,
404 unsigned int mode_flags
,
405 unsigned int *delay
, enum fe_status
*status
)
410 r
= set_parameters(fe
);
414 r
= read_status(fe
, status
);
418 if (*status
& FE_HAS_LOCK
)
424 static enum dvbfe_algo
get_algo(struct dvb_frontend
*fe
)
426 return DVBFE_ALGO_HW
;
429 static int set_input(struct dvb_frontend
*fe
, int input
)
431 struct sx8
*state
= fe
->demodulator_priv
;
432 struct mci_base
*mci_base
= state
->mci
.base
;
434 if (input
>= SX8_TUNER_NUM
)
437 state
->mci
.tuner
= input
;
438 dev_dbg(mci_base
->dev
, "MCI-%d: input=%d\n", state
->mci
.nr
, input
);
442 static struct dvb_frontend_ops sx8_ops
= {
443 .delsys
= { SYS_DVBS
, SYS_DVBS2
},
445 .name
= "Digital Devices MaxSX8 MCI DVB-S/S2/S2X",
446 .frequency_min_hz
= 950 * MHz
,
447 .frequency_max_hz
= 2150 * MHz
,
448 .symbol_rate_min
= 100000,
449 .symbol_rate_max
= 100000000,
450 .caps
= FE_CAN_INVERSION_AUTO
|
453 FE_CAN_2G_MODULATION
|
456 .get_frontend_algo
= get_algo
,
459 .read_status
= read_status
,
462 static int init(struct mci
*mci
)
464 struct sx8
*state
= (struct sx8
*)mci
;
466 state
->mci
.demod
= SX8_DEMOD_NONE
;
470 const struct mci_cfg ddb_max_sx8_cfg
= {
473 .base_size
= sizeof(struct sx8_base
),
474 .state_size
= sizeof(struct sx8
),
476 .set_input
= set_input
,