xref: /openbmc/linux/drivers/media/pci/cx88/cx88-dvb.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2b285192aSMauro Carvalho Chehab /*
3b285192aSMauro Carvalho Chehab  * device driver for Conexant 2388x based TV cards
4b285192aSMauro Carvalho Chehab  * MPEG Transport Stream (DVB) routines
5b285192aSMauro Carvalho Chehab  *
6b285192aSMauro Carvalho Chehab  * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
7b285192aSMauro Carvalho Chehab  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8b285192aSMauro Carvalho Chehab  */
9b285192aSMauro Carvalho Chehab 
1065bc2fe8SMauro Carvalho Chehab #include "cx88.h"
1165bc2fe8SMauro Carvalho Chehab #include "dvb-pll.h"
1265bc2fe8SMauro Carvalho Chehab 
13b285192aSMauro Carvalho Chehab #include <linux/module.h>
14b285192aSMauro Carvalho Chehab #include <linux/init.h>
15b285192aSMauro Carvalho Chehab #include <linux/device.h>
16b285192aSMauro Carvalho Chehab #include <linux/fs.h>
17b285192aSMauro Carvalho Chehab #include <linux/kthread.h>
18b285192aSMauro Carvalho Chehab #include <linux/file.h>
19b285192aSMauro Carvalho Chehab #include <linux/suspend.h>
20b285192aSMauro Carvalho Chehab 
21b285192aSMauro Carvalho Chehab #include <media/v4l2-common.h>
22b285192aSMauro Carvalho Chehab 
23b285192aSMauro Carvalho Chehab #include "mt352.h"
24b285192aSMauro Carvalho Chehab #include "mt352_priv.h"
25b285192aSMauro Carvalho Chehab #include "cx88-vp3054-i2c.h"
26b285192aSMauro Carvalho Chehab #include "zl10353.h"
27b285192aSMauro Carvalho Chehab #include "cx22702.h"
28b285192aSMauro Carvalho Chehab #include "or51132.h"
29b285192aSMauro Carvalho Chehab #include "lgdt330x.h"
30b285192aSMauro Carvalho Chehab #include "s5h1409.h"
31b285192aSMauro Carvalho Chehab #include "xc4000.h"
32b285192aSMauro Carvalho Chehab #include "xc5000.h"
33b285192aSMauro Carvalho Chehab #include "nxt200x.h"
34b285192aSMauro Carvalho Chehab #include "cx24123.h"
35b285192aSMauro Carvalho Chehab #include "isl6421.h"
36b285192aSMauro Carvalho Chehab #include "tuner-simple.h"
37b285192aSMauro Carvalho Chehab #include "tda9887.h"
38b285192aSMauro Carvalho Chehab #include "s5h1411.h"
39b285192aSMauro Carvalho Chehab #include "stv0299.h"
40b285192aSMauro Carvalho Chehab #include "z0194a.h"
41b285192aSMauro Carvalho Chehab #include "stv0288.h"
42b285192aSMauro Carvalho Chehab #include "stb6000.h"
43b285192aSMauro Carvalho Chehab #include "cx24116.h"
44b285192aSMauro Carvalho Chehab #include "stv0900.h"
45b285192aSMauro Carvalho Chehab #include "stb6100.h"
46b285192aSMauro Carvalho Chehab #include "stb6100_proc.h"
47b285192aSMauro Carvalho Chehab #include "mb86a16.h"
4873f0af44SKonstantin Dimitrov #include "ts2020.h"
49b285192aSMauro Carvalho Chehab #include "ds3000.h"
50b285192aSMauro Carvalho Chehab 
51b285192aSMauro Carvalho Chehab MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
52b285192aSMauro Carvalho Chehab MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
53b285192aSMauro Carvalho Chehab MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
54b285192aSMauro Carvalho Chehab MODULE_LICENSE("GPL");
55b285192aSMauro Carvalho Chehab MODULE_VERSION(CX88_VERSION);
56b285192aSMauro Carvalho Chehab 
57b285192aSMauro Carvalho Chehab static unsigned int debug;
58b285192aSMauro Carvalho Chehab module_param(debug, int, 0644);
59b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
60b285192aSMauro Carvalho Chehab 
61b285192aSMauro Carvalho Chehab static unsigned int dvb_buf_tscnt = 32;
62b285192aSMauro Carvalho Chehab module_param(dvb_buf_tscnt, int, 0644);
63b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]");
64b285192aSMauro Carvalho Chehab 
65b285192aSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
66b285192aSMauro Carvalho Chehab 
6765bc2fe8SMauro Carvalho Chehab #define dprintk(level, fmt, arg...) do {				\
6865bc2fe8SMauro Carvalho Chehab 	if (debug >= level)						\
6965bc2fe8SMauro Carvalho Chehab 		printk(KERN_DEBUG pr_fmt("%s: dvb:" fmt),		\
7065bc2fe8SMauro Carvalho Chehab 			__func__, ##arg);				\
7165bc2fe8SMauro Carvalho Chehab } while (0)
72b285192aSMauro Carvalho Chehab 
73b285192aSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
74b285192aSMauro Carvalho Chehab 
queue_setup(struct vb2_queue * q,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_devs[])75df9ecb0cSHans Verkuil static int queue_setup(struct vb2_queue *q,
760b6b6302SHans Verkuil 		       unsigned int *num_buffers, unsigned int *num_planes,
7736c0f8b3SHans Verkuil 		       unsigned int sizes[], struct device *alloc_devs[])
78b285192aSMauro Carvalho Chehab {
790b6b6302SHans Verkuil 	struct cx8802_dev *dev = q->drv_priv;
80b285192aSMauro Carvalho Chehab 
810b6b6302SHans Verkuil 	*num_planes = 1;
82b285192aSMauro Carvalho Chehab 	dev->ts_packet_size  = 188 * 4;
83b285192aSMauro Carvalho Chehab 	dev->ts_packet_count = dvb_buf_tscnt;
840b6b6302SHans Verkuil 	sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
850b6b6302SHans Verkuil 	*num_buffers = dvb_buf_tscnt;
86b285192aSMauro Carvalho Chehab 	return 0;
87b285192aSMauro Carvalho Chehab }
88b285192aSMauro Carvalho Chehab 
buffer_prepare(struct vb2_buffer * vb)890b6b6302SHans Verkuil static int buffer_prepare(struct vb2_buffer *vb)
90b285192aSMauro Carvalho Chehab {
912d700715SJunghak Sung 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
920b6b6302SHans Verkuil 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
932d700715SJunghak Sung 	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
940b6b6302SHans Verkuil 
95ccd6f1d4SHans Verkuil 	return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
96b285192aSMauro Carvalho Chehab }
97b285192aSMauro Carvalho Chehab 
buffer_finish(struct vb2_buffer * vb)980b6b6302SHans Verkuil static void buffer_finish(struct vb2_buffer *vb)
99b285192aSMauro Carvalho Chehab {
1002d700715SJunghak Sung 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1010b6b6302SHans Verkuil 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
1022d700715SJunghak Sung 	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
1035e7045e3SHans Verkuil 	struct cx88_riscmem *risc = &buf->risc;
1040b6b6302SHans Verkuil 
1055e7045e3SHans Verkuil 	if (risc->cpu)
106*00ae4ebcSChristophe JAILLET 		dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu,
107*00ae4ebcSChristophe JAILLET 				  risc->dma);
1085e7045e3SHans Verkuil 	memset(risc, 0, sizeof(*risc));
109b285192aSMauro Carvalho Chehab }
110b285192aSMauro Carvalho Chehab 
buffer_queue(struct vb2_buffer * vb)1110b6b6302SHans Verkuil static void buffer_queue(struct vb2_buffer *vb)
112b285192aSMauro Carvalho Chehab {
1132d700715SJunghak Sung 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1140b6b6302SHans Verkuil 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
1152d700715SJunghak Sung 	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
1160b6b6302SHans Verkuil 
1170b6b6302SHans Verkuil 	cx8802_buf_queue(dev, buf);
118b285192aSMauro Carvalho Chehab }
119b285192aSMauro Carvalho Chehab 
start_streaming(struct vb2_queue * q,unsigned int count)1200b6b6302SHans Verkuil static int start_streaming(struct vb2_queue *q, unsigned int count)
1210b6b6302SHans Verkuil {
1220b6b6302SHans Verkuil 	struct cx8802_dev *dev = q->drv_priv;
1230b6b6302SHans Verkuil 	struct cx88_dmaqueue *dmaq = &dev->mpegq;
1240b6b6302SHans Verkuil 	struct cx88_buffer *buf;
1250b6b6302SHans Verkuil 
1260b6b6302SHans Verkuil 	buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
1270b6b6302SHans Verkuil 	cx8802_start_dma(dev, dmaq, buf);
1280b6b6302SHans Verkuil 	return 0;
1290b6b6302SHans Verkuil }
1300b6b6302SHans Verkuil 
stop_streaming(struct vb2_queue * q)1310b6b6302SHans Verkuil static void stop_streaming(struct vb2_queue *q)
1320b6b6302SHans Verkuil {
1330b6b6302SHans Verkuil 	struct cx8802_dev *dev = q->drv_priv;
1340b6b6302SHans Verkuil 	struct cx88_dmaqueue *dmaq = &dev->mpegq;
1350b6b6302SHans Verkuil 	unsigned long flags;
1360b6b6302SHans Verkuil 
1370b6b6302SHans Verkuil 	cx8802_cancel_buffers(dev);
1380b6b6302SHans Verkuil 
1390b6b6302SHans Verkuil 	spin_lock_irqsave(&dev->slock, flags);
1400b6b6302SHans Verkuil 	while (!list_empty(&dmaq->active)) {
1410b6b6302SHans Verkuil 		struct cx88_buffer *buf = list_entry(dmaq->active.next,
1420b6b6302SHans Verkuil 			struct cx88_buffer, list);
1430b6b6302SHans Verkuil 
1440b6b6302SHans Verkuil 		list_del(&buf->list);
1452d700715SJunghak Sung 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
1460b6b6302SHans Verkuil 	}
1470b6b6302SHans Verkuil 	spin_unlock_irqrestore(&dev->slock, flags);
1480b6b6302SHans Verkuil }
1490b6b6302SHans Verkuil 
15010accd2eSJulia Lawall static const struct vb2_ops dvb_qops = {
1510b6b6302SHans Verkuil 	.queue_setup    = queue_setup,
1520b6b6302SHans Verkuil 	.buf_prepare  = buffer_prepare,
1530b6b6302SHans Verkuil 	.buf_finish = buffer_finish,
1540b6b6302SHans Verkuil 	.buf_queue    = buffer_queue,
1550b6b6302SHans Verkuil 	.wait_prepare = vb2_ops_wait_prepare,
1560b6b6302SHans Verkuil 	.wait_finish = vb2_ops_wait_finish,
1570b6b6302SHans Verkuil 	.start_streaming = start_streaming,
1580b6b6302SHans Verkuil 	.stop_streaming = stop_streaming,
159b285192aSMauro Carvalho Chehab };
160b285192aSMauro Carvalho Chehab 
161b285192aSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
162b285192aSMauro Carvalho Chehab 
cx88_dvb_bus_ctrl(struct dvb_frontend * fe,int acquire)163b285192aSMauro Carvalho Chehab static int cx88_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
164b285192aSMauro Carvalho Chehab {
165b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
166b285192aSMauro Carvalho Chehab 	struct cx8802_driver *drv = NULL;
167b285192aSMauro Carvalho Chehab 	int ret = 0;
168b285192aSMauro Carvalho Chehab 	int fe_id;
169b285192aSMauro Carvalho Chehab 
1700b6b6302SHans Verkuil 	fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
171b285192aSMauro Carvalho Chehab 	if (!fe_id) {
17265bc2fe8SMauro Carvalho Chehab 		pr_err("%s() No frontend found\n", __func__);
173b285192aSMauro Carvalho Chehab 		return -EINVAL;
174b285192aSMauro Carvalho Chehab 	}
175b285192aSMauro Carvalho Chehab 
176b285192aSMauro Carvalho Chehab 	mutex_lock(&dev->core->lock);
177b285192aSMauro Carvalho Chehab 	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
178b285192aSMauro Carvalho Chehab 	if (drv) {
179b285192aSMauro Carvalho Chehab 		if (acquire) {
180b285192aSMauro Carvalho Chehab 			dev->frontends.active_fe_id = fe_id;
181b285192aSMauro Carvalho Chehab 			ret = drv->request_acquire(drv);
182b285192aSMauro Carvalho Chehab 		} else {
183b285192aSMauro Carvalho Chehab 			ret = drv->request_release(drv);
184b285192aSMauro Carvalho Chehab 			dev->frontends.active_fe_id = 0;
185b285192aSMauro Carvalho Chehab 		}
186b285192aSMauro Carvalho Chehab 	}
187b285192aSMauro Carvalho Chehab 	mutex_unlock(&dev->core->lock);
188b285192aSMauro Carvalho Chehab 
189b285192aSMauro Carvalho Chehab 	return ret;
190b285192aSMauro Carvalho Chehab }
191b285192aSMauro Carvalho Chehab 
cx88_dvb_gate_ctrl(struct cx88_core * core,int open)192b285192aSMauro Carvalho Chehab static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
193b285192aSMauro Carvalho Chehab {
1940b6b6302SHans Verkuil 	struct vb2_dvb_frontends *f;
1950b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe;
196b285192aSMauro Carvalho Chehab 
197b285192aSMauro Carvalho Chehab 	if (!core->dvbdev)
198b285192aSMauro Carvalho Chehab 		return;
199b285192aSMauro Carvalho Chehab 
200b285192aSMauro Carvalho Chehab 	f = &core->dvbdev->frontends;
201b285192aSMauro Carvalho Chehab 
202b285192aSMauro Carvalho Chehab 	if (!f)
203b285192aSMauro Carvalho Chehab 		return;
204b285192aSMauro Carvalho Chehab 
205b285192aSMauro Carvalho Chehab 	if (f->gate <= 1) /* undefined or fe0 */
2060b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(f, 1);
207b285192aSMauro Carvalho Chehab 	else
2080b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(f, f->gate);
209b285192aSMauro Carvalho Chehab 
210b285192aSMauro Carvalho Chehab 	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
211b285192aSMauro Carvalho Chehab 		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
212b285192aSMauro Carvalho Chehab }
213b285192aSMauro Carvalho Chehab 
214b285192aSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
215b285192aSMauro Carvalho Chehab 
dvico_fusionhdtv_demod_init(struct dvb_frontend * fe)216b285192aSMauro Carvalho Chehab static int dvico_fusionhdtv_demod_init(struct dvb_frontend *fe)
217b285192aSMauro Carvalho Chehab {
218b285192aSMauro Carvalho Chehab 	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x39 };
219b285192aSMauro Carvalho Chehab 	static const u8 reset[]         = { RESET,      0x80 };
220b285192aSMauro Carvalho Chehab 	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
221b285192aSMauro Carvalho Chehab 	static const u8 agc_cfg[]       = { AGC_TARGET, 0x24, 0x20 };
222b285192aSMauro Carvalho Chehab 	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
223b285192aSMauro Carvalho Chehab 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
224b285192aSMauro Carvalho Chehab 
225b285192aSMauro Carvalho Chehab 	mt352_write(fe, clock_config,   sizeof(clock_config));
226b285192aSMauro Carvalho Chehab 	udelay(200);
227b285192aSMauro Carvalho Chehab 	mt352_write(fe, reset,          sizeof(reset));
228b285192aSMauro Carvalho Chehab 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
229b285192aSMauro Carvalho Chehab 
230b285192aSMauro Carvalho Chehab 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
231b285192aSMauro Carvalho Chehab 	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
232b285192aSMauro Carvalho Chehab 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
233b285192aSMauro Carvalho Chehab 	return 0;
234b285192aSMauro Carvalho Chehab }
235b285192aSMauro Carvalho Chehab 
dvico_dual_demod_init(struct dvb_frontend * fe)236b285192aSMauro Carvalho Chehab static int dvico_dual_demod_init(struct dvb_frontend *fe)
237b285192aSMauro Carvalho Chehab {
238b285192aSMauro Carvalho Chehab 	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x38 };
239b285192aSMauro Carvalho Chehab 	static const u8 reset[]         = { RESET,      0x80 };
240b285192aSMauro Carvalho Chehab 	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
241b285192aSMauro Carvalho Chehab 	static const u8 agc_cfg[]       = { AGC_TARGET, 0x28, 0x20 };
242b285192aSMauro Carvalho Chehab 	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
243b285192aSMauro Carvalho Chehab 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
244b285192aSMauro Carvalho Chehab 
245b285192aSMauro Carvalho Chehab 	mt352_write(fe, clock_config,   sizeof(clock_config));
246b285192aSMauro Carvalho Chehab 	udelay(200);
247b285192aSMauro Carvalho Chehab 	mt352_write(fe, reset,          sizeof(reset));
248b285192aSMauro Carvalho Chehab 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
249b285192aSMauro Carvalho Chehab 
250b285192aSMauro Carvalho Chehab 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
251b285192aSMauro Carvalho Chehab 	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
252b285192aSMauro Carvalho Chehab 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
253b285192aSMauro Carvalho Chehab 
254b285192aSMauro Carvalho Chehab 	return 0;
255b285192aSMauro Carvalho Chehab }
256b285192aSMauro Carvalho Chehab 
dntv_live_dvbt_demod_init(struct dvb_frontend * fe)257b285192aSMauro Carvalho Chehab static int dntv_live_dvbt_demod_init(struct dvb_frontend *fe)
258b285192aSMauro Carvalho Chehab {
259b285192aSMauro Carvalho Chehab 	static const u8 clock_config[]  = { 0x89, 0x38, 0x39 };
260b285192aSMauro Carvalho Chehab 	static const u8 reset[]         = { 0x50, 0x80 };
261b285192aSMauro Carvalho Chehab 	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
262b285192aSMauro Carvalho Chehab 	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
263b285192aSMauro Carvalho Chehab 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
264b285192aSMauro Carvalho Chehab 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
265b285192aSMauro Carvalho Chehab 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
266b285192aSMauro Carvalho Chehab 
267b285192aSMauro Carvalho Chehab 	mt352_write(fe, clock_config,   sizeof(clock_config));
268b285192aSMauro Carvalho Chehab 	udelay(2000);
269b285192aSMauro Carvalho Chehab 	mt352_write(fe, reset,          sizeof(reset));
270b285192aSMauro Carvalho Chehab 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
271b285192aSMauro Carvalho Chehab 
272b285192aSMauro Carvalho Chehab 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
273b285192aSMauro Carvalho Chehab 	udelay(2000);
274b285192aSMauro Carvalho Chehab 	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
275b285192aSMauro Carvalho Chehab 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
276b285192aSMauro Carvalho Chehab 
277b285192aSMauro Carvalho Chehab 	return 0;
278b285192aSMauro Carvalho Chehab }
279b285192aSMauro Carvalho Chehab 
280b285192aSMauro Carvalho Chehab static const struct mt352_config dvico_fusionhdtv = {
281b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
282b285192aSMauro Carvalho Chehab 	.demod_init    = dvico_fusionhdtv_demod_init,
283b285192aSMauro Carvalho Chehab };
284b285192aSMauro Carvalho Chehab 
285b285192aSMauro Carvalho Chehab static const struct mt352_config dntv_live_dvbt_config = {
286b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
287b285192aSMauro Carvalho Chehab 	.demod_init    = dntv_live_dvbt_demod_init,
288b285192aSMauro Carvalho Chehab };
289b285192aSMauro Carvalho Chehab 
290b285192aSMauro Carvalho Chehab static const struct mt352_config dvico_fusionhdtv_dual = {
291b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
292b285192aSMauro Carvalho Chehab 	.demod_init    = dvico_dual_demod_init,
293b285192aSMauro Carvalho Chehab };
294b285192aSMauro Carvalho Chehab 
295b285192aSMauro Carvalho Chehab static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
296b285192aSMauro Carvalho Chehab 	.demod_address = (0x1e >> 1),
297b285192aSMauro Carvalho Chehab 	.no_tuner      = 1,
298b285192aSMauro Carvalho Chehab 	.if2           = 45600,
299b285192aSMauro Carvalho Chehab };
300b285192aSMauro Carvalho Chehab 
3010244fd78SBhumika Goyal static const struct mb86a16_config twinhan_vp1027 = {
302b285192aSMauro Carvalho Chehab 	.demod_address  = 0x08,
303b285192aSMauro Carvalho Chehab };
304b285192aSMauro Carvalho Chehab 
3057b34be71SPeter Senna Tschudin #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
dntv_live_dvbt_pro_demod_init(struct dvb_frontend * fe)306b285192aSMauro Carvalho Chehab static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend *fe)
307b285192aSMauro Carvalho Chehab {
308b285192aSMauro Carvalho Chehab 	static const u8 clock_config[]  = { 0x89, 0x38, 0x38 };
309b285192aSMauro Carvalho Chehab 	static const u8 reset[]         = { 0x50, 0x80 };
310b285192aSMauro Carvalho Chehab 	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
311b285192aSMauro Carvalho Chehab 	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
312b285192aSMauro Carvalho Chehab 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
313b285192aSMauro Carvalho Chehab 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
314b285192aSMauro Carvalho Chehab 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
315b285192aSMauro Carvalho Chehab 
316b285192aSMauro Carvalho Chehab 	mt352_write(fe, clock_config,   sizeof(clock_config));
317b285192aSMauro Carvalho Chehab 	udelay(2000);
318b285192aSMauro Carvalho Chehab 	mt352_write(fe, reset,          sizeof(reset));
319b285192aSMauro Carvalho Chehab 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
320b285192aSMauro Carvalho Chehab 
321b285192aSMauro Carvalho Chehab 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
322b285192aSMauro Carvalho Chehab 	udelay(2000);
323b285192aSMauro Carvalho Chehab 	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
324b285192aSMauro Carvalho Chehab 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
325b285192aSMauro Carvalho Chehab 
326b285192aSMauro Carvalho Chehab 	return 0;
327b285192aSMauro Carvalho Chehab }
328b285192aSMauro Carvalho Chehab 
329b285192aSMauro Carvalho Chehab static const struct mt352_config dntv_live_dvbt_pro_config = {
330b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
331b285192aSMauro Carvalho Chehab 	.no_tuner      = 1,
332b285192aSMauro Carvalho Chehab 	.demod_init    = dntv_live_dvbt_pro_demod_init,
333b285192aSMauro Carvalho Chehab };
334b285192aSMauro Carvalho Chehab #endif
335b285192aSMauro Carvalho Chehab 
336b285192aSMauro Carvalho Chehab static const struct zl10353_config dvico_fusionhdtv_hybrid = {
337b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
338b285192aSMauro Carvalho Chehab 	.no_tuner      = 1,
339b285192aSMauro Carvalho Chehab };
340b285192aSMauro Carvalho Chehab 
341b285192aSMauro Carvalho Chehab static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
342b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
343b285192aSMauro Carvalho Chehab 	.if2           = 45600,
344b285192aSMauro Carvalho Chehab 	.no_tuner      = 1,
345b285192aSMauro Carvalho Chehab };
346b285192aSMauro Carvalho Chehab 
347b285192aSMauro Carvalho Chehab static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
348b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
349b285192aSMauro Carvalho Chehab 	.if2 = 4560,
350b285192aSMauro Carvalho Chehab 	.no_tuner = 1,
351b285192aSMauro Carvalho Chehab 	.demod_init = dvico_fusionhdtv_demod_init,
352b285192aSMauro Carvalho Chehab };
353b285192aSMauro Carvalho Chehab 
354b285192aSMauro Carvalho Chehab static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
355b285192aSMauro Carvalho Chehab 	.demod_address = 0x0f,
356b285192aSMauro Carvalho Chehab };
357b285192aSMauro Carvalho Chehab 
358b285192aSMauro Carvalho Chehab static const struct cx22702_config connexant_refboard_config = {
359b285192aSMauro Carvalho Chehab 	.demod_address = 0x43,
360b285192aSMauro Carvalho Chehab 	.output_mode   = CX22702_SERIAL_OUTPUT,
361b285192aSMauro Carvalho Chehab };
362b285192aSMauro Carvalho Chehab 
363b285192aSMauro Carvalho Chehab static const struct cx22702_config hauppauge_hvr_config = {
364b285192aSMauro Carvalho Chehab 	.demod_address = 0x63,
365b285192aSMauro Carvalho Chehab 	.output_mode   = CX22702_SERIAL_OUTPUT,
366b285192aSMauro Carvalho Chehab };
367b285192aSMauro Carvalho Chehab 
or51132_set_ts_param(struct dvb_frontend * fe,int is_punctured)368b285192aSMauro Carvalho Chehab static int or51132_set_ts_param(struct dvb_frontend *fe, int is_punctured)
369b285192aSMauro Carvalho Chehab {
370b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
3717b61ba8fSMauro Carvalho Chehab 
372b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
373b285192aSMauro Carvalho Chehab 	return 0;
374b285192aSMauro Carvalho Chehab }
375b285192aSMauro Carvalho Chehab 
376b285192aSMauro Carvalho Chehab static const struct or51132_config pchdtv_hd3000 = {
377b285192aSMauro Carvalho Chehab 	.demod_address = 0x15,
378b285192aSMauro Carvalho Chehab 	.set_ts_params = or51132_set_ts_param,
379b285192aSMauro Carvalho Chehab };
380b285192aSMauro Carvalho Chehab 
lgdt330x_pll_rf_set(struct dvb_frontend * fe,int index)381b285192aSMauro Carvalho Chehab static int lgdt330x_pll_rf_set(struct dvb_frontend *fe, int index)
382b285192aSMauro Carvalho Chehab {
383b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
384b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
385b285192aSMauro Carvalho Chehab 
386b285192aSMauro Carvalho Chehab 	dprintk(1, "%s: index = %d\n", __func__, index);
387b285192aSMauro Carvalho Chehab 	if (index == 0)
388b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 8);
389b285192aSMauro Carvalho Chehab 	else
390b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 8);
391b285192aSMauro Carvalho Chehab 	return 0;
392b285192aSMauro Carvalho Chehab }
393b285192aSMauro Carvalho Chehab 
lgdt330x_set_ts_param(struct dvb_frontend * fe,int is_punctured)394b285192aSMauro Carvalho Chehab static int lgdt330x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
395b285192aSMauro Carvalho Chehab {
396b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
3977b61ba8fSMauro Carvalho Chehab 
398b285192aSMauro Carvalho Chehab 	if (is_punctured)
399b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl |= 0x04;
400b285192aSMauro Carvalho Chehab 	else
401b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl &= ~0x04;
402b285192aSMauro Carvalho Chehab 	return 0;
403b285192aSMauro Carvalho Chehab }
404b285192aSMauro Carvalho Chehab 
405b285192aSMauro Carvalho Chehab static struct lgdt330x_config fusionhdtv_3_gold = {
406b285192aSMauro Carvalho Chehab 	.demod_chip    = LGDT3302,
407b285192aSMauro Carvalho Chehab 	.serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
408b285192aSMauro Carvalho Chehab 	.set_ts_params = lgdt330x_set_ts_param,
409b285192aSMauro Carvalho Chehab };
410b285192aSMauro Carvalho Chehab 
411b285192aSMauro Carvalho Chehab static const struct lgdt330x_config fusionhdtv_5_gold = {
412b285192aSMauro Carvalho Chehab 	.demod_chip    = LGDT3303,
413b285192aSMauro Carvalho Chehab 	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
414b285192aSMauro Carvalho Chehab 	.set_ts_params = lgdt330x_set_ts_param,
415b285192aSMauro Carvalho Chehab };
416b285192aSMauro Carvalho Chehab 
417b285192aSMauro Carvalho Chehab static const struct lgdt330x_config pchdtv_hd5500 = {
418b285192aSMauro Carvalho Chehab 	.demod_chip    = LGDT3303,
419b285192aSMauro Carvalho Chehab 	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
420b285192aSMauro Carvalho Chehab 	.set_ts_params = lgdt330x_set_ts_param,
421b285192aSMauro Carvalho Chehab };
422b285192aSMauro Carvalho Chehab 
nxt200x_set_ts_param(struct dvb_frontend * fe,int is_punctured)423b285192aSMauro Carvalho Chehab static int nxt200x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
424b285192aSMauro Carvalho Chehab {
425b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
4267b61ba8fSMauro Carvalho Chehab 
427b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
428b285192aSMauro Carvalho Chehab 	return 0;
429b285192aSMauro Carvalho Chehab }
430b285192aSMauro Carvalho Chehab 
431b285192aSMauro Carvalho Chehab static const struct nxt200x_config ati_hdtvwonder = {
432b285192aSMauro Carvalho Chehab 	.demod_address = 0x0a,
433b285192aSMauro Carvalho Chehab 	.set_ts_params = nxt200x_set_ts_param,
434b285192aSMauro Carvalho Chehab };
435b285192aSMauro Carvalho Chehab 
cx24123_set_ts_param(struct dvb_frontend * fe,int is_punctured)436b285192aSMauro Carvalho Chehab static int cx24123_set_ts_param(struct dvb_frontend *fe,
437b285192aSMauro Carvalho Chehab 				int is_punctured)
438b285192aSMauro Carvalho Chehab {
439b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
4407b61ba8fSMauro Carvalho Chehab 
441b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = 0x02;
442b285192aSMauro Carvalho Chehab 	return 0;
443b285192aSMauro Carvalho Chehab }
444b285192aSMauro Carvalho Chehab 
kworld_dvbs_100_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)445b285192aSMauro Carvalho Chehab static int kworld_dvbs_100_set_voltage(struct dvb_frontend *fe,
4460df289a2SMauro Carvalho Chehab 				       enum fe_sec_voltage voltage)
447b285192aSMauro Carvalho Chehab {
448b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
449b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
450b285192aSMauro Carvalho Chehab 
451b285192aSMauro Carvalho Chehab 	if (voltage == SEC_VOLTAGE_OFF)
452b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x000006fb);
453b285192aSMauro Carvalho Chehab 	else
454b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x000006f9);
455b285192aSMauro Carvalho Chehab 
456b285192aSMauro Carvalho Chehab 	if (core->prev_set_voltage)
457b285192aSMauro Carvalho Chehab 		return core->prev_set_voltage(fe, voltage);
458b285192aSMauro Carvalho Chehab 	return 0;
459b285192aSMauro Carvalho Chehab }
460b285192aSMauro Carvalho Chehab 
geniatech_dvbs_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)461b285192aSMauro Carvalho Chehab static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
4620df289a2SMauro Carvalho Chehab 				      enum fe_sec_voltage voltage)
463b285192aSMauro Carvalho Chehab {
464b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
465b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
466b285192aSMauro Carvalho Chehab 
467b285192aSMauro Carvalho Chehab 	if (voltage == SEC_VOLTAGE_OFF) {
468b285192aSMauro Carvalho Chehab 		dprintk(1, "LNB Voltage OFF\n");
469b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x0000efff);
470b285192aSMauro Carvalho Chehab 	}
471b285192aSMauro Carvalho Chehab 
472b285192aSMauro Carvalho Chehab 	if (core->prev_set_voltage)
473b285192aSMauro Carvalho Chehab 		return core->prev_set_voltage(fe, voltage);
474b285192aSMauro Carvalho Chehab 	return 0;
475b285192aSMauro Carvalho Chehab }
476b285192aSMauro Carvalho Chehab 
tevii_dvbs_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)477b285192aSMauro Carvalho Chehab static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
4780df289a2SMauro Carvalho Chehab 				  enum fe_sec_voltage voltage)
479b285192aSMauro Carvalho Chehab {
480b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
481b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
482b285192aSMauro Carvalho Chehab 
483b285192aSMauro Carvalho Chehab 	cx_set(MO_GP0_IO, 0x6040);
484b285192aSMauro Carvalho Chehab 	switch (voltage) {
485b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_13:
486b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x20);
487b285192aSMauro Carvalho Chehab 		break;
488b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_18:
489b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x20);
490b285192aSMauro Carvalho Chehab 		break;
491b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_OFF:
492b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x20);
493b285192aSMauro Carvalho Chehab 		break;
494b285192aSMauro Carvalho Chehab 	}
495b285192aSMauro Carvalho Chehab 
496b285192aSMauro Carvalho Chehab 	if (core->prev_set_voltage)
497b285192aSMauro Carvalho Chehab 		return core->prev_set_voltage(fe, voltage);
498b285192aSMauro Carvalho Chehab 	return 0;
499b285192aSMauro Carvalho Chehab }
500b285192aSMauro Carvalho Chehab 
vp1027_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)501b285192aSMauro Carvalho Chehab static int vp1027_set_voltage(struct dvb_frontend *fe,
5020df289a2SMauro Carvalho Chehab 			      enum fe_sec_voltage voltage)
503b285192aSMauro Carvalho Chehab {
504b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
505b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
506b285192aSMauro Carvalho Chehab 
507b285192aSMauro Carvalho Chehab 	switch (voltage) {
508b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_13:
509b285192aSMauro Carvalho Chehab 		dprintk(1, "LNB SEC Voltage=13\n");
510b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x00001220);
511b285192aSMauro Carvalho Chehab 		break;
512b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_18:
513b285192aSMauro Carvalho Chehab 		dprintk(1, "LNB SEC Voltage=18\n");
514b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x00001222);
515b285192aSMauro Carvalho Chehab 		break;
516b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_OFF:
517b285192aSMauro Carvalho Chehab 		dprintk(1, "LNB Voltage OFF\n");
518b285192aSMauro Carvalho Chehab 		cx_write(MO_GP0_IO, 0x00001230);
519b285192aSMauro Carvalho Chehab 		break;
520b285192aSMauro Carvalho Chehab 	}
521b285192aSMauro Carvalho Chehab 
522b285192aSMauro Carvalho Chehab 	if (core->prev_set_voltage)
523b285192aSMauro Carvalho Chehab 		return core->prev_set_voltage(fe, voltage);
524b285192aSMauro Carvalho Chehab 	return 0;
525b285192aSMauro Carvalho Chehab }
526b285192aSMauro Carvalho Chehab 
527b285192aSMauro Carvalho Chehab static const struct cx24123_config geniatech_dvbs_config = {
528b285192aSMauro Carvalho Chehab 	.demod_address = 0x55,
529b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24123_set_ts_param,
530b285192aSMauro Carvalho Chehab };
531b285192aSMauro Carvalho Chehab 
532b285192aSMauro Carvalho Chehab static const struct cx24123_config hauppauge_novas_config = {
533b285192aSMauro Carvalho Chehab 	.demod_address = 0x55,
534b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24123_set_ts_param,
535b285192aSMauro Carvalho Chehab };
536b285192aSMauro Carvalho Chehab 
537b285192aSMauro Carvalho Chehab static const struct cx24123_config kworld_dvbs_100_config = {
538b285192aSMauro Carvalho Chehab 	.demod_address = 0x15,
539b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24123_set_ts_param,
540b285192aSMauro Carvalho Chehab 	.lnb_polarity  = 1,
541b285192aSMauro Carvalho Chehab };
542b285192aSMauro Carvalho Chehab 
543b285192aSMauro Carvalho Chehab static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
544b285192aSMauro Carvalho Chehab 	.demod_address = 0x32 >> 1,
545b285192aSMauro Carvalho Chehab 	.output_mode   = S5H1409_PARALLEL_OUTPUT,
546b285192aSMauro Carvalho Chehab 	.gpio	       = S5H1409_GPIO_ON,
547b285192aSMauro Carvalho Chehab 	.qam_if	       = 44000,
548b285192aSMauro Carvalho Chehab 	.inversion     = S5H1409_INVERSION_OFF,
549b285192aSMauro Carvalho Chehab 	.status_mode   = S5H1409_DEMODLOCKING,
550ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINUOUS_NONINVERTING_CLOCK,
551b285192aSMauro Carvalho Chehab };
552b285192aSMauro Carvalho Chehab 
553b285192aSMauro Carvalho Chehab static const struct s5h1409_config dvico_hdtv5_pci_nano_config = {
554b285192aSMauro Carvalho Chehab 	.demod_address = 0x32 >> 1,
555b285192aSMauro Carvalho Chehab 	.output_mode   = S5H1409_SERIAL_OUTPUT,
556b285192aSMauro Carvalho Chehab 	.gpio          = S5H1409_GPIO_OFF,
557b285192aSMauro Carvalho Chehab 	.inversion     = S5H1409_INVERSION_OFF,
558b285192aSMauro Carvalho Chehab 	.status_mode   = S5H1409_DEMODLOCKING,
559ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
560b285192aSMauro Carvalho Chehab };
561b285192aSMauro Carvalho Chehab 
562b285192aSMauro Carvalho Chehab static const struct s5h1409_config kworld_atsc_120_config = {
563b285192aSMauro Carvalho Chehab 	.demod_address = 0x32 >> 1,
564b285192aSMauro Carvalho Chehab 	.output_mode   = S5H1409_SERIAL_OUTPUT,
565b285192aSMauro Carvalho Chehab 	.gpio	       = S5H1409_GPIO_OFF,
566b285192aSMauro Carvalho Chehab 	.inversion     = S5H1409_INVERSION_OFF,
567b285192aSMauro Carvalho Chehab 	.status_mode   = S5H1409_DEMODLOCKING,
568ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
569b285192aSMauro Carvalho Chehab };
570b285192aSMauro Carvalho Chehab 
571b285192aSMauro Carvalho Chehab static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
572b285192aSMauro Carvalho Chehab 	.i2c_address	= 0x64,
573b285192aSMauro Carvalho Chehab 	.if_khz		= 5380,
574b285192aSMauro Carvalho Chehab };
575b285192aSMauro Carvalho Chehab 
576b285192aSMauro Carvalho Chehab static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
577b285192aSMauro Carvalho Chehab 	.demod_address = (0x1e >> 1),
578b285192aSMauro Carvalho Chehab 	.no_tuner      = 1,
579b285192aSMauro Carvalho Chehab 	.if2           = 45600,
580b285192aSMauro Carvalho Chehab };
581b285192aSMauro Carvalho Chehab 
582b285192aSMauro Carvalho Chehab static const struct zl10353_config cx88_geniatech_x8000_mt = {
583b285192aSMauro Carvalho Chehab 	.demod_address = (0x1e >> 1),
584b285192aSMauro Carvalho Chehab 	.no_tuner = 1,
585b285192aSMauro Carvalho Chehab 	.disable_i2c_gate_ctrl = 1,
586b285192aSMauro Carvalho Chehab };
587b285192aSMauro Carvalho Chehab 
588b285192aSMauro Carvalho Chehab static const struct s5h1411_config dvico_fusionhdtv7_config = {
589b285192aSMauro Carvalho Chehab 	.output_mode   = S5H1411_SERIAL_OUTPUT,
590b285192aSMauro Carvalho Chehab 	.gpio          = S5H1411_GPIO_ON,
591ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
592b285192aSMauro Carvalho Chehab 	.qam_if        = S5H1411_IF_44000,
593b285192aSMauro Carvalho Chehab 	.vsb_if        = S5H1411_IF_44000,
594b285192aSMauro Carvalho Chehab 	.inversion     = S5H1411_INVERSION_OFF,
595b285192aSMauro Carvalho Chehab 	.status_mode   = S5H1411_DEMODLOCKING
596b285192aSMauro Carvalho Chehab };
597b285192aSMauro Carvalho Chehab 
598b285192aSMauro Carvalho Chehab static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
599b285192aSMauro Carvalho Chehab 	.i2c_address    = 0xc2 >> 1,
600b285192aSMauro Carvalho Chehab 	.if_khz         = 5380,
601b285192aSMauro Carvalho Chehab };
602b285192aSMauro Carvalho Chehab 
attach_xc3028(u8 addr,struct cx8802_dev * dev)603b285192aSMauro Carvalho Chehab static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
604b285192aSMauro Carvalho Chehab {
605b285192aSMauro Carvalho Chehab 	struct dvb_frontend *fe;
6060b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0 = NULL;
607b285192aSMauro Carvalho Chehab 	struct xc2028_ctrl ctl;
608b285192aSMauro Carvalho Chehab 	struct xc2028_config cfg = {
609b285192aSMauro Carvalho Chehab 		.i2c_adap  = &dev->core->i2c_adap,
610b285192aSMauro Carvalho Chehab 		.i2c_addr  = addr,
611b285192aSMauro Carvalho Chehab 		.ctrl      = &ctl,
612b285192aSMauro Carvalho Chehab 	};
613b285192aSMauro Carvalho Chehab 
614b285192aSMauro Carvalho Chehab 	/* Get the first frontend */
6150b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
616b285192aSMauro Carvalho Chehab 	if (!fe0)
617b285192aSMauro Carvalho Chehab 		return -EINVAL;
618b285192aSMauro Carvalho Chehab 
619b285192aSMauro Carvalho Chehab 	if (!fe0->dvb.frontend) {
62065bc2fe8SMauro Carvalho Chehab 		pr_err("dvb frontend not attached. Can't attach xc3028\n");
621b285192aSMauro Carvalho Chehab 		return -EINVAL;
622b285192aSMauro Carvalho Chehab 	}
623b285192aSMauro Carvalho Chehab 
624b285192aSMauro Carvalho Chehab 	/*
625b285192aSMauro Carvalho Chehab 	 * Some xc3028 devices may be hidden by an I2C gate. This is known
626b285192aSMauro Carvalho Chehab 	 * to happen with some s5h1409-based devices.
627b285192aSMauro Carvalho Chehab 	 * Now that I2C gate is open, sets up xc3028 configuration
628b285192aSMauro Carvalho Chehab 	 */
629b285192aSMauro Carvalho Chehab 	cx88_setup_xc3028(dev->core, &ctl);
630b285192aSMauro Carvalho Chehab 
631b285192aSMauro Carvalho Chehab 	fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
632b285192aSMauro Carvalho Chehab 	if (!fe) {
63365bc2fe8SMauro Carvalho Chehab 		pr_err("xc3028 attach failed\n");
634b285192aSMauro Carvalho Chehab 		dvb_frontend_detach(fe0->dvb.frontend);
635b285192aSMauro Carvalho Chehab 		dvb_unregister_frontend(fe0->dvb.frontend);
636b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = NULL;
637b285192aSMauro Carvalho Chehab 		return -EINVAL;
638b285192aSMauro Carvalho Chehab 	}
639b285192aSMauro Carvalho Chehab 
64065bc2fe8SMauro Carvalho Chehab 	pr_info("xc3028 attached\n");
641b285192aSMauro Carvalho Chehab 
642b285192aSMauro Carvalho Chehab 	return 0;
643b285192aSMauro Carvalho Chehab }
644b285192aSMauro Carvalho Chehab 
attach_xc4000(struct cx8802_dev * dev,struct xc4000_config * cfg)645b285192aSMauro Carvalho Chehab static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
646b285192aSMauro Carvalho Chehab {
647b285192aSMauro Carvalho Chehab 	struct dvb_frontend *fe;
6480b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0 = NULL;
649b285192aSMauro Carvalho Chehab 
650b285192aSMauro Carvalho Chehab 	/* Get the first frontend */
6510b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
652b285192aSMauro Carvalho Chehab 	if (!fe0)
653b285192aSMauro Carvalho Chehab 		return -EINVAL;
654b285192aSMauro Carvalho Chehab 
655b285192aSMauro Carvalho Chehab 	if (!fe0->dvb.frontend) {
65665bc2fe8SMauro Carvalho Chehab 		pr_err("dvb frontend not attached. Can't attach xc4000\n");
657b285192aSMauro Carvalho Chehab 		return -EINVAL;
658b285192aSMauro Carvalho Chehab 	}
659b285192aSMauro Carvalho Chehab 
660b285192aSMauro Carvalho Chehab 	fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
661b285192aSMauro Carvalho Chehab 			cfg);
662b285192aSMauro Carvalho Chehab 	if (!fe) {
66365bc2fe8SMauro Carvalho Chehab 		pr_err("xc4000 attach failed\n");
664b285192aSMauro Carvalho Chehab 		dvb_frontend_detach(fe0->dvb.frontend);
665b285192aSMauro Carvalho Chehab 		dvb_unregister_frontend(fe0->dvb.frontend);
666b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = NULL;
667b285192aSMauro Carvalho Chehab 		return -EINVAL;
668b285192aSMauro Carvalho Chehab 	}
669b285192aSMauro Carvalho Chehab 
67065bc2fe8SMauro Carvalho Chehab 	pr_info("xc4000 attached\n");
671b285192aSMauro Carvalho Chehab 
672b285192aSMauro Carvalho Chehab 	return 0;
673b285192aSMauro Carvalho Chehab }
674b285192aSMauro Carvalho Chehab 
cx24116_set_ts_param(struct dvb_frontend * fe,int is_punctured)675b285192aSMauro Carvalho Chehab static int cx24116_set_ts_param(struct dvb_frontend *fe,
676b285192aSMauro Carvalho Chehab 				int is_punctured)
677b285192aSMauro Carvalho Chehab {
678b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
6797b61ba8fSMauro Carvalho Chehab 
680b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = 0x2;
681b285192aSMauro Carvalho Chehab 
682b285192aSMauro Carvalho Chehab 	return 0;
683b285192aSMauro Carvalho Chehab }
684b285192aSMauro Carvalho Chehab 
stv0900_set_ts_param(struct dvb_frontend * fe,int is_punctured)685b285192aSMauro Carvalho Chehab static int stv0900_set_ts_param(struct dvb_frontend *fe,
686b285192aSMauro Carvalho Chehab 				int is_punctured)
687b285192aSMauro Carvalho Chehab {
688b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
6897b61ba8fSMauro Carvalho Chehab 
690b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = 0;
691b285192aSMauro Carvalho Chehab 
692b285192aSMauro Carvalho Chehab 	return 0;
693b285192aSMauro Carvalho Chehab }
694b285192aSMauro Carvalho Chehab 
cx24116_reset_device(struct dvb_frontend * fe)695b285192aSMauro Carvalho Chehab static int cx24116_reset_device(struct dvb_frontend *fe)
696b285192aSMauro Carvalho Chehab {
697b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
698b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
699b285192aSMauro Carvalho Chehab 
700b285192aSMauro Carvalho Chehab 	/* Reset the part */
701b285192aSMauro Carvalho Chehab 	/* Put the cx24116 into reset */
702b285192aSMauro Carvalho Chehab 	cx_write(MO_SRST_IO, 0);
703399426caSMauro Carvalho Chehab 	usleep_range(10000, 20000);
704b285192aSMauro Carvalho Chehab 	/* Take the cx24116 out of reset */
705b285192aSMauro Carvalho Chehab 	cx_write(MO_SRST_IO, 1);
706399426caSMauro Carvalho Chehab 	usleep_range(10000, 20000);
707b285192aSMauro Carvalho Chehab 
708b285192aSMauro Carvalho Chehab 	return 0;
709b285192aSMauro Carvalho Chehab }
710b285192aSMauro Carvalho Chehab 
711b285192aSMauro Carvalho Chehab static const struct cx24116_config hauppauge_hvr4000_config = {
712b285192aSMauro Carvalho Chehab 	.demod_address          = 0x05,
713b285192aSMauro Carvalho Chehab 	.set_ts_params          = cx24116_set_ts_param,
714b285192aSMauro Carvalho Chehab 	.reset_device           = cx24116_reset_device,
715b285192aSMauro Carvalho Chehab };
716b285192aSMauro Carvalho Chehab 
717b285192aSMauro Carvalho Chehab static const struct cx24116_config tevii_s460_config = {
718b285192aSMauro Carvalho Chehab 	.demod_address = 0x55,
719b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24116_set_ts_param,
720b285192aSMauro Carvalho Chehab 	.reset_device  = cx24116_reset_device,
721b285192aSMauro Carvalho Chehab };
722b285192aSMauro Carvalho Chehab 
ds3000_set_ts_param(struct dvb_frontend * fe,int is_punctured)723b285192aSMauro Carvalho Chehab static int ds3000_set_ts_param(struct dvb_frontend *fe,
724b285192aSMauro Carvalho Chehab 			       int is_punctured)
725b285192aSMauro Carvalho Chehab {
726b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
7277b61ba8fSMauro Carvalho Chehab 
728b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = 4;
729b285192aSMauro Carvalho Chehab 
730b285192aSMauro Carvalho Chehab 	return 0;
731b285192aSMauro Carvalho Chehab }
732b285192aSMauro Carvalho Chehab 
733b285192aSMauro Carvalho Chehab static struct ds3000_config tevii_ds3000_config = {
734b285192aSMauro Carvalho Chehab 	.demod_address = 0x68,
735b285192aSMauro Carvalho Chehab 	.set_ts_params = ds3000_set_ts_param,
736b285192aSMauro Carvalho Chehab };
737b285192aSMauro Carvalho Chehab 
73873f0af44SKonstantin Dimitrov static struct ts2020_config tevii_ts2020_config  = {
73973f0af44SKonstantin Dimitrov 	.tuner_address = 0x60,
740b858c331SIgor M. Liplianin 	.clk_out_div = 1,
74173f0af44SKonstantin Dimitrov };
74273f0af44SKonstantin Dimitrov 
743b285192aSMauro Carvalho Chehab static const struct stv0900_config prof_7301_stv0900_config = {
744b285192aSMauro Carvalho Chehab 	.demod_address = 0x6a,
745b285192aSMauro Carvalho Chehab /*	demod_mode = 0,*/
746b285192aSMauro Carvalho Chehab 	.xtal = 27000000,
747b285192aSMauro Carvalho Chehab 	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
748b285192aSMauro Carvalho Chehab 	.diseqc_mode = 2,/* 2/3 PWM */
749b285192aSMauro Carvalho Chehab 	.tun1_maddress = 0,/* 0x60 */
750b285192aSMauro Carvalho Chehab 	.tun1_adc = 0,/* 2 Vpp */
751b285192aSMauro Carvalho Chehab 	.path1_mode = 3,
752b285192aSMauro Carvalho Chehab 	.set_ts_params = stv0900_set_ts_param,
753b285192aSMauro Carvalho Chehab };
754b285192aSMauro Carvalho Chehab 
755b285192aSMauro Carvalho Chehab static const struct stb6100_config prof_7301_stb6100_config = {
756b285192aSMauro Carvalho Chehab 	.tuner_address = 0x60,
757b285192aSMauro Carvalho Chehab 	.refclock = 27000000,
758b285192aSMauro Carvalho Chehab };
759b285192aSMauro Carvalho Chehab 
760b285192aSMauro Carvalho Chehab static const struct stv0299_config tevii_tuner_sharp_config = {
761b285192aSMauro Carvalho Chehab 	.demod_address = 0x68,
762b285192aSMauro Carvalho Chehab 	.inittab = sharp_z0194a_inittab,
763b285192aSMauro Carvalho Chehab 	.mclk = 88000000UL,
764b285192aSMauro Carvalho Chehab 	.invert = 1,
765b285192aSMauro Carvalho Chehab 	.skip_reinit = 0,
766b285192aSMauro Carvalho Chehab 	.lock_output = 1,
767b285192aSMauro Carvalho Chehab 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
768b285192aSMauro Carvalho Chehab 	.min_delay_ms = 100,
769b285192aSMauro Carvalho Chehab 	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
770b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24116_set_ts_param,
771b285192aSMauro Carvalho Chehab };
772b285192aSMauro Carvalho Chehab 
773b285192aSMauro Carvalho Chehab static const struct stv0288_config tevii_tuner_earda_config = {
774b285192aSMauro Carvalho Chehab 	.demod_address = 0x68,
775b285192aSMauro Carvalho Chehab 	.min_delay_ms = 100,
776b285192aSMauro Carvalho Chehab 	.set_ts_params = cx24116_set_ts_param,
777b285192aSMauro Carvalho Chehab };
778b285192aSMauro Carvalho Chehab 
cx8802_alloc_frontends(struct cx8802_dev * dev)779b285192aSMauro Carvalho Chehab static int cx8802_alloc_frontends(struct cx8802_dev *dev)
780b285192aSMauro Carvalho Chehab {
781b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
7820b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe = NULL;
783b285192aSMauro Carvalho Chehab 	int i;
784b285192aSMauro Carvalho Chehab 
785b285192aSMauro Carvalho Chehab 	mutex_init(&dev->frontends.lock);
786b285192aSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->frontends.felist);
787b285192aSMauro Carvalho Chehab 
788b285192aSMauro Carvalho Chehab 	if (!core->board.num_frontends)
789b285192aSMauro Carvalho Chehab 		return -ENODEV;
790b285192aSMauro Carvalho Chehab 
79165bc2fe8SMauro Carvalho Chehab 	pr_info("%s: allocating %d frontend(s)\n", __func__,
792b285192aSMauro Carvalho Chehab 		core->board.num_frontends);
793b285192aSMauro Carvalho Chehab 	for (i = 1; i <= core->board.num_frontends; i++) {
7940b6b6302SHans Verkuil 		fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
795b285192aSMauro Carvalho Chehab 		if (!fe) {
79665bc2fe8SMauro Carvalho Chehab 			pr_err("%s() failed to alloc\n", __func__);
7970b6b6302SHans Verkuil 			vb2_dvb_dealloc_frontends(&dev->frontends);
798b285192aSMauro Carvalho Chehab 			return -ENOMEM;
799b285192aSMauro Carvalho Chehab 		}
800b285192aSMauro Carvalho Chehab 	}
801b285192aSMauro Carvalho Chehab 	return 0;
802b285192aSMauro Carvalho Chehab }
803b285192aSMauro Carvalho Chehab 
804b285192aSMauro Carvalho Chehab static const u8 samsung_smt_7020_inittab[] = {
805b285192aSMauro Carvalho Chehab 	     0x01, 0x15,
806b285192aSMauro Carvalho Chehab 	     0x02, 0x00,
807b285192aSMauro Carvalho Chehab 	     0x03, 0x00,
808b285192aSMauro Carvalho Chehab 	     0x04, 0x7D,
809b285192aSMauro Carvalho Chehab 	     0x05, 0x0F,
810b285192aSMauro Carvalho Chehab 	     0x06, 0x02,
811b285192aSMauro Carvalho Chehab 	     0x07, 0x00,
812b285192aSMauro Carvalho Chehab 	     0x08, 0x60,
813b285192aSMauro Carvalho Chehab 
814b285192aSMauro Carvalho Chehab 	     0x0A, 0xC2,
815b285192aSMauro Carvalho Chehab 	     0x0B, 0x00,
816b285192aSMauro Carvalho Chehab 	     0x0C, 0x01,
817b285192aSMauro Carvalho Chehab 	     0x0D, 0x81,
818b285192aSMauro Carvalho Chehab 	     0x0E, 0x44,
819b285192aSMauro Carvalho Chehab 	     0x0F, 0x09,
820b285192aSMauro Carvalho Chehab 	     0x10, 0x3C,
821b285192aSMauro Carvalho Chehab 	     0x11, 0x84,
822b285192aSMauro Carvalho Chehab 	     0x12, 0xDA,
823b285192aSMauro Carvalho Chehab 	     0x13, 0x99,
824b285192aSMauro Carvalho Chehab 	     0x14, 0x8D,
825b285192aSMauro Carvalho Chehab 	     0x15, 0xCE,
826b285192aSMauro Carvalho Chehab 	     0x16, 0xE8,
827b285192aSMauro Carvalho Chehab 	     0x17, 0x43,
828b285192aSMauro Carvalho Chehab 	     0x18, 0x1C,
829b285192aSMauro Carvalho Chehab 	     0x19, 0x1B,
830b285192aSMauro Carvalho Chehab 	     0x1A, 0x1D,
831b285192aSMauro Carvalho Chehab 
832b285192aSMauro Carvalho Chehab 	     0x1C, 0x12,
833b285192aSMauro Carvalho Chehab 	     0x1D, 0x00,
834b285192aSMauro Carvalho Chehab 	     0x1E, 0x00,
835b285192aSMauro Carvalho Chehab 	     0x1F, 0x00,
836b285192aSMauro Carvalho Chehab 	     0x20, 0x00,
837b285192aSMauro Carvalho Chehab 	     0x21, 0x00,
838b285192aSMauro Carvalho Chehab 	     0x22, 0x00,
839b285192aSMauro Carvalho Chehab 	     0x23, 0x00,
840b285192aSMauro Carvalho Chehab 
841b285192aSMauro Carvalho Chehab 	     0x28, 0x02,
842b285192aSMauro Carvalho Chehab 	     0x29, 0x28,
843b285192aSMauro Carvalho Chehab 	     0x2A, 0x14,
844b285192aSMauro Carvalho Chehab 	     0x2B, 0x0F,
845b285192aSMauro Carvalho Chehab 	     0x2C, 0x09,
846b285192aSMauro Carvalho Chehab 	     0x2D, 0x05,
847b285192aSMauro Carvalho Chehab 
848b285192aSMauro Carvalho Chehab 	     0x31, 0x1F,
849b285192aSMauro Carvalho Chehab 	     0x32, 0x19,
850b285192aSMauro Carvalho Chehab 	     0x33, 0xFC,
851b285192aSMauro Carvalho Chehab 	     0x34, 0x13,
852b285192aSMauro Carvalho Chehab 	     0xff, 0xff,
853b285192aSMauro Carvalho Chehab };
854b285192aSMauro Carvalho Chehab 
samsung_smt_7020_tuner_set_params(struct dvb_frontend * fe)855b285192aSMauro Carvalho Chehab static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
856b285192aSMauro Carvalho Chehab {
857b285192aSMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
858b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
859b285192aSMauro Carvalho Chehab 	u8 buf[4];
860b285192aSMauro Carvalho Chehab 	u32 div;
861b285192aSMauro Carvalho Chehab 	struct i2c_msg msg = {
862b285192aSMauro Carvalho Chehab 		.addr = 0x61,
863b285192aSMauro Carvalho Chehab 		.flags = 0,
864b285192aSMauro Carvalho Chehab 		.buf = buf,
865b285192aSMauro Carvalho Chehab 		.len = sizeof(buf) };
866b285192aSMauro Carvalho Chehab 
867b285192aSMauro Carvalho Chehab 	div = c->frequency / 125;
868b285192aSMauro Carvalho Chehab 
869b285192aSMauro Carvalho Chehab 	buf[0] = (div >> 8) & 0x7f;
870b285192aSMauro Carvalho Chehab 	buf[1] = div & 0xff;
871b285192aSMauro Carvalho Chehab 	buf[2] = 0x84;  /* 0xC4 */
872b285192aSMauro Carvalho Chehab 	buf[3] = 0x00;
873b285192aSMauro Carvalho Chehab 
874b285192aSMauro Carvalho Chehab 	if (c->frequency < 1500000)
875b285192aSMauro Carvalho Chehab 		buf[3] |= 0x10;
876b285192aSMauro Carvalho Chehab 
877b285192aSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
878b285192aSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
879b285192aSMauro Carvalho Chehab 
880b285192aSMauro Carvalho Chehab 	if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
881b285192aSMauro Carvalho Chehab 		return -EIO;
882b285192aSMauro Carvalho Chehab 
883b285192aSMauro Carvalho Chehab 	return 0;
884b285192aSMauro Carvalho Chehab }
885b285192aSMauro Carvalho Chehab 
samsung_smt_7020_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)886b285192aSMauro Carvalho Chehab static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
8870df289a2SMauro Carvalho Chehab 				     enum fe_sec_tone_mode tone)
888b285192aSMauro Carvalho Chehab {
889b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
890b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
891b285192aSMauro Carvalho Chehab 
892b285192aSMauro Carvalho Chehab 	cx_set(MO_GP0_IO, 0x0800);
893b285192aSMauro Carvalho Chehab 
894b285192aSMauro Carvalho Chehab 	switch (tone) {
895b285192aSMauro Carvalho Chehab 	case SEC_TONE_ON:
896b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x08);
897b285192aSMauro Carvalho Chehab 		break;
898b285192aSMauro Carvalho Chehab 	case SEC_TONE_OFF:
899b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x08);
900b285192aSMauro Carvalho Chehab 		break;
901b285192aSMauro Carvalho Chehab 	default:
902b285192aSMauro Carvalho Chehab 		return -EINVAL;
903b285192aSMauro Carvalho Chehab 	}
904b285192aSMauro Carvalho Chehab 
905b285192aSMauro Carvalho Chehab 	return 0;
906b285192aSMauro Carvalho Chehab }
907b285192aSMauro Carvalho Chehab 
samsung_smt_7020_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)908b285192aSMauro Carvalho Chehab static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
9090df289a2SMauro Carvalho Chehab 					enum fe_sec_voltage voltage)
910b285192aSMauro Carvalho Chehab {
911b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = fe->dvb->priv;
912b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
913b285192aSMauro Carvalho Chehab 
914b285192aSMauro Carvalho Chehab 	u8 data;
915b285192aSMauro Carvalho Chehab 	struct i2c_msg msg = {
916b285192aSMauro Carvalho Chehab 		.addr = 8,
917b285192aSMauro Carvalho Chehab 		.flags = 0,
918b285192aSMauro Carvalho Chehab 		.buf = &data,
919b285192aSMauro Carvalho Chehab 		.len = sizeof(data) };
920b285192aSMauro Carvalho Chehab 
921b285192aSMauro Carvalho Chehab 	cx_set(MO_GP0_IO, 0x8000);
922b285192aSMauro Carvalho Chehab 
923b285192aSMauro Carvalho Chehab 	switch (voltage) {
924b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_OFF:
925b285192aSMauro Carvalho Chehab 		break;
926b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_13:
927b285192aSMauro Carvalho Chehab 		data = ISL6421_EN1 | ISL6421_LLC1;
928b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x80);
929b285192aSMauro Carvalho Chehab 		break;
930b285192aSMauro Carvalho Chehab 	case SEC_VOLTAGE_18:
931b285192aSMauro Carvalho Chehab 		data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
932b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x80);
933b285192aSMauro Carvalho Chehab 		break;
934b285192aSMauro Carvalho Chehab 	default:
935b285192aSMauro Carvalho Chehab 		return -EINVAL;
936c2c1b415SPeter Senna Tschudin 	}
937b285192aSMauro Carvalho Chehab 
938b285192aSMauro Carvalho Chehab 	return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
939b285192aSMauro Carvalho Chehab }
940b285192aSMauro Carvalho Chehab 
samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)941b285192aSMauro Carvalho Chehab static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
942b285192aSMauro Carvalho Chehab 						    u32 srate, u32 ratio)
943b285192aSMauro Carvalho Chehab {
944b285192aSMauro Carvalho Chehab 	u8 aclk = 0;
945b285192aSMauro Carvalho Chehab 	u8 bclk = 0;
946b285192aSMauro Carvalho Chehab 
947b285192aSMauro Carvalho Chehab 	if (srate < 1500000) {
948b285192aSMauro Carvalho Chehab 		aclk = 0xb7;
949b285192aSMauro Carvalho Chehab 		bclk = 0x47;
950b285192aSMauro Carvalho Chehab 	} else if (srate < 3000000) {
951b285192aSMauro Carvalho Chehab 		aclk = 0xb7;
952b285192aSMauro Carvalho Chehab 		bclk = 0x4b;
953b285192aSMauro Carvalho Chehab 	} else if (srate < 7000000) {
954b285192aSMauro Carvalho Chehab 		aclk = 0xb7;
955b285192aSMauro Carvalho Chehab 		bclk = 0x4f;
956b285192aSMauro Carvalho Chehab 	} else if (srate < 14000000) {
957b285192aSMauro Carvalho Chehab 		aclk = 0xb7;
958b285192aSMauro Carvalho Chehab 		bclk = 0x53;
959b285192aSMauro Carvalho Chehab 	} else if (srate < 30000000) {
960b285192aSMauro Carvalho Chehab 		aclk = 0xb6;
961b285192aSMauro Carvalho Chehab 		bclk = 0x53;
962b285192aSMauro Carvalho Chehab 	} else if (srate < 45000000) {
963b285192aSMauro Carvalho Chehab 		aclk = 0xb4;
964b285192aSMauro Carvalho Chehab 		bclk = 0x51;
965b285192aSMauro Carvalho Chehab 	}
966b285192aSMauro Carvalho Chehab 
967b285192aSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x13, aclk);
968b285192aSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x14, bclk);
969b285192aSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
970b285192aSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
971b285192aSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x21, ratio & 0xf0);
972b285192aSMauro Carvalho Chehab 
973b285192aSMauro Carvalho Chehab 	return 0;
974b285192aSMauro Carvalho Chehab }
975b285192aSMauro Carvalho Chehab 
976b285192aSMauro Carvalho Chehab static const struct stv0299_config samsung_stv0299_config = {
977b285192aSMauro Carvalho Chehab 	.demod_address = 0x68,
978b285192aSMauro Carvalho Chehab 	.inittab = samsung_smt_7020_inittab,
979b285192aSMauro Carvalho Chehab 	.mclk = 88000000UL,
980b285192aSMauro Carvalho Chehab 	.invert = 0,
981b285192aSMauro Carvalho Chehab 	.skip_reinit = 0,
982b285192aSMauro Carvalho Chehab 	.lock_output = STV0299_LOCKOUTPUT_LK,
983b285192aSMauro Carvalho Chehab 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
984b285192aSMauro Carvalho Chehab 	.min_delay_ms = 100,
985b285192aSMauro Carvalho Chehab 	.set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
986b285192aSMauro Carvalho Chehab };
987b285192aSMauro Carvalho Chehab 
dvb_register(struct cx8802_dev * dev)988b285192aSMauro Carvalho Chehab static int dvb_register(struct cx8802_dev *dev)
989b285192aSMauro Carvalho Chehab {
990b285192aSMauro Carvalho Chehab 	struct cx88_core *core = dev->core;
9910b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0, *fe1 = NULL;
992b285192aSMauro Carvalho Chehab 	int mfe_shared = 0; /* bus not shared by default */
993b285192aSMauro Carvalho Chehab 	int res = -EINVAL;
994b285192aSMauro Carvalho Chehab 
9957b61ba8fSMauro Carvalho Chehab 	if (core->i2c_rc != 0) {
99665bc2fe8SMauro Carvalho Chehab 		pr_err("no i2c-bus available, cannot attach dvb drivers\n");
997b285192aSMauro Carvalho Chehab 		goto frontend_detach;
998b285192aSMauro Carvalho Chehab 	}
999b285192aSMauro Carvalho Chehab 
1000b285192aSMauro Carvalho Chehab 	/* Get the first frontend */
10010b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
1002b285192aSMauro Carvalho Chehab 	if (!fe0)
1003b285192aSMauro Carvalho Chehab 		goto frontend_detach;
1004b285192aSMauro Carvalho Chehab 
1005b285192aSMauro Carvalho Chehab 	/* multi-frontend gate control is undefined or defaults to fe0 */
1006b285192aSMauro Carvalho Chehab 	dev->frontends.gate = 0;
1007b285192aSMauro Carvalho Chehab 
1008b285192aSMauro Carvalho Chehab 	/* Sets the gate control callback to be used by i2c command calls */
1009b285192aSMauro Carvalho Chehab 	core->gate_ctrl = cx88_dvb_gate_ctrl;
1010b285192aSMauro Carvalho Chehab 
1011b285192aSMauro Carvalho Chehab 	/* init frontend(s) */
1012b285192aSMauro Carvalho Chehab 	switch (core->boardnr) {
1013b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
1014b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1015b285192aSMauro Carvalho Chehab 					       &connexant_refboard_config,
1016b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1017399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1018b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1019b285192aSMauro Carvalho Chehab 					0x61, &core->i2c_adap,
1020b285192aSMauro Carvalho Chehab 					DVB_PLL_THOMSON_DTT759X))
1021b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1022b285192aSMauro Carvalho Chehab 		}
1023b285192aSMauro Carvalho Chehab 		break;
1024b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
1025b285192aSMauro Carvalho Chehab 	case CX88_BOARD_CONEXANT_DVB_T1:
1026b285192aSMauro Carvalho Chehab 	case CX88_BOARD_KWORLD_DVB_T_CX22702:
1027b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV1000:
1028b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1029b285192aSMauro Carvalho Chehab 					       &connexant_refboard_config,
1030b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1031399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1032b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1033b285192aSMauro Carvalho Chehab 					0x60, &core->i2c_adap,
1034b285192aSMauro Carvalho Chehab 					DVB_PLL_THOMSON_DTT7579))
1035b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1036b285192aSMauro Carvalho Chehab 		}
1037b285192aSMauro Carvalho Chehab 		break;
1038b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV2000H:
1039b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR1100:
1040b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
1041b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR1300:
1042b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1043b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr_config,
1044b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1045399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1046b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1047b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1048b285192aSMauro Carvalho Chehab 					TUNER_PHILIPS_FMD1216ME_MK3))
1049b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1050b285192aSMauro Carvalho Chehab 		}
1051b285192aSMauro Carvalho Chehab 		break;
1052b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV2000H_J:
1053b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1054b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr_config,
1055b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1056399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1057b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1058b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1059b285192aSMauro Carvalho Chehab 					TUNER_PHILIPS_FMD1216MEX_MK3))
1060b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1061b285192aSMauro Carvalho Chehab 		}
1062b285192aSMauro Carvalho Chehab 		break;
1063b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR3000:
1064b285192aSMauro Carvalho Chehab 		/* MFE frontend 1 */
1065b285192aSMauro Carvalho Chehab 		mfe_shared = 1;
1066b285192aSMauro Carvalho Chehab 		dev->frontends.gate = 2;
1067b285192aSMauro Carvalho Chehab 		/* DVB-S init */
1068b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1069b285192aSMauro Carvalho Chehab 					       &hauppauge_novas_config,
1070b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1071b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1072b285192aSMauro Carvalho Chehab 			if (!dvb_attach(isl6421_attach,
1073b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend,
1074b285192aSMauro Carvalho Chehab 					&dev->core->i2c_adap,
107548a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
1076b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1077b285192aSMauro Carvalho Chehab 		}
1078b285192aSMauro Carvalho Chehab 		/* MFE frontend 2 */
10790b6b6302SHans Verkuil 		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
1080b285192aSMauro Carvalho Chehab 		if (!fe1)
1081b285192aSMauro Carvalho Chehab 			goto frontend_detach;
1082b285192aSMauro Carvalho Chehab 		/* DVB-T init */
1083b285192aSMauro Carvalho Chehab 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
1084b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr_config,
1085b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1086b285192aSMauro Carvalho Chehab 		if (fe1->dvb.frontend) {
1087b285192aSMauro Carvalho Chehab 			fe1->dvb.frontend->id = 1;
1088b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach,
1089b285192aSMauro Carvalho Chehab 					fe1->dvb.frontend,
1090b285192aSMauro Carvalho Chehab 					&dev->core->i2c_adap,
1091b285192aSMauro Carvalho Chehab 					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1092b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1093b285192aSMauro Carvalho Chehab 		}
1094b285192aSMauro Carvalho Chehab 		break;
1095b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
1096b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1097b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv,
1098b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1099399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1100b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1101b285192aSMauro Carvalho Chehab 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1102b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1103b285192aSMauro Carvalho Chehab 			break;
1104b285192aSMauro Carvalho Chehab 		}
1105b285192aSMauro Carvalho Chehab 		/* ZL10353 replaces MT352 on later cards */
1106b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1107b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv_plus_v1_1,
1108b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1109399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1110b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1111b285192aSMauro Carvalho Chehab 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1112b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1113b285192aSMauro Carvalho Chehab 		}
1114b285192aSMauro Carvalho Chehab 		break;
1115b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
1116399426caSMauro Carvalho Chehab 		/*
1117399426caSMauro Carvalho Chehab 		 * The tin box says DEE1601, but it seems to be DTT7579
1118399426caSMauro Carvalho Chehab 		 * compatible, with a slightly different MT352 AGC gain.
1119399426caSMauro Carvalho Chehab 		 */
1120b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1121b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv_dual,
1122b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1123399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1124b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1125b285192aSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1126b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1127b285192aSMauro Carvalho Chehab 			break;
1128b285192aSMauro Carvalho Chehab 		}
1129b285192aSMauro Carvalho Chehab 		/* ZL10353 replaces MT352 on later cards */
1130b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1131b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv_plus_v1_1,
1132b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1133399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1134b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1135b285192aSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1136b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1137b285192aSMauro Carvalho Chehab 		}
1138b285192aSMauro Carvalho Chehab 		break;
1139b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
1140b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1141b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv,
1142b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1143399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1144b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1145b285192aSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_LG_Z201))
1146b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1147b285192aSMauro Carvalho Chehab 		}
1148b285192aSMauro Carvalho Chehab 		break;
1149b285192aSMauro Carvalho Chehab 	case CX88_BOARD_KWORLD_DVB_T:
1150b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DNTV_LIVE_DVB_T:
1151b285192aSMauro Carvalho Chehab 	case CX88_BOARD_ADSTECH_DVB_T_PCI:
1152b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1153b285192aSMauro Carvalho Chehab 					       &dntv_live_dvbt_config,
1154b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1155399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1156b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1157b285192aSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_UNKNOWN_1))
1158b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1159b285192aSMauro Carvalho Chehab 		}
1160b285192aSMauro Carvalho Chehab 		break;
1161b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
11627b34be71SPeter Senna Tschudin #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
1163b285192aSMauro Carvalho Chehab 		/* MT352 is on a secondary I2C bus made from some GPIO lines */
1164399426caSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1165399426caSMauro Carvalho Chehab 					       &dntv_live_dvbt_pro_config,
1166b285192aSMauro Carvalho Chehab 					       &dev->vp3054->adap);
1167399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1168b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1169b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1170b285192aSMauro Carvalho Chehab 					TUNER_PHILIPS_FMD1216ME_MK3))
1171b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1172b285192aSMauro Carvalho Chehab 		}
1173b285192aSMauro Carvalho Chehab #else
117465bc2fe8SMauro Carvalho Chehab 		pr_err("built without vp3054 support\n");
1175b285192aSMauro Carvalho Chehab #endif
1176b285192aSMauro Carvalho Chehab 		break;
1177b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
1178b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1179b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv_hybrid,
1180b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1181399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1182b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1183b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1184b285192aSMauro Carvalho Chehab 					TUNER_THOMSON_FE6600))
1185b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1186b285192aSMauro Carvalho Chehab 		}
1187b285192aSMauro Carvalho Chehab 		break;
1188b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
1189b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1190b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv_xc3028,
1191b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1192399426caSMauro Carvalho Chehab 		if (!fe0->dvb.frontend)
1193b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend = dvb_attach(mt352_attach,
1194b285192aSMauro Carvalho Chehab 						&dvico_fusionhdtv_mt352_xc3028,
1195b285192aSMauro Carvalho Chehab 						&core->i2c_adap);
1196b285192aSMauro Carvalho Chehab 		/*
1197b285192aSMauro Carvalho Chehab 		 * On this board, the demod provides the I2C bus pullup.
1198b285192aSMauro Carvalho Chehab 		 * We must not permit gate_ctrl to be performed, or
1199b285192aSMauro Carvalho Chehab 		 * the xc3028 cannot communicate on the bus.
1200b285192aSMauro Carvalho Chehab 		 */
1201b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend)
1202b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1203b285192aSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
1204b285192aSMauro Carvalho Chehab 			goto frontend_detach;
1205b285192aSMauro Carvalho Chehab 		break;
1206b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PCHDTV_HD3000:
1207b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
1208b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1209399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1210b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1211b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1212b285192aSMauro Carvalho Chehab 					TUNER_THOMSON_DTT761X))
1213b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1214b285192aSMauro Carvalho Chehab 		}
1215b285192aSMauro Carvalho Chehab 		break;
1216b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
1217b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1218b285192aSMauro Carvalho Chehab 
1219b285192aSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1220b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 1);
12219d08ba6dSJia-Ju Bai 		msleep(100);
1222b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 1);
12239d08ba6dSJia-Ju Bai 		msleep(200);
1224b285192aSMauro Carvalho Chehab 
1225b285192aSMauro Carvalho Chehab 		/* Select RF connector callback */
1226b285192aSMauro Carvalho Chehab 		fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
1227b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1228b285192aSMauro Carvalho Chehab 					       &fusionhdtv_3_gold,
122923ba635dSMauro Carvalho Chehab 					       0x0e,
1230b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1231399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1232b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1233b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1234b285192aSMauro Carvalho Chehab 					TUNER_MICROTUNE_4042FI5))
1235b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1236b285192aSMauro Carvalho Chehab 		}
1237b285192aSMauro Carvalho Chehab 		break;
1238b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
1239b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1240b285192aSMauro Carvalho Chehab 
1241b285192aSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1242b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 1);
12439d08ba6dSJia-Ju Bai 		msleep(100);
1244b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 9);
12459d08ba6dSJia-Ju Bai 		msleep(200);
1246b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1247b285192aSMauro Carvalho Chehab 					       &fusionhdtv_3_gold,
124823ba635dSMauro Carvalho Chehab 					       0x0e,
1249b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1250399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1251b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1252b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1253b285192aSMauro Carvalho Chehab 					TUNER_THOMSON_DTT761X))
1254b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1255b285192aSMauro Carvalho Chehab 		}
1256b285192aSMauro Carvalho Chehab 		break;
1257b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1258b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1259b285192aSMauro Carvalho Chehab 
1260b285192aSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1261b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 1);
12629d08ba6dSJia-Ju Bai 		msleep(100);
1263b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 1);
12649d08ba6dSJia-Ju Bai 		msleep(200);
1265b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1266b285192aSMauro Carvalho Chehab 					       &fusionhdtv_5_gold,
126723ba635dSMauro Carvalho Chehab 					       0x0e,
1268b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1269399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1270b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1271b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1272b285192aSMauro Carvalho Chehab 					TUNER_LG_TDVS_H06XF))
1273b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1274b285192aSMauro Carvalho Chehab 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1275b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x43))
1276b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1277b285192aSMauro Carvalho Chehab 		}
1278b285192aSMauro Carvalho Chehab 		break;
1279b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PCHDTV_HD5500:
1280b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1281b285192aSMauro Carvalho Chehab 
1282b285192aSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1283b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 1);
12849d08ba6dSJia-Ju Bai 		msleep(100);
1285b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 1);
12869d08ba6dSJia-Ju Bai 		msleep(200);
1287b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1288b285192aSMauro Carvalho Chehab 					       &pchdtv_hd5500,
128923ba635dSMauro Carvalho Chehab 					       0x59,
1290b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1291399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1292b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1293b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1294b285192aSMauro Carvalho Chehab 					TUNER_LG_TDVS_H06XF))
1295b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1296b285192aSMauro Carvalho Chehab 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1297b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x43))
1298b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1299b285192aSMauro Carvalho Chehab 		}
1300b285192aSMauro Carvalho Chehab 		break;
1301b285192aSMauro Carvalho Chehab 	case CX88_BOARD_ATI_HDTVWONDER:
1302b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(nxt200x_attach,
1303b285192aSMauro Carvalho Chehab 					       &ati_hdtvwonder,
1304b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1305399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1306b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1307b285192aSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
1308b285192aSMauro Carvalho Chehab 					TUNER_PHILIPS_TUV1236D))
1309b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1310b285192aSMauro Carvalho Chehab 		}
1311b285192aSMauro Carvalho Chehab 		break;
1312b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
1313b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
1314b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1315b285192aSMauro Carvalho Chehab 					       &hauppauge_novas_config,
1316b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1317b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
131848a8a03bSMauro Carvalho Chehab 			bool override_tone;
131948a8a03bSMauro Carvalho Chehab 
132048a8a03bSMauro Carvalho Chehab 			if (core->model == 92001)
132148a8a03bSMauro Carvalho Chehab 				override_tone = true;
132248a8a03bSMauro Carvalho Chehab 			else
132348a8a03bSMauro Carvalho Chehab 				override_tone = false;
132448a8a03bSMauro Carvalho Chehab 
1325b285192aSMauro Carvalho Chehab 			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
1326399426caSMauro Carvalho Chehab 					&core->i2c_adap, 0x08, ISL6421_DCL,
1327399426caSMauro Carvalho Chehab 					0x00, override_tone))
1328b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1329b285192aSMauro Carvalho Chehab 		}
1330b285192aSMauro Carvalho Chehab 		break;
1331b285192aSMauro Carvalho Chehab 	case CX88_BOARD_KWORLD_DVBS_100:
1332b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1333b285192aSMauro Carvalho Chehab 					       &kworld_dvbs_100_config,
1334b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1335b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1336b285192aSMauro Carvalho Chehab 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1337b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
1338b285192aSMauro Carvalho Chehab 		}
1339b285192aSMauro Carvalho Chehab 		break;
1340b285192aSMauro Carvalho Chehab 	case CX88_BOARD_GENIATECH_DVBS:
1341b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1342b285192aSMauro Carvalho Chehab 					       &geniatech_dvbs_config,
1343b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1344b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1345b285192aSMauro Carvalho Chehab 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1346b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
1347b285192aSMauro Carvalho Chehab 		}
1348b285192aSMauro Carvalho Chehab 		break;
1349b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
1350b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1351b285192aSMauro Carvalho Chehab 					       &pinnacle_pctv_hd_800i_config,
1352b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1353399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1354b285192aSMauro Carvalho Chehab 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1355b285192aSMauro Carvalho Chehab 					&core->i2c_adap,
1356b285192aSMauro Carvalho Chehab 					&pinnacle_pctv_hd_800i_tuner_config))
1357b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1358b285192aSMauro Carvalho Chehab 		}
1359b285192aSMauro Carvalho Chehab 		break;
1360b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1361b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1362b285192aSMauro Carvalho Chehab 					       &dvico_hdtv5_pci_nano_config,
1363b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1364399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1365b285192aSMauro Carvalho Chehab 			struct dvb_frontend *fe;
1366b285192aSMauro Carvalho Chehab 			struct xc2028_config cfg = {
1367b285192aSMauro Carvalho Chehab 				.i2c_adap  = &core->i2c_adap,
1368b285192aSMauro Carvalho Chehab 				.i2c_addr  = 0x61,
1369b285192aSMauro Carvalho Chehab 			};
1370b285192aSMauro Carvalho Chehab 			static struct xc2028_ctrl ctl = {
1371b285192aSMauro Carvalho Chehab 				.fname       = XC2028_DEFAULT_FIRMWARE,
1372b285192aSMauro Carvalho Chehab 				.max_len     = 64,
1373b285192aSMauro Carvalho Chehab 				.scode_table = XC3028_FE_OREN538,
1374b285192aSMauro Carvalho Chehab 			};
1375b285192aSMauro Carvalho Chehab 
1376b285192aSMauro Carvalho Chehab 			fe = dvb_attach(xc2028_attach,
1377b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend, &cfg);
1378399426caSMauro Carvalho Chehab 			if (fe && fe->ops.tuner_ops.set_config)
1379b285192aSMauro Carvalho Chehab 				fe->ops.tuner_ops.set_config(fe, &ctl);
1380b285192aSMauro Carvalho Chehab 		}
1381b285192aSMauro Carvalho Chehab 		break;
1382e6f45ea2SDaniel Gonzalez Cabanelas 	case CX88_BOARD_NOTONLYTV_LV3H:
1383b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
1384b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV1800H:
1385b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1386b285192aSMauro Carvalho Chehab 					       &cx88_pinnacle_hybrid_pctv,
1387b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1388b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1389b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1390b285192aSMauro Carvalho Chehab 			if (attach_xc3028(0x61, dev) < 0)
1391b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1392b285192aSMauro Carvalho Chehab 		}
1393b285192aSMauro Carvalho Chehab 		break;
1394b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
1395b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1396b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1397b285192aSMauro Carvalho Chehab 					       &cx88_pinnacle_hybrid_pctv,
1398b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1399b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1400b285192aSMauro Carvalho Chehab 			struct xc4000_config cfg = {
1401b285192aSMauro Carvalho Chehab 				.i2c_address	  = 0x61,
1402b285192aSMauro Carvalho Chehab 				.default_pm	  = 0,
1403b285192aSMauro Carvalho Chehab 				.dvb_amplitude	  = 134,
1404b285192aSMauro Carvalho Chehab 				.set_smoothedcvbs = 1,
1405b285192aSMauro Carvalho Chehab 				.if_khz		  = 4560
1406b285192aSMauro Carvalho Chehab 			};
1407b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1408b285192aSMauro Carvalho Chehab 			if (attach_xc4000(dev, &cfg) < 0)
1409b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1410b285192aSMauro Carvalho Chehab 		}
1411b285192aSMauro Carvalho Chehab 		break;
1412b285192aSMauro Carvalho Chehab 	case CX88_BOARD_GENIATECH_X8000_MT:
1413b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x00;
1414b285192aSMauro Carvalho Chehab 
1415b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1416b285192aSMauro Carvalho Chehab 					       &cx88_geniatech_x8000_mt,
1417b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1418b285192aSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
1419b285192aSMauro Carvalho Chehab 			goto frontend_detach;
1420b285192aSMauro Carvalho Chehab 		break;
1421b285192aSMauro Carvalho Chehab 	case CX88_BOARD_KWORLD_ATSC_120:
1422b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1423b285192aSMauro Carvalho Chehab 					       &kworld_atsc_120_config,
1424b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1425b285192aSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
1426b285192aSMauro Carvalho Chehab 			goto frontend_detach;
1427b285192aSMauro Carvalho Chehab 		break;
1428b285192aSMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
1429b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
1430b285192aSMauro Carvalho Chehab 					       &dvico_fusionhdtv7_config,
1431b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1432399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1433b285192aSMauro Carvalho Chehab 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1434b285192aSMauro Carvalho Chehab 					&core->i2c_adap,
1435b285192aSMauro Carvalho Chehab 					&dvico_fusionhdtv7_tuner_config))
1436b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1437b285192aSMauro Carvalho Chehab 		}
1438b285192aSMauro Carvalho Chehab 		break;
1439b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR4000:
1440b285192aSMauro Carvalho Chehab 		/* MFE frontend 1 */
1441b285192aSMauro Carvalho Chehab 		mfe_shared = 1;
1442b285192aSMauro Carvalho Chehab 		dev->frontends.gate = 2;
1443b285192aSMauro Carvalho Chehab 		/* DVB-S/S2 Init */
1444b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1445b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr4000_config,
1446b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1447b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1448b285192aSMauro Carvalho Chehab 			if (!dvb_attach(isl6421_attach,
1449b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend,
1450b285192aSMauro Carvalho Chehab 					&dev->core->i2c_adap,
145148a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
1452b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1453b285192aSMauro Carvalho Chehab 		}
1454b285192aSMauro Carvalho Chehab 		/* MFE frontend 2 */
14550b6b6302SHans Verkuil 		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
1456b285192aSMauro Carvalho Chehab 		if (!fe1)
1457b285192aSMauro Carvalho Chehab 			goto frontend_detach;
1458b285192aSMauro Carvalho Chehab 		/* DVB-T Init */
1459b285192aSMauro Carvalho Chehab 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
1460b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr_config,
1461b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1462b285192aSMauro Carvalho Chehab 		if (fe1->dvb.frontend) {
1463b285192aSMauro Carvalho Chehab 			fe1->dvb.frontend->id = 1;
1464b285192aSMauro Carvalho Chehab 			if (!dvb_attach(simple_tuner_attach,
1465b285192aSMauro Carvalho Chehab 					fe1->dvb.frontend,
1466b285192aSMauro Carvalho Chehab 					&dev->core->i2c_adap,
1467b285192aSMauro Carvalho Chehab 					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1468b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1469b285192aSMauro Carvalho Chehab 		}
1470b285192aSMauro Carvalho Chehab 		break;
1471b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
1472b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1473b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr4000_config,
1474b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1475b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1476b285192aSMauro Carvalho Chehab 			if (!dvb_attach(isl6421_attach,
1477b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend,
1478b285192aSMauro Carvalho Chehab 					&dev->core->i2c_adap,
147948a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
1480b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1481b285192aSMauro Carvalho Chehab 		}
1482b285192aSMauro Carvalho Chehab 		break;
1483b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PROF_6200:
1484b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TBS_8910:
1485b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TEVII_S420:
1486b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
1487b285192aSMauro Carvalho Chehab 						&tevii_tuner_sharp_config,
1488b285192aSMauro Carvalho Chehab 						&core->i2c_adap);
1489399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1490b285192aSMauro Carvalho Chehab 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
1491b285192aSMauro Carvalho Chehab 					&core->i2c_adap, DVB_PLL_OPERA1))
1492b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1493b285192aSMauro Carvalho Chehab 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1494b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1495b285192aSMauro Carvalho Chehab 
1496b285192aSMauro Carvalho Chehab 		} else {
1497b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend = dvb_attach(stv0288_attach,
1498b285192aSMauro Carvalho Chehab 							    &tevii_tuner_earda_config,
1499b285192aSMauro Carvalho Chehab 							    &core->i2c_adap);
1500399426caSMauro Carvalho Chehab 			if (fe0->dvb.frontend) {
1501399426caSMauro Carvalho Chehab 				if (!dvb_attach(stb6000_attach,
1502399426caSMauro Carvalho Chehab 						fe0->dvb.frontend, 0x61,
1503b285192aSMauro Carvalho Chehab 						&core->i2c_adap))
1504b285192aSMauro Carvalho Chehab 					goto frontend_detach;
1505b285192aSMauro Carvalho Chehab 				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1506b285192aSMauro Carvalho Chehab 				fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1507b285192aSMauro Carvalho Chehab 			}
1508b285192aSMauro Carvalho Chehab 		}
1509b285192aSMauro Carvalho Chehab 		break;
1510b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TEVII_S460:
1511b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1512b285192aSMauro Carvalho Chehab 					       &tevii_s460_config,
1513b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1514399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend)
1515b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1516b285192aSMauro Carvalho Chehab 		break;
1517b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TEVII_S464:
1518b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(ds3000_attach,
1519b285192aSMauro Carvalho Chehab 						&tevii_ds3000_config,
1520b285192aSMauro Carvalho Chehab 						&core->i2c_adap);
1521399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
152273f0af44SKonstantin Dimitrov 			dvb_attach(ts2020_attach, fe0->dvb.frontend,
152373f0af44SKonstantin Dimitrov 				   &tevii_ts2020_config, &core->i2c_adap);
1524b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage =
1525b285192aSMauro Carvalho Chehab 							tevii_dvbs_set_voltage;
152673f0af44SKonstantin Dimitrov 		}
1527b285192aSMauro Carvalho Chehab 		break;
1528b285192aSMauro Carvalho Chehab 	case CX88_BOARD_OMICOM_SS4_PCI:
1529b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TBS_8920:
1530b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PROF_7300:
1531b285192aSMauro Carvalho Chehab 	case CX88_BOARD_SATTRADE_ST4200:
1532b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1533b285192aSMauro Carvalho Chehab 					       &hauppauge_hvr4000_config,
1534b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1535399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend)
1536b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1537b285192aSMauro Carvalho Chehab 		break;
1538b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
1539b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1540b285192aSMauro Carvalho Chehab 					       &cx88_terratec_cinergy_ht_pci_mkii_config,
1541b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1542b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1543b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1544b285192aSMauro Carvalho Chehab 			if (attach_xc3028(0x61, dev) < 0)
1545b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1546b285192aSMauro Carvalho Chehab 		}
1547b285192aSMauro Carvalho Chehab 		break;
1548b285192aSMauro Carvalho Chehab 	case CX88_BOARD_PROF_7301:{
1549b285192aSMauro Carvalho Chehab 		struct dvb_tuner_ops *tuner_ops = NULL;
1550b285192aSMauro Carvalho Chehab 
1551b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(stv0900_attach,
1552b285192aSMauro Carvalho Chehab 					       &prof_7301_stv0900_config,
1553b285192aSMauro Carvalho Chehab 					       &core->i2c_adap, 0);
1554399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1555b285192aSMauro Carvalho Chehab 			if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
1556b285192aSMauro Carvalho Chehab 					&prof_7301_stb6100_config,
1557b285192aSMauro Carvalho Chehab 					&core->i2c_adap))
1558b285192aSMauro Carvalho Chehab 				goto frontend_detach;
1559b285192aSMauro Carvalho Chehab 
1560b285192aSMauro Carvalho Chehab 			tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
1561b285192aSMauro Carvalho Chehab 			tuner_ops->set_frequency = stb6100_set_freq;
1562b285192aSMauro Carvalho Chehab 			tuner_ops->get_frequency = stb6100_get_freq;
1563b285192aSMauro Carvalho Chehab 			tuner_ops->set_bandwidth = stb6100_set_bandw;
1564b285192aSMauro Carvalho Chehab 			tuner_ops->get_bandwidth = stb6100_get_bandw;
1565b285192aSMauro Carvalho Chehab 
1566b285192aSMauro Carvalho Chehab 			core->prev_set_voltage =
1567b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend->ops.set_voltage;
1568b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage =
1569b285192aSMauro Carvalho Chehab 					tevii_dvbs_set_voltage;
1570b285192aSMauro Carvalho Chehab 		}
1571b285192aSMauro Carvalho Chehab 		break;
1572b285192aSMauro Carvalho Chehab 		}
1573b285192aSMauro Carvalho Chehab 	case CX88_BOARD_SAMSUNG_SMT_7020:
1574b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1575b285192aSMauro Carvalho Chehab 
1576b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x0101);
1577b285192aSMauro Carvalho Chehab 
1578b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x01);
15799d08ba6dSJia-Ju Bai 		msleep(100);
1580b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x01);
15819d08ba6dSJia-Ju Bai 		msleep(200);
1582b285192aSMauro Carvalho Chehab 
1583b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
1584b285192aSMauro Carvalho Chehab 					       &samsung_stv0299_config,
1585b285192aSMauro Carvalho Chehab 					       &dev->core->i2c_adap);
1586b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1587b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.tuner_ops.set_params =
1588b285192aSMauro Carvalho Chehab 				samsung_smt_7020_tuner_set_params;
1589b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->tuner_priv =
1590b285192aSMauro Carvalho Chehab 				&dev->core->i2c_adap;
1591b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage =
1592b285192aSMauro Carvalho Chehab 				samsung_smt_7020_set_voltage;
1593b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_tone =
1594b285192aSMauro Carvalho Chehab 				samsung_smt_7020_set_tone;
1595b285192aSMauro Carvalho Chehab 		}
1596b285192aSMauro Carvalho Chehab 
1597b285192aSMauro Carvalho Chehab 		break;
1598b285192aSMauro Carvalho Chehab 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
1599b285192aSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x00;
1600b285192aSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mb86a16_attach,
1601b285192aSMauro Carvalho Chehab 					       &twinhan_vp1027,
1602b285192aSMauro Carvalho Chehab 					       &core->i2c_adap);
1603b285192aSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1604b285192aSMauro Carvalho Chehab 			core->prev_set_voltage =
1605b285192aSMauro Carvalho Chehab 					fe0->dvb.frontend->ops.set_voltage;
1606b285192aSMauro Carvalho Chehab 			fe0->dvb.frontend->ops.set_voltage =
1607b285192aSMauro Carvalho Chehab 					vp1027_set_voltage;
1608b285192aSMauro Carvalho Chehab 		}
1609b285192aSMauro Carvalho Chehab 		break;
1610b285192aSMauro Carvalho Chehab 
1611b285192aSMauro Carvalho Chehab 	default:
161265bc2fe8SMauro Carvalho Chehab 		pr_err("The frontend of your DVB/ATSC card isn't supported yet\n");
1613b285192aSMauro Carvalho Chehab 		break;
1614b285192aSMauro Carvalho Chehab 	}
1615b285192aSMauro Carvalho Chehab 
1616b285192aSMauro Carvalho Chehab 	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
161765bc2fe8SMauro Carvalho Chehab 		pr_err("frontend initialization failed\n");
1618b285192aSMauro Carvalho Chehab 		goto frontend_detach;
1619b285192aSMauro Carvalho Chehab 	}
1620b285192aSMauro Carvalho Chehab 	/* define general-purpose callback pointer */
1621b285192aSMauro Carvalho Chehab 	fe0->dvb.frontend->callback = cx88_tuner_callback;
1622b285192aSMauro Carvalho Chehab 
1623b285192aSMauro Carvalho Chehab 	/* Ensure all frontends negotiate bus access */
1624b285192aSMauro Carvalho Chehab 	fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1625b285192aSMauro Carvalho Chehab 	if (fe1)
1626b285192aSMauro Carvalho Chehab 		fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1627b285192aSMauro Carvalho Chehab 
16283aab15afSHans Verkuil 	/* Put the tuner in standby to keep it quiet */
16293aab15afSHans Verkuil 	call_all(core, tuner, standby);
1630b285192aSMauro Carvalho Chehab 
1631b285192aSMauro Carvalho Chehab 	/* register everything */
16320b6b6302SHans Verkuil 	res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
16332773b0e9SMauro Carvalho Chehab 				   &dev->pci->dev, NULL, adapter_nr,
16342773b0e9SMauro Carvalho Chehab 				   mfe_shared);
1635b285192aSMauro Carvalho Chehab 	if (res)
1636b285192aSMauro Carvalho Chehab 		goto frontend_detach;
1637b285192aSMauro Carvalho Chehab 	return res;
1638b285192aSMauro Carvalho Chehab 
1639b285192aSMauro Carvalho Chehab frontend_detach:
1640b285192aSMauro Carvalho Chehab 	core->gate_ctrl = NULL;
16410b6b6302SHans Verkuil 	vb2_dvb_dealloc_frontends(&dev->frontends);
1642b285192aSMauro Carvalho Chehab 	return res;
1643b285192aSMauro Carvalho Chehab }
1644b285192aSMauro Carvalho Chehab 
1645b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */
1646b285192aSMauro Carvalho Chehab 
1647b285192aSMauro Carvalho Chehab /* CX8802 MPEG -> mini driver - We have been given the hardware */
cx8802_dvb_advise_acquire(struct cx8802_driver * drv)1648b285192aSMauro Carvalho Chehab static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
1649b285192aSMauro Carvalho Chehab {
1650b285192aSMauro Carvalho Chehab 	struct cx88_core *core = drv->core;
1651b285192aSMauro Carvalho Chehab 	int err = 0;
16527b61ba8fSMauro Carvalho Chehab 
1653b285192aSMauro Carvalho Chehab 	dprintk(1, "%s\n", __func__);
1654b285192aSMauro Carvalho Chehab 
1655b285192aSMauro Carvalho Chehab 	switch (core->boardnr) {
1656b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR1300:
1657b285192aSMauro Carvalho Chehab 		/* We arrive here with either the cx23416 or the cx22702
1658b285192aSMauro Carvalho Chehab 		 * on the bus. Take the bus from the cx23416 and enable the
1659b285192aSMauro Carvalho Chehab 		 * cx22702 demod
1660b285192aSMauro Carvalho Chehab 		 */
1661b285192aSMauro Carvalho Chehab 		/* Toggle reset on cx22702 leaving i2c active */
1662b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x00000080);
1663b285192aSMauro Carvalho Chehab 		udelay(1000);
1664b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x00000080);
1665b285192aSMauro Carvalho Chehab 		udelay(50);
1666b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x00000080);
1667b285192aSMauro Carvalho Chehab 		udelay(1000);
1668b285192aSMauro Carvalho Chehab 		/* enable the cx22702 pins */
1669b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x00000004);
1670b285192aSMauro Carvalho Chehab 		udelay(1000);
1671b285192aSMauro Carvalho Chehab 		break;
1672b285192aSMauro Carvalho Chehab 
1673b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR3000:
1674b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR4000:
1675b285192aSMauro Carvalho Chehab 		/* Toggle reset on cx22702 leaving i2c active */
1676b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x00000080);
1677b285192aSMauro Carvalho Chehab 		udelay(1000);
1678b285192aSMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 0x00000080);
1679b285192aSMauro Carvalho Chehab 		udelay(50);
1680b285192aSMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 0x00000080);
1681b285192aSMauro Carvalho Chehab 		udelay(1000);
1682b285192aSMauro Carvalho Chehab 		switch (core->dvbdev->frontends.active_fe_id) {
1683b285192aSMauro Carvalho Chehab 		case 1: /* DVB-S/S2 Enabled */
1684b285192aSMauro Carvalho Chehab 			/* tri-state the cx22702 pins */
1685b285192aSMauro Carvalho Chehab 			cx_set(MO_GP0_IO, 0x00000004);
1686b285192aSMauro Carvalho Chehab 			/* Take the cx24116/cx24123 out of reset */
1687b285192aSMauro Carvalho Chehab 			cx_write(MO_SRST_IO, 1);
1688b285192aSMauro Carvalho Chehab 			core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
1689b285192aSMauro Carvalho Chehab 			break;
1690b285192aSMauro Carvalho Chehab 		case 2: /* DVB-T Enabled */
1691b285192aSMauro Carvalho Chehab 			/* Put the cx24116/cx24123 into reset */
1692b285192aSMauro Carvalho Chehab 			cx_write(MO_SRST_IO, 0);
1693b285192aSMauro Carvalho Chehab 			/* enable the cx22702 pins */
1694b285192aSMauro Carvalho Chehab 			cx_clear(MO_GP0_IO, 0x00000004);
1695b285192aSMauro Carvalho Chehab 			core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
1696b285192aSMauro Carvalho Chehab 			break;
1697b285192aSMauro Carvalho Chehab 		}
1698b285192aSMauro Carvalho Chehab 		udelay(1000);
1699b285192aSMauro Carvalho Chehab 		break;
1700b285192aSMauro Carvalho Chehab 
1701b285192aSMauro Carvalho Chehab 	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1702b285192aSMauro Carvalho Chehab 		/* set RF input to AIR for DVB-T (GPIO 16) */
1703b285192aSMauro Carvalho Chehab 		cx_write(MO_GP2_IO, 0x0101);
1704b285192aSMauro Carvalho Chehab 		break;
1705b285192aSMauro Carvalho Chehab 
1706b285192aSMauro Carvalho Chehab 	default:
1707b285192aSMauro Carvalho Chehab 		err = -ENODEV;
1708b285192aSMauro Carvalho Chehab 	}
1709b285192aSMauro Carvalho Chehab 	return err;
1710b285192aSMauro Carvalho Chehab }
1711b285192aSMauro Carvalho Chehab 
1712b285192aSMauro Carvalho Chehab /* CX8802 MPEG -> mini driver - We no longer have the hardware */
cx8802_dvb_advise_release(struct cx8802_driver * drv)1713b285192aSMauro Carvalho Chehab static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
1714b285192aSMauro Carvalho Chehab {
1715b285192aSMauro Carvalho Chehab 	struct cx88_core *core = drv->core;
1716b285192aSMauro Carvalho Chehab 	int err = 0;
17177b61ba8fSMauro Carvalho Chehab 
1718b285192aSMauro Carvalho Chehab 	dprintk(1, "%s\n", __func__);
1719b285192aSMauro Carvalho Chehab 
1720b285192aSMauro Carvalho Chehab 	switch (core->boardnr) {
1721b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR1300:
1722b285192aSMauro Carvalho Chehab 		/* Do Nothing, leave the cx22702 on the bus. */
1723b285192aSMauro Carvalho Chehab 		break;
1724b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR3000:
1725b285192aSMauro Carvalho Chehab 	case CX88_BOARD_HAUPPAUGE_HVR4000:
1726b285192aSMauro Carvalho Chehab 		break;
1727b285192aSMauro Carvalho Chehab 	default:
1728b285192aSMauro Carvalho Chehab 		err = -ENODEV;
1729b285192aSMauro Carvalho Chehab 	}
1730b285192aSMauro Carvalho Chehab 	return err;
1731b285192aSMauro Carvalho Chehab }
1732b285192aSMauro Carvalho Chehab 
cx8802_dvb_probe(struct cx8802_driver * drv)1733b285192aSMauro Carvalho Chehab static int cx8802_dvb_probe(struct cx8802_driver *drv)
1734b285192aSMauro Carvalho Chehab {
1735b285192aSMauro Carvalho Chehab 	struct cx88_core *core = drv->core;
1736b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = drv->core->dvbdev;
1737b285192aSMauro Carvalho Chehab 	int err;
17380b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe;
1739b285192aSMauro Carvalho Chehab 	int i;
1740b285192aSMauro Carvalho Chehab 
1741b285192aSMauro Carvalho Chehab 	dprintk(1, "%s\n", __func__);
1742b285192aSMauro Carvalho Chehab 	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1743b285192aSMauro Carvalho Chehab 		core->boardnr,
1744b285192aSMauro Carvalho Chehab 		core->name,
1745b285192aSMauro Carvalho Chehab 		core->pci_bus,
1746b285192aSMauro Carvalho Chehab 		core->pci_slot);
1747b285192aSMauro Carvalho Chehab 
1748b285192aSMauro Carvalho Chehab 	err = -ENODEV;
1749b285192aSMauro Carvalho Chehab 	if (!(core->board.mpeg & CX88_MPEG_DVB))
1750b285192aSMauro Carvalho Chehab 		goto fail_core;
1751b285192aSMauro Carvalho Chehab 
1752b285192aSMauro Carvalho Chehab 	/* If vp3054 isn't enabled, a stub will just return 0 */
1753b285192aSMauro Carvalho Chehab 	err = vp3054_i2c_probe(dev);
17547b61ba8fSMauro Carvalho Chehab 	if (err != 0)
1755b285192aSMauro Carvalho Chehab 		goto fail_core;
1756b285192aSMauro Carvalho Chehab 
1757b285192aSMauro Carvalho Chehab 	/* dvb stuff */
175865bc2fe8SMauro Carvalho Chehab 	pr_info("cx2388x based DVB/ATSC card\n");
1759b285192aSMauro Carvalho Chehab 	dev->ts_gen_cntrl = 0x0c;
1760b285192aSMauro Carvalho Chehab 
1761b285192aSMauro Carvalho Chehab 	err = cx8802_alloc_frontends(dev);
1762b285192aSMauro Carvalho Chehab 	if (err)
1763b285192aSMauro Carvalho Chehab 		goto fail_core;
1764b285192aSMauro Carvalho Chehab 
1765b285192aSMauro Carvalho Chehab 	for (i = 1; i <= core->board.num_frontends; i++) {
17660b6b6302SHans Verkuil 		struct vb2_queue *q;
17670b6b6302SHans Verkuil 
17680b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
1769399426caSMauro Carvalho Chehab 		if (!fe) {
177065bc2fe8SMauro Carvalho Chehab 			pr_err("%s() failed to get frontend(%d)\n",
1771b285192aSMauro Carvalho Chehab 			       __func__, i);
1772e546b1efSWei Yongjun 			err = -ENODEV;
1773b285192aSMauro Carvalho Chehab 			goto fail_probe;
1774b285192aSMauro Carvalho Chehab 		}
17750b6b6302SHans Verkuil 		q = &fe->dvb.dvbq;
17760b6b6302SHans Verkuil 		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
17770b6b6302SHans Verkuil 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
17780b6b6302SHans Verkuil 		q->gfp_flags = GFP_DMA32;
17790b6b6302SHans Verkuil 		q->min_buffers_needed = 2;
17800b6b6302SHans Verkuil 		q->drv_priv = dev;
17810b6b6302SHans Verkuil 		q->buf_struct_size = sizeof(struct cx88_buffer);
17820b6b6302SHans Verkuil 		q->ops = &dvb_qops;
17830b6b6302SHans Verkuil 		q->mem_ops = &vb2_dma_sg_memops;
17840b6b6302SHans Verkuil 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
17850b6b6302SHans Verkuil 		q->lock = &core->lock;
17862bc46b3aSHans Verkuil 		q->dev = &dev->pci->dev;
17870b6b6302SHans Verkuil 
17880b6b6302SHans Verkuil 		err = vb2_queue_init(q);
17890b6b6302SHans Verkuil 		if (err < 0)
17900b6b6302SHans Verkuil 			goto fail_probe;
17910b6b6302SHans Verkuil 
17920b6b6302SHans Verkuil 		/* init struct vb2_dvb */
1793b285192aSMauro Carvalho Chehab 		fe->dvb.name = dev->core->name;
1794b285192aSMauro Carvalho Chehab 	}
1795b285192aSMauro Carvalho Chehab 
1796b285192aSMauro Carvalho Chehab 	err = dvb_register(dev);
1797b285192aSMauro Carvalho Chehab 	if (err)
1798b285192aSMauro Carvalho Chehab 		/* frontends/adapter de-allocated in dvb_register */
179965bc2fe8SMauro Carvalho Chehab 		pr_err("dvb_register failed (err = %d)\n", err);
1800b285192aSMauro Carvalho Chehab 	return err;
1801b285192aSMauro Carvalho Chehab fail_probe:
18020b6b6302SHans Verkuil 	vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
1803b285192aSMauro Carvalho Chehab fail_core:
1804b285192aSMauro Carvalho Chehab 	return err;
1805b285192aSMauro Carvalho Chehab }
1806b285192aSMauro Carvalho Chehab 
cx8802_dvb_remove(struct cx8802_driver * drv)1807b285192aSMauro Carvalho Chehab static int cx8802_dvb_remove(struct cx8802_driver *drv)
1808b285192aSMauro Carvalho Chehab {
1809b285192aSMauro Carvalho Chehab 	struct cx88_core *core = drv->core;
1810b285192aSMauro Carvalho Chehab 	struct cx8802_dev *dev = drv->core->dvbdev;
1811b285192aSMauro Carvalho Chehab 
1812b285192aSMauro Carvalho Chehab 	dprintk(1, "%s\n", __func__);
1813b285192aSMauro Carvalho Chehab 
18140b6b6302SHans Verkuil 	vb2_dvb_unregister_bus(&dev->frontends);
1815b285192aSMauro Carvalho Chehab 
1816b285192aSMauro Carvalho Chehab 	vp3054_i2c_remove(dev);
1817b285192aSMauro Carvalho Chehab 
1818b285192aSMauro Carvalho Chehab 	core->gate_ctrl = NULL;
1819b285192aSMauro Carvalho Chehab 
1820b285192aSMauro Carvalho Chehab 	return 0;
1821b285192aSMauro Carvalho Chehab }
1822b285192aSMauro Carvalho Chehab 
1823b285192aSMauro Carvalho Chehab static struct cx8802_driver cx8802_dvb_driver = {
1824b285192aSMauro Carvalho Chehab 	.type_id        = CX88_MPEG_DVB,
1825b285192aSMauro Carvalho Chehab 	.hw_access      = CX8802_DRVCTL_SHARED,
1826b285192aSMauro Carvalho Chehab 	.probe          = cx8802_dvb_probe,
1827b285192aSMauro Carvalho Chehab 	.remove         = cx8802_dvb_remove,
1828b285192aSMauro Carvalho Chehab 	.advise_acquire = cx8802_dvb_advise_acquire,
1829b285192aSMauro Carvalho Chehab 	.advise_release = cx8802_dvb_advise_release,
1830b285192aSMauro Carvalho Chehab };
1831b285192aSMauro Carvalho Chehab 
dvb_init(void)1832b285192aSMauro Carvalho Chehab static int __init dvb_init(void)
1833b285192aSMauro Carvalho Chehab {
183465bc2fe8SMauro Carvalho Chehab 	pr_info("cx2388x dvb driver version %s loaded\n", CX88_VERSION);
1835b285192aSMauro Carvalho Chehab 	return cx8802_register_driver(&cx8802_dvb_driver);
1836b285192aSMauro Carvalho Chehab }
1837b285192aSMauro Carvalho Chehab 
dvb_fini(void)1838b285192aSMauro Carvalho Chehab static void __exit dvb_fini(void)
1839b285192aSMauro Carvalho Chehab {
1840b285192aSMauro Carvalho Chehab 	cx8802_unregister_driver(&cx8802_dvb_driver);
1841b285192aSMauro Carvalho Chehab }
1842b285192aSMauro Carvalho Chehab 
1843b285192aSMauro Carvalho Chehab module_init(dvb_init);
1844b285192aSMauro Carvalho Chehab module_exit(dvb_fini);
1845