xref: /OK3568_Linux_fs/kernel/drivers/media/pci/saa7164/saa7164-dvb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Driver for the NXP SAA7164 PCIe bridge
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "saa7164.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "tda10048.h"
11*4882a593Smuzhiyun #include "tda18271.h"
12*4882a593Smuzhiyun #include "s5h1411.h"
13*4882a593Smuzhiyun #include "si2157.h"
14*4882a593Smuzhiyun #include "si2168.h"
15*4882a593Smuzhiyun #include "lgdt3306a.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define DRIVER_NAME "saa7164"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* addr is in the card struct, get it from there */
22*4882a593Smuzhiyun static struct tda10048_config hauppauge_hvr2200_1_config = {
23*4882a593Smuzhiyun 	.demod_address    = 0x10 >> 1,
24*4882a593Smuzhiyun 	.output_mode      = TDA10048_SERIAL_OUTPUT,
25*4882a593Smuzhiyun 	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
26*4882a593Smuzhiyun 	.inversion        = TDA10048_INVERSION_ON,
27*4882a593Smuzhiyun 	.dtv6_if_freq_khz = TDA10048_IF_3300,
28*4882a593Smuzhiyun 	.dtv7_if_freq_khz = TDA10048_IF_3500,
29*4882a593Smuzhiyun 	.dtv8_if_freq_khz = TDA10048_IF_4000,
30*4882a593Smuzhiyun 	.clk_freq_khz     = TDA10048_CLK_16000,
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun static struct tda10048_config hauppauge_hvr2200_2_config = {
33*4882a593Smuzhiyun 	.demod_address    = 0x12 >> 1,
34*4882a593Smuzhiyun 	.output_mode      = TDA10048_SERIAL_OUTPUT,
35*4882a593Smuzhiyun 	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
36*4882a593Smuzhiyun 	.inversion        = TDA10048_INVERSION_ON,
37*4882a593Smuzhiyun 	.dtv6_if_freq_khz = TDA10048_IF_3300,
38*4882a593Smuzhiyun 	.dtv7_if_freq_khz = TDA10048_IF_3500,
39*4882a593Smuzhiyun 	.dtv8_if_freq_khz = TDA10048_IF_4000,
40*4882a593Smuzhiyun 	.clk_freq_khz     = TDA10048_CLK_16000,
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun static struct tda18271_std_map hauppauge_tda18271_std_map = {
44*4882a593Smuzhiyun 	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 3,
45*4882a593Smuzhiyun 		      .if_lvl = 6, .rfagc_top = 0x37 },
46*4882a593Smuzhiyun 	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
47*4882a593Smuzhiyun 		      .if_lvl = 6, .rfagc_top = 0x37 },
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun static struct tda18271_config hauppauge_hvr22x0_tuner_config = {
51*4882a593Smuzhiyun 	.std_map	= &hauppauge_tda18271_std_map,
52*4882a593Smuzhiyun 	.gate		= TDA18271_GATE_ANALOG,
53*4882a593Smuzhiyun 	.role		= TDA18271_MASTER,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static struct tda18271_config hauppauge_hvr22x0s_tuner_config = {
57*4882a593Smuzhiyun 	.std_map	= &hauppauge_tda18271_std_map,
58*4882a593Smuzhiyun 	.gate		= TDA18271_GATE_ANALOG,
59*4882a593Smuzhiyun 	.role		= TDA18271_SLAVE,
60*4882a593Smuzhiyun 	.output_opt     = TDA18271_OUTPUT_LT_OFF,
61*4882a593Smuzhiyun 	.rf_cal_on_startup = 1
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun static struct s5h1411_config hauppauge_s5h1411_config = {
65*4882a593Smuzhiyun 	.output_mode   = S5H1411_SERIAL_OUTPUT,
66*4882a593Smuzhiyun 	.gpio          = S5H1411_GPIO_ON,
67*4882a593Smuzhiyun 	.qam_if        = S5H1411_IF_4000,
68*4882a593Smuzhiyun 	.vsb_if        = S5H1411_IF_3250,
69*4882a593Smuzhiyun 	.inversion     = S5H1411_INVERSION_ON,
70*4882a593Smuzhiyun 	.status_mode   = S5H1411_DEMODLOCKING,
71*4882a593Smuzhiyun 	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static struct lgdt3306a_config hauppauge_hvr2255a_config = {
75*4882a593Smuzhiyun 	.i2c_addr               = 0xb2 >> 1,
76*4882a593Smuzhiyun 	.qam_if_khz             = 4000,
77*4882a593Smuzhiyun 	.vsb_if_khz             = 3250,
78*4882a593Smuzhiyun 	.deny_i2c_rptr          = 1, /* Disabled */
79*4882a593Smuzhiyun 	.spectral_inversion     = 0, /* Disabled */
80*4882a593Smuzhiyun 	.mpeg_mode              = LGDT3306A_MPEG_SERIAL,
81*4882a593Smuzhiyun 	.tpclk_edge             = LGDT3306A_TPCLK_RISING_EDGE,
82*4882a593Smuzhiyun 	.tpvalid_polarity       = LGDT3306A_TP_VALID_HIGH,
83*4882a593Smuzhiyun 	.xtalMHz                = 25, /* 24 or 25 */
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static struct lgdt3306a_config hauppauge_hvr2255b_config = {
87*4882a593Smuzhiyun 	.i2c_addr               = 0x1c >> 1,
88*4882a593Smuzhiyun 	.qam_if_khz             = 4000,
89*4882a593Smuzhiyun 	.vsb_if_khz             = 3250,
90*4882a593Smuzhiyun 	.deny_i2c_rptr          = 1, /* Disabled */
91*4882a593Smuzhiyun 	.spectral_inversion     = 0, /* Disabled */
92*4882a593Smuzhiyun 	.mpeg_mode              = LGDT3306A_MPEG_SERIAL,
93*4882a593Smuzhiyun 	.tpclk_edge             = LGDT3306A_TPCLK_RISING_EDGE,
94*4882a593Smuzhiyun 	.tpvalid_polarity       = LGDT3306A_TP_VALID_HIGH,
95*4882a593Smuzhiyun 	.xtalMHz                = 25, /* 24 or 25 */
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static struct si2157_config hauppauge_hvr2255_tuner_config = {
99*4882a593Smuzhiyun 	.inversion = 1,
100*4882a593Smuzhiyun 	.if_port = 1,
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun 
si2157_attach(struct saa7164_port * port,struct i2c_adapter * adapter,struct dvb_frontend * fe,u8 addr8bit,struct si2157_config * cfg)103*4882a593Smuzhiyun static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter,
104*4882a593Smuzhiyun 	struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	struct i2c_board_info bi;
107*4882a593Smuzhiyun 	struct i2c_client *tuner;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	cfg->fe = fe;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	memset(&bi, 0, sizeof(bi));
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	strscpy(bi.type, "si2157", I2C_NAME_SIZE);
114*4882a593Smuzhiyun 	bi.platform_data = cfg;
115*4882a593Smuzhiyun 	bi.addr = addr8bit >> 1;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	request_module(bi.type);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	tuner = i2c_new_client_device(adapter, &bi);
120*4882a593Smuzhiyun 	if (!i2c_client_has_driver(tuner))
121*4882a593Smuzhiyun 		return -ENODEV;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	if (!try_module_get(tuner->dev.driver->owner)) {
124*4882a593Smuzhiyun 		i2c_unregister_device(tuner);
125*4882a593Smuzhiyun 		return -ENODEV;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	port->i2c_client_tuner = tuner;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
saa7164_dvb_stop_port(struct saa7164_port * port)133*4882a593Smuzhiyun static int saa7164_dvb_stop_port(struct saa7164_port *port)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
136*4882a593Smuzhiyun 	int ret;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
139*4882a593Smuzhiyun 	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
140*4882a593Smuzhiyun 		printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
141*4882a593Smuzhiyun 			__func__, ret);
142*4882a593Smuzhiyun 		ret = -EIO;
143*4882a593Smuzhiyun 	} else {
144*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s()    Stopped\n", __func__);
145*4882a593Smuzhiyun 		ret = 0;
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	return ret;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
saa7164_dvb_acquire_port(struct saa7164_port * port)151*4882a593Smuzhiyun static int saa7164_dvb_acquire_port(struct saa7164_port *port)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
154*4882a593Smuzhiyun 	int ret;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
157*4882a593Smuzhiyun 	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
158*4882a593Smuzhiyun 		printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
159*4882a593Smuzhiyun 			__func__, ret);
160*4882a593Smuzhiyun 		ret = -EIO;
161*4882a593Smuzhiyun 	} else {
162*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s() Acquired\n", __func__);
163*4882a593Smuzhiyun 		ret = 0;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return ret;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
saa7164_dvb_pause_port(struct saa7164_port * port)169*4882a593Smuzhiyun static int saa7164_dvb_pause_port(struct saa7164_port *port)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
172*4882a593Smuzhiyun 	int ret;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
175*4882a593Smuzhiyun 	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
176*4882a593Smuzhiyun 		printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
177*4882a593Smuzhiyun 			__func__, ret);
178*4882a593Smuzhiyun 		ret = -EIO;
179*4882a593Smuzhiyun 	} else {
180*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
181*4882a593Smuzhiyun 		ret = 0;
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	return ret;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* Firmware is very windows centric, meaning you have to transition
188*4882a593Smuzhiyun  * the part through AVStream / KS Windows stages, forwards or backwards.
189*4882a593Smuzhiyun  * States are: stopped, acquired (h/w), paused, started.
190*4882a593Smuzhiyun  */
saa7164_dvb_stop_streaming(struct saa7164_port * port)191*4882a593Smuzhiyun static int saa7164_dvb_stop_streaming(struct saa7164_port *port)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
194*4882a593Smuzhiyun 	struct saa7164_buffer *buf;
195*4882a593Smuzhiyun 	struct list_head *p, *q;
196*4882a593Smuzhiyun 	int ret;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	ret = saa7164_dvb_pause_port(port);
201*4882a593Smuzhiyun 	ret = saa7164_dvb_acquire_port(port);
202*4882a593Smuzhiyun 	ret = saa7164_dvb_stop_port(port);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	/* Mark the hardware buffers as free */
205*4882a593Smuzhiyun 	mutex_lock(&port->dmaqueue_lock);
206*4882a593Smuzhiyun 	list_for_each_safe(p, q, &port->dmaqueue.list) {
207*4882a593Smuzhiyun 		buf = list_entry(p, struct saa7164_buffer, list);
208*4882a593Smuzhiyun 		buf->flags = SAA7164_BUFFER_FREE;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 	mutex_unlock(&port->dmaqueue_lock);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	return ret;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
saa7164_dvb_start_port(struct saa7164_port * port)215*4882a593Smuzhiyun static int saa7164_dvb_start_port(struct saa7164_port *port)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
218*4882a593Smuzhiyun 	int ret = 0, result;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	saa7164_buffer_cfg_port(port);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	/* Acquire the hardware */
225*4882a593Smuzhiyun 	result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
226*4882a593Smuzhiyun 	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
227*4882a593Smuzhiyun 		printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
228*4882a593Smuzhiyun 			__func__, result);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 		/* Stop the hardware, regardless */
231*4882a593Smuzhiyun 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
232*4882a593Smuzhiyun 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
233*4882a593Smuzhiyun 			printk(KERN_ERR "%s() acquire/forced stop transition failed, res = 0x%x\n",
234*4882a593Smuzhiyun 			       __func__, result);
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun 		ret = -EIO;
237*4882a593Smuzhiyun 		goto out;
238*4882a593Smuzhiyun 	} else
239*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s()   Acquired\n", __func__);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	/* Pause the hardware */
242*4882a593Smuzhiyun 	result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
243*4882a593Smuzhiyun 	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
244*4882a593Smuzhiyun 		printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
245*4882a593Smuzhiyun 				__func__, result);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 		/* Stop the hardware, regardless */
248*4882a593Smuzhiyun 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
249*4882a593Smuzhiyun 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
250*4882a593Smuzhiyun 			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
251*4882a593Smuzhiyun 			       __func__, result);
252*4882a593Smuzhiyun 		}
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 		ret = -EIO;
255*4882a593Smuzhiyun 		goto out;
256*4882a593Smuzhiyun 	} else
257*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	/* Start the hardware */
260*4882a593Smuzhiyun 	result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
261*4882a593Smuzhiyun 	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
262*4882a593Smuzhiyun 		printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
263*4882a593Smuzhiyun 				__func__, result);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 		/* Stop the hardware, regardless */
266*4882a593Smuzhiyun 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
267*4882a593Smuzhiyun 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
268*4882a593Smuzhiyun 			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
269*4882a593Smuzhiyun 			       __func__, result);
270*4882a593Smuzhiyun 		}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 		ret = -EIO;
273*4882a593Smuzhiyun 	} else
274*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s()   Running\n", __func__);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun out:
277*4882a593Smuzhiyun 	return ret;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
saa7164_dvb_start_feed(struct dvb_demux_feed * feed)280*4882a593Smuzhiyun static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct dvb_demux *demux = feed->demux;
283*4882a593Smuzhiyun 	struct saa7164_port *port = (struct saa7164_port *) demux->priv;
284*4882a593Smuzhiyun 	struct saa7164_dvb *dvb = &port->dvb;
285*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
286*4882a593Smuzhiyun 	int ret = 0;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	if (!demux->dmx.frontend)
291*4882a593Smuzhiyun 		return -EINVAL;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (dvb) {
294*4882a593Smuzhiyun 		mutex_lock(&dvb->lock);
295*4882a593Smuzhiyun 		if (dvb->feeding++ == 0) {
296*4882a593Smuzhiyun 			/* Start transport */
297*4882a593Smuzhiyun 			ret = saa7164_dvb_start_port(port);
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 		mutex_unlock(&dvb->lock);
300*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
301*4882a593Smuzhiyun 			__func__, port->nr, dvb->feeding);
302*4882a593Smuzhiyun 	}
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return ret;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
saa7164_dvb_stop_feed(struct dvb_demux_feed * feed)307*4882a593Smuzhiyun static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	struct dvb_demux *demux = feed->demux;
310*4882a593Smuzhiyun 	struct saa7164_port *port = (struct saa7164_port *) demux->priv;
311*4882a593Smuzhiyun 	struct saa7164_dvb *dvb = &port->dvb;
312*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
313*4882a593Smuzhiyun 	int ret = 0;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	if (dvb) {
318*4882a593Smuzhiyun 		mutex_lock(&dvb->lock);
319*4882a593Smuzhiyun 		if (--dvb->feeding == 0) {
320*4882a593Smuzhiyun 			/* Stop transport */
321*4882a593Smuzhiyun 			ret = saa7164_dvb_stop_streaming(port);
322*4882a593Smuzhiyun 		}
323*4882a593Smuzhiyun 		mutex_unlock(&dvb->lock);
324*4882a593Smuzhiyun 		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
325*4882a593Smuzhiyun 			__func__, port->nr, dvb->feeding);
326*4882a593Smuzhiyun 	}
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	return ret;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
dvb_register(struct saa7164_port * port)331*4882a593Smuzhiyun static int dvb_register(struct saa7164_port *port)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	struct saa7164_dvb *dvb = &port->dvb;
334*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
335*4882a593Smuzhiyun 	struct saa7164_buffer *buf;
336*4882a593Smuzhiyun 	int result, i;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	BUG_ON(port->type != SAA7164_MPEG_DVB);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	/* Sanity check that the PCI configuration space is active */
343*4882a593Smuzhiyun 	if (port->hwcfg.BARLocation == 0) {
344*4882a593Smuzhiyun 		result = -ENOMEM;
345*4882a593Smuzhiyun 		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), NO PCI configuration\n",
346*4882a593Smuzhiyun 			DRIVER_NAME, result);
347*4882a593Smuzhiyun 		goto fail_adapter;
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	/* Init and establish defaults */
351*4882a593Smuzhiyun 	port->hw_streamingparams.bitspersample = 8;
352*4882a593Smuzhiyun 	port->hw_streamingparams.samplesperline = 188;
353*4882a593Smuzhiyun 	port->hw_streamingparams.numberoflines =
354*4882a593Smuzhiyun 		(SAA7164_TS_NUMBER_OF_LINES * 188) / 188;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	port->hw_streamingparams.pitch = 188;
357*4882a593Smuzhiyun 	port->hw_streamingparams.linethreshold = 0;
358*4882a593Smuzhiyun 	port->hw_streamingparams.pagetablelistvirt = NULL;
359*4882a593Smuzhiyun 	port->hw_streamingparams.pagetablelistphys = NULL;
360*4882a593Smuzhiyun 	port->hw_streamingparams.numpagetables = 2 +
361*4882a593Smuzhiyun 		((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	/* Allocate the PCI resources */
366*4882a593Smuzhiyun 	for (i = 0; i < port->hwcfg.buffercount; i++) {
367*4882a593Smuzhiyun 		buf = saa7164_buffer_alloc(port,
368*4882a593Smuzhiyun 			port->hw_streamingparams.numberoflines *
369*4882a593Smuzhiyun 			port->hw_streamingparams.pitch);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		if (!buf) {
372*4882a593Smuzhiyun 			result = -ENOMEM;
373*4882a593Smuzhiyun 			printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), unable to allocate buffers\n",
374*4882a593Smuzhiyun 				DRIVER_NAME, result);
375*4882a593Smuzhiyun 			goto fail_adapter;
376*4882a593Smuzhiyun 		}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 		mutex_lock(&port->dmaqueue_lock);
379*4882a593Smuzhiyun 		list_add_tail(&buf->list, &port->dmaqueue.list);
380*4882a593Smuzhiyun 		mutex_unlock(&port->dmaqueue_lock);
381*4882a593Smuzhiyun 	}
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	/* register adapter */
384*4882a593Smuzhiyun 	result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
385*4882a593Smuzhiyun 			&dev->pci->dev, adapter_nr);
386*4882a593Smuzhiyun 	if (result < 0) {
387*4882a593Smuzhiyun 		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d)\n",
388*4882a593Smuzhiyun 		       DRIVER_NAME, result);
389*4882a593Smuzhiyun 		goto fail_adapter;
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 	dvb->adapter.priv = port;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	/* register frontend */
394*4882a593Smuzhiyun 	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
395*4882a593Smuzhiyun 	if (result < 0) {
396*4882a593Smuzhiyun 		printk(KERN_ERR "%s: dvb_register_frontend failed (errno = %d)\n",
397*4882a593Smuzhiyun 		       DRIVER_NAME, result);
398*4882a593Smuzhiyun 		goto fail_frontend;
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	/* register demux stuff */
402*4882a593Smuzhiyun 	dvb->demux.dmx.capabilities =
403*4882a593Smuzhiyun 		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
404*4882a593Smuzhiyun 		DMX_MEMORY_BASED_FILTERING;
405*4882a593Smuzhiyun 	dvb->demux.priv       = port;
406*4882a593Smuzhiyun 	dvb->demux.filternum  = 256;
407*4882a593Smuzhiyun 	dvb->demux.feednum    = 256;
408*4882a593Smuzhiyun 	dvb->demux.start_feed = saa7164_dvb_start_feed;
409*4882a593Smuzhiyun 	dvb->demux.stop_feed  = saa7164_dvb_stop_feed;
410*4882a593Smuzhiyun 	result = dvb_dmx_init(&dvb->demux);
411*4882a593Smuzhiyun 	if (result < 0) {
412*4882a593Smuzhiyun 		printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
413*4882a593Smuzhiyun 		       DRIVER_NAME, result);
414*4882a593Smuzhiyun 		goto fail_dmx;
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	dvb->dmxdev.filternum    = 256;
418*4882a593Smuzhiyun 	dvb->dmxdev.demux        = &dvb->demux.dmx;
419*4882a593Smuzhiyun 	dvb->dmxdev.capabilities = 0;
420*4882a593Smuzhiyun 	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
421*4882a593Smuzhiyun 	if (result < 0) {
422*4882a593Smuzhiyun 		printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
423*4882a593Smuzhiyun 		       DRIVER_NAME, result);
424*4882a593Smuzhiyun 		goto fail_dmxdev;
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	dvb->fe_hw.source = DMX_FRONTEND_0;
428*4882a593Smuzhiyun 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
429*4882a593Smuzhiyun 	if (result < 0) {
430*4882a593Smuzhiyun 		printk(KERN_ERR "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
431*4882a593Smuzhiyun 		       DRIVER_NAME, result);
432*4882a593Smuzhiyun 		goto fail_fe_hw;
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	dvb->fe_mem.source = DMX_MEMORY_FE;
436*4882a593Smuzhiyun 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
437*4882a593Smuzhiyun 	if (result < 0) {
438*4882a593Smuzhiyun 		printk(KERN_ERR "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
439*4882a593Smuzhiyun 		       DRIVER_NAME, result);
440*4882a593Smuzhiyun 		goto fail_fe_mem;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
444*4882a593Smuzhiyun 	if (result < 0) {
445*4882a593Smuzhiyun 		printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
446*4882a593Smuzhiyun 		       DRIVER_NAME, result);
447*4882a593Smuzhiyun 		goto fail_fe_conn;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	/* register network adapter */
451*4882a593Smuzhiyun 	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun fail_fe_conn:
455*4882a593Smuzhiyun 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
456*4882a593Smuzhiyun fail_fe_mem:
457*4882a593Smuzhiyun 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
458*4882a593Smuzhiyun fail_fe_hw:
459*4882a593Smuzhiyun 	dvb_dmxdev_release(&dvb->dmxdev);
460*4882a593Smuzhiyun fail_dmxdev:
461*4882a593Smuzhiyun 	dvb_dmx_release(&dvb->demux);
462*4882a593Smuzhiyun fail_dmx:
463*4882a593Smuzhiyun 	dvb_unregister_frontend(dvb->frontend);
464*4882a593Smuzhiyun fail_frontend:
465*4882a593Smuzhiyun 	dvb_frontend_detach(dvb->frontend);
466*4882a593Smuzhiyun 	dvb_unregister_adapter(&dvb->adapter);
467*4882a593Smuzhiyun fail_adapter:
468*4882a593Smuzhiyun 	return result;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
saa7164_dvb_unregister(struct saa7164_port * port)471*4882a593Smuzhiyun int saa7164_dvb_unregister(struct saa7164_port *port)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	struct saa7164_dvb *dvb = &port->dvb;
474*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
475*4882a593Smuzhiyun 	struct saa7164_buffer *b;
476*4882a593Smuzhiyun 	struct list_head *c, *n;
477*4882a593Smuzhiyun 	struct i2c_client *client;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s()\n", __func__);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	BUG_ON(port->type != SAA7164_MPEG_DVB);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	/* Remove any allocated buffers */
484*4882a593Smuzhiyun 	mutex_lock(&port->dmaqueue_lock);
485*4882a593Smuzhiyun 	list_for_each_safe(c, n, &port->dmaqueue.list) {
486*4882a593Smuzhiyun 		b = list_entry(c, struct saa7164_buffer, list);
487*4882a593Smuzhiyun 		list_del(c);
488*4882a593Smuzhiyun 		saa7164_buffer_dealloc(b);
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 	mutex_unlock(&port->dmaqueue_lock);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (dvb->frontend == NULL)
493*4882a593Smuzhiyun 		return 0;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	/* remove I2C client for tuner */
496*4882a593Smuzhiyun 	client = port->i2c_client_tuner;
497*4882a593Smuzhiyun 	if (client) {
498*4882a593Smuzhiyun 		module_put(client->dev.driver->owner);
499*4882a593Smuzhiyun 		i2c_unregister_device(client);
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	/* remove I2C client for demodulator */
503*4882a593Smuzhiyun 	client = port->i2c_client_demod;
504*4882a593Smuzhiyun 	if (client) {
505*4882a593Smuzhiyun 		module_put(client->dev.driver->owner);
506*4882a593Smuzhiyun 		i2c_unregister_device(client);
507*4882a593Smuzhiyun 	}
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	dvb_net_release(&dvb->net);
510*4882a593Smuzhiyun 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
511*4882a593Smuzhiyun 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
512*4882a593Smuzhiyun 	dvb_dmxdev_release(&dvb->dmxdev);
513*4882a593Smuzhiyun 	dvb_dmx_release(&dvb->demux);
514*4882a593Smuzhiyun 	dvb_unregister_frontend(dvb->frontend);
515*4882a593Smuzhiyun 	dvb_frontend_detach(dvb->frontend);
516*4882a593Smuzhiyun 	dvb_unregister_adapter(&dvb->adapter);
517*4882a593Smuzhiyun 	return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun /* All the DVB attach calls go here, this function gets modified
521*4882a593Smuzhiyun  * for each new card.
522*4882a593Smuzhiyun  */
saa7164_dvb_register(struct saa7164_port * port)523*4882a593Smuzhiyun int saa7164_dvb_register(struct saa7164_port *port)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun 	struct saa7164_dev *dev = port->dev;
526*4882a593Smuzhiyun 	struct saa7164_dvb *dvb = &port->dvb;
527*4882a593Smuzhiyun 	struct saa7164_i2c *i2c_bus = NULL;
528*4882a593Smuzhiyun 	struct si2168_config si2168_config;
529*4882a593Smuzhiyun 	struct si2157_config si2157_config;
530*4882a593Smuzhiyun 	struct i2c_adapter *adapter;
531*4882a593Smuzhiyun 	struct i2c_board_info info;
532*4882a593Smuzhiyun 	struct i2c_client *client_demod;
533*4882a593Smuzhiyun 	struct i2c_client *client_tuner;
534*4882a593Smuzhiyun 	int ret;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	dprintk(DBGLVL_DVB, "%s()\n", __func__);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	/* init frontend */
539*4882a593Smuzhiyun 	switch (dev->board) {
540*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
541*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
542*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
543*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
544*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
545*4882a593Smuzhiyun 		i2c_bus = &dev->i2c_bus[port->nr + 1];
546*4882a593Smuzhiyun 		switch (port->nr) {
547*4882a593Smuzhiyun 		case 0:
548*4882a593Smuzhiyun 			port->dvb.frontend = dvb_attach(tda10048_attach,
549*4882a593Smuzhiyun 				&hauppauge_hvr2200_1_config,
550*4882a593Smuzhiyun 				&i2c_bus->i2c_adap);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 			if (port->dvb.frontend != NULL) {
553*4882a593Smuzhiyun 				/* TODO: addr is in the card struct */
554*4882a593Smuzhiyun 				dvb_attach(tda18271_attach, port->dvb.frontend,
555*4882a593Smuzhiyun 					0xc0 >> 1, &i2c_bus->i2c_adap,
556*4882a593Smuzhiyun 					&hauppauge_hvr22x0_tuner_config);
557*4882a593Smuzhiyun 			}
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 			break;
560*4882a593Smuzhiyun 		case 1:
561*4882a593Smuzhiyun 			port->dvb.frontend = dvb_attach(tda10048_attach,
562*4882a593Smuzhiyun 				&hauppauge_hvr2200_2_config,
563*4882a593Smuzhiyun 				&i2c_bus->i2c_adap);
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 			if (port->dvb.frontend != NULL) {
566*4882a593Smuzhiyun 				/* TODO: addr is in the card struct */
567*4882a593Smuzhiyun 				dvb_attach(tda18271_attach, port->dvb.frontend,
568*4882a593Smuzhiyun 					0xc0 >> 1, &i2c_bus->i2c_adap,
569*4882a593Smuzhiyun 					&hauppauge_hvr22x0s_tuner_config);
570*4882a593Smuzhiyun 			}
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 			break;
573*4882a593Smuzhiyun 		}
574*4882a593Smuzhiyun 		break;
575*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
576*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
577*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
578*4882a593Smuzhiyun 		i2c_bus = &dev->i2c_bus[port->nr + 1];
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 		port->dvb.frontend = dvb_attach(s5h1411_attach,
581*4882a593Smuzhiyun 			&hauppauge_s5h1411_config,
582*4882a593Smuzhiyun 			&i2c_bus->i2c_adap);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 		if (port->dvb.frontend != NULL) {
585*4882a593Smuzhiyun 			if (port->nr == 0) {
586*4882a593Smuzhiyun 				/* Master TDA18271 */
587*4882a593Smuzhiyun 				/* TODO: addr is in the card struct */
588*4882a593Smuzhiyun 				dvb_attach(tda18271_attach, port->dvb.frontend,
589*4882a593Smuzhiyun 					0xc0 >> 1, &i2c_bus->i2c_adap,
590*4882a593Smuzhiyun 					&hauppauge_hvr22x0_tuner_config);
591*4882a593Smuzhiyun 			} else {
592*4882a593Smuzhiyun 				/* Slave TDA18271 */
593*4882a593Smuzhiyun 				dvb_attach(tda18271_attach, port->dvb.frontend,
594*4882a593Smuzhiyun 					0xc0 >> 1, &i2c_bus->i2c_adap,
595*4882a593Smuzhiyun 					&hauppauge_hvr22x0s_tuner_config);
596*4882a593Smuzhiyun 			}
597*4882a593Smuzhiyun 		}
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 		break;
600*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
601*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2255:
602*4882a593Smuzhiyun 		i2c_bus = &dev->i2c_bus[2];
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 		if (port->nr == 0) {
605*4882a593Smuzhiyun 			port->dvb.frontend = dvb_attach(lgdt3306a_attach,
606*4882a593Smuzhiyun 				&hauppauge_hvr2255a_config, &i2c_bus->i2c_adap);
607*4882a593Smuzhiyun 		} else {
608*4882a593Smuzhiyun 			port->dvb.frontend = dvb_attach(lgdt3306a_attach,
609*4882a593Smuzhiyun 				&hauppauge_hvr2255b_config, &i2c_bus->i2c_adap);
610*4882a593Smuzhiyun 		}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 		if (port->dvb.frontend != NULL) {
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 			if (port->nr == 0) {
615*4882a593Smuzhiyun 				si2157_attach(port, &dev->i2c_bus[0].i2c_adap,
616*4882a593Smuzhiyun 					      port->dvb.frontend, 0xc0,
617*4882a593Smuzhiyun 					      &hauppauge_hvr2255_tuner_config);
618*4882a593Smuzhiyun 			} else {
619*4882a593Smuzhiyun 				si2157_attach(port, &dev->i2c_bus[1].i2c_adap,
620*4882a593Smuzhiyun 					      port->dvb.frontend, 0xc0,
621*4882a593Smuzhiyun 					      &hauppauge_hvr2255_tuner_config);
622*4882a593Smuzhiyun 			}
623*4882a593Smuzhiyun 		}
624*4882a593Smuzhiyun 		break;
625*4882a593Smuzhiyun 	case SAA7164_BOARD_HAUPPAUGE_HVR2205:
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 		if (port->nr == 0) {
628*4882a593Smuzhiyun 			/* attach frontend */
629*4882a593Smuzhiyun 			memset(&si2168_config, 0, sizeof(si2168_config));
630*4882a593Smuzhiyun 			si2168_config.i2c_adapter = &adapter;
631*4882a593Smuzhiyun 			si2168_config.fe = &port->dvb.frontend;
632*4882a593Smuzhiyun 			si2168_config.ts_mode = SI2168_TS_SERIAL;
633*4882a593Smuzhiyun 			memset(&info, 0, sizeof(struct i2c_board_info));
634*4882a593Smuzhiyun 			strscpy(info.type, "si2168", I2C_NAME_SIZE);
635*4882a593Smuzhiyun 			info.addr = 0xc8 >> 1;
636*4882a593Smuzhiyun 			info.platform_data = &si2168_config;
637*4882a593Smuzhiyun 			request_module(info.type);
638*4882a593Smuzhiyun 			client_demod = i2c_new_client_device(&dev->i2c_bus[2].i2c_adap, &info);
639*4882a593Smuzhiyun 			if (!i2c_client_has_driver(client_demod))
640*4882a593Smuzhiyun 				goto frontend_detach;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 			if (!try_module_get(client_demod->dev.driver->owner)) {
643*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
644*4882a593Smuzhiyun 				goto frontend_detach;
645*4882a593Smuzhiyun 			}
646*4882a593Smuzhiyun 			port->i2c_client_demod = client_demod;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 			/* attach tuner */
649*4882a593Smuzhiyun 			memset(&si2157_config, 0, sizeof(si2157_config));
650*4882a593Smuzhiyun 			si2157_config.if_port = 1;
651*4882a593Smuzhiyun 			si2157_config.fe = port->dvb.frontend;
652*4882a593Smuzhiyun 			memset(&info, 0, sizeof(struct i2c_board_info));
653*4882a593Smuzhiyun 			strscpy(info.type, "si2157", I2C_NAME_SIZE);
654*4882a593Smuzhiyun 			info.addr = 0xc0 >> 1;
655*4882a593Smuzhiyun 			info.platform_data = &si2157_config;
656*4882a593Smuzhiyun 			request_module(info.type);
657*4882a593Smuzhiyun 			client_tuner = i2c_new_client_device(&dev->i2c_bus[0].i2c_adap, &info);
658*4882a593Smuzhiyun 			if (!i2c_client_has_driver(client_tuner)) {
659*4882a593Smuzhiyun 				module_put(client_demod->dev.driver->owner);
660*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
661*4882a593Smuzhiyun 				goto frontend_detach;
662*4882a593Smuzhiyun 			}
663*4882a593Smuzhiyun 			if (!try_module_get(client_tuner->dev.driver->owner)) {
664*4882a593Smuzhiyun 				i2c_unregister_device(client_tuner);
665*4882a593Smuzhiyun 				module_put(client_demod->dev.driver->owner);
666*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
667*4882a593Smuzhiyun 				goto frontend_detach;
668*4882a593Smuzhiyun 			}
669*4882a593Smuzhiyun 			port->i2c_client_tuner = client_tuner;
670*4882a593Smuzhiyun 		} else {
671*4882a593Smuzhiyun 			/* attach frontend */
672*4882a593Smuzhiyun 			memset(&si2168_config, 0, sizeof(si2168_config));
673*4882a593Smuzhiyun 			si2168_config.i2c_adapter = &adapter;
674*4882a593Smuzhiyun 			si2168_config.fe = &port->dvb.frontend;
675*4882a593Smuzhiyun 			si2168_config.ts_mode = SI2168_TS_SERIAL;
676*4882a593Smuzhiyun 			memset(&info, 0, sizeof(struct i2c_board_info));
677*4882a593Smuzhiyun 			strscpy(info.type, "si2168", I2C_NAME_SIZE);
678*4882a593Smuzhiyun 			info.addr = 0xcc >> 1;
679*4882a593Smuzhiyun 			info.platform_data = &si2168_config;
680*4882a593Smuzhiyun 			request_module(info.type);
681*4882a593Smuzhiyun 			client_demod = i2c_new_client_device(&dev->i2c_bus[2].i2c_adap, &info);
682*4882a593Smuzhiyun 			if (!i2c_client_has_driver(client_demod))
683*4882a593Smuzhiyun 				goto frontend_detach;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 			if (!try_module_get(client_demod->dev.driver->owner)) {
686*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
687*4882a593Smuzhiyun 				goto frontend_detach;
688*4882a593Smuzhiyun 			}
689*4882a593Smuzhiyun 			port->i2c_client_demod = client_demod;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 			/* attach tuner */
692*4882a593Smuzhiyun 			memset(&si2157_config, 0, sizeof(si2157_config));
693*4882a593Smuzhiyun 			si2157_config.fe = port->dvb.frontend;
694*4882a593Smuzhiyun 			si2157_config.if_port = 1;
695*4882a593Smuzhiyun 			memset(&info, 0, sizeof(struct i2c_board_info));
696*4882a593Smuzhiyun 			strscpy(info.type, "si2157", I2C_NAME_SIZE);
697*4882a593Smuzhiyun 			info.addr = 0xc0 >> 1;
698*4882a593Smuzhiyun 			info.platform_data = &si2157_config;
699*4882a593Smuzhiyun 			request_module(info.type);
700*4882a593Smuzhiyun 			client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
701*4882a593Smuzhiyun 			if (!i2c_client_has_driver(client_tuner)) {
702*4882a593Smuzhiyun 				module_put(client_demod->dev.driver->owner);
703*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
704*4882a593Smuzhiyun 				goto frontend_detach;
705*4882a593Smuzhiyun 			}
706*4882a593Smuzhiyun 			if (!try_module_get(client_tuner->dev.driver->owner)) {
707*4882a593Smuzhiyun 				i2c_unregister_device(client_tuner);
708*4882a593Smuzhiyun 				module_put(client_demod->dev.driver->owner);
709*4882a593Smuzhiyun 				i2c_unregister_device(client_demod);
710*4882a593Smuzhiyun 				goto frontend_detach;
711*4882a593Smuzhiyun 			}
712*4882a593Smuzhiyun 			port->i2c_client_tuner = client_tuner;
713*4882a593Smuzhiyun 		}
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 		break;
716*4882a593Smuzhiyun 	default:
717*4882a593Smuzhiyun 		printk(KERN_ERR "%s: The frontend isn't supported\n",
718*4882a593Smuzhiyun 		       dev->name);
719*4882a593Smuzhiyun 		break;
720*4882a593Smuzhiyun 	}
721*4882a593Smuzhiyun 	if (NULL == dvb->frontend) {
722*4882a593Smuzhiyun 		printk(KERN_ERR "%s() Frontend initialization failed\n",
723*4882a593Smuzhiyun 		       __func__);
724*4882a593Smuzhiyun 		return -1;
725*4882a593Smuzhiyun 	}
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	/* register everything */
728*4882a593Smuzhiyun 	ret = dvb_register(port);
729*4882a593Smuzhiyun 	if (ret < 0) {
730*4882a593Smuzhiyun 		if (dvb->frontend->ops.release)
731*4882a593Smuzhiyun 			dvb->frontend->ops.release(dvb->frontend);
732*4882a593Smuzhiyun 		return ret;
733*4882a593Smuzhiyun 	}
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	return 0;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun frontend_detach:
738*4882a593Smuzhiyun 	printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__);
739*4882a593Smuzhiyun 	return -1;
740*4882a593Smuzhiyun }
741