tda8290.c revision ab1660503ac3af7febfcf987648509b484d4feda
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
3de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   i2c tv tuner chip device driver
4de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   controls the philips tda8290+75 tuner chip combo.
5de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
6de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   This program is free software; you can redistribute it and/or modify
7de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   it under the terms of the GNU General Public License as published by
8de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   the Free Software Foundation; either version 2 of the License, or
9de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   (at your option) any later version.
10de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
11de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   This program is distributed in the hope that it will be useful,
12de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   but WITHOUT ANY WARRANTY; without even the implied warranty of
13de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   GNU General Public License for more details.
15de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
16de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   You should have received a copy of the GNU General Public License
17de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   along with this program; if not, write to the Free Software
18de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
20910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky   This "tda8290" module was split apart from the original "tuner" module.
21de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann*/
22de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
25ffbb807c1362a2b64b473c0e093c496a4c7de4bbMichael Krufky#include <linux/videodev.h>
26ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky#include "tuner-driver.h"
27ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky#include "tuner-i2c.h"
28910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky#include "tda8290.h"
29746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky#include "tda827x.h"
305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky#include "tda18271.h"
31910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
32ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkystatic int debug;
33ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkymodule_param(debug, int, 0644);
34910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael KrufkyMODULE_PARM_DESC(debug, "enable verbose debug messages");
35910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
369dd659de9fbd1687c6175053c6453db5b932f152Hans Verkuil#define PREFIX "tda8290"
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---------------------------------------------------------------------- */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufkystruct tda8290_priv {
41db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	struct tuner_i2c_props i2c_props;
42db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
43b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char tda8290_easy_mode;
44746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
45b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char tda827x_addr;
468c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
478c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	unsigned char ver;
488c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8290   1
498c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8295   2
508c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8275   4
518c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8275A  8
528c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA18271 16
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	struct tda827x_config cfg;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufkystatic int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
60de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
614e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
62db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
63de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char  enable[2] = { 0x21, 0xC0 };
640157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char disable[2] = { 0x21, 0x00 };
65de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char *msg;
66a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
67a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	if (close) {
68de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg = enable;
69db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
70de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		/* let the bridge stabilize */
71de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msleep(20);
72de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	} else {
73de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg = disable;
74db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
75de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
76a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
77a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	return 0;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufkystatic int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
824e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char  enable[2] = { 0x45, 0xc1 };
855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char disable[2] = { 0x46, 0x00 };
865bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[3] = { 0x45, 0x01, 0x00 };
875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char *msg;
88a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
895bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (close) {
905bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg = enable;
915bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		/* let the bridge stabilize */
935bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msleep(20);
945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	} else {
955bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg = disable;
965bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] = msg[1];
1005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] &= ~0x04;
1015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
1025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msleep(5);
1035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
1045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg[1] |= 0x04;
1055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
1065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
107a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
108a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	return 0;
1095bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
1105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
111de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
112de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
113c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void set_audio(struct dvb_frontend *fe,
114c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		      struct analog_parameters *params)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1164e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
117910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	char* mode;
118910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
119c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	if (params->std & V4L2_STD_MN) {
120910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x01;
121910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "MN";
122c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_B) {
123910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x02;
124910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "B";
125c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_GH) {
126910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x04;
127910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "GH";
128c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_PAL_I) {
129910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x08;
130910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "I";
131c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_DK) {
132910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
133910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "DK";
134c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_L) {
135910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x20;
136910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "L";
137c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_LC) {
138910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x40;
139910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "LC";
140910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	} else {
141910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
142910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "xx";
143910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	}
144910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
1458c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	tuner_dbg("setting tda829x to system %s\n", mode);
146910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
147910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
148c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8290_set_params(struct dvb_frontend *fe,
149c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
150910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky{
1514e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
1524e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
153de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char soft_reset[]  = { 0x00, 0x00 };
154b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };
155de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char expert_mode[] = { 0x01, 0x80 };
1560157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char agc_out_on[]  = { 0x02, 0x00 };
157de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_off[] = { 0x28, 0x14 };
158de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_spd[]  = { 0x0f, 0x88 };
159de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_6[]  = { 0x05, 0x04 };
160de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_9[]  = { 0x05, 0x02 };
161de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_12[] = { 0x05, 0x01 };
162de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };
163de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_low[]  = { 0x0d, 0x27 };
164de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_2[]   = { 0x28, 0x64 };
165de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_on[]  = { 0x0e, 0x0b };
166de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_off[] = { 0x0e, 0x09 };
167de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_set[]  = { 0x0f, 0x81 };
168de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_adc_sat  = 0x1a;
169de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_agc_stat = 0x1d;
170de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_pll_stat = 0x1b;
171de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_sat, agc_stat,
1729a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev		      pll_stat;
17358ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	int i;
174de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
175c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
176910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
177ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	if (priv->cfg.config)
178ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config);
179db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
180db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
181db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
182de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msleep(1);
183de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
184b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	expert_mode[1] = priv->tda8290_easy_mode + 0x80;
185db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
186db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
187db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
188b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	if (priv->tda8290_easy_mode & 0x60)
189db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
190de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	else
191db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
192db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
193de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
1944e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
195746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
1964e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.set_analog_params)
197c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		fe->ops.tuner_ops.set_analog_params(fe, params);
198746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
19958ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	for (i = 0; i < 3; i++) {
200db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
201db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
20258ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		if (pll_stat & 0x80) {
203db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
204db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
205db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
206db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
20758ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
20858ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			break;
20958ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		} else {
21058ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 not locked, no signal?\n");
21158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			msleep(100);
21258ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		}
21358ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	}
214de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* adjust headroom resp. gain */
2154ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
2164ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
2174ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			   agc_stat, adc_sat, pll_stat & 0x80);
218db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
219de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msleep(100);
220db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
221db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
222db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
223db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
224de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
2254ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
2264ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann				   agc_stat, pll_stat & 0x80);
227746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky			if (priv->cfg.agcf)
2284e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky				priv->cfg.agcf(fe);
229de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(100);
230db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
231db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
232db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
233db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
234de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			if((agc_stat > 115) || !(pll_stat & 0x80)) {
235de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
236db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
237db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
238de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				msleep(100);
239de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			}
240de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
241de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
243de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* l/ l' deadlock? */
244b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	if(priv->tda8290_easy_mode & 0x60) {
245db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
246db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
247db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
248db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
249de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
2504ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("trying to resolve SECAM L deadlock\n");
251db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
252de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(40);
253db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
254de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
255de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
256586b0cab2516640fec4dffc3049c4d8bca188f89Mauro Carvalho Chehab
2574e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
258db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
262de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
2634e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_power(struct dvb_frontend *fe, int enable)
2645bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
2654e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
2665bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
2675bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2685bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
2695bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
2705bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2715bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
2725bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01;
2735bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
2745bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x03;
2755bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
2775bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
2785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2794e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
2805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
2814e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
2825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x01, 0x00 };
2835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
2855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
2865bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
2885bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
2895bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
2905bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x00; /* reset active bit */
2915bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
2935bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
2945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
2954e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_video_std(struct dvb_frontend *fe)
2965bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
2974e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
2985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
2995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3024e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 1);
3035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
3044e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
3055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
3085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3094e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
3105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3114e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
3135bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3145bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
3155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
3165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] &= ~0x40;
3195bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] |= 0x40;
3215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3235bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3254e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
3265bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3274e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3285bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
3295bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
3305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3315bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
3325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
3335bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
3345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
3355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
3375bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3385bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable) {
3395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */
3405bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
3415bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
3425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
3435bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
3445bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3455bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3464e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8295_has_signal(struct dvb_frontend *fe)
3475bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3484e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3495bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3505bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char hvpll_stat = 0x26;
3515bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char ret;
3525bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3535bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
3545bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
3555bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	return (ret & 0x01) ? 65535 : 0;
3565bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3575bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3585bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
3595bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
360c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8295_set_params(struct dvb_frontend *fe,
361c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
3625bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3634e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3645bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3655bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char blanking_mode[]     = { 0x1d, 0x00 };
3665bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
367c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
3685bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
369c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
3705bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3714e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
3724e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 1);
3735bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3745bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
3755bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
3765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3774e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
3785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3795bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	blanking_mode[1] = 0x03;
3805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
3815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
3825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3834e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 1);
3845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3854e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.set_analog_params)
386c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		fe->ops.tuner_ops.set_analog_params(fe, params);
3875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3885bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv->cfg.agcf)
3894e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky		priv->cfg.agcf(fe);
3905bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3914e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (tda8295_has_signal(fe))
3925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 is locked\n");
3935bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 not locked, no signal?\n");
3955bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3964e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 0);
3975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
4005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4014e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8290_has_signal(struct dvb_frontend *fe)
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4034e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
405910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char i2c_get_afc[1] = { 0x1B };
406910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char afc = 0;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
408910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
409910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
410746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return (afc & 0x80)? 65535:0;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
413de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
414de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4154e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_standby(struct dvb_frontend *fe)
416793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab{
4174e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4184e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
419de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char cb1[] = { 0x30, 0xD0 };
420de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8290_standby[] = { 0x00, 0x02 };
4210157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
422b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
423de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4244e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
4258c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
426de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		cb1[1] = 0x90;
427db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
4284e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
429db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
430db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
431793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab}
432793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab
4334e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_standby(struct dvb_frontend *fe)
4345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4354e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
4365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4374e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 0);
4385bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4404e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_if(struct dvb_frontend *fe)
441de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
4424e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
443db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
444de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_VS[] = { 0x30, 0x6F };
44558ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	unsigned char set_GP00_CF[] = { 0x20, 0x01 };
446de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_GP01_CF[] = { 0x20, 0x0B };
447de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
448ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	if ((priv->cfg.config) &&
449ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	    ((*priv->cfg.config == 1) || (*priv->cfg.config == 2)))
450db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
45158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	else
452db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
453db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
454de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
455de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4564e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_init_if(struct dvb_frontend *fe)
4575bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4584e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4595bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4605bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };
4615bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };
4625bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };
4635bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };
4645bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };
4655bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };
4665bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };
4675bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4684e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
4695bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4704e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
4714e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
4725bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4735bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
4745bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
4755bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
4765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
4775bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
4785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
4795bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
4805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4814e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0);
4824e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc2_out(fe, 0);
4835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4854e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_tuner(struct dvb_frontend *fe)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4874e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
488de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275_init[]  = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
4899a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
490de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
4919a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
492b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
493c2f6f9d866d3ea25eebe32c6c51e47e5141669cfRicardo Cerqueira			      .buf=tda8275_init, .len = 14};
4948c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
495de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.buf = tda8275a_init;
496de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4974e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
498db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
4994e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
500de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
501de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
502de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5044e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda829x_release(struct dvb_frontend *fe)
505024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky{
5064e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.release)
5074e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky		fe->ops.tuner_ops.release(fe);
508024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky
5094e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	kfree(fe->analog_demod_priv);
5104e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	fe->analog_demod_priv = NULL;
511910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
512910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
5138c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufkystatic int tda829x_find_tuner(struct dvb_frontend *fe)
514de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
5158c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
5168c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct analog_tuner_ops *ops = fe->ops.analog_demod_ops;
517de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	int i, ret, tuners_found;
518de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	u32 tuner_addrs;
5198c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	u8 data;
5208c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
521de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
5228c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (NULL == ops)
5238c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EINVAL;
524746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
5258c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	ops->i2c_gate_ctrl(fe, 1);
526db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
527de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* probe for tuner chip */
528de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuners_found = 0;
529de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuner_addrs = 0;
5308c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	for (i = 0x60; i <= 0x63; i++) {
531de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.addr = i;
532db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
533de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if (ret == 1) {
534de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuners_found++;
535de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuner_addrs = (tuner_addrs << 8) + i;
536de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
537de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
538de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* if there is more than one tuner, we expect the right one is
539de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   behind the bridge and we choose the highest address that doesn't
540de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   give a response now
541de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	 */
5428c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
5438c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	ops->i2c_gate_ctrl(fe, 0);
5448c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
5458c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (tuners_found > 1)
546de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		for (i = 0; i < tuners_found; i++) {
547de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msg.addr = tuner_addrs  & 0xff;
548db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
5498c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			if (ret == 1)
550de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_addrs = tuner_addrs >> 8;
551de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			else
552de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				break;
553de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
5548c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
555de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	if (tuner_addrs == 0) {
5568c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_addrs = 0x60;
5578c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_info("could not clearly identify tuner address, "
5588c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			   "defaulting to %x\n", tuner_addrs);
559de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	} else {
560de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		tuner_addrs = tuner_addrs & 0xff;
561910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_info("setting tuner address to %x\n", tuner_addrs);
562de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
563b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	priv->tda827x_addr = tuner_addrs;
564de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msg.addr = tuner_addrs;
565de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
5668c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	ops->i2c_gate_ctrl(fe, 1);
567db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
568910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
5698c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (ret != 1) {
5708c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_warn("tuner access failed!\n");
5718c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EREMOTEIO;
572de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
573746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
5748c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (data == 0x83) {
5758c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver |= TDA18271;
5766881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		tda18271_attach(fe, priv->tda827x_addr,
5778c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky				priv->i2c_props.adap);
5788c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else {
5798c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		if ((data & 0x3c) == 0)
5808c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275;
5818c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		else
5828c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275A;
5837fd8b263678ab8430b49c99976ade681f8a78439Michael Krufky
5846881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		tda827x_attach(fe, priv->tda827x_addr,
5858c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			       priv->i2c_props.adap, &priv->cfg);
5868c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	}
5876881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.init)
5886881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.init(fe);
58963c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
5906881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.sleep)
5916881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.sleep(fe);
59263c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
5938c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	ops->i2c_gate_ctrl(fe, 0);
594746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
595746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return 0;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
598f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8290_probe(struct tuner_i2c_props *i2c_props)
599f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
600f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8290_ID 0x89
601f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	unsigned char tda8290_id[] = { 0x1f, 0x00 };
602f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
603f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* detect tda8290 */
604f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
605f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
606f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
607f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8290_id[1] == TDA8290_ID) {
608ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
609f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
610f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       __FUNCTION__, i2c_adapter_id(i2c_props->adap),
611f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
612f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
613f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
614f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
6151f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
616f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
617f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
618f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8295_probe(struct tuner_i2c_props *i2c_props)
619f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
620f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8295_ID 0x8a
621f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	unsigned char tda8295_id[] = { 0x2f, 0x00 };
622f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
623f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* detect tda8295 */
624f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
625f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
626f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
627f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8295_id[1] == TDA8295_ID) {
628ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
629f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
630f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       __FUNCTION__, i2c_adapter_id(i2c_props->adap),
631f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
632f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
633f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
634f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
6351f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
636f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
637f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
6388c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufkystatic struct analog_tuner_ops tda8290_tuner_ops = {
639c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8290_set_params,
6408c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8290_has_signal,
6418c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8290_standby,
6428c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
6438c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8290_i2c_bridge,
6448c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
6458c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
6468c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufkystatic struct analog_tuner_ops tda8295_tuner_ops = {
647c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8295_set_params,
6488c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8295_has_signal,
6498c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8295_standby,
6508c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
6518c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8295_i2c_bridge,
6528c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
6538c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
654ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkystruct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
655ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct i2c_adapter *i2c_adap, u8 i2c_addr,
656ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct tda829x_config *cfg)
6575bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
6585bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	struct tda8290_priv *priv = NULL;
659ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	char *name;
6608c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
6615bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
6625bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv == NULL)
663ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		return NULL;
6648c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	fe->analog_demod_priv = priv;
6655bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
666ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.addr     = i2c_addr;
667ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.adap     = i2c_adap;
668ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	if (cfg) {
669ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		priv->cfg.config         = cfg->lna_cfg;
670ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		priv->cfg.tuner_callback = cfg->tuner_callback;
671ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	}
6725bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
673f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8290_probe(&priv->i2c_props) == 0) {
6748c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8290;
6758c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		fe->ops.analog_demod_ops = &tda8290_tuner_ops;
6765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
6778c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
678f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8295_probe(&priv->i2c_props) == 0) {
6798c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8295;
6808c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		fe->ops.analog_demod_ops = &tda8295_tuner_ops;
6815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
6825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
6838c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (tda829x_find_tuner(fe) < 0)
684fa746aee336fedfe25e6945e5967399966948420Michael Krufky		goto fail;
6855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
686ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	switch (priv->ver) {
687ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275:
688ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75";
689ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
690ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275:
691ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75";
692ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
693ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275A:
694ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75a";
695ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
696ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275A:
697ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75a";
698ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
699ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA18271:
700ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+18271";
701ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
702ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA18271:
703ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+18271";
704ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
705ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	default:
706ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		goto fail;
707ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	}
708ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	tuner_info("type set to %s\n", name);
709ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky
7108c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8290) {
7118c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8290_init_tuner(fe);
7128c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8290_init_if(fe);
7138c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else if (priv->ver & TDA8295)
7148c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8295_init_if(fe);
7155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
716ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return fe;
717fa746aee336fedfe25e6945e5967399966948420Michael Krufky
718fa746aee336fedfe25e6945e5967399966948420Michael Krufkyfail:
719fa746aee336fedfe25e6945e5967399966948420Michael Krufky	tda829x_release(fe);
720fa746aee336fedfe25e6945e5967399966948420Michael Krufky	fe->ops.analog_demod_ops = NULL;
721ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return NULL;
7225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
7238c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyEXPORT_SYMBOL_GPL(tda829x_attach);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
725ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkyint tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
72695736034df751631657140aebe677e67d7522867Hartmut Hackmann{
727910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	struct tuner_i2c_props i2c_props = {
728ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.adap = i2c_adap,
729ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.addr = i2c_addr,
730910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	};
731db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
73244fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char soft_reset[]   = { 0x00, 0x00 };
73344fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_b[]  = { 0x01, 0x02 };
73444fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_g[]  = { 0x01, 0x04 };
73544fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
73695736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char addr_dto_lsb = 0x07;
73795736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char data;
738a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky#define PROBE_BUFFER_SIZE 8
739a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	unsigned char buf[PROBE_BUFFER_SIZE];
740a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	int i;
741a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
742a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* rule out tda9887, which would return the same byte repeatedly */
743a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
744a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
745a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
746bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky		if (buf[i] != buf[0])
747bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky			break;
748a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	}
749a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
750a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* all bytes are equal, not a tda829x - probably a tda9887 */
751a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	if (i == PROBE_BUFFER_SIZE)
752a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky		return -ENODEV;
75395736034df751631657140aebe677e67d7522867Hartmut Hackmann
754f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if ((tda8290_probe(&i2c_props) == 0) ||
755f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	    (tda8295_probe(&i2c_props) == 0))
756f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
757f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
758f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* fall back to old probing method */
759910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
760910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
761910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
762910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_recv(&i2c_props, &data, 1);
76395736034df751631657140aebe677e67d7522867Hartmut Hackmann	if (data == 0) {
764910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
765910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
766910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
767910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_recv(&i2c_props, &data, 1);
76895736034df751631657140aebe677e67d7522867Hartmut Hackmann		if (data == 0x7b) {
76995736034df751631657140aebe677e67d7522867Hartmut Hackmann			return 0;
77095736034df751631657140aebe677e67d7522867Hartmut Hackmann		}
77195736034df751631657140aebe677e67d7522867Hartmut Hackmann	}
772910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
7731f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
77495736034df751631657140aebe677e67d7522867Hartmut Hackmann}
775f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael KrufkyEXPORT_SYMBOL_GPL(tda829x_probe);
776910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
7778c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyMODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
7785bea1cd3871351d70cc7624af138f8aa68b7be77Michael KrufkyMODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
779910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael KrufkyMODULE_LICENSE("GPL");
780910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overrides for Emacs so that we follow Linus's tabbing style.
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ---------------------------------------------------------------------------
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables:
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-basic-offset: 8
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End:
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
788