diff options
author | Jason Gunthorpe <jgg@mellanox.com> | 2018-08-16 23:13:03 +0300 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-08-16 23:21:29 +0300 |
commit | 0a3173a5f09bc58a3638ecfd0a80bdbae55e123c (patch) | |
tree | d6c0bc84863cca54dfbde3b7463e5d49c82af9f1 /drivers/media/pci/ddbridge/ddbridge-mci.c | |
parent | 92f4e77c85918eab5e5803d7e28ab89a7e6bd3a2 (diff) | |
parent | 5c60a7389d795e001c8748b458eb76e3a5b6008c (diff) | |
download | linux-0a3173a5f09bc58a3638ecfd0a80bdbae55e123c.tar.xz |
Merge branch 'linus/master' into rdma.git for-next
rdma.git merge resolution for the 4.19 merge window
Conflicts:
drivers/infiniband/core/rdma_core.c
- Use the rdma code and revise with the new spelling for
atomic_fetch_add_unless
drivers/nvme/host/rdma.c
- Replace max_sge with max_send_sge in new blk code
drivers/nvme/target/rdma.c
- Use the blk code and revise to use NULL for ib_post_recv when
appropriate
- Replace max_sge with max_recv_sge in new blk code
net/rds/ib_send.c
- Use the net code and revise to use NULL for ib_post_recv when
appropriate
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/media/pci/ddbridge/ddbridge-mci.c')
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge-mci.c | 409 |
1 files changed, 18 insertions, 391 deletions
diff --git a/drivers/media/pci/ddbridge/ddbridge-mci.c b/drivers/media/pci/ddbridge/ddbridge-mci.c index 4ac634fc96e4..97384ae9ad27 100644 --- a/drivers/media/pci/ddbridge/ddbridge-mci.c +++ b/drivers/media/pci/ddbridge/ddbridge-mci.c @@ -2,9 +2,9 @@ /* * ddbridge-mci.c: Digital Devices microcode interface * - * Copyright (C) 2017 Digital Devices GmbH - * Ralph Metzler <rjkm@metzlerbros.de> - * Marcus Metzler <mocm@metzlerbros.de> + * Copyright (C) 2017-2018 Digital Devices GmbH + * Ralph Metzler <rjkm@metzlerbros.de> + * Marcus Metzler <mocm@metzlerbros.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,42 +22,6 @@ static LIST_HEAD(mci_list); -static const u32 MCLK = (1550000000 / 12); -static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); -static const u32 MAX_LDPC_BITRATE = (720000000); - -struct mci_base { - struct list_head mci_list; - void *key; - struct ddb_link *link; - struct completion completion; - - struct device *dev; - struct mutex tuner_lock; /* concurrent tuner access lock */ - u8 adr; - struct mutex mci_lock; /* concurrent MCI access lock */ - int count; - - u8 tuner_use_count[MCI_TUNER_MAX]; - u8 assigned_demod[MCI_DEMOD_MAX]; - u32 used_ldpc_bitrate[MCI_DEMOD_MAX]; - u8 demod_in_use[MCI_DEMOD_MAX]; - u32 iq_mode; -}; - -struct mci { - struct mci_base *base; - struct dvb_frontend fe; - int nr; - int demod; - int tuner; - int first_time_lock; - int started; - struct mci_result signal_info; - - u32 bb_mode; -}; - static int mci_reset(struct mci *state) { struct ddb_link *link = state->base->link; @@ -84,7 +48,7 @@ static int mci_reset(struct mci *state) return 0; } -static int mci_config(struct mci *state, u32 config) +int ddb_mci_config(struct mci *state, u32 config) { struct ddb_link *link = state->base->link; @@ -122,16 +86,16 @@ static int _mci_cmd_unlocked(struct mci *state, return 0; } -static int mci_cmd(struct mci *state, - struct mci_command *command, - struct mci_result *result) +int ddb_mci_cmd(struct mci *state, + struct mci_command *command, + struct mci_result *result) { int stat; mutex_lock(&state->base->mci_lock); stat = _mci_cmd_unlocked(state, (u32 *)command, sizeof(*command) / sizeof(u32), - (u32 *)result, sizeof(*result) / sizeof(u32)); + (u32 *)result, sizeof(*result) / sizeof(u32)); mutex_unlock(&state->base->mci_lock); return stat; } @@ -143,344 +107,6 @@ static void mci_handler(void *priv) complete(&base->completion); } -static void release(struct dvb_frontend *fe) -{ - struct mci *state = fe->demodulator_priv; - - state->base->count--; - if (state->base->count == 0) { - list_del(&state->base->mci_list); - kfree(state->base); - } - kfree(state); -} - -static int read_status(struct dvb_frontend *fe, enum fe_status *status) -{ - int stat; - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - struct mci_result res; - - cmd.command = MCI_CMD_GETSTATUS; - cmd.demod = state->demod; - stat = mci_cmd(state, &cmd, &res); - if (stat) - return stat; - *status = 0x00; - if (res.status == SX8_DEMOD_WAIT_MATYPE) - *status = 0x0f; - if (res.status == SX8_DEMOD_LOCKED) - *status = 0x1f; - return stat; -} - -static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) -{ - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.tuner = state->tuner; - cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; - return mci_cmd(state, &cmd, NULL); -} - -static int stop(struct dvb_frontend *fe) -{ - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - u32 input = state->tuner; - - memset(&cmd, 0, sizeof(cmd)); - if (state->demod != DEMOD_UNUSED) { - cmd.command = MCI_CMD_STOP; - cmd.demod = state->demod; - 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]--; - if (!state->base->tuner_use_count[input]) - mci_set_tuner(fe, input, 0); - if (state->demod < MCI_DEMOD_MAX) - state->base->demod_in_use[state->demod] = 0; - state->base->used_ldpc_bitrate[state->nr] = 0; - state->demod = DEMOD_UNUSED; - state->base->assigned_demod[state->nr] = DEMOD_UNUSED; - state->base->iq_mode = 0; - mutex_unlock(&state->base->tuner_lock); - state->started = 0; - return 0; -} - -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; - u32 used_ldpc_bitrate = 0, free_ldpc_bitrate; - u32 used_demods = 0; - struct mci_command cmd; - u32 input = state->tuner; - 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); - if (state->base->iq_mode) { - stat = -EBUSY; - goto unlock; - } - for (i = 0; i < MCI_DEMOD_MAX; i++) { - used_ldpc_bitrate += state->base->used_ldpc_bitrate[i]; - 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; - } - free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; - if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) - free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; - - while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) - bits_per_symbol--; - - if (bits_per_symbol < 2) { - stat = -EBUSY; - goto unlock; - } - i = (p->symbol_rate > (MCLK / 2)) ? 3 : 7; - while (i >= 0 && state->base->demod_in_use[i]) - i--; - if (i < 0) { - stat = -EBUSY; - goto unlock; - } - state->base->demod_in_use[i] = 1; - state->base->used_ldpc_bitrate[state->nr] = p->symbol_rate - * bits_per_symbol; - state->demod = i; - state->base->assigned_demod[state->nr] = i; - - 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); - } - if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) - flags |= 0x80; - dev_dbg(state->base->dev, "MCI-%d: tuner=%d demod=%d\n", - state->nr, state->tuner, state->demod); - 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 = 2; - cmd.dvbs2_search.frequency = p->frequency * 1000; - cmd.dvbs2_search.symbol_rate = p->symbol_rate; - cmd.dvbs2_search.scrambling_sequence_index = - p->scrambling_sequence_index; - 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; - if (p->stream_id == 0x80000000) - cmd.output |= 0x80; - 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; - 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 < MCI_DEMOD_MAX; i++) - if (state->base->demod_in_use[i]) - used_demods++; - if (used_demods > 0) { - stat = -EBUSY; - goto unlock; - } - state->demod = 0; - 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; - - memset(&cmd, 0, sizeof(cmd)); - 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; -} - -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); - - 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; - state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; - } - - return stat; -} - -static int tune(struct dvb_frontend *fe, bool re_tune, - unsigned int mode_flags, - unsigned int *delay, enum fe_status *status) -{ - int r; - - if (re_tune) { - r = set_parameters(fe); - if (r) - return r; - } - r = read_status(fe, status); - if (r) - return r; - - if (*status & FE_HAS_LOCK) - return 0; - *delay = HZ / 10; - return 0; -} - -static enum dvbfe_algo get_algo(struct dvb_frontend *fe) -{ - return DVBFE_ALGO_HW; -} - -static int set_input(struct dvb_frontend *fe, int input) -{ - struct mci *state = fe->demodulator_priv; - - state->tuner = input; - dev_dbg(state->base->dev, "MCI-%d: input=%d\n", state->nr, input); - return 0; -} - -static struct dvb_frontend_ops mci_ops = { - .delsys = { SYS_DVBS, SYS_DVBS2 }, - .info = { - .name = "Digital Devices MaxSX8 MCI DVB-S/S2/S2X", - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 0, - .frequency_tolerance = 0, - .symbol_rate_min = 100000, - .symbol_rate_max = 100000000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | - FE_CAN_2G_MODULATION | - FE_CAN_MULTISTREAM, - }, - .get_frontend_algo = get_algo, - .tune = tune, - .release = release, - .read_status = read_status, -}; - static struct mci_base *match_base(void *key) { struct mci_base *p; @@ -498,8 +124,7 @@ static int probe(struct mci *state) } struct dvb_frontend -*ddb_mci_attach(struct ddb_input *input, - int mci_type, int nr, +*ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int (**fn_set_input)(struct dvb_frontend *fe, int input)) { struct ddb_port *port = input->port; @@ -507,9 +132,9 @@ struct dvb_frontend struct ddb_link *link = &dev->link[port->lnr]; struct mci_base *base; struct mci *state; - void *key = mci_type ? (void *)port : (void *)link; + void *key = cfg->type ? (void *)port : (void *)link; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = kzalloc(cfg->state_size, GFP_KERNEL); if (!state) return NULL; @@ -518,7 +143,7 @@ struct dvb_frontend base->count++; state->base = base; } else { - base = kzalloc(sizeof(*base), GFP_KERNEL); + base = kzalloc(cfg->base_size, GFP_KERNEL); if (!base) goto fail; base->key = key; @@ -535,15 +160,17 @@ struct dvb_frontend goto fail; } list_add(&base->mci_list, &mci_list); + if (cfg->base_init) + cfg->base_init(base); } - state->fe.ops = mci_ops; + memcpy(&state->fe.ops, cfg->fe_ops, sizeof(struct dvb_frontend_ops)); state->fe.demodulator_priv = state; state->nr = nr; - *fn_set_input = set_input; - + *fn_set_input = cfg->set_input; state->tuner = nr; state->demod = nr; - + if (cfg->init) + cfg->init(state); return &state->fe; fail: kfree(state); |