1daeeb131SDaniel Scheller // SPDX-License-Identifier: GPL-2.0 2daeeb131SDaniel Scheller /* 3daeeb131SDaniel Scheller * ddbridge-mci.c: Digital Devices microcode interface 4daeeb131SDaniel Scheller * 5*3addf0faSDaniel Scheller * Copyright (C) 2017-2018 Digital Devices GmbH 6daeeb131SDaniel Scheller * Ralph Metzler <rjkm@metzlerbros.de> 7daeeb131SDaniel Scheller * Marcus Metzler <mocm@metzlerbros.de> 8daeeb131SDaniel Scheller * 9daeeb131SDaniel Scheller * This program is free software; you can redistribute it and/or 10daeeb131SDaniel Scheller * modify it under the terms of the GNU General Public License 11daeeb131SDaniel Scheller * version 2 only, as published by the Free Software Foundation. 12daeeb131SDaniel Scheller * 13daeeb131SDaniel Scheller * This program is distributed in the hope that it will be useful, 14daeeb131SDaniel Scheller * but WITHOUT ANY WARRANTY; without even the implied warranty of 15daeeb131SDaniel Scheller * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16daeeb131SDaniel Scheller * GNU General Public License for more details. 17daeeb131SDaniel Scheller */ 18daeeb131SDaniel Scheller 19daeeb131SDaniel Scheller #include "ddbridge.h" 20daeeb131SDaniel Scheller #include "ddbridge-io.h" 21daeeb131SDaniel Scheller #include "ddbridge-mci.h" 22daeeb131SDaniel Scheller 23daeeb131SDaniel Scheller static LIST_HEAD(mci_list); 24daeeb131SDaniel Scheller 25daeeb131SDaniel Scheller static const u32 MCLK = (1550000000 / 12); 26daeeb131SDaniel Scheller static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); 27daeeb131SDaniel Scheller static const u32 MAX_LDPC_BITRATE = (720000000); 28daeeb131SDaniel Scheller 29daeeb131SDaniel Scheller struct mci_base { 30daeeb131SDaniel Scheller struct list_head mci_list; 31daeeb131SDaniel Scheller void *key; 32daeeb131SDaniel Scheller struct ddb_link *link; 33daeeb131SDaniel Scheller struct completion completion; 34daeeb131SDaniel Scheller 35daeeb131SDaniel Scheller struct device *dev; 36daeeb131SDaniel Scheller struct mutex tuner_lock; /* concurrent tuner access lock */ 37daeeb131SDaniel Scheller u8 adr; 38daeeb131SDaniel Scheller struct mutex mci_lock; /* concurrent MCI access lock */ 39daeeb131SDaniel Scheller int count; 40daeeb131SDaniel Scheller 41525cac75SDaniel Scheller u8 tuner_use_count[MCI_TUNER_MAX]; 42525cac75SDaniel Scheller u8 assigned_demod[MCI_DEMOD_MAX]; 43525cac75SDaniel Scheller u32 used_ldpc_bitrate[MCI_DEMOD_MAX]; 44525cac75SDaniel Scheller u8 demod_in_use[MCI_DEMOD_MAX]; 45daeeb131SDaniel Scheller u32 iq_mode; 46daeeb131SDaniel Scheller }; 47daeeb131SDaniel Scheller 48daeeb131SDaniel Scheller struct mci { 49daeeb131SDaniel Scheller struct mci_base *base; 50daeeb131SDaniel Scheller struct dvb_frontend fe; 51daeeb131SDaniel Scheller int nr; 52daeeb131SDaniel Scheller int demod; 53daeeb131SDaniel Scheller int tuner; 54daeeb131SDaniel Scheller int first_time_lock; 55daeeb131SDaniel Scheller int started; 56daeeb131SDaniel Scheller struct mci_result signal_info; 57daeeb131SDaniel Scheller 58daeeb131SDaniel Scheller u32 bb_mode; 59daeeb131SDaniel Scheller }; 60daeeb131SDaniel Scheller 61daeeb131SDaniel Scheller static int mci_reset(struct mci *state) 62daeeb131SDaniel Scheller { 63daeeb131SDaniel Scheller struct ddb_link *link = state->base->link; 64daeeb131SDaniel Scheller u32 status = 0; 65daeeb131SDaniel Scheller u32 timeout = 40; 66daeeb131SDaniel Scheller 67daeeb131SDaniel Scheller ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL); 68daeeb131SDaniel Scheller ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */ 69daeeb131SDaniel Scheller msleep(300); 70daeeb131SDaniel Scheller ddblwritel(link, 0, MCI_CONTROL); 71daeeb131SDaniel Scheller 72daeeb131SDaniel Scheller while (1) { 73daeeb131SDaniel Scheller status = ddblreadl(link, MCI_CONTROL); 74daeeb131SDaniel Scheller if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) 75daeeb131SDaniel Scheller break; 76daeeb131SDaniel Scheller if (--timeout == 0) 77daeeb131SDaniel Scheller break; 78daeeb131SDaniel Scheller msleep(50); 79daeeb131SDaniel Scheller } 80daeeb131SDaniel Scheller if ((status & MCI_CONTROL_READY) == 0) 81daeeb131SDaniel Scheller return -1; 82daeeb131SDaniel Scheller if (link->ids.device == 0x0009) 83daeeb131SDaniel Scheller ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); 84daeeb131SDaniel Scheller return 0; 85daeeb131SDaniel Scheller } 86daeeb131SDaniel Scheller 87daeeb131SDaniel Scheller static int mci_config(struct mci *state, u32 config) 88daeeb131SDaniel Scheller { 89daeeb131SDaniel Scheller struct ddb_link *link = state->base->link; 90daeeb131SDaniel Scheller 91daeeb131SDaniel Scheller if (link->ids.device != 0x0009) 92daeeb131SDaniel Scheller return -EINVAL; 93daeeb131SDaniel Scheller ddblwritel(link, config, SX8_TSCONFIG); 94daeeb131SDaniel Scheller return 0; 95daeeb131SDaniel Scheller } 96daeeb131SDaniel Scheller 97daeeb131SDaniel Scheller static int _mci_cmd_unlocked(struct mci *state, 98daeeb131SDaniel Scheller u32 *cmd, u32 cmd_len, 99daeeb131SDaniel Scheller u32 *res, u32 res_len) 100daeeb131SDaniel Scheller { 101daeeb131SDaniel Scheller struct ddb_link *link = state->base->link; 102daeeb131SDaniel Scheller u32 i, val; 103daeeb131SDaniel Scheller unsigned long stat; 104daeeb131SDaniel Scheller 105daeeb131SDaniel Scheller val = ddblreadl(link, MCI_CONTROL); 106daeeb131SDaniel Scheller if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) 107daeeb131SDaniel Scheller return -EIO; 108daeeb131SDaniel Scheller if (cmd && cmd_len) 109daeeb131SDaniel Scheller for (i = 0; i < cmd_len; i++) 110daeeb131SDaniel Scheller ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); 111daeeb131SDaniel Scheller val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); 112daeeb131SDaniel Scheller ddblwritel(link, val, MCI_CONTROL); 113daeeb131SDaniel Scheller 114daeeb131SDaniel Scheller stat = wait_for_completion_timeout(&state->base->completion, HZ); 115daeeb131SDaniel Scheller if (stat == 0) { 116daeeb131SDaniel Scheller dev_warn(state->base->dev, "MCI-%d: MCI timeout\n", state->nr); 117daeeb131SDaniel Scheller return -EIO; 118daeeb131SDaniel Scheller } 119daeeb131SDaniel Scheller if (res && res_len) 120daeeb131SDaniel Scheller for (i = 0; i < res_len; i++) 121daeeb131SDaniel Scheller res[i] = ddblreadl(link, MCI_RESULT + i * 4); 122daeeb131SDaniel Scheller return 0; 123daeeb131SDaniel Scheller } 124daeeb131SDaniel Scheller 125daeeb131SDaniel Scheller static int mci_cmd(struct mci *state, 126daeeb131SDaniel Scheller struct mci_command *command, 127daeeb131SDaniel Scheller struct mci_result *result) 128daeeb131SDaniel Scheller { 129daeeb131SDaniel Scheller int stat; 130daeeb131SDaniel Scheller 131daeeb131SDaniel Scheller mutex_lock(&state->base->mci_lock); 132daeeb131SDaniel Scheller stat = _mci_cmd_unlocked(state, 133daeeb131SDaniel Scheller (u32 *)command, sizeof(*command) / sizeof(u32), 134daeeb131SDaniel Scheller (u32 *)result, sizeof(*result) / sizeof(u32)); 135daeeb131SDaniel Scheller mutex_unlock(&state->base->mci_lock); 136daeeb131SDaniel Scheller return stat; 137daeeb131SDaniel Scheller } 138daeeb131SDaniel Scheller 139daeeb131SDaniel Scheller static void mci_handler(void *priv) 140daeeb131SDaniel Scheller { 141daeeb131SDaniel Scheller struct mci_base *base = (struct mci_base *)priv; 142daeeb131SDaniel Scheller 143daeeb131SDaniel Scheller complete(&base->completion); 144daeeb131SDaniel Scheller } 145daeeb131SDaniel Scheller 146daeeb131SDaniel Scheller static void release(struct dvb_frontend *fe) 147daeeb131SDaniel Scheller { 148daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 149daeeb131SDaniel Scheller 150daeeb131SDaniel Scheller state->base->count--; 151daeeb131SDaniel Scheller if (state->base->count == 0) { 152daeeb131SDaniel Scheller list_del(&state->base->mci_list); 153daeeb131SDaniel Scheller kfree(state->base); 154daeeb131SDaniel Scheller } 155daeeb131SDaniel Scheller kfree(state); 156daeeb131SDaniel Scheller } 157daeeb131SDaniel Scheller 158daeeb131SDaniel Scheller static int read_status(struct dvb_frontend *fe, enum fe_status *status) 159daeeb131SDaniel Scheller { 160daeeb131SDaniel Scheller int stat; 161daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 162daeeb131SDaniel Scheller struct mci_command cmd; 163daeeb131SDaniel Scheller struct mci_result res; 164daeeb131SDaniel Scheller 165daeeb131SDaniel Scheller cmd.command = MCI_CMD_GETSTATUS; 166daeeb131SDaniel Scheller cmd.demod = state->demod; 167daeeb131SDaniel Scheller stat = mci_cmd(state, &cmd, &res); 168daeeb131SDaniel Scheller if (stat) 169daeeb131SDaniel Scheller return stat; 170daeeb131SDaniel Scheller *status = 0x00; 171daeeb131SDaniel Scheller if (res.status == SX8_DEMOD_WAIT_MATYPE) 172daeeb131SDaniel Scheller *status = 0x0f; 173daeeb131SDaniel Scheller if (res.status == SX8_DEMOD_LOCKED) 174daeeb131SDaniel Scheller *status = 0x1f; 175daeeb131SDaniel Scheller return stat; 176daeeb131SDaniel Scheller } 177daeeb131SDaniel Scheller 178daeeb131SDaniel Scheller static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) 179daeeb131SDaniel Scheller { 180daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 181daeeb131SDaniel Scheller struct mci_command cmd; 182daeeb131SDaniel Scheller 183daeeb131SDaniel Scheller memset(&cmd, 0, sizeof(cmd)); 184daeeb131SDaniel Scheller cmd.tuner = state->tuner; 185daeeb131SDaniel Scheller cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; 186daeeb131SDaniel Scheller return mci_cmd(state, &cmd, NULL); 187daeeb131SDaniel Scheller } 188daeeb131SDaniel Scheller 189daeeb131SDaniel Scheller static int stop(struct dvb_frontend *fe) 190daeeb131SDaniel Scheller { 191daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 192daeeb131SDaniel Scheller struct mci_command cmd; 193daeeb131SDaniel Scheller u32 input = state->tuner; 194daeeb131SDaniel Scheller 195daeeb131SDaniel Scheller memset(&cmd, 0, sizeof(cmd)); 196525cac75SDaniel Scheller if (state->demod != DEMOD_UNUSED) { 197daeeb131SDaniel Scheller cmd.command = MCI_CMD_STOP; 198daeeb131SDaniel Scheller cmd.demod = state->demod; 199daeeb131SDaniel Scheller mci_cmd(state, &cmd, NULL); 200daeeb131SDaniel Scheller if (state->base->iq_mode) { 201daeeb131SDaniel Scheller cmd.command = MCI_CMD_STOP; 202daeeb131SDaniel Scheller cmd.demod = state->demod; 203daeeb131SDaniel Scheller cmd.output = 0; 204daeeb131SDaniel Scheller mci_cmd(state, &cmd, NULL); 205daeeb131SDaniel Scheller mci_config(state, SX8_TSCONFIG_MODE_NORMAL); 206daeeb131SDaniel Scheller } 207daeeb131SDaniel Scheller } 208daeeb131SDaniel Scheller mutex_lock(&state->base->tuner_lock); 209daeeb131SDaniel Scheller state->base->tuner_use_count[input]--; 210daeeb131SDaniel Scheller if (!state->base->tuner_use_count[input]) 211daeeb131SDaniel Scheller mci_set_tuner(fe, input, 0); 212525cac75SDaniel Scheller if (state->demod < MCI_DEMOD_MAX) 213daeeb131SDaniel Scheller state->base->demod_in_use[state->demod] = 0; 214daeeb131SDaniel Scheller state->base->used_ldpc_bitrate[state->nr] = 0; 215525cac75SDaniel Scheller state->demod = DEMOD_UNUSED; 216525cac75SDaniel Scheller state->base->assigned_demod[state->nr] = DEMOD_UNUSED; 217daeeb131SDaniel Scheller state->base->iq_mode = 0; 218daeeb131SDaniel Scheller mutex_unlock(&state->base->tuner_lock); 219daeeb131SDaniel Scheller state->started = 0; 220daeeb131SDaniel Scheller return 0; 221daeeb131SDaniel Scheller } 222daeeb131SDaniel Scheller 223daeeb131SDaniel Scheller static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) 224daeeb131SDaniel Scheller { 225daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 226daeeb131SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 227daeeb131SDaniel Scheller u32 used_ldpc_bitrate = 0, free_ldpc_bitrate; 228daeeb131SDaniel Scheller u32 used_demods = 0; 229daeeb131SDaniel Scheller struct mci_command cmd; 230daeeb131SDaniel Scheller u32 input = state->tuner; 231daeeb131SDaniel Scheller u32 bits_per_symbol = 0; 232daeeb131SDaniel Scheller int i, stat = 0; 233daeeb131SDaniel Scheller 234daeeb131SDaniel Scheller if (p->symbol_rate >= (MCLK / 2)) 235daeeb131SDaniel Scheller flags &= ~1; 236daeeb131SDaniel Scheller if ((flags & 3) == 0) 237daeeb131SDaniel Scheller return -EINVAL; 238daeeb131SDaniel Scheller 239daeeb131SDaniel Scheller if (flags & 2) { 240daeeb131SDaniel Scheller u32 tmp = modmask; 241daeeb131SDaniel Scheller 242daeeb131SDaniel Scheller bits_per_symbol = 1; 243daeeb131SDaniel Scheller while (tmp & 1) { 244daeeb131SDaniel Scheller tmp >>= 1; 245daeeb131SDaniel Scheller bits_per_symbol++; 246daeeb131SDaniel Scheller } 247daeeb131SDaniel Scheller } 248daeeb131SDaniel Scheller 249daeeb131SDaniel Scheller mutex_lock(&state->base->tuner_lock); 250daeeb131SDaniel Scheller if (state->base->iq_mode) { 251daeeb131SDaniel Scheller stat = -EBUSY; 252daeeb131SDaniel Scheller goto unlock; 253daeeb131SDaniel Scheller } 254525cac75SDaniel Scheller for (i = 0; i < MCI_DEMOD_MAX; i++) { 255daeeb131SDaniel Scheller used_ldpc_bitrate += state->base->used_ldpc_bitrate[i]; 256daeeb131SDaniel Scheller if (state->base->demod_in_use[i]) 257daeeb131SDaniel Scheller used_demods++; 258daeeb131SDaniel Scheller } 259daeeb131SDaniel Scheller if (used_ldpc_bitrate >= MAX_LDPC_BITRATE || 260daeeb131SDaniel Scheller ((ts_config & SX8_TSCONFIG_MODE_MASK) > 261daeeb131SDaniel Scheller SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) { 262daeeb131SDaniel Scheller stat = -EBUSY; 263daeeb131SDaniel Scheller goto unlock; 264daeeb131SDaniel Scheller } 265daeeb131SDaniel Scheller free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; 266daeeb131SDaniel Scheller if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) 267daeeb131SDaniel Scheller free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; 268daeeb131SDaniel Scheller 269daeeb131SDaniel Scheller while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) 270daeeb131SDaniel Scheller bits_per_symbol--; 271daeeb131SDaniel Scheller 272daeeb131SDaniel Scheller if (bits_per_symbol < 2) { 273daeeb131SDaniel Scheller stat = -EBUSY; 274daeeb131SDaniel Scheller goto unlock; 275daeeb131SDaniel Scheller } 276daeeb131SDaniel Scheller i = (p->symbol_rate > (MCLK / 2)) ? 3 : 7; 277daeeb131SDaniel Scheller while (i >= 0 && state->base->demod_in_use[i]) 278daeeb131SDaniel Scheller i--; 279daeeb131SDaniel Scheller if (i < 0) { 280daeeb131SDaniel Scheller stat = -EBUSY; 281daeeb131SDaniel Scheller goto unlock; 282daeeb131SDaniel Scheller } 283daeeb131SDaniel Scheller state->base->demod_in_use[i] = 1; 284daeeb131SDaniel Scheller state->base->used_ldpc_bitrate[state->nr] = p->symbol_rate 285daeeb131SDaniel Scheller * bits_per_symbol; 286daeeb131SDaniel Scheller state->demod = i; 287daeeb131SDaniel Scheller state->base->assigned_demod[state->nr] = i; 288daeeb131SDaniel Scheller 289daeeb131SDaniel Scheller if (!state->base->tuner_use_count[input]) 290daeeb131SDaniel Scheller mci_set_tuner(fe, input, 1); 291daeeb131SDaniel Scheller state->base->tuner_use_count[input]++; 292daeeb131SDaniel Scheller state->base->iq_mode = (ts_config > 1); 293daeeb131SDaniel Scheller unlock: 294daeeb131SDaniel Scheller mutex_unlock(&state->base->tuner_lock); 295daeeb131SDaniel Scheller if (stat) 296daeeb131SDaniel Scheller return stat; 297daeeb131SDaniel Scheller memset(&cmd, 0, sizeof(cmd)); 298daeeb131SDaniel Scheller 299daeeb131SDaniel Scheller if (state->base->iq_mode) { 300daeeb131SDaniel Scheller cmd.command = SX8_CMD_SELECT_IQOUT; 301daeeb131SDaniel Scheller cmd.demod = state->demod; 302daeeb131SDaniel Scheller cmd.output = 0; 303daeeb131SDaniel Scheller mci_cmd(state, &cmd, NULL); 304daeeb131SDaniel Scheller mci_config(state, ts_config); 305daeeb131SDaniel Scheller } 306daeeb131SDaniel Scheller if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) 307daeeb131SDaniel Scheller flags |= 0x80; 308daeeb131SDaniel Scheller dev_dbg(state->base->dev, "MCI-%d: tuner=%d demod=%d\n", 309daeeb131SDaniel Scheller state->nr, state->tuner, state->demod); 310daeeb131SDaniel Scheller cmd.command = MCI_CMD_SEARCH_DVBS; 311daeeb131SDaniel Scheller cmd.dvbs2_search.flags = flags; 312daeeb131SDaniel Scheller cmd.dvbs2_search.s2_modulation_mask = 313daeeb131SDaniel Scheller modmask & ((1 << (bits_per_symbol - 1)) - 1); 314daeeb131SDaniel Scheller cmd.dvbs2_search.retry = 2; 315daeeb131SDaniel Scheller cmd.dvbs2_search.frequency = p->frequency * 1000; 316daeeb131SDaniel Scheller cmd.dvbs2_search.symbol_rate = p->symbol_rate; 317daeeb131SDaniel Scheller cmd.dvbs2_search.scrambling_sequence_index = 318daeeb131SDaniel Scheller p->scrambling_sequence_index; 319daeeb131SDaniel Scheller cmd.dvbs2_search.input_stream_id = 320daeeb131SDaniel Scheller (p->stream_id != NO_STREAM_ID_FILTER) ? p->stream_id : 0; 321daeeb131SDaniel Scheller cmd.tuner = state->tuner; 322daeeb131SDaniel Scheller cmd.demod = state->demod; 323daeeb131SDaniel Scheller cmd.output = state->nr; 324daeeb131SDaniel Scheller if (p->stream_id == 0x80000000) 325daeeb131SDaniel Scheller cmd.output |= 0x80; 326daeeb131SDaniel Scheller stat = mci_cmd(state, &cmd, NULL); 327daeeb131SDaniel Scheller if (stat) 328daeeb131SDaniel Scheller stop(fe); 329daeeb131SDaniel Scheller return stat; 330daeeb131SDaniel Scheller } 331daeeb131SDaniel Scheller 332daeeb131SDaniel Scheller static int start_iq(struct dvb_frontend *fe, u32 ts_config) 333daeeb131SDaniel Scheller { 334daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 335daeeb131SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 336daeeb131SDaniel Scheller u32 used_demods = 0; 337daeeb131SDaniel Scheller struct mci_command cmd; 338daeeb131SDaniel Scheller u32 input = state->tuner; 339daeeb131SDaniel Scheller int i, stat = 0; 340daeeb131SDaniel Scheller 341daeeb131SDaniel Scheller mutex_lock(&state->base->tuner_lock); 342daeeb131SDaniel Scheller if (state->base->iq_mode) { 343daeeb131SDaniel Scheller stat = -EBUSY; 344daeeb131SDaniel Scheller goto unlock; 345daeeb131SDaniel Scheller } 346525cac75SDaniel Scheller for (i = 0; i < MCI_DEMOD_MAX; i++) 347daeeb131SDaniel Scheller if (state->base->demod_in_use[i]) 348daeeb131SDaniel Scheller used_demods++; 349daeeb131SDaniel Scheller if (used_demods > 0) { 350daeeb131SDaniel Scheller stat = -EBUSY; 351daeeb131SDaniel Scheller goto unlock; 352daeeb131SDaniel Scheller } 353daeeb131SDaniel Scheller state->demod = 0; 354daeeb131SDaniel Scheller state->base->assigned_demod[state->nr] = 0; 355daeeb131SDaniel Scheller if (!state->base->tuner_use_count[input]) 356daeeb131SDaniel Scheller mci_set_tuner(fe, input, 1); 357daeeb131SDaniel Scheller state->base->tuner_use_count[input]++; 358daeeb131SDaniel Scheller state->base->iq_mode = (ts_config > 1); 359daeeb131SDaniel Scheller unlock: 360daeeb131SDaniel Scheller mutex_unlock(&state->base->tuner_lock); 361daeeb131SDaniel Scheller if (stat) 362daeeb131SDaniel Scheller return stat; 363daeeb131SDaniel Scheller 364daeeb131SDaniel Scheller memset(&cmd, 0, sizeof(cmd)); 365daeeb131SDaniel Scheller cmd.command = SX8_CMD_START_IQ; 366daeeb131SDaniel Scheller cmd.dvbs2_search.frequency = p->frequency * 1000; 367daeeb131SDaniel Scheller cmd.dvbs2_search.symbol_rate = p->symbol_rate; 368daeeb131SDaniel Scheller cmd.tuner = state->tuner; 369daeeb131SDaniel Scheller cmd.demod = state->demod; 370daeeb131SDaniel Scheller cmd.output = 7; 371daeeb131SDaniel Scheller mci_config(state, ts_config); 372daeeb131SDaniel Scheller stat = mci_cmd(state, &cmd, NULL); 373daeeb131SDaniel Scheller if (stat) 374daeeb131SDaniel Scheller stop(fe); 375daeeb131SDaniel Scheller return stat; 376daeeb131SDaniel Scheller } 377daeeb131SDaniel Scheller 378daeeb131SDaniel Scheller static int set_parameters(struct dvb_frontend *fe) 379daeeb131SDaniel Scheller { 380daeeb131SDaniel Scheller int stat = 0; 381daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 382daeeb131SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 383daeeb131SDaniel Scheller u32 ts_config, iq_mode = 0, isi; 384daeeb131SDaniel Scheller 385daeeb131SDaniel Scheller if (state->started) 386daeeb131SDaniel Scheller stop(fe); 387daeeb131SDaniel Scheller 388daeeb131SDaniel Scheller isi = p->stream_id; 389daeeb131SDaniel Scheller if (isi != NO_STREAM_ID_FILTER) 390daeeb131SDaniel Scheller iq_mode = (isi & 0x30000000) >> 28; 391daeeb131SDaniel Scheller 392daeeb131SDaniel Scheller switch (iq_mode) { 393daeeb131SDaniel Scheller case 1: 394daeeb131SDaniel Scheller ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); 395daeeb131SDaniel Scheller break; 396daeeb131SDaniel Scheller case 2: 397daeeb131SDaniel Scheller ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); 398daeeb131SDaniel Scheller break; 399daeeb131SDaniel Scheller default: 400daeeb131SDaniel Scheller ts_config = SX8_TSCONFIG_MODE_NORMAL; 401daeeb131SDaniel Scheller break; 402daeeb131SDaniel Scheller } 403daeeb131SDaniel Scheller 404daeeb131SDaniel Scheller if (iq_mode != 2) { 405daeeb131SDaniel Scheller u32 flags = 3; 406daeeb131SDaniel Scheller u32 mask = 3; 407daeeb131SDaniel Scheller 408daeeb131SDaniel Scheller if (p->modulation == APSK_16 || 409daeeb131SDaniel Scheller p->modulation == APSK_32) { 410daeeb131SDaniel Scheller flags = 2; 411daeeb131SDaniel Scheller mask = 15; 412daeeb131SDaniel Scheller } 413daeeb131SDaniel Scheller stat = start(fe, flags, mask, ts_config); 414daeeb131SDaniel Scheller } else { 415daeeb131SDaniel Scheller stat = start_iq(fe, ts_config); 416daeeb131SDaniel Scheller } 417daeeb131SDaniel Scheller 418daeeb131SDaniel Scheller if (!stat) { 419daeeb131SDaniel Scheller state->started = 1; 420daeeb131SDaniel Scheller state->first_time_lock = 1; 421daeeb131SDaniel Scheller state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; 422daeeb131SDaniel Scheller } 423daeeb131SDaniel Scheller 424daeeb131SDaniel Scheller return stat; 425daeeb131SDaniel Scheller } 426daeeb131SDaniel Scheller 427daeeb131SDaniel Scheller static int tune(struct dvb_frontend *fe, bool re_tune, 428daeeb131SDaniel Scheller unsigned int mode_flags, 429daeeb131SDaniel Scheller unsigned int *delay, enum fe_status *status) 430daeeb131SDaniel Scheller { 431daeeb131SDaniel Scheller int r; 432daeeb131SDaniel Scheller 433daeeb131SDaniel Scheller if (re_tune) { 434daeeb131SDaniel Scheller r = set_parameters(fe); 435daeeb131SDaniel Scheller if (r) 436daeeb131SDaniel Scheller return r; 437daeeb131SDaniel Scheller } 438daeeb131SDaniel Scheller r = read_status(fe, status); 439daeeb131SDaniel Scheller if (r) 440daeeb131SDaniel Scheller return r; 441daeeb131SDaniel Scheller 442daeeb131SDaniel Scheller if (*status & FE_HAS_LOCK) 443daeeb131SDaniel Scheller return 0; 444daeeb131SDaniel Scheller *delay = HZ / 10; 445daeeb131SDaniel Scheller return 0; 446daeeb131SDaniel Scheller } 447daeeb131SDaniel Scheller 4488d718e53SLuc Van Oostenryck static enum dvbfe_algo get_algo(struct dvb_frontend *fe) 449daeeb131SDaniel Scheller { 450daeeb131SDaniel Scheller return DVBFE_ALGO_HW; 451daeeb131SDaniel Scheller } 452daeeb131SDaniel Scheller 453daeeb131SDaniel Scheller static int set_input(struct dvb_frontend *fe, int input) 454daeeb131SDaniel Scheller { 455daeeb131SDaniel Scheller struct mci *state = fe->demodulator_priv; 456daeeb131SDaniel Scheller 457daeeb131SDaniel Scheller state->tuner = input; 458daeeb131SDaniel Scheller dev_dbg(state->base->dev, "MCI-%d: input=%d\n", state->nr, input); 459daeeb131SDaniel Scheller return 0; 460daeeb131SDaniel Scheller } 461daeeb131SDaniel Scheller 462daeeb131SDaniel Scheller static struct dvb_frontend_ops mci_ops = { 463daeeb131SDaniel Scheller .delsys = { SYS_DVBS, SYS_DVBS2 }, 464daeeb131SDaniel Scheller .info = { 465daeeb131SDaniel Scheller .name = "Digital Devices MaxSX8 MCI DVB-S/S2/S2X", 466daeeb131SDaniel Scheller .frequency_min = 950000, 467daeeb131SDaniel Scheller .frequency_max = 2150000, 468daeeb131SDaniel Scheller .frequency_stepsize = 0, 469daeeb131SDaniel Scheller .frequency_tolerance = 0, 470daeeb131SDaniel Scheller .symbol_rate_min = 100000, 471daeeb131SDaniel Scheller .symbol_rate_max = 100000000, 472daeeb131SDaniel Scheller .caps = FE_CAN_INVERSION_AUTO | 473daeeb131SDaniel Scheller FE_CAN_FEC_AUTO | 474daeeb131SDaniel Scheller FE_CAN_QPSK | 475daeeb131SDaniel Scheller FE_CAN_2G_MODULATION | 476daeeb131SDaniel Scheller FE_CAN_MULTISTREAM, 477daeeb131SDaniel Scheller }, 478daeeb131SDaniel Scheller .get_frontend_algo = get_algo, 479daeeb131SDaniel Scheller .tune = tune, 480daeeb131SDaniel Scheller .release = release, 481daeeb131SDaniel Scheller .read_status = read_status, 482daeeb131SDaniel Scheller }; 483daeeb131SDaniel Scheller 484daeeb131SDaniel Scheller static struct mci_base *match_base(void *key) 485daeeb131SDaniel Scheller { 486daeeb131SDaniel Scheller struct mci_base *p; 487daeeb131SDaniel Scheller 488daeeb131SDaniel Scheller list_for_each_entry(p, &mci_list, mci_list) 489daeeb131SDaniel Scheller if (p->key == key) 490daeeb131SDaniel Scheller return p; 491daeeb131SDaniel Scheller return NULL; 492daeeb131SDaniel Scheller } 493daeeb131SDaniel Scheller 494daeeb131SDaniel Scheller static int probe(struct mci *state) 495daeeb131SDaniel Scheller { 496daeeb131SDaniel Scheller mci_reset(state); 497daeeb131SDaniel Scheller return 0; 498daeeb131SDaniel Scheller } 499daeeb131SDaniel Scheller 500daeeb131SDaniel Scheller struct dvb_frontend 501daeeb131SDaniel Scheller *ddb_mci_attach(struct ddb_input *input, 502daeeb131SDaniel Scheller int mci_type, int nr, 503caf2827cSDaniel Scheller int (**fn_set_input)(struct dvb_frontend *fe, int input)) 504daeeb131SDaniel Scheller { 505daeeb131SDaniel Scheller struct ddb_port *port = input->port; 506daeeb131SDaniel Scheller struct ddb *dev = port->dev; 507daeeb131SDaniel Scheller struct ddb_link *link = &dev->link[port->lnr]; 508daeeb131SDaniel Scheller struct mci_base *base; 509daeeb131SDaniel Scheller struct mci *state; 510daeeb131SDaniel Scheller void *key = mci_type ? (void *)port : (void *)link; 511daeeb131SDaniel Scheller 512daeeb131SDaniel Scheller state = kzalloc(sizeof(*state), GFP_KERNEL); 513daeeb131SDaniel Scheller if (!state) 514daeeb131SDaniel Scheller return NULL; 515daeeb131SDaniel Scheller 516daeeb131SDaniel Scheller base = match_base(key); 517daeeb131SDaniel Scheller if (base) { 518daeeb131SDaniel Scheller base->count++; 519daeeb131SDaniel Scheller state->base = base; 520daeeb131SDaniel Scheller } else { 521daeeb131SDaniel Scheller base = kzalloc(sizeof(*base), GFP_KERNEL); 522daeeb131SDaniel Scheller if (!base) 523daeeb131SDaniel Scheller goto fail; 524daeeb131SDaniel Scheller base->key = key; 525daeeb131SDaniel Scheller base->count = 1; 526daeeb131SDaniel Scheller base->link = link; 527daeeb131SDaniel Scheller base->dev = dev->dev; 528daeeb131SDaniel Scheller mutex_init(&base->mci_lock); 529daeeb131SDaniel Scheller mutex_init(&base->tuner_lock); 530daeeb131SDaniel Scheller ddb_irq_set(dev, link->nr, 0, mci_handler, base); 531daeeb131SDaniel Scheller init_completion(&base->completion); 532daeeb131SDaniel Scheller state->base = base; 533daeeb131SDaniel Scheller if (probe(state) < 0) { 534daeeb131SDaniel Scheller kfree(base); 535daeeb131SDaniel Scheller goto fail; 536daeeb131SDaniel Scheller } 537daeeb131SDaniel Scheller list_add(&base->mci_list, &mci_list); 538daeeb131SDaniel Scheller } 539daeeb131SDaniel Scheller state->fe.ops = mci_ops; 540daeeb131SDaniel Scheller state->fe.demodulator_priv = state; 541daeeb131SDaniel Scheller state->nr = nr; 542daeeb131SDaniel Scheller *fn_set_input = set_input; 543daeeb131SDaniel Scheller 544daeeb131SDaniel Scheller state->tuner = nr; 545daeeb131SDaniel Scheller state->demod = nr; 546daeeb131SDaniel Scheller 547daeeb131SDaniel Scheller return &state->fe; 548daeeb131SDaniel Scheller fail: 549daeeb131SDaniel Scheller kfree(state); 550daeeb131SDaniel Scheller return NULL; 551daeeb131SDaniel Scheller } 552