xref: /linux/drivers/media/pci/cx88/cx88-dvb.c (revision c771600c6af14749609b49565ffb4cac2959710d)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * device driver for Conexant 2388x based TV cards
41da177e4SLinus Torvalds  * MPEG Transport Stream (DVB) routines
51da177e4SLinus Torvalds  *
6fc40b261SChris Pascoe  * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
71da177e4SLinus Torvalds  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
1065bc2fe8SMauro Carvalho Chehab #include "cx88.h"
1165bc2fe8SMauro Carvalho Chehab #include "dvb-pll.h"
1265bc2fe8SMauro Carvalho Chehab 
131da177e4SLinus Torvalds #include <linux/module.h>
141da177e4SLinus Torvalds #include <linux/init.h>
151da177e4SLinus Torvalds #include <linux/device.h>
161da177e4SLinus Torvalds #include <linux/fs.h>
171da177e4SLinus Torvalds #include <linux/kthread.h>
181da177e4SLinus Torvalds #include <linux/file.h>
191da177e4SLinus Torvalds #include <linux/suspend.h>
201da177e4SLinus Torvalds 
215e453dc7SMichael Krufky #include <media/v4l2-common.h>
2241ef7c1eSMauro Carvalho Chehab 
231da177e4SLinus Torvalds #include "mt352.h"
241da177e4SLinus Torvalds #include "mt352_priv.h"
25fc40b261SChris Pascoe #include "cx88-vp3054-i2c.h"
26780dfef3SChris Pascoe #include "zl10353.h"
271da177e4SLinus Torvalds #include "cx22702.h"
281da177e4SLinus Torvalds #include "or51132.h"
296ddcc919SMichael Krufky #include "lgdt330x.h"
3060464da8SSteven Toth #include "s5h1409.h"
31c21973e8Sistvan_v@mailbox.hu #include "xc4000.h"
3260464da8SSteven Toth #include "xc5000.h"
33fde6d31eSKirk Lapray #include "nxt200x.h"
340fa14aa6SSteven Toth #include "cx24123.h"
35cd20ca9fSAndrew de Quincey #include "isl6421.h"
360df31f83SMichael Krufky #include "tuner-simple.h"
37827855d3SMichael Krufky #include "tda9887.h"
38d893d5dcSSteven Toth #include "s5h1411.h"
39e4aab64cSIgor M. Liplianin #include "stv0299.h"
40e4aab64cSIgor M. Liplianin #include "z0194a.h"
41e4aab64cSIgor M. Liplianin #include "stv0288.h"
42e4aab64cSIgor M. Liplianin #include "stb6000.h"
435bd1b663SSteven Toth #include "cx24116.h"
44b699c271SIgor M. Liplianin #include "stv0900.h"
45b699c271SIgor M. Liplianin #include "stb6100.h"
46b699c271SIgor M. Liplianin #include "stb6100_proc.h"
47111ac84aSSergey Ivanov #include "mb86a16.h"
4873f0af44SKonstantin Dimitrov #include "ts2020.h"
490cb73639SIgor M. Liplianin #include "ds3000.h"
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
521da177e4SLinus Torvalds MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
531da177e4SLinus Torvalds MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
541da177e4SLinus Torvalds MODULE_LICENSE("GPL");
551990d50bSMauro Carvalho Chehab MODULE_VERSION(CX88_VERSION);
561da177e4SLinus Torvalds 
57ff699e6bSDouglas Schilling Landgraf static unsigned int debug;
581da177e4SLinus Torvalds module_param(debug, int, 0644);
591da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
601da177e4SLinus Torvalds 
6144c6e2a7SAng Way Chuang static unsigned int dvb_buf_tscnt = 32;
6244c6e2a7SAng Way Chuang module_param(dvb_buf_tscnt, int, 0644);
6344c6e2a7SAng Way Chuang MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]");
6444c6e2a7SAng Way Chuang 
6578e92006SJanne Grunau DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
6678e92006SJanne Grunau 
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)
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds /* ------------------------------------------------------------------ */
741da177e4SLinus Torvalds 
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[])
781da177e4SLinus Torvalds {
790b6b6302SHans Verkuil 	struct cx8802_dev *dev = q->drv_priv;
801da177e4SLinus Torvalds 
810b6b6302SHans Verkuil 	*num_planes = 1;
821da177e4SLinus Torvalds 	dev->ts_packet_size  = 188 * 4;
8344c6e2a7SAng Way Chuang 	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;
861da177e4SLinus Torvalds 	return 0;
871da177e4SLinus Torvalds }
881da177e4SLinus Torvalds 
buffer_prepare(struct vb2_buffer * vb)890b6b6302SHans Verkuil static int buffer_prepare(struct vb2_buffer *vb)
901da177e4SLinus Torvalds {
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);
961da177e4SLinus Torvalds }
971da177e4SLinus Torvalds 
buffer_finish(struct vb2_buffer * vb)980b6b6302SHans Verkuil static void buffer_finish(struct vb2_buffer *vb)
991da177e4SLinus Torvalds {
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)
10600ae4ebcSChristophe JAILLET 		dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu,
10700ae4ebcSChristophe JAILLET 				  risc->dma);
1085e7045e3SHans Verkuil 	memset(risc, 0, sizeof(*risc));
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds 
buffer_queue(struct vb2_buffer * vb)1110b6b6302SHans Verkuil static void buffer_queue(struct vb2_buffer *vb)
1121da177e4SLinus Torvalds {
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);
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
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 	.start_streaming = start_streaming,
1560b6b6302SHans Verkuil 	.stop_streaming = stop_streaming,
1571da177e4SLinus Torvalds };
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds /* ------------------------------------------------------------------ */
16022f3f17dSMichael Krufky 
cx88_dvb_bus_ctrl(struct dvb_frontend * fe,int acquire)16122f3f17dSMichael Krufky static int cx88_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
16222f3f17dSMichael Krufky {
16322f3f17dSMichael Krufky 	struct cx8802_dev *dev = fe->dvb->priv;
16422f3f17dSMichael Krufky 	struct cx8802_driver *drv = NULL;
16522f3f17dSMichael Krufky 	int ret = 0;
166363c35fcSSteven Toth 	int fe_id;
167363c35fcSSteven Toth 
1680b6b6302SHans Verkuil 	fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
169363c35fcSSteven Toth 	if (!fe_id) {
17065bc2fe8SMauro Carvalho Chehab 		pr_err("%s() No frontend found\n", __func__);
171363c35fcSSteven Toth 		return -EINVAL;
172363c35fcSSteven Toth 	}
173363c35fcSSteven Toth 
1748a317a87SJonathan Nieder 	mutex_lock(&dev->core->lock);
17522f3f17dSMichael Krufky 	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
17622f3f17dSMichael Krufky 	if (drv) {
177363c35fcSSteven Toth 		if (acquire) {
178363c35fcSSteven Toth 			dev->frontends.active_fe_id = fe_id;
17922f3f17dSMichael Krufky 			ret = drv->request_acquire(drv);
180363c35fcSSteven Toth 		} else {
18122f3f17dSMichael Krufky 			ret = drv->request_release(drv);
182363c35fcSSteven Toth 			dev->frontends.active_fe_id = 0;
183363c35fcSSteven Toth 		}
18422f3f17dSMichael Krufky 	}
1851fe70e96SJonathan Nieder 	mutex_unlock(&dev->core->lock);
18622f3f17dSMichael Krufky 
18722f3f17dSMichael Krufky 	return ret;
18822f3f17dSMichael Krufky }
18922f3f17dSMichael Krufky 
cx88_dvb_gate_ctrl(struct cx88_core * core,int open)190e32fadc4SMauro Carvalho Chehab static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
191e32fadc4SMauro Carvalho Chehab {
1920b6b6302SHans Verkuil 	struct vb2_dvb_frontends *f;
1930b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe;
194e32fadc4SMauro Carvalho Chehab 
195e32fadc4SMauro Carvalho Chehab 	if (!core->dvbdev)
196e32fadc4SMauro Carvalho Chehab 		return;
197e32fadc4SMauro Carvalho Chehab 
198e32fadc4SMauro Carvalho Chehab 	f = &core->dvbdev->frontends;
199e32fadc4SMauro Carvalho Chehab 
200e32fadc4SMauro Carvalho Chehab 	if (!f)
201e32fadc4SMauro Carvalho Chehab 		return;
202e32fadc4SMauro Carvalho Chehab 
203e32fadc4SMauro Carvalho Chehab 	if (f->gate <= 1) /* undefined or fe0 */
2040b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(f, 1);
205e32fadc4SMauro Carvalho Chehab 	else
2060b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(f, f->gate);
207e32fadc4SMauro Carvalho Chehab 
208e32fadc4SMauro Carvalho Chehab 	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
209e32fadc4SMauro Carvalho Chehab 		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
210e32fadc4SMauro Carvalho Chehab }
211e32fadc4SMauro Carvalho Chehab 
21222f3f17dSMichael Krufky /* ------------------------------------------------------------------ */
21322f3f17dSMichael Krufky 
dvico_fusionhdtv_demod_init(struct dvb_frontend * fe)2143d7d027aSChris Pascoe static int dvico_fusionhdtv_demod_init(struct dvb_frontend *fe)
2151da177e4SLinus Torvalds {
2162e4e98e7Slawrence rust 	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x39 };
2172e4e98e7Slawrence rust 	static const u8 reset[]         = { RESET,      0x80 };
2182e4e98e7Slawrence rust 	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
2192e4e98e7Slawrence rust 	static const u8 agc_cfg[]       = { AGC_TARGET, 0x24, 0x20 };
2202e4e98e7Slawrence rust 	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
2212e4e98e7Slawrence rust 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 	mt352_write(fe, clock_config,   sizeof(clock_config));
2241da177e4SLinus Torvalds 	udelay(200);
2251da177e4SLinus Torvalds 	mt352_write(fe, reset,          sizeof(reset));
2261da177e4SLinus Torvalds 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
2291da177e4SLinus Torvalds 	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
2301da177e4SLinus Torvalds 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
2311da177e4SLinus Torvalds 	return 0;
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds 
dvico_dual_demod_init(struct dvb_frontend * fe)23443eabb4eSChris Pascoe static int dvico_dual_demod_init(struct dvb_frontend *fe)
23543eabb4eSChris Pascoe {
2362e4e98e7Slawrence rust 	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x38 };
2372e4e98e7Slawrence rust 	static const u8 reset[]         = { RESET,      0x80 };
2382e4e98e7Slawrence rust 	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
2392e4e98e7Slawrence rust 	static const u8 agc_cfg[]       = { AGC_TARGET, 0x28, 0x20 };
2402e4e98e7Slawrence rust 	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
2412e4e98e7Slawrence rust 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
24243eabb4eSChris Pascoe 
24343eabb4eSChris Pascoe 	mt352_write(fe, clock_config,   sizeof(clock_config));
24443eabb4eSChris Pascoe 	udelay(200);
24543eabb4eSChris Pascoe 	mt352_write(fe, reset,          sizeof(reset));
24643eabb4eSChris Pascoe 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
24743eabb4eSChris Pascoe 
24843eabb4eSChris Pascoe 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
24943eabb4eSChris Pascoe 	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
25043eabb4eSChris Pascoe 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
25143eabb4eSChris Pascoe 
25243eabb4eSChris Pascoe 	return 0;
25343eabb4eSChris Pascoe }
25443eabb4eSChris Pascoe 
dntv_live_dvbt_demod_init(struct dvb_frontend * fe)2551da177e4SLinus Torvalds static int dntv_live_dvbt_demod_init(struct dvb_frontend *fe)
2561da177e4SLinus Torvalds {
2572e4e98e7Slawrence rust 	static const u8 clock_config[]  = { 0x89, 0x38, 0x39 };
2582e4e98e7Slawrence rust 	static const u8 reset[]         = { 0x50, 0x80 };
2592e4e98e7Slawrence rust 	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
2602e4e98e7Slawrence rust 	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
2611da177e4SLinus Torvalds 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
2622e4e98e7Slawrence rust 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
2632e4e98e7Slawrence rust 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
2641da177e4SLinus Torvalds 
2651da177e4SLinus Torvalds 	mt352_write(fe, clock_config,   sizeof(clock_config));
2661da177e4SLinus Torvalds 	udelay(2000);
2671da177e4SLinus Torvalds 	mt352_write(fe, reset,          sizeof(reset));
2681da177e4SLinus Torvalds 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
2711da177e4SLinus Torvalds 	udelay(2000);
2721da177e4SLinus Torvalds 	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
2731da177e4SLinus Torvalds 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds 	return 0;
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
2782e4e98e7Slawrence rust static const struct mt352_config dvico_fusionhdtv = {
279f7b54b10SMichael Krufky 	.demod_address = 0x0f,
2803d7d027aSChris Pascoe 	.demod_init    = dvico_fusionhdtv_demod_init,
2811da177e4SLinus Torvalds };
2821da177e4SLinus Torvalds 
2832e4e98e7Slawrence rust static const struct mt352_config dntv_live_dvbt_config = {
2841da177e4SLinus Torvalds 	.demod_address = 0x0f,
2851da177e4SLinus Torvalds 	.demod_init    = dntv_live_dvbt_demod_init,
2861da177e4SLinus Torvalds };
287fc40b261SChris Pascoe 
2882e4e98e7Slawrence rust static const struct mt352_config dvico_fusionhdtv_dual = {
289f7b54b10SMichael Krufky 	.demod_address = 0x0f,
29043eabb4eSChris Pascoe 	.demod_init    = dvico_dual_demod_init,
29143eabb4eSChris Pascoe };
29243eabb4eSChris Pascoe 
2932e4e98e7Slawrence rust static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
29470101a27SStephan Wienczny 	.demod_address = (0x1e >> 1),
29570101a27SStephan Wienczny 	.no_tuner      = 1,
29670101a27SStephan Wienczny 	.if2           = 45600,
29770101a27SStephan Wienczny };
29870101a27SStephan Wienczny 
2990244fd78SBhumika Goyal static const struct mb86a16_config twinhan_vp1027 = {
300111ac84aSSergey Ivanov 	.demod_address  = 0x08,
301111ac84aSSergey Ivanov };
302111ac84aSSergey Ivanov 
3037b34be71SPeter Senna Tschudin #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
dntv_live_dvbt_pro_demod_init(struct dvb_frontend * fe)3043d7d027aSChris Pascoe static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend *fe)
3053d7d027aSChris Pascoe {
3062e4e98e7Slawrence rust 	static const u8 clock_config[]  = { 0x89, 0x38, 0x38 };
3072e4e98e7Slawrence rust 	static const u8 reset[]         = { 0x50, 0x80 };
3082e4e98e7Slawrence rust 	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
3092e4e98e7Slawrence rust 	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
3103d7d027aSChris Pascoe 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
3112e4e98e7Slawrence rust 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
3122e4e98e7Slawrence rust 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
3133d7d027aSChris Pascoe 
3143d7d027aSChris Pascoe 	mt352_write(fe, clock_config,   sizeof(clock_config));
3153d7d027aSChris Pascoe 	udelay(2000);
3163d7d027aSChris Pascoe 	mt352_write(fe, reset,          sizeof(reset));
3173d7d027aSChris Pascoe 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
3183d7d027aSChris Pascoe 
3193d7d027aSChris Pascoe 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
3203d7d027aSChris Pascoe 	udelay(2000);
3213d7d027aSChris Pascoe 	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
3223d7d027aSChris Pascoe 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
3233d7d027aSChris Pascoe 
3243d7d027aSChris Pascoe 	return 0;
3253d7d027aSChris Pascoe }
3263d7d027aSChris Pascoe 
3272e4e98e7Slawrence rust static const struct mt352_config dntv_live_dvbt_pro_config = {
328fc40b261SChris Pascoe 	.demod_address = 0x0f,
329fc40b261SChris Pascoe 	.no_tuner      = 1,
3303d7d027aSChris Pascoe 	.demod_init    = dntv_live_dvbt_pro_demod_init,
331fc40b261SChris Pascoe };
332fc40b261SChris Pascoe #endif
3331da177e4SLinus Torvalds 
3342e4e98e7Slawrence rust static const struct zl10353_config dvico_fusionhdtv_hybrid = {
335f7b54b10SMichael Krufky 	.demod_address = 0x0f,
336f54376e2SAndrew de Quincey 	.no_tuner      = 1,
337780dfef3SChris Pascoe };
338780dfef3SChris Pascoe 
3392e4e98e7Slawrence rust static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
340b3fb91d2SChris Pascoe 	.demod_address = 0x0f,
341b3fb91d2SChris Pascoe 	.if2           = 45600,
342b3fb91d2SChris Pascoe 	.no_tuner      = 1,
343b3fb91d2SChris Pascoe };
344b3fb91d2SChris Pascoe 
3452e4e98e7Slawrence rust static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
346b3fb91d2SChris Pascoe 	.demod_address = 0x0f,
347b3fb91d2SChris Pascoe 	.if2 = 4560,
348b3fb91d2SChris Pascoe 	.no_tuner = 1,
349b3fb91d2SChris Pascoe 	.demod_init = dvico_fusionhdtv_demod_init,
350b3fb91d2SChris Pascoe };
351b3fb91d2SChris Pascoe 
3522e4e98e7Slawrence rust static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
353f7b54b10SMichael Krufky 	.demod_address = 0x0f,
354780dfef3SChris Pascoe };
355780dfef3SChris Pascoe 
3562e4e98e7Slawrence rust static const struct cx22702_config connexant_refboard_config = {
3571da177e4SLinus Torvalds 	.demod_address = 0x43,
35838d84c3bSPatrick Boettcher 	.output_mode   = CX22702_SERIAL_OUTPUT,
3591da177e4SLinus Torvalds };
3601da177e4SLinus Torvalds 
3612e4e98e7Slawrence rust static const struct cx22702_config hauppauge_hvr_config = {
362aa481a65SSteven Toth 	.demod_address = 0x63,
363aa481a65SSteven Toth 	.output_mode   = CX22702_SERIAL_OUTPUT,
364aa481a65SSteven Toth };
3651da177e4SLinus Torvalds 
or51132_set_ts_param(struct dvb_frontend * fe,int is_punctured)3664a390558SMichael Krufky static int or51132_set_ts_param(struct dvb_frontend *fe, int is_punctured)
3671da177e4SLinus Torvalds {
3681da177e4SLinus Torvalds 	struct cx8802_dev *dev = fe->dvb->priv;
3697b61ba8fSMauro Carvalho Chehab 
3701da177e4SLinus Torvalds 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
3711da177e4SLinus Torvalds 	return 0;
3721da177e4SLinus Torvalds }
3731da177e4SLinus Torvalds 
3742e4e98e7Slawrence rust static const struct or51132_config pchdtv_hd3000 = {
3751da177e4SLinus Torvalds 	.demod_address = 0x15,
3761da177e4SLinus Torvalds 	.set_ts_params = or51132_set_ts_param,
3771da177e4SLinus Torvalds };
3781da177e4SLinus Torvalds 
lgdt330x_pll_rf_set(struct dvb_frontend * fe,int index)3796ddcc919SMichael Krufky static int lgdt330x_pll_rf_set(struct dvb_frontend *fe, int index)
3800ccef6dbSMichael Krufky {
3810ccef6dbSMichael Krufky 	struct cx8802_dev *dev = fe->dvb->priv;
3820ccef6dbSMichael Krufky 	struct cx88_core *core = dev->core;
3830ccef6dbSMichael Krufky 
38432d83efcSHarvey Harrison 	dprintk(1, "%s: index = %d\n", __func__, index);
3850ccef6dbSMichael Krufky 	if (index == 0)
3860ccef6dbSMichael Krufky 		cx_clear(MO_GP0_IO, 8);
3870ccef6dbSMichael Krufky 	else
3880ccef6dbSMichael Krufky 		cx_set(MO_GP0_IO, 8);
3890ccef6dbSMichael Krufky 	return 0;
3900ccef6dbSMichael Krufky }
3910ccef6dbSMichael Krufky 
lgdt330x_set_ts_param(struct dvb_frontend * fe,int is_punctured)3926ddcc919SMichael Krufky static int lgdt330x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
393f1798495SMichael Krufky {
394f1798495SMichael Krufky 	struct cx8802_dev *dev = fe->dvb->priv;
3957b61ba8fSMauro Carvalho Chehab 
396f1798495SMichael Krufky 	if (is_punctured)
397f1798495SMichael Krufky 		dev->ts_gen_cntrl |= 0x04;
398f1798495SMichael Krufky 	else
399f1798495SMichael Krufky 		dev->ts_gen_cntrl &= ~0x04;
400f1798495SMichael Krufky 	return 0;
401f1798495SMichael Krufky }
402f1798495SMichael Krufky 
4036ddcc919SMichael Krufky static struct lgdt330x_config fusionhdtv_3_gold = {
4041963c907SMichael Krufky 	.demod_chip    = LGDT3302,
4051963c907SMichael Krufky 	.serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
4066ddcc919SMichael Krufky 	.set_ts_params = lgdt330x_set_ts_param,
4070d723c09SMichael Krufky };
408e52e98a7SMauro Carvalho Chehab 
4092e4e98e7Slawrence rust static const struct lgdt330x_config fusionhdtv_5_gold = {
410e52e98a7SMauro Carvalho Chehab 	.demod_chip    = LGDT3303,
411e52e98a7SMauro Carvalho Chehab 	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
412e52e98a7SMauro Carvalho Chehab 	.set_ts_params = lgdt330x_set_ts_param,
413e52e98a7SMauro Carvalho Chehab };
414da215d22SRusty Scott 
4152e4e98e7Slawrence rust static const struct lgdt330x_config pchdtv_hd5500 = {
416da215d22SRusty Scott 	.demod_chip    = LGDT3303,
417da215d22SRusty Scott 	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
418da215d22SRusty Scott 	.set_ts_params = lgdt330x_set_ts_param,
419da215d22SRusty Scott };
420f1798495SMichael Krufky 
nxt200x_set_ts_param(struct dvb_frontend * fe,int is_punctured)4214a390558SMichael Krufky static int nxt200x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
422fde6d31eSKirk Lapray {
423fde6d31eSKirk Lapray 	struct cx8802_dev *dev = fe->dvb->priv;
4247b61ba8fSMauro Carvalho Chehab 
425fde6d31eSKirk Lapray 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
426fde6d31eSKirk Lapray 	return 0;
427fde6d31eSKirk Lapray }
428fde6d31eSKirk Lapray 
4292e4e98e7Slawrence rust static const struct nxt200x_config ati_hdtvwonder = {
430fde6d31eSKirk Lapray 	.demod_address = 0x0a,
431fde6d31eSKirk Lapray 	.set_ts_params = nxt200x_set_ts_param,
432fde6d31eSKirk Lapray };
433fde6d31eSKirk Lapray 
cx24123_set_ts_param(struct dvb_frontend * fe,int is_punctured)4340fa14aa6SSteven Toth static int cx24123_set_ts_param(struct dvb_frontend *fe,
4350fa14aa6SSteven Toth 				int is_punctured)
4360fa14aa6SSteven Toth {
4370fa14aa6SSteven Toth 	struct cx8802_dev *dev = fe->dvb->priv;
4387b61ba8fSMauro Carvalho Chehab 
439f7b54b10SMichael Krufky 	dev->ts_gen_cntrl = 0x02;
4400fa14aa6SSteven Toth 	return 0;
4410fa14aa6SSteven Toth }
4420fa14aa6SSteven Toth 
kworld_dvbs_100_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)443f7b54b10SMichael Krufky static int kworld_dvbs_100_set_voltage(struct dvb_frontend *fe,
4440df289a2SMauro Carvalho Chehab 				       enum fe_sec_voltage voltage)
4450e0351e3SVadim Catana {
4460e0351e3SVadim Catana 	struct cx8802_dev *dev = fe->dvb->priv;
4470e0351e3SVadim Catana 	struct cx88_core *core = dev->core;
4480e0351e3SVadim Catana 
4494a390558SMichael Krufky 	if (voltage == SEC_VOLTAGE_OFF)
450f7b54b10SMichael Krufky 		cx_write(MO_GP0_IO, 0x000006fb);
4514a390558SMichael Krufky 	else
452cd20ca9fSAndrew de Quincey 		cx_write(MO_GP0_IO, 0x000006f9);
453cd20ca9fSAndrew de Quincey 
454cd20ca9fSAndrew de Quincey 	if (core->prev_set_voltage)
455cd20ca9fSAndrew de Quincey 		return core->prev_set_voltage(fe, voltage);
456cd20ca9fSAndrew de Quincey 	return 0;
4570e0351e3SVadim Catana }
4580e0351e3SVadim Catana 
geniatech_dvbs_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)459f7b54b10SMichael Krufky static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
4600df289a2SMauro Carvalho Chehab 				      enum fe_sec_voltage voltage)
461c02a34f4SSaqeb Akhter {
462c02a34f4SSaqeb Akhter 	struct cx8802_dev *dev = fe->dvb->priv;
463c02a34f4SSaqeb Akhter 	struct cx88_core *core = dev->core;
464c02a34f4SSaqeb Akhter 
465c02a34f4SSaqeb Akhter 	if (voltage == SEC_VOLTAGE_OFF) {
466c02a34f4SSaqeb Akhter 		dprintk(1, "LNB Voltage OFF\n");
467c02a34f4SSaqeb Akhter 		cx_write(MO_GP0_IO, 0x0000efff);
468c02a34f4SSaqeb Akhter 	}
469c02a34f4SSaqeb Akhter 
470c02a34f4SSaqeb Akhter 	if (core->prev_set_voltage)
471c02a34f4SSaqeb Akhter 		return core->prev_set_voltage(fe, voltage);
472c02a34f4SSaqeb Akhter 	return 0;
473c02a34f4SSaqeb Akhter }
474c02a34f4SSaqeb Akhter 
tevii_dvbs_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)475af832623SIgor M. Liplianin static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
4760df289a2SMauro Carvalho Chehab 				  enum fe_sec_voltage voltage)
477af832623SIgor M. Liplianin {
478af832623SIgor M. Liplianin 	struct cx8802_dev *dev = fe->dvb->priv;
479af832623SIgor M. Liplianin 	struct cx88_core *core = dev->core;
480af832623SIgor M. Liplianin 
481ad5f74c0SIgor M. Liplianin 	cx_set(MO_GP0_IO, 0x6040);
482af832623SIgor M. Liplianin 	switch (voltage) {
483af832623SIgor M. Liplianin 	case SEC_VOLTAGE_13:
484ad5f74c0SIgor M. Liplianin 		cx_clear(MO_GP0_IO, 0x20);
485af832623SIgor M. Liplianin 		break;
486af832623SIgor M. Liplianin 	case SEC_VOLTAGE_18:
487ad5f74c0SIgor M. Liplianin 		cx_set(MO_GP0_IO, 0x20);
488af832623SIgor M. Liplianin 		break;
489af832623SIgor M. Liplianin 	case SEC_VOLTAGE_OFF:
490ad5f74c0SIgor M. Liplianin 		cx_clear(MO_GP0_IO, 0x20);
491af832623SIgor M. Liplianin 		break;
492af832623SIgor M. Liplianin 	}
493af832623SIgor M. Liplianin 
494af832623SIgor M. Liplianin 	if (core->prev_set_voltage)
495af832623SIgor M. Liplianin 		return core->prev_set_voltage(fe, voltage);
496af832623SIgor M. Liplianin 	return 0;
497af832623SIgor M. Liplianin }
498af832623SIgor M. Liplianin 
vp1027_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)499111ac84aSSergey Ivanov static int vp1027_set_voltage(struct dvb_frontend *fe,
5000df289a2SMauro Carvalho Chehab 			      enum fe_sec_voltage voltage)
501111ac84aSSergey Ivanov {
502111ac84aSSergey Ivanov 	struct cx8802_dev *dev = fe->dvb->priv;
503111ac84aSSergey Ivanov 	struct cx88_core *core = dev->core;
504111ac84aSSergey Ivanov 
505111ac84aSSergey Ivanov 	switch (voltage) {
506111ac84aSSergey Ivanov 	case SEC_VOLTAGE_13:
507111ac84aSSergey Ivanov 		dprintk(1, "LNB SEC Voltage=13\n");
508111ac84aSSergey Ivanov 		cx_write(MO_GP0_IO, 0x00001220);
509111ac84aSSergey Ivanov 		break;
510111ac84aSSergey Ivanov 	case SEC_VOLTAGE_18:
511111ac84aSSergey Ivanov 		dprintk(1, "LNB SEC Voltage=18\n");
512111ac84aSSergey Ivanov 		cx_write(MO_GP0_IO, 0x00001222);
513111ac84aSSergey Ivanov 		break;
514111ac84aSSergey Ivanov 	case SEC_VOLTAGE_OFF:
515111ac84aSSergey Ivanov 		dprintk(1, "LNB Voltage OFF\n");
516111ac84aSSergey Ivanov 		cx_write(MO_GP0_IO, 0x00001230);
517111ac84aSSergey Ivanov 		break;
518111ac84aSSergey Ivanov 	}
519111ac84aSSergey Ivanov 
520111ac84aSSergey Ivanov 	if (core->prev_set_voltage)
521111ac84aSSergey Ivanov 		return core->prev_set_voltage(fe, voltage);
522111ac84aSSergey Ivanov 	return 0;
523111ac84aSSergey Ivanov }
524111ac84aSSergey Ivanov 
5252e4e98e7Slawrence rust static const struct cx24123_config geniatech_dvbs_config = {
526c02a34f4SSaqeb Akhter 	.demod_address = 0x55,
527c02a34f4SSaqeb Akhter 	.set_ts_params = cx24123_set_ts_param,
528c02a34f4SSaqeb Akhter };
529c02a34f4SSaqeb Akhter 
5302e4e98e7Slawrence rust static const struct cx24123_config hauppauge_novas_config = {
5310fa14aa6SSteven Toth 	.demod_address = 0x55,
5320fa14aa6SSteven Toth 	.set_ts_params = cx24123_set_ts_param,
5330fa14aa6SSteven Toth };
5340e0351e3SVadim Catana 
5352e4e98e7Slawrence rust static const struct cx24123_config kworld_dvbs_100_config = {
5360e0351e3SVadim Catana 	.demod_address = 0x15,
5370e0351e3SVadim Catana 	.set_ts_params = cx24123_set_ts_param,
538ef76856dSYeasah Pell 	.lnb_polarity  = 1,
5390e0351e3SVadim Catana };
5400fa14aa6SSteven Toth 
5412e4e98e7Slawrence rust static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
54260464da8SSteven Toth 	.demod_address = 0x32 >> 1,
54360464da8SSteven Toth 	.output_mode   = S5H1409_PARALLEL_OUTPUT,
54460464da8SSteven Toth 	.gpio	       = S5H1409_GPIO_ON,
54560464da8SSteven Toth 	.qam_if	       = 44000,
54660464da8SSteven Toth 	.inversion     = S5H1409_INVERSION_OFF,
54760464da8SSteven Toth 	.status_mode   = S5H1409_DEMODLOCKING,
548ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINUOUS_NONINVERTING_CLOCK,
54960464da8SSteven Toth };
55060464da8SSteven Toth 
5512e4e98e7Slawrence rust static const struct s5h1409_config dvico_hdtv5_pci_nano_config = {
5525c00fac0SSteven Toth 	.demod_address = 0x32 >> 1,
5535c00fac0SSteven Toth 	.output_mode   = S5H1409_SERIAL_OUTPUT,
5545c00fac0SSteven Toth 	.gpio          = S5H1409_GPIO_OFF,
5555c00fac0SSteven Toth 	.inversion     = S5H1409_INVERSION_OFF,
5565c00fac0SSteven Toth 	.status_mode   = S5H1409_DEMODLOCKING,
557ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
5585c00fac0SSteven Toth };
5595c00fac0SSteven Toth 
5602e4e98e7Slawrence rust static const struct s5h1409_config kworld_atsc_120_config = {
56199e09eacSMauro Carvalho Chehab 	.demod_address = 0x32 >> 1,
56299e09eacSMauro Carvalho Chehab 	.output_mode   = S5H1409_SERIAL_OUTPUT,
56399e09eacSMauro Carvalho Chehab 	.gpio	       = S5H1409_GPIO_OFF,
56499e09eacSMauro Carvalho Chehab 	.inversion     = S5H1409_INVERSION_OFF,
56599e09eacSMauro Carvalho Chehab 	.status_mode   = S5H1409_DEMODLOCKING,
566ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
56799e09eacSMauro Carvalho Chehab };
56899e09eacSMauro Carvalho Chehab 
5692e4e98e7Slawrence rust static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
57060464da8SSteven Toth 	.i2c_address	= 0x64,
57160464da8SSteven Toth 	.if_khz		= 5380,
57260464da8SSteven Toth };
57360464da8SSteven Toth 
5742e4e98e7Slawrence rust static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
5753f6014fcSStéphane Voltz 	.demod_address = (0x1e >> 1),
5763f6014fcSStéphane Voltz 	.no_tuner      = 1,
5773f6014fcSStéphane Voltz 	.if2           = 45600,
5783f6014fcSStéphane Voltz };
5793f6014fcSStéphane Voltz 
5802e4e98e7Slawrence rust static const struct zl10353_config cx88_geniatech_x8000_mt = {
5819507901eSMauro Carvalho Chehab 	.demod_address = (0x1e >> 1),
5829507901eSMauro Carvalho Chehab 	.no_tuner = 1,
58311db9069SDevin Heitmueller 	.disable_i2c_gate_ctrl = 1,
5849507901eSMauro Carvalho Chehab };
5859507901eSMauro Carvalho Chehab 
5862e4e98e7Slawrence rust static const struct s5h1411_config dvico_fusionhdtv7_config = {
587d893d5dcSSteven Toth 	.output_mode   = S5H1411_SERIAL_OUTPUT,
588d893d5dcSSteven Toth 	.gpio          = S5H1411_GPIO_ON,
589ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
590d893d5dcSSteven Toth 	.qam_if        = S5H1411_IF_44000,
591d893d5dcSSteven Toth 	.vsb_if        = S5H1411_IF_44000,
592d893d5dcSSteven Toth 	.inversion     = S5H1411_INVERSION_OFF,
593d893d5dcSSteven Toth 	.status_mode   = S5H1411_DEMODLOCKING
594d893d5dcSSteven Toth };
595d893d5dcSSteven Toth 
5962e4e98e7Slawrence rust static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
597d893d5dcSSteven Toth 	.i2c_address    = 0xc2 >> 1,
598d893d5dcSSteven Toth 	.if_khz         = 5380,
599d893d5dcSSteven Toth };
600d893d5dcSSteven Toth 
attach_xc3028(u8 addr,struct cx8802_dev * dev)60123fb348dSMauro Carvalho Chehab static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
60223fb348dSMauro Carvalho Chehab {
60323fb348dSMauro Carvalho Chehab 	struct dvb_frontend *fe;
6040b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0 = NULL;
60599e09eacSMauro Carvalho Chehab 	struct xc2028_ctrl ctl;
60623fb348dSMauro Carvalho Chehab 	struct xc2028_config cfg = {
60723fb348dSMauro Carvalho Chehab 		.i2c_adap  = &dev->core->i2c_adap,
60823fb348dSMauro Carvalho Chehab 		.i2c_addr  = addr,
60999e09eacSMauro Carvalho Chehab 		.ctrl      = &ctl,
61023fb348dSMauro Carvalho Chehab 	};
61123fb348dSMauro Carvalho Chehab 
612363c35fcSSteven Toth 	/* Get the first frontend */
6130b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
614363c35fcSSteven Toth 	if (!fe0)
615363c35fcSSteven Toth 		return -EINVAL;
616363c35fcSSteven Toth 
617363c35fcSSteven Toth 	if (!fe0->dvb.frontend) {
61865bc2fe8SMauro Carvalho Chehab 		pr_err("dvb frontend not attached. Can't attach xc3028\n");
619ddd5441dSMauro Carvalho Chehab 		return -EINVAL;
620ddd5441dSMauro Carvalho Chehab 	}
621ddd5441dSMauro Carvalho Chehab 
62299e09eacSMauro Carvalho Chehab 	/*
62399e09eacSMauro Carvalho Chehab 	 * Some xc3028 devices may be hidden by an I2C gate. This is known
62499e09eacSMauro Carvalho Chehab 	 * to happen with some s5h1409-based devices.
62599e09eacSMauro Carvalho Chehab 	 * Now that I2C gate is open, sets up xc3028 configuration
62699e09eacSMauro Carvalho Chehab 	 */
62799e09eacSMauro Carvalho Chehab 	cx88_setup_xc3028(dev->core, &ctl);
62899e09eacSMauro Carvalho Chehab 
629363c35fcSSteven Toth 	fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
63023fb348dSMauro Carvalho Chehab 	if (!fe) {
63165bc2fe8SMauro Carvalho Chehab 		pr_err("xc3028 attach failed\n");
632363c35fcSSteven Toth 		dvb_frontend_detach(fe0->dvb.frontend);
633363c35fcSSteven Toth 		dvb_unregister_frontend(fe0->dvb.frontend);
634363c35fcSSteven Toth 		fe0->dvb.frontend = NULL;
63523fb348dSMauro Carvalho Chehab 		return -EINVAL;
63623fb348dSMauro Carvalho Chehab 	}
63723fb348dSMauro Carvalho Chehab 
63865bc2fe8SMauro Carvalho Chehab 	pr_info("xc3028 attached\n");
63923fb348dSMauro Carvalho Chehab 
64023fb348dSMauro Carvalho Chehab 	return 0;
64123fb348dSMauro Carvalho Chehab }
6429507901eSMauro Carvalho Chehab 
attach_xc4000(struct cx8802_dev * dev,struct xc4000_config * cfg)643c21973e8Sistvan_v@mailbox.hu static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
644c21973e8Sistvan_v@mailbox.hu {
645c21973e8Sistvan_v@mailbox.hu 	struct dvb_frontend *fe;
6460b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0 = NULL;
647c21973e8Sistvan_v@mailbox.hu 
648c21973e8Sistvan_v@mailbox.hu 	/* Get the first frontend */
6490b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
650c21973e8Sistvan_v@mailbox.hu 	if (!fe0)
651c21973e8Sistvan_v@mailbox.hu 		return -EINVAL;
652c21973e8Sistvan_v@mailbox.hu 
653c21973e8Sistvan_v@mailbox.hu 	if (!fe0->dvb.frontend) {
65465bc2fe8SMauro Carvalho Chehab 		pr_err("dvb frontend not attached. Can't attach xc4000\n");
655c21973e8Sistvan_v@mailbox.hu 		return -EINVAL;
656c21973e8Sistvan_v@mailbox.hu 	}
657c21973e8Sistvan_v@mailbox.hu 
658c21973e8Sistvan_v@mailbox.hu 	fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
659c21973e8Sistvan_v@mailbox.hu 			cfg);
660c21973e8Sistvan_v@mailbox.hu 	if (!fe) {
66165bc2fe8SMauro Carvalho Chehab 		pr_err("xc4000 attach failed\n");
662c21973e8Sistvan_v@mailbox.hu 		dvb_frontend_detach(fe0->dvb.frontend);
663c21973e8Sistvan_v@mailbox.hu 		dvb_unregister_frontend(fe0->dvb.frontend);
664c21973e8Sistvan_v@mailbox.hu 		fe0->dvb.frontend = NULL;
665c21973e8Sistvan_v@mailbox.hu 		return -EINVAL;
666c21973e8Sistvan_v@mailbox.hu 	}
667c21973e8Sistvan_v@mailbox.hu 
66865bc2fe8SMauro Carvalho Chehab 	pr_info("xc4000 attached\n");
669c21973e8Sistvan_v@mailbox.hu 
670c21973e8Sistvan_v@mailbox.hu 	return 0;
671c21973e8Sistvan_v@mailbox.hu }
672c21973e8Sistvan_v@mailbox.hu 
cx24116_set_ts_param(struct dvb_frontend * fe,int is_punctured)6735bd1b663SSteven Toth static int cx24116_set_ts_param(struct dvb_frontend *fe,
6745bd1b663SSteven Toth 				int is_punctured)
6755bd1b663SSteven Toth {
6765bd1b663SSteven Toth 	struct cx8802_dev *dev = fe->dvb->priv;
6777b61ba8fSMauro Carvalho Chehab 
6785bd1b663SSteven Toth 	dev->ts_gen_cntrl = 0x2;
6795bd1b663SSteven Toth 
6805bd1b663SSteven Toth 	return 0;
6815bd1b663SSteven Toth }
6825bd1b663SSteven Toth 
stv0900_set_ts_param(struct dvb_frontend * fe,int is_punctured)683b699c271SIgor M. Liplianin static int stv0900_set_ts_param(struct dvb_frontend *fe,
684b699c271SIgor M. Liplianin 				int is_punctured)
685b699c271SIgor M. Liplianin {
686b699c271SIgor M. Liplianin 	struct cx8802_dev *dev = fe->dvb->priv;
6877b61ba8fSMauro Carvalho Chehab 
688b699c271SIgor M. Liplianin 	dev->ts_gen_cntrl = 0;
689b699c271SIgor M. Liplianin 
690b699c271SIgor M. Liplianin 	return 0;
691b699c271SIgor M. Liplianin }
692b699c271SIgor M. Liplianin 
cx24116_reset_device(struct dvb_frontend * fe)6935bd1b663SSteven Toth static int cx24116_reset_device(struct dvb_frontend *fe)
6945bd1b663SSteven Toth {
6955bd1b663SSteven Toth 	struct cx8802_dev *dev = fe->dvb->priv;
6965bd1b663SSteven Toth 	struct cx88_core *core = dev->core;
6975bd1b663SSteven Toth 
6985bd1b663SSteven Toth 	/* Reset the part */
699363c35fcSSteven Toth 	/* Put the cx24116 into reset */
7005bd1b663SSteven Toth 	cx_write(MO_SRST_IO, 0);
701399426caSMauro Carvalho Chehab 	usleep_range(10000, 20000);
702363c35fcSSteven Toth 	/* Take the cx24116 out of reset */
7035bd1b663SSteven Toth 	cx_write(MO_SRST_IO, 1);
704399426caSMauro Carvalho Chehab 	usleep_range(10000, 20000);
7055bd1b663SSteven Toth 
7065bd1b663SSteven Toth 	return 0;
7075bd1b663SSteven Toth }
7085bd1b663SSteven Toth 
7092e4e98e7Slawrence rust static const struct cx24116_config hauppauge_hvr4000_config = {
7105bd1b663SSteven Toth 	.demod_address          = 0x05,
7115bd1b663SSteven Toth 	.set_ts_params          = cx24116_set_ts_param,
7125bd1b663SSteven Toth 	.reset_device           = cx24116_reset_device,
7135bd1b663SSteven Toth };
7145bd1b663SSteven Toth 
7152e4e98e7Slawrence rust static const struct cx24116_config tevii_s460_config = {
716af832623SIgor M. Liplianin 	.demod_address = 0x55,
717af832623SIgor M. Liplianin 	.set_ts_params = cx24116_set_ts_param,
718af832623SIgor M. Liplianin 	.reset_device  = cx24116_reset_device,
719af832623SIgor M. Liplianin };
720af832623SIgor M. Liplianin 
ds3000_set_ts_param(struct dvb_frontend * fe,int is_punctured)7210cb73639SIgor M. Liplianin static int ds3000_set_ts_param(struct dvb_frontend *fe,
7220cb73639SIgor M. Liplianin 			       int is_punctured)
7230cb73639SIgor M. Liplianin {
7240cb73639SIgor M. Liplianin 	struct cx8802_dev *dev = fe->dvb->priv;
7257b61ba8fSMauro Carvalho Chehab 
7260cb73639SIgor M. Liplianin 	dev->ts_gen_cntrl = 4;
7270cb73639SIgor M. Liplianin 
7280cb73639SIgor M. Liplianin 	return 0;
7290cb73639SIgor M. Liplianin }
7300cb73639SIgor M. Liplianin 
7310cb73639SIgor M. Liplianin static struct ds3000_config tevii_ds3000_config = {
7320cb73639SIgor M. Liplianin 	.demod_address = 0x68,
7330cb73639SIgor M. Liplianin 	.set_ts_params = ds3000_set_ts_param,
7340cb73639SIgor M. Liplianin };
7350cb73639SIgor M. Liplianin 
73673f0af44SKonstantin Dimitrov static struct ts2020_config tevii_ts2020_config  = {
73773f0af44SKonstantin Dimitrov 	.tuner_address = 0x60,
738b858c331SIgor M. Liplianin 	.clk_out_div = 1,
73973f0af44SKonstantin Dimitrov };
74073f0af44SKonstantin Dimitrov 
7412e4e98e7Slawrence rust static const struct stv0900_config prof_7301_stv0900_config = {
742b699c271SIgor M. Liplianin 	.demod_address = 0x6a,
743b699c271SIgor M. Liplianin /*	demod_mode = 0,*/
744b699c271SIgor M. Liplianin 	.xtal = 27000000,
745b699c271SIgor M. Liplianin 	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
746b699c271SIgor M. Liplianin 	.diseqc_mode = 2,/* 2/3 PWM */
747b699c271SIgor M. Liplianin 	.tun1_maddress = 0,/* 0x60 */
748b699c271SIgor M. Liplianin 	.tun1_adc = 0,/* 2 Vpp */
749b699c271SIgor M. Liplianin 	.path1_mode = 3,
750b699c271SIgor M. Liplianin 	.set_ts_params = stv0900_set_ts_param,
751b699c271SIgor M. Liplianin };
752b699c271SIgor M. Liplianin 
7532e4e98e7Slawrence rust static const struct stb6100_config prof_7301_stb6100_config = {
754b699c271SIgor M. Liplianin 	.tuner_address = 0x60,
755b699c271SIgor M. Liplianin 	.refclock = 27000000,
756b699c271SIgor M. Liplianin };
757b699c271SIgor M. Liplianin 
7582e4e98e7Slawrence rust static const struct stv0299_config tevii_tuner_sharp_config = {
759e4aab64cSIgor M. Liplianin 	.demod_address = 0x68,
760d4305c68SIgor M. Liplianin 	.inittab = sharp_z0194a_inittab,
761e4aab64cSIgor M. Liplianin 	.mclk = 88000000UL,
762e4aab64cSIgor M. Liplianin 	.invert = 1,
763e4aab64cSIgor M. Liplianin 	.skip_reinit = 0,
764e4aab64cSIgor M. Liplianin 	.lock_output = 1,
765e4aab64cSIgor M. Liplianin 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
766e4aab64cSIgor M. Liplianin 	.min_delay_ms = 100,
767d4305c68SIgor M. Liplianin 	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
768e4aab64cSIgor M. Liplianin 	.set_ts_params = cx24116_set_ts_param,
769e4aab64cSIgor M. Liplianin };
770e4aab64cSIgor M. Liplianin 
7712e4e98e7Slawrence rust static const struct stv0288_config tevii_tuner_earda_config = {
772e4aab64cSIgor M. Liplianin 	.demod_address = 0x68,
773e4aab64cSIgor M. Liplianin 	.min_delay_ms = 100,
774e4aab64cSIgor M. Liplianin 	.set_ts_params = cx24116_set_ts_param,
775e4aab64cSIgor M. Liplianin };
776e4aab64cSIgor M. Liplianin 
cx8802_alloc_frontends(struct cx8802_dev * dev)7776e0e12f1SAndy Walls static int cx8802_alloc_frontends(struct cx8802_dev *dev)
7786e0e12f1SAndy Walls {
7796e0e12f1SAndy Walls 	struct cx88_core *core = dev->core;
7800b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe = NULL;
7816e0e12f1SAndy Walls 	int i;
7826e0e12f1SAndy Walls 
7836e0e12f1SAndy Walls 	mutex_init(&dev->frontends.lock);
7846e0e12f1SAndy Walls 	INIT_LIST_HEAD(&dev->frontends.felist);
7856e0e12f1SAndy Walls 
7866e0e12f1SAndy Walls 	if (!core->board.num_frontends)
7876e0e12f1SAndy Walls 		return -ENODEV;
7886e0e12f1SAndy Walls 
78965bc2fe8SMauro Carvalho Chehab 	pr_info("%s: allocating %d frontend(s)\n", __func__,
7906e0e12f1SAndy Walls 		core->board.num_frontends);
7916e0e12f1SAndy Walls 	for (i = 1; i <= core->board.num_frontends; i++) {
7920b6b6302SHans Verkuil 		fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
7936e0e12f1SAndy Walls 		if (!fe) {
79465bc2fe8SMauro Carvalho Chehab 			pr_err("%s() failed to alloc\n", __func__);
7950b6b6302SHans Verkuil 			vb2_dvb_dealloc_frontends(&dev->frontends);
7966e0e12f1SAndy Walls 			return -ENOMEM;
7976e0e12f1SAndy Walls 		}
7986e0e12f1SAndy Walls 	}
7996e0e12f1SAndy Walls 	return 0;
8006e0e12f1SAndy Walls }
8016e0e12f1SAndy Walls 
8022e4e98e7Slawrence rust static const u8 samsung_smt_7020_inittab[] = {
8034f3ca2f1SDirk Herrendoerfer 	     0x01, 0x15,
8044f3ca2f1SDirk Herrendoerfer 	     0x02, 0x00,
8054f3ca2f1SDirk Herrendoerfer 	     0x03, 0x00,
8064f3ca2f1SDirk Herrendoerfer 	     0x04, 0x7D,
8074f3ca2f1SDirk Herrendoerfer 	     0x05, 0x0F,
8084f3ca2f1SDirk Herrendoerfer 	     0x06, 0x02,
8094f3ca2f1SDirk Herrendoerfer 	     0x07, 0x00,
8104f3ca2f1SDirk Herrendoerfer 	     0x08, 0x60,
8114f3ca2f1SDirk Herrendoerfer 
8124f3ca2f1SDirk Herrendoerfer 	     0x0A, 0xC2,
8134f3ca2f1SDirk Herrendoerfer 	     0x0B, 0x00,
8144f3ca2f1SDirk Herrendoerfer 	     0x0C, 0x01,
8154f3ca2f1SDirk Herrendoerfer 	     0x0D, 0x81,
8164f3ca2f1SDirk Herrendoerfer 	     0x0E, 0x44,
8174f3ca2f1SDirk Herrendoerfer 	     0x0F, 0x09,
8184f3ca2f1SDirk Herrendoerfer 	     0x10, 0x3C,
8194f3ca2f1SDirk Herrendoerfer 	     0x11, 0x84,
8204f3ca2f1SDirk Herrendoerfer 	     0x12, 0xDA,
8214f3ca2f1SDirk Herrendoerfer 	     0x13, 0x99,
8224f3ca2f1SDirk Herrendoerfer 	     0x14, 0x8D,
8234f3ca2f1SDirk Herrendoerfer 	     0x15, 0xCE,
8244f3ca2f1SDirk Herrendoerfer 	     0x16, 0xE8,
8254f3ca2f1SDirk Herrendoerfer 	     0x17, 0x43,
8264f3ca2f1SDirk Herrendoerfer 	     0x18, 0x1C,
8274f3ca2f1SDirk Herrendoerfer 	     0x19, 0x1B,
8284f3ca2f1SDirk Herrendoerfer 	     0x1A, 0x1D,
8294f3ca2f1SDirk Herrendoerfer 
8304f3ca2f1SDirk Herrendoerfer 	     0x1C, 0x12,
8314f3ca2f1SDirk Herrendoerfer 	     0x1D, 0x00,
8324f3ca2f1SDirk Herrendoerfer 	     0x1E, 0x00,
8334f3ca2f1SDirk Herrendoerfer 	     0x1F, 0x00,
8344f3ca2f1SDirk Herrendoerfer 	     0x20, 0x00,
8354f3ca2f1SDirk Herrendoerfer 	     0x21, 0x00,
8364f3ca2f1SDirk Herrendoerfer 	     0x22, 0x00,
8374f3ca2f1SDirk Herrendoerfer 	     0x23, 0x00,
8384f3ca2f1SDirk Herrendoerfer 
8394f3ca2f1SDirk Herrendoerfer 	     0x28, 0x02,
8404f3ca2f1SDirk Herrendoerfer 	     0x29, 0x28,
8414f3ca2f1SDirk Herrendoerfer 	     0x2A, 0x14,
8424f3ca2f1SDirk Herrendoerfer 	     0x2B, 0x0F,
8434f3ca2f1SDirk Herrendoerfer 	     0x2C, 0x09,
8444f3ca2f1SDirk Herrendoerfer 	     0x2D, 0x05,
8454f3ca2f1SDirk Herrendoerfer 
8464f3ca2f1SDirk Herrendoerfer 	     0x31, 0x1F,
8474f3ca2f1SDirk Herrendoerfer 	     0x32, 0x19,
8484f3ca2f1SDirk Herrendoerfer 	     0x33, 0xFC,
8494f3ca2f1SDirk Herrendoerfer 	     0x34, 0x13,
8504f3ca2f1SDirk Herrendoerfer 	     0xff, 0xff,
8514f3ca2f1SDirk Herrendoerfer };
8524f3ca2f1SDirk Herrendoerfer 
samsung_smt_7020_tuner_set_params(struct dvb_frontend * fe)85314d24d14SMauro Carvalho Chehab static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
8544f3ca2f1SDirk Herrendoerfer {
855b738ae16SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
8564f3ca2f1SDirk Herrendoerfer 	struct cx8802_dev *dev = fe->dvb->priv;
8574f3ca2f1SDirk Herrendoerfer 	u8 buf[4];
8584f3ca2f1SDirk Herrendoerfer 	u32 div;
8594f3ca2f1SDirk Herrendoerfer 	struct i2c_msg msg = {
8604f3ca2f1SDirk Herrendoerfer 		.addr = 0x61,
8614f3ca2f1SDirk Herrendoerfer 		.flags = 0,
8624f3ca2f1SDirk Herrendoerfer 		.buf = buf,
8634f3ca2f1SDirk Herrendoerfer 		.len = sizeof(buf) };
8644f3ca2f1SDirk Herrendoerfer 
865b738ae16SMauro Carvalho Chehab 	div = c->frequency / 125;
8664f3ca2f1SDirk Herrendoerfer 
8674f3ca2f1SDirk Herrendoerfer 	buf[0] = (div >> 8) & 0x7f;
8684f3ca2f1SDirk Herrendoerfer 	buf[1] = div & 0xff;
8694f3ca2f1SDirk Herrendoerfer 	buf[2] = 0x84;  /* 0xC4 */
8704f3ca2f1SDirk Herrendoerfer 	buf[3] = 0x00;
8714f3ca2f1SDirk Herrendoerfer 
872b738ae16SMauro Carvalho Chehab 	if (c->frequency < 1500000)
8734f3ca2f1SDirk Herrendoerfer 		buf[3] |= 0x10;
8744f3ca2f1SDirk Herrendoerfer 
8754f3ca2f1SDirk Herrendoerfer 	if (fe->ops.i2c_gate_ctrl)
8764f3ca2f1SDirk Herrendoerfer 		fe->ops.i2c_gate_ctrl(fe, 1);
8774f3ca2f1SDirk Herrendoerfer 
8784f3ca2f1SDirk Herrendoerfer 	if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
8794f3ca2f1SDirk Herrendoerfer 		return -EIO;
8804f3ca2f1SDirk Herrendoerfer 
8814f3ca2f1SDirk Herrendoerfer 	return 0;
8824f3ca2f1SDirk Herrendoerfer }
8834f3ca2f1SDirk Herrendoerfer 
samsung_smt_7020_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)8844f3ca2f1SDirk Herrendoerfer static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
8850df289a2SMauro Carvalho Chehab 				     enum fe_sec_tone_mode tone)
8864f3ca2f1SDirk Herrendoerfer {
8874f3ca2f1SDirk Herrendoerfer 	struct cx8802_dev *dev = fe->dvb->priv;
8884f3ca2f1SDirk Herrendoerfer 	struct cx88_core *core = dev->core;
8894f3ca2f1SDirk Herrendoerfer 
8904f3ca2f1SDirk Herrendoerfer 	cx_set(MO_GP0_IO, 0x0800);
8914f3ca2f1SDirk Herrendoerfer 
8924f3ca2f1SDirk Herrendoerfer 	switch (tone) {
8934f3ca2f1SDirk Herrendoerfer 	case SEC_TONE_ON:
8944f3ca2f1SDirk Herrendoerfer 		cx_set(MO_GP0_IO, 0x08);
8954f3ca2f1SDirk Herrendoerfer 		break;
8964f3ca2f1SDirk Herrendoerfer 	case SEC_TONE_OFF:
8974f3ca2f1SDirk Herrendoerfer 		cx_clear(MO_GP0_IO, 0x08);
8984f3ca2f1SDirk Herrendoerfer 		break;
8994f3ca2f1SDirk Herrendoerfer 	default:
9004f3ca2f1SDirk Herrendoerfer 		return -EINVAL;
9014f3ca2f1SDirk Herrendoerfer 	}
9024f3ca2f1SDirk Herrendoerfer 
9034f3ca2f1SDirk Herrendoerfer 	return 0;
9044f3ca2f1SDirk Herrendoerfer }
9054f3ca2f1SDirk Herrendoerfer 
samsung_smt_7020_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)9064f3ca2f1SDirk Herrendoerfer static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
9070df289a2SMauro Carvalho Chehab 					enum fe_sec_voltage voltage)
9084f3ca2f1SDirk Herrendoerfer {
9094f3ca2f1SDirk Herrendoerfer 	struct cx8802_dev *dev = fe->dvb->priv;
9104f3ca2f1SDirk Herrendoerfer 	struct cx88_core *core = dev->core;
9114f3ca2f1SDirk Herrendoerfer 
9124f3ca2f1SDirk Herrendoerfer 	u8 data;
9134f3ca2f1SDirk Herrendoerfer 	struct i2c_msg msg = {
9144f3ca2f1SDirk Herrendoerfer 		.addr = 8,
9154f3ca2f1SDirk Herrendoerfer 		.flags = 0,
9164f3ca2f1SDirk Herrendoerfer 		.buf = &data,
9174f3ca2f1SDirk Herrendoerfer 		.len = sizeof(data) };
9184f3ca2f1SDirk Herrendoerfer 
9194f3ca2f1SDirk Herrendoerfer 	cx_set(MO_GP0_IO, 0x8000);
9204f3ca2f1SDirk Herrendoerfer 
9214f3ca2f1SDirk Herrendoerfer 	switch (voltage) {
9224f3ca2f1SDirk Herrendoerfer 	case SEC_VOLTAGE_OFF:
9234f3ca2f1SDirk Herrendoerfer 		break;
9244f3ca2f1SDirk Herrendoerfer 	case SEC_VOLTAGE_13:
9254f3ca2f1SDirk Herrendoerfer 		data = ISL6421_EN1 | ISL6421_LLC1;
9264f3ca2f1SDirk Herrendoerfer 		cx_clear(MO_GP0_IO, 0x80);
9274f3ca2f1SDirk Herrendoerfer 		break;
9284f3ca2f1SDirk Herrendoerfer 	case SEC_VOLTAGE_18:
9294f3ca2f1SDirk Herrendoerfer 		data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
9304f3ca2f1SDirk Herrendoerfer 		cx_clear(MO_GP0_IO, 0x80);
9314f3ca2f1SDirk Herrendoerfer 		break;
9324f3ca2f1SDirk Herrendoerfer 	default:
9334f3ca2f1SDirk Herrendoerfer 		return -EINVAL;
934c2c1b415SPeter Senna Tschudin 	}
9354f3ca2f1SDirk Herrendoerfer 
9364f3ca2f1SDirk Herrendoerfer 	return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
9374f3ca2f1SDirk Herrendoerfer }
9384f3ca2f1SDirk Herrendoerfer 
samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)9394f3ca2f1SDirk Herrendoerfer static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
9404f3ca2f1SDirk Herrendoerfer 						    u32 srate, u32 ratio)
9414f3ca2f1SDirk Herrendoerfer {
9424f3ca2f1SDirk Herrendoerfer 	u8 aclk = 0;
9434f3ca2f1SDirk Herrendoerfer 	u8 bclk = 0;
9444f3ca2f1SDirk Herrendoerfer 
9454f3ca2f1SDirk Herrendoerfer 	if (srate < 1500000) {
9464f3ca2f1SDirk Herrendoerfer 		aclk = 0xb7;
9474f3ca2f1SDirk Herrendoerfer 		bclk = 0x47;
9484f3ca2f1SDirk Herrendoerfer 	} else if (srate < 3000000) {
9494f3ca2f1SDirk Herrendoerfer 		aclk = 0xb7;
9504f3ca2f1SDirk Herrendoerfer 		bclk = 0x4b;
9514f3ca2f1SDirk Herrendoerfer 	} else if (srate < 7000000) {
9524f3ca2f1SDirk Herrendoerfer 		aclk = 0xb7;
9534f3ca2f1SDirk Herrendoerfer 		bclk = 0x4f;
9544f3ca2f1SDirk Herrendoerfer 	} else if (srate < 14000000) {
9554f3ca2f1SDirk Herrendoerfer 		aclk = 0xb7;
9564f3ca2f1SDirk Herrendoerfer 		bclk = 0x53;
9574f3ca2f1SDirk Herrendoerfer 	} else if (srate < 30000000) {
9584f3ca2f1SDirk Herrendoerfer 		aclk = 0xb6;
9594f3ca2f1SDirk Herrendoerfer 		bclk = 0x53;
9604f3ca2f1SDirk Herrendoerfer 	} else if (srate < 45000000) {
9614f3ca2f1SDirk Herrendoerfer 		aclk = 0xb4;
9624f3ca2f1SDirk Herrendoerfer 		bclk = 0x51;
9634f3ca2f1SDirk Herrendoerfer 	}
9644f3ca2f1SDirk Herrendoerfer 
9654f3ca2f1SDirk Herrendoerfer 	stv0299_writereg(fe, 0x13, aclk);
9664f3ca2f1SDirk Herrendoerfer 	stv0299_writereg(fe, 0x14, bclk);
9674f3ca2f1SDirk Herrendoerfer 	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
9684f3ca2f1SDirk Herrendoerfer 	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
9694f3ca2f1SDirk Herrendoerfer 	stv0299_writereg(fe, 0x21, ratio & 0xf0);
9704f3ca2f1SDirk Herrendoerfer 
9714f3ca2f1SDirk Herrendoerfer 	return 0;
9724f3ca2f1SDirk Herrendoerfer }
9734f3ca2f1SDirk Herrendoerfer 
9742e4e98e7Slawrence rust static const struct stv0299_config samsung_stv0299_config = {
9754f3ca2f1SDirk Herrendoerfer 	.demod_address = 0x68,
9764f3ca2f1SDirk Herrendoerfer 	.inittab = samsung_smt_7020_inittab,
9774f3ca2f1SDirk Herrendoerfer 	.mclk = 88000000UL,
9784f3ca2f1SDirk Herrendoerfer 	.invert = 0,
9794f3ca2f1SDirk Herrendoerfer 	.skip_reinit = 0,
9804f3ca2f1SDirk Herrendoerfer 	.lock_output = STV0299_LOCKOUTPUT_LK,
9814f3ca2f1SDirk Herrendoerfer 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
9824f3ca2f1SDirk Herrendoerfer 	.min_delay_ms = 100,
9834f3ca2f1SDirk Herrendoerfer 	.set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
9844f3ca2f1SDirk Herrendoerfer };
9854f3ca2f1SDirk Herrendoerfer 
dvb_register(struct cx8802_dev * dev)9861da177e4SLinus Torvalds static int dvb_register(struct cx8802_dev *dev)
9871da177e4SLinus Torvalds {
988363c35fcSSteven Toth 	struct cx88_core *core = dev->core;
9890b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe0, *fe1 = NULL;
99059b1842dSDarron Broad 	int mfe_shared = 0; /* bus not shared by default */
9917b0962d3SDavid Fries 	int res = -EINVAL;
992363c35fcSSteven Toth 
9937b61ba8fSMauro Carvalho Chehab 	if (core->i2c_rc != 0) {
99465bc2fe8SMauro Carvalho Chehab 		pr_err("no i2c-bus available, cannot attach dvb drivers\n");
9950e8bac97SMatthias Schwarzott 		goto frontend_detach;
9960e8bac97SMatthias Schwarzott 	}
9970e8bac97SMatthias Schwarzott 
998363c35fcSSteven Toth 	/* Get the first frontend */
9990b6b6302SHans Verkuil 	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
1000363c35fcSSteven Toth 	if (!fe0)
100160a5a927SDarron Broad 		goto frontend_detach;
10021da177e4SLinus Torvalds 
10038e739090SDarron Broad 	/* multi-frontend gate control is undefined or defaults to fe0 */
10048e739090SDarron Broad 	dev->frontends.gate = 0;
10058e739090SDarron Broad 
1006e32fadc4SMauro Carvalho Chehab 	/* Sets the gate control callback to be used by i2c command calls */
1007e32fadc4SMauro Carvalho Chehab 	core->gate_ctrl = cx88_dvb_gate_ctrl;
1008e32fadc4SMauro Carvalho Chehab 
10098e739090SDarron Broad 	/* init frontend(s) */
10100590d91cSMauro Carvalho Chehab 	switch (core->boardnr) {
10111da177e4SLinus Torvalds 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
1012363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1013ed355260SMichael Krufky 					       &connexant_refboard_config,
10140590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1015399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1016363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
10170590d91cSMauro Carvalho Chehab 					0x61, &core->i2c_adap,
10180590d91cSMauro Carvalho Chehab 					DVB_PLL_THOMSON_DTT759X))
10190590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1020f54376e2SAndrew de Quincey 		}
10211da177e4SLinus Torvalds 		break;
1022e057ee11SMichael Krufky 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
10231da177e4SLinus Torvalds 	case CX88_BOARD_CONEXANT_DVB_T1:
1024f39624fdSManenti Marco 	case CX88_BOARD_KWORLD_DVB_T_CX22702:
10252b5200a7SDavid Shirley 	case CX88_BOARD_WINFAST_DTV1000:
1026363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1027f7b54b10SMichael Krufky 					       &connexant_refboard_config,
10280590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1029399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1030363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
10310590d91cSMauro Carvalho Chehab 					0x60, &core->i2c_adap,
10320590d91cSMauro Carvalho Chehab 					DVB_PLL_THOMSON_DTT7579))
10330590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1034f54376e2SAndrew de Quincey 		}
10351da177e4SLinus Torvalds 		break;
10364bd6e9d9SMalcolm Valentine 	case CX88_BOARD_WINFAST_DTV2000H:
1037611900c1SSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR1100:
1038611900c1SSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
1039a5a2ecfcSTrent Piepho 	case CX88_BOARD_HAUPPAUGE_HVR1300:
1040363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
1041ed355260SMichael Krufky 					       &hauppauge_hvr_config,
10420590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1043399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1044363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
10450590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
10460590d91cSMauro Carvalho Chehab 					TUNER_PHILIPS_FMD1216ME_MK3))
10470590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1048f54376e2SAndrew de Quincey 		}
1049611900c1SSteven Toth 		break;
105027b93d8aSMiroslav Slugen 	case CX88_BOARD_WINFAST_DTV2000H_J:
105127b93d8aSMiroslav Slugen 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
105227b93d8aSMiroslav Slugen 					       &hauppauge_hvr_config,
105327b93d8aSMiroslav Slugen 					       &core->i2c_adap);
1054399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
105527b93d8aSMiroslav Slugen 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
105627b93d8aSMiroslav Slugen 					&core->i2c_adap, 0x61,
105727b93d8aSMiroslav Slugen 					TUNER_PHILIPS_FMD1216MEX_MK3))
105827b93d8aSMiroslav Slugen 				goto frontend_detach;
105927b93d8aSMiroslav Slugen 		}
106027b93d8aSMiroslav Slugen 		break;
1061363c35fcSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR3000:
106260a5a927SDarron Broad 		/* MFE frontend 1 */
106360a5a927SDarron Broad 		mfe_shared = 1;
106460a5a927SDarron Broad 		dev->frontends.gate = 2;
1065363c35fcSSteven Toth 		/* DVB-S init */
1066363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1067363c35fcSSteven Toth 					       &hauppauge_novas_config,
1068363c35fcSSteven Toth 					       &dev->core->i2c_adap);
1069363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
107060a5a927SDarron Broad 			if (!dvb_attach(isl6421_attach,
107160a5a927SDarron Broad 					fe0->dvb.frontend,
107260a5a927SDarron Broad 					&dev->core->i2c_adap,
107348a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
107460a5a927SDarron Broad 				goto frontend_detach;
1075363c35fcSSteven Toth 		}
107660a5a927SDarron Broad 		/* MFE frontend 2 */
10770b6b6302SHans Verkuil 		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
107860a5a927SDarron Broad 		if (!fe1)
107960a5a927SDarron Broad 			goto frontend_detach;
108060a5a927SDarron Broad 		/* DVB-T init */
1081363c35fcSSteven Toth 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
1082363c35fcSSteven Toth 					       &hauppauge_hvr_config,
1083363c35fcSSteven Toth 					       &dev->core->i2c_adap);
1084363c35fcSSteven Toth 		if (fe1->dvb.frontend) {
1085363c35fcSSteven Toth 			fe1->dvb.frontend->id = 1;
108660a5a927SDarron Broad 			if (!dvb_attach(simple_tuner_attach,
108760a5a927SDarron Broad 					fe1->dvb.frontend,
108860a5a927SDarron Broad 					&dev->core->i2c_adap,
108960a5a927SDarron Broad 					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
109060a5a927SDarron Broad 				goto frontend_detach;
1091363c35fcSSteven Toth 		}
1092363c35fcSSteven Toth 		break;
1093780dfef3SChris Pascoe 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
1094363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1095f7b54b10SMichael Krufky 					       &dvico_fusionhdtv,
10960590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1097399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1098363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
10990590d91cSMauro Carvalho Chehab 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
11000590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1101780dfef3SChris Pascoe 			break;
1102f54376e2SAndrew de Quincey 		}
1103780dfef3SChris Pascoe 		/* ZL10353 replaces MT352 on later cards */
1104363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1105f7b54b10SMichael Krufky 					       &dvico_fusionhdtv_plus_v1_1,
11060590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1107399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1108363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
11090590d91cSMauro Carvalho Chehab 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
11100590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1111f54376e2SAndrew de Quincey 		}
1112780dfef3SChris Pascoe 		break;
1113c2af3cd6SMichael Krufky 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
1114399426caSMauro Carvalho Chehab 		/*
1115399426caSMauro Carvalho Chehab 		 * The tin box says DEE1601, but it seems to be DTT7579
1116399426caSMauro Carvalho Chehab 		 * compatible, with a slightly different MT352 AGC gain.
1117399426caSMauro Carvalho Chehab 		 */
1118363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1119f7b54b10SMichael Krufky 					       &dvico_fusionhdtv_dual,
11200590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1121399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1122363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
11230590d91cSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
11240590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1125c2af3cd6SMichael Krufky 			break;
1126c2af3cd6SMichael Krufky 		}
1127c2af3cd6SMichael Krufky 		/* ZL10353 replaces MT352 on later cards */
1128363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1129f7b54b10SMichael Krufky 					       &dvico_fusionhdtv_plus_v1_1,
11300590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1131399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1132363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
11330590d91cSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
11340590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1135c2af3cd6SMichael Krufky 		}
1136c2af3cd6SMichael Krufky 		break;
11371da177e4SLinus Torvalds 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
1138363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1139f7b54b10SMichael Krufky 					       &dvico_fusionhdtv,
11400590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1141399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1142363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
11430590d91cSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_LG_Z201))
11440590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1145f54376e2SAndrew de Quincey 		}
11461da177e4SLinus Torvalds 		break;
11471da177e4SLinus Torvalds 	case CX88_BOARD_KWORLD_DVB_T:
11481da177e4SLinus Torvalds 	case CX88_BOARD_DNTV_LIVE_DVB_T:
1149a82decf6SMauro Carvalho Chehab 	case CX88_BOARD_ADSTECH_DVB_T_PCI:
1150363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1151f7b54b10SMichael Krufky 					       &dntv_live_dvbt_config,
11520590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1153399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1154363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
11550590d91cSMauro Carvalho Chehab 					0x61, NULL, DVB_PLL_UNKNOWN_1))
11560590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1157f54376e2SAndrew de Quincey 		}
11581da177e4SLinus Torvalds 		break;
1159fc40b261SChris Pascoe 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
11607b34be71SPeter Senna Tschudin #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
1161f0ad9097STrent Piepho 		/* MT352 is on a secondary I2C bus made from some GPIO lines */
1162399426caSMauro Carvalho Chehab 		fe0->dvb.frontend = dvb_attach(mt352_attach,
1163399426caSMauro Carvalho Chehab 					       &dntv_live_dvbt_pro_config,
1164f0ad9097STrent Piepho 					       &dev->vp3054->adap);
1165399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1166363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
11670590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
11680590d91cSMauro Carvalho Chehab 					TUNER_PHILIPS_FMD1216ME_MK3))
11690590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1170f54376e2SAndrew de Quincey 		}
1171fc40b261SChris Pascoe #else
117265bc2fe8SMauro Carvalho Chehab 		pr_err("built without vp3054 support\n");
1173fc40b261SChris Pascoe #endif
1174fc40b261SChris Pascoe 		break;
1175780dfef3SChris Pascoe 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
1176363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1177f7b54b10SMichael Krufky 					       &dvico_fusionhdtv_hybrid,
11780590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1179399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1180363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
11810590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
11820590d91cSMauro Carvalho Chehab 					TUNER_THOMSON_FE6600))
11830590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1184f54376e2SAndrew de Quincey 		}
1185780dfef3SChris Pascoe 		break;
1186b3fb91d2SChris Pascoe 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
1187363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1188b3fb91d2SChris Pascoe 					       &dvico_fusionhdtv_xc3028,
11890590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1190399426caSMauro Carvalho Chehab 		if (!fe0->dvb.frontend)
1191363c35fcSSteven Toth 			fe0->dvb.frontend = dvb_attach(mt352_attach,
1192b3fb91d2SChris Pascoe 						&dvico_fusionhdtv_mt352_xc3028,
11930590d91cSMauro Carvalho Chehab 						&core->i2c_adap);
11948765561fSChris Pascoe 		/*
11958765561fSChris Pascoe 		 * On this board, the demod provides the I2C bus pullup.
11968765561fSChris Pascoe 		 * We must not permit gate_ctrl to be performed, or
11978765561fSChris Pascoe 		 * the xc3028 cannot communicate on the bus.
11988765561fSChris Pascoe 		 */
1199363c35fcSSteven Toth 		if (fe0->dvb.frontend)
1200363c35fcSSteven Toth 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
120123fb348dSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
1202becd4305SDarron Broad 			goto frontend_detach;
1203b3fb91d2SChris Pascoe 		break;
12041da177e4SLinus Torvalds 	case CX88_BOARD_PCHDTV_HD3000:
1205363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
12060590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1207399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1208363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
12090590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
12100590d91cSMauro Carvalho Chehab 					TUNER_THOMSON_DTT761X))
12110590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1212f54376e2SAndrew de Quincey 		}
12131da177e4SLinus Torvalds 		break;
1214f1798495SMichael Krufky 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
1215f1798495SMichael Krufky 		dev->ts_gen_cntrl = 0x08;
1216f1798495SMichael Krufky 
12170590d91cSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1218f1798495SMichael Krufky 		cx_clear(MO_GP0_IO, 1);
12199d08ba6dSJia-Ju Bai 		msleep(100);
12200ccef6dbSMichael Krufky 		cx_set(MO_GP0_IO, 1);
12219d08ba6dSJia-Ju Bai 		msleep(200);
12220ccef6dbSMichael Krufky 
12230ccef6dbSMichael Krufky 		/* Select RF connector callback */
12246ddcc919SMichael Krufky 		fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
1225363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1226f7b54b10SMichael Krufky 					       &fusionhdtv_3_gold,
122723ba635dSMauro Carvalho Chehab 					       0x0e,
12280590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1229399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1230363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
12310590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
12320590d91cSMauro Carvalho Chehab 					TUNER_MICROTUNE_4042FI5))
12330590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1234f1798495SMichael Krufky 		}
1235f1798495SMichael Krufky 		break;
12360d723c09SMichael Krufky 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
12370d723c09SMichael Krufky 		dev->ts_gen_cntrl = 0x08;
12380d723c09SMichael Krufky 
12390590d91cSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
12400d723c09SMichael Krufky 		cx_clear(MO_GP0_IO, 1);
12419d08ba6dSJia-Ju Bai 		msleep(100);
1242d975872cSMichael Krufky 		cx_set(MO_GP0_IO, 9);
12439d08ba6dSJia-Ju Bai 		msleep(200);
1244363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1245f7b54b10SMichael Krufky 					       &fusionhdtv_3_gold,
124623ba635dSMauro Carvalho Chehab 					       0x0e,
12470590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1248399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1249363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
12500590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
12510590d91cSMauro Carvalho Chehab 					TUNER_THOMSON_DTT761X))
12520590d91cSMauro Carvalho Chehab 				goto frontend_detach;
12530d723c09SMichael Krufky 		}
12540d723c09SMichael Krufky 		break;
1255e52e98a7SMauro Carvalho Chehab 	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1256e52e98a7SMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x08;
1257e52e98a7SMauro Carvalho Chehab 
12580590d91cSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1259e52e98a7SMauro Carvalho Chehab 		cx_clear(MO_GP0_IO, 1);
12609d08ba6dSJia-Ju Bai 		msleep(100);
1261e52e98a7SMauro Carvalho Chehab 		cx_set(MO_GP0_IO, 1);
12629d08ba6dSJia-Ju Bai 		msleep(200);
1263363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1264f7b54b10SMichael Krufky 					       &fusionhdtv_5_gold,
126523ba635dSMauro Carvalho Chehab 					       0x0e,
12660590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1267399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1268363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
12690590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
12700590d91cSMauro Carvalho Chehab 					TUNER_LG_TDVS_H06XF))
12710590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1272363c35fcSSteven Toth 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
12730590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x43))
12740590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1275e52e98a7SMauro Carvalho Chehab 		}
1276e52e98a7SMauro Carvalho Chehab 		break;
1277da215d22SRusty Scott 	case CX88_BOARD_PCHDTV_HD5500:
1278da215d22SRusty Scott 		dev->ts_gen_cntrl = 0x08;
1279da215d22SRusty Scott 
12800590d91cSMauro Carvalho Chehab 		/* Do a hardware reset of chip before using it. */
1281da215d22SRusty Scott 		cx_clear(MO_GP0_IO, 1);
12829d08ba6dSJia-Ju Bai 		msleep(100);
1283da215d22SRusty Scott 		cx_set(MO_GP0_IO, 1);
12849d08ba6dSJia-Ju Bai 		msleep(200);
1285363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1286f7b54b10SMichael Krufky 					       &pchdtv_hd5500,
128723ba635dSMauro Carvalho Chehab 					       0x59,
12880590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1289399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1290363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
12910590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
12920590d91cSMauro Carvalho Chehab 					TUNER_LG_TDVS_H06XF))
12930590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1294363c35fcSSteven Toth 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
12950590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x43))
12960590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1297da215d22SRusty Scott 		}
1298da215d22SRusty Scott 		break;
1299fde6d31eSKirk Lapray 	case CX88_BOARD_ATI_HDTVWONDER:
1300363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(nxt200x_attach,
1301f7b54b10SMichael Krufky 					       &ati_hdtvwonder,
13020590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1303399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1304363c35fcSSteven Toth 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
13050590d91cSMauro Carvalho Chehab 					&core->i2c_adap, 0x61,
13060590d91cSMauro Carvalho Chehab 					TUNER_PHILIPS_TUV1236D))
13070590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1308f54376e2SAndrew de Quincey 		}
1309fde6d31eSKirk Lapray 		break;
13100fa14aa6SSteven Toth 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
13110fa14aa6SSteven Toth 	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
1312363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1313f7b54b10SMichael Krufky 					       &hauppauge_novas_config,
13140590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1315363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
131648a8a03bSMauro Carvalho Chehab 			bool override_tone;
131748a8a03bSMauro Carvalho Chehab 
131848a8a03bSMauro Carvalho Chehab 			if (core->model == 92001)
131948a8a03bSMauro Carvalho Chehab 				override_tone = true;
132048a8a03bSMauro Carvalho Chehab 			else
132148a8a03bSMauro Carvalho Chehab 				override_tone = false;
132248a8a03bSMauro Carvalho Chehab 
1323363c35fcSSteven Toth 			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
1324399426caSMauro Carvalho Chehab 					&core->i2c_adap, 0x08, ISL6421_DCL,
1325399426caSMauro Carvalho Chehab 					0x00, override_tone))
13260590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1327cd20ca9fSAndrew de Quincey 		}
13280fa14aa6SSteven Toth 		break;
13290e0351e3SVadim Catana 	case CX88_BOARD_KWORLD_DVBS_100:
1330363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1331f7b54b10SMichael Krufky 					       &kworld_dvbs_100_config,
13320590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1333363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
1334363c35fcSSteven Toth 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1335363c35fcSSteven Toth 			fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
1336cd20ca9fSAndrew de Quincey 		}
13370e0351e3SVadim Catana 		break;
1338c02a34f4SSaqeb Akhter 	case CX88_BOARD_GENIATECH_DVBS:
1339363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
1340f7b54b10SMichael Krufky 					       &geniatech_dvbs_config,
13410590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1342363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
1343363c35fcSSteven Toth 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1344363c35fcSSteven Toth 			fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
1345c02a34f4SSaqeb Akhter 		}
1346c02a34f4SSaqeb Akhter 		break;
134760464da8SSteven Toth 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
1348363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
134960464da8SSteven Toth 					       &pinnacle_pctv_hd_800i_config,
13500590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1351399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1352363c35fcSSteven Toth 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
13530590d91cSMauro Carvalho Chehab 					&core->i2c_adap,
135430650961SMichael Krufky 					&pinnacle_pctv_hd_800i_tuner_config))
13550590d91cSMauro Carvalho Chehab 				goto frontend_detach;
135660464da8SSteven Toth 		}
135760464da8SSteven Toth 		break;
13585c00fac0SSteven Toth 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1359363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
13605c00fac0SSteven Toth 					       &dvico_hdtv5_pci_nano_config,
13610590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1362399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
13635c00fac0SSteven Toth 			struct dvb_frontend *fe;
13645c00fac0SSteven Toth 			struct xc2028_config cfg = {
13650590d91cSMauro Carvalho Chehab 				.i2c_adap  = &core->i2c_adap,
13665c00fac0SSteven Toth 				.i2c_addr  = 0x61,
13675c00fac0SSteven Toth 			};
13685c00fac0SSteven Toth 			static struct xc2028_ctrl ctl = {
1369ef80bfebSMichael Krufky 				.fname       = XC2028_DEFAULT_FIRMWARE,
13705c00fac0SSteven Toth 				.max_len     = 64,
137133e53161SMauro Carvalho Chehab 				.scode_table = XC3028_FE_OREN538,
13725c00fac0SSteven Toth 			};
13735c00fac0SSteven Toth 
13745c00fac0SSteven Toth 			fe = dvb_attach(xc2028_attach,
1375363c35fcSSteven Toth 					fe0->dvb.frontend, &cfg);
1376399426caSMauro Carvalho Chehab 			if (fe && fe->ops.tuner_ops.set_config)
13775c00fac0SSteven Toth 				fe->ops.tuner_ops.set_config(fe, &ctl);
13785c00fac0SSteven Toth 		}
13795c00fac0SSteven Toth 		break;
1380e6f45ea2SDaniel Gonzalez Cabanelas 	case CX88_BOARD_NOTONLYTV_LV3H:
13819507901eSMauro Carvalho Chehab 	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
13823047a176SMiroslav Sustek 	case CX88_BOARD_WINFAST_DTV1800H:
1383363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
13843f6014fcSStéphane Voltz 					       &cx88_pinnacle_hybrid_pctv,
13850590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1386363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
1387363c35fcSSteven Toth 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
138823fb348dSMauro Carvalho Chehab 			if (attach_xc3028(0x61, dev) < 0)
13890590d91cSMauro Carvalho Chehab 				goto frontend_detach;
13903f6014fcSStéphane Voltz 		}
13919507901eSMauro Carvalho Chehab 		break;
13928eb79c0bSistvan_v@mailbox.hu 	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
1393f271a3afSistvan_v@mailbox.hu 	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1394f271a3afSistvan_v@mailbox.hu 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
1395f271a3afSistvan_v@mailbox.hu 					       &cx88_pinnacle_hybrid_pctv,
1396f271a3afSistvan_v@mailbox.hu 					       &core->i2c_adap);
1397f271a3afSistvan_v@mailbox.hu 		if (fe0->dvb.frontend) {
1398f271a3afSistvan_v@mailbox.hu 			struct xc4000_config cfg = {
1399f271a3afSistvan_v@mailbox.hu 				.i2c_address	  = 0x61,
1400f271a3afSistvan_v@mailbox.hu 				.default_pm	  = 0,
1401f271a3afSistvan_v@mailbox.hu 				.dvb_amplitude	  = 134,
1402f271a3afSistvan_v@mailbox.hu 				.set_smoothedcvbs = 1,
1403f271a3afSistvan_v@mailbox.hu 				.if_khz		  = 4560
1404f271a3afSistvan_v@mailbox.hu 			};
1405f271a3afSistvan_v@mailbox.hu 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1406f271a3afSistvan_v@mailbox.hu 			if (attach_xc4000(dev, &cfg) < 0)
1407f271a3afSistvan_v@mailbox.hu 				goto frontend_detach;
1408f271a3afSistvan_v@mailbox.hu 		}
1409f271a3afSistvan_v@mailbox.hu 		break;
14109507901eSMauro Carvalho Chehab 	case CX88_BOARD_GENIATECH_X8000_MT:
14119507901eSMauro Carvalho Chehab 		dev->ts_gen_cntrl = 0x00;
14129507901eSMauro Carvalho Chehab 
1413363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
14149507901eSMauro Carvalho Chehab 					       &cx88_geniatech_x8000_mt,
14150590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
141623fb348dSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
14170590d91cSMauro Carvalho Chehab 			goto frontend_detach;
14189507901eSMauro Carvalho Chehab 		break;
141999e09eacSMauro Carvalho Chehab 	case CX88_BOARD_KWORLD_ATSC_120:
1420363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
142199e09eacSMauro Carvalho Chehab 					       &kworld_atsc_120_config,
14220590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
142399e09eacSMauro Carvalho Chehab 		if (attach_xc3028(0x61, dev) < 0)
14240590d91cSMauro Carvalho Chehab 			goto frontend_detach;
142599e09eacSMauro Carvalho Chehab 		break;
1426d893d5dcSSteven Toth 	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
1427363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
1428d893d5dcSSteven Toth 					       &dvico_fusionhdtv7_config,
14290590d91cSMauro Carvalho Chehab 					       &core->i2c_adap);
1430399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1431363c35fcSSteven Toth 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
14320590d91cSMauro Carvalho Chehab 					&core->i2c_adap,
143330650961SMichael Krufky 					&dvico_fusionhdtv7_tuner_config))
14340590d91cSMauro Carvalho Chehab 				goto frontend_detach;
1435d893d5dcSSteven Toth 		}
1436d893d5dcSSteven Toth 		break;
14375bd1b663SSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR4000:
143860a5a927SDarron Broad 		/* MFE frontend 1 */
143960a5a927SDarron Broad 		mfe_shared = 1;
144060a5a927SDarron Broad 		dev->frontends.gate = 2;
1441363c35fcSSteven Toth 		/* DVB-S/S2 Init */
1442363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
14435bd1b663SSteven Toth 					       &hauppauge_hvr4000_config,
14445bd1b663SSteven Toth 					       &dev->core->i2c_adap);
1445363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
144660a5a927SDarron Broad 			if (!dvb_attach(isl6421_attach,
144760a5a927SDarron Broad 					fe0->dvb.frontend,
144860a5a927SDarron Broad 					&dev->core->i2c_adap,
144948a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
145060a5a927SDarron Broad 				goto frontend_detach;
1451363c35fcSSteven Toth 		}
145260a5a927SDarron Broad 		/* MFE frontend 2 */
14530b6b6302SHans Verkuil 		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
145460a5a927SDarron Broad 		if (!fe1)
145560a5a927SDarron Broad 			goto frontend_detach;
145660a5a927SDarron Broad 		/* DVB-T Init */
1457363c35fcSSteven Toth 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
1458363c35fcSSteven Toth 					       &hauppauge_hvr_config,
1459363c35fcSSteven Toth 					       &dev->core->i2c_adap);
1460363c35fcSSteven Toth 		if (fe1->dvb.frontend) {
1461363c35fcSSteven Toth 			fe1->dvb.frontend->id = 1;
146260a5a927SDarron Broad 			if (!dvb_attach(simple_tuner_attach,
146360a5a927SDarron Broad 					fe1->dvb.frontend,
146460a5a927SDarron Broad 					&dev->core->i2c_adap,
146560a5a927SDarron Broad 					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
146660a5a927SDarron Broad 				goto frontend_detach;
1467363c35fcSSteven Toth 		}
1468363c35fcSSteven Toth 		break;
1469363c35fcSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
1470363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1471363c35fcSSteven Toth 					       &hauppauge_hvr4000_config,
1472363c35fcSSteven Toth 					       &dev->core->i2c_adap);
1473363c35fcSSteven Toth 		if (fe0->dvb.frontend) {
147460a5a927SDarron Broad 			if (!dvb_attach(isl6421_attach,
147560a5a927SDarron Broad 					fe0->dvb.frontend,
14765bd1b663SSteven Toth 					&dev->core->i2c_adap,
147748a8a03bSMauro Carvalho Chehab 					0x08, ISL6421_DCL, 0x00, false))
147860a5a927SDarron Broad 				goto frontend_detach;
14795bd1b663SSteven Toth 		}
14805bd1b663SSteven Toth 		break;
1481cd3cde12SIgor M. Liplianin 	case CX88_BOARD_PROF_6200:
14824b29631dSIgor M. Liplianin 	case CX88_BOARD_TBS_8910:
1483e4aab64cSIgor M. Liplianin 	case CX88_BOARD_TEVII_S420:
1484363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
1485e4aab64cSIgor M. Liplianin 						&tevii_tuner_sharp_config,
1486e4aab64cSIgor M. Liplianin 						&core->i2c_adap);
1487399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1488363c35fcSSteven Toth 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
1489e4aab64cSIgor M. Liplianin 					&core->i2c_adap, DVB_PLL_OPERA1))
1490e4aab64cSIgor M. Liplianin 				goto frontend_detach;
1491363c35fcSSteven Toth 			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1492363c35fcSSteven Toth 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1493e4aab64cSIgor M. Liplianin 
1494e4aab64cSIgor M. Liplianin 		} else {
1495363c35fcSSteven Toth 			fe0->dvb.frontend = dvb_attach(stv0288_attach,
1496e4aab64cSIgor M. Liplianin 							    &tevii_tuner_earda_config,
1497e4aab64cSIgor M. Liplianin 							    &core->i2c_adap);
1498399426caSMauro Carvalho Chehab 			if (fe0->dvb.frontend) {
1499399426caSMauro Carvalho Chehab 				if (!dvb_attach(stb6000_attach,
1500399426caSMauro Carvalho Chehab 						fe0->dvb.frontend, 0x61,
1501e4aab64cSIgor M. Liplianin 						&core->i2c_adap))
1502e4aab64cSIgor M. Liplianin 					goto frontend_detach;
1503363c35fcSSteven Toth 				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1504363c35fcSSteven Toth 				fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1505e4aab64cSIgor M. Liplianin 			}
1506e4aab64cSIgor M. Liplianin 		}
1507e4aab64cSIgor M. Liplianin 		break;
1508af832623SIgor M. Liplianin 	case CX88_BOARD_TEVII_S460:
1509363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1510af832623SIgor M. Liplianin 					       &tevii_s460_config,
1511af832623SIgor M. Liplianin 					       &core->i2c_adap);
1512399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend)
1513363c35fcSSteven Toth 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1514af832623SIgor M. Liplianin 		break;
15150cb73639SIgor M. Liplianin 	case CX88_BOARD_TEVII_S464:
15160cb73639SIgor M. Liplianin 		fe0->dvb.frontend = dvb_attach(ds3000_attach,
15170cb73639SIgor M. Liplianin 						&tevii_ds3000_config,
15180cb73639SIgor M. Liplianin 						&core->i2c_adap);
1519399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
152073f0af44SKonstantin Dimitrov 			dvb_attach(ts2020_attach, fe0->dvb.frontend,
152173f0af44SKonstantin Dimitrov 				   &tevii_ts2020_config, &core->i2c_adap);
15220cb73639SIgor M. Liplianin 			fe0->dvb.frontend->ops.set_voltage =
15230cb73639SIgor M. Liplianin 							tevii_dvbs_set_voltage;
152473f0af44SKonstantin Dimitrov 		}
15250cb73639SIgor M. Liplianin 		break;
15264cd7fb87SOleg Roitburd 	case CX88_BOARD_OMICOM_SS4_PCI:
1527ee73042cSOleg Roitburd 	case CX88_BOARD_TBS_8920:
152857f51dbcSOleg Roitburd 	case CX88_BOARD_PROF_7300:
15294b29631dSIgor M. Liplianin 	case CX88_BOARD_SATTRADE_ST4200:
1530363c35fcSSteven Toth 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
1531ee73042cSOleg Roitburd 					       &hauppauge_hvr4000_config,
1532ee73042cSOleg Roitburd 					       &core->i2c_adap);
1533399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend)
1534363c35fcSSteven Toth 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1535ee73042cSOleg Roitburd 		break;
153670101a27SStephan Wienczny 	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
153770101a27SStephan Wienczny 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
153870101a27SStephan Wienczny 					       &cx88_terratec_cinergy_ht_pci_mkii_config,
153970101a27SStephan Wienczny 					       &core->i2c_adap);
154070101a27SStephan Wienczny 		if (fe0->dvb.frontend) {
154170101a27SStephan Wienczny 			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
154270101a27SStephan Wienczny 			if (attach_xc3028(0x61, dev) < 0)
154370101a27SStephan Wienczny 				goto frontend_detach;
154470101a27SStephan Wienczny 		}
154570101a27SStephan Wienczny 		break;
1546b699c271SIgor M. Liplianin 	case CX88_BOARD_PROF_7301:{
1547b699c271SIgor M. Liplianin 		struct dvb_tuner_ops *tuner_ops = NULL;
1548b699c271SIgor M. Liplianin 
1549b699c271SIgor M. Liplianin 		fe0->dvb.frontend = dvb_attach(stv0900_attach,
1550b699c271SIgor M. Liplianin 					       &prof_7301_stv0900_config,
1551b699c271SIgor M. Liplianin 					       &core->i2c_adap, 0);
1552399426caSMauro Carvalho Chehab 		if (fe0->dvb.frontend) {
1553b699c271SIgor M. Liplianin 			if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
1554b699c271SIgor M. Liplianin 					&prof_7301_stb6100_config,
1555b699c271SIgor M. Liplianin 					&core->i2c_adap))
1556b699c271SIgor M. Liplianin 				goto frontend_detach;
1557b699c271SIgor M. Liplianin 
1558b699c271SIgor M. Liplianin 			tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
1559b699c271SIgor M. Liplianin 			tuner_ops->set_frequency = stb6100_set_freq;
1560b699c271SIgor M. Liplianin 			tuner_ops->get_frequency = stb6100_get_freq;
1561b699c271SIgor M. Liplianin 			tuner_ops->set_bandwidth = stb6100_set_bandw;
1562b699c271SIgor M. Liplianin 			tuner_ops->get_bandwidth = stb6100_get_bandw;
1563b699c271SIgor M. Liplianin 
1564b699c271SIgor M. Liplianin 			core->prev_set_voltage =
1565b699c271SIgor M. Liplianin 					fe0->dvb.frontend->ops.set_voltage;
1566b699c271SIgor M. Liplianin 			fe0->dvb.frontend->ops.set_voltage =
1567b699c271SIgor M. Liplianin 					tevii_dvbs_set_voltage;
1568b699c271SIgor M. Liplianin 		}
1569b699c271SIgor M. Liplianin 		break;
1570b699c271SIgor M. Liplianin 		}
15714f3ca2f1SDirk Herrendoerfer 	case CX88_BOARD_SAMSUNG_SMT_7020:
15724f3ca2f1SDirk Herrendoerfer 		dev->ts_gen_cntrl = 0x08;
15734f3ca2f1SDirk Herrendoerfer 
15744f3ca2f1SDirk Herrendoerfer 		cx_set(MO_GP0_IO, 0x0101);
15754f3ca2f1SDirk Herrendoerfer 
15764f3ca2f1SDirk Herrendoerfer 		cx_clear(MO_GP0_IO, 0x01);
15779d08ba6dSJia-Ju Bai 		msleep(100);
15784f3ca2f1SDirk Herrendoerfer 		cx_set(MO_GP0_IO, 0x01);
15799d08ba6dSJia-Ju Bai 		msleep(200);
15804f3ca2f1SDirk Herrendoerfer 
15814f3ca2f1SDirk Herrendoerfer 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
15824f3ca2f1SDirk Herrendoerfer 					       &samsung_stv0299_config,
15834f3ca2f1SDirk Herrendoerfer 					       &dev->core->i2c_adap);
15844f3ca2f1SDirk Herrendoerfer 		if (fe0->dvb.frontend) {
15854f3ca2f1SDirk Herrendoerfer 			fe0->dvb.frontend->ops.tuner_ops.set_params =
15864f3ca2f1SDirk Herrendoerfer 				samsung_smt_7020_tuner_set_params;
15874f3ca2f1SDirk Herrendoerfer 			fe0->dvb.frontend->tuner_priv =
15884f3ca2f1SDirk Herrendoerfer 				&dev->core->i2c_adap;
15894f3ca2f1SDirk Herrendoerfer 			fe0->dvb.frontend->ops.set_voltage =
15904f3ca2f1SDirk Herrendoerfer 				samsung_smt_7020_set_voltage;
15914f3ca2f1SDirk Herrendoerfer 			fe0->dvb.frontend->ops.set_tone =
15924f3ca2f1SDirk Herrendoerfer 				samsung_smt_7020_set_tone;
15934f3ca2f1SDirk Herrendoerfer 		}
15944f3ca2f1SDirk Herrendoerfer 
15954f3ca2f1SDirk Herrendoerfer 		break;
1596111ac84aSSergey Ivanov 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
1597111ac84aSSergey Ivanov 		dev->ts_gen_cntrl = 0x00;
1598111ac84aSSergey Ivanov 		fe0->dvb.frontend = dvb_attach(mb86a16_attach,
1599111ac84aSSergey Ivanov 					       &twinhan_vp1027,
1600111ac84aSSergey Ivanov 					       &core->i2c_adap);
1601111ac84aSSergey Ivanov 		if (fe0->dvb.frontend) {
1602111ac84aSSergey Ivanov 			core->prev_set_voltage =
1603111ac84aSSergey Ivanov 					fe0->dvb.frontend->ops.set_voltage;
1604111ac84aSSergey Ivanov 			fe0->dvb.frontend->ops.set_voltage =
1605111ac84aSSergey Ivanov 					vp1027_set_voltage;
1606111ac84aSSergey Ivanov 		}
1607111ac84aSSergey Ivanov 		break;
16084f3ca2f1SDirk Herrendoerfer 
16091da177e4SLinus Torvalds 	default:
161065bc2fe8SMauro Carvalho Chehab 		pr_err("The frontend of your DVB/ATSC card isn't supported yet\n");
16111da177e4SLinus Torvalds 		break;
16121da177e4SLinus Torvalds 	}
1613363c35fcSSteven Toth 
1614363c35fcSSteven Toth 	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
161565bc2fe8SMauro Carvalho Chehab 		pr_err("frontend initialization failed\n");
161660a5a927SDarron Broad 		goto frontend_detach;
16179507901eSMauro Carvalho Chehab 	}
1618d7cba043SMichael Krufky 	/* define general-purpose callback pointer */
1619363c35fcSSteven Toth 	fe0->dvb.frontend->callback = cx88_tuner_callback;
16209507901eSMauro Carvalho Chehab 
16216c5be74cSSteven Toth 	/* Ensure all frontends negotiate bus access */
1622363c35fcSSteven Toth 	fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1623363c35fcSSteven Toth 	if (fe1)
1624363c35fcSSteven Toth 		fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
16251da177e4SLinus Torvalds 
16263aab15afSHans Verkuil 	/* Put the tuner in standby to keep it quiet */
16273aab15afSHans Verkuil 	call_all(core, tuner, standby);
162893352f5cSMauro Carvalho Chehab 
16291da177e4SLinus Torvalds 	/* register everything */
16300b6b6302SHans Verkuil 	res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
16312773b0e9SMauro Carvalho Chehab 				   &dev->pci->dev, NULL, adapter_nr,
16322773b0e9SMauro Carvalho Chehab 				   mfe_shared);
16337b0962d3SDavid Fries 	if (res)
16347b0962d3SDavid Fries 		goto frontend_detach;
16357b0962d3SDavid Fries 	return res;
16360590d91cSMauro Carvalho Chehab 
16370590d91cSMauro Carvalho Chehab frontend_detach:
1638e32fadc4SMauro Carvalho Chehab 	core->gate_ctrl = NULL;
16390b6b6302SHans Verkuil 	vb2_dvb_dealloc_frontends(&dev->frontends);
16407b0962d3SDavid Fries 	return res;
16411da177e4SLinus Torvalds }
16421da177e4SLinus Torvalds 
16431da177e4SLinus Torvalds /* ----------------------------------------------------------- */
16441da177e4SLinus Torvalds 
16456c5be74cSSteven Toth /* CX8802 MPEG -> mini driver - We have been given the hardware */
cx8802_dvb_advise_acquire(struct cx8802_driver * drv)16466c5be74cSSteven Toth static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
16471da177e4SLinus Torvalds {
16486c5be74cSSteven Toth 	struct cx88_core *core = drv->core;
16496c5be74cSSteven Toth 	int err = 0;
16507b61ba8fSMauro Carvalho Chehab 
165132d83efcSHarvey Harrison 	dprintk(1, "%s\n", __func__);
16526c5be74cSSteven Toth 
16536a59d64cSTrent Piepho 	switch (core->boardnr) {
16546c5be74cSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR1300:
16556c5be74cSSteven Toth 		/* We arrive here with either the cx23416 or the cx22702
16566c5be74cSSteven Toth 		 * on the bus. Take the bus from the cx23416 and enable the
16576c5be74cSSteven Toth 		 * cx22702 demod
16586c5be74cSSteven Toth 		 */
165979392737SDarron Broad 		/* Toggle reset on cx22702 leaving i2c active */
166079392737SDarron Broad 		cx_set(MO_GP0_IO, 0x00000080);
166179392737SDarron Broad 		udelay(1000);
166279392737SDarron Broad 		cx_clear(MO_GP0_IO, 0x00000080);
166379392737SDarron Broad 		udelay(50);
166479392737SDarron Broad 		cx_set(MO_GP0_IO, 0x00000080);
166579392737SDarron Broad 		udelay(1000);
166679392737SDarron Broad 		/* enable the cx22702 pins */
16676c5be74cSSteven Toth 		cx_clear(MO_GP0_IO, 0x00000004);
16686c5be74cSSteven Toth 		udelay(1000);
16696c5be74cSSteven Toth 		break;
1670363c35fcSSteven Toth 
167192abe9eeSDarron Broad 	case CX88_BOARD_HAUPPAUGE_HVR3000:
1672363c35fcSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR4000:
1673363c35fcSSteven Toth 		/* Toggle reset on cx22702 leaving i2c active */
167479392737SDarron Broad 		cx_set(MO_GP0_IO, 0x00000080);
1675363c35fcSSteven Toth 		udelay(1000);
1676363c35fcSSteven Toth 		cx_clear(MO_GP0_IO, 0x00000080);
1677363c35fcSSteven Toth 		udelay(50);
167879392737SDarron Broad 		cx_set(MO_GP0_IO, 0x00000080);
1679363c35fcSSteven Toth 		udelay(1000);
168079392737SDarron Broad 		switch (core->dvbdev->frontends.active_fe_id) {
168179392737SDarron Broad 		case 1: /* DVB-S/S2 Enabled */
168279392737SDarron Broad 			/* tri-state the cx22702 pins */
168379392737SDarron Broad 			cx_set(MO_GP0_IO, 0x00000004);
168479392737SDarron Broad 			/* Take the cx24116/cx24123 out of reset */
168579392737SDarron Broad 			cx_write(MO_SRST_IO, 1);
1686363c35fcSSteven Toth 			core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
168779392737SDarron Broad 			break;
168879392737SDarron Broad 		case 2: /* DVB-T Enabled */
1689363c35fcSSteven Toth 			/* Put the cx24116/cx24123 into reset */
1690363c35fcSSteven Toth 			cx_write(MO_SRST_IO, 0);
169179392737SDarron Broad 			/* enable the cx22702 pins */
1692363c35fcSSteven Toth 			cx_clear(MO_GP0_IO, 0x00000004);
1693363c35fcSSteven Toth 			core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
169479392737SDarron Broad 			break;
1695363c35fcSSteven Toth 		}
169679392737SDarron Broad 		udelay(1000);
1697363c35fcSSteven Toth 		break;
1698363c35fcSSteven Toth 
1699f271a3afSistvan_v@mailbox.hu 	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1700f271a3afSistvan_v@mailbox.hu 		/* set RF input to AIR for DVB-T (GPIO 16) */
1701f271a3afSistvan_v@mailbox.hu 		cx_write(MO_GP2_IO, 0x0101);
1702f271a3afSistvan_v@mailbox.hu 		break;
1703f271a3afSistvan_v@mailbox.hu 
17046c5be74cSSteven Toth 	default:
17056c5be74cSSteven Toth 		err = -ENODEV;
17066c5be74cSSteven Toth 	}
17076c5be74cSSteven Toth 	return err;
17086c5be74cSSteven Toth }
17096c5be74cSSteven Toth 
17106c5be74cSSteven Toth /* CX8802 MPEG -> mini driver - We no longer have the hardware */
cx8802_dvb_advise_release(struct cx8802_driver * drv)17116c5be74cSSteven Toth static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
17126c5be74cSSteven Toth {
17136c5be74cSSteven Toth 	struct cx88_core *core = drv->core;
17146c5be74cSSteven Toth 	int err = 0;
17157b61ba8fSMauro Carvalho Chehab 
171632d83efcSHarvey Harrison 	dprintk(1, "%s\n", __func__);
17176c5be74cSSteven Toth 
17186a59d64cSTrent Piepho 	switch (core->boardnr) {
17196c5be74cSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR1300:
17206c5be74cSSteven Toth 		/* Do Nothing, leave the cx22702 on the bus. */
17216c5be74cSSteven Toth 		break;
1722363c35fcSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR3000:
1723363c35fcSSteven Toth 	case CX88_BOARD_HAUPPAUGE_HVR4000:
1724363c35fcSSteven Toth 		break;
17256c5be74cSSteven Toth 	default:
17266c5be74cSSteven Toth 		err = -ENODEV;
17276c5be74cSSteven Toth 	}
17286c5be74cSSteven Toth 	return err;
17296c5be74cSSteven Toth }
17306c5be74cSSteven Toth 
cx8802_dvb_probe(struct cx8802_driver * drv)17316c5be74cSSteven Toth static int cx8802_dvb_probe(struct cx8802_driver *drv)
17326c5be74cSSteven Toth {
17336c5be74cSSteven Toth 	struct cx88_core *core = drv->core;
17346c5be74cSSteven Toth 	struct cx8802_dev *dev = drv->core->dvbdev;
1735cbd82441SDarron Broad 	int err;
17360b6b6302SHans Verkuil 	struct vb2_dvb_frontend *fe;
17376e0e12f1SAndy Walls 	int i;
17381da177e4SLinus Torvalds 
173932d83efcSHarvey Harrison 	dprintk(1, "%s\n", __func__);
17406c5be74cSSteven Toth 	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
17416a59d64cSTrent Piepho 		core->boardnr,
17426c5be74cSSteven Toth 		core->name,
17436c5be74cSSteven Toth 		core->pci_bus,
17446c5be74cSSteven Toth 		core->pci_slot);
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds 	err = -ENODEV;
17476a59d64cSTrent Piepho 	if (!(core->board.mpeg & CX88_MPEG_DVB))
17481da177e4SLinus Torvalds 		goto fail_core;
17491da177e4SLinus Torvalds 
1750ecf854dfSTrent Piepho 	/* If vp3054 isn't enabled, a stub will just return 0 */
1751fc40b261SChris Pascoe 	err = vp3054_i2c_probe(dev);
17527b61ba8fSMauro Carvalho Chehab 	if (err != 0)
17536e0e12f1SAndy Walls 		goto fail_core;
1754fc40b261SChris Pascoe 
17551da177e4SLinus Torvalds 	/* dvb stuff */
175665bc2fe8SMauro Carvalho Chehab 	pr_info("cx2388x based DVB/ATSC card\n");
1757363c35fcSSteven Toth 	dev->ts_gen_cntrl = 0x0c;
1758363c35fcSSteven Toth 
17596e0e12f1SAndy Walls 	err = cx8802_alloc_frontends(dev);
17606e0e12f1SAndy Walls 	if (err)
17616e0e12f1SAndy Walls 		goto fail_core;
1762cbd82441SDarron Broad 
1763363c35fcSSteven Toth 	for (i = 1; i <= core->board.num_frontends; i++) {
17640b6b6302SHans Verkuil 		struct vb2_queue *q;
17650b6b6302SHans Verkuil 
17660b6b6302SHans Verkuil 		fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
1767399426caSMauro Carvalho Chehab 		if (!fe) {
176865bc2fe8SMauro Carvalho Chehab 			pr_err("%s() failed to get frontend(%d)\n",
1769cbd82441SDarron Broad 			       __func__, i);
1770e546b1efSWei Yongjun 			err = -ENODEV;
1771cbd82441SDarron Broad 			goto fail_probe;
1772363c35fcSSteven Toth 		}
17730b6b6302SHans Verkuil 		q = &fe->dvb.dvbq;
17740b6b6302SHans Verkuil 		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
17750b6b6302SHans Verkuil 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
17760b6b6302SHans Verkuil 		q->gfp_flags = GFP_DMA32;
177780c2b40aSBenjamin Gaignard 		q->min_queued_buffers = 2;
17780b6b6302SHans Verkuil 		q->drv_priv = dev;
17790b6b6302SHans Verkuil 		q->buf_struct_size = sizeof(struct cx88_buffer);
17800b6b6302SHans Verkuil 		q->ops = &dvb_qops;
17810b6b6302SHans Verkuil 		q->mem_ops = &vb2_dma_sg_memops;
17820b6b6302SHans Verkuil 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
17830b6b6302SHans Verkuil 		q->lock = &core->lock;
17842bc46b3aSHans Verkuil 		q->dev = &dev->pci->dev;
17850b6b6302SHans Verkuil 
17860b6b6302SHans Verkuil 		err = vb2_queue_init(q);
17870b6b6302SHans Verkuil 		if (err < 0)
17880b6b6302SHans Verkuil 			goto fail_probe;
17890b6b6302SHans Verkuil 
17900b6b6302SHans Verkuil 		/* init struct vb2_dvb */
1791363c35fcSSteven Toth 		fe->dvb.name = dev->core->name;
1792363c35fcSSteven Toth 	}
17936e0e12f1SAndy Walls 
17941da177e4SLinus Torvalds 	err = dvb_register(dev);
1795cbd82441SDarron Broad 	if (err)
1796cbd82441SDarron Broad 		/* frontends/adapter de-allocated in dvb_register */
179765bc2fe8SMauro Carvalho Chehab 		pr_err("dvb_register failed (err = %d)\n", err);
1798cbd82441SDarron Broad 	return err;
1799cbd82441SDarron Broad fail_probe:
18000b6b6302SHans Verkuil 	vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
18011da177e4SLinus Torvalds fail_core:
18021da177e4SLinus Torvalds 	return err;
18031da177e4SLinus Torvalds }
18041da177e4SLinus Torvalds 
cx8802_dvb_remove(struct cx8802_driver * drv)18056c5be74cSSteven Toth static int cx8802_dvb_remove(struct cx8802_driver *drv)
18061da177e4SLinus Torvalds {
18070fcd488dSDarron Broad 	struct cx88_core *core = drv->core;
18086c5be74cSSteven Toth 	struct cx8802_dev *dev = drv->core->dvbdev;
1809611900c1SSteven Toth 
18100fcd488dSDarron Broad 	dprintk(1, "%s\n", __func__);
18110fcd488dSDarron Broad 
18120b6b6302SHans Verkuil 	vb2_dvb_unregister_bus(&dev->frontends);
18131da177e4SLinus Torvalds 
1814fc40b261SChris Pascoe 	vp3054_i2c_remove(dev);
1815fc40b261SChris Pascoe 
1816e32fadc4SMauro Carvalho Chehab 	core->gate_ctrl = NULL;
1817e32fadc4SMauro Carvalho Chehab 
18186c5be74cSSteven Toth 	return 0;
18191da177e4SLinus Torvalds }
18201da177e4SLinus Torvalds 
18216c5be74cSSteven Toth static struct cx8802_driver cx8802_dvb_driver = {
18226c5be74cSSteven Toth 	.type_id        = CX88_MPEG_DVB,
18236c5be74cSSteven Toth 	.hw_access      = CX8802_DRVCTL_SHARED,
18246c5be74cSSteven Toth 	.probe          = cx8802_dvb_probe,
18256c5be74cSSteven Toth 	.remove         = cx8802_dvb_remove,
18266c5be74cSSteven Toth 	.advise_acquire = cx8802_dvb_advise_acquire,
18276c5be74cSSteven Toth 	.advise_release = cx8802_dvb_advise_release,
18281da177e4SLinus Torvalds };
18291da177e4SLinus Torvalds 
dvb_init(void)183031d0f845SPeter Huewe static int __init dvb_init(void)
18311da177e4SLinus Torvalds {
183265bc2fe8SMauro Carvalho Chehab 	pr_info("cx2388x dvb driver version %s loaded\n", CX88_VERSION);
18336c5be74cSSteven Toth 	return cx8802_register_driver(&cx8802_dvb_driver);
18341da177e4SLinus Torvalds }
18351da177e4SLinus Torvalds 
dvb_fini(void)183631d0f845SPeter Huewe static void __exit dvb_fini(void)
18371da177e4SLinus Torvalds {
18386c5be74cSSteven Toth 	cx8802_unregister_driver(&cx8802_dvb_driver);
18391da177e4SLinus Torvalds }
18401da177e4SLinus Torvalds 
18411da177e4SLinus Torvalds module_init(dvb_init);
18421da177e4SLinus Torvalds module_exit(dvb_fini);
1843