ddbridge-sx8.c (12251B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * ddbridge-sx8.c: Digital Devices MAX SX8 driver 4 * 5 * Copyright (C) 2018 Digital Devices GmbH 6 * Marcus Metzler <mocm@metzlerbros.de> 7 * Ralph Metzler <rjkm@metzlerbros.de> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * version 2 only, as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19#include "ddbridge.h" 20#include "ddbridge-io.h" 21#include "ddbridge-mci.h" 22 23static const u32 MCLK = (1550000000 / 12); 24static const u32 MAX_LDPC_BITRATE = (720000000); 25static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); 26 27#define SX8_TUNER_NUM 4 28#define SX8_DEMOD_NUM 8 29#define SX8_DEMOD_NONE 0xff 30 31struct sx8_base { 32 struct mci_base mci_base; 33 34 u8 tuner_use_count[SX8_TUNER_NUM]; 35 u32 gain_mode[SX8_TUNER_NUM]; 36 37 u32 used_ldpc_bitrate[SX8_DEMOD_NUM]; 38 u8 demod_in_use[SX8_DEMOD_NUM]; 39 u32 iq_mode; 40 u32 burst_size; 41 u32 direct_mode; 42}; 43 44struct sx8 { 45 struct mci mci; 46 47 int first_time_lock; 48 int started; 49 struct mci_result signal_info; 50 51 u32 bb_mode; 52 u32 local_frequency; 53}; 54 55static void release(struct dvb_frontend *fe) 56{ 57 struct sx8 *state = fe->demodulator_priv; 58 struct mci_base *mci_base = state->mci.base; 59 60 mci_base->count--; 61 if (mci_base->count == 0) { 62 list_del(&mci_base->mci_list); 63 kfree(mci_base); 64 } 65 kfree(state); 66} 67 68static int get_info(struct dvb_frontend *fe) 69{ 70 int stat; 71 struct sx8 *state = fe->demodulator_priv; 72 struct mci_command cmd; 73 74 memset(&cmd, 0, sizeof(cmd)); 75 cmd.command = MCI_CMD_GETSIGNALINFO; 76 cmd.demod = state->mci.demod; 77 stat = ddb_mci_cmd(&state->mci, &cmd, &state->signal_info); 78 return stat; 79} 80 81static int get_snr(struct dvb_frontend *fe) 82{ 83 struct sx8 *state = fe->demodulator_priv; 84 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 85 86 p->cnr.len = 1; 87 p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 88 p->cnr.stat[0].svalue = 89 (s64)state->signal_info.dvbs2_signal_info.signal_to_noise 90 * 10; 91 return 0; 92} 93 94static int get_strength(struct dvb_frontend *fe) 95{ 96 struct sx8 *state = fe->demodulator_priv; 97 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 98 s32 str; 99 100 str = 100000 - 101 (state->signal_info.dvbs2_signal_info.channel_power 102 * 10 + 108750); 103 p->strength.len = 1; 104 p->strength.stat[0].scale = FE_SCALE_DECIBEL; 105 p->strength.stat[0].svalue = str; 106 return 0; 107} 108 109static int read_status(struct dvb_frontend *fe, enum fe_status *status) 110{ 111 int stat; 112 struct sx8 *state = fe->demodulator_priv; 113 struct mci_command cmd; 114 struct mci_result res; 115 116 cmd.command = MCI_CMD_GETSTATUS; 117 cmd.demod = state->mci.demod; 118 stat = ddb_mci_cmd(&state->mci, &cmd, &res); 119 if (stat) 120 return stat; 121 *status = 0x00; 122 get_info(fe); 123 get_strength(fe); 124 if (res.status == SX8_DEMOD_WAIT_MATYPE) 125 *status = 0x0f; 126 if (res.status == SX8_DEMOD_LOCKED) { 127 *status = 0x1f; 128 get_snr(fe); 129 } 130 return stat; 131} 132 133static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) 134{ 135 struct sx8 *state = fe->demodulator_priv; 136 struct mci_base *mci_base = state->mci.base; 137 struct sx8_base *sx8_base = (struct sx8_base *)mci_base; 138 struct mci_command cmd; 139 140 memset(&cmd, 0, sizeof(cmd)); 141 cmd.tuner = state->mci.tuner; 142 cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; 143 cmd.sx8_input_enable.flags = sx8_base->gain_mode[state->mci.tuner]; 144 return ddb_mci_cmd(&state->mci, &cmd, NULL); 145} 146 147static int stop(struct dvb_frontend *fe) 148{ 149 struct sx8 *state = fe->demodulator_priv; 150 struct mci_base *mci_base = state->mci.base; 151 struct sx8_base *sx8_base = (struct sx8_base *)mci_base; 152 struct mci_command cmd; 153 u32 input = state->mci.tuner; 154 155 memset(&cmd, 0, sizeof(cmd)); 156 if (state->mci.demod != SX8_DEMOD_NONE) { 157 cmd.command = MCI_CMD_STOP; 158 cmd.demod = state->mci.demod; 159 ddb_mci_cmd(&state->mci, &cmd, NULL); 160 if (sx8_base->iq_mode) { 161 cmd.command = SX8_CMD_DISABLE_IQOUTPUT; 162 cmd.demod = state->mci.demod; 163 cmd.output = 0; 164 ddb_mci_cmd(&state->mci, &cmd, NULL); 165 ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); 166 } 167 } 168 mutex_lock(&mci_base->tuner_lock); 169 sx8_base->tuner_use_count[input]--; 170 if (!sx8_base->tuner_use_count[input]) 171 mci_set_tuner(fe, input, 0); 172 if (state->mci.demod < SX8_DEMOD_NUM) { 173 sx8_base->demod_in_use[state->mci.demod] = 0; 174 state->mci.demod = SX8_DEMOD_NONE; 175 } 176 sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; 177 sx8_base->iq_mode = 0; 178 mutex_unlock(&mci_base->tuner_lock); 179 state->started = 0; 180 return 0; 181} 182 183static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) 184{ 185 struct sx8 *state = fe->demodulator_priv; 186 struct mci_base *mci_base = state->mci.base; 187 struct sx8_base *sx8_base = (struct sx8_base *)mci_base; 188 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 189 u32 used_ldpc_bitrate = 0, free_ldpc_bitrate; 190 u32 used_demods = 0; 191 struct mci_command cmd; 192 u32 input = state->mci.tuner; 193 u32 bits_per_symbol = 0; 194 int i = -1, stat = 0; 195 196 if (p->symbol_rate >= (MCLK / 2)) 197 flags &= ~1; 198 if ((flags & 3) == 0) 199 return -EINVAL; 200 201 if (flags & 2) { 202 u32 tmp = modmask; 203 204 bits_per_symbol = 1; 205 while (tmp & 1) { 206 tmp >>= 1; 207 bits_per_symbol++; 208 } 209 } 210 211 mutex_lock(&mci_base->tuner_lock); 212 if (sx8_base->iq_mode) { 213 stat = -EBUSY; 214 goto unlock; 215 } 216 217 if (sx8_base->direct_mode) { 218 if (p->symbol_rate >= MCLK / 2) { 219 if (state->mci.nr < 4) 220 i = state->mci.nr; 221 } else { 222 i = state->mci.nr; 223 } 224 } else { 225 for (i = 0; i < SX8_DEMOD_NUM; i++) { 226 used_ldpc_bitrate += sx8_base->used_ldpc_bitrate[i]; 227 if (sx8_base->demod_in_use[i]) 228 used_demods++; 229 } 230 if (used_ldpc_bitrate >= MAX_LDPC_BITRATE || 231 ((ts_config & SX8_TSCONFIG_MODE_MASK) > 232 SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) { 233 stat = -EBUSY; 234 goto unlock; 235 } 236 free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; 237 if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) 238 free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; 239 240 while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) 241 bits_per_symbol--; 242 if (bits_per_symbol < 2) { 243 stat = -EBUSY; 244 goto unlock; 245 } 246 247 modmask &= ((1 << (bits_per_symbol - 1)) - 1); 248 if (((flags & 0x02) != 0) && modmask == 0) { 249 stat = -EBUSY; 250 goto unlock; 251 } 252 253 i = (p->symbol_rate > (MCLK / 2)) ? 3 : 7; 254 while (i >= 0 && sx8_base->demod_in_use[i]) 255 i--; 256 } 257 258 if (i < 0) { 259 stat = -EBUSY; 260 goto unlock; 261 } 262 sx8_base->demod_in_use[i] = 1; 263 sx8_base->used_ldpc_bitrate[state->mci.nr] = p->symbol_rate 264 * bits_per_symbol; 265 state->mci.demod = i; 266 267 if (!sx8_base->tuner_use_count[input]) 268 mci_set_tuner(fe, input, 1); 269 sx8_base->tuner_use_count[input]++; 270 sx8_base->iq_mode = (ts_config > 1); 271unlock: 272 mutex_unlock(&mci_base->tuner_lock); 273 if (stat) 274 return stat; 275 memset(&cmd, 0, sizeof(cmd)); 276 277 if (sx8_base->iq_mode) { 278 cmd.command = SX8_CMD_ENABLE_IQOUTPUT; 279 cmd.demod = state->mci.demod; 280 cmd.output = 0; 281 ddb_mci_cmd(&state->mci, &cmd, NULL); 282 ddb_mci_config(&state->mci, ts_config); 283 } 284 if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) 285 flags |= 0x80; 286 dev_dbg(mci_base->dev, "MCI-%d: tuner=%d demod=%d\n", 287 state->mci.nr, state->mci.tuner, state->mci.demod); 288 cmd.command = MCI_CMD_SEARCH_DVBS; 289 cmd.dvbs2_search.flags = flags; 290 cmd.dvbs2_search.s2_modulation_mask = modmask; 291 cmd.dvbs2_search.retry = 2; 292 cmd.dvbs2_search.frequency = p->frequency * 1000; 293 cmd.dvbs2_search.symbol_rate = p->symbol_rate; 294 cmd.dvbs2_search.scrambling_sequence_index = 295 p->scrambling_sequence_index | 0x80000000; 296 cmd.dvbs2_search.input_stream_id = 297 (p->stream_id != NO_STREAM_ID_FILTER) ? p->stream_id : 0; 298 cmd.tuner = state->mci.tuner; 299 cmd.demod = state->mci.demod; 300 cmd.output = state->mci.nr; 301 if (p->stream_id == 0x80000000) 302 cmd.output |= 0x80; 303 stat = ddb_mci_cmd(&state->mci, &cmd, NULL); 304 if (stat) 305 stop(fe); 306 return stat; 307} 308 309static int start_iq(struct dvb_frontend *fe, u32 flags, u32 roll_off, 310 u32 ts_config) 311{ 312 struct sx8 *state = fe->demodulator_priv; 313 struct mci_base *mci_base = state->mci.base; 314 struct sx8_base *sx8_base = (struct sx8_base *)mci_base; 315 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 316 u32 used_demods = 0; 317 struct mci_command cmd; 318 u32 input = state->mci.tuner; 319 int i, stat = 0; 320 321 mutex_lock(&mci_base->tuner_lock); 322 if (sx8_base->iq_mode) { 323 stat = -EBUSY; 324 goto unlock; 325 } 326 for (i = 0; i < SX8_DEMOD_NUM; i++) 327 if (sx8_base->demod_in_use[i]) 328 used_demods++; 329 if (used_demods > 0) { 330 stat = -EBUSY; 331 goto unlock; 332 } 333 state->mci.demod = 0; 334 if (!sx8_base->tuner_use_count[input]) 335 mci_set_tuner(fe, input, 1); 336 sx8_base->tuner_use_count[input]++; 337 sx8_base->iq_mode = (ts_config > 1); 338unlock: 339 mutex_unlock(&mci_base->tuner_lock); 340 if (stat) 341 return stat; 342 343 memset(&cmd, 0, sizeof(cmd)); 344 cmd.command = SX8_CMD_START_IQ; 345 cmd.sx8_start_iq.flags = flags; 346 cmd.sx8_start_iq.roll_off = roll_off; 347 cmd.sx8_start_iq.frequency = p->frequency * 1000; 348 cmd.sx8_start_iq.symbol_rate = p->symbol_rate; 349 cmd.tuner = state->mci.tuner; 350 cmd.demod = state->mci.demod; 351 stat = ddb_mci_cmd(&state->mci, &cmd, NULL); 352 if (stat) 353 stop(fe); 354 ddb_mci_config(&state->mci, ts_config); 355 return stat; 356} 357 358static int set_parameters(struct dvb_frontend *fe) 359{ 360 int stat = 0; 361 struct sx8 *state = fe->demodulator_priv; 362 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 363 u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi; 364 365 if (state->started) 366 stop(fe); 367 368 isi = p->stream_id; 369 if (isi != NO_STREAM_ID_FILTER) 370 iq_mode = (isi & 0x30000000) >> 28; 371 372 if (iq_mode) 373 ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); 374 if (iq_mode < 3) { 375 u32 mask; 376 377 switch (p->modulation) { 378 /* uncomment whenever these modulations hit the DVB API 379 * case APSK_256: 380 * mask = 0x7f; 381 * break; 382 * case APSK_128: 383 * mask = 0x3f; 384 * break; 385 * case APSK_64: 386 * mask = 0x1f; 387 * break; 388 */ 389 case APSK_32: 390 mask = 0x0f; 391 break; 392 case APSK_16: 393 mask = 0x07; 394 break; 395 default: 396 mask = 0x03; 397 break; 398 } 399 stat = start(fe, 3, mask, ts_config); 400 } else { 401 stat = start_iq(fe, 0, 4, ts_config); 402 } 403 if (!stat) { 404 state->started = 1; 405 state->first_time_lock = 1; 406 state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; 407 } 408 409 return stat; 410} 411 412static int tune(struct dvb_frontend *fe, bool re_tune, 413 unsigned int mode_flags, 414 unsigned int *delay, enum fe_status *status) 415{ 416 int r; 417 418 if (re_tune) { 419 r = set_parameters(fe); 420 if (r) 421 return r; 422 } 423 r = read_status(fe, status); 424 if (r) 425 return r; 426 427 if (*status & FE_HAS_LOCK) 428 return 0; 429 *delay = HZ / 10; 430 return 0; 431} 432 433static enum dvbfe_algo get_algo(struct dvb_frontend *fe) 434{ 435 return DVBFE_ALGO_HW; 436} 437 438static int set_input(struct dvb_frontend *fe, int input) 439{ 440 struct sx8 *state = fe->demodulator_priv; 441 struct mci_base *mci_base = state->mci.base; 442 443 if (input >= SX8_TUNER_NUM) 444 return -EINVAL; 445 446 state->mci.tuner = input; 447 dev_dbg(mci_base->dev, "MCI-%d: input=%d\n", state->mci.nr, input); 448 return 0; 449} 450 451static struct dvb_frontend_ops sx8_ops = { 452 .delsys = { SYS_DVBS, SYS_DVBS2 }, 453 .info = { 454 .name = "Digital Devices MaxSX8 MCI DVB-S/S2/S2X", 455 .frequency_min_hz = 950 * MHz, 456 .frequency_max_hz = 2150 * MHz, 457 .symbol_rate_min = 100000, 458 .symbol_rate_max = 100000000, 459 .caps = FE_CAN_INVERSION_AUTO | 460 FE_CAN_FEC_AUTO | 461 FE_CAN_QPSK | 462 FE_CAN_2G_MODULATION | 463 FE_CAN_MULTISTREAM, 464 }, 465 .get_frontend_algo = get_algo, 466 .tune = tune, 467 .release = release, 468 .read_status = read_status, 469}; 470 471static int init(struct mci *mci) 472{ 473 struct sx8 *state = (struct sx8 *)mci; 474 475 state->mci.demod = SX8_DEMOD_NONE; 476 return 0; 477} 478 479const struct mci_cfg ddb_max_sx8_cfg = { 480 .type = 0, 481 .fe_ops = &sx8_ops, 482 .base_size = sizeof(struct sx8_base), 483 .state_size = sizeof(struct sx8), 484 .init = init, 485 .set_input = set_input, 486};