xref: /linux/drivers/media/pci/ddbridge/ddbridge-mci.c (revision 3addf0fa820b3da34e0c0e532167afcee8089a3b)
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